void resetRSID() { sProgramMode= MAIN_OFFSET_MASK; sMainLoopOnlyMode= 0; sTodInMillies= 0; // some IRQ players don't finish within one screen, e.g. A-Maze-Ing.sid and Axel_F.sid // (Sean Connolly) even seems to play digis during multi-screen IRQs (so give them more time) setIrqTimeout(getCyclesPerScreen()*4); // reset IO area resetIO(getCyclesPerScreen(), isRsid()); }
static int EMSCRIPTEN_KEEPALIVE playTune(int selectedTrack) { sActualSubsong= selectedTrack; reInitEngine(); synth_init(sSampleRate); initClockSpeed(); initSampleBuffer(); initC64Rom(); // reset & init memcpy(memory, sMemorySnapshot, MEMORY_SIZE); // restore original mem content.. previous "sInitAddr" run may have corrupted the state // CIA 1 defaults (by default C64 is configured with CIA1 timer / not raster irq) setIO(0xdc0d, 0x81); // interrupt control (interrupt through timer A) setIO(0xdc0e, 0x01); // control timer A: start - must already be started (e.g. Phobia, GianaSisters, etc expect it) setIO(0xdc0f, 0x08); // control timer B (start/stop) means auto-restart setIO(0xdc04, sTotalCyclesPerScreen&0xff); // timer A (1x pro screen refresh) setIO(0xdc05, sTotalCyclesPerScreen>>8); if (isRsid()) { // by default C64 is configured with CIA1 timer / not raster irq setIO(0xd01a, 0x00); // raster irq not active setIO(0xd011, 0x1B); setIO(0xd012, 0x00); // raster at line x // CIA 2 defaults setIO(0xdd0e, 0x08); // control timer 2A (start/stop) setIO(0xdd0f, 0x08); // control timer 2B (start/stop) } setupInitMemoryBank(); initCia(); initVic(); sOverflowDigiCount=0; sDigiCount=0; hackIfNeeded(); sMainProgStatus= callMain(sInitAddr, sActualSubsong, 0, CYCLELIMIT); // if it does not complete then it is likely in an endless loop / maybe digi player initBuffers(); setupPsidPlayMemoryBank(); return 0; }
static int EMSCRIPTEN_KEEPALIVE loadSidFile(void * inBuffer, int inBufSize) { sSampleRate= 44100; // TODO: extend API & use actual target sample rate sInitAddr= 0; sPlayAddr= 0; sLoadEndAddr= 0; sActualSubsong= 0; sMaxSubsong= 0; sPlaySpeed= 0; sNtscMode= 0; unsigned char sidmem[65536]; unsigned char *buffer = sidmem; memcpy(buffer, inBuffer, inBufSize); sIsPSID= (buffer[0x00]==0x50?1:0); sSidVersion= buffer[0x05]; sIsC64compatible= (sSidVersion & 0x2) && ((buffer[0x77] & 0x2) == 0); sNtscMode= (sSidVersion == 2) && !isRsid() && (buffer[0x77] & 0x8); // NTSC bit int i; for (i=0;i<32;i++) song_name[i] = buffer[0x16+i]; for (i=0;i<32;i++) song_author[i] = buffer[0x36+i]; for (i=0;i<32;i++) song_copyright[i] = buffer[0x56+i]; unsigned short load_addr; LoadSIDFromMemory(sidmem, &load_addr, &sLoadEndAddr, &sInitAddr, &sPlayAddr, &sMaxSubsong, &sActualSubsong, &sPlaySpeed, inBufSize); memcpy(sMemorySnapshot, memory, MEMORY_SIZE); loadResult[0]= &load_addr; loadResult[1]= &sPlaySpeed; loadResult[2]= &sMaxSubsong; loadResult[3]= &sActualSubsong; loadResult[4]= song_name; loadResult[5]= song_author; loadResult[6]= song_copyright; return 0; }
static void setupInitMemoryBank() { unsigned char memBankSetting= 0x37; // default memory config: basic ROM, IO area & kernal ROM visible if (!isRsid()) { // problem: some PSID init routines want to initialize registers in the IO area while others // actually expect to use the RAM in that area.. none of them setup the memory banks accordingly :( if ((sInitAddr >= 0xd000) && (sInitAddr < 0xe000)) { memBankSetting= 0x34; // default memory config: all RAM } else if ((sInitAddr >= 0xe000)) { // PSIDv2 songs like IK_plus.sid, Pandora.sid use the ROM below the kernal *without* setting 0x0001 // so obviously here we must use a default like this: memBankSetting= 0x35; // default memory config: IO area visible, RAM $a000-b000 + $e000-$ffff } else if (sLoadEndAddr >= 0xa000) { memBankSetting= 0x36; } else { // normally the kernal ROM should be visible: e.g. A-Maz-Ing.sid uses kernal ROM routines & vectors // without setting $01! memBankSetting= 0x37; // default memory config: basic ROM, IO area & kernal ROM visible } } memory[0x0001]= memBankSetting; }