1 /* Caprice32 - Amstrad CPC Emulator
2    (c) Copyright 1997-2004 Ulrich Doewich
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2 of the License, or
7    (at your option) any later version.
8 
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software
16    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18 
19 /* Hitachi HD6845S CRT Controller (CRTC Type 0) emulation
20    based on the CRTC emulation of WinAPE32 v2.0a5b by Richard Wilson
21 
22    Oct 16, 2000 - 23:12 started conversion from assembly to C
23    Oct 17, 2000 - 19:25 finished converting main CRTC update loop
24    Oct 17, 2000 - 22:04 added framework for mode draw handlers
25    Oct 25, 2000 - 22:03 changed all CRTC counters to be only 8 bits wide; fixed address calculation
26    Oct 30, 2000 - 19:03 fixed CPC screen address line advancement (test should have been for a _reset_ bit!)
27    Mar 20, 2001 - 16:00 added draw_mode2
28    Jun 20, 2001 - 23:24 added drawing routines for 32bpp video modes
29    Jul 04, 2001 - 22:28 16bpp rendering; updated 8bpp code with VDU visible region limiting
30    Sep 26, 2002 - 22:39 moved rendering code to separate files; added line doubling (in software) code
31    Oct 07, 2002 - 21:58 removed the CPC.scr_max test in write_video_data; added support for variable line spacing
32 
33    May 23, 2004 - 17:38 added some preliminary VDU frame cropping to reduce the amount of data written to the video buffer
34    May 24, 2004 - 00:44 moved the write_video_data code into the body of access_video_memory
35 
36    Jul 08, 2004 - 16:58 started implementing Richard's assembly CRTC emulation in C
37 */
38 
39 #include <math.h>
40 #include <retro_endianness.h>
41 
42 #include "cap32.h"
43 #include "crtc.h"
44 #include "z80.h"
45 #include "asic.h"
46 
47 extern t_CPC CPC;
48 extern t_CRTC CRTC;
49 extern t_GateArray GateArray;
50 extern t_VDU VDU;
51 extern t_z80regs z80;
52 
53 extern uint32_t dwXScale;
54 extern uint8_t *pbRAM;
55 
56 #ifdef DEBUG_CRTC
57 extern uint32_t dwDebugFlag;
58 extern FILE *pfoDebug;
59 #endif
60 
61 #define MAX_SYNC_DEC 80
62 #define MAX_SYNC_INC 80
63 
64 #define MAX_DRAWN 270 // Max displayed scan line (+1)
65 
66 #define MIN_VHOLD 250
67 #define MAX_VHOLD 380
68 #define MID_VHOLD 295
69 #define MIN_VHOLD_RANGE 46
70 #define MAX_VHOLD_RANGE 74
71 
72 t_flags1 flags1;
73 t_new_dt new_dt;
74 
75 uint32_t LastPreRend;
76 uint16_t MinVSync, MaxVSync;
77 int iMonHSPeakPos, iMonHSStartPos, iMonHSEndPos, iMonHSPeakToStart, iMonHSStartToPeak, iMonHSEndToPeak, iMonHSPeakToEnd;
78 int HorzPos, MonHSYNC, MonFreeSync;
79 int HSyncDuration, MinHSync, MaxHSync;
80 int HadP;
81 uint8_t PosShift, HorzChar, HorzMax;
82 
83 uint32_t *ModeMaps[4];
84 uint32_t *ModeMap;
85 uint8_t HorzPix[49];
86 uint8_t RendBuff[800];
87 uint8_t *RendWid, *RendOut;
88 uint32_t *RendStart, *RendPos;
89 uint32_t PrData[6]; // used in CPC+
90 
91 uint16_t MAXlate[0x7400];
92 
93 void (*PreRender)(void);
94 
95 // Version 2 translation tables - static
96 uint32_t M0Map[0x200] = {
97    0x00000000,0x00000000,0x00000000,0x08080808,0x08080808,0x00000000,0x08080808,0x08080808,
98    0x00000000,0x02020202,0x00000000,0x0A0A0A0A,0x08080808,0x02020202,0x08080808,0x0A0A0A0A,
99    0x02020202,0x00000000,0x02020202,0x08080808,0x0A0A0A0A,0x00000000,0x0A0A0A0A,0x08080808,
100    0x02020202,0x02020202,0x02020202,0x0A0A0A0A,0x0A0A0A0A,0x02020202,0x0A0A0A0A,0x0A0A0A0A,
101    0x00000000,0x04040404,0x00000000,0x0C0C0C0C,0x08080808,0x04040404,0x08080808,0x0C0C0C0C,
102    0x00000000,0x06060606,0x00000000,0x0E0E0E0E,0x08080808,0x06060606,0x08080808,0x0E0E0E0E,
103    0x02020202,0x04040404,0x02020202,0x0C0C0C0C,0x0A0A0A0A,0x04040404,0x0A0A0A0A,0x0C0C0C0C,
104    0x02020202,0x06060606,0x02020202,0x0E0E0E0E,0x0A0A0A0A,0x06060606,0x0A0A0A0A,0x0E0E0E0E,
105    0x04040404,0x00000000,0x04040404,0x08080808,0x0C0C0C0C,0x00000000,0x0C0C0C0C,0x08080808,
106    0x04040404,0x02020202,0x04040404,0x0A0A0A0A,0x0C0C0C0C,0x02020202,0x0C0C0C0C,0x0A0A0A0A,
107    0x06060606,0x00000000,0x06060606,0x08080808,0x0E0E0E0E,0x00000000,0x0E0E0E0E,0x08080808,
108    0x06060606,0x02020202,0x06060606,0x0A0A0A0A,0x0E0E0E0E,0x02020202,0x0E0E0E0E,0x0A0A0A0A,
109    0x04040404,0x04040404,0x04040404,0x0C0C0C0C,0x0C0C0C0C,0x04040404,0x0C0C0C0C,0x0C0C0C0C,
110    0x04040404,0x06060606,0x04040404,0x0E0E0E0E,0x0C0C0C0C,0x06060606,0x0C0C0C0C,0x0E0E0E0E,
111    0x06060606,0x04040404,0x06060606,0x0C0C0C0C,0x0E0E0E0E,0x04040404,0x0E0E0E0E,0x0C0C0C0C,
112    0x06060606,0x06060606,0x06060606,0x0E0E0E0E,0x0E0E0E0E,0x06060606,0x0E0E0E0E,0x0E0E0E0E,
113    0x00000000,0x01010101,0x00000000,0x09090909,0x08080808,0x01010101,0x08080808,0x09090909,
114    0x00000000,0x03030303,0x00000000,0x0B0B0B0B,0x08080808,0x03030303,0x08080808,0x0B0B0B0B,
115    0x02020202,0x01010101,0x02020202,0x09090909,0x0A0A0A0A,0x01010101,0x0A0A0A0A,0x09090909,
116    0x02020202,0x03030303,0x02020202,0x0B0B0B0B,0x0A0A0A0A,0x03030303,0x0A0A0A0A,0x0B0B0B0B,
117    0x00000000,0x05050505,0x00000000,0x0D0D0D0D,0x08080808,0x05050505,0x08080808,0x0D0D0D0D,
118    0x00000000,0x07070707,0x00000000,0x0F0F0F0F,0x08080808,0x07070707,0x08080808,0x0F0F0F0F,
119    0x02020202,0x05050505,0x02020202,0x0D0D0D0D,0x0A0A0A0A,0x05050505,0x0A0A0A0A,0x0D0D0D0D,
120    0x02020202,0x07070707,0x02020202,0x0F0F0F0F,0x0A0A0A0A,0x07070707,0x0A0A0A0A,0x0F0F0F0F,
121    0x04040404,0x01010101,0x04040404,0x09090909,0x0C0C0C0C,0x01010101,0x0C0C0C0C,0x09090909,
122    0x04040404,0x03030303,0x04040404,0x0B0B0B0B,0x0C0C0C0C,0x03030303,0x0C0C0C0C,0x0B0B0B0B,
123    0x06060606,0x01010101,0x06060606,0x09090909,0x0E0E0E0E,0x01010101,0x0E0E0E0E,0x09090909,
124    0x06060606,0x03030303,0x06060606,0x0B0B0B0B,0x0E0E0E0E,0x03030303,0x0E0E0E0E,0x0B0B0B0B,
125    0x04040404,0x05050505,0x04040404,0x0D0D0D0D,0x0C0C0C0C,0x05050505,0x0C0C0C0C,0x0D0D0D0D,
126    0x04040404,0x07070707,0x04040404,0x0F0F0F0F,0x0C0C0C0C,0x07070707,0x0C0C0C0C,0x0F0F0F0F,
127    0x06060606,0x05050505,0x06060606,0x0D0D0D0D,0x0E0E0E0E,0x05050505,0x0E0E0E0E,0x0D0D0D0D,
128    0x06060606,0x07070707,0x06060606,0x0F0F0F0F,0x0E0E0E0E,0x07070707,0x0E0E0E0E,0x0F0F0F0F,
129    0x01010101,0x00000000,0x01010101,0x08080808,0x09090909,0x00000000,0x09090909,0x08080808,
130    0x01010101,0x02020202,0x01010101,0x0A0A0A0A,0x09090909,0x02020202,0x09090909,0x0A0A0A0A,
131    0x03030303,0x00000000,0x03030303,0x08080808,0x0B0B0B0B,0x00000000,0x0B0B0B0B,0x08080808,
132    0x03030303,0x02020202,0x03030303,0x0A0A0A0A,0x0B0B0B0B,0x02020202,0x0B0B0B0B,0x0A0A0A0A,
133    0x01010101,0x04040404,0x01010101,0x0C0C0C0C,0x09090909,0x04040404,0x09090909,0x0C0C0C0C,
134    0x01010101,0x06060606,0x01010101,0x0E0E0E0E,0x09090909,0x06060606,0x09090909,0x0E0E0E0E,
135    0x03030303,0x04040404,0x03030303,0x0C0C0C0C,0x0B0B0B0B,0x04040404,0x0B0B0B0B,0x0C0C0C0C,
136    0x03030303,0x06060606,0x03030303,0x0E0E0E0E,0x0B0B0B0B,0x06060606,0x0B0B0B0B,0x0E0E0E0E,
137    0x05050505,0x00000000,0x05050505,0x08080808,0x0D0D0D0D,0x00000000,0x0D0D0D0D,0x08080808,
138    0x05050505,0x02020202,0x05050505,0x0A0A0A0A,0x0D0D0D0D,0x02020202,0x0D0D0D0D,0x0A0A0A0A,
139    0x07070707,0x00000000,0x07070707,0x08080808,0x0F0F0F0F,0x00000000,0x0F0F0F0F,0x08080808,
140    0x07070707,0x02020202,0x07070707,0x0A0A0A0A,0x0F0F0F0F,0x02020202,0x0F0F0F0F,0x0A0A0A0A,
141    0x05050505,0x04040404,0x05050505,0x0C0C0C0C,0x0D0D0D0D,0x04040404,0x0D0D0D0D,0x0C0C0C0C,
142    0x05050505,0x06060606,0x05050505,0x0E0E0E0E,0x0D0D0D0D,0x06060606,0x0D0D0D0D,0x0E0E0E0E,
143    0x07070707,0x04040404,0x07070707,0x0C0C0C0C,0x0F0F0F0F,0x04040404,0x0F0F0F0F,0x0C0C0C0C,
144    0x07070707,0x06060606,0x07070707,0x0E0E0E0E,0x0F0F0F0F,0x06060606,0x0F0F0F0F,0x0E0E0E0E,
145    0x01010101,0x01010101,0x01010101,0x09090909,0x09090909,0x01010101,0x09090909,0x09090909,
146    0x01010101,0x03030303,0x01010101,0x0B0B0B0B,0x09090909,0x03030303,0x09090909,0x0B0B0B0B,
147    0x03030303,0x01010101,0x03030303,0x09090909,0x0B0B0B0B,0x01010101,0x0B0B0B0B,0x09090909,
148    0x03030303,0x03030303,0x03030303,0x0B0B0B0B,0x0B0B0B0B,0x03030303,0x0B0B0B0B,0x0B0B0B0B,
149    0x01010101,0x05050505,0x01010101,0x0D0D0D0D,0x09090909,0x05050505,0x09090909,0x0D0D0D0D,
150    0x01010101,0x07070707,0x01010101,0x0F0F0F0F,0x09090909,0x07070707,0x09090909,0x0F0F0F0F,
151    0x03030303,0x05050505,0x03030303,0x0D0D0D0D,0x0B0B0B0B,0x05050505,0x0B0B0B0B,0x0D0D0D0D,
152    0x03030303,0x07070707,0x03030303,0x0F0F0F0F,0x0B0B0B0B,0x07070707,0x0B0B0B0B,0x0F0F0F0F,
153    0x05050505,0x01010101,0x05050505,0x09090909,0x0D0D0D0D,0x01010101,0x0D0D0D0D,0x09090909,
154    0x05050505,0x03030303,0x05050505,0x0B0B0B0B,0x0D0D0D0D,0x03030303,0x0D0D0D0D,0x0B0B0B0B,
155    0x07070707,0x01010101,0x07070707,0x09090909,0x0F0F0F0F,0x01010101,0x0F0F0F0F,0x09090909,
156    0x07070707,0x03030303,0x07070707,0x0B0B0B0B,0x0F0F0F0F,0x03030303,0x0F0F0F0F,0x0B0B0B0B,
157    0x05050505,0x05050505,0x05050505,0x0D0D0D0D,0x0D0D0D0D,0x05050505,0x0D0D0D0D,0x0D0D0D0D,
158    0x05050505,0x07070707,0x05050505,0x0F0F0F0F,0x0D0D0D0D,0x07070707,0x0D0D0D0D,0x0F0F0F0F,
159    0x07070707,0x05050505,0x07070707,0x0D0D0D0D,0x0F0F0F0F,0x05050505,0x0F0F0F0F,0x0D0D0D0D,
160    0x07070707,0x07070707,0x07070707,0x0F0F0F0F,0x0F0F0F0F,0x07070707,0x0F0F0F0F,0x0F0F0F0F
161 };
162 
163 uint32_t M1Map[0x200] = {
164    0x00000000,0x00000000,0x00000000,0x02020000,0x00000000,0x00000202,0x00000000,0x02020202,
165    0x02020000,0x00000000,0x02020000,0x02020000,0x02020000,0x00000202,0x02020000,0x02020202,
166    0x00000202,0x00000000,0x00000202,0x02020000,0x00000202,0x00000202,0x00000202,0x02020202,
167    0x02020202,0x00000000,0x02020202,0x02020000,0x02020202,0x00000202,0x02020202,0x02020202,
168    0x00000000,0x01010000,0x00000000,0x03030000,0x00000000,0x01010202,0x00000000,0x03030202,
169    0x02020000,0x01010000,0x02020000,0x03030000,0x02020000,0x01010202,0x02020000,0x03030202,
170    0x00000202,0x01010000,0x00000202,0x03030000,0x00000202,0x01010202,0x00000202,0x03030202,
171    0x02020202,0x01010000,0x02020202,0x03030000,0x02020202,0x01010202,0x02020202,0x03030202,
172    0x00000000,0x00000101,0x00000000,0x02020101,0x00000000,0x00000303,0x00000000,0x02020303,
173    0x02020000,0x00000101,0x02020000,0x02020101,0x02020000,0x00000303,0x02020000,0x02020303,
174    0x00000202,0x00000101,0x00000202,0x02020101,0x00000202,0x00000303,0x00000202,0x02020303,
175    0x02020202,0x00000101,0x02020202,0x02020101,0x02020202,0x00000303,0x02020202,0x02020303,
176    0x00000000,0x01010101,0x00000000,0x03030101,0x00000000,0x01010303,0x00000000,0x03030303,
177    0x02020000,0x01010101,0x02020000,0x03030101,0x02020000,0x01010303,0x02020000,0x03030303,
178    0x00000202,0x01010101,0x00000202,0x03030101,0x00000202,0x01010303,0x00000202,0x03030303,
179    0x02020202,0x01010101,0x02020202,0x03030101,0x02020202,0x01010303,0x02020202,0x03030303,
180    0x01010000,0x00000000,0x01010000,0x02020000,0x01010000,0x00000202,0x01010000,0x02020202,
181    0x03030000,0x00000000,0x03030000,0x02020000,0x03030000,0x00000202,0x03030000,0x02020202,
182    0x01010202,0x00000000,0x01010202,0x02020000,0x01010202,0x00000202,0x01010202,0x02020202,
183    0x03030202,0x00000000,0x03030202,0x02020000,0x03030202,0x00000202,0x03030202,0x02020202,
184    0x01010000,0x01010000,0x01010000,0x03030000,0x01010000,0x01010202,0x01010000,0x03030202,
185    0x03030000,0x01010000,0x03030000,0x03030000,0x03030000,0x01010202,0x03030000,0x03030202,
186    0x01010202,0x01010000,0x01010202,0x03030000,0x01010202,0x01010202,0x01010202,0x03030202,
187    0x03030202,0x01010000,0x03030202,0x03030000,0x03030202,0x01010202,0x03030202,0x03030202,
188    0x01010000,0x00000101,0x01010000,0x02020101,0x01010000,0x00000303,0x01010000,0x02020303,
189    0x03030000,0x00000101,0x03030000,0x02020101,0x03030000,0x00000303,0x03030000,0x02020303,
190    0x01010202,0x00000101,0x01010202,0x02020101,0x01010202,0x00000303,0x01010202,0x02020303,
191    0x03030202,0x00000101,0x03030202,0x02020101,0x03030202,0x00000303,0x03030202,0x02020303,
192    0x01010000,0x01010101,0x01010000,0x03030101,0x01010000,0x01010303,0x01010000,0x03030303,
193    0x03030000,0x01010101,0x03030000,0x03030101,0x03030000,0x01010303,0x03030000,0x03030303,
194    0x01010202,0x01010101,0x01010202,0x03030101,0x01010202,0x01010303,0x01010202,0x03030303,
195    0x03030202,0x01010101,0x03030202,0x03030101,0x03030202,0x01010303,0x03030202,0x03030303,
196    0x00000101,0x00000000,0x00000101,0x02020000,0x00000101,0x00000202,0x00000101,0x02020202,
197    0x02020101,0x00000000,0x02020101,0x02020000,0x02020101,0x00000202,0x02020101,0x02020202,
198    0x00000303,0x00000000,0x00000303,0x02020000,0x00000303,0x00000202,0x00000303,0x02020202,
199    0x02020303,0x00000000,0x02020303,0x02020000,0x02020303,0x00000202,0x02020303,0x02020202,
200    0x00000101,0x01010000,0x00000101,0x03030000,0x00000101,0x01010202,0x00000101,0x03030202,
201    0x02020101,0x01010000,0x02020101,0x03030000,0x02020101,0x01010202,0x02020101,0x03030202,
202    0x00000303,0x01010000,0x00000303,0x03030000,0x00000303,0x01010202,0x00000303,0x03030202,
203    0x02020303,0x01010000,0x02020303,0x03030000,0x02020303,0x01010202,0x02020303,0x03030202,
204    0x00000101,0x00000101,0x00000101,0x02020101,0x00000101,0x00000303,0x00000101,0x02020303,
205    0x02020101,0x00000101,0x02020101,0x02020101,0x02020101,0x00000303,0x02020101,0x02020303,
206    0x00000303,0x00000101,0x00000303,0x02020101,0x00000303,0x00000303,0x00000303,0x02020303,
207    0x02020303,0x00000101,0x02020303,0x02020101,0x02020303,0x00000303,0x02020303,0x02020303,
208    0x00000101,0x01010101,0x00000101,0x03030101,0x00000101,0x01010303,0x00000101,0x03030303,
209    0x02020101,0x01010101,0x02020101,0x03030101,0x02020101,0x01010303,0x02020101,0x03030303,
210    0x00000303,0x01010101,0x00000303,0x03030101,0x00000303,0x01010303,0x00000303,0x03030303,
211    0x02020303,0x01010101,0x02020303,0x03030101,0x02020303,0x01010303,0x02020303,0x03030303,
212    0x01010101,0x00000000,0x01010101,0x02020000,0x01010101,0x00000202,0x01010101,0x02020202,
213    0x03030101,0x00000000,0x03030101,0x02020000,0x03030101,0x00000202,0x03030101,0x02020202,
214    0x01010303,0x00000000,0x01010303,0x02020000,0x01010303,0x00000202,0x01010303,0x02020202,
215    0x03030303,0x00000000,0x03030303,0x02020000,0x03030303,0x00000202,0x03030303,0x02020202,
216    0x01010101,0x01010000,0x01010101,0x03030000,0x01010101,0x01010202,0x01010101,0x03030202,
217    0x03030101,0x01010000,0x03030101,0x03030000,0x03030101,0x01010202,0x03030101,0x03030202,
218    0x01010303,0x01010000,0x01010303,0x03030000,0x01010303,0x01010202,0x01010303,0x03030202,
219    0x03030303,0x01010000,0x03030303,0x03030000,0x03030303,0x01010202,0x03030303,0x03030202,
220    0x01010101,0x00000101,0x01010101,0x02020101,0x01010101,0x00000303,0x01010101,0x02020303,
221    0x03030101,0x00000101,0x03030101,0x02020101,0x03030101,0x00000303,0x03030101,0x02020303,
222    0x01010303,0x00000101,0x01010303,0x02020101,0x01010303,0x00000303,0x01010303,0x02020303,
223    0x03030303,0x00000101,0x03030303,0x02020101,0x03030303,0x00000303,0x03030303,0x02020303,
224    0x01010101,0x01010101,0x01010101,0x03030101,0x01010101,0x01010303,0x01010101,0x03030303,
225    0x03030101,0x01010101,0x03030101,0x03030101,0x03030101,0x01010303,0x03030101,0x03030303,
226    0x01010303,0x01010101,0x01010303,0x03030101,0x01010303,0x01010303,0x01010303,0x03030303,
227    0x03030303,0x01010101,0x03030303,0x03030101,0x03030303,0x01010303,0x03030303,0x03030303
228 };
229 
230 uint32_t M2Map[0x200] = {
231    0x00000000,0x00000000,0x00000000,0x01000000,0x00000000,0x00010000,0x00000000,0x01010000,
232    0x00000000,0x00000100,0x00000000,0x01000100,0x00000000,0x00010100,0x00000000,0x01010100,
233    0x00000000,0x00000001,0x00000000,0x01000001,0x00000000,0x00010001,0x00000000,0x01010001,
234    0x00000000,0x00000101,0x00000000,0x01000101,0x00000000,0x00010101,0x00000000,0x01010101,
235    0x01000000,0x00000000,0x01000000,0x01000000,0x01000000,0x00010000,0x01000000,0x01010000,
236    0x01000000,0x00000100,0x01000000,0x01000100,0x01000000,0x00010100,0x01000000,0x01010100,
237    0x01000000,0x00000001,0x01000000,0x01000001,0x01000000,0x00010001,0x01000000,0x01010001,
238    0x01000000,0x00000101,0x01000000,0x01000101,0x01000000,0x00010101,0x01000000,0x01010101,
239    0x00010000,0x00000000,0x00010000,0x01000000,0x00010000,0x00010000,0x00010000,0x01010000,
240    0x00010000,0x00000100,0x00010000,0x01000100,0x00010000,0x00010100,0x00010000,0x01010100,
241    0x00010000,0x00000001,0x00010000,0x01000001,0x00010000,0x00010001,0x00010000,0x01010001,
242    0x00010000,0x00000101,0x00010000,0x01000101,0x00010000,0x00010101,0x00010000,0x01010101,
243    0x01010000,0x00000000,0x01010000,0x01000000,0x01010000,0x00010000,0x01010000,0x01010000,
244    0x01010000,0x00000100,0x01010000,0x01000100,0x01010000,0x00010100,0x01010000,0x01010100,
245    0x01010000,0x00000001,0x01010000,0x01000001,0x01010000,0x00010001,0x01010000,0x01010001,
246    0x01010000,0x00000101,0x01010000,0x01000101,0x01010000,0x00010101,0x01010000,0x01010101,
247    0x00000100,0x00000000,0x00000100,0x01000000,0x00000100,0x00010000,0x00000100,0x01010000,
248    0x00000100,0x00000100,0x00000100,0x01000100,0x00000100,0x00010100,0x00000100,0x01010100,
249    0x00000100,0x00000001,0x00000100,0x01000001,0x00000100,0x00010001,0x00000100,0x01010001,
250    0x00000100,0x00000101,0x00000100,0x01000101,0x00000100,0x00010101,0x00000100,0x01010101,
251    0x01000100,0x00000000,0x01000100,0x01000000,0x01000100,0x00010000,0x01000100,0x01010000,
252    0x01000100,0x00000100,0x01000100,0x01000100,0x01000100,0x00010100,0x01000100,0x01010100,
253    0x01000100,0x00000001,0x01000100,0x01000001,0x01000100,0x00010001,0x01000100,0x01010001,
254    0x01000100,0x00000101,0x01000100,0x01000101,0x01000100,0x00010101,0x01000100,0x01010101,
255    0x00010100,0x00000000,0x00010100,0x01000000,0x00010100,0x00010000,0x00010100,0x01010000,
256    0x00010100,0x00000100,0x00010100,0x01000100,0x00010100,0x00010100,0x00010100,0x01010100,
257    0x00010100,0x00000001,0x00010100,0x01000001,0x00010100,0x00010001,0x00010100,0x01010001,
258    0x00010100,0x00000101,0x00010100,0x01000101,0x00010100,0x00010101,0x00010100,0x01010101,
259    0x01010100,0x00000000,0x01010100,0x01000000,0x01010100,0x00010000,0x01010100,0x01010000,
260    0x01010100,0x00000100,0x01010100,0x01000100,0x01010100,0x00010100,0x01010100,0x01010100,
261    0x01010100,0x00000001,0x01010100,0x01000001,0x01010100,0x00010001,0x01010100,0x01010001,
262    0x01010100,0x00000101,0x01010100,0x01000101,0x01010100,0x00010101,0x01010100,0x01010101,
263    0x00000001,0x00000000,0x00000001,0x01000000,0x00000001,0x00010000,0x00000001,0x01010000,
264    0x00000001,0x00000100,0x00000001,0x01000100,0x00000001,0x00010100,0x00000001,0x01010100,
265    0x00000001,0x00000001,0x00000001,0x01000001,0x00000001,0x00010001,0x00000001,0x01010001,
266    0x00000001,0x00000101,0x00000001,0x01000101,0x00000001,0x00010101,0x00000001,0x01010101,
267    0x01000001,0x00000000,0x01000001,0x01000000,0x01000001,0x00010000,0x01000001,0x01010000,
268    0x01000001,0x00000100,0x01000001,0x01000100,0x01000001,0x00010100,0x01000001,0x01010100,
269    0x01000001,0x00000001,0x01000001,0x01000001,0x01000001,0x00010001,0x01000001,0x01010001,
270    0x01000001,0x00000101,0x01000001,0x01000101,0x01000001,0x00010101,0x01000001,0x01010101,
271    0x00010001,0x00000000,0x00010001,0x01000000,0x00010001,0x00010000,0x00010001,0x01010000,
272    0x00010001,0x00000100,0x00010001,0x01000100,0x00010001,0x00010100,0x00010001,0x01010100,
273    0x00010001,0x00000001,0x00010001,0x01000001,0x00010001,0x00010001,0x00010001,0x01010001,
274    0x00010001,0x00000101,0x00010001,0x01000101,0x00010001,0x00010101,0x00010001,0x01010101,
275    0x01010001,0x00000000,0x01010001,0x01000000,0x01010001,0x00010000,0x01010001,0x01010000,
276    0x01010001,0x00000100,0x01010001,0x01000100,0x01010001,0x00010100,0x01010001,0x01010100,
277    0x01010001,0x00000001,0x01010001,0x01000001,0x01010001,0x00010001,0x01010001,0x01010001,
278    0x01010001,0x00000101,0x01010001,0x01000101,0x01010001,0x00010101,0x01010001,0x01010101,
279    0x00000101,0x00000000,0x00000101,0x01000000,0x00000101,0x00010000,0x00000101,0x01010000,
280    0x00000101,0x00000100,0x00000101,0x01000100,0x00000101,0x00010100,0x00000101,0x01010100,
281    0x00000101,0x00000001,0x00000101,0x01000001,0x00000101,0x00010001,0x00000101,0x01010001,
282    0x00000101,0x00000101,0x00000101,0x01000101,0x00000101,0x00010101,0x00000101,0x01010101,
283    0x01000101,0x00000000,0x01000101,0x01000000,0x01000101,0x00010000,0x01000101,0x01010000,
284    0x01000101,0x00000100,0x01000101,0x01000100,0x01000101,0x00010100,0x01000101,0x01010100,
285    0x01000101,0x00000001,0x01000101,0x01000001,0x01000101,0x00010001,0x01000101,0x01010001,
286    0x01000101,0x00000101,0x01000101,0x01000101,0x01000101,0x00010101,0x01000101,0x01010101,
287    0x00010101,0x00000000,0x00010101,0x01000000,0x00010101,0x00010000,0x00010101,0x01010000,
288    0x00010101,0x00000100,0x00010101,0x01000100,0x00010101,0x00010100,0x00010101,0x01010100,
289    0x00010101,0x00000001,0x00010101,0x01000001,0x00010101,0x00010001,0x00010101,0x01010001,
290    0x00010101,0x00000101,0x00010101,0x01000101,0x00010101,0x00010101,0x00010101,0x01010101,
291    0x01010101,0x00000000,0x01010101,0x01000000,0x01010101,0x00010000,0x01010101,0x01010000,
292    0x01010101,0x00000100,0x01010101,0x01000100,0x01010101,0x00010100,0x01010101,0x01010100,
293    0x01010101,0x00000001,0x01010101,0x01000001,0x01010101,0x00010001,0x01010101,0x01010001,
294    0x01010101,0x00000101,0x01010101,0x01000101,0x01010101,0x00010101,0x01010101,0x01010101
295 };
296 
297 uint32_t M3Map[0x200] = {
298    0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
299    0x00000000,0x02020202,0x00000000,0x02020202,0x00000000,0x02020202,0x00000000,0x02020202,
300    0x02020202,0x00000000,0x02020202,0x00000000,0x02020202,0x00000000,0x02020202,0x00000000,
301    0x02020202,0x02020202,0x02020202,0x02020202,0x02020202,0x02020202,0x02020202,0x02020202,
302    0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
303    0x00000000,0x02020202,0x00000000,0x02020202,0x00000000,0x02020202,0x00000000,0x02020202,
304    0x02020202,0x00000000,0x02020202,0x00000000,0x02020202,0x00000000,0x02020202,0x00000000,
305    0x02020202,0x02020202,0x02020202,0x02020202,0x02020202,0x02020202,0x02020202,0x02020202,
306    0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
307    0x00000000,0x02020202,0x00000000,0x02020202,0x00000000,0x02020202,0x00000000,0x02020202,
308    0x02020202,0x00000000,0x02020202,0x00000000,0x02020202,0x00000000,0x02020202,0x00000000,
309    0x02020202,0x02020202,0x02020202,0x02020202,0x02020202,0x02020202,0x02020202,0x02020202,
310    0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
311    0x00000000,0x02020202,0x00000000,0x02020202,0x00000000,0x02020202,0x00000000,0x02020202,
312    0x02020202,0x00000000,0x02020202,0x00000000,0x02020202,0x00000000,0x02020202,0x00000000,
313    0x02020202,0x02020202,0x02020202,0x02020202,0x02020202,0x02020202,0x02020202,0x02020202,
314    0x00000000,0x01010101,0x00000000,0x01010101,0x00000000,0x01010101,0x00000000,0x01010101,
315    0x00000000,0x03030303,0x00000000,0x03030303,0x00000000,0x03030303,0x00000000,0x03030303,
316    0x02020202,0x01010101,0x02020202,0x01010101,0x02020202,0x01010101,0x02020202,0x01010101,
317    0x02020202,0x03030303,0x02020202,0x03030303,0x02020202,0x03030303,0x02020202,0x03030303,
318    0x00000000,0x01010101,0x00000000,0x01010101,0x00000000,0x01010101,0x00000000,0x01010101,
319    0x00000000,0x03030303,0x00000000,0x03030303,0x00000000,0x03030303,0x00000000,0x03030303,
320    0x02020202,0x01010101,0x02020202,0x01010101,0x02020202,0x01010101,0x02020202,0x01010101,
321    0x02020202,0x03030303,0x02020202,0x03030303,0x02020202,0x03030303,0x02020202,0x03030303,
322    0x00000000,0x01010101,0x00000000,0x01010101,0x00000000,0x01010101,0x00000000,0x01010101,
323    0x00000000,0x03030303,0x00000000,0x03030303,0x00000000,0x03030303,0x00000000,0x03030303,
324    0x02020202,0x01010101,0x02020202,0x01010101,0x02020202,0x01010101,0x02020202,0x01010101,
325    0x02020202,0x03030303,0x02020202,0x03030303,0x02020202,0x03030303,0x02020202,0x03030303,
326    0x00000000,0x01010101,0x00000000,0x01010101,0x00000000,0x01010101,0x00000000,0x01010101,
327    0x00000000,0x03030303,0x00000000,0x03030303,0x00000000,0x03030303,0x00000000,0x03030303,
328    0x02020202,0x01010101,0x02020202,0x01010101,0x02020202,0x01010101,0x02020202,0x01010101,
329    0x02020202,0x03030303,0x02020202,0x03030303,0x02020202,0x03030303,0x02020202,0x03030303,
330    0x01010101,0x00000000,0x01010101,0x00000000,0x01010101,0x00000000,0x01010101,0x00000000,
331    0x01010101,0x02020202,0x01010101,0x02020202,0x01010101,0x02020202,0x01010101,0x02020202,
332    0x03030303,0x00000000,0x03030303,0x00000000,0x03030303,0x00000000,0x03030303,0x00000000,
333    0x03030303,0x02020202,0x03030303,0x02020202,0x03030303,0x02020202,0x03030303,0x02020202,
334    0x01010101,0x00000000,0x01010101,0x00000000,0x01010101,0x00000000,0x01010101,0x00000000,
335    0x01010101,0x02020202,0x01010101,0x02020202,0x01010101,0x02020202,0x01010101,0x02020202,
336    0x03030303,0x00000000,0x03030303,0x00000000,0x03030303,0x00000000,0x03030303,0x00000000,
337    0x03030303,0x02020202,0x03030303,0x02020202,0x03030303,0x02020202,0x03030303,0x02020202,
338    0x01010101,0x00000000,0x01010101,0x00000000,0x01010101,0x00000000,0x01010101,0x00000000,
339    0x01010101,0x02020202,0x01010101,0x02020202,0x01010101,0x02020202,0x01010101,0x02020202,
340    0x03030303,0x00000000,0x03030303,0x00000000,0x03030303,0x00000000,0x03030303,0x00000000,
341    0x03030303,0x02020202,0x03030303,0x02020202,0x03030303,0x02020202,0x03030303,0x02020202,
342    0x01010101,0x00000000,0x01010101,0x00000000,0x01010101,0x00000000,0x01010101,0x00000000,
343    0x01010101,0x02020202,0x01010101,0x02020202,0x01010101,0x02020202,0x01010101,0x02020202,
344    0x03030303,0x00000000,0x03030303,0x00000000,0x03030303,0x00000000,0x03030303,0x00000000,
345    0x03030303,0x02020202,0x03030303,0x02020202,0x03030303,0x02020202,0x03030303,0x02020202,
346    0x01010101,0x01010101,0x01010101,0x01010101,0x01010101,0x01010101,0x01010101,0x01010101,
347    0x01010101,0x03030303,0x01010101,0x03030303,0x01010101,0x03030303,0x01010101,0x03030303,
348    0x03030303,0x01010101,0x03030303,0x01010101,0x03030303,0x01010101,0x03030303,0x01010101,
349    0x03030303,0x03030303,0x03030303,0x03030303,0x03030303,0x03030303,0x03030303,0x03030303,
350    0x01010101,0x01010101,0x01010101,0x01010101,0x01010101,0x01010101,0x01010101,0x01010101,
351    0x01010101,0x03030303,0x01010101,0x03030303,0x01010101,0x03030303,0x01010101,0x03030303,
352    0x03030303,0x01010101,0x03030303,0x01010101,0x03030303,0x01010101,0x03030303,0x01010101,
353    0x03030303,0x03030303,0x03030303,0x03030303,0x03030303,0x03030303,0x03030303,0x03030303,
354    0x01010101,0x01010101,0x01010101,0x01010101,0x01010101,0x01010101,0x01010101,0x01010101,
355    0x01010101,0x03030303,0x01010101,0x03030303,0x01010101,0x03030303,0x01010101,0x03030303,
356    0x03030303,0x01010101,0x03030303,0x01010101,0x03030303,0x01010101,0x03030303,0x01010101,
357    0x03030303,0x03030303,0x03030303,0x03030303,0x03030303,0x03030303,0x03030303,0x03030303,
358    0x01010101,0x01010101,0x01010101,0x01010101,0x01010101,0x01010101,0x01010101,0x01010101,
359    0x01010101,0x03030303,0x01010101,0x03030303,0x01010101,0x03030303,0x01010101,0x03030303,
360    0x03030303,0x01010101,0x03030303,0x01010101,0x03030303,0x01010101,0x03030303,0x01010101,
361    0x03030303,0x03030303,0x03030303,0x03030303,0x03030303,0x03030303,0x03030303,0x03030303
362 };
363 
364 uint32_t M0hMap[0x100] = {
365    0x00000000,0x08080000,0x00000808,0x08080808,0x02020000,0x0A0A0000,0x02020808,0x0A0A0808,
366    0x00000202,0x08080202,0x00000A0A,0x08080A0A,0x02020202,0x0A0A0202,0x02020A0A,0x0A0A0A0A,
367    0x04040000,0x0C0C0000,0x04040808,0x0C0C0808,0x06060000,0x0E0E0000,0x06060808,0x0E0E0808,
368    0x04040202,0x0C0C0202,0x04040A0A,0x0C0C0A0A,0x06060202,0x0E0E0202,0x06060A0A,0x0E0E0A0A,
369    0x00000404,0x08080404,0x00000C0C,0x08080C0C,0x02020404,0x0A0A0404,0x02020C0C,0x0A0A0C0C,
370    0x00000606,0x08080606,0x00000E0E,0x08080E0E,0x02020606,0x0A0A0606,0x02020E0E,0x0A0A0E0E,
371    0x04040404,0x0C0C0404,0x04040C0C,0x0C0C0C0C,0x06060404,0x0E0E0404,0x06060C0C,0x0E0E0C0C,
372    0x04040606,0x0C0C0606,0x04040E0E,0x0C0C0E0E,0x06060606,0x0E0E0606,0x06060E0E,0x0E0E0E0E,
373    0x01010000,0x09090000,0x01010808,0x09090808,0x03030000,0x0B0B0000,0x03030808,0x0B0B0808,
374    0x01010202,0x09090202,0x01010A0A,0x09090A0A,0x03030202,0x0B0B0202,0x03030A0A,0x0B0B0A0A,
375    0x05050000,0x0D0D0000,0x05050808,0x0D0D0808,0x07070000,0x0F0F0000,0x07070808,0x0F0F0808,
376    0x05050202,0x0D0D0202,0x05050A0A,0x0D0D0A0A,0x07070202,0x0F0F0202,0x07070A0A,0x0F0F0A0A,
377    0x01010404,0x09090404,0x01010C0C,0x09090C0C,0x03030404,0x0B0B0404,0x03030C0C,0x0B0B0C0C,
378    0x01010606,0x09090606,0x01010E0E,0x09090E0E,0x03030606,0x0B0B0606,0x03030E0E,0x0B0B0E0E,
379    0x05050404,0x0D0D0404,0x05050C0C,0x0D0D0C0C,0x07070404,0x0F0F0404,0x07070C0C,0x0F0F0C0C,
380    0x05050606,0x0D0D0606,0x05050E0E,0x0D0D0E0E,0x07070606,0x0F0F0606,0x07070E0E,0x0F0F0E0E,
381    0x00000101,0x08080101,0x00000909,0x08080909,0x02020101,0x0A0A0101,0x02020909,0x0A0A0909,
382    0x00000303,0x08080303,0x00000B0B,0x08080B0B,0x02020303,0x0A0A0303,0x02020B0B,0x0A0A0B0B,
383    0x04040101,0x0C0C0101,0x04040909,0x0C0C0909,0x06060101,0x0E0E0101,0x06060909,0x0E0E0909,
384    0x04040303,0x0C0C0303,0x04040B0B,0x0C0C0B0B,0x06060303,0x0E0E0303,0x06060B0B,0x0E0E0B0B,
385    0x00000505,0x08080505,0x00000D0D,0x08080D0D,0x02020505,0x0A0A0505,0x02020D0D,0x0A0A0D0D,
386    0x00000707,0x08080707,0x00000F0F,0x08080F0F,0x02020707,0x0A0A0707,0x02020F0F,0x0A0A0F0F,
387    0x04040505,0x0C0C0505,0x04040D0D,0x0C0C0D0D,0x06060505,0x0E0E0505,0x06060D0D,0x0E0E0D0D,
388    0x04040707,0x0C0C0707,0x04040F0F,0x0C0C0F0F,0x06060707,0x0E0E0707,0x06060F0F,0x0E0E0F0F,
389    0x01010101,0x09090101,0x01010909,0x09090909,0x03030101,0x0B0B0101,0x03030909,0x0B0B0909,
390    0x01010303,0x09090303,0x01010B0B,0x09090B0B,0x03030303,0x0B0B0303,0x03030B0B,0x0B0B0B0B,
391    0x05050101,0x0D0D0101,0x05050909,0x0D0D0909,0x07070101,0x0F0F0101,0x07070909,0x0F0F0909,
392    0x05050303,0x0D0D0303,0x05050B0B,0x0D0D0B0B,0x07070303,0x0F0F0303,0x07070B0B,0x0F0F0B0B,
393    0x01010505,0x09090505,0x01010D0D,0x09090D0D,0x03030505,0x0B0B0505,0x03030D0D,0x0B0B0D0D,
394    0x01010707,0x09090707,0x01010F0F,0x09090F0F,0x03030707,0x0B0B0707,0x03030F0F,0x0B0B0F0F,
395    0x05050505,0x0D0D0505,0x05050D0D,0x0D0D0D0D,0x07070505,0x0F0F0505,0x07070D0D,0x0F0F0D0D,
396    0x05050707,0x0D0D0707,0x05050F0F,0x0D0D0F0F,0x07070707,0x0F0F0707,0x07070F0F,0x0F0F0F0F
397 };
398 
399 uint32_t M1hMap[0x100] = {
400    0x00000000,0x02000000,0x00020000,0x02020000,0x00000200,0x02000200,0x00020200,0x02020200,
401    0x00000002,0x02000002,0x00020002,0x02020002,0x00000202,0x02000202,0x00020202,0x02020202,
402    0x01000000,0x03000000,0x01020000,0x03020000,0x01000200,0x03000200,0x01020200,0x03020200,
403    0x01000002,0x03000002,0x01020002,0x03020002,0x01000202,0x03000202,0x01020202,0x03020202,
404    0x00010000,0x02010000,0x00030000,0x02030000,0x00010200,0x02010200,0x00030200,0x02030200,
405    0x00010002,0x02010002,0x00030002,0x02030002,0x00010202,0x02010202,0x00030202,0x02030202,
406    0x01010000,0x03010000,0x01030000,0x03030000,0x01010200,0x03010200,0x01030200,0x03030200,
407    0x01010002,0x03010002,0x01030002,0x03030002,0x01010202,0x03010202,0x01030202,0x03030202,
408    0x00000100,0x02000100,0x00020100,0x02020100,0x00000300,0x02000300,0x00020300,0x02020300,
409    0x00000102,0x02000102,0x00020102,0x02020102,0x00000302,0x02000302,0x00020302,0x02020302,
410    0x01000100,0x03000100,0x01020100,0x03020100,0x01000300,0x03000300,0x01020300,0x03020300,
411    0x01000102,0x03000102,0x01020102,0x03020102,0x01000302,0x03000302,0x01020302,0x03020302,
412    0x00010100,0x02010100,0x00030100,0x02030100,0x00010300,0x02010300,0x00030300,0x02030300,
413    0x00010102,0x02010102,0x00030102,0x02030102,0x00010302,0x02010302,0x00030302,0x02030302,
414    0x01010100,0x03010100,0x01030100,0x03030100,0x01010300,0x03010300,0x01030300,0x03030300,
415    0x01010102,0x03010102,0x01030102,0x03030102,0x01010302,0x03010302,0x01030302,0x03030302,
416    0x00000001,0x02000001,0x00020001,0x02020001,0x00000201,0x02000201,0x00020201,0x02020201,
417    0x00000003,0x02000003,0x00020003,0x02020003,0x00000203,0x02000203,0x00020203,0x02020203,
418    0x01000001,0x03000001,0x01020001,0x03020001,0x01000201,0x03000201,0x01020201,0x03020201,
419    0x01000003,0x03000003,0x01020003,0x03020003,0x01000203,0x03000203,0x01020203,0x03020203,
420    0x00010001,0x02010001,0x00030001,0x02030001,0x00010201,0x02010201,0x00030201,0x02030201,
421    0x00010003,0x02010003,0x00030003,0x02030003,0x00010203,0x02010203,0x00030203,0x02030203,
422    0x01010001,0x03010001,0x01030001,0x03030001,0x01010201,0x03010201,0x01030201,0x03030201,
423    0x01010003,0x03010003,0x01030003,0x03030003,0x01010203,0x03010203,0x01030203,0x03030203,
424    0x00000101,0x02000101,0x00020101,0x02020101,0x00000301,0x02000301,0x00020301,0x02020301,
425    0x00000103,0x02000103,0x00020103,0x02020103,0x00000303,0x02000303,0x00020303,0x02020303,
426    0x01000101,0x03000101,0x01020101,0x03020101,0x01000301,0x03000301,0x01020301,0x03020301,
427    0x01000103,0x03000103,0x01020103,0x03020103,0x01000303,0x03000303,0x01020303,0x03020303,
428    0x00010101,0x02010101,0x00030101,0x02030101,0x00010301,0x02010301,0x00030301,0x02030301,
429    0x00010103,0x02010103,0x00030103,0x02030103,0x00010303,0x02010303,0x00030303,0x02030303,
430    0x01010101,0x03010101,0x01030101,0x03030101,0x01010301,0x03010301,0x01030301,0x03030301,
431    0x01010103,0x03010103,0x01030103,0x03030103,0x01010303,0x03010303,0x01030303,0x03030303
432 };
433 
434 // 0x21 = 33 is the anti-aliasing color for mode 2 in halved resolution
435 uint32_t M2hMap[0x100] = {
436    0x00000000,0x21000000,0x21000000,0x01000000,0x00210000,0x21210000,0x21210000,0x01210000,
437    0x00210000,0x21210000,0x21210000,0x01210000,0x00010000,0x21010000,0x21010000,0x01010000,
438    0x00002100,0x21002100,0x21002100,0x01002100,0x00212100,0x21212100,0x21212100,0x01212100,
439    0x00212100,0x21212100,0x21212100,0x01212100,0x00012100,0x21012100,0x21012100,0x01012100,
440    0x00002100,0x21002100,0x21002100,0x01002100,0x00212100,0x21212100,0x21212100,0x01212100,
441    0x00212100,0x21212100,0x21212100,0x01212100,0x00012100,0x21012100,0x21012100,0x01012100,
442    0x00000100,0x21000100,0x21000100,0x01000100,0x00210100,0x21210100,0x21210100,0x01210100,
443    0x00210100,0x21210100,0x21210100,0x01210100,0x00010100,0x21010100,0x21010100,0x01010100,
444    0x00000021,0x21000021,0x21000021,0x01000021,0x00210021,0x21210021,0x21210021,0x01210021,
445    0x00210021,0x21210021,0x21210021,0x01210021,0x00010021,0x21010021,0x21010021,0x01010021,
446    0x00002121,0x21002121,0x21002121,0x01002121,0x00212121,0x21212121,0x21212121,0x01212121,
447    0x00212121,0x21212121,0x21212121,0x01212121,0x00012121,0x21012121,0x21012121,0x01012121,
448    0x00002121,0x21002121,0x21002121,0x01002121,0x00212121,0x21212121,0x21212121,0x01212121,
449    0x00212121,0x21212121,0x21212121,0x01212121,0x00012121,0x21012121,0x21012121,0x01012121,
450    0x00000121,0x21000121,0x21000121,0x01000121,0x00210121,0x21210121,0x21210121,0x01210121,
451    0x00210121,0x21210121,0x21210121,0x01210121,0x00010121,0x21010121,0x21010121,0x01010121,
452    0x00000021,0x21000021,0x21000021,0x01000021,0x00210021,0x21210021,0x21210021,0x01210021,
453    0x00210021,0x21210021,0x21210021,0x01210021,0x00010021,0x21010021,0x21010021,0x01010021,
454    0x00002121,0x21002121,0x21002121,0x01002121,0x00212121,0x21212121,0x21212121,0x01212121,
455    0x00212121,0x21212121,0x21212121,0x01212121,0x00012121,0x21012121,0x21012121,0x01012121,
456    0x00002121,0x21002121,0x21002121,0x01002121,0x00212121,0x21212121,0x21212121,0x01212121,
457    0x00212121,0x21212121,0x21212121,0x01212121,0x00012121,0x21012121,0x21012121,0x01012121,
458    0x00000121,0x21000121,0x21000121,0x01000121,0x00210121,0x21210121,0x21210121,0x01210121,
459    0x00210121,0x21210121,0x21210121,0x01210121,0x00010121,0x21010121,0x21010121,0x01010121,
460    0x00000001,0x21000001,0x21000001,0x01000001,0x00210001,0x21210001,0x21210001,0x01210001,
461    0x00210001,0x21210001,0x21210001,0x01210001,0x00010001,0x21010001,0x21010001,0x01010001,
462    0x00002101,0x21002101,0x21002101,0x01002101,0x00212101,0x21212101,0x21212101,0x01212101,
463    0x00212101,0x21212101,0x21212101,0x01212101,0x00012101,0x21012101,0x21012101,0x01012101,
464    0x00002101,0x21002101,0x21002101,0x01002101,0x00212101,0x21212101,0x21212101,0x01212101,
465    0x00212101,0x21212101,0x21212101,0x01212101,0x00012101,0x21012101,0x21012101,0x01012101,
466    0x00000101,0x21000101,0x21000101,0x01000101,0x00210101,0x21210101,0x21210101,0x01210101,
467    0x00210101,0x21210101,0x21210101,0x01210101,0x00010101,0x21010101,0x21010101,0x01010101
468 };
469 
470 uint32_t M3hMap[0x100] = {
471    0x00000000,0x00000000,0x00000000,0x00000000,0x02020000,0x02020000,0x02020000,0x02020000,
472    0x00000202,0x00000202,0x00000202,0x00000202,0x02020202,0x02020202,0x02020202,0x02020202,
473    0x00000000,0x00000000,0x00000000,0x00000000,0x02020000,0x02020000,0x02020000,0x02020000,
474    0x00000202,0x00000202,0x00000202,0x00000202,0x02020202,0x02020202,0x02020202,0x02020202,
475    0x00000000,0x00000000,0x00000000,0x00000000,0x02020000,0x02020000,0x02020000,0x02020000,
476    0x00000202,0x00000202,0x00000202,0x00000202,0x02020202,0x02020202,0x02020202,0x02020202,
477    0x00000000,0x00000000,0x00000000,0x00000000,0x02020000,0x02020000,0x02020000,0x02020000,
478    0x00000202,0x00000202,0x00000202,0x00000202,0x02020202,0x02020202,0x02020202,0x02020202,
479    0x01010000,0x01010000,0x01010000,0x01010000,0x03030000,0x03030000,0x03030000,0x03030000,
480    0x01010202,0x01010202,0x01010202,0x01010202,0x03030202,0x03030202,0x03030202,0x03030202,
481    0x01010000,0x01010000,0x01010000,0x01010000,0x03030000,0x03030000,0x03030000,0x03030000,
482    0x01010202,0x01010202,0x01010202,0x01010202,0x03030202,0x03030202,0x03030202,0x03030202,
483    0x01010000,0x01010000,0x01010000,0x01010000,0x03030000,0x03030000,0x03030000,0x03030000,
484    0x01010202,0x01010202,0x01010202,0x01010202,0x03030202,0x03030202,0x03030202,0x03030202,
485    0x01010000,0x01010000,0x01010000,0x01010000,0x03030000,0x03030000,0x03030000,0x03030000,
486    0x01010202,0x01010202,0x01010202,0x01010202,0x03030202,0x03030202,0x03030202,0x03030202,
487    0x00000101,0x00000101,0x00000101,0x00000101,0x02020101,0x02020101,0x02020101,0x02020101,
488    0x00000303,0x00000303,0x00000303,0x00000303,0x02020303,0x02020303,0x02020303,0x02020303,
489    0x00000101,0x00000101,0x00000101,0x00000101,0x02020101,0x02020101,0x02020101,0x02020101,
490    0x00000303,0x00000303,0x00000303,0x00000303,0x02020303,0x02020303,0x02020303,0x02020303,
491    0x00000101,0x00000101,0x00000101,0x00000101,0x02020101,0x02020101,0x02020101,0x02020101,
492    0x00000303,0x00000303,0x00000303,0x00000303,0x02020303,0x02020303,0x02020303,0x02020303,
493    0x00000101,0x00000101,0x00000101,0x00000101,0x02020101,0x02020101,0x02020101,0x02020101,
494    0x00000303,0x00000303,0x00000303,0x00000303,0x02020303,0x02020303,0x02020303,0x02020303,
495    0x01010101,0x01010101,0x01010101,0x01010101,0x03030101,0x03030101,0x03030101,0x03030101,
496    0x01010303,0x01010303,0x01010303,0x01010303,0x03030303,0x03030303,0x03030303,0x03030303,
497    0x01010101,0x01010101,0x01010101,0x01010101,0x03030101,0x03030101,0x03030101,0x03030101,
498    0x01010303,0x01010303,0x01010303,0x01010303,0x03030303,0x03030303,0x03030303,0x03030303,
499    0x01010101,0x01010101,0x01010101,0x01010101,0x03030101,0x03030101,0x03030101,0x03030101,
500    0x01010303,0x01010303,0x01010303,0x01010303,0x03030303,0x03030303,0x03030303,0x03030303,
501    0x01010101,0x01010101,0x01010101,0x01010101,0x03030101,0x03030101,0x03030101,0x03030101,
502    0x01010303,0x01010303,0x01010303,0x01010303,0x03030303,0x03030303,0x03030303,0x03030303
503 };
504 
505 
update_skew(void)506 void update_skew(void)
507 {
508    new_dt.NewHDSPTIMG |= 0x02; // enable horizontal DISPTMG by default
509    uint32_t skew = (CRTC.registers[8] >> 4) & 3; // isolate the display skew
510    if (skew == 3) { // disable output?
511       new_dt.NewHDSPTIMG &= 0xfd; // disable horizontal DISPTMG
512    } else {
513       CRTC.hstart = skew; // position at which horizontal display starts
514       CRTC.hend = CRTC.hstart + CRTC.registers[1]; // position at which it ends
515    }
516    if(asic.extend_border)
517       CRTC.hstart++;
518 }
519 
change_mode(void)520 static INLINE void change_mode(void)
521 {
522    if (CRTC.flag_hadhsync) { // have we had an HSYNC on this scan line?
523       CRTC.flag_hadhsync = 0;
524       GateArray.scr_mode = GateArray.requested_scr_mode; // execute mode change
525 
526      ModeMap = ModeMaps[GateArray.scr_mode]; // update ModeMap pointer
527 
528    }
529 }
530 
end_vdu_hsync(void)531 static INLINE void end_vdu_hsync(void)
532 {
533    int temp;
534 
535    CRTC.flag_inmonhsync = 0;
536    iMonHSPeakToEnd = iMonHSPeakPos;
537    if (HadP) {
538       HadP = 0;
539       if (iMonHSPeakPos >= iMonHSStartPos) {
540          temp = iMonHSEndPos - HSyncDuration;
541          if (temp < MonFreeSync) {
542             if (MonFreeSync != MinHSync) {
543                MonFreeSync--;
544             }
545          } else if (temp > MonFreeSync) {
546             if (MonFreeSync != MaxHSync) {
547                MonFreeSync++;
548             }
549          }
550          temp = iMonHSPeakToEnd - iMonHSEndToPeak;
551          if (temp < 0) {
552             temp = -temp;
553             if (temp > iMonHSStartPos) {
554                temp = iMonHSStartPos;
555             }
556             temp >>= 3;
557             if (!temp) {
558                temp++;
559             }
560             if (temp > MAX_SYNC_INC) {
561                temp = MAX_SYNC_INC;
562             }
563             MonHSYNC = MonFreeSync + temp;
564             if (MonHSYNC > MaxHSync) {
565                MonHSYNC = MaxHSync;
566             }
567          } else {
568             if (temp > iMonHSStartPos) {
569                temp = iMonHSStartPos;
570             }
571             temp >>= 3;
572             if (!temp) {
573                temp++;
574             }
575             if (temp > MAX_SYNC_DEC) {
576                temp = MAX_SYNC_DEC;
577             }
578             MonHSYNC = MonFreeSync - temp;
579             if (MonHSYNC < MinHSync) {
580                MonHSYNC = MinHSync;
581             }
582          }
583       } else {
584          temp = iMonHSStartToPeak - iMonHSPeakToEnd;
585          if (!temp) {
586             MonHSYNC = MonFreeSync;
587          } else if (temp < 0) {
588             temp = -temp;
589             if (temp > iMonHSStartPos) {
590                temp = iMonHSStartPos;
591             }
592             temp >>= 3;
593             if (!temp) {
594                temp++;
595             }
596             if (temp > MAX_SYNC_INC) {
597                temp = MAX_SYNC_INC;
598             }
599             MonHSYNC = MonFreeSync + temp;
600             if (MonHSYNC > MaxHSync) {
601                MonHSYNC = MaxHSync;
602             }
603          } else if (temp > 0) {
604             if (temp > iMonHSStartPos) {
605                temp = iMonHSStartPos;
606             }
607             temp >>= 3;
608             if (!temp) {
609                temp++;
610             }
611             if (temp > MAX_SYNC_DEC) {
612                temp = MAX_SYNC_DEC;
613             }
614             MonHSYNC = MonFreeSync - temp;
615             if (MonHSYNC < MinHSync) {
616                MonHSYNC = MinHSync;
617             }
618          }
619       }
620    }
621    iMonHSEndPos = 0;
622 }
623 
match_line_count(void)624 static INLINE void match_line_count(void)
625 {
626    if (CRTC.line_count == CRTC.registers[6]) { // matches vertical displayed?
627       new_dt.NewDISPTIMG = 0; // disable vertical DISPTMG
628    }
629    if (CRTC.line_count == CRTC.registers[7]) { // matches vertical sync position?
630       if (CRTC.last_hend >= 2) { // line length was at least 2 chars?
631          if (!CRTC.r7match) {
632             CRTC.flag_resvsync = 0;
633             if (!CRTC.flag_invsync) { // not in VSYNC?
634                CRTC.vsw_count = 0; // reset vertical sync width counter
635                CRTC.flag_invsync = 1; // enter VSYNC
636                flags1.monVSYNC = 26; // enter vertical blanking period for 26 scanlines
637                GateArray.hs_count = 2; // GA delays its VSYNC by two CRTC HSYNCs
638             }
639          }
640       }
641       CRTC.r7match = 1;
642    } else {
643       CRTC.r7match = 0;
644    }
645 }
646 
reload_addr(void)647 static INLINE void reload_addr(void)
648 {
649    if (CRTC.line_count == 0) { // has line count been reset?
650       new_dt.NewDISPTIMG = 0xff; // enable vertical DISPTMG
651       CRTC.addr =
652       CRTC.next_addr = CRTC.requested_addr; // load with screen start address
653    }
654    match_line_count();
655 }
656 
restart_frame(void)657 static INLINE void restart_frame(void)
658 {
659    CRTC.flag_invta = 0;
660    CRTC.flag_resframe = 0;
661    CRTC.flag_resscan = 0;
662    CRTC.flag_reschar = 0;
663    CRTC.raster_count = 0; // reset raster line counter
664    CRTC.scr_base = 0;
665    CRTC.line_count = 0; // reset character line counter
666    CRTC.sl_count = 0; // reset scan line counter
667    reload_addr();
668 }
669 
match_hsw(void)670 static INLINE void match_hsw(void)
671 {
672    if (CRTC.hsw_count == CRTC.hsw) { // matches horizontal sync width?
673       GateArray.sl_count++; // update GA scan line counter
674       if (GateArray.sl_count == 52) { // trigger interrupt?
675          if (CRTC.interrupt_sl == 0) { // ASIC interrupt
676             z80.int_pending = 1; // queue Z80 interrupt
677          }
678          GateArray.sl_count = 0; // clear counter
679       } else if (CRTC.sl_count == CRTC.interrupt_sl && CRTC.interrupt_sl != 0) { // ASIC interrupt
680          z80.int_pending = 1;
681       }
682       if (GateArray.hs_count) { // delaying on VSYNC?
683          GateArray.hs_count--;
684          if (!GateArray.hs_count) {
685             if (GateArray.sl_count >= 32 && CRTC.interrupt_sl == 0) { // counter above save margin?
686                z80.int_pending = 1; // queue interrupt
687             }
688             GateArray.sl_count = 0; // clear counter
689          }
690       }
691       flags1.inHSYNC = 0; // turn HSYNC off
692       if (flags1.monVSYNC) { // in vertical blanking period?
693          flags1.monVSYNC--; // update counter
694       }
695       change_mode(); // process possible mode change
696       if (CRTC.flag_inmonhsync) { // monitor HSYNC still active?
697          end_vdu_hsync();
698       }
699    } else {
700       CRTC.hsw_count++; // update counter
701       CRTC.hsw_count &= 15; // limit to 4 bits
702       if (CRTC.hsw_count == 3) { // ready to start monitor HSYNC?
703          CRTC.flag_inmonhsync = 1; // enter monitor HSYNC
704          iMonHSStartPos = 0;
705          iMonHSPeakToStart = iMonHSPeakPos;
706          asic_dma_cycle();
707       } else if (CRTC.hsw_count == 7) { // reached GA HSYNC output cutoff?
708          change_mode();
709          end_vdu_hsync();
710       }
711    }
712 }
713 
714 
715 
NoChar(void)716 void NoChar(void)
717 {
718    // nothing to do
719 }
720 
721 
722 
CharSL2(void)723 void CharSL2(void)
724 {
725    CRTC.reg5 = CRTC.registers[5];
726    CRTC.CharInstSL = (void(*)(void))NoChar;
727 }
728 
729 
730 
CharSL1(void)731 void CharSL1(void)
732 {
733    CRTC.CharInstSL = (void(*)(void))CharSL2;
734 }
735 
736 
737 
CharMR2(void)738 void CharMR2(void)
739 {
740    if (CRTC.flag_startvta) { // starting vertical total adjust?
741       if (CRTC.line_count == CRTC.registers[4]) { // matches vertical total?
742          if (CRTC.registers[5] == 0) { // no vertical total adjust?
743             CRTC.flag_resnext = 1; // request a frame restart
744          }
745       }
746    }
747    CRTC.CharInstMR = (void(*)(void))NoChar;
748 }
749 
750 
751 
CharMR1(void)752 void CharMR1(void)
753 {
754    if ((CRTC.raster_count == CRTC.registers[9]) && (CRTC.line_count == CRTC.registers[4])) {
755       CRTC.flag_invta = 0;
756       CRTC.flag_startvta = 1; // request start of vertical total adjust
757    } else {
758       CRTC.flag_startvta = 0; // not yet at end of frame
759    }
760    CRTC.CharInstMR = (void(*)(void))CharMR2;
761 }
762 
763 
764 
frame_finished(void)765 void frame_finished(void)
766 {
767 /*   if (VDU.scrln < MAX_DRAWN) { // monitor line below maximum visible?
768       int cnt = (MAX_DRAWN - VDU.scrln) << 1; // number of lines remaining to be drawn
769       uint32_t *addr = CPC.scr_base;
770       while (cnt--) {
771          uint32_t *tmp_addr = addr;
772          for (int n = CPC.scr_bpp * 24; n; n--) {
773             *tmp_addr++ = 0; // clear old surface contents
774          }
775          addr += CPC.scr_bps; // advance surface pointer
776       }
777    }
778 */   VDU.frame_completed = 1; // emulation loop exit condition met
779    VDU.scrln = -(((VDU.scanline - MIN_VHOLD) + 1) >> 1);
780    VDU.scanline = 0;
781    VDU.flag_drawing = 0;
782 }
783 
784 
785 
prerender_border(void)786 void prerender_border(void)
787 {
788    memset(RendPos, 0x10, sizeof(*RendPos) * 4);
789    RendPos += 4;
790 }
791 
792 
793 
prerender_border_half(void)794 void prerender_border_half(void)
795 {
796    memset(RendPos, 0x10, sizeof(*RendPos) * 2);
797    RendPos += 2;
798 }
799 
800 
801 
prerender_sync(void)802 void prerender_sync(void)
803 {
804    register uint32_t dwVal = 0x11111111;
805    *RendPos = dwVal;
806    *(RendPos + 1) = dwVal;
807    *(RendPos + 2) = dwVal;
808    *(RendPos + 3) = dwVal;
809    RendPos += 4;
810 }
811 
812 
813 
prerender_sync_half(void)814 void prerender_sync_half(void)
815 {
816    register uint32_t dwVal = 0x11111111;
817    *RendPos = dwVal;
818    *(RendPos + 1) = dwVal;
819    RendPos += 2;
820 }
821 
822 
get_sprite_asic(unsigned short offset)823 static INLINE uint8_t get_sprite_asic(unsigned short offset)
824 {
825    const int borderWidth = 64 + (asic.extend_border ? 16 : 0);
826    const int borderHeight = 40 + 8*(30 - CRTC.registers[7]);
827    const int screenWidth = 640 + borderWidth;
828    const int screenHeight = 400 + borderHeight; // FIXME 200¿?
829    int i = 0;
830    int x = 2 * (CPC.scr_pos + offset - CPC.scr_base) / dwXScale - borderWidth;
831    int y = VDU.scrln - borderHeight;
832    if (x >= 0 && x < screenWidth && y >= 0 && y < screenHeight) {
833       for(i = 0; i < ASIC_SPRITES; i++) {
834          int sx = asic.sprites_x[i];
835          int mx = asic.sprites_mag_x[i];
836          if(mx > 0 && x >= sx && x < sx + 16 * mx) {
837             int sy = asic.sprites_y[i];
838             int my = asic.sprites_mag_y[i];
839             if(my > 0 && y >= sy && y < sy + 16 * my) {
840                int px = (x - sx) / mx;
841                int py = (y - sy) / my;
842                uint8_t pcol = asic.sprites[i][px][py];
843                if(pcol != 0) {
844                   return pcol;
845                }
846             }
847          }
848       }
849    }
850    return 0;
851 }
852 
853 
prerender_normal(void)854 void prerender_normal(void)
855 {
856    uint8_t bVidMem = *(pbRAM + CRTC.next_address);
857    *RendPos = *(ModeMap + (bVidMem * 2));
858    *(RendPos + 1) = *(ModeMap + (bVidMem * 2) + 1);
859    bVidMem = *(pbRAM + CRTC.next_address + 1);
860    *(RendPos + 2) = *(ModeMap + (bVidMem * 2));
861    *(RendPos + 3) = *(ModeMap + (bVidMem * 2) + 1);
862    RendPos += 4;
863 }
864 
865 /* shift_scroll_pixel / byte shift scroll operations
866  * uses PrData as temp buffer
867  *
868  * TODO: need a BIG ENDIAN version
869  * TODO: need alignment-safe version
870  *
871  * b(0x01000000, 0x00000001, 0x00010100, shift:0)=[0x00010100]
872  * b(0x01000000, 0x00000001, 0x00010100, shift:1)=[0x01010000]
873  * b(0x01000000, 0x00000001, 0x00010100, shift:2)=[0x01000000]
874  * b(0x01000000, 0x00000001, 0x00010100, shift:3)=[0x00000000]
875  * b(0x01000000, 0x00000001, 0x00010100, shift:4)=[0x00000001]
876  * ...
877  */
shift_scroll_pixel(int value,int byteShift)878 static INLINE uint32_t shift_scroll_pixel(int value, int byteShift){
879    uint8_t* p =  (((uint8_t*) &PrData[value]) - byteShift);
880    return (*((uint32_t*) p));
881 }
882 /**
883  * added asic functions to PreRender
884  *  Display sprite in prerender instead of render to be independent of screen resolution
885  */
prerender_normal_plus(void)886 void prerender_normal_plus(void)
887 {
888    unsigned int next_address = CRTC.next_address;
889    if(asic.vscroll) {
890       if (CRTC.raster_count + asic.vscroll <= CRTC.registers[9]) {
891          next_address += asic.vscroll * 0x0800;
892       } else {
893          next_address += 80;
894          next_address -= ((CRTC.registers[9] + 1 - asic.vscroll) * 0x0800);
895       }
896    }
897 
898    uint8_t* bVidMem = pbRAM + next_address;
899    // check scroll
900    if(asic.hscroll) {
901       int byteOffset = asic.hscroll / 8;
902       int byteShift = asic.hscroll % 8;
903 
904       bVidMem -= byteOffset;
905       // prerender data
906       PrData[0] = *(ModeMap + ((*(bVidMem - 1)) * 2));
907       PrData[1] = *(ModeMap + ((*(bVidMem - 1)) * 2) + 1);
908       PrData[2] = *(ModeMap + ((*bVidMem) * 2));
909       PrData[3] = *(ModeMap + ((*bVidMem) * 2) + 1);
910       PrData[4] = *(ModeMap + ((*(bVidMem + 1)) * 2));
911       PrData[5] = *(ModeMap + ((*(bVidMem + 1)) * 2) + 1);
912       *RendPos = shift_scroll_pixel(2, byteShift);
913       *(RendPos + 1) = shift_scroll_pixel(3, byteShift);
914       *(RendPos + 2) = shift_scroll_pixel(4, byteShift);
915       *(RendPos + 3) = shift_scroll_pixel(5, byteShift);
916    }
917    else {
918       *RendPos = *(ModeMap + ((*bVidMem) * 2));
919       *(RendPos + 1) = *(ModeMap + ((*bVidMem) * 2) + 1);
920       *(RendPos + 2) = *(ModeMap + ((*(bVidMem + 1)) * 2));
921       *(RendPos + 3) = *(ModeMap + ((*(bVidMem + 1)) * 2) + 1);
922    }
923 
924    // TODO: optimize
925    uint16_t i, offset = 0;
926    for(i = 0; i < 4; i++) {
927       uint8_t c1 = get_sprite_asic(offset++);
928       uint8_t c2 = get_sprite_asic(offset++);
929       uint8_t c3 = get_sprite_asic(offset++);
930       uint8_t c4 = get_sprite_asic(offset++);
931 #if RETRO_IS_BIG_ENDIAN
932       if (c1) {
933          *RendPos = ((*RendPos) & 0x00FFFFFF) | (c1 << 24);
934       }
935       if (c2) {
936          *RendPos = ((*RendPos) & 0xFF00FFFF) | (c2 << 16);
937       }
938       if (c3) {
939          *RendPos = ((*RendPos) & 0xFFFF00FF) | (c3 << 8);
940       }
941       if (c4) {
942          *RendPos = ((*RendPos) & 0xFFFFFF00) | c4;
943       }
944 #else
945       if (c4) {
946          *RendPos = ((*RendPos) & 0x00FFFFFF) | (c4 << 24);
947       }
948       if (c3) {
949          *RendPos = ((*RendPos) & 0xFF00FFFF) | (c3 << 16);
950       }
951       if (c2) {
952          *RendPos = ((*RendPos) & 0xFFFF00FF) | (c2 << 8);
953       }
954       if (c1) {
955          *RendPos = ((*RendPos) & 0xFFFFFF00) | c1;
956       }
957 #endif
958       RendPos++;
959    }
960 }
961 
prerender_normal_half_plus(void)962 void prerender_normal_half_plus(void)
963 {
964    unsigned int next_address = CRTC.next_address;
965    if(asic.vscroll) {
966       if (CRTC.raster_count + asic.vscroll <= CRTC.registers[9]) {
967          next_address += asic.vscroll * 0x0800;
968       } else {
969          next_address += 80;
970          next_address -= ((CRTC.registers[9] + 1 - asic.vscroll) * 0x0800);
971       }
972    }
973 
974    uint8_t* bVidMem = pbRAM + next_address;
975    // check scroll
976    if(asic.hscroll) {
977       int byteOffset = (asic.hscroll / 2) / 4;
978       int byteShift = ((asic.hscroll / 2) % 4);
979 
980       bVidMem -= byteOffset;
981       PrData[3] = PrData[0] = 0;
982       PrData[1] = *(ModeMap + *(bVidMem - 1) );
983       PrData[4] = PrData[2] = *(ModeMap + *bVidMem );
984       PrData[5] = *(ModeMap + *(bVidMem + 1) );
985       *(RendPos) = shift_scroll_pixel(2, byteShift);
986       *(RendPos + 1) = shift_scroll_pixel(5, byteShift);
987    }
988    else {
989       *RendPos = *(ModeMap + (*bVidMem));
990       *(RendPos + 1) = *(ModeMap + (*(bVidMem + 1)) );
991    }
992 
993    uint16_t i, offset = 0;
994    for(i = 0; i < 2; i++) {
995       uint8_t c1 = get_sprite_asic(offset++);
996       uint8_t c2 = get_sprite_asic(offset++);
997       uint8_t c3 = get_sprite_asic(offset++);
998       uint8_t c4 = get_sprite_asic(offset++);
999 #if RETRO_IS_BIG_ENDIAN
1000       if (c1) {
1001          *RendPos = ((*RendPos) & 0x00FFFFFF) | (c1 << 24);
1002       }
1003       if (c2) {
1004          *RendPos = ((*RendPos) & 0xFF00FFFF) | (c2 << 16);
1005       }
1006       if (c3) {
1007          *RendPos = ((*RendPos) & 0xFFFF00FF) | (c3 << 8);
1008       }
1009       if (c4) {
1010          *RendPos = ((*RendPos) & 0xFFFFFF00) | c4;
1011       }
1012 #else
1013       if (c4) {
1014          *RendPos = ((*RendPos) & 0x00FFFFFF) | (c4 << 24);
1015       }
1016       if (c3) {
1017          *RendPos = ((*RendPos) & 0xFF00FFFF) | (c3 << 16);
1018       }
1019       if (c2) {
1020          *RendPos = ((*RendPos) & 0xFFFF00FF) | (c2 << 8);
1021       }
1022       if (c1) {
1023          *RendPos = ((*RendPos) & 0xFFFFFF00) | c1;
1024       }
1025 #endif
1026       RendPos++;
1027    }
1028 }
1029 
prerender_normal_half(void)1030 void prerender_normal_half(void)
1031 {
1032    uint8_t bVidMem = *(pbRAM + CRTC.next_address);
1033    *RendPos = *(ModeMap + bVidMem);
1034    bVidMem = *(pbRAM + CRTC.next_address+1);
1035    *(RendPos + 1) = *(ModeMap + bVidMem);
1036    RendPos += 2;
1037 }
1038 
set_prerender(void)1039 void set_prerender(void)
1040 {
1041    LastPreRend =flags1.combined;
1042 
1043 #ifdef MSB_FIRST
1044    if (LastPreRend == 0x0000ff03)
1045 #else
1046    if (LastPreRend == 0x03ff0000)
1047 #endif
1048    {
1049       PreRender = CPC.scr_prerendernorm;
1050    }
1051    else
1052    {
1053       if (!(uint16_t)LastPreRend)
1054          PreRender = CPC.scr_prerenderbord;
1055       else
1056          PreRender = CPC.scr_prerendersync;
1057    }
1058 }
1059 
render16bpp(void)1060 void render16bpp(void)
1061 {
1062    register uint16_t *pwPos = (uint16_t *)CPC.scr_pos;
1063    register uint8_t bCount = *RendWid++;
1064    while (bCount--) {
1065       *pwPos++ = GateArray.palette[*RendOut++];
1066    }
1067    CPC.scr_pos = (uint32_t *)pwPos;
1068 }
1069 
render16bpp_doubleY(void)1070 void render16bpp_doubleY(void)
1071 {
1072    register uint16_t *pwPos = (uint16_t *)CPC.scr_pos;
1073    register uint16_t dwLineOffs = CPC.scr_bps;
1074    register uint8_t bCount = *RendWid++;
1075    while (bCount--) {
1076       register uint16_t val = GateArray.palette[*RendOut++];
1077       *(pwPos + dwLineOffs) = val;
1078       *pwPos++ = val;
1079    }
1080    CPC.scr_pos = (uint32_t *)pwPos;
1081 }
1082 
1083 
render32bpp(void)1084 void render32bpp(void)
1085 {
1086    register uint8_t bCount = *RendWid++;
1087    while (bCount--) {
1088       *CPC.scr_pos++ = GateArray.palette[*RendOut++];
1089    }
1090 }
1091 
render32bpp_doubleY(void)1092 void render32bpp_doubleY(void)
1093 {
1094    register uint8_t bCount = *RendWid++;
1095    while (bCount--) {
1096       register uint32_t val = GateArray.palette[*RendOut++];
1097       *(CPC.scr_pos + CPC.scr_bps) = val;
1098       *CPC.scr_pos++ = val;
1099    }
1100 }
1101 
crtc_cycle(int repeat_count)1102 void crtc_cycle(int repeat_count)
1103 {
1104    while (repeat_count) {
1105 
1106       if (VDU.flag_drawing) { // are we within the rendering area?
1107          if (HorzChar < HorzMax) { // below horizontal cut-off?
1108             if (flags1.combined != LastPreRend) {
1109                set_prerender(); // change pre-renderer if necessary
1110             }
1111             PreRender(); // translate CPC video memory bytes to entries referencing the palette
1112 
1113             CPC.scr_render(); // render to the video surface at the current bit depth
1114 
1115          }
1116       }
1117 
1118       CRTC.next_address = MAXlate[(CRTC.addr + CRTC.char_count) & 0x73ff] | CRTC.scr_base; // next address for PreRender
1119 
1120       flags1.dt.combined = new_dt.combined; // update the DISPTMG flags
1121 
1122       #ifdef DEBUG_CRTC
1123       if (dwDebugFlag) {
1124          char str[16];
1125          char on[]  = "vhDDHVMa";
1126          char off[] = "........";
1127 
1128          if (CRTC.flag_invsync) {
1129             str[0] = on[0];
1130          } else {
1131             str[0] = off[0];
1132          }
1133          if (flags1.inHSYNC) {
1134             str[1] = on[1];
1135          } else {
1136             str[1] = off[1];
1137          }
1138          if (flags1.dt.HDSPTIMG & 1) {
1139             str[2] = on[2];
1140          } else {
1141             str[2] = off[2];
1142          }
1143          if (flags1.dt.DISPTIMG) {
1144             str[3] = on[3];
1145          } else {
1146             str[3] = off[3];
1147          }
1148          if (CRTC.flag_newscan) {
1149             str[4] = on[4];
1150          } else {
1151             str[4] = off[4];
1152          }
1153          if (CRTC.flag_resframe) {
1154             str[5] = on[5];
1155          } else {
1156             str[5] = off[5];
1157          }
1158          if (CRTC.flag_resscan) {
1159             str[6] = on[6];
1160          } else {
1161             str[6] = off[6];
1162          }
1163          if (CRTC.flag_invta) {
1164             str[7] = on[7];
1165          } else {
1166             str[7] = off[7];
1167          }
1168          str[8] = '\0';
1169 
1170          fprintf(pfoDebug, "%04X | CC:%2X RC:%2X LC:%2X - HSWC:%2X VSWC:%2X - %s %c %2X  mhs%04X mfs%04X  s%04X p%04X e%04X p%04X c%d\r\n",
1171             CRTC.next_address,
1172             CRTC.char_count,
1173             CRTC.raster_count,
1174             CRTC.line_count,
1175             CRTC.hsw_count,
1176             CRTC.vsw_count,
1177             str,
1178             z80.int_pending ? 'I' : '.',
1179             GateArray.sl_count,
1180             MonHSYNC,
1181             MonFreeSync,
1182             iMonHSStartPos,
1183             iMonHSPeakPos,
1184             iMonHSEndPos,
1185             HorzPos,
1186             HorzChar);
1187       }
1188       #endif
1189 
1190       iMonHSStartPos += 0x100;
1191       iMonHSEndPos += 0x100;
1192       iMonHSPeakPos += 0x100;
1193       HorzPos += 0x100;
1194       HorzChar++;
1195       if (HorzPos >= MonHSYNC) {
1196          if (VDU.flag_drawing) {
1197             CPC.scr_base += CPC.scr_line_offs; // advance surface pointer to next row
1198          }
1199          HadP = 1;
1200          iMonHSPeakPos = HorzPos - MonHSYNC;
1201          iMonHSStartToPeak = iMonHSStartPos - iMonHSPeakPos;
1202          iMonHSEndToPeak = iMonHSEndPos - iMonHSPeakPos;
1203          HorzPos = iMonHSPeakPos - HSyncDuration;
1204 
1205          HorzChar = HorzPos >> 8;
1206          uint32_t val = (HorzPos & 0xf0) >> PosShift;
1207          if (!val) {
1208             HorzMax = 48;
1209             HorzPix[0] = HorzPix[1];
1210             RendPos = RendStart;
1211             HorzChar--;
1212          } else {
1213             RendPos = (uint32_t *)&RendBuff[val];
1214             int tmp = (uint8_t*)RendStart - (uint8_t*)RendPos;
1215             HorzPix[48] = (uint8_t)tmp;
1216             HorzPix[0] = HorzPix[1] - (uint8_t)tmp;
1217             HorzMax = 49;
1218          }
1219          RendOut = (uint8_t*)RendStart;
1220          RendWid = &HorzPix[0];
1221          CPC.scr_pos = CPC.scr_base;
1222          VDU.scrln++;
1223          VDU.scanline++;
1224          if ((uint32_t)VDU.scrln >= MAX_DRAWN) {
1225             VDU.flag_drawing = 0;
1226          } else {
1227             VDU.flag_drawing = 1;
1228          }
1229       }
1230 
1231 // ----------------------------------------------------------------------------
1232 
1233       if (CRTC.char_count == CRTC.registers[0]) { // matches horizontal total?
1234          CRTC.last_hend = CRTC.char_count; // preserve current line length in chars
1235          CRTC.flag_newscan = 1; // request starting a new scan line
1236          CRTC.char_count = 0; // reset the horizontal character count
1237       } else {
1238          CRTC.char_count++; // update counter
1239          CRTC.char_count &= 255; // limit to 8 bits
1240       }
1241 
1242       if (CRTC.char_count == CRTC.registers[0]) { // matches horizontal total?
1243          if (CRTC.raster_count == CRTC.registers[9]) { // matches maximum raster address?
1244             CRTC.flag_reschar = 1; // request a line count update
1245          } else {
1246             CRTC.flag_reschar = 0; // still within the current character line
1247          }
1248          if (CRTC.flag_resnext) { // ready to restart frame?
1249             CRTC.flag_resnext = 0;
1250             CRTC.flag_resframe = 1; // request a frame restart
1251          }
1252          if (CRTC.flag_startvta) { // ready to start vertical total adjust?
1253             CRTC.flag_startvta = 0;
1254             CRTC.flag_invta = 1; // entering vertical total adjust
1255          }
1256          if (CRTC.flag_invta) { // in vertical total adjust?
1257             if ((CRTC.raster_count == CRTC.registers[9]) && (CRTC.line_count == CRTC.registers[4])) {
1258                CRTC.flag_resscan = 1; // raster counter only resets once at start of vta
1259             } else {
1260                CRTC.flag_resscan = 0; // raster counter keeps increasing while in vta
1261             }
1262          }
1263       }
1264 
1265       if (CRTC.char_count == CRTC.registers[1]) { // matches horizontal displayed?
1266          if (CRTC.raster_count == CRTC.registers[9]) { // matches maximum raster address?
1267             CRTC.next_addr = CRTC.addr + CRTC.char_count;
1268          }
1269       }
1270 
1271       if (!flags1.inHSYNC) { // not in HSYNC?
1272          if (CRTC.char_count == CRTC.registers[2]) { // matches horizontal sync position?
1273             flags1.inHSYNC = 0xff; // turn HSYNC on
1274             CRTC.flag_hadhsync = 1; // prevent GA from processing more than one HSYNC per scan line
1275             CRTC.hsw_count = 0; // initialize horizontal sync width counter
1276             match_hsw();
1277          }
1278       } else {
1279          match_hsw();
1280       }
1281 
1282       CRTC.CharInstSL(); // if necessary, process vertical total delay
1283       CRTC.CharInstMR(); // if necessary, process maximum raster count delay
1284 
1285       if (CRTC.flag_newscan) { // scanline change requested?
1286          CRTC.flag_newscan = 0;
1287          if (CRTC.split_sl && CRTC.sl_count == CRTC.split_sl) {
1288             CRTC.next_addr = CRTC.split_addr;
1289          }
1290          CRTC.addr = CRTC.next_addr; // FIX split screen
1291          CRTC.sl_count++;            // <-- CPC-PLUS only?
1292 
1293          if (CRTC.flag_invsync) { // VSYNC active?
1294             CRTC.vsw_count++; // update counter
1295             CRTC.vsw_count &= 15; // limit to 4 bits
1296             if (CRTC.vsw_count == CRTC.vsw) { // matches vertical sync width?
1297                CRTC.vsw_count = 0; // reset counter
1298                CRTC.flag_resvsync = 1; // request VSYNC reset
1299             }
1300          }
1301 
1302          if (CRTC.flag_resframe) { // frame restart requested?
1303             restart_frame();
1304          } else {
1305             if (CRTC.flag_resscan) { // raster counter reset requested?
1306                CRTC.flag_resscan = 0;
1307                CRTC.raster_count = 0; // reset counter
1308                CRTC.scr_base = 0;
1309             } else {
1310                CRTC.raster_count++; // update counter
1311                CRTC.raster_count &= 31; // limit to 5 bits
1312                if (!CRTC.raster_count) { // did the counter wrap around?
1313                   match_line_count();
1314                }
1315                CRTC.scr_base = (CRTC.scr_base + 0x0800) & 0x3800;
1316             }
1317          }
1318 
1319          CRTC.CharInstSL = (void(*)(void))CharSL1;
1320 
1321          register uint32_t temp = 0;
1322          if (CRTC.raster_count == CRTC.registers[9]) { // matches maximum raster address?
1323             temp = 1;
1324             CRTC.flag_resscan = 1; // request a raster counter reset
1325          }
1326          if (CRTC.r9match != temp) {
1327             CRTC.r9match = temp;
1328          }
1329          if (temp) {
1330             CRTC.CharInstMR = (void(*)(void))CharMR1;
1331          }
1332 
1333          if (CRTC.flag_invta) { // in vertical total adjust?
1334             if (CRTC.raster_count == CRTC.reg5) { // matches vertical total adjust?
1335                restart_frame();
1336                if (CRTC.registers[9] == 0) { // maximum raster address is zero?
1337                   CRTC.flag_resscan = 1; // request a raster counter reset
1338                }
1339             }
1340          }
1341 
1342          if (CRTC.flag_reschar) { // line count update requested?
1343             CRTC.line_count++; // update counter
1344             CRTC.line_count &= 127; // limit to 7 bits
1345             reload_addr();
1346          }
1347 
1348          if (CRTC.flag_invsync) { // in VSYNC?
1349             if (CRTC.flag_resvsync) { // end of VSYNC?
1350                CRTC.flag_invsync = 0; // turn VSYNC off
1351                CRTC.flag_resvsync = 0;
1352                if (VDU.scanline == MaxVSync) { // above maximum scanline count?
1353                   frame_finished();
1354                }
1355             } else {
1356                if (VDU.scanline > MinVSync) { // above minimum scanline count?
1357                   frame_finished();
1358                }
1359             }
1360          } else if (VDU.scanline == MaxVSync) { // above maximum scanline count?
1361             frame_finished();
1362          }
1363       }
1364 
1365       if (CRTC.char_count == CRTC.hstart) { // leaving border area?
1366          new_dt.NewHDSPTIMG |= 0x01;
1367       }
1368       if (CRTC.char_count == CRTC.hend) { // entering border area?
1369          new_dt.NewHDSPTIMG &= 0xfe;
1370       }
1371 
1372 // ----------------------------------------------------------------------------
1373 
1374       repeat_count--;
1375    }
1376 }
1377 
1378 
1379 
crtc_init(void)1380 void crtc_init(void)
1381 {
1382    unsigned l;
1383 
1384 #if RETRO_IS_BIG_ENDIAN
1385    static int byte_swapped = 0;
1386    if (!byte_swapped) {
1387      int j;
1388      byte_swapped = 1;
1389      for (j = 0; j < 0x200; j++) {
1390 	 M0Map[j] = retro_cpu_to_le32(M0Map[j]);
1391 	 M1Map[j] = retro_cpu_to_le32(M1Map[j]);
1392 	 M2Map[j] = retro_cpu_to_le32(M2Map[j]);
1393 	 M3Map[j] = retro_cpu_to_le32(M3Map[j]);
1394      }
1395      for (j = 0; j < 0x100; j++) {
1396 	 M0hMap[j] = retro_cpu_to_le32(M0hMap[j]);
1397 	 M1hMap[j] = retro_cpu_to_le32(M1hMap[j]);
1398 	 M2hMap[j] = retro_cpu_to_le32(M2hMap[j]);
1399 	 M3hMap[j] = retro_cpu_to_le32(M3hMap[j]);
1400      }
1401    }
1402 #endif
1403 
1404    if (dwXScale == 1)
1405    {
1406       ModeMaps[0] = M0hMap;
1407       ModeMaps[1] = M1hMap;
1408       ModeMaps[2] = M2hMap;
1409       ModeMaps[3] = M3hMap;
1410    }
1411    else
1412    {
1413       ModeMaps[0] = M0Map;
1414       ModeMaps[1] = M1Map;
1415       ModeMaps[2] = M2Map;
1416       ModeMaps[3] = M3Map;
1417    }
1418    ModeMap = ModeMaps[0];
1419 
1420    for (l = 0; l < 0x7400; l++)
1421    {
1422       int j = l << 1; // actual address
1423       MAXlate[l] = (j & 0x7FE) | ((j & 0x6000) << 1);
1424    }
1425 }
1426 
1427 
1428 
crtc_reset(void)1429 void crtc_reset(void)
1430 {
1431    unsigned i;
1432    int Wid;
1433 
1434    memset(&CRTC, 0, sizeof(CRTC)); // clear CRTC data structure
1435    CRTC.registers[0] = 0x3f;
1436    CRTC.registers[2] = 0x2e;
1437    CRTC.registers[3] = 0x8e;
1438 
1439    if (dwXScale == 1)
1440    {
1441       Wid = 8;
1442       PosShift = 5;
1443    }
1444    else
1445    {
1446       Wid = 16;
1447       PosShift = 4;
1448    }
1449 
1450    for (i = 0; i < 48; i++)
1451       HorzPix[i] = Wid;
1452 
1453    HorzPix[48] = 0;
1454    RendStart = (uint32_t *)&RendBuff[Wid];
1455    RendPos = (uint32_t *)&RendBuff[0];
1456    RendOut = (uint8_t*)RendStart;
1457    RendWid = &HorzPix[0];
1458 
1459    HorzPos = 0x500;
1460    HorzChar = 0x04;
1461    HorzMax = 48;
1462    HSyncDuration = 0xA00;
1463    MinHSync = 0x4000 - HSyncDuration - 257;
1464    MaxHSync = 0x4000 - HSyncDuration + 257;
1465    MonHSYNC = 0x4000 - HSyncDuration;
1466    MonFreeSync = MonHSYNC;
1467    flags1.monVSYNC = 0;
1468    flags1.dt.DISPTIMG = 0xff;
1469    flags1.dt.HDSPTIMG = 0x03;
1470    new_dt.NewDISPTIMG = 0xff;
1471    new_dt.NewHDSPTIMG = 0x03;
1472    CRTC.CharInstSL = (void(*)(void))NoChar;
1473    CRTC.CharInstMR = (void(*)(void))NoChar;
1474 
1475    // ASIC vars - split screens and raster interrupt
1476    CRTC.split_addr = 0;
1477    CRTC.split_sl = 0;
1478    CRTC.sl_count = 0;
1479    CRTC.interrupt_sl = 0;
1480 
1481    MinVSync = MID_VHOLD;
1482    MaxVSync = MinVSync + MIN_VHOLD_RANGE + (int)ceil((float)((MinVSync - MIN_VHOLD) *
1483     (MAX_VHOLD_RANGE - MIN_VHOLD_RANGE) / (MAX_VHOLD - MIN_VHOLD)));
1484 }
1485