]> Shamusworld >> Repos - virtualjaguar/blobdiff - src/jerry.cpp
Major rewrite/added BUTCH functionality
[virtualjaguar] / src / jerry.cpp
index 8b97e86280c7db2a533afa472ccf6dd9d6e59a02..27c3cab25d8c381b43216ec87932a2e6a533bc7c 100644 (file)
 //#define JERRY_DEBUG
 
 static uint8 * jerry_ram_8;
-//static uint16 *jerry_ram_16;
-//static uint8 * jerry_wave_rom;
 
-
-//#define JERRY_CONFIG jerry_ram_16[0x4002>>1]
 #define JERRY_CONFIG   0x4002
 
 uint8 analog_x, analog_y;
@@ -164,36 +160,50 @@ static int32 jerry_timer_1_counter;
 static int32 jerry_timer_2_counter;
 
 static uint32 jerry_i2s_interrupt_divide = 8;
-static int32  jerry_i2s_interrupt_timer = -1;
-static int32  jerry_i2s_interrupt_cycles_per_scanline = 0;
-
+static int32 jerry_i2s_interrupt_timer = -1;
+uint32 jerryI2SCycles;
+uint32 jerryIntPending;
 
+//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!)
 void jerry_i2s_exec(uint32 cycles)
 {      
+       extern uint16 serialMode;                                               // From DAC.CPP
+       if (!(serialMode & 0x01))                                               // INTERNAL flag
+               return;
+
+       // Why is it called this? Instead of SCLK? Shouldn't this be read from DAC.CPP???
+//Yes, it should. !!! FIX !!!
        jerry_i2s_interrupt_divide &= 0xFF;
 
        if (jerry_i2s_interrupt_timer == -1)
        {
-               uint32 jerry_i2s_int_freq = (26591000 / 64) / (jerry_i2s_interrupt_divide + 1);
-               jerry_i2s_interrupt_cycles_per_scanline = 13300000 / jerry_i2s_int_freq;
-               jerry_i2s_interrupt_timer = jerry_i2s_interrupt_cycles_per_scanline;
-               //fprintf(log_get(),"jerry: i2s interrupt rate set to %i hz (every %i cpu clock cycles) jerry_i2s_interrupt_divide=%i\n",jerry_i2s_int_freq,jerry_i2s_interrupt_cycles_per_scanline,jerry_i2s_interrupt_divide);
-               pcm_set_sample_rate(jerry_i2s_int_freq);
+               // 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 * (jerry_i2s_interrupt_divide + 1));
        }
+
        jerry_i2s_interrupt_timer -= cycles;
-       // note : commented since the sound doesn't work properly else
-       if (1)//jerry_i2s_interrupt_timer<=0)
+       if (jerry_i2s_interrupt_timer <= 0)
        {
-               // i2s interrupt
-               dsp_check_if_i2s_interrupt_needed();
-               //fprintf(log_get(),"jerry_i2s_interrupt_timer=%i, generating an i2s interrupt\n",jerry_i2s_interrupt_timer);
-               jerry_i2s_interrupt_timer += jerry_i2s_interrupt_cycles_per_scanline;
+               DSPSetIRQLine(DSPIRQ_SSI, ASSERT_LINE);
+               jerry_i2s_interrupt_timer += jerryI2SCycles;
+#ifdef JERRY_DEBUG
+               if (jerry_i2s_interrupt_timer < 0)
+                       WriteLog("JERRY: Missed generating an interrupt (missed %u)!\n", (-jerry_i2s_interrupt_timer / jerryI2SCycles) + 1);
+#endif
        }
 }
 
 void jerry_reset_i2s_timer(void)
 {
-       //fprintf(log_get(),"i2s: reseting\n");
+       //WriteLog("i2s: reseting\n");
+//This is really SCLK... !!! FIX !!!
        jerry_i2s_interrupt_divide = 8;
        jerry_i2s_interrupt_timer = -1;
 }
@@ -206,7 +216,7 @@ void jerry_reset_timer_1(void)
                jerry_timer_1_counter = (1 + jerry_timer_1_prescaler) * (1 + jerry_timer_1_divider);
 
 //     if (jerry_timer_1_counter)
-//             fprintf(log_get(),"jerry: reseting timer 1 to 0x%.8x (%i)\n",jerry_timer_1_counter,jerry_timer_1_counter);
+//             WriteLog("jerry: reseting timer 1 to 0x%.8x (%i)\n",jerry_timer_1_counter,jerry_timer_1_counter);
 }
 
 void jerry_reset_timer_2(void)
@@ -220,17 +230,17 @@ void jerry_reset_timer_2(void)
                jerry_timer_2_counter = ((1 + jerry_timer_2_prescaler) * (1 + jerry_timer_2_divider));
 
 //     if (jerry_timer_2_counter)
-//             fprintf(log_get(),"jerry: reseting timer 2 to 0x%.8x (%i)\n",jerry_timer_2_counter,jerry_timer_2_counter);
+//             WriteLog("jerry: reseting timer 2 to 0x%.8x (%i)\n",jerry_timer_2_counter,jerry_timer_2_counter);
 }
 
-void jerry_pit_exec(uint32 cycles)
+void JERRYExecPIT(uint32 cycles)
 {
        if (jerry_timer_1_counter)
                jerry_timer_1_counter -= cycles;
 
        if (jerry_timer_1_counter <= 0)
        {
-               dsp_set_irq_line(2, 1);
+               DSPSetIRQLine(DSPIRQ_TIMER0, ASSERT_LINE);
                jerry_reset_timer_1();
        }
 
@@ -239,92 +249,77 @@ void jerry_pit_exec(uint32 cycles)
 
        if (jerry_timer_2_counter <= 0)
        {
-               dsp_set_irq_line(3, 1);
+               DSPSetIRQLine(DSPIRQ_TIMER1, ASSERT_LINE);
                jerry_reset_timer_2();
        }
 }
 
-void jerry_wave_rom_init(void)
-{
-//     memory_malloc_secure((void **)&jerry_wave_rom, 0x1000, "jerry wave rom");
-//     uint32 * jaguar_wave_rom_32 = (uint32 *)jerry_wave_rom;
-
-       // use real wave table dump
-// JLH: Looks like this WT dump is in the wrong endian (For the Jaguar, that is)...
-//     memcpy(jerry_wave_rom, wave_table, 0x1000);
-
-       // reverse byte ordering
-// JLH: Actually, this does nothing...
-/*     for(int i=0; i<0x400; i++)
-       {
-               uint32 data = jaguar_wave_rom_32[i];
-               data = ((data & 0xFF000000) >> 24) | ((data & 0x0000FF00) << 8)
-                       | ((data & 0x00FF0000) >> 8) | ((data & 0x000000FF) << 24);
-       }*/
-// Why the need for an extra buffer to hold it, when it already exists in the form of wave_table???
-// Also, there was a memory leak, since it was never deallocated... (jerry_wave_rom)
-       
-       // Copy it to DSP RAM
-//WAS: memcpy(&jerry_ram_8[0xD000], jerry_wave_rom, 0x1000);
-       memcpy(&jerry_ram_8[0xD000], wave_table, 0x1000);
-}
-
 void jerry_init(void)
 {
-       //fprintf(log_get(),"jerry_init()\n");
        clock_init();
        anajoy_init();
        joystick_init();
-       eeprom_init();
-       memory_malloc_secure((void **)&jerry_ram_8, 0x10000, "jerry ram");
-//     jerry_ram_16 = (uint16 *)jerry_ram_8;
-       jerry_wave_rom_init();
+       DACInit();
+//This should be handled with the cart initialization...
+//     eeprom_init();
+       memory_malloc_secure((void **)&jerry_ram_8, 0x10000, "JERRY RAM/ROM");
+       memcpy(&jerry_ram_8[0xD000], wave_table, 0x1000);
 }
 
 void jerry_reset(void)
 {
-       //fprintf(log_get(),"jerry_reset()\n");
        clock_reset();
        anajoy_reset();
        joystick_reset();
        eeprom_reset();
        jerry_reset_i2s_timer();
+       DACReset();
 
-       memset(jerry_ram_8, 0x00, 0x10000);
-       jerry_ram_8[JERRY_CONFIG+1] |= 0x10; // NTSC (bit 4)
+       memset(jerry_ram_8, 0x00, 0xD000);              // Don't clear out the Wavetable ROM...!
        jerry_timer_1_prescaler = 0xFFFF;
        jerry_timer_2_prescaler = 0xFFFF;
        jerry_timer_1_divider = 0xFFFF;
        jerry_timer_2_divider = 0xFFFF;
        jerry_timer_1_counter = 0;
        jerry_timer_2_counter = 0;
-
 }
 
 void jerry_done(void)
 {
-       //fprintf(log_get(),"jerry_done()\n");
+       WriteLog("JERRY: M68K Interrupt control ($F10020) = %04X\n", GET16(jerry_ram_8, 0x20));
        memory_free(jerry_ram_8);
        clock_done();
        anajoy_done();
        joystick_done();
+       DACDone();
        eeprom_done();
 }
 
+bool JERRYIRQEnabled(int irq)
+{
+       // Read the word @ $F10020 
+       return jerry_ram_8[0x21] & (1 << irq);
+}
+
+void JERRYSetPendingIRQ(int irq)
+{
+       // This is the shadow of INT (it's a split RO/WO register)
+       jerryIntPending |= (1 << irq);
+}
+
 //
 // JERRY byte access (read)
 //
-
-unsigned jerry_byte_read(unsigned int offset)
+uint8 JERRYReadByte(uint32 offset, uint32 who/*=UNKNOWN*/)
 {
 #ifdef JERRY_DEBUG
-       fprintf(log_get(),"jerry: reading byte at 0x%.6x\n",offset);
+       WriteLog("JERRY: Reading byte at %06X\n", offset);
 #endif
-       if ((offset >= dsp_control_ram_base) && (offset < dsp_control_ram_base+0x20))
-               return dsp_byte_read(offset);
-       else if ((offset >= dsp_work_ram_base) && (offset < dsp_work_ram_base+0x2000))
-               return dsp_byte_read(offset);
-       else if ((offset >= 0xF10000) && (offset <= 0xF10007))
+       if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE+0x20))
+               return DSPReadByte(offset, who);
+       else if ((offset >= DSP_WORK_RAM_BASE) && (offset < DSP_WORK_RAM_BASE+0x2000))
+               return DSPReadByte(offset, who);
+       else if (offset >= 0xF10000 && offset <= 0xF10007)
        {
                switch(offset & 0x07)
                {
@@ -346,15 +341,15 @@ unsigned jerry_byte_read(unsigned int offset)
                        return jerry_timer_2_divider & 0xFF;
                }
        }
-       else if ((offset >= 0xF10010) && (offset <= 0xf10015))
+       else if (offset >= 0xF10010 && offset <= 0xF10015)
                return clock_byte_read(offset);
-       else if ((offset >= 0xF17C00) && (offset <= 0xF17C01))
+       else if (offset >= 0xF17C00 && offset <= 0xF17C01)
                return anajoy_byte_read(offset);
-       else if ((offset >= 0xF14000) && (offset <= 0xF14003))
+       else if (offset >= 0xF14000 && offset <= 0xF14003)
        {
                return joystick_byte_read(offset) | eeprom_byte_read(offset);
        }
-       else if ((offset >= 0xF14000) && (offset <= 0xF1A0FF))
+       else if (offset >= 0xF14000 && offset <= 0xF1A0FF)
                return eeprom_byte_read(offset);
        
        return jerry_ram_8[offset & 0xFFFF];
@@ -363,17 +358,16 @@ unsigned jerry_byte_read(unsigned int offset)
 //
 // JERRY word access (read)
 //
-
-unsigned jerry_word_read(unsigned int offset)
+uint16 JERRYReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
 {
 #ifdef JERRY_DEBUG
-       fprintf(log_get(),"jerry: reading word at 0x%.6x\n",offset);
+       WriteLog("JERRY: Reading word at %06X\n", offset);
 #endif
 
-       if ((offset >= dsp_control_ram_base) && (offset < dsp_control_ram_base+0x20))
-               return dsp_word_read(offset);
-       else if ((offset >= dsp_work_ram_base) && (offset < dsp_work_ram_base+0x2000))
-               return dsp_word_read(offset);
+       if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE+0x20))
+               return DSPReadWord(offset, who);
+       else if (offset >= DSP_WORK_RAM_BASE && offset <= DSP_WORK_RAM_BASE + 0x1FFF)
+               return DSPReadWord(offset, who);
        else if ((offset >= 0xF10000) && (offset <= 0xF10007))
        {
                switch(offset & 0x07)
@@ -392,12 +386,12 @@ unsigned jerry_word_read(unsigned int offset)
        else if ((offset >= 0xF10010) && (offset <= 0xF10015))
                return clock_word_read(offset);
        else if (offset == 0xF10020)
-               return 0x00;
+               return jerryIntPending;
        else if ((offset >= 0xF17C00) && (offset <= 0xF17C01))
                return anajoy_word_read(offset);
        else if (offset == 0xF14000)
        {
-               //fprintf(log_get(),"reading 0x%.4x from 0xf14000\n");
+               //WriteLog("reading 0x%.4x from 0xf14000\n");
                return (joystick_word_read(offset) & 0xFFFE) | eeprom_word_read(offset);
        }
        else if ((offset >= 0xF14002) && (offset < 0xF14003))
@@ -405,40 +399,35 @@ unsigned jerry_word_read(unsigned int offset)
        else if ((offset >= 0xF14000) && (offset <= 0xF1A0FF))
                return eeprom_word_read(offset);
 
-// This is never executed!
-/*     offset &= 0xFFFF;
-       if (offset==0x4002)
-               return(0xffff);*/
+/*if (offset >= 0xF1D000)
+       WriteLog("JERRY: Reading word at %08X [%04X]...\n", offset, ((uint16)jerry_ram_8[(offset+0)&0xFFFF] << 8) | jerry_ram_8[(offset+1)&0xFFFF]);//*/
 
-/*     uint16 data = jerry_ram_8[offset+0];
-       data <<= 8;
-       data |= jerry_ram_8[offset+1];
-       return data;*/
+       offset &= 0xFFFF;                               // Prevent crashing...!
        return ((uint16)jerry_ram_8[offset+0] << 8) | jerry_ram_8[offset+1];
 }
 
 //
 // JERRY byte access (write)
 //
-
-void jerry_byte_write(unsigned offset, unsigned data)
+void JERRYWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
 {
 #ifdef JERRY_DEBUG
-       fprintf(log_get(),"jerry: writing byte %.2x at 0x%.6x\n",data,offset);
+       WriteLog("jerry: writing byte %.2x at 0x%.6x\n",data,offset);
 #endif
-       if ((offset >= dsp_control_ram_base) && (offset < dsp_control_ram_base+0x20))
+       if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE+0x20))
        {
-               dsp_byte_write(offset, data);
+               DSPWriteByte(offset, data, who);
                return;
        }
-       else if ((offset >= dsp_work_ram_base) && (offset < dsp_work_ram_base+0x2000))
+       else if ((offset >= DSP_WORK_RAM_BASE) && (offset < DSP_WORK_RAM_BASE+0x2000))
        {
-               dsp_byte_write(offset, data);
+               DSPWriteByte(offset, data, who);
                return;
        }
+       // SCLK ($F1A150--8 bits wide)
        else if ((offset >= 0xF1A152) && (offset <= 0xF1A153))
        {
-//             fprintf(log_get(),"i2s: writing 0x%.2x to SCLK\n",data);
+//             WriteLog("JERRY: Writing %02X to SCLK...\n", data);
                if ((offset & 0x03) == 2)
                        jerry_i2s_interrupt_divide = (jerry_i2s_interrupt_divide & 0x00FF) | ((uint32)data << 8);
                else
@@ -446,17 +435,26 @@ void jerry_byte_write(unsigned offset, unsigned data)
 
                jerry_i2s_interrupt_timer = -1;
                jerry_i2s_exec(0);
-               return;
+//             return;
        }
-       else if ((offset >= 0xF10000) && (offset <= 0xF10007))
+       // LTXD/RTXD/SCLK/SMODE $F1A148/4C/50/54 (really 16-bit registers...)
+       else if (offset >= 0xF1A148 && offset <= 0xF1A157)
+       { 
+               DACWriteByte(offset, data);
+               return; 
+       }
+       else if (offset >= 0xF10000 && offset <= 0xF10007)
        {
-               switch(offset & 0x07)
+               switch (offset & 0x07)
                {
                case 0:
                        jerry_timer_1_prescaler = (jerry_timer_1_prescaler & 0x00FF) | (data << 8);
                        jerry_reset_timer_1();
                        break;
-               case 1: { jerry_timer_1_prescaler=(jerry_timer_1_prescaler&0xff00)|(data);              jerry_reset_timer_1(); return; }
+               case 1:
+                       jerry_timer_1_prescaler = (jerry_timer_1_prescaler & 0xFF00) | (data);
+                       jerry_reset_timer_1();
+                       break;
                case 2: { jerry_timer_1_divider=(jerry_timer_1_divider&0x00ff)|(data<<8);               jerry_reset_timer_1(); return; }
                case 3: { jerry_timer_1_divider=(jerry_timer_1_divider&0xff00)|(data);                  jerry_reset_timer_1(); return; }
                case 4: { jerry_timer_2_prescaler=(jerry_timer_2_prescaler&0x00ff)|(data<<8);   jerry_reset_timer_2(); return; }
@@ -488,35 +486,47 @@ void jerry_byte_write(unsigned offset, unsigned data)
                return;
        }
 
+//Need to protect write attempts to Wavetable ROM (F1D000-FFF)
+       if (offset >= 0xF1D000 && offset <= 0xF1DFFF)
+               return;
+
        jerry_ram_8[offset & 0xFFFF] = data;
 }
 
 //
 // JERRY word access (write)
 //
-
-void jerry_word_write(unsigned offset, unsigned data)
+void JERRYWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
 {
 #ifdef JERRY_DEBUG
-       fprintf(log_get(), "JERRY: Writing word %04X at %06X\n", data, offset);
+       WriteLog( "JERRY: Writing word %04X at %06X\n", data, offset);
 #endif
 
-       if ((offset >= dsp_control_ram_base) && (offset < dsp_control_ram_base+0x20))
+       if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE+0x20))
        {
-               dsp_word_write(offset, data);
+               DSPWriteWord(offset, data, who);
                return;
        }
-       else if ((offset >= dsp_work_ram_base) && (offset < dsp_work_ram_base+0x2000))
+       else if ((offset >= DSP_WORK_RAM_BASE) && (offset < DSP_WORK_RAM_BASE+0x2000))
        {
-               dsp_word_write(offset, data);
+               DSPWriteWord(offset, data, who);
                return;
        }
-       else if (offset == 0xF1A152)
+       else if (offset == 0xF1A152)                                    // Bottom half of SCLK ($F1A150)
        {
-//             fprintf(log_get(),"i2s: writing 0x%.4x to SCLK\n",data);
-               jerry_i2s_interrupt_divide = data & 0xFF;
+               WriteLog("JERRY: Writing %04X to SCLK (by %s)...\n", data, whoName[who]);
+               jerry_i2s_interrupt_divide = (uint8)data;
                jerry_i2s_interrupt_timer = -1;
                jerry_i2s_exec(0);
+
+               DACWriteWord(offset, data);
+               return; 
+       }
+       // LTXD/RTXD/SCLK/SMODE $F1A148/4C/50/54 (really 16-bit registers...)
+       else if (offset >= 0xF1A148 && offset <= 0xF1A156)
+       { 
+               DACWriteWord(offset, data);
+               return; 
        }
        else if ((offset >= 0xF10000) && (offset <= 0xF10007))
        {
@@ -541,18 +551,18 @@ void jerry_word_write(unsigned offset, unsigned data)
                // Need to handle (unaligned) cases???
                return;
        }
-       else if ((offset >= 0xF1A148) && (offset < 0xF1A150)) 
-       { 
-               pcm_word_write(offset - 0xF1A148, data); 
-               return; 
-       }
        else if ((offset >= 0xF10010) && (offset < 0xF10016))
        {
                clock_word_write(offset, data);
                return;
        }
+       // JERRY -> 68K interrupt enables/latches (need to be handled!)
+       else if (offset >= 0xF10020 && offset <= 0xF10022)
+       {
+       }
        else if ((offset >= 0xF17C00) && (offset < 0xF17C02))
        {
+//I think this was removed from the Jaguar. If so, then we don't need this...!
                anajoy_word_write(offset, data);
                return;
        }
@@ -568,6 +578,10 @@ void jerry_word_write(unsigned offset, unsigned data)
                return;
        }
 
+//Need to protect write attempts to Wavetable ROM (F1D000-FFF)
+       if (offset >= 0xF1D000 && offset <= 0xF1DFFF)
+               return;
+
        jerry_ram_8[(offset+0) & 0xFFFF] = (data >> 8) & 0xFF;
        jerry_ram_8[(offset+1) & 0xFFFF] = data & 0xFF;
 }