]> Shamusworld >> Repos - virtualjaguar/blobdiff - src/dsp.cpp
Initial fixes for audio subsystem. Fragile; may break in unexpected ways.
[virtualjaguar] / src / dsp.cpp
index 812d1035b31297cb9c1c636f3adf8bbfa4f4f4be..74839cc4b7eee9b6708d02c8e56a5573ca724ad2 100644 (file)
@@ -3,20 +3,34 @@
 //
 // Originally by David Raingeard
 // GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (BeOS)
-// Extensive cleanups/rewrites by James L. Hammons
+// Extensive cleanups/rewrites by James Hammons
+// (C) 2010 Underground Software
+//
+// JLH = James Hammons <jlhamm@acm.org>
+//
+// Who  When        What
+// ---  ----------  -------------------------------------------------------------
+// JLH  01/16/2010  Created this log ;-)
+// JLH  11/26/2011  Added fixes for LOAD/STORE alignment issues
 //
 
 #include "dsp.h"
 
+#include <SDL.h>                                                               // Used only for SDL_GetTicks...
 #include <stdlib.h>
-#include <SDL.h>       // Used only for SDL_GetTicks...
-#include "memory.h"
-#include "log.h"
-#include "jaguar.h"
-#include "jerry.h"
+#include "dac.h"
 #include "gpu.h"
 #include "jagdasm.h"
+#include "jaguar.h"
+#include "jerry.h"
+#include "log.h"
 #include "m68k.h"
+//#include "memory.h"
+
+
+// Seems alignment in loads & stores was off...
+#define DSP_CORRECT_ALIGNMENT
+//#define DSP_CORRECT_ALIGNMENT_STORE
 
 //#define DSP_DEBUG
 //#define DSP_DEBUG_IRQ
@@ -27,6 +41,7 @@
 
 // Disassembly definitions
 
+#if 0
 #define DSP_DIS_ABS
 #define DSP_DIS_ADD
 #define DSP_DIS_ADDC
@@ -82,7 +97,7 @@
 //*/
 bool doDSPDis = false;
 //bool doDSPDis = true;
-
+#endif
 
 /*
 No dis yet:
@@ -231,7 +246,7 @@ static void dsp_opcode_abs(void);
 static void dsp_opcode_add(void);
 static void dsp_opcode_addc(void);
 static void dsp_opcode_addq(void);
-static void dsp_opcode_addqmod(void);  
+static void dsp_opcode_addqmod(void);
 static void dsp_opcode_addqt(void);
 static void dsp_opcode_and(void);
 static void dsp_opcode_bclr(void);
@@ -252,7 +267,7 @@ static void dsp_opcode_load_r14_indexed(void);
 static void dsp_opcode_load_r14_ri(void);
 static void dsp_opcode_load_r15_indexed(void);
 static void dsp_opcode_load_r15_ri(void);
-static void dsp_opcode_mirror(void);   
+static void dsp_opcode_mirror(void);
 static void dsp_opcode_mmult(void);
 static void dsp_opcode_move(void);
 static void dsp_opcode_movei(void);
@@ -271,8 +286,8 @@ static void dsp_opcode_resmac(void);
 static void dsp_opcode_ror(void);
 static void dsp_opcode_rorq(void);
 static void dsp_opcode_xor(void);
-static void dsp_opcode_sat16s(void);   
-static void dsp_opcode_sat32s(void);   
+static void dsp_opcode_sat16s(void);
+static void dsp_opcode_sat32s(void);
 static void dsp_opcode_sh(void);
 static void dsp_opcode_sha(void);
 static void dsp_opcode_sharq(void);
@@ -288,25 +303,25 @@ static void dsp_opcode_store_r15_ri(void);
 static void dsp_opcode_sub(void);
 static void dsp_opcode_subc(void);
 static void dsp_opcode_subq(void);
-static void dsp_opcode_subqmod(void);  
+static void dsp_opcode_subqmod(void);
 static void dsp_opcode_subqt(void);
 
 uint8 dsp_opcode_cycles[64] =
 {
-       3,  3,  3,  3,  3,  3,  3,  3,  
        3,  3,  3,  3,  3,  3,  3,  3,
-       3,  3,  1,  3,  1, 18,  3,  3,  
        3,  3,  3,  3,  3,  3,  3,  3,
-       3,  3,  2,  2,  2,  2,  3,  4,  
+       3,  3,  1,  3,  1, 18,  3,  3,
+       3,  3,  3,  3,  3,  3,  3,  3,
+       3,  3,  2,  2,  2,  2,  3,  4,
        5,  4,  5,  6,  6,  1,  1,  1,
-       1,  2,  2,  2,  1,  1,  9,  3,  
+       1,  2,  2,  2,  1,  1,  9,  3,
        3,  1,  6,  6,  2,  2,  3,  3
 };//*/
 //Here's a QnD kludge...
 //This is wrong, wrong, WRONG, but it seems to work for the time being...
 //(That is, it fixes Flip Out which relies on GPU timing rather than semaphores. Bad developers! Bad!)
 //What's needed here is a way to take pipeline effects into account (including pipeline stalls!)...
-/*uint8 dsp_opcode_cycles[64] = 
+/*uint8 dsp_opcode_cycles[64] =
 {
        1,  1,  1,  1,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,
@@ -319,7 +334,7 @@ uint8 dsp_opcode_cycles[64] =
 };//*/
 
 void (* dsp_opcode[64])() =
-{      
+{
        dsp_opcode_add,                                 dsp_opcode_addc,                                dsp_opcode_addq,                                dsp_opcode_addqt,
        dsp_opcode_sub,                                 dsp_opcode_subc,                                dsp_opcode_subq,                                dsp_opcode_subqt,
        dsp_opcode_neg,                                 dsp_opcode_and,                                 dsp_opcode_or,                                  dsp_opcode_xor,
@@ -341,7 +356,7 @@ void (* dsp_opcode[64])() =
 uint32 dsp_opcode_use[65];
 
 const char * dsp_opcode_str[65]=
-{      
+{
        "add",                          "addc",                         "addq",                         "addqt",
        "sub",                          "subc",                         "subq",                         "subqt",
        "neg",                          "and",                          "or",                           "xor",
@@ -371,7 +386,7 @@ static uint32 dsp_pointer_to_matrix;
 static uint32 dsp_data_organization;
 uint32 dsp_control;
 static uint32 dsp_div_control;
-static uint8 dsp_flag_z, dsp_flag_n, dsp_flag_c;    
+static uint8 dsp_flag_z, dsp_flag_n, dsp_flag_c;
 static uint32 * dsp_reg = NULL, * dsp_alternate_reg = NULL;
 static uint32 dsp_reg_bank_0[32], dsp_reg_bank_1[32];
 
@@ -431,7 +446,7 @@ void dsp_reset_stats(void)
                dsp_opcode_use[i] = 0;
 }
 
-void dsp_releaseTimeslice(void)
+void DSPReleaseTimeslice(void)
 {
 //This does absolutely nothing!!! !!! FIX !!!
        dsp_releaseTimeSlice_flag = 1;
@@ -441,7 +456,7 @@ void dsp_build_branch_condition_table(void)
 {
        // Allocate the mirror table
        if (!mirror_table)
-               mirror_table = (uint16 *)memory_malloc(65536 * sizeof(uint16), "DSP mirror table");
+               mirror_table = (uint16 *)malloc(65536 * sizeof(uint16));
 
        // Fill in the mirror table
        if (mirror_table)
@@ -457,7 +472,7 @@ void dsp_build_branch_condition_table(void)
 
        if (!dsp_branch_condition_table)
        {
-               dsp_branch_condition_table = (uint8 *)memory_malloc(32 * 8 * sizeof(uint8), "DSP branch condition table");
+               dsp_branch_condition_table = (uint8 *)malloc(32 * 8 * sizeof(uint8));
 
                // Fill in the condition table
                if (dsp_branch_condition_table)
@@ -520,7 +535,7 @@ uint8 DSPReadByte(uint32 offset, uint32 who/*=UNKNOWN*/)
        }
 
        return JaguarReadByte(offset, who);
-} 
+}
 
 uint16 DSPReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
 {
@@ -651,7 +666,7 @@ void DSPWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
 /*             if (dsp_in_exec == 0)
                {
                        m68k_end_timeslice();
-                       gpu_releaseTimeslice();
+                       dsp_releaseTimeslice();
                }*/
                return;
        }
@@ -659,7 +674,7 @@ void DSPWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
        {
                uint32 reg = offset & 0x1C;
                int bytenum = offset & 0x03;
-               
+
                if ((reg >= 0x1C) && (reg <= 0x1F))
                        dsp_div_control = (dsp_div_control & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
                else
@@ -667,7 +682,7 @@ void DSPWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
 //This looks funky. !!! FIX !!!
                        uint32 old_data = DSPReadLong(offset&0xFFFFFFC, who);
                        bytenum = 3 - bytenum; // convention motorola !!!
-                       old_data = (old_data & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3)); 
+                       old_data = (old_data & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
                        DSPWriteLong(offset & 0xFFFFFFC, old_data, who);
                }
                return;
@@ -701,7 +716,7 @@ void DSPWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
                {
 //                     WriteLog("dsp: writing %.4x at 0x%.8x\n",data,offset+DSP_WORK_RAM_BASE);
                        m68k_end_timeslice();
-                       gpu_releaseTimeslice();
+                       dsp_releaseTimeslice();
                }*/
 //CC only!
 #ifdef DSP_DEBUG_CC
@@ -782,6 +797,28 @@ SET32(ram2, offset, data);
                        DSPUpdateRegisterBanks();
                        dsp_control &= ~((dsp_flags & CINT04FLAGS) >> 3);
                        dsp_control &= ~((dsp_flags & CINT5FLAG) >> 1);
+
+// NB: This is just a wild hairy-assed guess as to what the playback frequency is.
+//     It can be timed to anything really, anything that writes to L/RTXD at a regular
+//     interval. Most things seem to use either the I2S interrupt or the TIMER 0
+//     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
+                       if (data & INT_ENA1) // I2S interrupt
+                       {
+                               int freq = GetCalculatedFrequency();
+//This happens too often to be useful...
+//                             WriteLog("DSP: Setting audio freqency to %u Hz...\n", freq);
+                               DACSetNewFrequency(freq);
+                       }
+                       else if (data & INT_ENA2) // TIMER 0 interrupt
+                       {
+                               int freq = JERRYGetPIT1Frequency();
+//This happens too often to be useful...
+//                             WriteLog("DSP: Setting audio freqency to %u Hz...\n", freq);
+                               DACSetNewFrequency(freq);
+                       }
+
 /*                     if (IMASKCleared)                                               // If IMASK was cleared,
 #ifdef DSP_DEBUG_IRQ
                        {
@@ -840,7 +877,7 @@ if (who != DSP)
 //!!!!!!!!
                        break;
                case 0x14:
-               {       
+               {
 //#ifdef DSP_DEBUG
 WriteLog("Write to DSP CTRL by %s: %08X\n", whoName[who], data);
 //#endif
@@ -853,12 +890,13 @@ WriteLog("Write to DSP CTRL by %s: %08X\n", whoName[who], data);
                                WriteLog("DSP: DSP -> CPU interrupt\n");
 #endif
 // This was WRONG
-// Why do we check for a valid handler at 64? Isn't that the Jag programmer's responsibility?
+// Why do we check for a valid handler at 64? Isn't that the Jag programmer's responsibility? (YES)
+#warning "!!! DSP IRQs that go to the 68K have to be routed thru TOM !!! FIX !!!"
                                if (JERRYIRQEnabled(IRQ2_DSP))// && jaguar_interrupt_handler_is_valid(64))
                                {
                                        JERRYSetPendingIRQ(IRQ2_DSP);
-                                       dsp_releaseTimeslice();
-                                       m68k_set_irq(7);                        // Set 68000 NMI...
+                                       DSPReleaseTimeslice();
+                                       m68k_set_irq(2);                        // Set 68000 IPL 2...
                                }
                                data &= ~CPUINT;
                        }
@@ -869,7 +907,7 @@ WriteLog("Write to DSP CTRL by %s: %08X\n", whoName[who], data);
                                WriteLog("DSP: CPU -> DSP interrupt\n");
 #endif
                                m68k_end_timeslice();
-                               gpu_releaseTimeslice();
+                               DSPReleaseTimeslice();
                                DSPSetIRQLine(DSPIRQ_CPU, ASSERT_LINE);
                                data &= ~DSPINT0;
                        }
@@ -909,14 +947,14 @@ else
        WriteLog(" --> Stopped by %s! (DSP PC: %08X)", whoName[who], dsp_pc);
 WriteLog("\n");
 #endif // DSP_DEBUG
-//This isn't exactly right either--we don't know if it was the M68K or the GPU writing here...
+//This isn't exactly right either--we don't know if it was the M68K or the DSP writing here...
 // !!! FIX !!! [DONE]
                        if (DSP_RUNNING)
                        {
                                if (who == M68K)
                                        m68k_end_timeslice();
-                               else if (who == GPU)
-                                       gpu_releaseTimeslice();
+                               else if (who == DSP)
+                                       DSPReleaseTimeslice();
 
                                if (!wasRunning)
                                        FlushDSPPipeline();
@@ -978,7 +1016,7 @@ void DSPHandleIRQs(void)
        if (!bits)                                                                              // Bail if nothing is enabled
                return;
 
-       int which = 0;                                                                  // Determine which interrupt 
+       int which = 0;                                                                  // Determine which interrupt
        if (bits & 0x01)
                which = 0;
        if (bits & 0x02)
@@ -1060,8 +1098,8 @@ ctrl2[4] = dsp_flags;
        WriteLog(" [PC will return to %08X, R31 = %08X]\n", dsp_pc - (pipeline[plPtrExec].opcode == 38 ? 6 : (pipeline[plPtrExec].opcode == PIPELINE_STALL ? 0 : 2)), dsp_reg[31]);
 #endif
 
-       // subqt  #4,r31                ; pre-decrement stack pointer 
-       // move   pc,r30                ; address of interrupted code 
+       // subqt  #4,r31                ; pre-decrement stack pointer
+       // move   pc,r30                ; address of interrupted code
        // store  r30,(r31)     ; store return address
        dsp_reg[31] -= 4;
 //CC only!
@@ -1092,8 +1130,8 @@ SET32(ram2, regs2[31] - 0xF1B000, dsp_pc - 2 - (pipeline[plPtrExec].opcode == 38
 #endif
 //!!!!!!!!
 
-       // movei  #service_address,r30  ; pointer to ISR entry 
-       // jump  (r30)                                  ; jump to ISR 
+       // movei  #service_address,r30  ; pointer to ISR entry
+       // jump  (r30)                                  ; jump to ISR
        // nop
        dsp_pc = dsp_reg[30] = DSP_WORK_RAM_BASE + (which * 0x10);
 //CC only!
@@ -1144,7 +1182,7 @@ DSPUpdateRegisterBanks();
        if (!bits)                                                                              // Bail if nothing is enabled
                return;
 
-       int which = 0;                                                                  // Determine which interrupt 
+       int which = 0;                                                                  // Determine which interrupt
        if (bits & 0x01)
                which = 0;
        if (bits & 0x02)
@@ -1173,8 +1211,8 @@ ctrl1[4] = dsp_flags;
        WriteLog(" [PC will return to %08X, R31 = %08X]\n", dsp_pc, dsp_reg[31]);
 #endif
 
-       // subqt  #4,r31                ; pre-decrement stack pointer 
-       // move   pc,r30                ; address of interrupted code 
+       // subqt  #4,r31                ; pre-decrement stack pointer
+       // move   pc,r30                ; address of interrupted code
        // store  r30,(r31)     ; store return address
        dsp_reg[31] -= 4;
 //CC only!
@@ -1189,8 +1227,8 @@ SET32(ram1, regs1[31] - 0xF1B000, dsp_pc - 2);
 #endif
 //!!!!!!!!
 
-       // movei  #service_address,r30  ; pointer to ISR entry 
-       // jump  (r30)                                  ; jump to ISR 
+       // movei  #service_address,r30  ; pointer to ISR entry
+       // jump  (r30)                                  ; jump to ISR
        // nop
        dsp_pc = dsp_reg[30] = DSP_WORK_RAM_BASE + (which * 0x10);
 //CC only!
@@ -1313,12 +1351,15 @@ void DSPDone(void)
        WriteLog("DSP: Stopped at PC=%08X dsp_modulo=%08X (dsp %s running)\n", dsp_pc, dsp_modulo, (DSP_RUNNING ? "was" : "wasn't"));
        WriteLog("DSP: %sin interrupt handler\n", (dsp_flags & IMASK ? "" : "not "));
 
-       // get the active interrupt bits 
+       // get the active interrupt bits
        int bits = ((dsp_control >> 10) & 0x20) | ((dsp_control >> 6) & 0x1F);
-       // get the interrupt mask 
+       // get the interrupt mask
        int mask = ((dsp_flags >> 11) & 0x20) | ((dsp_flags >> 4) & 0x1F);
 
-       WriteLog("DSP: pending=%08X enabled=%08X\n", bits, mask);
+       WriteLog("DSP: pending=$%X enabled=$%X (%s%s%s%s%s%s)\n", bits, mask,
+               (mask & 0x01 ? "CPU " : ""), (mask & 0x02 ? "I2S " : ""),
+               (mask & 0x04 ? "Timer0 " : ""), (mask & 0x08 ? "Timer1 " : ""),
+               (mask & 0x10 ? "Ext0 " : ""), (mask & 0x20 ? "Ext1" : ""));
        WriteLog("\nRegisters bank 0\n");
        for(int j=0; j<8; j++)
        {
@@ -1355,9 +1396,14 @@ void DSPDone(void)
                        WriteLog("\t%s %i\n", dsp_opcode_str[i], dsp_opcode_use[i]);
        }//*/
 
-       memory_free(dsp_ram_8);
-       memory_free(dsp_reg_bank_0);
-       memory_free(dsp_reg_bank_1);
+//     memory_free(dsp_ram_8);
+//     memory_free(dsp_reg_bank_0);
+//     memory_free(dsp_reg_bank_1);
+       if (dsp_branch_condition_table)
+               free(dsp_branch_condition_table);
+
+       if (mirror_table)
+               free(mirror_table);
 }
 
 
@@ -1936,7 +1982,11 @@ static void dsp_opcode_store_r14_indexed(void)
        if (doDSPDis)
                WriteLog("%06X: STORE  R%02u, (R14+$%02X) [NCZ:%u%u%u, R%02u=%08X, R14+$%02X=%08X]\n", dsp_pc-2, IMM_2, dsp_convert_zero[IMM_1] << 2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN, dsp_convert_zero[IMM_1] << 2, dsp_reg[14]+(dsp_convert_zero[IMM_1] << 2));
 #endif
+#ifdef DSP_CORRECT_ALIGNMENT_STORE
+       DSPWriteLong((dsp_reg[14] & 0xFFFFFFFC) + (dsp_convert_zero[IMM_1] << 2), RN, DSP);
+#else
        DSPWriteLong(dsp_reg[14] + (dsp_convert_zero[IMM_1] << 2), RN, DSP);
+#endif
 }
 
 static void dsp_opcode_store_r15_indexed(void)
@@ -1945,7 +1995,11 @@ static void dsp_opcode_store_r15_indexed(void)
        if (doDSPDis)
                WriteLog("%06X: STORE  R%02u, (R15+$%02X) [NCZ:%u%u%u, R%02u=%08X, R15+$%02X=%08X]\n", dsp_pc-2, IMM_2, dsp_convert_zero[IMM_1] << 2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN, dsp_convert_zero[IMM_1] << 2, dsp_reg[15]+(dsp_convert_zero[IMM_1] << 2));
 #endif
+#ifdef DSP_CORRECT_ALIGNMENT_STORE
+       DSPWriteLong((dsp_reg[15] & 0xFFFFFFFC) + (dsp_convert_zero[IMM_1] << 2), RN, DSP);
+#else
        DSPWriteLong(dsp_reg[15] + (dsp_convert_zero[IMM_1] << 2), RN, DSP);
+#endif
 }
 
 static void dsp_opcode_load_r14_ri(void)
@@ -1954,7 +2008,11 @@ static void dsp_opcode_load_r14_ri(void)
        if (doDSPDis)
                WriteLog("%06X: LOAD   (R14+R%02u), R%02u [NCZ:%u%u%u, R14+R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM+dsp_reg[14], IMM_2, RN);
 #endif
+#ifdef DSP_CORRECT_ALIGNMENT
+       RN = DSPReadLong((dsp_reg[14] + RM) & 0xFFFFFFFC, DSP);
+#else
        RN = DSPReadLong(dsp_reg[14] + RM, DSP);
+#endif
 #ifdef DSP_DIS_LOAD14R
        if (doDSPDis)
                WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
@@ -1967,7 +2025,11 @@ static void dsp_opcode_load_r15_ri(void)
        if (doDSPDis)
                WriteLog("%06X: LOAD   (R15+R%02u), R%02u [NCZ:%u%u%u, R15+R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM+dsp_reg[15], IMM_2, RN);
 #endif
+#ifdef DSP_CORRECT_ALIGNMENT
+       RN = DSPReadLong((dsp_reg[15] + RM) & 0xFFFFFFFC, DSP);
+#else
        RN = DSPReadLong(dsp_reg[15] + RM, DSP);
+#endif
 #ifdef DSP_DIS_LOAD15R
        if (doDSPDis)
                WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
@@ -2010,10 +2072,17 @@ static void dsp_opcode_storew(void)
        if (doDSPDis)
                WriteLog("%06X: STOREW R%02u, (R%02u) [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_pc-2, IMM_2, IMM_1, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN, IMM_1, RM);
 #endif
+#ifdef DSP_CORRECT_ALIGNMENT_STORE
+       if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
+               DSPWriteLong(RM & 0xFFFFFFFE, RN & 0xFFFF, DSP);
+       else
+               JaguarWriteWord(RM & 0xFFFFFFFE, RN, DSP);
+#else
        if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
                DSPWriteLong(RM, RN & 0xFFFF, DSP);
        else
                JaguarWriteWord(RM, RN, DSP);
+#endif
 }
 
 static void dsp_opcode_store(void)
@@ -2022,7 +2091,11 @@ static void dsp_opcode_store(void)
        if (doDSPDis)
                WriteLog("%06X: STORE  R%02u, (R%02u) [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_pc-2, IMM_2, IMM_1, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN, IMM_1, RM);
 #endif
+#ifdef DSP_CORRECT_ALIGNMENT_STORE
+       DSPWriteLong(RM & 0xFFFFFFFC, RN, DSP);
+#else
        DSPWriteLong(RM, RN, DSP);
+#endif
 }
 
 static void dsp_opcode_loadb(void)
@@ -2047,10 +2120,17 @@ static void dsp_opcode_loadw(void)
        if (doDSPDis)
                WriteLog("%06X: LOADW  (R%02u), R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
 #endif
+#ifdef DSP_CORRECT_ALIGNMENT
+       if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
+               RN = DSPReadLong(RM & 0xFFFFFFFE, DSP) & 0xFFFF;
+       else
+               RN = JaguarReadWord(RM & 0xFFFFFFFE, DSP);
+#else
        if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
                RN = DSPReadLong(RM, DSP) & 0xFFFF;
        else
                RN = JaguarReadWord(RM, DSP);
+#endif
 #ifdef DSP_DIS_LOADW
        if (doDSPDis)
                WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
@@ -2063,7 +2143,11 @@ static void dsp_opcode_load(void)
        if (doDSPDis)
                WriteLog("%06X: LOAD   (R%02u), R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
 #endif
+#ifdef DSP_CORRECT_ALIGNMENT
+       RN = DSPReadLong(RM & 0xFFFFFFFC, DSP);
+#else
        RN = DSPReadLong(RM, DSP);
+#endif
 #ifdef DSP_DIS_LOAD
        if (doDSPDis)
                WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
@@ -2076,7 +2160,11 @@ static void dsp_opcode_load_r14_indexed(void)
        if (doDSPDis)
                WriteLog("%06X: LOAD   (R14+$%02X), R%02u [NCZ:%u%u%u, R14+$%02X=%08X, R%02u=%08X] -> ", dsp_pc-2, dsp_convert_zero[IMM_1] << 2, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, dsp_convert_zero[IMM_1] << 2, dsp_reg[14]+(dsp_convert_zero[IMM_1] << 2), IMM_2, RN);
 #endif
+#ifdef DSP_CORRECT_ALIGNMENT
+       RN = DSPReadLong((dsp_reg[14] & 0xFFFFFFFC) + (dsp_convert_zero[IMM_1] << 2), DSP);
+#else
        RN = DSPReadLong(dsp_reg[14] + (dsp_convert_zero[IMM_1] << 2), DSP);
+#endif
 #ifdef DSP_DIS_LOAD14I
        if (doDSPDis)
                WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
@@ -2089,7 +2177,11 @@ static void dsp_opcode_load_r15_indexed(void)
        if (doDSPDis)
                WriteLog("%06X: LOAD   (R15+$%02X), R%02u [NCZ:%u%u%u, R15+$%02X=%08X, R%02u=%08X] -> ", dsp_pc-2, dsp_convert_zero[IMM_1] << 2, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, dsp_convert_zero[IMM_1] << 2, dsp_reg[15]+(dsp_convert_zero[IMM_1] << 2), IMM_2, RN);
 #endif
+#ifdef DSP_CORRECT_ALIGNMENT
+       RN = DSPReadLong((dsp_reg[15] & 0xFFFFFFFC) + (dsp_convert_zero[IMM_1] << 2), DSP);
+#else
        RN = DSPReadLong(dsp_reg[15] + (dsp_convert_zero[IMM_1] << 2), DSP);
+#endif
 #ifdef DSP_DIS_LOAD15I
        if (doDSPDis)
                WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
@@ -2286,7 +2378,7 @@ static void dsp_opcode_imacn(void)
        if (doDSPDis)
                WriteLog("[NCZ:%u%u%u, DSP_ACC=%02X%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, (uint8)(dsp_acc >> 32), (uint32)(dsp_acc & 0xFFFFFFFF));
 #endif
-} 
+}
 
 static void dsp_opcode_mtoi(void)
 {
@@ -2319,14 +2411,14 @@ static void dsp_opcode_normi(void)
 static void dsp_opcode_mmult(void)
 {
        int count       = dsp_matrix_control&0x0f;
-       uint32 addr = dsp_pointer_to_matrix; // in the gpu ram
+       uint32 addr = dsp_pointer_to_matrix; // in the dsp ram
        int64 accum = 0;
        uint32 res;
 
        if (!(dsp_matrix_control & 0x10))
        {
                for (int i = 0; i < count; i++)
-               { 
+               {
                        int16 a;
                        if (i&0x01)
                                a=(int16)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
@@ -2365,7 +2457,7 @@ static void dsp_opcode_abs(void)
 #endif
        uint32 _Rn = RN;
        uint32 res;
-       
+
        if (_Rn == 0x80000000)
                dsp_flag_n = 1;
        else
@@ -2597,25 +2689,25 @@ void dsp_opcode_addqmod(void)
 #endif
 }
 
-void dsp_opcode_subqmod(void)  
+void dsp_opcode_subqmod(void)
 {
        uint32 r1 = dsp_convert_zero[IMM_1];
        uint32 r2 = RN;
        uint32 res = r2 - r1;
        res = (res & (~dsp_modulo)) | (r2 & dsp_modulo);
        RN = res;
-       
+
        SET_ZNC_SUB(r2, r1, res);
 }
 
-void dsp_opcode_mirror(void)   
+void dsp_opcode_mirror(void)
 {
        uint32 r1 = RN;
        RN = (mirror_table[r1 & 0xFFFF] << 16) | mirror_table[r1 >> 16];
        SET_ZN(RN);
 }
 
-void dsp_opcode_sat32s(void)           
+void dsp_opcode_sat32s(void)
 {
        int32 r2 = (uint32)RN;
        int32 temp = dsp_acc >> 32;
@@ -2624,7 +2716,7 @@ void dsp_opcode_sat32s(void)
        SET_ZN(res);
 }
 
-void dsp_opcode_sat16s(void)           
+void dsp_opcode_sat16s(void)
 {
        int32 r2 = RN;
        uint32 res = (r2 < -32768) ? -32768 : (r2 > 32767) ? 32767 : r2;
@@ -2640,7 +2732,7 @@ static void DSP_abs(void);
 static void DSP_add(void);
 static void DSP_addc(void);
 static void DSP_addq(void);
-static void DSP_addqmod(void); 
+static void DSP_addqmod(void);
 static void DSP_addqt(void);
 static void DSP_and(void);
 static void DSP_bclr(void);
@@ -2662,7 +2754,7 @@ static void DSP_load_r14_i(void);
 static void DSP_load_r14_r(void);
 static void DSP_load_r15_i(void);
 static void DSP_load_r15_r(void);
-static void DSP_mirror(void);  
+static void DSP_mirror(void);
 static void DSP_mmult(void);
 static void DSP_move(void);
 static void DSP_movefa(void);
@@ -2680,8 +2772,8 @@ static void DSP_or(void);
 static void DSP_resmac(void);
 static void DSP_ror(void);
 static void DSP_rorq(void);
-static void DSP_sat16s(void);  
-static void DSP_sat32s(void);  
+static void DSP_sat16s(void);
+static void DSP_sat32s(void);
 static void DSP_sh(void);
 static void DSP_sha(void);
 static void DSP_sharq(void);
@@ -2697,7 +2789,7 @@ static void DSP_store_r15_r(void);
 static void DSP_sub(void);
 static void DSP_subc(void);
 static void DSP_subq(void);
-static void DSP_subqmod(void); 
+static void DSP_subqmod(void);
 static void DSP_subqt(void);
 static void DSP_xor(void);
 
@@ -3080,6 +3172,7 @@ if (dsp_pc == 0xF1B092)
 pcQueue1[pcQPtr1++] = dsp_pc;
 pcQPtr1 &= 0x3FF;
 
+#ifdef DSP_DEBUG_PL2
 if ((dsp_pc < 0xF1B000 || dsp_pc > 0xF1CFFF) && !doDSPDis)
 {
        WriteLog("DSP: PC has stepped out of bounds...\n\nBacktrace:\n\n");
@@ -3094,6 +3187,8 @@ if ((dsp_pc < 0xF1B000 || dsp_pc > 0xF1CFFF) && !doDSPDis)
        }
        WriteLog("\n");
 }//*/
+#endif
+
                if (IMASKCleared)                                               // If IMASK was cleared,
                {
 #ifdef DSP_DEBUG_IRQ
@@ -3197,9 +3292,10 @@ WriteLog("\tW -> %02u, %02u, %02u; r1=%08X, r2= %08X, res=%08X, wb=%u (%s)\n", p
                // Stage 2: Execute
                if (pipeline[plPtrExec].opcode != PIPELINE_STALL)
                {
+#ifdef DSP_DEBUG_PL2
 if (doDSPDis)
        WriteLog("\t[inst=%02u][R28=%08X, alt R28=%08X, REGPAGE=%s]\n", pipeline[plPtrExec].opcode, dsp_reg[28], dsp_alternate_reg[28], (dsp_flags & REGPAGE ? "set" : "not set"));
-#ifdef DSP_DEBUG_PL2
+
 if (doDSPDis)
 {
 WriteLog("DSPExecP: About to execute opcode %s...\n", dsp_opcode_str[pipeline[plPtrExec].opcode]);
@@ -3418,7 +3514,7 @@ static void DSP_abs(void)
                WriteLog("%06X: ABS    R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", DSP_PPC, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
 #endif
        uint32 _Rn = PRN;
-       
+
        if (_Rn == 0x80000000)
                dsp_flag_n = 1;
        else
@@ -3641,7 +3737,7 @@ static void DSP_imacn(void)
        if (doDSPDis)
                WriteLog("[NCZ:%u%u%u, DSP_ACC=%02X%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, (uint8)(dsp_acc >> 32), (uint32)(dsp_acc & 0xFFFFFFFF));
 #endif
-} 
+}
 
 static void DSP_imult(void)
 {
@@ -3717,7 +3813,7 @@ const char * condition[32] =
                // Now that we've branched, we have to make sure that the following instruction
                // is executed atomically with this one and then flush the pipeline before setting
                // the new PC.
-               
+
                // Step 1: Handle writebacks at stage 3 of pipeline
 /*             if (pipeline[plPtrWrite].opcode != PIPELINE_STALL)
                {
@@ -3822,7 +3918,7 @@ const char * condition[32] =
                // Now that we've branched, we have to make sure that the following instruction
                // is executed atomically with this one and then flush the pipeline before setting
                // the new PC.
-               
+
                // Step 1: Handle writebacks at stage 3 of pipeline
 /*             if (pipeline[plPtrWrite].opcode != PIPELINE_STALL)
                {
@@ -3909,7 +4005,11 @@ static void DSP_load(void)
        if (doDSPDis)
                WriteLog("%06X: LOAD   (R%02u), R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
 #endif
+#ifdef DSP_CORRECT_ALIGNMENT
+       PRES = DSPReadLong(PRM & 0xFFFFFFFC, DSP);
+#else
        PRES = DSPReadLong(PRM, DSP);
+#endif
 #ifdef DSP_DIS_LOAD
        if (doDSPDis)
                WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
@@ -3938,10 +4038,17 @@ static void DSP_loadw(void)
        if (doDSPDis)
                WriteLog("%06X: LOADW  (R%02u), R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
 #endif
+#ifdef DSP_CORRECT_ALIGNMENT
+       if (PRM >= DSP_WORK_RAM_BASE && PRM <= (DSP_WORK_RAM_BASE + 0x1FFF))
+               PRES = DSPReadLong(PRM & 0xFFFFFFFE, DSP) & 0xFFFF;
+       else
+               PRES = JaguarReadWord(PRM & 0xFFFFFFFE, DSP);
+#else
        if (PRM >= DSP_WORK_RAM_BASE && PRM <= (DSP_WORK_RAM_BASE + 0x1FFF))
                PRES = DSPReadLong(PRM, DSP) & 0xFFFF;
        else
                PRES = JaguarReadWord(PRM, DSP);
+#endif
 #ifdef DSP_DIS_LOADW
        if (doDSPDis)
                WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
@@ -3954,7 +4061,11 @@ static void DSP_load_r14_i(void)
        if (doDSPDis)
                WriteLog("%06X: LOAD   (R14+$%02X), R%02u [NCZ:%u%u%u, R14+$%02X=%08X, R%02u=%08X] -> ", DSP_PPC, dsp_convert_zero[PIMM1] << 2, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, dsp_convert_zero[PIMM1] << 2, dsp_reg[14]+(dsp_convert_zero[PIMM1] << 2), PIMM2, PRN);
 #endif
+#ifdef DSP_CORRECT_ALIGNMENT
+       PRES = DSPReadLong((dsp_reg[14] & 0xFFFFFFFC) + (dsp_convert_zero[PIMM1] << 2), DSP);
+#else
        PRES = DSPReadLong(dsp_reg[14] + (dsp_convert_zero[PIMM1] << 2), DSP);
+#endif
 #ifdef DSP_DIS_LOAD14I
        if (doDSPDis)
                WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
@@ -3967,7 +4078,11 @@ static void DSP_load_r14_r(void)
        if (doDSPDis)
                WriteLog("%06X: LOAD   (R14+R%02u), R%02u [NCZ:%u%u%u, R14+R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM+dsp_reg[14], PIMM2, PRES);
 #endif
+#ifdef DSP_CORRECT_ALIGNMENT
+       PRES = DSPReadLong((dsp_reg[14] + PRM) & 0xFFFFFFFC, DSP);
+#else
        PRES = DSPReadLong(dsp_reg[14] + PRM, DSP);
+#endif
 #ifdef DSP_DIS_LOAD14R
        if (doDSPDis)
                WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
@@ -3980,7 +4095,11 @@ static void DSP_load_r15_i(void)
        if (doDSPDis)
                WriteLog("%06X: LOAD   (R15+$%02X), R%02u [NCZ:%u%u%u, R15+$%02X=%08X, R%02u=%08X] -> ", DSP_PPC, dsp_convert_zero[PIMM1] << 2, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, dsp_convert_zero[PIMM1] << 2, dsp_reg[15]+(dsp_convert_zero[PIMM1] << 2), PIMM2, PRN);
 #endif
+#ifdef DSP_CORRECT_ALIGNMENT
+       PRES = DSPReadLong((dsp_reg[15] &0xFFFFFFFC) + (dsp_convert_zero[PIMM1] << 2), DSP);
+#else
        PRES = DSPReadLong(dsp_reg[15] + (dsp_convert_zero[PIMM1] << 2), DSP);
+#endif
 #ifdef DSP_DIS_LOAD15I
        if (doDSPDis)
                WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
@@ -3993,14 +4112,18 @@ static void DSP_load_r15_r(void)
        if (doDSPDis)
                WriteLog("%06X: LOAD   (R15+R%02u), R%02u [NCZ:%u%u%u, R15+R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM+dsp_reg[15], PIMM2, PRN);
 #endif
+#ifdef DSP_CORRECT_ALIGNMENT
+       PRES = DSPReadLong((dsp_reg[15] + PRM) & 0xFFFFFFFC, DSP);
+#else
        PRES = DSPReadLong(dsp_reg[15] + PRM, DSP);
+#endif
 #ifdef DSP_DIS_LOAD15R
        if (doDSPDis)
                WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
 #endif
 }
 
-static void DSP_mirror(void)   
+static void DSP_mirror(void)
 {
        uint32 r1 = PRN;
        PRES = (mirror_table[r1 & 0xFFFF] << 16) | mirror_table[r1 >> 16];
@@ -4010,14 +4133,14 @@ static void DSP_mirror(void)
 static void DSP_mmult(void)
 {
        int count       = dsp_matrix_control&0x0f;
-       uint32 addr = dsp_pointer_to_matrix; // in the gpu ram
+       uint32 addr = dsp_pointer_to_matrix; // in the dsp ram
        int64 accum = 0;
        uint32 res;
 
        if (!(dsp_matrix_control & 0x10))
        {
                for (int i = 0; i < count; i++)
-               { 
+               {
                        int16 a;
                        if (i&0x01)
                                a=(int16)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
@@ -4279,7 +4402,7 @@ static void DSP_rorq(void)
 #endif
 }
 
-static void DSP_sat16s(void)           
+static void DSP_sat16s(void)
 {
        int32 r2 = PRN;
        uint32 res = (r2 < -32768) ? -32768 : (r2 > 32767) ? 32767 : r2;
@@ -4287,7 +4410,7 @@ static void DSP_sat16s(void)
        SET_ZN(res);
 }
 
-static void DSP_sat32s(void)           
+static void DSP_sat32s(void)
 {
        int32 r2 = (uint32)PRN;
        int32 temp = dsp_acc >> 32;
@@ -4431,7 +4554,11 @@ static void DSP_store(void)
 #endif
 //     DSPWriteLong(PRM, PRN, DSP);
 //     NO_WRITEBACK;
+#ifdef DSP_CORRECT_ALIGNMENT_STORE
+       pipeline[plPtrExec].address = PRM & 0xFFFFFFFC;
+#else
        pipeline[plPtrExec].address = PRM;
+#endif
        pipeline[plPtrExec].value = PRN;
        pipeline[plPtrExec].type = TYPE_DWORD;
        WRITEBACK_ADDR;
@@ -4477,7 +4604,11 @@ static void DSP_storew(void)
 //             JaguarWriteWord(PRM, PRN, DSP);
 //
 //     NO_WRITEBACK;
+#ifdef DSP_CORRECT_ALIGNMENT_STORE
+       pipeline[plPtrExec].address = PRM & 0xFFFFFFFE;
+#else
        pipeline[plPtrExec].address = PRM;
+#endif
 
        if (PRM >= DSP_WORK_RAM_BASE && PRM <= (DSP_WORK_RAM_BASE + 0x1FFF))
        {
@@ -4500,7 +4631,11 @@ static void DSP_store_r14_i(void)
 #endif
 //     DSPWriteLong(dsp_reg[14] + (dsp_convert_zero[PIMM1] << 2), PRN, DSP);
 //     NO_WRITEBACK;
+#ifdef DSP_CORRECT_ALIGNMENT_STORE
+       pipeline[plPtrExec].address = (dsp_reg[14] & 0xFFFFFFFC) + (dsp_convert_zero[PIMM1] << 2);
+#else
        pipeline[plPtrExec].address = dsp_reg[14] + (dsp_convert_zero[PIMM1] << 2);
+#endif
        pipeline[plPtrExec].value = PRN;
        pipeline[plPtrExec].type = TYPE_DWORD;
        WRITEBACK_ADDR;
@@ -4510,7 +4645,11 @@ static void DSP_store_r14_r(void)
 {
 //     DSPWriteLong(dsp_reg[14] + PRM, PRN, DSP);
 //     NO_WRITEBACK;
+#ifdef DSP_CORRECT_ALIGNMENT_STORE
+       pipeline[plPtrExec].address = (dsp_reg[14] + PRM) & 0xFFFFFFFC;
+#else
        pipeline[plPtrExec].address = dsp_reg[14] + PRM;
+#endif
        pipeline[plPtrExec].value = PRN;
        pipeline[plPtrExec].type = TYPE_DWORD;
        WRITEBACK_ADDR;
@@ -4524,7 +4663,11 @@ static void DSP_store_r15_i(void)
 #endif
 //     DSPWriteLong(dsp_reg[15] + (dsp_convert_zero[PIMM1] << 2), PRN, DSP);
 //     NO_WRITEBACK;
+#ifdef DSP_CORRECT_ALIGNMENT_STORE
+       pipeline[plPtrExec].address = (dsp_reg[15] & 0xFFFFFFFC) + (dsp_convert_zero[PIMM1] << 2);
+#else
        pipeline[plPtrExec].address = dsp_reg[15] + (dsp_convert_zero[PIMM1] << 2);
+#endif
        pipeline[plPtrExec].value = PRN;
        pipeline[plPtrExec].type = TYPE_DWORD;
        WRITEBACK_ADDR;
@@ -4534,7 +4677,11 @@ static void DSP_store_r15_r(void)
 {
 //     DSPWriteLong(dsp_reg[15] + PRM, PRN, DSP);
 //     NO_WRITEBACK;
+#ifdef DSP_CORRECT_ALIGNMENT_STORE
+       pipeline[plPtrExec].address = (dsp_reg[15] + PRM) & 0xFFFFFFFC;
+#else
        pipeline[plPtrExec].address = dsp_reg[15] + PRM;
+#endif
        pipeline[plPtrExec].value = PRN;
        pipeline[plPtrExec].type = TYPE_DWORD;
        WRITEBACK_ADDR;
@@ -4587,7 +4734,7 @@ static void DSP_subq(void)
 #endif
 }
 
-static void DSP_subqmod(void)  
+static void DSP_subqmod(void)
 {
        uint32 r1 = dsp_convert_zero[PIMM1];
        uint32 r2 = PRN;