Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/lynx/susie.cpp
2 views
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 SUSIE_CPP
48
49
//#include <crtdbg.h>
50
//#define TRACE_SUSIE
51
52
#include "system.h"
53
#include "susie.h"
54
#include "lynxdef.h"
55
56
//
57
// As the Susie sprite engine only ever sees system RAM
58
// wa can access this directly without the hassle of
59
// going through the system object, much faster
60
//
61
//#define RAM_PEEK(m) (mSystem.Peek_RAM((m)))
62
//#define RAM_POKE(m1,m2) (mSystem.Poke_RAM((m1),(m2)))
63
//#define RAM_PEEKW(m) (mSystem.PeekW_RAM((m)))
64
65
#define RAM_PEEK(m) (mRamPointer[(m)])
66
#define RAM_PEEKW(m) (mRamPointer[(m)]+(mRamPointer[(m)+1]<<8))
67
#define RAM_POKE(m1,m2) {mRamPointer[(m1)]=(m2);}
68
69
CSusie::CSusie(CSystem& parent)
70
:mSystem(parent)
71
{
72
TRACE_SUSIE0("CSusie()");
73
Reset();
74
}
75
76
CSusie::~CSusie()
77
{
78
TRACE_SUSIE0("~CSusie()");
79
}
80
81
void CSusie::Reset(void)
82
{
83
TRACE_SUSIE0("Reset()");
84
85
// Fetch pointer to system RAM, faster than object access
86
// and seeing as Susie only ever sees RAM.
87
88
mRamPointer=mSystem.GetRamPointer();
89
90
// Reset ALL variables
91
92
mTMPADR.Val16=0;
93
mTILTACUM.Val16=0;
94
mHOFF.Val16=0;
95
mVOFF.Val16=0;
96
mVIDBAS.Val16=0;
97
mCOLLBAS.Val16=0;
98
mVIDADR.Val16=0;
99
mCOLLADR.Val16=0;
100
mSCBNEXT.Val16=0;
101
mSPRDLINE.Val16=0;
102
mHPOSSTRT.Val16=0;
103
mVPOSSTRT.Val16=0;
104
mSPRHSIZ.Val16=0;
105
mSPRVSIZ.Val16=0;
106
mSTRETCH.Val16=0;
107
mTILT.Val16=0;
108
mSPRDOFF.Val16=0;
109
mSPRVPOS.Val16=0;
110
mCOLLOFF.Val16=0;
111
mVSIZACUM.Val16=0;
112
mHSIZACUM.Val16=0;
113
mHSIZOFF.Val16=0x007f;
114
mVSIZOFF.Val16=0x007f;
115
mSCBADR.Val16=0;
116
mPROCADR.Val16=0;
117
118
// Must be initialised to this due to
119
// stun runner math initialisation bug
120
// see whatsnew for 0.7
121
mMATHABCD.Long=0xffffffff;
122
mMATHEFGH.Long=0xffffffff;
123
mMATHJKLM.Long=0xffffffff;
124
mMATHNP.Long=0xffff;
125
126
mMATHAB_sign=1;
127
mMATHCD_sign=1;
128
mMATHEFGH_sign=1;
129
130
mSPRCTL0_Type=0;
131
mSPRCTL0_Vflip=0;
132
mSPRCTL0_Hflip=0;
133
mSPRCTL0_PixelBits=0;
134
135
mSPRCTL1_StartLeft=0;
136
mSPRCTL1_StartUp=0;
137
mSPRCTL1_SkipSprite=0;
138
mSPRCTL1_ReloadPalette=0;
139
mSPRCTL1_ReloadDepth=0;
140
mSPRCTL1_Sizing=0;
141
mSPRCTL1_Literal=0;
142
143
mSPRCOLL_Number=0;
144
mSPRCOLL_Collide=0;
145
146
mSPRSYS_StopOnCurrent=0;
147
mSPRSYS_LeftHand=0;
148
mSPRSYS_VStretch=0;
149
mSPRSYS_NoCollide=0;
150
mSPRSYS_Accumulate=0;
151
mSPRSYS_SignedMath=0;
152
mSPRSYS_Status=0;
153
mSPRSYS_UnsafeAccess=0;
154
mSPRSYS_LastCarry=0;
155
mSPRSYS_Mathbit=0;
156
mSPRSYS_MathInProgress=0;
157
158
mSUZYBUSEN=FALSE;
159
160
mSPRINIT.Byte=0;
161
162
mSPRGO=FALSE;
163
mEVERON=FALSE;
164
165
for(int loop=0;loop<16;loop++) mPenIndex[loop]=loop;
166
167
hquadoff = vquadoff = 0;
168
169
mJOYSTICK.Byte=0;
170
mSWITCHES.Byte=0;
171
}
172
173
174
void CSusie::DoMathMultiply(void)
175
{
176
mSPRSYS_Mathbit=FALSE;
177
178
// Multiplies with out sign or accumulate take 44 ticks to complete.
179
// Multiplies with sign and accumulate take 54 ticks to complete.
180
//
181
// AB EFGH
182
// * CD / NP
183
// ------- -----------
184
// EFGH ABCD
185
// Accumulate in JKLM Remainder in (JK)LM
186
//
187
188
189
uint32 result;
190
191
// Basic multiply is ALWAYS unsigned, sign conversion is done later
192
result=(uint32)mMATHABCD.Words.AB*(uint32)mMATHABCD.Words.CD;
193
mMATHEFGH.Long=result;
194
195
if(mSPRSYS_SignedMath)
196
{
197
TRACE_SUSIE0("DoMathMultiply() - SIGNED");
198
// Add the sign bits, only >0 is +ve result
199
mMATHEFGH_sign=mMATHAB_sign+mMATHCD_sign;
200
if(!mMATHEFGH_sign)
201
{
202
mMATHEFGH.Long^=0xffffffff;
203
mMATHEFGH.Long++;
204
}
205
}
206
else
207
{
208
TRACE_SUSIE0("DoMathMultiply() - UNSIGNED");
209
}
210
211
TRACE_SUSIE2("DoMathMultiply() AB=$%04x * CD=$%04x",mMATHABCD.Words.AB,mMATHABCD.Words.CD);
212
213
// Check overflow, if B31 has changed from 1->0 then its overflow time
214
if(mSPRSYS_Accumulate)
215
{
216
TRACE_SUSIE0("DoMathMultiply() - ACCUMULATED JKLM+=EFGH");
217
uint32 tmp=mMATHJKLM.Long+mMATHEFGH.Long;
218
// Let sign change indicate overflow
219
if((tmp&0x80000000)!=(mMATHJKLM.Long&0x80000000))
220
{
221
TRACE_SUSIE0("DoMathMultiply() - OVERFLOW DETECTED");
222
// mSPRSYS_Mathbit=TRUE;
223
}
224
else
225
{
226
// mSPRSYS_Mathbit=FALSE;
227
}
228
// Save accumulated result
229
mMATHJKLM.Long=tmp;
230
}
231
232
TRACE_SUSIE1("DoMathMultiply() Results (raw - no sign) Result=$%08x",result);
233
TRACE_SUSIE1("DoMathMultiply() Results (Multi) EFGH=$%08x",mMATHEFGH.Long);
234
TRACE_SUSIE1("DoMathMultiply() Results (Accum) JKLM=$%08x",mMATHJKLM.Long);
235
}
236
237
void CSusie::DoMathDivide(void)
238
{
239
mSPRSYS_Mathbit=FALSE;
240
241
//
242
// Divides take 176 + 14*N ticks
243
// (N is the number of most significant zeros in the divisor.)
244
//
245
// AB EFGH
246
// * CD / NP
247
// ------- -----------
248
// EFGH ABCD
249
// Accumulate in JKLM Remainder in (JK)LM
250
//
251
252
// Divide is ALWAYS unsigned arithmetic...
253
if(mMATHNP.Long)
254
{
255
TRACE_SUSIE0("DoMathDivide() - UNSIGNED");
256
mMATHABCD.Long=mMATHEFGH.Long/mMATHNP.Long;
257
mMATHJKLM.Long=mMATHEFGH.Long%mMATHNP.Long;
258
}
259
else
260
{
261
TRACE_SUSIE0("DoMathDivide() - DIVIDE BY ZERO ERROR");
262
mMATHABCD.Long=0xffffffff;
263
mMATHJKLM.Long=0;
264
mSPRSYS_Mathbit=TRUE;
265
}
266
TRACE_SUSIE2("DoMathDivide() EFGH=$%08x / NP=%04x",mMATHEFGH.Long,mMATHNP.Long);
267
TRACE_SUSIE1("DoMathDivide() Results (div) ABCD=$%08x",mMATHABCD.Long);
268
TRACE_SUSIE1("DoMathDivide() Results (mod) JKLM=$%08x",mMATHJKLM.Long);
269
}
270
271
272
uint32 CSusie::PaintSprites(void)
273
{
274
int sprcount=0;
275
int data=0;
276
int everonscreen=0;
277
278
TRACE_SUSIE0(" ");
279
TRACE_SUSIE0(" ");
280
TRACE_SUSIE0(" ");
281
TRACE_SUSIE0("**************************************************************");
282
TRACE_SUSIE0("********************** PaintSprites **************************");
283
TRACE_SUSIE0("**************************************************************");
284
TRACE_SUSIE0(" ");
285
286
TRACE_SUSIE1("PaintSprites() VIDBAS $%04x",mVIDBAS.Val16);
287
TRACE_SUSIE1("PaintSprites() COLLBAS $%04x",mCOLLBAS.Val16);
288
TRACE_SUSIE1("PaintSprites() SPRSYS $%02x",Peek(SPRSYS));
289
290
if(!mSUZYBUSEN || !mSPRGO)
291
{
292
TRACE_SUSIE0("PaintSprites() Returned !mSUZYBUSEN || !mSPRGO");
293
return 0;
294
}
295
296
cycles_used=0;
297
298
do
299
{
300
everonscreen = 0;
301
302
TRACE_SUSIE1("PaintSprites() ************ Rendering Sprite %03d ************",sprcount);
303
304
// Step 1 load up the SCB params into Susie
305
306
// And thus it is documented that only the top byte of SCBNEXT is used.
307
// Its mentioned under the bits that are broke section in the bluebook
308
if(!(mSCBNEXT.Val16&0xff00))
309
{
310
TRACE_SUSIE0("PaintSprites() mSCBNEXT==0 - FINISHED");
311
mSPRSYS_Status=0; // Engine has finished
312
mSPRGO=FALSE;
313
break;
314
}
315
else
316
{
317
mSPRSYS_Status=1;
318
}
319
320
mTMPADR.Val16=mSCBNEXT.Val16; // Copy SCB pointer
321
mSCBADR.Val16=mSCBNEXT.Val16; // Copy SCB pointer
322
TRACE_SUSIE1("PaintSprites() SCBADDR $%04x",mSCBADR.Val16);
323
324
data=RAM_PEEK(mTMPADR.Val16); // Fetch control 0
325
TRACE_SUSIE1("PaintSprites() SPRCTL0 $%02x",data);
326
mSPRCTL0_Type=data&0x0007;
327
mSPRCTL0_Vflip=data&0x0010;
328
mSPRCTL0_Hflip=data&0x0020;
329
mSPRCTL0_PixelBits=((data&0x00c0)>>6)+1;
330
mTMPADR.Val16+=1;
331
332
data=RAM_PEEK(mTMPADR.Val16); // Fetch control 1
333
TRACE_SUSIE1("PaintSprites() SPRCTL1 $%02x",data);
334
mSPRCTL1_StartLeft=data&0x0001;
335
mSPRCTL1_StartUp=data&0x0002;
336
mSPRCTL1_SkipSprite=data&0x0004;
337
mSPRCTL1_ReloadPalette=data&0x0008;
338
mSPRCTL1_ReloadDepth=(data&0x0030)>>4;
339
mSPRCTL1_Sizing=data&0x0040;
340
mSPRCTL1_Literal=data&0x0080;
341
mTMPADR.Val16+=1;
342
343
data=RAM_PEEK(mTMPADR.Val16); // Collision num
344
TRACE_SUSIE1("PaintSprites() SPRCOLL $%02x",data);
345
mSPRCOLL_Number=data&0x000f;
346
mSPRCOLL_Collide=data&0x0020;
347
mTMPADR.Val16+=1;
348
349
mSCBNEXT.Val16=RAM_PEEKW(mTMPADR.Val16); // Next SCB
350
TRACE_SUSIE1("PaintSprites() SCBNEXT $%04x",mSCBNEXT.Val16);
351
mTMPADR.Val16+=2;
352
353
cycles_used+=5*SPR_RDWR_CYC;
354
355
// Initialise the collision depositary
356
357
// Although Tom Schenck says this is correct, it doesnt appear to be
358
// if(!mSPRCOLL_Collide && !mSPRSYS_NoCollide)
359
// {
360
// mCollision=RAM_PEEK((mSCBADR.Val16+mCOLLOFF.Val16)&0xffff);
361
// mCollision&=0x0f;
362
// }
363
mCollision=0;
364
365
// Check if this is a skip sprite
366
367
if(!mSPRCTL1_SkipSprite)
368
{
369
370
mSPRDLINE.Val16=RAM_PEEKW(mTMPADR.Val16); // Sprite pack data
371
TRACE_SUSIE1("PaintSprites() SPRDLINE $%04x",mSPRDLINE.Val16);
372
mTMPADR.Val16+=2;
373
374
mHPOSSTRT.Val16=RAM_PEEKW(mTMPADR.Val16); // Sprite horizontal start position
375
TRACE_SUSIE1("PaintSprites() HPOSSTRT $%04x",mHPOSSTRT.Val16);
376
mTMPADR.Val16+=2;
377
378
mVPOSSTRT.Val16=RAM_PEEKW(mTMPADR.Val16); // Sprite vertical start position
379
TRACE_SUSIE1("PaintSprites() VPOSSTRT $%04x",mVPOSSTRT.Val16);
380
mTMPADR.Val16+=2;
381
382
cycles_used+=6*SPR_RDWR_CYC;
383
384
bool enable_sizing=FALSE;
385
bool enable_stretch=FALSE;
386
bool enable_tilt=FALSE;
387
388
// Optional section defined by reload type in Control 1
389
390
TRACE_SUSIE1("PaintSprites() mSPRCTL1.Bits.ReloadDepth=%d",mSPRCTL1_ReloadDepth);
391
switch(mSPRCTL1_ReloadDepth)
392
{
393
case 1:
394
TRACE_SUSIE0("PaintSprites() Sizing Enabled");
395
enable_sizing=TRUE;
396
397
mSPRHSIZ.Val16=RAM_PEEKW(mTMPADR.Val16); // Sprite Horizontal size
398
mTMPADR.Val16+=2;
399
400
mSPRVSIZ.Val16=RAM_PEEKW(mTMPADR.Val16); // Sprite Verticalal size
401
mTMPADR.Val16+=2;
402
403
cycles_used+=4*SPR_RDWR_CYC;
404
break;
405
406
case 2:
407
TRACE_SUSIE0("PaintSprites() Sizing Enabled");
408
TRACE_SUSIE0("PaintSprites() Stretch Enabled");
409
enable_sizing=TRUE;
410
enable_stretch=TRUE;
411
412
mSPRHSIZ.Val16=RAM_PEEKW(mTMPADR.Val16); // Sprite Horizontal size
413
mTMPADR.Val16+=2;
414
415
mSPRVSIZ.Val16=RAM_PEEKW(mTMPADR.Val16); // Sprite Verticalal size
416
mTMPADR.Val16+=2;
417
418
mSTRETCH.Val16=RAM_PEEKW(mTMPADR.Val16); // Sprite stretch
419
mTMPADR.Val16+=2;
420
421
cycles_used+=6*SPR_RDWR_CYC;
422
break;
423
424
case 3:
425
TRACE_SUSIE0("PaintSprites() Sizing Enabled");
426
TRACE_SUSIE0("PaintSprites() Stretch Enabled");
427
TRACE_SUSIE0("PaintSprites() Tilt Enabled");
428
enable_sizing=TRUE;
429
enable_stretch=TRUE;
430
enable_tilt=TRUE;
431
432
mSPRHSIZ.Val16=RAM_PEEKW(mTMPADR.Val16); // Sprite Horizontal size
433
mTMPADR.Val16+=2;
434
435
mSPRVSIZ.Val16=RAM_PEEKW(mTMPADR.Val16); // Sprite Verticalal size
436
mTMPADR.Val16+=2;
437
438
mSTRETCH.Val16=RAM_PEEKW(mTMPADR.Val16); // Sprite stretch
439
mTMPADR.Val16+=2;
440
441
mTILT.Val16=RAM_PEEKW(mTMPADR.Val16); // Sprite tilt
442
mTMPADR.Val16+=2;
443
444
cycles_used+=8*SPR_RDWR_CYC;
445
break;
446
447
default:
448
break;
449
}
450
451
TRACE_SUSIE1("PaintSprites() SPRHSIZ $%04x",mSPRHSIZ.Val16);
452
TRACE_SUSIE1("PaintSprites() SPRVSIZ $%04x",mSPRVSIZ.Val16);
453
TRACE_SUSIE1("PaintSprites() STRETCH $%04x",mSTRETCH.Val16);
454
TRACE_SUSIE1("PaintSprites() TILT $%04x",mTILT.Val16);
455
456
457
// Optional Palette reload
458
459
if(!mSPRCTL1_ReloadPalette)
460
{
461
TRACE_SUSIE0("PaintSprites() Palette reloaded");
462
for(int loop=0;loop<8;loop++)
463
{
464
uint8 data_tmp = RAM_PEEK(mTMPADR.Val16++);
465
mPenIndex[loop*2]=(data_tmp>>4)&0x0f;
466
mPenIndex[(loop*2)+1]=data_tmp&0x0f;
467
}
468
// Increment cycle count for the reads
469
cycles_used+=8*SPR_RDWR_CYC;
470
}
471
472
// Now we can start painting
473
474
// Quadrant drawing order is: SE,NE,NW,SW
475
// start quadrant is given by sprite_control1:0 & 1
476
477
// Setup screen start end variables
478
479
int screen_h_start=(int16)mHOFF.Val16;
480
int screen_h_end=(int16)mHOFF.Val16+SCREEN_WIDTH;
481
int screen_v_start=(int16)mVOFF.Val16;
482
int screen_v_end=(int16)mVOFF.Val16+SCREEN_HEIGHT;
483
484
int world_h_mid=screen_h_start+0x8000+(SCREEN_WIDTH/2);
485
int world_v_mid=screen_v_start+0x8000+(SCREEN_HEIGHT/2);
486
487
TRACE_SUSIE2("PaintSprites() screen_h_start $%04x screen_h_end $%04x",screen_h_start,screen_h_end);
488
TRACE_SUSIE2("PaintSprites() screen_v_start $%04x screen_v_end $%04x",screen_v_start,screen_v_end);
489
TRACE_SUSIE2("PaintSprites() world_h_mid $%04x world_v_mid $%04x",world_h_mid,world_v_mid);
490
491
bool superclip=FALSE;
492
int quadrant=0;
493
int hsign,vsign;
494
495
if(mSPRCTL1_StartLeft)
496
{
497
if(mSPRCTL1_StartUp) quadrant=2; else quadrant=3;
498
}
499
else
500
{
501
if(mSPRCTL1_StartUp) quadrant=1; else quadrant=0;
502
}
503
TRACE_SUSIE1("PaintSprites() Quadrant=%d",quadrant);
504
505
// Check ref is inside screen area
506
507
//if((int16)mHPOSSTRT.Val16<screen_h_start || (int16)mHPOSSTRT.Val16>=screen_h_end ||
508
// (int16)mVPOSSTRT.Val16<screen_v_start || (int16)mVPOSSTRT.Val16>=screen_v_end) superclip=TRUE;
509
510
TRACE_SUSIE1("PaintSprites() Superclip=%d",superclip);
511
512
513
// Quadrant mapping is: SE NE NW SW
514
// 0 1 2 3
515
// hsign +1 +1 -1 -1
516
// vsign +1 -1 -1 +1
517
//
518
//
519
// 2 | 1
520
// -------
521
// 3 | 0
522
//
523
524
// Loop for 4 quadrants
525
526
for(int loop=0;loop<4;loop++)
527
{
528
TRACE_SUSIE1("PaintSprites() -------- Rendering Quadrant %03d --------",quadrant);
529
530
int sprite_v=mVPOSSTRT.Val16;
531
int sprite_h=mHPOSSTRT.Val16;
532
533
bool render=FALSE;
534
535
// Set quadrand multipliers
536
hsign=(quadrant==0 || quadrant==1)?1:-1;
537
vsign=(quadrant==0 || quadrant==3)?1:-1;
538
539
// Preflip TRACE_SUSIE2("PaintSprites() hsign=%d vsign=%d",hsign,vsign);
540
541
//Use h/v flip to invert v/hsign
542
543
if(mSPRCTL0_Vflip) vsign=-vsign;
544
if(mSPRCTL0_Hflip) hsign=-hsign;
545
546
TRACE_SUSIE2("PaintSprites() Hflip=%d Vflip=%d",mSPRCTL0_Hflip,mSPRCTL0_Vflip);
547
TRACE_SUSIE2("PaintSprites() Hsign=%d Vsign=%d",hsign,vsign);
548
TRACE_SUSIE2("PaintSprites() Hpos =%04x Vpos =%04x",mHPOSSTRT.Val16,mVPOSSTRT.Val16);
549
TRACE_SUSIE2("PaintSprites() Hsizoff =%04x Vsizoff =%04x",mHSIZOFF.Val16,mVSIZOFF.Val16);
550
551
// Two different rendering algorithms used, on-screen & superclip
552
// when on screen we draw in x until off screen then skip to next
553
// line, BUT on superclip we draw all the way to the end of any
554
// given line checking each pixel is on screen.
555
556
if(superclip)
557
{
558
// Check on the basis of each quad, we only render the quad
559
// IF the screen is in the quad, relative to the centre of
560
// the screen which is calculated below.
561
562
// Quadrant mapping is: SE NE NW SW
563
// 0 1 2 3
564
// hsign +1 +1 -1 -1
565
// vsign +1 -1 -1 +1
566
//
567
//
568
// 2 | 1
569
// -------
570
// 3 | 0
571
//
572
// Quadrant mapping for superclipping must also take into account
573
// the hflip, vflip bits & negative tilt to be able to work correctly
574
//
575
int modquad=quadrant;
576
static const int vquadflip[4]={1,0,3,2};
577
static const int hquadflip[4]={3,2,1,0};
578
579
if(mSPRCTL0_Vflip) modquad=vquadflip[modquad];
580
if(mSPRCTL0_Hflip) modquad=hquadflip[modquad];
581
582
// This is causing Eurosoccer to fail!!
583
//if(enable_tilt && mTILT.Val16&0x8000) modquad=hquadflip[modquad];
584
//if(quadrant == 0 && sprite_v == 219 && sprite_h == 890)
585
//printf("%d:%d %d %d\n", quadrant, modquad, sprite_h, sprite_v);
586
587
switch(modquad)
588
{
589
case 3:
590
if((sprite_h>=screen_h_start || sprite_h<world_h_mid) && (sprite_v<screen_v_end || sprite_v>world_v_mid)) render=TRUE;
591
break;
592
case 2:
593
if((sprite_h>=screen_h_start || sprite_h<world_h_mid) && (sprite_v>=screen_v_start || sprite_v<world_v_mid)) render=TRUE;
594
break;
595
case 1:
596
if((sprite_h<screen_h_end || sprite_h>world_h_mid) && (sprite_v>=screen_v_start || sprite_v<world_v_mid)) render=TRUE;
597
break;
598
default:
599
if((sprite_h<screen_h_end || sprite_h>world_h_mid) && (sprite_v<screen_v_end || sprite_v>world_v_mid)) render=TRUE;
600
break;
601
}
602
}
603
else
604
{
605
render=TRUE;
606
}
607
608
// Is this quad to be rendered ??
609
610
TRACE_SUSIE1("PaintSprites() Render status %d",render);
611
612
int pixel_height;
613
int pixel_width;
614
int pixel;
615
int hoff,voff;
616
int hloop,vloop;
617
bool onscreen;
618
619
if(render)
620
{
621
// Set the vertical position & offset
622
voff=(int16)mVPOSSTRT.Val16-screen_v_start;
623
624
// Zero the stretch,tilt & acum values
625
mTILTACUM.Val16=0;
626
627
// Perform the SIZOFF
628
if(vsign==1) mVSIZACUM.Val16=mVSIZOFF.Val16; else mVSIZACUM.Val16=0;
629
630
// Take the sign of the first quad (0) as the basic
631
// sign, all other quads drawing in the other direction
632
// get offset by 1 pixel in the other direction, this
633
// fixes the squashed look on the multi-quad sprites.
634
// if(vsign==-1 && loop>0) voff+=vsign;
635
if(loop==0) vquadoff=vsign;
636
if(vsign!=vquadoff) voff+=vsign;
637
638
for(;;)
639
{
640
// Vertical scaling is done here
641
mVSIZACUM.Val16+=mSPRVSIZ.Val16;
642
pixel_height=mVSIZACUM.Union8.High;
643
mVSIZACUM.Union8.High=0;
644
645
// Update the next data line pointer and initialise our line
646
mSPRDOFF.Val16=(uint16)LineInit(0);
647
648
// If 1 == next quad, ==0 end of sprite, anyways its END OF LINE
649
if(mSPRDOFF.Val16==1) // End of quad
650
{
651
mSPRDLINE.Val16+=mSPRDOFF.Val16;
652
break;
653
}
654
655
if(mSPRDOFF.Val16==0) // End of sprite
656
{
657
loop=4; // Halt the quad loop
658
break;
659
}
660
661
// Draw one horizontal line of the sprite
662
for(vloop=0;vloop<pixel_height;vloop++)
663
{
664
// Early bailout if the sprite has moved off screen, terminate quad
665
if(vsign==1 && voff>=SCREEN_HEIGHT) break;
666
if(vsign==-1 && voff<0) break;
667
668
// Only allow the draw to take place if the line is visible
669
if(voff>=0 && voff<SCREEN_HEIGHT)
670
{
671
// Work out the horizontal pixel start position, start + tilt
672
mHPOSSTRT.Val16+=((int16)mTILTACUM.Val16>>8);
673
mTILTACUM.Union8.High=0;
674
hoff=(int)((int16)mHPOSSTRT.Val16)-screen_h_start;
675
676
// Zero/Force the horizontal scaling accumulator
677
if(hsign==1) mHSIZACUM.Val16=mHSIZOFF.Val16; else mHSIZACUM.Val16=0;
678
679
// Take the sign of the first quad (0) as the basic
680
// sign, all other quads drawing in the other direction
681
// get offset by 1 pixel in the other direction, this
682
// fixes the squashed look on the multi-quad sprites.
683
// if(hsign==-1 && loop>0) hoff+=hsign;
684
if(loop==0) hquadoff=hsign;
685
if(hsign!=hquadoff) hoff+=hsign;
686
687
// Initialise our line
688
LineInit(voff);
689
onscreen=FALSE;
690
691
// Now render an individual destination line
692
while((pixel=LineGetPixel())!=LINE_END)
693
{
694
// This is allowed to update every pixel
695
mHSIZACUM.Val16+=mSPRHSIZ.Val16;
696
pixel_width=mHSIZACUM.Union8.High;
697
mHSIZACUM.Union8.High=0;
698
699
for(hloop=0;hloop<pixel_width;hloop++)
700
{
701
// Draw if onscreen but break loop on transition to offscreen
702
if(hoff>=0 && hoff<SCREEN_WIDTH)
703
{
704
ProcessPixel(hoff,pixel);
705
onscreen = TRUE;
706
everonscreen = TRUE;
707
}
708
else
709
{
710
if(onscreen) break;
711
}
712
hoff+=hsign;
713
}
714
}
715
}
716
voff+=vsign;
717
718
// For every destination line we can modify SPRHSIZ & SPRVSIZ & TILTACUM
719
if(enable_stretch)
720
{
721
mSPRHSIZ.Val16+=mSTRETCH.Val16;
722
// if(mSPRSYS_VStretch) mSPRVSIZ.Val16+=mSTRETCH.Val16;
723
}
724
if(enable_tilt)
725
{
726
// Manipulate the tilt stuff
727
mTILTACUM.Val16+=mTILT.Val16;
728
}
729
}
730
// According to the docs this increments per dest line
731
// but only gets set when the source line is read
732
if(mSPRSYS_VStretch) mSPRVSIZ.Val16+=mSTRETCH.Val16*pixel_height;
733
734
// Update the line start for our next run thru the loop
735
mSPRDLINE.Val16+=mSPRDOFF.Val16;
736
}
737
}
738
else
739
{
740
// Skip thru data to next quad
741
for(;;)
742
{
743
// Read the start of line offset
744
745
mSPRDOFF.Val16=(uint16)LineInit(0);
746
747
// We dont want to process data so mSPRDLINE is useless to us
748
mSPRDLINE.Val16+=mSPRDOFF.Val16;
749
750
// If 1 == next quad, ==0 end of sprite, anyways its END OF LINE
751
752
if(mSPRDOFF.Val16==1) break; // End of quad
753
if(mSPRDOFF.Val16==0) // End of sprite
754
{
755
loop=4; // Halt the quad loop
756
break;
757
}
758
759
}
760
}
761
762
// Increment quadrant and mask to 2 bit value (0-3)
763
quadrant++;
764
quadrant&=0x03;
765
}
766
767
// Write the collision depositary if required
768
769
if(!mSPRCOLL_Collide && !mSPRSYS_NoCollide)
770
{
771
switch(mSPRCTL0_Type)
772
{
773
case sprite_xor_shadow:
774
case sprite_boundary:
775
case sprite_normal:
776
case sprite_boundary_shadow:
777
case sprite_shadow:
778
{
779
uint16 coldep=mSCBADR.Val16+mCOLLOFF.Val16;
780
RAM_POKE(coldep,(uint8)mCollision);
781
TRACE_SUSIE2("PaintSprites() COLLOFF=$%04x SCBADR=$%04x",mCOLLOFF.Val16,mSCBADR.Val16);
782
TRACE_SUSIE2("PaintSprites() Wrote $%02x to SCB collision depositary at $%04x",(uint8)mCollision,coldep);
783
}
784
break;
785
default:
786
break;
787
}
788
}
789
790
if(mEVERON)
791
{
792
uint16 coldep=mSCBADR.Val16+mCOLLOFF.Val16;
793
uint8 coldat=RAM_PEEK(coldep);
794
if(!everonscreen) coldat|=0x80; else coldat&=0x7f;
795
RAM_POKE(coldep,coldat);
796
TRACE_SUSIE0("PaintSprites() EVERON IS ACTIVE");
797
TRACE_SUSIE2("PaintSprites() Wrote $%02x to SCB collision depositary at $%04x",coldat,coldep);
798
}
799
}
800
else
801
{
802
TRACE_SUSIE0("PaintSprites() mSPRCTL1.Bits.SkipSprite==TRUE");
803
}
804
805
// Increase sprite number
806
sprcount++;
807
808
// Check if we abort after 1st sprite is complete
809
810
// if(mSPRSYS.Read.StopOnCurrent)
811
// {
812
// mSPRSYS.Read.Status=0; // Engine has finished
813
// mSPRGO=FALSE;
814
// break;
815
// }
816
817
// Check sprcount for looping SCB, random large number chosen
818
if(sprcount>4096)
819
{
820
// Stop the system, otherwise we may just come straight back in.....
821
mSystem.gSystemHalt=TRUE;
822
// Display warning message
823
//gError->Warning("CSusie:PaintSprites(): Single draw sprite limit exceeded (>4096). The SCB is most likely looped back on itself. Reset/Exit is recommended");
824
// Signal error to the caller
825
return 0;
826
}
827
}
828
while(1);
829
830
// Fudge factor to fix many flickering issues, also the keypress
831
// problem with Hard Drivin and the strange pause in Dirty Larry.
832
//cycles_used>>=2;
833
return cycles_used;
834
}
835
836
837
INLINE void CSusie::WritePixel(uint32 hoff,uint32 pixel)
838
{
839
uint32 scr_addr=mLineBaseAddress+(hoff/2);
840
841
uint8 dest=RAM_PEEK(scr_addr);
842
if(!(hoff&0x01))
843
{
844
// Upper nibble screen write
845
dest&=0x0f;
846
dest|=pixel<<4;
847
}
848
else
849
{
850
// Lower nibble screen write
851
dest&=0xf0;
852
dest|=pixel;
853
}
854
RAM_POKE(scr_addr,dest);
855
856
// Increment cycle count for the read/modify/write
857
cycles_used+=2*SPR_RDWR_CYC;
858
}
859
860
INLINE uint32 CSusie::ReadPixel(uint32 hoff)
861
{
862
uint32 scr_addr=mLineBaseAddress+(hoff/2);
863
864
uint32 data=RAM_PEEK(scr_addr);
865
if(!(hoff&0x01))
866
{
867
// Upper nibble read
868
data>>=4;
869
}
870
else
871
{
872
// Lower nibble read
873
data&=0x0f;
874
}
875
876
// Increment cycle count for the read/modify/write
877
cycles_used+=SPR_RDWR_CYC;
878
879
return data;
880
}
881
882
INLINE void CSusie::WriteCollision(uint32 hoff,uint32 pixel)
883
{
884
uint32 col_addr=mLineCollisionAddress+(hoff/2);
885
886
uint8 dest=RAM_PEEK(col_addr);
887
if(!(hoff&0x01))
888
{
889
// Upper nibble screen write
890
dest&=0x0f;
891
dest|=pixel<<4;
892
}
893
else
894
{
895
// Lower nibble screen write
896
dest&=0xf0;
897
dest|=pixel;
898
}
899
RAM_POKE(col_addr,dest);
900
901
// Increment cycle count for the read/modify/write
902
cycles_used+=2*SPR_RDWR_CYC;
903
}
904
905
INLINE uint32 CSusie::ReadCollision(uint32 hoff)
906
{
907
uint32 col_addr=mLineCollisionAddress+(hoff/2);
908
909
uint32 data=RAM_PEEK(col_addr);
910
if(!(hoff&0x01))
911
{
912
// Upper nibble read
913
data>>=4;
914
}
915
else
916
{
917
// Lower nibble read
918
data&=0x0f;
919
}
920
921
// Increment cycle count for the read/modify/write
922
cycles_used+=SPR_RDWR_CYC;
923
924
return data;
925
}
926
927
928
INLINE uint32 CSusie::LineGetBits(uint32 bits)
929
{
930
uint32 retval;
931
932
// Sanity, not really needed
933
// if(bits>32) return 0;
934
935
// Only return data IF there is enought bits left in the packet
936
937
//if(mLinePacketBitsLeft<bits) return 0;
938
if(mLinePacketBitsLeft<=bits) return 0; // Hardware bug(<= instead of <), apparently
939
940
// Make sure shift reg has enough bits to fulfil the request
941
942
if(mLineShiftRegCount<bits)
943
{
944
// This assumes data comes into LSB and out of MSB
945
// mLineShiftReg&=0x000000ff; // Has no effect
946
mLineShiftReg<<=24;
947
mLineShiftReg|=RAM_PEEK(mTMPADR.Val16++)<<16;
948
mLineShiftReg|=RAM_PEEK(mTMPADR.Val16++)<<8;
949
mLineShiftReg|=RAM_PEEK(mTMPADR.Val16++);
950
951
mLineShiftRegCount+=24;
952
953
// Increment cycle count for the read
954
cycles_used+=3*SPR_RDWR_CYC;
955
}
956
957
// Extract the return value
958
retval=mLineShiftReg>>(mLineShiftRegCount-bits);
959
retval&=(1<<bits)-1;
960
961
// Update internal vars;
962
mLineShiftRegCount-=bits;
963
mLinePacketBitsLeft-=bits;
964
965
return retval;
966
}
967
968
969
970
//
971
// Collision code modified by KW 22/11/98
972
// Collision buffer cler added if there is no
973
// apparent collision, I have a gut feeling this
974
// is the wrong solution to the inv07.com bug but
975
// it seems to work OK.
976
//
977
// Shadow-------------------------------|
978
// Boundary-Shadow--------------------| |
979
// Normal---------------------------| | |
980
// Boundary-----------------------| | | |
981
// Background-Shadow------------| | | | |
982
// Background-No Collision----| | | | | |
983
// Non-Collideable----------| | | | | | |
984
// Exclusive-or-Shadow----| | | | | | | |
985
// | | | | | | | |
986
// 1 1 1 1 0 1 0 1 F is opaque
987
// 0 0 0 0 1 1 0 0 E is collideable
988
// 0 0 1 1 0 0 0 0 0 is opaque and collideable
989
// 1 0 0 0 1 1 1 1 allow collision detect
990
// 1 0 0 1 1 1 1 1 allow coll. buffer access
991
// 1 0 0 0 0 0 0 0 exclusive-or the data
992
//
993
994
//inline
995
void CSusie::ProcessPixel(uint32 hoff,uint32 pixel)
996
{
997
switch(mSPRCTL0_Type)
998
{
999
// BACKGROUND SHADOW
1000
// 1 F is opaque
1001
// 0 E is collideable
1002
// 1 0 is opaque and collideable
1003
// 0 allow collision detect
1004
// 1 allow coll. buffer access
1005
// 0 exclusive-or the data
1006
case sprite_background_shadow:
1007
WritePixel(hoff,pixel);
1008
if(!mSPRCOLL_Collide && !mSPRSYS_NoCollide && pixel!=0x0e)
1009
{
1010
WriteCollision(hoff,mSPRCOLL_Number);
1011
}
1012
break;
1013
1014
// BACKGROUND NOCOLLIDE
1015
// 1 F is opaque
1016
// 0 E is collideable
1017
// 1 0 is opaque and collideable
1018
// 0 allow collision detect
1019
// 0 allow coll. buffer access
1020
// 0 exclusive-or the data
1021
case sprite_background_noncollide:
1022
WritePixel(hoff,pixel);
1023
break;
1024
1025
// NOCOLLIDE
1026
// 1 F is opaque
1027
// 0 E is collideable
1028
// 0 0 is opaque and collideable
1029
// 0 allow collision detect
1030
// 0 allow coll. buffer access
1031
// 0 exclusive-or the data
1032
case sprite_noncollide:
1033
if(pixel!=0x00) WritePixel(hoff,pixel);
1034
break;
1035
1036
// BOUNDARY
1037
// 0 F is opaque
1038
// 1 E is collideable
1039
// 0 0 is opaque and collideable
1040
// 1 allow collision detect
1041
// 1 allow coll. buffer access
1042
// 0 exclusive-or the data
1043
case sprite_boundary:
1044
if(pixel!=0x00 && pixel!=0x0f)
1045
{
1046
WritePixel(hoff,pixel);
1047
}
1048
if(pixel!=0x00)
1049
{
1050
if(!mSPRCOLL_Collide && !mSPRSYS_NoCollide)
1051
{
1052
int collision=ReadCollision(hoff);
1053
if(collision>mCollision)
1054
{
1055
mCollision=collision;
1056
}
1057
// 01/05/00 V0.7 if(mSPRCOLL_Number>collision)
1058
{
1059
WriteCollision(hoff,mSPRCOLL_Number);
1060
}
1061
}
1062
}
1063
break;
1064
1065
// NORMAL
1066
// 1 F is opaque
1067
// 1 E is collideable
1068
// 0 0 is opaque and collideable
1069
// 1 allow collision detect
1070
// 1 allow coll. buffer access
1071
// 0 exclusive-or the data
1072
case sprite_normal:
1073
if(pixel!=0x00)
1074
{
1075
WritePixel(hoff,pixel);
1076
if(!mSPRCOLL_Collide && !mSPRSYS_NoCollide)
1077
{
1078
int collision=ReadCollision(hoff);
1079
if(collision>mCollision)
1080
{
1081
mCollision=collision;
1082
}
1083
// 01/05/00 V0.7 if(mSPRCOLL_Number>collision)
1084
{
1085
WriteCollision(hoff,mSPRCOLL_Number);
1086
}
1087
}
1088
}
1089
break;
1090
1091
// BOUNDARY_SHADOW
1092
// 0 F is opaque
1093
// 0 E is collideable
1094
// 0 0 is opaque and collideable
1095
// 1 allow collision detect
1096
// 1 allow coll. buffer access
1097
// 0 exclusive-or the data
1098
case sprite_boundary_shadow:
1099
if(pixel!=0x00 && pixel!=0x0e && pixel!=0x0f)
1100
{
1101
WritePixel(hoff,pixel);
1102
}
1103
if(pixel!=0x00 && pixel!=0x0e)
1104
{
1105
if(!mSPRCOLL_Collide && !mSPRSYS_NoCollide)
1106
{
1107
int collision=ReadCollision(hoff);
1108
if(collision>mCollision)
1109
{
1110
mCollision=collision;
1111
}
1112
// 01/05/00 V0.7 if(mSPRCOLL_Number>collision)
1113
{
1114
WriteCollision(hoff,mSPRCOLL_Number);
1115
}
1116
}
1117
}
1118
break;
1119
1120
// SHADOW
1121
// 1 F is opaque
1122
// 0 E is collideable
1123
// 0 0 is opaque and collideable
1124
// 1 allow collision detect
1125
// 1 allow coll. buffer access
1126
// 0 exclusive-or the data
1127
case sprite_shadow:
1128
if(pixel!=0x00)
1129
{
1130
WritePixel(hoff,pixel);
1131
}
1132
if(pixel!=0x00 && pixel!=0x0e)
1133
{
1134
if(!mSPRCOLL_Collide && !mSPRSYS_NoCollide)
1135
{
1136
int collision=ReadCollision(hoff);
1137
if(collision>mCollision)
1138
{
1139
mCollision=collision;
1140
}
1141
// 01/05/00 V0.7 if(mSPRCOLL_Number>collision)
1142
{
1143
WriteCollision(hoff,mSPRCOLL_Number);
1144
}
1145
}
1146
}
1147
break;
1148
1149
// XOR SHADOW
1150
// 1 F is opaque
1151
// 0 E is collideable
1152
// 0 0 is opaque and collideable
1153
// 1 allow collision detect
1154
// 1 allow coll. buffer access
1155
// 1 exclusive-or the data
1156
case sprite_xor_shadow:
1157
if(pixel!=0x00)
1158
{
1159
WritePixel(hoff,ReadPixel(hoff)^pixel);
1160
}
1161
if(pixel!=0x00 && pixel!=0x0e)
1162
{
1163
if(!mSPRCOLL_Collide && !mSPRSYS_NoCollide && pixel!=0x0e)
1164
{
1165
int collision=ReadCollision(hoff);
1166
if(collision>mCollision)
1167
{
1168
mCollision=collision;
1169
}
1170
// 01/05/00 V0.7 if(mSPRCOLL_Number>collision)
1171
{
1172
WriteCollision(hoff,mSPRCOLL_Number);
1173
}
1174
}
1175
}
1176
break;
1177
default:
1178
// _asm int 3;
1179
break;
1180
}
1181
}
1182
1183
uint32 CSusie::LineInit(uint32 voff)
1184
{
1185
// TRACE_SUSIE0("LineInit()");
1186
1187
mLineShiftReg=0;
1188
mLineShiftRegCount=0;
1189
mLineRepeatCount=0;
1190
mLinePixel=0;
1191
mLineType=line_error;
1192
mLinePacketBitsLeft=0xffff;
1193
1194
// Initialise the temporary pointer
1195
1196
mTMPADR=mSPRDLINE;
1197
1198
// First read the Offset to the next line
1199
1200
uint32 offset=LineGetBits(8);
1201
// TRACE_SUSIE1("LineInit() Offset=%04x",offset);
1202
1203
// Specify the MAXIMUM number of bits in this packet, it
1204
// can terminate early but can never use more than this
1205
// without ending the current packet, we count down in LineGetBits()
1206
1207
mLinePacketBitsLeft=(offset-1)*8;
1208
1209
// Literals are a special case and get their count set on a line basis
1210
1211
if(mSPRCTL1_Literal)
1212
{
1213
mLineType=line_abs_literal;
1214
mLineRepeatCount=((offset-1)*8)/mSPRCTL0_PixelBits;
1215
// Why is this necessary, is this compensating for the 1,1 offset bug
1216
// mLineRepeatCount--;
1217
}
1218
// TRACE_SUSIE1("LineInit() mLineRepeatCount=$%04x",mLineRepeatCount);
1219
1220
// Set the line base address for use in the calls to pixel painting
1221
1222
if(voff>101)
1223
{
1224
//gError->Warning("CSusie::LineInit() Out of bounds (voff)");
1225
voff=0;
1226
}
1227
1228
mLineBaseAddress=mVIDBAS.Val16+(voff*(SCREEN_WIDTH/2));
1229
mLineCollisionAddress=mCOLLBAS.Val16+(voff*(SCREEN_WIDTH/2));
1230
// TRACE_SUSIE1("LineInit() mLineBaseAddress=$%04x",mLineBaseAddress);
1231
// TRACE_SUSIE1("LineInit() mLineCollisionAddress=$%04x",mLineCollisionAddress);
1232
1233
// Return the offset to the next line
1234
1235
return offset;
1236
}
1237
1238
uint32 CSusie::LineGetPixel()
1239
{
1240
if(!mLineRepeatCount)
1241
{
1242
// Normal sprites fetch their counts on a packet basis
1243
if(mLineType!=line_abs_literal)
1244
{
1245
uint32 literal=LineGetBits(1);
1246
if(literal) mLineType=line_literal; else mLineType=line_packed;
1247
}
1248
1249
// Pixel store is empty what should we do
1250
switch(mLineType)
1251
{
1252
case line_abs_literal:
1253
// This means end of line for us
1254
mLinePixel=LINE_END;
1255
return mLinePixel; // SPEEDUP
1256
break;
1257
case line_literal:
1258
mLineRepeatCount=LineGetBits(4);
1259
mLineRepeatCount++;
1260
break;
1261
case line_packed:
1262
//
1263
// From reading in between the lines only a packed line with
1264
// a zero size i.e 0b00000 as a header is allowable as a packet end
1265
//
1266
mLineRepeatCount=LineGetBits(4);
1267
if(!mLineRepeatCount)
1268
{
1269
mLinePixel=LINE_END;
1270
}
1271
else
1272
{
1273
mLinePixel=mPenIndex[LineGetBits(mSPRCTL0_PixelBits)];
1274
}
1275
mLineRepeatCount++;
1276
break;
1277
default:
1278
return 0;
1279
}
1280
}
1281
1282
if(mLinePixel!=LINE_END)
1283
{
1284
mLineRepeatCount--;
1285
1286
switch(mLineType)
1287
{
1288
case line_abs_literal:
1289
mLinePixel=LineGetBits(mSPRCTL0_PixelBits);
1290
// Check the special case of a zero in the last pixel
1291
if(!mLineRepeatCount && !mLinePixel)
1292
mLinePixel=LINE_END;
1293
else
1294
mLinePixel=mPenIndex[mLinePixel];
1295
break;
1296
case line_literal:
1297
mLinePixel=mPenIndex[LineGetBits(mSPRCTL0_PixelBits)];
1298
break;
1299
case line_packed:
1300
break;
1301
default:
1302
return 0;
1303
}
1304
}
1305
1306
return mLinePixel;
1307
}
1308
1309
1310
void CSusie::Poke(uint32 addr,uint8 data)
1311
{
1312
switch(addr&0xff)
1313
{
1314
case (TMPADRL&0xff):
1315
mTMPADR.Union8.Low=data;
1316
mTMPADR.Union8.High=0;
1317
TRACE_SUSIE2("Poke(TMPADRL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1318
break;
1319
case (TMPADRH&0xff):
1320
mTMPADR.Union8.High=data;
1321
TRACE_SUSIE2("Poke(TMPADRH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1322
break;
1323
case (TILTACUML&0xff):
1324
mTILTACUM.Union8.Low=data;
1325
mTILTACUM.Union8.High=0;
1326
TRACE_SUSIE2("Poke(TILTACUML,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1327
break;
1328
case (TILTACUMH&0xff):
1329
mTILTACUM.Union8.High=data;
1330
TRACE_SUSIE2("Poke(TILTACUMH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1331
break;
1332
case (HOFFL&0xff):
1333
mHOFF.Union8.Low=data;
1334
mHOFF.Union8.High=0;
1335
TRACE_SUSIE2("Poke(HOFFL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1336
break;
1337
case (HOFFH&0xff):
1338
mHOFF.Union8.High=data;
1339
TRACE_SUSIE2("Poke(HOFFH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1340
break;
1341
case (VOFFL&0xff):
1342
mVOFF.Union8.Low=data;
1343
mVOFF.Union8.High=0;
1344
TRACE_SUSIE2("Poke(VOFFL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1345
break;
1346
case (VOFFH&0xff):
1347
mVOFF.Union8.High=data;
1348
TRACE_SUSIE2("Poke(VOFFH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1349
break;
1350
case (VIDBASL&0xff):
1351
mVIDBAS.Union8.Low=data;
1352
mVIDBAS.Union8.High=0;
1353
TRACE_SUSIE2("Poke(VIDBASL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1354
break;
1355
case (VIDBASH&0xff):
1356
mVIDBAS.Union8.High=data;
1357
TRACE_SUSIE2("Poke(VIDBASH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1358
break;
1359
case (COLLBASL&0xff):
1360
mCOLLBAS.Union8.Low=data;
1361
mCOLLBAS.Union8.High=0;
1362
TRACE_SUSIE2("Poke(COLLBASL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1363
break;
1364
case (COLLBASH&0xff):
1365
mCOLLBAS.Union8.High=data;
1366
TRACE_SUSIE2("Poke(COLLBASH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1367
break;
1368
case (VIDADRL&0xff):
1369
mVIDADR.Union8.Low=data;
1370
mVIDADR.Union8.High=0;
1371
TRACE_SUSIE2("Poke(VIDADRL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1372
break;
1373
case (VIDADRH&0xff):
1374
mVIDADR.Union8.High=data;
1375
TRACE_SUSIE2("Poke(VIDADRH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1376
break;
1377
case (COLLADRL&0xff):
1378
mCOLLADR.Union8.Low=data;
1379
mCOLLADR.Union8.High=0;
1380
TRACE_SUSIE2("Poke(COLLADRL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1381
break;
1382
case (COLLADRH&0xff):
1383
mCOLLADR.Union8.High=data;
1384
TRACE_SUSIE2("Poke(COLLADRH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1385
break;
1386
case (SCBNEXTL&0xff):
1387
mSCBNEXT.Union8.Low=data;
1388
mSCBNEXT.Union8.High=0;
1389
TRACE_SUSIE2("Poke(SCBNEXTL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1390
break;
1391
case (SCBNEXTH&0xff):
1392
mSCBNEXT.Union8.High=data;
1393
TRACE_SUSIE2("Poke(SCBNEXTH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1394
break;
1395
case (SPRDLINEL&0xff):
1396
mSPRDLINE.Union8.Low=data;
1397
mSPRDLINE.Union8.High=0;
1398
TRACE_SUSIE2("Poke(SPRDLINEL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1399
break;
1400
case (SPRDLINEH&0xff):
1401
mSPRDLINE.Union8.High=data;
1402
TRACE_SUSIE2("Poke(SPRDLINEH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1403
break;
1404
case (HPOSSTRTL&0xff):
1405
mHPOSSTRT.Union8.Low=data;
1406
mHPOSSTRT.Union8.High=0;
1407
TRACE_SUSIE2("Poke(HPOSSTRTL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1408
break;
1409
case (HPOSSTRTH&0xff):
1410
mHPOSSTRT.Union8.High=data;
1411
TRACE_SUSIE2("Poke(HPOSSTRTH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1412
break;
1413
case (VPOSSTRTL&0xff):
1414
mVPOSSTRT.Union8.Low=data;
1415
mVPOSSTRT.Union8.High=0;
1416
TRACE_SUSIE2("Poke(VPOSSTRTL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1417
break;
1418
case (VPOSSTRTH&0xff):
1419
mVPOSSTRT.Union8.High=data;
1420
TRACE_SUSIE2("Poke(VPOSSTRTH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1421
break;
1422
case (SPRHSIZL&0xff):
1423
mSPRHSIZ.Union8.Low=data;
1424
mSPRHSIZ.Union8.High=0;
1425
TRACE_SUSIE2("Poke(SPRHSIZL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1426
break;
1427
case (SPRHSIZH&0xff):
1428
mSPRHSIZ.Union8.High=data;
1429
TRACE_SUSIE2("Poke(SPRHSIZH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1430
break;
1431
case (SPRVSIZL&0xff):
1432
mSPRVSIZ.Union8.Low=data;
1433
mSPRVSIZ.Union8.High=0;
1434
TRACE_SUSIE2("Poke(SPRVSIZL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1435
break;
1436
case (SPRVSIZH&0xff):
1437
mSPRVSIZ.Union8.High=data;
1438
TRACE_SUSIE2("Poke(SPRVSIZH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1439
break;
1440
case (STRETCHL&0xff):
1441
mSTRETCH.Union8.Low=data;
1442
mSTRETCH.Union8.High=0;
1443
TRACE_SUSIE2("Poke(STRETCHL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1444
break;
1445
case (STRETCHH&0xff):
1446
TRACE_SUSIE2("Poke(STRETCHH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1447
mSTRETCH.Union8.High=data;
1448
break;
1449
case (TILTL&0xff):
1450
mTILT.Union8.Low=data;
1451
mTILT.Union8.High=0;
1452
TRACE_SUSIE2("Poke(TILTL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1453
break;
1454
case (TILTH&0xff):
1455
mTILT.Union8.High=data;
1456
TRACE_SUSIE2("Poke(TILTH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1457
break;
1458
case (SPRDOFFL&0xff):
1459
TRACE_SUSIE2("Poke(SPRDOFFL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1460
mSPRDOFF.Union8.Low=data;
1461
mSPRDOFF.Union8.High=0;
1462
break;
1463
case (SPRDOFFH&0xff):
1464
TRACE_SUSIE2("Poke(SPRDOFFH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1465
mSPRDOFF.Union8.High=data;
1466
break;
1467
case (SPRVPOSL&0xff):
1468
TRACE_SUSIE2("Poke(SPRVPOSL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1469
mSPRVPOS.Union8.Low=data;
1470
mSPRVPOS.Union8.High=0;
1471
break;
1472
case (SPRVPOSH&0xff):
1473
mSPRVPOS.Union8.High=data;
1474
TRACE_SUSIE2("Poke(SPRVPOSH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1475
break;
1476
case (COLLOFFL&0xff):
1477
mCOLLOFF.Union8.Low=data;
1478
mCOLLOFF.Union8.High=0;
1479
TRACE_SUSIE2("Poke(COLLOFFL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1480
break;
1481
case (COLLOFFH&0xff):
1482
mCOLLOFF.Union8.High=data;
1483
TRACE_SUSIE2("Poke(COLLOFFH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1484
break;
1485
case (VSIZACUML&0xff):
1486
mVSIZACUM.Union8.Low=data;
1487
mVSIZACUM.Union8.High=0;
1488
TRACE_SUSIE2("Poke(VSIZACUML,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1489
break;
1490
case (VSIZACUMH&0xff):
1491
mVSIZACUM.Union8.High=data;
1492
TRACE_SUSIE2("Poke(VSIZACUMH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1493
break;
1494
case (HSIZOFFL&0xff):
1495
mHSIZOFF.Union8.Low=data;
1496
mHSIZOFF.Union8.High=0;
1497
TRACE_SUSIE2("Poke(HSIZOFFL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1498
break;
1499
case (HSIZOFFH&0xff):
1500
mHSIZOFF.Union8.High=data;
1501
TRACE_SUSIE2("Poke(HSIZOFFH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1502
break;
1503
case (VSIZOFFL&0xff):
1504
mVSIZOFF.Union8.Low=data;
1505
mVSIZOFF.Union8.High=0;
1506
TRACE_SUSIE2("Poke(VSIZOFFL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1507
break;
1508
case (VSIZOFFH&0xff):
1509
mVSIZOFF.Union8.High=data;
1510
TRACE_SUSIE2("Poke(VSIZOFFH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1511
break;
1512
case (SCBADRL&0xff):
1513
mSCBADR.Union8.Low=data;
1514
mSCBADR.Union8.High=0;
1515
TRACE_SUSIE2("Poke(SCBADRL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1516
break;
1517
case (SCBADRH&0xff):
1518
mSCBADR.Union8.High=data;
1519
TRACE_SUSIE2("Poke(SCBADRH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1520
break;
1521
case (PROCADRL&0xff):
1522
mPROCADR.Union8.Low=data;
1523
mPROCADR.Union8.High=0;
1524
TRACE_SUSIE2("Poke(PROCADRL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1525
break;
1526
case (PROCADRH&0xff):
1527
mPROCADR.Union8.High=data;
1528
TRACE_SUSIE2("Poke(PROCADRH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1529
break;
1530
1531
case (MATHD&0xff):
1532
TRACE_SUSIE2("Poke(MATHD,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1533
mMATHABCD.Bytes.D=data;
1534
// mMATHABCD.Bytes.C=0;
1535
// The hardware manual says that the sign shouldnt change
1536
// but if I dont do this then stun runner will hang as it
1537
// does the init in the wrong order and if the previous
1538
// calc left a zero there then we'll get a sign error
1539
Poke(MATHC,0);
1540
break;
1541
case (MATHC&0xff):
1542
TRACE_SUSIE2("Poke(MATHC,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1543
mMATHABCD.Bytes.C=data;
1544
// Perform sign conversion if required
1545
if(mSPRSYS_SignedMath)
1546
{
1547
// Account for the math bug that 0x8000 is +ve & 0x0000 is -ve by subracting 1
1548
if((mMATHABCD.Words.CD-1)&0x8000)
1549
{
1550
uint16 conv;
1551
conv=mMATHABCD.Words.CD^0xffff;
1552
conv++;
1553
mMATHCD_sign=-1;
1554
TRACE_SUSIE2("MATH CD signed conversion complete %04x to %04x",mMATHABCD.Words.CD,conv);
1555
mMATHABCD.Words.CD=conv;
1556
}
1557
else
1558
{
1559
mMATHCD_sign=1;
1560
}
1561
}
1562
break;
1563
case (MATHB&0xff):
1564
TRACE_SUSIE2("Poke(MATHB,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1565
mMATHABCD.Bytes.B=data;
1566
mMATHABCD.Bytes.A=0;
1567
break;
1568
case (MATHA&0xff):
1569
TRACE_SUSIE2("Poke(MATHA,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1570
mMATHABCD.Bytes.A=data;
1571
// Perform sign conversion if required
1572
if(mSPRSYS_SignedMath)
1573
{
1574
// Account for the math bug that 0x8000 is +ve & 0x0000 is -ve by subracting 1
1575
if((mMATHABCD.Words.AB-1)&0x8000)
1576
{
1577
uint16 conv;
1578
conv=mMATHABCD.Words.AB^0xffff;
1579
conv++;
1580
mMATHAB_sign=-1;
1581
TRACE_SUSIE2("MATH AB signed conversion complete %04x to %04x",mMATHABCD.Words.AB,conv);
1582
mMATHABCD.Words.AB=conv;
1583
}
1584
else
1585
{
1586
mMATHAB_sign=1;
1587
}
1588
}
1589
DoMathMultiply();
1590
break;
1591
1592
case (MATHP&0xff):
1593
mMATHNP.Bytes.P=data;
1594
mMATHNP.Bytes.N=0;
1595
TRACE_SUSIE2("Poke(MATHP,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1596
break;
1597
case (MATHN&0xff):
1598
mMATHNP.Bytes.N=data;
1599
TRACE_SUSIE2("Poke(MATHN,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1600
break;
1601
1602
case (MATHH&0xff):
1603
mMATHEFGH.Bytes.H=data;
1604
mMATHEFGH.Bytes.G=0;
1605
TRACE_SUSIE2("Poke(MATHH,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1606
break;
1607
case (MATHG&0xff):
1608
mMATHEFGH.Bytes.G=data;
1609
TRACE_SUSIE2("Poke(MATHG,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1610
break;
1611
case (MATHF&0xff):
1612
mMATHEFGH.Bytes.F=data;
1613
mMATHEFGH.Bytes.E=0;
1614
TRACE_SUSIE2("Poke(MATHF,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1615
break;
1616
case (MATHE&0xff):
1617
mMATHEFGH.Bytes.E=data;
1618
TRACE_SUSIE2("Poke(MATHE,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1619
DoMathDivide();
1620
break;
1621
1622
case (MATHM&0xff):
1623
mMATHJKLM.Bytes.M=data;
1624
mMATHJKLM.Bytes.L=0;
1625
mSPRSYS_Mathbit=FALSE;
1626
TRACE_SUSIE2("Poke(MATHM,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1627
break;
1628
case (MATHL&0xff):
1629
mMATHJKLM.Bytes.L=data;
1630
TRACE_SUSIE2("Poke(MATHL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1631
break;
1632
case (MATHK&0xff):
1633
mMATHJKLM.Bytes.K=data;
1634
mMATHJKLM.Bytes.J=0;
1635
TRACE_SUSIE2("Poke(MATHK,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1636
break;
1637
case (MATHJ&0xff):
1638
mMATHJKLM.Bytes.J=data;
1639
TRACE_SUSIE2("Poke(MATHJ,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1640
break;
1641
1642
case (SPRCTL0&0xff):
1643
mSPRCTL0_Type=data&0x0007;
1644
mSPRCTL0_Vflip=data&0x0010;
1645
mSPRCTL0_Hflip=data&0x0020;
1646
mSPRCTL0_PixelBits=((data&0x00c0)>>6)+1;
1647
TRACE_SUSIE2("Poke(SPRCTL0,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1648
break;
1649
case (SPRCTL1&0xff):
1650
mSPRCTL1_StartLeft=data&0x0001;
1651
mSPRCTL1_StartUp=data&0x0002;
1652
mSPRCTL1_SkipSprite=data&0x0004;
1653
mSPRCTL1_ReloadPalette=data&0x0008;
1654
mSPRCTL1_ReloadDepth=(data&0x0030)>>4;
1655
mSPRCTL1_Sizing=data&0x0040;
1656
mSPRCTL1_Literal=data&0x0080;
1657
TRACE_SUSIE2("Poke(SPRCTL1,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1658
break;
1659
case (SPRCOLL&0xff):
1660
mSPRCOLL_Number=data&0x000f;
1661
mSPRCOLL_Collide=data&0x0020;
1662
TRACE_SUSIE2("Poke(SPRCOLL,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1663
break;
1664
case (SPRINIT&0xff):
1665
mSPRINIT.Byte=data;
1666
TRACE_SUSIE2("Poke(SPRINIT,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1667
break;
1668
case (SUZYBUSEN&0xff):
1669
mSUZYBUSEN=data&0x01;
1670
TRACE_SUSIE2("Poke(SUZYBUSEN,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1671
break;
1672
case (SPRGO&0xff):
1673
mSPRGO=data&0x01;
1674
mEVERON=data&0x04;
1675
TRACE_SUSIE2("Poke(SPRGO,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1676
break;
1677
case (SPRSYS&0xff):
1678
mSPRSYS_StopOnCurrent=data&0x0002;
1679
if(data&0x0004) mSPRSYS_UnsafeAccess=0;
1680
mSPRSYS_LeftHand=data&0x0008;
1681
mSPRSYS_VStretch=data&0x0010;
1682
mSPRSYS_NoCollide=data&0x0020;
1683
mSPRSYS_Accumulate=data&0x0040;
1684
mSPRSYS_SignedMath=data&0x0080;
1685
TRACE_SUSIE2("Poke(SPRSYS,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1686
break;
1687
1688
// Cartridge writing ports
1689
1690
case (RCART0&0xff):
1691
mSystem.Poke_CARTB0(data);
1692
TRACE_SUSIE2("Poke(RCART0,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1693
break;
1694
case (RCART1&0xff):
1695
mSystem.Poke_CARTB1(data);
1696
TRACE_SUSIE2("Poke(RCART1,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1697
break;
1698
1699
// These are not so important, so lets ignore them for the moment
1700
1701
case (LEDS&0xff):
1702
case (PPORTSTAT&0xff):
1703
case (PPORTDATA&0xff):
1704
case (HOWIE&0xff):
1705
TRACE_SUSIE2("Poke(LEDS/PPORTSTST/PPORTDATA/HOWIE,%02x) at PC=$%04x",data,mSystem.mCpu->GetPC());
1706
break;
1707
1708
// Errors on read only register accesses
1709
1710
case (SUZYHREV&0xff):
1711
case (JOYSTICK&0xff):
1712
case (SWITCHES&0xff):
1713
TRACE_SUSIE3("Poke(%04x,%02x) - Poke to read only register location at PC=%04x",addr,data,mSystem.mCpu->GetPC());
1714
break;
1715
1716
// Errors on illegal location accesses
1717
1718
default:
1719
TRACE_SUSIE3("Poke(%04x,%02x) - Poke to illegal location at PC=%04x",addr,data,mSystem.mCpu->GetPC());
1720
break;
1721
}
1722
}
1723
1724
uint8 CSusie::Peek(uint32 addr)
1725
{
1726
uint8 retval=0;
1727
1728
switch(addr&0xff)
1729
{
1730
case (TMPADRL&0xff):
1731
retval=mTMPADR.Union8.Low;
1732
TRACE_SUSIE2("Peek(TMPADRL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1733
return retval;
1734
break;
1735
case (TMPADRH&0xff):
1736
retval=mTMPADR.Union8.High;
1737
TRACE_SUSIE2("Peek(TMPADRH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1738
return retval;
1739
break;
1740
case (TILTACUML&0xff):
1741
retval=mTILTACUM.Union8.Low;
1742
TRACE_SUSIE2("Peek(TILTACUML)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1743
return retval;
1744
break;
1745
case (TILTACUMH&0xff):
1746
retval=mTILTACUM.Union8.High;
1747
TRACE_SUSIE2("Peek(TILTACUMH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1748
return retval;
1749
break;
1750
case (HOFFL&0xff):
1751
retval=mHOFF.Union8.Low;
1752
TRACE_SUSIE2("Peek(HOFFL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1753
return retval;
1754
break;
1755
case (HOFFH&0xff):
1756
retval=mHOFF.Union8.High;
1757
TRACE_SUSIE2("Peek(HOFFH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1758
return retval;
1759
break;
1760
case (VOFFL&0xff):
1761
retval=mVOFF.Union8.Low;
1762
TRACE_SUSIE2("Peek(VOFFL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1763
return retval;
1764
break;
1765
case (VOFFH&0xff):
1766
retval=mVOFF.Union8.High;
1767
TRACE_SUSIE2("Peek(VOFFH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1768
return retval;
1769
break;
1770
case (VIDBASL&0xff):
1771
retval=mVIDBAS.Union8.Low;
1772
TRACE_SUSIE2("Peek(VIDBASL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1773
return retval;
1774
break;
1775
case (VIDBASH&0xff):
1776
retval=mVIDBAS.Union8.High;
1777
TRACE_SUSIE2("Peek(VIDBASH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1778
return retval;
1779
break;
1780
case (COLLBASL&0xff):
1781
retval=mCOLLBAS.Union8.Low;
1782
TRACE_SUSIE2("Peek(COLLBASL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1783
return retval;
1784
break;
1785
case (COLLBASH&0xff):
1786
retval=mCOLLBAS.Union8.High;
1787
TRACE_SUSIE2("Peek(COLLBASH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1788
return retval;
1789
break;
1790
case (VIDADRL&0xff):
1791
retval=mVIDADR.Union8.Low;
1792
TRACE_SUSIE2("Peek(VIDADRL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1793
return retval;
1794
break;
1795
case (VIDADRH&0xff):
1796
retval=mVIDADR.Union8.High;
1797
TRACE_SUSIE2("Peek(VIDADRH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1798
return retval;
1799
break;
1800
case (COLLADRL&0xff):
1801
retval=mCOLLADR.Union8.Low;
1802
TRACE_SUSIE2("Peek(COLLADRL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1803
return retval;
1804
break;
1805
case (COLLADRH&0xff):
1806
retval=mCOLLADR.Union8.High;
1807
TRACE_SUSIE2("Peek(COLLADRH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1808
return retval;
1809
break;
1810
case (SCBNEXTL&0xff):
1811
retval=mSCBNEXT.Union8.Low;
1812
TRACE_SUSIE2("Peek(SCBNEXTL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1813
return retval;
1814
break;
1815
case (SCBNEXTH&0xff):
1816
retval=mSCBNEXT.Union8.High;
1817
TRACE_SUSIE2("Peek(SCBNEXTH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1818
return retval;
1819
break;
1820
case (SPRDLINEL&0xff):
1821
retval=mSPRDLINE.Union8.Low;
1822
TRACE_SUSIE2("Peek(SPRDLINEL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1823
return retval;
1824
break;
1825
case (SPRDLINEH&0xff):
1826
retval=mSPRDLINE.Union8.High;
1827
TRACE_SUSIE2("Peek(SPRDLINEH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1828
return retval;
1829
break;
1830
case (HPOSSTRTL&0xff):
1831
retval=mHPOSSTRT.Union8.Low;
1832
TRACE_SUSIE2("Peek(HPOSSTRTL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1833
return retval;
1834
break;
1835
case (HPOSSTRTH&0xff):
1836
retval=mHPOSSTRT.Union8.High;
1837
TRACE_SUSIE2("Peek(HPOSSTRTH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1838
return retval;
1839
break;
1840
case (VPOSSTRTL&0xff):
1841
retval=mVPOSSTRT.Union8.Low;
1842
TRACE_SUSIE2("Peek(VPOSSTRTL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1843
return retval;
1844
break;
1845
case (VPOSSTRTH&0xff):
1846
retval=mVPOSSTRT.Union8.High;
1847
TRACE_SUSIE2("Peek(VPOSSTRTH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1848
return retval;
1849
break;
1850
case (SPRHSIZL&0xff):
1851
retval=mSPRHSIZ.Union8.Low;
1852
TRACE_SUSIE2("Peek(SPRHSIZL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1853
return retval;
1854
break;
1855
case (SPRHSIZH&0xff):
1856
retval=mSPRHSIZ.Union8.High;
1857
TRACE_SUSIE2("Peek(SPRHSIZH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1858
return retval;
1859
break;
1860
case (SPRVSIZL&0xff):
1861
retval=mSPRVSIZ.Union8.Low;
1862
TRACE_SUSIE2("Peek(SPRVSIZL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1863
return retval;
1864
break;
1865
case (SPRVSIZH&0xff):
1866
retval=mSPRVSIZ.Union8.High;
1867
TRACE_SUSIE2("Peek(SPRVSIZH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1868
return retval;
1869
break;
1870
case (STRETCHL&0xff):
1871
retval=mSTRETCH.Union8.Low;
1872
TRACE_SUSIE2("Peek(STRETCHL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1873
return retval;
1874
break;
1875
case (STRETCHH&0xff):
1876
retval=mSTRETCH.Union8.High;
1877
TRACE_SUSIE2("Peek(STRETCHH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1878
return retval;
1879
break;
1880
case (TILTL&0xff):
1881
retval=mTILT.Union8.Low;
1882
TRACE_SUSIE2("Peek(TILTL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1883
return retval;
1884
break;
1885
case (TILTH&0xff):
1886
retval=mTILT.Union8.High;
1887
TRACE_SUSIE2("Peek(TILTH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1888
return retval;
1889
break;
1890
case (SPRDOFFL&0xff):
1891
retval=mSPRDOFF.Union8.Low;
1892
TRACE_SUSIE2("Peek(SPRDOFFL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1893
return retval;
1894
break;
1895
case (SPRDOFFH&0xff):
1896
retval=mSPRDOFF.Union8.High;
1897
TRACE_SUSIE2("Peek(SPRDOFFH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1898
return retval;
1899
break;
1900
case (SPRVPOSL&0xff):
1901
retval=mSPRVPOS.Union8.Low;
1902
TRACE_SUSIE2("Peek(SPRVPOSL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1903
return retval;
1904
break;
1905
case (SPRVPOSH&0xff):
1906
retval=mSPRVPOS.Union8.High;
1907
TRACE_SUSIE2("Peek(SPRVPOSH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1908
return retval;
1909
break;
1910
case (COLLOFFL&0xff):
1911
retval=mCOLLOFF.Union8.Low;
1912
TRACE_SUSIE2("Peek(COLLOFFL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1913
return retval;
1914
break;
1915
case (COLLOFFH&0xff):
1916
retval=mCOLLOFF.Union8.High;
1917
TRACE_SUSIE2("Peek(COLLOFFH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1918
return retval;
1919
break;
1920
case (VSIZACUML&0xff):
1921
retval=mVSIZACUM.Union8.Low;
1922
TRACE_SUSIE2("Peek(VSIZACUML)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1923
return retval;
1924
break;
1925
case (VSIZACUMH&0xff):
1926
retval=mVSIZACUM.Union8.High;
1927
TRACE_SUSIE2("Peek(VSIZACUMH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1928
return retval;
1929
break;
1930
case (HSIZOFFL&0xff):
1931
retval=mHSIZOFF.Union8.Low;
1932
TRACE_SUSIE2("Peek(HSIZOFFL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1933
return retval;
1934
break;
1935
case (HSIZOFFH&0xff):
1936
retval=mHSIZOFF.Union8.High;
1937
TRACE_SUSIE2("Peek(HSIZOFFH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1938
return retval;
1939
break;
1940
case (VSIZOFFL&0xff):
1941
retval=mVSIZOFF.Union8.Low;
1942
TRACE_SUSIE2("Peek(VSIZOFFL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1943
return retval;
1944
break;
1945
case (VSIZOFFH&0xff):
1946
retval=mVSIZOFF.Union8.High;
1947
TRACE_SUSIE2("Peek(VSIZOFFH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1948
return retval;
1949
break;
1950
case (SCBADRL&0xff):
1951
retval=mSCBADR.Union8.Low;
1952
TRACE_SUSIE2("Peek(SCBADRL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1953
return retval;
1954
break;
1955
case (SCBADRH&0xff):
1956
retval=mSCBADR.Union8.High;
1957
TRACE_SUSIE2("Peek(SCBADRH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1958
return retval;
1959
break;
1960
case (PROCADRL&0xff):
1961
retval=mPROCADR.Union8.Low;
1962
TRACE_SUSIE2("Peek(PROCADRL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1963
return retval;
1964
break;
1965
case (PROCADRH&0xff):
1966
retval=mPROCADR.Union8.High;
1967
TRACE_SUSIE2("Peek(PROCADRH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1968
return retval;
1969
break;
1970
1971
case (MATHD&0xff):
1972
retval=mMATHABCD.Bytes.D;
1973
TRACE_SUSIE2("Peek(MATHD)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1974
return retval;
1975
break;
1976
case (MATHC&0xff):
1977
retval=mMATHABCD.Bytes.C;
1978
TRACE_SUSIE2("Peek(MATHC)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1979
return retval;
1980
break;
1981
case (MATHB&0xff):
1982
retval=mMATHABCD.Bytes.B;
1983
TRACE_SUSIE2("Peek(MATHB)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1984
return retval;
1985
break;
1986
case (MATHA&0xff):
1987
retval=mMATHABCD.Bytes.A;
1988
TRACE_SUSIE2("Peek(MATHA)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1989
return retval;
1990
break;
1991
1992
case (MATHP&0xff):
1993
retval=mMATHNP.Bytes.P;
1994
TRACE_SUSIE2("Peek(MATHP)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
1995
return retval;
1996
break;
1997
case (MATHN&0xff):
1998
retval=mMATHNP.Bytes.N;
1999
TRACE_SUSIE2("Peek(MATHN)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
2000
return retval;
2001
break;
2002
2003
case (MATHH&0xff):
2004
retval=mMATHEFGH.Bytes.H;
2005
TRACE_SUSIE2("Peek(MATHH)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
2006
return retval;
2007
break;
2008
case (MATHG&0xff):
2009
retval=mMATHEFGH.Bytes.G;
2010
TRACE_SUSIE2("Peek(MATHG)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
2011
return retval;
2012
break;
2013
case (MATHF&0xff):
2014
retval=mMATHEFGH.Bytes.F;
2015
TRACE_SUSIE2("Peek(MATHF)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
2016
return retval;
2017
break;
2018
case (MATHE&0xff):
2019
retval=mMATHEFGH.Bytes.E;
2020
TRACE_SUSIE2("Peek(MATHE)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
2021
return retval;
2022
break;
2023
2024
case (MATHM&0xff):
2025
retval=mMATHJKLM.Bytes.M;
2026
TRACE_SUSIE2("Peek(MATHM)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
2027
return retval;
2028
break;
2029
case (MATHL&0xff):
2030
retval=mMATHJKLM.Bytes.L;
2031
TRACE_SUSIE2("Peek(MATHL)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
2032
return retval;
2033
break;
2034
case (MATHK&0xff):
2035
retval=mMATHJKLM.Bytes.K;
2036
TRACE_SUSIE2("Peek(MATHK)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
2037
return retval;
2038
break;
2039
case (MATHJ&0xff):
2040
retval=mMATHJKLM.Bytes.J;
2041
TRACE_SUSIE2("Peek(MATHJ)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
2042
return retval;
2043
break;
2044
2045
case (SUZYHREV&0xff):
2046
retval=0x01;
2047
TRACE_SUSIE2("Peek(SUZYHREV)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
2048
return retval;
2049
2050
case (SPRSYS&0xff):
2051
retval=0x0000;
2052
// retval+=(mSPRSYS_Status)?0x0001:0x0000;
2053
retval+= (mSystem.gSuzieDoneTime)?0x0001:0x0000;
2054
retval+=(mSPRSYS_StopOnCurrent)?0x0002:0x0000;
2055
retval+=(mSPRSYS_UnsafeAccess)?0x0004:0x0000;
2056
retval+=(mSPRSYS_LeftHand)?0x0008:0x0000;
2057
retval+=(mSPRSYS_VStretch)?0x0010:0x0000;
2058
retval+=(mSPRSYS_LastCarry)?0x0020:0x0000;
2059
retval+=(mSPRSYS_Mathbit)?0x0040:0x0000;
2060
retval+=(mSPRSYS_MathInProgress)?0x0080:0x0000;
2061
TRACE_SUSIE2("Peek(SPRSYS)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
2062
return retval;
2063
2064
case (JOYSTICK&0xff):
2065
if(mSPRSYS_LeftHand)
2066
{
2067
retval= mJOYSTICK.Byte;
2068
}
2069
else
2070
{
2071
TJOYSTICK Modified=mJOYSTICK;
2072
Modified.Bits.Left=mJOYSTICK.Bits.Right;
2073
Modified.Bits.Right=mJOYSTICK.Bits.Left;
2074
Modified.Bits.Down=mJOYSTICK.Bits.Up;
2075
Modified.Bits.Up=mJOYSTICK.Bits.Down;
2076
retval= Modified.Byte;
2077
}
2078
// TRACE_SUSIE2("Peek(JOYSTICK)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
2079
lagged = false;
2080
return retval;
2081
break;
2082
2083
2084
case (SWITCHES&0xff):
2085
retval=mSWITCHES.Byte;
2086
// TRACE_SUSIE2("Peek(SWITCHES)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
2087
lagged = false;
2088
return retval;
2089
2090
// Cartridge reading ports
2091
2092
case (RCART0&0xff):
2093
retval=mSystem.Peek_CARTB0();
2094
// TRACE_SUSIE2("Peek(RCART0)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
2095
return retval;
2096
break;
2097
case (RCART1&0xff):
2098
retval=mSystem.Peek_CARTB1();
2099
// TRACE_SUSIE2("Peek(RCART1)=$%02x at PC=$%04x",retval,mSystem.mCpu->GetPC());
2100
return retval;
2101
break;
2102
2103
// These are no so important so lets ignore them for the moment
2104
2105
case (LEDS&0xff):
2106
case (PPORTSTAT&0xff):
2107
case (PPORTDATA&0xff):
2108
case (HOWIE&0xff):
2109
TRACE_SUSIE1("Peek(LEDS/PPORTSTAT/PPORTDATA) at PC=$%04x",mSystem.mCpu->GetPC());
2110
break;
2111
2112
// Errors on write only register accesses
2113
2114
case (SPRCTL0&0xff):
2115
case (SPRCTL1&0xff):
2116
case (SPRCOLL&0xff):
2117
case (SPRINIT&0xff):
2118
case (SUZYBUSEN&0xff):
2119
case (SPRGO&0xff):
2120
TRACE_SUSIE2("Peek(%04x) - Peek from write only register location at PC=$%04x",addr,mSystem.mCpu->GetPC());
2121
break;
2122
2123
// Errors on illegal location accesses
2124
2125
default:
2126
TRACE_SUSIE2("Peek(%04x) - Peek from illegal location at PC=$%04x",addr,mSystem.mCpu->GetPC());
2127
break;
2128
}
2129
2130
return 0xff;
2131
}
2132
2133
SYNCFUNC(CSusie)
2134
{
2135
NSS(lagged);
2136
2137
NSS(cycles_used);
2138
2139
NSS(mTMPADR);
2140
NSS(mTILTACUM);
2141
NSS(mHOFF);
2142
NSS(mVOFF);
2143
NSS(mVIDBAS);
2144
NSS(mCOLLBAS);
2145
NSS(mVIDADR);
2146
NSS(mCOLLADR);
2147
NSS(mSCBNEXT);
2148
NSS(mSPRDLINE);
2149
NSS(mHPOSSTRT);
2150
NSS(mVPOSSTRT);
2151
NSS(mSPRHSIZ);
2152
NSS(mSPRVSIZ);
2153
NSS(mSTRETCH);
2154
NSS(mTILT);
2155
NSS(mSPRDOFF);
2156
NSS(mSPRVPOS);
2157
NSS(mCOLLOFF);
2158
NSS(mVSIZACUM);
2159
NSS(mHSIZACUM);
2160
NSS(mHSIZOFF);
2161
NSS(mVSIZOFF);
2162
NSS(mSCBADR);
2163
NSS(mPROCADR);
2164
2165
2166
NSS(mMATHABCD);
2167
NSS(mMATHEFGH);
2168
NSS(mMATHJKLM);
2169
NSS(mMATHNP);
2170
NSS(mMATHAB_sign);
2171
NSS(mMATHCD_sign);
2172
NSS(mMATHEFGH_sign);
2173
2174
NSS(mSPRCTL0_Type);
2175
NSS(mSPRCTL0_Vflip);
2176
NSS(mSPRCTL0_Hflip);
2177
NSS(mSPRCTL0_PixelBits);
2178
2179
NSS(mSPRCTL1_StartLeft);
2180
NSS(mSPRCTL1_StartUp);
2181
NSS(mSPRCTL1_SkipSprite);
2182
NSS(mSPRCTL1_ReloadPalette);
2183
NSS(mSPRCTL1_ReloadDepth);
2184
NSS(mSPRCTL1_Sizing);
2185
NSS(mSPRCTL1_Literal);
2186
2187
NSS(mSPRCOLL_Number);
2188
NSS(mSPRCOLL_Collide);
2189
2190
NSS(mSPRSYS_StopOnCurrent);
2191
NSS(mSPRSYS_LeftHand);
2192
NSS(mSPRSYS_VStretch);
2193
NSS(mSPRSYS_NoCollide);
2194
NSS(mSPRSYS_Accumulate);
2195
NSS(mSPRSYS_SignedMath);
2196
NSS(mSPRSYS_Status);
2197
NSS(mSPRSYS_UnsafeAccess);
2198
NSS(mSPRSYS_LastCarry);
2199
NSS(mSPRSYS_Mathbit);
2200
NSS(mSPRSYS_MathInProgress);
2201
2202
NSS(mSUZYBUSEN);
2203
2204
NSS(mSPRINIT);
2205
2206
NSS(mSPRGO);
2207
NSS(mEVERON);
2208
2209
NSS(mPenIndex);
2210
2211
2212
2213
NSS(mLineType);
2214
NSS(mLineShiftRegCount);
2215
NSS(mLineShiftReg);
2216
NSS(mLineRepeatCount);
2217
NSS(mLinePixel);
2218
NSS(mLinePacketBitsLeft);
2219
2220
NSS(mCollision);
2221
2222
// mRamPointer;
2223
2224
NSS(mLineBaseAddress);
2225
NSS(mLineCollisionAddress);
2226
2227
NSS(hquadoff);
2228
NSS(vquadoff);
2229
2230
2231
2232
NSS(mJOYSTICK);
2233
NSS(mSWITCHES);
2234
}
2235
2236