diff --git a/src/emulator.c b/src/emulator.c index 4f92bc0..9b4bb3a 100644 --- a/src/emulator.c +++ b/src/emulator.c @@ -75,7 +75,6 @@ static void invalidBehaviorCheck(){ //add to opcode buffer strcpy(disassemblyBuffer[LOGGED_OPCODES - 1], opcodeName); - strcat(disassemblyBuffer[LOGGED_OPCODES - 1], "\n"); if(invalidInstruction || invalidBank || (instruction == 0x0000 && lastProgramCounter != 0x00000000)){ //0x0000 is "ori.b #$0, D0", effectivly NOP but still a valid opcode @@ -84,7 +83,7 @@ static void invalidBehaviorCheck(){ invalidBehaviorAbort = true; for(uint32_t i = 0; i < LOGGED_OPCODES; i++) - debugLog(disassemblyBuffer[i]); + debugLog("%s\n", disassemblyBuffer[i]); //currently CPU32 opcodes will be listed as "unknown", I cant change that properly unless I directly edit musashi source, something I want to avoid doing debugLog("Instruction:\"%s\", instruction value:0x%04X, program counter:0x%08X\n", invalidInstruction ? "unknown" : opcodeName, instruction, programCounter); } @@ -116,7 +115,7 @@ void emulatorInit(uint8_t* palmRomDump, uint8_t* palmBootDump, uint32_t specialF memcpy(palmReg + REG_SIZE - 1 - BOOTLOADER_SIZE, palmBootDump, BOOTLOADER_SIZE); else memset(palmReg + REG_SIZE - 1 - BOOTLOADER_SIZE, 0x00, BOOTLOADER_SIZE); - memcpy(palmRam, palmRom, 256);//copy ROM header + //memcpy(palmRam, palmRom, 256);//copy ROM header //memcpy(palmRam, palmRom, ROM_SIZE);//copy whole ROM memcpy(&palmFramebuffer[160 * 160], silkscreenData, SILKSCREEN_WIDTH * SILKSCREEN_HEIGHT * (SILKSCREEN_BPP / 8)); resetAddressSpace(); diff --git a/src/memoryAccess.c b/src/memoryAccess.c index a558c4d..100708e 100644 --- a/src/memoryAccess.c +++ b/src/memoryAccess.c @@ -10,9 +10,10 @@ static memory_access_t bankAccessors[TOTAL_MEMORY_BANKS];//these are not part of savestates because function pointers change with -fPIC uint8_t bankType[TOTAL_MEMORY_BANKS];//these go in savestates -//used for unmapped address space and writes to ROM, should trigger access exceptions if enabled -static unsigned int unmappedRead(unsigned int address){return 0x00000000;} -static void unmappedWrite(unsigned int address, unsigned int value){} + +//used for unmapped address space and writes to write protected chipselects, should trigger access exceptions if enabled +static unsigned int invalidRead(unsigned int address){return 0x00000000;} +static void invalidWrite(unsigned int address, unsigned int value){} //RAM accesses static unsigned int ramRead8(unsigned int address){return BUFFER_READ_8(palmRam, address, chips[CHIP_D_RAM].start, chips[CHIP_D_RAM].mask);} @@ -26,6 +27,8 @@ static void ramWrite32(unsigned int address, unsigned int value){BUFFER_WRITE_32 static unsigned int romRead8(unsigned int address){return BUFFER_READ_8(palmRom, address, chips[CHIP_A_ROM].start, chips[CHIP_A_ROM].mask);} static unsigned int romRead16(unsigned int address){return BUFFER_READ_16(palmRom, address, chips[CHIP_A_ROM].start, chips[CHIP_A_ROM].mask);} static unsigned int romRead32(unsigned int address){return BUFFER_READ_32(palmRom, address, chips[CHIP_A_ROM].start, chips[CHIP_A_ROM].mask);} +//the validity of attempting to write to ROM is determined by the read only bit in CSA, either way the write will do nothing +static void romWrite(unsigned int address, unsigned int value){} //SED1376 framebuffer static unsigned int sed1376FramebufferRead8(unsigned int address){return BUFFER_READ_8(sed1376Framebuffer, address, chips[CHIP_B_SED].start + SED1376_REG_SIZE, chips[CHIP_B_SED].mask);} @@ -83,102 +86,159 @@ static uint8_t getProperBankType(uint16_t bank){ return EMPTY_BANK; } -static void setBankType(uint16_t bank, uint8_t type){ +static bool getBankProtection(uint16_t bank){ + //special conditions + if((bank & 0x00FF) == 0x00FF && registersAreXXFFMapped()){ + //XXFF register mode + return false; + } + + //normal banks + else if(chips[CHIP_A_ROM].enable && BANK_IN_RANGE(bank, chips[CHIP_A_ROM].start, chips[CHIP_A_ROM].size)){ + return chips[CHIP_A_ROM].readOnly;//CSA has no protected memory segment + } + if(chips[CHIP_D_RAM].enable && BANK_IN_RANGE(bank, chips[CHIP_D_RAM].start, chips[CHIP_D_RAM].size)){ + return BANK_READ_ONLY(bank, CHIP_D_RAM); + } + else if(chips[CHIP_B_SED].enable && BANK_IN_RANGE(bank, chips[CHIP_B_SED].start, chips[CHIP_B_SED].size) && sed1376ClockConnected()){ + return BANK_READ_ONLY(bank, CHIP_B_SED); + } + else if(BANK_IN_RANGE(bank, REG_START_ADDRESS, REG_SIZE)){ + return false; + } + + return false; +} + +static void setBankType(uint16_t bank, uint8_t type, bool writeProtected){ bankType[bank] = type; + + //read handlers switch(type){ case EMPTY_BANK: - bankAccessors[bank].read8 = unmappedRead; - bankAccessors[bank].read16 = unmappedRead; - bankAccessors[bank].read32 = unmappedRead; - bankAccessors[bank].write8 = unmappedWrite; - bankAccessors[bank].write16 = unmappedWrite; - bankAccessors[bank].write32 = unmappedWrite; + bankAccessors[bank].read8 = invalidRead; + bankAccessors[bank].read16 = invalidRead; + bankAccessors[bank].read32 = invalidRead; break; case RAM_BANK: bankAccessors[bank].read8 = ramRead8; bankAccessors[bank].read16 = ramRead16; bankAccessors[bank].read32 = ramRead32; - bankAccessors[bank].write8 = ramWrite8; - bankAccessors[bank].write16 = ramWrite16; - bankAccessors[bank].write32 = ramWrite32; break; case ROM_BANK: bankAccessors[bank].read8 = romRead8; bankAccessors[bank].read16 = romRead16; bankAccessors[bank].read32 = romRead32; - bankAccessors[bank].write8 = unmappedWrite; - bankAccessors[bank].write16 = unmappedWrite; - bankAccessors[bank].write32 = unmappedWrite; break; case REG_BANK: bankAccessors[bank].read8 = getHwRegister8; bankAccessors[bank].read16 = getHwRegister16; bankAccessors[bank].read32 = getHwRegister32; - bankAccessors[bank].write8 = setHwRegister8; - bankAccessors[bank].write16 = setHwRegister16; - bankAccessors[bank].write32 = setHwRegister32; break; case SED1376_REG_BANK: bankAccessors[bank].read8 = sed1376GetRegister; bankAccessors[bank].read16 = sed1376GetRegister; bankAccessors[bank].read32 = sed1376GetRegister; - bankAccessors[bank].write8 = sed1376SetRegister; - bankAccessors[bank].write16 = sed1376SetRegister; - bankAccessors[bank].write32 = sed1376SetRegister; break; case SED1376_FB_BANK: bankAccessors[bank].read8 = sed1376FramebufferRead8; bankAccessors[bank].read16 = sed1376FramebufferRead16; bankAccessors[bank].read32 = sed1376FramebufferRead32; - bankAccessors[bank].write8 = sed1376FramebufferWrite8; - bankAccessors[bank].write16 = sed1376FramebufferWrite16; - bankAccessors[bank].write32 = sed1376FramebufferWrite32; break; } + + //write handlers + if(!writeProtected){ + switch(type){ + + case EMPTY_BANK: + bankAccessors[bank].write8 = invalidWrite; + bankAccessors[bank].write16 = invalidWrite; + bankAccessors[bank].write32 = invalidWrite; + break; + + case RAM_BANK: + bankAccessors[bank].write8 = ramWrite8; + bankAccessors[bank].write16 = ramWrite16; + bankAccessors[bank].write32 = ramWrite32; + break; + + case ROM_BANK: + bankAccessors[bank].write8 = romWrite; + bankAccessors[bank].write16 = romWrite; + bankAccessors[bank].write32 = romWrite; + break; + + case REG_BANK: + bankAccessors[bank].write8 = setHwRegister8; + bankAccessors[bank].write16 = setHwRegister16; + bankAccessors[bank].write32 = setHwRegister32; + break; + + case SED1376_REG_BANK: + bankAccessors[bank].write8 = sed1376SetRegister; + bankAccessors[bank].write16 = sed1376SetRegister; + bankAccessors[bank].write32 = sed1376SetRegister; + break; + + case SED1376_FB_BANK: + bankAccessors[bank].write8 = sed1376FramebufferWrite8; + bankAccessors[bank].write16 = sed1376FramebufferWrite16; + bankAccessors[bank].write32 = sed1376FramebufferWrite32; + break; + } + } + else{ + bankAccessors[bank].write8 = invalidWrite; + bankAccessors[bank].write16 = invalidWrite; + bankAccessors[bank].write32 = invalidWrite; + } } void setRegisterXXFFAccessMode(){ for(uint16_t topByte = 0; topByte < 0x100; topByte++){ uint32_t bank = topByte << 8 | 0xFF; - setBankType(bank, REG_BANK); + setBankType(bank, REG_BANK, false); } } void setRegisterFFFFAccessMode(){ for(uint16_t topByte = 0; topByte < 0x100; topByte++){ uint32_t bank = topByte << 8 | 0xFF; - setBankType(bank, getProperBankType(bank)); + setBankType(bank, getProperBankType(bank), getBankProtection(bank)); } } void setSed1376Attached(bool attached){ - if(attached){ - for(uint32_t bank = START_BANK(chips[CHIP_B_SED].start); bank < END_BANK(chips[CHIP_B_SED].start, chips[CHIP_B_SED].size); bank++){ - if(bank - START_BANK(chips[CHIP_B_SED].start) < NUM_BANKS(SED1376_REG_SIZE)) - setBankType(bank, SED1376_REG_BANK); - else - setBankType(bank, SED1376_FB_BANK); + if(chips[CHIP_B_SED].enable){ + if(attached){ + for(uint32_t bank = START_BANK(chips[CHIP_B_SED].start); bank < END_BANK(chips[CHIP_B_SED].start, chips[CHIP_B_SED].size); bank++){ + if(bank - START_BANK(chips[CHIP_B_SED].start) < NUM_BANKS(SED1376_REG_SIZE)) + setBankType(bank, SED1376_REG_BANK, getBankProtection(bank)); + else + setBankType(bank, SED1376_FB_BANK, getBankProtection(bank)); + } } - } - else{ - for(uint32_t bank = START_BANK(chips[CHIP_B_SED].start); bank < END_BANK(chips[CHIP_B_SED].start, chips[CHIP_B_SED].size); bank++){ - setBankType(bank, EMPTY_BANK); + else{ + for(uint32_t bank = START_BANK(chips[CHIP_B_SED].start); bank < END_BANK(chips[CHIP_B_SED].start, chips[CHIP_B_SED].size); bank++){ + setBankType(bank, EMPTY_BANK, getBankProtection(bank)); + } } } } void refreshBankHandlers(){ for(uint32_t bank = 0; bank < TOTAL_MEMORY_BANKS; bank++) - setBankType(bank, bankType[bank]); + setBankType(bank, bankType[bank], getBankProtection(bank)); } void resetAddressSpace(){ for(uint32_t bank = 0; bank < TOTAL_MEMORY_BANKS; bank++) - setBankType(bank, getProperBankType(bank)); + setBankType(bank, getProperBankType(bank), getBankProtection(bank)); } diff --git a/src/memoryAccess.h b/src/memoryAccess.h index 2549a4a..a5afa9e 100644 --- a/src/memoryAccess.h +++ b/src/memoryAccess.h @@ -7,11 +7,11 @@ #define START_BANK(address) (address >> 16) #define END_BANK(address, size) (START_BANK(address) + NUM_BANKS(size) - 1) #define BANK_IN_RANGE(bank, address, size) (bank >= START_BANK(address) && bank <= END_BANK(address, size)) +#define BANK_ADDRESS(bank) (bank << 16) +#define BANK_READ_ONLY(bank, chip) (chips[chip].readOnly || (chips[chip].readOnlyForProtectedMemory && (BANK_ADDRESS(bank) - chips[chip].start) >= chips[chip].unprotectedSize)) #define TOTAL_MEMORY_BANKS 0x10000 //memory chip addresses -//#define RAM_START_ADDRESS 0x00000000 -//#define ROM_START_ADDRESS 0x10000000 #define REG_START_ADDRESS 0xFFFFF000 #define RAM_SIZE (16 * 0x100000)//16mb RAM #define ROM_SIZE (4 * 0x100000)//4mb ROM @@ -19,8 +19,6 @@ #define BOOTLOADER_SIZE 0x200 //display chip addresses -//#define SED1376_REG_START_ADDRESS 0x1FF80000 -//#define SED1376_FB_START_ADDRESS 0x1FFA0000 #define SED1376_REG_SIZE 0x20000//it has 0x20000 used address space entrys but only 0xB4 registers #define SED1376_FB_SIZE 0x20000//0x14000 in size, likely also has 0x20000 used address space entrys, using 0x20000 to prevent speed penalty of checking validity on every access diff --git a/src/sed1376.c b/src/sed1376.c index ea3ce7f..cd77d57 100644 --- a/src/sed1376.c +++ b/src/sed1376.c @@ -2,24 +2,25 @@ #include #include "emulator.h" +#include "hardwareRegisters.h" //the SED1376 has only 16 address lines(17 if you count the line that switches between registers and framebuffer) and 16 data lines, the most you can read is 16 bits, registers are 8 bits //the actions described below are just my best guesses after reading the datasheet, I have not tested with actual hardware //you read and write the register on the address lines set -//8 bit reg access works normal -//16 bit reg reads will result in you getting (0x00 << 8 | register). -//16 bit reg writes will result in you writing the lower 8 bits. +//8 bit register access works normal +//16 bit register reads will result in you getting (0x00 << 8 | register). +//16 bit register writes will result in you writing the lower 8 bits. //32 bit register reads will result in you getting (randomUint16 << 16 | 0x00 << 8 | register), upper 16 bits are floating because SED1376 only has 16 address lines. //32 bit register writes will result in you writing the lower 8 bits. - //The LCD power-on sequence is activated by programming the Power Save Mode Enable bit (REG[A0h] bit 0) to 0. //The LCD power-off sequence is activated by programming the Power Save Mode Enable bit (REG[A0h] bit 0) to 1. + uint8_t sed1376Registers[SED1376_REG_SIZE]; -uint8_t sed1376Framebuffer[SED1376_FB_SIZE + 3];//+ 3 to prevent 32 bit writes on last byte from corrupting memory +uint8_t sed1376Framebuffer[SED1376_FB_SIZE]; unsigned int sed1376GetRegister(unsigned int address){ @@ -43,9 +44,9 @@ void sed1376Reset(){ } void sed1376Render(){ - if(palmMisc.lcdOn && palmMisc.backlightOn){ - //only render if lcd on and backlight on - + if(palmMisc.lcdOn && palmMisc.backlightOn && cpuIsOn()){ + //only render if LCD on and backlight on, SED1376 clock is provided by the CPU, if its off so is the SED + } else{ //black screen diff --git a/unimplementedFeatures.txt b/unimplementedFeatures.txt index c02cf92..02363f8 100644 --- a/unimplementedFeatures.txt +++ b/unimplementedFeatures.txt @@ -5,19 +5,19 @@ sysTrapPceNativeCall, ARM Emulator cpu32 table lookup opcodes Peripheral Control Register, audio ppm mixing selection All edge triggered interrupts(currently always level triggered) -The boot memory mapping where ROM starts at 0x00000000 and RAM is swapped in (debug tools)missing icons Port G SPI stuff RAM location and size setting, Dragonball VZ can set the page mapping SDCTRL DRAMC write enable All of DRAMMC -All chip select registers Setting the battery dead bit(PDDATA 0x80) if the emulated battery percent gets too low Sdcard can't be read or written to Sdcard can't be inserted or removed Sdcard has no error handling in save/load state Port M Infrared shutdown (PMDATA 0x20) -interrupt control register (ICR) partially unimplemented +interrupt control register (ICR), POL5 and edge trigger selects +Bits 15 and 14 of the chip selects, currently only the upper 16 bits are taken into account +Supervisor only chip select bits Fixed: System Control Register, 0xXXFFF000 all upper banks are registers mode @@ -28,3 +28,5 @@ PLL Control Register, Wake Select (Resolved by MC68VZ328UM_CORRECTIONS datasheet, its 0xA28, 16 bits)The data sheet says LRRA is 0xFFFFFA29 and 0xFFFFFA28 but its only 8 bits? (All except edge triggered INT0/1/2/3 restart PLL)Check if interrupts restart PLL when its disabled Disabling PLL also turns off general purpose timer 1 and 2 unless they are set to use clk32 as there source +All chip select registers +The boot memory mapping where ROM starts at 0x00000000 and RAM is swapped in