/[pcsx2_0.9.7]/trunk/pcsx2/HwWrite.cpp
ViewVC logotype

Diff of /trunk/pcsx2/HwWrite.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 31 by william, Tue Sep 7 03:24:11 2010 UTC revision 62 by william, Tue Sep 7 11:08:22 2010 UTC
# Line 16  Line 16 
16    
17  #include "PrecompiledHeader.h"  #include "PrecompiledHeader.h"
18  #include "Common.h"  #include "Common.h"
   
19  #include "Hardware.h"  #include "Hardware.h"
20    
21  using namespace R5900;  #include "ps2/HwInternal.h"
22    #include "ps2/eeHwTraceLog.inl"
 /////////////////////////////////////////////////////////////////////////  
 // DMA Execution Interfaces  
   
 static bool QuickDmaExec( void (*func)(), u32 mem)  
 {  
         bool ret = false;  
     DMACh *reg = &psH_DMACh(mem);  
   
         if (reg->chcr.STR && dmacRegs->ctrl.DMAE && !psHu8(DMAC_ENABLER+2))  
         {  
                 Registers::Freeze();  
                 func();  
                 Registers::Thaw();  
                 ret = true;  
         }  
23    
24    using namespace R5900;
25    
26          return ret;  // Shift the middle 8 bits (bits 4-12) into the lower 8 bits.
27  }  // This helps the compiler optimize the switch statement into a lookup table. :)
28    
29    #define HELPSWITCH(m) (((m)>>4) & 0xff)
30    #define mcase(src) case HELPSWITCH(src)
31    
32  tDMAC_QUEUE QueuedDMA(0);  template< uint page > void __fastcall _hwWrite8(u32 mem, u8 value);
33  u32 oldvalue = 0;  template< uint page > void __fastcall _hwWrite16(u32 mem, u8 value);
34    template< uint page > void __fastcall _hwWrite128(u32 mem, u8 value);
35    
 void __fastcall StartQueuedDMA()  
 {  
         if (QueuedDMA.VIF0) { DMA_LOG("Resuming DMA for VIF0"); if(QuickDmaExec(dmaVIF0, D0_CHCR) == true) QueuedDMA.VIF0 = false; }  
         if (QueuedDMA.VIF1) { DMA_LOG("Resuming DMA for VIF1"); if(QuickDmaExec(dmaVIF1, D1_CHCR) == true) QueuedDMA.VIF1 = false; }  
         if (QueuedDMA.GIF ) { DMA_LOG("Resuming DMA for GIF" ); if(QuickDmaExec(dmaGIF , D2_CHCR) == true) QueuedDMA.GIF = false; }  
         if (QueuedDMA.IPU0) { DMA_LOG("Resuming DMA for IPU0"); if(QuickDmaExec(dmaIPU0, D3_CHCR) == true) QueuedDMA.IPU0 = false; }  
         if (QueuedDMA.IPU1) { DMA_LOG("Resuming DMA for IPU1"); if(QuickDmaExec(dmaIPU1, D4_CHCR) == true) QueuedDMA.IPU1 = false; }  
         if (QueuedDMA.SIF0) { DMA_LOG("Resuming DMA for SIF0"); if(QuickDmaExec(dmaSIF0, D5_CHCR) == true) QueuedDMA.SIF0 = false; }  
         if (QueuedDMA.SIF1) { DMA_LOG("Resuming DMA for SIF1"); if(QuickDmaExec(dmaSIF1, D6_CHCR) == true) QueuedDMA.SIF1 = false; }  
         if (QueuedDMA.SIF2) { DMA_LOG("Resuming DMA for SIF2"); if(QuickDmaExec(dmaSIF2, D7_CHCR) == true) QueuedDMA.SIF2 = false; }  
         if (QueuedDMA.SPR0) { DMA_LOG("Resuming DMA for SPR0"); if(QuickDmaExec(dmaSPR0, D8_CHCR) == true) QueuedDMA.SPR0 = false; }  
         if (QueuedDMA.SPR1) { DMA_LOG("Resuming DMA for SPR1"); if(QuickDmaExec(dmaSPR1, D9_CHCR) == true) QueuedDMA.SPR1 = false; }  
 }  
36    
37  // dark cloud2 uses 8 bit DMAs register writes  template<uint page>
38  static __forceinline void DmaExec8( void (*func)(), u32 mem, u8 value )  void __fastcall _hwWrite32( u32 mem, u32 value )
39  {  {
40          DMACh *reg = &psH_DMACh(mem & ~0xf);          pxAssume( (mem & 0x03) == 0 );
41    
42          //The only thing we can do in an 8bit write is set the CHCR, so lets just do checks for that          // Notes:
43            // All unknown registers on the EE are "reserved" as discarded writes and indeterminate
44            // reads.  Bus error is only generated for registers outside the first 16k of mapped
45            // register space (which is handled by the VTLB mapping, so no need for checks here).
46    
47          //It's invalid for the hardware to write a DMA while it is active, not without Suspending the DMAC          switch (page)
         if (reg->chcr.STR)  
48          {          {
49                  if(psHu8(DMAC_ENABLER+2) == 1) //DMA is suspended so we can allow writes to anything                  case 0x00:      if (!rcntWrite32<0x00>(mem, value)) return;     break;
50                  {                  case 0x01:      if (!rcntWrite32<0x01>(mem, value)) return;     break;
                         //If it stops the DMA, we need to clear any pending interrupts so the DMA doesnt continue.  
                         if(value == 0)  
                         {  
                                 //DevCon.Warning(L"8bit %s DMA Stopped on Suspend", ChcrName(mem & ~0xf));  
                                 cpuClearInt( ChannelNumber(mem & ~0xf) );  
                                 QueuedDMA._u16 &= ~(1 << ChannelNumber(mem & ~0xf));  
                         }  
                         //Here we update the CHCR STR (Busy) bit, we don't touch anything else.  
                         reg->chcr.STR = value;  
                         return;  
                 }  
                 else //Else the DMA is running (Not Suspended), so we cant touch it!  
                 {  
                         //As the manual states "Fields other than STR can only be written to when the DMA is stopped"  
                         //Also "The DMA may not stop properly just by writing 0 to STR"  
                         //So the presumption is that STR can be written to (ala force stop the DMA) but nothing else  
51    
52                          if(value == 0)                  case 0x02:
53                          {                          if (!ipuWrite32(mem, value)) return;
54                                  //DevCon.Warning(L"8bit Force Stopping %s (Current CHCR %x) while DMA active", ChcrName(mem & ~0xf), reg->chcr._u32, value);                  break;
                                 reg->chcr.STR = value;  
                                 //We need to clear any existing DMA loops that are in progress else they will continue!  
                                 cpuClearInt( ChannelNumber(mem&~0xf) );  
                                 QueuedDMA._u16 &= ~(1 << ChannelNumber(mem&~0xf)); //Clear any queued DMA requests for this channel  
                         }  
                         //else DevCon.Warning(L"8bit Attempted to stop %s DMA without suspend, ignoring", ChcrName(mem & ~0xf));  
                         return;  
                 }  
55    
56          }                  case 0x04:
57                    case 0x05:
58                    case 0x06:
59                    case 0x07:
60                    {
61                            // [Ps2Confirm] Direct FIFO read/write behavior.  We need to create a test that writes
62                            // data to one of the FIFOs and determine the result.  I'm not quite sure offhand a good
63                            // way to do that --air
64                            // Current assumption is that 32-bit and 64-bit writes likely do 128-bit zero-filled
65                            // writes (upper 96 bits are 0, lower 32 bits are effective).
66    
67          reg->chcr.STR = value;                          u128 zerofill = u128::From32(0);
68                            zerofill._u32[(mem >> 2) & 0x03] = value;
69    
70          if (reg->chcr.STR && dmacRegs->ctrl.DMAE && !psHu8(DMAC_ENABLER+2))                          DevCon.WriteLn( Color_Cyan, "Writing 32-bit FIFO data (zero-extended to 128 bits)" );
71          {                          _hwWrite128<page>(mem & ~0x0f, &zerofill);
72                  Registers::Freeze();                  }
73                  func();                  return;
                 Registers::Thaw();  
         }  
         else if(reg->chcr.STR)  
         {  
                 //DevCon.Warning(L"8bit %s DMA Start while DMAC Disabled\n",ChcrName(mem));  
                 QueuedDMA._u16 |= (1 << ChannelNumber(mem & ~0xf)); //Queue the DMA up to be started then the DMA's are Enabled and or the Suspend is lifted  
         }  
 }  
74    
75  static __forceinline void DmaExec16( void (*func)(), u32 mem, u16 value )                  case 0x03:
76  {                          if (mem >= EEMemoryMap::VIF0_Start)
77                            {
78                                    if(mem >= EEMemoryMap::VIF1_Start)
79                                    {
80                                            if (!vifWrite32<1>(mem, value)) return;
81                                    }
82                                    else
83                                    {
84                                            if (!vifWrite32<0>(mem, value)) return;
85                                    }
86                            }
87                            else iswitch(mem)
88                            {
89                                    icase(GIF_CTRL)
90                                    {
91                                            psHu32(mem) = value & 0x8;
92    
93                                            if (value & 0x1)
94                                                    gsGIFReset();
95    
96                                            if (value & 8)
97                                                    gifRegs.stat.PSE = true;
98                                            else
99                                                    gifRegs.stat.PSE = false;
100    
101                                            return;
102                                    }
103    
104                                    icase(GIF_MODE)
105                                    {
106                                            // need to set GIF_MODE (hamster ball)
107                                            gifRegs.mode.write(value);
108    
109                                            // set/clear bits 0 and 2 as per the GIF_MODE value.
110                                            const u32 bitmask = GIF_MODE_M3R | GIF_MODE_IMT;
111                                            psHu32(GIF_STAT) &= ~bitmask;
112                                            psHu32(GIF_STAT) |= (u32)value & bitmask;
113    
114      DMACh *reg = &psH_DMACh(mem);                                          return;
115      tDMA_CHCR chcr(value);                                  }
116                            }
117                    break;
118    
119          //It's invalid for the hardware to write a DMA while it is active, not without Suspending the DMAC                  case 0x08:
120          if (reg->chcr.STR)                  case 0x09:
121          {                  case 0x0a:
122                  if(psHu8(DMAC_ENABLER+2) == 1) //DMA is suspended so we can allow writes to anything                  case 0x0b:
123                    case 0x0c:
124                    case 0x0d:
125                    case 0x0e:
126                            if (!dmacWrite32<page>(mem, value)) return;
127                    break;
128                    
129                    case 0x0f:
130                  {                  {
131                          //If it stops the DMA, we need to clear any pending interrupts so the DMA doesnt continue.                          switch( HELPSWITCH(mem) )
                         if(chcr.STR == 0)  
132                          {                          {
133                                  //DevCon.Warning(L"16bit %s DMA Stopped on Suspend", ChcrName(mem));                                  mcase(INTC_STAT):
134                                  cpuClearInt( ChannelNumber(mem) );                                          psHu32(INTC_STAT) &= ~value;
135                                  QueuedDMA._u16 &= ~(1 << ChannelNumber(mem)); //Clear any queued DMA requests for this channel                                          //cpuTestINTCInts();
136                          }                                  return;
137                          //Here we update the lower part of the CHCR, we dont touch the tag as it is only a 16bit value  
138                          reg->chcr.set((reg->chcr.TAG << 16) | chcr.lower());                                  mcase(INTC_MASK):
139                          return;                                          psHu32(INTC_MASK) ^= (u16)value;
140                  }                                          cpuTestINTCInts();
141                  else //Else the DMA is running (Not Suspended), so we cant touch it!                                  return;
142                  {  
143                          //As the manual states "Fields other than STR can only be written to when the DMA is stopped"                                  mcase(SIO_TXFIFO):
144                          //Also "The DMA may not stop properly just by writing 0 to STR"                                  {
145                          //So the presumption is that STR can be written to (ala force stop the DMA) but nothing else                                          u8* woot = (u8*)&value;
146                                            // [Ps2Confirm] What happens when we write 32 bit values to SIO_TXFIFO?
147                                            // If it works like the IOP, then all 32 bits are written to the FIFO in
148                                            // order.  PCSX2 up to this point simply ignored non-8bit writes to this port.
149                                            _hwWrite8<0x0f>(SIO_TXFIFO, woot[0]);
150                                            _hwWrite8<0x0f>(SIO_TXFIFO, woot[1]);
151                                            _hwWrite8<0x0f>(SIO_TXFIFO, woot[2]);
152                                            _hwWrite8<0x0f>(SIO_TXFIFO, woot[3]);
153                                    }
154                                    return;
155    
156                                    mcase(SBUS_F200):
157                                            // Performs a standard psHu32 assignment (which is the default action anyway).
158                                            //psHu32(mem) = value;
159                                    break;
160    
161                                    mcase(SBUS_F220):
162                                            psHu32(mem) |= value;
163                                    return;
164    
165                                    mcase(SBUS_F230):
166                                            psHu32(mem) &= ~value;
167                                    return;
168    
169                                    mcase(SBUS_F240):
170                                            if(!(value & 0x100))
171                                                    psHu32(mem) &= ~0x100;
172                                            else
173                                                    psHu32(mem) |= 0x100;
174                                    return;
175    
176                                    mcase(SBUS_F260):
177                                            psHu32(mem) = 0;
178                                    return;
179    
180                                    mcase(MCH_RICM)://MCH_RICM: x:4|SA:12|x:5|SDEV:1|SOP:4|SBC:1|SDEV:5
181                                            if ((((value >> 16) & 0xFFF) == 0x21) && (((value >> 6) & 0xF) == 1) && (((psHu32(0xf440) >> 7) & 1) == 0))//INIT & SRP=0
182                                                    rdram_sdevid = 0;       // if SIO repeater is cleared, reset sdevid
183                                            psHu32(mem) = value & ~0x80000000;      //kill the busy bit
184                                    return;
185    
186                                    mcase(MCH_DRD):
187                                            // Performs a standard psHu32 assignment (which is the default action anyway).
188                                            //psHu32(mem) = value;
189                                    break;
190    
191                                    mcase(DMAC_ENABLEW):
192                                            if (!dmacWrite32<0x0f>(DMAC_ENABLEW, value)) return;
193    
194                                    //mcase(SIO_ISR):
195                                    //mcase(0x1000f410):
196                                    // Mystery Regs!  No one knows!?
197                                    // (unhandled so fall through to default)
198    
                         if(chcr.STR == 0)  
                         {  
                                 //DevCon.Warning(L"16bit Force Stopping %s (Current CHCR %x) while DMA active", ChcrName(mem), reg->chcr._u32, chcr._u32);  
                                 reg->chcr.STR = 0;  
                                 //We need to clear any existing DMA loops that are in progress else they will continue!  
                                 cpuClearInt( ChannelNumber(mem) );  
                                 QueuedDMA._u16 &= ~(1 << ChannelNumber(mem)); //Clear any queued DMA requests for this channel  
199                          }                          }
200                          //else DevCon.Warning(L"16bit Attempted to change %s modes while DMA active, ignoring", ChcrName(mem));                  }      
201                          return;                  break;
                 }  
   
         }  
   
         reg->chcr.set((reg->chcr.TAG << 16) | chcr.lower());  
   
         if (reg->chcr.STR && dmacRegs->ctrl.DMAE && !psHu8(DMAC_ENABLER+2))  
         {  
                 Registers::Freeze();  
                 func();  
                 Registers::Thaw();  
         }  
         else if(reg->chcr.STR)  
         {  
                 //DevCon.Warning(L"16bit %s DMA Start while DMAC Disabled\n",ChcrName(mem));  
                 QueuedDMA._u16 |= (1 << ChannelNumber(mem)); //Queue the DMA up to be started then the DMA's are Enabled and or the Suspend is lifted  
202          }          }
203            
204            psHu32(mem) = value;
205  }  }
206    
207  static void DmaExec( void (*func)(), u32 mem, u32 value )  template<uint page>
208    void __fastcall hwWrite32( u32 mem, u32 value )
209  {  {
210            eeHwTraceLog( mem, value, false );
211            _hwWrite32<page>( mem, value );
212    }
213    
214          DMACh *reg = &psH_DMACh(mem);  // --------------------------------------------------------------------------------------
215      tDMA_CHCR chcr(value);  //  hwWrite8 / hwWrite16 / hwWrite64 / hwWrite128
216    // --------------------------------------------------------------------------------------
217    
218          //It's invalid for the hardware to write a DMA while it is active, not without Suspending the DMAC  template< uint page >
219          if (reg->chcr.STR)  void __fastcall _hwWrite8(u32 mem, u8 value)
220    {
221            iswitch (mem)
222            icase(SIO_TXFIFO)
223          {          {
224                  if(psHu8(DMAC_ENABLER+2) == 1) //DMA is suspended so we can allow writes to anything                  static bool iggy_newline = false;
225                    static char sio_buffer[1024];
226                    static int sio_count;
227    
228                    if (value == '\r')
229                  {                  {
230                          //If it stops the DMA, we need to clear any pending interrupts so the DMA doesnt continue.                          iggy_newline = true;
231                          if(chcr.STR == 0)                          sio_buffer[sio_count++] = '\n';
                         {  
                                 //DevCon.Warning(L"32bit %s DMA Stopped on Suspend", ChcrName(mem));  
                                 QueuedDMA._u16 &= ~(1 << ChannelNumber(mem)); //Clear any queued DMA requests for this channel  
                                 cpuClearInt( ChannelNumber(mem) );  
                         }  
                         //Sanity Check for possible future bug fix0rs ;p  
                         //Spams on Persona 4 opening.  
                         //if(reg->chcr.TAG != chcr.TAG) DevCon.Warning(L"32bit CHCR Tag on %s changed to %x from %x QWC = %x Channel Active", ChcrName(mem), chcr.TAG, reg->chcr.TAG, reg->qwc);  
                         //Here we update the LOWER CHCR, if a chain is stopped half way through, it can be manipulated in to a different mode  
                         //But we need to preserve the existing tag for now  
                         reg->chcr.set((reg->chcr.TAG << 16) | chcr.lower());  
                         return;  
232                  }                  }
233                  else //Else the DMA is running (Not Suspended), so we cant touch it!                  else if (!iggy_newline || (value != '\n'))
234                  {                  {
235                          //As the manual states "Fields other than STR can only be written to when the DMA is stopped"                          iggy_newline = false;
236                          //Also "The DMA may not stop properly just by writing 0 to STR"                          sio_buffer[sio_count++] = value;
                         //So the presumption is that STR can be written to (ala force stop the DMA) but nothing else  
   
                         if(chcr.STR == 0)  
                         {  
                                 //DevCon.Warning(L"32bit Force Stopping %s (Current CHCR %x) while DMA active", ChcrName(mem), reg->chcr._u32, chcr._u32);  
                                 reg->chcr.STR = 0;  
                                 //We need to clear any existing DMA loops that are in progress else they will continue!  
                                 cpuClearInt( ChannelNumber(mem) );  
                                 QueuedDMA._u16 &= ~(1 << ChannelNumber(mem)); //Clear any queued DMA requests for this channel  
                         }  
                         //else DevCon.Warning(L"32bit Attempted to change %s CHCR (Currently %x) with %x while DMA active, ignoring QWC = %x", ChcrName(mem), reg->chcr._u32, chcr._u32, reg->qwc);  
                         return;  
237                  }                  }
238    
239          }                  if ((sio_count == ArraySize(sio_buffer)-1) || (sio_buffer[sio_count-1] == '\n'))
   
         //if(reg->chcr.TAG != chcr.TAG && chcr.MOD == CHAIN_MODE) DevCon.Warning(L"32bit CHCR Tag on %s changed to %x from %x QWC = %x Channel Not Active", ChcrName(mem), chcr.TAG, reg->chcr.TAG, reg->qwc);  
   
         reg->chcr.set(value);  
   
         if (reg->chcr.STR && dmacRegs->ctrl.DMAE && !psHu8(DMAC_ENABLER+2))  
         {  
                 Registers::Freeze();  
                 func();  
                 Registers::Thaw();  
         }  
         else if(reg->chcr.STR)  
         {  
                 //DevCon.Warning(L"32bit %s DMA Start while DMAC Disabled\n", ChcrName(mem));  
                 QueuedDMA._u16 |= (1 << ChannelNumber(mem)); //Queue the DMA up to be started then the DMA's are Enabled and or the Suspend is lifted  
         } //else QueuedDMA._u16 &~= (1 << ChannelNumber(mem)); //  
 }  
   
 /////////////////////////////////////////////////////////////////////////  
 // Hardware WRITE 8 bit  
   
 char sio_buffer[1024];  
 int sio_count;  
   
   
 void hwWrite8(u32 mem, u8 value)  
 {  
         if ((mem >= VIF0_STAT) && (mem < VIF0_FIFO)) {  
                 u32 bytemod = mem & 0x3;  
                 u32 bitpos  = 8 * bytemod;  
                 u32 oldval  = ~(0xff  << bitpos) & psHu32(mem);  
                 u32 newval      =  (value << bitpos) | oldval;  
                 if (mem < VIF1_STAT) vif0Write32(mem & ~0x3, newval);  
                 else                             vif1Write32(mem & ~0x3, newval);  
                 return;  
         }  
   
         if( mem >= IPU_CMD && mem < D0_CHCR )  
                 DevCon.Warning( "hwWrite8 to 0x%x = 0x%x", mem, value );  
   
         switch (mem) {  
                 case RCNT0_COUNT: rcntWcount(0, value); break;  
                 case RCNT0_MODE: rcntWmode(0, (counters[0].modeval & 0xff00) | value); break;  
                 case RCNT0_MODE + 1: rcntWmode(0, (counters[0].modeval & 0xff) | value << 8); break;  
                 case RCNT0_TARGET: rcntWtarget(0, value); break;  
                 case RCNT0_HOLD: rcntWhold(0, value); break;  
   
                 case RCNT1_COUNT: rcntWcount(1, value); break;  
                 case RCNT1_MODE: rcntWmode(1, (counters[1].modeval & 0xff00) | value); break;  
                 case RCNT1_MODE + 1: rcntWmode(1, (counters[1].modeval & 0xff) | value << 8); break;  
                 case RCNT1_TARGET: rcntWtarget(1, value); break;  
                 case RCNT1_HOLD: rcntWhold(1, value); break;  
   
                 case RCNT2_COUNT: rcntWcount(2, value); break;  
                 case RCNT2_MODE: rcntWmode(2, (counters[2].modeval & 0xff00) | value); break;  
                 case RCNT2_MODE + 1: rcntWmode(2, (counters[2].modeval & 0xff) | value << 8); break;  
                 case RCNT2_TARGET: rcntWtarget(2, value); break;  
   
                 case RCNT3_COUNT: rcntWcount(3, value); break;  
                 case RCNT3_MODE: rcntWmode(3, (counters[3].modeval & 0xff00) | value); break;  
                 case RCNT3_MODE + 1: rcntWmode(3, (counters[3].modeval & 0xff) | value << 8); break;  
                 case RCNT3_TARGET: rcntWtarget(3, value); break;  
   
                 case SIO_TXFIFO:  
240                  {                  {
241                          // Terminate lines on CR or full buffers, and ignore \n's if the string contents                          sio_buffer[sio_count] = 0;
242                          // are empty (otherwise terminate on \n too!)                          eeConLog( ShiftJIS_ConvertString(sio_buffer) );
243                          if (( value == '\r' ) || ( sio_count == 1023 ) ||                          sio_count = 0;
                              ( value == '\n' && sio_count != 0 ))  
                         {  
                                 // Use "%s" below even though it feels indirect -- it's necessary to avoid  
                                 // errors if/when games use printf formatting control chars.  
   
                                 sio_buffer[sio_count] = 0;  
                                 Console.WriteLn( ConColor_EE, L"%s", ShiftJIS_ConvertString(sio_buffer).c_str() );  
                                 sio_count = 0;  
                         }  
                         else if( value != '\n' )  
                         {  
                                 sio_buffer[sio_count++] = value;  
                         }  
244                  }                  }
245                  break;                  return;
   
                 //case 0x10003c02: //Tony Hawks Project 8 uses this  
                 //      vif1Write32(mem & ~0x2, value << 16);  
                 //      break;  
                 case D0_CHCR + 1: // dma0 - vif0  
                         DMA_LOG("VIF0dma EXECUTE, value=0x%x", value);  
                         DmaExec8(dmaVIF0, mem, value);  
                         break;  
   
                 case D1_CHCR + 1: // dma1 - vif1  
                         DMA_LOG("VIF1dma EXECUTE, value=0x%x", value);  
                         DmaExec8(dmaVIF1, mem, value);  
                         break;  
   
                 case D2_CHCR + 1: // dma2 - gif  
                         DMA_LOG("GSdma EXECUTE, value=0x%x", value);  
                         DmaExec8(dmaGIF, mem, value);  
                         break;  
   
                 case D3_CHCR + 1: // dma3 - fromIPU  
                         DMA_LOG("IPU0dma EXECUTE, value=0x%x", value);  
                         DmaExec8(dmaIPU0, mem, value);  
                         break;  
   
                 case D4_CHCR + 1: // dma4 - toIPU  
                         DMA_LOG("IPU1dma EXECUTE, value=0x%x", value);  
                         DmaExec8(dmaIPU1, mem, value);  
                         break;  
   
                 case D5_CHCR + 1: // dma5 - sif0  
                         DMA_LOG("SIF0dma EXECUTE, value=0x%x", value);  
 //                      if (value == 0) psxSu32(0x30) = 0x40000;  
                         DmaExec8(dmaSIF0, mem, value);  
                         break;  
   
                 case D6_CHCR + 1: // dma6 - sif1  
                         DMA_LOG("SIF1dma EXECUTE, value=0x%x", value);  
                         DmaExec8(dmaSIF1, mem, value);  
                         break;  
   
                 case D7_CHCR + 1: // dma7 - sif2  
                         DMA_LOG("SIF2dma EXECUTE, value=0x%x", value);  
                         DmaExec8(dmaSIF2, mem, value);  
                         break;  
   
                 case D8_CHCR + 1: // dma8 - fromSPR  
                         DMA_LOG("fromSPRdma8 EXECUTE, value=0x%x", value);  
                         DmaExec8(dmaSPR0, mem, value);  
                         break;  
   
                 case D9_CHCR + 1: // dma9 - toSPR  
                         DMA_LOG("toSPRdma8 EXECUTE, value=0x%x", value);  
                         DmaExec8(dmaSPR1, mem, value);  
                         break;  
                 case D0_CHCR: // dma0 - vif0  
                 case D1_CHCR: // dma1 - vif1  
                 case D2_CHCR: // dma2 - gif  
                 case D3_CHCR: // dma3 - fromIPU  
                 case D4_CHCR: // dma4 - toIPU  
                 case D5_CHCR: // dma5 - sif0  
                 case D6_CHCR: // dma6 - sif1  
                 case D7_CHCR: // dma7 - sif2  
                 case D8_CHCR: // dma8 - fromSPR  
                 case D9_CHCR: // dma9 - toSPR  
                         //DevCon.Warning(L"8bit lower CHCR changed to %x from %x on %s DMA", value, psHu32(mem), ChcrName(mem));  
                         psHu8(mem) = value;  
                         break;  
   
                 case D0_CHCR + 2: // dma0 - vif0  
                 case D0_CHCR + 3: // dma0 - vif0  
                 case D1_CHCR + 2: // dma1 - vif1  
                 case D1_CHCR + 3: // dma1 - vif1  
                 case D2_CHCR + 2: // dma2 - gif  
                 case D2_CHCR + 3: // dma2 - gif  
                 case D3_CHCR + 2: // dma3 - fromIPU  
                 case D3_CHCR + 3: // dma3 - fromIPU  
                 case D4_CHCR + 2: // dma4 - toIPU  
                 case D4_CHCR + 3: // dma4 - toIPU  
                 case D5_CHCR + 2: // dma5 - sif0  
                 case D5_CHCR + 3: // dma5 - sif0  
                 case D6_CHCR + 2: // dma6 - sif1  
                 case D6_CHCR + 3: // dma6 - sif1  
                 case D7_CHCR + 2: // dma7 - sif2  
                 case D7_CHCR + 3: // dma7 - sif2  
                 case D8_CHCR + 2: // dma8 - fromSPR  
                 case D8_CHCR + 3: // dma8 - fromSPR  
                 case D9_CHCR + 2: // dma9 - toSPR  
                 case D9_CHCR + 3: // dma9 - toSPR  
                         //DevCon.Warning(L"8bit CHCR TAG changed to %x from %x on %s DMA", value, psHu32(mem), ChcrName(mem & ~0xf));  
                         psHu8(mem) = value;  
                         break;  
   
                 case DMAC_ENABLEW + 2:  
                         oldvalue = psHu8(DMAC_ENABLEW + 2);  
                         psHu8(DMAC_ENABLEW + 2) = value;  
                         psHu8(DMAC_ENABLER + 2) = value;  
                         if (((oldvalue & 0x1) == 1) && ((value & 0x1) == 0))  
                         {  
                                 if (!QueuedDMA.empty()) StartQueuedDMA();  
                         }  
                         break;  
   
                 case SBUS_F200: // SIF(?)  
                         psHu8(mem) = value;  
                         break;  
   
                 case SBUS_F210:  
                         psHu8(mem) = value;  
                         break;  
   
                 case SBUS_F220:  
                         psHu8(mem) = value;  
                         break;  
   
                 case SBUS_F230:  
                         psHu8(mem) = value;  
                         break;  
   
                 case SBUS_F240:  
                         if (!(value & 0x100)) psHu32(mem) &= ~0x100;  
                         break;  
   
                 case SBUS_F250:  
                         psHu8(mem) = value;  
                         break;  
   
                 case SBUS_F260:  
                         psHu8(mem) = value;  
                         break;  
   
                 default:  
                         pxAssert( (mem & 0xff0f) != 0xf200 );  
   
                         switch(mem&~3) {  
                                 case SIO_ISR:  
                                 case 0x1000f410:  
                                 case MCH_RICM:  
                                         break;  
   
                                 default:  
                                         psHu8(mem) = value;  
                         }  
                         HW_LOG("Unknown Hardware write 8 at %x with value %x", mem, value);  
                         break;  
246          }          }
 }  
247    
248  __forceinline void hwWrite16(u32 mem, u16 value)          u32 merged = _hwRead32<page,false>(mem & ~0x03);
249  {          ((u8*)&merged)[mem & 0x3] = value;
         if( mem >= IPU_CMD && mem < D0_CHCR )  
                 Console.Warning( "hwWrite16 to %x", mem );  
250    
251          switch(mem)          _hwWrite32<page>(mem & ~0x03, merged);
         {  
                 case RCNT0_COUNT: rcntWcount(0, value); break;  
                 case RCNT0_MODE: rcntWmode(0, value); break;  
                 case RCNT0_TARGET: rcntWtarget(0, value); break;  
                 case RCNT0_HOLD: rcntWhold(0, value); break;  
   
                 case RCNT1_COUNT: rcntWcount(1, value); break;  
                 case RCNT1_MODE: rcntWmode(1, value); break;  
                 case RCNT1_TARGET: rcntWtarget(1, value); break;  
                 case RCNT1_HOLD: rcntWhold(1, value); break;  
   
                 case RCNT2_COUNT: rcntWcount(2, value); break;  
                 case RCNT2_MODE: rcntWmode(2, value); break;  
                 case RCNT2_TARGET: rcntWtarget(2, value); break;  
   
                 case RCNT3_COUNT: rcntWcount(3, value); break;  
                 case RCNT3_MODE: rcntWmode(3, value); break;  
                 case RCNT3_TARGET: rcntWtarget(3, value); break;  
   
                 case D0_CHCR: // dma0 - vif0  
                         DMA_LOG("VIF0dma %lx", value);  
                         DmaExec16(dmaVIF0, mem, value);  
                         break;  
   
                 case D1_CHCR: // dma1 - vif1 - chcr  
                         DMA_LOG("VIF1dma CHCR %lx", value);  
                         DmaExec16(dmaVIF1, mem, value);  
                         break;  
   
 #ifdef PCSX2_DEVBUILD  
                 case D1_MADR: // dma1 - vif1 - madr  
                         HW_LOG("VIF1dma Madr %lx", value);  
                         psHu16(mem) = value;//dma1 madr  
                         break;  
   
                 case D1_QWC: // dma1 - vif1 - qwc  
                         HW_LOG("VIF1dma QWC %lx", value);  
                         psHu16(mem) = value;//dma1 qwc  
                         break;  
   
                 case D1_TADR: // dma1 - vif1 - tadr  
                         HW_LOG("VIF1dma TADR %lx", value);  
                         psHu16(mem) = value;//dma1 tadr  
                         break;  
   
                 case D1_ASR0: // dma1 - vif1 - asr0  
                         HW_LOG("VIF1dma ASR0 %lx", value);  
                         psHu16(mem) = value;//dma1 asr0  
                         break;  
   
                 case D1_ASR1: // dma1 - vif1 - asr1  
                         HW_LOG("VIF1dma ASR1 %lx", value);  
                         psHu16(mem) = value;//dma1 asr1  
                         break;  
   
                 case D1_SADR: // dma1 - vif1 - sadr  
                         HW_LOG("VIF1dma SADR %lx", value);  
                         psHu16(mem) = value;//dma1 sadr  
                         break;  
 #endif  
 // ---------------------------------------------------  
   
                 case D2_CHCR: // dma2 - gif  
                         DMA_LOG("0x%8.8x hwWrite32: GSdma %lx", cpuRegs.cycle, value);  
                         DmaExec16(dmaGIF, mem, value);  
                         break;  
   
 #ifdef PCSX2_DEVBUILD  
                 case D2_MADR:  
                     psHu16(mem) = value;//dma2 madr  
                         HW_LOG("Hardware write DMA2_MADR 32bit at %x with value %x",mem,value);  
                     break;  
   
                 case D2_QWC:  
                         psHu16(mem) = value;//dma2 qwc  
                         HW_LOG("Hardware write DMA2_QWC 32bit at %x with value %x",mem,value);  
                         break;  
   
                 case D2_TADR:  
                         psHu16(mem) = value;//dma2 taddr  
                         HW_LOG("Hardware write DMA2_TADDR 32bit at %x with value %x",mem,value);  
                         break;  
   
                 case D2_ASR0:  
                         psHu16(mem) = value;//dma2 asr0  
                         HW_LOG("Hardware write DMA2_ASR0 32bit at %x with value %x",mem,value);  
                         break;  
   
                 case D2_ASR1:  
                         psHu16(mem) = value;//dma2 asr1  
                         HW_LOG("Hardware write DMA2_ASR1 32bit at %x with value %x",mem,value);  
                         break;  
   
                 case D2_SADR:  
                         psHu16(mem) = value;//dma2 saddr  
                         HW_LOG("Hardware write DMA2_SADDR 32bit at %x with value %x",mem,value);  
                         break;  
 #endif  
   
                 case D3_CHCR: // dma3 - fromIPU  
                         DMA_LOG("IPU0dma %lx", value);  
                         DmaExec16(dmaIPU0, mem, value);  
                         break;  
   
 #ifdef PCSX2_DEVBUILD  
                 case D3_MADR:  
                         psHu16(mem) = value;//dma2 madr  
                         HW_LOG("Hardware write IPU0DMA_MADR 32bit at %x with value %x",mem,value);  
                         break;  
   
                 case D3_QWC:  
                         psHu16(mem) = value;//dma2 madr  
                         HW_LOG("Hardware write IPU0DMA_QWC 32bit at %x with value %x",mem,value);  
                         break;  
   
                 case D3_TADR:  
                         psHu16(mem) = value;//dma2 tadr  
                         HW_LOG("Hardware write IPU0DMA_TADR 32bit at %x with value %x",mem,value);  
                         break;  
   
                 case D3_SADR:  
                         psHu16(mem) = value;//dma2 saddr  
                         HW_LOG("Hardware write IPU0DMA_SADDR 32bit at %x with value %x",mem,value);  
                         break;  
 #endif  
   
                 case D4_CHCR: // dma4 - toIPU  
                         DMA_LOG("IPU1dma %lx", value);  
                         DmaExec16(dmaIPU1, mem, value);  
                         break;  
   
 #ifdef PCSX2_DEVBUILD  
                 case D4_MADR:  
                         psHu16(mem) = value;//dma2 madr  
                         HW_LOG("Hardware write IPU1DMA_MADR 32bit at %x with value %x",mem,value);  
                 break;  
   
                 case D4_QWC:  
                         psHu16(mem) = value;//dma2 madr  
                         HW_LOG("Hardware write IPU1DMA_QWC 32bit at %x with value %x",mem,value);  
                 break;  
   
                 case D4_TADR:  
                         psHu16(mem) = value;//dma2 tadr  
                         HW_LOG("Hardware write IPU1DMA_TADR 32bit at %x with value %x",mem,value);  
                         break;  
   
                 case D4_SADR:  
                         psHu16(mem) = value;//dma2 saddr  
                         HW_LOG("Hardware write IPU1DMA_SADDR 32bit at %x with value %x",mem,value);  
                         break;  
 #endif  
                 case D5_CHCR: // dma5 - sif0  
                         DMA_LOG("SIF0dma %lx", value);  
                         DmaExec16(dmaSIF0, mem, value);  
                         break;  
   
                 case D6_CHCR: // dma6 - sif1  
                         DMA_LOG("SIF1dma %lx", value);  
                         DmaExec16(dmaSIF1, mem, value);  
                         break;  
   
                 // Given the other values here, perhaps something like this is in order?  
                 /*case 0x1000C402: // D6_CHCR + 2  
                         //?  
                         break;*/  
   
 #ifdef PCSX2_DEVBUILD  
                 case D6_MADR: // dma6 - sif1 - madr  
                         HW_LOG("SIF1dma MADR = %lx", value);  
                         psHu16(mem) = value;  
                         break;  
   
                 case D6_QWC: // dma6 - sif1 - qwc  
                         HW_LOG("SIF1dma QWC = %lx", value);  
                         psHu16(mem) = value;  
                         break;  
   
                 case D6_TADR: // dma6 - sif1 - tadr  
                         HW_LOG("SIF1dma TADR = %lx", value);  
                         psHu16(mem) = value;  
                         break;  
 #endif  
   
                 case D7_CHCR: // dma7 - sif2  
                         DMA_LOG("SIF2dma %lx", value);  
                         DmaExec16(dmaSIF2, mem, value);  
                         break;  
   
                 case D8_CHCR: // dma8 - fromSPR  
                         DMA_LOG("fromSPRdma %lx", value);  
                         DmaExec16(dmaSPR0, mem, value);  
                         break;  
   
                 case D9_CHCR: // dma9 - toSPR  
                         DMA_LOG("toSPRdma %lx", value);  
                         DmaExec16(dmaSPR1, mem, value);  
                         break;  
   
                 case D0_CHCR + 2: // dma0 - vif0  
                 case D1_CHCR + 2: // dma1 - vif1  
                 case D2_CHCR + 2: // dma2 - gif  
                 case D3_CHCR + 2: // dma3 - fromIPU  
                 case D4_CHCR + 2: // dma4 - toIPU  
                 case D5_CHCR + 2: // dma5 - sif0  
                 case D6_CHCR + 2: // dma6 - sif1  
                 case D7_CHCR + 2: // dma7 - sif2  
                 case D8_CHCR + 2: // dma8 - fromSPR  
                 case D9_CHCR + 2: // dma9 - toSPR  
                         //DevCon.Warning(L"16bit CHCR TAG changed to %x from %x on %s DMA", value, psHu32(mem), ChcrName(mem & ~0xf));  
                         psHu16(mem) = value;  
                         break;  
   
                 case DMAC_ENABLEW + 2:  
                         oldvalue = psHu8(DMAC_ENABLEW + 2);  
                         psHu16(DMAC_ENABLEW + 2) = value;  
                         psHu16(DMAC_ENABLER + 2) = value;  
                         if (((oldvalue & 0x1) == 1) && ((value & 0x1) == 0))  
                         {  
                                 if (!QueuedDMA.empty()) StartQueuedDMA();  
                         }  
                         break;  
   
                 case SIO_ISR:  
                 case SIO_ISR + 2:  
                 case 0x1000f410:  
                 case 0x1000f410 + 2:  
                 case MCH_RICM:  
                 case MCH_RICM + 2:  
                         break;  
   
                 case SBUS_F200:  
                         psHu16(mem) = value;  
                         break;  
   
                 case SBUS_F210:  
                         psHu16(mem) = value;  
                         break;  
   
                 case SBUS_F220:  
                         psHu16(mem) |= value;  
                         break;  
   
                 case SBUS_F230:  
                         psHu16(mem) &= ~value;  
                         break;  
   
                 case SBUS_F240:  
                         if (!(value & 0x100))  
                                 psHu16(mem) &= ~0x100;  
                         else  
                                 psHu16(mem) |= 0x100;  
                         break;  
   
                 case SBUS_F250:  
                         psHu16(mem) = value;  
                         break;  
   
                 case SBUS_F260:  
                         psHu16(mem) = 0;  
                         break;  
   
                 default:  
                         psHu16(mem) = value;  
                         UnknownHW_LOG("Unknown Hardware write 16 at %x with value %x",mem,value);  
         }  
252  }  }
253    
254  // Page 0 of HW memory houses registers for Counters 0 and 1  template< uint page >
255  void __fastcall hwWrite32_page_00( u32 mem, u32 value )  void __fastcall hwWrite8(u32 mem, u8 value)
256  {  {
257          mem &= 0xffff;          eeHwTraceLog( mem, value, false );
258          switch (mem)          _hwWrite8<page>(mem, value);
         {  
                 case 0x000: rcntWcount(0, value); return;  
                 case 0x010: rcntWmode(0, value); return;  
                 case 0x020: rcntWtarget(0, value); return;  
                 case 0x030: rcntWhold(0, value); return;  
   
                 case 0x800: rcntWcount(1, value); return;  
                 case 0x810: rcntWmode(1, value); return;  
                 case 0x820: rcntWtarget(1, value); return;  
                 case 0x830: rcntWhold(1, value); return;  
         }  
   
         *((u32*)&PS2MEM_HW[mem]) = value;  
259  }  }
260    
261  // Page 1 of HW memory houses registers for Counters 2 and 3  template< uint page >
262  void __fastcall hwWrite32_page_01( u32 mem, u32 value )  void __fastcall _hwWrite16(u32 mem, u16 value)
263  {  {
264          mem &= 0xffff;          pxAssume( (mem & 0x01) == 0 );
         switch (mem)  
         {  
                 case 0x1000: rcntWcount(2, value); return;  
                 case 0x1010: rcntWmode(2, value); return;  
                 case 0x1020: rcntWtarget(2, value); return;  
   
                 case 0x1800: rcntWcount(3, value); return;  
                 case 0x1810: rcntWmode(3, value); return;  
                 case 0x1820: rcntWtarget(3, value); return;  
         }  
265    
266          *((u32*)&PS2MEM_HW[mem]) = value;          u32 merged = _hwRead32<page,false>(mem & ~0x03);
267  }          ((u16*)&merged)[(mem>>1) & 0x1] = value;
268    
269  // page 2 is the IPU register space!          hwWrite32<page>(mem & ~0x03, merged);
 void __fastcall hwWrite32_page_02( u32 mem, u32 value )  
 {  
         ipuWrite32(mem, value);  
270  }  }
271    
272  // Page 3 contains writes to vif0 and vif1 registers, plus some GIF stuff!  template< uint page >
273  void __fastcall hwWrite32_page_03( u32 mem, u32 value )  void __fastcall hwWrite16(u32 mem, u16 value)
274  {  {
275          if (mem >= VIF0_STAT)          eeHwTraceLog( mem, value, false );
276          {          _hwWrite16<page>(mem, value);
                 if(mem < VIF1_STAT)  
                         vif0Write32(mem, value);  
                 else  
                         vif1Write32(mem, value);  
                 return;  
         }  
   
         switch (mem)  
         {  
                 case GIF_CTRL:  
                         psHu32(mem) = value & 0x8;  
   
                         if (value & 0x1)  
                                 gsGIFReset();  
                         else if ( value & 8 )  
                                 gifRegs->stat.PSE = true;  
                         else  
                                 gifRegs->stat.PSE = false;  
                 break;  
   
                 case GIF_MODE:  
                 {  
                         // need to set GIF_MODE (hamster ball)  
                         gifRegs->mode.write(value);  
   
                         // set/clear bits 0 and 2 as per the GIF_MODE value.  
             const u32 bitmask = GIF_MODE_M3R | GIF_MODE_IMT;  
                         psHu32(GIF_STAT) &= ~bitmask;  
                         psHu32(GIF_STAT) |= (u32)value & bitmask;  
   
                 }  
                 break;  
   
                 case GIF_STAT: // stat is readonly  
                         DevCon.Warning("*PCSX2* GIFSTAT write value = 0x%x (readonly, ignored)", value);  
                 break;  
   
                 default:  
                         psHu32(mem) = value;  
         }  
277  }  }
278    
279  void __fastcall hwWrite32_page_0B( u32 mem, u32 value )  template<uint page>
280    void __fastcall _hwWrite64( u32 mem, const mem64_t* srcval )
281  {  {
282          // Used for developer logging -- optimized away in Public Release.          pxAssume( (mem & 0x07) == 0 );
         const char* regName = "Unknown";  
   
         switch( mem )  
         {  
                 case D3_CHCR: // dma3 - fromIPU  
                         DMA_LOG("IPU0dma EXECUTE, value=0x%x\n", value);  
                         DmaExec(dmaIPU0, mem, value);  
                         return;  
   
                 case D3_MADR: regName = "IPU0DMA_MADR"; break;  
                 case D3_QWC: regName = "IPU0DMA_QWC"; break;  
                 case D3_TADR: regName = "IPU0DMA_TADR"; break;  
                 case D3_SADR: regName = "IPU0DMA_SADDR"; break;  
   
                 //------------------------------------------------------------------  
   
                 case D4_CHCR: // dma4 - toIPU  
                         DMA_LOG("IPU1dma EXECUTE, value=0x%x\n", value);  
                         DmaExec(dmaIPU1, mem, value);  
                         return;  
   
                 case D4_MADR: regName = "IPU1DMA_MADR"; break;  
                 case D4_QWC: regName = "IPU1DMA_QWC"; break;  
                 case D4_TADR: regName = "IPU1DMA_TADR"; break;  
                 case D4_SADR: regName = "IPU1DMA_SADDR"; break;  
         }  
   
         HW_LOG( "Hardware Write32 at 0x%x (%s), value=0x%x", mem, regName, value );  
         psHu32(mem) = value;  
 }  
283    
284            // * Only the IPU has true 64 bit registers.
285            // * FIFOs have 128 bit registers that are probably zero-fill.
286            // * All other registers likely disregard the upper 32-bits and simply act as normal
287            //   32-bit writes.
288    
289            switch (page)
 void __fastcall hwWrite32_page_0E( u32 mem, u32 value )  
 {  
         switch (mem)  
290          {          {
291                  case DMAC_CTRL:                  case 0x02:
292                  {                          if (!ipuWrite64(mem, *srcval)) return;
293                          u32 oldvalue = psHu32(mem);                  break;
   
                         HW_LOG("DMAC_CTRL Write 32bit %x", value);  
294    
295                          psHu32(mem) = value;                  case 0x04:
296                          //Check for DMAS that were started while the DMAC was disabled                  case 0x05:
297                          if (((oldvalue & 0x1) == 0) && ((value & 0x1) == 1))                  case 0x06:
298                          {                  case 0x07:
299                                  if (!QueuedDMA.empty()) StartQueuedDMA();                  {
300                          }                          DevCon.WriteLn( Color_Cyan, "Writing 64-bit FIFO data (zero-extended to 128 bits)" );
301                          break;  
302                            u128 zerofill = u128::From32(0);
303                            zerofill._u64[(mem >> 3) & 0x01] = *srcval;
304                            hwWrite128<page>(mem & ~0x0f, &zerofill);
305                  }                  }
306                    return;
307                  case DMAC_STAT:                  
                         HW_LOG("DMAC_STAT Write 32bit %x", value);  
   
                         // lower 16 bits: clear on 1  
                         // upper 16 bits: reverse on 1  
   
                         psHu16(0xe010) &= ~(value & 0xffff);  
                         psHu16(0xe012) ^= (u16)(value >> 16);  
   
                         cpuTestDMACInts();  
                         break;  
   
                 default:  
                         psHu32(mem) = value;  
                         break;  
         }  
 }  
   
 void __fastcall hwWrite32_page_0F( u32 mem, u32 value )  
 {  
         // Shift the middle 8 bits (bits 4-12) into the lower 8 bits.  
         // This helps the compiler optimize the switch statement into a lookup table. :)  
   
 #define HELPSWITCH(m) (((m)>>4) & 0xff)  
   
         switch( HELPSWITCH(mem) )  
         {  
                 case HELPSWITCH(INTC_STAT):  
                         HW_LOG("INTC_STAT Write 32bit %x", value);  
                         psHu32(INTC_STAT) &= ~value;  
                         //cpuTestINTCInts();  
                         break;  
   
                 case HELPSWITCH(INTC_MASK):  
                         HW_LOG("INTC_MASK Write 32bit %x", value);  
                         psHu32(INTC_MASK) ^= (u16)value;  
                         cpuTestINTCInts();  
                         break;  
   
                 //------------------------------------------------------------------  
                 case HELPSWITCH(MCH_RICM)://MCH_RICM: x:4|SA:12|x:5|SDEV:1|SOP:4|SBC:1|SDEV:5  
                         if ((((value >> 16) & 0xFFF) == 0x21) && (((value >> 6) & 0xF) == 1) && (((psHu32(0xf440) >> 7) & 1) == 0))//INIT & SRP=0  
                                 rdram_sdevid = 0;       // if SIO repeater is cleared, reset sdevid  
                         psHu32(mem) = value & ~0x80000000;      //kill the busy bit  
                         break;  
   
                 case HELPSWITCH(SBUS_F200):  
                         psHu32(mem) = value;  
                         break;  
   
                 case HELPSWITCH(SBUS_F220):  
                         psHu32(mem) |= value;  
                         break;  
   
                 case HELPSWITCH(SBUS_F230):  
                         psHu32(mem) &= ~value;  
                         break;  
   
                 case HELPSWITCH(SBUS_F240):  
                         if(!(value & 0x100))  
                                 psHu32(mem) &= ~0x100;  
                         else  
                                 psHu32(mem) |= 0x100;  
                         break;  
   
                 case HELPSWITCH(SBUS_F260):  
                         psHu32(mem) = 0;  
                         break;  
   
                 case HELPSWITCH(MCH_DRD)://MCH_DRD:  
                         psHu32(mem) = value;  
                         break;  
   
                 case HELPSWITCH(DMAC_ENABLEW):  
                         HW_LOG("DMAC_ENABLEW Write 32bit %lx", value);  
                         oldvalue = psHu8(DMAC_ENABLEW + 2);  
                         psHu32(DMAC_ENABLEW) = value;  
                         psHu32(DMAC_ENABLER) = value;  
                         if (((oldvalue & 0x1) == 1) && (((value >> 16) & 0x1) == 0))  
                         {  
                                 if (!QueuedDMA.empty()) StartQueuedDMA();  
                         }  
                         break;  
   
                 //------------------------------------------------------------------  
                 case HELPSWITCH(SIO_ISR):  
                 case HELPSWITCH(0x1000f410):  
                         UnknownHW_LOG("Unknown Hardware write 32 at %x with value %x (%x)", mem, value, cpuRegs.CP0.n.Status.val);  
                         break;  
   
308                  default:                  default:
309                          psHu32(mem) = value;                          // disregard everything except the lower 32 bits.
310          }                          // ... and skip the 64 bit writeback since the 32-bit one will suffice.
311  }                          hwWrite32<page>( mem, ((u32*)srcval)[0] );
312                    return;
 void __fastcall hwWrite32_generic( u32 mem, u32 value )  
 {  
         // Used for developer logging -- optimized away in Public Release.  
         const char* regName = "Unknown";  
   
         switch (mem)  
         {  
                 case D0_CHCR: // dma0 - vif0  
                         DMA_LOG("VIF0dma EXECUTE, value=0x%x", value);  
                         DmaExec(dmaVIF0, mem, value);  
                         return;  
   
 //------------------------------------------------------------------  
                 case D1_CHCR: // dma1 - vif1 - chcr  
                         DMA_LOG("VIF1dma EXECUTE, value=0x%x", value);  
                         DmaExec(dmaVIF1, mem, value);  
                         return;  
   
                 case D1_MADR: regName = "VIF1dma MADR"; break;  
                 case D1_QWC: regName = "VIF1dma QWC"; break;  
                 case D1_TADR: regName = "VIF1dma TADR"; break;  
                 case D1_ASR0: regName = "VIF1dma ASR0"; break;  
                 case D1_ASR1: regName = "VIF1dma ASR1"; break;  
                 case D1_SADR: regName = "VIF1dma SADR"; break;  
   
 //------------------------------------------------------------------  
                 case D2_CHCR: // dma2 - gif  
                         DMA_LOG("GIFdma EXECUTE, value=0x%x", value);  
                         DmaExec(dmaGIF, mem, value);  
                         return;  
   
                 case D2_MADR: regName = "GIFdma MADR"; break;  
                 case D2_QWC: regName = "GIFdma QWC"; break;  
                 case D2_TADR: regName = "GIFdma TADDR"; break;  
                 case D2_ASR0: regName = "GIFdma ASR0"; break;  
                 case D2_ASR1: regName = "GIFdma ASR1"; break;  
                 case D2_SADR: regName = "GIFdma SADDR"; break;  
   
 //------------------------------------------------------------------  
                 case D5_CHCR: // dma5 - sif0  
                         DMA_LOG("SIF0dma EXECUTE, value=0x%x", value);  
                         DmaExec(dmaSIF0, mem, value);  
                         return;  
 //------------------------------------------------------------------  
                 case D6_CHCR: // dma6 - sif1  
                         DMA_LOG("SIF1dma EXECUTE, value=0x%x", value);  
                         DmaExec(dmaSIF1, mem, value);  
                         return;  
   
                 case D6_MADR: regName = "SIF1dma MADR"; break;  
                 case D6_QWC: regName = "SIF1dma QWC"; break;  
                 case D6_TADR: regName = "SIF1dma TADR"; break;  
   
 //------------------------------------------------------------------  
                 case D7_CHCR: // dma7 - sif2  
                         DMA_LOG("SIF2dma EXECUTE, value=0x%x", value);  
                         DmaExec(dmaSIF2, mem, value);  
                         return;  
 //------------------------------------------------------------------  
                 case D8_CHCR: // dma8 - fromSPR  
                         DMA_LOG("SPR0dma EXECUTE (fromSPR), value=0x%x", value);  
                         DmaExec(dmaSPR0, mem, value);  
                         return;  
 //------------------------------------------------------------------  
                 case D9_CHCR: // dma9 - toSPR  
                         DMA_LOG("SPR1dma EXECUTE (toSPR), value=0x%x", value);  
                         DmaExec(dmaSPR1, mem, value);  
                         return;  
313          }          }
         HW_LOG( "Hardware Write32 at 0x%x (%s), value=0x%x", mem, regName, value );  
         psHu32(mem) = value;  
 }  
314    
 /////////////////////////////////////////////////////////////////////////  
 // HW Write 64 bit  
   
 // Page 0 of HW memory houses registers for Counters 0 and 1  
 void __fastcall hwWrite64_page_00( u32 mem, const mem64_t* srcval )  
 {  
         hwWrite32_page_00( mem, (u32)*srcval );         // just ignore upper 32 bits.  
315          psHu64(mem) = *srcval;          psHu64(mem) = *srcval;
316  }  }
317    
318  // Page 1 of HW memory houses registers for Counters 2 and 3  template<uint page>
319  void __fastcall hwWrite64_page_01( u32 mem, const mem64_t* srcval )  void __fastcall hwWrite64( u32 mem, const mem64_t* srcval )
320  {  {
321          hwWrite32_page_01( mem, (u32)*srcval );         // just ignore upper 32 bits.          eeHwTraceLog( mem, *srcval, false );
322          psHu64(mem) = *srcval;          _hwWrite64<page>(mem, srcval);
323  }  }
324    
325  void __fastcall hwWrite64_page_02( u32 mem, const mem64_t* srcval )  template< uint page >
326    void __fastcall _hwWrite128(u32 mem, const mem128_t* srcval)
327  {  {
328          //hwWrite64( mem, *srcval );  return;          pxAssume( (mem & 0x0f) == 0 );
         ipuWrite64( mem, *srcval );  
 }  
329    
330  void __fastcall hwWrite64_page_03( u32 mem, const mem64_t* srcval )          // FIFOs are the only "legal" 128 bit registers.  Handle them first.
331  {          // all other registers fall back on the 64-bit handler (and from there
332          //hwWrite64( mem, *srcval ); return;          // most of them fall back to the 32-bit handler).
         const u64 value = *srcval;  
333    
334          if (mem >= VIF0_STAT)          switch (page)
335          {          {
336                  if (mem < VIF1_STAT)                  case 0x04:
337                          vif0Write32(mem, value);                          WriteFIFO_VIF0(srcval);
                 else  
                         vif1Write32(mem, value);  
338                  return;                  return;
         }  
   
         switch (mem)  
         {  
                 case GIF_CTRL:  
                         DevCon.WriteLn("GIF_CTRL write 64", value);  
                         psHu32(mem) = value & 0x8;  
                         if(value & 0x1)  
                                 gsGIFReset();  
                         else  
                         {  
                                 if( value & 8 )  
                                         gifRegs->stat.PSE = true;  
                                 else  
                                         gifRegs->stat.PSE = false;  
                         }  
                         break;  
   
                 case GIF_MODE:  
                 {  
                         // set/clear bits 0 and 2 as per the GIF_MODE value.  
                         const u32 bitmask = GIF_MODE_M3R | GIF_MODE_IMT;  
   
                         Console.WriteLn("GIFMODE64 %x", value);  
   
                         psHu64(GIF_MODE) = value;  
                         psHu32(GIF_STAT) &= ~bitmask;  
                         psHu32(GIF_STAT) |= (u32)value & bitmask;  
                         break;  
                 }  
   
                 case GIF_STAT: // stat is readonly  
                         break;  
         }  
 }  
339    
340  void __fastcall hwWrite64_page_0E( u32 mem, const mem64_t* srcval )                  case 0x05:
341  {                          WriteFIFO_VIF1(srcval);
342          //hwWrite64( mem, *srcval ); return;                  return;
   
         const u64 value = *srcval;  
   
         switch (mem)  
         {  
                 case DMAC_CTRL:  
                 {  
                         u32 oldvalue = psHu32(mem);  
                         psHu64(mem) = value;  
343    
344                          HW_LOG("DMAC_CTRL Write 64bit %x", value);                  case 0x06:
345                            WriteFIFO_GIF(srcval);
346                    return;
347    
348                          if (((oldvalue & 0x1) == 0) && ((value & 0x1) == 1))                  case 0x07:
349                            if (mem & 0x10)
350                          {                          {
351                                  if (!QueuedDMA.empty()) StartQueuedDMA();                                  WriteFIFO_IPUin(srcval);
352                          }                          }
353                          break;                          else
354                  }                          {
355                                    // [Ps2Confirm] Most likely writes to IPUout will be silently discarded.  A test
356                  case DMAC_STAT:                                  // to confirm such would be easy -- just dump some data to FIFO_IPUout and see
357                          HW_LOG("DMAC_STAT Write 64bit %x", value);                                  // if the program causes BUSERR or something on the PS2.
   
                         // lower 16 bits: clear on 1  
                         // upper 16 bits: reverse on 1  
   
                         psHu16(0xe010) &= ~(value & 0xffff);  
                         psHu16(0xe012) ^= (u16)(value >> 16);  
   
                         cpuTestDMACInts();  
                         break;  
358    
359                  default:                                  //WriteFIFO_IPUout(srcval);
360                          psHu64(mem) = value;                          }
361                          break;                                  
362                    return;
363          }          }
 }  
364    
365  void __fastcall hwWrite64_generic( u32 mem, const mem64_t* srcval )          // All upper bits of all non-FIFO 128-bit HW writes are almost certainly disregarded. --air
366  {          hwWrite64<page>(mem, (mem64_t*)srcval);
         const u64 value = *srcval;  
367    
368          switch (mem)          //CopyQWC(&psHu128(mem), srcval);
         {  
                 case D2_CHCR: // dma2 - gif  
                         DMA_LOG("0x%8.8x hwWrite64: GSdma %x", cpuRegs.cycle, value);  
                         DmaExec(dmaGIF, mem, value);  
                         break;  
   
                 case INTC_STAT:  
                         HW_LOG("INTC_STAT Write 64bit %x", (u32)value);  
                         psHu32(INTC_STAT) &= ~value;  
                         //cpuTestINTCInts();  
                         break;  
   
                 case INTC_MASK:  
                         HW_LOG("INTC_MASK Write 64bit %x", (u32)value);  
                         psHu32(INTC_MASK) ^= (u16)value;  
                         cpuTestINTCInts();  
                         break;  
   
                 case SIO_ISR:  
                 case 0x1000f410:  
                 case MCH_RICM:  
                         break;  
   
                 case DMAC_ENABLEW: // DMAC_ENABLEW  
                         oldvalue = psHu8(DMAC_ENABLEW + 2);  
                         psHu32(DMAC_ENABLEW) = value;  
                         psHu32(DMAC_ENABLER) = value;  
                         if (((oldvalue & 0x1) == 1) && (((value >> 16) & 0x1) == 0))  
                         {  
                                 if (!QueuedDMA.empty()) StartQueuedDMA();  
                         }  
                 break;  
   
                 default:  
                         psHu64(mem) = value;  
                         UnknownHW_LOG("Unknown Hardware write 64 at %x with value %x (status=%x)",mem,value, cpuRegs.CP0.n.Status.val);  
                 break;  
         }  
369  }  }
370    
371  /////////////////////////////////////////////////////////////////////////  template< uint page >
372  // HW Write 128 bit  void __fastcall hwWrite128(u32 mem, const mem128_t* srcval)
   
 void __fastcall hwWrite128_generic(u32 mem, const mem128_t *srcval)  
373  {  {
374          //hwWrite128( mem, srcval ); return;          eeHwTraceLog( mem, *srcval, false );
375            _hwWrite128<page>(mem, srcval);
376          switch (mem)  }
377          {  
378                  case INTC_STAT:  #define InstantizeHwWrite(pageidx) \
379                          HW_LOG("INTC_STAT Write 64bit %x", (u32)srcval[0]);          template void __fastcall hwWrite8<pageidx>(u32 mem, mem8_t value); \
380                          psHu32(INTC_STAT) &= ~srcval[0];          template void __fastcall hwWrite16<pageidx>(u32 mem, mem16_t value); \
381                          //cpuTestINTCInts();          template void __fastcall hwWrite32<pageidx>(u32 mem, mem32_t value); \
382                  break;          template void __fastcall hwWrite64<pageidx>(u32 mem, const mem64_t* srcval); \
383            template void __fastcall hwWrite128<pageidx>(u32 mem, const mem128_t* srcval);
384                  case INTC_MASK:  
385                          HW_LOG("INTC_MASK Write 64bit %x", (u32)srcval[0]);  InstantizeHwWrite(0x00);        InstantizeHwWrite(0x08);
386                          psHu32(INTC_MASK) ^= (u16)srcval[0];  InstantizeHwWrite(0x01);        InstantizeHwWrite(0x09);
387                          cpuTestINTCInts();  InstantizeHwWrite(0x02);        InstantizeHwWrite(0x0a);
388                  break;  InstantizeHwWrite(0x03);        InstantizeHwWrite(0x0b);
389    InstantizeHwWrite(0x04);        InstantizeHwWrite(0x0c);
390                  case DMAC_ENABLEW: // DMAC_ENABLEW  InstantizeHwWrite(0x05);        InstantizeHwWrite(0x0d);
391                          oldvalue = psHu8(DMAC_ENABLEW + 2);  InstantizeHwWrite(0x06);        InstantizeHwWrite(0x0e);
392                          psHu32(DMAC_ENABLEW) = srcval[0];  InstantizeHwWrite(0x07);        InstantizeHwWrite(0x0f);
                         psHu32(DMAC_ENABLER) = srcval[0];  
                         if (((oldvalue & 0x1) == 1) && (((srcval[0] >> 16) & 0x1) == 0))  
                         {  
                                 if (!QueuedDMA.empty()) StartQueuedDMA();  
                         }  
                 break;  
   
                 case SIO_ISR:  
                 case 0x1000f410:  
                 case MCH_RICM:  
                         break;  
   
                 default:  
                         psHu64(mem  ) = srcval[0];  
                         psHu64(mem+8) = srcval[1];  
   
                         UnknownHW_LOG("Unknown Hardware write 128 at %x with value %x_%x (status=%x)", mem, srcval[1], srcval[0], cpuRegs.CP0.n.Status.val);  
                 break;  
         }  
 }  

Legend:
Removed from v.31  
changed lines
  Added in v.62

  ViewVC Help
Powered by ViewVC 1.1.22