From 10f249cb763ddc00cd80e1d47940784e25d3e4a7 Mon Sep 17 00:00:00 2001 From: Shamus Hammons Date: Tue, 1 May 2012 12:07:31 +0000 Subject: [PATCH] Initial stab at getting the DSP to run in the host audio IRQ. Needs testing. --- src/dac.cpp | 190 +++++++++++++++++++++- src/dac.h | 3 + src/dsp.cpp | 5 + src/dsp.h | 1 + src/event.cpp | 384 ++++++++++++++++++++++++++------------------ src/event.h | 12 +- src/gui/mainwin.cpp | 3 + src/jaguar.cpp | 95 ++--------- src/jerry.cpp | 261 +++--------------------------- src/memory.cpp | 2 + 10 files changed, 470 insertions(+), 486 deletions(-) diff --git a/src/dac.cpp b/src/dac.cpp index 9836807..be6c3ae 100644 --- a/src/dac.cpp +++ b/src/dac.cpp @@ -50,16 +50,21 @@ #include "dac.h" #include "SDL.h" -//#include "gui.h" +#include "cdrom.h" +#include "dsp.h" +#include "event.h" +#include "jerry.h" #include "jaguar.h" #include "log.h" #include "m68k.h" //#include "memory.h" #include "settings.h" + //#define DEBUG_DAC -#define BUFFER_SIZE 0x10000 // Make the DAC buffers 64K x 16 bits +#define BUFFER_SIZE 0x10000 // Make the DAC buffers 64K x 16 bits +#define DAC_AUDIO_RATE 48000 // Set the audio rate to 48 KHz // Jaguar memory locations @@ -72,7 +77,7 @@ // Global variables -//uint16 lrxd, rrxd; // I2S ports (into Jaguar) +//uint16 lrxd, rrxd; // I2S ports (into Jaguar) // Local variables @@ -84,12 +89,15 @@ static bool SDLSoundInitialized; // endian when looking at the sample buffer, i.e., no need to worry about it. static uint16 DACBuffer[BUFFER_SIZE]; -static uint8 SCLKFrequencyDivider = 19; // Default is roughly 22 KHz (20774 Hz in NTSC mode) +static uint8 SCLKFrequencyDivider = 19; // Default is roughly 22 KHz (20774 Hz in NTSC mode) /*static*/ uint16 serialMode = 0; // Private function prototypes void SDLSoundCallback(void * userdata, Uint8 * buffer, int length); +void SDLSoundCallbackNew(void * userdata, Uint8 * buffer, int length); +void DSPSampleCallback(void); + // // Initialize the SDL sound system @@ -104,6 +112,13 @@ void DACInit(void) return; } +#ifdef NEW_DAC_CODE + desired.freq = DAC_AUDIO_RATE; + desired.format = AUDIO_S16SYS; + desired.channels = 2; + desired.samples = 2048; + desired.callback = SDLSoundCallbackNew; +#else // memory_malloc_secure((void **)&DACBuffer, BUFFER_SIZE * sizeof(uint16), "DAC buffer"); // DACBuffer = (uint16 *)memory_malloc(BUFFER_SIZE * sizeof(uint16), "DAC buffer"); @@ -113,6 +128,7 @@ void DACInit(void) // desired.samples = 4096; // Let's try a 4K buffer (can always go lower) desired.samples = 2048; // Let's try a 2K buffer (can always go lower) desired.callback = SDLSoundCallback; +#endif if (SDL_OpenAudio(&desired, NULL) < 0) // NULL means SDL guarantees what we want WriteLog("DAC: Failed to initialize SDL sound...\n"); @@ -120,19 +136,28 @@ void DACInit(void) { SDLSoundInitialized = true; DACReset(); - SDL_PauseAudio(false); // Start playback! - WriteLog("DAC: Successfully initialized.\n"); + SDL_PauseAudio(false); // Start playback! + WriteLog("DAC: Successfully initialized. Sample rate: %u\n", desired.freq); } + + ltxd = lrxd = desired.silence; + + uint32_t riscClockRate = (vjs.hardwareTypeNTSC ? RISC_CLOCK_RATE_NTSC : RISC_CLOCK_RATE_PAL); + uint32_t cyclesPerSample = riscClockRate / DAC_AUDIO_RATE; + WriteLog("DAC: RISC clock = %u, cyclesPerSample = %u\n", riscClockRate, cyclesPerSample); } + // // Reset the sound buffer FIFOs // void DACReset(void) { LeftFIFOHeadPtr = LeftFIFOTailPtr = 0, RightFIFOHeadPtr = RightFIFOTailPtr = 1; + ltxd = lrxd = desired.silence; } + // // Close down the SDL sound subsystem // @@ -162,6 +187,138 @@ void DACDone(void) // SDL callback routine to fill audio buffer // // Note: The samples are packed in the buffer in 16 bit left/16 bit right pairs. +// Also, length is the length of the buffer in BYTES +// +//static double timePerSample = 0; +static Uint8 * sampleBuffer; +static int bufferIndex = 0; +static int numberOfSamples = 0; +static bool bufferDone = false; +void SDLSoundCallbackNew(void * userdata, Uint8 * buffer, int length) +{ + // 1st, check to see if the DSP is running. If not, fill the buffer with L/RXTD and exit. + + if (!DSPIsRunning()) + { + for(int i=0; i<(length/2); i+=2) + { + ((uint16_t *)buffer)[i + 0] = ltxd; + ((uint16_t *)buffer)[i + 1] = rtxd; + } + + return; + } + + // The length of time we're dealing with here is 1/48000 s, so we multiply this + // by the number of cycles per second to get the number of cycles for one sample. + uint32_t riscClockRate = (vjs.hardwareTypeNTSC ? RISC_CLOCK_RATE_NTSC : RISC_CLOCK_RATE_PAL); + uint32_t cyclesPerSample = riscClockRate / DAC_AUDIO_RATE; + // This is the length of time +// timePerSample = (1000000.0 / (double)riscClockRate) * (); + + // Now, run the DSP for that length of time for each sample we need to make + +#if 0 + for(int i=0; i<(length/2); i+=2) + { +//This stuff is from the old Jaguar execute loop. New stuff is timer based... +//which means we need to figure that crap out, and how to make it work here. +//Seems like we need two separate timing queues. Tho not sure how to make that work here... +//Maybe like the "frameDone" in JaguarExecuteNew() in jaguar.cpp? +// JERRYExecPIT(cyclesPerSample); +// JERRYI2SExec(cyclesPerSample); +// BUTCHExec(cyclesPerSample); + + if (vjs.DSPEnabled) + { + if (vjs.usePipelinedDSP) + DSPExecP2(cyclesPerSample); + else + DSPExec(cyclesPerSample); + } + + ((uint16_t *)buffer)[i + 0] = ltxd; + ((uint16_t *)buffer)[i + 1] = rtxd; + } +#else + bufferIndex = 0; + sampleBuffer = buffer; + numberOfSamples = length / 2; + bufferDone = false; + + SetCallbackTime(DSPSampleCallback, 1000000.0 / (double)DAC_AUDIO_RATE, EVENT_JERRY); + + // These timings are tied to NTSC, need to fix that in event.cpp/h! + do + { + double timeToNextEvent = GetTimeToNextEvent(EVENT_JERRY); + + if (vjs.DSPEnabled) + { + if (vjs.usePipelinedDSP) + DSPExecP2(USEC_TO_RISC_CYCLES(timeToNextEvent)); + else + DSPExec(USEC_TO_RISC_CYCLES(timeToNextEvent)); + } + + HandleNextEvent(EVENT_JERRY); + } + while (!bufferDone); + + // We do this to prevent problems with trying to write past the end of the buffer... +// RemoveCallback(DSPSampleCallback); +#endif +} + + +void DSPSampleCallback(void) +{ + ((uint16_t *)sampleBuffer)[bufferIndex + 0] = ltxd; + ((uint16_t *)sampleBuffer)[bufferIndex + 1] = rtxd; + bufferIndex += 2; + + if (bufferIndex == numberOfSamples) + { + bufferDone = true; + return; + } + + SetCallbackTime(DSPSampleCallback, 1000000.0 / (double)DAC_AUDIO_RATE, EVENT_JERRY); +} +#if 0 + frameDone = false; + + do + { + double timeToNextEvent = GetTimeToNextEvent(); +//WriteLog("JEN: Time to next event (%u) is %f usec (%u RISC cycles)...\n", nextEvent, timeToNextEvent, USEC_TO_RISC_CYCLES(timeToNextEvent)); + + m68k_execute(USEC_TO_M68K_CYCLES(timeToNextEvent)); + + if (vjs.GPUEnabled) + GPUExec(USEC_TO_RISC_CYCLES(timeToNextEvent)); + +#ifndef NEW_DAC_CODE + if (vjs.DSPEnabled) + { + if (vjs.usePipelinedDSP) + DSPExecP2(USEC_TO_RISC_CYCLES(timeToNextEvent)); // Pipelined DSP execution (3 stage)... + else + DSPExec(USEC_TO_RISC_CYCLES(timeToNextEvent)); // Ordinary non-pipelined DSP + } +#endif + + HandleNextEvent(); + } + while (!frameDone); +#endif + + +// +// SDL callback routine to fill audio buffer +// +// Note: The samples are packed in the buffer in 16 bit left/16 bit right pairs. +// Also, length is the length of the buffer in BYTES // void SDLSoundCallback(void * userdata, Uint8 * buffer, int length) { @@ -219,6 +376,7 @@ if (numLeftSamplesReady == 0 || numRightSamplesReady == 0) // WriteLog("DAC: Silence...!\n"); } + // // Calculate the frequency of SCLK * 32 using the divider // @@ -231,10 +389,13 @@ int GetCalculatedFrequency(void) return systemClockFrequency / (32 * (2 * (SCLKFrequencyDivider + 1))); } + static int oldFreq = 0; void DACSetNewFrequency(int freq) { +#ifdef NEW_DAC_CODE +#else if (freq == oldFreq) return; @@ -267,8 +428,10 @@ void DACSetNewFrequency(int freq) if (SDLSoundInitialized) SDL_PauseAudio(false); // Start playback! +#endif } + // // LTXD/RTXD/SCLK/SMODE ($F1A148/4C/50/54) // @@ -279,12 +442,17 @@ void DACWriteByte(uint32 offset, uint8 data, uint32 who/*= UNKNOWN*/) DACWriteWord(offset - 3, (uint16)data); } + void DACWriteWord(uint32 offset, uint16 data, uint32 who/*= UNKNOWN*/) { if (offset == LTXD + 2) { if (!SDLSoundInitialized) return; + +#ifdef NEW_DAC_CODE + ltxd = data; +#else // Spin until buffer has been drained (for too fast processors!)... //Small problem--if Head == 0 and Tail == buffer end, then this will fail... !!! FIX !!! //[DONE] @@ -321,6 +489,7 @@ WriteLog("Tail=%X, Head=%X", ltail, lhead); LeftFIFOTailPtr = (LeftFIFOTailPtr + 2) % BUFFER_SIZE; DACBuffer[LeftFIFOTailPtr] = data; SDL_UnlockAudio(); +#endif } else if (offset == RTXD + 2) { @@ -381,6 +550,9 @@ LTail=60D8, LHead=60D8, BUFFER_SIZE-1=FFFF RTail=DB, RHead=60D9, BUFFER_SIZE-1=FFFF From while: Tail=60DA, Head=60D8 */ +#ifdef NEW_DAC_CODE + rtxd = data; +#else #warning Spinlock problem--!!! FIX !!! #warning Odd: The right FIFO is empty, but the left FIFO is full! // Spin until buffer has been drained (for too fast processors!)... @@ -416,6 +588,7 @@ WriteLog("Tail=%X, Head=%X", rtail, rhead); else WriteLog("DAC: Ran into FIFO's right tail pointer!\n"); #endif*/ +#endif } else if (offset == SCLK + 2) // Sample rate { @@ -423,6 +596,8 @@ WriteLog("Tail=%X, Head=%X", rtail, rhead); if ((uint8)data != SCLKFrequencyDivider) { SCLKFrequencyDivider = (uint8)data; +#ifdef NEW_DAC_CODE +#else //Of course a better way would be to query the hardware to find the upper limit... if (data > 7) // Anything less than 8 is too high! { @@ -452,6 +627,7 @@ WriteLog("Tail=%X, Head=%X", rtail, rhead); if (SDLSoundInitialized) SDL_PauseAudio(false); // Start playback! } +#endif } } else if (offset == SMODE + 2) @@ -465,6 +641,7 @@ WriteLog("Tail=%X, Head=%X", rtail, rhead); } } + // // LRXD/RRXD/SSTAT ($F1A148/4C/50) // @@ -474,6 +651,7 @@ uint8 DACReadByte(uint32 offset, uint32 who/*= UNKNOWN*/) return 0xFF; } + //static uint16 fakeWord = 0; uint16 DACReadWord(uint32 offset, uint32 who/*= UNKNOWN*/) { diff --git a/src/dac.h b/src/dac.h index 023855f..ef30549 100644 --- a/src/dac.h +++ b/src/dac.h @@ -5,6 +5,9 @@ #ifndef __DAC_H__ #define __DAC_H__ +//this is here, because we have to compensate in more than just dac.cpp... +#define NEW_DAC_CODE // New code paths! + //#include "types.h" #include "memory.h" diff --git a/src/dsp.cpp b/src/dsp.cpp index 7db98ae..d321d47 100644 --- a/src/dsp.cpp +++ b/src/dsp.cpp @@ -1280,6 +1280,11 @@ DSPHandleIRQsNP(); // GPUSetIRQLine(GPUIRQ_DSP, ASSERT_LINE); } +bool DSPIsRunning(void) +{ + return (DSP_RUNNING ? true : false); +} + void DSPInit(void) { // memory_malloc_secure((void **)&dsp_ram_8, 0x2000, "DSP work RAM"); diff --git a/src/dsp.h b/src/dsp.h index 44e8b70..67e5299 100644 --- a/src/dsp.h +++ b/src/dsp.h @@ -25,6 +25,7 @@ void DSPWriteByte(uint32 offset, uint8 data, uint32 who = UNKNOWN); void DSPWriteWord(uint32 offset, uint16 data, uint32 who = UNKNOWN); void DSPWriteLong(uint32 offset, uint32 data, uint32 who = UNKNOWN); void DSPReleaseTimeslice(void); +bool DSPIsRunning(void); void DSPExecP(int32 cycles); void DSPExecP2(int32 cycles); diff --git a/src/event.cpp b/src/event.cpp index b455cd6..a923f37 100644 --- a/src/event.cpp +++ b/src/event.cpp @@ -20,51 +20,12 @@ #include "event.h" #include "log.h" +#include "types.h" -#define EVENT_LIST_SIZE 512 -/* -// Current execution path: - -do -{ - HandleJoystick - - // Execute one frame - - for(int i=0; i 0 && TOMIRQEnabled(IRQ_VIDEO)) // Time for Vertical Interrupt? - { - // We don't have to worry about autovectors & whatnot because the Jaguar - // tells you through its HW registers who sent the interrupt... - TOMSetPendingVideoInt(); - m68k_set_irq(2); - } - -//if (start_logging) -// WriteLog("About to execute M68K (%u)...\n", i); - m68k_execute(M68KCyclesPerScanline); -//if (start_logging) -// WriteLog("About to execute TOM's PIT (%u)...\n", i); - TOMExecPIT(RISCCyclesPerScanline); -//if (start_logging) -// WriteLog("About to execute JERRY's PIT (%u)...\n", i); - JERRYExecPIT(RISCCyclesPerScanline); -//if (start_logging) -// WriteLog("About to execute JERRY's SSI (%u)...\n", i); - JERRYI2SExec(RISCCyclesPerScanline); - BUTCHExec(RISCCyclesPerScanline); -//if (start_logging) -// WriteLog("About to execute GPU (%u)...\n", i); - if (vjs.GPUEnabled) - GPUExec(RISCCyclesPerScanline); - - if (vjs.DSPEnabled) - { - if (vjs.usePipelinedDSP) - DSPExecP2(RISCCyclesPerScanline); // Pipelined DSP execution (3 stage)... - else - DSPExec(RISCCyclesPerScanline); // Ordinary non-pipelined DSP -// DSPExecComp(RISCCyclesPerScanline); // Comparison core - } - -//if (start_logging) -// WriteLog("About to execute OP (%u)...\n", i); - TOMExecHalfline(i, render); - } -} // Temp debugging stuff @@ -2008,11 +1925,13 @@ void DumpMainMemory(void) fclose(fp); } + uint8 * GetRamPtr(void) { return jaguarMainRAM; } + // // New Jaguar execution stack // This executes 1 frame's worth of code. @@ -2032,6 +1951,7 @@ void JaguarExecuteNew(void) if (vjs.GPUEnabled) GPUExec(USEC_TO_RISC_CYCLES(timeToNextEvent)); +#ifndef NEW_DAC_CODE if (vjs.DSPEnabled) { if (vjs.usePipelinedDSP) @@ -2039,12 +1959,14 @@ void JaguarExecuteNew(void) else DSPExec(USEC_TO_RISC_CYCLES(timeToNextEvent)); // Ordinary non-pipelined DSP } +#endif HandleNextEvent(); } while (!frameDone); } + #define USE_CORRECT_PAL_TIMINGS // A lot of confusion comes from here... // The thing to keep in mind is that the VC is advanced every HALF line, regardless @@ -2129,6 +2051,7 @@ void HalflineCallback(void) #endif } + // This isn't currently used, but maybe it should be... /* Nah, the scanline based code is good enough, and runs in 1 frame. The GUI diff --git a/src/jerry.cpp b/src/jerry.cpp index d0d44af..0b44b8f 100644 --- a/src/jerry.cpp +++ b/src/jerry.cpp @@ -170,7 +170,6 @@ #include "wavetable.h" //Note that 44100 Hz requires samples every 22.675737 usec. -#define NEW_TIMER_SYSTEM //#define JERRY_DEBUG /*static*/ uint8 jerry_ram_8[0x10000]; @@ -193,6 +192,7 @@ uint32 jerryIntPending; static uint16 jerryInterruptMask = 0; static uint16 jerryPendingInterrupt = 0; + // Private function prototypes void JERRYResetPIT1(void); @@ -203,100 +203,6 @@ void JERRYPIT1Callback(void); void JERRYPIT2Callback(void); void JERRYI2SCallback(void); -//This approach is probably wrong, since the timer is continuously counting down, though -//it might only be a problem if the # of interrupts generated is greater than 1--the M68K's -//timeslice should be running during that phase... (The DSP needs to be aware of this!) - -//This is only used by the old system, so once the new timer system is working this -//should be safe to nuke. -void JERRYI2SExec(uint32 cycles) -{ -#ifndef NEW_TIMER_SYSTEM -#warning "externed var in source--should be in header file. !!! FIX !!!" - extern uint16 serialMode; // From DAC.CPP - if (serialMode & 0x01) // INTERNAL flag (JERRY is master) - { - - // Why is it called this? Instead of SCLK? Shouldn't this be read from DAC.CPP??? -//Yes, it should. !!! FIX !!! - JERRYI2SInterruptDivide &= 0xFF; - - if (JERRYI2SInterruptTimer == -1) - { - // We don't have to divide the RISC clock rate by this--the reason is a bit - // convoluted. Will put explanation here later... -// What's needed here is to find the ratio of the frequency to the number of clock cycles -// in one second. For example, if the sample rate is 44100, we divide the clock rate by -// this: 26590906 / 44100 = 602 cycles. -// Which means, every 602 cycles that go by we have to generate an interrupt. - jerryI2SCycles = 32 * (2 * (JERRYI2SInterruptDivide + 1)); - } - - JERYI2SInterruptTimer -= cycles; - if (JERRYI2SInterruptTimer <= 0) - { -//This is probably wrong as well (i.e., need to check enable lines)... !!! FIX !!! - DSPSetIRQLine(DSPIRQ_SSI, ASSERT_LINE); - JERRYI2SInterruptTimer += jerryI2SCycles; -#ifdef JERRY_DEBUG - if (JERRYI2SInterruptTimer < 0) - WriteLog("JERRY: Missed generating an interrupt (missed %u)!\n", (-JERRYI2SInterruptTimer / jerryI2SCycles) + 1); -#endif - } - } - else // JERRY is slave to external word clock - { - // This is just a temporary kludge to see if the CD bus mastering works - // I.e., this is totally faked...! -// The whole interrupt system is pretty much borked and is need of an overhaul. -// What we need is a way of handling these interrupts when they happen instead of -// scanline boundaries the way it is now. - JERRYI2SInterruptTimer -= cycles; - if (JERRYI2SInterruptTimer <= 0) - { -//This is probably wrong as well (i.e., need to check enable lines)... !!! FIX !!! [DONE] - if (ButchIsReadyToSend())//Not sure this is right spot to check... - { -// return GetWordFromButchSSI(offset, who); - SetSSIWordsXmittedFromButch(); - DSPSetIRQLine(DSPIRQ_SSI, ASSERT_LINE); - } - JERRYI2SInterruptTimer += 602; - } - } -#else - RemoveCallback(JERRYI2SCallback); - JERRYI2SCallback(); -#endif -} - -//NOTE: This is only used by the old execution core. Safe to nuke once it's stable. -void JERRYExecPIT(uint32 cycles) -{ -//This is wrong too: Counters are *always* spinning! !!! FIX !!! [DONE] -// if (jerry_timer_1_counter) - jerry_timer_1_counter -= cycles; - - if (jerry_timer_1_counter <= 0) - { -//Also, it can generate a CPU interrupt as well... !!! FIX !!! or does it? Maybe it goes Timer->GPU->CPU? - DSPSetIRQLine(DSPIRQ_TIMER0, ASSERT_LINE); // This does the 'IRQ enabled' checking... -// JERRYResetPIT1(); - jerry_timer_1_counter += (JERRYPIT1Prescaler + 1) * (JERRYPIT1Divider + 1); - } - -//This is wrong too: Counters are *always* spinning! !!! FIX !!! [DONE] -// if (jerry_timer_2_counter) - jerry_timer_2_counter -= cycles; - - if (jerry_timer_2_counter <= 0) - { -//Also, it can generate a CPU interrupt as well... !!! FIX !!! or does it? Maybe it goes Timer->GPU->CPU? - DSPSetIRQLine(DSPIRQ_TIMER1, ASSERT_LINE); // This does the 'IRQ enabled' checking... -// JERRYResetPIT2(); - jerry_timer_2_counter += (JERRYPIT2Prescaler + 1) * (JERRYPIT2Divider + 1); - } -} void JERRYResetI2S(void) { @@ -306,54 +212,31 @@ void JERRYResetI2S(void) JERRYI2SInterruptTimer = -1; } + void JERRYResetPIT1(void) { -#ifndef NEW_TIMER_SYSTEM -/* if (!JERRYPIT1Prescaler || !JERRYPIT1Divider) - jerry_timer_1_counter = 0; - else//*/ -//Small problem with this approach: Overflow if both are = $FFFF. !!! FIX !!! - jerry_timer_1_counter = (JERRYPIT1Prescaler + 1) * (JERRYPIT1Divider + 1); - -// if (jerry_timer_1_counter) -// WriteLog("jerry: reseting timer 1 to 0x%.8x (%i)\n",jerry_timer_1_counter,jerry_timer_1_counter); - -#else RemoveCallback(JERRYPIT1Callback); if (JERRYPIT1Prescaler | JERRYPIT1Divider) { double usecs = (float)(JERRYPIT1Prescaler + 1) * (float)(JERRYPIT1Divider + 1) * RISC_CYCLE_IN_USEC; - SetCallbackTime(JERRYPIT1Callback, usecs); + SetCallbackTime(JERRYPIT1Callback, usecs, EVENT_JERRY); } -#endif } + void JERRYResetPIT2(void) { -#ifndef NEW_TIMER_SYSTEM -/* if (!JERRYPIT2Prescaler || !JERRYPIT2Divider) - { - jerry_timer_2_counter = 0; - return; - } - else//*/ - jerry_timer_2_counter = (JERRYPIT2Prescaler + 1) * (JERRYPIT2Divider + 1); - -// if (jerry_timer_2_counter) -// WriteLog("jerry: reseting timer 2 to 0x%.8x (%i)\n",jerry_timer_2_counter,jerry_timer_2_counter); - -#else RemoveCallback(JERRYPIT2Callback); if (JERRYPIT1Prescaler | JERRYPIT1Divider) { double usecs = (float)(JERRYPIT2Prescaler + 1) * (float)(JERRYPIT2Divider + 1) * RISC_CYCLE_IN_USEC; - SetCallbackTime(JERRYPIT2Callback, usecs); + SetCallbackTime(JERRYPIT2Callback, usecs, EVENT_JERRY); } -#endif } + // This is the cause of the regressions in Cybermorph and Missile Command 3D... // Solution: Probably have to check the DSP enable bit before sending these thru. //#define JERRY_NO_IRQS @@ -377,6 +260,7 @@ void JERRYPIT1Callback(void) JERRYResetPIT1(); } + void JERRYPIT2Callback(void) { #ifndef JERRY_NO_IRQS @@ -395,6 +279,7 @@ void JERRYPIT2Callback(void) JERRYResetPIT2(); } + void JERRYI2SCallback(void) { // Why is it called this? Instead of SCLK? Shouldn't this be read from DAC.CPP??? @@ -417,7 +302,7 @@ void JERRYI2SCallback(void) { DSPSetIRQLine(DSPIRQ_SSI, ASSERT_LINE); // This does the 'IRQ enabled' checking... double usecs = (float)jerryI2SCycles * RISC_CYCLE_IN_USEC; - SetCallbackTime(JERRYI2SCallback, usecs); + SetCallbackTime(JERRYI2SCallback, usecs, EVENT_JERRY); } else // JERRY is slave to external word clock { @@ -449,7 +334,7 @@ void JERRYI2SCallback(void) DSPSetIRQLine(DSPIRQ_SSI, ASSERT_LINE); } - SetCallbackTime(JERRYI2SCallback, 22.675737); + SetCallbackTime(JERRYI2SCallback, 22.675737, EVENT_JERRY); } } @@ -457,7 +342,6 @@ void JERRYI2SCallback(void) void JERRYInit(void) { JoystickInit(); - DACInit(); memcpy(&jerry_ram_8[0xD000], waveTableROM, 0x1000); JERRYPIT1Prescaler = 0xFFFF; @@ -466,14 +350,16 @@ void JERRYInit(void) JERRYPIT2Divider = 0xFFFF; jerryInterruptMask = 0x0000; jerryPendingInterrupt = 0x0000; + + DACInit(); } + void JERRYReset(void) { JoystickReset(); EepromReset(); JERRYResetI2S(); - DACReset(); memset(jerry_ram_8, 0x00, 0xD000); // Don't clear out the Wavetable ROM...! JERRYPIT1Prescaler = 0xFFFF; @@ -484,8 +370,11 @@ void JERRYReset(void) jerry_timer_2_counter = 0; jerryInterruptMask = 0x0000; jerryPendingInterrupt = 0x0000; + + DACReset(); } + void JERRYDone(void) { WriteLog("JERRY: M68K Interrupt control ($F10020) = %04X\n", GET16(jerry_ram_8, 0x20)); @@ -494,6 +383,7 @@ void JERRYDone(void) EepromDone(); } + bool JERRYIRQEnabled(int irq) { // Read the word @ $F10020 @@ -501,6 +391,7 @@ bool JERRYIRQEnabled(int irq) return jerryInterruptMask & irq; } + void JERRYSetPendingIRQ(int irq) { // This is the shadow of INT (it's a split RO/WO register) @@ -508,6 +399,7 @@ void JERRYSetPendingIRQ(int irq) jerryPendingInterrupt |= irq; } + // // JERRY byte access (read) // @@ -536,43 +428,7 @@ uint8 JERRYReadByte(uint32 offset, uint32 who/*=UNKNOWN*/) //under the new system... !!! FIX !!! else if ((offset >= 0xF10036) && (offset <= 0xF1003D)) { -#ifndef NEW_TIMER_SYSTEM -// jerry_timer_1_counter = (JERRYPIT1Prescaler + 1) * (JERRYPIT1Divider + 1); - uint32 counter1Hi = (jerry_timer_1_counter / (JERRYPIT1Divider + 1)) - 1; - uint32 counter1Lo = (jerry_timer_1_counter % (JERRYPIT1Divider + 1)) - 1; - uint32 counter2Hi = (jerry_timer_2_counter / (JERRYPIT2Divider + 1)) - 1; - uint32 counter2Lo = (jerry_timer_2_counter % (JERRYPIT2Divider + 1)) - 1; - - switch(offset & 0x0F) - { - case 6: -// return JERRYPIT1Prescaler >> 8; - return counter1Hi >> 8; - case 7: -// return JERRYPIT1Prescaler & 0xFF; - return counter1Hi & 0xFF; - case 8: -// return JERRYPIT1Divider >> 8; - return counter1Lo >> 8; - case 9: -// return JERRYPIT1Divider & 0xFF; - return counter1Lo & 0xFF; - case 10: -// return JERRYPIT2Prescaler >> 8; - return counter2Hi >> 8; - case 11: -// return JERRYPIT2Prescaler & 0xFF; - return counter2Hi & 0xFF; - case 12: -// return JERRYPIT2Divider >> 8; - return counter2Lo >> 8; - case 13: -// return JERRYPIT2Divider & 0xFF; - return counter2Lo & 0xFF; - } -#else WriteLog("JERRY: Unhandled timer read (BYTE) at %08X...\n", offset); -#endif } // else if (offset >= 0xF10010 && offset <= 0xF10015) // return clock_byte_read(offset); @@ -586,6 +442,7 @@ WriteLog("JERRY: Unhandled timer read (BYTE) at %08X...\n", offset); return jerry_ram_8[offset & 0xFFFF]; } + // // JERRY word access (read) // @@ -612,32 +469,7 @@ uint16 JERRYReadWord(uint32 offset, uint32 who/*=UNKNOWN*/) //in the jerry_timer_n_counter variables... !!! FIX !!! [DONE] else if ((offset >= 0xF10036) && (offset <= 0xF1003D)) { -#ifndef NEW_TIMER_SYSTEM -// jerry_timer_1_counter = (JERRYPIT1Prescaler + 1) * (JERRYPIT1Divider + 1); - uint32 counter1Hi = (jerry_timer_1_counter / (JERRYPIT1Divider + 1)) - 1; - uint32 counter1Lo = (jerry_timer_1_counter % (JERRYPIT1Divider + 1)) - 1; - uint32 counter2Hi = (jerry_timer_2_counter / (JERRYPIT2Divider + 1)) - 1; - uint32 counter2Lo = (jerry_timer_2_counter % (JERRYPIT2Divider + 1)) - 1; - - switch(offset & 0x0F) - { - case 6: -// return JERRYPIT1Prescaler; - return counter1Hi; - case 8: -// return JERRYPIT1Divider; - return counter1Lo; - case 10: -// return JERRYPIT2Prescaler; - return counter2Hi; - case 12: -// return JERRYPIT2Divider; - return counter2Lo; - } - // Unaligned word reads??? -#else WriteLog("JERRY: Unhandled timer read (WORD) at %08X...\n", offset); -#endif } // else if ((offset >= 0xF10010) && (offset <= 0xF10015)) // return clock_word_read(offset); @@ -660,6 +492,7 @@ WriteLog("JERRY: Unhandled timer read (WORD) at %08X...\n", offset); return ((uint16)jerry_ram_8[offset+0] << 8) | jerry_ram_8[offset+1]; } + // // JERRY byte access (write) // @@ -689,12 +522,8 @@ void JERRYWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/) JERRYI2SInterruptDivide = (JERRYI2SInterruptDivide & 0xFF00) | (uint32)data; JERRYI2SInterruptTimer = -1; -#ifndef NEW_TIMER_SYSTEM - jerry_i2s_exec(0); -#else RemoveCallback(JERRYI2SCallback); JERRYI2SCallback(); -#endif // return; } // LTXD/RTXD/SCLK/SMODE $F1A148/4C/50/54 (really 16-bit registers...) @@ -705,44 +534,7 @@ void JERRYWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/) } else if (offset >= 0xF10000 && offset <= 0xF10007) { -#ifndef NEW_TIMER_SYSTEM - switch (offset & 0x07) - { - case 0: - JERRYPIT1Prescaler = (JERRYPIT1Prescaler & 0x00FF) | (data << 8); - JERRYResetPIT1(); - break; - case 1: - JERRYPIT1Prescaler = (JERRYPIT1Prescaler & 0xFF00) | data; - JERRYResetPIT1(); - break; - case 2: - JERRYPIT1Divider = (JERRYPIT1Divider & 0x00FF) | (data << 8); - JERRYResetPIT1(); - break; - case 3: - JERRYPIT1Divider = (JERRYPIT1Divider & 0xFF00) | data; - JERRYResetPIT1(); - break; - case 4: - JERRYPIT2Prescaler = (JERRYPIT2Prescaler & 0x00FF) | (data << 8); - JERRYResetPIT2(); - break; - case 5: - JERRYPIT2Prescaler = (JERRYPIT2Prescaler & 0xFF00) | data; - JERRYResetPIT2(); - break; - case 6: - JERRYPIT2Divider = (JERRYPIT2Divider & 0x00FF) | (data << 8); - JERRYResetPIT2(); - break; - case 7: - JERRYPIT2Divider = (JERRYPIT2Divider & 0xFF00) | data; - JERRYResetPIT2(); - } -#else WriteLog("JERRY: Unhandled timer write (BYTE) at %08X...\n", offset); -#endif return; } /* else if ((offset >= 0xF10010) && (offset <= 0xF10015)) @@ -787,6 +579,7 @@ WriteLog("JERRY: Unhandled timer write (BYTE) at %08X...\n", offset); jerry_ram_8[offset & 0xFFFF] = data; } + // // JERRY word access (write) // @@ -838,12 +631,8 @@ else if (offset == 0xF10020) //This should *only* be enabled when SMODE has its INTERNAL bit set! !!! FIX !!! JERRYI2SInterruptDivide = (uint8)data; JERRYI2SInterruptTimer = -1; -#ifndef NEW_TIMER_SYSTEM - jerry_i2s_exec(0); -#else RemoveCallback(JERRYI2SCallback); JERRYI2SCallback(); -#endif DACWriteWord(offset, data, who); return; @@ -856,8 +645,6 @@ else if (offset == 0xF10020) } else if (offset >= 0xF10000 && offset <= 0xF10007) { -//#ifndef NEW_TIMER_SYSTEM -#if 1 switch(offset & 0x07) { case 0: @@ -877,9 +664,7 @@ else if (offset == 0xF10020) JERRYResetPIT2(); } // Need to handle (unaligned) cases??? -#else -WriteLog("JERRY: Unhandled timer write %04X (WORD) at %08X by %s...\n", data, offset, whoName[who]); -#endif + return; } /* else if (offset >= 0xF10010 && offset < 0xF10016) diff --git a/src/memory.cpp b/src/memory.cpp index 6d57ca3..6492147 100644 --- a/src/memory.cpp +++ b/src/memory.cpp @@ -156,6 +156,8 @@ uint32 butch, dscntrl, ds_data, i2cntrl, sbcntrl, subdata, subdatb, sb_time, fif // Actually, considering that "byteswap.h" doesn't exist elsewhere, the above // is probably our best bet here. Just need to rename them to ESAFExx(). +// Look at and see if that header is portable or not. + uint16 & memcon1 = *((uint16 *)&jagMemSpace[0xF00000]); uint16 & memcon2 = *((uint16 *)&jagMemSpace[0xF00002]); uint16 & hc = *((uint16 *)&jagMemSpace[0xF00004]); -- 2.37.2