2235 lines
61 KiB
C++
2235 lines
61 KiB
C++
//
|
|
// Copyright (c) 2004 K. Wilkins
|
|
//
|
|
// This software is provided 'as-is', without any express or implied warranty.
|
|
// In no event will the authors be held liable for any damages arising from
|
|
// the use of this software.
|
|
//
|
|
// Permission is granted to anyone to use this software for any purpose,
|
|
// including commercial applications, and to alter it and redistribute it
|
|
// freely, subject to the following restrictions:
|
|
//
|
|
// 1. The origin of this software must not be misrepresented; you must not
|
|
// claim that you wrote the original software. If you use this software
|
|
// in a product, an acknowledgment in the product documentation would be
|
|
// appreciated but is not required.
|
|
//
|
|
// 2. Altered source versions must be plainly marked as such, and must not
|
|
// be misrepresented as being the original software.
|
|
//
|
|
// 3. This notice may not be removed or altered from any source distribution.
|
|
//
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// Handy - An Atari Lynx Emulator //
|
|
// Copyright (c) 1996,1997 //
|
|
// K. Wilkins //
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// Suzy emulation class //
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// This class emulates the Suzy chip within the lynx. This provides math //
|
|
// and sprite painting facilities. SpritePaint() is called from within //
|
|
// the Mikey POKE functions when SPRGO is set and is called via the system //
|
|
// object to keep the interface clean. //
|
|
// //
|
|
// K. Wilkins //
|
|
// August 1997 //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// Revision History: //
|
|
// ----------------- //
|
|
// //
|
|
// 01Aug1997 KW Document header added & class documented. //
|
|
// //
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
#define SUSIE_CPP
|
|
|
|
//#include <crtdbg.h>
|
|
//#define TRACE_SUSIE
|
|
|
|
#include "system.h"
|
|
#include "susie.h"
|
|
#include "lynxdef.h"
|
|
|
|
//
|
|
// As the Susie sprite engine only ever sees system RAM
|
|
// wa can access this directly without the hassle of
|
|
// going through the system object, much faster
|
|
//
|
|
//#define RAM_PEEK(m) (mSystem.Peek_RAM((m)))
|
|
//#define RAM_POKE(m1,m2) (mSystem.Poke_RAM((m1),(m2)))
|
|
//#define RAM_PEEKW(m) (mSystem.PeekW_RAM((m)))
|
|
|
|
#define RAM_PEEK(m) (mRamPointer[(m)])
|
|
#define RAM_PEEKW(m) (mRamPointer[(m)]+(mRamPointer[(m)+1]<<8))
|
|
#define RAM_POKE(m1,m2) {mRamPointer[(m1)]=(m2);}
|
|
|
|
CSusie::CSusie(CSystem& parent)
|
|
:mSystem(parent)
|
|
{
|
|
TRACE_SUSIE0("CSusie()");
|
|
Reset();
|
|
}
|
|
|
|
CSusie::~CSusie()
|
|
{
|
|
TRACE_SUSIE0("~CSusie()");
|
|
}
|
|
|
|
void CSusie::Reset(void)
|
|
{
|
|
TRACE_SUSIE0("Reset()");
|
|
|
|
// Fetch pointer to system RAM, faster than object access
|
|
// and seeing as Susie only ever sees RAM.
|
|
|
|
mRamPointer=mSystem.GetRamPointer();
|
|
|
|
// Reset ALL variables
|
|
|
|
mTMPADR.Val16=0;
|
|
mTILTACUM.Val16=0;
|
|
mHOFF.Val16=0;
|
|
mVOFF.Val16=0;
|
|
mVIDBAS.Val16=0;
|
|
mCOLLBAS.Val16=0;
|
|
mVIDADR.Val16=0;
|
|
mCOLLADR.Val16=0;
|
|
mSCBNEXT.Val16=0;
|
|
mSPRDLINE.Val16=0;
|
|
mHPOSSTRT.Val16=0;
|
|
mVPOSSTRT.Val16=0;
|
|
mSPRHSIZ.Val16=0;
|
|
mSPRVSIZ.Val16=0;
|
|
mSTRETCH.Val16=0;
|
|
mTILT.Val16=0;
|
|
mSPRDOFF.Val16=0;
|
|
mSPRVPOS.Val16=0;
|
|
mCOLLOFF.Val16=0;
|
|
mVSIZACUM.Val16=0;
|
|
mHSIZACUM.Val16=0;
|
|
mHSIZOFF.Val16=0x007f;
|
|
mVSIZOFF.Val16=0x007f;
|
|
mSCBADR.Val16=0;
|
|
mPROCADR.Val16=0;
|
|
|
|
// Must be initialised to this due to
|
|
// stun runner math initialisation bug
|
|
// see whatsnew for 0.7
|
|
mMATHABCD.Long=0xffffffff;
|
|
mMATHEFGH.Long=0xffffffff;
|
|
mMATHJKLM.Long=0xffffffff;
|
|
mMATHNP.Long=0xffff;
|
|
|
|
mMATHAB_sign=1;
|
|
mMATHCD_sign=1;
|
|
mMATHEFGH_sign=1;
|
|
|
|
mSPRCTL0_Type=0;
|
|
mSPRCTL0_Vflip=0;
|
|
mSPRCTL0_Hflip=0;
|
|
mSPRCTL0_PixelBits=0;
|
|
|
|
mSPRCTL1_StartLeft=0;
|
|
mSPRCTL1_StartUp=0;
|
|
mSPRCTL1_SkipSprite=0;
|
|
mSPRCTL1_ReloadPalette=0;
|
|
mSPRCTL1_ReloadDepth=0;
|
|
mSPRCTL1_Sizing=0;
|
|
mSPRCTL1_Literal=0;
|
|
|
|
mSPRCOLL_Number=0;
|
|
mSPRCOLL_Collide=0;
|
|
|
|
mSPRSYS_StopOnCurrent=0;
|
|
mSPRSYS_LeftHand=0;
|
|
mSPRSYS_VStretch=0;
|
|
mSPRSYS_NoCollide=0;
|
|
mSPRSYS_Accumulate=0;
|
|
mSPRSYS_SignedMath=0;
|
|
mSPRSYS_Status=0;
|
|
mSPRSYS_UnsafeAccess=0;
|
|
mSPRSYS_LastCarry=0;
|
|
mSPRSYS_Mathbit=0;
|
|
mSPRSYS_MathInProgress=0;
|
|
|
|
mSUZYBUSEN=FALSE;
|
|
|
|
mSPRINIT.Byte=0;
|
|
|
|
mSPRGO=FALSE;
|
|
mEVERON=FALSE;
|
|
|
|
for(int loop=0;loop<16;loop++) mPenIndex[loop]=loop;
|
|
|
|
hquadoff = vquadoff = 0;
|
|
|
|
mJOYSTICK.Byte=0;
|
|
mSWITCHES.Byte=0;
|
|
}
|
|
|
|
|
|
void CSusie::DoMathMultiply(void)
|
|
{
|
|
mSPRSYS_Mathbit=FALSE;
|
|
|
|
// Multiplies with out sign or accumulate take 44 ticks to complete.
|
|
// Multiplies with sign and accumulate take 54 ticks to complete.
|
|
//
|
|
// AB EFGH
|
|
// * CD / NP
|
|
// ------- -----------
|
|
// EFGH ABCD
|
|
// Accumulate in JKLM Remainder in (JK)LM
|
|
//
|
|
|
|
|
|
uint32 result;
|
|
|
|
// Basic multiply is ALWAYS unsigned, sign conversion is done later
|
|
result=(uint32)mMATHABCD.Words.AB*(uint32)mMATHABCD.Words.CD;
|
|
mMATHEFGH.Long=result;
|
|
|
|
if(mSPRSYS_SignedMath)
|
|
{
|
|
TRACE_SUSIE0("DoMathMultiply() - SIGNED");
|
|
// Add the sign bits, only >0 is +ve result
|
|
mMATHEFGH_sign=mMATHAB_sign+mMATHCD_sign;
|
|
if(!mMATHEFGH_sign)
|
|
{
|
|
mMATHEFGH.Long^=0xffffffff;
|
|
mMATHEFGH.Long++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TRACE_SUSIE0("DoMathMultiply() - UNSIGNED");
|
|
}
|
|
|
|
TRACE_SUSIE2("DoMathMultiply() AB=$%04x * CD=$%04x",mMATHABCD.Words.AB,mMATHABCD.Words.CD);
|
|
|
|
// Check overflow, if B31 has changed from 1->0 then its overflow time
|
|
if(mSPRSYS_Accumulate)
|
|
{
|
|
TRACE_SUSIE0("DoMathMultiply() - ACCUMULATED JKLM+=EFGH");
|
|
uint32 tmp=mMATHJKLM.Long+mMATHEFGH.Long;
|
|
// Let sign change indicate overflow
|
|
if((tmp&0x80000000)!=(mMATHJKLM.Long&0x80000000))
|
|
{
|
|
TRACE_SUSIE0("DoMathMultiply() - OVERFLOW DETECTED");
|
|
// mSPRSYS_Mathbit=TRUE;
|
|
}
|
|
else
|
|
{
|
|
// mSPRSYS_Mathbit=FALSE;
|
|
}
|
|
// Save accumulated result
|
|
mMATHJKLM.Long=tmp;
|
|
}
|
|
|
|
TRACE_SUSIE1("DoMathMultiply() Results (raw - no sign) Result=$%08x",result);
|
|
TRACE_SUSIE1("DoMathMultiply() Results (Multi) EFGH=$%08x",mMATHEFGH.Long);
|
|
TRACE_SUSIE1("DoMathMultiply() Results (Accum) JKLM=$%08x",mMATHJKLM.Long);
|
|
}
|
|
|
|
void CSusie::DoMathDivide(void)
|
|
{
|
|
mSPRSYS_Mathbit=FALSE;
|
|
|
|
//
|
|
// Divides take 176 + 14*N ticks
|
|
// (N is the number of most significant zeros in the divisor.)
|
|
//
|
|
// AB EFGH
|
|
// * CD / NP
|
|
// ------- -----------
|
|
// EFGH ABCD
|
|
// Accumulate in JKLM Remainder in (JK)LM
|
|
//
|
|
|
|
// Divide is ALWAYS unsigned arithmetic...
|
|
if(mMATHNP.Long)
|
|
{
|
|
TRACE_SUSIE0("DoMathDivide() - UNSIGNED");
|
|
mMATHABCD.Long=mMATHEFGH.Long/mMATHNP.Long;
|
|
mMATHJKLM.Long=mMATHEFGH.Long%mMATHNP.Long;
|
|
}
|
|
else
|
|
{
|
|
TRACE_SUSIE0("DoMathDivide() - DIVIDE BY ZERO ERROR");
|
|
mMATHABCD.Long=0xffffffff;
|
|
mMATHJKLM.Long=0;
|
|
mSPRSYS_Mathbit=TRUE;
|
|
}
|
|
TRACE_SUSIE2("DoMathDivide() EFGH=$%08x / NP=%04x",mMATHEFGH.Long,mMATHNP.Long);
|
|
TRACE_SUSIE1("DoMathDivide() Results (div) ABCD=$%08x",mMATHABCD.Long);
|
|
TRACE_SUSIE1("DoMathDivide() Results (mod) JKLM=$%08x",mMATHJKLM.Long);
|
|
}
|
|
|
|
|
|
uint32 CSusie::PaintSprites(void)
|
|
{
|
|
int sprcount=0;
|
|
int data=0;
|
|
int everonscreen=0;
|
|
|
|
TRACE_SUSIE0(" ");
|
|
TRACE_SUSIE0(" ");
|
|
TRACE_SUSIE0(" ");
|
|
TRACE_SUSIE0("**************************************************************");
|
|
TRACE_SUSIE0("********************** PaintSprites **************************");
|
|
TRACE_SUSIE0("**************************************************************");
|
|
TRACE_SUSIE0(" ");
|
|
|
|
TRACE_SUSIE1("PaintSprites() VIDBAS $%04x",mVIDBAS.Val16);
|
|
TRACE_SUSIE1("PaintSprites() COLLBAS $%04x",mCOLLBAS.Val16);
|
|
TRACE_SUSIE1("PaintSprites() SPRSYS $%02x",Peek(SPRSYS));
|
|
|
|
if(!mSUZYBUSEN || !mSPRGO)
|
|
{
|
|
TRACE_SUSIE0("PaintSprites() Returned !mSUZYBUSEN || !mSPRGO");
|
|
return 0;
|
|
}
|
|
|
|
cycles_used=0;
|
|
|
|
do
|
|
{
|
|
everonscreen = 0;
|
|
|
|
TRACE_SUSIE1("PaintSprites() ************ Rendering Sprite %03d ************",sprcount);
|
|
|
|
// Step 1 load up the SCB params into Susie
|
|
|
|
// And thus it is documented that only the top byte of SCBNEXT is used.
|
|
// Its mentioned under the bits that are broke section in the bluebook
|
|
if(!(mSCBNEXT.Val16&0xff00))
|
|
{
|
|
TRACE_SUSIE0("PaintSprites() mSCBNEXT==0 - FINISHED");
|
|
mSPRSYS_Status=0; // Engine has finished
|
|
mSPRGO=FALSE;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
mSPRSYS_Status=1;
|
|
}
|
|
|
|
mTMPADR.Val16=mSCBNEXT.Val16; // Copy SCB pointer
|
|
mSCBADR.Val16=mSCBNEXT.Val16; // Copy SCB pointer
|
|
TRACE_SUSIE1("PaintSprites() SCBADDR $%04x",mSCBADR.Val16);
|
|
|
|
data=RAM_PEEK(mTMPADR.Val16); // Fetch control 0
|
|
TRACE_SUSIE1("PaintSprites() SPRCTL0 $%02x",data);
|
|
mSPRCTL0_Type=data&0x0007;
|
|
mSPRCTL0_Vflip=data&0x0010;
|
|
mSPRCTL0_Hflip=data&0x0020;
|
|
mSPRCTL0_PixelBits=((data&0x00c0)>>6)+1;
|
|
mTMPADR.Val16+=1;
|
|
|
|
data=RAM_PEEK(mTMPADR.Val16); // Fetch control 1
|
|
TRACE_SUSIE1("PaintSprites() SPRCTL1 $%02x",data);
|
|
mSPRCTL1_StartLeft=data&0x0001;
|
|
mSPRCTL1_StartUp=data&0x0002;
|
|
mSPRCTL1_SkipSprite=data&0x0004;
|
|
mSPRCTL1_ReloadPalette=data&0x0008;
|
|
mSPRCTL1_ReloadDepth=(data&0x0030)>>4;
|
|
mSPRCTL1_Sizing=data&0x0040;
|
|
mSPRCTL1_Literal=data&0x0080;
|
|
mTMPADR.Val16+=1;
|
|
|
|
data=RAM_PEEK(mTMPADR.Val16); // Collision num
|
|
TRACE_SUSIE1("PaintSprites() SPRCOLL $%02x",data);
|
|
mSPRCOLL_Number=data&0x000f;
|
|
mSPRCOLL_Collide=data&0x0020;
|
|
mTMPADR.Val16+=1;
|
|
|
|
mSCBNEXT.Val16=RAM_PEEKW(mTMPADR.Val16); // Next SCB
|
|
TRACE_SUSIE1("PaintSprites() SCBNEXT $%04x",mSCBNEXT.Val16);
|
|
mTMPADR.Val16+=2;
|
|
|
|
cycles_used+=5*SPR_RDWR_CYC;
|
|
|
|
// Initialise the collision depositary
|
|
|
|
// Although Tom Schenck says this is correct, it doesnt appear to be
|
|
// if(!mSPRCOLL_Collide && !mSPRSYS_NoCollide)
|
|
// {
|
|
// mCollision=RAM_PEEK((mSCBADR.Val16+mCOLLOFF.Val16)&0xffff);
|
|
// mCollision&=0x0f;
|
|
// }
|
|
mCollision=0;
|
|
|
|
// Check if this is a skip sprite
|
|
|
|
if(!mSPRCTL1_SkipSprite)
|
|
{
|
|
|
|
mSPRDLINE.Val16=RAM_PEEKW(mTMPADR.Val16); // Sprite pack data
|
|
TRACE_SUSIE1("PaintSprites() SPRDLINE $%04x",mSPRDLINE.Val16);
|
|
mTMPADR.Val16+=2;
|
|
|
|
mHPOSSTRT.Val16=RAM_PEEKW(mTMPADR.Val16); // Sprite horizontal start position
|
|
TRACE_SUSIE1("PaintSprites() HPOSSTRT $%04x",mHPOSSTRT.Val16);
|
|
mTMPADR.Val16+=2;
|
|
|
|
mVPOSSTRT.Val16=RAM_PEEKW(mTMPADR.Val16); // Sprite vertical start position
|
|
TRACE_SUSIE1("PaintSprites() VPOSSTRT $%04x",mVPOSSTRT.Val16);
|
|
mTMPADR.Val16+=2;
|
|
|
|
cycles_used+=6*SPR_RDWR_CYC;
|
|
|
|
bool enable_sizing=FALSE;
|
|
bool enable_stretch=FALSE;
|
|
bool enable_tilt=FALSE;
|
|
|
|
// Optional section defined by reload type in Control 1
|
|
|
|
TRACE_SUSIE1("PaintSprites() mSPRCTL1.Bits.ReloadDepth=%d",mSPRCTL1_ReloadDepth);
|
|
switch(mSPRCTL1_ReloadDepth)
|
|
{
|
|
case 1:
|
|
TRACE_SUSIE0("PaintSprites() Sizing Enabled");
|
|
enable_sizing=TRUE;
|
|
|
|
mSPRHSIZ.Val16=RAM_PEEKW(mTMPADR.Val16); // Sprite Horizontal size
|
|
mTMPADR.Val16+=2;
|
|
|
|
mSPRVSIZ.Val16=RAM_PEEKW(mTMPADR.Val16); // Sprite Verticalal size
|
|
mTMPADR.Val16+=2;
|
|
|
|
cycles_used+=4*SPR_RDWR_CYC;
|
|
break;
|
|
|
|
case 2:
|
|
TRACE_SUSIE0("PaintSprites() Sizing Enabled");
|
|
TRACE_SUSIE0("PaintSprites() Stretch Enabled");
|
|
enable_sizing=TRUE;
|
|
enable_stretch=TRUE;
|
|
|
|
mSPRHSIZ.Val16=RAM_PEEKW(mTMPADR.Val16); // Sprite Horizontal size
|
|
mTMPADR.Val16+=2;
|
|
|
|
mSPRVSIZ.Val16=RAM_PEEKW(mTMPADR.Val16); // Sprite Verticalal size
|
|
mTMPADR.Val16+=2;
|
|
|
|
mSTRETCH.Val16=RAM_PEEKW(mTMPADR.Val16); // Sprite stretch
|
|
mTMPADR.Val16+=2;
|
|
|
|
cycles_used+=6*SPR_RDWR_CYC;
|
|
break;
|
|
|
|
case 3:
|
|
TRACE_SUSIE0("PaintSprites() Sizing Enabled");
|
|
TRACE_SUSIE0("PaintSprites() Stretch Enabled");
|
|
TRACE_SUSIE0("PaintSprites() Tilt Enabled");
|
|
enable_sizing=TRUE;
|
|
enable_stretch=TRUE;
|
|
enable_tilt=TRUE;
|
|
|
|
mSPRHSIZ.Val16=RAM_PEEKW(mTMPADR.Val16); // Sprite Horizontal size
|
|
mTMPADR.Val16+=2;
|
|
|
|
mSPRVSIZ.Val16=RAM_PEEKW(mTMPADR.Val16); // Sprite Verticalal size
|
|
mTMPADR.Val16+=2;
|
|
|
|
mSTRETCH.Val16=RAM_PEEKW(mTMPADR.Val16); // Sprite stretch
|
|
mTMPADR.Val16+=2;
|
|
|
|
mTILT.Val16=RAM_PEEKW(mTMPADR.Val16); // Sprite tilt
|
|
mTMPADR.Val16+=2;
|
|
|
|
cycles_used+=8*SPR_RDWR_CYC;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
TRACE_SUSIE1("PaintSprites() SPRHSIZ $%04x",mSPRHSIZ.Val16);
|
|
TRACE_SUSIE1("PaintSprites() SPRVSIZ $%04x",mSPRVSIZ.Val16);
|
|
TRACE_SUSIE1("PaintSprites() STRETCH $%04x",mSTRETCH.Val16);
|
|
TRACE_SUSIE1("PaintSprites() TILT $%04x",mTILT.Val16);
|
|
|
|
|
|
// Optional Palette reload
|
|
|
|
if(!mSPRCTL1_ReloadPalette)
|
|
{
|
|
TRACE_SUSIE0("PaintSprites() Palette reloaded");
|
|
for(int loop=0;loop<8;loop++)
|
|
{
|
|
uint8 data_tmp = RAM_PEEK(mTMPADR.Val16++);
|
|
mPenIndex[loop*2]=(data_tmp>>4)&0x0f;
|
|
mPenIndex[(loop*2)+1]=data_tmp&0x0f;
|
|
}
|
|
// Increment cycle count for the reads
|
|
cycles_used+=8*SPR_RDWR_CYC;
|
|
}
|
|
|
|
// Now we can start painting
|
|
|
|
// Quadrant drawing order is: SE,NE,NW,SW
|
|
// start quadrant is given by sprite_control1:0 & 1
|
|
|
|
// Setup screen start end variables
|
|
|
|
int screen_h_start=(int16)mHOFF.Val16;
|
|
int screen_h_end=(int16)mHOFF.Val16+SCREEN_WIDTH;
|
|
int screen_v_start=(int16)mVOFF.Val16;
|
|
int screen_v_end=(int16)mVOFF.Val16+SCREEN_HEIGHT;
|
|
|
|
int world_h_mid=screen_h_start+0x8000+(SCREEN_WIDTH/2);
|
|
int world_v_mid=screen_v_start+0x8000+(SCREEN_HEIGHT/2);
|
|
|
|
TRACE_SUSIE2("PaintSprites() screen_h_start $%04x screen_h_end $%04x",screen_h_start,screen_h_end);
|
|
TRACE_SUSIE2("PaintSprites() screen_v_start $%04x screen_v_end $%04x",screen_v_start,screen_v_end);
|
|
TRACE_SUSIE2("PaintSprites() world_h_mid $%04x world_v_mid $%04x",world_h_mid,world_v_mid);
|
|
|
|
bool superclip=FALSE;
|
|
int quadrant=0;
|
|
int hsign,vsign;
|
|
|
|
if(mSPRCTL1_StartLeft)
|
|
{
|
|
if(mSPRCTL1_StartUp) quadrant=2; else quadrant=3;
|
|
}
|
|
else
|
|
{
|
|
if(mSPRCTL1_StartUp) quadrant=1; else quadrant=0;
|
|
}
|
|
TRACE_SUSIE1("PaintSprites() Quadrant=%d",quadrant);
|
|
|
|
// Check ref is inside screen area
|
|
|
|
//if((int16)mHPOSSTRT.Val16<screen_h_start || (int16)mHPOSSTRT.Val16>=screen_h_end ||
|
|
// (int16)mVPOSSTRT.Val16<screen_v_start || (int16)mVPOSSTRT.Val16>=screen_v_end) superclip=TRUE;
|
|
|
|
TRACE_SUSIE1("PaintSprites() Superclip=%d",superclip);
|
|
|
|
|
|
// Quadrant mapping is: SE NE NW SW
|
|
// 0 1 2 3
|
|
// hsign +1 +1 -1 -1
|
|
// vsign +1 -1 -1 +1
|
|
//
|
|
//
|
|
// 2 | 1
|
|
// -------
|
|
// 3 | 0
|
|
//
|
|
|
|
// Loop for 4 quadrants
|
|
|
|
for(int loop=0;loop<4;loop++)
|
|
{
|
|
TRACE_SUSIE1("PaintSprites() -------- Rendering Quadrant %03d --------",quadrant);
|
|
|
|
int sprite_v=mVPOSSTRT.Val16;
|
|
int sprite_h=mHPOSSTRT.Val16;
|
|
|
|
bool render=FALSE;
|
|
|
|
// Set quadrand multipliers
|
|
hsign=(quadrant==0 || quadrant==1)?1:-1;
|
|
vsign=(quadrant==0 || quadrant==3)?1:-1;
|
|
|
|
// Preflip TRACE_SUSIE2("PaintSprites() hsign=%d vsign=%d",hsign,vsign);
|
|
|
|
//Use h/v flip to invert v/hsign
|
|
|
|
if(mSPRCTL0_Vflip) vsign=-vsign;
|
|
if(mSPRCTL0_Hflip) hsign=-hsign;
|
|
|
|
TRACE_SUSIE2("PaintSprites() Hflip=%d Vflip=%d",mSPRCTL0_Hflip,mSPRCTL0_Vflip);
|
|
TRACE_SUSIE2("PaintSprites() Hsign=%d Vsign=%d",hsign,vsign);
|
|
TRACE_SUSIE2("PaintSprites() Hpos =%04x Vpos =%04x",mHPOSSTRT.Val16,mVPOSSTRT.Val16);
|
|
TRACE_SUSIE2("PaintSprites() Hsizoff =%04x Vsizoff =%04x",mHSIZOFF.Val16,mVSIZOFF.Val16);
|
|
|
|
// Two different rendering algorithms used, on-screen & superclip
|
|
// when on screen we draw in x until off screen then skip to next
|
|
// line, BUT on superclip we draw all the way to the end of any
|
|
// given line checking each pixel is on screen.
|
|
|
|
if(superclip)
|
|
{
|
|
// Check on the basis of each quad, we only render the quad
|
|
// IF the screen is in the quad, relative to the centre of
|
|
// the screen which is calculated below.
|
|
|
|
// Quadrant mapping is: SE NE NW SW
|
|
// 0 1 2 3
|
|
// hsign +1 +1 -1 -1
|
|
// vsign +1 -1 -1 +1
|
|
//
|
|
//
|
|
// 2 | 1
|
|
// -------
|
|
// 3 | 0
|
|
//
|
|
// Quadrant mapping for superclipping must also take into account
|
|
// the hflip, vflip bits & negative tilt to be able to work correctly
|
|
//
|
|
int modquad=quadrant;
|
|
static const int vquadflip[4]={1,0,3,2};
|
|
static const int hquadflip[4]={3,2,1,0};
|
|
|
|
if(mSPRCTL0_Vflip) modquad=vquadflip[modquad];
|
|
if(mSPRCTL0_Hflip) modquad=hquadflip[modquad];
|
|
|
|
// This is causing Eurosoccer to fail!!
|
|
//if(enable_tilt && mTILT.Val16&0x8000) modquad=hquadflip[modquad];
|
|
//if(quadrant == 0 && sprite_v == 219 && sprite_h == 890)
|
|
//printf("%d:%d %d %d\n", quadrant, modquad, sprite_h, sprite_v);
|
|
|
|
switch(modquad)
|
|
{
|
|
case 3:
|
|
if((sprite_h>=screen_h_start || sprite_h<world_h_mid) && (sprite_v<screen_v_end || sprite_v>world_v_mid)) render=TRUE;
|
|
break;
|
|
case 2:
|
|
if((sprite_h>=screen_h_start || sprite_h<world_h_mid) && (sprite_v>=screen_v_start || sprite_v<world_v_mid)) render=TRUE;
|
|
break;
|
|
case 1:
|
|
if((sprite_h<screen_h_end || sprite_h>world_h_mid) && (sprite_v>=screen_v_start || sprite_v<world_v_mid)) render=TRUE;
|
|
break;
|
|
default:
|
|
if((sprite_h<screen_h_end || sprite_h>world_h_mid) && (sprite_v<screen_v_end || sprite_v>world_v_mid)) render=TRUE;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
render=TRUE;
|
|
}
|
|
|
|
// Is this quad to be rendered ??
|
|
|
|
TRACE_SUSIE1("PaintSprites() Render status %d",render);
|
|
|
|
int pixel_height;
|
|
int pixel_width;
|
|
int pixel;
|
|
int hoff,voff;
|
|
int hloop,vloop;
|
|
bool onscreen;
|
|
|
|
if(render)
|
|
{
|
|
// Set the vertical position & offset
|
|
voff=(int16)mVPOSSTRT.Val16-screen_v_start;
|
|
|
|
// Zero the stretch,tilt & acum values
|
|
mTILTACUM.Val16=0;
|
|
|
|
// Perform the SIZOFF
|
|
if(vsign==1) mVSIZACUM.Val16=mVSIZOFF.Val16; else mVSIZACUM.Val16=0;
|
|
|
|
// Take the sign of the first quad (0) as the basic
|
|
// sign, all other quads drawing in the other direction
|
|
// get offset by 1 pixel in the other direction, this
|
|
// fixes the squashed look on the multi-quad sprites.
|
|
// if(vsign==-1 && loop>0) voff+=vsign;
|
|
if(loop==0) vquadoff=vsign;
|
|
if(vsign!=vquadoff) voff+=vsign;
|
|
|
|
for(;;)
|
|
{
|
|
// Vertical scaling is done here
|
|
mVSIZACUM.Val16+=mSPRVSIZ.Val16;
|
|
pixel_height=mVSIZACUM.Union8.High;
|
|
mVSIZACUM.Union8.High=0;
|
|
|
|
// Update the next data line pointer and initialise our line
|
|
mSPRDOFF.Val16=(uint16)LineInit(0);
|
|
|
|
// If 1 == next quad, ==0 end of sprite, anyways its END OF LINE
|
|
if(mSPRDOFF.Val16==1) // End of quad
|
|
{
|
|
mSPRDLINE.Val16+=mSPRDOFF.Val16;
|
|
break;
|
|
}
|
|
|
|
if(mSPRDOFF.Val16==0) // End of sprite
|
|
{
|
|
loop=4; // Halt the quad loop
|
|
break;
|
|
}
|
|
|
|
// Draw one horizontal line of the sprite
|
|
for(vloop=0;vloop<pixel_height;vloop++)
|
|
{
|
|
// Early bailout if the sprite has moved off screen, terminate quad
|
|
if(vsign==1 && voff>=SCREEN_HEIGHT) break;
|
|
if(vsign==-1 && voff<0) break;
|
|
|
|
// Only allow the draw to take place if the line is visible
|
|
if(voff>=0 && voff<SCREEN_HEIGHT)
|
|
{
|
|
// Work out the horizontal pixel start position, start + tilt
|
|
mHPOSSTRT.Val16+=((int16)mTILTACUM.Val16>>8);
|
|
mTILTACUM.Union8.High=0;
|
|
hoff=(int)((int16)mHPOSSTRT.Val16)-screen_h_start;
|
|
|
|
// Zero/Force the horizontal scaling accumulator
|
|
if(hsign==1) mHSIZACUM.Val16=mHSIZOFF.Val16; else mHSIZACUM.Val16=0;
|
|
|
|
// Take the sign of the first quad (0) as the basic
|
|
// sign, all other quads drawing in the other direction
|
|
// get offset by 1 pixel in the other direction, this
|
|
// fixes the squashed look on the multi-quad sprites.
|
|
// if(hsign==-1 && loop>0) hoff+=hsign;
|
|
if(loop==0) hquadoff=hsign;
|
|
if(hsign!=hquadoff) hoff+=hsign;
|
|
|
|
// Initialise our line
|
|
LineInit(voff);
|
|
onscreen=FALSE;
|
|
|
|
// Now render an individual destination line
|
|
while((pixel=LineGetPixel())!=LINE_END)
|
|
{
|
|
// This is allowed to update every pixel
|
|
mHSIZACUM.Val16+=mSPRHSIZ.Val16;
|
|
pixel_width=mHSIZACUM.Union8.High;
|
|
mHSIZACUM.Union8.High=0;
|
|
|
|
for(hloop=0;hloop<pixel_width;hloop++)
|
|
{
|
|
// Draw if onscreen but break loop on transition to offscreen
|
|
if(hoff>=0 && hoff<SCREEN_WIDTH)
|
|
{
|
|
ProcessPixel(hoff,pixel);
|
|
onscreen = TRUE;
|
|
everonscreen = TRUE;
|
|
}
|
|
else
|
|
{
|
|
if(onscreen) break;
|
|
}
|
|
hoff+=hsign;
|
|
}
|
|
}
|
|
}
|
|
voff+=vsign;
|
|
|
|
// For every destination line we can modify SPRHSIZ & SPRVSIZ & TILTACUM
|
|
if(enable_stretch)
|
|
{
|
|
mSPRHSIZ.Val16+=mSTRETCH.Val16;
|
|
// if(mSPRSYS_VStretch) mSPRVSIZ.Val16+=mSTRETCH.Val16;
|
|
}
|
|
if(enable_tilt)
|
|
{
|
|
// Manipulate the tilt stuff
|
|
mTILTACUM.Val16+=mTILT.Val16;
|
|
}
|
|
}
|
|
// According to the docs this increments per dest line
|
|
// but only gets set when the source line is read
|
|
if(mSPRSYS_VStretch) mSPRVSIZ.Val16+=mSTRETCH.Val16*pixel_height;
|
|
|
|
// Update the line start for our next run thru the loop
|
|
mSPRDLINE.Val16+=mSPRDOFF.Val16;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Skip thru data to next quad
|
|
for(;;)
|
|
{
|
|
// Read the start of line offset
|
|
|
|
mSPRDOFF.Val16=(uint16)LineInit(0);
|
|
|
|
// We dont want to process data so mSPRDLINE is useless to us
|
|
mSPRDLINE.Val16+=mSPRDOFF.Val16;
|
|
|
|
// If 1 == next quad, ==0 end of sprite, anyways its END OF LINE
|
|
|
|
if(mSPRDOFF.Val16==1) break; // End of quad
|
|
if(mSPRDOFF.Val16==0) // End of sprite
|
|
{
|
|
loop=4; // Halt the quad loop
|
|
break;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
// Increment quadrant and mask to 2 bit value (0-3)
|
|
quadrant++;
|
|
quadrant&=0x03;
|
|
}
|
|
|
|
// Write the collision depositary if required
|
|
|
|
if(!mSPRCOLL_Collide && !mSPRSYS_NoCollide)
|
|
{
|
|
switch(mSPRCTL0_Type)
|
|
{
|
|
case sprite_xor_shadow:
|
|
case sprite_boundary:
|
|
case sprite_normal:
|
|
case sprite_boundary_shadow:
|
|
case sprite_shadow:
|
|
{
|
|
uint16 coldep=mSCBADR.Val16+mCOLLOFF.Val16;
|
|
RAM_POKE(coldep,(uint8)mCollision);
|
|
TRACE_SUSIE2("PaintSprites() COLLOFF=$%04x SCBADR=$%04x",mCOLLOFF.Val16,mSCBADR.Val16);
|
|
TRACE_SUSIE2("PaintSprites() Wrote $%02x to SCB collision depositary at $%04x",(uint8)mCollision,coldep);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(mEVERON)
|
|
{
|
|
uint16 coldep=mSCBADR.Val16+mCOLLOFF.Val16;
|
|
uint8 coldat=RAM_PEEK(coldep);
|
|
if(!everonscreen) coldat|=0x80; else coldat&=0x7f;
|
|
RAM_POKE(coldep,coldat);
|
|
TRACE_SUSIE0("PaintSprites() EVERON IS ACTIVE");
|
|
TRACE_SUSIE2("PaintSprites() Wrote $%02x to SCB collision depositary at $%04x",coldat,coldep);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TRACE_SUSIE0("PaintSprites() mSPRCTL1.Bits.SkipSprite==TRUE");
|
|
}
|
|
|
|
// Increase sprite number
|
|
sprcount++;
|
|
|
|
// Check if we abort after 1st sprite is complete
|
|
|
|
// if(mSPRSYS.Read.StopOnCurrent)
|
|
// {
|
|
// mSPRSYS.Read.Status=0; // Engine has finished
|
|
// mSPRGO=FALSE;
|
|
// break;
|
|
// }
|
|
|
|
// Check sprcount for looping SCB, random large number chosen
|
|
if(sprcount>4096)
|
|
{
|
|
// Stop the system, otherwise we may just come straight back in.....
|
|
mSystem.gSystemHalt=TRUE;
|
|
// Display warning message
|
|
//gError->Warning("CSusie:PaintSprites(): Single draw sprite limit exceeded (>4096). The SCB is most likely looped back on itself. Reset/Exit is recommended");
|
|
// Signal error to the caller
|
|
return 0;
|
|
}
|
|
}
|
|
while(1);
|
|
|
|
// Fudge factor to fix many flickering issues, also the keypress
|
|
// problem with Hard Drivin and the strange pause in Dirty Larry.
|
|
//cycles_used>>=2;
|
|
return cycles_used;
|
|
}
|
|
|
|
|
|
INLINE void CSusie::WritePixel(uint32 hoff,uint32 pixel)
|
|
{
|
|
uint32 scr_addr=mLineBaseAddress+(hoff/2);
|
|
|
|
uint8 dest=RAM_PEEK(scr_addr);
|
|
if(!(hoff&0x01))
|
|
{
|
|
// Upper nibble screen write
|
|
dest&=0x0f;
|
|
dest|=pixel<<4;
|
|
}
|
|
else
|
|
{
|
|
// Lower nibble screen write
|
|
dest&=0xf0;
|
|
dest|=pixel;
|
|
}
|
|
RAM_POKE(scr_addr,dest);
|
|
|
|
// Increment cycle count for the read/modify/write
|
|
cycles_used+=2*SPR_RDWR_CYC;
|
|
}
|
|
|
|
INLINE uint32 CSusie::ReadPixel(uint32 hoff)
|
|
{
|
|
uint32 scr_addr=mLineBaseAddress+(hoff/2);
|
|
|
|
uint32 data=RAM_PEEK(scr_addr);
|
|
if(!(hoff&0x01))
|
|
{
|
|
// Upper nibble read
|
|
data>>=4;
|
|
}
|
|
else
|
|
{
|
|
// Lower nibble read
|
|
data&=0x0f;
|
|
}
|
|
|
|
// Increment cycle count for the read/modify/write
|
|
cycles_used+=SPR_RDWR_CYC;
|
|
|
|
return data;
|
|
}
|
|
|
|
INLINE void CSusie::WriteCollision(uint32 hoff,uint32 pixel)
|
|
{
|
|
uint32 col_addr=mLineCollisionAddress+(hoff/2);
|
|
|
|
uint8 dest=RAM_PEEK(col_addr);
|
|
if(!(hoff&0x01))
|
|
{
|
|
// Upper nibble screen write
|
|
dest&=0x0f;
|
|
dest|=pixel<<4;
|
|
}
|
|
else
|
|
{
|
|
// Lower nibble screen write
|
|
dest&=0xf0;
|
|
dest|=pixel;
|
|
}
|
|
RAM_POKE(col_addr,dest);
|
|
|
|
// Increment cycle count for the read/modify/write
|
|
cycles_used+=2*SPR_RDWR_CYC;
|
|
}
|
|
|
|
INLINE uint32 CSusie::ReadCollision(uint32 hoff)
|
|
{
|
|
uint32 col_addr=mLineCollisionAddress+(hoff/2);
|
|
|
|
uint32 data=RAM_PEEK(col_addr);
|
|
if(!(hoff&0x01))
|
|
{
|
|
// Upper nibble read
|
|
data>>=4;
|
|
}
|
|
else
|
|
{
|
|
// Lower nibble read
|
|
data&=0x0f;
|
|
}
|
|
|
|
// Increment cycle count for the read/modify/write
|
|
cycles_used+=SPR_RDWR_CYC;
|
|
|
|
return data;
|
|
}
|
|
|
|
|
|
INLINE uint32 CSusie::LineGetBits(uint32 bits)
|
|
{
|
|
uint32 retval;
|
|
|
|
// Sanity, not really needed
|
|
// if(bits>32) return 0;
|
|
|
|
// Only return data IF there is enought bits left in the packet
|
|
|
|
//if(mLinePacketBitsLeft<bits) return 0;
|
|
if(mLinePacketBitsLeft<=bits) return 0; // Hardware bug(<= instead of <), apparently
|
|
|
|
// Make sure shift reg has enough bits to fulfil the request
|
|
|
|
if(mLineShiftRegCount<bits)
|
|
{
|
|
// This assumes data comes into LSB and out of MSB
|
|
// mLineShiftReg&=0x000000ff; // Has no effect
|
|
mLineShiftReg<<=24;
|
|
mLineShiftReg|=RAM_PEEK(mTMPADR.Val16++)<<16;
|
|
mLineShiftReg|=RAM_PEEK(mTMPADR.Val16++)<<8;
|
|
mLineShiftReg|=RAM_PEEK(mTMPADR.Val16++);
|
|
|
|
mLineShiftRegCount+=24;
|
|
|
|
// Increment cycle count for the read
|
|
cycles_used+=3*SPR_RDWR_CYC;
|
|
}
|
|
|
|
// Extract the return value
|
|
retval=mLineShiftReg>>(mLineShiftRegCount-bits);
|
|
retval&=(1<<bits)-1;
|
|
|
|
// Update internal vars;
|
|
mLineShiftRegCount-=bits;
|
|
mLinePacketBitsLeft-=bits;
|
|
|
|
return retval;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Collision code modified by KW 22/11/98
|
|
// Collision buffer cler added if there is no
|
|
// apparent collision, I have a gut feeling this
|
|
// is the wrong solution to the inv07.com bug but
|
|
// it seems to work OK.
|
|
//
|
|
// Shadow-------------------------------|
|
|
// Boundary-Shadow--------------------| |
|
|
// Normal---------------------------| | |
|
|
// Boundary-----------------------| | | |
|
|
// Background-Shadow------------| | | | |
|
|
// Background-No Collision----| | | | | |
|
|
// Non-Collideable----------| | | | | | |
|
|
// Exclusive-or-Shadow----| | | | | | | |
|
|
// | | | | | | | |
|
|
// 1 1 1 1 0 1 0 1 F is opaque
|
|
// 0 0 0 0 1 1 0 0 E is collideable
|
|
// 0 0 1 1 0 0 0 0 0 is opaque and collideable
|
|
// 1 0 0 0 1 1 1 1 allow collision detect
|
|
// 1 0 0 1 1 1 1 1 allow coll. buffer access
|
|
// 1 0 0 0 0 0 0 0 exclusive-or the data
|
|
//
|
|
|
|
//inline
|
|
void CSusie::ProcessPixel(uint32 hoff,uint32 pixel)
|
|
{
|
|
switch(mSPRCTL0_Type)
|
|
{
|
|
// BACKGROUND SHADOW
|
|
// 1 F is opaque
|
|
// 0 E is collideable
|
|
// 1 0 is opaque and collideable
|
|
// 0 allow collision detect
|
|
// 1 allow coll. buffer access
|
|
// 0 exclusive-or the data
|
|
case sprite_background_shadow:
|
|
WritePixel(hoff,pixel);
|
|
if(!mSPRCOLL_Collide && !mSPRSYS_NoCollide && pixel!=0x0e)
|
|
{
|
|
WriteCollision(hoff,mSPRCOLL_Number);
|
|
}
|
|
break;
|
|
|
|
// BACKGROUND NOCOLLIDE
|
|
// 1 F is opaque
|
|
// 0 E is collideable
|
|
// 1 0 is opaque and collideable
|
|
// 0 allow collision detect
|
|
// 0 allow coll. buffer access
|
|
// 0 exclusive-or the data
|
|
case sprite_background_noncollide:
|
|
WritePixel(hoff,pixel);
|
|
break;
|
|
|
|
// NOCOLLIDE
|
|
// 1 F is opaque
|
|
// 0 E is collideable
|
|
// 0 0 is opaque and collideable
|
|
// 0 allow collision detect
|
|
// 0 allow coll. buffer access
|
|
// 0 exclusive-or the data
|
|
case sprite_noncollide:
|
|
if(pixel!=0x00) WritePixel(hoff,pixel);
|
|
break;
|
|
|
|
// BOUNDARY
|
|
// 0 F is opaque
|
|
// 1 E is collideable
|
|
// 0 0 is opaque and collideable
|
|
// 1 allow collision detect
|
|
// 1 allow coll. buffer access
|
|
// 0 exclusive-or the data
|
|
case sprite_boundary:
|
|
if(pixel!=0x00 && pixel!=0x0f)
|
|
{
|
|
WritePixel(hoff,pixel);
|
|
}
|
|
if(pixel!=0x00)
|
|
{
|
|
if(!mSPRCOLL_Collide && !mSPRSYS_NoCollide)
|
|
{
|
|
int collision=ReadCollision(hoff);
|
|
if(collision>mCollision)
|
|
{
|
|
mCollision=collision;
|
|
}
|
|
// 01/05/00 V0.7 if(mSPRCOLL_Number>collision)
|
|
{
|
|
WriteCollision(hoff,mSPRCOLL_Number);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
// NORMAL
|
|
// 1 F is opaque
|
|
// 1 E is collideable
|
|
// 0 0 is opaque and collideable
|
|
// 1 allow collision detect
|
|
// 1 allow coll. buffer access
|
|
// 0 exclusive-or the data
|
|
case sprite_normal:
|
|
if(pixel!=0x00)
|
|
{
|
|
WritePixel(hoff,pixel);
|
|
if(!mSPRCOLL_Collide && !mSPRSYS_NoCollide)
|
|
{
|
|
int collision=ReadCollision(hoff);
|
|
if(collision>mCollision)
|
|
{
|
|
mCollision=collision;
|
|
}
|
|
// 01/05/00 V0.7 if(mSPRCOLL_Number>collision)
|
|
{
|
|
WriteCollision(hoff,mSPRCOLL_Number);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
// BOUNDARY_SHADOW
|
|
// 0 F is opaque
|
|
// 0 E is collideable
|
|
// 0 0 is opaque and collideable
|
|
// 1 allow collision detect
|
|
// 1 allow coll. buffer access
|
|
// 0 exclusive-or the data
|
|
case sprite_boundary_shadow:
|
|
if(pixel!=0x00 && pixel!=0x0e && pixel!=0x0f)
|
|
{
|
|
WritePixel(hoff,pixel);
|
|
}
|
|
if(pixel!=0x00 && pixel!=0x0e)
|
|
{
|
|
if(!mSPRCOLL_Collide && !mSPRSYS_NoCollide)
|
|
{
|
|
int collision=ReadCollision(hoff);
|
|
if(collision>mCollision)
|
|
{
|
|
mCollision=collision;
|
|
}
|
|
// 01/05/00 V0.7 if(mSPRCOLL_Number>collision)
|
|
{
|
|
WriteCollision(hoff,mSPRCOLL_Number);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
// SHADOW
|
|
// 1 F is opaque
|
|
// 0 E is collideable
|
|
// 0 0 is opaque and collideable
|
|
// 1 allow collision detect
|
|
// 1 allow coll. buffer access
|
|
// 0 exclusive-or the data
|
|
case sprite_shadow:
|
|
if(pixel!=0x00)
|
|
{
|
|
WritePixel(hoff,pixel);
|
|
}
|
|
if(pixel!=0x00 && pixel!=0x0e)
|
|
{
|
|
if(!mSPRCOLL_Collide && !mSPRSYS_NoCollide)
|
|
{
|
|
int collision=ReadCollision(hoff);
|
|
if(collision>mCollision)
|
|
{
|
|
mCollision=collision;
|
|
}
|
|
// 01/05/00 V0.7 if(mSPRCOLL_Number>collision)
|
|
{
|
|
WriteCollision(hoff,mSPRCOLL_Number);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
// XOR SHADOW
|
|
// 1 F is opaque
|
|
// 0 E is collideable
|
|
// 0 0 is opaque and collideable
|
|
// 1 allow collision detect
|
|
// 1 allow coll. buffer access
|
|
// 1 exclusive-or the data
|
|
case sprite_xor_shadow:
|
|
if(pixel!=0x00)
|
|
{
|
|
WritePixel(hoff,ReadPixel(hoff)^pixel);
|
|
}
|
|
if(pixel!=0x00 && pixel!=0x0e)
|
|
{
|
|
if(!mSPRCOLL_Collide && !mSPRSYS_NoCollide && pixel!=0x0e)
|
|
{
|
|
int collision=ReadCollision(hoff);
|
|
if(collision>mCollision)
|
|
{
|
|
mCollision=collision;
|
|
}
|
|
// 01/05/00 V0.7 if(mSPRCOLL_Number>collision)
|
|
{
|
|
WriteCollision(hoff,mSPRCOLL_Number);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
// _asm int 3;
|
|
break;
|
|
}
|
|
}
|
|
|
|
uint32 CSusie::LineInit(uint32 voff)
|
|
{
|
|
// TRACE_SUSIE0("LineInit()");
|
|
|
|
mLineShiftReg=0;
|
|
mLineShiftRegCount=0;
|
|
mLineRepeatCount=0;
|
|
mLinePixel=0;
|
|
mLineType=line_error;
|
|
mLinePacketBitsLeft=0xffff;
|
|
|
|
// Initialise the temporary pointer
|
|
|
|
mTMPADR=mSPRDLINE;
|
|
|
|
// First read the Offset to the next line
|
|
|
|
uint32 offset=LineGetBits(8);
|
|
// TRACE_SUSIE1("LineInit() Offset=%04x",offset);
|
|
|
|
// Specify the MAXIMUM number of bits in this packet, it
|
|
// can terminate early but can never use more than this
|
|
// without ending the current packet, we count down in LineGetBits()
|
|
|
|
mLinePacketBitsLeft=(offset-1)*8;
|
|
|
|
// Literals are a special case and get their count set on a line basis
|
|
|
|
if(mSPRCTL1_Literal)
|
|
{
|
|
mLineType=line_abs_literal;
|
|
mLineRepeatCount=((offset-1)*8)/mSPRCTL0_PixelBits;
|
|
// Why is this necessary, is this compensating for the 1,1 offset bug
|
|
// mLineRepeatCount--;
|
|
}
|
|
// TRACE_SUSIE1("LineInit() mLineRepeatCount=$%04x",mLineRepeatCount);
|
|
|
|
// Set the line base address for use in the calls to pixel painting
|
|
|
|
if(voff>101)
|
|
{
|
|
//gError->Warning("CSusie::LineInit() Out of bounds (voff)");
|
|
voff=0;
|
|
}
|
|
|
|
mLineBaseAddress=mVIDBAS.Val16+(voff*(SCREEN_WIDTH/2));
|
|
mLineCollisionAddress=mCOLLBAS.Val16+(voff*(SCREEN_WIDTH/2));
|
|
// TRACE_SUSIE1("LineInit() mLineBaseAddress=$%04x",mLineBaseAddress);
|
|
// TRACE_SUSIE1("LineInit() mLineCollisionAddress=$%04x",mLineCollisionAddress);
|
|
|
|
// Return the offset to the next line
|
|
|
|
return offset;
|
|
}
|
|
|
|
uint32 CSusie::LineGetPixel()
|
|
{
|
|
if(!mLineRepeatCount)
|
|
{
|
|
// Normal sprites fetch their counts on a packet basis
|
|
if(mLineType!=line_abs_literal)
|
|
{
|
|
uint32 literal=LineGetBits(1);
|
|
if(literal) mLineType=line_literal; else mLineType=line_packed;
|
|
}
|
|
|
|
// Pixel store is empty what should we do
|
|
switch(mLineType)
|
|
{
|
|
case line_abs_literal:
|
|
// This means end of line for us
|
|
mLinePixel=LINE_END;
|
|
return mLinePixel; // SPEEDUP
|
|
break;
|
|
case line_literal:
|
|
mLineRepeatCount=LineGetBits(4);
|
|
mLineRepeatCount++;
|
|
break;
|
|
case line_packed:
|
|
//
|
|
// From reading in between the lines only a packed line with
|
|
// a zero size i.e 0b00000 as a header is allowable as a packet end
|
|
//
|
|
mLineRepeatCount=LineGetBits(4);
|
|
if(!mLineRepeatCount)
|
|
{
|
|
mLinePixel=LINE_END;
|
|
}
|
|
else
|
|
{
|
|
mLinePixel=mPenIndex[LineGetBits(mSPRCTL0_PixelBits)];
|
|
}
|
|
mLineRepeatCount++;
|
|
break;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
if(mLinePixel!=LINE_END)
|
|
{
|
|
mLineRepeatCount--;
|
|
|
|
switch(mLineType)
|
|
{
|
|
case line_abs_literal:
|
|
mLinePixel=LineGetBits(mSPRCTL0_PixelBits);
|
|
// Check the special case of a zero in the last pixel
|
|
if(!mLineRepeatCount && !mLinePixel)
|
|
mLinePixel=LINE_END;
|
|
else
|
|
mLinePixel=mPenIndex[mLinePixel];
|
|
break;
|
|
case line_literal:
|
|
mLinePixel=mPenIndex[LineGetBits(mSPRCTL0_PixelBits)];
|
|
break;
|
|
case line_packed:
|
|
break;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return mLinePixel;
|
|
}
|
|
|
|
|
|
void CSusie::Poke(uint32 addr,uint8 data)
|
|
{
|
|
switch(addr&0xff)
|
|
{
|
|
case (TMPADRL&0xff):
|
|
mTMPADR.Union8.Low=data;
|
|
mTMPADR.Union8.High=0;
|
|
TRACE_SUSIE2("Poke(TMPADRL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (TMPADRH&0xff):
|
|
mTMPADR.Union8.High=data;
|
|
TRACE_SUSIE2("Poke(TMPADRH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (TILTACUML&0xff):
|
|
mTILTACUM.Union8.Low=data;
|
|
mTILTACUM.Union8.High=0;
|
|
TRACE_SUSIE2("Poke(TILTACUML,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (TILTACUMH&0xff):
|
|
mTILTACUM.Union8.High=data;
|
|
TRACE_SUSIE2("Poke(TILTACUMH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (HOFFL&0xff):
|
|
mHOFF.Union8.Low=data;
|
|
mHOFF.Union8.High=0;
|
|
TRACE_SUSIE2("Poke(HOFFL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (HOFFH&0xff):
|
|
mHOFF.Union8.High=data;
|
|
TRACE_SUSIE2("Poke(HOFFH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (VOFFL&0xff):
|
|
mVOFF.Union8.Low=data;
|
|
mVOFF.Union8.High=0;
|
|
TRACE_SUSIE2("Poke(VOFFL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (VOFFH&0xff):
|
|
mVOFF.Union8.High=data;
|
|
TRACE_SUSIE2("Poke(VOFFH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (VIDBASL&0xff):
|
|
mVIDBAS.Union8.Low=data;
|
|
mVIDBAS.Union8.High=0;
|
|
TRACE_SUSIE2("Poke(VIDBASL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (VIDBASH&0xff):
|
|
mVIDBAS.Union8.High=data;
|
|
TRACE_SUSIE2("Poke(VIDBASH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (COLLBASL&0xff):
|
|
mCOLLBAS.Union8.Low=data;
|
|
mCOLLBAS.Union8.High=0;
|
|
TRACE_SUSIE2("Poke(COLLBASL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (COLLBASH&0xff):
|
|
mCOLLBAS.Union8.High=data;
|
|
TRACE_SUSIE2("Poke(COLLBASH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (VIDADRL&0xff):
|
|
mVIDADR.Union8.Low=data;
|
|
mVIDADR.Union8.High=0;
|
|
TRACE_SUSIE2("Poke(VIDADRL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (VIDADRH&0xff):
|
|
mVIDADR.Union8.High=data;
|
|
TRACE_SUSIE2("Poke(VIDADRH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (COLLADRL&0xff):
|
|
mCOLLADR.Union8.Low=data;
|
|
mCOLLADR.Union8.High=0;
|
|
TRACE_SUSIE2("Poke(COLLADRL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (COLLADRH&0xff):
|
|
mCOLLADR.Union8.High=data;
|
|
TRACE_SUSIE2("Poke(COLLADRH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (SCBNEXTL&0xff):
|
|
mSCBNEXT.Union8.Low=data;
|
|
mSCBNEXT.Union8.High=0;
|
|
TRACE_SUSIE2("Poke(SCBNEXTL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (SCBNEXTH&0xff):
|
|
mSCBNEXT.Union8.High=data;
|
|
TRACE_SUSIE2("Poke(SCBNEXTH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (SPRDLINEL&0xff):
|
|
mSPRDLINE.Union8.Low=data;
|
|
mSPRDLINE.Union8.High=0;
|
|
TRACE_SUSIE2("Poke(SPRDLINEL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (SPRDLINEH&0xff):
|
|
mSPRDLINE.Union8.High=data;
|
|
TRACE_SUSIE2("Poke(SPRDLINEH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (HPOSSTRTL&0xff):
|
|
mHPOSSTRT.Union8.Low=data;
|
|
mHPOSSTRT.Union8.High=0;
|
|
TRACE_SUSIE2("Poke(HPOSSTRTL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (HPOSSTRTH&0xff):
|
|
mHPOSSTRT.Union8.High=data;
|
|
TRACE_SUSIE2("Poke(HPOSSTRTH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (VPOSSTRTL&0xff):
|
|
mVPOSSTRT.Union8.Low=data;
|
|
mVPOSSTRT.Union8.High=0;
|
|
TRACE_SUSIE2("Poke(VPOSSTRTL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (VPOSSTRTH&0xff):
|
|
mVPOSSTRT.Union8.High=data;
|
|
TRACE_SUSIE2("Poke(VPOSSTRTH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (SPRHSIZL&0xff):
|
|
mSPRHSIZ.Union8.Low=data;
|
|
mSPRHSIZ.Union8.High=0;
|
|
TRACE_SUSIE2("Poke(SPRHSIZL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (SPRHSIZH&0xff):
|
|
mSPRHSIZ.Union8.High=data;
|
|
TRACE_SUSIE2("Poke(SPRHSIZH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (SPRVSIZL&0xff):
|
|
mSPRVSIZ.Union8.Low=data;
|
|
mSPRVSIZ.Union8.High=0;
|
|
TRACE_SUSIE2("Poke(SPRVSIZL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (SPRVSIZH&0xff):
|
|
mSPRVSIZ.Union8.High=data;
|
|
TRACE_SUSIE2("Poke(SPRVSIZH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (STRETCHL&0xff):
|
|
mSTRETCH.Union8.Low=data;
|
|
mSTRETCH.Union8.High=0;
|
|
TRACE_SUSIE2("Poke(STRETCHL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (STRETCHH&0xff):
|
|
TRACE_SUSIE2("Poke(STRETCHH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
mSTRETCH.Union8.High=data;
|
|
break;
|
|
case (TILTL&0xff):
|
|
mTILT.Union8.Low=data;
|
|
mTILT.Union8.High=0;
|
|
TRACE_SUSIE2("Poke(TILTL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (TILTH&0xff):
|
|
mTILT.Union8.High=data;
|
|
TRACE_SUSIE2("Poke(TILTH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (SPRDOFFL&0xff):
|
|
TRACE_SUSIE2("Poke(SPRDOFFL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
mSPRDOFF.Union8.Low=data;
|
|
mSPRDOFF.Union8.High=0;
|
|
break;
|
|
case (SPRDOFFH&0xff):
|
|
TRACE_SUSIE2("Poke(SPRDOFFH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
mSPRDOFF.Union8.High=data;
|
|
break;
|
|
case (SPRVPOSL&0xff):
|
|
TRACE_SUSIE2("Poke(SPRVPOSL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
mSPRVPOS.Union8.Low=data;
|
|
mSPRVPOS.Union8.High=0;
|
|
break;
|
|
case (SPRVPOSH&0xff):
|
|
mSPRVPOS.Union8.High=data;
|
|
TRACE_SUSIE2("Poke(SPRVPOSH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (COLLOFFL&0xff):
|
|
mCOLLOFF.Union8.Low=data;
|
|
mCOLLOFF.Union8.High=0;
|
|
TRACE_SUSIE2("Poke(COLLOFFL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (COLLOFFH&0xff):
|
|
mCOLLOFF.Union8.High=data;
|
|
TRACE_SUSIE2("Poke(COLLOFFH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (VSIZACUML&0xff):
|
|
mVSIZACUM.Union8.Low=data;
|
|
mVSIZACUM.Union8.High=0;
|
|
TRACE_SUSIE2("Poke(VSIZACUML,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (VSIZACUMH&0xff):
|
|
mVSIZACUM.Union8.High=data;
|
|
TRACE_SUSIE2("Poke(VSIZACUMH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (HSIZOFFL&0xff):
|
|
mHSIZOFF.Union8.Low=data;
|
|
mHSIZOFF.Union8.High=0;
|
|
TRACE_SUSIE2("Poke(HSIZOFFL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (HSIZOFFH&0xff):
|
|
mHSIZOFF.Union8.High=data;
|
|
TRACE_SUSIE2("Poke(HSIZOFFH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (VSIZOFFL&0xff):
|
|
mVSIZOFF.Union8.Low=data;
|
|
mVSIZOFF.Union8.High=0;
|
|
TRACE_SUSIE2("Poke(VSIZOFFL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (VSIZOFFH&0xff):
|
|
mVSIZOFF.Union8.High=data;
|
|
TRACE_SUSIE2("Poke(VSIZOFFH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (SCBADRL&0xff):
|
|
mSCBADR.Union8.Low=data;
|
|
mSCBADR.Union8.High=0;
|
|
TRACE_SUSIE2("Poke(SCBADRL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (SCBADRH&0xff):
|
|
mSCBADR.Union8.High=data;
|
|
TRACE_SUSIE2("Poke(SCBADRH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (PROCADRL&0xff):
|
|
mPROCADR.Union8.Low=data;
|
|
mPROCADR.Union8.High=0;
|
|
TRACE_SUSIE2("Poke(PROCADRL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (PROCADRH&0xff):
|
|
mPROCADR.Union8.High=data;
|
|
TRACE_SUSIE2("Poke(PROCADRH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
|
|
case (MATHD&0xff):
|
|
TRACE_SUSIE2("Poke(MATHD,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
mMATHABCD.Bytes.D=data;
|
|
// mMATHABCD.Bytes.C=0;
|
|
// The hardware manual says that the sign shouldnt change
|
|
// but if I dont do this then stun runner will hang as it
|
|
// does the init in the wrong order and if the previous
|
|
// calc left a zero there then we'll get a sign error
|
|
Poke(MATHC,0);
|
|
break;
|
|
case (MATHC&0xff):
|
|
TRACE_SUSIE2("Poke(MATHC,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
mMATHABCD.Bytes.C=data;
|
|
// Perform sign conversion if required
|
|
if(mSPRSYS_SignedMath)
|
|
{
|
|
// Account for the math bug that 0x8000 is +ve & 0x0000 is -ve by subracting 1
|
|
if((mMATHABCD.Words.CD-1)&0x8000)
|
|
{
|
|
uint16 conv;
|
|
conv=mMATHABCD.Words.CD^0xffff;
|
|
conv++;
|
|
mMATHCD_sign=-1;
|
|
TRACE_SUSIE2("MATH CD signed conversion complete %04x to %04x",mMATHABCD.Words.CD,conv);
|
|
mMATHABCD.Words.CD=conv;
|
|
}
|
|
else
|
|
{
|
|
mMATHCD_sign=1;
|
|
}
|
|
}
|
|
break;
|
|
case (MATHB&0xff):
|
|
TRACE_SUSIE2("Poke(MATHB,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
mMATHABCD.Bytes.B=data;
|
|
mMATHABCD.Bytes.A=0;
|
|
break;
|
|
case (MATHA&0xff):
|
|
TRACE_SUSIE2("Poke(MATHA,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
mMATHABCD.Bytes.A=data;
|
|
// Perform sign conversion if required
|
|
if(mSPRSYS_SignedMath)
|
|
{
|
|
// Account for the math bug that 0x8000 is +ve & 0x0000 is -ve by subracting 1
|
|
if((mMATHABCD.Words.AB-1)&0x8000)
|
|
{
|
|
uint16 conv;
|
|
conv=mMATHABCD.Words.AB^0xffff;
|
|
conv++;
|
|
mMATHAB_sign=-1;
|
|
TRACE_SUSIE2("MATH AB signed conversion complete %04x to %04x",mMATHABCD.Words.AB,conv);
|
|
mMATHABCD.Words.AB=conv;
|
|
}
|
|
else
|
|
{
|
|
mMATHAB_sign=1;
|
|
}
|
|
}
|
|
DoMathMultiply();
|
|
break;
|
|
|
|
case (MATHP&0xff):
|
|
mMATHNP.Bytes.P=data;
|
|
mMATHNP.Bytes.N=0;
|
|
TRACE_SUSIE2("Poke(MATHP,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (MATHN&0xff):
|
|
mMATHNP.Bytes.N=data;
|
|
TRACE_SUSIE2("Poke(MATHN,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
|
|
case (MATHH&0xff):
|
|
mMATHEFGH.Bytes.H=data;
|
|
mMATHEFGH.Bytes.G=0;
|
|
TRACE_SUSIE2("Poke(MATHH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (MATHG&0xff):
|
|
mMATHEFGH.Bytes.G=data;
|
|
TRACE_SUSIE2("Poke(MATHG,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (MATHF&0xff):
|
|
mMATHEFGH.Bytes.F=data;
|
|
mMATHEFGH.Bytes.E=0;
|
|
TRACE_SUSIE2("Poke(MATHF,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (MATHE&0xff):
|
|
mMATHEFGH.Bytes.E=data;
|
|
TRACE_SUSIE2("Poke(MATHE,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
DoMathDivide();
|
|
break;
|
|
|
|
case (MATHM&0xff):
|
|
mMATHJKLM.Bytes.M=data;
|
|
mMATHJKLM.Bytes.L=0;
|
|
mSPRSYS_Mathbit=FALSE;
|
|
TRACE_SUSIE2("Poke(MATHM,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (MATHL&0xff):
|
|
mMATHJKLM.Bytes.L=data;
|
|
TRACE_SUSIE2("Poke(MATHL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (MATHK&0xff):
|
|
mMATHJKLM.Bytes.K=data;
|
|
mMATHJKLM.Bytes.J=0;
|
|
TRACE_SUSIE2("Poke(MATHK,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (MATHJ&0xff):
|
|
mMATHJKLM.Bytes.J=data;
|
|
TRACE_SUSIE2("Poke(MATHJ,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
|
|
case (SPRCTL0&0xff):
|
|
mSPRCTL0_Type=data&0x0007;
|
|
mSPRCTL0_Vflip=data&0x0010;
|
|
mSPRCTL0_Hflip=data&0x0020;
|
|
mSPRCTL0_PixelBits=((data&0x00c0)>>6)+1;
|
|
TRACE_SUSIE2("Poke(SPRCTL0,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (SPRCTL1&0xff):
|
|
mSPRCTL1_StartLeft=data&0x0001;
|
|
mSPRCTL1_StartUp=data&0x0002;
|
|
mSPRCTL1_SkipSprite=data&0x0004;
|
|
mSPRCTL1_ReloadPalette=data&0x0008;
|
|
mSPRCTL1_ReloadDepth=(data&0x0030)>>4;
|
|
mSPRCTL1_Sizing=data&0x0040;
|
|
mSPRCTL1_Literal=data&0x0080;
|
|
TRACE_SUSIE2("Poke(SPRCTL1,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (SPRCOLL&0xff):
|
|
mSPRCOLL_Number=data&0x000f;
|
|
mSPRCOLL_Collide=data&0x0020;
|
|
TRACE_SUSIE2("Poke(SPRCOLL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (SPRINIT&0xff):
|
|
mSPRINIT.Byte=data;
|
|
TRACE_SUSIE2("Poke(SPRINIT,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (SUZYBUSEN&0xff):
|
|
mSUZYBUSEN=data&0x01;
|
|
TRACE_SUSIE2("Poke(SUZYBUSEN,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (SPRGO&0xff):
|
|
mSPRGO=data&0x01;
|
|
mEVERON=data&0x04;
|
|
TRACE_SUSIE2("Poke(SPRGO,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (SPRSYS&0xff):
|
|
mSPRSYS_StopOnCurrent=data&0x0002;
|
|
if(data&0x0004) mSPRSYS_UnsafeAccess=0;
|
|
mSPRSYS_LeftHand=data&0x0008;
|
|
mSPRSYS_VStretch=data&0x0010;
|
|
mSPRSYS_NoCollide=data&0x0020;
|
|
mSPRSYS_Accumulate=data&0x0040;
|
|
mSPRSYS_SignedMath=data&0x0080;
|
|
TRACE_SUSIE2("Poke(SPRSYS,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
|
|
// Cartridge writing ports
|
|
|
|
case (RCART0&0xff):
|
|
mSystem.Poke_CARTB0(data);
|
|
TRACE_SUSIE2("Poke(RCART0,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
case (RCART1&0xff):
|
|
mSystem.Poke_CARTB1(data);
|
|
TRACE_SUSIE2("Poke(RCART1,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
|
|
// These are not so important, so lets ignore them for the moment
|
|
|
|
case (LEDS&0xff):
|
|
case (PPORTSTAT&0xff):
|
|
case (PPORTDATA&0xff):
|
|
case (HOWIE&0xff):
|
|
TRACE_SUSIE2("Poke(LEDS/PPORTSTST/PPORTDATA/HOWIE,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
|
|
break;
|
|
|
|
// Errors on read only register accesses
|
|
|
|
case (SUZYHREV&0xff):
|
|
case (JOYSTICK&0xff):
|
|
case (SWITCHES&0xff):
|
|
TRACE_SUSIE3("Poke(%04x,%02x) - Poke to read only register location at PC=%04x",addr,data,mSystem.mCpu->GetPC());
|
|
break;
|
|
|
|
// Errors on illegal location accesses
|
|
|
|
default:
|
|
TRACE_SUSIE3("Poke(%04x,%02x) - Poke to illegal location at PC=%04x",addr,data,mSystem.mCpu->GetPC());
|
|
break;
|
|
}
|
|
}
|
|
|
|
uint8 CSusie::Peek(uint32 addr)
|
|
{
|
|
uint8 retval=0;
|
|
|
|
switch(addr&0xff)
|
|
{
|
|
case (TMPADRL&0xff):
|
|
retval=mTMPADR.Union8.Low;
|
|
TRACE_SUSIE2("Peek(TMPADRL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (TMPADRH&0xff):
|
|
retval=mTMPADR.Union8.High;
|
|
TRACE_SUSIE2("Peek(TMPADRH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (TILTACUML&0xff):
|
|
retval=mTILTACUM.Union8.Low;
|
|
TRACE_SUSIE2("Peek(TILTACUML)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (TILTACUMH&0xff):
|
|
retval=mTILTACUM.Union8.High;
|
|
TRACE_SUSIE2("Peek(TILTACUMH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (HOFFL&0xff):
|
|
retval=mHOFF.Union8.Low;
|
|
TRACE_SUSIE2("Peek(HOFFL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (HOFFH&0xff):
|
|
retval=mHOFF.Union8.High;
|
|
TRACE_SUSIE2("Peek(HOFFH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (VOFFL&0xff):
|
|
retval=mVOFF.Union8.Low;
|
|
TRACE_SUSIE2("Peek(VOFFL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (VOFFH&0xff):
|
|
retval=mVOFF.Union8.High;
|
|
TRACE_SUSIE2("Peek(VOFFH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (VIDBASL&0xff):
|
|
retval=mVIDBAS.Union8.Low;
|
|
TRACE_SUSIE2("Peek(VIDBASL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (VIDBASH&0xff):
|
|
retval=mVIDBAS.Union8.High;
|
|
TRACE_SUSIE2("Peek(VIDBASH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (COLLBASL&0xff):
|
|
retval=mCOLLBAS.Union8.Low;
|
|
TRACE_SUSIE2("Peek(COLLBASL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (COLLBASH&0xff):
|
|
retval=mCOLLBAS.Union8.High;
|
|
TRACE_SUSIE2("Peek(COLLBASH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (VIDADRL&0xff):
|
|
retval=mVIDADR.Union8.Low;
|
|
TRACE_SUSIE2("Peek(VIDADRL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (VIDADRH&0xff):
|
|
retval=mVIDADR.Union8.High;
|
|
TRACE_SUSIE2("Peek(VIDADRH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (COLLADRL&0xff):
|
|
retval=mCOLLADR.Union8.Low;
|
|
TRACE_SUSIE2("Peek(COLLADRL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (COLLADRH&0xff):
|
|
retval=mCOLLADR.Union8.High;
|
|
TRACE_SUSIE2("Peek(COLLADRH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (SCBNEXTL&0xff):
|
|
retval=mSCBNEXT.Union8.Low;
|
|
TRACE_SUSIE2("Peek(SCBNEXTL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (SCBNEXTH&0xff):
|
|
retval=mSCBNEXT.Union8.High;
|
|
TRACE_SUSIE2("Peek(SCBNEXTH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (SPRDLINEL&0xff):
|
|
retval=mSPRDLINE.Union8.Low;
|
|
TRACE_SUSIE2("Peek(SPRDLINEL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (SPRDLINEH&0xff):
|
|
retval=mSPRDLINE.Union8.High;
|
|
TRACE_SUSIE2("Peek(SPRDLINEH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (HPOSSTRTL&0xff):
|
|
retval=mHPOSSTRT.Union8.Low;
|
|
TRACE_SUSIE2("Peek(HPOSSTRTL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (HPOSSTRTH&0xff):
|
|
retval=mHPOSSTRT.Union8.High;
|
|
TRACE_SUSIE2("Peek(HPOSSTRTH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (VPOSSTRTL&0xff):
|
|
retval=mVPOSSTRT.Union8.Low;
|
|
TRACE_SUSIE2("Peek(VPOSSTRTL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (VPOSSTRTH&0xff):
|
|
retval=mVPOSSTRT.Union8.High;
|
|
TRACE_SUSIE2("Peek(VPOSSTRTH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (SPRHSIZL&0xff):
|
|
retval=mSPRHSIZ.Union8.Low;
|
|
TRACE_SUSIE2("Peek(SPRHSIZL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (SPRHSIZH&0xff):
|
|
retval=mSPRHSIZ.Union8.High;
|
|
TRACE_SUSIE2("Peek(SPRHSIZH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (SPRVSIZL&0xff):
|
|
retval=mSPRVSIZ.Union8.Low;
|
|
TRACE_SUSIE2("Peek(SPRVSIZL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (SPRVSIZH&0xff):
|
|
retval=mSPRVSIZ.Union8.High;
|
|
TRACE_SUSIE2("Peek(SPRVSIZH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (STRETCHL&0xff):
|
|
retval=mSTRETCH.Union8.Low;
|
|
TRACE_SUSIE2("Peek(STRETCHL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (STRETCHH&0xff):
|
|
retval=mSTRETCH.Union8.High;
|
|
TRACE_SUSIE2("Peek(STRETCHH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (TILTL&0xff):
|
|
retval=mTILT.Union8.Low;
|
|
TRACE_SUSIE2("Peek(TILTL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (TILTH&0xff):
|
|
retval=mTILT.Union8.High;
|
|
TRACE_SUSIE2("Peek(TILTH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (SPRDOFFL&0xff):
|
|
retval=mSPRDOFF.Union8.Low;
|
|
TRACE_SUSIE2("Peek(SPRDOFFL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (SPRDOFFH&0xff):
|
|
retval=mSPRDOFF.Union8.High;
|
|
TRACE_SUSIE2("Peek(SPRDOFFH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (SPRVPOSL&0xff):
|
|
retval=mSPRVPOS.Union8.Low;
|
|
TRACE_SUSIE2("Peek(SPRVPOSL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (SPRVPOSH&0xff):
|
|
retval=mSPRVPOS.Union8.High;
|
|
TRACE_SUSIE2("Peek(SPRVPOSH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (COLLOFFL&0xff):
|
|
retval=mCOLLOFF.Union8.Low;
|
|
TRACE_SUSIE2("Peek(COLLOFFL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (COLLOFFH&0xff):
|
|
retval=mCOLLOFF.Union8.High;
|
|
TRACE_SUSIE2("Peek(COLLOFFH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (VSIZACUML&0xff):
|
|
retval=mVSIZACUM.Union8.Low;
|
|
TRACE_SUSIE2("Peek(VSIZACUML)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (VSIZACUMH&0xff):
|
|
retval=mVSIZACUM.Union8.High;
|
|
TRACE_SUSIE2("Peek(VSIZACUMH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (HSIZOFFL&0xff):
|
|
retval=mHSIZOFF.Union8.Low;
|
|
TRACE_SUSIE2("Peek(HSIZOFFL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (HSIZOFFH&0xff):
|
|
retval=mHSIZOFF.Union8.High;
|
|
TRACE_SUSIE2("Peek(HSIZOFFH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (VSIZOFFL&0xff):
|
|
retval=mVSIZOFF.Union8.Low;
|
|
TRACE_SUSIE2("Peek(VSIZOFFL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (VSIZOFFH&0xff):
|
|
retval=mVSIZOFF.Union8.High;
|
|
TRACE_SUSIE2("Peek(VSIZOFFH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (SCBADRL&0xff):
|
|
retval=mSCBADR.Union8.Low;
|
|
TRACE_SUSIE2("Peek(SCBADRL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (SCBADRH&0xff):
|
|
retval=mSCBADR.Union8.High;
|
|
TRACE_SUSIE2("Peek(SCBADRH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (PROCADRL&0xff):
|
|
retval=mPROCADR.Union8.Low;
|
|
TRACE_SUSIE2("Peek(PROCADRL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (PROCADRH&0xff):
|
|
retval=mPROCADR.Union8.High;
|
|
TRACE_SUSIE2("Peek(PROCADRH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
|
|
case (MATHD&0xff):
|
|
retval=mMATHABCD.Bytes.D;
|
|
TRACE_SUSIE2("Peek(MATHD)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (MATHC&0xff):
|
|
retval=mMATHABCD.Bytes.C;
|
|
TRACE_SUSIE2("Peek(MATHC)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (MATHB&0xff):
|
|
retval=mMATHABCD.Bytes.B;
|
|
TRACE_SUSIE2("Peek(MATHB)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (MATHA&0xff):
|
|
retval=mMATHABCD.Bytes.A;
|
|
TRACE_SUSIE2("Peek(MATHA)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
|
|
case (MATHP&0xff):
|
|
retval=mMATHNP.Bytes.P;
|
|
TRACE_SUSIE2("Peek(MATHP)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (MATHN&0xff):
|
|
retval=mMATHNP.Bytes.N;
|
|
TRACE_SUSIE2("Peek(MATHN)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
|
|
case (MATHH&0xff):
|
|
retval=mMATHEFGH.Bytes.H;
|
|
TRACE_SUSIE2("Peek(MATHH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (MATHG&0xff):
|
|
retval=mMATHEFGH.Bytes.G;
|
|
TRACE_SUSIE2("Peek(MATHG)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (MATHF&0xff):
|
|
retval=mMATHEFGH.Bytes.F;
|
|
TRACE_SUSIE2("Peek(MATHF)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (MATHE&0xff):
|
|
retval=mMATHEFGH.Bytes.E;
|
|
TRACE_SUSIE2("Peek(MATHE)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
|
|
case (MATHM&0xff):
|
|
retval=mMATHJKLM.Bytes.M;
|
|
TRACE_SUSIE2("Peek(MATHM)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (MATHL&0xff):
|
|
retval=mMATHJKLM.Bytes.L;
|
|
TRACE_SUSIE2("Peek(MATHL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (MATHK&0xff):
|
|
retval=mMATHJKLM.Bytes.K;
|
|
TRACE_SUSIE2("Peek(MATHK)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (MATHJ&0xff):
|
|
retval=mMATHJKLM.Bytes.J;
|
|
TRACE_SUSIE2("Peek(MATHJ)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
|
|
case (SUZYHREV&0xff):
|
|
retval=0x01;
|
|
TRACE_SUSIE2("Peek(SUZYHREV)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
|
|
case (SPRSYS&0xff):
|
|
retval=0x0000;
|
|
// retval+=(mSPRSYS_Status)?0x0001:0x0000;
|
|
retval+= (mSystem.gSuzieDoneTime)?0x0001:0x0000;
|
|
retval+=(mSPRSYS_StopOnCurrent)?0x0002:0x0000;
|
|
retval+=(mSPRSYS_UnsafeAccess)?0x0004:0x0000;
|
|
retval+=(mSPRSYS_LeftHand)?0x0008:0x0000;
|
|
retval+=(mSPRSYS_VStretch)?0x0010:0x0000;
|
|
retval+=(mSPRSYS_LastCarry)?0x0020:0x0000;
|
|
retval+=(mSPRSYS_Mathbit)?0x0040:0x0000;
|
|
retval+=(mSPRSYS_MathInProgress)?0x0080:0x0000;
|
|
TRACE_SUSIE2("Peek(SPRSYS)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
|
|
case (JOYSTICK&0xff):
|
|
if(mSPRSYS_LeftHand)
|
|
{
|
|
retval= mJOYSTICK.Byte;
|
|
}
|
|
else
|
|
{
|
|
TJOYSTICK Modified=mJOYSTICK;
|
|
Modified.Bits.Left=mJOYSTICK.Bits.Right;
|
|
Modified.Bits.Right=mJOYSTICK.Bits.Left;
|
|
Modified.Bits.Down=mJOYSTICK.Bits.Up;
|
|
Modified.Bits.Up=mJOYSTICK.Bits.Down;
|
|
retval= Modified.Byte;
|
|
}
|
|
// TRACE_SUSIE2("Peek(JOYSTICK)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
lagged = false;
|
|
return retval;
|
|
break;
|
|
|
|
|
|
case (SWITCHES&0xff):
|
|
retval=mSWITCHES.Byte;
|
|
// TRACE_SUSIE2("Peek(SWITCHES)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
lagged = false;
|
|
return retval;
|
|
|
|
// Cartridge reading ports
|
|
|
|
case (RCART0&0xff):
|
|
retval=mSystem.Peek_CARTB0();
|
|
// TRACE_SUSIE2("Peek(RCART0)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
case (RCART1&0xff):
|
|
retval=mSystem.Peek_CARTB1();
|
|
// TRACE_SUSIE2("Peek(RCART1)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
|
|
return retval;
|
|
break;
|
|
|
|
// These are no so important so lets ignore them for the moment
|
|
|
|
case (LEDS&0xff):
|
|
case (PPORTSTAT&0xff):
|
|
case (PPORTDATA&0xff):
|
|
case (HOWIE&0xff):
|
|
TRACE_SUSIE1("Peek(LEDS/PPORTSTAT/PPORTDATA) at PC=$%04x",mSystem.mCpu->GetPC());
|
|
break;
|
|
|
|
// Errors on write only register accesses
|
|
|
|
case (SPRCTL0&0xff):
|
|
case (SPRCTL1&0xff):
|
|
case (SPRCOLL&0xff):
|
|
case (SPRINIT&0xff):
|
|
case (SUZYBUSEN&0xff):
|
|
case (SPRGO&0xff):
|
|
TRACE_SUSIE2("Peek(%04x) - Peek from write only register location at PC=$%04x",addr,mSystem.mCpu->GetPC());
|
|
break;
|
|
|
|
// Errors on illegal location accesses
|
|
|
|
default:
|
|
TRACE_SUSIE2("Peek(%04x) - Peek from illegal location at PC=$%04x",addr,mSystem.mCpu->GetPC());
|
|
break;
|
|
}
|
|
|
|
return 0xff;
|
|
}
|
|
|
|
SYNCFUNC(CSusie)
|
|
{
|
|
NSS(lagged);
|
|
|
|
NSS(cycles_used);
|
|
|
|
NSS(mTMPADR);
|
|
NSS(mTILTACUM);
|
|
NSS(mHOFF);
|
|
NSS(mVOFF);
|
|
NSS(mVIDBAS);
|
|
NSS(mCOLLBAS);
|
|
NSS(mVIDADR);
|
|
NSS(mCOLLADR);
|
|
NSS(mSCBNEXT);
|
|
NSS(mSPRDLINE);
|
|
NSS(mHPOSSTRT);
|
|
NSS(mVPOSSTRT);
|
|
NSS(mSPRHSIZ);
|
|
NSS(mSPRVSIZ);
|
|
NSS(mSTRETCH);
|
|
NSS(mTILT);
|
|
NSS(mSPRDOFF);
|
|
NSS(mSPRVPOS);
|
|
NSS(mCOLLOFF);
|
|
NSS(mVSIZACUM);
|
|
NSS(mHSIZACUM);
|
|
NSS(mHSIZOFF);
|
|
NSS(mVSIZOFF);
|
|
NSS(mSCBADR);
|
|
NSS(mPROCADR);
|
|
|
|
|
|
NSS(mMATHABCD);
|
|
NSS(mMATHEFGH);
|
|
NSS(mMATHJKLM);
|
|
NSS(mMATHNP);
|
|
NSS(mMATHAB_sign);
|
|
NSS(mMATHCD_sign);
|
|
NSS(mMATHEFGH_sign);
|
|
|
|
NSS(mSPRCTL0_Type);
|
|
NSS(mSPRCTL0_Vflip);
|
|
NSS(mSPRCTL0_Hflip);
|
|
NSS(mSPRCTL0_PixelBits);
|
|
|
|
NSS(mSPRCTL1_StartLeft);
|
|
NSS(mSPRCTL1_StartUp);
|
|
NSS(mSPRCTL1_SkipSprite);
|
|
NSS(mSPRCTL1_ReloadPalette);
|
|
NSS(mSPRCTL1_ReloadDepth);
|
|
NSS(mSPRCTL1_Sizing);
|
|
NSS(mSPRCTL1_Literal);
|
|
|
|
NSS(mSPRCOLL_Number);
|
|
NSS(mSPRCOLL_Collide);
|
|
|
|
NSS(mSPRSYS_StopOnCurrent);
|
|
NSS(mSPRSYS_LeftHand);
|
|
NSS(mSPRSYS_VStretch);
|
|
NSS(mSPRSYS_NoCollide);
|
|
NSS(mSPRSYS_Accumulate);
|
|
NSS(mSPRSYS_SignedMath);
|
|
NSS(mSPRSYS_Status);
|
|
NSS(mSPRSYS_UnsafeAccess);
|
|
NSS(mSPRSYS_LastCarry);
|
|
NSS(mSPRSYS_Mathbit);
|
|
NSS(mSPRSYS_MathInProgress);
|
|
|
|
NSS(mSUZYBUSEN);
|
|
|
|
NSS(mSPRINIT);
|
|
|
|
NSS(mSPRGO);
|
|
NSS(mEVERON);
|
|
|
|
NSS(mPenIndex);
|
|
|
|
|
|
|
|
NSS(mLineType);
|
|
NSS(mLineShiftRegCount);
|
|
NSS(mLineShiftReg);
|
|
NSS(mLineRepeatCount);
|
|
NSS(mLinePixel);
|
|
NSS(mLinePacketBitsLeft);
|
|
|
|
NSS(mCollision);
|
|
|
|
// mRamPointer;
|
|
|
|
NSS(mLineBaseAddress);
|
|
NSS(mLineCollisionAddress);
|
|
|
|
NSS(hquadoff);
|
|
NSS(vquadoff);
|
|
|
|
|
|
|
|
NSS(mJOYSTICK);
|
|
NSS(mSWITCHES);
|
|
}
|