1 /******************************************************************************/
2 /* Mednafen NEC PC-FX Emulation Module */
3 /******************************************************************************/
4 /* king.cpp - Emulation of HuC6261(VCE descendant) and the HuC6272(KING)
5 ** Copyright (C) 2006-2016 Mednafen Team
6 **
7 ** This program is free software; you can redistribute it and/or
8 ** modify it under the terms of the GNU General Public License
9 ** as published by the Free Software Foundation; either version 2
10 ** of the License, or (at your option) any later version.
11 **
12 ** This program is distributed in the hope that it will be useful,
13 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ** GNU General Public License for more details.
16 **
17 ** You should have received a copy of the GNU General Public License
18 ** along with this program; if not, write to the Free Software Foundation, Inc.,
19 ** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 */
21
22 /* Note: Some technical comments may be outdated */
23
24 /*
25 Current issues:
26 VCE "natural" priorities for the layers when their priorities are the same(technically an illegal condition) are probably not correct. A game test case: "Miraculum" erroneously sets
27 up the priority registers like this after exiting the airship(I believe).
28
29 SCSI RST interrupt timing is guessed(and with nothing to go on), so it definitely needs to be tested on the real thing.
30
31 The data bus is not handled/asserted properly. Excluding pseudo-DMA and DMA modes(which I'd need to test), the data bus will only be asserted if the lower bit of register 0x1 is set, and the
32 phase match bits must match the state of the C/D, I/O, and MSG signals(IE there isn't a bus mismatch state).
33
34 Raw subchannel reading timing is probably wrong.
35
36 KRAM mode register is not emulated(I'm not even sure what it does exactly).
37 */
38
39 #include "pcfx.h"
40 #include "king.h"
41 #include <mednafen/cdrom/scsicd.h>
42 #include "interrupt.h"
43 #include "rainbow.h"
44 #include "soundbox.h"
45 #include "input.h"
46 #include "timer.h"
47 #include "debug.h"
48 #include <trio/trio.h>
49 #include <mednafen/video.h>
50 #include <mednafen/sound/OwlResampler.h>
51
52 namespace MDFN_IEN_PCFX
53 {
54
55 #define KINGDBG(format, ...) (void)0
56 //#define KINGDBG FXDBG
57 #define KING_UNDEF FXDBG
58 #define ADPCMDBG(format, ...) (void)0
59 //FXDBG
60
61 /*
62 SCSI Questions(this list needs to be revised more and merged into the issues list at the beginning of the file):
63
64 What happens when there is no more data to transfer during DMA and the status SCSI bus phase is entered(before the DMA count reaches 0)?
65
66 Why is the "sequential DMA" bit needed?
67
68 Which SCSI registers return the values of the SCSI bus, and which return latched values(from previous writes or pseudo-DMA)?
69
70 Is real DMA layered on top of pseudo-DMA? Reading the developer documents, it looks that way.
71
72 What triggers the setting of ACK during pseudo-DMA? A timer? Reading from the upper 16-bits of KING register 0x05? The lower bits(in which case,
73 the value would be latched..)?
74
75 */
76
77 // 16 bit YUV format: upper 8 bits Y, next 4 bits U, lower 4 bits V, transformed to 8-bit U and 8-bit V by shifting in 0 in lower bits.
78
79 typedef struct
80 {
81 uint8 AR;
82
83 uint16 priority[2]; /* uint16 0:
84 bit 3-0: Legacy VDC BG priority?
85 bit 7-4: Legacy VDC SPR priority?
86 bit 11-8: RAINBOW(MJPEG) priority
87 uint16 1:
88 bit 3-0: KING BG0 priority
89 bit 7-4: KING BG1 priority
90 bit 11-8: KING BG2 priority
91 bit 15-12: KING BG3 priority
92 */
93
94 bool odd_field; /* true if interlaced mode is enabled and we're in the odd field, false otherwise. */
95
96 bool in_hblank; /* true if we're in H-blank */
97 bool in_vdc_hsync;
98
99 bool frame_interlaced;
100
101 uint16 picture_mode;
102
103 bool dot_clock; // Cached from picture_mode in hblank
104 uint32 dot_clock_ratio; // Cached from picture mode in hblank
105 int32 clock_divider;
106
107 int32 vdc_event[2];
108
109
110 uint32 raster_counter;
111
112 uint16 palette_rw_offset; // Read/write offset
113 uint16 palette_rw_latch;
114
115 uint16 palette_offset[4]; //
116 // BMG1 and BMG 0 in [1](BMG1 in upper 8 bits, BMG0 in lower), BMG2 and 3 in [2]
117 // RAINBOW in lower(?) 8 bits of [3]?
118
119 uint16 palette_table[512]; // The YUV palette, woohoo!
120
121 // Chroma keys, minimum value in lower 8 bits, maximum value in upper 8 bits
122 uint16 ChromaKeyY; // Register 0xA
123 uint16 ChromaKeyU; // Register 0xB
124 uint16 ChromaKeyV; // register 0xC
125
126 uint16 CCR; // Register 0x0D, fixed color register, 16-bit YUV
127 uint16 BLE; // Register 0x0E, cellophane setting register
128 // 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
129 // F/B |E/D | IDU |CTRL BMG3|CTRL BMG2|CTRL BMG1|CTRL BMG0| VDP SP | VDP BG
130 // IDU is AKA Rainbow
131 // F/B
132 // 0 = Back cellophane.
133 // 1 = Front cellophane.
134 // E/D
135 // 0 = Back/Front cellophane off
136 // 1 = Back/Front cellophane on
137 // Ctrl format:
138 // 00 = Cellophane disabled.
139 // 01 = Cellophane with 1A/1B(Coeffs 0, 1?)
140 // 02 = Cellophane with 2A/2B(Coeffs 2, 3?)
141 // 03 = Cellophane with 3A/3B(Coeffs 4, 5?)
142
143 uint16 SPBL; // Register 0x0F, Sprite cellophane setting register
144 // Specifies a color palette bank for which cellophane will always be disabled.
145
146 uint16 coefficients[6]; // Cellophane coefficients, YUV, 4-bits each, on the least-significant end(xxxxYYYYUUUUVVVV).
147 // Valid settings: 0(cellophane disabled for layer), 1-8. 9-F are "unsupported".
148 } fx_vce_t;
149
150 fx_vce_t fx_vce;
151
152 //
153 // VCE render cache, including registers cached at hblank
154 //
155 typedef struct
156 {
157 uint16 priority[2];
158 uint16 picture_mode;
159
160 uint16 palette_offset[4];
161 uint32 palette_table_cache[512 * 2]; // 24-bit YUV cache for SPEED(HAH), * 2 to remove need for & 0x1FF in rendering code
162
163 uint16 ChromaKeyY;
164 uint16 ChromaKeyU;
165 uint16 ChromaKeyV;
166
167 uint16 CCR;
168 uint16 BLE;
169
170 uint16 SPBL;
171
172 uint16 coefficients[6];
173
174 uint8 coefficient_mul_table_y[16][256];
175 int8 coefficient_mul_table_uv[16][256];
176
177 uint32 LayerPriority[8]; // [LAYER_n] = ordered_priority_for_n(real priority 0-15 mapped to 1-7)
178 // priority = 0, layer is disabled(via the layer enable bit not being set)
179 } vce_rendercache_t;
180
181 static vce_rendercache_t vce_rendercache;
182
183 static int32 scsicd_ne;
184
185 enum
186 {
187 HPHASE_ACTIVE = 0,
188 HPHASE_HBLANK_PART1,
189 HPHASE_HBLANK_PART3,
190 HPHASE_HBLANK_PART4,
191 HPHASE_COUNT
192 };
193
194 static int32 HPhase;
195 static int32 HPhaseCounter;
196 static uint32 vdc_lb_pos;
197
198 alignas(8) static uint16 vdc_linebuffers[2][512];
199 alignas(8) static uint32 vdc_linebuffer[512];
200 alignas(8) static uint32 vdc_linebuffer_yuved[512];
201 alignas(8) static uint32 rainbow_linebuffer[256];
202
203 // 8 * 2 for left + right padding for scrolling
204 alignas(8) static uint32 bg_linebuffer[256 + 8 + 8];
205
206
207
208 // Don't change these enums, there are some hardcoded values still used(particularly, LAYER_NONE).
209 enum
210 {
211 LAYER_NONE = 0,
212 LAYER_BG0,
213 LAYER_BG1,
214 LAYER_BG2,
215 LAYER_BG3,
216 LAYER_VDC_BG,
217 LAYER_VDC_SPR,
218 LAYER_RAINBOW
219 };
220
221 static uint8 VCEPrioMap[8][8][8][4]; // [n][n][n][3] is dummy, for padding to a power of 2.
222
BuildCMT(void)223 static void BuildCMT(void)
224 {
225 for(int coeff = 0; coeff < 16; coeff++)
226 {
227 for(int value = 0; value < 256; value++)
228 {
229 vce_rendercache.coefficient_mul_table_y[coeff][value] = (value * coeff / 8); // Y
230 vce_rendercache.coefficient_mul_table_uv[coeff][value] = ((value - 128) * coeff / 8); // UV
231 }
232 }
233
234 }
235
RebuildLayerPrioCache(void)236 static INLINE void RebuildLayerPrioCache(void)
237 {
238 vce_rendercache_t *vr = &vce_rendercache;
239
240 vr->LayerPriority[LAYER_NONE] = 0;
241
242 for(int n = 0; n < 4; n++)
243 {
244 if(((fx_vce.picture_mode >> (10 + n)) & 1))
245 {
246 vr->LayerPriority[LAYER_BG0 + n] = (((vce_rendercache.priority[1] >> (n * 4)) & 0xF) + 1);
247 if(vr->LayerPriority[LAYER_BG0 + n] > 8)
248 {
249 printf("KING BG%d Priority Too Large: %d\n", n, vr->LayerPriority[LAYER_BG0 + n] - 1);
250 vr->LayerPriority[LAYER_BG0 + n] = 0;
251 }
252 }
253 else
254 vr->LayerPriority[LAYER_BG0 + n] = 0;
255 }
256
257 if(fx_vce.picture_mode & 0x0100)
258 {
259 vr->LayerPriority[LAYER_VDC_BG] = ((vce_rendercache.priority[0] & 0xF) + 1);
260 if(vr->LayerPriority[LAYER_VDC_BG] > 8)
261 {
262 printf("VDC BG Priority Too Large: %d\n", vr->LayerPriority[LAYER_VDC_BG] - 1);
263 vr->LayerPriority[LAYER_VDC_BG] = 0;
264 }
265 }
266 else
267 vr->LayerPriority[LAYER_VDC_BG] = 0;
268
269 if(fx_vce.picture_mode & 0x0200)
270 {
271 vr->LayerPriority[LAYER_VDC_SPR] = (((vce_rendercache.priority[0] >> 4) & 0xF) + 1);
272 if(vr->LayerPriority[LAYER_VDC_SPR] > 8)
273 {
274 printf("VDC SPR Priority Too Large: %d\n", vr->LayerPriority[LAYER_VDC_SPR] - 1);
275 vr->LayerPriority[LAYER_VDC_SPR] = 0;
276 }
277 }
278 else
279 vr->LayerPriority[LAYER_VDC_SPR] = 0;
280
281 if(fx_vce.picture_mode & 0x4000)
282 {
283 vr->LayerPriority[LAYER_RAINBOW] = (((vce_rendercache.priority[0] >> 8) & 0xF) + 1);
284 if(vr->LayerPriority[LAYER_RAINBOW] > 8)
285 {
286 printf("RAINBOW Priority Too Large: %d\n", vr->LayerPriority[LAYER_RAINBOW] - 1);
287 vr->LayerPriority[LAYER_RAINBOW] = 0;
288 }
289 }
290 else
291 vr->LayerPriority[LAYER_RAINBOW] = 0;
292
293
294 // At this point, all entries in vr->LayerPriority should be one of 0 through 8(inclusive).
295
296 int RemapPriority = 1;
297 bool Done[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
298
299 for(unsigned int i = 1; i < (1 + 8); i++)
300 {
301 for(int n = 0; n < 4; n++)
302 {
303 if(vr->LayerPriority[LAYER_BG0 + n] == i && !Done[LAYER_BG0 + n])
304 {
305 vr->LayerPriority[LAYER_BG0 + n] = RemapPriority++;
306 Done[LAYER_BG0 + n] = true;
307 }
308 }
309
310 if(vr->LayerPriority[LAYER_VDC_BG] == i && !Done[LAYER_VDC_BG])
311 {
312 vr->LayerPriority[LAYER_VDC_BG] = RemapPriority++;
313 Done[LAYER_VDC_BG] = true;
314 }
315
316 if(vr->LayerPriority[LAYER_VDC_SPR] == i && !Done[LAYER_VDC_SPR])
317 {
318 vr->LayerPriority[LAYER_VDC_SPR] = RemapPriority++;
319 Done[LAYER_VDC_SPR] = true;
320 }
321
322 if(vr->LayerPriority[LAYER_RAINBOW] == i && !Done[LAYER_RAINBOW])
323 {
324 vr->LayerPriority[LAYER_RAINBOW] = RemapPriority++;
325 Done[LAYER_RAINBOW] = true;
326 }
327 }
328 assert(RemapPriority <= 8);
329
330 //if(fx_vce.raster_counter == 50)
331 // MDFN_DispMessage("%d BG0: %d %d %d %d, VBG: %d, VSPR: %d, RAIN: %d", vr->LayerPriority[0], vr->LayerPriority[1], vr->LayerPriority[2], vr->LayerPriority[3],
332 // vr->LayerPriority[4], vr->LayerPriority[5], vr->LayerPriority[6], vr->LayerPriority[7]);
333 }
334
335 // Call this function in FX VCE hblank(or at the end/immediate start of active display)
DoHBlankVCECaching(void)336 static void DoHBlankVCECaching(void)
337 {
338 const fx_vce_t *source = &fx_vce;
339 vce_rendercache_t *dest = &vce_rendercache;
340
341 dest->picture_mode = source->picture_mode;
342
343 fx_vce.dot_clock = (bool)(fx_vce.picture_mode & 0x08);
344 fx_vce.dot_clock_ratio = (fx_vce.picture_mode & 0x08) ? 3 : 4;
345
346 for(int i = 0; i < 2; i++)
347 dest->priority[i] = source->priority[i];
348
349
350 for(int i = 0; i < 4; i++)
351 dest->palette_offset[i] = source->palette_offset[i];
352
353 dest->ChromaKeyY = source->ChromaKeyY;
354 dest->ChromaKeyU = source->ChromaKeyU;
355 dest->ChromaKeyV = source->ChromaKeyV;
356
357 dest->CCR = source->CCR;
358 dest->BLE = source->BLE;
359 dest->SPBL = source->SPBL;
360
361 for(int i = 0; i < 6; i++)
362 dest->coefficients[i] = source->coefficients[i];
363
364 RebuildLayerPrioCache();
365 }
366
RedoPaletteCache(int n)367 static INLINE void RedoPaletteCache(int n)
368 {
369 uint32 YUV = fx_vce.palette_table[n];
370 uint8 Y = (YUV >> 8) & 0xFF;
371 uint8 U = (YUV & 0xF0);
372 uint8 V = (YUV & 0x0F) << 4;
373
374 vce_rendercache.palette_table_cache[n] =
375 vce_rendercache.palette_table_cache[0x200 | n] = (Y << 16) | (U << 8) | (V << 0);
376 }
377
378 enum
379 {
380 BGMODE_INVALID = 0,
381 BGMODE_4 = 1,
382 BGMODE_16 = 2,
383 BGMODE_256 = 3,
384 BGMODE_64K = 4,
385 BGMODE_16M = 5,
386 BGMODE_64K_EXTDOT = 6,
387 BGMODE_16M_EXTDOT = 7,
388 };
389
390 typedef struct
391 {
392 uint8 AR;
393
394 uint32 KRAMRA, KRAMWA;
395 uint8 KRAM_Mode;
396
397 uint32 PageSetting;
398 uint16 *RainbowPagePtr, *DMAPagePtr; // Calculated off of PageSetting
399
400 uint16 bgmode; // 4 bits each BG: 3333 2222 1111 0000
401 /* Possible settings:
402 0x0: Invalid?
403 0x1: 4-color palette, 1 byte for 4 pixels, transparent on entry 0
404 0x2: 16-color palette, 1 byte for 2 pixels, transparent on entry 0
405 0x3: 256-color palette, 1 byte for 1 pixel, transparent on entry 0
406 0x4: 64K color(Y-8, U-4, V-4), 1 halfword for 1 pixel, transparent on Y=0
407 0x5: 16M colors(Y-8, Y-8, U-8, V-8, 4 bytes for 2 pixels), transparent on Y=0
408
409 If & 8, enable palette bank mode(only for 4 and 16-colors)???
410 BAT format would be PPPPCCCCCCCCCCCC in this mode.
411 4 color: 00PPPPnn 16 color: PPPPnnnn, where "n" is the 2 or 4-bit pixel data
412 */
413 uint16 priority;
414
415 uint16 BGScrollMode; // Register 0x16
416 uint16 BGSize[4];
417
418 uint8 BGBATAddr[4];
419 uint8 BGCGAddr[4];
420 uint8 BG0SubBATAddr, BG0SubCGAddr;
421
422 uint16 BGXScroll[4];
423 uint16 BGYScroll[4];
424
425 uint16 BGAffinA, BGAffinB, BGAffinC, BGAffinD;
426 uint16 BGAffinCenterX, BGAffinCenterY;
427
428 uint16 ADPCMControl;
429 uint16 ADPCMBufferMode[2];
430
431 uint16 ADPCMSAL[2];
432
433 uint32 ADPCMEndAddress[2];
434 uint32 ADPCMPlayAddress[2];
435 uint16 ADPCMIntermediateAddress[2];
436 uint16 ADPCMStatus[2]; // Register 0x53, a bit maimed :)
437 bool ADPCMIRQPending;
438
439 uint16 RAINBOWTransferControl; // Register 0x40
440 uint32 RAINBOWKRAMA; // Register 0x41
441 uint16 RAINBOWTransferStartPosition; // Register 0x42, line number(0-262)
442 uint16 RAINBOWTransferBlockCount; // Register 0x43
443
444
445 bool RAINBOWStartPending;
446 int32 RAINBOWBusyCount, RAINBOWBlockCount;
447
448 uint16 RasterIRQLine; // Register 0x44
449 bool RasterIRQPending;
450
451 uint32 RAINBOWKRAMReadPos;
452
453 bool DMATransferFlipFlop;
454 uint32 DMATransferAddr; // Register 0x09
455 uint32 DMATransferSize; // Register 0x0A
456 uint16 DMAStatus; // Register 0x0B
457 uint8 DMALatch;
458
459
460 uint16 MPROGControl; // register 0x15
461 uint16 MPROGControlCache;
462 uint16 MPROGAddress;
463 uint16 MPROGData[0x10];
464
465 bool DMAInterrupt;
466 uint8 Reg00;
467 uint8 Reg01;
468 uint8 Reg02;
469 uint8 Reg03;
470
471
472 uint8 SubChannelControl;
473
474 bool CDInterrupt, SubChannelInterrupt;
475 uint8 SubChannelBuf;
476 uint8 data_cache;
477
478 bool DRQ;
479 bool dma_receive_active;
480 bool dma_send_active;
481 int32 dma_cycle_counter;
482 int32 lastts;
483
484
485 uint16 KRAM[2][262144];
486
487 #define KING_MAGIC_INTERVAL 10 //4 //32 //10
488 } king_t;
489
490 static king_t *king = NULL;
491
492 static uint8 BGLayerDisable;
493 static bool RAINBOWLayerDisable;
494
495 static void RedoKINGIRQCheck(void);
496
REGSETP(uint16 & reg,const uint8 data,const bool msb)497 static INLINE void REGSETP(uint16 ®, const uint8 data, const bool msb)
498 {
499 reg &= 0xFF << (msb ? 0 : 8);
500 reg |= data << (msb ? 8 : 0);
501 }
502
503 #ifdef WANT_DEBUGGER
504 static bool KRAMReadBPE = false;
505 static bool KRAMWriteBPE = false;
506
KING_NotifyOfBPE(bool read,bool write)507 void KING_NotifyOfBPE(bool read, bool write)
508 {
509 KRAMReadBPE = read;
510 KRAMWriteBPE = write;
511
512 //FXVDC_SetAux0BPBpase(fx_vdc_chips[0], (read || write) ? 0x80000 : ~0);
513 //FXVDC_SetAux0BPBpase(fx_vdc_chips[1], (read || write) ? 0x90000 : ~0);
514 }
515
516 static void (*KINGLog)(const char *, const char *, ...) = NULL;
KING_SetLogFunc(void (* logfunc)(const char *,const char *,...))517 void KING_SetLogFunc(void (*logfunc)(const char *, const char *, ...))
518 {
519 KINGLog = logfunc;
520 }
521
522 static MDFN_Surface *GfxDecode_Buf = NULL;
523 static int GfxDecode_Line = -1;
524 static int GfxDecode_Layer = 0;
525 static int GfxDecode_Scroll = 0;
526 static int GfxDecode_PBN = 0;
527 static void DoGfxDecode(void);
528
KING_MemPeek(uint32 A)529 uint8 KING_MemPeek(uint32 A)
530 {
531 uint8 ret = king->KRAM[(A & 0x80000) ? 1 : 0][A >> 1] >> ((A & 1) * 8);
532
533 return(ret);
534 }
535
Do16BitGet(const char * name,uint32 Address,uint32 Length,uint8 * Buffer)536 static void Do16BitGet(const char *name, uint32 Address, uint32 Length, uint8 *Buffer)
537 {
538 int wc = 0;
539
540 if(!strcmp(name, "vdcvram0"))
541 wc = 0;
542 else if(!strcmp(name, "vdcvram1"))
543 wc = 1;
544
545 while(Length)
546 {
547 uint16 data;
548
549 data = fx_vdc_chips[wc & 1]->PeekVRAM((Address >> 1) & 0xFFFF);
550
551 if((Address & 1) || Length == 1)
552 {
553 *Buffer = data >> ((Address & 1) << 3);
554 Buffer++;
555 Address++;
556 Length--;
557 }
558 else
559 {
560 Buffer[0] = data & 0xFF;
561 Buffer[1] = data >> 8;
562
563 Buffer += 2;
564 Address += 2;
565 Length -= 2;
566 }
567 }
568 }
569
Do16BitPut(const char * name,uint32 Address,uint32 Length,uint32 Granularity,bool hl,const uint8 * Buffer)570 static void Do16BitPut(const char *name, uint32 Address, uint32 Length, uint32 Granularity, bool hl, const uint8 *Buffer)
571 {
572 int wc = 0;
573
574 if(!strcmp(name, "vdcvram0"))
575 wc = 0;
576 else if(!strcmp(name, "vdcvram1"))
577 wc = 1;
578
579 while(Length)
580 {
581 uint16 data;
582 int inc_amount;
583
584 if((Address & 1) || Length == 1)
585 {
586 data = fx_vdc_chips[wc & 1]->PeekVRAM((Address >> 1) & 0xFFFF);
587
588 data &= ~(0xFF << ((Address & 1) << 3));
589 data |= *Buffer << ((Address & 1) << 3);
590
591 inc_amount = 1;
592 }
593 else
594 {
595 data = Buffer[0] | (Buffer[1] << 8);
596 inc_amount = 2;
597 }
598
599 fx_vdc_chips[wc & 1]->PokeVRAM((Address >> 1) & 0xFFFF, data);
600
601 Buffer += inc_amount;
602 Address += inc_amount;
603 Length -= inc_amount;
604 }
605 }
606
KING_GetAddressSpaceBytes(const char * name,uint32 Address,uint32 Length,uint8 * Buffer)607 static void KING_GetAddressSpaceBytes(const char *name, uint32 Address, uint32 Length, uint8 *Buffer)
608 {
609 if(!strcmp(name, "kram0") || !strcmp(name, "kram1"))
610 {
611 int wk = name[4] - '0';
612
613 while(Length--)
614 {
615 *Buffer = king->KRAM[wk][(Address >> 1) & 0x3ffff] >> ((Address & 1) * 8);
616 Address++;
617 Buffer++;
618 }
619 }
620 else if(!strcmp(name, "vce"))
621 {
622 while(Length--)
623 {
624 Address &= 0x3FF;
625 *Buffer = fx_vce.palette_table[Address >> 1] >> ((Address & 1) * 8);
626 Address++;
627 Buffer++;
628 }
629 }
630 }
631
KING_PutAddressSpaceBytes(const char * name,uint32 Address,uint32 Length,uint32 Granularity,bool hl,const uint8 * Buffer)632 static void KING_PutAddressSpaceBytes(const char *name, uint32 Address, uint32 Length, uint32 Granularity, bool hl, const uint8 *Buffer)
633 {
634 if(!strcmp(name, "kram0") || !strcmp(name, "kram1"))
635 {
636 int wk = name[4] - '0';
637
638 while(Length--)
639 {
640 REGSETP(king->KRAM[wk][(Address >> 1) & 0x3ffff], *Buffer, Address & 1);
641 Address++;
642 Buffer++;
643 }
644 }
645 else if(!strcmp(name, "vce"))
646 {
647 while(Length--)
648 {
649 Address &= 0x3FF;
650 REGSETP(fx_vce.palette_table[Address >> 1], *Buffer, Address & 1);
651 RedoPaletteCache(Address >> 1);
652 Address++;
653 Buffer++;
654 }
655 }
656 }
657 #endif
658
RecalcKRAMPagePtrs(void)659 static void RecalcKRAMPagePtrs(void)
660 {
661 king->RainbowPagePtr = king->KRAM[(king->PageSetting & 0x1000) ? 1 : 0];
662 king->DMAPagePtr = king->KRAM[king->PageSetting & 1];
663 }
664
KING_RB_Fetch(void)665 uint8 KING_RB_Fetch(void)
666 {
667 uint8 ret = king->RainbowPagePtr[(king->RAINBOWKRAMReadPos >> 1) & 0x3FFFF] >> ((king->RAINBOWKRAMReadPos & 1) * 8);
668
669 king->RAINBOWKRAMReadPos = ((king->RAINBOWKRAMReadPos + 1) & 0x3FFFF) | (king->RAINBOWKRAMReadPos & 0x40000);
670
671 return(ret);
672 }
673
DoRealDMA(uint8 db)674 static void DoRealDMA(uint8 db)
675 {
676 if(!king->DMATransferFlipFlop)
677 king->DMALatch = db;
678 else
679 {
680 king->DMAPagePtr[king->DMATransferAddr & 0x3FFFF] = king->DMALatch | (db << 8);
681 king->DMATransferAddr = ((king->DMATransferAddr + 1) & 0x1FFFF) | (king->DMATransferAddr & 0x20000);
682 king->DMATransferSize = (king->DMATransferSize - 2) & 0x3FFFF;
683 if(!king->DMATransferSize)
684 {
685 KINGDBG("DMA Done\n");
686 king->DMAInterrupt = true;
687 RedoKINGIRQCheck();
688 king->DMAStatus &= ~1;
689 return;
690 }
691 }
692 king->DMATransferFlipFlop ^= 1;
693 }
694
FXVCE_Read16(uint32 A)695 uint16 FXVCE_Read16(uint32 A)
696 {
697 // bit 4-0: Register number
698 // bit 13-5: Raster counter
699 // bit 14: In interlace mode and when on odd fields set bit.
700 // bit 15: "0" during blanking(h or v), "1" during active screen area
701 // Raster counter increments a few cycles after the start of hblank.
702
703 if(!(A & 0x4))
704 {
705 uint16 fullret = 0;
706
707 fullret |= fx_vce.AR;
708 fullret |= fx_vce.odd_field ? 0x4000 : 0x0000;
709 fullret |= fx_vce.raster_counter << 5;
710
711 if(fx_vce.in_hblank || fx_vce.raster_counter < 22 || fx_vce.raster_counter == 262)
712 fullret |= 0 << 15; // Clear on blanking
713 else
714 fullret |= 1 << 15; // Set on active display.
715
716 return(fullret);
717 }
718 else
719 {
720 switch(fx_vce.AR) // No idea which registers are readable, so make them all readable :b
721 {
722 default: break;
723 case 0x00: return(fx_vce.picture_mode);
724 case 0x01: return(fx_vce.palette_rw_offset);
725 case 0x03: // Boundary Gate reads from 0x03 expecting palette data...
726 case 0x02:
727 {
728 uint16 ret = fx_vce.palette_rw_latch;
729 fx_vce.palette_rw_offset = (fx_vce.palette_rw_offset + 1) & 0x1FF;
730 fx_vce.palette_rw_latch = fx_vce.palette_table[fx_vce.palette_rw_offset];
731 return(ret);
732 }
733 case 0x04: return(fx_vce.palette_offset[0]);
734 case 0x05: return(fx_vce.palette_offset[1]);
735 case 0x06: return(fx_vce.palette_offset[2]);
736 case 0x07: return(fx_vce.palette_offset[3]);
737 case 0x08: return(fx_vce.priority[0]);
738 case 0x09: return(fx_vce.priority[1]);
739 case 0x0a: return(fx_vce.ChromaKeyY);
740 case 0x0b: return(fx_vce.ChromaKeyU);
741 case 0x0c: return(fx_vce.ChromaKeyV);
742
743 case 0x0d: return(fx_vce.CCR);
744 case 0x0e: return(fx_vce.BLE);
745 case 0x0f: return(fx_vce.SPBL);
746 case 0x10: return(fx_vce.coefficients[0]);
747 case 0x11: return(fx_vce.coefficients[1]);
748
749 case 0x12: return(fx_vce.coefficients[2]);
750 case 0x13: return(fx_vce.coefficients[3]);
751
752 case 0x14: return(fx_vce.coefficients[4]);
753 case 0x15: return(fx_vce.coefficients[5]);
754 }
755 }
756
757 return(0);
758 }
759
FXVCE_Write16(uint32 A,uint16 V)760 void FXVCE_Write16(uint32 A, uint16 V)
761 {
762 if(!(A & 0x4))
763 {
764 fx_vce.AR = V & 0x1F;
765 }
766 else
767 {
768 switch(fx_vce.AR)
769 {
770 case 0x00: fx_vce.picture_mode = V;
771 break;
772
773 case 0x01: fx_vce.palette_rw_offset = V & 0x1FF;
774 fx_vce.palette_rw_latch = fx_vce.palette_table[fx_vce.palette_rw_offset];
775 break;
776
777 case 0x02: fx_vce.palette_rw_latch = V;
778 fx_vce.palette_table[fx_vce.palette_rw_offset] = fx_vce.palette_rw_latch;
779 RedoPaletteCache(fx_vce.palette_rw_offset);
780 fx_vce.palette_rw_offset = (fx_vce.palette_rw_offset + 1) & 0x1FF;
781 break;
782
783 case 0x04: fx_vce.palette_offset[0] = V; break;
784 case 0x05: fx_vce.palette_offset[1] = V; break;
785 case 0x06: fx_vce.palette_offset[2] = V; break;
786 case 0x07: fx_vce.palette_offset[3] = V & 0x00FF; break;
787 case 0x08: fx_vce.priority[0] = V & 0x0777; break;
788 case 0x09: fx_vce.priority[1] = V & 0x7777; break;
789
790 case 0x0a: fx_vce.ChromaKeyY = V; break;
791 case 0x0b: fx_vce.ChromaKeyU = V; break;
792 case 0x0c: fx_vce.ChromaKeyV = V; break;
793
794 case 0x0d: fx_vce.CCR = V; break;
795 case 0x0e: fx_vce.BLE = V; break;
796 case 0x0f: fx_vce.SPBL = V; break;
797
798 case 0x10: fx_vce.coefficients[0] = V & 0xFFF; break;
799 case 0x11: fx_vce.coefficients[1] = V & 0xFFF; break;
800
801 case 0x12: fx_vce.coefficients[2] = V & 0xFFF; break;
802 case 0x13: fx_vce.coefficients[3] = V & 0xFFF; break;
803
804 case 0x14: fx_vce.coefficients[4] = V & 0xFFF; break;
805 case 0x15: fx_vce.coefficients[5] = V & 0xFFF; break;
806 }
807 }
808 }
809
RedoKINGIRQCheck(void)810 static void RedoKINGIRQCheck(void)
811 {
812 bool asserted = 0;
813
814 if(king->ADPCMIRQPending)
815 {
816 asserted = 1;
817 }
818
819 if(king->DMAInterrupt && (king->DMAStatus & 0x2))
820 {
821 asserted = 1;
822 }
823
824 if(king->CDInterrupt)
825 {
826 asserted = 1;
827 }
828
829 if(king->SubChannelInterrupt)
830 asserted = 1;
831
832 if(king->RasterIRQPending)
833 asserted = 1;
834
835 PCFXIRQ_Assert(PCFXIRQ_SOURCE_KING, asserted);
836 }
837
KING_CDIRQ(int type)838 void KING_CDIRQ(int type)
839 {
840 if(type == SCSICD_IRQ_MAGICAL_REQ)
841 {
842 if(king->Reg02 & 0x2)
843 {
844 if(SCSICD_GetIO() != ((king->Reg03 >> 0) & 1) ||
845 SCSICD_GetCD() != ((king->Reg03 >> 1) & 1) ||
846 SCSICD_GetMSG() != ((king->Reg03 >> 2) & 1))
847 {
848 KINGDBG("Phase mismatch interrupt asserted.\n");
849 king->CDInterrupt = true;
850 RedoKINGIRQCheck();
851 }
852 }
853 }
854 }
855
KING_StuffSubchannels(uint8 subchannels,int subindex)856 void KING_StuffSubchannels(uint8 subchannels, int subindex)
857 {
858 if(king->SubChannelControl & 0x1)
859 {
860 if(subindex == -2)
861 king->SubChannelBuf = 0x00;
862 else if(subindex == -1)
863 king->SubChannelBuf = 0x80;
864 else
865 king->SubChannelBuf = (subchannels & 0x7F);
866
867 if(king->SubChannelControl & 0x2)
868 {
869 king->SubChannelInterrupt = true;
870 RedoKINGIRQCheck();
871 }
872 }
873
874
875 }
876
KING_Read8(const v810_timestamp_t timestamp,uint32 A)877 uint8 KING_Read8(const v810_timestamp_t timestamp, uint32 A)
878 {
879 uint8 ret = KING_Read16(timestamp, A & ~1) >> ((A & 1) * 8);
880
881 //printf("Read8: %04x\n", A);
882 return(ret);
883 }
884
KING_EndFrame(v810_timestamp_t timestamp)885 void KING_EndFrame(v810_timestamp_t timestamp)
886 {
887 PCFX_SetEvent(PCFX_EVENT_KING, KING_Update(timestamp));
888 scsicd_ne = SCSICD_Run(timestamp);
889 }
890
KING_ResetTS(v810_timestamp_t ts_base)891 void KING_ResetTS(v810_timestamp_t ts_base)
892 {
893 SCSICD_ResetTS(ts_base);
894
895 king->lastts = ts_base;
896
897 if(king->dma_cycle_counter & 0x40000000)
898 {
899 king->dma_cycle_counter = 0x7FFFFFFF;
900 }
901 }
902
903 //static INLINE void StartKingMagic(void)
904 //{
905 // king->lastts = v810_timestamp;
906 // king->dma_cycle_counter = KING_MAGIC_INTERVAL;
907 // PCFX_SetEvent(PCFX_EVENT_KING, KING_MAGIC_INTERVAL);
908 //}
909
CalcNextEvent(int32 next_event)910 static INLINE int32 CalcNextEvent(int32 next_event)
911 {
912 if(king->dma_cycle_counter < next_event)
913 next_event = king->dma_cycle_counter;
914
915 if(scsicd_ne < next_event)
916 next_event = scsicd_ne;
917
918 return(next_event);
919 }
920
CalcNextExternalEvent(int32 next_event)921 static int32 CalcNextExternalEvent(int32 next_event)
922 {
923 // 100 = Hack to make the emulator go faster during CD DMA transfers.
924 if(king->dma_cycle_counter < next_event)
925 next_event = 100; //king->dma_cycle_counter;
926
927 if(scsicd_ne < next_event)
928 next_event = scsicd_ne;
929
930 if(next_event > HPhaseCounter)
931 next_event = HPhaseCounter;
932
933 //printf("KING: %d %d %d; %d\n", king->dma_cycle_counter, scsicd_ne, HPhaseCounter, next_event);
934
935 for(int chip = 0; chip < 2; chip++)
936 {
937 int fwoom = (fx_vce.vdc_event[chip] * fx_vce.dot_clock_ratio - fx_vce.clock_divider);
938
939 if(fwoom < 1)
940 fwoom = 1;
941
942 if(next_event > fwoom)
943 next_event = fwoom;
944 }
945
946 return(next_event);
947 }
948
949 static void MDFN_FASTCALL KING_RunGfx(int32 clocks);
950
KING_Update(const v810_timestamp_t timestamp)951 v810_timestamp_t MDFN_FASTCALL KING_Update(const v810_timestamp_t timestamp)
952 {
953 int32 clocks = timestamp - king->lastts;
954 uint32 running_timestamp = king->lastts;
955
956 //printf("KING Run for: %d\n", clocks);
957
958 king->lastts = timestamp;
959
960 KING_RunGfx(clocks);
961
962 while(clocks > 0)
963 {
964 int32 chunk_clocks = CalcNextEvent(clocks);
965
966 running_timestamp += chunk_clocks;
967 clocks -= chunk_clocks;
968
969 scsicd_ne -= chunk_clocks;
970 if(scsicd_ne <= 0)
971 scsicd_ne = SCSICD_Run(running_timestamp);
972
973 king->dma_cycle_counter -= chunk_clocks;
974 if(king->dma_cycle_counter <= 0)
975 {
976 //assert(king->dma_receive_active || king->dma_send_active);
977 king->dma_cycle_counter += KING_MAGIC_INTERVAL;
978 if(king->dma_receive_active)
979 {
980 if(!SCSICD_GetCD() && SCSICD_GetIO())
981 {
982 if(SCSICD_GetREQ() && !SCSICD_GetACK())
983 {
984 if(!king->DRQ)
985 {
986 king->DRQ = true;
987 king->data_cache = SCSICD_GetDB();
988 //SCSICD_SetACK(true);
989 //PCFX_SetEvent(PCFX_EVENT_SCSI, SCSICD_Run(timestamp));
990
991 if(king->DMAStatus & 0x1)
992 {
993 king->DRQ = false;
994 DoRealDMA(king->data_cache);
995 SCSICD_SetACK(true);
996 scsicd_ne = SCSICD_Run(running_timestamp);
997 }
998 }
999 }
1000 else if(SCSICD_GetACK() && !SCSICD_GetREQ())
1001 {
1002 SCSICD_SetACK(false);
1003 scsicd_ne = SCSICD_Run(running_timestamp);
1004 }
1005 }
1006 }
1007 else if(king->dma_send_active)
1008 {
1009 if(!SCSICD_GetIO())
1010 {
1011 if(SCSICD_GetREQ() && !SCSICD_GetACK())
1012 {
1013 if(!king->DRQ)
1014 {
1015 //KINGDBG("Did write: %02x\n", king->data_cache);
1016 SCSICD_SetDB(king->data_cache);
1017 SCSICD_SetACK(true);
1018 scsicd_ne = SCSICD_Run(running_timestamp);
1019 king->DRQ = true;
1020 }
1021 }
1022 else if(SCSICD_GetACK() && !SCSICD_GetREQ())
1023 {
1024 SCSICD_SetACK(false);
1025 scsicd_ne = SCSICD_Run(running_timestamp);
1026 }
1027 }
1028 }
1029 }
1030 } // end while(clocks > 0)
1031
1032 return(timestamp + CalcNextExternalEvent(0x4FFFFFFF));
1033 }
1034
KING_Read16(const v810_timestamp_t timestamp,uint32 A)1035 uint16 KING_Read16(const v810_timestamp_t timestamp, uint32 A)
1036 {
1037 int msh = A & 2;
1038 uint16 ret = 0;
1039
1040 KING_Update(timestamp);
1041
1042 //printf("KRead16: %08x, %d; %04x\n", A, timestamp, king->AR);
1043
1044 switch(A & 0x704)
1045 {
1046 case 0x600: // ?CDSRP?? AAAAAAAA
1047 // C = 0x4000, SCSI interrupt
1048 // D = 0x2000, DMA IRQ
1049 // S = 0x1000, CD Subchannel IRQ?
1050 // R = 0x0800, Raster IRQ
1051 // P = 0x0400, ADPCM IRQ
1052
1053 if(!msh)
1054 {
1055 ret = king->AR;
1056
1057 if(king->ADPCMIRQPending)
1058 ret |= 0x400;
1059
1060 if(king->SubChannelInterrupt)
1061 ret |= 0x1000;
1062
1063 // Gaaah, this is probably a hack...Anime Freak FX Vol 4 gets confused and crashes
1064 // if both bits are set at once.
1065 if(king->DMAInterrupt && (king->DMAStatus & 0x2))
1066 ret |= 0x2000;
1067 else if(king->CDInterrupt)
1068 ret |= 0x4000;
1069
1070 if(king->RasterIRQPending)
1071 ret |= 0x800;
1072
1073 king->SubChannelInterrupt = false;
1074 king->RasterIRQPending = false;
1075 RedoKINGIRQCheck();
1076 }
1077 else
1078 {
1079 ret |= SCSICD_GetSEL() ? 0x02: 0x00;
1080 ret |= SCSICD_GetIO() ? 0x04 : 0x00;
1081 ret |= SCSICD_GetCD() ? 0x08 : 0x00;
1082 ret |= SCSICD_GetMSG() ? 0x10 : 0x00;
1083 ret |= SCSICD_GetREQ() ? 0x20 : 0x00;
1084 ret |= SCSICD_GetBSY() ? 0x40 : 0x00;
1085 ret |= SCSICD_GetRST() ? 0x80 : 0x00;
1086
1087 ret |= king->SubChannelBuf << 8;
1088 }
1089 break; // status...
1090
1091 case 0x604: switch(king->AR)
1092 {
1093 default:
1094 KINGDBG("Unknown 16-bit register read: %02x\n", king->AR);
1095 break;
1096
1097 case 0x00:
1098 ret = SCSICD_GetDB();
1099 break;
1100
1101 case 0x01:
1102 ret = REGGETHW(king->Reg01, msh);
1103 break;
1104
1105 case 0x02:
1106 ret = REGGETHW(king->Reg02, msh);
1107 break;
1108
1109 case 0x03:
1110 ret = REGGETHW(king->Reg03, msh);
1111 break;
1112
1113 case 0x04:
1114 if(!msh)
1115 {
1116 ret |= SCSICD_GetSEL() ? 0x02: 0x00;
1117 ret |= SCSICD_GetIO() ? 0x04 : 0x00;
1118 ret |= SCSICD_GetCD() ? 0x08 : 0x00;
1119 ret |= SCSICD_GetMSG() ? 0x10 : 0x00;
1120 ret |= SCSICD_GetREQ() ? 0x20 : 0x00;
1121 ret |= SCSICD_GetBSY() ? 0x40 : 0x00;
1122 ret |= SCSICD_GetRST() ? 0x80 : 0x00;
1123 }
1124 break;
1125
1126 case 0x05:
1127 if(king->Reg01 & 0x80)
1128 {
1129 ret = 0x00;
1130 break;
1131 }
1132
1133 if(msh)
1134 {
1135 ret = king->data_cache;
1136 //printf("Fooball: %02x\n", ret);
1137 if(king->dma_receive_active)
1138 {
1139 king->DRQ = false;
1140 SCSICD_SetACK(true);
1141 scsicd_ne = 1;
1142 }
1143 }
1144 else
1145 {
1146 ret |= SCSICD_GetACK() ? 0x01 : 0x00;
1147 ret |= SCSICD_GetATN() ? 0x02 : 0x00;
1148
1149 if(king->dma_receive_active || king->dma_send_active)
1150 if(king->DRQ)
1151 ret |= 0x40;
1152
1153 // Gaaah, this is probably a hack...Anime Freak FX Vol 4 gets confused and crashes
1154 // if both bits are set at once.
1155 if(!king->DMAInterrupt)
1156 ret |= king->CDInterrupt ? 0x10 : 0x00;
1157
1158 if(SCSICD_GetIO() == ((king->Reg03 >> 0) & 1) &&
1159 SCSICD_GetCD() == ((king->Reg03 >> 1) & 1) &&
1160 SCSICD_GetMSG() == ((king->Reg03 >> 2) & 1))
1161 {
1162 ret |= 0x8; // Phase match
1163 }
1164 }
1165 break;
1166
1167 case 0x06: // SCSI Input Data Register, same value returned as reading D16-D23 of register 0x05?
1168 KINGDBG("Input data for...?\n");
1169 ret = king->data_cache;
1170 break;
1171
1172 case 0x07:
1173 // SCSI IRQ acknowledge/reset
1174 KINGDBG("SCSI IRQ acknowledge\n");
1175 king->CDInterrupt = false;
1176 RedoKINGIRQCheck();
1177 ret = 0xFF;
1178 break;
1179
1180 case 0x08: // Sub-channel data
1181 if(!msh)
1182 {
1183 ret = king->SubChannelBuf;
1184 king->SubChannelBuf = 0;
1185 //puts("Sub-channel data read.");
1186 }
1187 break;
1188
1189 case 0x09:
1190 ret = REGGETHW(king->DMATransferAddr, msh);
1191 break;
1192
1193 case 0x0A:
1194 ret = REGGETHW(king->DMATransferSize, msh);
1195 break;
1196
1197 case 0x0B: // Value read in the BIOS always seems to be discarded... DMA IRQ acknowledge?
1198 if(!msh)
1199 {
1200 ret = king->DMAInterrupt ? 1 : 0;
1201 KINGDBG("DMA IRQ Acknowledge: %d\n", ret);
1202 king->DMAInterrupt = 0;
1203 RedoKINGIRQCheck();
1204 }
1205 break;
1206
1207 case 0x0C:
1208 ret = REGGETHW(king->KRAMRA, msh);
1209 break;
1210
1211 case 0x0D:
1212 ret = REGGETHW(king->KRAMWA, msh);
1213 break;
1214
1215 case 0x0E:
1216 {
1217 unsigned int page = (king->KRAMRA & 0x80000000) ? 1 : 0;
1218 int32 inc_amount = ((int32)((king->KRAMRA & (0x3FF << 18)) << 4)) >> 22; // Convert from 10-bit signed 2's complement
1219
1220 ret = king->KRAM[page][king->KRAMRA & 0x3FFFF];
1221
1222 #ifdef WANT_DEBUGGER
1223 if(KRAMReadBPE)
1224 PCFXDBG_CheckBP(BPOINT_AUX_READ, (king->KRAMRA & 0x3FFFF) | (page ? 0x40000 : 0), 0, 1);
1225 #endif
1226
1227 king->KRAMRA = (king->KRAMRA &~ 0x1FFFF) | ((king->KRAMRA + inc_amount) & 0x1FFFF);
1228 }
1229 break;
1230
1231 case 0x0F: ret = king->PageSetting;
1232 break;
1233
1234 case 0x10: ret = REGGETHW(king->bgmode, msh);
1235 break;
1236
1237 case 0x15: ret = king->MPROGControl;
1238 break;
1239
1240 //case 0x40: break; // Super Power League FX reads this, but I think it's write-only.
1241
1242 case 0x53:
1243 {
1244 ret = king->ADPCMStatus[0] | (king->ADPCMStatus[1] << 2);
1245
1246 king->ADPCMStatus[0] = king->ADPCMStatus[1] = 0;
1247 king->ADPCMIRQPending = 0;
1248
1249 RedoKINGIRQCheck();
1250
1251 ADPCMDBG("Status read: %02x\n", ret);
1252 }
1253 break;
1254 }
1255 break;
1256
1257 }
1258
1259 PCFX_SetEvent(PCFX_EVENT_KING, timestamp + CalcNextExternalEvent(0x4FFFFFFF)); // TODO: Optimize this to only be called when necessary.
1260
1261 return(ret);
1262 }
1263
KING_Write8(const v810_timestamp_t timestamp,uint32 A,uint8 V)1264 void KING_Write8(const v810_timestamp_t timestamp, uint32 A, uint8 V)
1265 {
1266 KING_Write16(timestamp, A & 0x706, V << ((A & 1) ? 8 : 0));
1267 }
1268
SCSI_Reg0_Write(const v810_timestamp_t timestamp,uint8 V,bool delay_run=0)1269 static INLINE void SCSI_Reg0_Write(const v810_timestamp_t timestamp, uint8 V, bool delay_run = 0)
1270 {
1271 king->Reg00 = V;
1272 SCSICD_SetDB(V);
1273
1274 KINGDBG("WriteDB: %02x\n", V);
1275
1276 if(!delay_run)
1277 {
1278 scsicd_ne = 1; //SCSICD_Run(timestamp);
1279 }
1280 }
1281
SCSI_Reg2_Write(const v810_timestamp_t timestamp,uint8 V,bool delay_run=0)1282 static INLINE void SCSI_Reg2_Write(const v810_timestamp_t timestamp, uint8 V, bool delay_run = 0)
1283 {
1284 KINGDBG("SCSI Mode: %04x\n", V);
1285
1286 /* SCSI Mode Register
1287 D0 = SED: When using with sequential DMA mode, you use.
1288 (It sets the normal DMA mode time to "0".)
1289 Sequential DMA, the number of transfer data bytes which are set to the SCSI device (m) HuC6272 (REG.A) the number
1290 of transfer bytes (n) it sets more largely, abbreviates the status message command phase after the n byte
1291 transferring and being something which makes the transfer after the n + 1 byte possible, it is possible to
1292 increase the transfer performance from the slow SCSI device of CD-ROM and the like.
1293 Sequential DMA cannot use with imitation DMA. When this bit is designated as 1, because -ACK the signal
1294 mandatorily ネゲート it is done, other than the stipulated sequence please do not use.
1295
1296 D1 = DMA Mode:
1297 When using the SCSI control section with normal DMA mode, "1" is set.
1298 */
1299 if(!(V & 0x2) && (king->Reg02 & 0x2))
1300 {
1301
1302 { // HACK(probably)
1303 king->CDInterrupt = false;
1304 RedoKINGIRQCheck();
1305 }
1306
1307 SCSICD_SetACK(0);
1308
1309 if(!delay_run)
1310 {
1311 scsicd_ne = 1; //SCSICD_Run(timestamp);
1312 }
1313 king->DRQ = false;
1314
1315 king->dma_receive_active = false;
1316 king->dma_send_active = false;
1317 king->dma_cycle_counter = 0x7FFFFFFF;
1318 }
1319
1320 king->Reg02 = V;
1321 }
1322
SCSI_Reg3_Write(const v810_timestamp_t timestamp,uint8 V,bool delay_run=0)1323 static INLINE void SCSI_Reg3_Write(const v810_timestamp_t timestamp, uint8 V, bool delay_run = 0)
1324 {
1325 KINGDBG("Set phase match SCSI bus bits: IO: %d, CD: %d, MSG: %d\n", (int)(bool)(V & 1), (int)(bool)(V & 2), (int)(bool)(V & 4));
1326 king->Reg03 = V & 0x7;
1327
1328 if(!delay_run)
1329 {
1330 scsicd_ne = 1; //SCSICD_Run(timestamp);
1331 }
1332 }
1333
KING_Write16(const v810_timestamp_t timestamp,uint32 A,uint16 V)1334 void KING_Write16(const v810_timestamp_t timestamp, uint32 A, uint16 V)
1335 {
1336 int msh = A & 0x2;
1337
1338 //printf("Write16: %08x %04x\n", A, V);
1339
1340
1341 if(!(A & 0x4))
1342 {
1343 if(!msh)
1344 king->AR = V & 0x7F;
1345 }
1346 else
1347 {
1348 //if(king->AR != 0x0E)
1349 // printf("KING: %02x %04x, %d\n", king->AR, V, fx_vce.raster_counter);
1350 KING_Update(timestamp);
1351
1352 if(king->AR >= 0x50 && king->AR <= 0x5E)
1353 {
1354 //ADPCMDBG("Write: %02x(%d), %04x", king->AR, msh, V);
1355 }
1356
1357 switch(king->AR)
1358 {
1359 default:
1360 KINGDBG("Unknown 16-bit register write: %02x %04x %d\n", king->AR, V, msh);
1361 break;
1362
1363 case 0x00: if(king->Reg01 & 0x80)
1364 break;
1365
1366 if(!msh)
1367 {
1368 SCSI_Reg0_Write(timestamp, V);
1369 }
1370 break;
1371
1372 case 0x01: if(!msh)
1373 {
1374 KINGDBG("Set SCSI BUS bits; Assert DB: %d, ATN: %d, SEL: %d, ACK: %d, RST: %d, %02x\n",
1375 (int)(bool)(V & 1), (int)(bool)(V & 2), (int)(bool)(V & 4),
1376 (int)(bool)(V & 0x10), (int)(bool)(V &0x80), SCSICD_GetDB());
1377
1378 if(V & 0x80) // RST, silly KING, resets SCSI internal control registers too!
1379 {
1380 if(!(king->Reg01 & 0x80))
1381 {
1382 SCSI_Reg0_Write(timestamp, 0, true);
1383 SCSI_Reg2_Write(timestamp, 0, true);
1384 SCSI_Reg3_Write(timestamp, 0, true);
1385 king->data_cache = 0x00;
1386
1387 //king->CDInterrupt = true;
1388 //RedoKINGIRQCheck();
1389 //puts("KING RST IRQ");
1390 }
1391
1392 king->Reg01 = V & 0x80; // Only this bit remains...how lonely.
1393 }
1394 else
1395 {
1396 king->Reg01 = V & (1 | 2 | 4 | 0x10 | 0x80);
1397
1398 SCSICD_SetATN(V & 2);
1399 SCSICD_SetSEL(V & 4);
1400 SCSICD_SetACK(V & 0x10);
1401 }
1402 SCSICD_SetRST(V & 0x80);
1403 scsicd_ne = 1;
1404 }
1405 break;
1406
1407 case 0x02: if(king->Reg01 & 0x80)
1408 break;
1409
1410 if(!msh)
1411 {
1412 SCSI_Reg2_Write(timestamp, V);
1413 }
1414 break;
1415
1416 case 0x03: if(king->Reg01 & 0x80)
1417 break;
1418
1419 if(!msh)
1420 {
1421 SCSI_Reg3_Write(timestamp, V);
1422 }
1423 break;
1424
1425 case 0x05: if(king->Reg01 & 0x80)
1426 break;
1427
1428 if(!msh) // Start DMA target receive
1429 {
1430 KINGDBG("DMA target receive: %04x, %d\n", V, msh);
1431 king->dma_receive_active = false;
1432 king->dma_send_active = true;
1433 king->DRQ = true;
1434 //StartKingMagic();
1435 king->dma_cycle_counter = KING_MAGIC_INTERVAL;
1436 }
1437 else
1438 {
1439 if(king->dma_send_active && king->DRQ)
1440 {
1441 //KINGDBG("%02x\n", V);
1442 king->data_cache = V;
1443 king->DRQ = false;
1444 }
1445 }
1446 break;
1447
1448 case 0x06: break; // Not used for writes?
1449
1450 case 0x07: if(king->Reg01 & 0x80)
1451 break;
1452
1453 KINGDBG("Start DMA initiator receive: %04x\n", V);
1454
1455 if(king->Reg02 & 0x2)
1456 {
1457 king->dma_receive_active = true;
1458 king->dma_send_active = false;
1459 //StartKingMagic();
1460 king->dma_cycle_counter = KING_MAGIC_INTERVAL;
1461 }
1462 break;
1463
1464 case 0x08: // Sub-channel control
1465 KINGDBG("Sub-channel control: %02x\n", V);
1466
1467 king->SubChannelControl = V & 0x3;
1468 king->SubChannelInterrupt = false;
1469 RedoKINGIRQCheck();
1470 break;
1471
1472 case 0x09: REGSETHW(king->DMATransferAddr, V, msh); king->DMATransferAddr &= 0x3FFFF; break;
1473 case 0x0A: REGSETHW(king->DMATransferSize, V, msh); king->DMATransferSize &= 0x3FFFE; king->DMATransferFlipFlop = 0; break;
1474 case 0x0B: REGSETHW(king->DMAStatus, V, msh);
1475 king->DMAStatus &= 0x3;
1476 king->DMAInterrupt = 0;
1477 RedoKINGIRQCheck();
1478
1479 king->DMATransferFlipFlop = 0;
1480
1481 KINGDBG("SCSI DMA: %04x, dest=%06x, page=%d, size=%06x(16-bit words)\n", V, king->DMATransferAddr, king->PageSetting & 1, king->DMATransferSize >> 1);
1482
1483 #ifdef WANT_DEBUGGER
1484 if(KINGLog)
1485 {
1486 //if(V & 1)
1487 // KINGLog("KING", "SCSI DMA: dest=%06x, page=%d, size=%06x(16-bit words)", king->DMATransferAddr, king->PageSetting & 1, king->DMATransferSize >> 1);
1488 }
1489 #endif
1490 break;
1491 case 0x0C: REGSETHW(king->KRAMRA, V, msh); break;
1492 case 0x0D: REGSETHW(king->KRAMWA, V, msh); break;
1493 case 0x0E:
1494 {
1495 unsigned int page = (king->KRAMWA & 0x80000000) ? 1 : 0;
1496 int32 inc_amount = ((int32)((king->KRAMWA & (0x3FF << 18)) << 4)) >> 22; // Convert from 10-bit signed 2's complement
1497
1498 #ifdef WANT_DEBUGGER
1499 if(KRAMWriteBPE)
1500 PCFXDBG_CheckBP(BPOINT_AUX_WRITE, (king->KRAMWA & 0x3FFFF) | (page ? 0x40000 : 0), V, 1);
1501 #endif
1502
1503 king->KRAM[page][king->KRAMWA & 0x3FFFF] = V;
1504 king->KRAMWA = (king->KRAMWA &~ 0x1FFFF) | ((king->KRAMWA + inc_amount) & 0x1FFFF);
1505 }
1506 break;
1507
1508
1509 // Page settings(0/1) for BG, DMA, ADPCM, and RAINBOW transfers.
1510 case 0x0F: REGSETHW(king->PageSetting, V, msh);
1511 RecalcKRAMPagePtrs();
1512 break;
1513
1514
1515 // Background Modes
1516 case 0x10: REGSETHW(king->bgmode, V, msh);
1517 break;
1518
1519
1520 // Background priorities and affine transform master enable.
1521 case 0x12: if(!msh)
1522 {
1523 king->priority = V;
1524 if(king->priority & ~0x1FFF)
1525 {
1526 KING_UNDEF("Invalid priority bits set: %04x\n", king->priority);
1527 }
1528 }
1529 break;
1530
1531
1532 // Microprogram Address
1533 case 0x13: if(!msh)
1534 {
1535 king->MPROGAddress = V & 0xF;
1536 }
1537 break;
1538
1539
1540 // Microprogram Data Port
1541 case 0x14: if(!msh)
1542 {
1543 king->MPROGData[king->MPROGAddress] = V;
1544 king->MPROGAddress = (king->MPROGAddress + 1) & 0xF;
1545 }
1546 break;
1547
1548 case 0x15: REGSETHW(king->MPROGControl, V, msh); king->MPROGControl &= 0x1; break;
1549
1550 case 0x16: REGSETHW(king->BGScrollMode, V, msh); king->BGScrollMode &= 0xF; break;
1551
1552 case 0x20: REGSETHW(king->BGBATAddr[0], V, msh); break;
1553 case 0x21: REGSETHW(king->BGCGAddr[0], V, msh); break;
1554 case 0x22: REGSETHW(king->BG0SubBATAddr, V, msh); break;
1555 case 0x23: REGSETHW(king->BG0SubCGAddr, V, msh); break;
1556
1557 case 0x24: REGSETHW(king->BGBATAddr[1], V, msh); break;
1558 case 0x25: REGSETHW(king->BGCGAddr[1], V, msh); break;
1559 case 0x28: REGSETHW(king->BGBATAddr[2], V, msh); break;
1560 case 0x29: REGSETHW(king->BGCGAddr[2], V, msh); break;
1561 case 0x2A: REGSETHW(king->BGBATAddr[3], V, msh); break;
1562 case 0x2B: REGSETHW(king->BGCGAddr[3], V, msh); break;
1563
1564 case 0x2C: REGSETHW(king->BGSize[0], V, msh); break;
1565 case 0x2D: REGSETHW(king->BGSize[1], V, msh); king->BGSize[1] &= 0x00FF; break;
1566 case 0x2E: REGSETHW(king->BGSize[2], V, msh); king->BGSize[2] &= 0x00FF; break;
1567 case 0x2F: REGSETHW(king->BGSize[3], V, msh); king->BGSize[3] &= 0x00FF; break;
1568
1569 case 0x30: REGSETHW(king->BGXScroll[0], V, msh); king->BGXScroll[0] &= 0x7FF; break;
1570 case 0x31: REGSETHW(king->BGYScroll[0], V, msh); king->BGYScroll[0] &= 0x7FF; break;
1571
1572 case 0x32: REGSETHW(king->BGXScroll[1], V, msh); king->BGXScroll[1] &= 0x3FF; break;
1573 case 0x33: REGSETHW(king->BGYScroll[1], V, msh); king->BGYScroll[1] &= 0x3FF; break;
1574
1575 case 0x34: REGSETHW(king->BGXScroll[2], V, msh); king->BGXScroll[2] &= 0x3FF; break;
1576 case 0x35: REGSETHW(king->BGYScroll[2], V, msh); king->BGYScroll[2] &= 0x3FF; break;
1577
1578 case 0x36: REGSETHW(king->BGXScroll[3], V, msh); king->BGXScroll[3] &= 0x3FF; break;
1579 case 0x37: REGSETHW(king->BGYScroll[3], V, msh); king->BGYScroll[3] &= 0x3FF; break;
1580
1581
1582 case 0x38: REGSETHW(king->BGAffinA, V, msh); break;
1583 case 0x39: REGSETHW(king->BGAffinB, V, msh); break;
1584 case 0x3a: REGSETHW(king->BGAffinC, V, msh); break;
1585 case 0x3b: REGSETHW(king->BGAffinD, V, msh); break;
1586 case 0x3c: REGSETHW(king->BGAffinCenterX, V, msh); break;
1587 case 0x3d: REGSETHW(king->BGAffinCenterY, V, msh); break;
1588
1589
1590 case 0x40: // ------IE
1591 // I = 1, interrupt enable??
1592 // E = 1, rainbow transfer enable
1593 if(!msh)
1594 {
1595 king->RAINBOWTransferControl = V & 0x3;
1596 if(!(V & 1))
1597 {
1598 //if(king->RAINBOWBusyCount || king->RAINBOWBlockCount)
1599 // puts("RAINBOW transfer reset");
1600 // Not sure if this is completely correct or not. Test cases: "Tonari no Princess Rolfee", (others?)
1601 //king->RAINBOWBusyCount = 0;
1602 //king->RAINBOWBlockCount = 0;
1603 //RAINBOW_ForceTransferReset();
1604 king->RAINBOWBlockCount = 0;
1605 }
1606 }
1607 king->RasterIRQPending = false;
1608 RedoKINGIRQCheck();
1609 //printf("Transfer Control: %d, %08x\n", fx_vce.raster_counter, king->RAINBOWTransferControl);
1610 break;
1611
1612 // Rainbow transfer address
1613 case 0x41: REGSETHW(king->RAINBOWKRAMA, V, msh);
1614 king->RAINBOWKRAMA &= 0x3FFFF;
1615 //printf("KRAM Transfer Addr: %d, %08x\n", fx_vce.raster_counter, king->RAINBOWKRAMA);
1616 break;
1617
1618 // 0-262
1619 case 0x42: if(!msh)
1620 {
1621 king->RAINBOWTransferStartPosition = V & 0x1FF;
1622 //fprintf(stderr, "%d\n", king->RAINBOWTransferStartPosition);
1623 //printf("RAINBOW Start Line: %d, %08x\n", fx_vce.raster_counter, king->RAINBOWTransferStartPosition);
1624 }
1625 break;
1626
1627 case 0x43: REGSETHW(king->RAINBOWTransferBlockCount, V, msh);
1628 king->RAINBOWTransferBlockCount &= 0x1F;
1629 //printf("KRAM Transfer Block Count: %d, %08x\n", fx_vce.raster_counter, king->RAINBOWTransferBlockCount);
1630 break;
1631
1632 // Raster IRQ line
1633 case 0x44: if(!msh)
1634 {
1635 king->RasterIRQLine = V & 0x1FF;
1636 //printf("Raster IRQ scanline: %d, %08x\n", fx_vce.raster_counter, king->RasterIRQLine);
1637 }
1638 break;
1639
1640 case 0x50:
1641 if(!msh)
1642 {
1643 for(int ch = 0; ch < 2; ch++)
1644 {
1645 if(!(king->ADPCMControl & (1 << ch)) && (V & (1 << ch)))
1646 {
1647 king->ADPCMPlayAddress[ch] = king->ADPCMSAL[ch] * 256;
1648 }
1649 }
1650 king->ADPCMControl = V;
1651 RedoKINGIRQCheck();
1652 SoundBox_SetKINGADPCMControl(king->ADPCMControl);
1653 }
1654 break;
1655
1656 case 0x51: REGSETHW(king->ADPCMBufferMode[0], V, msh);
1657 RedoKINGIRQCheck();
1658 break;
1659
1660 case 0x52: REGSETHW(king->ADPCMBufferMode[1], V, msh);
1661 RedoKINGIRQCheck();
1662 break;
1663
1664 case 0x58: REGSETHW(king->ADPCMSAL[0], V, msh); king->ADPCMSAL[0] &= 0x3FF; break;
1665 case 0x59: REGSETHW(king->ADPCMEndAddress[0], V, msh); king->ADPCMEndAddress[0] &= 0x3FFFF; break;
1666 case 0x5A: REGSETHW(king->ADPCMIntermediateAddress[0], V, msh); king->ADPCMIntermediateAddress[0] &= 0xFFF; break;
1667
1668 case 0x5C: REGSETHW(king->ADPCMSAL[1], V, msh); king->ADPCMSAL[1] &= 0x3FF; break;
1669 case 0x5D: REGSETHW(king->ADPCMEndAddress[1], V, msh); king->ADPCMEndAddress[1] &= 0x3FFFF; break;
1670 case 0x5E: REGSETHW(king->ADPCMIntermediateAddress[1], V, msh); king->ADPCMIntermediateAddress[1] &= 0xFFF; break;
1671
1672
1673 case 0x61: if(king->KRAM_Mode ^ V)
1674 {
1675 KINGDBG("KRAM Mode Change To: %02x\n", V & 1);
1676 king->KRAM_Mode = V & 0x1;
1677 }
1678 break;
1679 }
1680
1681 PCFX_SetEvent(PCFX_EVENT_KING, timestamp + CalcNextExternalEvent(0x4FFFFFFF)); // TODO: Optimize this to only be called when necessary.
1682 }
1683 }
1684
KING_GetADPCMHalfWord(int ch)1685 uint16 KING_GetADPCMHalfWord(int ch)
1686 {
1687 int page = (king->PageSetting & 0x0100) ? 1 : 0;
1688 uint16 ret = king->KRAM[page][king->ADPCMPlayAddress[ch] & 0x3FFFF];
1689
1690 king->ADPCMPlayAddress[ch] = (king->ADPCMPlayAddress[ch] & 0x20000) | ((king->ADPCMPlayAddress[ch] + 1) & 0x1FFFF);
1691
1692 if(!(king->ADPCMPlayAddress[ch] & 0x1FFFF))
1693 {
1694 ADPCMDBG("Ch %d Wrapped", ch);
1695 }
1696
1697 if(king->ADPCMPlayAddress[ch] == (((king->ADPCMEndAddress[ch] + 1) & 0x1FFFF) | (king->ADPCMEndAddress[ch] & 0x20000)) )
1698 {
1699 ADPCMDBG("Ch %d End", ch);
1700
1701 if(!(king->ADPCMBufferMode[ch] & 1))
1702 {
1703 king->ADPCMControl &= ~(1 << ch);
1704 SoundBox_SetKINGADPCMControl(king->ADPCMControl);
1705 }
1706 else
1707 {
1708 king->ADPCMPlayAddress[ch] = king->ADPCMSAL[ch] << 8;
1709 }
1710
1711 king->ADPCMStatus[ch] |= 1;
1712
1713 if(king->ADPCMBufferMode[ch] & (0x1 << 1))
1714 {
1715 king->ADPCMIRQPending = true;
1716 RedoKINGIRQCheck();
1717 }
1718 }
1719 else if(king->ADPCMPlayAddress[ch] == ((uint32)king->ADPCMIntermediateAddress[ch] << 6) )
1720 {
1721 ADPCMDBG("Ch %d Intermediate", ch);
1722 king->ADPCMStatus[ch] |= 2;
1723
1724 if(king->ADPCMBufferMode[ch] & (0x2 << 1))
1725 {
1726 king->ADPCMIRQPending = true;
1727 RedoKINGIRQCheck();
1728 }
1729 }
1730
1731 return(ret);
1732 }
1733
1734 static uint32 HighDotClockWidth;
1735 extern RavenBuffer* FXCDDABufs[2]; // FIXME, externals are evil!
1736
Cleanup(void)1737 static void Cleanup(void)
1738 {
1739 if(king)
1740 {
1741 delete king;
1742 king = NULL;
1743 }
1744
1745 SCSICD_Close();
1746 }
1747
KING_Init(void)1748 void KING_Init(void)
1749 {
1750 try
1751 {
1752 king = new king_t();
1753 memset(king, 0, sizeof(king_t));
1754
1755 king->lastts = 0;
1756
1757 HighDotClockWidth = MDFN_GetSettingUI("pcfx.high_dotclock_width");
1758 BGLayerDisable = 0;
1759
1760 BuildCMT();
1761
1762 // Build VCE priority map.
1763 // Don't change this unless you know what you're doing!
1764 // There may appear to be a bug in the pixel mixing
1765 // code elsewhere, because it accesses this array like [vdc][bg][rainbow], but it's not a bug.
1766 // This multi-dimensional array has no concept of bg, vdc, rainbow, or their orders per-se, it just
1767 // contains priority information for 3 different layers.
1768
1769 for(int bg_prio = 0; bg_prio < 8; bg_prio++)
1770 for(int vdc_prio = 0; vdc_prio < 8; vdc_prio++)
1771 for(int rainbow_prio = 0; rainbow_prio < 8; rainbow_prio++)
1772 {
1773 int bg_prio_test = bg_prio ? bg_prio : 0x10;
1774 int vdc_prio_test = vdc_prio ? vdc_prio : 0x10;
1775 int rainbow_prio_test = rainbow_prio ? rainbow_prio : 0x10;
1776
1777 if(bg_prio_test >= 8)
1778 VCEPrioMap[bg_prio][vdc_prio][rainbow_prio][0] = 3;
1779 else
1780 {
1781 if(bg_prio_test < vdc_prio_test && bg_prio_test < rainbow_prio_test)
1782 VCEPrioMap[bg_prio][vdc_prio][rainbow_prio][0] = 0;
1783 else if(bg_prio_test > vdc_prio_test && bg_prio_test > rainbow_prio_test)
1784 VCEPrioMap[bg_prio][vdc_prio][rainbow_prio][0] = 2;
1785 else
1786 VCEPrioMap[bg_prio][vdc_prio][rainbow_prio][0] = 1;
1787 }
1788
1789 if(vdc_prio_test >= 8)
1790 VCEPrioMap[bg_prio][vdc_prio][rainbow_prio][1] = 3;
1791 else
1792 {
1793 if(vdc_prio_test < bg_prio_test && vdc_prio_test < rainbow_prio_test)
1794 VCEPrioMap[bg_prio][vdc_prio][rainbow_prio][1] = 0;
1795 else if(vdc_prio_test > bg_prio_test && vdc_prio_test > rainbow_prio_test)
1796 VCEPrioMap[bg_prio][vdc_prio][rainbow_prio][1] = 2;
1797 else
1798 VCEPrioMap[bg_prio][vdc_prio][rainbow_prio][1] = 1;
1799 }
1800
1801 if(rainbow_prio_test >= 8)
1802 VCEPrioMap[bg_prio][vdc_prio][rainbow_prio][2] = 3;
1803 else
1804 {
1805 if(rainbow_prio_test < bg_prio_test && rainbow_prio_test < vdc_prio_test)
1806 VCEPrioMap[bg_prio][vdc_prio][rainbow_prio][2] = 0;
1807 else if(rainbow_prio_test > bg_prio_test && rainbow_prio_test > vdc_prio_test)
1808 VCEPrioMap[bg_prio][vdc_prio][rainbow_prio][2] = 2;
1809 else
1810 VCEPrioMap[bg_prio][vdc_prio][rainbow_prio][2] = 1;
1811 }
1812 }
1813
1814 #ifdef WANT_DEBUGGER
1815 ASpace_Add(KING_GetAddressSpaceBytes, KING_PutAddressSpaceBytes, "kram0", "KRAM Page 0", 19);
1816 ASpace_Add(KING_GetAddressSpaceBytes, KING_PutAddressSpaceBytes, "kram1", "KRAM Page 1", 19);
1817 ASpace_Add(Do16BitGet, Do16BitPut, "vdcvram0", "VDC-A VRAM", 17);
1818 ASpace_Add(Do16BitGet, Do16BitPut, "vdcvram1", "VDC-B VRAM", 17);
1819 ASpace_Add(KING_GetAddressSpaceBytes, KING_PutAddressSpaceBytes, "vce", "VCE Palette RAM", 10);
1820 #endif
1821
1822 SCSICD_Init(SCSICD_PCFX, 3, FXCDDABufs[0]->Buf(), FXCDDABufs[1]->Buf(), 153600 * MDFN_GetSettingUI("pcfx.cdspeed"), 21477273, KING_CDIRQ, KING_StuffSubchannels);
1823 }
1824 catch(...)
1825 {
1826 Cleanup();
1827 throw;
1828 }
1829 }
1830
KING_Close(void)1831 void KING_Close(void)
1832 {
1833 Cleanup();
1834 }
1835
1836
KING_Reset(const v810_timestamp_t timestamp)1837 void KING_Reset(const v810_timestamp_t timestamp)
1838 {
1839 KING_Update(timestamp);
1840
1841 memset(&fx_vce, 0, sizeof(fx_vce));
1842
1843 int32 ltssave = king->lastts;
1844 memset(king, 0, sizeof(king_t));
1845 king->lastts = ltssave;
1846
1847 king->Reg00 = 0;
1848 king->Reg01 = 0;
1849 king->Reg02 = 0;
1850 king->Reg03 = 0;
1851 king->dma_receive_active = false;
1852 king->dma_send_active = false;
1853 king->dma_cycle_counter = 0x7FFFFFFF;
1854
1855
1856 RecalcKRAMPagePtrs();
1857
1858 HPhase = HPHASE_HBLANK_PART1;
1859 HPhaseCounter = 1;
1860 vdc_lb_pos = 0;
1861
1862 memset(vdc_linebuffers, 0, sizeof(vdc_linebuffers));
1863 memset(vdc_linebuffer, 0, sizeof(vdc_linebuffer));
1864 memset(vdc_linebuffer_yuved, 0, sizeof(vdc_linebuffer_yuved));
1865 memset(rainbow_linebuffer, 0, sizeof(rainbow_linebuffer));
1866 memset(bg_linebuffer, 0, sizeof(bg_linebuffer));
1867
1868
1869 king->dma_cycle_counter = 0x7FFFFFFF;
1870 scsicd_ne = 1; // FIXME
1871
1872 RedoKINGIRQCheck();
1873
1874 for(unsigned int x = 0; x < 0x200; x++)
1875 RedoPaletteCache(x);
1876
1877 DoHBlankVCECaching();
1878
1879 SoundBox_SetKINGADPCMControl(0);
1880
1881 SCSICD_Power(timestamp);
1882
1883 memset(king->KRAM, 0xFF, sizeof(king->KRAM));
1884 }
1885
1886
DRAWBG8x1_4(uint32 * target,const uint16 * cg,const uint32 * palette_ptr,const uint32 layer_or)1887 static INLINE void DRAWBG8x1_4(uint32 *target, const uint16 *cg, const uint32 *palette_ptr, const uint32 layer_or)
1888 {
1889 if(*cg >> 14) target[0] = palette_ptr[(*cg >> 14)] | layer_or;
1890 if((*cg >> 12) & 0x3) target[1] = palette_ptr[((*cg >> 12) & 0x3)] | layer_or;
1891 if((*cg >> 10) & 0x3) target[2] = palette_ptr[((*cg >> 10) & 0x3)] | layer_or;
1892 if((*cg >> 8) & 0x3) target[3] = palette_ptr[((*cg >> 8) & 0x3)] | layer_or;
1893 if((*cg >> 6) & 0x3) target[4] = palette_ptr[((*cg >> 6) & 0x3)] | layer_or;
1894 if((*cg >> 4) & 0x3) target[5] = palette_ptr[((*cg >> 4) & 0x3)] | layer_or;
1895 if((*cg >> 2) & 0x3) target[6] = palette_ptr[((*cg >> 2) & 0x3)] | layer_or;
1896 if((*cg >> 0) & 0x3) target[7] = palette_ptr[((*cg >> 0) & 0x3)] | layer_or;
1897 }
1898
DRAWBG8x1_16(uint32 * target,const uint16 * cgptr,const uint32 * palette_ptr,const uint32 layer_or)1899 static INLINE void DRAWBG8x1_16(uint32 *target, const uint16 *cgptr, const uint32 *palette_ptr, const uint32 layer_or)
1900 {
1901 if(cgptr[0] >> 12) target[0] = palette_ptr[((cgptr[0] >> 12))] | layer_or;
1902 if((cgptr[0] >> 8) & 0xF) target[1] = palette_ptr[(((cgptr[0] >> 8) & 0xF))] | layer_or;
1903 if((cgptr[0] >> 4) & 0xF) target[2] = palette_ptr[(((cgptr[0] >> 4) & 0xF))] | layer_or;
1904 if((cgptr[0] >> 0) & 0xF) target[3] = palette_ptr[(((cgptr[0] >> 0) & 0xF))] | layer_or;
1905
1906 if(cgptr[1] >> 12) target[4] = palette_ptr[((cgptr[1] >> 12))] | layer_or;
1907 if((cgptr[1] >> 8) & 0xF) target[5] = palette_ptr[(((cgptr[1] >> 8) & 0xF))] | layer_or;
1908 if((cgptr[1] >> 4) & 0xF) target[6] = palette_ptr[(((cgptr[1] >> 4) & 0xF))] | layer_or;
1909 if((cgptr[1] >> 0) & 0xF) target[7] = palette_ptr[(((cgptr[1] >> 0) & 0xF))] | layer_or;
1910 }
1911
DRAWBG8x1_256(uint32 * target,const uint16 * cgptr,const uint32 * palette_ptr,const uint32 layer_or)1912 static INLINE void DRAWBG8x1_256(uint32 *target, const uint16 *cgptr, const uint32 *palette_ptr, const uint32 layer_or)
1913 {
1914 if(cgptr[0] >> 8) target[0] = palette_ptr[(cgptr[0] >> 0x8)] | layer_or;
1915 if(cgptr[0] & 0xFF) target[1] = palette_ptr[(cgptr[0] & 0xFF)] | layer_or;
1916 if(cgptr[1] >> 8) target[2] = palette_ptr[(cgptr[1] >> 0x8)] | layer_or;
1917 if(cgptr[1] & 0xFF) target[3] = palette_ptr[(cgptr[1] & 0xFF)] | layer_or;
1918 if(cgptr[2] >> 8) target[4] = palette_ptr[(cgptr[2] >> 0x8)] | layer_or;
1919 if(cgptr[2] & 0xFF) target[5] = palette_ptr[(cgptr[2] & 0xFF)] | layer_or;
1920 if(cgptr[3] >> 8) target[6] = palette_ptr[(cgptr[3] >> 0x8)] | layer_or;
1921 if(cgptr[3] & 0xFF) target[7] = palette_ptr[(cgptr[3] & 0xFF)] | layer_or;
1922 }
1923
DRAWBG8x1_64K(uint32 * target,const uint16 * cgptr,const uint32 * palette_ptr,const uint32 layer_or)1924 static INLINE void DRAWBG8x1_64K(uint32 *target, const uint16 *cgptr, const uint32 *palette_ptr, const uint32 layer_or)
1925 {
1926 if(cgptr[0] & 0xFF00) target[0] = ((cgptr[0x0] & 0x00F0) << 8) | ((cgptr[0] & 0x000F)<<4) | ((cgptr[0] & 0xFF00) << 8) | layer_or;
1927 if(cgptr[1] & 0xFF00) target[1] = ((cgptr[0x1] & 0x00F0) << 8) | ((cgptr[1] & 0x000F)<<4) | ((cgptr[1] & 0xFF00) << 8) | layer_or;
1928 if(cgptr[2] & 0xFF00) target[2] = ((cgptr[0x2] & 0x00F0) << 8) | ((cgptr[2] & 0x000F)<<4) | ((cgptr[2] & 0xFF00) << 8) | layer_or;
1929 if(cgptr[3] & 0xFF00) target[3] = ((cgptr[0x3] & 0x00F0) << 8) | ((cgptr[3] & 0x000F)<<4) | ((cgptr[3] & 0xFF00) << 8) | layer_or;
1930 if(cgptr[4] & 0xFF00) target[4] = ((cgptr[0x4] & 0x00F0) << 8) | ((cgptr[4] & 0x000F)<<4) | ((cgptr[4] & 0xFF00) << 8) | layer_or;
1931 if(cgptr[5] & 0xFF00) target[5] = ((cgptr[0x5] & 0x00F0) << 8) | ((cgptr[5] & 0x000F)<<4) | ((cgptr[5] & 0xFF00) << 8) | layer_or;
1932 if(cgptr[6] & 0xFF00) target[6] = ((cgptr[0x6] & 0x00F0) << 8) | ((cgptr[6] & 0x000F)<<4) | ((cgptr[6] & 0xFF00) << 8) | layer_or;
1933 if(cgptr[7] & 0xFF00) target[7] = ((cgptr[0x7] & 0x00F0) << 8) | ((cgptr[7] & 0x000F)<<4) | ((cgptr[7] & 0xFF00) << 8) | layer_or;
1934 }
1935
DRAWBG8x1_16M(uint32 * target,const uint16 * cgptr,const uint32 * palette_ptr,const uint32 layer_or)1936 static INLINE void DRAWBG8x1_16M(uint32 *target, const uint16 *cgptr, const uint32 *palette_ptr, const uint32 layer_or)
1937 {
1938 if(cgptr[0] >> 8) target[0] = ((cgptr[0x0] & 0xFF00) << 8) | (cgptr[1] & 0xFF00) | (cgptr[1] & 0xFF) | layer_or;
1939 if(cgptr[0] & 0xFF) target[1] = ((cgptr[0x0] & 0x00FF) << 16) | (cgptr[1] & 0xFF00) | (cgptr[1] & 0xFF) | layer_or;
1940 if(cgptr[2] >> 8) target[2] = ((cgptr[0x2] & 0xFF00) << 8) | (cgptr[3] & 0xFF00) | (cgptr[3] & 0xFF) | layer_or;
1941 if(cgptr[2] & 0xFF) target[3] = ((cgptr[0x2] & 0x00FF) << 16) | (cgptr[3] & 0xFF00) | (cgptr[3] & 0xFF) | layer_or;
1942 if(cgptr[4] >> 8) target[4] = ((cgptr[0x4] & 0xFF00) << 8) | (cgptr[5] & 0xFF00) | (cgptr[5] & 0xFF) | layer_or;
1943 if(cgptr[4] & 0xFF) target[5] = ((cgptr[0x4] & 0x00FF) << 16) | (cgptr[5] & 0xFF00) | (cgptr[5] & 0xFF) | layer_or;
1944 if(cgptr[6] >> 8) target[6] = ((cgptr[0x6] & 0xFF00) << 8) | (cgptr[7] & 0xFF00) | (cgptr[7] & 0xFF) | layer_or;
1945 if(cgptr[6] & 0xFF) target[7] = ((cgptr[0x6] & 0x00FF) << 16) | (cgptr[7] & 0xFF00) | (cgptr[7] & 0xFF) | layer_or;
1946 }
1947
1948 static bool bgmode_warning = 0; // Debug
1949
1950 #include "king-bgfast.inc"
1951
max(int32 a,int32 b)1952 static INLINE int32 max(int32 a, int32 b)
1953 {
1954 if(a > b)
1955 return(a);
1956
1957 return(b);
1958 }
1959
DrawBG(uint32 * target,int n,bool sub)1960 static void DrawBG(uint32 *target, int n, bool sub)
1961 {
1962 // Size out-of-bounds behaves as if the size is at its minimum, with caveats(TO BE INVESTIGATED).
1963 const uint32 bg_ss_table[0x10] =
1964 {
1965 0x3, 0x3, 0x3, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0x3, 0x3, 0x3, 0x3, 0x3
1966 };
1967
1968 const bool bg_ss_invalid_table[0x10] =
1969 {
1970 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1
1971 };
1972
1973 #if 0
1974 const uint32 cg_per_mode[0x8] =
1975 {
1976 0, // Invalid mode
1977 1, // 2-bit mode
1978 2, // 4-bit mode
1979 4, // 8-bit mode
1980 8, // 16-bit mode
1981 8, // 16-bit mode
1982 8, // 16-bit mode
1983 8, // 16-bit mode
1984 };
1985 #endif
1986 const uint32 layer_or = (LAYER_BG0 + n) << 28;
1987
1988 const uint32 palette_offset = ((fx_vce.palette_offset[1 + (n >> 1)] >> ((n & 1) ? 8 : 0)) << 1) & 0x1FF;
1989 const uint32 *palette_ptr = &vce_rendercache.palette_table_cache[palette_offset];
1990 const uint32 bat_and_cg_page = (king->PageSetting & 0x0010) ? 1 : 0;
1991
1992 const uint16 bgmode = (king->bgmode >> (n * 4)) & 0xF;
1993 const bool endless = (king->BGScrollMode >> n) & 0x1;
1994 const uint32 XScroll = sign_x_to_s32((n ? 10 : 11), king->BGXScroll[n]);
1995 const uint32 YScroll = sign_x_to_s32((n ? 10 : 11), king->BGYScroll[n]);
1996
1997 const uint32 YOffset = (YScroll + (fx_vce.raster_counter - 22)) & 0xFFFF;
1998
1999 const uint32 bat_offset = king->BGBATAddr[n] * 1024;
2000 const uint32 bat_sub_offset = n ? bat_offset : (king->BG0SubBATAddr * 1024);
2001 const uint16 *bat_base = &king->KRAM[bat_and_cg_page][bat_offset & 0x20000];
2002 const uint16 *bat_sub_base = &king->KRAM[bat_and_cg_page][bat_sub_offset & 0x20000];
2003
2004 const uint32 cg_offset = king->BGCGAddr[n] * 1024;
2005 const uint32 cg_sub_offset = n ? cg_offset : (king->BG0SubCGAddr * 1024);
2006 const uint16 *cg_base = &king->KRAM[bat_and_cg_page][cg_offset & 0x20000];
2007 const uint16 *cg_sub_base = &king->KRAM[bat_and_cg_page][cg_sub_offset & 0x20000];
2008
2009 const int bat_bitsize_mask = 0x7FF >> 3;
2010
2011 const uint32 bat_width_shift = bg_ss_table[(king->BGSize[n] & 0xF0) >> 4];
2012 const bool bat_width_invalid = bg_ss_invalid_table[(king->BGSize[n] & 0xF0) >> 4];
2013 const uint32 bat_width = (1 << bat_width_shift) >> 3;
2014
2015 const int32 bat_height_shift = bg_ss_table[king->BGSize[n] & 0x0F];
2016 //const bool bat_height_invalid = bg_ss_invalid_table[king->BGSize[n] & 0x0F];
2017 const int32 bat_height = (1 << bat_height_shift) >> 3;
2018
2019 const bool bat_sub_width_invalid = n ? bat_width_invalid : bg_ss_invalid_table[(king->BGSize[n] & 0xF000) >> 12];
2020 const uint32 bat_sub_width_shift = n ? bat_width_shift : bg_ss_table[(king->BGSize[n] & 0xF000) >> 12];
2021 const uint32 bat_sub_width = (1 << bat_sub_width_shift) >> 3;
2022 const uint32 bat_sub_width_mask = bat_sub_width - 1;
2023 const uint32 bat_sub_width_test = endless ? (bat_bitsize_mask + 1) : max(bat_width, bat_sub_width);
2024
2025 const int32 bat_sub_height_shift = n ? bat_height_shift : bg_ss_table[(king->BGSize[n] & 0x0F00) >> 8];
2026 const int32 bat_sub_height = (1 << bat_sub_height_shift) >> 3;
2027 const int32 bat_sub_height_mask = bat_sub_height - 1;
2028 const int32 bat_sub_height_test = endless ? (bat_bitsize_mask + 1) : max(bat_height, bat_sub_height);
2029
2030 uint16 cg_mask[8];
2031 uint16 cg_remap[8];
2032 bool cg_ofbat[8];
2033
2034 uint16 cg_sub_mask[8];
2035 uint16 cg_sub_remap[8];
2036 bool cg_sub_ofbat[8];
2037
2038 bool BATFetchCycle = false;
2039 bool BATSubFetchCycle = false;
2040
2041 const bool rotate_mode = (n == 0) && (king->priority & 0x1000);
2042
2043 // If the bg mode is invalid, don't draw this layer, duuhhhh
2044 if(!(bgmode & 0x7))
2045 return;
2046
2047 if((bgmode & 0x7) >= 6)
2048 {
2049 if(!bgmode_warning)
2050 {
2051 printf("Unsupported KING BG Mode for KING BG %d: %02x\n", n, bgmode);
2052 bgmode_warning = true;
2053 }
2054 return;
2055 }
2056
2057 memset(cg_mask, 0, sizeof(cg_mask));
2058 memset(cg_remap, 0, sizeof(cg_remap));
2059 memset(cg_ofbat, 0, sizeof(cg_ofbat));
2060 memset(cg_sub_mask, 0, sizeof(cg_sub_mask));
2061 memset(cg_sub_remap, 0, sizeof(cg_sub_remap));
2062 memset(cg_sub_ofbat, 0, sizeof(cg_sub_ofbat));
2063
2064 if(king->MPROGControl & 0x1)
2065 {
2066 int remap_thing = 0;
2067 int remap_sub_thing = 0;
2068
2069 for(int x = 0; x < 8; x++)
2070 {
2071 uint16 mpd;
2072
2073 // Forcing CG and BAT to 0 if the affine bit != rotate_mode is not technically correct.
2074 // If there is a mismatch, it's more likely the effective CG and BAT address for the pixel/segment
2075 // being drawn won't be calculated correctly, likely being just the initial offsets.
2076
2077 mpd = king->MPROGData[((cg_offset & 0x20000) ? 0x8 : 0x0) + x];
2078 if(((mpd >> 6) & 0x3) == n && !(mpd & 0x100) && !(mpd & 0x010))
2079 {
2080 cg_mask[remap_thing] = 0xFFFF;
2081 cg_remap[remap_thing] = mpd & 0x7;
2082 cg_ofbat[remap_thing] = mpd & 0x8;
2083
2084 if((bool)(mpd & 0x20) != rotate_mode)
2085 {
2086 KINGDBG("Affine bit != rotate_mode?");
2087 cg_mask[remap_thing] = 0;
2088 }
2089 remap_thing++;
2090 }
2091
2092 mpd = king->MPROGData[((cg_sub_offset & 0x20000) ? 0x8 : 0x0) + x];
2093 if(((mpd >> 6) & 0x3) == n && !(mpd & 0x100) && !(mpd & 0x010))
2094 {
2095 cg_sub_mask[remap_sub_thing] = 0xFFFF;
2096 cg_sub_remap[remap_sub_thing] = mpd & 0x7;
2097 cg_sub_ofbat[remap_sub_thing] = mpd & 0x8;
2098
2099 if((bool)(mpd & 0x20) != rotate_mode)
2100 {
2101 KINGDBG("Affine bit != rotate_mode? (SUB)");
2102 cg_sub_mask[remap_sub_thing] = 0;
2103 }
2104 remap_sub_thing++;
2105 }
2106 }
2107
2108 for(int x = 0; x < 8; x++)
2109 {
2110 uint16 mpd;
2111
2112 mpd = king->MPROGData[((bat_offset & 0x20000) ? 0x8 : 0x0) + x];
2113 if(((mpd >> 6) & 0x3) == n && !(mpd & 0x100) && (mpd & 0x010) && (bool)(mpd & 0x020) == rotate_mode)
2114 BATFetchCycle = true;
2115
2116 mpd = king->MPROGData[((bat_sub_offset & 0x20000) ? 0x8 : 0x0) + x];
2117 if(((mpd >> 6) & 0x3) == n && !(mpd & 0x100) && (mpd & 0x010) && (bool)(mpd & 0x020) == rotate_mode)
2118 BATSubFetchCycle = true;
2119 }
2120 }
2121
2122 int bat_y = (YOffset >> 3) & bat_bitsize_mask;
2123 uint32 bat_x = (XScroll >> 3) & bat_bitsize_mask;
2124 int ysmall = YOffset & 0x7;
2125
2126 const uint32 bat_invalid_y_mask = bat_width_invalid ? 0 : 0xFFFFFFFF;
2127 const uint32 bat_invalid_sub_y_mask = bat_sub_width_invalid ? 0 : 0xFFFFFFFF;
2128
2129 if(rotate_mode)
2130 target += 8;
2131 else
2132 target += 8 - (XScroll & 0x7);
2133
2134
2135 {
2136 int32 wmul = (1 << bat_width_shift), wmask = ((1 << bat_height_shift) - 1) & bat_invalid_y_mask;
2137 int32 sexy_y_pos = (YOffset & wmask) * wmul;
2138
2139 int32 wmul_sub = (1 << bat_sub_width_shift), wmask_sub = ((1 << bat_sub_height_shift) - 1) & bat_invalid_sub_y_mask;
2140 int32 sexy_y_sub_pos = (YOffset & wmask_sub) * wmul_sub;
2141
2142
2143 #define ROTCODE_PRE \
2144 const int32 bat_width_mask = endless ? (bat_width - 1) : 0xFFFF; \
2145 const int32 bat_height_mask = endless ? (bat_height - 1) : 0xFFFF; \
2146 int32 a, b, c, d; \
2147 int32 raw_x_coord = (int32)sign_11_to_s16(XScroll) - (int16)king->BGAffinCenterX; \
2148 int32 raw_y_coord = fx_vce.raster_counter + (int32)sign_11_to_s16(YScroll) - 22 - (int16)king->BGAffinCenterY; \
2149 int32 xaccum; \
2150 int32 yaccum; \
2151 \
2152 a = (int16)king->BGAffinA; \
2153 b = (int16)king->BGAffinB; \
2154 c = (int16)king->BGAffinC; \
2155 d = (int16)king->BGAffinD; \
2156 \
2157 xaccum = raw_x_coord * a + raw_y_coord * b; \
2158 yaccum = raw_y_coord * d + raw_x_coord * c; \
2159 xaccum += (int16)king->BGAffinCenterX << 8; \
2160 yaccum += (int16)king->BGAffinCenterY << 8; \
2161
2162 #define ROTCODE_LOOP_PRE \
2163 for(int x = 0; x < 256; x++) \
2164 { \
2165 uint16 new_x = (xaccum >> 8); \
2166 uint16 new_y = (yaccum >> 8); \
2167 const uint16 *cgptr; \
2168 bat_x = (new_x >> 3) & bat_width_mask; \
2169 bat_y = (new_y >> 3) & bat_height_mask; \
2170 ysmall = new_y & 0x7;
2171
2172 #define ROTCODE_LOOP_POST \
2173 xaccum += a; \
2174 yaccum += c; \
2175 }
2176
2177 if((bgmode & 0x7) == BGMODE_4 && rotate_mode)
2178 {
2179 ROTCODE_PRE;
2180
2181 ROTCODE_LOOP_PRE;
2182 uint32 pbn = 0;
2183 if(bgmode & 0x8)
2184 {
2185 uint16 bat = bat_base[(bat_offset + (bat_x + ((bat_y << bat_width_shift) >> 3) )) & 0x1FFFF];
2186 pbn = ((bat >> 12) << 2);
2187 bat &= 0x0FFF;
2188 cgptr = &cg_base[(cg_offset + (bat * 8) + ysmall) & 0x1FFFF];
2189 }
2190 else
2191 {
2192 cgptr = &cg_base[(cg_offset + bat_x + ((new_y & wmask) * wmul / 8)) & 0x1FFFF];
2193 }
2194 uint8 ze_cg = (cgptr[0] >> ((7 - (new_x & 7)) << 1)) & 0x03;
2195
2196 if(endless || (bat_x < bat_width && bat_y < bat_height))
2197 {
2198 if(ze_cg) target[x] = palette_ptr[pbn + ze_cg] | layer_or;
2199 }
2200 ROTCODE_LOOP_POST;
2201 }
2202 else if((bgmode & 0x7) == BGMODE_16 && rotate_mode)
2203 {
2204 ROTCODE_PRE;
2205
2206 ROTCODE_LOOP_PRE;
2207 uint32 pbn = 0;
2208
2209 if(bgmode & 0x8)
2210 {
2211 uint16 bat = bat_base[(bat_offset + (bat_x + ((bat_y << bat_width_shift) >> 3) )) & 0x1FFFF];
2212 pbn = ((bat >> 12) << 4);
2213 bat &= 0x0FFF;
2214 cgptr = &cg_base[(cg_offset + (bat * 16) + ysmall * 2) & 0x1FFFF];
2215 }
2216 else
2217 {
2218 cgptr = &cg_base[(cg_offset + (bat_x * 2) + ((new_y & wmask) * wmul / 4)) & 0x1FFFF];
2219 }
2220 uint8 ze_cg = (cgptr[(new_x >> 2) & 0x1] >> ((3 - (new_x & 3)) << 2)) & 0x0F;
2221
2222 if(endless || (bat_x < bat_width && bat_y < bat_height))
2223 {
2224 if(ze_cg) target[x] = palette_ptr[pbn + ze_cg] | layer_or;
2225 }
2226 ROTCODE_LOOP_POST;
2227 }
2228 else if((bgmode & 0x7) == BGMODE_256 && rotate_mode)
2229 {
2230 ROTCODE_PRE;
2231
2232 ROTCODE_LOOP_PRE;
2233 if(bgmode & 0x8)
2234 {
2235 uint16 bat = bat_base[(bat_offset + (bat_x + ((bat_y << bat_width_shift) >> 3) )) & 0x1FFFF];
2236 cgptr = &cg_base[(cg_offset + (bat * 32) + ysmall * 4) & 0x1FFFF];
2237 }
2238 else
2239 {
2240 cgptr = &cg_base[(cg_offset + (bat_x * 4) + ((new_y & wmask) * wmul / 2)) & 0x1FFFF];
2241 }
2242 uint8 ze_cg = cgptr[(new_x >> 1) & 0x3] >> (((new_x & 1) ^ 1) << 3);
2243
2244 if(endless || (bat_x < bat_width && bat_y < bat_height))
2245 {
2246 if(ze_cg) target[x] = palette_ptr[ze_cg] | layer_or;
2247 }
2248 ROTCODE_LOOP_POST;
2249 }
2250 else if((bgmode & 0x7) == BGMODE_64K && rotate_mode)
2251 {
2252 ROTCODE_PRE;
2253 ROTCODE_LOOP_PRE;
2254 if(bgmode & 0x8)
2255 {
2256 uint16 bat = bat_base[(bat_offset + (bat_x + ((bat_y << bat_width_shift) >> 3) )) & 0x1FFFF];
2257 cgptr = &cg_base[(cg_offset + (bat * 64) + ysmall * 8) & 0x1FFFF];
2258 }
2259 else
2260 {
2261 cgptr = &cg_base[(cg_offset + (bat_x * 8) + ((new_y & wmask) * wmul)) & 0x1FFFF];
2262 }
2263 uint16 ze_cg = cgptr[new_x & 0x7];
2264
2265 if(endless || (bat_x < bat_width && bat_y < bat_height))
2266 {
2267 if(ze_cg >> 8) target[x] = ((ze_cg & 0x00F0) << 8) | ((ze_cg & 0x000F)<<4) | ((ze_cg & 0xFF00) << 8) | layer_or;
2268 }
2269 ROTCODE_LOOP_POST;
2270 }
2271 else switch(bgmode & 0x7)
2272 {
2273 #define DRAWBG8x1_MAC(cg_needed, blit_suffix, pbn_arg) \
2274 for(int x = 0; x < 256 + 8; x+= 8) \
2275 { \
2276 if(bat_x < bat_width && bat_y < bat_height) \
2277 { \
2278 uint32 eff_bat_loc = bat_offset; \
2279 uint16 bat = 0; \
2280 uint16 pbn MDFN_NOWARN_UNUSED = 0; \
2281 const uint16 *cgptr[2]; \
2282 uint16 cg[cg_needed]; \
2283 \
2284 if(bgmode & 0x8) \
2285 eff_bat_loc += bat_x + (((bat_y & bat_invalid_y_mask) << bat_width_shift) >> 3); \
2286 \
2287 eff_bat_loc &= 0x1FFFF; \
2288 \
2289 if(BATFetchCycle) \
2290 bat = bat_base[eff_bat_loc]; \
2291 \
2292 if(bgmode & 0x08) \
2293 pbn = bat >> 12; \
2294 bat &= 0xFFF; \
2295 \
2296 cgptr[0] = &cg_base[(cg_offset + (bat_x * cg_needed) + sexy_y_pos) \
2297 & 0x1FFFF]; \
2298 cgptr[1] = &cg_base[(cg_offset + (bat * 8 * cg_needed) + ysmall * cg_needed) \
2299 & 0x1FFFF]; \
2300 \
2301 for(int cow = 0; cow < cg_needed; cow++) \
2302 cg[cow] = cgptr[cg_ofbat[cow]][cg_remap[cow]] & cg_mask[cow]; \
2303 \
2304 DRAWBG8x1_##blit_suffix(target + x, cg, palette_ptr + pbn_arg, layer_or); \
2305 } \
2306 else if(bat_x < bat_sub_width_test && bat_y < bat_sub_height_test) \
2307 { \
2308 uint32 eff_bat_loc = bat_sub_offset; \
2309 uint16 bat = 0; \
2310 uint16 pbn MDFN_NOWARN_UNUSED = 0; \
2311 const uint16 *cgptr[2]; \
2312 uint16 cg[cg_needed]; \
2313 \
2314 if(bgmode & 0x8) \
2315 eff_bat_loc += (bat_x & bat_sub_width_mask) + (((bat_y & bat_invalid_sub_y_mask & bat_sub_height_mask) << bat_sub_width_shift) >> 3); \
2316 \
2317 eff_bat_loc &= 0x1FFFF; \
2318 \
2319 if(BATSubFetchCycle) \
2320 bat = bat_sub_base[eff_bat_loc]; \
2321 \
2322 if(bgmode & 0x08) \
2323 pbn = bat >> 12; \
2324 bat &= 0xFFF; \
2325 \
2326 cgptr[0] = &cg_sub_base[(cg_sub_offset + ((bat_x & bat_sub_width_mask) * cg_needed) + sexy_y_sub_pos) \
2327 & 0x1FFFF]; \
2328 cgptr[1] = &cg_sub_base[(cg_sub_offset + (bat * 8 * cg_needed) + ysmall * cg_needed) \
2329 & 0x1FFFF]; \
2330 \
2331 for(int cow = 0; cow < cg_needed; cow++) \
2332 cg[cow] = cgptr[cg_sub_ofbat[cow]][cg_sub_remap[cow]] & cg_sub_mask[cow]; \
2333 \
2334 DRAWBG8x1_##blit_suffix(target + x, cg, palette_ptr + pbn_arg, layer_or); \
2335 } \
2336 bat_x = (bat_x + 1) & bat_bitsize_mask; \
2337 }
2338
2339
2340 case 0x01: // 4 color, 1/4 byte per pixel :b
2341 sexy_y_pos >>= 3;
2342 sexy_y_sub_pos >>= 3;
2343
2344 DRAWBG8x1_MAC(1, 4, (pbn << 2));
2345 break;
2346
2347 case 0x02: // 16 color, 1/2 byte per pixel
2348 sexy_y_pos >>= 2;
2349 sexy_y_sub_pos >>= 2;
2350
2351 DRAWBG8x1_MAC(2, 16, (pbn << 4));
2352 break;
2353
2354 case 0x03: // 256 color, 1 byte per pixel palettized - OK
2355 sexy_y_pos >>= 1;
2356 sexy_y_sub_pos >>= 1;
2357
2358 DRAWBG8x1_MAC(4, 256, 0);
2359 break;
2360
2361 case 0x04: // 64K color, 2 bytes per pixel - OK
2362 DRAWBG8x1_MAC(8, 64K, 0);
2363 break;
2364
2365 case 0x05: // 16M color, 2 bytes per pixel - OK
2366 DRAWBG8x1_MAC(8, 16M, 0);
2367 break;
2368 #if 0
2369 case BGMODE_64K_EXTDOT:
2370 break;
2371
2372 case BGMODE_16M_EXTDOT:
2373 {
2374 uint32 fat_bat = ((YOffset & ((1 << bat_height_shift) - 1)) << bat_width_shift) + (((XScroll & ~ 7) & ((1 << bat_width_shift) - 1));
2375 }
2376 break;
2377 #endif
2378 }
2379 }
2380 }
2381
2382 static int16 UVLUT[65536][3];
2383 static uint8 RGBDeflower[1152]; // 0 is at 384
2384 static uint32 CbCrLUT[65536];
2385
RebuildUVLUT(const MDFN_PixelFormat & format)2386 static void RebuildUVLUT(const MDFN_PixelFormat &format)
2387 {
2388 for(int ur = 0; ur < 256; ur++)
2389 {
2390 for(int vr = 0; vr < 256; vr++)
2391 {
2392 int r, g, b;
2393 int u, v;
2394
2395 u = ur - 128;
2396 v = vr - 128;
2397
2398 // FIXME: Use lrint() ?
2399 r = (int)(0 - 0.000039457070707 * u + 1.139827967171717 * v);
2400 g = (int)(0 - 0.394610164141414 * u - 0.580500315656566 * v);
2401 b = (int)(0 + 2.031999684343434 * u - 0.000481376262626 * v);
2402
2403 UVLUT[vr + ur * 256][0] = r;
2404 UVLUT[vr + ur * 256][1] = g;
2405 UVLUT[vr + ur * 256][2] = b;
2406
2407 CbCrLUT[vr + ur * 256] = clamp_to_u8(128 + ((r * -9699 + g * -19071 + b * 28770) >> 16)) << format.Cbshift;
2408 CbCrLUT[vr + ur * 256] |= clamp_to_u8(128 + ((r * 28770 + g * -24117 + b * -4653) >> 16)) << format.Crshift;
2409
2410 //printf("%d %d %d, %08x\n", r, g, b, CbCrLUT[vr + ur * 256]);
2411 }
2412 }
2413 for(int x = 0; x < 1152; x++)
2414 {
2415 if(x < 384) RGBDeflower[x] = 0;
2416 else if(x > (384 + 255)) RGBDeflower[x] = 255;
2417 else
2418 RGBDeflower[x] = x - 384;
2419 }
2420 }
2421
2422 // FIXME
2423 static int rs, gs, bs;
YUV888_TO_RGB888(uint32 yuv)2424 static uint32 INLINE YUV888_TO_RGB888(uint32 yuv)
2425 {
2426 int32 r, g, b;
2427 uint8 y = yuv >> 16;
2428
2429 r = y + UVLUT[yuv & 0xFFFF][0];
2430 g = y + UVLUT[yuv & 0xFFFF][1];
2431 b = y + UVLUT[yuv & 0xFFFF][2];
2432
2433 r = clamp_to_u8(r);
2434 g = clamp_to_u8(g);
2435 b = clamp_to_u8(b);
2436
2437 return((r << rs) | (g << gs) | (b << bs));
2438 }
2439
YUV888_TO_PF(const uint32 yuv,const MDFN_PixelFormat & pf,const uint8 a=0x00)2440 static uint32 INLINE YUV888_TO_PF(const uint32 yuv, const MDFN_PixelFormat &pf, const uint8 a = 0x00)
2441 {
2442 const uint8 y = yuv >> 16;
2443 uint8 r, g, b;
2444
2445 r = clamp_to_u8((int32)(y + UVLUT[yuv & 0xFFFF][0]));
2446 g = clamp_to_u8((int32)(y + UVLUT[yuv & 0xFFFF][1]));
2447 b = clamp_to_u8((int32)(y + UVLUT[yuv & 0xFFFF][2]));
2448
2449 return pf.MakeColor(r, g, b, a);
2450 }
2451
YUV888_TO_YCbCr888(uint32 yuv)2452 static uint32 INLINE YUV888_TO_YCbCr888(uint32 yuv)
2453 {
2454 uint32 y;
2455
2456 y = 16 + ((((yuv >> 16) & 0xFF) * 220) >> 8);
2457
2458 return(y | CbCrLUT[yuv & 0xFFFF]);
2459 }
2460
2461 // FIXME:
2462 //static unsigned int lines_per_frame; //= (fx_vce.picture_mode & 0x1) ? 262 : 263;
2463 static VDC **vdc_chips;
2464 static MDFN_Surface *surface;
2465 static MDFN_Rect *DisplayRect;
2466 static int32 *LineWidths;
2467 static int skip;
2468
KING_StartFrame(VDC ** arg_vdc_chips,EmulateSpecStruct * espec)2469 void KING_StartFrame(VDC **arg_vdc_chips, EmulateSpecStruct *espec)
2470 {
2471 MDFN_IEN_PCFX::vdc_chips = arg_vdc_chips;
2472 MDFN_IEN_PCFX::surface = espec->surface;
2473 MDFN_IEN_PCFX::DisplayRect = &espec->DisplayRect;
2474 MDFN_IEN_PCFX::LineWidths = espec->LineWidths;
2475 MDFN_IEN_PCFX::skip = espec->skip;
2476
2477 //MDFN_DispMessage("P0:%06x P1:%06x; I0: %06x I1: %06x", king->ADPCMPlayAddress[0], king->ADPCMPlayAddress[1], king->ADPCMIntermediateAddress[0] << 6, king->ADPCMIntermediateAddress[1] << 6);
2478 //MDFN_DispMessage("%d %d\n", SCSICD_GetACK(), SCSICD_GetREQ());
2479
2480 // For the case of interlaced mode(clear ~0 state)
2481 LineWidths[0] = 0;
2482
2483 // These 2 should be overwritten in the big loop below.
2484 DisplayRect->x = 0;
2485 DisplayRect->w = 256;
2486
2487 DisplayRect->y = MDFN_GetSettingUI("pcfx.slstart");
2488 DisplayRect->h = MDFN_GetSettingUI("pcfx.slend") - DisplayRect->y + 1;
2489
2490 if(fx_vce.frame_interlaced)
2491 {
2492 skip = false;
2493
2494 espec->InterlaceOn = true;
2495 espec->InterlaceField = fx_vce.odd_field;
2496 DisplayRect->y *= 2;
2497 DisplayRect->h *= 2;
2498 }
2499 }
2500
2501 static int rb_type;
2502 // unsigned int width = (fx_vce.picture_mode & 0x08) ? 341 : 256;
2503
DrawActive(void)2504 static void DrawActive(void)
2505 {
2506 rb_type = -1;
2507
2508 #ifdef WANT_DEBUGGER
2509 if(GfxDecode_Buf && GfxDecode_Line == (int32)fx_vce.raster_counter)
2510 DoGfxDecode();
2511 #endif
2512
2513 if(fx_vce.raster_counter == king->RAINBOWTransferStartPosition && (king->RAINBOWTransferControl & 1))
2514 {
2515 king->RAINBOWStartPending = true;
2516
2517 //printf("Rainbow start pending: line=%d, busycount=%d, blockcount=%d\n", fx_vce.raster_counter, king->RAINBOWBusyCount, king->RAINBOWBlockCount);
2518
2519 //if(fx_vce.raster_counter == 262)
2520 // puts("MOOO");
2521 }
2522
2523 if(fx_vce.raster_counter < 262)
2524 {
2525 if(king->RAINBOWBusyCount)
2526 {
2527 king->RAINBOWBusyCount--;
2528 if(!king->RAINBOWBusyCount)
2529 RAINBOW_SwapBuffers();
2530 }
2531
2532 if(!king->RAINBOWBusyCount)
2533 {
2534 bool WantDecode = false;
2535 bool FirstDecode = false;
2536
2537 if(!king->RAINBOWBlockCount && king->RAINBOWStartPending)
2538 {
2539 //printf("Rainbow start real: %d %d\n", fx_vce.raster_counter, king->RAINBOWTransferBlockCount);
2540 king->RAINBOWBlockCount = king->RAINBOWTransferBlockCount;
2541 if(king->RAINBOWBlockCount)
2542 {
2543 king->RAINBOWKRAMReadPos = king->RAINBOWKRAMA << 1;
2544 FirstDecode = true;
2545 }
2546 }
2547
2548 if(king->RAINBOWBlockCount)
2549 {
2550 king->RAINBOWBlockCount--;
2551 WantDecode = true;
2552 }
2553
2554 if(WantDecode)
2555 {
2556 king->RAINBOWBusyCount = 16;
2557
2558 if(fx_vce.raster_counter == 262)
2559 king->RAINBOWBusyCount++;
2560
2561 // If we ever change the emulation time range from the current 0 through 262/263, we will need to readjust this
2562 // statement to prevent the previous frame's skip value to mess up the current frame's graphics data, since
2563 // RAINBOW data is delayed by 16 scanlines from when it's decoded(16 + 15 maximum delay).
2564 RAINBOW_DecodeBlock(FirstDecode, skip && fx_vce.raster_counter < 246);
2565 }
2566 }
2567
2568 rb_type = RAINBOW_FetchRaster(skip ? NULL : rainbow_linebuffer, LAYER_RAINBOW << 28, &vce_rendercache.palette_table_cache[((fx_vce.palette_offset[3] >> 0) & 0xFF) << 1]);
2569
2570 king->RAINBOWStartPending = false;
2571 } // end if(fx_vce.raster_counter < 262)
2572
2573 if(fx_vce.raster_counter >= 22 && fx_vce.raster_counter < 262)
2574 {
2575 if(!skip)
2576 {
2577 if(rb_type == 1) // YUV
2578 {
2579 // Only chroma key when we're not in 7.16MHz pixel mode
2580 if(!(fx_vce.picture_mode & 0x08))
2581 {
2582 const unsigned int ymin = fx_vce.ChromaKeyY & 0xFF;
2583 const unsigned int ymax = fx_vce.ChromaKeyY >> 8;
2584 const unsigned int umin = fx_vce.ChromaKeyU & 0xFF;
2585 const unsigned int umax = fx_vce.ChromaKeyU >> 8;
2586 const unsigned int vmin = fx_vce.ChromaKeyV & 0xFF;
2587 const unsigned int vmax = fx_vce.ChromaKeyV >> 8;
2588
2589 if((fx_vce.ChromaKeyY | fx_vce.ChromaKeyU | fx_vce.ChromaKeyV) == 0)
2590 {
2591 //puts("Opt: 0 chroma key");
2592 for(int x = 0; x < 256; x++)
2593 {
2594 if(!(rainbow_linebuffer[x] & 0xFFFFFF))
2595 rainbow_linebuffer[x] = 0;
2596 }
2597 }
2598 else if(ymin == ymax && umin == umax && vmin == vmax)
2599 {
2600 const uint32 compare_color = (ymin << 16) | (umin << 8) | (vmin << 0);
2601
2602 //puts("Opt: Single color chroma key");
2603
2604 for(int x = 0; x < 256; x++)
2605 {
2606 if((rainbow_linebuffer[x] & 0xFFFFFF) == compare_color)
2607 rainbow_linebuffer[x] = 0;
2608 }
2609 }
2610 else if(ymin <= ymax && umin <= umax && vmin <= vmax)
2611 {
2612 const uint32 yv_min_sub = (ymin << 16) | vmin;
2613 const uint32 u_min_sub = umin << 8;
2614 const uint32 yv_max_add = ((0xFF - ymax) << 16) | (0xFF - vmax);
2615 const uint32 u_max_add = (0xFF - umax) << 8;
2616
2617 for(int x = 0; x < 256; x++)
2618 {
2619 const uint32 pixel = rainbow_linebuffer[x];
2620 const uint32 yv = pixel & 0xFF00FF;
2621 const uint32 u = pixel & 0x00FF00;
2622 uint32 testie;
2623
2624 testie = ((yv - yv_min_sub) | (yv + yv_max_add)) & 0xFF00FF00;
2625 testie |= ((u - u_min_sub) | (u + u_max_add)) & 0x00FF00FF;
2626
2627 if(!testie)
2628 rainbow_linebuffer[x] = 0;
2629 }
2630 }
2631 else
2632 {
2633 //puts("Opt: color keying off\n");
2634 }
2635 }
2636 }
2637
2638 /*
2639 4 = Foremost
2640 1 = Hindmost
2641 0 = Hidden
2642 */
2643
2644 MDFN_FastArraySet(bg_linebuffer + 8, 0, 256);
2645
2646 // Only bother to draw the BGs if the microprogram is enabled.
2647 if(king->MPROGControl & 0x1)
2648 {
2649 for(int prio = 1; prio <= 7; prio++)
2650 {
2651 for(int x = 0; x < 4; x++)
2652 {
2653 int thisprio = (king->priority >> (x * 3)) & 0x7;
2654
2655 if(BGLayerDisable & (1 << x)) continue;
2656
2657 if(thisprio == prio)
2658 {
2659 //if(fx_vce.raster_counter == 50)
2660 // CanDrawBG_Fast(x);
2661
2662 // TODO/FIXME: TEST MORE
2663 if(CanDrawBG_Fast(x)) // && (rand() & 1))
2664 DrawBG_Fast(bg_linebuffer, x);
2665 else
2666 DrawBG(bg_linebuffer, x, 0);
2667 }
2668 }
2669 }
2670 }
2671
2672 } // end if(!skip)
2673 } // end if(fx_vce.raster_counter >= 22 && fx_vce.raster_counter < 262)
2674 }
2675
VDC_PIXELMIX(bool SPRCOMBO_ON,bool BGCOMBO_ON)2676 static INLINE void VDC_PIXELMIX(bool SPRCOMBO_ON, bool BGCOMBO_ON)
2677 {
2678 static const uint32 vdc_layer_num[2] = { LAYER_VDC_BG << 28, LAYER_VDC_SPR << 28};
2679 const uint32 vdc_poffset[2] = {
2680 (((uint32)fx_vce.palette_offset[0] >> 0) & 0xFF) << 1, // BG
2681 (((uint32)fx_vce.palette_offset[0] >> 8) & 0xFF) << 1 // SPR
2682 };
2683
2684 const int width = fx_vce.dot_clock ? 342 : 256; // 342, not 341, to prevent garbage pixels in high dot clock mode.
2685
2686 for(int x = 0; x < width; x++)
2687 {
2688 const uint32 zort[2] = { vdc_linebuffers[0][x], vdc_linebuffers[1][x] };
2689 uint32 tmp_pixel;
2690
2691 /* SPR combination */
2692 if(SPRCOMBO_ON && (zort[1] & 0x18F) > 0x180)
2693 tmp_pixel = (zort[1] & 0xF) | ((zort[0] & 0xF) << 4) | 0x100;
2694 /* BG combination */
2695 else if(BGCOMBO_ON && ((zort[1] ^ 0x100) & 0x18F) > 0x180)
2696 tmp_pixel = (zort[1] & 0xF) | ((zort[0] & 0xF) << 4);
2697 else
2698 tmp_pixel = (zort[1] & 0xF) ? zort[1] : zort[0];
2699
2700 vdc_linebuffer[x] = tmp_pixel;
2701 vdc_linebuffer_yuved[x] = 0;
2702 if(tmp_pixel & 0xF)
2703 vdc_linebuffer_yuved[x] = vce_rendercache.palette_table_cache[(tmp_pixel & 0xFF) + vdc_poffset[(tmp_pixel >> 8) & 1]] | vdc_layer_num[(tmp_pixel >> 8) & 1];
2704 }
2705 }
2706
MixVDC(void)2707 static NO_INLINE void MixVDC(void)
2708 {
2709 // Optimization for when both layers are disabled in the VCE.
2710 if(!vce_rendercache.LayerPriority[LAYER_VDC_BG] && !vce_rendercache.LayerPriority[LAYER_VDC_SPR])
2711 {
2712 MDFN_FastArraySet(vdc_linebuffer_yuved, 0, 512);
2713 }
2714 else switch(fx_vce.picture_mode & 0xC0)
2715 {
2716 case 0x00: VDC_PIXELMIX(0, 0); break; // None on
2717 case 0x40: VDC_PIXELMIX(0, 1); break; // BG combo on
2718 case 0x80: VDC_PIXELMIX(1, 0); break; // SPR combo on
2719 case 0xC0: VDC_PIXELMIX(1, 1); break; // Both on
2720 }
2721 }
2722
2723
MixLayers(void)2724 static void MixLayers(void)
2725 {
2726 uint32 *pXBuf = surface->pixels;
2727
2728 // Now we have to mix everything together... I'm scared, mommy.
2729 // We have, vdc_linebuffer[0] and bg_linebuffer
2730 // Which layer is specified in bits 28-31(check the enum earlier on)
2731 uint32 priority_remap[8];
2732 uint32 ble_cache[8];
2733 bool ble_cache_any = false;
2734
2735 for(int n = 0; n < 8; n++)
2736 {
2737 priority_remap[n] = vce_rendercache.LayerPriority[n];
2738 //printf("%d: %d\n", n, priority_remap[n]);
2739 }
2740
2741 // Rainbow layer disabled?
2742 if(rb_type == -1 || RAINBOWLayerDisable)
2743 priority_remap[LAYER_RAINBOW] = 0;
2744
2745 ble_cache[LAYER_NONE] = 0;
2746 for(int x = 0; x < 4; x++)
2747 ble_cache[LAYER_BG0 + x] = (vce_rendercache.BLE >> (4 + x * 2)) & 0x3;
2748
2749 ble_cache[LAYER_VDC_BG] = (vce_rendercache.BLE >> 0) & 0x3;
2750 ble_cache[LAYER_VDC_SPR] = (vce_rendercache.BLE >> 2) & 0x3;
2751 ble_cache[LAYER_RAINBOW] = (vce_rendercache.BLE >> 12) & 0x3;
2752
2753 for(int x = 0; x < 8; x++)
2754 if(ble_cache[x])
2755 {
2756 ble_cache_any = true;
2757 break;
2758 }
2759
2760 uint8 *coeff_cache_y_back[3];
2761 int8 *coeff_cache_u_back[3], *coeff_cache_v_back[3];
2762 uint8 *coeff_cache_y_fore[3];
2763 int8 *coeff_cache_u_fore[3], *coeff_cache_v_fore[3];
2764
2765 for(int x = 0; x < 3; x++)
2766 {
2767 coeff_cache_y_fore[x] = vce_rendercache.coefficient_mul_table_y[(vce_rendercache.coefficients[x * 2 + 0] >> 8) & 0xF];
2768 coeff_cache_u_fore[x] = vce_rendercache.coefficient_mul_table_uv[(vce_rendercache.coefficients[x * 2 + 0] >> 4) & 0xF];
2769 coeff_cache_v_fore[x] = vce_rendercache.coefficient_mul_table_uv[(vce_rendercache.coefficients[x * 2 + 0] >> 0) & 0xF];
2770
2771 coeff_cache_y_back[x] = vce_rendercache.coefficient_mul_table_y[(vce_rendercache.coefficients[x * 2 + 1] >> 8) & 0xF];
2772 coeff_cache_u_back[x] = vce_rendercache.coefficient_mul_table_uv[(vce_rendercache.coefficients[x * 2 + 1] >> 4) & 0xF];
2773 coeff_cache_v_back[x] = vce_rendercache.coefficient_mul_table_uv[(vce_rendercache.coefficients[x * 2 + 1] >> 0) & 0xF];
2774 }
2775
2776 uint32 *target;
2777 uint32 BPC_Cache = (LAYER_NONE << 28); // Backmost pixel color(cache)
2778
2779 if(fx_vce.frame_interlaced)
2780 target = pXBuf + surface->pitch32 * ((fx_vce.raster_counter - 22) * 2 + fx_vce.odd_field);
2781 else
2782 target = pXBuf + surface->pitch32 * (fx_vce.raster_counter - 22);
2783
2784
2785 // If at least one layer is enabled with the HuC6261, hindmost color is palette[0]
2786 // If no layers are on, this color is black.
2787 // If front cellophane is enabled, this color is forced to black(TODO: Confirm on a real system. Black or from CCR).
2788 // If back cellophane is enabled, this color is forced to the value in CCR
2789 // (back and front conditions are handled closer to the pixel mixing loops down below)
2790 // TODO: Test on a real PC-FX to see if CCR is used or not if back cellophane is enabled even if all layers are disabled in the HuC6261,
2791 // or if it just outputs black.
2792 // TODO: See if enabling front/back cellophane in high dot-clock mode will set the hindmost color, even though the cellophane color mixing
2793 // is disabled in high dot-clock mode.
2794 if(vce_rendercache.picture_mode & 0x7F00)
2795 BPC_Cache |= vce_rendercache.palette_table_cache[0];
2796 else
2797 BPC_Cache |= 0x008080;
2798
2799 #define DOCELLO(pixpoo) \
2800 if((pixel[pixpoo] >> 28) != LAYER_VDC_SPR || ((vce_rendercache.SPBL >> ((vdc_linebuffer[x] & 0xF0)>> 4)) & 1)) \
2801 { \
2802 int which_co = (ble_cache[pixel[pixpoo] >> 28] - 1); \
2803 uint8 back_y = coeff_cache_y_back[which_co][(zeout >> 16) & 0xFF]; \
2804 int8 back_u = coeff_cache_u_back[which_co][(zeout >> 8) & 0xFF]; \
2805 int8 back_v = coeff_cache_v_back[which_co][(zeout >> 0) & 0xFF]; \
2806 uint8 fore_y = coeff_cache_y_fore[which_co][(pixel[pixpoo] >> 16) & 0xFF]; \
2807 int8 fore_u = coeff_cache_u_fore[which_co][(pixel[pixpoo] >> 8) & 0xFF]; \
2808 int8 fore_v = coeff_cache_v_fore[which_co][(pixel[pixpoo] >> 0) & 0xFF]; \
2809 zeout = (pixel[pixpoo] & 0xFF000000) | ((RGBDeflower + 384)[back_y + fore_y] << 16) | ((RGBDeflower + 384)[back_u + fore_u + 128] << 8) | ((RGBDeflower + 384)[back_v + fore_v + 128] << 0); \
2810 } else zeout = pixel[pixpoo]; \
2811
2812 #define DOCELLOSPECIALFRONT() \
2813 { \
2814 uint8 y = coeff_cache_y_back[0][(zeout >> 16) & 0xFF]; \
2815 int8 u = coeff_cache_u_back[0][(zeout >> 8) & 0xFF]; \
2816 int8 v = coeff_cache_v_back[0][(zeout >> 0) & 0xFF]; \
2817 zeout = (zeout & 0xFF000000) | ((RGBDeflower + 384)[CCR_Y_front + y] << 16) | ((RGBDeflower + 384)[CCR_U_front + u + 128] << 8) | \
2818 ((RGBDeflower + 384)[CCR_V_front + v + 128] << 0); \
2819 }
2820
2821 #define LAYER_MIX_BODY(index_256, index_341) \
2822 { uint32 pixel[4]; \
2823 uint32 prio[3]; \
2824 uint32 zeout = BPC_Cache; \
2825 prio[0] = priority_remap[vdc_linebuffer_yuved[index_341] >> 28]; \
2826 prio[1] = priority_remap[(bg_linebuffer + 8)[index_256] >> 28]; \
2827 prio[2] = priority_remap[rainbow_linebuffer[index_256] >> 28]; \
2828 pixel[0] = 0; \
2829 pixel[1] = 0; \
2830 pixel[2] = 0; \
2831 { \
2832 uint8 pi0 = VCEPrioMap[prio[0]][prio[1]][prio[2]][0]; \
2833 uint8 pi1 = VCEPrioMap[prio[0]][prio[1]][prio[2]][1]; \
2834 uint8 pi2 = VCEPrioMap[prio[0]][prio[1]][prio[2]][2]; \
2835 /*assert(pi0 == 3 || !pixel[pi0]);*/ pixel[pi0] = vdc_linebuffer_yuved[index_341]; \
2836 /*assert(pi1 == 3 || !pixel[pi1]);*/ pixel[pi1] = (bg_linebuffer + 8)[index_256]; \
2837 /*assert(pi2 == 3 || !pixel[pi2]);*/ pixel[pi2] = rainbow_linebuffer[index_256]; \
2838 }
2839
2840 #define LAYER_MIX_FINAL_NOCELLO \
2841 if(pixel[0]) \
2842 zeout = pixel[0]; \
2843 if(pixel[1]) \
2844 zeout = pixel[1]; \
2845 if(pixel[2]) \
2846 zeout = pixel[2]; \
2847 target[x] = YUV888_TO_xxx(zeout); \
2848 }
2849
2850 // For back cellophane, the hindmost pixel is always a valid pixel to mix with, a "layer" in its own right,
2851 // so we don't need to check the current pixel value before mixing.
2852 #define LAYER_MIX_FINAL_BACK_CELLO \
2853 if(pixel[0]) \
2854 { \
2855 if(ble_cache[pixel[0] >> 28]) \
2856 { \
2857 DOCELLO(0); \
2858 } \
2859 else \
2860 zeout = pixel[0]; \
2861 } \
2862 if(pixel[1]) \
2863 { \
2864 if(ble_cache[pixel[1] >> 28]) \
2865 { \
2866 DOCELLO(1); \
2867 } \
2868 else \
2869 zeout = pixel[1]; \
2870 } \
2871 if(pixel[2]) \
2872 { \
2873 if(ble_cache[pixel[2] >> 28]) \
2874 { \
2875 DOCELLO(2); \
2876 } \
2877 else \
2878 zeout = pixel[2]; \
2879 } \
2880 target[x] = YUV888_TO_xxx(zeout); \
2881 }
2882
2883 // ..however, for front and "normal" cellophane, we need to make sure that the
2884 // layer is indeed a real layer(KBG, VDC, RAINBOW) before mixing.
2885 // Note: We need to check the upper 4 bits in determining whether the previous pixel is from a real layer or not, because the default
2886 // hindmost non-layer color in front cellophane and normal cellophane modes is black, and black is represented in YUV as non-zero. We COULD bias/XOR each of U/V
2887 // by 0x80 in the rendering code so that it would work if we just tested for the non-zeroness of the previous pixel, and adjust the YUV->RGB
2888 // to compensate...TODO as a future possible optimization(MAYBE, it would obfuscate things more than they already are).
2889 //
2890 // Also, since the hindmost real layer pixel will never mix with anything behind it, we can leave
2891 // out a few checks for the first possible hindmost real pixel.
2892 //
2893 // Also, the front cellophane effect itself doesn't need to check if the effective pixel output is a real layer (TODO: Confirm on real hardware!)
2894 //
2895 #define LAYER_MIX_FINAL_FRONT_CELLO \
2896 if(pixel[0]) \
2897 zeout = pixel[0]; \
2898 if(pixel[1]) \
2899 { \
2900 if(ble_cache[pixel[1] >> 28] && (zeout & (0xF << 28))) \
2901 { \
2902 DOCELLO(1); \
2903 } \
2904 else \
2905 zeout = pixel[1]; \
2906 } \
2907 if(pixel[2]) \
2908 { \
2909 if(ble_cache[pixel[2] >> 28] && (zeout & (0xF << 28))) \
2910 { \
2911 DOCELLO(2); \
2912 } \
2913 else \
2914 zeout = pixel[2]; \
2915 } \
2916 DOCELLOSPECIALFRONT(); \
2917 target[x] = YUV888_TO_xxx(zeout); \
2918 }
2919
2920 #define LAYER_MIX_FINAL_CELLO \
2921 if(pixel[0]) \
2922 zeout = pixel[0]; \
2923 if(pixel[1]) \
2924 { \
2925 if(ble_cache[pixel[1] >> 28] && (zeout & (0xF << 28))) \
2926 { \
2927 DOCELLO(1); \
2928 } \
2929 else \
2930 zeout = pixel[1]; \
2931 } \
2932 if(pixel[2]) \
2933 { \
2934 if(ble_cache[pixel[2] >> 28] && (zeout & (0xF << 28))) \
2935 { \
2936 DOCELLO(2); \
2937 } \
2938 else \
2939 zeout = pixel[2]; \
2940 } \
2941 target[x] = YUV888_TO_xxx(zeout); \
2942 }
2943
2944 if(surface->format.colorspace == MDFN_COLORSPACE_YCbCr)
2945 {
2946 #define YUV888_TO_xxx YUV888_TO_YCbCr888
2947 #include "king_mix_body.inc"
2948 #undef YUV888_TO_xxx
2949 }
2950 else
2951 {
2952 #define YUV888_TO_xxx YUV888_TO_RGB888
2953 #include "king_mix_body.inc"
2954 #undef YUV888_TO_xxx
2955 }
2956 DisplayRect->w = fx_vce.dot_clock ? HighDotClockWidth : 256;
2957 DisplayRect->x = 0;
2958
2959 // FIXME
2960 if(fx_vce.frame_interlaced)
2961 LineWidths[(fx_vce.raster_counter - 22) * 2 + fx_vce.odd_field] = DisplayRect->w;
2962 else
2963 LineWidths[fx_vce.raster_counter - 22] = DisplayRect->w;
2964 }
2965
RunVDCs(const int master_cycles,uint16 * pixels0,uint16 * pixels1)2966 static INLINE void RunVDCs(const int master_cycles, uint16 *pixels0, uint16 *pixels1)
2967 {
2968 int32 div_clocks;
2969
2970 fx_vce.clock_divider += master_cycles;
2971 div_clocks = fx_vce.clock_divider / fx_vce.dot_clock_ratio;
2972 fx_vce.clock_divider -= div_clocks * fx_vce.dot_clock_ratio;
2973
2974 if(pixels0)
2975 pixels0 += vdc_lb_pos;
2976
2977 if(pixels1)
2978 pixels1 += vdc_lb_pos;
2979
2980 if(MDFN_UNLIKELY(((uint64)vdc_lb_pos + div_clocks) > 512))
2981 {
2982 //puts("Bug");
2983 pixels0 = pixels1 = NULL;
2984 }
2985
2986 fx_vce.vdc_event[0] = vdc_chips[0]->Run(div_clocks, pixels0, pixels0 ? false : true);
2987 fx_vce.vdc_event[1] = vdc_chips[1]->Run(div_clocks, pixels1, pixels1 ? false : true);
2988
2989 vdc_lb_pos += div_clocks;
2990
2991 // printf("%d\n", vdc_lb_pos);
2992 // if(fx_vce.dot_clock)
2993 // assert(vdc_lb_pos <= 342);
2994 // else
2995 // assert(vdc_lb_pos <= 257);
2996 }
2997
KING_RunGfx(int32 clocks)2998 static void MDFN_FASTCALL KING_RunGfx(int32 clocks)
2999 {
3000 while(clocks > 0)
3001 {
3002 int32 chunk_clocks = clocks;
3003
3004 if(chunk_clocks > HPhaseCounter)
3005 chunk_clocks = HPhaseCounter;
3006
3007 clocks -= chunk_clocks;
3008 HPhaseCounter -= chunk_clocks;
3009
3010 if(skip)
3011 RunVDCs(chunk_clocks, NULL, NULL);
3012 else if(fx_vce.in_hblank)
3013 {
3014 static uint16 dummybuf[1024];
3015 RunVDCs(chunk_clocks, dummybuf, dummybuf);
3016 }
3017 else
3018 {
3019 RunVDCs(chunk_clocks, vdc_linebuffers[0], vdc_linebuffers[1]);
3020 }
3021
3022 assert(HPhaseCounter >= 0);
3023
3024 while(HPhaseCounter <= 0)
3025 {
3026 HPhase = (HPhase + 1) % HPHASE_COUNT;
3027 switch(HPhase)
3028 {
3029 case HPHASE_ACTIVE: vdc_lb_pos = 0;
3030 fx_vce.in_hblank = false;
3031 DoHBlankVCECaching();
3032 DrawActive();
3033 HPhaseCounter += 1024;
3034 break;
3035
3036 case HPHASE_HBLANK_PART1:
3037 if(!skip)
3038 {
3039 if(fx_vce.raster_counter >= 22 && fx_vce.raster_counter < 262)
3040 {
3041 MixVDC();
3042 MixLayers();
3043 }
3044 }
3045 fx_vce.in_hblank = true;
3046 fx_vce.in_vdc_hsync = true;
3047
3048 for(int chip = 0; chip < 2; chip++)
3049 vdc_chips[chip]->HSync(true);
3050
3051 HPhaseCounter += 48;
3052 break;
3053
3054 case HPHASE_HBLANK_PART3:
3055 fx_vce.raster_counter = (fx_vce.raster_counter + 1) % ((fx_vce.picture_mode & 0x1) ? 262 : 263); //lines_per_frame;
3056
3057 if(fx_vce.raster_counter == 0)
3058 for(int chip = 0; chip < 2; chip++)
3059 vdc_chips[chip]->VSync(true);
3060
3061 if(fx_vce.raster_counter == 3)
3062 for(int chip = 0; chip < 2; chip++)
3063 vdc_chips[chip]->VSync(false);
3064
3065 if(!fx_vce.raster_counter)
3066 {
3067 bool previous_interlaced = fx_vce.frame_interlaced;
3068
3069 fx_vce.frame_interlaced = fx_vce.picture_mode & 2;
3070
3071 if(fx_vce.frame_interlaced && previous_interlaced)
3072 fx_vce.odd_field ^= 1;
3073
3074 if(!fx_vce.frame_interlaced)
3075 fx_vce.odd_field = 0;
3076
3077 PCFX_V810.Exit();
3078 }
3079
3080 if(fx_vce.raster_counter == king->RasterIRQLine && (king->RAINBOWTransferControl & 0x2))
3081 {
3082 //printf("Wovely: %d, %d, %d\n", fx_vce.raster_counter, king->RAINBOWRasterCounter, king->RAINBOWTransferControl);
3083
3084 //if(fx_vce.raster_counter == 262)
3085 //{
3086 // printf("Rainbow raster IRQ on line 262?\n");
3087 //}
3088 //else
3089 {
3090 king->RasterIRQPending = true;
3091 RedoKINGIRQCheck();
3092 }
3093 }
3094
3095 // This -18(and +18) may or may not be correct in regards to how a real PC-FX adjusts the VDC layer horizontal position
3096 // versus the KING and RAINBOW layers.
3097
3098 if(fx_vce.dot_clock)
3099 HPhaseCounter += 173 - 18;
3100 else
3101 HPhaseCounter += 165;
3102 break;
3103
3104 case HPHASE_HBLANK_PART4:
3105 fx_vce.in_vdc_hsync = false;
3106 for(int chip = 0; chip < 2; chip++)
3107 vdc_chips[chip]->HSync(false);
3108
3109 if(fx_vce.dot_clock)
3110 HPhaseCounter += 120 + 18;
3111 else
3112 HPhaseCounter += 128;
3113 break;
3114
3115 } // end: switch(HPhase)
3116 } // end: while(HPhaseCounter <= 0)
3117 } // end: while(clocks > 0)
3118 } // end KING_RunGfx()
3119
KING_SetPixelFormat(const MDFN_PixelFormat & format)3120 void KING_SetPixelFormat(const MDFN_PixelFormat &format)
3121 {
3122 rs = format.Rshift;
3123 gs = format.Gshift;
3124 bs = format.Bshift;
3125 RebuildUVLUT(format);
3126 }
3127
KING_SetLayerEnableMask(uint64 mask)3128 void KING_SetLayerEnableMask(uint64 mask)
3129 {
3130 uint64 ms = mask;
3131 // "BG0\0BG1\0BG2\0BG3\0VDC-A BG\0VDC-A SPR\0VDC-B BG\0VDC-B SPR\0RAINBOW\0",
3132
3133 BGLayerDisable = (~ms) & 0xF;
3134 ms >>= 4;
3135
3136 for(unsigned chip = 0; chip < 2; chip++)
3137 {
3138 fx_vdc_chips[chip]->SetLayerEnableMask(ms & 0x3);
3139 ms >>= 2;
3140 }
3141
3142 RAINBOWLayerDisable = (~ms) & 0x1;
3143 ms >>= 1;
3144
3145 #if 0
3146 if(which < 4)
3147 {
3148 BGLayerDisable ^= 1 << which;
3149 return( !((BGLayerDisable >> which) & 1));
3150 }
3151 else if(which == 4 || which == 5)
3152 {
3153 return(fx_vdc_chips[0]->ToggleLayer(which - 4));
3154 }
3155 else if(which == 6 || which == 7)
3156 {
3157 return(fx_vdc_chips[1]->ToggleLayer(which - 6));
3158 }
3159 else if(which == 8)
3160 {
3161 RAINBOWLayerDisable = !RAINBOWLayerDisable;
3162 return(!RAINBOWLayerDisable);
3163 }
3164 else
3165 return(0);
3166 #endif
3167 }
3168
3169
KING_StateAction(StateMem * sm,const unsigned load,const bool data_only)3170 void KING_StateAction(StateMem *sm, const unsigned load, const bool data_only)
3171 {
3172 SFORMAT KINGStateRegs[] =
3173 {
3174 SFVARN(king->AR, "AR"),
3175 SFVARN(king->KRAM[0], "KRAM0"),
3176 SFVARN(king->KRAM[1], "KRAM1"),
3177 SFVARN(king->KRAMWA, "KRAMWA"),
3178 SFVARN(king->KRAMRA, "KRAMRA"),
3179 SFVARN(king->KRAM_Mode, "KRAM_Mode"),
3180 SFVARN(king->PageSetting, "PageSetting"),
3181 SFVARN(king->bgmode, "bgmode"),
3182 SFVARN(king->priority, "priority"),
3183 SFVARN(king->BGScrollMode, "BGScrollMode"),
3184 SFVARN(king->BGSize, "BGSize"),
3185
3186 SFVARN(king->BGBATAddr, "BGBATAddr"),
3187 SFVARN(king->BGCGAddr, "BGCGAddr"),
3188 SFVARN(king->BG0SubBATAddr, "BG0SubBATAddr"),
3189 SFVARN(king->BG0SubCGAddr, "BG0SubCGAddr"),
3190
3191 SFVARN(king->BGXScroll, "BGXScroll"),
3192 SFVARN(king->BGYScroll, "BGYScroll"),
3193 SFVARN(king->BGAffinA, "BGAffinA"),
3194 SFVARN(king->BGAffinB, "BGAffinB"),
3195 SFVARN(king->BGAffinC, "BGAffinC"),
3196 SFVARN(king->BGAffinD, "BGAffinD"),
3197 SFVARN(king->BGAffinCenterX, "BGAffinCenterX"),
3198 SFVARN(king->BGAffinCenterY, "BGAffinCenterY"),
3199
3200 SFVARN(king->ADPCMControl, "ADPCMControl"),
3201 SFVARN(king->ADPCMBufferMode, "ADPCMBufferMode"),
3202 SFVARN(king->ADPCMSAL, "ADPCMSAL"),
3203 SFVARN(king->ADPCMEndAddress, "ADPCMEndAddress"),
3204 SFVARN(king->ADPCMPlayAddress, "ADPCMPlayAddress"),
3205 SFVARN(king->ADPCMIntermediateAddress, "ADPCMIntermediateAddress"),
3206 SFVARN(king->ADPCMStatus, "ADPCMStatus"),
3207 SFVARN(king->ADPCMIRQPending, "ADPCMIRQPending"),
3208 SFVARN(king->RAINBOWTransferControl, "RAINBOWTransferControl"),
3209 SFVARN(king->RAINBOWKRAMA, "RAINBOWKRAMA"),
3210 SFVARN(king->RAINBOWTransferStartPosition, "RAINBOWTransferStartPosition"),
3211 SFVARN(king->RAINBOWTransferBlockCount, "RAINBOWTransferBlockCount"),
3212
3213 SFVARN(king->RAINBOWStartPending, "RAINBOWStartPending"),
3214 SFVARN(king->RAINBOWBusyCount, "RAINBOWBusyCount"),
3215 SFVARN(king->RAINBOWBlockCount, "RAINBOWBlockCount"),
3216
3217 SFVARN(king->RasterIRQLine, "RasterIRQLine"),
3218 SFVARN(king->RasterIRQPending, "RasterIRQPending"),
3219 SFVARN(king->RAINBOWKRAMReadPos, "RAINBOWKRAMReadPos"),
3220 SFVARN(king->DMATransferFlipFlop, "DMATransferFlipFlop"),
3221 SFVARN(king->DMATransferAddr, "DMATransferAddr"),
3222 SFVARN(king->DMATransferSize, "DMATransferSize"),
3223 SFVARN(king->DMAStatus, "DMAStatus"),
3224 SFVARN(king->DMAInterrupt, "DMAInterrupt"),
3225 SFVARN(king->DMALatch, "DMALatch"),
3226 SFVARN(king->MPROGControl, "MPROGControl"),
3227 SFVARN(king->MPROGAddress, "MPROGAddress"),
3228 SFVARN(king->MPROGData, "MPROGData"),
3229 SFVARN(king->Reg00, "Port00"),
3230 SFVARN(king->Reg01, "Port01"),
3231 SFVARN(king->Reg02, "Port02"),
3232 SFVARN(king->Reg03, "Port03"),
3233 SFVARN(king->CDInterrupt, "CDInterrupt"),
3234 SFVARN(king->data_cache, "data_cache"),
3235 SFVARN(king->DRQ, "DRQ"),
3236 SFVARN(king->dma_receive_active, "dma_receive_active"),
3237 SFVARN(king->dma_send_active, "dma_send_active"),
3238 SFVARN(king->dma_cycle_counter, "dma_cycle_counter"),
3239
3240 SFVARN(king->SubChannelBuf, "SubChannelBuf"),
3241 SFVARN(king->SubChannelInterrupt, "SubChannelInterrupt"),
3242 SFVARN(king->SubChannelControl, "SubChannelControl"),
3243
3244 SFVAR(scsicd_ne),
3245 // scsicd_ne here??
3246 SFEND
3247 };
3248
3249 SFORMAT VCEStateRegs[] =
3250 {
3251 SFVARN(fx_vce.AR, "AR"),
3252 SFVARN(fx_vce.priority, "priority"),
3253 SFVARN(fx_vce.odd_field, "odd_field"),
3254 SFVARN(fx_vce.in_hblank, "in_hblank"),
3255 SFVARN(fx_vce.in_vdc_hsync, "in_vdc_hsync"),
3256 SFVARN(fx_vce.picture_mode, "picture_mode"),
3257
3258 SFVARN(HPhase, "HPhase"),
3259 SFVARN(HPhaseCounter, "HPhaseCounter"),
3260 SFVAR(vdc_lb_pos),
3261
3262 SFVARN(fx_vce.dot_clock, "dot_clock"),
3263 SFVARN(fx_vce.clock_divider, "clock_divider"),
3264
3265 SFVARN(fx_vce.vdc_event, "vdc_event"),
3266
3267 SFVARN(fx_vce.raster_counter, "raster_counter"),
3268 SFVARN(fx_vce.palette_rw_offset, "palette_rw_offset"),
3269 SFVARN(fx_vce.palette_rw_latch, "palette_rw_latch"),
3270 SFVARN(fx_vce.palette_offset, "palette_offset"),
3271 SFVARN(fx_vce.palette_table, "palette_table"),
3272 SFVARN(fx_vce.ChromaKeyY, "ChromaKeyY"),
3273 SFVARN(fx_vce.ChromaKeyU, "ChromaKeyU"),
3274 SFVARN(fx_vce.ChromaKeyV, "ChromaKeyV"),
3275 SFVARN(fx_vce.CCR, "CCR"),
3276 SFVARN(fx_vce.BLE, "BLE"),
3277 SFVARN(fx_vce.SPBL, "SPBL"),
3278 SFVARN(fx_vce.coefficients, "coefficients"),
3279
3280
3281 // HB render cache:
3282 // FIXME
3283 SFVARN(vce_rendercache.priority, "rc_priority"),
3284 SFVARN(vce_rendercache.picture_mode, "rc_picture_mode"),
3285 SFVARN(vce_rendercache.palette_offset, "rc_palette_offset"),
3286 SFVARN(vce_rendercache.ChromaKeyY, "rc_ChromaKeyY"),
3287 SFVARN(vce_rendercache.ChromaKeyU, "rc_ChromaKeyU"),
3288 SFVARN(vce_rendercache.ChromaKeyV, "rc_ChromaKeyV"),
3289 SFVARN(vce_rendercache.CCR, "rc_CCR"),
3290 SFVARN(vce_rendercache.BLE, "rc_BLE"),
3291 SFVARN(vce_rendercache.SPBL, "rc_SPBL"),
3292 SFVARN(vce_rendercache.coefficients, "rc_coefficients"),
3293
3294 SFEND
3295 };
3296
3297 MDFNSS_StateAction(sm, load, data_only, KINGStateRegs, "KING");
3298
3299 MDFNSS_StateAction(sm, load, data_only, VCEStateRegs, "VCE");
3300
3301 if(load)
3302 {
3303 RecalcKRAMPagePtrs();
3304
3305 fx_vce.dot_clock_ratio = fx_vce.dot_clock ? 3 : 4;
3306
3307 if(fx_vce.clock_divider < 0)
3308 fx_vce.clock_divider = 0;
3309 else if(fx_vce.clock_divider > 3)
3310 fx_vce.clock_divider = 3;
3311
3312
3313 fx_vce.palette_rw_offset &= 0x1FF;
3314 fx_vce.palette_offset[3] &= 0x00FF;
3315 fx_vce.priority[0] &= 0x0777;
3316 fx_vce.priority[1] &= 0x7777;
3317
3318 for(int x = 0; x < 6; x++)
3319 fx_vce.coefficients[x] &= 0x0FFF;
3320
3321 for(int x = 0; x < 0x200; x++)
3322 RedoPaletteCache(x);
3323
3324 vdc_lb_pos &= 0x1FF; // FIXME: Better checks(in case we remove the assert() elsewhere)?
3325 //
3326 if(king->dma_cycle_counter < 1)
3327 king->dma_cycle_counter = 1;
3328
3329 if(scsicd_ne < 1)
3330 scsicd_ne = 1;
3331
3332 if(HPhaseCounter < 1)
3333 HPhaseCounter = 1;
3334 //
3335 RedoKINGIRQCheck();
3336 SoundBox_SetKINGADPCMControl(king->ADPCMControl);
3337 }
3338 }
3339
3340 #ifdef WANT_DEBUGGER
KING_SetRegister(const unsigned int id,uint32 value)3341 void KING_SetRegister(const unsigned int id, uint32 value)
3342 {
3343 if(id == KING_GSREG_AR)
3344 king->AR = value & 0x7F;
3345 else if(id == KING_GSREG_MPROGADDR)
3346 king->MPROGAddress = value & 0xF;
3347 else if(id == KING_GSREG_MPROGCTRL)
3348 king->MPROGControl = value & 0x1;
3349 else if(id == KING_GSREG_MPROG0 || id == KING_GSREG_MPROG1 || id == KING_GSREG_MPROG2 || id == KING_GSREG_MPROG3 || id == KING_GSREG_MPROG4 || id == KING_GSREG_MPROG5 || id == KING_GSREG_MPROG6 || id == KING_GSREG_MPROG7 ||
3350 id == KING_GSREG_MPROG8 || id == KING_GSREG_MPROG9 || id == KING_GSREG_MPROGA || id == KING_GSREG_MPROGB || id == KING_GSREG_MPROGC || id == KING_GSREG_MPROGD || id == KING_GSREG_MPROGE || id == KING_GSREG_MPROGF)
3351 {
3352 king->MPROGData[id - KING_GSREG_MPROG0] = value;
3353 }
3354 else if(id == KING_GSREG_PAGESET)
3355 {
3356 king->PageSetting = value;
3357 RecalcKRAMPagePtrs();
3358 }
3359 else if(id == KING_GSREG_BGMODE)
3360 {
3361 king->bgmode = value;
3362 }
3363 else if(id == KING_GSREG_BGPRIO)
3364 {
3365 king->priority = value;
3366 }
3367 else if(id == KING_GSREG_BGSCRM)
3368 {
3369 king->BGScrollMode = value;
3370 }
3371 else if(id == KING_GSREG_BGSIZ0)
3372 king->BGSize[0] = value;
3373 else if(id == KING_GSREG_BGSIZ1)
3374 king->BGSize[1] = value & 0x00FF;
3375 else if(id == KING_GSREG_BGSIZ2)
3376 king->BGSize[2] = value & 0x00FF;
3377 else if(id == KING_GSREG_BGSIZ3)
3378 king->BGSize[3] = value & 0x00FF;
3379 else if(id == KING_GSREG_BGXSC0)
3380 king->BGXScroll[0] = value & 0x7FF;
3381 else if(id == KING_GSREG_BGXSC1)
3382 king->BGXScroll[1] = value & 0x3FF;
3383 else if(id == KING_GSREG_BGXSC2)
3384 king->BGXScroll[2] = value & 0x3FF;
3385 else if(id == KING_GSREG_BGXSC3)
3386 king->BGXScroll[3] = value & 0x3FF;
3387 else if(id == KING_GSREG_BGYSC0)
3388 king->BGYScroll[0] = value & 0x7FF;
3389 else if(id == KING_GSREG_BGYSC1)
3390 king->BGYScroll[1] = value & 0x3FF;
3391 else if(id == KING_GSREG_BGYSC2)
3392 king->BGYScroll[2] = value & 0x3FF;
3393 else if(id == KING_GSREG_BGYSC3)
3394 king->BGYScroll[3] = value & 0x3FF;
3395 else if(id == KING_GSREG_AFFINA)
3396 king->BGAffinA = value;
3397 else if(id == KING_GSREG_AFFINB)
3398 king->BGAffinB = value;
3399 else if(id == KING_GSREG_AFFINC)
3400 king->BGAffinC = value;
3401 else if(id == KING_GSREG_AFFIND)
3402 king->BGAffinD = value;
3403 else if(id == KING_GSREG_AFFINX)
3404 king->BGAffinCenterX = value;
3405 else if(id == KING_GSREG_AFFINY)
3406 king->BGAffinCenterY = value;
3407 else if(id == KING_GSREG_BGBATS || id == KING_GSREG_BGBAT0 || id == KING_GSREG_BGBAT1 || id == KING_GSREG_BGBAT2 || id == KING_GSREG_BGBAT3)
3408 {
3409 if(id == KING_GSREG_BGBATS)
3410 king->BG0SubBATAddr = value;
3411 else
3412 king->BGBATAddr[id - KING_GSREG_BGBAT0] = value;
3413 }
3414 else if(id == KING_GSREG_BGCGS || id == KING_GSREG_BGCG0 || id == KING_GSREG_BGCG1 || id == KING_GSREG_BGCG2 || id == KING_GSREG_BGCG3)
3415 {
3416 if(id == KING_GSREG_BGCGS)
3417 king->BG0SubCGAddr = value;
3418 else
3419 king->BGCGAddr[id - KING_GSREG_BGCG0] = value;
3420 }
3421 else if(id == KING_GSREG_RTCTRL)
3422 king->RAINBOWTransferControl = value & 0x3;
3423 else if(id == KING_GSREG_RKRAMA)
3424 king->RAINBOWKRAMA = value & 0x3FFFF;
3425 else if(id == KING_GSREG_RSTART)
3426 king->RAINBOWTransferStartPosition = value & 0x1FF;
3427 else if(id == KING_GSREG_RCOUNT)
3428 king->RAINBOWTransferBlockCount = value & 0x1F;
3429 else if(id == KING_GSREG_RIRQLINE)
3430 king->RasterIRQLine = value;
3431 else if(id == KING_GSREG_KRAMRA)
3432 {
3433 king->KRAMRA = value;
3434 }
3435 else if(id == KING_GSREG_KRAMWA)
3436 {
3437 king->KRAMWA = value;
3438 }
3439 else if(id == KING_GSREG_DMATA)
3440 king->DMATransferAddr = value;
3441 else if(id == KING_GSREG_DMATS)
3442 king->DMATransferSize = value;
3443 else if(id == KING_GSREG_DMASTT)
3444 king->DMAStatus = value;
3445 else if(id == KING_GSREG_ADPCMCTRL)
3446 {
3447 king->ADPCMControl = value;
3448 SoundBox_SetKINGADPCMControl(king->ADPCMControl);
3449 }
3450 else if(id == KING_GSREG_ADPCMBM0 || id == KING_GSREG_ADPCMBM1)
3451 {
3452 king->ADPCMBufferMode[id - KING_GSREG_ADPCMBM0] = value;
3453 }
3454 else if(id == KING_GSREG_ADPCMPA0 || id == KING_GSREG_ADPCMPA1)
3455 {
3456 king->ADPCMPlayAddress[id - KING_GSREG_ADPCMPA0] = value;
3457 }
3458 else if(id == KING_GSREG_ADPCMSA0 || id == KING_GSREG_ADPCMSA1)
3459 {
3460 king->ADPCMSAL[id - KING_GSREG_ADPCMSA0] = value;
3461 }
3462 else if(id == KING_GSREG_ADPCMIA0 || id == KING_GSREG_ADPCMIA1)
3463 {
3464 king->ADPCMIntermediateAddress[id - KING_GSREG_ADPCMIA0] = value;
3465 }
3466 else if(id == KING_GSREG_ADPCMEA0 || id == KING_GSREG_ADPCMEA1)
3467 {
3468 king->ADPCMEndAddress[id - KING_GSREG_ADPCMEA0] = value;
3469 }
3470 else if(id == KING_GSREG_ADPCMStat)
3471 {
3472
3473 }
3474 else if(id == KING_GSREG_Reg01)
3475 {
3476 king->Reg01 = value;
3477 }
3478 else if(id == KING_GSREG_Reg02)
3479 {
3480 king->Reg02 = value;
3481 }
3482 else if(id == KING_GSREG_Reg03)
3483 {
3484 king->Reg03 = value;
3485 }
3486 else if(id == KING_GSREG_SUBCC)
3487 {
3488 king->SubChannelControl = value & 0x3;
3489 }
3490 }
3491
KING_GetRegister(const unsigned int id,char * special,const uint32 special_len)3492 uint32 KING_GetRegister(const unsigned int id, char *special, const uint32 special_len)
3493 {
3494 uint32 value = 0xDEADBEEF;
3495
3496 if(id == KING_GSREG_AR)
3497 {
3498 value = king->AR;
3499 }
3500 else if(id == KING_GSREG_MPROGADDR)
3501 value = king->MPROGAddress;
3502 else if(id == KING_GSREG_MPROGCTRL)
3503 {
3504 value = king->MPROGControl;
3505 }
3506 else if(id == KING_GSREG_MPROG0 || id == KING_GSREG_MPROG1 || id == KING_GSREG_MPROG2 || id == KING_GSREG_MPROG3 || id == KING_GSREG_MPROG4 || id == KING_GSREG_MPROG5 || id == KING_GSREG_MPROG6 || id == KING_GSREG_MPROG7 ||
3507 id == KING_GSREG_MPROG8 || id == KING_GSREG_MPROG9 || id == KING_GSREG_MPROGA || id == KING_GSREG_MPROGB || id == KING_GSREG_MPROGC || id == KING_GSREG_MPROGD || id == KING_GSREG_MPROGE || id == KING_GSREG_MPROGF)
3508 {
3509 value = king->MPROGData[id - KING_GSREG_MPROG0];
3510
3511 if(special)
3512 {
3513 static const char *atypes[4] = { "CG", "CG of BAT", "BAT", "???" };
3514
3515 trio_snprintf(special, special_len, "Offset: %d, Access Type: %s, Rotation: %d, BG Number: %d, NOP: %d",
3516 value & 0x7, atypes[(value >> 3) & 0x3], (int)(bool)(value & 0x20),
3517 (value >> 6) & 0x3, (int)(bool)(value & 0x100));
3518 }
3519
3520 }
3521 else if(id == KING_GSREG_PAGESET)
3522 {
3523 value = king->PageSetting;
3524
3525 if(special)
3526 {
3527 trio_snprintf(special, special_len, "SCSI: %d, BG: %d, ADPCM: %d, RAINBOW: %d", (int)(bool)(value & 0x1), (int)(bool)(value & 0x10), (int)(bool)(value & 0x100), (int)(bool)(value & 0x1000));
3528 }
3529 }
3530 else if(id == KING_GSREG_BGMODE)
3531 {
3532 value = king->bgmode;
3533 if(special)
3534 {
3535 static const char *bgmodes[16] = { "Disabled", "4-color", "16-color", "256-color", "64K-color", "16M-color", "Undefined", "Undefined",
3536 "Disabled", "4-color w/BAT", "16-color w/BAT", "256-color w/BAT", "64K-color w/BAT", "16M-color w/BAT", "Undefined", "Undefined"
3537 };
3538 trio_snprintf(special, special_len, "BG0: %2d(%s), BG1: %2d(%s), BG2: %2d(%s), BG3: %2d(%s)", value & 0xF, bgmodes[value & 0xF], (value >> 4) & 0xF, bgmodes[(value >> 4) & 0xF], (value >> 8) & 0xF, bgmodes[(value >> 8) & 0xf], (value >> 12) & 0xF, bgmodes[(value >> 12) & 0xf]);
3539 }
3540 }
3541 else if(id == KING_GSREG_BGPRIO)
3542 {
3543 value = king->priority;
3544 if(special)
3545 {
3546 trio_snprintf(special, special_len, "Affine enable: %s - BG0: %2d, BG1: %2d, BG2: %2d, BG3: %2d", (value & (1 << 12)) ? "Yes" : "No", value & 0x7, (value >> 3) & 0x7, (value >> 6) & 0x7, (value >> 9) & 0x7);
3547 }
3548 }
3549 else if(id == KING_GSREG_BGSCRM)
3550 {
3551 value = king->BGScrollMode;
3552 if(special)
3553 {
3554 trio_snprintf(special, special_len, "BG0: %s, BG1: %s, BG2: %s, BG3: %s", (value & 1) ? "Endless" : "Non-endless",(value & 2) ? "Endless" : "Non-endless",
3555 (value & 4) ? "Endless" : "Non-endless", (value & 8) ? "Endless" : "Non-endless");
3556 }
3557 }
3558 else if(id == KING_GSREG_BGSIZ0 || id == KING_GSREG_BGSIZ1 || id == KING_GSREG_BGSIZ2 || id == KING_GSREG_BGSIZ3)
3559 {
3560 value = king->BGSize[id - KING_GSREG_BGSIZ0];
3561 }
3562 else if(id == KING_GSREG_BGXSC0)
3563 value = king->BGXScroll[0];
3564 else if(id == KING_GSREG_BGXSC1)
3565 value = king->BGXScroll[1];
3566 else if(id == KING_GSREG_BGXSC2)
3567 value = king->BGXScroll[2];
3568 else if(id == KING_GSREG_BGXSC3)
3569 value = king->BGXScroll[3];
3570
3571 else if(id == KING_GSREG_BGYSC0)
3572 value = king->BGYScroll[0];
3573 else if(id == KING_GSREG_BGYSC1)
3574 value = king->BGYScroll[1];
3575 else if(id == KING_GSREG_BGYSC2)
3576 value = king->BGYScroll[2];
3577 else if(id == KING_GSREG_BGYSC3)
3578 value = king->BGYScroll[3];
3579 else if(id == KING_GSREG_AFFINA || id == KING_GSREG_AFFINB || id == KING_GSREG_AFFINC || id == KING_GSREG_AFFIND)
3580 {
3581 const uint16 *coeffs[4] = { &king->BGAffinA, &king->BGAffinB, &king->BGAffinC, &king->BGAffinD };
3582 value = *coeffs[id - KING_GSREG_AFFINA];
3583 if(special)
3584 {
3585 trio_snprintf(special, special_len, "%f", (double)(int16)value / 256);
3586 }
3587 }
3588 else if(id == KING_GSREG_AFFINX)
3589 value = king->BGAffinCenterX;
3590 else if(id == KING_GSREG_AFFINY)
3591 value = king->BGAffinCenterY;
3592 else if(id == KING_GSREG_BGBATS || id == KING_GSREG_BGBAT0 || id == KING_GSREG_BGBAT1 || id == KING_GSREG_BGBAT2 || id == KING_GSREG_BGBAT3)
3593 {
3594 if(id == KING_GSREG_BGBATS)
3595 value = king->BG0SubBATAddr;
3596 else
3597 value = king->BGBATAddr[id - KING_GSREG_BGBAT0];
3598
3599 if(special)
3600 {
3601 trio_snprintf(special, special_len, "0x%04x * 1024 = 0x%05x", value, (value * 1024) & 0x3FFFF);
3602 }
3603 }
3604 else if(id == KING_GSREG_BGCGS || id == KING_GSREG_BGCG0 || id == KING_GSREG_BGCG1 || id == KING_GSREG_BGCG2 || id == KING_GSREG_BGCG3)
3605 {
3606 if(id == KING_GSREG_BGCGS)
3607 value = king->BG0SubCGAddr;
3608 else
3609 value = king->BGCGAddr[id - KING_GSREG_BGCG0];
3610 if(special)
3611 {
3612 trio_snprintf(special, special_len, "0x%04x * 1024 = 0x%05x", value, (value * 1024) & 0x3FFFF);
3613 }
3614 }
3615 else if(id == KING_GSREG_RTCTRL)
3616 {
3617 value = king->RAINBOWTransferControl;
3618 if(special)
3619 {
3620 trio_snprintf(special, special_len, "Raster Interrupt: %s, Rainbow Transfer: %s", (value & 2) ? "On" : "Off", (value & 1) ? "On" : "Off");
3621 }
3622 }
3623 else if(id == KING_GSREG_RKRAMA)
3624 value = king->RAINBOWKRAMA;
3625 else if(id == KING_GSREG_RSTART)
3626 value = king->RAINBOWTransferStartPosition;
3627 else if(id == KING_GSREG_RCOUNT)
3628 value = king->RAINBOWTransferBlockCount;
3629 else if(id == KING_GSREG_RIRQLINE)
3630 value = king->RasterIRQLine;
3631 else if(id == KING_GSREG_KRAMRA)
3632 {
3633 value = king->KRAMRA;
3634 }
3635 else if(id == KING_GSREG_KRAMWA)
3636 {
3637 value = king->KRAMWA;
3638 }
3639 else if(id == KING_GSREG_DMATA)
3640 value = king->DMATransferAddr;
3641 else if(id == KING_GSREG_DMATS)
3642 value = king->DMATransferSize;
3643 else if(id == KING_GSREG_DMASTT)
3644 value = king->DMAStatus;
3645 else if(id == KING_GSREG_ADPCMCTRL)
3646 {
3647 value = king->ADPCMControl;
3648
3649 }
3650 else if(id == KING_GSREG_ADPCMBM0 || id == KING_GSREG_ADPCMBM1)
3651 {
3652 value = king->ADPCMBufferMode[id - KING_GSREG_ADPCMBM0];
3653 }
3654 else if(id == KING_GSREG_ADPCMPA0 || id == KING_GSREG_ADPCMPA1)
3655 {
3656 value = king->ADPCMPlayAddress[id - KING_GSREG_ADPCMPA0];
3657 }
3658 else if(id == KING_GSREG_ADPCMSA0 || id == KING_GSREG_ADPCMSA1)
3659 {
3660 value = king->ADPCMSAL[id - KING_GSREG_ADPCMSA0];
3661 }
3662 else if(id == KING_GSREG_ADPCMIA0 || id == KING_GSREG_ADPCMIA1)
3663 {
3664 value = king->ADPCMIntermediateAddress[id - KING_GSREG_ADPCMIA0];
3665
3666 if(special)
3667 {
3668 trio_snprintf(special, special_len, "0x%03x * 64 = 0x%08x", value, value << 6);
3669 }
3670 }
3671 else if(id == KING_GSREG_ADPCMEA0 || id == KING_GSREG_ADPCMEA1)
3672 {
3673 value = king->ADPCMEndAddress[id - KING_GSREG_ADPCMEA0];
3674 }
3675 else if(id == KING_GSREG_ADPCMStat)
3676 {
3677 value = king->ADPCMStatus[0] | (king->ADPCMStatus[1] << 2);
3678 if(special)
3679 {
3680 trio_snprintf(special, special_len, "Ch0 End: %d, Ch0 Intermediate: %d, Ch1 End: %d, Ch1 Intermediate: %d", (int)(bool)(value & 0x1),
3681 (int)(bool)(value & 0x2),
3682 (int)(bool)(value & 0x4),
3683 (int)(bool)(value & 0x8));
3684 }
3685 }
3686 else if(id == KING_GSREG_Reg01)
3687 {
3688 value = king->Reg01;
3689 if(special)
3690 {
3691 trio_snprintf(special, special_len, "BSY: %d, ATN: %d, SEL: %d, ACK: %d, RST: %d", (int)(bool)(value & 1), (int)(bool)(value & 2), (int)(bool)(value & 4),
3692 (int)(bool)(value & 0x10), (int)(bool)(value & 0x80));
3693 }
3694 }
3695 else if(id == KING_GSREG_Reg02)
3696 {
3697 value = king->Reg02;
3698 }
3699 else if(id == KING_GSREG_Reg03)
3700 {
3701 value = king->Reg03;
3702 if(special)
3703 {
3704
3705 trio_snprintf(special, special_len, "I/O: %d, C/D: %d, MSG: %d", (int)(bool)(value & 1), (int)(bool)(value & 2), (int)(bool)(value & 4));
3706 }
3707 }
3708 else if(id == KING_GSREG_SUBCC)
3709 {
3710 value = king->SubChannelControl;
3711 if(special)
3712 {
3713
3714 trio_snprintf(special, special_len, "Subchannel reading: %s, Subchannel read IRQ: %s", (value & 0x1) ? "Enabled" : "Disabled", (value & 0x2) ? "On" : "Off");
3715 }
3716 }
3717 else if(id == KING_GSREG_DB)
3718 value = SCSICD_GetDB();
3719 else if(id == KING_GSREG_BSY)
3720 value = SCSICD_GetBSY();
3721 else if(id == KING_GSREG_REQ)
3722 value = SCSICD_GetREQ();
3723 else if(id == KING_GSREG_ACK)
3724 value = SCSICD_GetACK();
3725 else if(id == KING_GSREG_MSG)
3726 value = SCSICD_GetMSG();
3727 else if(id == KING_GSREG_CD)
3728 value = SCSICD_GetCD();
3729 else if(id == KING_GSREG_IO)
3730 value = SCSICD_GetIO();
3731 else if(id == KING_GSREG_SEL)
3732 value = SCSICD_GetSEL();
3733
3734 return(value);
3735 }
3736
FXVCE_SetRegister(const unsigned int id,uint32 value)3737 void FXVCE_SetRegister(const unsigned int id, uint32 value)
3738 {
3739 if(id == FXVCE_GSREG_PRIO0)
3740 {
3741 fx_vce.priority[0] = value & 0x0777;
3742 }
3743 else if(id == FXVCE_GSREG_PRIO1)
3744 {
3745 fx_vce.priority[1] = value & 0x7777;
3746 }
3747 else if(id == FXVCE_GSREG_PICMODE)
3748 {
3749 fx_vce.picture_mode = value;
3750 }
3751 else if(id == FXVCE_GSREG_PALRWOF)
3752 {
3753 fx_vce.palette_rw_offset = value;
3754 fx_vce.palette_rw_offset &= 0x1FF;
3755 }
3756 else if(id == FXVCE_GSREG_PALRWLA)
3757 fx_vce.palette_rw_latch = value;
3758 else if(id == FXVCE_GSREG_PALOFS0)
3759 fx_vce.palette_offset[0] = value;
3760 else if(id == FXVCE_GSREG_PALOFS1)
3761 fx_vce.palette_offset[1] = value;
3762 else if(id == FXVCE_GSREG_PALOFS2)
3763 fx_vce.palette_offset[2] = value;
3764 else if(id == FXVCE_GSREG_PALOFS3)
3765 {
3766 fx_vce.palette_offset[3] = value;
3767 fx_vce.palette_offset[3] &= 0x00FF;
3768 }
3769 else if(id == FXVCE_GSREG_CKeyY)
3770 fx_vce.ChromaKeyY = value;
3771 else if(id == FXVCE_GSREG_CKeyU)
3772 fx_vce.ChromaKeyU = value;
3773 else if(id == FXVCE_GSREG_CKeyV)
3774 fx_vce.ChromaKeyV = value;
3775 else if(id == FXVCE_GSREG_CCR)
3776 fx_vce.CCR = value;
3777 else if(id == FXVCE_GSREG_BLE)
3778 fx_vce.BLE = value;
3779 else if(id == FXVCE_GSREG_SPBL)
3780 fx_vce.SPBL = value;
3781 else if(id == FXVCE_GSREG_COEFF0 || id == FXVCE_GSREG_COEFF1 || id == FXVCE_GSREG_COEFF2 || id == FXVCE_GSREG_COEFF3 || id == FXVCE_GSREG_COEFF4 || id == FXVCE_GSREG_COEFF5)
3782 fx_vce.coefficients[id - FXVCE_GSREG_COEFF0] = value & 0xFFF;
3783 }
3784
FXVCE_GetRegister(const unsigned int id,char * special,const uint32 special_len)3785 uint32 FXVCE_GetRegister(const unsigned int id, char* special, const uint32 special_len)
3786 {
3787 uint32 value = 0xDEADBEEF;
3788
3789 if(id == FXVCE_GSREG_PRIO0)
3790 {
3791 value = fx_vce.priority[0];
3792 if(special)
3793 {
3794 trio_snprintf(special, special_len, "VDC BG: %2d, VDC SPR: %2d, RAINBOW: %2d", value & 0xF, (value >> 4) & 0xF, (value >> 8) & 0xF);
3795 }
3796 }
3797 else if(id == FXVCE_GSREG_PRIO1)
3798 {
3799 value = fx_vce.priority[1];
3800 if(special)
3801 {
3802 trio_snprintf(special, special_len, "BG0: %2d, BG1: %2d, BG2: %2d, BG3: %2d", value & 0xF, (value >> 4) & 0xF, (value >> 8) & 0xF, (value >> 12) & 0xF);
3803 }
3804 }
3805 else if(id == FXVCE_GSREG_PICMODE)
3806 {
3807 value = fx_vce.picture_mode;
3808 if(special)
3809 {
3810 static const char *DCCModes[4] =
3811 {
3812 "263 lines/frame", "262 lines/frame", "Interlaced", "Interlaced+1/2 dot shift"
3813 };
3814
3815 trio_snprintf(special, special_len, "BG0: %s, BG1: %s, BG2: %s, BG3: %s, VDC BG: %s%s, VDC SPR: %s%s, RAINBOW: %s, VDC Clk: %sMHz, %s",
3816 (value & (1 << 10)) ? "On" : "Off", (value & (1 << 11)) ? "On": "Off",
3817 (value & (1 << 12)) ? "On" : "Off", (value & (1 << 13)) ? "On": "Off",
3818 (value & 0x0100) ? "On" : "Off", (value & 0x0040) ? "+merge mode" : "", (value & 0x0200) ? "On" : "Off", (value & 0x0080) ? "+merge mode" : "",
3819 (value & 0x4000) ? "On" : "Off", (value & 0x0008) ? "7.16":"5.37", DCCModes[value & 0x3]);
3820 }
3821 }
3822 else if(id == FXVCE_GSREG_Line)
3823 value = fx_vce.raster_counter;
3824 else if(id == FXVCE_GSREG_PALRWOF)
3825 value = fx_vce.palette_rw_offset;
3826 else if(id == FXVCE_GSREG_PALRWLA)
3827 value = fx_vce.palette_rw_latch;
3828 else if(id == FXVCE_GSREG_PALOFS0)
3829 value = fx_vce.palette_offset[0];
3830 else if(id == FXVCE_GSREG_PALOFS1)
3831 value = fx_vce.palette_offset[1];
3832 else if(id == FXVCE_GSREG_PALOFS2)
3833 value = fx_vce.palette_offset[2];
3834 else if(id == FXVCE_GSREG_PALOFS3)
3835 value = fx_vce.palette_offset[3];
3836 else if(id == FXVCE_GSREG_CKeyY)
3837 value = fx_vce.ChromaKeyY;
3838 else if(id == FXVCE_GSREG_CKeyU)
3839 value = fx_vce.ChromaKeyU;
3840 else if(id == FXVCE_GSREG_CKeyV)
3841 value = fx_vce.ChromaKeyV;
3842
3843 else if(id == FXVCE_GSREG_CCR)
3844 value = fx_vce.CCR;
3845 else if(id == FXVCE_GSREG_BLE)
3846 {
3847 value = fx_vce.BLE;
3848 if(special)
3849 {
3850 trio_snprintf(special, special_len, "%s(%s), Rainbow: %d, BG3: %d, BG2: %d, BG1: %d, BG0: %d, VDC SP: %d, VDC BG: %d", (value & 0x8000) ? "Front" : "Back", (value & 0x4000) ? "On" : "Off", (value >> 12) & 0x3,
3851 (value >> 10) & 3, (value >> 8) & 3, (value >> 6) & 3, (value >> 4) & 3, (value >> 2) & 3, value & 3);
3852 }
3853 }
3854 else if(id == FXVCE_GSREG_SPBL)
3855 value = fx_vce.SPBL;
3856 else if(id == FXVCE_GSREG_COEFF0 || id == FXVCE_GSREG_COEFF1 || id == FXVCE_GSREG_COEFF2 || id == FXVCE_GSREG_COEFF3 || id == FXVCE_GSREG_COEFF4 || id == FXVCE_GSREG_COEFF5)
3857 {
3858 value = fx_vce.coefficients[id - FXVCE_GSREG_COEFF0];
3859
3860 if(special)
3861 {
3862 trio_snprintf(special, special_len, "Y: %1d, U: %1d, V: %1d", (value >> 8) & 0xF, (value >> 4) & 0xf, value & 0xf);
3863 }
3864 }
3865
3866 return(value);
3867 }
3868
KING_SetGraphicsDecode(MDFN_Surface * decode_surface,int line,int which,int xscroll,int yscroll,int pbn)3869 void KING_SetGraphicsDecode(MDFN_Surface *decode_surface, int line, int which, int xscroll, int yscroll, int pbn)
3870 {
3871 GfxDecode_Buf = decode_surface;
3872 GfxDecode_Line = line;
3873 GfxDecode_Layer = which;
3874 GfxDecode_Scroll = yscroll;
3875 GfxDecode_PBN = pbn;
3876
3877 if(GfxDecode_Buf && GfxDecode_Line == -1)
3878 DoGfxDecode();
3879 }
3880
DoGfxDecode(void)3881 static void DoGfxDecode(void)
3882 {
3883 int pbn = GfxDecode_PBN;
3884
3885 if(GfxDecode_Layer >= 4 && GfxDecode_Layer <= 7)
3886 {
3887 uint32 palette_offset = fx_vce.palette_offset[0] >> (((GfxDecode_Layer - 4) & 1) * 8);
3888 palette_offset <<= 1;
3889 palette_offset &= 0x1FF;
3890 uint32 *palette_ptr = &vce_rendercache.palette_table_cache[palette_offset];
3891 uint32 neo_palette[16];
3892
3893 if(pbn == -1)
3894 {
3895 for(int x = 0; x < 16; x++)
3896 {
3897 int ccval = (int)(255 * pow((double)x / 15, 1.0f / 2.2));
3898 neo_palette[x] = GfxDecode_Buf->MakeColor(ccval, ccval, ccval, 0xFF);
3899 }
3900 }
3901 else
3902 {
3903 pbn &= 0x0F;
3904 palette_ptr += pbn * 16;
3905
3906 for(int x = 0; x < 16; x++)
3907 neo_palette[x] = YUV888_TO_PF(palette_ptr[x], GfxDecode_Buf->format, 0xFF);
3908 }
3909
3910 fx_vdc_chips[(GfxDecode_Layer - 4) / 2]->DoGfxDecode(GfxDecode_Buf->pixels, neo_palette, GfxDecode_Buf->MakeColor(0, 0, 0, 0xFF), (GfxDecode_Layer - 4) & 1, GfxDecode_Buf->w, GfxDecode_Buf->h, GfxDecode_Scroll);
3911 }
3912 else if(GfxDecode_Layer < 4)
3913 {
3914 int n = GfxDecode_Layer;
3915 uint16 bgmode = (king->bgmode >> (n * 4)) & 0xF;
3916 uint32 cg_offset = king->BGCGAddr[n] * 1024;
3917 uint32 bat_and_cg_page = (king->PageSetting & 0x0010) ? 1 : 0;
3918 uint32 *target = GfxDecode_Buf->pixels;
3919 uint32 layer_or = 0;
3920 uint32 page_addr_or = bat_and_cg_page ? 0x40000 : 0x00000;
3921 uint32 palette_offset = fx_vce.palette_offset[1 + (n >> 1)] >> ((n & 1) ? 8 : 0);
3922 palette_offset <<= 1;
3923 palette_offset &= 0x1FF;
3924 uint32 *palette_ptr = &vce_rendercache.palette_table_cache[palette_offset];
3925 int tile_width = 8;
3926 int tile_height = 8;
3927
3928 if(!(bgmode & 0x8))
3929 {
3930 int shiftmoo = (king->BGSize[n] & 0xF0) >> 4;
3931 if(shiftmoo < 3) shiftmoo = 3;
3932 if(shiftmoo > 0xA) shiftmoo = 0xA;
3933 tile_width = 1 << shiftmoo;
3934
3935 shiftmoo = (king->BGSize[n] & 0x0F);
3936 if(shiftmoo < 3) shiftmoo = 3;
3937 if(shiftmoo > 0xA) shiftmoo = 0xA;
3938 tile_height = 1 << shiftmoo;
3939
3940 if(tile_width > GfxDecode_Buf->w) tile_width = GfxDecode_Buf->w;
3941 if(tile_height > GfxDecode_Buf->h) tile_height = GfxDecode_Buf->h;
3942 }
3943
3944 switch(bgmode & 0x7)
3945 {
3946 default: memset(target, 0, GfxDecode_Buf->w * GfxDecode_Buf->h * sizeof(uint32) * 3);
3947 break;
3948
3949 case 0x01: // 4
3950 {
3951 pbn *= 4;
3952 pbn &= 0x1FF;
3953
3954 for(int y = 0; y < GfxDecode_Buf->h; y++)
3955 {
3956 for(int x = 0; x < GfxDecode_Buf->w; x+=8)
3957 {
3958 int which_tile = (x / 8) + (GfxDecode_Scroll + (y / 8)) * (GfxDecode_Buf->w / 8);
3959 uint16 cg = king->KRAM[bat_and_cg_page][(cg_offset + (which_tile * 8) + (y & 0x7)) & 0x3FFFF];
3960
3961 target[x + 0] = target[x + 1] = target[x + 2] = target[x + 3] =
3962 target[x + 4] = target[x + 5] = target[x + 6] = target[x + 7] = 0x008080; // For transparent pixels
3963
3964 DRAWBG8x1_4(target + x, &cg, palette_ptr + pbn, layer_or);
3965
3966 target[x + GfxDecode_Buf->w * 2 + 0] = target[x + GfxDecode_Buf->w * 2 + 1] = target[x + GfxDecode_Buf->w * 2 + 2] = target[x + GfxDecode_Buf->w * 2 + 3] =
3967 target[x + GfxDecode_Buf->w * 2 + 4] = target[x + GfxDecode_Buf->w * 2 + 5] = target[x + GfxDecode_Buf->w * 2 + 6] = target[x + GfxDecode_Buf->w * 2 + 7] = ((cg_offset + (which_tile * 8)) & 0x3FFFF) | page_addr_or;
3968
3969 target[x + GfxDecode_Buf->w*1 + 0]=target[x + GfxDecode_Buf->w*1 + 1]=target[x + GfxDecode_Buf->w*1 + 2]=target[x + GfxDecode_Buf->w*1 + 3] =
3970 target[x + GfxDecode_Buf->w*1 + 4]=target[x + GfxDecode_Buf->w*1 + 5]=target[x + GfxDecode_Buf->w*1 + 6]=target[x + GfxDecode_Buf->w*1 + 7] = which_tile;
3971 }
3972 for(int x = 0; x < GfxDecode_Buf->w; x++)
3973 target[x] = YUV888_TO_PF(target[x], GfxDecode_Buf->format, 0xFF);
3974 target += GfxDecode_Buf->w * 3;
3975 }
3976 }
3977 break;
3978
3979 case 0x02: // 16
3980 {
3981 pbn *= 8;
3982 pbn &= 0x1FF;
3983 for(int y = 0; y < GfxDecode_Buf->h; y++)
3984 {
3985 for(int x = 0; x < GfxDecode_Buf->w; x+=8)
3986 {
3987 int which_tile = (x / 8) + (GfxDecode_Scroll + (y / 8)) * (GfxDecode_Buf->w / 8);
3988 uint16 *cgptr = &king->KRAM[bat_and_cg_page][(cg_offset + (which_tile * 16) + (y & 0x7) * 2) & 0x3FFFF];
3989
3990 target[x + 0] = target[x + 1] = target[x + 2] = target[x + 3] =
3991 target[x + 4] = target[x + 5] = target[x + 6] = target[x + 7] = 0x008080; // For transparent pixels
3992
3993 DRAWBG8x1_16(target + x, cgptr, palette_ptr + pbn, layer_or);
3994
3995 target[x + GfxDecode_Buf->w*2 + 0] = target[x + GfxDecode_Buf->w*2 + 1] = target[x + GfxDecode_Buf->w*2 + 2] = target[x + GfxDecode_Buf->w*2 + 3] =
3996 target[x + GfxDecode_Buf->w*2 + 4] = target[x + GfxDecode_Buf->w*2 + 5] = target[x + GfxDecode_Buf->w*2 + 6] = target[x + GfxDecode_Buf->w*2 + 7] = ((cg_offset + (which_tile * 16)) & 0x3FFFF) | page_addr_or;
3997
3998 target[x + GfxDecode_Buf->w*1 + 0]=target[x + GfxDecode_Buf->w*1 + 1]=target[x + GfxDecode_Buf->w*1 + 2]=target[x + GfxDecode_Buf->w*1 + 3] =
3999 target[x + GfxDecode_Buf->w*1 + 4]=target[x + GfxDecode_Buf->w*1 + 5]=target[x + GfxDecode_Buf->w*1 + 6]=target[x + GfxDecode_Buf->w*1 + 7] = which_tile;
4000 }
4001 for(int x = 0; x < GfxDecode_Buf->w; x++)
4002 target[x] = YUV888_TO_PF(target[x], GfxDecode_Buf->format, 0xFF);
4003 target += GfxDecode_Buf->w * 3;
4004 }
4005 }
4006 break;
4007
4008 case 0x03: // 256
4009 {
4010 for(int y = 0; y < GfxDecode_Buf->h; y++)
4011 {
4012 for(int x = 0; x < GfxDecode_Buf->w; x+=8)
4013 {
4014 int which_tile = (x / 8) + (GfxDecode_Scroll + (y / 8)) * (GfxDecode_Buf->w / 8);
4015 uint16 *cgptr = &king->KRAM[bat_and_cg_page][(cg_offset + (which_tile * 32) + (y & 0x7) * 4) & 0x3FFFF];
4016
4017 target[x + 0] = target[x + 1] = target[x + 2] = target[x + 3] =
4018 target[x + 4] = target[x + 5] = target[x + 6] = target[x + 7] = 0x008080; // For transparent pixels
4019
4020 DRAWBG8x1_256(target + x, cgptr, palette_ptr, layer_or);
4021
4022 target[x + GfxDecode_Buf->w*2 + 0] = target[x + GfxDecode_Buf->w*2 + 1] = target[x + GfxDecode_Buf->w*2 + 2] = target[x + GfxDecode_Buf->w*2 + 3] =
4023 target[x + GfxDecode_Buf->w*2 + 4] = target[x + GfxDecode_Buf->w*2 + 5] = target[x + GfxDecode_Buf->w*2 + 6] = target[x + GfxDecode_Buf->w*2 + 7] = ((cg_offset + (which_tile * 32)) & 0x3FFFF) | page_addr_or;
4024
4025 target[x + GfxDecode_Buf->w*1 + 0]=target[x + GfxDecode_Buf->w*1 + 1]=target[x + GfxDecode_Buf->w*1 + 2]=target[x + GfxDecode_Buf->w*1 + 3] =
4026 target[x + GfxDecode_Buf->w*1 + 4]=target[x + GfxDecode_Buf->w*1 + 5]=target[x + GfxDecode_Buf->w*1 + 6]=target[x + GfxDecode_Buf->w*1 + 7] = which_tile;
4027 }
4028
4029 for(int x = 0; x < GfxDecode_Buf->w; x++)
4030 target[x] = YUV888_TO_PF(target[x], GfxDecode_Buf->format, 0xFF);
4031
4032 target += GfxDecode_Buf->w * 3;
4033 }
4034 }
4035 break;
4036
4037 case 0x04: // 64K
4038 for(int y = 0; y < GfxDecode_Buf->h; y++)
4039 {
4040 for(int x = 0; x < GfxDecode_Buf->w; x+=8)
4041 {
4042 int which_tile = (x / 8) + (GfxDecode_Scroll + (y / 8)) * (GfxDecode_Buf->w / 8);
4043 uint16 *cgptr = &king->KRAM[bat_and_cg_page][(cg_offset + (which_tile * 64) + (y & 0x7) * 8) & 0x3FFFF];
4044
4045 target[x + 0] = target[x + 1] = target[x + 2] = target[x + 3] =
4046 target[x + 4] = target[x + 5] = target[x + 6] = target[x + 7] = 0x008080; // For transparent pixels
4047
4048 DRAWBG8x1_64K(target + x, cgptr, palette_ptr, layer_or);
4049 }
4050
4051 for(int x = 0; x < GfxDecode_Buf->w; x++)
4052 target[x] = YUV888_TO_PF(target[x], GfxDecode_Buf->format, 0xFF);
4053
4054 target += GfxDecode_Buf->w * 3;
4055 }
4056 break;
4057
4058 case 0x05: // 16M
4059 for(int y = 0; y < GfxDecode_Buf->h; y++)
4060 {
4061 for(int x = 0; x < GfxDecode_Buf->w; x+=8)
4062 {
4063 int which_tile = (x / 8) + (GfxDecode_Scroll + (y / 8)) * (GfxDecode_Buf->w / 8);
4064 uint16 *cgptr = &king->KRAM[bat_and_cg_page][(cg_offset + (which_tile * 64) + (y & 0x7) * 8) & 0x3FFFF];
4065
4066 target[x + 0] = target[x + 1] = target[x + 2] = target[x + 3] =
4067 target[x + 4] = target[x + 5] = target[x + 6] = target[x + 7] = 0x008080; // For transparent pixels
4068
4069 DRAWBG8x1_16M(target + x, cgptr, palette_ptr, layer_or);
4070 }
4071
4072 for(int x = 0; x < GfxDecode_Buf->w; x++)
4073 target[x] = YUV888_TO_PF(target[x], GfxDecode_Buf->format, 0xFF);
4074
4075 target += GfxDecode_Buf->w * 3;
4076 }
4077 break;
4078
4079 }
4080 }
4081 else
4082 memset(GfxDecode_Buf->pixels, 0, GfxDecode_Buf->w * GfxDecode_Buf->h * sizeof(uint32) * 3);
4083 }
4084
4085 #endif
4086
4087 }
4088