Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/genplus-gx/core/cd_hw/gfx.c
2 views
1
/***************************************************************************************
2
* Genesis Plus
3
* CD graphics processor
4
*
5
* Copyright (C) 2012 Eke-Eke (Genesis Plus GX)
6
*
7
* Redistribution and use of this code or any derivative works are permitted
8
* provided that the following conditions are met:
9
*
10
* - Redistributions may not be sold, nor may they be used in a commercial
11
* product or activity.
12
*
13
* - Redistributions that are modified from the original source must include the
14
* complete source code, including the source code for all components used by a
15
* binary built from the modified sources. However, as a special exception, the
16
* source code distributed need not include anything that is normally distributed
17
* (in either source or binary form) with the major components (compiler, kernel,
18
* and so on) of the operating system on which the executable runs, unless that
19
* component itself accompanies the executable.
20
*
21
* - Redistributions must reproduce the above copyright notice, this list of
22
* conditions and the following disclaimer in the documentation and/or other
23
* materials provided with the distribution.
24
*
25
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
29
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35
* POSSIBILITY OF SUCH DAMAGE.
36
*
37
****************************************************************************************/
38
#include "shared.h"
39
40
/***************************************************************/
41
/* WORD-RAM DMA interfaces (1M & 2M modes) */
42
/***************************************************************/
43
44
void word_ram_0_dma_w(unsigned int words)
45
{
46
uint16 data;
47
48
/* CDC buffer source address */
49
uint16 src_index = cdc.dac.w & 0x3ffe;
50
51
/* WORD-RAM destination address*/
52
uint32 dst_index = (scd.regs[0x0a>>1].w << 3) & 0x1fffe;
53
54
/* update DMA destination address */
55
scd.regs[0x0a>>1].w += (words >> 2);
56
57
/* update DMA source address */
58
cdc.dac.w += (words << 1);
59
60
/* DMA transfer */
61
while (words--)
62
{
63
/* read 16-bit word from CDC buffer */
64
data = *(uint16 *)(cdc.ram + src_index);
65
66
#ifdef LSB_FIRST
67
/* source data is stored in big endian format */
68
data = ((data >> 8) | (data << 8)) & 0xffff;
69
#endif
70
71
/* write 16-bit word to WORD-RAM */
72
*(uint16 *)(scd.word_ram[0] + dst_index) = data ;
73
74
/* increment CDC buffer source address */
75
src_index = (src_index + 2) & 0x3ffe;
76
77
/* increment WORD-RAM destination address */
78
dst_index = (dst_index + 2) & 0x1fffe;
79
}
80
}
81
82
void word_ram_1_dma_w(unsigned int words)
83
{
84
uint16 data;
85
86
/* CDC buffer source address */
87
uint16 src_index = cdc.dac.w & 0x3ffe;
88
89
/* WORD-RAM destination address*/
90
uint32 dst_index = ((scd.regs[0x0a>>1].w << 3) & 0x1fffe);
91
92
/* update DMA destination address */
93
scd.regs[0x0a>>1].w += (words >> 2);
94
95
/* update DMA source address */
96
cdc.dac.w += (words << 1);
97
98
/* DMA transfer */
99
while (words--)
100
{
101
/* read 16-bit word from CDC buffer */
102
data = *(uint16 *)(cdc.ram + src_index);
103
104
#ifdef LSB_FIRST
105
/* source data is stored in big endian format */
106
data = ((data >> 8) | (data << 8)) & 0xffff;
107
#endif
108
109
/* write 16-bit word to WORD-RAM */
110
*(uint16 *)(scd.word_ram[1] + dst_index) = data ;
111
112
/* increment CDC buffer source address */
113
src_index = (src_index + 2) & 0x3ffe;
114
115
/* increment WORD-RAM destination address */
116
dst_index = (dst_index + 2) & 0x1fffe;
117
}
118
}
119
120
void word_ram_2M_dma_w(unsigned int words)
121
{
122
uint16 data;
123
124
/* CDC buffer source address */
125
uint16 src_index = cdc.dac.w & 0x3ffe;
126
127
/* WORD-RAM destination address*/
128
uint32 dst_index = (scd.regs[0x0a>>1].w << 3) & 0x3fffe;
129
130
/* update DMA destination address */
131
scd.regs[0x0a>>1].w += (words >> 2);
132
133
/* update DMA source address */
134
cdc.dac.w += (words << 1);
135
136
/* DMA transfer */
137
while (words--)
138
{
139
/* read 16-bit word from CDC buffer */
140
data = *(uint16 *)(cdc.ram + src_index);
141
142
#ifdef LSB_FIRST
143
/* source data is stored in big endian format */
144
data = ((data >> 8) | (data << 8)) & 0xffff;
145
#endif
146
147
/* write 16-bit word to WORD-RAM */
148
*(uint16 *)(scd.word_ram_2M + dst_index) = data ;
149
150
/* increment CDC buffer source address */
151
src_index = (src_index + 2) & 0x3ffe;
152
153
/* increment WORD-RAM destination address */
154
dst_index = (dst_index + 2) & 0x3fffe;
155
}
156
}
157
158
159
/***************************************************************/
160
/* WORD-RAM 0 & 1 DOT image SUB-CPU interface (1M Mode) */
161
/***************************************************************/
162
163
unsigned int dot_ram_0_read16(unsigned int address)
164
{
165
uint8 data = READ_BYTE(scd.word_ram[0], (address >> 1) & 0x1ffff);
166
return ((data & 0x0f) | ((data << 4) & 0xf00));
167
}
168
169
unsigned int dot_ram_1_read16(unsigned int address)
170
{
171
uint8 data = READ_BYTE(scd.word_ram[1], (address >> 1) & 0x1ffff);
172
return ((data & 0x0f) | ((data << 4) & 0xf00));
173
}
174
175
void dot_ram_0_write16(unsigned int address, unsigned int data)
176
{
177
uint8 prev;
178
address = (address >> 1) & 0x1ffff;
179
prev = READ_BYTE(scd.word_ram[0], address);
180
data = (data & 0x0f) | ((data >> 4) & 0xf0);
181
data = gfx.lut_prio[(scd.regs[0x02>>1].w >> 3) & 0x03][prev][data];
182
WRITE_BYTE(scd.word_ram[0], address, data);
183
}
184
185
void dot_ram_1_write16(unsigned int address, unsigned int data)
186
{
187
uint8 prev;
188
address = (address >> 1) & 0x1ffff;
189
prev = READ_BYTE(scd.word_ram[1], address);
190
data = (data & 0x0f) | ((data >> 4) & 0xf0);
191
data = gfx.lut_prio[(scd.regs[0x02>>1].w >> 3) & 0x03][prev][data];
192
WRITE_BYTE(scd.word_ram[1], address, data);
193
}
194
195
unsigned int dot_ram_0_read8(unsigned int address)
196
{
197
uint8 data = READ_BYTE(scd.word_ram[0], (address >> 1) & 0x1ffff);
198
199
if (address & 1)
200
{
201
return (data & 0x0f);
202
}
203
204
return (data >> 4);
205
}
206
207
unsigned int dot_ram_1_read8(unsigned int address)
208
{
209
uint8 data = READ_BYTE(scd.word_ram[1], (address >> 1) & 0x1ffff);
210
211
if (address & 1)
212
{
213
return (data & 0x0f);
214
}
215
216
return (data >> 4);
217
}
218
219
void dot_ram_0_write8(unsigned int address, unsigned int data)
220
{
221
uint8 prev = READ_BYTE(scd.word_ram[0], (address >> 1) & 0x1ffff);
222
223
if (address & 1)
224
{
225
data = (prev & 0xf0) | (data & 0x0f);
226
}
227
else
228
{
229
data = (prev & 0x0f) | (data << 4);
230
}
231
232
data = gfx.lut_prio[(scd.regs[0x02>>1].w >> 3) & 0x03][prev][data];
233
WRITE_BYTE(scd.word_ram[0], (address >> 1) & 0x1ffff, data);
234
}
235
236
void dot_ram_1_write8(unsigned int address, unsigned int data)
237
{
238
uint8 prev = READ_BYTE(scd.word_ram[1], (address >> 1) & 0x1ffff);
239
240
if (address & 1)
241
{
242
data = (prev & 0xf0) | (data & 0x0f);
243
}
244
else
245
{
246
data = (prev & 0x0f) | (data << 4);
247
}
248
249
data = gfx.lut_prio[(scd.regs[0x02>>1].w >> 3) & 0x03][prev][data];
250
WRITE_BYTE(scd.word_ram[1], (address >> 1) & 0x1ffff, data);
251
}
252
253
254
/***************************************************************/
255
/* WORD-RAM 0 & 1 CELL image MAIN-CPU interface (1M Mode) */
256
/***************************************************************/
257
258
unsigned int cell_ram_0_read16(unsigned int address)
259
{
260
address = gfx.lut_offset[(address >> 2) & 0x7fff] | (address & 0x10002);
261
return *(uint16 *)(scd.word_ram[0] + address);
262
}
263
264
unsigned int cell_ram_1_read16(unsigned int address)
265
{
266
address = gfx.lut_offset[(address >> 2) & 0x7fff] | (address & 0x10002);
267
return *(uint16 *)(scd.word_ram[1] + address);
268
}
269
270
void cell_ram_0_write16(unsigned int address, unsigned int data)
271
{
272
address = gfx.lut_offset[(address >> 2) & 0x7fff] | (address & 0x10002);
273
*(uint16 *)(scd.word_ram[0] + address) = data;
274
}
275
276
void cell_ram_1_write16(unsigned int address, unsigned int data)
277
{
278
address = gfx.lut_offset[(address >> 2) & 0x7fff] | (address & 0x10002);
279
*(uint16 *)(scd.word_ram[1] + address) = data;
280
}
281
282
unsigned int cell_ram_0_read8(unsigned int address)
283
{
284
address = gfx.lut_offset[(address >> 2) & 0x7fff] | (address & 0x10003);
285
return READ_BYTE(scd.word_ram[0], address);
286
}
287
288
unsigned int cell_ram_1_read8(unsigned int address)
289
{
290
address = gfx.lut_offset[(address >> 2) & 0x7fff] | (address & 0x10003);
291
return READ_BYTE(scd.word_ram[1], address);
292
}
293
294
void cell_ram_0_write8(unsigned int address, unsigned int data)
295
{
296
address = gfx.lut_offset[(address >> 2) & 0x7fff] | (address & 0x10003);
297
WRITE_BYTE(scd.word_ram[0], address, data);
298
}
299
300
void cell_ram_1_write8(unsigned int address, unsigned int data)
301
{
302
address = gfx.lut_offset[(address >> 2) & 0x7fff] | (address & 0x10003);
303
WRITE_BYTE(scd.word_ram[1], address, data);
304
}
305
306
307
/***************************************************************/
308
/* Rotation / Scaling operation (2M Mode) */
309
/***************************************************************/
310
311
void gfx_init(void)
312
{
313
int i, j;
314
uint16 offset;
315
uint8 mask, row, col, temp;
316
317
memset(&gfx, 0, sizeof(gfx_t));
318
319
/* Initialize cell image lookup table */
320
/* $220000-$22FFFF corresponds to $200000-$20FFFF */
321
for (i=0; i<0x4000; i++)
322
{
323
offset = (i & 0x07) << 8; /* cell vline (0-7) */
324
offset = offset | (((i >> 8) & 0x3f) << 2); /* cell x offset (0-63) */
325
offset = offset | (((i >> 3) & 0x1f) << 11); /* cell y offset (0-31) */
326
gfx.lut_offset[i] = offset;
327
}
328
329
/* $230000-$237FFF corresponds to $210000-$217FFF */
330
for (i=0x4000; i<0x6000; i++)
331
{
332
offset = (i & 0x07) << 8; /* cell vline (0-7) */
333
offset = offset | (((i >> 7) & 0x3f) << 2); /* cell x offset (0-63) */
334
offset = offset | (((i >> 3) & 0x0f) << 11); /* cell y offset (0-15) */
335
gfx.lut_offset[i] = offset;
336
}
337
338
/* $238000-$23BFFF corresponds to $218000-$21BFFF */
339
for (i=0x6000; i<0x7000; i++)
340
{
341
offset = (i & 0x07) << 8; /* cell vline (0-7) */
342
offset = offset | (((i >> 6) & 0x3f) << 2); /* cell x offset (0-63) */
343
offset = offset | (((i >> 3) & 0x07) << 11); /* cell y offset (0-7) */
344
gfx.lut_offset[i] = offset | 0x8000;
345
}
346
347
/* $23C000-$23DFFF corresponds to $21C000-$21DFFF */
348
for (i=0x7000; i<0x7800; i++)
349
{
350
offset = (i & 0x07) << 8; /* cell vline (0-7) */
351
offset = offset | (((i >> 5) & 0x3f) << 2); /* cell x offset (0-63) */
352
offset = offset | (((i >> 3) & 0x03) << 11); /* cell y offset (0-3) */
353
gfx.lut_offset[i] = offset | 0xc000;
354
}
355
356
/* $23E000-$23FFFF corresponds to $21E000-$21FFFF */
357
for (i=0x7800; i<0x8000; i++)
358
{
359
offset = (i & 0x07) << 8; /* cell vline (0-7) */
360
offset = offset | (((i >> 5) & 0x3f) << 2); /* cell x offset (0-63) */
361
offset = offset | (((i >> 3) & 0x03) << 11); /* cell y offset (0-3) */
362
gfx.lut_offset[i] = offset | 0xe000;
363
}
364
365
/* Initialize priority modes lookup table */
366
for (i=0; i<0x100; i++)
367
{
368
for (j=0; j<0x100; j++)
369
{
370
/* normal */
371
gfx.lut_prio[0][i][j] = j;
372
/* underwrite */
373
gfx.lut_prio[1][i][j] = ((i & 0x0f) ? (i & 0x0f) : (j & 0x0f)) | ((i & 0xf0) ? (i & 0xf0) : (j & 0xf0));
374
/* overwrite */
375
gfx.lut_prio[2][i][j] = ((j & 0x0f) ? (j & 0x0f) : (i & 0x0f)) | ((j & 0xf0) ? (j & 0xf0) : (i & 0xf0));
376
/* invalid */
377
gfx.lut_prio[3][i][j] = i;
378
}
379
}
380
381
/* Initialize cell lookup table */
382
/* table entry = yyxxshrr (8 bits) */
383
/* with: yy = cell row (0-3) */
384
/* xx = cell column (0-3) */
385
/* s = stamp size (0=16x16, 1=32x32) */
386
/* hrr = HFLIP & ROTATION bits */
387
for (i=0; i<0x100; i++)
388
{
389
/* one stamp = 2x2 cells (16x16) or 4x4 cells (32x32) */
390
mask = (i & 8) ? 3 : 1;
391
row = (i >> 6) & mask;
392
col = (i >> 4) & mask;
393
394
if (i & 4) { col = col ^ mask; } /* HFLIP (always first) */
395
if (i & 2) { col = col ^ mask; row = row ^ mask; } /* ROLL1 */
396
if (i & 1) { temp = col; col = row ^ mask; row = temp; } /* ROLL0 */
397
398
/* cell offset (0-3 or 0-15) */
399
gfx.lut_cell[i] = row + col * (mask + 1);
400
}
401
402
/* Initialize pixel lookup table */
403
/* table entry = yyyxxxhrr (9 bits) */
404
/* with: yyy = pixel row (0-7) */
405
/* xxx = pixel column (0-7) */
406
/* hrr = HFLIP & ROTATION bits */
407
for (i=0; i<0x200; i++)
408
{
409
/* one cell = 8x8 pixels */
410
row = (i >> 6) & 7;
411
col = (i >> 3) & 7;
412
413
if (i & 4) { col = col ^ 7; } /* HFLIP (always first) */
414
if (i & 2) { col = col ^ 7; row = row ^ 7; } /* ROLL1 */
415
if (i & 1) { temp = col; col = row ^ 7; row = temp; } /* ROLL0 */
416
417
/* pixel offset (0-63) */
418
gfx.lut_pixel[i] = col + row * 8;
419
}
420
}
421
422
void gfx_reset(void)
423
{
424
/* Reset cycle counter */
425
gfx.cycles = 0;
426
}
427
428
int gfx_context_save(uint8 *state)
429
{
430
uint32 tmp32;
431
int bufferptr = 0;
432
433
save_param(&gfx.cycles, sizeof(gfx.cycles));
434
save_param(&gfx.cyclesPerLine, sizeof(gfx.cyclesPerLine));
435
save_param(&gfx.dotMask, sizeof(gfx.dotMask));
436
save_param(&gfx.stampShift, sizeof(gfx.stampShift));
437
save_param(&gfx.mapShift, sizeof(gfx.mapShift));
438
save_param(&gfx.bufferOffset, sizeof(gfx.bufferOffset));
439
save_param(&gfx.bufferStart, sizeof(gfx.bufferStart));
440
441
tmp32 = (uint8 *)(gfx.tracePtr) - scd.word_ram_2M;
442
save_param(&tmp32, 4);
443
444
tmp32 = (uint8 *)(gfx.mapPtr) - scd.word_ram_2M;
445
save_param(&tmp32, 4);
446
447
return bufferptr;
448
}
449
450
int gfx_context_load(uint8 *state)
451
{
452
uint32 tmp32;
453
int bufferptr = 0;
454
455
load_param(&gfx.cycles, sizeof(gfx.cycles));
456
load_param(&gfx.cyclesPerLine, sizeof(gfx.cyclesPerLine));
457
load_param(&gfx.dotMask, sizeof(gfx.dotMask));
458
load_param(&gfx.stampShift, sizeof(gfx.stampShift));
459
load_param(&gfx.mapShift, sizeof(gfx.mapShift));
460
load_param(&gfx.bufferOffset, sizeof(gfx.bufferOffset));
461
load_param(&gfx.bufferStart, sizeof(gfx.bufferStart));
462
463
load_param(&tmp32, 4);
464
gfx.tracePtr = (uint16 *)(scd.word_ram_2M + tmp32);
465
466
load_param(&tmp32, 4);
467
gfx.mapPtr = (uint16 *)(scd.word_ram_2M + tmp32);
468
469
return bufferptr;
470
}
471
472
INLINE void gfx_render(uint32 bufferIndex, uint32 width)
473
{
474
uint8 pixel_in, pixel_out;
475
uint16 stamp_data;
476
uint32 stamp_index;
477
478
/* pixel map start position for current line (13.3 format converted to 13.11) */
479
uint32 xpos = *gfx.tracePtr++ << 8;
480
uint32 ypos = *gfx.tracePtr++ << 8;
481
482
/* pixel map offset values for current line (5.11 format) */
483
uint32 xoffset = (int16) *gfx.tracePtr++;
484
uint32 yoffset = (int16) *gfx.tracePtr++;
485
486
/* process all dots */
487
while (width--)
488
{
489
/* check if stamp map is repeated */
490
if (scd.regs[0x58>>1].byte.l & 0x01)
491
{
492
/* stamp map range */
493
xpos &= gfx.dotMask;
494
ypos &= gfx.dotMask;
495
}
496
else
497
{
498
/* 24-bit range */
499
xpos &= 0xffffff;
500
ypos &= 0xffffff;
501
}
502
503
/* check if pixel is outside stamp map */
504
if ((xpos | ypos) & ~gfx.dotMask)
505
{
506
/* force pixel output to 0 */
507
pixel_out = 0x00;
508
}
509
else
510
{
511
/* read stamp map table data */
512
stamp_data = gfx.mapPtr[(xpos >> gfx.stampShift) | ((ypos >> gfx.stampShift) << gfx.mapShift)];
513
514
/* stamp generator base index */
515
/* sss ssssssss ccyyyxxx (16x16) or sss sssssscc ccyyyxxx (32x32) */
516
/* with: s = stamp number (1 stamp = 16x16 or 32x32 pixels) */
517
/* c = cell offset (0-3 for 16x16, 0-15 for 32x32) */
518
/* yyy = line offset (0-7) */
519
/* xxx = pixel offset (0-7) */
520
stamp_index = (stamp_data & 0x7ff) << 8;
521
522
if (stamp_index)
523
{
524
/* extract HFLIP & ROTATION bits */
525
stamp_data = (stamp_data >> 13) & 7;
526
527
/* cell offset (0-3 or 0-15) */
528
/* table entry = yyxxshrr (8 bits) */
529
/* with: yy = cell row (0-3) = (ypos >> (11 + 3)) & 3 */
530
/* xx = cell column (0-3) = (xpos >> (11 + 3)) & 3 */
531
/* s = stamp size (0=16x16, 1=32x32) */
532
/* hrr = HFLIP & ROTATION bits */
533
stamp_index |= gfx.lut_cell[stamp_data | ((scd.regs[0x58>>1].byte.l & 0x02) << 2 ) | ((ypos >> 8) & 0xc0) | ((xpos >> 10) & 0x30)] << 6;
534
535
/* pixel offset (0-63) */
536
/* table entry = yyyxxxhrr (9 bits) */
537
/* with: yyy = pixel row (0-7) = (ypos >> 11) & 7 */
538
/* xxx = pixel column (0-7) = (xpos >> 11) & 7 */
539
/* hrr = HFLIP & ROTATION bits */
540
stamp_index |= gfx.lut_pixel[stamp_data | ((xpos >> 8) & 0x38) | ((ypos >> 5) & 0x1c0)];
541
542
/* read pixel pair (2 pixels/byte) */
543
pixel_out = READ_BYTE(scd.word_ram_2M, stamp_index >> 1);
544
545
/* extract left or rigth pixel */
546
if (stamp_index & 1)
547
{
548
pixel_out &= 0x0f;
549
}
550
else
551
{
552
pixel_out >>= 4;
553
}
554
}
555
else
556
{
557
/* stamp 0 is not used: force pixel output to 0 */
558
pixel_out = 0x00;
559
}
560
}
561
562
/* read out paired pixel data */
563
pixel_in = READ_BYTE(scd.word_ram_2M, bufferIndex >> 1);
564
565
/* update left or rigth pixel */
566
if (bufferIndex & 1)
567
{
568
pixel_out |= (pixel_in & 0xf0);
569
}
570
else
571
{
572
pixel_out = (pixel_out << 4) | (pixel_in & 0x0f);
573
}
574
575
/* priority mode write */
576
pixel_out = gfx.lut_prio[(scd.regs[0x02>>1].w >> 3) & 0x03][pixel_in][pixel_out];
577
578
/* write data to image buffer */
579
WRITE_BYTE(scd.word_ram_2M, bufferIndex >> 1, pixel_out);
580
581
/* check current pixel position */
582
if ((bufferIndex & 7) != 7)
583
{
584
/* next pixel */
585
bufferIndex++;
586
}
587
else
588
{
589
/* next cell: increment image buffer offset by one column (minus 7 pixels) */
590
bufferIndex += gfx.bufferOffset;
591
}
592
593
/* increment pixel position */
594
xpos += xoffset;
595
ypos += yoffset;
596
}
597
}
598
599
void gfx_start(unsigned int base, int cycles)
600
{
601
/* make sure 2M mode is enabled */
602
if (!(scd.regs[0x02>>1].byte.l & 0x04))
603
{
604
uint32 mask;
605
606
/* trace vector pointer */
607
gfx.tracePtr = (uint16 *)(scd.word_ram_2M + ((base << 2) & 0x3fff8));
608
609
/* stamps & stamp map size */
610
switch ((scd.regs[0x58>>1].byte.l >> 1) & 0x03)
611
{
612
case 0:
613
gfx.dotMask = 0x07ffff; /* 256x256 dots/map */
614
gfx.stampShift = 11 + 4; /* 16x16 dots/stamps */
615
gfx.mapShift = 4; /* 16x16 stamps/map */
616
mask = 0x3fe00; /* 512 bytes/table */
617
break;
618
619
case 1:
620
gfx.dotMask = 0x07ffff; /* 256x256 dots/map */
621
gfx.stampShift = 11 + 5; /* 32x32 dots/stamps */
622
gfx.mapShift = 3; /* 8x8 stamps/map */
623
mask = 0x3ff80; /* 128 bytes/table */
624
break;
625
626
case 2:
627
gfx.dotMask = 0x7fffff; /* 4096*4096 dots/map */
628
gfx.stampShift = 11 + 4; /* 16x16 dots/stamps */
629
gfx.mapShift = 8; /* 256x256 stamps/map */
630
mask = 0x20000; /* 131072 bytes/table */
631
break;
632
633
case 3:
634
gfx.dotMask = 0x7fffff; /* 4096*4096 dots/map */
635
gfx.stampShift = 11 + 5; /* 32x32 dots/stamps */
636
gfx.mapShift = 7; /* 128x128 stamps/map */
637
mask = 0x38000; /* 32768 bytes/table */
638
break;
639
}
640
641
/* stamp map table base address */
642
gfx.mapPtr = (uint16 *)(scd.word_ram_2M + ((scd.regs[0x5a>>1].w << 2) & mask));
643
644
/* image buffer column offset (64 pixels/cell, minus 7 pixels to restart at cell beginning) */
645
gfx.bufferOffset = (((scd.regs[0x5c>>1].byte.l & 0x1f) + 1) << 6) - 7;
646
647
/* image buffer start index in dot units (2 pixels/byte) */
648
gfx.bufferStart = (scd.regs[0x5e>>1].w << 3) & 0x7ffc0;
649
650
/* add image buffer horizontal dot offset */
651
gfx.bufferStart += (scd.regs[0x60>>1].byte.l & 0x3f);
652
653
/* reset GFX chip cycle counter */
654
gfx.cycles = cycles;
655
656
/* update GFX chip timings (see AC3:Thunderhawk / Thunderstrike) */
657
gfx.cyclesPerLine = 4 * 5 * scd.regs[0x62>>1].w;
658
659
/* start graphics operation */
660
scd.regs[0x58>>1].byte.h = 0x80;
661
}
662
}
663
664
void gfx_update(int cycles)
665
{
666
/* synchronize GFX chip with SUB-CPU */
667
cycles -= gfx.cycles;
668
669
/* make sure SUB-CPU is ahead */
670
if (cycles > 0)
671
{
672
/* number of lines to process */
673
unsigned int lines = (cycles + gfx.cyclesPerLine - 1) / gfx.cyclesPerLine;
674
675
/* check against remaining lines */
676
if (lines < scd.regs[0x64>>1].byte.l)
677
{
678
/* update Vdot remaining size */
679
scd.regs[0x64>>1].byte.l -= lines;
680
681
/* increment cycle counter */
682
gfx.cycles += lines * gfx.cyclesPerLine;
683
}
684
else
685
{
686
/* process remaining lines */
687
lines = scd.regs[0x64>>1].byte.l;
688
689
/* clear Vdot remaining size */
690
scd.regs[0x64>>1].byte.l = 0;
691
692
/* end of graphics operation */
693
scd.regs[0x58>>1].byte.h = 0;
694
695
/* SUB-CPU idle on register $58 polling ? */
696
if (s68k.stopped & (1<<0x08))
697
{
698
/* sync SUB-CPU with GFX chip */
699
s68k.cycles = scd.cycles;
700
701
/* restart SUB-CPU */
702
s68k.stopped = 0;
703
#ifdef LOG_SCD
704
error("s68k started from %d cycles\n", s68k.cycles);
705
#endif
706
}
707
708
/* level 1 interrupt enabled ? */
709
if (scd.regs[0x32>>1].byte.l & 0x02)
710
{
711
/* trigger level 1 interrupt */
712
scd.pending |= (1 << 1);
713
714
/* update IRQ level */
715
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
716
}
717
}
718
719
/* render lines */
720
while (lines--)
721
{
722
/* process dots to image buffer */
723
gfx_render(gfx.bufferStart, scd.regs[0x62>>1].w);
724
725
/* increment image buffer start index for next line (8 pixels/line) */
726
gfx.bufferStart += 8;
727
}
728
}
729
}
730
731