Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
RishiRecon
GitHub Repository: RishiRecon/exploits
Path: blob/main/misc/emulator/xnes/snes9x/c4emu.cpp
28515 views
1
/***********************************************************************************
2
Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3
4
(c) Copyright 1996 - 2002 Gary Henderson ([email protected]),
5
Jerremy Koot ([email protected])
6
7
(c) Copyright 2002 - 2004 Matthew Kendora
8
9
(c) Copyright 2002 - 2005 Peter Bortas ([email protected])
10
11
(c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/)
12
13
(c) Copyright 2001 - 2006 John Weidman ([email protected])
14
15
(c) Copyright 2002 - 2006 funkyass ([email protected]),
16
Kris Bleakley ([email protected])
17
18
(c) Copyright 2002 - 2010 Brad Jorsch ([email protected]),
19
Nach ([email protected]),
20
21
(c) Copyright 2002 - 2011 zones ([email protected])
22
23
(c) Copyright 2006 - 2007 nitsuja
24
25
(c) Copyright 2009 - 2011 BearOso,
26
OV2
27
28
29
BS-X C emulator code
30
(c) Copyright 2005 - 2006 Dreamer Nom,
31
zones
32
33
C4 x86 assembler and some C emulation code
34
(c) Copyright 2000 - 2003 _Demo_ ([email protected]),
35
Nach,
36
zsKnight ([email protected])
37
38
C4 C++ code
39
(c) Copyright 2003 - 2006 Brad Jorsch,
40
Nach
41
42
DSP-1 emulator code
43
(c) Copyright 1998 - 2006 _Demo_,
44
Andreas Naive ([email protected]),
45
Gary Henderson,
46
Ivar ([email protected]),
47
John Weidman,
48
Kris Bleakley,
49
Matthew Kendora,
50
Nach,
51
neviksti ([email protected])
52
53
DSP-2 emulator code
54
(c) Copyright 2003 John Weidman,
55
Kris Bleakley,
56
Lord Nightmare ([email protected]),
57
Matthew Kendora,
58
neviksti
59
60
DSP-3 emulator code
61
(c) Copyright 2003 - 2006 John Weidman,
62
Kris Bleakley,
63
Lancer,
64
z80 gaiden
65
66
DSP-4 emulator code
67
(c) Copyright 2004 - 2006 Dreamer Nom,
68
John Weidman,
69
Kris Bleakley,
70
Nach,
71
z80 gaiden
72
73
OBC1 emulator code
74
(c) Copyright 2001 - 2004 zsKnight,
75
pagefault ([email protected]),
76
Kris Bleakley
77
Ported from x86 assembler to C by sanmaiwashi
78
79
SPC7110 and RTC C++ emulator code used in 1.39-1.51
80
(c) Copyright 2002 Matthew Kendora with research by
81
zsKnight,
82
John Weidman,
83
Dark Force
84
85
SPC7110 and RTC C++ emulator code used in 1.52+
86
(c) Copyright 2009 byuu,
87
neviksti
88
89
S-DD1 C emulator code
90
(c) Copyright 2003 Brad Jorsch with research by
91
Andreas Naive,
92
John Weidman
93
94
S-RTC C emulator code
95
(c) Copyright 2001 - 2006 byuu,
96
John Weidman
97
98
ST010 C++ emulator code
99
(c) Copyright 2003 Feather,
100
John Weidman,
101
Kris Bleakley,
102
Matthew Kendora
103
104
Super FX x86 assembler emulator code
105
(c) Copyright 1998 - 2003 _Demo_,
106
pagefault,
107
zsKnight
108
109
Super FX C emulator code
110
(c) Copyright 1997 - 1999 Ivar,
111
Gary Henderson,
112
John Weidman
113
114
Sound emulator code used in 1.5-1.51
115
(c) Copyright 1998 - 2003 Brad Martin
116
(c) Copyright 1998 - 2006 Charles Bilyue'
117
118
Sound emulator code used in 1.52+
119
(c) Copyright 2004 - 2007 Shay Green ([email protected])
120
121
SH assembler code partly based on x86 assembler code
122
(c) Copyright 2002 - 2004 Marcus Comstedt ([email protected])
123
124
2xSaI filter
125
(c) Copyright 1999 - 2001 Derek Liauw Kie Fa
126
127
HQ2x, HQ3x, HQ4x filters
128
(c) Copyright 2003 Maxim Stepin ([email protected])
129
130
NTSC filter
131
(c) Copyright 2006 - 2007 Shay Green
132
133
GTK+ GUI code
134
(c) Copyright 2004 - 2011 BearOso
135
136
Win32 GUI code
137
(c) Copyright 2003 - 2006 blip,
138
funkyass,
139
Matthew Kendora,
140
Nach,
141
nitsuja
142
(c) Copyright 2009 - 2011 OV2
143
144
Mac OS GUI code
145
(c) Copyright 1998 - 2001 John Stiles
146
(c) Copyright 2001 - 2011 zones
147
148
149
Specific ports contains the works of other authors. See headers in
150
individual files.
151
152
153
Snes9x homepage: http://www.snes9x.com/
154
155
Permission to use, copy, modify and/or distribute Snes9x in both binary
156
and source form, for non-commercial purposes, is hereby granted without
157
fee, providing that this license information and copyright notice appear
158
with all copies and any derived work.
159
160
This software is provided 'as-is', without any express or implied
161
warranty. In no event shall the authors be held liable for any damages
162
arising from the use of this software or it's derivatives.
163
164
Snes9x is freeware for PERSONAL USE only. Commercial users should
165
seek permission of the copyright holders first. Commercial use includes,
166
but is not limited to, charging money for Snes9x or software derived from
167
Snes9x, including Snes9x or derivatives in commercial game bundles, and/or
168
using Snes9x as a promotion for your commercial product.
169
170
The copyright holders request that bug fixes and improvements to the code
171
should be forwarded to them so everyone can benefit from the modifications
172
in future versions.
173
174
Super NES and Super Nintendo Entertainment System are trademarks of
175
Nintendo Co., Limited and its subsidiary companies.
176
***********************************************************************************/
177
178
179
#include <math.h>
180
#include "snes9x.h"
181
#include "memmap.h"
182
#include "sar.h"
183
184
static int16 C4SinTable[512] =
185
{
186
0, 402, 804, 1206, 1607, 2009, 2410, 2811,
187
3211, 3611, 4011, 4409, 4808, 5205, 5602, 5997,
188
6392, 6786, 7179, 7571, 7961, 8351, 8739, 9126,
189
9512, 9896, 10278, 10659, 11039, 11416, 11793, 12167,
190
12539, 12910, 13278, 13645, 14010, 14372, 14732, 15090,
191
15446, 15800, 16151, 16499, 16846, 17189, 17530, 17869,
192
18204, 18537, 18868, 19195, 19519, 19841, 20159, 20475,
193
20787, 21097, 21403, 21706, 22005, 22301, 22594, 22884,
194
23170, 23453, 23732, 24007, 24279, 24547, 24812, 25073,
195
25330, 25583, 25832, 26077, 26319, 26557, 26790, 27020,
196
27245, 27466, 27684, 27897, 28106, 28310, 28511, 28707,
197
28898, 29086, 29269, 29447, 29621, 29791, 29956, 30117,
198
30273, 30425, 30572, 30714, 30852, 30985, 31114, 31237,
199
31357, 31471, 31581, 31685, 31785, 31881, 31971, 32057,
200
32138, 32214, 32285, 32351, 32413, 32469, 32521, 32568,
201
32610, 32647, 32679, 32706, 32728, 32745, 32758, 32765,
202
32767, 32765, 32758, 32745, 32728, 32706, 32679, 32647,
203
32610, 32568, 32521, 32469, 32413, 32351, 32285, 32214,
204
32138, 32057, 31971, 31881, 31785, 31685, 31581, 31471,
205
31357, 31237, 31114, 30985, 30852, 30714, 30572, 30425,
206
30273, 30117, 29956, 29791, 29621, 29447, 29269, 29086,
207
28898, 28707, 28511, 28310, 28106, 27897, 27684, 27466,
208
27245, 27020, 26790, 26557, 26319, 26077, 25832, 25583,
209
25330, 25073, 24812, 24547, 24279, 24007, 23732, 23453,
210
23170, 22884, 22594, 22301, 22005, 21706, 21403, 21097,
211
20787, 20475, 20159, 19841, 19519, 19195, 18868, 18537,
212
18204, 17869, 17530, 17189, 16846, 16499, 16151, 15800,
213
15446, 15090, 14732, 14372, 14010, 13645, 13278, 12910,
214
12539, 12167, 11793, 11416, 11039, 10659, 10278, 9896,
215
9512, 9126, 8739, 8351, 7961, 7571, 7179, 6786,
216
6392, 5997, 5602, 5205, 4808, 4409, 4011, 3611,
217
3211, 2811, 2410, 2009, 1607, 1206, 804, 402,
218
0, -402, -804, -1206, -1607, -2009, -2410, -2811,
219
-3211, -3611, -4011, -4409, -4808, -5205, -5602, -5997,
220
-6392, -6786, -7179, -7571, -7961, -8351, -8739, -9126,
221
-9512, -9896, -10278, -10659, -11039, -11416, -11793, -12167,
222
-12539, -12910, -13278, -13645, -14010, -14372, -14732, -15090,
223
-15446, -15800, -16151, -16499, -16846, -17189, -17530, -17869,
224
-18204, -18537, -18868, -19195, -19519, -19841, -20159, -20475,
225
-20787, -21097, -21403, -21706, -22005, -22301, -22594, -22884,
226
-23170, -23453, -23732, -24007, -24279, -24547, -24812, -25073,
227
-25330, -25583, -25832, -26077, -26319, -26557, -26790, -27020,
228
-27245, -27466, -27684, -27897, -28106, -28310, -28511, -28707,
229
-28898, -29086, -29269, -29447, -29621, -29791, -29956, -30117,
230
-30273, -30425, -30572, -30714, -30852, -30985, -31114, -31237,
231
-31357, -31471, -31581, -31685, -31785, -31881, -31971, -32057,
232
-32138, -32214, -32285, -32351, -32413, -32469, -32521, -32568,
233
-32610, -32647, -32679, -32706, -32728, -32745, -32758, -32765,
234
-32767, -32765, -32758, -32745, -32728, -32706, -32679, -32647,
235
-32610, -32568, -32521, -32469, -32413, -32351, -32285, -32214,
236
-32138, -32057, -31971, -31881, -31785, -31685, -31581, -31471,
237
-31357, -31237, -31114, -30985, -30852, -30714, -30572, -30425,
238
-30273, -30117, -29956, -29791, -29621, -29447, -29269, -29086,
239
-28898, -28707, -28511, -28310, -28106, -27897, -27684, -27466,
240
-27245, -27020, -26790, -26557, -26319, -26077, -25832, -25583,
241
-25330, -25073, -24812, -24547, -24279, -24007, -23732, -23453,
242
-23170, -22884, -22594, -22301, -22005, -21706, -21403, -21097,
243
-20787, -20475, -20159, -19841, -19519, -19195, -18868, -18537,
244
-18204, -17869, -17530, -17189, -16846, -16499, -16151, -15800,
245
-15446, -15090, -14732, -14372, -14010, -13645, -13278, -12910,
246
-12539, -12167, -11793, -11416, -11039, -10659, -10278, -9896,
247
-9512, -9126, -8739, -8351, -7961, -7571, -7179, -6786,
248
-6392, -5997, -5602, -5205, -4808, -4409, -4011, -3611,
249
-3211, -2811, -2410, -2009, -1607, -1206, -804, -402
250
};
251
252
static int16 C4CosTable[512] =
253
{
254
32767, 32765, 32758, 32745, 32728, 32706, 32679, 32647,
255
32610, 32568, 32521, 32469, 32413, 32351, 32285, 32214,
256
32138, 32057, 31971, 31881, 31785, 31685, 31581, 31471,
257
31357, 31237, 31114, 30985, 30852, 30714, 30572, 30425,
258
30273, 30117, 29956, 29791, 29621, 29447, 29269, 29086,
259
28898, 28707, 28511, 28310, 28106, 27897, 27684, 27466,
260
27245, 27020, 26790, 26557, 26319, 26077, 25832, 25583,
261
25330, 25073, 24812, 24547, 24279, 24007, 23732, 23453,
262
23170, 22884, 22594, 22301, 22005, 21706, 21403, 21097,
263
20787, 20475, 20159, 19841, 19519, 19195, 18868, 18537,
264
18204, 17869, 17530, 17189, 16846, 16499, 16151, 15800,
265
15446, 15090, 14732, 14372, 14010, 13645, 13278, 12910,
266
12539, 12167, 11793, 11416, 11039, 10659, 10278, 9896,
267
9512, 9126, 8739, 8351, 7961, 7571, 7179, 6786,
268
6392, 5997, 5602, 5205, 4808, 4409, 4011, 3611,
269
3211, 2811, 2410, 2009, 1607, 1206, 804, 402,
270
0, -402, -804, -1206, -1607, -2009, -2410, -2811,
271
-3211, -3611, -4011, -4409, -4808, -5205, -5602, -5997,
272
-6392, -6786, -7179, -7571, -7961, -8351, -8739, -9126,
273
-9512, -9896, -10278, -10659, -11039, -11416, -11793, -12167,
274
-12539, -12910, -13278, -13645, -14010, -14372, -14732, -15090,
275
-15446, -15800, -16151, -16499, -16846, -17189, -17530, -17869,
276
-18204, -18537, -18868, -19195, -19519, -19841, -20159, -20475,
277
-20787, -21097, -21403, -21706, -22005, -22301, -22594, -22884,
278
-23170, -23453, -23732, -24007, -24279, -24547, -24812, -25073,
279
-25330, -25583, -25832, -26077, -26319, -26557, -26790, -27020,
280
-27245, -27466, -27684, -27897, -28106, -28310, -28511, -28707,
281
-28898, -29086, -29269, -29447, -29621, -29791, -29956, -30117,
282
-30273, -30425, -30572, -30714, -30852, -30985, -31114, -31237,
283
-31357, -31471, -31581, -31685, -31785, -31881, -31971, -32057,
284
-32138, -32214, -32285, -32351, -32413, -32469, -32521, -32568,
285
-32610, -32647, -32679, -32706, -32728, -32745, -32758, -32765,
286
-32767, -32765, -32758, -32745, -32728, -32706, -32679, -32647,
287
-32610, -32568, -32521, -32469, -32413, -32351, -32285, -32214,
288
-32138, -32057, -31971, -31881, -31785, -31685, -31581, -31471,
289
-31357, -31237, -31114, -30985, -30852, -30714, -30572, -30425,
290
-30273, -30117, -29956, -29791, -29621, -29447, -29269, -29086,
291
-28898, -28707, -28511, -28310, -28106, -27897, -27684, -27466,
292
-27245, -27020, -26790, -26557, -26319, -26077, -25832, -25583,
293
-25330, -25073, -24812, -24547, -24279, -24007, -23732, -23453,
294
-23170, -22884, -22594, -22301, -22005, -21706, -21403, -21097,
295
-20787, -20475, -20159, -19841, -19519, -19195, -18868, -18537,
296
-18204, -17869, -17530, -17189, -16846, -16499, -16151, -15800,
297
-15446, -15090, -14732, -14372, -14010, -13645, -13278, -12910,
298
-12539, -12167, -11793, -11416, -11039, -10659, -10278, -9896,
299
-9512, -9126, -8739, -8351, -7961, -7571, -7179, -6786,
300
-6392, -5997, -5602, -5205, -4808, -4409, -4011, -3611,
301
-3211, -2811, -2410, -2009, -1607, -1206, -804, -402,
302
0, 402, 804, 1206, 1607, 2009, 2410, 2811,
303
3211, 3611, 4011, 4409, 4808, 5205, 5602, 5997,
304
6392, 6786, 7179, 7571, 7961, 8351, 8739, 9126,
305
9512, 9896, 10278, 10659, 11039, 11416, 11793, 12167,
306
12539, 12910, 13278, 13645, 14010, 14372, 14732, 15090,
307
15446, 15800, 16151, 16499, 16846, 17189, 17530, 17869,
308
18204, 18537, 18868, 19195, 19519, 19841, 20159, 20475,
309
20787, 21097, 21403, 21706, 22005, 22301, 22594, 22884,
310
23170, 23453, 23732, 24007, 24279, 24547, 24812, 25073,
311
25330, 25583, 25832, 26077, 26319, 26557, 26790, 27020,
312
27245, 27466, 27684, 27897, 28106, 28310, 28511, 28707,
313
28898, 29086, 29269, 29447, 29621, 29791, 29956, 30117,
314
30273, 30425, 30572, 30714, 30852, 30985, 31114, 31237,
315
31357, 31471, 31581, 31685, 31785, 31881, 31971, 32057,
316
32138, 32214, 32285, 32351, 32413, 32469, 32521, 32568,
317
32610, 32647, 32679, 32706, 32728, 32745, 32758, 32765
318
};
319
320
static uint8 C4TestPattern[12 * 4] =
321
{
322
0x00, 0x00, 0x00, 0xff,
323
0xff, 0xff, 0x00, 0xff,
324
0x00, 0x00, 0x00, 0xff,
325
0xff, 0xff, 0x00, 0x00,
326
0xff, 0xff, 0x00, 0x00,
327
0x80, 0xff, 0xff, 0x7f,
328
0x00, 0x80, 0x00, 0xff,
329
0x7f, 0x00, 0xff, 0x7f,
330
0xff, 0x7f, 0xff, 0xff,
331
0x00, 0x00, 0x01, 0xff,
332
0xff, 0xfe, 0x00, 0x01,
333
0x00, 0xff, 0xfe, 0x00
334
};
335
336
static void C4ConvOAM (void);
337
static void C4DoScaleRotate (int);
338
static void C4DrawLine (int32, int32, int16, int32, int32, int16, uint8);
339
static void C4DrawWireFrame (void);
340
static void C4TransformLines (void);
341
static void C4BitPlaneWave (void);
342
static void C4SprDisintegrate (void);
343
static void C4ProcessSprites (void);
344
345
346
static void C4ConvOAM (void)
347
{
348
uint8 *OAMptr = Memory.C4RAM + (Memory.C4RAM[0x626] << 2);
349
for (uint8 *i = Memory.C4RAM + 0x1fd; i > OAMptr; i -= 4)
350
*i = 0xe0; // Clear OAM-to-be
351
352
uint8 *OAMptr2;
353
uint16 globalX, globalY;
354
int16 SprX, SprY;
355
uint8 SprName, SprAttr;
356
uint8 SprCount;
357
358
globalX = READ_WORD(Memory.C4RAM + 0x0621);
359
globalY = READ_WORD(Memory.C4RAM + 0x0623);
360
OAMptr2 = Memory.C4RAM + 0x200 + (Memory.C4RAM[0x626] >> 2);
361
362
#ifdef DEBUGGER
363
if (Memory.C4RAM[0x625] != 0)
364
printf("$6625=%02x, expected 00\n", Memory.C4RAM[0x625]);
365
if ((Memory.C4RAM[0x626] >> 2) != Memory.C4RAM[0x629])
366
printf("$6629=%02x, expected %02x\n", Memory.C4RAM[0x629], (Memory.C4RAM[0x626] >> 2));
367
if (((uint16) Memory.C4RAM[0x626] << 2) != READ_WORD(Memory.C4RAM + 0x627))
368
printf("$6627=%04x, expected %04x\n", READ_WORD(Memory.C4RAM + 0x627), ((uint16) Memory.C4RAM[0x626] << 2));
369
#endif
370
371
if (Memory.C4RAM[0x0620] != 0)
372
{
373
SprCount = 128 - Memory.C4RAM[0x626];
374
375
uint8 offset = (Memory.C4RAM[0x626] & 3) * 2;
376
uint8 *srcptr = Memory.C4RAM + 0x220;
377
378
for (int i = Memory.C4RAM[0x0620]; i > 0 && SprCount > 0; i--, srcptr += 16)
379
{
380
SprX = READ_WORD(srcptr) - globalX;
381
SprY = READ_WORD(srcptr + 2) - globalY;
382
SprName = srcptr[5];
383
SprAttr = srcptr[4] | srcptr[0x06]; // XXX: mask bits?
384
385
uint8 *sprptr = C4GetMemPointer(READ_3WORD(srcptr + 7));
386
if (*sprptr != 0)
387
{
388
int16 X, Y;
389
390
for (int SprCnt = *sprptr++; SprCnt > 0 && SprCount > 0; SprCnt--, sprptr += 4)
391
{
392
X = (int8) sprptr[1];
393
if (SprAttr & 0x40)
394
X = -X - ((sprptr[0] & 0x20) ? 16 : 8); // flip X
395
X += SprX;
396
397
if (X >= -16 && X <= 272)
398
{
399
Y = (int8) sprptr[2];
400
if (SprAttr & 0x80)
401
Y = -Y - ((sprptr[0] & 0x20) ? 16 : 8);
402
Y += SprY;
403
404
if (Y >= -16 && Y <= 224)
405
{
406
OAMptr[0] = X & 0xff;
407
OAMptr[1] = (uint8) Y;
408
OAMptr[2] = SprName + sprptr[3];
409
OAMptr[3] = SprAttr ^ (sprptr[0] & 0xc0); // XXX: Carry from SprName addition?
410
411
*OAMptr2 &= ~(3 << offset);
412
if (X & 0x100)
413
*OAMptr2 |= 1 << offset;
414
if (sprptr[0] & 0x20)
415
*OAMptr2 |= 2 << offset;
416
417
OAMptr += 4;
418
SprCount--;
419
420
offset = (offset + 2) & 6;
421
if (offset == 0)
422
OAMptr2++;
423
}
424
}
425
}
426
}
427
else
428
if (SprCount > 0)
429
{
430
// XXX: Should we be testing -16<=SprX<=272 and -16<=SprY<=224?
431
OAMptr[0] = (uint8) SprX;
432
OAMptr[1] = (uint8) SprY;
433
OAMptr[2] = SprName;
434
OAMptr[3] = SprAttr;
435
436
*OAMptr2 &= ~(3 << offset);
437
if (SprX & 0x100)
438
*OAMptr2 |= 3 << offset;
439
else
440
*OAMptr2 |= 2 << offset;
441
442
OAMptr += 4;
443
SprCount--;
444
445
offset = (offset + 2) & 6;
446
if (offset == 0)
447
OAMptr2++;
448
}
449
}
450
}
451
}
452
453
static void C4DoScaleRotate (int row_padding)
454
{
455
int16 A, B, C, D;
456
457
// Calculate matrix
458
int32 XScale = READ_WORD(Memory.C4RAM + 0x1f8f);
459
if (XScale & 0x8000)
460
XScale = 0x7fff;
461
462
int32 YScale = READ_WORD(Memory.C4RAM + 0x1f92);
463
if (YScale & 0x8000)
464
YScale = 0x7fff;
465
466
if (READ_WORD(Memory.C4RAM + 0x1f80) == 0) // no rotation
467
{
468
// XXX: only do this for C and D?
469
// XXX: and then only when YScale is 0x1000?
470
A = (int16) XScale;
471
B = 0;
472
C = 0;
473
D = (int16) YScale;
474
}
475
else
476
if (READ_WORD(Memory.C4RAM + 0x1f80) == 128) // 90 degree rotation
477
{
478
// XXX: Really do this?
479
A = 0;
480
B = (int16) (-YScale);
481
C = (int16) XScale;
482
D = 0;
483
}
484
else
485
if (READ_WORD(Memory.C4RAM + 0x1f80) == 256) // 180 degree rotation
486
{
487
// XXX: Really do this?
488
A = (int16) (-XScale);
489
B = 0;
490
C = 0;
491
D = (int16) (-YScale);
492
}
493
else
494
if (READ_WORD(Memory.C4RAM + 0x1f80) == 384) // 270 degree rotation
495
{
496
// XXX: Really do this?
497
A = 0;
498
B = (int16) YScale;
499
C = (int16) (-XScale);
500
D = 0;
501
}
502
else
503
{
504
A = (int16) SAR(C4CosTable[READ_WORD(Memory.C4RAM + 0x1f80) & 0x1ff] * XScale, 15);
505
B = (int16) (-SAR(C4SinTable[READ_WORD(Memory.C4RAM + 0x1f80) & 0x1ff] * YScale, 15));
506
C = (int16) SAR(C4SinTable[READ_WORD(Memory.C4RAM + 0x1f80) & 0x1ff] * XScale, 15);
507
D = (int16) SAR(C4CosTable[READ_WORD(Memory.C4RAM + 0x1f80) & 0x1ff] * YScale, 15);
508
}
509
510
// Calculate Pixel Resolution
511
uint8 w = Memory.C4RAM[0x1f89] & ~7;
512
uint8 h = Memory.C4RAM[0x1f8c] & ~7;
513
514
//printf("%dx%d XScale=%04x YScale=%04x angle=%03x\n", w, h, XScale, YScale, READ_WORD(Memory.C4RAM + 0x1f80) & 0x1ff);
515
//printf("Matrix: [%10g %10g] [%04x %04x]\n", A / 4096.0, B / 4096.0, A & 0xffff, B & 0xffff);
516
//printf(" [%10g %10g] [%04x %04x]\n", C / 4096.0, D / 4096.0, C & 0xffff, D & 0xffff);
517
518
// Clear the output RAM
519
memset(Memory.C4RAM, 0, (w + row_padding / 4) * h / 2);
520
521
int32 Cx = (int16) READ_WORD(Memory.C4RAM + 0x1f83);
522
int32 Cy = (int16) READ_WORD(Memory.C4RAM + 0x1f86);
523
524
#ifdef DEBUGGER
525
if (Memory.C4RAM[0x1f97] != 0)
526
printf("$7f97=%02x, expected 00\n", Memory.C4RAM[0x1f97]);
527
if ((Cx & ~1) != w / 2 || (Cy & ~1) != h / 2)
528
printf("Center is not middle of image! (%d, %d) != (%d, %d)\n", Cx, Cy, w / 2, h / 2);
529
#endif
530
531
// Calculate start position (i.e. (Ox, Oy) = (0, 0))
532
// The low 12 bits are fractional, so (Cx<<12) gives us the Cx we want in the function.
533
// We do Cx*A etc normally because the matrix parameters already have the fractional parts.
534
int32 LineX = (Cx << 12) - Cx * A - Cx * B;
535
int32 LineY = (Cy << 12) - Cy * C - Cy * D;
536
537
// Start loop
538
uint32 X, Y;
539
uint8 byte;
540
int outidx = 0;
541
uint8 bit = 0x80;
542
543
for (int y = 0; y < h; y++)
544
{
545
X = LineX;
546
Y = LineY;
547
548
for (int x = 0; x < w; x++)
549
{
550
if ((X >> 12) >= w || (Y >> 12) >= h)
551
byte = 0;
552
else
553
{
554
uint32 addr = (Y >> 12) * w + (X >> 12);
555
byte = Memory.C4RAM[0x600 + (addr >> 1)];
556
if (addr & 1)
557
byte >>= 4;
558
}
559
560
// De-bitplanify
561
if (byte & 1)
562
Memory.C4RAM[outidx] |= bit;
563
if (byte & 2)
564
Memory.C4RAM[outidx + 1] |= bit;
565
if (byte & 4)
566
Memory.C4RAM[outidx + 16] |= bit;
567
if (byte & 8)
568
Memory.C4RAM[outidx + 17] |= bit;
569
570
bit >>= 1;
571
if (bit == 0)
572
{
573
bit = 0x80;
574
outidx += 32;
575
}
576
577
X += A; // Add 1 to output x => add an A and a C
578
Y += C;
579
}
580
581
outidx += 2 + row_padding;
582
if (outidx & 0x10)
583
outidx &= ~0x10;
584
else
585
outidx -= w * 4 + row_padding;
586
587
LineX += B; // Add 1 to output y => add a B and a D
588
LineY += D;
589
}
590
}
591
592
static void C4DrawLine (int32 X1, int32 Y1, int16 Z1, int32 X2, int32 Y2, int16 Z2, uint8 Color)
593
{
594
// Transform coordinates
595
C4WFXVal = (int16) X1;
596
C4WFYVal = (int16) Y1;
597
C4WFZVal = Z1;
598
C4WFScale = Memory.C4RAM[0x1f90];
599
C4WFX2Val = Memory.C4RAM[0x1f86];
600
C4WFY2Val = Memory.C4RAM[0x1f87];
601
C4WFDist = Memory.C4RAM[0x1f88];
602
C4TransfWireFrame2();
603
X1 = (C4WFXVal + 48) << 8;
604
Y1 = (C4WFYVal + 48) << 8;
605
606
C4WFXVal = (int16) X2;
607
C4WFYVal = (int16) Y2;
608
C4WFZVal = Z2;
609
C4TransfWireFrame2();
610
X2 = (C4WFXVal + 48) << 8;
611
Y2 = (C4WFYVal + 48) << 8;
612
613
// Get line info
614
C4WFXVal = (int16) (X1 >> 8);
615
C4WFYVal = (int16) (Y1 >> 8);
616
C4WFX2Val = (int16) (X2 >> 8);
617
C4WFY2Val = (int16) (Y2 >> 8);
618
C4CalcWireFrame();
619
X2 = (int16) C4WFXVal;
620
Y2 = (int16) C4WFYVal;
621
622
// Render line
623
for (int i = C4WFDist ? C4WFDist : 1; i > 0; i--)
624
{
625
if (X1 > 0xff && Y1 > 0xff && X1 < 0x6000 && Y1 < 0x6000)
626
{
627
uint16 addr = (((Y1 >> 8) >> 3) << 8) - (((Y1 >> 8) >> 3) << 6) + (((X1 >> 8) >> 3) << 4) + ((Y1 >> 8) & 7) * 2;
628
uint8 bit = 0x80 >> ((X1 >> 8) & 7);
629
630
Memory.C4RAM[addr + 0x300] &= ~bit;
631
Memory.C4RAM[addr + 0x301] &= ~bit;
632
if (Color & 1)
633
Memory.C4RAM[addr + 0x300] |= bit;
634
if (Color & 2)
635
Memory.C4RAM[addr + 0x301] |= bit;
636
}
637
638
X1 += X2;
639
Y1 += Y2;
640
}
641
}
642
643
static void C4DrawWireFrame (void)
644
{
645
uint8 *line = C4GetMemPointer(READ_3WORD(Memory.C4RAM + 0x1f80));
646
uint8 *point1, *point2;
647
int16 X1, Y1, Z1;
648
int16 X2, Y2, Z2;
649
uint8 Color;
650
651
#ifdef DEBUGGER
652
if (READ_3WORD(Memory.C4RAM + 0x1f8f) & 0xff00ff)
653
printf("wireframe: Unexpected value in $7f8f: %06x\n", READ_3WORD(Memory.C4RAM + 0x1f8f));
654
if (READ_3WORD(Memory.C4RAM + 0x1fa4) != 0x001000)
655
printf("wireframe: Unexpected value in $7fa4: %06x\n", READ_3WORD(Memory.C4RAM + 0x1fa4));
656
#endif
657
658
for (int i = Memory.C4RAM[0x0295]; i > 0; i--, line += 5)
659
{
660
if (line[0] == 0xff && line[1] == 0xff)
661
{
662
uint8 *tmp = line - 5;
663
while (tmp[2] == 0xff && tmp[3] == 0xff)
664
tmp -= 5;
665
point1 = C4GetMemPointer((Memory.C4RAM[0x1f82] << 16) | (tmp[2] << 8) | tmp[3]);
666
}
667
else
668
point1 = C4GetMemPointer((Memory.C4RAM[0x1f82] << 16) | (line[0] << 8) | line[1]);
669
670
point2 = C4GetMemPointer((Memory.C4RAM[0x1f82] << 16) | (line[2] << 8) | line[3]);
671
672
X1 = (point1[0] << 8) | point1[1];
673
Y1 = (point1[2] << 8) | point1[3];
674
Z1 = (point1[4] << 8) | point1[5];
675
X2 = (point2[0] << 8) | point2[1];
676
Y2 = (point2[2] << 8) | point2[3];
677
Z2 = (point2[4] << 8) | point2[5];
678
679
Color = line[4];
680
681
C4DrawLine(X1, Y1, Z1, X2, Y2, Z2, Color);
682
}
683
}
684
685
static void C4TransformLines (void)
686
{
687
C4WFX2Val = Memory.C4RAM[0x1f83];
688
C4WFY2Val = Memory.C4RAM[0x1f86];
689
C4WFDist = Memory.C4RAM[0x1f89];
690
C4WFScale = Memory.C4RAM[0x1f8c];
691
692
#ifdef DEBUGGER
693
if (Memory.C4RAM[0x1f8a] != 0x90)
694
printf("lines: $7f8a = %02x, expected 90\n", READ_WORD(Memory.C4RAM + 0x1f8a));
695
#endif
696
697
// Transform vertices
698
uint8 *ptr = Memory.C4RAM;
699
700
for (int i = READ_WORD(Memory.C4RAM + 0x1f80); i > 0; i--, ptr += 0x10)
701
{
702
C4WFXVal = READ_WORD(ptr + 1);
703
C4WFYVal = READ_WORD(ptr + 5);
704
C4WFZVal = READ_WORD(ptr + 9);
705
C4TransfWireFrame();
706
707
// Displace
708
WRITE_WORD(ptr + 1, C4WFXVal + 0x80);
709
WRITE_WORD(ptr + 5, C4WFYVal + 0x50);
710
}
711
712
WRITE_WORD(Memory.C4RAM + 0x600, 23);
713
WRITE_WORD(Memory.C4RAM + 0x602, 0x60);
714
WRITE_WORD(Memory.C4RAM + 0x605, 0x40);
715
WRITE_WORD(Memory.C4RAM + 0x600 + 8, 23);
716
WRITE_WORD(Memory.C4RAM + 0x602 + 8, 0x60);
717
WRITE_WORD(Memory.C4RAM + 0x605 + 8, 0x40);
718
719
ptr = Memory.C4RAM + 0xb02;
720
uint8 *ptr2 = Memory.C4RAM;
721
722
for (int i = READ_WORD(Memory.C4RAM + 0xb00); i > 0; i--, ptr += 2, ptr2 += 8)
723
{
724
C4WFXVal = READ_WORD(Memory.C4RAM + (ptr[0] << 4) + 1);
725
C4WFYVal = READ_WORD(Memory.C4RAM + (ptr[0] << 4) + 5);
726
C4WFX2Val = READ_WORD(Memory.C4RAM + (ptr[1] << 4) + 1);
727
C4WFY2Val = READ_WORD(Memory.C4RAM + (ptr[1] << 4) + 5);
728
C4CalcWireFrame();
729
730
WRITE_WORD(ptr2 + 0x600, C4WFDist ? C4WFDist : 1);
731
WRITE_WORD(ptr2 + 0x602, C4WFXVal);
732
WRITE_WORD(ptr2 + 0x605, C4WFYVal);
733
}
734
}
735
736
static void C4BitPlaneWave (void)
737
{
738
static uint16 bmpdata[] =
739
{
740
0x0000, 0x0002, 0x0004, 0x0006, 0x0008, 0x000A, 0x000C, 0x000E,
741
0x0200, 0x0202, 0x0204, 0x0206, 0x0208, 0x020A, 0x020C, 0x020E,
742
0x0400, 0x0402, 0x0404, 0x0406, 0x0408, 0x040A, 0x040C, 0x040E,
743
0x0600, 0x0602, 0x0604, 0x0606, 0x0608, 0x060A, 0x060C, 0x060E,
744
0x0800, 0x0802, 0x0804, 0x0806, 0x0808, 0x080A, 0x080C, 0x080E
745
};
746
747
uint8 *dst = Memory.C4RAM;
748
uint32 waveptr = Memory.C4RAM[0x1f83];
749
uint16 mask1 = 0xc0c0;
750
uint16 mask2 = 0x3f3f;
751
752
#ifdef DEBUGGER
753
if (READ_3WORD(Memory.C4RAM + 0x1f80) != Memory.C4RAM[waveptr + 0xb00])
754
printf("$7f80=%06x, expected %02x\n", READ_3WORD(Memory.C4RAM + 0x1f80), Memory.C4RAM[waveptr + 0xb00]);
755
#endif
756
757
for (int j = 0; j < 0x10; j++)
758
{
759
do
760
{
761
int16 height = -((int8) Memory.C4RAM[waveptr + 0xb00]) - 16;
762
763
for (int i = 0; i < 40; i++)
764
{
765
uint16 tmp = READ_WORD(dst + bmpdata[i]) & mask2;
766
if (height >= 0)
767
{
768
if (height < 8)
769
tmp |= mask1 & READ_WORD(Memory.C4RAM + 0xa00 + height * 2);
770
else
771
tmp |= mask1 & 0xff00;
772
}
773
774
WRITE_WORD(dst + bmpdata[i], tmp);
775
776
height++;
777
}
778
779
waveptr = (waveptr + 1) & 0x7f;
780
mask1 = (mask1 >> 2) | (mask1 << 6);
781
mask2 = (mask2 >> 2) | (mask2 << 6);
782
}
783
while (mask1 != 0xc0c0);
784
785
dst += 16;
786
787
do
788
{
789
int16 height = -((int8) Memory.C4RAM[waveptr + 0xb00]) - 16;
790
791
for (int i = 0; i < 40; i++)
792
{
793
uint16 tmp = READ_WORD(dst + bmpdata[i]) & mask2;
794
if (height >= 0)
795
{
796
if (height < 8)
797
tmp |= mask1 & READ_WORD(Memory.C4RAM + 0xa10 + height * 2);
798
else
799
tmp |= mask1 & 0xff00;
800
}
801
802
WRITE_WORD(dst + bmpdata[i], tmp);
803
804
height++;
805
}
806
807
waveptr = (waveptr + 1) & 0x7f;
808
mask1 = (mask1 >> 2) | (mask1 << 6);
809
mask2 = (mask2 >> 2) | (mask2 << 6);
810
}
811
while (mask1 != 0xc0c0);
812
813
dst += 16;
814
}
815
}
816
817
static void C4SprDisintegrate (void)
818
{
819
uint8 *src;
820
uint8 width, height;
821
uint32 StartX, StartY;
822
int32 scaleX, scaleY;
823
int32 Cx, Cy;
824
825
width = Memory.C4RAM[0x1f89];
826
height = Memory.C4RAM[0x1f8c];
827
Cx = (int16) READ_WORD(Memory.C4RAM + 0x1f80);
828
Cy = (int16) READ_WORD(Memory.C4RAM + 0x1f83);
829
830
#ifdef DEBUGGER
831
if ((Cx & ~1) != width / 2 || (Cy & ~1) != height / 2)
832
printf("Center is not middle of image for disintegrate! (%d, %d) != (%d, %d)\n", Cx, Cy, width / 2, height / 2);
833
#endif
834
835
scaleX = (int16) READ_WORD(Memory.C4RAM + 0x1f86);
836
scaleY = (int16) READ_WORD(Memory.C4RAM + 0x1f8f);
837
StartX = -Cx * scaleX + (Cx << 8);
838
StartY = -Cy * scaleY + (Cy << 8);
839
840
src = Memory.C4RAM + 0x600;
841
842
memset(Memory.C4RAM, 0, width * height / 2);
843
844
for (uint32 y = StartY, i = 0; i < height; i++, y += scaleY)
845
{
846
for (uint32 x = StartX, j = 0; j < width; j++, x += scaleX)
847
{
848
if ((x >> 8) < width && (y >> 8) < height && (y >> 8) * width + (x >> 8) < 0x2000)
849
{
850
uint8 pixel = (j & 1) ? (*src >> 4) : *src;
851
int idx = (y >> 11) * width * 4 + (x >> 11) * 32 + ((y >> 8) & 7) * 2;
852
uint8 mask = 0x80 >> ((x >> 8) & 7);
853
854
if (pixel & 1)
855
Memory.C4RAM[idx] |= mask;
856
if (pixel & 2)
857
Memory.C4RAM[idx + 1] |= mask;
858
if (pixel & 4)
859
Memory.C4RAM[idx + 16] |= mask;
860
if (pixel & 8)
861
Memory.C4RAM[idx + 17] |= mask;
862
}
863
864
if (j & 1)
865
src++;
866
}
867
}
868
}
869
870
static void C4ProcessSprites (void)
871
{
872
switch (Memory.C4RAM[0x1f4d])
873
{
874
case 0x00: // Build OAM
875
#ifdef DEBUGGER
876
//printf("00 00 Build OAM!\n");
877
#endif
878
C4ConvOAM();
879
break;
880
881
case 0x03: // Scale/Rotate
882
#ifdef DEBUGGER
883
//printf("00 03 Scale/Rotate!\n");
884
#endif
885
C4DoScaleRotate(0);
886
break;
887
888
case 0x05: // Transform Lines
889
#ifdef DEBUGGER
890
//printf("00 05 Transform Lines!\n");
891
#endif
892
C4TransformLines();
893
break;
894
895
case 0x07: // Scale/Rotate
896
#ifdef DEBUGGER
897
//printf("00 07 Scale/Rotate!\n");
898
#endif
899
C4DoScaleRotate(64);
900
break;
901
902
case 0x08: // Draw wireframe
903
#ifdef DEBUGGER
904
//printf("00 08 Draw wireframe!\n");
905
#endif
906
C4DrawWireFrame();
907
break;
908
909
case 0x0b: // Disintegrate
910
#ifdef DEBUGGER
911
//printf("00 0b Disintegrate!\n");
912
#endif
913
C4SprDisintegrate();
914
break;
915
916
case 0x0c: // Wave
917
#ifdef DEBUGGER
918
//printf("00 0b Wave!\n");
919
#endif
920
C4BitPlaneWave();
921
break;
922
923
default:
924
#ifdef DEBUGGER
925
printf("Unknown C4 sprite command (%02x)\n", Memory.C4RAM[0x1f4d]);
926
#endif
927
break;
928
}
929
}
930
931
void S9xInitC4 (void)
932
{
933
// Stupid zsnes code, we can't do the logical thing without breaking savestates
934
// Memory.C4RAM = &Memory.FillRAM [0x6000];
935
memset(Memory.C4RAM, 0, 0x2000);
936
}
937
938
uint8 S9xGetC4 (uint16 Address)
939
{
940
if (Address == 0x7f5e)
941
return (0);
942
943
return (Memory.C4RAM[Address - 0x6000]);
944
}
945
946
void S9xSetC4 (uint8 byte, uint16 Address)
947
{
948
Memory.C4RAM[Address - 0x6000] = byte;
949
950
if (Address == 0x7f4f)
951
{
952
if (Memory.C4RAM[0x1f4d] == 0x0e && byte < 0x40 && (byte & 3) == 0)
953
{
954
#ifdef DEBUGGER
955
printf("Test command %02x 0e used!\n", byte);
956
#endif
957
Memory.C4RAM[0x1f80] = byte >> 2;
958
}
959
else
960
{
961
switch (byte)
962
{
963
case 0x00: // Sprite
964
#ifdef DEBUGGER
965
//printf("00 Sprite!\n");
966
#endif
967
C4ProcessSprites();
968
break;
969
970
case 0x01: // Draw wireframe
971
#ifdef DEBUGGER
972
//printf("01 Draw wireframe!\n");
973
if (Memory.C4RAM[0x1f4d] != 8)
974
printf("$7f4d=%02x, expected 08 for command 01 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]);
975
#endif
976
memset(Memory.C4RAM + 0x300, 0, 16 * 12 * 3 * 4);
977
C4DrawWireFrame();
978
break;
979
980
case 0x05: // Propulsion (?)
981
{
982
#ifdef DEBUGGER
983
//printf("05 Propulsion (?)!\n");
984
if (Memory.C4RAM[0x1f4d] != 2)
985
printf("$7f4d=%02x, expected 02 for command 05 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]);
986
#endif
987
int32 tmp = 0x10000;
988
if (READ_WORD(Memory.C4RAM + 0x1f83))
989
tmp = SAR((tmp / READ_WORD(Memory.C4RAM + 0x1f83)) * READ_WORD(Memory.C4RAM + 0x1f81), 8);
990
991
WRITE_WORD(Memory.C4RAM + 0x1f80, (uint16) tmp);
992
break;
993
}
994
995
case 0x0d: // Set vector length
996
#ifdef DEBUGGER
997
//printf("0d Set vector length!\n");
998
if (Memory.C4RAM[0x1f4d] != 2)
999
printf("$7f4d=%02x, expected 02 for command 0d %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]);
1000
#endif
1001
C41FXVal = READ_WORD(Memory.C4RAM + 0x1f80);
1002
C41FYVal = READ_WORD(Memory.C4RAM + 0x1f83);
1003
C41FDistVal = READ_WORD(Memory.C4RAM + 0x1f86);
1004
C4Op0D();
1005
WRITE_WORD(Memory.C4RAM + 0x1f89, C41FXVal);
1006
WRITE_WORD(Memory.C4RAM + 0x1f8c, C41FYVal);
1007
break;
1008
1009
case 0x10: // Polar to rectangluar
1010
{
1011
#ifdef DEBUGGER
1012
//printf("10 Polar->Rect!\n");
1013
if (Memory.C4RAM[0x1f4d] != 2)
1014
printf("$7f4d=%02x, expected 02 for command 10 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]);
1015
#endif
1016
int32 tmp;
1017
int32 r1;
1018
r1 = READ_WORD(Memory.C4RAM + 0x1f83);
1019
if (r1 & 0x8000)
1020
r1 |= ~0x7fff;
1021
else
1022
r1 &= 0x7fff;
1023
1024
tmp = SAR(r1 * C4CosTable[READ_WORD(Memory.C4RAM + 0x1f80) & 0x1ff] * 2, 16);
1025
WRITE_3WORD(Memory.C4RAM + 0x1f86, tmp);
1026
tmp = SAR(r1 * C4SinTable[READ_WORD(Memory.C4RAM + 0x1f80) & 0x1ff] * 2, 16);
1027
WRITE_3WORD(Memory.C4RAM + 0x1f89, (tmp - SAR(tmp, 6)));
1028
break;
1029
}
1030
1031
case 0x13: // Polar to rectangluar
1032
{
1033
#ifdef DEBUGGER
1034
//printf("13 Polar->Rect!\n");
1035
if (Memory.C4RAM[0x1f4d] != 2)
1036
printf("$7f4d=%02x, expected 02 for command 13 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]);
1037
#endif
1038
int32 tmp;
1039
tmp = SAR((int32) READ_WORD(Memory.C4RAM + 0x1f83) * C4CosTable[READ_WORD(Memory.C4RAM + 0x1f80) & 0x1ff] * 2, 8);
1040
WRITE_3WORD(Memory.C4RAM + 0x1f86, tmp);
1041
tmp = SAR((int32) READ_WORD(Memory.C4RAM + 0x1f83) * C4SinTable[READ_WORD(Memory.C4RAM + 0x1f80) & 0x1ff] * 2, 8);
1042
WRITE_3WORD(Memory.C4RAM + 0x1f89, tmp);
1043
break;
1044
}
1045
1046
case 0x15: // Pythagorean
1047
#ifdef DEBUGGER
1048
//printf("15 Pythagorean!\n");
1049
if (Memory.C4RAM[0x1f4d] != 2)
1050
printf("$7f4d=%02x, expected 02 for command 15 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]);
1051
#endif
1052
C41FXVal = READ_WORD(Memory.C4RAM + 0x1f80);
1053
C41FYVal = READ_WORD(Memory.C4RAM + 0x1f83);
1054
//C4Op15(); // optimized to:
1055
C41FDist = (int16) sqrt((double) C41FXVal * C41FXVal + (double) C41FYVal * C41FYVal);
1056
WRITE_WORD(Memory.C4RAM + 0x1f80, C41FDist);
1057
break;
1058
1059
case 0x1f: // atan
1060
#ifdef DEBUGGER
1061
//printf("1f atan!\n");
1062
if (Memory.C4RAM[0x1f4d] != 2)
1063
printf("$7f4d=%02x, expected 02 for command 1f %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]);
1064
#endif
1065
C41FXVal = READ_WORD(Memory.C4RAM + 0x1f80);
1066
C41FYVal = READ_WORD(Memory.C4RAM + 0x1f83);
1067
C4Op1F();
1068
WRITE_WORD(Memory.C4RAM + 0x1f86, C41FAngleRes);
1069
break;
1070
1071
case 0x22: // Trapezoid
1072
{
1073
#ifdef DEBUGGER
1074
//printf("22 Trapezoid!\n");
1075
if (Memory.C4RAM[0x1f4d] != 2)
1076
printf("$7f4d=%02x, expected 02 for command 22 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]);
1077
#endif
1078
int16 angle1 = READ_WORD(Memory.C4RAM + 0x1f8c) & 0x1ff;
1079
int16 angle2 = READ_WORD(Memory.C4RAM + 0x1f8f) & 0x1ff;
1080
1081
#ifdef DEBUGGER
1082
if (C4CosTable[angle1] == 0)
1083
fprintf(stderr, "22 Trapezoid: Invalid tangent! angle1=%d\n", angle1);
1084
if (C4CosTable[angle2] == 0)
1085
fprintf(stderr, "22 Trapezoid: Invalid tangent! angle2=%d\n", angle2);
1086
#endif
1087
1088
int32 tan1 = (C4CosTable[angle1] != 0) ? ((((int32) C4SinTable[angle1]) << 16) / C4CosTable[angle1]) : 0x80000000;
1089
int32 tan2 = (C4CosTable[angle2] != 0) ? ((((int32) C4SinTable[angle2]) << 16) / C4CosTable[angle2]) : 0x80000000;
1090
1091
int16 y = READ_WORD(Memory.C4RAM + 0x1f83) - READ_WORD(Memory.C4RAM + 0x1f89);
1092
int16 left, right;
1093
1094
for (int j = 0; j < 225; j++)
1095
{
1096
if (y >= 0)
1097
{
1098
left = SAR((int32) tan1 * y, 16) - READ_WORD(Memory.C4RAM + 0x1f80) + READ_WORD(Memory.C4RAM + 0x1f86);
1099
right = SAR((int32) tan2 * y, 16) - READ_WORD(Memory.C4RAM + 0x1f80) + READ_WORD(Memory.C4RAM + 0x1f86) + READ_WORD(Memory.C4RAM + 0x1f93);
1100
1101
if (left < 0 && right < 0)
1102
{
1103
left = 1;
1104
right = 0;
1105
}
1106
else
1107
if (left < 0)
1108
left = 0;
1109
else
1110
if (right < 0)
1111
right = 0;
1112
1113
if (left > 255 && right > 255)
1114
{
1115
left = 255;
1116
right = 254;
1117
}
1118
else
1119
if (left > 255)
1120
left = 255;
1121
else
1122
if (right > 255)
1123
right = 255;
1124
}
1125
else
1126
{
1127
left = 1;
1128
right = 0;
1129
}
1130
1131
Memory.C4RAM[j + 0x800] = (uint8) left;
1132
Memory.C4RAM[j + 0x900] = (uint8) right;
1133
1134
y++;
1135
}
1136
1137
break;
1138
}
1139
1140
case 0x25: // Multiply
1141
{
1142
#ifdef DEBUGGER
1143
//printf("25 Multiply!\n");
1144
if (Memory.C4RAM[0x1f4d] != 2)
1145
printf("$7f4d=%02x, expected 02 for command 25 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]);
1146
#endif
1147
int32 foo = READ_3WORD(Memory.C4RAM + 0x1f80);
1148
int32 bar = READ_3WORD(Memory.C4RAM + 0x1f83);
1149
foo *= bar;
1150
WRITE_3WORD(Memory.C4RAM + 0x1f80, foo);
1151
break;
1152
}
1153
1154
case 0x2d: // Transform Coords
1155
#ifdef DEBUGGER
1156
//printf("2d Transform Coords!\n");
1157
if (Memory.C4RAM[0x1f4d] != 2)
1158
printf("$7f4d=%02x, expected 02 for command 2d %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]);
1159
if (READ_3WORD(Memory.C4RAM + 0x1f8f) & 0xff00ff)
1160
printf("2d transform coords: Unexpected value in $7f8f: %06x\n", READ_3WORD(Memory.C4RAM + 0x1f8f));
1161
if (READ_3WORD(Memory.C4RAM + 0x1f8c) != 0x001000)
1162
printf("0d transform coords: Unexpected value in $7f8c: %06x\n", READ_3WORD(Memory.C4RAM + 0x1f8c));
1163
#endif
1164
C4WFXVal = READ_WORD(Memory.C4RAM + 0x1f81);
1165
C4WFYVal = READ_WORD(Memory.C4RAM + 0x1f84);
1166
C4WFZVal = READ_WORD(Memory.C4RAM + 0x1f87);
1167
C4WFX2Val = Memory.C4RAM[0x1f89];
1168
C4WFY2Val = Memory.C4RAM[0x1f8a];
1169
C4WFDist = Memory.C4RAM[0x1f8b];
1170
C4WFScale = READ_WORD(Memory.C4RAM + 0x1f90);
1171
C4TransfWireFrame2();
1172
WRITE_WORD(Memory.C4RAM + 0x1f80, C4WFXVal);
1173
WRITE_WORD(Memory.C4RAM + 0x1f83, C4WFYVal);
1174
break;
1175
1176
case 0x40: // Sum
1177
{
1178
#ifdef DEBUGGER
1179
//printf("40 Sum!\n");
1180
if (Memory.C4RAM[0x1f4d] != 0x0e)
1181
printf("$7f4d=%02x, expected 0e for command 40 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]);
1182
#endif
1183
uint16 sum = 0;
1184
for (int i = 0; i < 0x800; sum += Memory.C4RAM[i++]) ;
1185
WRITE_WORD(Memory.C4RAM + 0x1f80, sum);
1186
break;
1187
}
1188
1189
case 0x54: // Square
1190
{
1191
#ifdef DEBUGGER
1192
//printf("54 Square!\n");
1193
if (Memory.C4RAM[0x1f4d] != 0x0e)
1194
printf("$7f4d=%02x, expected 0e for command 54 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]);
1195
#endif
1196
int64 a = SAR((int64) READ_3WORD(Memory.C4RAM + 0x1f80) << 40, 40);
1197
//printf("%08X%08X\n", (uint32) (a>>32), (uint32) (a&0xFFFFFFFF));
1198
a *= a;
1199
//printf("%08X%08X\n", (uint32) (a>>32), (uint32) (a&0xFFFFFFFF));
1200
WRITE_3WORD(Memory.C4RAM + 0x1f83, a);
1201
WRITE_3WORD(Memory.C4RAM + 0x1f86, (a >> 24));
1202
break;
1203
}
1204
1205
case 0x5c: // Immediate Reg
1206
#ifdef DEBUGGER
1207
//printf("5c Immediate Reg!\n");
1208
if (Memory.C4RAM[0x1f4d] != 0x0e)
1209
printf("$7f4d=%02x, expected 0e for command 5c %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]);
1210
#endif
1211
for (int i = 0; i < 12 * 4; i++)
1212
Memory.C4RAM[i] = C4TestPattern[i];
1213
break;
1214
1215
case 0x89: // Immediate ROM
1216
#ifdef DEBUGGER
1217
//printf("89 Immediate ROM!\n");
1218
if (Memory.C4RAM[0x1f4d] != 0x0e)
1219
printf("$7f4d=%02x, expected 0e for command 89 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]);
1220
#endif
1221
Memory.C4RAM[0x1f80] = 0x36;
1222
Memory.C4RAM[0x1f81] = 0x43;
1223
Memory.C4RAM[0x1f82] = 0x05;
1224
break;
1225
1226
default:
1227
#ifdef DEBUGGER
1228
printf("Unknown C4 command (%02x)\n", byte);
1229
#endif
1230
break;
1231
}
1232
}
1233
}
1234
else
1235
if (Address == 0x7f47)
1236
{
1237
#ifdef DEBUGGER
1238
//printf("C4 load memory %06x => %04x, %04x bytes\n", READ_3WORD(Memory.C4RAM + 0x1f40), READ_WORD(Memory.C4RAM + 0x1f45), READ_WORD(Memory.C4RAM + 0x1f43));
1239
if (byte != 0)
1240
printf("C4 load: non-0 written to $7f47! Wrote %02x\n", byte);
1241
if (READ_WORD(Memory.C4RAM + 0x1f45) < 0x6000 || (READ_WORD(Memory.C4RAM + 0x1f45) + READ_WORD(Memory.C4RAM + 0x1f43)) > 0x6c00)
1242
printf("C4 load: Dest unusual! It's %04x\n", READ_WORD(Memory.C4RAM + 0x1f45));
1243
#endif
1244
memmove(Memory.C4RAM + (READ_WORD(Memory.C4RAM + 0x1f45) & 0x1fff), C4GetMemPointer(READ_3WORD(Memory.C4RAM + 0x1f40)), READ_WORD(Memory.C4RAM + 0x1f43));
1245
}
1246
}
1247
1248