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