Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/waterbox/gpgx/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
INLINE void gfx_render(uint32 bufferIndex, uint32 width)
429
{
430
uint8 pixel_in, pixel_out;
431
uint16 stamp_data;
432
uint32 stamp_index;
433
434
/* pixel map start position for current line (13.3 format converted to 13.11) */
435
uint32 xpos = *gfx.tracePtr++ << 8;
436
uint32 ypos = *gfx.tracePtr++ << 8;
437
438
/* pixel map offset values for current line (5.11 format) */
439
uint32 xoffset = (int16) *gfx.tracePtr++;
440
uint32 yoffset = (int16) *gfx.tracePtr++;
441
442
/* process all dots */
443
while (width--)
444
{
445
/* check if stamp map is repeated */
446
if (scd.regs[0x58>>1].byte.l & 0x01)
447
{
448
/* stamp map range */
449
xpos &= gfx.dotMask;
450
ypos &= gfx.dotMask;
451
}
452
else
453
{
454
/* 24-bit range */
455
xpos &= 0xffffff;
456
ypos &= 0xffffff;
457
}
458
459
/* check if pixel is outside stamp map */
460
if ((xpos | ypos) & ~gfx.dotMask)
461
{
462
/* force pixel output to 0 */
463
pixel_out = 0x00;
464
}
465
else
466
{
467
/* read stamp map table data */
468
stamp_data = gfx.mapPtr[(xpos >> gfx.stampShift) | ((ypos >> gfx.stampShift) << gfx.mapShift)];
469
470
/* stamp generator base index */
471
/* sss ssssssss ccyyyxxx (16x16) or sss sssssscc ccyyyxxx (32x32) */
472
/* with: s = stamp number (1 stamp = 16x16 or 32x32 pixels) */
473
/* c = cell offset (0-3 for 16x16, 0-15 for 32x32) */
474
/* yyy = line offset (0-7) */
475
/* xxx = pixel offset (0-7) */
476
stamp_index = (stamp_data & 0x7ff) << 8;
477
478
if (stamp_index)
479
{
480
/* extract HFLIP & ROTATION bits */
481
stamp_data = (stamp_data >> 13) & 7;
482
483
/* cell offset (0-3 or 0-15) */
484
/* table entry = yyxxshrr (8 bits) */
485
/* with: yy = cell row (0-3) = (ypos >> (11 + 3)) & 3 */
486
/* xx = cell column (0-3) = (xpos >> (11 + 3)) & 3 */
487
/* s = stamp size (0=16x16, 1=32x32) */
488
/* hrr = HFLIP & ROTATION bits */
489
stamp_index |= gfx.lut_cell[stamp_data | ((scd.regs[0x58>>1].byte.l & 0x02) << 2 ) | ((ypos >> 8) & 0xc0) | ((xpos >> 10) & 0x30)] << 6;
490
491
/* pixel offset (0-63) */
492
/* table entry = yyyxxxhrr (9 bits) */
493
/* with: yyy = pixel row (0-7) = (ypos >> 11) & 7 */
494
/* xxx = pixel column (0-7) = (xpos >> 11) & 7 */
495
/* hrr = HFLIP & ROTATION bits */
496
stamp_index |= gfx.lut_pixel[stamp_data | ((xpos >> 8) & 0x38) | ((ypos >> 5) & 0x1c0)];
497
498
/* read pixel pair (2 pixels/byte) */
499
pixel_out = READ_BYTE(scd.word_ram_2M, stamp_index >> 1);
500
501
/* extract left or rigth pixel */
502
if (stamp_index & 1)
503
{
504
pixel_out &= 0x0f;
505
}
506
else
507
{
508
pixel_out >>= 4;
509
}
510
}
511
else
512
{
513
/* stamp 0 is not used: force pixel output to 0 */
514
pixel_out = 0x00;
515
}
516
}
517
518
/* read out paired pixel data */
519
pixel_in = READ_BYTE(scd.word_ram_2M, bufferIndex >> 1);
520
521
/* update left or rigth pixel */
522
if (bufferIndex & 1)
523
{
524
pixel_out |= (pixel_in & 0xf0);
525
}
526
else
527
{
528
pixel_out = (pixel_out << 4) | (pixel_in & 0x0f);
529
}
530
531
/* priority mode write */
532
pixel_out = gfx.lut_prio[(scd.regs[0x02>>1].w >> 3) & 0x03][pixel_in][pixel_out];
533
534
/* write data to image buffer */
535
WRITE_BYTE(scd.word_ram_2M, bufferIndex >> 1, pixel_out);
536
537
/* check current pixel position */
538
if ((bufferIndex & 7) != 7)
539
{
540
/* next pixel */
541
bufferIndex++;
542
}
543
else
544
{
545
/* next cell: increment image buffer offset by one column (minus 7 pixels) */
546
bufferIndex += gfx.bufferOffset;
547
}
548
549
/* increment pixel position */
550
xpos += xoffset;
551
ypos += yoffset;
552
}
553
}
554
555
void gfx_start(unsigned int base, int cycles)
556
{
557
/* make sure 2M mode is enabled */
558
if (!(scd.regs[0x02>>1].byte.l & 0x04))
559
{
560
uint32 mask;
561
562
/* trace vector pointer */
563
gfx.tracePtr = (uint16 *)(scd.word_ram_2M + ((base << 2) & 0x3fff8));
564
565
/* stamps & stamp map size */
566
switch ((scd.regs[0x58>>1].byte.l >> 1) & 0x03)
567
{
568
case 0:
569
gfx.dotMask = 0x07ffff; /* 256x256 dots/map */
570
gfx.stampShift = 11 + 4; /* 16x16 dots/stamps */
571
gfx.mapShift = 4; /* 16x16 stamps/map */
572
mask = 0x3fe00; /* 512 bytes/table */
573
break;
574
575
case 1:
576
gfx.dotMask = 0x07ffff; /* 256x256 dots/map */
577
gfx.stampShift = 11 + 5; /* 32x32 dots/stamps */
578
gfx.mapShift = 3; /* 8x8 stamps/map */
579
mask = 0x3ff80; /* 128 bytes/table */
580
break;
581
582
case 2:
583
gfx.dotMask = 0x7fffff; /* 4096*4096 dots/map */
584
gfx.stampShift = 11 + 4; /* 16x16 dots/stamps */
585
gfx.mapShift = 8; /* 256x256 stamps/map */
586
mask = 0x20000; /* 131072 bytes/table */
587
break;
588
589
case 3:
590
gfx.dotMask = 0x7fffff; /* 4096*4096 dots/map */
591
gfx.stampShift = 11 + 5; /* 32x32 dots/stamps */
592
gfx.mapShift = 7; /* 128x128 stamps/map */
593
mask = 0x38000; /* 32768 bytes/table */
594
break;
595
}
596
597
/* stamp map table base address */
598
gfx.mapPtr = (uint16 *)(scd.word_ram_2M + ((scd.regs[0x5a>>1].w << 2) & mask));
599
600
/* image buffer column offset (64 pixels/cell, minus 7 pixels to restart at cell beginning) */
601
gfx.bufferOffset = (((scd.regs[0x5c>>1].byte.l & 0x1f) + 1) << 6) - 7;
602
603
/* image buffer start index in dot units (2 pixels/byte) */
604
gfx.bufferStart = (scd.regs[0x5e>>1].w << 3) & 0x7ffc0;
605
606
/* add image buffer horizontal dot offset */
607
gfx.bufferStart += (scd.regs[0x60>>1].byte.l & 0x3f);
608
609
/* reset GFX chip cycle counter */
610
gfx.cycles = cycles;
611
612
/* update GFX chip timings (see AC3:Thunderhawk / Thunderstrike) */
613
gfx.cyclesPerLine = 4 * 5 * scd.regs[0x62>>1].w;
614
615
/* start graphics operation */
616
scd.regs[0x58>>1].byte.h = 0x80;
617
}
618
}
619
620
void gfx_update(int cycles)
621
{
622
/* synchronize GFX chip with SUB-CPU */
623
cycles -= gfx.cycles;
624
625
/* make sure SUB-CPU is ahead */
626
if (cycles > 0)
627
{
628
/* number of lines to process */
629
unsigned int lines = (cycles + gfx.cyclesPerLine - 1) / gfx.cyclesPerLine;
630
631
/* check against remaining lines */
632
if (lines < scd.regs[0x64>>1].byte.l)
633
{
634
/* update Vdot remaining size */
635
scd.regs[0x64>>1].byte.l -= lines;
636
637
/* increment cycle counter */
638
gfx.cycles += lines * gfx.cyclesPerLine;
639
}
640
else
641
{
642
/* process remaining lines */
643
lines = scd.regs[0x64>>1].byte.l;
644
645
/* clear Vdot remaining size */
646
scd.regs[0x64>>1].byte.l = 0;
647
648
/* end of graphics operation */
649
scd.regs[0x58>>1].byte.h = 0;
650
651
/* SUB-CPU idle on register $58 polling ? */
652
if (s68k.stopped & (1<<0x08))
653
{
654
/* sync SUB-CPU with GFX chip */
655
s68k.cycles = scd.cycles;
656
657
/* restart SUB-CPU */
658
s68k.stopped = 0;
659
#ifdef LOG_SCD
660
error("s68k started from %d cycles\n", s68k.cycles);
661
#endif
662
}
663
664
/* level 1 interrupt enabled ? */
665
if (scd.regs[0x32>>1].byte.l & 0x02)
666
{
667
/* trigger level 1 interrupt */
668
scd.pending |= (1 << 1);
669
670
/* update IRQ level */
671
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
672
}
673
}
674
675
/* render lines */
676
while (lines--)
677
{
678
/* process dots to image buffer */
679
gfx_render(gfx.bufferStart, scd.regs[0x62>>1].w);
680
681
/* increment image buffer start index for next line (8 pixels/line) */
682
gfx.bufferStart += 8;
683
}
684
}
685
}
686
687