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 &reg, 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