]> Shamusworld >> Repos - virtualjaguar/blobdiff - src/dsp.cpp
More gamepad work.
[virtualjaguar] / src / dsp.cpp
index aa12cf504457a1d08a1b8dbeb705b5c3d64a6c9e..7a0553f292b6c432a8daaa80b56c51daf88e7ef5 100644 (file)
 
 #include <SDL.h>                                                               // Used only for SDL_GetTicks...
 #include <stdlib.h>
+#include <time.h>
 #include "dac.h"
 #include "gpu.h"
 #include "jagdasm.h"
 #include "jaguar.h"
 #include "jerry.h"
 #include "log.h"
-#include "m68k.h"
+#include "m68000/m68kinterface.h"
 //#include "memory.h"
 
 
@@ -623,12 +624,9 @@ uint32 DSPReadLong(uint32 offset, uint32 who/*=UNKNOWN*/)
                offset &= 0x3F;
                switch (offset)
                {
-               case 0x00:      /*dsp_flag_c?(dsp_flag_c=1):(dsp_flag_c=0);
-                                       dsp_flag_z?(dsp_flag_z=1):(dsp_flag_z=0);
-                                       dsp_flag_n?(dsp_flag_n=1):(dsp_flag_n=0);*/
-
-                                       dsp_flags = (dsp_flags & 0xFFFFFFF8) | (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
-                                       return dsp_flags & 0xFFFFC1FF;
+               case 0x00:
+                       dsp_flags = (dsp_flags & 0xFFFFFFF8) | (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
+                       return dsp_flags & 0xFFFFC1FF;
                case 0x04: return dsp_matrix_control;
                case 0x08: return dsp_pointer_to_matrix;
                case 0x0C: return dsp_data_organization;
@@ -724,19 +722,22 @@ SET16(ram2, offset, data);
                if ((offset & 0x1C) == 0x1C)
                {
                        if (offset & 0x03)
-                               dsp_div_control = (dsp_div_control&0xffff0000)|(data&0xffff);
+                               dsp_div_control = (dsp_div_control & 0xFFFF0000) | (data & 0xFFFF);
                        else
-                               dsp_div_control = (dsp_div_control&0xffff)|((data&0xffff)<<16);
+                               dsp_div_control = (dsp_div_control & 0xFFFF) | ((data & 0xFFFF) << 16);
                }
                else
                {
-                       uint32 old_data = DSPReadLong(offset & 0xffffffc, who);
+                       uint32 old_data = DSPReadLong(offset & 0xFFFFFFC, who);
+
                        if (offset & 0x03)
-                               old_data = (old_data&0xffff0000)|(data&0xffff);
+                               old_data = (old_data & 0xFFFF0000) | (data & 0xFFFF);
                        else
-                               old_data = (old_data&0xffff)|((data&0xffff)<<16);
-                       DSPWriteLong(offset & 0xffffffc, old_data, who);
+                               old_data = (old_data & 0xFFFF) | ((data & 0xFFFF) << 16);
+
+                       DSPWriteLong(offset & 0xFFFFFFC, old_data, who);
                }
+
                return;
        }
 
@@ -779,11 +780,13 @@ SET32(ram2, offset, data);
                case 0x00:
                {
 #ifdef DSP_DEBUG
-                       WriteLog("DSP: Writing %08X to DSP_FLAGS by %s (REGPAGE is %s)...\n", data, whoName[who], (dsp_flags & REGPAGE ? "set" : "not set"));
+                       WriteLog("DSP: Writing %08X to DSP_FLAGS by %s (REGPAGE is %sset)...\n", data, whoName[who], (dsp_flags & REGPAGE ? "" : "not "));
 #endif
 //                     bool IMASKCleared = (dsp_flags & IMASK) && !(data & IMASK);
                        IMASKCleared = (dsp_flags & IMASK) && !(data & IMASK);
-                       dsp_flags = data;
+                       // NOTE: According to the JTRM, writing a 1 to IMASK has no effect; only the
+                       //       IRQ logic can set it. So we mask it out here to prevent problems...
+                       dsp_flags = data & (~IMASK);
                        dsp_flag_z = dsp_flags & 0x01;
                        dsp_flag_c = (dsp_flags >> 1) & 0x01;
                        dsp_flag_n = (dsp_flags >> 2) & 0x01;
@@ -797,6 +800,25 @@ SET32(ram2, offset, data);
 //     interrupt, so that's what we check for here. Just know that this approach
 //     can be easily fooled!
 //     Note also that if both interrupts are enabled, the I2S freq will win. :-P
+
+// Further Note:
+// The impetus for this "fix" was Cybermorph, which sets the SCLK to 7 which is an
+// audio frequency > 48 KHz. However, it stuffs the L/RTXD registers using TIMER0.
+// So, while this works, it's a by-product of the lame way in which audio is currently
+// handled. Hopefully, once we run the DSP in the host audio IRQ, this problem will
+// go away of its own accord. :-P
+// Or does it? It seems the I2S interrupt isn't on with Cybermorph, so something
+// weird is going on here...
+// Maybe it works like this: It acknowledges the 1st interrupt, but never clears it.
+// So subsequent interrupts come into the chip, but they're never serviced but the
+// I2S subsystem keeps going.
+// After some testing on real hardware, it seems that if you enable TIMER0 and EXTERNAL
+// IRQs on J_INT ($F10020), you don't have to run an I2S interrupt on the DSP. Also,
+// It seems that it's only stable for values of SCLK <= 9.
+
+// All of the preceeding is moot now; we run the DSP in the host audio IRQ. This means
+// that we don't actually need this stuff anymore. :-D
+#if 0
                        if (data & INT_ENA1) // I2S interrupt
                        {
                                int freq = GetCalculatedFrequency();
@@ -811,6 +833,7 @@ SET32(ram2, offset, data);
 //                             WriteLog("DSP: Setting audio freqency to %u Hz...\n", freq);
                                DACSetNewFrequency(freq);
                        }
+#endif
 
 /*                     if (IMASKCleared)                                               // If IMASK was cleared,
 #ifdef DSP_DEBUG_IRQ
@@ -872,7 +895,7 @@ if (who != DSP)
                case 0x14:
                {
 //#ifdef DSP_DEBUG
-WriteLog("Write to DSP CTRL by %s: %08X\n", whoName[who], data);
+WriteLog("Write to DSP CTRL by %s: %08X (DSP PC=$%08X)\n", whoName[who], data, dsp_pc);
 //#endif
                        bool wasRunning = DSP_RUNNING;
 //                     uint32 dsp_was_running = DSP_RUNNING;
@@ -1263,6 +1286,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");
@@ -1271,6 +1299,7 @@ void DSPInit(void)
 
        dsp_build_branch_condition_table();
        DSPReset();
+       srand(time(NULL));                                                      // For randomizing local RAM
 }
 
 void DSPReset(void)
@@ -1297,7 +1326,12 @@ void DSPReset(void)
        IMASKCleared = false;
        FlushDSPPipeline();
        dsp_reset_stats();
-       memset(dsp_ram_8, 0xFF, 0x2000);
+//     memset(dsp_ram_8, 0xFF, 0x2000);
+       // Contents of local RAM are quasi-stable; we simulate this by randomizing RAM contents
+       for(uint32 i=0; i<8192; i+=4)
+       {
+               *((uint32 *)(&dsp_ram_8[i])) = rand();
+       }
 }
 
 void DSPDumpDisassembly(void)
@@ -1377,13 +1411,14 @@ void DSPDone(void)
                                                  (j << 2) + 1, dsp_reg_bank_1[(j << 2) + 1],
                                                  (j << 2) + 2, dsp_reg_bank_1[(j << 2) + 2],
                                                  (j << 2) + 3, dsp_reg_bank_1[(j << 2) + 3]);
-
        }
 
+       WriteLog("\n");
+
        static char buffer[512];
        j = DSP_WORK_RAM_BASE;
 
-       while (j <= 0xF1BFFF)
+       while (j <= 0xF1CFFF)
        {
                uint32 oldj = j;
                j += dasmjag(JAGUAR_DSP, buffer, j);