susie.cpp
1 // 2 // Copyright (c) 2004 K. Wilkins 3 // 4 // This software is provided 'as-is', without any express or implied warranty. 5 // In no event will the authors be held liable for any damages arising from 6 // the use of this software. 7 // 8 // Permission is granted to anyone to use this software for any purpose, 9 // including commercial applications, and to alter it and redistribute it 10 // freely, subject to the following restrictions: 11 // 12 // 1. The origin of this software must not be misrepresented; you must not 13 // claim that you wrote the original software. If you use this software 14 // in a product, an acknowledgment in the product documentation would be 15 // appreciated but is not required. 16 // 17 // 2. Altered source versions must be plainly marked as such, and must not 18 // be misrepresented as being the original software. 19 // 20 // 3. This notice may not be removed or altered from any source distribution. 21 // 22 23 ////////////////////////////////////////////////////////////////////////////// 24 // Handy - An Atari Lynx Emulator // 25 // Copyright (c) 1996,1997 // 26 // K. Wilkins // 27 ////////////////////////////////////////////////////////////////////////////// 28 // Suzy emulation class // 29 ////////////////////////////////////////////////////////////////////////////// 30 // // 31 // This class emulates the Suzy chip within the lynx. This provides math // 32 // and sprite painting facilities. SpritePaint() is called from within // 33 // the Mikey POKE functions when SPRGO is set and is called via the system // 34 // object to keep the interface clean. // 35 // // 36 // K. Wilkins // 37 // August 1997 // 38 // // 39 ////////////////////////////////////////////////////////////////////////////// 40 // Revision History: // 41 // ----------------- // 42 // // 43 // 01Aug1997 KW Document header added & class documented. // 44 // // 45 ////////////////////////////////////////////////////////////////////////////// 46 47 //#define TRACE_SUSIE 48 49 #include <stdio.h> 50 #include <stdlib.h> 51 #include <string.h> 52 #include "system.h" 53 #include "susie.h" 54 #include "lynxdef.h" 55 56 CSusie::CSusie(CSystem& parent) 57 :mSystem(parent) 58 { 59 TRACE_SUSIE0("CSusie()"); 60 Reset(); 61 } 62 63 CSusie::~CSusie() 64 { 65 TRACE_SUSIE0("~CSusie()"); 66 } 67 68 void CSusie::Reset(void) 69 { 70 TRACE_SUSIE0("Reset()"); 71 72 // Fetch pointer to system RAM, faster than object access 73 // and seeing as Susie only ever sees RAM. 74 75 mRamPointer=mSystem.GetRamPointer(); 76 77 // Reset ALL variables 78 79 mTMPADR.Word=0; 80 mTILTACUM.Word=0; 81 mHOFF.Word=0; 82 mVOFF.Word=0; 83 mVIDBAS.Word=0; 84 mCOLLBAS.Word=0; 85 mVIDADR.Word=0; 86 mCOLLADR.Word=0; 87 mSCBNEXT.Word=0; 88 mSPRDLINE.Word=0; 89 mHPOSSTRT.Word=0; 90 mVPOSSTRT.Word=0; 91 mSPRHSIZ.Word=0; 92 mSPRVSIZ.Word=0; 93 mSTRETCH.Word=0; 94 mTILT.Word=0; 95 mSPRDOFF.Word=0; 96 mSPRVPOS.Word=0; 97 mCOLLOFF.Word=0; 98 mVSIZACUM.Word=0; 99 mHSIZACUM.Word=0; 100 mHSIZOFF.Word=0x007f; 101 mVSIZOFF.Word=0x007f; 102 mSCBADR.Word=0; 103 mPROCADR.Word=0; 104 105 // Must be initialised to this due to 106 // stun runner math initialisation bug 107 // see whatsnew for 0.7 108 mMATHABCD.Long=0xffffffff; 109 mMATHEFGH.Long=0xffffffff; 110 mMATHJKLM.Long=0xffffffff; 111 mMATHNP.Long=0xffff; 112 113 mMATHAB_sign=1; 114 mMATHCD_sign=1; 115 mMATHEFGH_sign=1; 116 117 mSPRCTL0_Type=0; 118 mSPRCTL0_Vflip=0; 119 mSPRCTL0_Hflip=0; 120 mSPRCTL0_PixelBits=0; 121 122 mSPRCTL1_StartLeft=0; 123 mSPRCTL1_StartUp=0; 124 mSPRCTL1_SkipSprite=0; 125 mSPRCTL1_ReloadPalette=0; 126 mSPRCTL1_ReloadDepth=0; 127 mSPRCTL1_Sizing=0; 128 mSPRCTL1_Literal=0; 129 130 mSPRCOLL_Number=0; 131 mSPRCOLL_Collide=0; 132 133 mSPRSYS_StopOnCurrent=0; 134 mSPRSYS_LeftHand=0; 135 mSPRSYS_VStretch=0; 136 mSPRSYS_NoCollide=0; 137 mSPRSYS_Accumulate=0; 138 mSPRSYS_SignedMath=0; 139 mSPRSYS_Status=0; 140 mSPRSYS_UnsafeAccess=0; 141 mSPRSYS_LastCarry=0; 142 mSPRSYS_Mathbit=0; 143 mSPRSYS_MathInProgress=0; 144 145 mSUZYBUSEN=FALSE; 146 147 mSPRINIT.Byte=0; 148 149 mSPRGO=FALSE; 150 mEVERON=FALSE; 151 152 for(int loop=0;loop<16;loop++) mPenIndex[loop]=loop; 153 154 mJOYSTICK.Byte=0; 155 mSWITCHES.Byte=0; 156 } 157 158 bool CSusie::ContextSave(LSS_FILE *fp) 159 { 160 TRACE_SUSIE0("ContextSave()"); 161 162 if(!lss_printf(fp,"CSusie::ContextSave")) return 0; 163 164 if(!lss_write(&mTMPADR,sizeof(UUWORD),1,fp)) return 0; 165 if(!lss_write(&mTILTACUM,sizeof(UUWORD),1,fp)) return 0; 166 if(!lss_write(&mHOFF,sizeof(UUWORD),1,fp)) return 0; 167 if(!lss_write(&mVOFF,sizeof(UUWORD),1,fp)) return 0; 168 if(!lss_write(&mVIDBAS,sizeof(UUWORD),1,fp)) return 0; 169 if(!lss_write(&mCOLLBAS,sizeof(UUWORD),1,fp)) return 0; 170 if(!lss_write(&mVIDADR,sizeof(UUWORD),1,fp)) return 0; 171 if(!lss_write(&mCOLLADR,sizeof(UUWORD),1,fp)) return 0; 172 if(!lss_write(&mSCBNEXT,sizeof(UUWORD),1,fp)) return 0; 173 if(!lss_write(&mSPRDLINE,sizeof(UUWORD),1,fp)) return 0; 174 if(!lss_write(&mHPOSSTRT,sizeof(UUWORD),1,fp)) return 0; 175 if(!lss_write(&mVPOSSTRT,sizeof(UUWORD),1,fp)) return 0; 176 if(!lss_write(&mSPRHSIZ,sizeof(UUWORD),1,fp)) return 0; 177 if(!lss_write(&mSPRVSIZ,sizeof(UUWORD),1,fp)) return 0; 178 if(!lss_write(&mSTRETCH,sizeof(UUWORD),1,fp)) return 0; 179 if(!lss_write(&mTILT,sizeof(UUWORD),1,fp)) return 0; 180 if(!lss_write(&mSPRDOFF,sizeof(UUWORD),1,fp)) return 0; 181 if(!lss_write(&mSPRVPOS,sizeof(UUWORD),1,fp)) return 0; 182 if(!lss_write(&mCOLLOFF,sizeof(UUWORD),1,fp)) return 0; 183 if(!lss_write(&mVSIZACUM,sizeof(UUWORD),1,fp)) return 0; 184 if(!lss_write(&mHSIZACUM,sizeof(UUWORD),1,fp)) return 0; 185 if(!lss_write(&mHSIZOFF,sizeof(UUWORD),1,fp)) return 0; 186 if(!lss_write(&mVSIZOFF,sizeof(UUWORD),1,fp)) return 0; 187 if(!lss_write(&mSCBADR,sizeof(UUWORD),1,fp)) return 0; 188 if(!lss_write(&mPROCADR,sizeof(UUWORD),1,fp)) return 0; 189 190 if(!lss_write(&mMATHABCD,sizeof(TMATHABCD),1,fp)) return 0; 191 if(!lss_write(&mMATHEFGH,sizeof(TMATHEFGH),1,fp)) return 0; 192 if(!lss_write(&mMATHJKLM,sizeof(TMATHJKLM),1,fp)) return 0; 193 if(!lss_write(&mMATHNP,sizeof(TMATHNP),1,fp)) return 0; 194 195 if(!lss_write(&mSPRCTL0_Type,sizeof(ULONG),1,fp)) return 0; 196 if(!lss_write(&mSPRCTL0_Vflip,sizeof(ULONG),1,fp)) return 0; 197 if(!lss_write(&mSPRCTL0_Hflip,sizeof(ULONG),1,fp)) return 0; 198 if(!lss_write(&mSPRCTL0_PixelBits,sizeof(ULONG),1,fp)) return 0; 199 200 if(!lss_write(&mSPRCTL1_StartLeft,sizeof(ULONG),1,fp)) return 0; 201 if(!lss_write(&mSPRCTL1_StartUp,sizeof(ULONG),1,fp)) return 0; 202 if(!lss_write(&mSPRCTL1_SkipSprite,sizeof(ULONG),1,fp)) return 0; 203 if(!lss_write(&mSPRCTL1_ReloadPalette,sizeof(ULONG),1,fp)) return 0; 204 if(!lss_write(&mSPRCTL1_ReloadDepth,sizeof(ULONG),1,fp)) return 0; 205 if(!lss_write(&mSPRCTL1_Sizing,sizeof(ULONG),1,fp)) return 0; 206 if(!lss_write(&mSPRCTL1_Literal,sizeof(ULONG),1,fp)) return 0; 207 208 if(!lss_write(&mSPRCOLL_Number,sizeof(ULONG),1,fp)) return 0; 209 if(!lss_write(&mSPRCOLL_Collide,sizeof(ULONG),1,fp)) return 0; 210 211 if(!lss_write(&mSPRSYS_StopOnCurrent,sizeof(ULONG),1,fp)) return 0; 212 if(!lss_write(&mSPRSYS_LeftHand,sizeof(ULONG),1,fp)) return 0; 213 if(!lss_write(&mSPRSYS_VStretch,sizeof(ULONG),1,fp)) return 0; 214 if(!lss_write(&mSPRSYS_NoCollide,sizeof(ULONG),1,fp)) return 0; 215 if(!lss_write(&mSPRSYS_Accumulate,sizeof(ULONG),1,fp)) return 0; 216 if(!lss_write(&mSPRSYS_SignedMath,sizeof(ULONG),1,fp)) return 0; 217 if(!lss_write(&mSPRSYS_Status,sizeof(ULONG),1,fp)) return 0; 218 if(!lss_write(&mSPRSYS_UnsafeAccess,sizeof(ULONG),1,fp)) return 0; 219 if(!lss_write(&mSPRSYS_LastCarry,sizeof(ULONG),1,fp)) return 0; 220 if(!lss_write(&mSPRSYS_Mathbit,sizeof(ULONG),1,fp)) return 0; 221 if(!lss_write(&mSPRSYS_MathInProgress,sizeof(ULONG),1,fp)) return 0; 222 223 if(!lss_write(&mSUZYBUSEN,sizeof(ULONG),1,fp)) return 0; 224 225 if(!lss_write(&mSPRINIT,sizeof(TSPRINIT),1,fp)) return 0; 226 227 if(!lss_write(&mSPRGO,sizeof(ULONG),1,fp)) return 0; 228 if(!lss_write(&mEVERON,sizeof(ULONG),1,fp)) return 0; 229 230 if(!lss_write(mPenIndex,sizeof(UBYTE),16,fp)) return 0; 231 232 if(!lss_write(&mLineType,sizeof(ULONG),1,fp)) return 0; 233 if(!lss_write(&mLineShiftRegCount,sizeof(ULONG),1,fp)) return 0; 234 if(!lss_write(&mLineShiftReg,sizeof(ULONG),1,fp)) return 0; 235 if(!lss_write(&mLineRepeatCount,sizeof(ULONG),1,fp)) return 0; 236 if(!lss_write(&mLinePixel,sizeof(ULONG),1,fp)) return 0; 237 if(!lss_write(&mLinePacketBitsLeft,sizeof(ULONG),1,fp)) return 0; 238 239 if(!lss_write(&mCollision,sizeof(ULONG),1,fp)) return 0; 240 241 if(!lss_write(&mLineBaseAddress,sizeof(ULONG),1,fp)) return 0; 242 if(!lss_write(&mLineCollisionAddress,sizeof(ULONG),1,fp)) return 0; 243 244 if(!lss_write(&mJOYSTICK,sizeof(TJOYSTICK),1,fp)) return 0; 245 if(!lss_write(&mSWITCHES,sizeof(TSWITCHES),1,fp)) return 0; 246 247 return 1; 248 } 249 250 bool CSusie::ContextLoad(LSS_FILE *fp) 251 { 252 TRACE_SUSIE0("ContextLoad()"); 253 254 char teststr[32]="XXXXXXXXXXXXXXXXXXX"; 255 if(!lss_read(teststr,sizeof(char),19,fp)) return 0; 256 if(strcmp(teststr,"CSusie::ContextSave")!=0) return 0; 257 258 if(!lss_read(&mTMPADR,sizeof(UUWORD),1,fp)) return 0; 259 if(!lss_read(&mTILTACUM,sizeof(UUWORD),1,fp)) return 0; 260 if(!lss_read(&mHOFF,sizeof(UUWORD),1,fp)) return 0; 261 if(!lss_read(&mVOFF,sizeof(UUWORD),1,fp)) return 0; 262 if(!lss_read(&mVIDBAS,sizeof(UUWORD),1,fp)) return 0; 263 if(!lss_read(&mCOLLBAS,sizeof(UUWORD),1,fp)) return 0; 264 if(!lss_read(&mVIDADR,sizeof(UUWORD),1,fp)) return 0; 265 if(!lss_read(&mCOLLADR,sizeof(UUWORD),1,fp)) return 0; 266 if(!lss_read(&mSCBNEXT,sizeof(UUWORD),1,fp)) return 0; 267 if(!lss_read(&mSPRDLINE,sizeof(UUWORD),1,fp)) return 0; 268 if(!lss_read(&mHPOSSTRT,sizeof(UUWORD),1,fp)) return 0; 269 if(!lss_read(&mVPOSSTRT,sizeof(UUWORD),1,fp)) return 0; 270 if(!lss_read(&mSPRHSIZ,sizeof(UUWORD),1,fp)) return 0; 271 if(!lss_read(&mSPRVSIZ,sizeof(UUWORD),1,fp)) return 0; 272 if(!lss_read(&mSTRETCH,sizeof(UUWORD),1,fp)) return 0; 273 if(!lss_read(&mTILT,sizeof(UUWORD),1,fp)) return 0; 274 if(!lss_read(&mSPRDOFF,sizeof(UUWORD),1,fp)) return 0; 275 if(!lss_read(&mSPRVPOS,sizeof(UUWORD),1,fp)) return 0; 276 if(!lss_read(&mCOLLOFF,sizeof(UUWORD),1,fp)) return 0; 277 if(!lss_read(&mVSIZACUM,sizeof(UUWORD),1,fp)) return 0; 278 if(!lss_read(&mHSIZACUM,sizeof(UUWORD),1,fp)) return 0; 279 if(!lss_read(&mHSIZOFF,sizeof(UUWORD),1,fp)) return 0; 280 if(!lss_read(&mVSIZOFF,sizeof(UUWORD),1,fp)) return 0; 281 if(!lss_read(&mSCBADR,sizeof(UUWORD),1,fp)) return 0; 282 if(!lss_read(&mPROCADR,sizeof(UUWORD),1,fp)) return 0; 283 284 if(!lss_read(&mMATHABCD,sizeof(TMATHABCD),1,fp)) return 0; 285 if(!lss_read(&mMATHEFGH,sizeof(TMATHEFGH),1,fp)) return 0; 286 if(!lss_read(&mMATHJKLM,sizeof(TMATHJKLM),1,fp)) return 0; 287 if(!lss_read(&mMATHNP,sizeof(TMATHNP),1,fp)) return 0; 288 289 if(!lss_read(&mSPRCTL0_Type,sizeof(ULONG),1,fp)) return 0; 290 if(!lss_read(&mSPRCTL0_Vflip,sizeof(ULONG),1,fp)) return 0; 291 if(!lss_read(&mSPRCTL0_Hflip,sizeof(ULONG),1,fp)) return 0; 292 if(!lss_read(&mSPRCTL0_PixelBits,sizeof(ULONG),1,fp)) return 0; 293 294 if(!lss_read(&mSPRCTL1_StartLeft,sizeof(ULONG),1,fp)) return 0; 295 if(!lss_read(&mSPRCTL1_StartUp,sizeof(ULONG),1,fp)) return 0; 296 if(!lss_read(&mSPRCTL1_SkipSprite,sizeof(ULONG),1,fp)) return 0; 297 if(!lss_read(&mSPRCTL1_ReloadPalette,sizeof(ULONG),1,fp)) return 0; 298 if(!lss_read(&mSPRCTL1_ReloadDepth,sizeof(ULONG),1,fp)) return 0; 299 if(!lss_read(&mSPRCTL1_Sizing,sizeof(ULONG),1,fp)) return 0; 300 if(!lss_read(&mSPRCTL1_Literal,sizeof(ULONG),1,fp)) return 0; 301 302 if(!lss_read(&mSPRCOLL_Number,sizeof(ULONG),1,fp)) return 0; 303 if(!lss_read(&mSPRCOLL_Collide,sizeof(ULONG),1,fp)) return 0; 304 305 if(!lss_read(&mSPRSYS_StopOnCurrent,sizeof(ULONG),1,fp)) return 0; 306 if(!lss_read(&mSPRSYS_LeftHand,sizeof(ULONG),1,fp)) return 0; 307 if(!lss_read(&mSPRSYS_VStretch,sizeof(ULONG),1,fp)) return 0; 308 if(!lss_read(&mSPRSYS_NoCollide,sizeof(ULONG),1,fp)) return 0; 309 if(!lss_read(&mSPRSYS_Accumulate,sizeof(ULONG),1,fp)) return 0; 310 if(!lss_read(&mSPRSYS_SignedMath,sizeof(ULONG),1,fp)) return 0; 311 if(!lss_read(&mSPRSYS_Status,sizeof(ULONG),1,fp)) return 0; 312 if(!lss_read(&mSPRSYS_UnsafeAccess,sizeof(ULONG),1,fp)) return 0; 313 if(!lss_read(&mSPRSYS_LastCarry,sizeof(ULONG),1,fp)) return 0; 314 if(!lss_read(&mSPRSYS_Mathbit,sizeof(ULONG),1,fp)) return 0; 315 if(!lss_read(&mSPRSYS_MathInProgress,sizeof(ULONG),1,fp)) return 0; 316 317 if(!lss_read(&mSUZYBUSEN,sizeof(ULONG),1,fp)) return 0; 318 319 if(!lss_read(&mSPRINIT,sizeof(TSPRINIT),1,fp)) return 0; 320 321 if(!lss_read(&mSPRGO,sizeof(ULONG),1,fp)) return 0; 322 if(!lss_read(&mEVERON,sizeof(ULONG),1,fp)) return 0; 323 324 if(!lss_read(mPenIndex,sizeof(UBYTE),16,fp)) return 0; 325 326 if(!lss_read(&mLineType,sizeof(ULONG),1,fp)) return 0; 327 if(!lss_read(&mLineShiftRegCount,sizeof(ULONG),1,fp)) return 0; 328 if(!lss_read(&mLineShiftReg,sizeof(ULONG),1,fp)) return 0; 329 if(!lss_read(&mLineRepeatCount,sizeof(ULONG),1,fp)) return 0; 330 if(!lss_read(&mLinePixel,sizeof(ULONG),1,fp)) return 0; 331 if(!lss_read(&mLinePacketBitsLeft,sizeof(ULONG),1,fp)) return 0; 332 333 if(!lss_read(&mCollision,sizeof(ULONG),1,fp)) return 0; 334 335 if(!lss_read(&mLineBaseAddress,sizeof(ULONG),1,fp)) return 0; 336 if(!lss_read(&mLineCollisionAddress,sizeof(ULONG),1,fp)) return 0; 337 338 if(!lss_read(&mJOYSTICK,sizeof(TJOYSTICK),1,fp)) return 0; 339 if(!lss_read(&mSWITCHES,sizeof(TSWITCHES),1,fp)) return 0; 340 341 return 1; 342 } 343 344 ULONG CSusie::PaintSprites(void) 345 { 346 int sprcount=0; 347 int data=0; 348 int everonscreen=0; 349 350 TRACE_SUSIE0(" "); 351 TRACE_SUSIE0(" "); 352 TRACE_SUSIE0(" "); 353 TRACE_SUSIE0("**************************************************************"); 354 TRACE_SUSIE0("********************** PaintSprites **************************"); 355 TRACE_SUSIE0("**************************************************************"); 356 TRACE_SUSIE0(" "); 357 358 TRACE_SUSIE1("PaintSprites() VIDBAS $%04x",mVIDBAS.Word); 359 TRACE_SUSIE1("PaintSprites() COLLBAS $%04x",mCOLLBAS.Word); 360 TRACE_SUSIE1("PaintSprites() SPRSYS $%02x",Peek(SPRSYS)); 361 362 if(!mSUZYBUSEN || !mSPRGO) { 363 TRACE_SUSIE0("PaintSprites() Returned !mSUZYBUSEN || !mSPRGO"); 364 return 0; 365 } 366 367 //ULONG mPenIndex[16]; 368 mCycles=0; 369 370 while (1) 371 { 372 TRACE_SUSIE1("PaintSprites() ************ Rendering Sprite %03d ************",sprcount); 373 374 everonscreen=0;// everon has to be reset for every sprite, thus line was moved inside this loop 375 376 // Step 1 load up the SCB params into Susie 377 378 // And thus it is documented that only the top byte of SCBNEXT is used. 379 // Its mentioned under the bits that are broke section in the bluebook 380 if(!(mSCBNEXT.Word&0xff00)) { 381 TRACE_SUSIE0("PaintSprites() mSCBNEXT==0 - FINISHED"); 382 mSPRSYS_Status=0; // Engine has finished 383 mSPRGO=FALSE; 384 break; 385 } else { 386 mSPRSYS_Status=1; 387 } 388 389 mTMPADR.Word=mSCBNEXT.Word; // Copy SCB pointer 390 mSCBADR.Word=mSCBNEXT.Word; // Copy SCB pointer 391 TRACE_SUSIE1("PaintSprites() SCBADDR $%04x",mSCBADR.Word); 392 393 data=RAM_PEEK(mTMPADR.Word); // Fetch control 0 394 TRACE_SUSIE1("PaintSprites() SPRCTL0 $%02x",data); 395 mSPRCTL0_Type=data&0x0007; 396 mSPRCTL0_Vflip=data&0x0010; 397 mSPRCTL0_Hflip=data&0x0020; 398 mSPRCTL0_PixelBits=((data&0x00c0)>>6)+1; 399 mTMPADR.Word+=1; 400 401 data=RAM_PEEK(mTMPADR.Word); // Fetch control 1 402 TRACE_SUSIE1("PaintSprites() SPRCTL1 $%02x",data); 403 mSPRCTL1_StartLeft=data&0x0001; 404 mSPRCTL1_StartUp=data&0x0002; 405 mSPRCTL1_SkipSprite=data&0x0004; 406 mSPRCTL1_ReloadPalette=data&0x0008; 407 mSPRCTL1_ReloadDepth=(data&0x0030)>>4; 408 mSPRCTL1_Sizing=data&0x0040; 409 mSPRCTL1_Literal=data&0x0080; 410 mTMPADR.Word+=1; 411 412 data=RAM_PEEK(mTMPADR.Word); // Collision num 413 TRACE_SUSIE1("PaintSprites() SPRCOLL $%02x",data); 414 mSPRCOLL_Number=data&0x000f; 415 mSPRCOLL_Collide=data&0x0020; 416 mTMPADR.Word+=1; 417 418 mSCBNEXT.Word=RAM_PEEKW(mTMPADR.Word); // Next SCB 419 TRACE_SUSIE1("PaintSprites() SCBNEXT $%04x",mSCBNEXT.Word); 420 mTMPADR.Word+=2; 421 422 mCycles+=5*SPR_RDWR_CYC; 423 424 // Initialise the collision depositary 425 426 // Although Tom Schenck says this is correct, it doesnt appear to be 427 // if(!mSPRCOLL_Collide && !mSPRSYS_NoCollide) 428 // { 429 // mCollision=RAM_PEEK((mSCBADR.Word+mCOLLOFF.Word)&0xffff); 430 // mCollision&=0x0f; 431 // } 432 mCollision=0; 433 434 // Check if this is a skip sprite 435 436 if(!mSPRCTL1_SkipSprite) { 437 mSPRDLINE.Word=RAM_PEEKW(mTMPADR.Word); // Sprite pack data 438 TRACE_SUSIE1("PaintSprites() SPRDLINE $%04x",mSPRDLINE.Word); 439 mTMPADR.Word+=2; 440 441 mHPOSSTRT.Word=RAM_PEEKW(mTMPADR.Word); // Sprite horizontal start position 442 TRACE_SUSIE1("PaintSprites() HPOSSTRT $%04x",mHPOSSTRT.Word); 443 mTMPADR.Word+=2; 444 445 mVPOSSTRT.Word=RAM_PEEKW(mTMPADR.Word); // Sprite vertical start position 446 TRACE_SUSIE1("PaintSprites() VPOSSTRT $%04x",mVPOSSTRT.Word); 447 mTMPADR.Word+=2; 448 449 mCycles+=6*SPR_RDWR_CYC; 450 451 // bool enable_sizing = FALSE; 452 bool enable_stretch = FALSE; 453 bool enable_tilt = FALSE; 454 455 // Optional section defined by reload type in Control 1 456 457 TRACE_SUSIE1("PaintSprites() mSPRCTL1.Bits.ReloadDepth=%d",mSPRCTL1_ReloadDepth); 458 switch(mSPRCTL1_ReloadDepth) { 459 case 1: 460 TRACE_SUSIE0("PaintSprites() Sizing Enabled"); 461 // enable_sizing=TRUE; 462 463 mSPRHSIZ.Word=RAM_PEEKW(mTMPADR.Word); // Sprite Horizontal size 464 mTMPADR.Word+=2; 465 466 mSPRVSIZ.Word=RAM_PEEKW(mTMPADR.Word); // Sprite Verticalal size 467 mTMPADR.Word+=2; 468 469 mCycles+=4*SPR_RDWR_CYC; 470 break; 471 472 case 2: 473 TRACE_SUSIE0("PaintSprites() Sizing Enabled"); 474 TRACE_SUSIE0("PaintSprites() Stretch Enabled"); 475 // enable_sizing=TRUE; 476 enable_stretch=TRUE; 477 478 mSPRHSIZ.Word=RAM_PEEKW(mTMPADR.Word); // Sprite Horizontal size 479 mTMPADR.Word+=2; 480 481 mSPRVSIZ.Word=RAM_PEEKW(mTMPADR.Word); // Sprite Verticalal size 482 mTMPADR.Word+=2; 483 484 mSTRETCH.Word=RAM_PEEKW(mTMPADR.Word); // Sprite stretch 485 mTMPADR.Word+=2; 486 487 mCycles+=6*SPR_RDWR_CYC; 488 break; 489 490 case 3: 491 TRACE_SUSIE0("PaintSprites() Sizing Enabled"); 492 TRACE_SUSIE0("PaintSprites() Stretch Enabled"); 493 TRACE_SUSIE0("PaintSprites() Tilt Enabled"); 494 // enable_sizing=TRUE; 495 enable_stretch=TRUE; 496 enable_tilt=TRUE; 497 498 mSPRHSIZ.Word=RAM_PEEKW(mTMPADR.Word); // Sprite Horizontal size 499 mTMPADR.Word+=2; 500 501 mSPRVSIZ.Word=RAM_PEEKW(mTMPADR.Word); // Sprite Verticalal size 502 mTMPADR.Word+=2; 503 504 mSTRETCH.Word=RAM_PEEKW(mTMPADR.Word); // Sprite stretch 505 mTMPADR.Word+=2; 506 507 mTILT.Word=RAM_PEEKW(mTMPADR.Word); // Sprite tilt 508 mTMPADR.Word+=2; 509 510 mCycles+=8*SPR_RDWR_CYC; 511 break; 512 513 default: 514 break; 515 } 516 517 TRACE_SUSIE1("PaintSprites() SPRHSIZ $%04x",mSPRHSIZ.Word); 518 TRACE_SUSIE1("PaintSprites() SPRVSIZ $%04x",mSPRVSIZ.Word); 519 TRACE_SUSIE1("PaintSprites() STRETCH $%04x",mSTRETCH.Word); 520 TRACE_SUSIE1("PaintSprites() TILT $%04x",mTILT.Word); 521 522 523 // Optional Palette reload 524 525 if(!mSPRCTL1_ReloadPalette) { 526 TRACE_SUSIE0("PaintSprites() Palette reloaded"); 527 for(int loop=0;loop<8;loop++) { 528 UBYTE data_tmp=RAM_PEEK(mTMPADR.Word++); 529 mPenIndex[loop*2]=(data_tmp>>4)&0x0f; 530 mPenIndex[(loop*2)+1]=data_tmp&0x0f; 531 } 532 // Increment cycle count for the reads 533 mCycles+=8*SPR_RDWR_CYC; 534 } 535 536 // Now we can start painting 537 538 // Quadrant drawing order is: SE,NE,NW,SW 539 // start quadrant is given by sprite_control1:0 & 1 540 541 // Setup screen start end variables 542 543 int screen_h_start=(SWORD)mHOFF.Word; 544 int screen_h_end=(SWORD)mHOFF.Word+HANDY_SCREEN_WIDTH; 545 int screen_v_start=(SWORD)mVOFF.Word; 546 int screen_v_end=(SWORD)mVOFF.Word+HANDY_SCREEN_HEIGHT; 547 548 int world_h_mid=screen_h_start+0x8000+(HANDY_SCREEN_WIDTH/2); 549 int world_v_mid=screen_v_start+0x8000+(HANDY_SCREEN_HEIGHT/2); 550 551 TRACE_SUSIE2("PaintSprites() screen_h_start $%04x screen_h_end $%04x",screen_h_start,screen_h_end); 552 TRACE_SUSIE2("PaintSprites() screen_v_start $%04x screen_v_end $%04x",screen_v_start,screen_v_end); 553 TRACE_SUSIE2("PaintSprites() world_h_mid $%04x world_v_mid $%04x",world_h_mid,world_v_mid); 554 555 bool superclip=FALSE; 556 int quadrant=0; 557 int hsign,vsign; 558 559 if(mSPRCTL1_StartLeft) { 560 if(mSPRCTL1_StartUp) quadrant=2; else quadrant=3; 561 } else { 562 if(mSPRCTL1_StartUp) quadrant=1; else quadrant=0; 563 } 564 TRACE_SUSIE1("PaintSprites() Quadrant=%d",quadrant); 565 566 // Check ref is inside screen area 567 568 if((SWORD)mHPOSSTRT.Word<screen_h_start || (SWORD)mHPOSSTRT.Word>=screen_h_end || 569 (SWORD)mVPOSSTRT.Word<screen_v_start || (SWORD)mVPOSSTRT.Word>=screen_v_end) superclip=TRUE; 570 571 TRACE_SUSIE1("PaintSprites() Superclip=%d",superclip); 572 573 574 // Quadrant mapping is: SE NE NW SW 575 // 0 1 2 3 576 // hsign +1 +1 -1 -1 577 // vsign +1 -1 -1 +1 578 // 579 // 580 // 2 | 1 581 // ------- 582 // 3 | 0 583 // 584 585 // Loop for 4 quadrants 586 587 for(int loop=0;loop<4;loop++) { 588 TRACE_SUSIE1("PaintSprites() -------- Rendering Quadrant %03d --------",quadrant); 589 590 int sprite_v=mVPOSSTRT.Word; 591 int sprite_h=mHPOSSTRT.Word; 592 593 bool render=FALSE; 594 595 // Set quadrand multipliers 596 hsign=(quadrant==0 || quadrant==1)?1:-1; 597 vsign=(quadrant==0 || quadrant==3)?1:-1; 598 599 // Preflip TRACE_SUSIE2("PaintSprites() hsign=%d vsign=%d",hsign,vsign); 600 601 //Use h/v flip to invert v/hsign 602 603 if(mSPRCTL0_Vflip) vsign=-vsign; 604 if(mSPRCTL0_Hflip) hsign=-hsign; 605 606 TRACE_SUSIE2("PaintSprites() Hflip=%d Vflip=%d",mSPRCTL0_Hflip,mSPRCTL0_Vflip); 607 TRACE_SUSIE2("PaintSprites() Hsign=%d Vsign=%d",hsign,vsign); 608 TRACE_SUSIE2("PaintSprites() Hpos =%04x Vpos =%04x",mHPOSSTRT.Word,mVPOSSTRT.Word); 609 TRACE_SUSIE2("PaintSprites() Hsizoff =%04x Vsizoff =%04x",mHSIZOFF.Word,mVSIZOFF.Word); 610 611 // Two different rendering algorithms used, on-screen & superclip 612 // when on screen we draw in x until off screen then skip to next 613 // line, BUT on superclip we draw all the way to the end of any 614 // given line checking each pixel is on screen. 615 616 if(superclip) { 617 // Check on the basis of each quad, we only render the quad 618 // IF the screen is in the quad, relative to the centre of 619 // the screen which is calculated below. 620 621 // Quadrant mapping is: SE NE NW SW 622 // 0 1 2 3 623 // hsign +1 +1 -1 -1 624 // vsign +1 -1 -1 +1 625 // 626 // 627 // 2 | 1 628 // ------- 629 // 3 | 0 630 // 631 // Quadrant mapping for superclipping must also take into account 632 // the hflip, vflip bits & negative tilt to be able to work correctly 633 // 634 int modquad=quadrant; 635 static int vquadflip[4]={1,0,3,2}; 636 static int hquadflip[4]={3,2,1,0}; 637 638 if(mSPRCTL0_Vflip) modquad=vquadflip[modquad]; 639 if(mSPRCTL0_Hflip) modquad=hquadflip[modquad]; 640 641 // This is causing Eurosoccer to fail!! 642 // if(enable_tilt && mTILT.Word&0x8000) modquad=hquadflip[modquad]; 643 644 switch(modquad) { 645 case 3: 646 if((sprite_h>=screen_h_start || sprite_h<world_h_mid) && (sprite_v<screen_v_end || sprite_v>world_v_mid)) render=TRUE; 647 break; 648 case 2: 649 if((sprite_h>=screen_h_start || sprite_h<world_h_mid) && (sprite_v>=screen_v_start || sprite_v<world_v_mid)) render=TRUE; 650 break; 651 case 1: 652 if((sprite_h<screen_h_end || sprite_h>world_h_mid) && (sprite_v>=screen_v_start || sprite_v<world_v_mid)) render=TRUE; 653 break; 654 default: 655 if((sprite_h<screen_h_end || sprite_h>world_h_mid) && (sprite_v<screen_v_end || sprite_v>world_v_mid)) render=TRUE; 656 break; 657 } 658 } else { 659 render=TRUE; 660 } 661 662 // Is this quad to be rendered ?? 663 664 TRACE_SUSIE1("PaintSprites() Render status %d",render); 665 666 int pixel_height=0; 667 int pixel_width=0; 668 // static int pixel=0; 669 int hoff=0,voff=0; 670 // int hloop=0; 671 int vloop=0; 672 bool onscreen=0; 673 static int vquadoff=0; 674 static int hquadoff=0; 675 676 if(render) { // && gRenderFrame 677 // Set the vertical position & offset 678 voff=(SWORD)mVPOSSTRT.Word-screen_v_start; 679 680 // Zero the stretch,tilt & acum values 681 mTILTACUM.Word=0; 682 683 // Perform the SIZOFF 684 if(vsign==1) mVSIZACUM.Word=mVSIZOFF.Word; 685 else mVSIZACUM.Word=0; 686 687 // Take the sign of the first quad (0) as the basic 688 // sign, all other quads drawing in the other direction 689 // get offset by 1 pixel in the other direction, this 690 // fixes the squashed look on the multi-quad sprites. 691 // if(vsign==-1 && loop>0) voff+=vsign; 692 if(loop==0) vquadoff=vsign; 693 if(vsign!=vquadoff) voff+=vsign; 694 695 for(;;) { 696 // Vertical scaling is done here 697 mVSIZACUM.Word+=mSPRVSIZ.Word; 698 pixel_height=mVSIZACUM.Byte.High; 699 mVSIZACUM.Byte.High=0; 700 701 // Update the next data line pointer and initialise our line 702 mSPRDOFF.Word=(UWORD)LineInit(0); 703 704 // If 1 == next quad, ==0 end of sprite, anyways its END OF LINE 705 if(mSPRDOFF.Word==1) { // End of quad 706 mSPRDLINE.Word+=mSPRDOFF.Word; 707 break; 708 } 709 710 if(mSPRDOFF.Word==0) { // End of sprite 711 loop=4; // Halt the quad loop 712 break; 713 } 714 715 // Draw one horizontal line of the sprite 716 for(vloop=0;vloop<pixel_height;vloop++) { 717 // Early bailout if the sprite has moved off screen, terminate quad 718 if(vsign==1 && voff>=HANDY_SCREEN_HEIGHT) break; 719 if(vsign==-1 && voff<0) break; 720 721 // Only allow the draw to take place if the line is visible 722 if(voff>=0 && voff<HANDY_SCREEN_HEIGHT) { 723 // Work out the horizontal pixel start position, start + tilt 724 mHPOSSTRT.Word+=((SWORD)mTILTACUM.Word>>8); 725 mTILTACUM.Byte.High=0; 726 hoff=(int)((SWORD)mHPOSSTRT.Word)-screen_h_start; 727 728 // Zero/Force the horizontal scaling accumulator 729 if(hsign==1) mHSIZACUM.Word=mHSIZOFF.Word; 730 else mHSIZACUM.Word=0; 731 732 // Take the sign of the first quad (0) as the basic 733 // sign, all other quads drawing in the other direction 734 // get offset by 1 pixel in the other direction, this 735 // fixes the squashed look on the multi-quad sprites. 736 // if(hsign==-1 && loop>0) hoff+=hsign; 737 if(loop==0) hquadoff=hsign; 738 if(hsign!=hquadoff) hoff+=hsign; 739 740 // Initialise our line 741 LineInit(voff); 742 onscreen=FALSE; 743 744 ULONG pixel = mLinePixel; // Much faster 745 switch(mSPRCTL0_Type) 746 { 747 case sprite_background_shadow: 748 #undef PROCESS_PIXEL 749 #define PROCESS_PIXEL \ 750 WritePixel(hoff,pixel); \ 751 if(!mSPRCOLL_Collide && !mSPRSYS_NoCollide && pixel!=0x0e) \ 752 { \ 753 WriteCollision(hoff,mSPRCOLL_Number); \ 754 } 755 756 #undef EndWhile 757 #undef LoopContinue 758 #define EndWhile EndWhile01b 759 #define LoopContinue LoopContinue01b 760 #include "susie_pixel_loop.h" 761 break; 762 case sprite_background_noncollide: 763 #undef PROCESS_PIXEL 764 #define PROCESS_PIXEL WritePixel(hoff,pixel); 765 766 #undef EndWhile 767 #undef LoopContinue 768 #define EndWhile EndWhile02b 769 #define LoopContinue LoopContinue02b 770 #include "susie_pixel_loop.h" 771 break; 772 case sprite_noncollide: 773 #undef PROCESS_PIXEL 774 #define PROCESS_PIXEL if(pixel!=0x00) WritePixel(hoff,pixel); 775 776 #undef EndWhile 777 #undef LoopContinue 778 #define EndWhile EndWhile03b 779 #define LoopContinue LoopContinue03b 780 #include "susie_pixel_loop.h" 781 break; 782 case sprite_boundary: 783 #undef PROCESS_PIXEL 784 #define PROCESS_PIXEL \ 785 if(pixel!=0x00 && pixel!=0x0f) \ 786 { \ 787 WritePixel(hoff,pixel); \ 788 } \ 789 if(pixel!=0x00) \ 790 { \ 791 if(!mSPRCOLL_Collide && !mSPRSYS_NoCollide) \ 792 { \ 793 ULONG collision=ReadCollision(hoff); \ 794 if(collision>mCollision) \ 795 { \ 796 mCollision=collision; \ 797 } \ 798 { \ 799 WriteCollision(hoff,mSPRCOLL_Number); \ 800 } \ 801 } \ 802 } 803 804 #undef EndWhile 805 #undef LoopContinue 806 #define EndWhile EndWhile04b 807 #define LoopContinue LoopContinue04b 808 #include "susie_pixel_loop.h" 809 break; 810 case sprite_normal: 811 #undef PROCESS_PIXEL 812 #define PROCESS_PIXEL \ 813 if(pixel!=0x00) \ 814 { \ 815 WritePixel(hoff,pixel); \ 816 if(!mSPRCOLL_Collide && !mSPRSYS_NoCollide) \ 817 { \ 818 ULONG collision=ReadCollision(hoff); \ 819 if(collision>mCollision) \ 820 { \ 821 mCollision=collision; \ 822 } \ 823 { \ 824 WriteCollision(hoff,mSPRCOLL_Number); \ 825 } \ 826 } \ 827 } 828 829 #undef EndWhile 830 #undef LoopContinue 831 #define EndWhile EndWhile05b 832 #define LoopContinue LoopContinue05b 833 #include "susie_pixel_loop.h" 834 break; 835 case sprite_boundary_shadow: 836 #undef PROCESS_PIXEL 837 #define PROCESS_PIXEL \ 838 if(pixel!=0x00 && pixel!=0x0e && pixel!=0x0f) \ 839 { \ 840 WritePixel(hoff,pixel); \ 841 } \ 842 if(pixel!=0x00 && pixel!=0x0e) \ 843 { \ 844 if(!mSPRCOLL_Collide && !mSPRSYS_NoCollide) \ 845 { \ 846 ULONG collision=ReadCollision(hoff); \ 847 if(collision>mCollision) \ 848 { \ 849 mCollision=collision; \ 850 } \ 851 { \ 852 WriteCollision(hoff,mSPRCOLL_Number); \ 853 } \ 854 } \ 855 } 856 857 #undef EndWhile 858 #undef LoopContinue 859 #define EndWhile EndWhile06b 860 #define LoopContinue LoopContinue06b 861 #include "susie_pixel_loop.h" 862 break; 863 case sprite_shadow: 864 #undef PROCESS_PIXEL 865 #define PROCESS_PIXEL \ 866 if(pixel!=0x00) \ 867 { \ 868 WritePixel(hoff,pixel); \ 869 } \ 870 if(pixel!=0x00 && pixel!=0x0e) \ 871 { \ 872 if(!mSPRCOLL_Collide && !mSPRSYS_NoCollide) \ 873 { \ 874 ULONG collision=ReadCollision(hoff); \ 875 if(collision>mCollision) \ 876 { \ 877 mCollision=collision; \ 878 } \ 879 { \ 880 WriteCollision(hoff,mSPRCOLL_Number); \ 881 } \ 882 } \ 883 } 884 885 #undef EndWhile 886 #undef LoopContinue 887 #define EndWhile EndWhile07b 888 #define LoopContinue LoopContinue07b 889 #include "susie_pixel_loop.h" 890 break; 891 case sprite_xor_shadow: 892 #undef PROCESS_PIXEL 893 #define PROCESS_PIXEL \ 894 if(pixel!=0x00) \ 895 { \ 896 WritePixel(hoff,ReadPixel(hoff)^pixel); \ 897 } \ 898 if(pixel!=0x00 && pixel!=0x0e) \ 899 { \ 900 if(!mSPRCOLL_Collide && !mSPRSYS_NoCollide && pixel!=0x0e) \ 901 { \ 902 ULONG collision=ReadCollision(hoff); \ 903 if(collision>mCollision) \ 904 { \ 905 mCollision=collision; \ 906 } \ 907 { \ 908 WriteCollision(hoff,mSPRCOLL_Number); \ 909 } \ 910 } \ 911 } 912 913 #undef EndWhile 914 #undef LoopContinue 915 #define EndWhile EndWhile08b 916 #define LoopContinue LoopContinue08b 917 #include "susie_pixel_loop.h" 918 break; 919 default: 920 #undef PROCESS_PIXEL 921 #define PROCESS_PIXEL 922 923 #undef EndWhile 924 #undef LoopContinue 925 #define EndWhile EndWhile09b 926 #define LoopContinue LoopContinue09b 927 #include "susie_pixel_loop.h" 928 break; 929 } 930 } 931 voff+=vsign; 932 933 // For every destination line we can modify SPRHSIZ & SPRVSIZ & TILTACUM 934 if(enable_stretch) { 935 mSPRHSIZ.Word+=mSTRETCH.Word; 936 // if(mSPRSYS_VStretch) mSPRVSIZ.Word+=mSTRETCH.Word; 937 } 938 if(enable_tilt) { 939 // Manipulate the tilt stuff 940 mTILTACUM.Word+=mTILT.Word; 941 } 942 } 943 // According to the docs this increments per dest line 944 // but only gets set when the source line is read 945 if(mSPRSYS_VStretch) mSPRVSIZ.Word+=mSTRETCH.Word*pixel_height; 946 947 // Update the line start for our next run thru the loop 948 mSPRDLINE.Word+=mSPRDOFF.Word; 949 } 950 } else { 951 // Skip thru data to next quad 952 for(;;) { 953 // Read the start of line offset 954 955 mSPRDOFF.Word=(UWORD)LineInit(0); 956 957 // We dont want to process data so mSPRDLINE is useless to us 958 mSPRDLINE.Word+=mSPRDOFF.Word; 959 960 // If 1 == next quad, ==0 end of sprite, anyways its END OF LINE 961 962 if(mSPRDOFF.Word==1) break; // End of quad 963 if(mSPRDOFF.Word==0) { // End of sprite 964 loop=4; // Halt the quad loop 965 break; 966 } 967 968 } 969 } 970 971 // Increment quadrant and mask to 2 bit value (0-3) 972 quadrant++; 973 quadrant&=0x03; 974 } 975 976 // Write the collision depositary if required 977 978 if(!mSPRCOLL_Collide && !mSPRSYS_NoCollide) { 979 switch(mSPRCTL0_Type) { 980 case sprite_xor_shadow: 981 case sprite_boundary: 982 case sprite_normal: 983 case sprite_boundary_shadow: 984 case sprite_shadow: { 985 UWORD coldep=mSCBADR.Word+mCOLLOFF.Word; 986 RAM_POKE(coldep,(UBYTE)mCollision); 987 TRACE_SUSIE2("PaintSprites() COLLOFF=$%04x SCBADR=$%04x",mCOLLOFF.Word,mSCBADR.Word); 988 TRACE_SUSIE2("PaintSprites() Wrote $%02x to SCB collision depositary at $%04x",(UBYTE)mCollision,coldep); 989 } 990 break; 991 default: 992 break; 993 } 994 } 995 996 if(mEVERON) { 997 UWORD coldep=mSCBADR.Word+mCOLLOFF.Word; 998 UBYTE coldat=RAM_PEEK(coldep); 999 if(!everonscreen) coldat|=0x80; 1000 else coldat&=0x7f; 1001 RAM_POKE(coldep,coldat); 1002 TRACE_SUSIE0("PaintSprites() EVERON IS ACTIVE"); 1003 TRACE_SUSIE2("PaintSprites() Wrote $%02x to SCB collision depositary at $%04x",coldat,coldep); 1004 } 1005 1006 // Perform Sprite debugging if required, single step on sprite draw 1007 if(gSingleStepModeSprites) { 1008 // char message[256]; 1009 //log_printf("CSusie:PaintSprites() - Rendered Sprite %03d\n",sprcount); 1010 //SingleStepModeSprites=0; 1011 } 1012 } else { 1013 TRACE_SUSIE0("PaintSprites() mSPRCTL1.Bits.SkipSprite==TRUE"); 1014 } 1015 1016 // Increase sprite number 1017 sprcount++; 1018 1019 // Check if we abort after 1st sprite is complete 1020 1021 // if(mSPRSYS.Read.StopOnCurrent) 1022 // { 1023 // mSPRSYS.Read.Status=0; // Engine has finished 1024 // mSPRGO=FALSE; 1025 // break; 1026 // } 1027 1028 // Check sprcount for looping SCB, random large number chosen 1029 if(sprcount>4096) { 1030 // Stop the system, otherwise we may just come straight back in..... 1031 gSystemHalt=TRUE; 1032 // Display warning message 1033 log_printf("CSusie:PaintSprites(): Single draw sprite limit exceeded (>4096). The SCB is most likely looped back on itself. Reset/Exit is recommended\n"); 1034 // Signal error to the caller 1035 return 0; 1036 } 1037 } 1038 // Fudge factor to fix many flickering issues, also the keypress 1039 // problem with Hard Drivin and the strange pause in Dirty Larry. 1040 // mCycles>>=2; 1041 return mCycles; 1042 } 1043 1044 void CSusie::Poke(ULONG addr,UBYTE data) 1045 { 1046 switch(addr&0xff) { 1047 case (TMPADRL&0xff): 1048 mTMPADR.Byte.Low=data; 1049 mTMPADR.Byte.High=0; 1050 TRACE_SUSIE2("Poke(TMPADRL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1051 break; 1052 case (TMPADRH&0xff): 1053 mTMPADR.Byte.High=data; 1054 TRACE_SUSIE2("Poke(TMPADRH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1055 break; 1056 case (TILTACUML&0xff): 1057 mTILTACUM.Byte.Low=data; 1058 mTILTACUM.Byte.High=0; 1059 TRACE_SUSIE2("Poke(TILTACUML,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1060 break; 1061 case (TILTACUMH&0xff): 1062 mTILTACUM.Byte.High=data; 1063 TRACE_SUSIE2("Poke(TILTACUMH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1064 break; 1065 case (HOFFL&0xff): 1066 mHOFF.Byte.Low=data; 1067 mHOFF.Byte.High=0; 1068 TRACE_SUSIE2("Poke(HOFFL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1069 break; 1070 case (HOFFH&0xff): 1071 mHOFF.Byte.High=data; 1072 TRACE_SUSIE2("Poke(HOFFH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1073 break; 1074 case (VOFFL&0xff): 1075 mVOFF.Byte.Low=data; 1076 mVOFF.Byte.High=0; 1077 TRACE_SUSIE2("Poke(VOFFL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1078 break; 1079 case (VOFFH&0xff): 1080 mVOFF.Byte.High=data; 1081 TRACE_SUSIE2("Poke(VOFFH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1082 break; 1083 case (VIDBASL&0xff): 1084 mVIDBAS.Byte.Low=data; 1085 mVIDBAS.Byte.High=0; 1086 TRACE_SUSIE2("Poke(VIDBASL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1087 break; 1088 case (VIDBASH&0xff): 1089 mVIDBAS.Byte.High=data; 1090 TRACE_SUSIE2("Poke(VIDBASH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1091 break; 1092 case (COLLBASL&0xff): 1093 mCOLLBAS.Byte.Low=data; 1094 mCOLLBAS.Byte.High=0; 1095 TRACE_SUSIE2("Poke(COLLBASL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1096 break; 1097 case (COLLBASH&0xff): 1098 mCOLLBAS.Byte.High=data; 1099 TRACE_SUSIE2("Poke(COLLBASH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1100 break; 1101 case (VIDADRL&0xff): 1102 mVIDADR.Byte.Low=data; 1103 mVIDADR.Byte.High=0; 1104 TRACE_SUSIE2("Poke(VIDADRL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1105 break; 1106 case (VIDADRH&0xff): 1107 mVIDADR.Byte.High=data; 1108 TRACE_SUSIE2("Poke(VIDADRH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1109 break; 1110 case (COLLADRL&0xff): 1111 mCOLLADR.Byte.Low=data; 1112 mCOLLADR.Byte.High=0; 1113 TRACE_SUSIE2("Poke(COLLADRL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1114 break; 1115 case (COLLADRH&0xff): 1116 mCOLLADR.Byte.High=data; 1117 TRACE_SUSIE2("Poke(COLLADRH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1118 break; 1119 case (SCBNEXTL&0xff): 1120 mSCBNEXT.Byte.Low=data; 1121 mSCBNEXT.Byte.High=0; 1122 TRACE_SUSIE2("Poke(SCBNEXTL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1123 break; 1124 case (SCBNEXTH&0xff): 1125 mSCBNEXT.Byte.High=data; 1126 TRACE_SUSIE2("Poke(SCBNEXTH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1127 break; 1128 case (SPRDLINEL&0xff): 1129 mSPRDLINE.Byte.Low=data; 1130 mSPRDLINE.Byte.High=0; 1131 TRACE_SUSIE2("Poke(SPRDLINEL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1132 break; 1133 case (SPRDLINEH&0xff): 1134 mSPRDLINE.Byte.High=data; 1135 TRACE_SUSIE2("Poke(SPRDLINEH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1136 break; 1137 case (HPOSSTRTL&0xff): 1138 mHPOSSTRT.Byte.Low=data; 1139 mHPOSSTRT.Byte.High=0; 1140 TRACE_SUSIE2("Poke(HPOSSTRTL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1141 break; 1142 case (HPOSSTRTH&0xff): 1143 mHPOSSTRT.Byte.High=data; 1144 TRACE_SUSIE2("Poke(HPOSSTRTH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1145 break; 1146 case (VPOSSTRTL&0xff): 1147 mVPOSSTRT.Byte.Low=data; 1148 mVPOSSTRT.Byte.High=0; 1149 TRACE_SUSIE2("Poke(VPOSSTRTL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1150 break; 1151 case (VPOSSTRTH&0xff): 1152 mVPOSSTRT.Byte.High=data; 1153 TRACE_SUSIE2("Poke(VPOSSTRTH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1154 break; 1155 case (SPRHSIZL&0xff): 1156 mSPRHSIZ.Byte.Low=data; 1157 mSPRHSIZ.Byte.High=0; 1158 TRACE_SUSIE2("Poke(SPRHSIZL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1159 break; 1160 case (SPRHSIZH&0xff): 1161 mSPRHSIZ.Byte.High=data; 1162 TRACE_SUSIE2("Poke(SPRHSIZH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1163 break; 1164 case (SPRVSIZL&0xff): 1165 mSPRVSIZ.Byte.Low=data; 1166 mSPRVSIZ.Byte.High=0; 1167 TRACE_SUSIE2("Poke(SPRVSIZL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1168 break; 1169 case (SPRVSIZH&0xff): 1170 mSPRVSIZ.Byte.High=data; 1171 TRACE_SUSIE2("Poke(SPRVSIZH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1172 break; 1173 case (STRETCHL&0xff): 1174 mSTRETCH.Byte.Low=data; 1175 mSTRETCH.Byte.High=0; 1176 TRACE_SUSIE2("Poke(STRETCHL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1177 break; 1178 case (STRETCHH&0xff): 1179 TRACE_SUSIE2("Poke(STRETCHH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1180 mSTRETCH.Byte.High=data; 1181 break; 1182 case (TILTL&0xff): 1183 mTILT.Byte.Low=data; 1184 mTILT.Byte.High=0; 1185 TRACE_SUSIE2("Poke(TILTL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1186 break; 1187 case (TILTH&0xff): 1188 mTILT.Byte.High=data; 1189 TRACE_SUSIE2("Poke(TILTH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1190 break; 1191 case (SPRDOFFL&0xff): 1192 TRACE_SUSIE2("Poke(SPRDOFFL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1193 mSPRDOFF.Byte.Low=data; 1194 mSPRDOFF.Byte.High=0; 1195 break; 1196 case (SPRDOFFH&0xff): 1197 TRACE_SUSIE2("Poke(SPRDOFFH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1198 mSPRDOFF.Byte.High=data; 1199 break; 1200 case (SPRVPOSL&0xff): 1201 TRACE_SUSIE2("Poke(SPRVPOSL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1202 mSPRVPOS.Byte.Low=data; 1203 mSPRVPOS.Byte.High=0; 1204 break; 1205 case (SPRVPOSH&0xff): 1206 mSPRVPOS.Byte.High=data; 1207 TRACE_SUSIE2("Poke(SPRVPOSH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1208 break; 1209 case (COLLOFFL&0xff): 1210 mCOLLOFF.Byte.Low=data; 1211 mCOLLOFF.Byte.High=0; 1212 TRACE_SUSIE2("Poke(COLLOFFL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1213 break; 1214 case (COLLOFFH&0xff): 1215 mCOLLOFF.Byte.High=data; 1216 TRACE_SUSIE2("Poke(COLLOFFH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1217 break; 1218 case (VSIZACUML&0xff): 1219 mVSIZACUM.Byte.Low=data; 1220 mVSIZACUM.Byte.High=0; 1221 TRACE_SUSIE2("Poke(VSIZACUML,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1222 break; 1223 case (VSIZACUMH&0xff): 1224 mVSIZACUM.Byte.High=data; 1225 TRACE_SUSIE2("Poke(VSIZACUMH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1226 break; 1227 case (HSIZOFFL&0xff): 1228 mHSIZOFF.Byte.Low=data; 1229 mHSIZOFF.Byte.High=0; 1230 TRACE_SUSIE2("Poke(HSIZOFFL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1231 break; 1232 case (HSIZOFFH&0xff): 1233 mHSIZOFF.Byte.High=data; 1234 TRACE_SUSIE2("Poke(HSIZOFFH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1235 break; 1236 case (VSIZOFFL&0xff): 1237 mVSIZOFF.Byte.Low=data; 1238 mVSIZOFF.Byte.High=0; 1239 TRACE_SUSIE2("Poke(VSIZOFFL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1240 break; 1241 case (VSIZOFFH&0xff): 1242 mVSIZOFF.Byte.High=data; 1243 TRACE_SUSIE2("Poke(VSIZOFFH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1244 break; 1245 case (SCBADRL&0xff): 1246 mSCBADR.Byte.Low=data; 1247 mSCBADR.Byte.High=0; 1248 TRACE_SUSIE2("Poke(SCBADRL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1249 break; 1250 case (SCBADRH&0xff): 1251 mSCBADR.Byte.High=data; 1252 TRACE_SUSIE2("Poke(SCBADRH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1253 break; 1254 case (PROCADRL&0xff): 1255 mPROCADR.Byte.Low=data; 1256 mPROCADR.Byte.High=0; 1257 TRACE_SUSIE2("Poke(PROCADRL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1258 break; 1259 case (PROCADRH&0xff): 1260 mPROCADR.Byte.High=data; 1261 TRACE_SUSIE2("Poke(PROCADRH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1262 break; 1263 1264 case (MATHD&0xff): 1265 TRACE_SUSIE2("Poke(MATHD,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1266 mMATHABCD.Bytes.D=data; 1267 // mMATHABCD.Bytes.C=0; 1268 // The hardware manual says that the sign shouldnt change 1269 // but if I dont do this then stun runner will hang as it 1270 // does the init in the wrong order and if the previous 1271 // calc left a zero there then we'll get a sign error 1272 Poke(MATHC,0); 1273 break; 1274 case (MATHC&0xff): 1275 TRACE_SUSIE2("Poke(MATHC,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1276 mMATHABCD.Bytes.C=data; 1277 // Perform sign conversion if required 1278 if(mSPRSYS_SignedMath) { 1279 // Account for the math bug that 0x8000 is +ve & 0x0000 is -ve by subracting 1 1280 if((mMATHABCD.Words.CD-1)&0x8000) { 1281 UWORD conv; 1282 conv=mMATHABCD.Words.CD^0xffff; 1283 conv++; 1284 mMATHCD_sign=-1; 1285 TRACE_SUSIE2("MATH CD signed conversion complete %04x to %04x",mMATHABCD.Words.CD,conv); 1286 mMATHABCD.Words.CD=conv; 1287 } else { 1288 mMATHCD_sign=1; 1289 } 1290 } 1291 break; 1292 case (MATHB&0xff): 1293 TRACE_SUSIE2("Poke(MATHB,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1294 mMATHABCD.Bytes.B=data; 1295 mMATHABCD.Bytes.A=0; 1296 break; 1297 case (MATHA&0xff): 1298 TRACE_SUSIE2("Poke(MATHA,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1299 mMATHABCD.Bytes.A=data; 1300 // Perform sign conversion if required 1301 if(mSPRSYS_SignedMath) { 1302 // Account for the math bug that 0x8000 is +ve & 0x0000 is -ve by subracting 1 1303 if((mMATHABCD.Words.AB-1)&0x8000) { 1304 UWORD conv; 1305 conv=mMATHABCD.Words.AB^0xffff; 1306 conv++; 1307 mMATHAB_sign=-1; 1308 TRACE_SUSIE2("MATH AB signed conversion complete %04x to %04x",mMATHABCD.Words.AB,conv); 1309 mMATHABCD.Words.AB=conv; 1310 } else { 1311 mMATHAB_sign=1; 1312 } 1313 } 1314 1315 TRACE_SUSIE2("DoMathMultiply() AB=$%04x * CD=$%04x",mMATHABCD.Words.AB,mMATHABCD.Words.CD); 1316 1317 mSPRSYS_Mathbit=FALSE; 1318 1319 // Multiplies with out sign or accumulate take 44 ticks to complete. 1320 // Multiplies with sign and accumulate take 54 ticks to complete. 1321 // 1322 // AB EFGH 1323 // * CD / NP 1324 // ------- ----------- 1325 // EFGH ABCD 1326 // Accumulate in JKLM Remainder in (JK)LM 1327 // 1328 1329 // Basic multiply is ALWAYS unsigned, sign conversion is done later 1330 mMATHEFGH.Long=(ULONG)mMATHABCD.Words.AB*(ULONG)mMATHABCD.Words.CD; 1331 1332 if(mSPRSYS_SignedMath) { 1333 // Add the sign bits, only >0 is +ve result 1334 mMATHEFGH_sign=mMATHAB_sign+mMATHCD_sign; 1335 if(!mMATHEFGH_sign) { 1336 mMATHEFGH.Long^=0xffffffff; 1337 mMATHEFGH.Long++; 1338 } 1339 } 1340 1341 // Check overflow, if B31 has changed from 1->0 then its overflow time 1342 if(mSPRSYS_Accumulate) { 1343 TRACE_SUSIE0("DoMathMultiply() - ACCUMULATED JKLM+=EFGH"); 1344 ULONG tmp=mMATHJKLM.Long+mMATHEFGH.Long; 1345 // Let sign change indicate overflow 1346 if((tmp&0x80000000)!=(mMATHJKLM.Long&0x80000000)) { 1347 TRACE_SUSIE0("DoMathMultiply() - OVERFLOW DETECTED"); 1348 // mSPRSYS_Mathbit=TRUE; 1349 } 1350 // Save accumulated result 1351 mMATHJKLM.Long=tmp; 1352 } 1353 TRACE_SUSIE1("DoMathMultiply() Results (Multi) EFGH=$%08x",mMATHEFGH.Long); 1354 TRACE_SUSIE1("DoMathMultiply() Results (Accum) JKLM=$%08x",mMATHJKLM.Long); 1355 break; 1356 1357 case (MATHP&0xff): 1358 mMATHNP.Bytes.P=data; 1359 mMATHNP.Bytes.N=0; 1360 TRACE_SUSIE2("Poke(MATHP,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1361 break; 1362 case (MATHN&0xff): 1363 mMATHNP.Bytes.N=data; 1364 TRACE_SUSIE2("Poke(MATHN,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1365 break; 1366 1367 case (MATHH&0xff): 1368 mMATHEFGH.Bytes.H=data; 1369 mMATHEFGH.Bytes.G=0; 1370 TRACE_SUSIE2("Poke(MATHH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1371 break; 1372 case (MATHG&0xff): 1373 mMATHEFGH.Bytes.G=data; 1374 TRACE_SUSIE2("Poke(MATHG,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1375 break; 1376 case (MATHF&0xff): 1377 mMATHEFGH.Bytes.F=data; 1378 mMATHEFGH.Bytes.E=0; 1379 TRACE_SUSIE2("Poke(MATHF,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1380 break; 1381 case (MATHE&0xff): 1382 mMATHEFGH.Bytes.E=data; 1383 TRACE_SUSIE2("Poke(MATHE,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1384 mSPRSYS_Mathbit=FALSE; 1385 1386 // 1387 // Divides take 176 + 14*N ticks 1388 // (N is the number of most significant zeros in the divisor.) 1389 // 1390 // AB EFGH 1391 // * CD / NP 1392 // ------- ----------- 1393 // EFGH ABCD 1394 // Accumulate in JKLM Remainder in (JK)LM 1395 // 1396 1397 // Divide is ALWAYS unsigned arithmetic... 1398 if(mMATHNP.Long) { 1399 TRACE_SUSIE0("DoMathDivide() - UNSIGNED"); 1400 mMATHABCD.Long=mMATHEFGH.Long/mMATHNP.Long; 1401 mMATHJKLM.Long=mMATHEFGH.Long%mMATHNP.Long; 1402 // mSPRSYS_Mathbit=FALSE; 1403 } else { 1404 TRACE_SUSIE0("DoMathDivide() - DIVIDE BY ZERO ERROR"); 1405 mMATHABCD.Long=0xffffffff; 1406 mMATHJKLM.Long=0; 1407 mSPRSYS_Mathbit=TRUE; 1408 } 1409 break; 1410 1411 case (MATHM&0xff): 1412 mMATHJKLM.Bytes.M=data; 1413 mMATHJKLM.Bytes.L=0; 1414 mSPRSYS_Mathbit=FALSE; 1415 TRACE_SUSIE2("Poke(MATHM,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1416 break; 1417 case (MATHL&0xff): 1418 mMATHJKLM.Bytes.L=data; 1419 TRACE_SUSIE2("Poke(MATHL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1420 break; 1421 case (MATHK&0xff): 1422 mMATHJKLM.Bytes.K=data; 1423 mMATHJKLM.Bytes.J=0; 1424 TRACE_SUSIE2("Poke(MATHK,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1425 break; 1426 case (MATHJ&0xff): 1427 mMATHJKLM.Bytes.J=data; 1428 TRACE_SUSIE2("Poke(MATHJ,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1429 break; 1430 1431 case (SPRCTL0&0xff): 1432 // mSPRCTL0_Type=data&0x0007; 1433 mSPRCTL0_Vflip=data&0x0010; 1434 mSPRCTL0_Hflip=data&0x0020; 1435 mSPRCTL0_PixelBits=((data&0x00c0)>>6)+1; 1436 TRACE_SUSIE2("Poke(SPRCTL0,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1437 break; 1438 case (SPRCTL1&0xff): 1439 mSPRCTL1_StartLeft=data&0x0001; 1440 mSPRCTL1_StartUp=data&0x0002; 1441 mSPRCTL1_SkipSprite=data&0x0004; 1442 mSPRCTL1_ReloadPalette=data&0x0008; 1443 mSPRCTL1_ReloadDepth=(data&0x0030)>>4; 1444 mSPRCTL1_Sizing=data&0x0040; 1445 mSPRCTL1_Literal=data&0x0080; 1446 TRACE_SUSIE2("Poke(SPRCTL1,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1447 break; 1448 case (SPRCOLL&0xff): 1449 mSPRCOLL_Number=data&0x000f; 1450 mSPRCOLL_Collide=data&0x0020; 1451 TRACE_SUSIE2("Poke(SPRCOLL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1452 break; 1453 case (SPRINIT&0xff): 1454 mSPRINIT.Byte=data; 1455 TRACE_SUSIE2("Poke(SPRINIT,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1456 break; 1457 case (SUZYBUSEN&0xff): 1458 mSUZYBUSEN=data&0x01; 1459 TRACE_SUSIE2("Poke(SUZYBUSEN,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1460 break; 1461 case (SPRGO&0xff): 1462 mSPRGO=data&0x01; 1463 mEVERON=data&0x04; 1464 TRACE_SUSIE2("Poke(SPRGO,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1465 break; 1466 case (SPRSYS&0xff): 1467 mSPRSYS_StopOnCurrent=data&0x0002; 1468 if(data&0x0004) mSPRSYS_UnsafeAccess=0; 1469 mSPRSYS_LeftHand=data&0x0008; 1470 mSPRSYS_VStretch=data&0x0010; 1471 mSPRSYS_NoCollide=data&0x0020; 1472 mSPRSYS_Accumulate=data&0x0040; 1473 mSPRSYS_SignedMath=data&0x0080; 1474 TRACE_SUSIE2("Poke(SPRSYS,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1475 break; 1476 1477 // Cartridge writing ports 1478 1479 case (RCART0&0xff): 1480 if(mSystem.mCart->CartGetAudin() && mSystem.mMikie->SwitchAudInValue()){ 1481 mSystem.mCart->Poke0A(data); 1482 }else{ 1483 mSystem.mCart->Poke0(data); 1484 } 1485 mSystem.mEEPROM->ProcessEepromCounter(mSystem.mCart->GetCounterValue()); 1486 TRACE_SUSIE2("Poke(RCART0,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1487 break; 1488 case (RCART1&0xff): 1489 if(mSystem.mCart->CartGetAudin() && mSystem.mMikie->SwitchAudInValue()){ 1490 mSystem.mCart->Poke1A(data); 1491 }else{ 1492 mSystem.mCart->Poke1(data); 1493 } 1494 mSystem.mEEPROM->ProcessEepromCounter(mSystem.mCart->GetCounterValue()); 1495 TRACE_SUSIE2("Poke(RCART1,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1496 break; 1497 1498 // These are not so important, so lets ignore them for the moment 1499 1500 case (LEDS&0xff): 1501 case (PPORTSTAT&0xff): 1502 case (PPORTDATA&0xff): 1503 case (HOWIE&0xff): 1504 TRACE_SUSIE2("Poke(LEDS/PPORTSTST/PPORTDATA/HOWIE,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC()); 1505 break; 1506 1507 // Errors on read only register accesses 1508 1509 case (SUZYHREV&0xff): 1510 case (JOYSTICK&0xff): 1511 case (SWITCHES&0xff): 1512 TRACE_SUSIE3("Poke(%04x,%02x) - Poke to read only register location at PC=%04x",addr,data,mSystem.mCpu->GetPC()); 1513 break; 1514 1515 // Errors on illegal location accesses 1516 1517 default: 1518 TRACE_SUSIE3("Poke(%04x,%02x) - Poke to illegal location at PC=%04x",addr,data,mSystem.mCpu->GetPC()); 1519 break; 1520 } 1521 } 1522 1523 UBYTE CSusie::Peek(ULONG addr) 1524 { 1525 UBYTE retval=0; 1526 switch(addr&0xff) { 1527 case (TMPADRL&0xff): 1528 retval=mTMPADR.Byte.Low; 1529 TRACE_SUSIE2("Peek(TMPADRL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1530 return retval; 1531 case (TMPADRH&0xff): 1532 retval=mTMPADR.Byte.High; 1533 TRACE_SUSIE2("Peek(TMPADRH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1534 return retval; 1535 case (TILTACUML&0xff): 1536 retval=mTILTACUM.Byte.Low; 1537 TRACE_SUSIE2("Peek(TILTACUML)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1538 return retval; 1539 case (TILTACUMH&0xff): 1540 retval=mTILTACUM.Byte.High; 1541 TRACE_SUSIE2("Peek(TILTACUMH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1542 return retval; 1543 case (HOFFL&0xff): 1544 retval=mHOFF.Byte.Low; 1545 TRACE_SUSIE2("Peek(HOFFL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1546 return retval; 1547 case (HOFFH&0xff): 1548 retval=mHOFF.Byte.High; 1549 TRACE_SUSIE2("Peek(HOFFH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1550 return retval; 1551 case (VOFFL&0xff): 1552 retval=mVOFF.Byte.Low; 1553 TRACE_SUSIE2("Peek(VOFFL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1554 return retval; 1555 case (VOFFH&0xff): 1556 retval=mVOFF.Byte.High; 1557 TRACE_SUSIE2("Peek(VOFFH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1558 return retval; 1559 case (VIDBASL&0xff): 1560 retval=mVIDBAS.Byte.Low; 1561 TRACE_SUSIE2("Peek(VIDBASL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1562 return retval; 1563 case (VIDBASH&0xff): 1564 retval=mVIDBAS.Byte.High; 1565 TRACE_SUSIE2("Peek(VIDBASH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1566 return retval; 1567 case (COLLBASL&0xff): 1568 retval=mCOLLBAS.Byte.Low; 1569 TRACE_SUSIE2("Peek(COLLBASL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1570 return retval; 1571 case (COLLBASH&0xff): 1572 retval=mCOLLBAS.Byte.High; 1573 TRACE_SUSIE2("Peek(COLLBASH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1574 return retval; 1575 case (VIDADRL&0xff): 1576 retval=mVIDADR.Byte.Low; 1577 TRACE_SUSIE2("Peek(VIDADRL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1578 return retval; 1579 case (VIDADRH&0xff): 1580 retval=mVIDADR.Byte.High; 1581 TRACE_SUSIE2("Peek(VIDADRH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1582 return retval; 1583 case (COLLADRL&0xff): 1584 retval=mCOLLADR.Byte.Low; 1585 TRACE_SUSIE2("Peek(COLLADRL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1586 return retval; 1587 case (COLLADRH&0xff): 1588 retval=mCOLLADR.Byte.High; 1589 TRACE_SUSIE2("Peek(COLLADRH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1590 return retval; 1591 case (SCBNEXTL&0xff): 1592 retval=mSCBNEXT.Byte.Low; 1593 TRACE_SUSIE2("Peek(SCBNEXTL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1594 return retval; 1595 case (SCBNEXTH&0xff): 1596 retval=mSCBNEXT.Byte.High; 1597 TRACE_SUSIE2("Peek(SCBNEXTH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1598 return retval; 1599 case (SPRDLINEL&0xff): 1600 retval=mSPRDLINE.Byte.Low; 1601 TRACE_SUSIE2("Peek(SPRDLINEL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1602 return retval; 1603 case (SPRDLINEH&0xff): 1604 retval=mSPRDLINE.Byte.High; 1605 TRACE_SUSIE2("Peek(SPRDLINEH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1606 return retval; 1607 case (HPOSSTRTL&0xff): 1608 retval=mHPOSSTRT.Byte.Low; 1609 TRACE_SUSIE2("Peek(HPOSSTRTL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1610 return retval; 1611 case (HPOSSTRTH&0xff): 1612 retval=mHPOSSTRT.Byte.High; 1613 TRACE_SUSIE2("Peek(HPOSSTRTH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1614 return retval; 1615 case (VPOSSTRTL&0xff): 1616 retval=mVPOSSTRT.Byte.Low; 1617 TRACE_SUSIE2("Peek(VPOSSTRTL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1618 return retval; 1619 case (VPOSSTRTH&0xff): 1620 retval=mVPOSSTRT.Byte.High; 1621 TRACE_SUSIE2("Peek(VPOSSTRTH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1622 return retval; 1623 case (SPRHSIZL&0xff): 1624 retval=mSPRHSIZ.Byte.Low; 1625 TRACE_SUSIE2("Peek(SPRHSIZL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1626 return retval; 1627 case (SPRHSIZH&0xff): 1628 retval=mSPRHSIZ.Byte.High; 1629 TRACE_SUSIE2("Peek(SPRHSIZH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1630 return retval; 1631 case (SPRVSIZL&0xff): 1632 retval=mSPRVSIZ.Byte.Low; 1633 TRACE_SUSIE2("Peek(SPRVSIZL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1634 return retval; 1635 case (SPRVSIZH&0xff): 1636 retval=mSPRVSIZ.Byte.High; 1637 TRACE_SUSIE2("Peek(SPRVSIZH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1638 return retval; 1639 case (STRETCHL&0xff): 1640 retval=mSTRETCH.Byte.Low; 1641 TRACE_SUSIE2("Peek(STRETCHL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1642 return retval; 1643 case (STRETCHH&0xff): 1644 retval=mSTRETCH.Byte.High; 1645 TRACE_SUSIE2("Peek(STRETCHH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1646 return retval; 1647 case (TILTL&0xff): 1648 retval=mTILT.Byte.Low; 1649 TRACE_SUSIE2("Peek(TILTL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1650 return retval; 1651 case (TILTH&0xff): 1652 retval=mTILT.Byte.High; 1653 TRACE_SUSIE2("Peek(TILTH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1654 return retval; 1655 case (SPRDOFFL&0xff): 1656 retval=mSPRDOFF.Byte.Low; 1657 TRACE_SUSIE2("Peek(SPRDOFFL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1658 return retval; 1659 case (SPRDOFFH&0xff): 1660 retval=mSPRDOFF.Byte.High; 1661 TRACE_SUSIE2("Peek(SPRDOFFH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1662 return retval; 1663 case (SPRVPOSL&0xff): 1664 retval=mSPRVPOS.Byte.Low; 1665 TRACE_SUSIE2("Peek(SPRVPOSL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1666 return retval; 1667 case (SPRVPOSH&0xff): 1668 retval=mSPRVPOS.Byte.High; 1669 TRACE_SUSIE2("Peek(SPRVPOSH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1670 return retval; 1671 case (COLLOFFL&0xff): 1672 retval=mCOLLOFF.Byte.Low; 1673 TRACE_SUSIE2("Peek(COLLOFFL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1674 return retval; 1675 case (COLLOFFH&0xff): 1676 retval=mCOLLOFF.Byte.High; 1677 TRACE_SUSIE2("Peek(COLLOFFH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1678 return retval; 1679 case (VSIZACUML&0xff): 1680 retval=mVSIZACUM.Byte.Low; 1681 TRACE_SUSIE2("Peek(VSIZACUML)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1682 return retval; 1683 case (VSIZACUMH&0xff): 1684 retval=mVSIZACUM.Byte.High; 1685 TRACE_SUSIE2("Peek(VSIZACUMH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1686 return retval; 1687 case (HSIZOFFL&0xff): 1688 retval=mHSIZOFF.Byte.Low; 1689 TRACE_SUSIE2("Peek(HSIZOFFL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1690 return retval; 1691 case (HSIZOFFH&0xff): 1692 retval=mHSIZOFF.Byte.High; 1693 TRACE_SUSIE2("Peek(HSIZOFFH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1694 return retval; 1695 case (VSIZOFFL&0xff): 1696 retval=mVSIZOFF.Byte.Low; 1697 TRACE_SUSIE2("Peek(VSIZOFFL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1698 return retval; 1699 case (VSIZOFFH&0xff): 1700 retval=mVSIZOFF.Byte.High; 1701 TRACE_SUSIE2("Peek(VSIZOFFH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1702 return retval; 1703 case (SCBADRL&0xff): 1704 retval=mSCBADR.Byte.Low; 1705 TRACE_SUSIE2("Peek(SCBADRL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1706 return retval; 1707 case (SCBADRH&0xff): 1708 retval=mSCBADR.Byte.High; 1709 TRACE_SUSIE2("Peek(SCBADRH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1710 return retval; 1711 case (PROCADRL&0xff): 1712 retval=mPROCADR.Byte.Low; 1713 TRACE_SUSIE2("Peek(PROCADRL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1714 return retval; 1715 case (PROCADRH&0xff): 1716 retval=mPROCADR.Byte.High; 1717 TRACE_SUSIE2("Peek(PROCADRH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1718 return retval; 1719 case (MATHD&0xff): 1720 retval=mMATHABCD.Bytes.D; 1721 TRACE_SUSIE2("Peek(MATHD)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1722 return retval; 1723 case (MATHC&0xff): 1724 retval=mMATHABCD.Bytes.C; 1725 TRACE_SUSIE2("Peek(MATHC)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1726 return retval; 1727 case (MATHB&0xff): 1728 retval=mMATHABCD.Bytes.B; 1729 TRACE_SUSIE2("Peek(MATHB)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1730 return retval; 1731 case (MATHA&0xff): 1732 retval=mMATHABCD.Bytes.A; 1733 TRACE_SUSIE2("Peek(MATHA)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1734 return retval; 1735 1736 case (MATHP&0xff): 1737 retval=mMATHNP.Bytes.P; 1738 TRACE_SUSIE2("Peek(MATHP)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1739 return retval; 1740 case (MATHN&0xff): 1741 retval=mMATHNP.Bytes.N; 1742 TRACE_SUSIE2("Peek(MATHN)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1743 return retval; 1744 1745 case (MATHH&0xff): 1746 retval=mMATHEFGH.Bytes.H; 1747 TRACE_SUSIE2("Peek(MATHH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1748 return retval; 1749 case (MATHG&0xff): 1750 retval=mMATHEFGH.Bytes.G; 1751 TRACE_SUSIE2("Peek(MATHG)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1752 return retval; 1753 case (MATHF&0xff): 1754 retval=mMATHEFGH.Bytes.F; 1755 TRACE_SUSIE2("Peek(MATHF)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1756 return retval; 1757 case (MATHE&0xff): 1758 retval=mMATHEFGH.Bytes.E; 1759 TRACE_SUSIE2("Peek(MATHE)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1760 return retval; 1761 case (MATHM&0xff): 1762 retval=mMATHJKLM.Bytes.M; 1763 TRACE_SUSIE2("Peek(MATHM)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1764 return retval; 1765 case (MATHL&0xff): 1766 retval=mMATHJKLM.Bytes.L; 1767 TRACE_SUSIE2("Peek(MATHL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1768 return retval; 1769 case (MATHK&0xff): 1770 retval=mMATHJKLM.Bytes.K; 1771 TRACE_SUSIE2("Peek(MATHK)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1772 return retval; 1773 case (MATHJ&0xff): 1774 retval=mMATHJKLM.Bytes.J; 1775 TRACE_SUSIE2("Peek(MATHJ)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1776 return retval; 1777 case (SUZYHREV&0xff): 1778 retval=0x01; 1779 TRACE_SUSIE2("Peek(SUZYHREV)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1780 return retval; 1781 1782 case (SPRSYS&0xff): 1783 retval=0x0000; 1784 // retval+=(mSPRSYS_Status)?0x0001:0x0000; 1785 // Use gSystemCPUSleep to signal the status instead, if we are asleep then 1786 // we must be rendering sprites 1787 retval+=(gSystemCPUSleep)?0x0001:0x0000; 1788 retval+=(mSPRSYS_StopOnCurrent)?0x0002:0x0000; 1789 retval+=(mSPRSYS_UnsafeAccess)?0x0004:0x0000; 1790 retval+=(mSPRSYS_LeftHand)?0x0008:0x0000; 1791 retval+=(mSPRSYS_VStretch)?0x0010:0x0000; 1792 retval+=(mSPRSYS_LastCarry)?0x0020:0x0000; 1793 retval+=(mSPRSYS_Mathbit)?0x0040:0x0000; 1794 retval+=(mSPRSYS_MathInProgress)?0x0080:0x0000; 1795 TRACE_SUSIE2("Peek(SPRSYS)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1796 return retval; 1797 1798 case (JOYSTICK&0xff): 1799 if(mSPRSYS_LeftHand) { 1800 retval= mJOYSTICK.Byte; 1801 } else { 1802 TJOYSTICK Modified=mJOYSTICK; 1803 Modified.Bits.Left=mJOYSTICK.Bits.Right; 1804 Modified.Bits.Right=mJOYSTICK.Bits.Left; 1805 Modified.Bits.Down=mJOYSTICK.Bits.Up; 1806 Modified.Bits.Up=mJOYSTICK.Bits.Down; 1807 retval= Modified.Byte; 1808 } 1809 // TRACE_SUSIE2("Peek(JOYSTICK)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1810 return retval; 1811 1812 case (SWITCHES&0xff): 1813 retval=mSWITCHES.Byte; 1814 // TRACE_SUSIE2("Peek(SWITCHES)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1815 return retval; 1816 1817 // Cartridge reading ports 1818 1819 case (RCART0&0xff): 1820 if(mSystem.mCart->CartGetAudin() && mSystem.mMikie->SwitchAudInValue()){ 1821 retval=mSystem.mCart->Peek0A(); 1822 }else{ 1823 retval=mSystem.mCart->Peek0(); 1824 } 1825 mSystem.mEEPROM->ProcessEepromCounter(mSystem.mCart->GetCounterValue()); 1826 // TRACE_SUSIE2("Peek(RCART0)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1827 return retval; 1828 case (RCART1&0xff): 1829 if(mSystem.mCart->CartGetAudin() && mSystem.mMikie->SwitchAudInValue()){ 1830 retval=mSystem.mCart->Peek1A(); 1831 }else{ 1832 retval=mSystem.mCart->Peek1(); 1833 } 1834 mSystem.mEEPROM->ProcessEepromCounter(mSystem.mCart->GetCounterValue()); 1835 // TRACE_SUSIE2("Peek(RCART1)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC()); 1836 return retval; 1837 1838 // These are no so important so lets ignore them for the moment 1839 1840 case (LEDS&0xff): 1841 case (PPORTSTAT&0xff): 1842 case (PPORTDATA&0xff): 1843 case (HOWIE&0xff): 1844 TRACE_SUSIE1("Peek(LEDS/PPORTSTAT/PPORTDATA) at PC=$%04x",mSystem.mCpu->GetPC()); 1845 break; 1846 1847 // Errors on write only register accesses 1848 1849 case (SPRCTL0&0xff): 1850 case (SPRCTL1&0xff): 1851 case (SPRCOLL&0xff): 1852 case (SPRINIT&0xff): 1853 case (SUZYBUSEN&0xff): 1854 case (SPRGO&0xff): 1855 TRACE_SUSIE2("Peek(%04x) - Peek from write only register location at PC=$%04x",addr,mSystem.mCpu->GetPC()); 1856 break; 1857 1858 // Errors on illegal location accesses 1859 1860 default: 1861 TRACE_SUSIE2("Peek(%04x) - Peek from illegal location at PC=$%04x",addr,mSystem.mCpu->GetPC()); 1862 break; 1863 } 1864 1865 return 0xff; 1866 }