diff --git a/A7800DS.nds b/A7800DS.nds index 764030c..c258aa9 100644 Binary files a/A7800DS.nds and b/A7800DS.nds differ diff --git a/Makefile b/Makefile index d0bf416..46941d5 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -VERSION=4.7 +VERSION=4.8 TARGNAME=A7800DS #--------------------------------------------------------------------------------- diff --git a/README.md b/README.md index a790419..91296e8 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ Features : Copyright : ---------- -A7800DS is Copyright 2021-2024 by Dave Bernazzani (wavemotion-dave). +A7800DS is Copyright 2021-2025 by Dave Bernazzani (wavemotion-dave). This emulator is based heavily upon ProSystem and that emulator was released in 2005 by Greg Stanton under the GNU General Public License and, as such, @@ -197,6 +197,12 @@ Updates by wavemotion-dave: https://github.com/wavemotion-dave/A7800DS -------------------------------------------------------------------------------- History : -------------------------------------------------------------------------------- +V4.8 : 15-Feb-2025 by wavemotion-dave + * High Score (HSC) now auto-saves the .hsc file after it is written by the game. The HSC button is gone. + * Smoother console button operation so that a press is registered more consistently and with better debounce. + * Improved magnifying glass icon debounce so that it registers more consistently and with better debounce. + * New game icon to align with the other emulators in the Atari lineup on the DS. + V4.7 : 11-May-2024 by wavemotion-dave * X and Y buttons now shift the screen down/up by 16 pixels so you can position the score off-screen and use these to pan up/down to see it. * Fix for Supercarts so that they start in bank 0 (Legend of Silverpeak should now load) diff --git a/arm9/gfx/bgBottom.png b/arm9/gfx/bgBottom.png index ff2d6c8..df253ac 100644 Binary files a/arm9/gfx/bgBottom.png and b/arm9/gfx/bgBottom.png differ diff --git a/arm9/gfx/pdev_bg0.png b/arm9/gfx/pdev_bg0.png index 5329bbd..04040e3 100644 Binary files a/arm9/gfx/pdev_bg0.png and b/arm9/gfx/pdev_bg0.png differ diff --git a/arm9/source/a7800utils.c b/arm9/source/a7800utils.c index 108a51e..8fd0d55 100644 --- a/arm9/source/a7800utils.c +++ b/arm9/source/a7800utils.c @@ -1,5 +1,5 @@ // ===================================================================================== -// Copyright (c) 2022-2024 Dave Bernazzani (wavemotion-dave) +// Copyright (c) 2022-2025 Dave Bernazzani (wavemotion-dave) // // Copying and distribution of this emulator, it's source code and associated // readme files, with or without modification, are permitted in any medium without @@ -64,6 +64,8 @@ u32 snes_adaptor __attribute__((section(".dtcm"))) = 0x00 extern u32 tiaBufIdx; char fpsbuf[34]; char dbgbuf[40]; +u8 bJustSavedHSC = 0; +u8 spamHSC = 0; // ----------------------------------------------------------------- // Some vars for listing filenames of ROMs... 1K of ROMs is plenty @@ -170,6 +172,8 @@ void FadeToColor(unsigned char ucSens, unsigned short ucBG, unsigned char ucScr, } } +u8 tchepres_delay = 0; +u8 tchepres_value = 0; #define tchepres(a) \ keyboard_data[GameConf.DS_Pad[a]] = 1; @@ -347,7 +351,9 @@ void dsLoadGame(char *filename) prosystem_Reset(); lastSample = 0; - + bJustSavedHSC = 0; + spamHSC = 0; + if (DEBUG_DUMP) { extern char header[]; @@ -393,6 +399,9 @@ void dsLoadGame(char *filename) TIMER0_CR=0; TIMER0_DATA=0; TIMER0_CR=TIMER_ENABLE|TIMER_DIV_1024; + + tchepres_delay = 0; + tchepres_value = 0; SoundUnPause(); } @@ -428,7 +437,7 @@ bool dsWaitOnQuit(void) { dmaFillWords(dmaVal | (dmaVal<<16),(void*) bgGetMapPtr(bg1b),32*24*2); strcpy(szName,"Quit a7800DS ?"); - dsPrintValue(16-strlen(szName)/2,3,0,szName); + dsPrintValue(16-strlen(szName)/2,5,0,szName); sprintf(szName,"%s","A TO CONFIRM, B TO GO BACK"); dsPrintValue(16-strlen(szName)/2,23,0,szName); @@ -977,7 +986,14 @@ ITCM_CODE void dsMainLoop(void) } memset(keyboard_data, 0x00, 15); // Not the difficulty switches which are the two bytes after this... } - + + // If we have recently pressed any of the console keys... keep it pressed for a minimum duration + if (tchepres_delay) + { + tchepres_delay--; + tchepres(tchepres_value); + } + scanKeys(); keys_pressed = keysCurrent(); @@ -990,7 +1006,7 @@ ITCM_CODE void dsMainLoop(void) touchRead(&touch); iTx = touch.px; iTy = touch.py; - if ((iTx>8) && (iTx<55) && (iTy>154) && (iTy<171)) { // 32,160 -> 64,168 POWER + if ((iTx>2) && (iTx<67) && (iTy>154) && (iTy<171)) { // POWER SoundPause(); mmEffect(SFX_KEYCLICK); // Play short key click for feedback... if (dsWaitOnQuit()) emu_state=A7800_QUITSTDS; @@ -1005,34 +1021,28 @@ ITCM_CODE void dsMainLoop(void) fpsDisplay = 1-fpsDisplay; gTotalAtariFrames=0; if (!fpsDisplay) dsPrintValue(0,0,0," "); dampen=60; } - else if ((iTx>63) && (iTx<105) && (iTy>154) && (iTy<171)) { // 72,160 -> 105,168 PAUSE + else if ((iTx>67) && (iTx<128) && (iTy>154) && (iTy<171)) { // PAUSE if (keys_touch == 0) mmEffect(SFX_KEYCLICK); // Play short key click for feedback... + tchepres_value = 10; + tchepres_delay = 5; tchepres(10); } - else if ((iTx>152) && (iTx<198) && (iTy>154) && (iTy<171)) { // 142,160 -> 175,168 SELECT + else if ((iTx>128) && (iTx<193) && (iTy>154) && (iTy<171)) { // SELECT if (keys_touch == 0) mmEffect(SFX_KEYCLICK); // Play short key click for feedback... + tchepres_value = 11; + tchepres_delay = 5; tchepres(11); } - else if ((iTx>208) && (iTx<251) && (iTy>154) && (iTy<171)) { // 191,160 -> 224,168 RESET + else if ((iTx>193) && (iTx<254) && (iTy>154) && (iTy<171)) { // RESET if (keys_touch == 0) mmEffect(SFX_KEYCLICK); // Play short key click for feedback... + tchepres_value = 6; + tchepres_delay = 5; tchepres(6); } else if ((iTx>90) && (iTx<110) && (iTy>90) && (iTy<110)) { // Atari Logo - Activate HSC Maintenence Mode (only on High Score screen) special_hsc_entry=70; } - else if ((iTx>115) && (iTx<144) && (iTy>154) && (iTy<171)) { // Snap HSC SRAM file - if (high_score_cart_loaded) - { - dsPrintValue(13,0,0, "SAVING"); - mmEffect(SFX_KEYCLICK); // Play short key click for feedback... - WAITVBL;WAITVBL; - cartridge_SaveHighScoreSram(); - dsPrintValue(13,0,0, " "); - } - dampen=60; - continue; - } - else if ((iTx>69) && (iTx<180) && (iTy>22) && (iTy<62)) // Cartridge slot + else if ((iTx>69) && (iTx<180) && (iTy>21) && (iTy<62)) // Cartridge slot { SoundPause(); // Find files in current directory and show it @@ -1052,7 +1062,7 @@ ITCM_CODE void dsMainLoop(void) } else if ((iTx>10) && (iTx<58) && (iTy>22) && (iTy<62)) // Magnifying Glass (zoom) { - toggle_zoom(); + if (!keys_touch) toggle_zoom(); } keys_touch=1; @@ -1063,11 +1073,11 @@ ITCM_CODE void dsMainLoop(void) last_keys_pressed = keys_pressed; if ((myCartInfo.cardctrl1 != SNES)) { - if ( (keys_pressed & KEY_SELECT) ) { tchepres(11); } // BUTTON SELECT + if ( (keys_pressed & KEY_SELECT) ) { tchepres_value = 11; tchepres_delay = 5;tchepres(11); } // BUTTON SELECT } if ((myCartInfo.cardctrl1 != TWIN) && (myCartInfo.cardctrl1 != SNES)) { - if ( (keys_pressed & KEY_START) ) {tchepres(10);} // BUTTON PAUSE + if ( (keys_pressed & KEY_START) ) { tchepres_value = 10; tchepres_delay = 5; tchepres(10); } // BUTTON PAUSE } if (myCartInfo.cardctrl1 == SOTA) { @@ -1124,6 +1134,26 @@ ITCM_CODE void dsMainLoop(void) // ------------------------------------------------------------- if (TIMER1_DATA >= 32728) // 1000MS (1 sec) { + if (bHSC_dirty) // Check to see if the High Score area has changed ... if so, snap out the .hsc file + { + if (high_score_cart_loaded && myCartInfo.hsc) // Check if HSC is enabled + { + if (++spamHSC <= 8) // Check that we haven't been spamming the HSC saving... + { + dsPrintValue(11,0,0, "HSC SAVING"); + cartridge_SaveHighScoreSram(); + bJustSavedHSC = 1; + } + } + bHSC_dirty = 0; + } + else if (bJustSavedHSC) + { + bJustSavedHSC = 0; + if (spamHSC <= 8) spamHSC = 0; + dsPrintValue(11,0,0, " "); + } + TIMER1_CR = 0; TIMER1_DATA = 0; TIMER1_CR=TIMER_ENABLE | TIMER_DIV_1024; diff --git a/arm9/source/config.c b/arm9/source/config.c index 5b89c3a..787b775 100644 --- a/arm9/source/config.c +++ b/arm9/source/config.c @@ -1,5 +1,5 @@ // ===================================================================================== -// Copyright (c) 2022-2024 Dave Bernazzani (wavemotion-dave) +// Copyright (c) 2022-2025 Dave Bernazzani (wavemotion-dave) // // Copying and distribution of this emulator, it's source code and associated // readme files, with or without modification, are permitted in any medium without diff --git a/arm9/source/emu/HighScore.c b/arm9/source/emu/HighScore.c index 06d9300..d838ed8 100644 --- a/arm9/source/emu/HighScore.c +++ b/arm9/source/emu/HighScore.c @@ -218,16 +218,20 @@ bool cartridge_SaveHighScoreSram(void) return false; // If we didn't load the high score cartridge, or don't have an HSC enabled cart: don't save. } - memcpy(high_score_sram, memory_ram+HS_SRAM_START, HS_SRAM_SIZE); // Copy from main memory to SRAM buffer - - make_hsc_name(); // HSC filename is same as base filename with .hsc extension - - // Write out the .hsc file - FILE *handle = fopen(szName, "wb"); - if (handle != NULL) + // Make sure something actually changed before writing... + if (memcmp(high_score_sram, memory_ram+HS_SRAM_START, HS_SRAM_SIZE) != 0) { - fwrite(high_score_sram, HS_SRAM_SIZE, 1, handle); - fclose(handle); + memcpy(high_score_sram, memory_ram+HS_SRAM_START, HS_SRAM_SIZE); // Copy from main memory to SRAM buffer + + make_hsc_name(); // HSC filename is same as base filename with .hsc extension + + // Write out the .hsc file + FILE *handle = fopen(szName, "wb"); + if (handle != NULL) + { + fwrite(high_score_sram, HS_SRAM_SIZE, 1, handle); + fclose(handle); + } } return true; // We at least made the attempt to write out the .hsc save file @@ -266,6 +270,8 @@ static bool cartridge_LoadHighScoreSram(void) memory_Write(HS_SRAM_START + i, high_score_sram[i]); } + bHSC_dirty = 0; // We don't consider the init of SRAM directly above to be a 'write' (no need to persist) + return true; // HSC SRAM is ready to go! } diff --git a/arm9/source/emu/Memory.c b/arm9/source/emu/Memory.c index 70a6762..c184152 100644 --- a/arm9/source/emu/Memory.c +++ b/arm9/source/emu/Memory.c @@ -30,6 +30,7 @@ byte memory_ram[MEMORY_SIZE] ALIGN(32) = {0}; u8 *is_memory_writable = (u8*)0x06820000; u32 snes_bit_pos = 0; +u8 bHSC_dirty = 0; extern bool write_only_pokey_at_4000; @@ -47,7 +48,8 @@ void memory_Reset( ) for(index = 0; index < 16384/2; index++) { ptr[index] = 0xFFFF; } - + + bHSC_dirty = 0; snes_bit_pos = 0; } @@ -147,7 +149,10 @@ ITCM_CODE void memory_Write(word address, byte data) memory_ram[address ^0x0100] = data; } } - //else if ((address & 0xF800) == 0x1000) // HSC RAM - someday we might trigger on this and auto-save the .hsc SRAM file + else if ((address & 0xF800) == 0x1000) // HSC RAM - set the dirty bit so we persist the .hsc file in the main loop + { + bHSC_dirty = 1; + } memory_ram[address] = data; return; diff --git a/arm9/source/emu/Memory.h b/arm9/source/emu/Memory.h index 809fb86..57326a7 100644 --- a/arm9/source/emu/Memory.h +++ b/arm9/source/emu/Memory.h @@ -33,6 +33,8 @@ #include "shared.h" +extern u8 bHSC_dirty; + extern byte memory_ram[MEMORY_SIZE]; extern void memory_Reset( ); diff --git a/logo.bmp b/logo.bmp index 4e4c7d7..a5e9837 100644 Binary files a/logo.bmp and b/logo.bmp differ