diff --git a/A5200DS.nds b/A5200DS.nds index 30ce718..f3d4098 100644 Binary files a/A5200DS.nds and b/A5200DS.nds differ diff --git a/Makefile b/Makefile index 5ed7ec1..a53061e 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -VERSION=2.9a +VERSION=3.0 #--------------------------------------------------------------------------------- .SUFFIXES: diff --git a/arm9/gfx/pdev_bg0.png b/arm9/gfx/pdev_bg0.png index e4d3b55..0202c2e 100644 Binary files a/arm9/gfx/pdev_bg0.png and b/arm9/gfx/pdev_bg0.png differ diff --git a/arm9/source/a5200utils.c b/arm9/source/a5200utils.c index 1e43c42..85dae93 100644 --- a/arm9/source/a5200utils.c +++ b/arm9/source/a5200utils.c @@ -43,8 +43,9 @@ int lcd_swap_counter = 0; unsigned int atari_pal16[256] = {0}; unsigned char *filebuffer; -unsigned char sound_buffer[SNDLENGTH]; -unsigned char *psound_buffer; +unsigned char sound_buffer[SNDLENGTH] __attribute__ ((aligned (4))) = {0}; +u16* aptr __attribute__((section(".dtcm"))) = (u16*) ((u32)&sound_buffer[0] + 0xA000000); +u16* bptr __attribute__((section(".dtcm"))) = (u16*) ((u32)&sound_buffer[2] + 0xA000000); #define MAX_DEBUG 5 int debug[MAX_DEBUG]={0}; @@ -92,22 +93,38 @@ static void DumpDebugData(void) } } +u16 sound_idx __attribute__((section(".dtcm"))) = 0; +u16 myPokeyBufIdx __attribute__((section(".dtcm"))) = 0; +u8 lastSample __attribute__((section(".dtcm"))) = 0; +u16 sampleExtender[256] __attribute__((section(".dtcm"))) = {0}; + +void VsoundClear(void) +{ + extern void PokeyClearBuffer(void); + + PokeyClearBuffer(); + memset(sound_buffer, 0x00, SNDLENGTH); + lastSample = 0x00; + myPokeyBufIdx = 0; + sound_idx = 0; +} + void VsoundHandler(void) { - static unsigned int sound_idx = 0; extern unsigned char pokey_buffer[]; - extern int pokeyBufIdx; - static int myPokeyBufIdx=0; - static unsigned char lastSample = 0; + extern u16 pokeyBufIdx; // If there is a fresh sample... if (myPokeyBufIdx != pokeyBufIdx) { - lastSample = pokey_buffer[myPokeyBufIdx]; + *aptr = sampleExtender[pokey_buffer[myPokeyBufIdx]]; myPokeyBufIdx = (myPokeyBufIdx+1) & (SNDLENGTH-1); + if (myPokeyBufIdx != pokeyBufIdx) + { + *bptr = sampleExtender[pokey_buffer[myPokeyBufIdx]]; + myPokeyBufIdx = (myPokeyBufIdx+1) & (SNDLENGTH-1); + } else *bptr = sampleExtender[pokey_buffer[myPokeyBufIdx]]; } - sound_buffer[sound_idx] = lastSample; - sound_idx = (sound_idx+1) & (SNDLENGTH-1); } void restore_bottom_screen(void) @@ -296,10 +313,23 @@ byte palette_data[PALETTE_SIZE] = { 0xFF,0xD4,0x61,0xFF,0xDD,0x69,0xFF,0xE6,0x79,0xFF,0xEA,0x98 }; - +char filetmp[256]; int load_os(char *filename ) { FILE *romfile = fopen(filename, "rb"); + + if (romfile == NULL) + { + sprintf(filetmp, "/roms/bios/%s", filename); + romfile = fopen(filetmp, "rb"); + } + + if (romfile == NULL) + { + sprintf(filetmp, "/data/bios/%s", filename); + romfile = fopen(filetmp, "rb"); + } + if (romfile == NULL) { memcpy(atari_os, ROM_altirra_5200_os, 0x800); // No 5200.rom found... use open source Altirra OS instead @@ -341,10 +371,9 @@ void dsLoadGame(char *filename) atari_pal16[index] = index; } - psound_buffer=sound_buffer; - TIMER2_DATA = TIMER_FREQ(SOUND_FREQ); + TIMER2_DATA = TIMER_FREQ((SOUND_FREQ/2)+20); // keep this a little faster than our Pokey sound generation TIMER2_CR = TIMER_DIV_1 | TIMER_IRQ_REQ | TIMER_ENABLE; - irqSet(IRQ_TIMER2, VsoundHandler); + irqSet(IRQ_TIMER2, VsoundHandler); TIMER0_CR=0; TIMER0_DATA=0; @@ -697,15 +726,32 @@ void dsPrintValue(int x, int y, unsigned int isSelect, char *pchStr) //--------------------------------------------------------------------------------- void dsInstallSoundEmuFIFO(void) { + // We are going to use the 16-bit sound engine so we need to scale up our 8-bit values... + for (int i=0; i<256; i++) + { + sampleExtender[i] = (i << 8); + } + + if (isDSiMode()) + { + aptr = (u16*) ((u32)&sound_buffer[0] + 0xA000000); + bptr = (u16*) ((u32)&sound_buffer[2] + 0xA000000); + } + else + { + aptr = (u16*) ((u32)&sound_buffer[0] + 0x00400000); + bptr = (u16*) ((u32)&sound_buffer[2] + 0x00400000); + } + FifoMessage msg; msg.SoundPlay.data = &sound_buffer; - msg.SoundPlay.freq = SOUND_FREQ; + msg.SoundPlay.freq = SOUND_FREQ*2; msg.SoundPlay.volume = 127; msg.SoundPlay.pan = 64; msg.SoundPlay.loop = 1; - msg.SoundPlay.format = ((1)<<4) | SoundFormat_8Bit; + msg.SoundPlay.format = ((1)<<4) | SoundFormat_16Bit; msg.SoundPlay.loopPoint = 0; - msg.SoundPlay.dataSize = SNDLENGTH >> 2; + msg.SoundPlay.dataSize = 4 >> 2; msg.type = EMUARM7_PLAY_SND; fifoSendDatamsg(FIFO_USER_01, sizeof(msg), (u8*)&msg); } @@ -742,9 +788,18 @@ void dsMainLoop(void) { break; case A5200_PLAYINIT: + irqDisable(IRQ_TIMER2); dsShowScreenEmu(); + VsoundClear(); + swiWaitForVBlank();swiWaitForVBlank(); irqEnable(IRQ_TIMER2); + fifoSendValue32(FIFO_USER_01,(1<<16) | (127) | SOUND_SET_VOLUME); etatEmu = A5200_PLAYGAME; + atari_frames=0; + TIMER0_DATA=0; + TIMER0_CR=TIMER_ENABLE|TIMER_DIV_1024; + TIMER1_DATA=0; + TIMER1_CR=TIMER_ENABLE | TIMER_DIV_1024; break; case A5200_PLAYGAME: @@ -803,10 +858,11 @@ void dsMainLoop(void) { iTx = touch.px; iTy = touch.py; if ((iTx>211) && (iTx<250) && (iTy>112) && (iTy<130)) { //quit - irqDisable(IRQ_TIMER2); fifoSendValue32(FIFO_USER_01,(1<<16) | (0) | SOUND_SET_VOLUME); + fifoSendValue32(FIFO_USER_01,(1<<16) | (0) | SOUND_SET_VOLUME); + soundPlaySample(clickNoQuit_wav, SoundFormat_16Bit, clickNoQuit_wav_size, 22050, 127, 64, false, 0); if (dsWaitOnQuit()) etatEmu=A5200_QUITSTDS; - else { irqEnable(IRQ_TIMER2); fifoSendValue32(FIFO_USER_01,(1<<16) | (127) | SOUND_SET_VOLUME); } + else { fifoSendValue32(FIFO_USER_01,(1<<16) | (127) | SOUND_SET_VOLUME);} } else if ((iTx>240) && (iTx<256) && (iTy>0) && (iTy<20)) { // Full Speed Toggle ... upper corner... if (keys_touch == 0) @@ -817,8 +873,10 @@ void dsMainLoop(void) { } } else if ((iTx>160) && (iTx<200) && (iTy>112) && (iTy<130)) { //highscore + fifoSendValue32(FIFO_USER_01,(1<<16) | (0) | SOUND_SET_VOLUME); highscore_display(); restore_bottom_screen(); + fifoSendValue32(FIFO_USER_01,(1<<16) | (127) | SOUND_SET_VOLUME); } else if ((iTx>115) && (iTx<150) && (iTy>112) && (iTy<130)) { //pause if (!keys_touch) soundPlaySample(clickNoQuit_wav, SoundFormat_16Bit, clickNoQuit_wav_size, 22050, 127, 64, false, 0); @@ -845,13 +903,20 @@ void dsMainLoop(void) { keys_touch = 1; } else if ((iTx>70) && (iTx<185) && (iTy>7) && (iTy<50)) { // 72,8 -> 182,42 cartridge slot - irqDisable(IRQ_TIMER2); fifoSendValue32(FIFO_USER_01,(1<<16) | (0) | SOUND_SET_VOLUME); + fifoSendValue32(FIFO_USER_01,(1<<16) | (0) | SOUND_SET_VOLUME); // Find files in current directory and show it a52FindFiles(); romSel=dsWaitForRom(); - if (romSel) { etatEmu=A5200_PLAYINIT; dsLoadGame(a5200romlist[ucFicAct].filename); if (full_speed) dsPrintValue(30,0,0,"FS"); else dsPrintValue(30,0,0," ");} - else { irqEnable(IRQ_TIMER2); } - fifoSendValue32(FIFO_USER_01,(1<<16) | (127) | SOUND_SET_VOLUME); + if (romSel) + { + etatEmu=A5200_PLAYINIT; + dsLoadGame(a5200romlist[ucFicAct].filename); + if (full_speed) dsPrintValue(30,0,0,"FS"); else dsPrintValue(30,0,0," "); + } + else + { + fifoSendValue32(FIFO_USER_01,(1<<16) | (127) | SOUND_SET_VOLUME); + } } } else diff --git a/arm9/source/emu/atari.h b/arm9/source/emu/atari.h index 8208354..793abb2 100644 --- a/arm9/source/emu/atari.h +++ b/arm9/source/emu/atari.h @@ -11,7 +11,7 @@ #define NODIRTYCOMPARE -#define BUILD_BOSCONIAN 1 // Enable this to produce a build that will run fast bankswitching at the expense of 10% slowdown in memory fetches. Renders games like Bosconian fully playable. +//#define BUILD_BOSCONIAN 1 // Enable this to produce a build that will run fast bankswitching at the expense of 10% slowdown in memory fetches. Renders games like Bosconian fully playable. #define PAGED_ATTRIB 1 diff --git a/arm9/source/emu/cartridge.c b/arm9/source/emu/cartridge.c index 15bcbd0..c7825c4 100644 --- a/arm9/source/emu/cartridge.c +++ b/arm9/source/emu/cartridge.c @@ -166,7 +166,7 @@ static const struct cart_t cart_table[] = {"84d88bcdeffee1ab880a5575c6aca45e", CART_5200_NS_16, CTRL_JOY, DIGITAL, ANA_NORMAL, 30, 185, 0, 256, 250, 32,22}, // Millipede (USA) (Proto).a52 {"d859bff796625e980db1840f15dec4b5", CART_5200_NS_16, CTRL_JOY, DIGITAL, ANA_NORMAL, 6, 220, 1, 256, 256, 32,24}, // Miner 2049er Starring Bounty Bob (USA).a52 {"69d472a79f404e49ad2278df3c8a266e", CART_5200_EE_16, CTRL_JOY, DIGITAL, ANA_NORMAL, 6, 220, 0, 256, 240, 32,19}, // Miniature Golf (1983) (Atari).a52 - {"972b6c0dbf5501cacfdc6665e86a796c", CART_5200_8, CTRL_JOY, ANALOG, ANA_SLOWER, 6, 220, 1, 256, 256, 32,22}, // Missile Command (USA).a52 + {"972b6c0dbf5501cacfdc6665e86a796c", CART_5200_8, CTRL_JOY, ANALOG, ANA_SLOWER, 20, 185, 1, 256, 256, 32,24}, // Missile Command (USA).a52 {"3090673bd3f8c04a92e391bf5540b88b", CART_5200_32, CTRL_JOY, ANALOG, ANA_SLOWER, 6, 220, 1, 256, 256, 32,24}, // MC+final.a52 {"694897cc0d98fcf2f59eef788881f67d", CART_5200_EE_16, CTRL_JOY, DIGITAL, ANA_NORMAL, 6, 220, 1, 256, 244, 32,24}, // Montezuma's Revenge featuring Panama Joe (USA).a52 {"296e5a3a9efd4f89531e9cf0259c903d", CART_5200_NS_16, CTRL_JOY, DIGITAL, ANA_NORMAL, 6, 220, 1, 256, 256, 32,24}, // Moon Patrol (USA).a52 @@ -263,7 +263,6 @@ static const struct cart_t cart_table[] = }; - UBYTE *cart_image = NULL; /* For cartridge memory */ char cart_filename[FILENAME_MAX]; struct cart_t myCart __attribute__((section(".dtcm"))) = {"", CART_5200_32, CTRL_JOY, 0,0,0,0}; @@ -495,7 +494,7 @@ void CART_Remove(void) cart_image = NULL; dFillMem(0x0000, 0, 0xC000); memset(pokey_buffer, 0x00, SNDLENGTH); - memset(sound_buffer, 0x00, SNDLENGTH); + memset(sound_buffer, 0x00, SNDLENGTH); SetROM(0x4000, 0xbfff); /* Set the entire 32k back to normal ROM */ bosconian_bank = 0; } @@ -535,7 +534,7 @@ void CART_Start(void) CopyROM(0x5000, 0x5fff, cart_image + 0x4000); CopyROM(0x8000, 0x9fff, cart_image + 0x8000); CopyROM(0xa000, 0xbfff, cart_image + 0x8000); - for (int i=0x0000; i<0x8000; i++) banked_image[i] = cart_image[i]; + memcpy(banked_image, cart_image, 0x8000); last_bounty_bob_bank = -1; for (int i=0x4ff6; i<=0x4ff9; i++) readmap[i] = BountyBob1_GetByte; for (int i=0x5ff6; i<=0x5ff9; i++) readmap[i] = BountyBob2_GetByte; @@ -544,14 +543,14 @@ void CART_Start(void) break; case CART_5200_64: bryan_bank = 1; last_bryan_bank=1; - for (int i=0x0000; i<=0xFFFF; i++) banked_image[i] = cart_image[i]; + memcpy(banked_image, cart_image, 0x10000); CopyROM(0x4000, 0xbfff, cart_image + (0x8000 * bryan_bank)); for (int i=0xbfd0; i<= 0xbfdf; i++) readmap[i] = Bryan_GetByte64; for (int i=0xbfe0; i<= 0xbfff; i++) readmap[i] = Bryan_GetByte64_reset; break; case CART_5200_512: bryan_bank = 15; last_bryan_bank=15; - for (int i=0x0000; i<0x40000; i++) banked_image[i] = cart_image[i+(0x8000*12)]; // We can copy the first (last!) 4 banks into faster ram... it helps... + memcpy(banked_image, cart_image+(0x8000*12), 0x40000); CopyROM(0x4000, 0xbfff, cart_image + (0x8000L * (long)bryan_bank)); for (int i=0xbfc0; i<= 0xbfff; i++) readmap[i] = Bryan_GetByte512; #ifdef BUILD_BOSCONIAN diff --git a/arm9/source/emu/input.c b/arm9/source/emu/input.c index 5835716..8b1c971 100644 --- a/arm9/source/emu/input.c +++ b/arm9/source/emu/input.c @@ -44,6 +44,7 @@ #include "input_win.h" #endif +extern int debug[]; #ifdef DREAMCAST extern int Atari_POT(int); #else @@ -231,8 +232,9 @@ void INPUT_Frame(void) { if (myCart.use_analog) { - if (PCPOT_input[2 * i] >joy_5200_min) PCPOT_input[2 * i] -= anlaog_speed_map[myCart.analog_speed][input_frame & 1]; - if (PCPOT_input[2 * i] <=joy_5200_min) PCPOT_input[2 * i]= joy_5200_min; + if (PCPOT_input[2 * i] >myCart.digital_min) PCPOT_input[2 * i] -= anlaog_speed_map[myCart.analog_speed][input_frame & 1]; + if (PCPOT_input[2 * i] <=myCart.digital_min) PCPOT_input[2 * i]= myCart.digital_min; + debug[0] = PCPOT_input[2 * i]; } else PCPOT_input[2 * i]= myCart.digital_min; @@ -241,8 +243,9 @@ void INPUT_Frame(void) { if (myCart.use_analog) { - if (PCPOT_input[2 * i] =joy_5200_max) PCPOT_input[2 * i]= joy_5200_max; + if (PCPOT_input[2 * i] =myCart.digital_max) PCPOT_input[2 * i]= myCart.digital_max; + debug[0] = PCPOT_input[2 * i]; } else PCPOT_input[2 * i]= myCart.digital_max; @@ -253,24 +256,30 @@ void INPUT_Frame(void) } - if ((STICK[i] & (STICK_CENTRE ^ STICK_FORWARD)) == 0) { - if (myCart.use_analog) { - if (PCPOT_input[2 * i +1] >joy_5200_min) PCPOT_input[2 * i +1] -= anlaog_speed_map[myCart.analog_speed][input_frame & 1]; - if (PCPOT_input[2 * i +1] <=joy_5200_min) PCPOT_input[2 * i +1]= joy_5200_min; + if ((STICK[i] & (STICK_CENTRE ^ STICK_FORWARD)) == 0) + { + if (myCart.use_analog) + { + if (PCPOT_input[2 * i +1] >myCart.digital_min) PCPOT_input[2 * i +1] -= anlaog_speed_map[myCart.analog_speed][input_frame & 1]; + if (PCPOT_input[2 * i +1] <=myCart.digital_min) PCPOT_input[2 * i +1]= myCart.digital_min; + debug[1] = PCPOT_input[2 * i +1]; } - else { + else PCPOT_input[2 * i +1]= myCart.digital_min; - } } - else if ((STICK[i] & (STICK_CENTRE ^ STICK_BACK)) == 0) { - if (myCart.use_analog) { - if (PCPOT_input[2 * i +1] =joy_5200_max) PCPOT_input[2 * i +1]= joy_5200_max; + else if ((STICK[i] & (STICK_CENTRE ^ STICK_BACK)) == 0) + { + if (myCart.use_analog) + { + if (PCPOT_input[2 * i +1] =myCart.digital_max) PCPOT_input[2 * i +1]= myCart.digital_max; + debug[1] = PCPOT_input[2 * i +1]; } else PCPOT_input[2 * i +1]= myCart.digital_max; } - else { + else + { if (!myCart.use_analog) PCPOT_input[2 * i + 1] = joy_5200_center; } } diff --git a/arm9/source/emu/pokey.c b/arm9/source/emu/pokey.c index 4d2b499..c289338 100644 --- a/arm9/source/emu/pokey.c +++ b/arm9/source/emu/pokey.c @@ -21,7 +21,7 @@ * along with Atari800; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - +#include #include "config.h" #include "atari.h" #include "cpu.h" @@ -35,7 +35,7 @@ #include "antic.h" #include "cassette.h" -int pokeyBufIdx __attribute__((section(".dtcm")))= 0; +unsigned short pokeyBufIdx __attribute__((section(".dtcm")))= 0; char pokey_buffer[SNDLENGTH] __attribute__((section(".dtcm"))); UBYTE KBCODE __attribute__((section(".dtcm"))); @@ -403,6 +403,12 @@ void Update_Counter(int chan_mask) } } +void PokeyClearBuffer(void) +{ + memset(pokey_buffer, 0x00, SNDLENGTH); + pokeyBufIdx = 0; +} + void POKEYStateSave(void) { } diff --git a/readme.txt b/readme.txt index ffdd326..024e3d7 100644 --- a/readme.txt +++ b/readme.txt @@ -2,16 +2,19 @@ a5200DS -------------------------------------------------------------------------------- a5200DS is an Atari VCS 5200 console emulator. To use this emulator, you must use NTSC compatible roms with a52/bin format. -You also need the 5200.rom rom bios in the same folder as A5200DS.NDS to use -this emulator properly (there is a built-in open-source replacement BIOS which -will work for many games but doesn't have full compatibilty so it is still -recommended you use 5200.bin). A quick search on atariage website -will help you about that ;-) Do not ask me about such files, I don't have them. +You also need the 5200.rom rom bios in the same folder as A5200DS.NDS (alternate +locations it can be: /roms/bios or /data/bios) to use this emulator properly +(there is a built-in open-source replacement BIOS which will work for some +games but doesn't have full compatibilty so it is still strongly recommended +you use 5200.bin). A quick search on atariage website will help you about that. +Do not ask me about such files, I don't have them. Features : ---------- Most things you should expect from an emulator. Most games run at full speed on a DSi or above. + For the DS-LITE/PHAT many games will play but there may + be some lag in sound/speed for the more complex games. Missing : --------- @@ -25,8 +28,9 @@ Check updates on my web site : https://github.com/wavemotion-dave/A5200DS -------------------------------------------------------------------------------- History : -------------------------------------------------------------------------------- -V3.0 : xxx - * Bosconian Build enabled by default! +V3.0 : 04-Nov-2021 + * New sound core to eliminate zingers. + * 5200.rom bios can be in /roms/bios or /data/bios V2.9 : 22-July-2021 by wavemotion-dave * High Score support added!