home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ST-Computer Leser 2002 January
/
STC_CD_01_2002.iso
/
JAGUAR
/
JAG_SRC
/
SOURCE
/
MEM.C
< prev
next >
Wrap
C/C++ Source or Header
|
2001-08-17
|
44KB
|
1,314 lines
////////////////////////////////////////////////////////////////////////////////
// Jagulator: Atari Jaguar Console Emulation Project (mem.c)
// -----------------------------------------------------------------------------
// Jagulator is the Copyright (c) RealityMan 1998-2001 and is provided "as is"
// without any expressed or implied warranty. I have no Trademarks, Legal or
// otherwise. Atari, Jaguar and the Atari Logo are copyright Hasbro Inc. All
// other Copyrights and Trademarks are acknowledged. This project is in no way
// linked to Atari/Hasbro or other associated Atari companies.
//
// 07-07-2001 GH: New Source, Rewritten for Release 1.5.0
// 00-00-0000 GH: All Previous Source Considered as Development Code Only
#include "core.h"
////////////////////////////////////////////////////////////////////////////////
// Globals
extern char eeprom[];
#ifdef DBGMEM
char memrdbg[] = "[0x%06X] %s --> 0x%04X\n";
char memwdbg[] = "[0x%06X] %s <-- 0x%04X\n";
#endif
////////////////////////////////////////////////////////////////////////////////
// TOM Read Word
unsigned mem_tomreadw( unsigned addr )
{
dword ret; // Return Value
ret = *(word *)(st.tom + (addr - 0xF00000));
// GPU RAM Read
if( addr >= 0xF03000 && addr <= 0xF03FFF ) return( ret );
// CLUT Read
if( addr >= 0xF00400 && addr <= 0xF007FE ) return( ret );
switch( addr )
{
case INT1:
#ifdef DBGMEM
print( memrdbg, INT1, "INT1 ", ret );
#endif
break;
case G_CTRL: break;
case 0xF02116:
ret &= 0x0FE9; // Mask out Bits Not Changed on a Read
ret |= 0x2000; // Include GPU Version
// Taken Out due to Repetition
// print( "[0xF02114] G_CTRL --> 0x0000%04X\n", ret );
break;
case B_CMD: break;
case 0xF0223A:
#ifdef DBGMEM
print( "[0xF02238] B_CMD --> 0x0000%04X \n", blt.bltInactive );
#endif
return( blt.bltInactive );
break;
case MEMCON1:
#ifdef DBGMEM
print( memrdbg, MEMCON1, "MEMCON1 ", ret );
#endif
break;
case MEMCON2:
#ifdef DBGMEM
print( memrdbg, MEMCON2, "MEMCON2 ", ret );
#endif
break;
case LPH:
#ifdef DBGMEM
print( memrdbg, LPH, "LPH ", ret );
#endif
break;
case LPV:
#ifdef DBGMEM
print( memrdbg, LPV, "LPV ", ret );
#endif
break;
case OB0:
#ifdef DBGMEM
print( memrdbg, OB0, "OB0 ", ret );
#endif
break;
case OB1:
#ifdef DBGMEM
print( memrdbg, OB1, "OB1 ", ret );
#endif
break;
case OB2:
#ifdef DBGMEM
print( memrdbg, OB2, "OB2 ", ret );
#endif
break;
case OB3:
#ifdef DBGMEM
print( memrdbg, OB3, "OB3 ", ret );
#endif
break;
case VI:
#ifdef DBGMEM
print( memrdbg, VI, "VI ", ret );
#endif
break;
//case G_FLAGS:
// write znc!!!
default:
#ifdef DBGMEM
print( YEL"\'TOM\' Read Word at 0x%08X\n", addr );
#endif
return( 0 );
break;
}
return( ret & 0x0000FFFF );
}
////////////////////////////////////////////////////////////////////////////////
// TOM Write Word
void mem_tomwritew( unsigned addr, unsigned data )
{
data &= 0x0000FFFF;
*(word *)(st.tom + (addr - 0xF00000)) = data;
if( addr >= 0xF03000 && addr <= 0xF0FFFF ) return;
if( addr >= 0xF00400 && addr <= 0xF007FE )
{
//color_ccry( addr, data );
switch( gst.cmode )
{
case 0: color_ccry( addr, data ); break;
case 3: color_crgb( addr, data ); break;
}
// Make Sure Write Happens to Both CLUTs
if( addr < 0xF00600 ) *(word *)(st.tom+((addr+0x200)-0xF00000))=data;
if( addr > 0xF005FF ) *(word *)(st.tom+((addr-0x200)-0xF00000))=data;
return;
}
switch( addr )
{
case INT1:
#ifdef DBGMEM
print( memwdbg, INT1, "INT1 ", data );
if( data & C_VIDENA )
print( BROWN"%% Enable Video Interrupts\n" );
if( data & C_GPUENA )
print( BROWN"%% Enable GPU Interrupts\n" );
if( data & C_OPENA )
print( BROWN"%% Enable Object Processor Interrupts\n" );
if( data & C_PITENA )
print( BROWN"%% Enable PIT Interrupts\n" );
if( data & C_JERENA )
print( BROWN"%% Enable Jerry Interrupts\n" );
if( data & C_VIDCLR )
print( BROWN"%% Clear Video Interrupts\n" );
if( data & C_GPUCLR )
print( BROWN"%% Clear GPU Interrupts\n" );
if( data & C_OPCLR )
print( BROWN"%% Clear Object Processor Interrupts\n" );
if( data & C_PITCLR )
print( BROWN"%% Clear PIT Interrupts\n" );
if( data & C_JERCLR )
print( BROWN"%% Clear Jerry Interrupts\n" );
#endif
break;
case G_FLAGS: break;
case 0xF02102:
#ifdef DBGMEM
print( "[0xF02100] G_FLAGS <-- 0x%04X%04X\n",
*(word *)(st.tom + 0x2100), *(word *)(st.tom + 0x2102) );
if( data & G_CPUENA )
print( BROWN"Enable GPU CPU Interrupt\n" );
if( data & G_DSPENA )
print( BROWN"Enable GPU DSP Interrupt\n" );
if( data & G_PITENA )
print( BROWN"Enable GPU Timer Interrupt\n" );
if( data & G_OPENA)
print( BROWN"Enable GPU OP Interrupt\n" );
if( data & G_BLITENA )
print( BROWN"Enable GPU Blitter Interrupt\n" );
if( data & G_CPUCLR )
print( BROWN"Clear GPU CPU Interrupt\n" );
if( data & G_DSPCLR )
print( BROWN"Clear GPU DSP Interrupt\n" );
if( data & G_PITCLR )
print( BROWN"Clear GPU Timer Interrupt\n" );
if( data & G_OPCLR)
print( BROWN"Clear GPU OP Interrupt\n" );
if( data & G_BLITCLR )
print( BROWN"Clear GPU Blitter Interrupt\n" );
#endif
if( data & REGPAGE ) // Switch Register Banks
{
sdword t;
int i;
#ifdef DBGMEM
print( BROWN"GPU SWITCH REG BANKS\n");
#endif
for( i = 0; i < 32; i ++ )
{
t = gst.arb[i];
gst.arb[i] = gst.srb[i];
gst.srb[i] = t;
}
}
#ifdef DBGMEM
if( data & DMAEN ) // DMAEN Enabled
print( BROWN"DMAEN Enable\n" );
#endif
break;
case G_PC:
if( st.tom[0x2116] & (byte)GPUGO )
{
#ifdef DBGMEM
print( YEL"GPU ACTIVE - CANNOT UPDATE GPU PC\n" );
#endif
}
else
gpc = data << 16;
break;
case 0xF02112: gpc |= data;
#ifdef DBGMEM
print( "[0xF02110] G_PC <-- 0x%08X\n", gpc );
#endif
break;
case G_CTRL: break;
case 0xF02116: gst.ctrl = data;
#ifdef DBGMEM
print( "[0xF02114] G_CTRL <-- 0x%08X\n", gst.ctrl );
#endif
if( data & 0x0001 ) // GPU_GO
{
#ifdef DBGMEM
print( CYAN"GPU Starting\n" );
#endif
gst.gpuActive = TRUE;
gst.hGPUThread = CreateThread( NULL, 0,
(LPTHREAD_START_ROUTINE)gpu_exec,
(LPVOID)0, 0, &gst.GPUTid );
}
else
{
#ifdef DBGMEM
print( RED"GPU Stopping/Reset\n" );
#endif
gst.gpuActive = FALSE;
}
#ifdef DBGMEM
if( data & CPUINT )
print( BROWN"Allow GPU to Interrupt CPU\n" );
if( data & FORCEINT0 )
print( BROWN"Send GPU Interrupt Zero (TBC)\n" );
#endif
if( data & SINGLE_STEP )
{
#ifdef DBGMEM
print( BROWN"GPU Single Stepping Enabled\n" );
#endif
gst.step = 1;
}
else
{
#ifdef DBGMEM
print( BROWN"GPU Single Stepping Disabled\n" );
#endif
gst.step = 0;
}
if( data & SINGLE_GO ) // SINGLE_GO
{
#ifdef DBGMEM
print( "Single Go: Advance GPU Execution by One Instruction\n" );
#endif
gst.stepgo = 1;
}
#ifdef DBGMEM
switch( data & 0xF000 )
{
case 0x2000:
print( BROWN"Version: First Production Release\n" ); break;
case 0x1000:
print( BROWN"Version: Pre-Production Test Silicon\n" ); break;
default:
print( BROWN"Unknown GPU Version\n" ); break;
}
if( data & 0x0FE0 )
print( YEL"UNHANDLED G_CTRL DATA [0x%08X]\n", gst.ctrl );
flushdisplay();
#endif
break;
case A1_BASE: blt.a1base = data << 16; break;
case 0xF02202: blt.a1base |= data;
#ifdef DBGMEM
print( "[0xF02200] A1_BASE <-- 0x%08X\n", blt.a1base );
#endif
break;
case A1_FLAGS: blt.a1flags = data << 16; break;
case 0xF02206: blt.a1flags |= data;
#ifdef DBGMEM
print( "[0xF02204] A1_FLAGS <-- 0x%08X\n", blt.a1flags );
#endif
break;
case A1_CLIP: blt.a1clip = data << 16; break;
case 0xF0220A: blt.a1clip |= data;
#ifdef DBGMEM
print( "[0xF02208] A1_CLIP <-- 0x%08X\n", blt.a1clip );
#endif
break;
case A1_PIXEL: blt.a1pixel = data << 16; break;
case 0xF0220E: blt.a1pixel |= data;
#ifdef DBGMEM
print( "[0xF0220C] A1_PIXEL <-- 0x%08X\n", blt.a1pixel );
#endif
break;
case A1_STEP: blt.a1step = data << 16; break;
case 0xF02212: blt.a1step |= data;
#ifdef DBGMEM
print( "[0xF02210] A1_STEP <-- 0x%08X\n", blt.a1step );
#endif
break;
case A1_FSTEP: blt.a1fstep = data << 16; break;
case 0xF02216: blt.a1fstep |= data;
#ifdef DBGMEM
print( "[0xF02214] A1_FSTEP <-- 0x%08X\n", blt.a1fstep );
#endif
break;
case A1_FPIXEL: blt.a1fpixel = data << 16; break;
case 0xF0221A: blt.a1fpixel |= data;
#ifdef DBGMEM
print( "[0xF02218] A1_FPIXEL <-- 0x%08X\n", blt.a1fpixel );
#endif
break;
case A1_INC: blt.a1inc = data << 16; break;
case 0xF0221E: blt.a1inc |= data;
#ifdef DBGMEM
print( "[0xF0221C] A1_INC <-- 0x%08X\n", blt.a1inc );
#endif
break;
case A1_FINC: blt.a1finc = data << 16; break;
case 0xF02222: blt.a1finc |= data;
#ifdef DBGMEM
print( "[0xF02220] A1_FINC <-- 0x%08X\n", blt.a1finc );
#endif
break;
case A2_BASE: blt.a2base = data << 16; break;
case 0xF02226: blt.a2base |= data;
#ifdef DBGMEM
print( "[0xF02224] A2_BASE <-- 0x%08X\n", blt.a2base );
#endif
break;
case A2_FLAGS: blt.a2flags = data << 16; break;
case 0xF0222A: blt.a2flags |= data;
#ifdef DBGMEM
print( "[0xF02228] A2_FLAGS <-- 0x%08X\n", blt.a2flags );
#endif
break;
case A2_MASK: blt.a2mask = data << 16; break;
case 0xF0222E: blt.a2mask |= data;
#ifdef DBGMEM
print( "[0xF0222C] A2_MASK <-- 0x%08X\n", blt.a2mask );
#endif
break;
case A2_PIXEL: blt.a2pixel = data << 16; break;
case 0xF02232: blt.a2pixel |= data;
#ifdef DBGMEM
print( "[0xF02230] A2_PIXEL <-- 0x%08X\n", blt.a2pixel );
#endif
break;
case A2_STEP: blt.a2step = data << 16; break;
case 0xF02236: blt.a2step |= data;
#ifdef DBGMEM
print( "[0xF02234] A2_STEP <-- 0x%08X\n", blt.a2step );
#endif
break;
case B_CMD: blt.bcmd = data << 16; break;
case 0xF0223A: blt.bcmd |= data;
#ifdef DBGMEM
print( "[0xF02238] B_CMD <-- 0x%08X\n", blt.bcmd );
// Any Write Activates the Blitter
print( CYAN"Blitter Starting...\n" );
#endif
/*blt.hBLTThread = CreateThread( NULL, 0,
(LPTHREAD_START_ROUTINE)exec_blitter,
(LPVOID)0, 0, &blt.BLTTid );*/
exec_blitter();
// This may well be able to be removed eventually
// Here for safety at the moment
//while( !blt.bltInactive ); // Wait for Blitter Operation to End
#ifdef DBGMEM
print( RED"Blitter Stopped...\n" );
#endif
break;
case B_COUNT: blt.bcount = data << 16; break;
case 0xF0223E: blt.bcount |= data;
#ifdef DBGMEM
print( "[0xF0223C] B_COUNT <-- 0x%08X\n", blt.bcount );
#endif
break;
case B_PATD: blt.bpatd.hi = data << 16; break;
case 0xF0226A: blt.bpatd.hi |= data; break;
case 0xF0226C: blt.bpatd.lo = data << 16; break;
case 0xF0226E: blt.bpatd.lo |= data;
#ifdef DBGMEM
print( "[0xF02268] B_PATD <-- 0x%08X%08X\n",
blt.bpatd.hi, blt.bpatd.lo );
#endif
break;
case OLPLO: gst.olp = data; break;
case OLPHI: gst.olp |= data << 16;
#ifdef DBGMEM
print( "[0xF00020] OLP <-- 0x%08X\n", gst.olp );
#endif
break;
case VMODE:
#ifdef DBGMEM
print( "[0xF00028] VMODE <-- 0x%04X\n", data );
#endif
gst.vmode = data;
if( !st.opened )
{
#ifdef DBGMEM
print( BROWN"Initialise Video\n" );
#endif
v_init( cfg.hres, cfg.vres );
}
switch( data & 0x0006 )
{
case 0x0000:
#ifdef DBGMEM
print( BROWN"%% CRY16\n" );
#endif
gst.cmode = 0; // CrY 16
break;
case 0x0002:
#ifdef DBGMEM
print( BROWN"%% RGB24\n" );
#endif
gst.cmode = 1; // RGB 16
break;
case 0x0004:
#ifdef DBGMEM
print( BROWN"%% DIRECT16\n" );
#endif
gst.cmode = 2; // Direct 16
break;
case 0x0006:
#ifdef DBGMEM
print( BROWN"%% RGB16\n" );
#endif
gst.cmode = 3; // RGB 16
break;
}
#ifdef DBGMEM
print( BROWN"%% PWIDTH = %i\n", (data & 0x0E00) >> 9 );
#endif
break;
case BORD1:
#ifdef DBGMEM
print( memwdbg, BORD1, "BORD1 ", data );
#endif
break;
case BORD2:
#ifdef DBGMEM
print( memwdbg, BORD2, "BORD2 ", data );
#endif
break;
case BG:
#ifdef DBGMEM
print( memwdbg, BG, "BG ", data );
#endif
{
dword tmp;
tmp = cry16_rgb32( data, 0 );
st.br = (GLclampf)(tmp & 0x000000FF);
st.bg = (GLclampf)((tmp & 0x0000FF00) >> 8);
st.bb = (GLclampf)((tmp & 0x00FF0000) >> 16);
}
break;
case MEMCON1:
#ifdef DBGMEM
print( memwdbg, MEMCON1, "MEMCON1 ", data );
#endif
break;
case MEMCON2:
#ifdef DBGMEM
print( memwdbg, MEMCON2, "MEMCON2 ", data );
#endif
break;
case HC:
#ifdef DBGMEM
print( memwdbg, HC, "HC ", data );
#endif
break;
case VC:
#ifdef DBGMEM
print( memwdbg, VC, "VC ", data );
#endif
break;
case ODP:
#ifdef DBGMEM
print( "[0xF00024] OP DtaPtr <-- 0x%02X%02X "
"(OP Internal Data Pointer/Flag - HI)\n",
st.tom[0x0025], st.tom[0x0024] );
#endif
break;
case HP:
#ifdef DBGMEM
print( memwdbg, HP, "HP ", data );
#endif
break;
case HBB:
#ifdef DBGMEM
print( memwdbg, HBB, "HBB ", data );
#endif
break;
case HBE:
#ifdef DBGMEM
print( memwdbg, HBE, "HBE ", data );
#endif
break;
case HS:
#ifdef DBGMEM
print( memwdbg, HS, "HS ", data );
#endif
break;
case HVS:
#ifdef DBGMEM
print( memwdbg, HVS, "HVS ", data );
#endif
break;
case HDB1:
#ifdef DBGMEM
print( memwdbg, HDB1, "HDB1 ", data );
#endif
break;
case HDB2:
#ifdef DBGMEM
print( memwdbg, HDB2, "HDB2 ", data );
#endif
break;
case HDE:
#ifdef DBGMEM
print( memwdbg, HDE, "HDE ", data );
#endif
break;
case VP:
#ifdef DBGMEM
print( memwdbg, VP, "VP ", data );
#endif
break;
case VBB:
#ifdef DBGMEM
print( memwdbg, VBB, "VBB ", data );
#endif
break;
case VBE:
#ifdef DBGMEM
print( memwdbg, VBE, "VBE ", data );
#endif
break;
case VS:
#ifdef DBGMEM
print( memwdbg, VS, "VS ", data );
#endif
break;
case VDB:
#ifdef DBGMEM
print( memwdbg, VDB, "VDB ", data );
#endif
break;
case VDE:
#ifdef DBGMEM
print( memwdbg, VDE, "VDE ", data );
#endif
break;
case VEB:
#ifdef DBGMEM
print( memwdbg, VEB, "VEB ", data );
#endif
break;
case VEE:
#ifdef DBGMEM
print( memwdbg, VEE, "VEE ", data );
#endif
break;
case VI:
#ifdef DBGMEM
print( memwdbg, VI, "VI ", data );
#endif
break;
case PIT0:
#ifdef DBGMEM
print( memwdbg, PIT0, "PIT0 ", data );
#endif
break;
case PIT1:
#ifdef DBGMEM
print( memwdbg, PIT1, "PIT1 ", data );
#endif
break;
case HEQ:
#ifdef DBGMEM
print( memwdbg, HEQ, "HEQ ", data );
#endif
break;
case INT2:
#ifdef DBGMEM
print( memwdbg, INT2, "INT2 ", data );
#endif
break;
case G_END: break;
case 0xF0210E:
// This check can be removed once all data organisations are
// being handled.
#ifdef DBGMEM
if( st.tom[0x210C] != (byte)BIG_END ||
st.tom[0x210E] != (byte)BIG_END )
error( "GPU DATA ORGANISATION CHANGED - "
"Write to G_END [0x%04X%04X]",
*(word *)(st.tom + 0x210C), *(word *)(st.tom + 0x210E) );
else
print( "[0xF0210C] G_END <-- 0x%04X%04X\n",
*(word *)(st.tom + 0x210C), *(word *)(st.tom + 0x210E) );
break;
#endif
default:
#ifdef DBGMEM
print( YEL"\'TOM\' Write Word at 0x%08X (Data = 0x%08X)\n",
addr, data );
#endif
break;
}
}
////////////////////////////////////////////////////////////////////////////////
// JERRY Read Word
unsigned mem_jryreadw( unsigned addr )
{
dword ret; // Return Value
ret = *(word *)(st.jerry + (addr - 0xF10000));
// DSP RAM Read + Waveforms
if( addr >= 0xF1B000 && addr < 0xF1E000 ) return( ret );
switch( addr )
{
case JOYSTICK:
#ifdef DBGMEM
//print( "[0xF14000] JOYSTICK --> 0x%04X\n", ret );
#endif
break;
case CONFIG:
#ifdef DBGMEM
//print( "[0xF14002] JOY/CFG --> 0x%04X\n", ret );
#endif
break;
case 0xF14800:
#ifdef DBGMEM
print( "[0xF14800] GPIO_0 --> 0x%04X\n", ret );
#endif
break;
case 0xF15000:
#ifdef DBGMEM
print( "[0xF15000] GPIO_1 --> Strobe ChipSelect\n" );
#endif
break;
//case D_FLAGS:
// write znc!!!
default:
#ifdef DBGMEM
print( YEL"\'JERRY\' Read Word at 0x%08X\n", addr );
#endif
return( 0 );
break;
}
return( ret & 0x0000FFFF );
}
////////////////////////////////////////////////////////////////////////////////
// JERRY Write Word
void mem_jrywritew( unsigned addr, unsigned data )
{
word joyhi, joylo;
data &= 0x0000FFFF;
*(word *)(st.jerry + (addr - 0xF10000)) = data;
// DSP RAM + Waveforms
if( addr >= 0xF1B000 && addr < 0xF1E000 ) return;
switch( addr )
{
case JPIT1:
#ifdef DBGMEM
print( "[0xF10000] JPIT1 <-- 0x%04X\n", data );
#endif
break;
case JPIT2:
#ifdef DBGMEM
print( "[0xF10002] JPIT2 <-- 0x%04X\n", data );
#endif
break;
case CLK2:
#ifdef DBGMEM
print( "[0xF10012] CLK2 <-- 0x%04X\n", data );
#endif
break;
case CHRO_CLK:
#ifdef DBGMEM
print( "[0xF10014] CHRO_CLK <-- 0x%04X\n", data );
#endif
break;
case J_INT:
#ifdef DBGMEM
print( "[0xF10020] J_INT <-- 0x%04X\n", data );
if( data & J_EXTENA ) print( BROWN"%% Jerry - Enable External Interrupts\n" );
if( data & J_DSPENA ) print( BROWN"%% Jerry - Enable DSP Interrupts\n" );
if( data & J_TIM1ENA ) print( BROWN"%% Jerry - Enable Timer1 Interrupts\n" );
if( data & J_TIM2ENA ) print( BROWN"%% Jerry - Enable Timer2 Interrupts\n" );
if( data & J_ASYNENA ) print( BROWN"%% Jerry - Enable Asynch Interrupts\n" );
if( data & J_SYNENA ) print( BROWN"%% Jerry - Enable Synch Interrupts\n" );
if( data & J_EXTCLR ) print( BROWN"%% Jerry - Clear Pending External Interrupts\n" );
if( data & J_DSPCLR ) print( BROWN"%% Jerry - Clear Pending DSP Interrupts\n" );
if( data & J_TIM1CLR ) print( BROWN"%% Jerry - Clear Pending Timer1 Interrupts\n" );
if( data & J_TIM2CLR ) print( BROWN"%% Jerry - Clear Pending Timer2 Interrupts\n" );
if( data & J_ASYNCLR ) print( BROWN"%% Jerry - Clear Pending Asynch Interrupts\n" );
if( data & J_SYNCLR ) print( BROWN"%% Jerry - Clear Pending Synch Interrupts\n" );
#endif
break;
case JOYSTICK:
#ifdef DBGMEM
//print( "[0xF14000] JOYSTICK <-- 0x%04X\n", data );
#endif
/*
Port 1 MASK = F0FF FFFC
Row0 Row1 Row2 Row3 Return
---- ---- ---- ---- ------
Pause C1 C2 C3 0F00 0002
A B C Option 0F00 0001
Up * 0 # 0E00 0003
Down 7 8 9 0D00 0003
Left 4 5 6 0B00 0003
Right 1 2 3 0700 0003
No Joy0 Pressed = 0F00 0003
Mappings:
A A
B S
C X
Up Up
Down Down
Left Left
Right Right
0-9 0-9
Option O
Pause P
* K
# L
*/
if( data & 0x8000 )
{
#ifdef DBGMEM
//print( "Enable JOYSTICK Outputs J7-J0\n" );
#endif
switch( data & 0x000F )
{
case 0x000E:
#ifdef DBGMEM
//print(BROWN"%% Read Row 0 of Controller 0, Port 1\n" );
#endif
joyhi = 0xFFFF; joylo = 0xFFFF;
if( GetAsyncKeyState( 0x50 ) & 0x8000 ) joylo &= 0xFFFE; // Button Pause
if( GetAsyncKeyState( 0x41 ) & 0x8000 ) joylo &= 0xFFFD; // Button A
if( GetAsyncKeyState( VK_UP ) & 0x8000 ) joyhi &= 0xFEFF; // Button Up
if( GetAsyncKeyState( VK_DOWN ) & 0x8000 ) joyhi &= 0xFDFF; // Button Down
if( GetAsyncKeyState( VK_LEFT ) & 0x8000 ) joyhi &= 0xFBFF; // Button Left
if( GetAsyncKeyState( VK_RIGHT ) & 0x8000 ) joyhi &= 0xF7FF; // Button Right
*(word *)(st.jerry + 0x4000) = joyhi;
*(word *)(st.jerry + 0x4002) = joylo;
break;
case 0x000D:
#ifdef DBGMEM
//print(BROWN"%% Read Row 1 of Controller 0, Port 1\n" );
#endif
joyhi = 0xFFFF; joylo = 0xFFFF;
if( GetAsyncKeyState( 0x53 ) & 0x8000 ) joylo &= 0xFFFD; // Button B
if( GetAsyncKeyState( 0x4B ) & 0x8000 ) joyhi &= 0xFEFF; // Button *
if( GetAsyncKeyState( 0x37 ) & 0x8000 ) joyhi &= 0xFDFF; // Button 7
if( GetAsyncKeyState( 0x34 ) & 0x8000 ) joyhi &= 0xFBFF; // Button 4
if( GetAsyncKeyState( 0x31 ) & 0x8000 ) joyhi &= 0xF7FF; // Button 1
*(word *)(st.jerry + 0x4000) = joyhi;
*(word *)(st.jerry + 0x4002) = joylo;
break;
case 0x000B:
#ifdef DBGMEM
//print(BROWN"%% Read Row 2 of Controller 0, Port 1\n" );
#endif
joyhi = 0xFFFF; joylo = 0xFFFF;
if( GetAsyncKeyState( 0x58 ) & 0x8000 ) joylo &= 0xFFFD; // Button C
if( GetAsyncKeyState( 0x30 ) & 0x8000 ) joyhi &= 0xFEFF; // Button 0
if( GetAsyncKeyState( 0x38 ) & 0x8000 ) joyhi &= 0xFDFF; // Button 8
if( GetAsyncKeyState( 0x35 ) & 0x8000 ) joyhi &= 0xFBFF; // Button 5
if( GetAsyncKeyState( 0x32 ) & 0x8000 ) joyhi &= 0xF7FF; // Button 2
*(word *)(st.jerry + 0x4000) = joyhi;
*(word *)(st.jerry + 0x4002) = joylo;
break;
case 0x0007:
#ifdef DBGMEM
//print(BROWN"%% Read Row 3 of Controller 0, Port 1\n" );
#endif
joyhi = 0xFFFF; joylo = 0xFFFF;
if( GetAsyncKeyState( 0x4F ) & 0x8000 ) joylo &= 0xFFFD; // Button Option
if( GetAsyncKeyState( 0x4C ) & 0x8000 ) joyhi &= 0xFEFF; // Button #
if( GetAsyncKeyState( 0x39 ) & 0x8000 ) joyhi &= 0xFDFF; // Button 9
if( GetAsyncKeyState( 0x36 ) & 0x8000 ) joyhi &= 0xFBFF; // Button 6
if( GetAsyncKeyState( 0x33 ) & 0x8000 ) joyhi &= 0xF7FF; // Button 3
*(word *)(st.jerry + 0x4000) = joyhi;
*(word *)(st.jerry + 0x4002) = joylo;
break;
case 0x000F: break;
default:
#ifdef DBGMEM
//print(BROWN"%% Unknown Row Read Identifier, Port 1\n" );
#endif
break;
}
switch( data & 0x00F0 )
{
case 0x0007:
*(word *)(st.jerry + 0x4000) = 0xFFFF;
*(word *)(st.jerry + 0x4002) = 0xFFFF;
#ifdef DBGMEM
//print(BROWN"%% Read Row 0 of Controller 0, Port 2\n" );
#endif
break;
case 0x000B:
*(word *)(st.jerry + 0x4000) = 0xFFFF;
*(word *)(st.jerry + 0x4002) = 0xFFFF;
#ifdef DBGMEM
//print(BROWN"%% Read Row 1 of Controller 0, Port 2\n" );
#endif
break;
case 0x000D:
*(word *)(st.jerry + 0x4000) = 0xFFFF;
*(word *)(st.jerry + 0x4002) = 0xFFFF;
#ifdef DBGMEM
//print(BROWN"%% Read Row 2 of Controller 0, Port 2\n" );
#endif
break;
case 0x000E:
*(word *)(st.jerry + 0x4000) = 0xFFFF;
*(word *)(st.jerry + 0x4002) = 0xFFFF;
#ifdef DBGMEM
//print(BROWN"%% Read Row 3 of Controller 0, Port 2\n" );
#endif
break;
case 0x000F: break;
default:
#ifdef DBGMEM
//print(BROWN"%% Unknown Row Read Identifier, Port 2\n" );
#endif
break;
}
}
else
{
#ifdef DBGMEM
//print( "Disable JOYSTICK Outputs J7-J0\n" );
#endif
}
if( data & 0x0100 )
{
cfg.sound = 1;
#ifdef DBGMEM
//print( BROWN"Audio Enabled\n" );
#endif
}
else
{
cfg.sound = 0;
#ifdef DBGMEM
//print( BROWN"Audio Muted\n" );
#endif
}
break;
case 0xF14800:
if( (data & 0xFFC0) == 0x0180 )
{
#ifdef DBGMEM
print( "[0xF14800] GPIO_0 <-- Read From EEPROM (Word Index %02i)\n", (data & 0x003F) );
#endif
*(word *)(st.jerry + 0x4800) = *(word *)(eeprom + (data & 0x003F));
}
else
{
#ifdef DBGMEM
print( "[0xF14800] GPIO_0 <-- 0x%04X\n", data );
#endif
}
break;
case D_FLAGS: break;
case 0xF1A102:
#ifdef DBGMEM
print( "[0xF1A100] D_FLAGS <-- 0x%04X%04X\n",
*(word *)(st.jerry + 0xA100),
*(word *)(st.jerry + 0xA102) );
if( data & D_CPUENA )
print( BROWN"Enable DSP CPU Interrupt\n" );
if( data & D_I2SENA )
print( BROWN"Enable DSP I2S Interrupt\n" );
if( data & D_TIM1ENA )
print( BROWN"Enable DSP Timer1 Interrupt\n" );
if( data & D_TIM2ENA )
print( BROWN"Enable DSP Timer2 Interrupt\n" );
if( data & D_EXT0ENA )
print( BROWN"Enable DSP EINT[0] Interrupt\n" );
if( data & D_CPUCLR )
print( BROWN"Clear DSP CPU Interrupt\n" );
if( data & D_I2SCLR )
print( BROWN"Clear DSP I2S Interrupt\n" );
if( data & D_TIM1CLR)
print( BROWN"Clear DSP Timer1 Interrupt\n" );
if( data & D_TIM2CLR )
print( BROWN"Clear DSP Timer2 Interrupt\n" );
if( data & D_EXT0CLR )
print( BROWN"Clear DSP EINT[0] Interrupt\n" );
#endif
if( data & REGPAGE ) // Switch Register Banks
{
sdword t;
int i;
#ifdef DBGMEM
print( BROWN"DSP Switch Register Banks\n");
#endif
for( i = 0; i < 32; i ++ )
{
t = dst.arb[i];
dst.arb[i] = dst.srb[i];
dst.srb[i] = t;
//print( "ARB-R%02i = 0x%08X SRB-R%02i = 0x%08X\n",
// i, dst.arb[i], i, dst.srb[i] );
}
dst.bswitched = TRUE;
}
if( !(data & REGPAGE) && dst.bswitched )
{
sdword t;
int i;
#ifdef DBGMEM
print( BROWN"DSP Restore Register Banks\n" );
#endif
for( i = 0; i < 32; i ++ )
{
t = dst.arb[i];
dst.arb[i] = dst.srb[i];
dst.srb[i] = t;
//print( "ARB-R%02i = 0x%08X SRB-R%02i = 0x%08X\n",
// i, dst.arb[i], i, dst.srb[i] );
}
dst.bswitched = FALSE;
}
#ifdef DBGMEM
if( data & DMAEN )
print( BROWN"DMA Enable\n" );
if( data & D_EXT1ENA )
print( BROWN"Enable DSP EINT[1] Interrupt\n" );
if( data & D_EXT1CLR )
print( BROWN"Enable DSP EINT[1] Interrupt\n" );
#endif
break;
case D_END: break;
case 0xF1A10E:
// This check can be removed once all data organisations are
// being handled.
#ifdef DBGMEM
if( st.jerry[0xA10C] != (byte)BIG_END ||
st.jerry[0xA10E] != (byte)BIG_END )
{
error( "DSP DATA ORGANISATION CHANGED - "
"Write to D_END [0x%04X%04X]",
*(word *)(st.jerry + 0xA10C),
*(word *)(st.jerry + 0xA10E) );
}
else
print( "[0xF1A10C] D_END <-- 0x%04X%04X\n",
*(word *)(st.jerry + 0xA10C),
*(word *)(st.jerry + 0xA10E) );
#endif
break;
case D_PC:
if( st.jerry[0xA116] & (byte)DSPGO )
{
#ifdef DBGMEM
print( YEL"DSP ACTIVE - CANNOT UPDATE DSP PC\n" );
#endif
}
else
dst.pc = data << 16;
break;
case 0xF1A112: dst.pc |= data;
#ifdef DBGMEM
print( "[0xF1A110] D_PC <-- 0x%08X\n", dst.pc );
#endif
break;
case D_CTRL: break;
case 0xF1A116:
#ifdef DBGMEM
print( "[0xF1A114] D_CTRL <-- 0x%04X%04X\n",
*(word *)(st.jerry + 0xA114),
*(word *)(st.jerry + 0xA116) );
#endif
if( data & DSPGO )
{
#ifdef DBGMEM
print( CYAN"DSP Starting\n" );
#endif
dst.dspActive = TRUE;
/*dst.hDSPThread = CreateThread( NULL, 0,
(LPTHREAD_START_ROUTINE)ExecDSP,
(LPVOID)0, 0, &dst.DSPTid );*/
}
else
{
#ifdef DBGMEM
print( RED"DSP Stopping/Reset\n" );
#endif
dst.dspActive = FALSE;
}
#ifdef DBGMEM
if( data & 0xFFFE )
print( YEL"UNHANDLED D_CTRL DATA\n" );
#endif
break;
case D_MOD: break;
case 0xF1A11A:
#ifdef DBGMEM
print( "[0xF1A118] D_MOD <-- 0x%04X%04X\n",
*(word *)(st.jerry + 0xA118),
*(word *)(st.jerry + 0xA11A) );
#endif
break;
case L_I2S: break;
case 0xF1A14A:
#ifdef DBGMEM
print( "[0xF1A148] L_I2S <-- 0x%04X%04X\n",
*(word *)(st.jerry + 0xA148),
*(word *)(st.jerry + 0xA14A) );
#endif
break;
case R_I2S: break;
case 0xF1A14E:
#ifdef DBGMEM
print( "[0xF1A14C] R_I2S <-- 0x%04X%04X\n",
*(word *)(st.jerry + 0xA14C),
*(word *)(st.jerry + 0xA14E) );
#endif
break;
case SCLK: break;
case 0xF1A152:
#ifdef DBGMEM
print( "[0xF1A150] SCLK <-- 0x%04X%04X\n",
*(word *)(st.jerry + 0xA150),
*(word *)(st.jerry + 0xA152) );
#endif
break;
case SMODE: break;
case 0xF1A156:
#ifdef DBGMEM
print( "[0xF1A154] SMODE <-- 0x%04X%04X\n",
*(word *)(st.jerry + 0xA154),
*(word *)(st.jerry + 0xA156) );
#endif
break;
default:
#ifdef DBGMEM
print( YEL"\'JERRY\' Write Word at 0x%08X (Data = 0x%08X)\n",
addr, data );
#endif
break;
}
}
////////////////////////////////////////////////////////////////////////////////
// Generic Read Word
unsigned mem_readword( unsigned addr )
{
if( addr >= 0x000000 && addr <= 0x3FFFFF )
return( *(word *)(st.ram + addr) );
if( addr >= 0x800000 && addr <= 0xE00000 )
return( *(word *)(st.game + (addr - 0x800000)) );
if( addr >= 0xF00000 && addr <= 0xF0FFFF )
return( mem_tomreadw( addr ) );
if( addr >= 0xF10000 && addr <= 0xF1FFFF )
return( mem_jryreadw( addr ) );
#ifdef DBGMEM
error( "Read Word at 0x%08X - Returning Zero\n", addr );
#endif
return( 0 );
}
////////////////////////////////////////////////////////////////////////////////
// Generic Read Byte
unsigned mem_readbyte( unsigned addr )
{
// Main Ram Read Byte
if( addr >= 0x000000 && addr <= 0x3FFFFF )
{
if( !(addr % 2) ) // Allow for Byte Swapping
return( st.ram[addr + 1] );
else
return( st.ram[addr - 1] );
}
// Game Rom Read Byte
if( addr >= 0x800000 && addr <= 0xDFFFFF )
{
if( !(addr % 2) ) // Allow for Byte Swapping
return( st.game[(addr - 0x800000) + 1] );
else
return( st.game[(addr - 0x800000) - 1] );
}
#ifdef DBGMEM
error( "Read Byte at 0x%08X, Returning Zero", addr );
#endif
return( 0 );
}
////////////////////////////////////////////////////////////////////////////////
// Generic Write Word
void mem_writeword( unsigned addr, unsigned data )
{
if( addr >= 0x000000 && addr <= 0x3FFFFF )
{
*(word *)(st.ram + addr) = data;
return;
}
if( addr >= 0xF03000 && addr <= 0xF04000 )
{
*(word *)(st.tom + (addr - 0xF00000)) = data;
return;
}
if( addr >= 0xF00000 && addr <= 0xF0FFFF )
{
mem_tomwritew( addr, data );
return;
}
if( addr >= 0xF10000 && addr <= 0xF1FFFF )
{
mem_jrywritew( addr, data );
return;
}
#ifdef DBGMEM
error( "Write Word at 0x%08X (0x%08X)", addr, data );
#endif
}
////////////////////////////////////////////////////////////////////////////////
// Generic Write Byte
void mem_writebyte( unsigned addr, unsigned data )
{
// Main Ram Write Byte
if( addr >= 0x000000 && addr <= 0x3FFFFF )
{
if( !(addr % 2) ) // Allow for Byte Swapping
st.ram[addr + 1] = (data & 0xFF);
else
st.ram[addr - 1] = (data & 0xFF);
return;
}
#ifdef DBGMEM
error( "Write Byte at 0x%08X (Data = 0x%08X)", addr, data );
#endif
}