diff --git a/ColecoDS.nds b/ColecoDS.nds index fe116ebe..9c8d2142 100644 Binary files a/ColecoDS.nds and b/ColecoDS.nds differ diff --git a/Makefile b/Makefile index d40338c8..0ae76358 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ include $(DEVKITARM)/ds_rules export TARGET := ColecoDS export TOPDIR := $(CURDIR) -export VERSION := 4.6a +export VERSION := 4.7 ICON := -b $(CURDIR)/logo.bmp "ColecoDS $(VERSION);wavemotion-dave;https://github.com/wavemotion-dave/ColecoDS" diff --git a/README.md b/README.md index 5c742ce3..543d5540 100644 --- a/README.md +++ b/README.md @@ -46,10 +46,10 @@ Thanks to Flubba for the SN76496 sound core. Special thanks to Marat Fayzullin, as the author of ColEM which is the code for the -core emulation (specifically TMS9918 VDP). -I think the original port was circa ColEM 2.1 -with some fixes and updated Sprite/Line handling -from ColEM 5.6 +core emulation (specifically TMS9918 VDP +and the CZ80 CPU core). I think the original +port was circa ColEM 2.1 with some fixes and +updated Sprite/Line handling from ColEM 5.6 Known Issues : ----------------------- @@ -96,8 +96,23 @@ it for almost all games (Princess Quest is one game where you might turn it off) handle it for the more simple games. So by default it's enabled for DSi and disabled for DS-LITE/PHAT. You can toggle this in the "Game Options" (and START=SAVE it out as you wish). +A Tale of Two Cores : +----------------------- +ColecoDS supports 2 different Z80 CPU cores. +DrZ80 is very fast but is not 100% accurate so some games don't run right. +CZ80 is slower but is much closer to 100% accurate and games generally run great. +For the DSi and above, the CZ80 core is the default. +For the DS-LITE/PHAT, the DrZ80 core is the default. +You can toggle this (and save on a per-game basis) in GAME OPTIONS. +If you want to use the CZ80 core but need a bit more speed to make the +games playable - you can also play with Vertical Sync and Frame Skip settings. + Versions : ----------------------- +V4.7: 23-Dec-2021 by wavemotion-dave +* Major speed improvements in the new CZ80 core. +* Installed new CZ80 core as the default for DSi and above. + V4.6: 22-Dec-2021 by wavemotion-dave * New CZ80 core added to solve compatibility problems with the remaining games. diff --git a/arm9/gfx_data/pdev_bg0.png b/arm9/gfx_data/pdev_bg0.png index 87d81024..7dec3c91 100644 Binary files a/arm9/gfx_data/pdev_bg0.png and b/arm9/gfx_data/pdev_bg0.png differ diff --git a/arm9/source/colecoDS.c b/arm9/source/colecoDS.c index 949e4393..aebca05c 100644 --- a/arm9/source/colecoDS.c +++ b/arm9/source/colecoDS.c @@ -485,7 +485,7 @@ void DisplayStatusLine(bool bForce) // ------------------------------------------------------------------------ // The main emulation loop is here... call into the Z80, VDP and PSG // ------------------------------------------------------------------------ -ITCM_CODE void colecoDS_main(void) +void colecoDS_main(void) { u32 keys_pressed; u16 iTx, iTy; @@ -494,8 +494,10 @@ ITCM_CODE void colecoDS_main(void) static u32 lastUN = 0; static u8 dampenClick = 0; - showMainMenu(); // Returns when user has asked for a game to run... + // Returns when user has asked for a game to run... + showMainMenu(); + // Get the Coleco Machine Emualtor ready colecoInit(gpFic[ucGameAct].szName); colecoSetPal(); @@ -513,10 +515,12 @@ ITCM_CODE void colecoDS_main(void) timingFrames = 0; emuFps=0; + // Default SGM statics back to init state last_sgm_mode = false; last_ay_mode = false; last_mc_mode = 0; + // Force the sound engine to turn on when we start emulation bStartSoundEngine = true; // ------------------------------------------------------------------- @@ -527,6 +531,7 @@ ITCM_CODE void colecoDS_main(void) // Take a tour of the Z80 counter and display the screen if necessary if (!LoopZ80()) { + // If we've been asked to start the sound engine, rock-and-roll! if (bStartSoundEngine) { bStartSoundEngine = false; diff --git a/arm9/source/colecoDS.h b/arm9/source/colecoDS.h index edbc4dff..e9316c3e 100644 --- a/arm9/source/colecoDS.h +++ b/arm9/source/colecoDS.h @@ -5,7 +5,7 @@ #include #include "cpu/z80/drz80/Z80_interface.h" -#define VERSIONCLDS "4.6" +#define VERSIONCLDS "4.7" //#define DEBUG_Z80 YES @@ -34,7 +34,7 @@ #define JST_RED JST_FIRER #define JST_YELLOW JST_FIREL -// These 4 are now actual Colecovision key maps... they trigger the spinners. +// These 4 are not actual Colecovision key maps... they trigger the spinner logic. #define META_SPINX_LEFT 0xFFFF0001 #define META_SPINX_RIGHT 0xFFFF0002 #define META_SPINY_LEFT 0xFFFF0003 diff --git a/arm9/source/colecogeneric.c b/arm9/source/colecogeneric.c index 37e779a3..a5717484 100644 --- a/arm9/source/colecogeneric.c +++ b/arm9/source/colecogeneric.c @@ -701,10 +701,10 @@ void SetDefaultGameConfig(void) myConfig.autoFire2 = 0; myConfig.overlay = 0; myConfig.maxSprites = 0; - myConfig.vertSync = (isDSiMode() ? 1:0); + myConfig.vertSync = (isDSiMode() ? 1:0); // Default is Vertical Sync ON for DSi and OFF for DS-LITE myConfig.spinSpeed = 0; myConfig.touchPad = 0; - myConfig.cpuCore = 0; // Default is the faster DrZ80 core + myConfig.cpuCore = (isDSiMode() ? 1:0); // Default is slower/accurate CZ80 for DSi and faster DrZ80 core for DS-LITE myConfig.reserved9 = 0; myConfig.reservedA = 0; myConfig.reservedB = 0; @@ -784,6 +784,7 @@ void SetDefaultGameConfig(void) // ------------------------------------------------------------------------ // These games all need the slower but higher compatibility CZ80 CPU Core + // so override the default above for these games in order to play them. // ------------------------------------------------------------------------ if ( (file_crc == 0xead5e824) || // Arno Dash @@ -889,7 +890,7 @@ const struct options_t Option_Table[] = {"AUTO FIRE B2", {"OFF", "ON"}, &myConfig.autoFire2, 2}, {"TOUCH PAD", {"PLAYER 1", "PLAYER 2"}, &myConfig.touchPad, 2}, {"SPIN SPEED", {"NORMAL", "FAST", "FASTEST", "SLOW", "SLOWEST"}, &myConfig.spinSpeed, 5}, - {"Z80 CPU CORE", {"DRZ80 (Fast)", "CZ80 (Slow)"}, &myConfig.cpuCore, 2}, + {"Z80 CPU CORE", {"DRZ80 (Faster)", "CZ80 (Slower)"}, &myConfig.cpuCore, 2}, #if 0 // Developer use only {"Z80 CYCLES!!", {"NORMAL", "+1", "+2", "+3", "+4", "+5", "+6", "+7", "+8", "+9", "+10", "-1", "-2", "-3", "-4", "-5"}, &dev_z80_cycles, 16}, #endif diff --git a/arm9/source/colecomngt.c b/arm9/source/colecomngt.c index 1b22ad0a..5cb05928 100644 --- a/arm9/source/colecomngt.c +++ b/arm9/source/colecomngt.c @@ -794,11 +794,11 @@ ITCM_CODE void cpu_writeport16(register unsigned short Port,register unsigned ch // ----------------------------------------------- // These two functions are for the CZ80 core... // ----------------------------------------------- -ITCM_CODE void OutZ80(register word Port,register byte Value) +void OutZ80(register word Port,register byte Value) { cpu_writeport16(Port, Value); } -ITCM_CODE byte InZ80(register word Port) +byte InZ80(register word Port) { return cpu_readport16(Port); } diff --git a/arm9/source/cpu/sn76496/Fake_AY.c b/arm9/source/cpu/sn76496/Fake_AY.c index 0ba43fba..2bd09062 100644 --- a/arm9/source/cpu/sn76496/Fake_AY.c +++ b/arm9/source/cpu/sn76496/Fake_AY.c @@ -70,7 +70,7 @@ u8 c_idx=0; // We handle envelopes here... the timing is nowhere near exact but so few games utilize this // and so accuracy isn't all that critical. The sound will be a little off - but it will be ok. // --------------------------------------------------------------------------------------------- -ITCM_CODE void FakeAY_Loop(void) +void FakeAY_Loop(void) { static u16 delay=0; diff --git a/arm9/source/cpu/tms9918a/tms9918a.c b/arm9/source/cpu/tms9918a/tms9918a.c index a343f14b..1c0e89fc 100644 --- a/arm9/source/cpu/tms9918a/tms9918a.c +++ b/arm9/source/cpu/tms9918a/tms9918a.c @@ -457,7 +457,7 @@ void ITCM_CODE RefreshLine2(u8 uY) { /** Refresh line Y (0..191) of SCREEN3, including sprites **/ /** in this line. **/ /*************************************************************/ -void ITCM_CODE RefreshLine3(u8 uY) { +void RefreshLine3(u8 uY) { register byte X,K,Offset; register byte *P,*T; diff --git a/arm9/source/cpu/tms9918a/tms9918a.h b/arm9/source/cpu/tms9918a/tms9918a.h index d06fb1d0..ffaca418 100644 --- a/arm9/source/cpu/tms9918a/tms9918a.h +++ b/arm9/source/cpu/tms9918a/tms9918a.h @@ -52,10 +52,10 @@ extern u8 bResetVLatch; extern u8 TMS9918A_palette[16*3]; extern tScrMode SCR[MAXSCREEN+1]; -extern void ITCM_CODE RefreshLine0(u8 uY); -extern void ITCM_CODE RefreshLine1(u8 uY); -extern void ITCM_CODE RefreshLine2(u8 uY); -extern void ITCM_CODE RefreshLine3(u8 uY); +extern void RefreshLine0(u8 uY); +extern void RefreshLine1(u8 uY); +extern void RefreshLine2(u8 uY); +extern void RefreshLine3(u8 uY); extern byte WrCtrl9918(byte value); extern void WrData9918(byte value); diff --git a/arm9/source/cpu/z80/Z80.c b/arm9/source/cpu/z80/Z80.c index dd8328e4..067e39e4 100644 --- a/arm9/source/cpu/z80/Z80.c +++ b/arm9/source/cpu/z80/Z80.c @@ -40,22 +40,10 @@ INLINE byte OpZ80(word A) { return pColecoMem[A]; } // ----------------------------------------------- // These two functions are for the CZ80 core... // ----------------------------------------------- -extern u8 bMagicMegaCart, romBankMask; extern void cpu_writemem16 (u8 value,u16 address); -extern void BankSwitch(u8 bank); -INLINE void WrZ80(register word address,register byte Value) -{ - cpu_writemem16(Value, address); -} - -INLINE byte RdZ80(register word address) -{ - if (bMagicMegaCart && (address >= 0xFFC0)) // Handle Megacart Hot Spots - { - BankSwitch(address & romBankMask); - } - return (pColecoMem[address]); -} +extern byte cpu_readmem16_banked (u16 address); +#define WrZ80(A,V) cpu_writemem16(V,A) +#define RdZ80(A) cpu_readmem16_banked(A) #define S(Fl) CPU.AF.B.l|=Fl #define R(Fl) CPU.AF.B.l&=~(Fl) @@ -520,7 +508,7 @@ void ResetZ80(Z80 *R) /** negative, and current register values in R. **/ /*************************************************************/ #ifdef EXECZ80 -int ExecZ80(register Z80 *R,register int RunCycles) +ITCM_CODE int ExecZ80(register Z80 *R,register int RunCycles) { register byte I; register pair J; diff --git a/arm9/source/cpu/z80/drz80/Z80_interface.c b/arm9/source/cpu/z80/drz80/Z80_interface.c index 3d42d78e..b1e0558b 100644 --- a/arm9/source/cpu/z80/drz80/Z80_interface.c +++ b/arm9/source/cpu/z80/drz80/Z80_interface.c @@ -27,33 +27,33 @@ extern u8 romBankMask; extern u8 romBuffer[]; -ITCM_CODE u32 z80_rebaseSP(u16 address) { + u32 z80_rebaseSP(u16 address) { drz80.Z80SP_BASE = (unsigned int) pColecoMem; drz80.Z80SP = drz80.Z80SP_BASE + address; return (drz80.Z80SP); } -ITCM_CODE u32 z80_rebasePC(u16 address) { + u32 z80_rebasePC(u16 address) { drz80.Z80PC_BASE = (unsigned int) pColecoMem; drz80.Z80PC = drz80.Z80PC_BASE + address; return (drz80.Z80PC); } -ITCM_CODE void z80_irq_callback(void) { + void z80_irq_callback(void) { drz80.Z80_IRQ = 0x00; } // ----------------------------- // Normal 8-bit Read... fast! // ----------------------------- -ITCM_CODE u8 cpu_readmem16 (u16 address) { + u8 cpu_readmem16 (u16 address) { return (pColecoMem[address]); } // ----------------------------- // Normal 16-bit Read... fast! // ----------------------------- -ITCM_CODE u16 drz80MemReadW(u16 address) + u16 drz80MemReadW(u16 address) { return (pColecoMem[address] | (pColecoMem[address+1] << 8)); } @@ -61,7 +61,7 @@ ITCM_CODE u16 drz80MemReadW(u16 address) // ------------------------------------------------ // Switch banks... do this as fast as possible.. // ------------------------------------------------ -ITCM_CODE void BankSwitch(u8 bank) + void BankSwitch(u8 bank) { if (lastBank != bank) // Only if the bank was changed... { @@ -82,7 +82,7 @@ ITCM_CODE void BankSwitch(u8 bank) // ------------------------------------------------- // 8-bit read with bankswitch support... slower... // ------------------------------------------------- -ITCM_CODE u8 cpu_readmem16_banked (u16 address) + u8 cpu_readmem16_banked (u16 address) { if (bMagicMegaCart) // Handle Megacart Hot Spots { @@ -97,7 +97,7 @@ ITCM_CODE u8 cpu_readmem16_banked (u16 address) // ------------------------------------------------- // 16-bit read with bankswitch support... slower... // ------------------------------------------------- -ITCM_CODE u16 drz80MemReadW_banked(u16 addr) + u16 drz80MemReadW_banked(u16 addr) { if (bMagicMegaCart) // Handle Megacart Hot Spots { @@ -112,7 +112,7 @@ ITCM_CODE u16 drz80MemReadW_banked(u16 addr) // Write memory handles both normal writes and bankswitched since // write is much less common than reads... // ------------------------------------------------------------------ -ITCM_CODE void cpu_writemem16 (u8 value,u16 address) + void cpu_writemem16 (u8 value,u16 address) { extern u8 sRamAtE000_OK; extern u8 sgm_enable; @@ -151,13 +151,13 @@ ITCM_CODE void cpu_writemem16 (u8 value,u16 address) // ----------------------------------------------------------------- // The 16-bit write simply makes 2 calls into the 8-bit writes... // ----------------------------------------------------------------- -ITCM_CODE void drz80MemWriteW(u16 data,u16 addr) + void drz80MemWriteW(u16 data,u16 addr) { cpu_writemem16(data & 0xff , addr); cpu_writemem16(data>>8,addr+1); } -ITCM_CODE void Z80_Cause_Interrupt(int type) + void Z80_Cause_Interrupt(int type) { if (type == Z80_NMI_INT) { @@ -174,13 +174,13 @@ ITCM_CODE void Z80_Cause_Interrupt(int type) } } -ITCM_CODE void Z80_Clear_Pending_Interrupts(void) + void Z80_Clear_Pending_Interrupts(void) { drz80.pending_irq = 0; drz80.Z80_IRQ = 0; } -ITCM_CODE void Interrupt(void) + void Interrupt(void) { if (drz80.pending_irq & NMI_IRQ) /* NMI IRQ */ { @@ -247,7 +247,7 @@ void DrZ80_Reset(void) { // produce exactly an evenly-divisible number of // cycles for a given scanline... // -------------------------------------------------- -ITCM_CODE int DrZ80_execute(int cycles) + int DrZ80_execute(int cycles) { drz80.cycles = cycles + cycle_deficit; diff --git a/arm9/source/cpu/z80/drz80/drz80.s b/arm9/source/cpu/z80/drz80/drz80.s index 433b3690..951215ac 100644 --- a/arm9/source/cpu/z80/drz80/drz80.s +++ b/arm9/source/cpu/z80/drz80/drz80.s @@ -1089,7 +1089,6 @@ DrZ80Ver: .long 0x0001 .equ Z80_HALT, 1<<2 ;@ --------------------------- Framework -------------------------- -.section .itcm DrZ80Run: ;@ r0 = pointer to cpu context ;@ r1 = ISTATES to execute