1 /*
2  * antic.c - ANTIC chip emulation
3  *
4  * Copyright (C) 1995-1998 David Firth
5  * Copyright (C) 1998-2008 Atari800 development team (see DOC/CREDITS)
6  *
7  * This file is part of the Atari800 emulator project which emulates
8  * the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers.
9  *
10  * Atari800 is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * Atari800 is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Atari800; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
23 */
24 
25 #include "config.h"
26 #include <string.h>
27 
28 #include "antic.h"
29 #include "atari.h"
30 #include "cpu.h"
31 #include "gtia.h"
32 #include "log.h"
33 #include "memory.h"
34 #include "platform.h"
35 #include "pokey.h"
36 #include "util.h"
37 #if !defined(BASIC) && !defined(CURSES_BASIC)
38 #include "input.h"
39 #include "screen.h"
40 #endif
41 #ifndef BASIC
42 #include "statesav.h"
43 #endif
44 #ifdef NEW_CYCLE_EXACT
45 #include "cycle_map.h"
46 #endif
47 
48 #define LCHOP 3			/* do not build leftmost 0..3 characters in wide mode */
49 #define RCHOP 3			/* do not build rightmost 0..3 characters in wide mode */
50 
51 int ANTIC_break_ypos = 999;
52 #if !defined(BASIC) && !defined(CURSES_BASIC)
53 static int gtia_bug_active = FALSE; /* The GTIA bug mode is active */
54 #endif
55 #ifdef NEW_CYCLE_EXACT
56 static void draw_partial_scanline(int l,int r);
57 static void update_scanline_chbase(void);
58 static void update_scanline_invert(void);
59 static void update_scanline_blank(void);
60 const int *ANTIC_cpu2antic_ptr;
61 const int *ANTIC_antic2cpu_ptr;
62 int ANTIC_delayed_wsync = 0;
63 static int dmactl_changed = 0;
64 static UBYTE delayed_DMACTL;
65 static int draw_antic_ptr_changed = 0;
66 static UBYTE need_load;
67 static int dmactl_bug_chdata;
68 #endif /* NEW_CYCLE_EXACT */
69 #ifndef NO_SIMPLE_PAL_BLENDING
70 int ANTIC_pal_blending = 0;
71 #endif /* NO_SIMPLE_PAL_BLENDING */
72 
73 /* Video memory access is hidden behind these macros. It allows to track dirty video memory
74    to improve video system performance */
75 #ifdef DIRTYRECT
76 
77 static UWORD *scratchUWordPtr;
78 static UWORD scratchUWord;
79 static ULONG *scratchULongPtr;
80 static ULONG scratchULong;
81 static UBYTE *scratchUBytePtr;
82 static UBYTE scratchUByte;
83 
84 #ifdef NODIRTYCOMPARE
85 
86 #define WRITE_VIDEO(ptr, val) \
87 	do { \
88 		scratchUWordPtr = (ptr); \
89 		Screen_dirty[((ULONG) scratchUWordPtr - (ULONG) Screen_atari) >> 3] = 1; \
90 		*scratchUWordPtr = (val); \
91 	} while (0)
92 #define WRITE_VIDEO_LONG(ptr, val) \
93 	do { \
94 		scratchULongPtr = (ptr); \
95 		Screen_dirty[((ULONG) scratchULongPtr - (ULONG) Screen_atari) >> 3] = 1; \
96 		*scratchULongPtr = (val); \
97 	} while (0)
98 #define WRITE_VIDEO_BYTE(ptr, val) \
99 	do { \
100 		scratchUBytePtr = (ptr); \
101 		Screen_dirty[((ULONG) scratchUBytePtr - (ULONG) Screen_atari) >> 3] = 1; \
102 		*scratchUBytePtr = (val); \
103 	} while (0)
104 #define FILL_VIDEO(ptr, val, size) \
105 	do { \
106 		scratchUBytePtr = (UBYTE*) (ptr); \
107 		scratchULong = (ULONG) (size); \
108 		memset(Screen_dirty + (((ULONG) scratchUBytePtr - (ULONG) Screen_atari) >> 3), 1, scratchULong >> 3); \
109 		memset(scratchUBytePtr, (val), scratchULong); \
110 	} while (0)
111 
112 #else /* NODIRTYCOMPARE not defined: */
113 
114 #define WRITE_VIDEO(ptr, val) \
115 	do { \
116 		scratchUWordPtr = (ptr); \
117 		scratchUWord = (val); \
118 		if (*scratchUWordPtr != scratchUWord) { \
119 			Screen_dirty[((ULONG) scratchUWordPtr - (ULONG) Screen_atari) >> 3] = 1; \
120 			*scratchUWordPtr = scratchUWord; \
121 		} \
122 	} while (0)
123 #ifndef WORDS_UNALIGNED_OK
124 #define WRITE_VIDEO_LONG(ptr, val) \
125 	do { \
126 		scratchULongPtr = (ptr); \
127 		scratchULong = (val); \
128 		if (*scratchULongPtr != scratchULong) { \
129 			Screen_dirty[((ULONG) scratchULongPtr - (ULONG) Screen_atari) >> 3] = 1; \
130 			*scratchULongPtr = scratchULong; \
131 		} \
132 	} while (0)
133 #else
134 #define WRITE_VIDEO_LONG(ptr, val) \
135 	do { \
136 		scratchULongPtr = (ptr); \
137 		scratchULong = (val); \
138 		if (*scratchULongPtr != scratchULong) { \
139 			Screen_dirty[((ULONG) scratchULongPtr - (ULONG) Screen_atari) >> 3] = 1; \
140 			Screen_dirty[((ULONG) scratchULongPtr - (ULONG) Screen_atari + 2) >> 3] = 1; \
141 			*scratchULongPtr = scratchULong; \
142 		} \
143 	} while (0)
144 #endif
145 #define WRITE_VIDEO_BYTE(ptr, val) \
146 	do { \
147 		scratchUBytePtr = (ptr); \
148 		scratchUByte = (val); \
149 		if (*scratchUBytePtr != scratchUByte) { \
150 			Screen_dirty[((ULONG) scratchUBytePtr - (ULONG) Screen_atari) >> 3] = 1; \
151 			*scratchUBytePtr = scratchUByte; \
152 		} \
153 	} while (0)
154 static UBYTE *scratchFillLimit;
155 #define FILL_VIDEO(ptr, val, size) \
156 	do { \
157 		scratchUBytePtr = (UBYTE *) (ptr); \
158 		scratchUByte = (UBYTE) (val); \
159 		scratchFillLimit = scratchUBytePtr + (size); \
160 		for (; scratchUBytePtr < scratchFillLimit; scratchUBytePtr++) { \
161 			if (*scratchUBytePtr != scratchUByte) { \
162 				Screen_dirty[((ULONG) scratchUBytePtr - (ULONG) Screen_atari) >> 3] = 1; \
163 				*scratchUBytePtr = scratchUByte; \
164 			} \
165 		} \
166 	} while (0)
167 
168 #endif /* NODIRTYCOMPARE */
169 
170 #else /* DIRTYRECT not defined: */
171 
172 #define WRITE_VIDEO(ptr, val) (*(ptr) = val)
173 #define WRITE_VIDEO_LONG(ptr, val) (*(ptr) = val)
174 #define WRITE_VIDEO_BYTE(ptr, val) (*(ptr) = val)
175 #define FILL_VIDEO(ptr, val, size) memset(ptr, val, size)
176 
177 #endif /* DIRTYRECT */
178 
179 #define READ_VIDEO_LONG(ptr) (*(ptr))
180 
ANTIC_VideoMemset(UBYTE * ptr,UBYTE val,ULONG size)181 void ANTIC_VideoMemset(UBYTE *ptr, UBYTE val, ULONG size)
182 {
183 	FILL_VIDEO(ptr, val, size);
184 }
185 
ANTIC_VideoPutByte(UBYTE * ptr,UBYTE val)186 void ANTIC_VideoPutByte(UBYTE *ptr, UBYTE val)
187 {
188 	WRITE_VIDEO_BYTE(ptr, val);
189 }
190 
191 
192 /* Memory access helpers----------------------------------------------------- */
193 /* Some optimizations result in unaligned 32-bit accesses. These macros have
194    been introduced for machines that don't allow unaligned memory accesses. */
195 
196 #ifdef DIRTYRECT
197 /* STAT_UNALIGNED_WORDS doesn't work with DIRTYRECT */
198 #define WRITE_VIDEO_LONG_UNALIGNED  WRITE_VIDEO_LONG
199 #else
200 #define WRITE_VIDEO_LONG_UNALIGNED(ptr, val)  UNALIGNED_PUT_LONG((ptr), (val), Screen_atari_write_long_stat)
201 #endif
202 
203 #ifdef WORDS_UNALIGNED_OK
204 #define IS_ZERO_ULONG(x) (! UNALIGNED_GET_LONG(x, pm_scanline_read_long_stat))
205 #define DO_GTIA_BYTE(p, l, x) { \
206 		WRITE_VIDEO_LONG_UNALIGNED((ULONG *) (p),     (l)[(x) >> 4]); \
207 		WRITE_VIDEO_LONG_UNALIGNED((ULONG *) (p) + 1, (l)[(x) & 0xf]); \
208 	}
209 #else /* WORDS_UNALIGNED_OK */
210 #define IS_ZERO_ULONG(x) (!((const UBYTE *)(x))[0] && !((const UBYTE *)(x))[1] && !((const UBYTE *)(x))[2] && !((const UBYTE *)(x))[3])
211 #define DO_GTIA_BYTE(p, l, x) { \
212 		WRITE_VIDEO((UWORD *) (p),     (UWORD) ((l)[(x) >> 4])); \
213 		WRITE_VIDEO((UWORD *) (p) + 1, (UWORD) ((l)[(x) >> 4])); \
214 		WRITE_VIDEO((UWORD *) (p) + 2, (UWORD) ((l)[(x) & 0xf])); \
215 		WRITE_VIDEO((UWORD *) (p) + 3, (UWORD) ((l)[(x) & 0xf])); \
216 	}
217 #endif /* WORDS_UNALIGNED_OK */
218 
219 /* ANTIC Registers --------------------------------------------------------- */
220 
221 UBYTE ANTIC_DMACTL;
222 UBYTE ANTIC_CHACTL;
223 UWORD ANTIC_dlist;
224 UBYTE ANTIC_HSCROL;
225 UBYTE ANTIC_VSCROL;
226 UBYTE ANTIC_PMBASE;
227 UBYTE ANTIC_CHBASE;
228 UBYTE ANTIC_NMIEN;
229 UBYTE ANTIC_NMIST;
230 
231 /* ANTIC Memory ------------------------------------------------------------ */
232 
233 #if !defined(BASIC) && !defined(CURSES_BASIC)
234 static UBYTE antic_memory[52];
235 #define ANTIC_margin 4
236 /* It's number of bytes in antic_memory, which are never loaded, but may be
237    read in wide playfield mode. These bytes are uninitialized, because on
238    real computer there's some kind of 'garbage'. Possibly 1 is enough, but
239    4 bytes surely won't cause negative indexes. :) */
240 
241 /* Screen -----------------------------------------------------------------
242    Define screen as ULONG to ensure that it is Longword aligned.
243    This allows special optimisations under certain conditions.
244    ------------------------------------------------------------------------ */
245 
246 static UWORD *scrn_ptr;
247 #endif /* !defined(BASIC) && !defined(CURSES_BASIC) */
248 
249 /* Separate access to XE extended memory ----------------------------------- */
250 /* It's available in 130 XE and 320 KB Compy Shop.
251    Note: during ANTIC access to extended memory in Compy Shop Self Test
252    is disabled. It is unknown if this is true for real 130 XE. If not,
253    then some extra code has to be added to:
254    - check if selftest_enabled is set
255    - check if the address is in range 0x5000..0x57ff
256    - if both conditions are true, then access memory instead of ANTIC_xe_ptr */
257 
258 /* Pointer to 16 KB seen by ANTIC in 0x4000-0x7fff.
259    If it's the same what the CPU sees (and what's in MEMORY_mem[0x4000..0x7fff],
260    then NULL. */
261 const UBYTE *ANTIC_xe_ptr = NULL;
262 
263 /* ANTIC Timing --------------------------------------------------------------
264 
265 NOTE: this information was written before NEW_CYCLE_EXACT was introduced!
266 
267 I've introduced global variable ANTIC_xpos, which contains current number of cycle
268 in a line. This simplifies ANTIC/CPU timing much. The CPU_GO() function which
269 emulates CPU is now void and is called with ANTIC_xpos limit, below which CPU can go.
270 
271 All strange variables holding 'unused cycles', 'DMA cycles', 'allocated cycles'
272 etc. are removed. Simply whenever ANTIC fetches a byte, it takes single cycle,
273 which can be done now with ANTIC_xpos++. There's only one exception: in text modes
274 2-5 ANTIC takes more bytes than cycles, because it does less than ANTIC_DMAR refresh
275 cycles.
276 
277 Now emulation is really screenline-oriented. We do ANTIC_ypos++ after a line,
278 not inside it.
279 
280 This simplified diagram shows when what is done in a line:
281 
282 MDPPPPDD..............(------R/S/F------)..........
283 ^  ^     ^      ^     ^                     ^    ^ ^        ---> time/xpos
284 0  |  NMIST_C NMI_C SCR_C                 WSYNC_C|LINE_C
285 VSCON_C                                        VSCOF_C
286 
287 M - fetch Missiles
288 D - fetch DL
289 P - fetch Players
290 S - fetch Screen
291 F - fetch Font (in text modes)
292 R - refresh Memory (ANTIC_DMAR cycles)
293 
294 Only Memory Refresh happens in every line, other tasks are optional.
295 
296 Below are exact diagrams for some non-scrolled modes:
297                                                                                                     11111111111111
298           11111111112222222222333333333344444444445555555555666666666677777777778888888888999999999900000000001111
299 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123
300                             /--------------------------narrow------------------------------\
301                     /----------------------------------normal--------------------------------------\
302             /-------------------------------------------wide--------------------------------------------\
303 
304 blank line:
305 MDPPPPDD.................R...R...R...R...R...R...R...R...R........................................................
306 
307 mode 8,9:
308 MDPPPPDD....S.......S....R..SR...R..SR...R..SR...R..SR...R..S.......S.......S.......S.......S.......S.............
309 
310 mode a,b,c:
311 MDPPPPDD....S...S...S...SR..SR..SR..SR..SR..SR..SR..SR..SR..S...S...S...S...S...S...S...S...S...S...S...S.........
312 
313 mode d,e,f:
314 MDPPPPDD....S.S.S.S.S.S.SRS.SRS.SRS.SRS.SRS.SRS.SRS.SRS.SRS.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.S.........
315 
316 Notes:
317 * At the beginning of a line fetched are:
318   - a byte of Missiles
319   - a byte of DL (instruction)
320   - four bytes of Players
321   - two bytes of DL argument (jump or screen address)
322   The emulator, however, fetches them all continuously.
323 
324 * Refresh cycles and Screen/Font fetches have been tested for some modes (see above).
325   This is for making the emulator more accurate, able to change colour registers,
326   sprite positions or GTIA modes during scanline. These modes are the most commonly used
327   with those effects.
328   Currently this isn't implemented, and all R/S/F cycles are fetched continuously in *all* modes
329   (however, right number of cycles is taken in every mode, basing on screen width and HSCROL).
330 
331 There are a few constants representing following events:
332 
333 * VSCON_C - in first VSC line dctr is loaded with VSCROL
334 
335 * ANTIC_NMIST_C - NMIST is updated (set to 0x9f on DLI, set to 0x5f on VBLKI)
336 
337 * ANTIC_NMI_C - If NMIEN permits, NMI interrupt is generated
338 
339 * SCR_C - We draw whole line of screen. On a real computer you can change
340   ANTIC/GTIA registers while displaying screen, however this emulator
341   isn't that accurate.
342 
343 * ANTIC_WSYNC_C - ANTIC holds CPU until this moment, when WSYNC is written
344 
345 * VSCOF_C - in last VSC line dctr is compared with VSCROL
346 
347 * ANTIC_LINE_C - simply end of line (this used to be called CPUL)
348 
349 All constants are determined by tests on real Atari computer. It is assumed,
350 that ANTIC registers are read with LDA, LDX, LDY and written with STA, STX,
351 STY, all in absolute addressing mode. All these instructions last 4 cycles
352 and perform read/write operation in last cycle. The CPU emulation should
353 correctly emulate WSYNC and add cycles for current instruction BEFORE
354 executing it. That's why VSCOF_C > ANTIC_LINE_C is correct.
355 
356 How WSYNC is now implemented:
357 
358 * On writing WSYNC:
359   - if ANTIC_xpos <= ANTIC_WSYNC_C && ANTIC_xpos_limit >= ANTIC_WSYNC_C,
360     we only change ANTIC_xpos to ANTIC_WSYNC_C - that's all
361   - otherwise we set ANTIC_wsync_halt and change ANTIC_xpos to ANTIC_xpos_limit causing CPU_GO()
362     to return
363 
364 * At the beginning of CPU_GO() (CPU emulation), when ANTIC_wsync_halt is set:
365   - if ANTIC_xpos_limit < ANTIC_WSYNC_C we return
366   - else we set ANTIC_xpos to ANTIC_WSYNC_C, reset ANTIC_wsync_halt and emulate some cycles
367 
368 We don't emulate ANTIC_NMIST_C, ANTIC_NMI_C and SCR_C if it is unnecessary.
369 These are all cases:
370 
371 * Common overscreen line
372   Nothing happens except that ANTIC gets ANTIC_DMAR cycles:
373   ANTIC_xpos += ANTIC_DMAR; GOEOL;
374 
375 * First overscreen line - start of vertical blank
376   - CPU goes until ANTIC_NMIST_C
377   - ANTIC sets NMIST to 0x5f
378   if (ANTIC_NMIEN & 0x40) {
379       - CPU goes until ANTIC_NMI_C
380       - ANTIC forces NMI
381   }
382   - ANTIC gets ANTIC_DMAR cycles
383   - CPU goes until ANTIC_LINE_C
384 
385 * Screen line without DLI
386   - ANTIC fetches DL and P/MG
387   - CPU goes until SCR_C
388   - ANTIC draws whole line fetching Screen/Font and refreshing memory
389   - CPU goes until ANTIC_LINE_C
390 
391 * Screen line with DLI
392   - ANTIC fetches DL and P/MG
393   - CPU goes until ANTIC_NMIST_C
394   - ANTIC sets NMIST to 0x9f
395   if (ANTIC_NMIEN & 0x80) {
396       - CPU goes until ANTIC_NMI_C
397       - ANTIC forces NMI
398   }
399   - CPU goes until SCR_C
400   - ANTIC draws line with ANTIC_DMAR
401   - CPU goes until ANTIC_LINE_C
402 
403   -------------------------------------------------------------------------- */
404 
405 #define VSCON_C	1
406 #define SCR_C	28
407 #define VSCOF_C	112
408 
409 unsigned int ANTIC_screenline_cpu_clock = 0;
410 
411 #ifdef NEW_CYCLE_EXACT
412 #define UPDATE_DMACTL do{if (dmactl_changed) { \
413 		dmactl_changed = 0; \
414 		ANTIC_PutByte(ANTIC_OFFSET_DMACTL, delayed_DMACTL); \
415 	} \
416 	if (draw_antic_ptr_changed) { \
417 		draw_antic_ptr_changed = 0; \
418 		draw_antic_ptr = saved_draw_antic_ptr; \
419 	}}while(0)
420 #else
421 #define UPDATE_DMACTL do{}while(0)
422 #endif /* NEW_CYCLE_EXACT */
423 #define UPDATE_GTIA_BUG /* update GTIA if it was in bug mode */\
424 	do{if(gtia_bug_active) {\
425 		/* restore draw_antic_ptr for multi-line modes*/\
426 		draw_antic_ptr = draw_antic_table[GTIA_PRIOR >> 6][anticmode];\
427 		gtia_bug_active = FALSE;\
428 	}}while(0)
429 #define GOEOL_CYCLE_EXACT  CPU_GO(ANTIC_antic2cpu_ptr[ANTIC_LINE_C]); \
430 	ANTIC_xpos = ANTIC_cpu2antic_ptr[ANTIC_xpos]; \
431 	ANTIC_xpos -= ANTIC_LINE_C; \
432 	ANTIC_screenline_cpu_clock += ANTIC_LINE_C; \
433 	ANTIC_ypos++; \
434 	GTIA_UpdatePmplColls();
435 #define GOEOL CPU_GO(ANTIC_LINE_C); ANTIC_xpos -= ANTIC_LINE_C; ANTIC_screenline_cpu_clock += ANTIC_LINE_C; UPDATE_DMACTL; ANTIC_ypos++; UPDATE_GTIA_BUG
436 #define OVERSCREEN_LINE	ANTIC_xpos += ANTIC_DMAR; GOEOL
437 
438 int ANTIC_xpos = 0;
439 int ANTIC_xpos_limit;
440 int ANTIC_wsync_halt = FALSE;
441 
442 int ANTIC_ypos;						/* Line number - lines 8..247 are on screen */
443 
444 /* Timing in first line of modes 2-5
445 In these modes ANTIC takes more bytes than cycles. Despite this, it would be
446 possible that SCR_C + cycles_taken > ANTIC_WSYNC_C. To avoid this we must take some
447 cycles before SCR_C. before_cycles contains number of them, while extra_cycles
448 contains difference between bytes taken and cycles taken plus before_cycles. */
449 
450 #define BEFORE_CYCLES (SCR_C - 28)
451 /* It's number of cycles taken before SCR_C for not scrolled, narrow playfield.
452    It wasn't tested, but should be ok. ;) */
453 
454 /* Light pen support ------------------------------------------------------- */
455 
456 static UBYTE PENH;
457 static UBYTE PENV;
458 UBYTE ANTIC_PENH_input = 0x00;
459 UBYTE ANTIC_PENV_input = 0xff;
460 
461 #ifndef BASIC
462 
463 /* Internal ANTIC registers ------------------------------------------------ */
464 
465 static UWORD screenaddr;		/* Screen Pointer */
466 static UBYTE IR;				/* Instruction Register */
467 static UBYTE anticmode;			/* Antic mode */
468 static UBYTE dctr;				/* Delta Counter */
469 static UBYTE lastline;			/* dctr limit */
470 static UBYTE need_dl;			/* boolean: fetch DL next line */
471 static UBYTE vscrol_off;		/* boolean: displaying line ending VSC */
472 
473 #endif
474 
475 #if !defined(BASIC) && !defined(CURSES_BASIC)
476 
477 /* Pre-computed values for improved performance ---------------------------- */
478 
479 #define NORMAL0 0				/* modes 2,3,4,5,0xd,0xe,0xf */
480 #define NORMAL1 1				/* modes 6,7,0xa,0xb,0xc */
481 #define NORMAL2 2				/* modes 8,9 */
482 #define SCROLL0 3				/* modes 2,3,4,5,0xd,0xe,0xf with HSC */
483 #define SCROLL1 4				/* modes 6,7,0xa,0xb,0xc with HSC */
484 #define SCROLL2 5				/* modes 8,9 with HSC */
485 static int md;					/* current mode NORMAL0..SCROLL2 */
486 /* tables for modes NORMAL0..SCROLL2 */
487 static int chars_read[6];
488 static int chars_displayed[6];
489 static int x_min[6];
490 static int ch_offset[6];
491 static int load_cycles[6];
492 static int font_cycles[6];
493 static int before_cycles[6];
494 static int extra_cycles[6];
495 
496 /* border parameters for current display width */
497 static int left_border_chars;
498 static int right_border_start;
499 #ifdef NEW_CYCLE_EXACT
500 static int left_border_start = LCHOP * 4;
501 static int right_border_end = (48 - RCHOP) * 4;
502 #define LBORDER_START left_border_start
503 #define RBORDER_END right_border_end
504 #else
505 #define LBORDER_START (LCHOP * 4)
506 #define RBORDER_END ((48 - RCHOP) * 4)
507 #endif /* NEW_CYCLE_EXACT */
508 
509 /* set with CHBASE *and* CHACTL - bits 0..2 set if flip on */
510 static UWORD chbase_20;			/* CHBASE for 20 character mode */
511 
512 /* set with CHACTL */
513 static UBYTE invert_mask;
514 static int blank_mask;
515 
516 /* A scanline of AN0 and AN1 signals as transmitted from ANTIC to GTIA.
517    In every byte, bit 0 is AN0 and bit 1 is AN1 */
518 static UBYTE an_scanline[Screen_WIDTH / 2 + 8];
519 
520 /* lookup tables */
521 static UBYTE blank_lookup[256];
522 static UWORD lookup2[256];
523 ULONG ANTIC_lookup_gtia9[16];
524 ULONG ANTIC_lookup_gtia11[16];
525 static UBYTE playfield_lookup[257];
526 static UBYTE mode_e_an_lookup[256];
527 
528 /* Colour lookup table
529    This single table replaces 4 previously used: cl_word, cur_prior,
530    prior_table and pf_colls. It should be treated as a two-dimensional table,
531    with playfield colours in rows and PMG colours in columns:
532        no_PMG PM0 PM1 PM01 PM2 PM3 PM23 PM023 PM123 PM0123 PM25 PM35 PM235 colls ... ...
533    BAK
534    ...
535    HI2
536    HI3
537    PF0
538    PF1
539    PF2
540    PF3
541    The table contains word value (lsb = msb) of colour to be drawn.
542    The table is being updated taking current PRIOR setting into consideration.
543    '...' represent two unused columns and single unused row.
544    HI2 and HI3 are used only if colour_translation_table is being used.
545    They're colours of hi-res pixels on PF2 and PF3 respectively (PF2 is
546    default background for hi-res, PF3 is PM5).
547    Columns PM023, PM123 and PM0123 are used when PRIOR & 0xf equals any
548    of 5,7,0xc,0xd,0xe,0xf. The columns represent PM0, PM1 and PM01 respectively
549    covered by PM2 and/or PM3. This is to handle black colour on PF2 and PF3.
550    Columns PM25, PM35 and PM235 are used when PRIOR & 0x1f equals any
551    of 0x10,0x1a,0x1c,0x1e. The columns represent PM2, PM3 and PM23
552    respectively covered by PM5. This to handle colour on PF0 and PF1:
553    PF3 if (PRIOR & 0x1f) == 0x10, PF0 or PF1 otherwise.
554    Additional column 'colls' holds collisions of playfields with PMG. */
555 
556 UWORD ANTIC_cl[128];
557 
558 #define C_PM0	0x01
559 #define C_PM1	0x02
560 #define C_PM01	0x03
561 #define C_PM2	0x04
562 #define C_PM3	0x05
563 #define C_PM23	0x06
564 #define C_PM023	0x07
565 #define C_PM123	0x08
566 #define C_PM0123 0x09
567 #define C_PM25	0x0a
568 #define C_PM35	0x0b
569 #define C_PM235	0x0c
570 #define C_COLLS	0x0d
571 #define C_BAK	0x00
572 #define C_HI2	0x20
573 #define C_HI3	0x30
574 #define C_PF0	0x40
575 #define C_PF1	0x50
576 #define C_PF2	0x60
577 #define C_PF3	0x70
578 #define C_BLACK	(C_PF3 | C_PM25)
579 
580 /* these are byte-offsets in the table, so left shift for indexing word table
581    has been avoided */
582 #define COLOUR(x) (*(UWORD *) ((UBYTE *) ANTIC_cl + (x) ))
583 #define L_PM0	(2 * C_PM0)
584 #define L_PM1	(2 * C_PM1)
585 #define L_PM01	(2 * C_PM01)
586 #define L_PM2	(2 * C_PM2)
587 #define L_PM3	(2 * C_PM3)
588 #define L_PM23	(2 * C_PM23)
589 #define L_PM023	(2 * C_PM023)
590 #define L_PM123	(2 * C_PM123)
591 #define L_PM0123 (2 * C_PM0123)
592 #define L_PM25	(2 * C_PM25)
593 #define L_PM35	(2 * C_PM35)
594 #define L_PM235	(2 * C_PM235)
595 #define L_COLLS	(2 * C_COLLS)
596 #define L_BAK	(2 * C_BAK)
597 #define L_HI2	(2 * C_HI2)
598 #define L_HI3	(2 * C_HI3)
599 #define L_PF0	(2 * C_PF0)
600 #define L_PF1	(2 * C_PF1)
601 #define L_PF2	(2 * C_PF2)
602 #define L_PF3	(2 * C_PF3)
603 #define L_BLACK	(2 * C_BLACK)
604 
605 /* Blank areas optimizations
606    Routines for most graphics modes take advantage of fact, that often
607    large areas of screen are background colour. If it is possible, 8 pixels
608    of background are drawn at once - with two longs or four words, if
609    the platform doesn't allow unaligned long access.
610    Artifacting also uses unaligned long access if it's supported. */
611 
612 #ifdef WORDS_UNALIGNED_OK
613 
614 #define INIT_BACKGROUND_6 ULONG background = ANTIC_cl[C_PF2] | (((ULONG) ANTIC_cl[C_PF2]) << 16);
615 #define INIT_BACKGROUND_8 ULONG background = ANTIC_lookup_gtia9[0];
616 #define DRAW_BACKGROUND(colreg) { \
617 		WRITE_VIDEO_LONG_UNALIGNED((ULONG *) ptr, background); \
618 		WRITE_VIDEO_LONG_UNALIGNED(((ULONG *) ptr) + 1, background); \
619 		ptr += 4; \
620 	}
621 #define DRAW_ARTIF { \
622 		WRITE_VIDEO_LONG_UNALIGNED((ULONG *) ptr, art_curtable[(UBYTE) (screendata_tally >> 10)]); \
623 		WRITE_VIDEO_LONG_UNALIGNED(((ULONG *) ptr) + 1, art_curtable[(UBYTE) (screendata_tally >> 6)]); \
624 		ptr += 4; \
625 	}
626 
627 #else
628 
629 #define INIT_BACKGROUND_6
630 #define INIT_BACKGROUND_8
631 #define DRAW_BACKGROUND(colreg) {\
632 		WRITE_VIDEO(ptr,     ANTIC_cl[colreg]); \
633 		WRITE_VIDEO(ptr + 1, ANTIC_cl[colreg]); \
634 		WRITE_VIDEO(ptr + 2, ANTIC_cl[colreg]); \
635 		WRITE_VIDEO(ptr + 3, ANTIC_cl[colreg]); \
636 		ptr += 4;\
637 	}
638 #define DRAW_ARTIF {\
639 		WRITE_VIDEO(ptr++, ((UWORD *) art_curtable)[(screendata_tally & 0x03fc00) >> 9]); \
640 		WRITE_VIDEO(ptr++, ((UWORD *) art_curtable)[((screendata_tally & 0x03fc00) >> 9) + 1]); \
641 		WRITE_VIDEO(ptr++, ((UWORD *) art_curtable)[(screendata_tally & 0x003fc0) >> 5]); \
642 		WRITE_VIDEO(ptr++, ((UWORD *) art_curtable)[((screendata_tally & 0x003fc0) >> 5) + 1]); \
643 	}
644 
645 #endif /* WORDS_UNALIGNED_OK */
646 
647 #define DRAW_ARTIF_NEW {\
648 		WRITE_VIDEO(ptr++, art_lookup_new[(screendata_tally & 0x03f000) >> 12]); \
649 		WRITE_VIDEO(ptr++, art_lookup_new[(screendata_tally & 0x00fc00) >> 10]); \
650 		WRITE_VIDEO(ptr++, art_lookup_new[(screendata_tally & 0x003f00) >> 8]); \
651 		WRITE_VIDEO(ptr++, art_lookup_new[(screendata_tally & 0x000fc0) >> 6]); \
652 	}
653 
654 /* Hi-res modes optimizations
655    Now hi-res modes are drawn with words, not bytes. Endianess defaults
656    to little-endian. WORDS_BIGENDIAN should be defined when compiling on
657    a big-endian machine. */
658 
659 #ifdef WORDS_BIGENDIAN
660 #define BYTE0_MASK		0xff00
661 #define BYTE1_MASK		0x00ff
662 #define HIRES_MASK_01	0xfff0
663 #define HIRES_MASK_10	0xf0ff
664 #define HIRES_LUM_01	0x000f
665 #define HIRES_LUM_10	0x0f00
666 #else
667 #define BYTE0_MASK		0x00ff
668 #define BYTE1_MASK		0xff00
669 #define HIRES_MASK_01	0xf0ff
670 #define HIRES_MASK_10	0xfff0
671 #define HIRES_LUM_01	0x0f00
672 #define HIRES_LUM_10	0x000f
673 #endif
674 
675 static UWORD hires_lookup_n[128];
676 static UWORD hires_lookup_m[128];
677 #define hires_norm(x)	hires_lookup_n[(x) >> 1]
678 #define hires_mask(x)	hires_lookup_m[(x) >> 1]
679 
680 #ifndef USE_COLOUR_TRANSLATION_TABLE
681 int ANTIC_artif_new = FALSE; /* New type of artifacting */
682 UWORD ANTIC_hires_lookup_l[128];	/* accessed in gtia.c */
683 #define hires_lum(x)	ANTIC_hires_lookup_l[(x) >> 1]
684 #endif
685 
686 /* Player/Missile Graphics ------------------------------------------------- */
687 
688 #define PF0PM (*(UBYTE *) &ANTIC_cl[C_PF0 | C_COLLS])
689 #define PF1PM (*(UBYTE *) &ANTIC_cl[C_PF1 | C_COLLS])
690 #define PF2PM (*(UBYTE *) &ANTIC_cl[C_PF2 | C_COLLS])
691 #define PF3PM (*(UBYTE *) &ANTIC_cl[C_PF3 | C_COLLS])
692 #define PF_COLLS(x) (((UBYTE *) &ANTIC_cl)[(x) + L_COLLS])
693 
694 static int singleline;
695 int ANTIC_player_dma_enabled;
696 int ANTIC_player_gra_enabled;
697 int ANTIC_missile_dma_enabled;
698 int ANTIC_missile_gra_enabled;
699 int ANTIC_player_flickering;
700 int ANTIC_missile_flickering;
701 
702 static UWORD pmbase_s;
703 static UWORD pmbase_d;
704 
705 /* PMG lookup tables */
706 static UBYTE pm_lookup_table[20][256];
707 /* current PMG lookup table */
708 static const UBYTE *pm_lookup_ptr;
709 
710 #define PL_00	0	/* 0x00,0x01,0x02,0x03,0x04,0x06,0x08,0x09,0x0a,0x0b */
711 #define PL_05	1	/* 0x05,0x07,0x0c,0x0d,0x0e,0x0f */
712 #define PL_10	2	/* 0x10,0x1a */
713 #define PL_11	3	/* 0x11,0x18,0x19 */
714 #define PL_12	4	/* 0x12 */
715 #define PL_13	5	/* 0x13,0x1b */
716 #define PL_14	6	/* 0x14,0x16 */
717 #define PL_15	7	/* 0x15,0x17,0x1d,0x1f */
718 #define PL_1c	8	/* 0x1c */
719 #define PL_1e	9	/* 0x1e */
720 #define PL_20	10	/* 0x20,0x21,0x22,0x23,0x24,0x26,0x28,0x29,0x2a,0x2b */
721 #define PL_25	11	/* 0x25,0x27,0x2c,0x2d,0x2e,0x2f */
722 #define PL_30	12	/* 0x30,0x3a */
723 #define PL_31	13	/* 0x31,0x38,0x39 */
724 #define PL_32	14	/* 0x32 */
725 #define PL_33	15	/* 0x33,0x3b */
726 #define PL_34	16	/* 0x34,0x36 */
727 #define PL_35	17	/* 0x35,0x37,0x3d,0x3f */
728 #define PL_3c	18	/* 0x3c */
729 #define PL_3e	19	/* 0x3e */
730 
731 static const UBYTE prior_to_pm_lookup[64] = {
732 	PL_00, PL_00, PL_00, PL_00, PL_00, PL_05, PL_00, PL_05,
733 	PL_00, PL_00, PL_00, PL_00, PL_05, PL_05, PL_05, PL_05,
734 	PL_10, PL_11, PL_12, PL_13, PL_14, PL_15, PL_14, PL_15,
735 	PL_11, PL_11, PL_10, PL_13, PL_1c, PL_15, PL_1e, PL_15,
736 	PL_20, PL_20, PL_20, PL_20, PL_20, PL_25, PL_20, PL_25,
737 	PL_20, PL_20, PL_20, PL_20, PL_25, PL_25, PL_25, PL_25,
738 	PL_30, PL_31, PL_32, PL_33, PL_34, PL_35, PL_34, PL_35,
739 	PL_31, PL_31, PL_30, PL_33, PL_3c, PL_35, PL_3e, PL_35
740 };
741 
init_pm_lookup(void)742 static void init_pm_lookup(void)
743 {
744 	static const UBYTE pm_lookup_template[10][16] = {
745 		/* PL_20 */
746 		{ L_BAK, L_PM0, L_PM1, L_PM01, L_PM2, L_PM0, L_PM1, L_PM01,
747 		L_PM3, L_PM0, L_PM1, L_PM01, L_PM23, L_PM0, L_PM1, L_PM01 },
748 		/* PL_25 */
749 		{ L_BAK, L_PM0, L_PM1, L_PM01, L_PM2, L_PM023, L_PM123, L_PM0123,
750 		L_PM3, L_PM023, L_PM123, L_PM0123, L_PM23, L_PM023, L_PM123, L_PM0123 },
751 		/* PL_30 */
752 		{ L_PF3, L_PM0, L_PM1, L_PM01, L_PM25, L_PM0, L_PM1, L_PM01,
753 		L_PM35, L_PM0, L_PM1, L_PM01, L_PM235, L_PM0, L_PM1, L_PM01 },
754 		/* PL_31 */
755 		{ L_PF3, L_PM0, L_PM1, L_PM01, L_PM2, L_PM0, L_PM1, L_PM01,
756 		L_PM3, L_PM0, L_PM1, L_PM01, L_PM23, L_PM0, L_PM1, L_PM01 },
757 		/* PL_32 */
758 		{ L_PF3, L_PM0, L_PM1, L_PM01, L_PF3, L_PM0, L_PM1, L_PM01,
759 		L_PF3, L_PM0, L_PM1, L_PM01, L_PF3, L_PM0, L_PM1, L_PM01 },
760 		/* PL_33 */
761 		{ L_PF3, L_PM0, L_PM1, L_PM01, L_BLACK, L_PM0, L_PM1, L_PM01,
762 		L_BLACK, L_PM0, L_PM1, L_PM01, L_BLACK, L_PM0, L_PM1, L_PM01 },
763 		/* PL_34 */
764 		{ L_PF3, L_PF3, L_PF3, L_PF3, L_PF3, L_PF3, L_PF3, L_PF3,
765 		L_PF3, L_PF3, L_PF3, L_PF3, L_PF3, L_PF3, L_PF3, L_PF3 },
766 		/* PL_35 */
767 		{ L_PF3, L_PF3, L_PF3, L_PF3, L_BLACK, L_BLACK, L_BLACK, L_BLACK,
768 		L_BLACK, L_BLACK, L_BLACK, L_BLACK, L_BLACK, L_BLACK, L_BLACK, L_BLACK },
769 		/* PL_3c */
770 		{ L_PF3, L_PF3, L_PF3, L_PF3, L_PM25, L_PM25, L_PM25, L_PM25,
771 		L_PM25, L_PM25, L_PM25, L_PM25, L_PM25, L_PM25, L_PM25, L_PM25 },
772 		/* PL_3e */
773 		{ L_PF3, L_PF3, L_PF3, L_PF3, L_PM25, L_BLACK, L_BLACK, L_BLACK,
774 		L_PM25, L_BLACK, L_BLACK, L_BLACK, L_PM25, L_BLACK, L_BLACK, L_BLACK }
775 	};
776 
777 	static const UBYTE multi_to_normal[] = {
778 		L_BAK,
779 		L_PM0, L_PM1, L_PM0,
780 		L_PM2, L_PM3, L_PM2,
781 		L_PM023, L_PM123, L_PM023,
782 		L_PM25, L_PM35, L_PM25
783 	};
784 
785 	int i;
786 	int j;
787 	UBYTE temp;
788 
789 	for (i = 0; i <= 1; i++)
790 		for (j = 0; j <= 255; j++) {
791 			pm_lookup_table[i + 10][j] = temp = pm_lookup_template[i][(j & 0xf) | (j >> 4)];
792 			pm_lookup_table[i][j] = temp <= L_PM235 ? multi_to_normal[temp >> 1] : temp;
793 		}
794 	for (; i <= 9; i++) {
795 		for (j = 0; j <= 15; j++) {
796 			pm_lookup_table[i + 10][j] = temp = pm_lookup_template[i < 7 ? 0 : 1][j];
797 			pm_lookup_table[i][j] = temp <= L_PM235 ? multi_to_normal[temp >> 1] : temp;
798 		}
799 		for (; j <= 255; j++) {
800 			pm_lookup_table[i + 10][j] = temp = pm_lookup_template[i][j & 0xf];
801 			pm_lookup_table[i][j] = temp <= L_PM235 ? multi_to_normal[temp >> 1] : temp;
802 		}
803 	}
804 }
805 
806 static const UBYTE hold_missiles_tab[16] = {
807 	0x00,0x03,0x0c,0x0f,0x30,0x33,0x3c,0x3f,
808 	0xc0,0xc3,0xcc,0xcf,0xf0,0xf3,0xfc,0xff};
809 
pmg_dma(void)810 static void pmg_dma(void)
811 {
812 	/* VDELAY bit set == GTIA ignores PMG DMA in even lines */
813 	if (ANTIC_player_dma_enabled) {
814 		if (ANTIC_player_gra_enabled) {
815 			const UBYTE *base;
816 			if (singleline) {
817 				if (ANTIC_xe_ptr != NULL && pmbase_s < 0x8000 && pmbase_s >= 0x4000)
818 					base = ANTIC_xe_ptr + pmbase_s - 0x4000 + ANTIC_ypos;
819 				else
820 					base = MEMORY_mem + pmbase_s + ANTIC_ypos;
821 				if (ANTIC_ypos & 1) {
822 					GTIA_GRAFP0 = base[0x400];
823 					GTIA_GRAFP1 = base[0x500];
824 					GTIA_GRAFP2 = base[0x600];
825 					GTIA_GRAFP3 = base[0x700];
826 				}
827 				else {
828 					if ((GTIA_VDELAY & 0x10) == 0)
829 						GTIA_GRAFP0 = base[0x400];
830 					if ((GTIA_VDELAY & 0x20) == 0)
831 						GTIA_GRAFP1 = base[0x500];
832 					if ((GTIA_VDELAY & 0x40) == 0)
833 						GTIA_GRAFP2 = base[0x600];
834 					if ((GTIA_VDELAY & 0x80) == 0)
835 						GTIA_GRAFP3 = base[0x700];
836 				}
837 			}
838 			else {
839 				if (ANTIC_xe_ptr != NULL && pmbase_d < 0x8000 && pmbase_d >= 0x4000)
840 					base = ANTIC_xe_ptr + (pmbase_d - 0x4000) + (ANTIC_ypos >> 1);
841 				else
842 					base = MEMORY_mem + pmbase_d + (ANTIC_ypos >> 1);
843 				if (ANTIC_ypos & 1) {
844 					GTIA_GRAFP0 = base[0x200];
845 					GTIA_GRAFP1 = base[0x280];
846 					GTIA_GRAFP2 = base[0x300];
847 					GTIA_GRAFP3 = base[0x380];
848 				}
849 				else {
850 					if ((GTIA_VDELAY & 0x10) == 0)
851 						GTIA_GRAFP0 = base[0x200];
852 					if ((GTIA_VDELAY & 0x20) == 0)
853 						GTIA_GRAFP1 = base[0x280];
854 					if ((GTIA_VDELAY & 0x40) == 0)
855 						GTIA_GRAFP2 = base[0x300];
856 					if ((GTIA_VDELAY & 0x80) == 0)
857 						GTIA_GRAFP3 = base[0x380];
858 				}
859 			}
860 		}
861 		ANTIC_xpos += 4;
862 	}
863 	if (ANTIC_missile_dma_enabled) {
864 		if (ANTIC_missile_gra_enabled) {
865 			UBYTE data;
866 			if (ANTIC_xe_ptr != NULL && pmbase_s < 0x8000 && pmbase_s >= 0x4000)
867 				data = ANTIC_xe_ptr[singleline ? pmbase_s + ANTIC_ypos + 0x300 - 0x4000 : pmbase_d + (ANTIC_ypos >> 1) + 0x180 - 0x4000];
868 			else
869 				data = MEMORY_dGetByte(singleline ? pmbase_s + ANTIC_ypos + 0x300 : pmbase_d + (ANTIC_ypos >> 1) + 0x180);
870 			/* in odd lines load all missiles, in even only those, for which VDELAY bit is zero */
871 			GTIA_GRAFM = ANTIC_ypos & 1 ? data : ((GTIA_GRAFM ^ data) & hold_missiles_tab[GTIA_VDELAY & 0xf]) ^ data;
872 		}
873 		ANTIC_xpos++;
874 	}
875 }
876 
877 /* Artifacting ------------------------------------------------------------ */
878 
879 int ANTIC_artif_mode;
880 
881 static UWORD art_lookup_new[64];
882 static UWORD art_colour1_new;
883 static UWORD art_colour2_new;
884 
885 static ULONG art_lookup_normal[256];
886 static ULONG art_lookup_reverse[256];
887 static ULONG art_bkmask_normal[256];
888 static ULONG art_lummask_normal[256];
889 static ULONG art_bkmask_reverse[256];
890 static ULONG art_lummask_reverse[256];
891 
892 static ULONG *art_curtable = art_lookup_normal;
893 static ULONG *art_curbkmask = art_bkmask_normal;
894 static ULONG *art_curlummask = art_lummask_normal;
895 
896 static UWORD art_normal_colpf1_save;
897 static UWORD art_normal_colpf2_save;
898 static UWORD art_reverse_colpf1_save;
899 static UWORD art_reverse_colpf2_save;
900 
setup_art_colours(void)901 static void setup_art_colours(void)
902 {
903 	static UWORD *art_colpf1_save = &art_normal_colpf1_save;
904 	static UWORD *art_colpf2_save = &art_normal_colpf2_save;
905 	UWORD curlum = ANTIC_cl[C_PF1] & 0x0f0f;
906 
907 	if (curlum != *art_colpf1_save || ANTIC_cl[C_PF2] != *art_colpf2_save) {
908 		if (curlum < (ANTIC_cl[C_PF2] & 0x0f0f)) {
909 			art_colpf1_save = &art_reverse_colpf1_save;
910 			art_colpf2_save = &art_reverse_colpf2_save;
911 			art_curtable = art_lookup_reverse;
912 			art_curlummask = art_lummask_reverse;
913 			art_curbkmask = art_bkmask_reverse;
914 		}
915 		else {
916 			art_colpf1_save = &art_normal_colpf1_save;
917 			art_colpf2_save = &art_normal_colpf2_save;
918 			art_curtable = art_lookup_normal;
919 			art_curlummask = art_lummask_normal;
920 			art_curbkmask = art_bkmask_normal;
921 		}
922 		if (curlum ^ *art_colpf1_save) {
923 			int i;
924 			ULONG new_colour = curlum ^ *art_colpf1_save;
925 			new_colour |= new_colour << 16;
926 			*art_colpf1_save = curlum;
927 			for (i = 0; i <= 255; i++)
928 				art_curtable[i] ^= art_curlummask[i] & new_colour;
929 		}
930 		if (ANTIC_cl[C_PF2] ^ *art_colpf2_save) {
931 			int i;
932 			ULONG new_colour = ANTIC_cl[C_PF2] ^ *art_colpf2_save;
933 			new_colour |= new_colour << 16;
934 			*art_colpf2_save = ANTIC_cl[C_PF2];
935 			for (i = 0; i <= 255; i++)
936 				art_curtable[i] ^= art_curbkmask[i] & new_colour;
937 		}
938 
939 	}
940 }
941 
942 #endif /* !defined(BASIC) && !defined(CURSES_BASIC) */
943 
944 /* Initialization ---------------------------------------------------------- */
945 
ANTIC_Initialise(int * argc,char * argv[])946 int ANTIC_Initialise(int *argc, char *argv[])
947 {
948 #if !defined(BASIC) && !defined(CURSES_BASIC)
949 	int i, j;
950 
951 	for (i = j = 1; i < *argc; i++) {
952 		int i_a = (i + 1 < *argc);		/* is argument available? */
953 		int a_m = FALSE;			/* error, argument missing! */
954 
955 		if (strcmp(argv[i], "-artif") == 0) {
956 			if (i_a) {
957 				ANTIC_artif_mode = Util_sscandec(argv[++i]);
958 				if (ANTIC_artif_mode < 0 || ANTIC_artif_mode > 4) {
959 					Log_print("Invalid artifacting mode, using default.");
960 					ANTIC_artif_mode = 0;
961 				}
962 			}
963 			else a_m = TRUE;
964 		}
965 		else {
966 			if (strcmp(argv[i], "-help") == 0) {
967 				Log_print("\t-artif <num>     Set artifacting mode 0-4 (0 = disable)");
968 			}
969 			argv[j++] = argv[i];
970 		}
971 
972 		if (a_m) {
973 			Log_print("Missing argument for '%s'", argv[i]);
974 			return FALSE;
975 		}
976 	}
977 	*argc = j;
978 
979 	ANTIC_UpdateArtifacting();
980 
981 	playfield_lookup[0x00] = L_BAK;
982 	playfield_lookup[0x40] = L_PF0;
983 	playfield_lookup[0x80] = L_PF1;
984 	playfield_lookup[0xc0] = L_PF2;
985 	playfield_lookup[0x100] = L_PF3;
986 	blank_lookup[0x80] = blank_lookup[0xa0] = blank_lookup[0xc0] = blank_lookup[0xe0] = 0x00;
987 	hires_mask(0x00) = 0xffff;
988 #ifdef USE_COLOUR_TRANSLATION_TABLE
989 	hires_mask(0x40) = BYTE0_MASK;
990 	hires_mask(0x80) = BYTE1_MASK;
991 	hires_mask(0xc0) = 0;
992 #else
993 	hires_mask(0x40) = HIRES_MASK_01;
994 	hires_mask(0x80) = HIRES_MASK_10;
995 	hires_mask(0xc0) = 0xf0f0;
996 	hires_lum(0x00) = hires_lum(0x40) = hires_lum(0x80) = hires_lum(0xc0) = 0;
997 #endif
998 	init_pm_lookup();
999 	mode_e_an_lookup[0] = 0;
1000 	mode_e_an_lookup[1] = mode_e_an_lookup[4] = mode_e_an_lookup[0x10] = mode_e_an_lookup[0x40] = 0;
1001 	mode_e_an_lookup[2] = mode_e_an_lookup[8] = mode_e_an_lookup[0x20] = mode_e_an_lookup[0x80] = 1;
1002 	mode_e_an_lookup[3] = mode_e_an_lookup[12] = mode_e_an_lookup[0x30] = mode_e_an_lookup[0xc0] = 2;
1003 #ifdef NEW_CYCLE_EXACT
1004 	CYCLE_MAP_Create();
1005 	ANTIC_cpu2antic_ptr = &CYCLE_MAP_cpu2antic[0];
1006 	ANTIC_antic2cpu_ptr = &CYCLE_MAP_antic2cpu[0];
1007 #endif /* NEW_CYCLE_EXACT */
1008 
1009 #endif /* !defined(BASIC) && !defined(CURSES_BASIC) */
1010 
1011 	return TRUE;
1012 }
1013 
ANTIC_Reset(void)1014 void ANTIC_Reset(void)
1015 {
1016 	ANTIC_NMIEN = 0x00;
1017 	ANTIC_NMIST = 0x1f;
1018 	ANTIC_PutByte(ANTIC_OFFSET_DMACTL, 0);
1019 }
1020 
1021 #if !defined(BASIC) && !defined(CURSES_BASIC)
1022 
1023 /* Border ------------------------------------------------------------------ */
1024 
1025 #define DO_BORDER_1 {\
1026 	if (IS_ZERO_ULONG(pm_scanline_ptr)) {\
1027 		ULONG *l_ptr = (ULONG *) ptr;\
1028 		WRITE_VIDEO_LONG(l_ptr++, background); \
1029 		WRITE_VIDEO_LONG(l_ptr++, background); \
1030 		ptr = (UWORD *) l_ptr;\
1031 		pm_scanline_ptr += 4;\
1032 	}\
1033 	else {\
1034 		int k = 4;\
1035 		do
1036 
1037 #define DO_BORDER DO_BORDER_1\
1038 			WRITE_VIDEO(ptr++, COLOUR(pm_lookup_ptr[*pm_scanline_ptr++]));\
1039 		while (--k);\
1040 	}\
1041 }
1042 
1043 #define DO_GTIA10_BORDER DO_BORDER_1\
1044 			WRITE_VIDEO(ptr++, COLOUR(pm_lookup_ptr[*pm_scanline_ptr++ | 1]));\
1045 		while (--k);\
1046 	}\
1047 }
1048 
do_border(void)1049 static void do_border(void)
1050 {
1051 	int kk;
1052 	UWORD *ptr = &scrn_ptr[LBORDER_START];
1053 	const UBYTE *pm_scanline_ptr = &GTIA_pm_scanline[LBORDER_START];
1054 	ULONG background = ANTIC_lookup_gtia9[0];
1055 	/* left border */
1056 	for (kk = left_border_chars; kk; kk--)
1057 			DO_BORDER
1058 	/* right border */
1059 	ptr = &scrn_ptr[right_border_start];
1060 	pm_scanline_ptr = &GTIA_pm_scanline[right_border_start];
1061 	while (pm_scanline_ptr < &GTIA_pm_scanline[RBORDER_END])
1062 			DO_BORDER
1063 }
1064 
do_border_gtia10(void)1065 static void do_border_gtia10(void)
1066 {
1067 	int kk;
1068 	UWORD *ptr = &scrn_ptr[LBORDER_START];
1069 	const UBYTE *pm_scanline_ptr = &GTIA_pm_scanline[LBORDER_START];
1070 	ULONG background = ANTIC_cl[C_PM0] | (ANTIC_cl[C_PM0] << 16);
1071 	/* left border */
1072 	for (kk = left_border_chars; kk; kk--)
1073 		DO_GTIA10_BORDER
1074 	WRITE_VIDEO(ptr, COLOUR(pm_lookup_ptr[*pm_scanline_ptr | 1])); /* one extra pixel, because of the right shift of gtia10*/
1075 	/* right border */
1076 	pm_scanline_ptr = &GTIA_pm_scanline[right_border_start];
1077 	if (pm_scanline_ptr < &GTIA_pm_scanline[RBORDER_END]) {
1078 		ptr = &scrn_ptr[right_border_start + 1]; /*start one pixel further right because of the right shift of gtia10*/
1079 		WRITE_VIDEO(ptr++, COLOUR(pm_lookup_ptr[pm_scanline_ptr[1] | 1]));
1080 		WRITE_VIDEO(ptr++, COLOUR(pm_lookup_ptr[pm_scanline_ptr[2] | 1]));
1081 		WRITE_VIDEO(ptr++, COLOUR(pm_lookup_ptr[pm_scanline_ptr[3] | 1]));
1082 		pm_scanline_ptr += 4;
1083 		while (pm_scanline_ptr < &GTIA_pm_scanline[RBORDER_END])
1084 			DO_GTIA10_BORDER
1085 	}
1086 }
1087 
do_border_gtia11(void)1088 static void do_border_gtia11(void)
1089 {
1090 	int kk;
1091 	UWORD *ptr = &scrn_ptr[LBORDER_START];
1092 	const UBYTE *pm_scanline_ptr = &GTIA_pm_scanline[LBORDER_START];
1093 	ULONG background = ANTIC_lookup_gtia11[0];
1094 #ifdef USE_COLOUR_TRANSLATION_TABLE
1095 	ANTIC_cl[C_PF3] = colour_translation_table[GTIA_COLPF3 & 0xf0];
1096 #else
1097 	ANTIC_cl[C_PF3] &= 0xf0f0;
1098 #endif
1099 	ANTIC_cl[C_BAK] = (UWORD) background;
1100 	/* left border */
1101 	for (kk = left_border_chars; kk; kk--)
1102 		DO_BORDER
1103 	/* right border */
1104 	ptr = &scrn_ptr[right_border_start];
1105 	pm_scanline_ptr = &GTIA_pm_scanline[right_border_start];
1106 	while (pm_scanline_ptr < &GTIA_pm_scanline[RBORDER_END])
1107 		DO_BORDER
1108 	GTIA_COLOUR_TO_WORD(ANTIC_cl[C_PF3],GTIA_COLPF3)
1109 	GTIA_COLOUR_TO_WORD(ANTIC_cl[C_BAK],GTIA_COLBK)
1110 }
1111 
draw_antic_0(void)1112 static void draw_antic_0(void)
1113 {
1114 	UWORD *ptr = scrn_ptr + LBORDER_START;
1115 	if (GTIA_pm_dirty) {
1116 		const UBYTE *pm_scanline_ptr = &GTIA_pm_scanline[LBORDER_START];
1117 		ULONG background = ANTIC_lookup_gtia9[0];
1118 		do
1119 			DO_BORDER
1120 		while (pm_scanline_ptr < &GTIA_pm_scanline[RBORDER_END]);
1121 	}
1122 	else
1123 		FILL_VIDEO(ptr, ANTIC_cl[C_BAK], (RBORDER_END - LBORDER_START) * 2);
1124 }
1125 
draw_antic_0_gtia10(void)1126 static void draw_antic_0_gtia10(void)
1127 {
1128 	UWORD *ptr = scrn_ptr + LBORDER_START;
1129 	if (GTIA_pm_dirty) {
1130 		const UBYTE *pm_scanline_ptr = &GTIA_pm_scanline[LBORDER_START];
1131 		ULONG background = ANTIC_cl[C_PM0] | (ANTIC_cl[C_PM0] << 16);
1132 		do
1133 			DO_GTIA10_BORDER
1134 		while (pm_scanline_ptr < &GTIA_pm_scanline[RBORDER_END]);
1135 	}
1136 	else
1137 		FILL_VIDEO(ptr, ANTIC_cl[C_PM0], (RBORDER_END - LBORDER_START) * 2);
1138 }
1139 
draw_antic_0_gtia11(void)1140 static void draw_antic_0_gtia11(void)
1141 {
1142 	UWORD *ptr = scrn_ptr + LBORDER_START;
1143 	if (GTIA_pm_dirty) {
1144 		const UBYTE *pm_scanline_ptr = &GTIA_pm_scanline[LBORDER_START];
1145 		ULONG background = ANTIC_lookup_gtia11[0];
1146 #ifdef USE_COLOUR_TRANSLATION_TABLE
1147 		ANTIC_cl[C_PF3] = colour_translation_table[GTIA_COLPF3 & 0xf0];
1148 #else
1149 		ANTIC_cl[C_PF3] &= 0xf0f0;
1150 #endif
1151 		ANTIC_cl[C_BAK] = (UWORD) background;
1152 		do
1153 			DO_BORDER
1154 		while (pm_scanline_ptr < &GTIA_pm_scanline[RBORDER_END]);
1155 		GTIA_COLOUR_TO_WORD(ANTIC_cl[C_PF3],GTIA_COLPF3)
1156 		GTIA_COLOUR_TO_WORD(ANTIC_cl[C_BAK],GTIA_COLBK)
1157 	}
1158 	else
1159 		FILL_VIDEO(ptr, ANTIC_lookup_gtia11[0], (RBORDER_END - LBORDER_START) * 2);
1160 }
1161 
1162 /* ANTIC modes ------------------------------------------------------------- */
1163 
1164 static const UBYTE gtia_10_lookup[] =
1165 {L_BAK, L_BAK, L_BAK, L_BAK, L_PF0, L_PF1, L_PF2, L_PF3,
1166  L_BAK, L_BAK, L_BAK, L_BAK, L_PF0, L_PF1, L_PF2, L_PF3};
1167 static const UBYTE gtia_10_pm[] =
1168 {1, 2, 4, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
1169 
draw_an_gtia9(const ULONG * t_pm_scanline_ptr)1170 static void draw_an_gtia9(const ULONG *t_pm_scanline_ptr)
1171 {
1172 	int i = ((const UBYTE *) t_pm_scanline_ptr - GTIA_pm_scanline) & ~1;
1173 	while (i < right_border_start) {
1174 		UWORD *ptr = scrn_ptr + i;
1175 		int pixel = (an_scanline[i] << 2) + an_scanline[i + 1];
1176 		UBYTE pm_reg;
1177 		WRITE_VIDEO_LONG((ULONG *) ptr, ANTIC_lookup_gtia9[pixel]);
1178 		pm_reg = GTIA_pm_scanline[i];
1179 		if (pm_reg) {
1180 			pm_reg = pm_lookup_ptr[pm_reg];
1181 			if (pm_reg == L_PF3) {
1182 #ifdef USE_COLOUR_TRANSLATION_TABLE
1183 				WRITE_VIDEO(ptr, colour_translation_table[pixel | GTIA_COLPF3]);
1184 #else
1185 				WRITE_VIDEO(ptr, pixel | (pixel << 8) | ANTIC_cl[C_PF3]);
1186 #endif
1187 			}
1188 			else {
1189 				WRITE_VIDEO(ptr, COLOUR(pm_reg));
1190 			}
1191 		}
1192 		i++;
1193 		pm_reg = GTIA_pm_scanline[i];
1194 		if (pm_reg) {
1195 			pm_reg = pm_lookup_ptr[pm_reg];
1196 			if (pm_reg == L_PF3) {
1197 #ifdef USE_COLOUR_TRANSLATION_TABLE
1198 				WRITE_VIDEO(ptr + 1, colour_translation_table[pixel | GTIA_COLPF3]);
1199 #else
1200 				WRITE_VIDEO(ptr + 1, pixel | (pixel << 8) | ANTIC_cl[C_PF3]);
1201 #endif
1202 			}
1203 			else {
1204 				WRITE_VIDEO(ptr + 1, COLOUR(pm_reg));
1205 			}
1206 		}
1207 		i++;
1208 	}
1209 	do_border();
1210 }
1211 
draw_an_gtia10(const ULONG * t_pm_scanline_ptr)1212 static void draw_an_gtia10(const ULONG *t_pm_scanline_ptr)
1213 {
1214 	int i = ((const UBYTE *) t_pm_scanline_ptr - GTIA_pm_scanline) | 1;
1215 	UWORD lookup_gtia10[16];
1216 	lookup_gtia10[0] = ANTIC_cl[C_PM0];
1217 	lookup_gtia10[1] = ANTIC_cl[C_PM1];
1218 	lookup_gtia10[2] = ANTIC_cl[C_PM2];
1219 	lookup_gtia10[3] = ANTIC_cl[C_PM3];
1220 	lookup_gtia10[12] = lookup_gtia10[4] = ANTIC_cl[C_PF0];
1221 	lookup_gtia10[13] = lookup_gtia10[5] = ANTIC_cl[C_PF1];
1222 	lookup_gtia10[14] = lookup_gtia10[6] = ANTIC_cl[C_PF2];
1223 	lookup_gtia10[15] = lookup_gtia10[7] = ANTIC_cl[C_PF3];
1224 	lookup_gtia10[8] = lookup_gtia10[9] = lookup_gtia10[10] = lookup_gtia10[11] = ANTIC_cl[C_BAK];
1225 	while (i < right_border_start) {
1226 		UWORD *ptr = scrn_ptr + i;
1227 		int pixel = (an_scanline[i - 1] << 2) + an_scanline[i];
1228 		UBYTE pm_reg;
1229 		int colreg;
1230 		pm_reg = GTIA_pm_scanline[i];
1231 		if (pm_reg) {
1232 			colreg = gtia_10_lookup[pixel];
1233 			PF_COLLS(colreg) |= pm_reg;
1234 			pm_reg |= gtia_10_pm[pixel];
1235 			WRITE_VIDEO(ptr, COLOUR(pm_lookup_ptr[pm_reg] | colreg));
1236 		}
1237 		else {
1238 			WRITE_VIDEO(ptr, lookup_gtia10[pixel]);
1239 		}
1240 		i++;
1241 		pm_reg = GTIA_pm_scanline[i];
1242 		if (pm_reg) {
1243 			colreg = gtia_10_lookup[pixel];
1244 			PF_COLLS(colreg) |= pm_reg;
1245 			pm_reg |= gtia_10_pm[pixel];
1246 			WRITE_VIDEO(ptr + 1, COLOUR(pm_lookup_ptr[pm_reg] | colreg));
1247 		}
1248 		else {
1249 			WRITE_VIDEO(ptr + 1, lookup_gtia10[pixel]);
1250 		}
1251 		i++;
1252 	}
1253 	do_border_gtia10();
1254 }
1255 
draw_an_gtia11(const ULONG * t_pm_scanline_ptr)1256 static void draw_an_gtia11(const ULONG *t_pm_scanline_ptr)
1257 {
1258 	int i = ((const UBYTE *) t_pm_scanline_ptr - GTIA_pm_scanline) & ~1;
1259 	while (i < right_border_start) {
1260 		UWORD *ptr = scrn_ptr + i;
1261 		int pixel = (an_scanline[i] << 2) + an_scanline[i + 1];
1262 		UBYTE pm_reg;
1263 		WRITE_VIDEO_LONG((ULONG *) ptr, ANTIC_lookup_gtia11[pixel]);
1264 		pm_reg = GTIA_pm_scanline[i];
1265 		if (pm_reg) {
1266 			pm_reg = pm_lookup_ptr[pm_reg];
1267 			if (pm_reg == L_PF3) {
1268 #ifdef USE_COLOUR_TRANSLATION_TABLE
1269 				WRITE_VIDEO(ptr, colour_translation_table[pixel ? pixel | GTIA_COLPF3 : GTIA_COLPF3 & 0xf0]);
1270 #else
1271 				WRITE_VIDEO(ptr, pixel ? (pixel << 4) | (pixel << 12) | ANTIC_cl[C_PF3] : ANTIC_cl[C_PF3] & 0xf0f0);
1272 #endif
1273 			}
1274 			else {
1275 				WRITE_VIDEO(ptr, COLOUR(pm_reg));
1276 			}
1277 		}
1278 		i++;
1279 		pm_reg = GTIA_pm_scanline[i];
1280 		if (pm_reg) {
1281 			pm_reg = pm_lookup_ptr[pm_reg];
1282 			if (pm_reg == L_PF3) {
1283 #ifdef USE_COLOUR_TRANSLATION_TABLE
1284 				WRITE_VIDEO(ptr + 1, colour_translation_table[pixel ? pixel | GTIA_COLPF3 : GTIA_COLPF3 & 0xf0]);
1285 #else
1286 				WRITE_VIDEO(ptr + 1, pixel ? (pixel << 4) | (pixel << 12) | ANTIC_cl[C_PF3] : ANTIC_cl[C_PF3] & 0xf0f0);
1287 #endif
1288 			}
1289 			else {
1290 				WRITE_VIDEO(ptr + 1, COLOUR(pm_reg));
1291 			}
1292 		}
1293 		i++;
1294 	}
1295 	do_border_gtia11();
1296 }
1297 
draw_an_gtia_bug(const ULONG * t_pm_scanline_ptr)1298 static void draw_an_gtia_bug(const ULONG *t_pm_scanline_ptr)
1299 {
1300 	static const UBYTE gtia_bug_colreg[] = {L_PF0, L_PF1, L_PF2, L_PF3};
1301 	UWORD lookup_gtia_bug[16];
1302 	int i;
1303 	lookup_gtia_bug[0] = ANTIC_cl[C_PF0];
1304 	lookup_gtia_bug[1] = ANTIC_cl[C_PF1];
1305 	lookup_gtia_bug[2] = ANTIC_cl[C_PF2];
1306 	lookup_gtia_bug[3] = ANTIC_cl[C_PF3];
1307 	i = ((const UBYTE *) t_pm_scanline_ptr - GTIA_pm_scanline);
1308 	while (i < right_border_start) {
1309 		UWORD *ptr = scrn_ptr + i;
1310 		int pixel = an_scanline[i];
1311 		UBYTE pm_reg;
1312 		int colreg;
1313 		pm_reg = GTIA_pm_scanline[i];
1314 		if (pm_reg) {
1315 			colreg = gtia_bug_colreg[pixel];
1316 			PF_COLLS(colreg) |= pm_reg;
1317 			WRITE_VIDEO(ptr, COLOUR(pm_lookup_ptr[pm_reg] | colreg));
1318 		}
1319 		else {
1320 			WRITE_VIDEO(ptr, lookup_gtia_bug[pixel]);
1321 		}
1322 		i++;
1323 	}
1324 	do_border();
1325 }
1326 
1327 #define DEFINE_DRAW_AN(anticmode) \
1328 	static void draw_antic_ ## anticmode ## _gtia9 (int nchars, const UBYTE *antic_memptr, UWORD *ptr, const ULONG *t_pm_scanline_ptr)\
1329 	{\
1330 		prepare_an_antic_ ## anticmode (nchars, antic_memptr, t_pm_scanline_ptr);\
1331 		draw_an_gtia9(t_pm_scanline_ptr);\
1332 	}\
1333 	static void draw_antic_ ## anticmode ## _gtia10 (int nchars, const UBYTE *antic_memptr, UWORD *ptr, const ULONG *t_pm_scanline_ptr)\
1334 	{\
1335 		prepare_an_antic_ ## anticmode (nchars, antic_memptr, t_pm_scanline_ptr);\
1336 		draw_an_gtia10(t_pm_scanline_ptr);\
1337 	}\
1338 	static void draw_antic_ ## anticmode ## _gtia11 (int nchars, const UBYTE *antic_memptr, UWORD *ptr, const ULONG *t_pm_scanline_ptr)\
1339 	{\
1340 		prepare_an_antic_ ## anticmode (nchars, antic_memptr, t_pm_scanline_ptr);\
1341 		draw_an_gtia11(t_pm_scanline_ptr);\
1342 	}
1343 
1344 #define CHAR_LOOP_BEGIN do {
1345 #define CHAR_LOOP_END } while (--nchars);
1346 
1347 #define DO_PMG_LORES PF_COLLS(colreg) |= pm_pixel = *c_pm_scanline_ptr++;\
1348 	WRITE_VIDEO(ptr++, COLOUR(pm_lookup_ptr[pm_pixel] | colreg));
1349 
1350 #ifdef ALTERNATE_LOOP_COUNTERS 	/* speeds-up pmg in hires a bit or not? try it :) */
1351 #define FOUR_LOOP_BEGIN(data) data |= 0x800000; do {	/* data becomes negative after four data <<= 2 */
1352 #define FOUR_LOOP_END(data) } while (data >= 0);
1353 #else
1354 #define FOUR_LOOP_BEGIN(data) int k = 4; do {
1355 #define FOUR_LOOP_END(data) } while (--k);
1356 #endif
1357 
1358 #ifdef USE_COLOUR_TRANSLATION_TABLE
1359 
1360 #define INIT_HIRES hires_norm(0x00) = ANTIC_cl[C_PF2];\
1361 	hires_norm(0x40) = hires_norm(0x10) = hires_norm(0x04) = (ANTIC_cl[C_PF2] & BYTE0_MASK) | (ANTIC_cl[C_HI2] & BYTE1_MASK);\
1362 	hires_norm(0x80) = hires_norm(0x20) = hires_norm(0x08) = (ANTIC_cl[C_HI2] & BYTE0_MASK) | (ANTIC_cl[C_PF2] & BYTE1_MASK);\
1363 	hires_norm(0xc0) = hires_norm(0x30) = hires_norm(0x0c) = ANTIC_cl[C_HI2];
1364 
1365 #define DO_PMG_HIRES(data) {\
1366 	const UBYTE *c_pm_scanline_ptr = (const UBYTE *) t_pm_scanline_ptr;\
1367 	int pm_pixel;\
1368 	int mask;\
1369 	FOUR_LOOP_BEGIN(data)\
1370 		pm_pixel = *c_pm_scanline_ptr++;\
1371 		if (data & 0xc0)\
1372 			PF2PM |= pm_pixel;\
1373 		mask = hires_mask(data & 0xc0);\
1374 		pm_pixel = pm_lookup_ptr[pm_pixel] | L_PF2;\
1375 		WRITE_VIDEO(ptr++, (COLOUR(pm_pixel) & mask) | (COLOUR(pm_pixel + (L_HI2 - L_PF2)) & ~mask));\
1376 		data <<= 2;\
1377 	FOUR_LOOP_END(data)\
1378 }
1379 
1380 #else /* USE_COLOUR_TRANSLATION_TABLE */
1381 
1382 #define INIT_HIRES hires_norm(0x00) = ANTIC_cl[C_PF2];\
1383 	hires_norm(0x40) = hires_norm(0x10) = hires_norm(0x04) = (ANTIC_cl[C_PF2] & HIRES_MASK_01) | hires_lum(0x40);\
1384 	hires_norm(0x80) = hires_norm(0x20) = hires_norm(0x08) = (ANTIC_cl[C_PF2] & HIRES_MASK_10) | hires_lum(0x80);\
1385 	hires_norm(0xc0) = hires_norm(0x30) = hires_norm(0x0c) = (ANTIC_cl[C_PF2] & 0xf0f0) | hires_lum(0xc0);
1386 
1387 #define INIT_ARTIF_NEW art_lookup_new[0] = art_lookup_new[1] = art_lookup_new[2] = art_lookup_new[3] = \
1388 	art_lookup_new[16] = art_lookup_new[17] = art_lookup_new[18] = art_lookup_new[19] = \
1389 	art_lookup_new[32] = art_lookup_new[33] = art_lookup_new[34] = art_lookup_new[35] = \
1390 	art_lookup_new[48] = art_lookup_new[49] = art_lookup_new[50] = art_lookup_new[51] = ANTIC_cl[C_PF2];\
1391 	art_lookup_new[7] = art_lookup_new[23] = art_lookup_new[39] = art_lookup_new[55] = (ANTIC_cl[C_PF2] & HIRES_MASK_01) | hires_lum(0x40);\
1392 	art_lookup_new[56] = art_lookup_new[57] = art_lookup_new[58] = art_lookup_new[59] = (ANTIC_cl[C_PF2] & HIRES_MASK_10) | hires_lum(0x80);\
1393 	art_lookup_new[12] = art_lookup_new[13] = art_lookup_new[14] = art_lookup_new[15] = \
1394 	art_lookup_new[28] = art_lookup_new[29] = art_lookup_new[30] = art_lookup_new[31] = \
1395 	art_lookup_new[44] = art_lookup_new[45] = art_lookup_new[46] = art_lookup_new[47] = \
1396 	art_lookup_new[60] = art_lookup_new[61] = art_lookup_new[62] = art_lookup_new[63] = (ANTIC_cl[C_PF2] & 0xf0f0) | hires_lum(0xc0);\
1397 	if ((ANTIC_cl[C_PF2] & 0x0F00) != (ANTIC_cl[C_PF1] & 0x0F00)) { \
1398 		art_lookup_new[4] = art_lookup_new[5] = art_lookup_new[36] = art_lookup_new[37] = \
1399 		art_lookup_new[52] = art_lookup_new[53 ]= ((art_colour1_new & BYTE1_MASK & ~(HIRES_LUM_01))) | hires_lum(0x40) | (ANTIC_cl[C_PF2] & BYTE0_MASK);\
1400 		art_lookup_new[20] = art_lookup_new[21] = (art_colour1_new & 0xf0f0) | hires_lum(0xc0);\
1401 		art_lookup_new[8] = art_lookup_new[9] = art_lookup_new[11] = art_lookup_new[40] = \
1402 		art_lookup_new[43] = ((art_colour2_new & BYTE0_MASK & ~(HIRES_LUM_10))) | hires_lum(0x80) | (ANTIC_cl[C_PF2] & BYTE1_MASK);\
1403 		art_lookup_new[10] = art_lookup_new[41] = art_lookup_new[42] = (art_colour2_new & 0xf0f0) | hires_lum(0xc0);\
1404 		}\
1405 	else {\
1406 		art_lookup_new[4] = art_lookup_new[5] = art_lookup_new[36] = art_lookup_new[37] = \
1407 		art_lookup_new[52] = art_lookup_new[53 ]= art_lookup_new[20] = art_lookup_new[21] = \
1408 		art_lookup_new[8] = art_lookup_new[9] = art_lookup_new[11] = art_lookup_new[40] = \
1409 		art_lookup_new[43] = art_lookup_new[10] = art_lookup_new[41] = art_lookup_new[42] = ANTIC_cl[C_PF2];\
1410 		}\
1411 	art_lookup_new[6] = art_lookup_new[22] = art_lookup_new[38] = art_lookup_new[54] = (ANTIC_cl[C_PF2] & HIRES_MASK_01) | hires_lum(0x40);\
1412 	art_lookup_new[24] = art_lookup_new[25] = art_lookup_new[26] = art_lookup_new[27] = (ANTIC_cl[C_PF2] & HIRES_MASK_10) | hires_lum(0x80);
1413 
1414 #define DO_PMG_HIRES(data) {\
1415 	const UBYTE *c_pm_scanline_ptr = (const UBYTE *) t_pm_scanline_ptr;\
1416 	int pm_pixel;\
1417 	FOUR_LOOP_BEGIN(data)\
1418 		pm_pixel = *c_pm_scanline_ptr++;\
1419 		if (data & 0xc0)\
1420 			PF2PM |= pm_pixel;\
1421 		WRITE_VIDEO(ptr++, (COLOUR(pm_lookup_ptr[pm_pixel] | L_PF2) & hires_mask(data & 0xc0)) | hires_lum(data & 0xc0));\
1422 		data <<= 2;\
1423 	FOUR_LOOP_END(data)\
1424 }
1425 
1426 #define DO_PMG_HIRES_NEW(data, tally) {\
1427 	const UBYTE *c_pm_scanline_ptr = (const UBYTE *) t_pm_scanline_ptr;\
1428 	int pm_pixel;\
1429 	FOUR_LOOP_BEGIN(data)\
1430 		pm_pixel = *c_pm_scanline_ptr++;\
1431 		if (pm_pixel) \
1432 			WRITE_VIDEO(ptr++, (COLOUR(pm_lookup_ptr[pm_pixel] | L_PF2)));\
1433 		else\
1434 			WRITE_VIDEO(ptr++, art_lookup_new[(tally & 0xfc0000) >> 18]); \
1435 		data <<= 2;\
1436 		tally <<= 6;\
1437 	FOUR_LOOP_END(data)\
1438 }
1439 
1440 #endif /* USE_COLOUR_TRANSLATION_TABLE */
1441 
1442 #ifdef NEW_CYCLE_EXACT
1443 #define ADD_FONT_CYCLES
1444 #else
1445 #define ADD_FONT_CYCLES ANTIC_xpos += font_cycles[md]
1446 #endif
1447 
1448 #ifdef PAGED_MEM
1449 
1450 #define INIT_ANTIC_2	int t_chbase = (dctr ^ chbase_20) & 0xfc07;\
1451 	ADD_FONT_CYCLES;\
1452 	blank_lookup[0x60] = (anticmode == 2 || dctr & 0xe) ? 0xff : 0;\
1453 	blank_lookup[0x00] = blank_lookup[0x20] = blank_lookup[0x40] = (dctr & 0xe) == 8 ? 0 : 0xff;
1454 
1455 #define GET_CHDATA_ANTIC_2	chdata = (screendata & invert_mask) ? 0xff : 0;\
1456 	if (blank_lookup[screendata & blank_mask])\
1457 		chdata ^= MEMORY_dGetByte(t_chbase + ((UWORD) (screendata & 0x7f) << 3));
1458 
1459 #else /* PAGED_MEM */
1460 
1461 #define INIT_ANTIC_2	const UBYTE *chptr;\
1462 	if (ANTIC_xe_ptr != NULL && chbase_20 < 0x8000 && chbase_20 >= 0x4000)\
1463 		chptr = ANTIC_xe_ptr + ((dctr ^ chbase_20) & 0x3c07);\
1464 	else\
1465 		chptr = MEMORY_mem + ((dctr ^ chbase_20) & 0xfc07);\
1466 	ADD_FONT_CYCLES;\
1467 	blank_lookup[0x60] = (anticmode == 2 || dctr & 0xe) ? 0xff : 0;\
1468 	blank_lookup[0x00] = blank_lookup[0x20] = blank_lookup[0x40] = (dctr & 0xe) == 8 ? 0 : 0xff;
1469 
1470 #define GET_CHDATA_ANTIC_2	chdata = (screendata & invert_mask) ? 0xff : 0;\
1471 	if (blank_lookup[screendata & blank_mask])\
1472 		chdata ^= chptr[(screendata & 0x7f) << 3];
1473 
1474 #endif /* PAGED_MEM */
1475 
draw_antic_2(int nchars,const UBYTE * antic_memptr,UWORD * ptr,const ULONG * t_pm_scanline_ptr)1476 static void draw_antic_2(int nchars, const UBYTE *antic_memptr, UWORD *ptr, const ULONG *t_pm_scanline_ptr)
1477 {
1478 	INIT_BACKGROUND_6
1479 	INIT_ANTIC_2
1480 	INIT_HIRES
1481 
1482 	CHAR_LOOP_BEGIN
1483 		UBYTE screendata = *antic_memptr++;
1484 		int chdata;
1485 
1486 		GET_CHDATA_ANTIC_2
1487 		if (IS_ZERO_ULONG(t_pm_scanline_ptr)) {
1488 			if (chdata) {
1489 				WRITE_VIDEO(ptr++, hires_norm(chdata & 0xc0));
1490 				WRITE_VIDEO(ptr++, hires_norm(chdata & 0x30));
1491 				WRITE_VIDEO(ptr++, hires_norm(chdata & 0x0c));
1492 				WRITE_VIDEO(ptr++, hires_norm((chdata & 0x03) << 2));
1493 			}
1494 			else
1495 				DRAW_BACKGROUND(C_PF2)
1496 		}
1497 		else
1498 			DO_PMG_HIRES(chdata)
1499 		t_pm_scanline_ptr++;
1500 	CHAR_LOOP_END
1501 	do_border();
1502 }
1503 
1504 #ifdef NEW_CYCLE_EXACT
draw_antic_2_dmactl_bug(int nchars,const UBYTE * antic_memptr,UWORD * ptr,const ULONG * t_pm_scanline_ptr)1505 static void draw_antic_2_dmactl_bug(int nchars, const UBYTE *antic_memptr, UWORD *ptr, const ULONG *t_pm_scanline_ptr)
1506 {
1507 	INIT_BACKGROUND_6
1508 	INIT_ANTIC_2
1509 	INIT_HIRES
1510 
1511 	CHAR_LOOP_BEGIN
1512 		/* UBYTE screendata = *antic_memptr++; */
1513 
1514 /* In this glitched mode, the output depends on the MSB of the last char */
1515 /* drawn in the previous line, and invert_mask.  It seems to reveal that */
1516 /* ANTIC has a latch that is set by the MSB of the char that controls an */
1517 /* invert gate. */
1518 /* When this gate was set on the last line and the next line is glitched */
1519 /* it remains set and the whole line appears inverted */
1520 /* We'll use this modeline to draw antic f glitched as well, and set */
1521 /* dmactl_bug_chdata to 0 */
1522 		int chdata = (dmactl_bug_chdata & invert_mask) ? 0xff : 0;
1523 		/* GET_CHDATA_ANTIC_2 */
1524 		if (IS_ZERO_ULONG(t_pm_scanline_ptr)) {
1525 
1526 			if (chdata) {
1527 				WRITE_VIDEO(ptr++, hires_norm(chdata & 0xc0));
1528 				WRITE_VIDEO(ptr++, hires_norm(chdata & 0x30));
1529 				WRITE_VIDEO(ptr++, hires_norm(chdata & 0x0c));
1530 				WRITE_VIDEO(ptr++, hires_norm((chdata & 0x03) << 2));
1531 			}
1532 			else
1533 				DRAW_BACKGROUND(C_PF2)
1534 		}
1535 		else
1536 			DO_PMG_HIRES(chdata)
1537 		t_pm_scanline_ptr++;
1538 	CHAR_LOOP_END
1539 	do_border();
1540 }
1541 #endif
1542 
draw_antic_2_artif(int nchars,const UBYTE * antic_memptr,UWORD * ptr,const ULONG * t_pm_scanline_ptr)1543 static void draw_antic_2_artif(int nchars, const UBYTE *antic_memptr, UWORD *ptr, const ULONG *t_pm_scanline_ptr)
1544 {
1545 	ULONG screendata_tally;
1546 	INIT_ANTIC_2
1547 	{
1548 		UBYTE screendata = *antic_memptr++;
1549 		UBYTE chdata;
1550 		GET_CHDATA_ANTIC_2
1551 		screendata_tally = chdata;
1552 	}
1553 	setup_art_colours();
1554 
1555 	CHAR_LOOP_BEGIN
1556 		UBYTE screendata = *antic_memptr++;
1557 		ULONG chdata;
1558 
1559 		GET_CHDATA_ANTIC_2
1560 		screendata_tally <<= 8;
1561 		screendata_tally |= chdata;
1562 		if (IS_ZERO_ULONG(t_pm_scanline_ptr))
1563 			DRAW_ARTIF
1564 		else {
1565 			chdata = screendata_tally >> 8;
1566 			DO_PMG_HIRES(chdata)
1567 		}
1568 		t_pm_scanline_ptr++;
1569 	CHAR_LOOP_END
1570 	do_border();
1571 }
1572 
1573 #ifndef USE_COLOUR_TRANSLATION_TABLE
draw_antic_2_artif_new(int nchars,const UBYTE * antic_memptr,UWORD * ptr,const ULONG * t_pm_scanline_ptr)1574 static void draw_antic_2_artif_new(int nchars, const UBYTE *antic_memptr, UWORD *ptr, const ULONG *t_pm_scanline_ptr)
1575 {
1576 	ULONG screendata_tally;
1577 	ULONG pmtally;
1578 	UBYTE screendata = *antic_memptr++;
1579 	UBYTE chdata;
1580 	INIT_ANTIC_2
1581 	INIT_ARTIF_NEW
1582 	GET_CHDATA_ANTIC_2
1583 	screendata_tally = chdata;
1584 	setup_art_colours();
1585 
1586 	CHAR_LOOP_BEGIN
1587 		UBYTE screendata = *antic_memptr++;
1588 		ULONG chdata;
1589 
1590 		GET_CHDATA_ANTIC_2
1591 		screendata_tally <<= 8;
1592 		screendata_tally |= chdata;
1593 		if (IS_ZERO_ULONG(t_pm_scanline_ptr))
1594 			DRAW_ARTIF_NEW
1595 		else {
1596 			chdata = screendata_tally >> 8;
1597 			pmtally = ((screendata_tally & 0x03f000) << 6) |
1598 					  ((screendata_tally & 0x00fc00) << 2) |
1599 					  ((screendata_tally & 0x003f00) >> 2) |
1600 					  ((screendata_tally & 0x000fc0) >> 6);
1601 			DO_PMG_HIRES_NEW(chdata,pmtally)
1602 		}
1603 		t_pm_scanline_ptr++;
1604 	CHAR_LOOP_END
1605 	do_border();
1606 }
1607 #endif
1608 
prepare_an_antic_2(int nchars,const UBYTE * antic_memptr,const ULONG * t_pm_scanline_ptr)1609 static void prepare_an_antic_2(int nchars, const UBYTE *antic_memptr, const ULONG *t_pm_scanline_ptr)
1610 {
1611 	UBYTE *an_ptr = (UBYTE *) t_pm_scanline_ptr + (an_scanline - GTIA_pm_scanline);
1612 #ifdef PAGED_MEM
1613 	int t_chbase = (dctr ^ chbase_20) & 0xfc07;
1614 #else
1615 	const UBYTE *chptr;
1616 	if (ANTIC_xe_ptr != NULL && chbase_20 < 0x8000 && chbase_20 >= 0x4000)
1617 		chptr = ANTIC_xe_ptr + ((dctr ^ chbase_20) & 0x3c07);
1618 	else
1619 		chptr = MEMORY_mem + ((dctr ^ chbase_20) & 0xfc07);
1620 #endif
1621 
1622 	CHAR_LOOP_BEGIN
1623 		UBYTE screendata = *antic_memptr++;
1624 		int chdata;
1625 		GET_CHDATA_ANTIC_2
1626 		*an_ptr++ = chdata >> 6;
1627 		*an_ptr++ = (chdata >> 4) & 3;
1628 		*an_ptr++ = (chdata >> 2) & 3;
1629 		*an_ptr++ = chdata & 3;
1630 	CHAR_LOOP_END
1631 }
1632 
draw_antic_2_gtia9(int nchars,const UBYTE * antic_memptr,UWORD * ptr,const ULONG * t_pm_scanline_ptr)1633 static void draw_antic_2_gtia9(int nchars, const UBYTE *antic_memptr, UWORD *ptr, const ULONG *t_pm_scanline_ptr)
1634 {
1635 	INIT_ANTIC_2
1636 	if ((unsigned long) ptr & 2) { /* HSCROL & 1 */
1637 		prepare_an_antic_2(nchars, antic_memptr, t_pm_scanline_ptr);
1638 		draw_an_gtia9(t_pm_scanline_ptr);
1639 		return;
1640 	}
1641 
1642 	CHAR_LOOP_BEGIN
1643 		UBYTE screendata = *antic_memptr++;
1644 		int chdata;
1645 
1646 		GET_CHDATA_ANTIC_2
1647 		WRITE_VIDEO_LONG((ULONG *) ptr, ANTIC_lookup_gtia9[chdata >> 4]);
1648 		WRITE_VIDEO_LONG((ULONG *) ptr + 1, ANTIC_lookup_gtia9[chdata & 0xf]);
1649 		if (IS_ZERO_ULONG(t_pm_scanline_ptr))
1650 			ptr += 4;
1651 		else {
1652 			const UBYTE *c_pm_scanline_ptr = (const UBYTE *) t_pm_scanline_ptr;
1653 			int k = 4;
1654 			UBYTE pm_reg;
1655 			do {
1656 				pm_reg = pm_lookup_ptr[*c_pm_scanline_ptr++];
1657 				if (pm_reg) {
1658 					if (pm_reg == L_PF3) {
1659 						UBYTE tmp = k > 2 ? chdata >> 4 : chdata & 0xf;
1660 #ifdef USE_COLOUR_TRANSLATION_TABLE
1661 						WRITE_VIDEO(ptr, colour_translation_table[tmp | GTIA_COLPF3]);
1662 #else
1663 						WRITE_VIDEO(ptr, tmp | ((UWORD)tmp << 8) | ANTIC_cl[C_PF3]);
1664 #endif
1665 					}
1666 					else
1667 					{
1668 						WRITE_VIDEO(ptr, COLOUR(pm_reg));
1669 					}
1670 				}
1671 				ptr++;
1672 			} while (--k);
1673 		}
1674 		t_pm_scanline_ptr++;
1675 	CHAR_LOOP_END
1676 	do_border();
1677 }
1678 
draw_antic_2_gtia10(int nchars,const UBYTE * antic_memptr,UWORD * ptr,const ULONG * t_pm_scanline_ptr)1679 static void draw_antic_2_gtia10(int nchars, const UBYTE *antic_memptr, UWORD *ptr, const ULONG *t_pm_scanline_ptr)
1680 {
1681 #ifdef WORDS_UNALIGNED_OK
1682 	ULONG lookup_gtia10[16];
1683 #else
1684 	UWORD lookup_gtia10[16];
1685 #endif
1686 	INIT_ANTIC_2
1687 	if ((unsigned long) ptr & 2) { /* HSCROL & 1 */
1688 		prepare_an_antic_2(nchars, antic_memptr, t_pm_scanline_ptr);
1689 		draw_an_gtia10(t_pm_scanline_ptr);
1690 		return;
1691 	}
1692 
1693 #ifdef WORDS_UNALIGNED_OK
1694 	lookup_gtia10[0] = ANTIC_cl[C_PM0] | (ANTIC_cl[C_PM0] << 16);
1695 	lookup_gtia10[1] = ANTIC_cl[C_PM1] | (ANTIC_cl[C_PM1] << 16);
1696 	lookup_gtia10[2] = ANTIC_cl[C_PM2] | (ANTIC_cl[C_PM2] << 16);
1697 	lookup_gtia10[3] = ANTIC_cl[C_PM3] | (ANTIC_cl[C_PM3] << 16);
1698 	lookup_gtia10[12] = lookup_gtia10[4] = ANTIC_cl[C_PF0] | (ANTIC_cl[C_PF0] << 16);
1699 	lookup_gtia10[13] = lookup_gtia10[5] = ANTIC_cl[C_PF1] | (ANTIC_cl[C_PF1] << 16);
1700 	lookup_gtia10[14] = lookup_gtia10[6] = ANTIC_cl[C_PF2] | (ANTIC_cl[C_PF2] << 16);
1701 	lookup_gtia10[15] = lookup_gtia10[7] = ANTIC_cl[C_PF3] | (ANTIC_cl[C_PF3] << 16);
1702 	lookup_gtia10[8] = lookup_gtia10[9] = lookup_gtia10[10] = lookup_gtia10[11] = ANTIC_lookup_gtia9[0];
1703 #else
1704 	lookup_gtia10[0] = ANTIC_cl[C_PM0];
1705 	lookup_gtia10[1] = ANTIC_cl[C_PM1];
1706 	lookup_gtia10[2] = ANTIC_cl[C_PM2];
1707 	lookup_gtia10[3] = ANTIC_cl[C_PM3];
1708 	lookup_gtia10[12] = lookup_gtia10[4] = ANTIC_cl[C_PF0];
1709 	lookup_gtia10[13] = lookup_gtia10[5] = ANTIC_cl[C_PF1];
1710 	lookup_gtia10[14] = lookup_gtia10[6] = ANTIC_cl[C_PF2];
1711 	lookup_gtia10[15] = lookup_gtia10[7] = ANTIC_cl[C_PF3];
1712 	lookup_gtia10[8] = lookup_gtia10[9] = lookup_gtia10[10] = lookup_gtia10[11] = ANTIC_cl[C_BAK];
1713 #endif
1714 	ptr++;
1715 	t_pm_scanline_ptr = (const ULONG *) (((const UBYTE *) t_pm_scanline_ptr) + 1);
1716 	CHAR_LOOP_BEGIN
1717 		UBYTE screendata = *antic_memptr++;
1718 		int chdata;
1719 
1720 		GET_CHDATA_ANTIC_2
1721 		if (IS_ZERO_ULONG(t_pm_scanline_ptr)) {
1722 			DO_GTIA_BYTE(ptr, lookup_gtia10, chdata)
1723 			ptr += 4;
1724 		}
1725 		else {
1726 			const UBYTE *c_pm_scanline_ptr = (const UBYTE *) t_pm_scanline_ptr;
1727 			int pm_pixel;
1728 			int colreg;
1729 			int k = 4;
1730 			UBYTE t_screendata = chdata >> 4;
1731 			do {
1732 				colreg = gtia_10_lookup[t_screendata];
1733 				PF_COLLS(colreg) |= pm_pixel = *c_pm_scanline_ptr++;
1734 				pm_pixel |= gtia_10_pm[t_screendata];
1735 				WRITE_VIDEO(ptr++, COLOUR(pm_lookup_ptr[pm_pixel] | colreg));
1736 				if (k == 3)
1737 					t_screendata = chdata & 0x0f;
1738 			} while (--k);
1739 		}
1740 		t_pm_scanline_ptr++;
1741 	CHAR_LOOP_END
1742 	do_border_gtia10();
1743 }
1744 
draw_antic_2_gtia11(int nchars,const UBYTE * antic_memptr,UWORD * ptr,const ULONG * t_pm_scanline_ptr)1745 static void draw_antic_2_gtia11(int nchars, const UBYTE *antic_memptr, UWORD *ptr, const ULONG *t_pm_scanline_ptr)
1746 {
1747 	INIT_ANTIC_2
1748 	if ((unsigned long) ptr & 2) { /* HSCROL & 1 */
1749 		prepare_an_antic_2(nchars, antic_memptr, t_pm_scanline_ptr);
1750 		draw_an_gtia11(t_pm_scanline_ptr);
1751 		return;
1752 	}
1753 
1754 	CHAR_LOOP_BEGIN
1755 		UBYTE screendata = *antic_memptr++;
1756 		int chdata;
1757 
1758 		GET_CHDATA_ANTIC_2
1759 		WRITE_VIDEO_LONG((ULONG *) ptr, ANTIC_lookup_gtia11[chdata >> 4]);
1760 		WRITE_VIDEO_LONG((ULONG *) ptr + 1, ANTIC_lookup_gtia11[chdata & 0xf]);
1761 		if (IS_ZERO_ULONG(t_pm_scanline_ptr))
1762 			ptr += 4;
1763 		else {
1764 			const UBYTE *c_pm_scanline_ptr = (const UBYTE *) t_pm_scanline_ptr;
1765 			int k = 4;
1766 			UBYTE pm_reg;
1767 			do {
1768 				pm_reg = pm_lookup_ptr[*c_pm_scanline_ptr++];
1769 				if (pm_reg) {
1770 					if (pm_reg == L_PF3) {
1771 						UBYTE tmp = k > 2 ? chdata & 0xf0 : chdata << 4;
1772 #ifdef USE_COLOUR_TRANSLATION_TABLE
1773 						WRITE_VIDEO(ptr, colour_translation_table[tmp ? tmp | GTIA_COLPF3 : GTIA_COLPF3 & 0xf0]);
1774 #else
1775 						WRITE_VIDEO(ptr, tmp ? tmp | ((UWORD)tmp << 8) | ANTIC_cl[C_PF3] : ANTIC_cl[C_PF3] & 0xf0f0);
1776 #endif
1777 					}
1778 					else
1779 					{
1780 						WRITE_VIDEO(ptr, COLOUR(pm_reg));
1781 					}
1782 				}
1783 				ptr++;
1784 			} while (--k);
1785 		}
1786 		t_pm_scanline_ptr++;
1787 	CHAR_LOOP_END
1788 	do_border_gtia11();
1789 }
1790 
draw_antic_2_gtia_bug(int nchars,const UBYTE * antic_memptr,UWORD * ptr,const ULONG * t_pm_scanline_ptr)1791 static void draw_antic_2_gtia_bug(int nchars, const UBYTE *antic_memptr, UWORD *ptr, const ULONG *t_pm_scanline_ptr)
1792 {
1793 	prepare_an_antic_2(nchars, antic_memptr, t_pm_scanline_ptr);
1794 	draw_an_gtia_bug(t_pm_scanline_ptr);
1795 	return;
1796 }
1797 
draw_antic_4(int nchars,const UBYTE * antic_memptr,UWORD * ptr,const ULONG * t_pm_scanline_ptr)1798 static void draw_antic_4(int nchars, const UBYTE *antic_memptr, UWORD *ptr, const ULONG *t_pm_scanline_ptr)
1799 {
1800 	INIT_BACKGROUND_8
1801 #ifdef PAGED_MEM
1802 	UWORD t_chbase = ((anticmode == 4 ? dctr : dctr >> 1) ^ chbase_20) & 0xfc07;
1803 #else
1804 	const UBYTE *chptr;
1805 	if (ANTIC_xe_ptr != NULL && chbase_20 < 0x8000 && chbase_20 >= 0x4000)
1806 		chptr = ANTIC_xe_ptr + (((anticmode == 4 ? dctr : dctr >> 1) ^ chbase_20) & 0x3c07);
1807 	else
1808 		chptr = MEMORY_mem + (((anticmode == 4 ? dctr : dctr >> 1) ^ chbase_20) & 0xfc07);
1809 #endif
1810 
1811 	ADD_FONT_CYCLES;
1812 	lookup2[0x0f] = lookup2[0x00] = ANTIC_cl[C_BAK];
1813 	lookup2[0x4f] = lookup2[0x1f] = lookup2[0x13] =
1814 	lookup2[0x40] = lookup2[0x10] = lookup2[0x04] = lookup2[0x01] = ANTIC_cl[C_PF0];
1815 	lookup2[0x8f] = lookup2[0x2f] = lookup2[0x17] = lookup2[0x11] =
1816 	lookup2[0x80] = lookup2[0x20] = lookup2[0x08] = lookup2[0x02] = ANTIC_cl[C_PF1];
1817 	lookup2[0xc0] = lookup2[0x30] = lookup2[0x0c] = lookup2[0x03] = ANTIC_cl[C_PF2];
1818 	lookup2[0xcf] = lookup2[0x3f] = lookup2[0x1b] = lookup2[0x12] = ANTIC_cl[C_PF3];
1819 
1820 	CHAR_LOOP_BEGIN
1821 		UBYTE screendata = *antic_memptr++;
1822 		const UWORD *lookup;
1823 		UBYTE chdata;
1824 		if (screendata & 0x80)
1825 			lookup = lookup2 + 0xf;
1826 		else
1827 			lookup = lookup2;
1828 #ifdef PAGED_MEM
1829 		chdata = MEMORY_dGetByte(t_chbase + ((UWORD) (screendata & 0x7f) << 3));
1830 #else
1831 		chdata = chptr[(screendata & 0x7f) << 3];
1832 #endif
1833 		if (IS_ZERO_ULONG(t_pm_scanline_ptr)) {
1834 			if (chdata) {
1835 				WRITE_VIDEO(ptr++, lookup[chdata & 0xc0]);
1836 				WRITE_VIDEO(ptr++, lookup[chdata & 0x30]);
1837 				WRITE_VIDEO(ptr++, lookup[chdata & 0x0c]);
1838 				WRITE_VIDEO(ptr++, lookup[chdata & 0x03]);
1839 			}
1840 			else
1841 				DRAW_BACKGROUND(C_BAK)
1842 		}
1843 		else {
1844 			const UBYTE *c_pm_scanline_ptr = (const UBYTE *) t_pm_scanline_ptr;
1845 			int pm_pixel;
1846 			int colreg;
1847 			int k = 4;
1848 			playfield_lookup[0xc0] = screendata & 0x80 ? L_PF3 : L_PF2;
1849 			do {
1850 				colreg = playfield_lookup[chdata & 0xc0];
1851 				DO_PMG_LORES
1852 				chdata <<= 2;
1853 			} while (--k);
1854 		}
1855 		t_pm_scanline_ptr++;
1856 	CHAR_LOOP_END
1857 	playfield_lookup[0xc0] = L_PF2;
1858 	do_border();
1859 }
1860 
prepare_an_antic_4(int nchars,const UBYTE * antic_memptr,const ULONG * t_pm_scanline_ptr)1861 static void prepare_an_antic_4(int nchars, const UBYTE *antic_memptr, const ULONG *t_pm_scanline_ptr)
1862 {
1863 	UBYTE *an_ptr = (UBYTE *) t_pm_scanline_ptr + (an_scanline - GTIA_pm_scanline);
1864 #ifdef PAGED_MEM
1865 	UWORD t_chbase = ((anticmode == 4 ? dctr : dctr >> 1) ^ chbase_20) & 0xfc07;
1866 #else
1867 	const UBYTE *chptr;
1868 	if (ANTIC_xe_ptr != NULL && chbase_20 < 0x8000 && chbase_20 >= 0x4000)
1869 		chptr = ANTIC_xe_ptr + (((anticmode == 4 ? dctr : dctr >> 1) ^ chbase_20) & 0x3c07);
1870 	else
1871 		chptr = MEMORY_mem + (((anticmode == 4 ? dctr : dctr >> 1) ^ chbase_20) & 0xfc07);
1872 #endif
1873 
1874 	ADD_FONT_CYCLES;
1875 	CHAR_LOOP_BEGIN
1876 		UBYTE screendata = *antic_memptr++;
1877 		UBYTE an;
1878 		UBYTE chdata;
1879 #ifdef PAGED_MEM
1880 		chdata = MEMORY_dGetByte(t_chbase + ((UWORD) (screendata & 0x7f) << 3));
1881 #else
1882 		chdata = chptr[(screendata & 0x7f) << 3];
1883 #endif
1884 		an = mode_e_an_lookup[chdata & 0xc0];
1885 		*an_ptr++ = (an == 2 && screendata & 0x80) ? 3 : an;
1886 		an = mode_e_an_lookup[chdata & 0x30];
1887 		*an_ptr++ = (an == 2 && screendata & 0x80) ? 3 : an;
1888 		an = mode_e_an_lookup[chdata & 0x0c];
1889 		*an_ptr++ = (an == 2 && screendata & 0x80) ? 3 : an;
1890 		an = mode_e_an_lookup[chdata & 0x03];
1891 		*an_ptr++ = (an == 2 && screendata & 0x80) ? 3 : an;
1892 	CHAR_LOOP_END
1893 }
1894 
1895 DEFINE_DRAW_AN(4)
1896 
draw_antic_6(int nchars,const UBYTE * antic_memptr,UWORD * ptr,const ULONG * t_pm_scanline_ptr)1897 static void draw_antic_6(int nchars, const UBYTE *antic_memptr, UWORD *ptr, const ULONG *t_pm_scanline_ptr)
1898 {
1899 #ifdef PAGED_MEM
1900 	UWORD t_chbase = (anticmode == 6 ? dctr & 7 : dctr >> 1) ^ chbase_20;
1901 #else
1902 	const UBYTE *chptr;
1903 	if (ANTIC_xe_ptr != NULL && chbase_20 < 0x8000 && chbase_20 >= 0x4000)
1904 		chptr = ANTIC_xe_ptr + (((anticmode == 6 ? dctr & 7 : dctr >> 1) ^ chbase_20) - 0x4000);
1905 	else
1906 		chptr = MEMORY_mem + ((anticmode == 6 ? dctr & 7 : dctr >> 1) ^ chbase_20);
1907 #endif
1908 
1909 	ADD_FONT_CYCLES;
1910 	CHAR_LOOP_BEGIN
1911 		UBYTE screendata = *antic_memptr++;
1912 		UBYTE chdata;
1913 		UWORD colour;
1914 		int kk = 2;
1915 		colour = COLOUR((playfield_lookup + 0x40)[screendata & 0xc0]);
1916 #ifdef PAGED_MEM
1917 		chdata = MEMORY_dGetByte(t_chbase + ((UWORD) (screendata & 0x3f) << 3));
1918 #else
1919 		chdata = chptr[(screendata & 0x3f) << 3];
1920 #endif
1921 		do {
1922 			if (IS_ZERO_ULONG(t_pm_scanline_ptr)) {
1923 				if (chdata & 0xf0) {
1924 					if (chdata & 0x80) {
1925 						WRITE_VIDEO(ptr++, colour);
1926 					}
1927 					else {
1928 						WRITE_VIDEO(ptr++, ANTIC_cl[C_BAK]);
1929 					}
1930 					if (chdata & 0x40) {
1931 						WRITE_VIDEO(ptr++, colour);
1932 					}
1933 					else {
1934 						WRITE_VIDEO(ptr++, ANTIC_cl[C_BAK]);
1935 					}
1936 					if (chdata & 0x20) {
1937 						WRITE_VIDEO(ptr++, colour);
1938 					}
1939 					else {
1940 						WRITE_VIDEO(ptr++, ANTIC_cl[C_BAK]);
1941 					}
1942 					if (chdata & 0x10) {
1943 						WRITE_VIDEO(ptr++, colour);
1944 					}
1945 					else {
1946 						WRITE_VIDEO(ptr++, ANTIC_cl[C_BAK]);
1947 					}
1948 				}
1949 				else {
1950 					WRITE_VIDEO(ptr++, ANTIC_cl[C_BAK]);
1951 					WRITE_VIDEO(ptr++, ANTIC_cl[C_BAK]);
1952 					WRITE_VIDEO(ptr++, ANTIC_cl[C_BAK]);
1953 					WRITE_VIDEO(ptr++, ANTIC_cl[C_BAK]);
1954 				}
1955 				chdata <<= 4;
1956 			}
1957 			else {
1958 				const UBYTE *c_pm_scanline_ptr = (const UBYTE *) t_pm_scanline_ptr;
1959 				int pm_pixel;
1960 				UBYTE setcol = (playfield_lookup + 0x40)[screendata & 0xc0];
1961 				int colreg;
1962 				int k = 4;
1963 				do {
1964 					colreg = chdata & 0x80 ? setcol : L_BAK;
1965 					DO_PMG_LORES
1966 					chdata <<= 1;
1967 				} while (--k);
1968 
1969 			}
1970 			t_pm_scanline_ptr++;
1971 		} while (--kk);
1972 	CHAR_LOOP_END
1973 	do_border();
1974 }
1975 
prepare_an_antic_6(int nchars,const UBYTE * antic_memptr,const ULONG * t_pm_scanline_ptr)1976 static void prepare_an_antic_6(int nchars, const UBYTE *antic_memptr, const ULONG *t_pm_scanline_ptr)
1977 {
1978 	UBYTE *an_ptr = (UBYTE *) t_pm_scanline_ptr + (an_scanline - GTIA_pm_scanline);
1979 #ifdef PAGED_MEM
1980 	UWORD t_chbase = (anticmode == 6 ? dctr & 7 : dctr >> 1) ^ chbase_20;
1981 #else
1982 	const UBYTE *chptr;
1983 	if (ANTIC_xe_ptr != NULL && chbase_20 < 0x8000 && chbase_20 >= 0x4000)
1984 		chptr = ANTIC_xe_ptr + (((anticmode == 6 ? dctr & 7 : dctr >> 1) ^ chbase_20) - 0x4000);
1985 	else
1986 		chptr = MEMORY_mem + ((anticmode == 6 ? dctr & 7 : dctr >> 1) ^ chbase_20);
1987 #endif
1988 
1989 	ADD_FONT_CYCLES;
1990 	CHAR_LOOP_BEGIN
1991 		UBYTE screendata = *antic_memptr++;
1992 		UBYTE an = screendata >> 6;
1993 		UBYTE chdata;
1994 #ifdef PAGED_MEM
1995 		chdata = MEMORY_dGetByte(t_chbase + ((UWORD) (screendata & 0x3f) << 3));
1996 #else
1997 		chdata = chptr[(screendata & 0x3f) << 3];
1998 #endif
1999 		*an_ptr++ = chdata & 0x80 ? an : 0;
2000 		*an_ptr++ = chdata & 0x40 ? an : 0;
2001 		*an_ptr++ = chdata & 0x20 ? an : 0;
2002 		*an_ptr++ = chdata & 0x10 ? an : 0;
2003 		*an_ptr++ = chdata & 0x08 ? an : 0;
2004 		*an_ptr++ = chdata & 0x04 ? an : 0;
2005 		*an_ptr++ = chdata & 0x02 ? an : 0;
2006 		*an_ptr++ = chdata & 0x01 ? an : 0;
2007 	CHAR_LOOP_END
2008 }
2009 
2010 DEFINE_DRAW_AN(6)
2011 
draw_antic_8(int nchars,const UBYTE * antic_memptr,UWORD * ptr,const ULONG * t_pm_scanline_ptr)2012 static void draw_antic_8(int nchars, const UBYTE *antic_memptr, UWORD *ptr, const ULONG *t_pm_scanline_ptr)
2013 {
2014 	lookup2[0x00] = ANTIC_cl[C_BAK];
2015 	lookup2[0x40] = ANTIC_cl[C_PF0];
2016 	lookup2[0x80] = ANTIC_cl[C_PF1];
2017 	lookup2[0xc0] = ANTIC_cl[C_PF2];
2018 	CHAR_LOOP_BEGIN
2019 		UBYTE screendata = *antic_memptr++;
2020 		int kk = 4;
2021 		do {
2022 			if ((const UBYTE *) t_pm_scanline_ptr >= GTIA_pm_scanline + 4 * (48 - RCHOP))
2023 				break;
2024 			if (IS_ZERO_ULONG(t_pm_scanline_ptr)) {
2025 				UWORD data = lookup2[screendata & 0xc0];
2026 				WRITE_VIDEO(ptr++, data);
2027 				WRITE_VIDEO(ptr++, data);
2028 				WRITE_VIDEO(ptr++, data);
2029 				WRITE_VIDEO(ptr++, data);
2030 			}
2031 			else {
2032 				const UBYTE *c_pm_scanline_ptr = (const UBYTE *) t_pm_scanline_ptr;
2033 				int pm_pixel;
2034 				int colreg = playfield_lookup[screendata & 0xc0];
2035 				int k = 4;
2036 				do {
2037 					DO_PMG_LORES
2038 				} while (--k);
2039 			}
2040 			screendata <<= 2;
2041 			t_pm_scanline_ptr++;
2042 		} while (--kk);
2043 	CHAR_LOOP_END
2044 	do_border();
2045 }
2046 
prepare_an_antic_8(int nchars,const UBYTE * antic_memptr,const ULONG * t_pm_scanline_ptr)2047 static void prepare_an_antic_8(int nchars, const UBYTE *antic_memptr, const ULONG *t_pm_scanline_ptr)
2048 {
2049 	UBYTE *an_ptr = (UBYTE *) t_pm_scanline_ptr + (an_scanline - GTIA_pm_scanline);
2050 	CHAR_LOOP_BEGIN
2051 		UBYTE screendata = *antic_memptr++;
2052 		int kk = 4;
2053 		do {
2054 			UBYTE data = mode_e_an_lookup[screendata & 0xc0];
2055 			*an_ptr++ = data;
2056 			*an_ptr++ = data;
2057 			*an_ptr++ = data;
2058 			*an_ptr++ = data;
2059 			screendata <<= 2;
2060 		} while (--kk);
2061 	CHAR_LOOP_END
2062 }
2063 
2064 DEFINE_DRAW_AN(8)
2065 
draw_antic_9(int nchars,const UBYTE * antic_memptr,UWORD * ptr,const ULONG * t_pm_scanline_ptr)2066 static void draw_antic_9(int nchars, const UBYTE *antic_memptr, UWORD *ptr, const ULONG *t_pm_scanline_ptr)
2067 {
2068 	lookup2[0x00] = ANTIC_cl[C_BAK];
2069 	lookup2[0x80] = lookup2[0x40] = ANTIC_cl[C_PF0];
2070 	CHAR_LOOP_BEGIN
2071 		UBYTE screendata = *antic_memptr++;
2072 		int kk = 4;
2073 		do {
2074 			if ((const UBYTE *) t_pm_scanline_ptr >= GTIA_pm_scanline + 4 * (48 - RCHOP))
2075 				break;
2076 			if (IS_ZERO_ULONG(t_pm_scanline_ptr)) {
2077 				WRITE_VIDEO(ptr++, lookup2[screendata & 0x80]);
2078 				WRITE_VIDEO(ptr++, lookup2[screendata & 0x80]);
2079 				WRITE_VIDEO(ptr++, lookup2[screendata & 0x40]);
2080 				WRITE_VIDEO(ptr++, lookup2[screendata & 0x40]);
2081 				screendata <<= 2;
2082 			}
2083 			else {
2084 				const UBYTE *c_pm_scanline_ptr = (const UBYTE *) t_pm_scanline_ptr;
2085 				int pm_pixel;
2086 				int colreg;
2087 				int k = 4;
2088 				do {
2089 					colreg = (screendata & 0x80) ? L_PF0 : L_BAK;
2090 					DO_PMG_LORES
2091 					if (k & 0x01)
2092 						screendata <<= 1;
2093 				} while (--k);
2094 			}
2095 			t_pm_scanline_ptr++;
2096 		} while (--kk);
2097 	CHAR_LOOP_END
2098 	do_border();
2099 }
2100 
2101 /* ANTIC modes 9, b and c use BAK and PF0 colours only so they're not visible in GTIA modes */
2102 
draw_antic_9_gtia9(int nchars,const UBYTE * antic_memptr,UWORD * ptr,const ULONG * t_pm_scanline_ptr)2103 static void draw_antic_9_gtia9(int nchars, const UBYTE *antic_memptr, UWORD *ptr, const ULONG *t_pm_scanline_ptr)
2104 {
2105 	draw_antic_0();
2106 }
2107 
draw_antic_9_gtia10(int nchars,const UBYTE * antic_memptr,UWORD * ptr,const ULONG * t_pm_scanline_ptr)2108 static void draw_antic_9_gtia10(int nchars, const UBYTE *antic_memptr, UWORD *ptr, const ULONG *t_pm_scanline_ptr)
2109 {
2110 	draw_antic_0_gtia10();
2111 }
2112 
draw_antic_9_gtia11(int nchars,const UBYTE * antic_memptr,UWORD * ptr,const ULONG * t_pm_scanline_ptr)2113 static void draw_antic_9_gtia11(int nchars, const UBYTE *antic_memptr, UWORD *ptr, const ULONG *t_pm_scanline_ptr)
2114 {
2115 	draw_antic_0_gtia11();
2116 }
2117 
draw_antic_a(int nchars,const UBYTE * antic_memptr,UWORD * ptr,const ULONG * t_pm_scanline_ptr)2118 static void draw_antic_a(int nchars, const UBYTE *antic_memptr, UWORD *ptr, const ULONG *t_pm_scanline_ptr)
2119 {
2120 	lookup2[0x00] = ANTIC_cl[C_BAK];
2121 	lookup2[0x40] = lookup2[0x10] = ANTIC_cl[C_PF0];
2122 	lookup2[0x80] = lookup2[0x20] = ANTIC_cl[C_PF1];
2123 	lookup2[0xc0] = lookup2[0x30] = ANTIC_cl[C_PF2];
2124 	CHAR_LOOP_BEGIN
2125 		UBYTE screendata = *antic_memptr++;
2126 		int kk = 2;
2127 		do {
2128 			if (IS_ZERO_ULONG(t_pm_scanline_ptr)) {
2129 				WRITE_VIDEO(ptr++, lookup2[screendata & 0xc0]);
2130 				WRITE_VIDEO(ptr++, lookup2[screendata & 0xc0]);
2131 				WRITE_VIDEO(ptr++, lookup2[screendata & 0x30]);
2132 				WRITE_VIDEO(ptr++, lookup2[screendata & 0x30]);
2133 				screendata <<= 4;
2134 			}
2135 			else {
2136 				const UBYTE *c_pm_scanline_ptr = (const UBYTE *) t_pm_scanline_ptr;
2137 				int pm_pixel;
2138 				int colreg;
2139 				int k = 4;
2140 				do {
2141 					colreg = playfield_lookup[screendata & 0xc0];
2142 					DO_PMG_LORES
2143 					if (k & 0x01)
2144 						screendata <<= 2;
2145 				} while (--k);
2146 			}
2147 			t_pm_scanline_ptr++;
2148 		} while (--kk);
2149 	CHAR_LOOP_END
2150 	do_border();
2151 }
2152 
prepare_an_antic_a(int nchars,const UBYTE * antic_memptr,const ULONG * t_pm_scanline_ptr)2153 static void prepare_an_antic_a(int nchars, const UBYTE *antic_memptr, const ULONG *t_pm_scanline_ptr)
2154 {
2155 	UBYTE *an_ptr = (UBYTE *) t_pm_scanline_ptr + (an_scanline - GTIA_pm_scanline);
2156 	CHAR_LOOP_BEGIN
2157 		UBYTE screendata = *antic_memptr++;
2158 		UBYTE data = mode_e_an_lookup[screendata & 0xc0];
2159 		*an_ptr++ = data;
2160 		*an_ptr++ = data;
2161 		data = mode_e_an_lookup[screendata & 0x30];
2162 		*an_ptr++ = data;
2163 		*an_ptr++ = data;
2164 		data = mode_e_an_lookup[screendata & 0x0c];
2165 		*an_ptr++ = data;
2166 		*an_ptr++ = data;
2167 		data = mode_e_an_lookup[screendata & 0x03];
2168 		*an_ptr++ = data;
2169 		*an_ptr++ = data;
2170 	CHAR_LOOP_END
2171 }
2172 
DEFINE_DRAW_AN(a)2173 DEFINE_DRAW_AN(a)
2174 
2175 static void draw_antic_c(int nchars, const UBYTE *antic_memptr, UWORD *ptr, const ULONG *t_pm_scanline_ptr)
2176 {
2177 	lookup2[0x00] = ANTIC_cl[C_BAK];
2178 	lookup2[0x80] = lookup2[0x40] = lookup2[0x20] = lookup2[0x10] = ANTIC_cl[C_PF0];
2179 	CHAR_LOOP_BEGIN
2180 		UBYTE screendata = *antic_memptr++;
2181 		int kk = 2;
2182 		do {
2183 			if (IS_ZERO_ULONG(t_pm_scanline_ptr)) {
2184 				WRITE_VIDEO(ptr++, lookup2[screendata & 0x80]);
2185 				WRITE_VIDEO(ptr++, lookup2[screendata & 0x40]);
2186 				WRITE_VIDEO(ptr++, lookup2[screendata & 0x20]);
2187 				WRITE_VIDEO(ptr++, lookup2[screendata & 0x10]);
2188 				screendata <<= 4;
2189 			}
2190 			else {
2191 				const UBYTE *c_pm_scanline_ptr = (const UBYTE *) t_pm_scanline_ptr;
2192 				int pm_pixel;
2193 				int colreg;
2194 				int k = 4;
2195 				do {
2196 					colreg = (screendata & 0x80) ? L_PF0 : L_BAK;
2197 					DO_PMG_LORES
2198 					screendata <<= 1;
2199 				} while (--k);
2200 			}
2201 			t_pm_scanline_ptr++;
2202 		} while (--kk);
2203 	CHAR_LOOP_END
2204 	do_border();
2205 }
2206 
draw_antic_e(int nchars,const UBYTE * antic_memptr,UWORD * ptr,const ULONG * t_pm_scanline_ptr)2207 static void draw_antic_e(int nchars, const UBYTE *antic_memptr, UWORD *ptr, const ULONG *t_pm_scanline_ptr)
2208 {
2209 	INIT_BACKGROUND_8
2210 	lookup2[0x00] = ANTIC_cl[C_BAK];
2211 	lookup2[0x40] = lookup2[0x10] = lookup2[0x04] = lookup2[0x01] = ANTIC_cl[C_PF0];
2212 	lookup2[0x80] = lookup2[0x20] = lookup2[0x08] = lookup2[0x02] = ANTIC_cl[C_PF1];
2213 	lookup2[0xc0] = lookup2[0x30] = lookup2[0x0c] = lookup2[0x03] = ANTIC_cl[C_PF2];
2214 
2215 	CHAR_LOOP_BEGIN
2216 		UBYTE screendata = *antic_memptr++;
2217 		if (IS_ZERO_ULONG(t_pm_scanline_ptr)) {
2218 			if (screendata) {
2219 				WRITE_VIDEO(ptr++, lookup2[screendata & 0xc0]);
2220 				WRITE_VIDEO(ptr++, lookup2[screendata & 0x30]);
2221 				WRITE_VIDEO(ptr++, lookup2[screendata & 0x0c]);
2222 				WRITE_VIDEO(ptr++, lookup2[screendata & 0x03]);
2223 			}
2224 			else
2225 				DRAW_BACKGROUND(C_BAK)
2226 		}
2227 		else {
2228 			const UBYTE *c_pm_scanline_ptr = (const UBYTE *) t_pm_scanline_ptr;
2229 			int pm_pixel;
2230 			int colreg;
2231 			int k = 4;
2232 			do {
2233 				colreg = playfield_lookup[screendata & 0xc0];
2234 				DO_PMG_LORES
2235 				screendata <<= 2;
2236 			} while (--k);
2237 
2238 		}
2239 		t_pm_scanline_ptr++;
2240 	CHAR_LOOP_END
2241 	do_border();
2242 }
2243 
prepare_an_antic_e(int nchars,const UBYTE * antic_memptr,const ULONG * t_pm_scanline_ptr)2244 static void prepare_an_antic_e(int nchars, const UBYTE *antic_memptr, const ULONG *t_pm_scanline_ptr)
2245 {
2246 	UBYTE *an_ptr = (UBYTE *) t_pm_scanline_ptr + (an_scanline - GTIA_pm_scanline);
2247 	CHAR_LOOP_BEGIN
2248 		UBYTE screendata = *antic_memptr++;
2249 		*an_ptr++ = mode_e_an_lookup[screendata & 0xc0];
2250 		*an_ptr++ = mode_e_an_lookup[screendata & 0x30];
2251 		*an_ptr++ = mode_e_an_lookup[screendata & 0x0c];
2252 		*an_ptr++ = mode_e_an_lookup[screendata & 0x03];
2253 	CHAR_LOOP_END
2254 }
2255 
draw_antic_e_gtia9(int nchars,const UBYTE * antic_memptr,UWORD * ptr,const ULONG * t_pm_scanline_ptr)2256 static void draw_antic_e_gtia9(int nchars, const UBYTE *antic_memptr, UWORD *ptr, const ULONG *t_pm_scanline_ptr)
2257 {
2258 	ULONG lookup[16];
2259 	if ((unsigned long) ptr & 2) { /* HSCROL & 1 */
2260 		prepare_an_antic_e(nchars, antic_memptr, t_pm_scanline_ptr);
2261 		draw_an_gtia9(t_pm_scanline_ptr);
2262 		return;
2263 	}
2264 	lookup[0] = lookup[1] = lookup[4] = lookup[5] = ANTIC_lookup_gtia9[0];
2265 	lookup[2] = lookup[6] = ANTIC_lookup_gtia9[1];
2266 	lookup[3] = lookup[7] = ANTIC_lookup_gtia9[2];
2267 	lookup[8] = lookup[9] = ANTIC_lookup_gtia9[4];
2268 	lookup[10] = ANTIC_lookup_gtia9[5];
2269 	lookup[11] = ANTIC_lookup_gtia9[6];
2270 	lookup[12] = lookup[13] = ANTIC_lookup_gtia9[8];
2271 	lookup[14] = ANTIC_lookup_gtia9[9];
2272 	lookup[15] = ANTIC_lookup_gtia9[10];
2273 	CHAR_LOOP_BEGIN
2274 		UBYTE screendata = *antic_memptr++;
2275 		WRITE_VIDEO_LONG((ULONG *) ptr, lookup[screendata >> 4]);
2276 		WRITE_VIDEO_LONG((ULONG *) ptr + 1, lookup[screendata & 0xf]);
2277 		if (IS_ZERO_ULONG(t_pm_scanline_ptr))
2278 			ptr += 4;
2279 		else {
2280 			const UBYTE *c_pm_scanline_ptr = (const UBYTE *) t_pm_scanline_ptr;
2281 			int k = 4;
2282 			UBYTE pm_reg;
2283 			do {
2284 				pm_reg = pm_lookup_ptr[*c_pm_scanline_ptr++];
2285 				if (pm_reg) {
2286 					if (pm_reg == L_PF3) {
2287 						UBYTE tmp = k > 2 ? screendata >> 4 : screendata & 0xf;
2288 #ifdef USE_COLOUR_TRANSLATION_TABLE
2289 						WRITE_VIDEO(ptr, colour_translation_table[tmp | GTIA_COLPF3]);
2290 #else
2291 						WRITE_VIDEO(ptr, tmp | ((UWORD)tmp << 8) | ANTIC_cl[C_PF3]);
2292 #endif
2293 					}
2294 					else
2295 					{
2296 						WRITE_VIDEO(ptr, COLOUR(pm_reg));
2297 					}
2298 				}
2299 				ptr++;
2300 			} while (--k);
2301 		}
2302 		t_pm_scanline_ptr++;
2303 	CHAR_LOOP_END
2304 	do_border();
2305 }
2306 
draw_antic_e_gtia10(int nchars,const UBYTE * antic_memptr,UWORD * ptr,const ULONG * t_pm_scanline_ptr)2307 static void draw_antic_e_gtia10 (int nchars, const UBYTE *antic_memptr, UWORD *ptr, const ULONG *t_pm_scanline_ptr)
2308 {
2309 	prepare_an_antic_e(nchars, antic_memptr, t_pm_scanline_ptr);
2310 	draw_an_gtia10(t_pm_scanline_ptr);
2311 }
draw_antic_e_gtia11(int nchars,const UBYTE * antic_memptr,UWORD * ptr,const ULONG * t_pm_scanline_ptr)2312 static void draw_antic_e_gtia11 (int nchars, const UBYTE *antic_memptr, UWORD *ptr, const ULONG *t_pm_scanline_ptr)
2313 {
2314 	prepare_an_antic_e(nchars, antic_memptr, t_pm_scanline_ptr);
2315 	draw_an_gtia11(t_pm_scanline_ptr);
2316 }
2317 
draw_antic_f(int nchars,const UBYTE * antic_memptr,UWORD * ptr,const ULONG * t_pm_scanline_ptr)2318 static void draw_antic_f(int nchars, const UBYTE *antic_memptr, UWORD *ptr, const ULONG *t_pm_scanline_ptr)
2319 {
2320 	INIT_BACKGROUND_6
2321 	INIT_HIRES
2322 
2323 	CHAR_LOOP_BEGIN
2324 		int screendata = *antic_memptr++;
2325 		if (IS_ZERO_ULONG(t_pm_scanline_ptr)) {
2326 			if (screendata) {
2327 				WRITE_VIDEO(ptr++, hires_norm(screendata & 0xc0));
2328 				WRITE_VIDEO(ptr++, hires_norm(screendata & 0x30));
2329 				WRITE_VIDEO(ptr++, hires_norm(screendata & 0x0c));
2330 				WRITE_VIDEO(ptr++, hires_norm((screendata & 0x03) << 2));
2331 			}
2332 			else
2333 				DRAW_BACKGROUND(C_PF2)
2334 		}
2335 		else
2336 			DO_PMG_HIRES(screendata)
2337 		t_pm_scanline_ptr++;
2338 	CHAR_LOOP_END
2339 	do_border();
2340 }
2341 
draw_antic_f_artif(int nchars,const UBYTE * antic_memptr,UWORD * ptr,const ULONG * t_pm_scanline_ptr)2342 static void draw_antic_f_artif(int nchars, const UBYTE *antic_memptr, UWORD *ptr, const ULONG *t_pm_scanline_ptr)
2343 {
2344 	ULONG screendata_tally = *antic_memptr++;
2345 
2346 	setup_art_colours();
2347 	CHAR_LOOP_BEGIN
2348 		int screendata = *antic_memptr++;
2349 		screendata_tally <<= 8;
2350 		screendata_tally |= screendata;
2351 		if (IS_ZERO_ULONG(t_pm_scanline_ptr))
2352 			DRAW_ARTIF
2353 		else {
2354 			screendata = antic_memptr[-2];
2355 			DO_PMG_HIRES(screendata)
2356 		}
2357 		t_pm_scanline_ptr++;
2358 	CHAR_LOOP_END
2359 	do_border();
2360 }
2361 
2362 #ifndef USE_COLOUR_TRANSLATION_TABLE
draw_antic_f_artif_new(int nchars,const UBYTE * antic_memptr,UWORD * ptr,const ULONG * t_pm_scanline_ptr)2363 static void draw_antic_f_artif_new(int nchars, const UBYTE *antic_memptr, UWORD *ptr, const ULONG *t_pm_scanline_ptr)
2364 {
2365 	ULONG pmtally;
2366 	ULONG screendata_tally = *antic_memptr++;
2367 	INIT_ARTIF_NEW
2368 
2369 	setup_art_colours();
2370 	CHAR_LOOP_BEGIN
2371 		int screendata = *antic_memptr++;
2372 		screendata_tally <<= 8;
2373 		screendata_tally |= screendata;
2374 		if (IS_ZERO_ULONG(t_pm_scanline_ptr))
2375 			DRAW_ARTIF_NEW
2376 		else {
2377 			screendata = antic_memptr[-2];
2378 			pmtally = ((screendata_tally & 0x03f000) << 6) |
2379 					  ((screendata_tally & 0x00fc00) << 2) |
2380 					  ((screendata_tally & 0x003f00) >> 2) |
2381 					  ((screendata_tally & 0x000fc0) >> 6);
2382 			DO_PMG_HIRES_NEW(screendata,pmtally)
2383 		}
2384 		t_pm_scanline_ptr++;
2385 	CHAR_LOOP_END
2386 	do_border();
2387 }
2388 #endif
2389 
prepare_an_antic_f(int nchars,const UBYTE * antic_memptr,const ULONG * t_pm_scanline_ptr)2390 static void prepare_an_antic_f(int nchars, const UBYTE *antic_memptr, const ULONG *t_pm_scanline_ptr)
2391 {
2392 	UBYTE *an_ptr = (UBYTE *) t_pm_scanline_ptr + (an_scanline - GTIA_pm_scanline);
2393 	CHAR_LOOP_BEGIN
2394 		UBYTE screendata = *antic_memptr++;
2395 		*an_ptr++ = screendata >> 6;
2396 		*an_ptr++ = (screendata >> 4) & 3;
2397 		*an_ptr++ = (screendata >> 2) & 3;
2398 		*an_ptr++ = screendata & 3;
2399 	CHAR_LOOP_END
2400 }
2401 
draw_antic_f_gtia9(int nchars,const UBYTE * antic_memptr,UWORD * ptr,const ULONG * t_pm_scanline_ptr)2402 static void draw_antic_f_gtia9(int nchars, const UBYTE *antic_memptr, UWORD *ptr, const ULONG *t_pm_scanline_ptr)
2403 {
2404 	if ((unsigned long) ptr & 2) { /* HSCROL & 1 */
2405 		prepare_an_antic_f(nchars, antic_memptr, t_pm_scanline_ptr);
2406 		draw_an_gtia9(t_pm_scanline_ptr);
2407 		return;
2408 	}
2409 	CHAR_LOOP_BEGIN
2410 		UBYTE screendata = *antic_memptr++;
2411 		WRITE_VIDEO_LONG((ULONG *) ptr, ANTIC_lookup_gtia9[screendata >> 4]);
2412 		WRITE_VIDEO_LONG((ULONG *) ptr + 1, ANTIC_lookup_gtia9[screendata & 0xf]);
2413 		if (IS_ZERO_ULONG(t_pm_scanline_ptr))
2414 			ptr += 4;
2415 		else {
2416 			const UBYTE *c_pm_scanline_ptr = (const UBYTE *) t_pm_scanline_ptr;
2417 			int k = 4;
2418 			UBYTE pm_reg;
2419 			do {
2420 				pm_reg = pm_lookup_ptr[*c_pm_scanline_ptr++];
2421 				if (pm_reg) {
2422 					if (pm_reg == L_PF3) {
2423 						UBYTE tmp = k > 2 ? screendata >> 4 : screendata & 0xf;
2424 #ifdef USE_COLOUR_TRANSLATION_TABLE
2425 						WRITE_VIDEO(ptr, colour_translation_table[tmp | GTIA_COLPF3]);
2426 #else
2427 						WRITE_VIDEO(ptr, tmp | ((UWORD)tmp << 8) | ANTIC_cl[C_PF3]);
2428 #endif
2429 					}
2430 					else {
2431 						WRITE_VIDEO(ptr, COLOUR(pm_reg));
2432 					}
2433 				}
2434 				ptr++;
2435 			} while (--k);
2436 		}
2437 		t_pm_scanline_ptr++;
2438 	CHAR_LOOP_END
2439 	do_border();
2440 }
2441 
draw_antic_f_gtia10(int nchars,const UBYTE * antic_memptr,UWORD * ptr,const ULONG * t_pm_scanline_ptr)2442 static void draw_antic_f_gtia10(int nchars, const UBYTE *antic_memptr, UWORD *ptr, const ULONG *t_pm_scanline_ptr)
2443 {
2444 #ifdef WORDS_UNALIGNED_OK
2445 	ULONG lookup_gtia10[16];
2446 #else
2447 	UWORD lookup_gtia10[16];
2448 #endif
2449 	if ((unsigned long) ptr & 2) { /* HSCROL & 1 */
2450 		prepare_an_antic_f(nchars, antic_memptr, t_pm_scanline_ptr);
2451 		draw_an_gtia10(t_pm_scanline_ptr);
2452 		return;
2453 	}
2454 #ifdef WORDS_UNALIGNED_OK
2455 	lookup_gtia10[0] = ANTIC_cl[C_PM0] | (ANTIC_cl[C_PM0] << 16);
2456 	lookup_gtia10[1] = ANTIC_cl[C_PM1] | (ANTIC_cl[C_PM1] << 16);
2457 	lookup_gtia10[2] = ANTIC_cl[C_PM2] | (ANTIC_cl[C_PM2] << 16);
2458 	lookup_gtia10[3] = ANTIC_cl[C_PM3] | (ANTIC_cl[C_PM3] << 16);
2459 	lookup_gtia10[12] = lookup_gtia10[4] = ANTIC_cl[C_PF0] | (ANTIC_cl[C_PF0] << 16);
2460 	lookup_gtia10[13] = lookup_gtia10[5] = ANTIC_cl[C_PF1] | (ANTIC_cl[C_PF1] << 16);
2461 	lookup_gtia10[14] = lookup_gtia10[6] = ANTIC_cl[C_PF2] | (ANTIC_cl[C_PF2] << 16);
2462 	lookup_gtia10[15] = lookup_gtia10[7] = ANTIC_cl[C_PF3] | (ANTIC_cl[C_PF3] << 16);
2463 	lookup_gtia10[8] = lookup_gtia10[9] = lookup_gtia10[10] = lookup_gtia10[11] = ANTIC_lookup_gtia9[0];
2464 #else
2465 	lookup_gtia10[0] = ANTIC_cl[C_PM0];
2466 	lookup_gtia10[1] = ANTIC_cl[C_PM1];
2467 	lookup_gtia10[2] = ANTIC_cl[C_PM2];
2468 	lookup_gtia10[3] = ANTIC_cl[C_PM3];
2469 	lookup_gtia10[12] = lookup_gtia10[4] = ANTIC_cl[C_PF0];
2470 	lookup_gtia10[13] = lookup_gtia10[5] = ANTIC_cl[C_PF1];
2471 	lookup_gtia10[14] = lookup_gtia10[6] = ANTIC_cl[C_PF2];
2472 	lookup_gtia10[15] = lookup_gtia10[7] = ANTIC_cl[C_PF3];
2473 	lookup_gtia10[8] = lookup_gtia10[9] = lookup_gtia10[10] = lookup_gtia10[11] = ANTIC_cl[C_BAK];
2474 #endif
2475 	ptr++;
2476 	t_pm_scanline_ptr = (const ULONG *) (((const UBYTE *) t_pm_scanline_ptr) + 1);
2477 	CHAR_LOOP_BEGIN
2478 		UBYTE screendata = *antic_memptr++;
2479 		if (IS_ZERO_ULONG(t_pm_scanline_ptr)) {
2480 			DO_GTIA_BYTE(ptr, lookup_gtia10, screendata)
2481 			ptr += 4;
2482 		}
2483 		else {
2484 			const UBYTE *c_pm_scanline_ptr = (const UBYTE *) t_pm_scanline_ptr;
2485 			int pm_pixel;
2486 			int colreg;
2487 			int k = 4;
2488 			UBYTE t_screendata = screendata >> 4;
2489 			do {
2490 				colreg = gtia_10_lookup[t_screendata];
2491 				PF_COLLS(colreg) |= pm_pixel = *c_pm_scanline_ptr++; /*playfield colours can generate collisions*/
2492 				pm_pixel |= gtia_10_pm[t_screendata]; /*but player colours don't*/
2493 				WRITE_VIDEO(ptr++, COLOUR(pm_lookup_ptr[pm_pixel] | colreg)); /*although they mix with the real players*/
2494 				if (k == 3)
2495 					t_screendata = screendata & 0x0f;
2496 			} while (--k);
2497 		}
2498 		t_pm_scanline_ptr++;
2499 	CHAR_LOOP_END
2500 	do_border_gtia10();
2501 }
2502 
draw_antic_f_gtia11(int nchars,const UBYTE * antic_memptr,UWORD * ptr,const ULONG * t_pm_scanline_ptr)2503 static void draw_antic_f_gtia11(int nchars, const UBYTE *antic_memptr, UWORD *ptr, const ULONG *t_pm_scanline_ptr)
2504 {
2505 	if ((unsigned long) ptr & 2) { /* HSCROL & 1 */
2506 		prepare_an_antic_f(nchars, antic_memptr, t_pm_scanline_ptr);
2507 		draw_an_gtia11(t_pm_scanline_ptr);
2508 		return;
2509 	}
2510 	CHAR_LOOP_BEGIN
2511 		UBYTE screendata = *antic_memptr++;
2512 		WRITE_VIDEO_LONG((ULONG *) ptr, ANTIC_lookup_gtia11[screendata >> 4]);
2513 		WRITE_VIDEO_LONG((ULONG *) ptr + 1, ANTIC_lookup_gtia11[screendata & 0xf]);
2514 		if (IS_ZERO_ULONG(t_pm_scanline_ptr))
2515 			ptr += 4;
2516 		else {
2517 			const UBYTE *c_pm_scanline_ptr = (const UBYTE *) t_pm_scanline_ptr;
2518 			int k = 4;
2519 			UBYTE pm_reg;
2520 			do {
2521 				pm_reg = pm_lookup_ptr[*c_pm_scanline_ptr++];
2522 				if (pm_reg) {
2523 					if (pm_reg == L_PF3) {
2524 						UBYTE tmp = k > 2 ? screendata & 0xf0 : screendata << 4;
2525 #ifdef USE_COLOUR_TRANSLATION_TABLE
2526 						WRITE_VIDEO(ptr, colour_translation_table[tmp ? tmp | GTIA_COLPF3 : GTIA_COLPF3 & 0xf0]);
2527 #else
2528 						WRITE_VIDEO(ptr, tmp ? tmp | ((UWORD)tmp << 8) | ANTIC_cl[C_PF3] : ANTIC_cl[C_PF3] & 0xf0f0);
2529 #endif
2530 					}
2531 					else
2532 					{
2533 						WRITE_VIDEO(ptr, COLOUR(pm_reg));
2534 					}
2535 				}
2536 				ptr++;
2537 			} while (--k);
2538 		}
2539 		t_pm_scanline_ptr++;
2540 	CHAR_LOOP_END
2541 	do_border_gtia11();
2542 }
2543 
2544 /* GTIA-switch-to-mode-00 bug
2545 If while drawing line in hi-res mode PRIOR is changed from 0x40..0xff to
2546 0x00..0x3f, GTIA doesn't back to hi-res, but starts generating mode similar
2547 to ANTIC's 0xe, but with colours PF0, PF1, PF2, PF3. */
2548 
2549 /* Technical explaination by perrym:
2550  * in gtia.pdf there is a flip-flop at page 40, drawing location C3 with
2551  * what looks like W and A on the gates
2552  * This is set by AN2=0 AN1=1 AN0=1 durning HBLANK
2553  * The middle input to the lower NOR gate is the inverted signal !NRM(?)
2554  * (NRM means NORMAL?) which arrives from the top left of the page.
2555  * This signal is defined on page 38, positions C2/B2
2556  * where there is a NOR gate pointing downwards with 00 written to the
2557  * right of its output.
2558  * !NRM is the condition that PRIOR is not set to b7=0,b6=0.
2559  * When PRIOR is not set to NRM, the flip-flip is always reset,
2560  * which seems necessary for the proper operation of the GTIA modes.
2561  * If PRIOR is reset to NRM then the flip-flop remains reset, and
2562  * since ANTIC data in hi-res modes is sent as PF0-PF3, this data is used
2563  * by GTIA directly.*/
2564 
draw_antic_f_gtia_bug(int nchars,const UBYTE * antic_memptr,UWORD * ptr,const ULONG * t_pm_scanline_ptr)2565 static void draw_antic_f_gtia_bug(int nchars, const UBYTE *antic_memptr, UWORD *ptr, const ULONG *t_pm_scanline_ptr)
2566 {
2567 	lookup2[0x00] = ANTIC_cl[C_PF0];
2568 	lookup2[0x40] = lookup2[0x10] = lookup2[0x04] = lookup2[0x01] = ANTIC_cl[C_PF1];
2569 	lookup2[0x80] = lookup2[0x20] = lookup2[0x08] = lookup2[0x02] = ANTIC_cl[C_PF2];
2570 	lookup2[0xc0] = lookup2[0x30] = lookup2[0x0c] = lookup2[0x03] = ANTIC_cl[C_PF3];
2571 
2572 	CHAR_LOOP_BEGIN
2573 		UBYTE screendata = *antic_memptr++;
2574 		if (IS_ZERO_ULONG(t_pm_scanline_ptr)) {
2575 			WRITE_VIDEO(ptr++, lookup2[screendata & 0xc0]);
2576 			WRITE_VIDEO(ptr++, lookup2[screendata & 0x30]);
2577 			WRITE_VIDEO(ptr++, lookup2[screendata & 0x0c]);
2578 			WRITE_VIDEO(ptr++, lookup2[screendata & 0x03]);
2579 		}
2580 		else {
2581 			const UBYTE *c_pm_scanline_ptr = (const UBYTE *) t_pm_scanline_ptr;
2582 			int pm_pixel;
2583 			int colreg;
2584 			int k = 4;
2585 			do {
2586 				colreg = (playfield_lookup + 0x40)[screendata & 0xc0];
2587 				DO_PMG_LORES
2588 				screendata <<= 2;
2589 			} while (--k);
2590 		}
2591 		t_pm_scanline_ptr++;
2592 	CHAR_LOOP_END
2593 	do_border();
2594 }
2595 
2596 /* pointer to a function that draws a single line of graphics */
2597 typedef void (*draw_antic_function)(int nchars, const UBYTE *antic_memptr, UWORD *ptr, const ULONG *t_pm_scanline_ptr);
2598 
2599 /* tables for all GTIA and ANTIC modes */
2600 static draw_antic_function draw_antic_table[4][16] = {
2601 /* normal */
2602 		{ NULL,			NULL,			draw_antic_2,	draw_antic_2,
2603 		draw_antic_4,	draw_antic_4,	draw_antic_6,	draw_antic_6,
2604 		draw_antic_8,	draw_antic_9,	draw_antic_a,	draw_antic_c,
2605 		draw_antic_c,	draw_antic_e,	draw_antic_e,	draw_antic_f},
2606 /* GTIA 9 */
2607 		{ NULL,			NULL,			draw_antic_2_gtia9,	draw_antic_2_gtia9,
2608 		draw_antic_4_gtia9,	draw_antic_4_gtia9,	draw_antic_6_gtia9,	draw_antic_6_gtia9,
2609 		draw_antic_8_gtia9,	draw_antic_9_gtia9,	draw_antic_a_gtia9,	draw_antic_9_gtia9,
2610 		draw_antic_9_gtia9, draw_antic_e_gtia9,	draw_antic_e_gtia9,	draw_antic_f_gtia9},
2611 /* GTIA 10 */
2612 		{ NULL,			NULL,			draw_antic_2_gtia10,	draw_antic_2_gtia10,
2613 		draw_antic_4_gtia10,	draw_antic_4_gtia10,	draw_antic_6_gtia10,	draw_antic_6_gtia10,
2614 		draw_antic_8_gtia10,	draw_antic_9_gtia10,	draw_antic_a_gtia10,	draw_antic_9_gtia10,
2615 		draw_antic_9_gtia10,	draw_antic_e_gtia10,	draw_antic_e_gtia10,	draw_antic_f_gtia10},
2616 /* GTIA 11 */
2617 		{ NULL,			NULL,			draw_antic_2_gtia11,	draw_antic_2_gtia11,
2618 		draw_antic_4_gtia11,	draw_antic_4_gtia11,	draw_antic_6_gtia11,	draw_antic_6_gtia11,
2619 		draw_antic_8_gtia11,	draw_antic_9_gtia11,	draw_antic_a_gtia11,	draw_antic_9_gtia11,
2620 		draw_antic_9_gtia11,	draw_antic_e_gtia11,	draw_antic_e_gtia11,	draw_antic_f_gtia11}};
2621 
2622 /* pointer to current GTIA/ANTIC mode routine */
2623 static draw_antic_function draw_antic_ptr = draw_antic_8;
2624 #ifdef NEW_CYCLE_EXACT
2625 static draw_antic_function saved_draw_antic_ptr;
2626 #endif
2627 /* pointer to current GTIA mode blank drawing routine */
2628 static void (*draw_antic_0_ptr)(void) = draw_antic_0;
2629 
2630 #ifdef NEW_CYCLE_EXACT
2631 /* wrapper for antic_0, for dmactl bugs */
draw_antic_0_dmactl_bug(int nchars,const UBYTE * antic_memptr,UWORD * ptr,const ULONG * t_pm_scanline_ptr)2632 static void draw_antic_0_dmactl_bug(int nchars, const UBYTE *antic_memptr, UWORD *ptr, const ULONG *t_pm_scanline_ptr)
2633 {
2634 	draw_antic_0_ptr();
2635 }
2636 #endif
2637 
2638 /* Artifacting ------------------------------------------------------------ */
2639 
ANTIC_UpdateArtifacting(void)2640 void ANTIC_UpdateArtifacting(void)
2641 {
2642 #define ART_BROWN 0
2643 #define ART_BLUE 1
2644 #define ART_DARK_BROWN 2
2645 #define ART_DARK_BLUE 3
2646 #define ART_BRIGHT_BROWN 4
2647 #define ART_BRIGHT_BLUE 5
2648 #define ART_RED 6
2649 #define ART_GREEN 7
2650 	static const UBYTE art_colour_table[4][8] = {
2651 		{ 0x88, 0x14, 0x88, 0x14, 0x8f, 0x1f, 0xbb, 0x5f },	/* brownblue */
2652 		{ 0x14, 0x88, 0x14, 0x88, 0x1f, 0x8f, 0x5f, 0xbb },	/* bluebrown */
2653 		{ 0xd6, 0x46, 0xd6, 0x46, 0xdf, 0x4a, 0x4f, 0xac },	/* redgreen */
2654 		{ 0x46, 0xd6, 0x46, 0xd6, 0x4a, 0xdf, 0xac, 0x4f }	/* greenred */
2655 	};
2656 
2657 	int i;
2658 	int j;
2659 	int c;
2660 	const UBYTE *art_colours;
2661 	UBYTE q;
2662 	UBYTE art_white;
2663 
2664 	if (ANTIC_artif_mode == 0) {
2665 		draw_antic_table[0][2] = draw_antic_table[0][3] = draw_antic_2;
2666 		draw_antic_table[0][0xf] = draw_antic_f;
2667 		return;
2668 	}
2669 
2670 #ifndef USE_COLOUR_TRANSLATION_TABLE
2671 	if (ANTIC_artif_new) {
2672 		static UWORD new_art_colour_table[4][2] = {
2673 			{0x4040, 0x8080},
2674 			{0x8080, 0x4040},
2675 			{0x8080, 0xd0d0},
2676 			{0xd0d0, 0x8080}
2677 		};
2678 		draw_antic_table[0][2] = draw_antic_table[0][3] = draw_antic_2_artif_new;
2679 		draw_antic_table[0][0xf] = draw_antic_f_artif_new;
2680 		art_colour1_new = new_art_colour_table[ANTIC_artif_mode - 1][0];
2681 		art_colour2_new = new_art_colour_table[ANTIC_artif_mode - 1][1];
2682 	}
2683 	else
2684 #endif
2685 	{
2686 		draw_antic_table[0][2] = draw_antic_table[0][3] = draw_antic_2_artif;
2687 		draw_antic_table[0][0xf] = draw_antic_f_artif;
2688 	}
2689 
2690 	art_colours = (ANTIC_artif_mode <= 4 ? art_colour_table[ANTIC_artif_mode - 1] : art_colour_table[2]);
2691 
2692 	art_reverse_colpf1_save = art_normal_colpf1_save = ANTIC_cl[C_PF1] & 0x0f0f;
2693 	art_reverse_colpf2_save = art_normal_colpf2_save = ANTIC_cl[C_PF2];
2694 	art_white = (ANTIC_cl[C_PF2] & 0xf0) | (ANTIC_cl[C_PF1] & 0x0f);
2695 
2696 	for (i = 0; i <= 255; i++) {
2697 		art_bkmask_normal[i] = 0;
2698 		art_lummask_normal[i] = 0;
2699 		art_bkmask_reverse[255 - i] = 0;
2700 		art_lummask_reverse[255 - i] = 0;
2701 
2702 		for (j = 0; j <= 3; j++) {
2703 			q = i << j;
2704 			if (!(q & 0x20)) {
2705 				if ((q & 0xf8) == 0x50)
2706 					c = ART_BLUE;				/* 01010 */
2707 				else if ((q & 0xf8) == 0xD8)
2708 					c = ART_DARK_BLUE;			/* 11011 */
2709 				else {							/* xx0xx */
2710 					((UBYTE *) art_lookup_normal)[(i << 2) + j] = GTIA_COLPF2;
2711 					((UBYTE *) art_lookup_reverse)[((255 - i) << 2) + j] = art_white;
2712 					((UBYTE *) art_bkmask_normal)[(i << 2) + j] = 0xff;
2713 					((UBYTE *) art_lummask_reverse)[((255 - i) << 2) + j] = 0x0f;
2714 					((UBYTE *) art_bkmask_reverse)[((255 - i) << 2) + j] = 0xf0;
2715 					continue;
2716 				}
2717 			}
2718 			else if (q & 0x40) {
2719 				if (q & 0x10)
2720 					goto colpf1_pixel;			/* x111x */
2721 				else if (q & 0x80) {
2722 					if (q & 0x08)
2723 						c = ART_BRIGHT_BROWN;	/* 11101 */
2724 					else
2725 						goto colpf1_pixel;		/* 11100 */
2726 				}
2727 				else
2728 					c = ART_GREEN;				/* 0110x */
2729 			}
2730 			else if (q & 0x10) {
2731 				if (q & 0x08) {
2732 					if (q & 0x80)
2733 						c = ART_BRIGHT_BROWN;	/* 00111 */
2734 					else
2735 						goto colpf1_pixel;		/* 10111 */
2736 				}
2737 				else
2738 					c = ART_RED;				/* x0110 */
2739 			}
2740 			else
2741 				c = ART_BROWN;					/* x010x */
2742 
2743 			((UBYTE *) art_lookup_reverse)[((255 - i) << 2) + j] =
2744 			((UBYTE *) art_lookup_normal)[(i << 2) + j] = art_colours[(j & 1) ^ c];
2745 			continue;
2746 
2747 			colpf1_pixel:
2748 			((UBYTE *) art_lookup_normal)[(i << 2) + j] = art_white;
2749 			((UBYTE *) art_lookup_reverse)[((255 - i) << 2) + j] = GTIA_COLPF2;
2750 			((UBYTE *) art_bkmask_reverse)[((255 - i) << 2) + j] = 0xff;
2751 			((UBYTE *) art_lummask_normal)[(i << 2) + j] = 0x0f;
2752 			((UBYTE *) art_bkmask_normal)[(i << 2) + j] = 0xf0;
2753 		}
2754 	}
2755 }
2756 
2757 #endif /* !defined(BASIC) && !defined(CURSES_BASIC) */
2758 
2759 /* Display List ------------------------------------------------------------ */
2760 
ANTIC_GetDLByte(UWORD * paddr)2761 UBYTE ANTIC_GetDLByte(UWORD *paddr)
2762 {
2763 	int addr = *paddr;
2764 	UBYTE result;
2765 	if (ANTIC_xe_ptr != NULL && addr < 0x8000 && addr >= 0x4000)
2766 		result = ANTIC_xe_ptr[addr - 0x4000];
2767 	else
2768 		result = MEMORY_GetByte((UWORD) addr);
2769 	addr++;
2770 	if ((addr & 0x3FF) == 0)
2771 		addr -= 0x400;
2772 	*paddr = (UWORD) addr;
2773 	return result;
2774 }
2775 
ANTIC_GetDLWord(UWORD * paddr)2776 UWORD ANTIC_GetDLWord(UWORD *paddr)
2777 {
2778 	UBYTE lsb = ANTIC_GetDLByte(paddr);
2779 #if !defined(BASIC) && !defined(CURSES_BASIC)
2780 	if (ANTIC_player_flickering && ((GTIA_VDELAY & 0x80) == 0 || ANTIC_ypos & 1))
2781 		GTIA_GRAFP3 = lsb;
2782 #endif
2783 	return (ANTIC_GetDLByte(paddr) << 8) + lsb;
2784 }
2785 
2786 #if !defined(BASIC) && !defined(CURSES_BASIC)
2787 
2788 /* Real ANTIC doesn't fetch beginning bytes in HSC
2789    nor screen+47 in wide playfield. This function does. */
antic_load(void)2790 static void antic_load(void)
2791 {
2792 #ifdef PAGED_MEM
2793 	UBYTE *antic_memptr = antic_memory + ANTIC_margin;
2794 	UWORD new_screenaddr = screenaddr + chars_read[md];
2795 	if ((screenaddr ^ new_screenaddr) & 0xf000) {
2796 		do
2797 			*antic_memptr++ = MEMORY_dGetByte(screenaddr++);
2798 		while (screenaddr & 0xfff);
2799 		screenaddr -= 0x1000;
2800 		new_screenaddr -= 0x1000;
2801 	}
2802 	while (screenaddr < new_screenaddr)
2803 		*antic_memptr++ = MEMORY_dGetByte(screenaddr++);
2804 #else
2805 	UWORD new_screenaddr = screenaddr + chars_read[md];
2806 	if ((screenaddr ^ new_screenaddr) & 0xf000) {
2807 		int bytes = (-screenaddr) & 0xfff;
2808 		if (ANTIC_xe_ptr != NULL && screenaddr < 0x8000 && screenaddr >= 0x4000) {
2809 			memcpy(antic_memory + ANTIC_margin, ANTIC_xe_ptr + (screenaddr - 0x4000), bytes);
2810 			if (new_screenaddr & 0xfff)
2811 				memcpy(antic_memory + ANTIC_margin + bytes, ANTIC_xe_ptr + (screenaddr + bytes - 0x5000), new_screenaddr & 0xfff);
2812 		}
2813 		else if ((screenaddr & 0xf000) == 0xd000) {
2814 			MEMORY_CopyFromMem(screenaddr, antic_memory + ANTIC_margin, bytes);
2815 			if (new_screenaddr & 0xfff)
2816 				MEMORY_CopyFromMem((UWORD) (screenaddr + bytes - 0x1000), antic_memory + ANTIC_margin + bytes, new_screenaddr & 0xfff);
2817 		}
2818 		else {
2819 			MEMORY_dCopyFromMem(screenaddr, antic_memory + ANTIC_margin, bytes);
2820 			if (new_screenaddr & 0xfff)
2821 				MEMORY_dCopyFromMem(screenaddr + bytes - 0x1000, antic_memory + ANTIC_margin + bytes, new_screenaddr & 0xfff);
2822 		}
2823 		screenaddr = new_screenaddr - 0x1000;
2824 	}
2825 	else {
2826 		if (ANTIC_xe_ptr != NULL && screenaddr < 0x8000 && screenaddr >= 0x4000)
2827 			memcpy(antic_memory + ANTIC_margin, ANTIC_xe_ptr + (screenaddr - 0x4000), chars_read[md]);
2828 		else if ((screenaddr & 0xf000) == 0xd000)
2829 			MEMORY_CopyFromMem(screenaddr, antic_memory + ANTIC_margin, chars_read[md]);
2830 		else
2831 			MEMORY_dCopyFromMem(screenaddr, antic_memory + ANTIC_margin, chars_read[md]);
2832 		screenaddr = new_screenaddr;
2833 	}
2834 #endif
2835 }
2836 
2837 #ifdef NEW_CYCLE_EXACT
2838 int ANTIC_cur_screen_pos = ANTIC_NOT_DRAWING;
2839 #endif
2840 
2841 #ifdef USE_CURSES
2842 static int scanlines_to_curses_display = 0;
2843 #endif
2844 
2845 /* This function emulates one frame drawing screen at Screen_atari */
ANTIC_Frame(int draw_display)2846 void ANTIC_Frame(int draw_display)
2847 {
2848 	static const UBYTE mode_type[32] = {
2849 		NORMAL0, NORMAL0, NORMAL0, NORMAL0, NORMAL0, NORMAL0, NORMAL1, NORMAL1,
2850 		NORMAL2, NORMAL2, NORMAL1, NORMAL1, NORMAL1, NORMAL0, NORMAL0, NORMAL0,
2851 		SCROLL0, SCROLL0, SCROLL0, SCROLL0, SCROLL0, SCROLL0, SCROLL1, SCROLL1,
2852 		SCROLL2, SCROLL2, SCROLL1, SCROLL1, SCROLL1, SCROLL0, SCROLL0, SCROLL0
2853 	};
2854 	static const UBYTE normal_lastline[16] =
2855 		{ 0, 0, 7, 9, 7, 15, 7, 15, 7, 3, 3, 1, 0, 1, 0, 0 };
2856 	UBYTE vscrol_flag = FALSE;
2857 	UBYTE no_jvb = TRUE;
2858 #ifndef NEW_CYCLE_EXACT
2859 	UBYTE need_load;
2860 #endif
2861 
2862 #ifdef NEW_CYCLE_EXACT
2863 	int cpu2antic_index;
2864 #endif /* NEW_CYCLE_EXACT */
2865 
2866 	ANTIC_ypos = 0;
2867 	do {
2868 		POKEY_Scanline();		/* check and generate IRQ */
2869 		OVERSCREEN_LINE;
2870 	} while (ANTIC_ypos < 8);
2871 
2872 	scrn_ptr = (UWORD *) Screen_atari;
2873 #ifdef NEW_CYCLE_EXACT
2874 	ANTIC_cur_screen_pos = ANTIC_NOT_DRAWING;
2875 #endif
2876 	need_dl = TRUE;
2877 	do {
2878 		if ((INPUT_mouse_mode == INPUT_MOUSE_PEN || INPUT_mouse_mode == INPUT_MOUSE_GUN) && (ANTIC_ypos >> 1 == ANTIC_PENV_input)) {
2879 			PENH = ANTIC_PENH_input;
2880 			PENV = ANTIC_PENV_input;
2881 			if (GTIA_GRACTL & 4)
2882 				GTIA_TRIG_latch[INPUT_mouse_port] = 0;
2883 		}
2884 
2885 		POKEY_Scanline();		/* check and generate IRQ */
2886 		pmg_dma();
2887 
2888 #ifdef USE_CURSES
2889 		if (--scanlines_to_curses_display == 0)
2890 			curses_display_line(anticmode, antic_memory + ANTIC_margin);
2891 #endif
2892 
2893 		need_load = FALSE;
2894 		if (need_dl) {
2895 			if (ANTIC_DMACTL & 0x20) {
2896 				IR = ANTIC_GetDLByte(&ANTIC_dlist);
2897 				anticmode = IR & 0xf;
2898 				ANTIC_xpos++;
2899 				/* PMG flickering :-) */
2900 				if (ANTIC_missile_flickering)
2901 					GTIA_GRAFM = ANTIC_ypos & 1 ? IR : ((GTIA_GRAFM ^ IR) & hold_missiles_tab[GTIA_VDELAY & 0xf]) ^ IR;
2902 				if (ANTIC_player_flickering) {
2903 					UBYTE hold = ANTIC_ypos & 1 ? 0 : GTIA_VDELAY;
2904 					if ((hold & 0x10) == 0)
2905 						GTIA_GRAFP0 = MEMORY_dGetByte((UWORD) (CPU_regPC - ANTIC_xpos + 8));
2906 					if ((hold & 0x20) == 0)
2907 						GTIA_GRAFP1 = MEMORY_dGetByte((UWORD) (CPU_regPC - ANTIC_xpos + 9));
2908 					if ((hold & 0x40) == 0)
2909 						GTIA_GRAFP2 = MEMORY_dGetByte((UWORD) (CPU_regPC - ANTIC_xpos + 10));
2910 					if ((hold & 0x80) == 0)
2911 						GTIA_GRAFP3 = MEMORY_dGetByte((UWORD) (CPU_regPC - ANTIC_xpos + 11));
2912 				}
2913 			}
2914 			else
2915 				IR &= 0x7f;	/* repeat last instruction, but don't generate DLI */
2916 
2917 			dctr = 0;
2918 			need_dl = FALSE;
2919 			vscrol_off = FALSE;
2920 
2921 			switch (anticmode) {
2922 			case 0x00:
2923 				lastline = (IR >> 4) & 7;
2924 				if (vscrol_flag) {
2925 					lastline = ANTIC_VSCROL;
2926 					vscrol_flag = FALSE;
2927 					vscrol_off = TRUE;
2928 				}
2929 				break;
2930 			case 0x01:
2931 				lastline = 0;
2932 				if (IR & 0x40 && ANTIC_DMACTL & 0x20) {
2933 					ANTIC_dlist = ANTIC_GetDLWord(&ANTIC_dlist);
2934 					ANTIC_xpos += 2;
2935 					no_jvb = FALSE;
2936 				}
2937 				else
2938 					if (vscrol_flag) {
2939 						lastline = ANTIC_VSCROL;
2940 						vscrol_flag = FALSE;
2941 						vscrol_off = TRUE;
2942 					}
2943 				break;
2944 			default:
2945 				lastline = normal_lastline[anticmode];
2946 				if (IR & 0x20) {
2947 					if (!vscrol_flag) {
2948 						CPU_GO(VSCON_C);
2949 						dctr = ANTIC_VSCROL;
2950 						vscrol_flag = TRUE;
2951 					}
2952 				}
2953 				else if (vscrol_flag) {
2954 					lastline = ANTIC_VSCROL;
2955 					vscrol_flag = FALSE;
2956 					vscrol_off = TRUE;
2957 				}
2958 				if (IR & 0x40 && ANTIC_DMACTL & 0x20) {
2959 					screenaddr = ANTIC_GetDLWord(&ANTIC_dlist);
2960 					ANTIC_xpos += 2;
2961 				}
2962 				md = mode_type[IR & 0x1f];
2963 				need_load = TRUE;
2964 				draw_antic_ptr = draw_antic_table[GTIA_PRIOR >> 6][anticmode];
2965 				break;
2966 			}
2967 		}
2968 #ifdef NEW_CYCLE_EXACT
2969 		cpu2antic_index = 0;
2970 		if (anticmode < 2 || (ANTIC_DMACTL & 3) == 0 ||
2971 			(anticmode >= 8 && !need_load)) {
2972 			cpu2antic_index = 0;
2973 		}
2974 		else {
2975 /* TODO: use a cleaner lookup table here */
2976 			if (!(IR & 0x10) && ((ANTIC_DMACTL & 3) == 1))
2977 				cpu2antic_index = 1;
2978 			else if ((!(IR &0x10) && ((ANTIC_DMACTL & 3) == 2)) ||
2979 				((IR & 0x10) && ((ANTIC_DMACTL & 3) == 1))) {
2980 				cpu2antic_index = 2;
2981 			}
2982 			else
2983 				cpu2antic_index = 10;
2984 			if (IR & 0x10) {
2985 				cpu2antic_index += (ANTIC_HSCROL >> 1);
2986 			}
2987 			if (anticmode >=2 && anticmode <=7 && !need_load)
2988 				cpu2antic_index += 17;
2989 			if (anticmode ==6 || anticmode ==7)
2990 				cpu2antic_index += 17 * 2;
2991 		 	else if (anticmode==8 || anticmode == 9)
2992 				cpu2antic_index += 17 * 6;
2993 			else if (anticmode >=0xa && anticmode <=0xc)
2994 				cpu2antic_index += 17 * 5;
2995 			else if (anticmode >=0x0d)
2996 				cpu2antic_index += 17 * 4;
2997 		}
2998 		ANTIC_cpu2antic_ptr = &CYCLE_MAP_cpu2antic[CYCLE_MAP_SIZE * cpu2antic_index];
2999 		ANTIC_antic2cpu_ptr = &CYCLE_MAP_antic2cpu[CYCLE_MAP_SIZE * cpu2antic_index];
3000 #endif /* NEW_CYCLE_EXACT */
3001 
3002 		if ((IR & 0x4f) == 1 && (ANTIC_DMACTL & 0x20)) {
3003 			ANTIC_dlist = ANTIC_GetDLWord(&ANTIC_dlist);
3004 			ANTIC_xpos += 2;
3005 		}
3006 
3007 #ifdef NEW_CYCLE_EXACT
3008 		/* begin drawing here */
3009 		if (draw_display) {
3010 			ANTIC_cur_screen_pos = LBORDER_START;
3011 			ANTIC_xpos = ANTIC_antic2cpu_ptr[ANTIC_xpos]; /* convert antic to cpu(need for WSYNC) */
3012 			if (dctr == lastline) {
3013 				if (no_jvb)
3014 					need_dl = TRUE;
3015 				if (IR & 0x80) {
3016 					CPU_GO(ANTIC_antic2cpu_ptr[ANTIC_NMIST_C]);
3017 					ANTIC_NMIST = 0x9f;
3018 					if (ANTIC_NMIEN & 0x80) {
3019 						CPU_GO(ANTIC_antic2cpu_ptr[ANTIC_NMI_C]);
3020 						CPU_NMI();
3021 					}
3022 				}
3023 			}
3024 		}
3025 		else /* force this to be within an else if NEW_CYCLE_EXACT */
3026 #endif /* NEW_CYCLE_EXACT */
3027 		if (dctr == lastline) {
3028 			if (no_jvb)
3029 				need_dl = TRUE;
3030 			if (IR & 0x80) {
3031 				CPU_GO(ANTIC_NMIST_C);
3032 				ANTIC_NMIST = 0x9f;
3033 				if (ANTIC_NMIEN & 0x80) {
3034 					CPU_GO(ANTIC_NMI_C);
3035 					CPU_NMI();
3036 				}
3037 			}
3038 		}
3039 		if (!draw_display) {
3040 			ANTIC_xpos += ANTIC_DMAR;
3041 			if (anticmode < 2 || (ANTIC_DMACTL & 3) == 0) {
3042 				GOEOL;
3043 				if (no_jvb) {
3044 					dctr++;
3045 					dctr &= 0xf;
3046 				}
3047 				continue;
3048 			}
3049 			if (need_load) {
3050 				ANTIC_xpos += load_cycles[md];
3051 				if (anticmode <= 5)	/* extra cycles in font modes */
3052 					ANTIC_xpos += before_cycles[md] - extra_cycles[md];
3053 			}
3054 			if (anticmode < 8)
3055 				ANTIC_xpos += font_cycles[md];
3056 			GOEOL;
3057 			dctr++;
3058 			dctr &= 0xf;
3059 			continue;
3060 		}
3061 #ifndef NO_YPOS_BREAK_FLICKER
3062 #define YPOS_BREAK_FLICKER do{if (ANTIC_ypos == ANTIC_break_ypos - 1000) {\
3063 				static int toggle;\
3064 				if (toggle == 1) {\
3065 					FILL_VIDEO(scrn_ptr + LBORDER_START, 0x0f0f, (RBORDER_END - LBORDER_START) * 2);\
3066 				}\
3067 				toggle = !toggle;\
3068 			}}while(0)
3069 #else
3070 #define YPOS_BREAK_FLICKER do{}while(0)
3071 #endif /* NO_YPOS_BREAK_FLICKER */
3072 
3073 #ifdef NEW_CYCLE_EXACT
3074 		GTIA_NewPmScanline();
3075 		if (anticmode < 2 || (ANTIC_DMACTL & 3) == 0) {
3076 			GOEOL_CYCLE_EXACT;
3077 			draw_partial_scanline(ANTIC_cur_screen_pos, RBORDER_END);
3078 			UPDATE_DMACTL;
3079 			UPDATE_GTIA_BUG;
3080 			ANTIC_cur_screen_pos = ANTIC_NOT_DRAWING;
3081 			YPOS_BREAK_FLICKER;
3082 			scrn_ptr += Screen_WIDTH / 2;
3083 			if (no_jvb) {
3084 				dctr++;
3085 				dctr &= 0xf;
3086 			}
3087 			continue;
3088 		}
3089 
3090 		GOEOL_CYCLE_EXACT;
3091 		draw_partial_scanline(ANTIC_cur_screen_pos, RBORDER_END);
3092 		UPDATE_DMACTL;
3093 		UPDATE_GTIA_BUG;
3094 		ANTIC_cur_screen_pos = ANTIC_NOT_DRAWING;
3095 
3096 #else /* NEW_CYCLE_EXACT not defined */
3097 		if (need_load && anticmode <= 5 && ANTIC_DMACTL & 3)
3098 			ANTIC_xpos += before_cycles[md];
3099 
3100 		CPU_GO(SCR_C);
3101 		GTIA_NewPmScanline();
3102 
3103 		ANTIC_xpos += ANTIC_DMAR;
3104 
3105 		if (anticmode < 2 || (ANTIC_DMACTL & 3) == 0) {
3106 			draw_antic_0_ptr();
3107 			GOEOL;
3108 			YPOS_BREAK_FLICKER;
3109 			scrn_ptr += Screen_WIDTH / 2;
3110 			if (no_jvb) {
3111 				dctr++;
3112 				dctr &= 0xf;
3113 			}
3114 			continue;
3115 		}
3116 
3117 		if (need_load) {
3118 			antic_load();
3119 #ifdef USE_CURSES
3120 			/* Normally, we would call curses_display_line here,
3121 			   and not use scanlines_to_curses_display at all.
3122 			   That would however cause incorrect color of the "MEMORY"
3123 			   menu item in Self Test - it isn't set properly
3124 			   in the first scanline. We therefore postpone
3125 			   curses_display_line call to the next scanline. */
3126 			scanlines_to_curses_display = 1;
3127 #endif
3128 			ANTIC_xpos += load_cycles[md];
3129 			if (anticmode <= 5)	/* extra cycles in font modes */
3130 				ANTIC_xpos -= extra_cycles[md];
3131 		}
3132 
3133 		draw_antic_ptr(chars_displayed[md],
3134 			antic_memory + ANTIC_margin + ch_offset[md],
3135 			scrn_ptr + x_min[md],
3136 			(ULONG *) &GTIA_pm_scanline[x_min[md]]);
3137 
3138 		GOEOL;
3139 #endif /* NEW_CYCLE_EXACT */
3140 		YPOS_BREAK_FLICKER;
3141 		scrn_ptr += Screen_WIDTH / 2;
3142 		dctr++;
3143 		dctr &= 0xf;
3144 	} while (ANTIC_ypos < (Screen_HEIGHT + 8));
3145 
3146 #ifndef NO_SIMPLE_PAL_BLENDING
3147 	/* Simple PAL blending, using only the base 256 color palette. */
3148 	if (ANTIC_pal_blending)
3149 	{
3150 		int ypos = ANTIC_ypos - 1;
3151 		/* Start at the last screen line (248). */
3152 		ULONG *ptr = (ULONG *) (scrn_ptr - 4 * RCHOP);
3153 		do {
3154 			int k = 2 * (48 - LCHOP - RCHOP);
3155 			do {
3156 				/* For each grayscale pixel (colors $00..$0f) blend it with
3157 				   chrominance of a pixel from the previous line. */
3158 				ULONG pix = READ_VIDEO_LONG(--ptr);
3159 				ULONG mask = 0xf0f0f0f0;
3160 				/* Take advantage of the fact that chrominance can change only
3161 				   every two pixels. This way we may test only two pixels in a
3162 				   quadruplet instead of four. */
3163 				if (pix & 0x0000f0f0)
3164 					/* Two LSBs are non-grayscale */
3165 					mask &= 0xf0f00000;
3166 				if (pix & 0xf0f00000)
3167 					/* Two MSBs are non-grayscale */
3168 					mask &= 0x0000f0f0;
3169 
3170 				WRITE_VIDEO_LONG(ptr, (READ_VIDEO_LONG(ptr - Screen_WIDTH / 4) & mask) | pix);
3171 			} while (--k);
3172 			ptr -= 2 * (LCHOP + RCHOP); /* Move one line up */
3173 		} while (--ypos > 8); /* Stop after line 9 */
3174 	}
3175 #endif /* NO_SIMPLE_PAL_BLENDING */
3176 
3177 /* TODO: cycle-exact overscreen lines */
3178 	POKEY_Scanline();		/* check and generate IRQ */
3179 	CPU_GO(ANTIC_NMIST_C);
3180 	ANTIC_NMIST = 0x5f;				/* Set VBLANK */
3181 	if (ANTIC_NMIEN & 0x40) {
3182 		CPU_GO(ANTIC_NMI_C);
3183 		CPU_NMI();
3184 	}
3185 	ANTIC_xpos += ANTIC_DMAR;
3186 	GOEOL;
3187 
3188 	do {
3189 		POKEY_Scanline();		/* check and generate IRQ */
3190 		OVERSCREEN_LINE;
3191 	} while (ANTIC_ypos < Atari800_tv_mode);
3192 	ANTIC_ypos = 0; /* just for monitor.c */
3193 }
3194 
3195 #ifdef NEW_CYCLE_EXACT
3196 
3197 /* update the scanline from the last changed position to the current
3198 position, when a change was made to a display register during drawing */
ANTIC_UpdateScanline(void)3199 void ANTIC_UpdateScanline(void)
3200 {
3201 	int actual_xpos = ANTIC_cpu2antic_ptr[ANTIC_xpos];
3202 	int newpos = actual_xpos * 2 - 37;
3203 	draw_partial_scanline(ANTIC_cur_screen_pos, newpos);
3204 	ANTIC_cur_screen_pos = newpos;
3205 }
3206 
3207 /* prior needs a different adjustment and could generate small glitches
3208 between mode changes */
3209 /* TODO: support glitches between mode changes (tiny areas that are neither
3210 the new mode nor the old mode, which occur between mode changes */
ANTIC_UpdateScanlinePrior(UBYTE byte)3211 void ANTIC_UpdateScanlinePrior(UBYTE byte)
3212 {
3213 	int actual_xpos = ANTIC_cpu2antic_ptr[ANTIC_xpos];
3214 	int prior_mode_adj = 2;
3215 	int newpos;
3216 	newpos = actual_xpos * 2 - 37 + prior_mode_adj;
3217 	draw_partial_scanline(ANTIC_cur_screen_pos, newpos);
3218 	ANTIC_cur_screen_pos = newpos;
3219 }
3220 
3221 /* chbase needs a different adjustment */
update_scanline_chbase(void)3222 void update_scanline_chbase(void)
3223 {
3224 	int actual_xpos = ANTIC_cpu2antic_ptr[ANTIC_xpos];
3225 	int hscrol_adj = (IR & 0x10) ? ANTIC_HSCROL : 0;
3226 	int hscrollsb_adj = (hscrol_adj & 1);
3227 	int newpos;
3228 	int fontfetch_adj;
3229 	/* antic fetches character font data every 2 or 4 cycles */
3230 	/* we want to delay the change until the next fetch */
3231 	/* empirically determined: */
3232 	if (anticmode >= 2 && anticmode <= 5) {
3233 		fontfetch_adj = (((hscrol_adj >>1) - actual_xpos + 0) & 1) * 2 + 9;
3234 	}
3235 	else if (anticmode == 6 || anticmode == 7) {
3236 		fontfetch_adj = (((hscrol_adj >> 1) - actual_xpos + 2) & 3) * 2 + 9;
3237 	}
3238 	else {
3239 		fontfetch_adj = 0;
3240 	}
3241 	newpos = actual_xpos * 2 - 37 + hscrollsb_adj + fontfetch_adj;
3242 	draw_partial_scanline(ANTIC_cur_screen_pos, newpos);
3243 	ANTIC_cur_screen_pos = newpos;
3244 }
3245 
3246 /* chactl invert needs a different adjustment */
update_scanline_invert(void)3247 void update_scanline_invert(void)
3248 {
3249 	int actual_xpos = ANTIC_cpu2antic_ptr[ANTIC_xpos];
3250 	int hscrol_adj = (IR & 0x10) ? ANTIC_HSCROL : 0;
3251 	int hscrollsb_adj = (hscrol_adj & 1);
3252 	int newpos;
3253 
3254 	/* empirically determined: adjustment of 4 */
3255 	newpos = actual_xpos * 2 - 37 + hscrollsb_adj + 4;
3256 	draw_partial_scanline(ANTIC_cur_screen_pos, newpos);
3257 	ANTIC_cur_screen_pos = newpos;
3258 }
3259 
3260 /* chactl blank needs a different adjustment */
update_scanline_blank(void)3261 void update_scanline_blank(void)
3262 {
3263 	int actual_xpos = ANTIC_cpu2antic_ptr[ANTIC_xpos];
3264 	int hscrol_adj = (IR & 0x10) ? ANTIC_HSCROL : 0;
3265 	int hscrollsb_adj = (hscrol_adj & 1);
3266 	int newpos;
3267 
3268 	/* empirically determined: adjustment of 7 */
3269 	newpos = actual_xpos * 2 - 37 + hscrollsb_adj + 7;
3270 	draw_partial_scanline(ANTIC_cur_screen_pos, newpos);
3271 	ANTIC_cur_screen_pos = newpos;
3272 }
3273 
set_dmactl_bug(void)3274 static void set_dmactl_bug(void){
3275 	need_load = FALSE;
3276 	saved_draw_antic_ptr = draw_antic_ptr;
3277 	draw_antic_ptr_changed = 1;
3278 	if (anticmode == 2 || anticmode == 3 || anticmode == 0xf) {
3279 		draw_antic_ptr = draw_antic_2_dmactl_bug;
3280 		dmactl_bug_chdata = (anticmode == 0xf) ? 0 : antic_memory[ANTIC_margin + chars_read[md] - 1];
3281 	}
3282 	else {
3283 		draw_antic_ptr = draw_antic_0_dmactl_bug;
3284 	}
3285 }
3286 
3287 /* draw a partial scanline between point l and point r */
3288 /* l is the left hand word, r is the point one past the right-most word to draw */
draw_partial_scanline(int l,int r)3289 void draw_partial_scanline(int l, int r)
3290 {
3291 	/* lborder_chars: save left border chars,we restore it after */
3292 	/*                it is the number of 8pixel 'chars' in the left border */
3293 	int lborder_chars = left_border_chars;
3294 
3295 	/* rborder_start: save right border start, we restore it after */
3296 	/*                it is the start of the right border, in words */
3297 	int rborder_start = right_border_start;
3298 
3299 	/* lborder_start: start of the left border, in words */
3300 	int lborder_start = LCHOP * 4;
3301 	/* end of the left border, in words */
3302 	int lborder_end = LCHOP * 4 + left_border_chars * 4;
3303 	/* end of the right border, in words */
3304 	int rborder_end = (48 - RCHOP) * 4;
3305 	/* flag: if true, don't show playfield. used if the partial scanline */
3306 	/*    does not include the playfield */
3307 	int dont_display_playfield = 0;
3308 	/* offset of the left most drawable 8 pixel pf block */
3309 	/* int l_pfchar = (lborder_end - x_min[md]) / 4; */
3310 	int l_pfchar = 0;
3311 	/* offset of the right most drawable 8 pixel pf plock, *plus one* */
3312 	int r_pfchar = 0;
3313 	/* buffer to save 0,1,2 or 3 words of the left hand portion of an 8pixel */
3314 	/* 'char' which is going to be erased by the left hand side of the */
3315 	/* left most 8pixel 'char' in the partial scanline and must be saved */
3316 	/* and restored later */
3317 	UWORD sv_buf[4];
3318 	/* buffer to save 0 or 1 (modes 6,7,a,b,c) ,or , (0,1,2 or 3) (modes 8,9) */
3319 	/* 8pixel 'chars' of playfield which is going to be erased by the left */
3320 	/* hand most 8pixel 'char's of the 2(modes 67abc) or 4(modes 89) 8pixel */
3321 	/* 'char'-sized blocks that these modes must draw. */
3322 	UWORD sv_buf2[4 * 4]; /* for modes 6,7,8,9,a,b,c */
3323 	/* start,size of the above buffers */
3324 	int sv_bufstart = 0;
3325 	int sv_bufsize = 0;
3326 	int sv_bufstart2 = 0;
3327 	int sv_bufsize2 = 0;
3328 	/* number of 8,16,32pixel chars to draw in the playfield */
3329 	int nchars = 0;
3330 	/* adjustment to ch_index , it is the number of 8,16,32pixel chars */
3331 	/* that we do not draw on the left hand side that would usually be drawn */
3332 	/* for this mode */
3333 	int ch_adj = 0;
3334 	/* adjustment to x_min to skip over the left side */
3335 	int x_min_adj = 0;
3336 	/* it's the offset of the left most drawable 8pixel pfblock which is */
3337 	/* rounded *down* to the nearest factor of (2:mode 67abc,4:mode 89) */
3338 	/* if it is divided by (2:mode 67abc,4:mode 89) it will give the */
3339 	/* offset of the left most drawable (16,32)pixel 'char' */
3340 	int l_pfactual = 0;
3341 	/* it is the offset of the right most drawable 8pixel pf block which is */
3342 	/* rounded *up* to the nearest factor of (2,4),  *plus one* */
3343 	/* so that r_pfactual-l_pfactual / (2,4) = number of 16,32 pixel 'chars' */
3344 	/* to be drawn */
3345 	int r_pfactual = 0;
3346 	/* it is the offset of the 8pixel block aligned with pf which overlaps */
3347 	/* the left border. We need this for modes 6-c, because in these modes */
3348 	/* the code will save 8pixel blocks to the left of l_pfchar and */
3349 	/* >= l_pfactual, which will result in portions of the left border */
3350 	/* being saved on some occasions which should not be, unless we */
3351 	/* use this variable to alter the number of chars saved */
3352 	/* int l_borderpfchar=0; */
3353 
3354 	r_pfchar = chars_displayed[md];
3355 	if (md == NORMAL1 || md == SCROLL1) { /* modes 6,7,a,b,c */
3356 		r_pfchar *= 2;
3357 	}
3358 	else if (md == NORMAL2 || md == SCROLL2) { /* modes 8,9 */
3359 		r_pfchar *= 4;
3360 	}
3361 	if (anticmode < 2 || (ANTIC_DMACTL & 3) == 0) {
3362 		lborder_end = rborder_end;
3363 		dont_display_playfield = 1;
3364 	}
3365 	if (l > rborder_end)
3366 		l = rborder_end;
3367 	if (r > rborder_end)
3368 		r = rborder_end;
3369 	if (l < lborder_start)
3370 		l = lborder_start;
3371 	if (r < lborder_start)
3372 		r = lborder_start;
3373 	if (l >= r)
3374 		return;
3375 	if (l < lborder_end) {
3376 		/* left point is within left border */
3377 		sv_bufstart = (l & (~3)); /* high order bits give buffer start */
3378 		sv_bufsize = l - sv_bufstart;
3379 		left_border_start = sv_bufstart;
3380 		left_border_chars = lborder_chars - (sv_bufstart - lborder_start) / 4;
3381 		if (l > x_min[md]) {
3382 			/* special case for modes 56789abc */
3383 			/* position buffer within the reference frame */
3384 			/* of the playfield if that */
3385 			/* results in more pixels being saved in the buffer */
3386 			/* needed because for modes 5789abc the overlapping part */
3387 			/* can be more than 1 8pixel char and we only save the left */
3388 			/* hand most 8pixel chars in the code in the later section */
3389 			/* further down, so there is a possibility that the 8pixels */
3390 			/* which are saved within the reference frame of the border */
3391 			/* are not enough to ensure that everything gets saved */
3392 			l_pfchar = (l - x_min[md]) / 4;
3393 			if (((l - x_min[md]) & 3) > sv_bufsize) {
3394 				sv_bufsize = ((l - x_min[md]) & 3);
3395 				sv_bufstart = l - sv_bufsize;
3396 			}
3397 		}
3398 	}
3399 	else if (l >= rborder_start) {
3400 		sv_bufstart = (l & (~3)); /* high order bits give buffer start */
3401 		sv_bufsize = l - sv_bufstart;
3402 		right_border_start = sv_bufstart;
3403 		dont_display_playfield = 1; /* don't display the playfield */
3404 	}
3405 	else { /*within screen */
3406 		sv_bufsize = ((l - x_min[md]) & 3); /* low bits have buf size */
3407 		sv_bufstart = l - sv_bufsize; /* difference gives start */
3408 		l_pfchar = (sv_bufstart - x_min[md]) / 4;
3409 		left_border_chars = 0; /* don't display left border */
3410 	}
3411 	memcpy(sv_buf, scrn_ptr + sv_bufstart, sv_bufsize * sizeof(UWORD)); /* save part of screen */
3412 
3413 	if (r <= lborder_end) {
3414 		/* right_end_char = (r + 3) / 4; */
3415 		left_border_chars = (r + 3) / 4 - sv_bufstart / 4;
3416 		/* everything must be within the left border */
3417 		dont_display_playfield = 1; /* don't display the playfield */
3418 	}
3419 	else { /* right point is past start of playfield */
3420 		/* now load ANTIC data: needed for ANTIC glitches */
3421 		if (need_load) {
3422 			antic_load();
3423 #ifdef USE_CURSES
3424 			/* Normally, we would call curses_display_line here,
3425 			   and not use scanlines_to_curses_display at all.
3426 			   That would however cause incorrect color of the "MEMORY"
3427 			   menu item in Self Test - it isn't set properly
3428 			   in the first scanline. We therefore postpone
3429 			   curses_display_line call to the next scanline. */
3430 			scanlines_to_curses_display = 1;
3431 #endif
3432 			need_load = FALSE;
3433 		}
3434 
3435 		if (r > rborder_start) {
3436 			right_border_end = ((r + 3) & (~3)); /* round up to nearest 8pixel */
3437 		}
3438 		else {
3439 			r_pfchar = (r - x_min[md] + 3) / 4; /* round up to nearest 8pixel */
3440 		}
3441 	}
3442 	if (dont_display_playfield) {
3443 		nchars = 0;
3444 		x_min_adj = 0;
3445 		ch_adj = 0;
3446 	}
3447 	else if (md == NORMAL1 || md == SCROLL1) { /* modes 6,7,a,b,c */
3448 		l_pfactual = (l_pfchar & (~1)); /* round down to nearest 16pixel */
3449 		sv_bufsize2 = (l_pfchar - l_pfactual) * 4;
3450 		sv_bufstart2 = x_min[md] + l_pfactual * 4;
3451 		r_pfactual = ((r_pfchar + 1) & (~1)); /* round up to nearest 16pixel */
3452 		nchars = (r_pfactual - l_pfactual) / 2;
3453 		x_min_adj = l_pfactual * 4;
3454 		ch_adj = l_pfactual / 2;
3455 	}
3456 	else if (md == NORMAL2 || md == SCROLL2) { /* modes 8,9 */
3457 		l_pfactual = (l_pfchar & (~3));
3458 		sv_bufsize2 = (l_pfchar - l_pfactual) * 4;
3459 		sv_bufstart2 = x_min[md] + l_pfactual * 4;
3460 		r_pfactual = ((r_pfchar + 3) & (~3));
3461 		nchars = (r_pfactual - l_pfactual) / 4;
3462 		x_min_adj = l_pfactual * 4;
3463 		ch_adj = l_pfactual / 4;
3464 	}
3465 	else {
3466 		nchars = r_pfchar - l_pfchar;
3467 		x_min_adj = l_pfchar * 4;
3468 		ch_adj = l_pfchar;
3469 	}
3470 	memcpy(sv_buf2, scrn_ptr + sv_bufstart2, sv_bufsize2 * sizeof(UWORD)); /* save part of screen */
3471 
3472 	if (dont_display_playfield) {
3473 /* the idea here is to use draw_antic_0_ptr() to draw just the border only, since */
3474 /* we can't set nchars=0.  draw_antic_0_ptr will work if left_border_start and */
3475 /* right_border_end are set correctly */
3476 		if (anticmode < 2 || (ANTIC_DMACTL & 3) == 0 || r <= lborder_end) {
3477 			right_border_end = left_border_start + left_border_chars * 4;
3478 		}
3479 		else if (l >= rborder_start) {
3480 			left_border_start = right_border_start;
3481 		}
3482 		draw_antic_0_ptr();
3483 	}
3484 	else {
3485 		draw_antic_ptr(nchars, /* chars_displayed[md], */
3486 			antic_memory + ANTIC_margin + ch_offset[md] + ch_adj,
3487 			scrn_ptr + x_min[md] + x_min_adj,
3488 			(ULONG *) &GTIA_pm_scanline[x_min[md] + x_min_adj]);
3489 	}
3490 	memcpy(scrn_ptr + sv_bufstart2, sv_buf2, sv_bufsize2 * sizeof(UWORD)); /* restore screen */
3491 	memcpy(scrn_ptr + sv_bufstart, sv_buf, sv_bufsize * sizeof(UWORD)); /* restore screen */
3492 
3493 	/* restore border global variables */
3494 	left_border_chars=lborder_chars;
3495 	right_border_start=rborder_start;
3496 	left_border_start = LCHOP * 4;
3497 	right_border_end = (48-RCHOP)  *4;
3498 }
3499 #endif /* NEW_CYCLE_EXACT */
3500 
3501 #endif /* !defined(BASIC) && !defined(CURSES_BASIC) */
3502 
3503 /* ANTIC registers --------------------------------------------------------- */
3504 
ANTIC_GetByte(UWORD addr,int no_side_effects)3505 UBYTE ANTIC_GetByte(UWORD addr, int no_side_effects)
3506 {
3507 	switch (addr & 0xf) {
3508 	case ANTIC_OFFSET_VCOUNT:
3509 		if (ANTIC_XPOS < ANTIC_LINE_C)
3510 			return ANTIC_ypos >> 1;
3511 		if (ANTIC_ypos + 1 < Atari800_tv_mode)
3512 			return (ANTIC_ypos + 1) >> 1;
3513 		return 0;
3514 	case ANTIC_OFFSET_PENH:
3515 		return PENH;
3516 	case ANTIC_OFFSET_PENV:
3517 		return PENV;
3518 	case ANTIC_OFFSET_NMIST:
3519 		return ANTIC_NMIST;
3520 	default:
3521 		return 0xff;
3522 	}
3523 }
3524 
3525 #if !defined(BASIC) && !defined(CURSES_BASIC)
3526 
3527 /* GTIA calls it on write to PRIOR */
ANTIC_SetPrior(UBYTE byte)3528 void ANTIC_SetPrior(UBYTE byte)
3529 {
3530 	if ((byte ^ GTIA_PRIOR) & 0x0f) {
3531 #ifdef USE_COLOUR_TRANSLATION_TABLE
3532 		UBYTE col = 0;
3533 		UBYTE col2 = 0;
3534 		UBYTE hi;
3535 		UBYTE hi2;
3536 		if ((byte & 3) == 0) {
3537 			col = GTIA_COLPF0;
3538 			col2 = GTIA_COLPF1;
3539 		}
3540 		if ((byte & 0xc) == 0) {
3541 			ANTIC_cl[C_PF0 | C_PM0] = colour_translation_table[col | GTIA_COLPM0];
3542 			ANTIC_cl[C_PF0 | C_PM1] = colour_translation_table[col | GTIA_COLPM1];
3543 			ANTIC_cl[C_PF0 | C_PM01] = colour_translation_table[col | GTIA_COLPM0 | GTIA_COLPM1];
3544 			ANTIC_cl[C_PF1 | C_PM0] = colour_translation_table[col2 | GTIA_COLPM0];
3545 			ANTIC_cl[C_PF1 | C_PM1] = colour_translation_table[col2 | GTIA_COLPM1];
3546 			ANTIC_cl[C_PF1 | C_PM01] = colour_translation_table[col2 | GTIA_COLPM0 | GTIA_COLPM1];
3547 		}
3548 		else {
3549 			ANTIC_cl[C_PF0 | C_PM01] = ANTIC_cl[C_PF0 | C_PM1] = ANTIC_cl[C_PF0 | C_PM0] = colour_translation_table[col];
3550 			ANTIC_cl[C_PF1 | C_PM01] = ANTIC_cl[C_PF1 | C_PM1] = ANTIC_cl[C_PF1 | C_PM0] = colour_translation_table[col2];
3551 		}
3552 		if (byte & 4) {
3553 			ANTIC_cl[C_PF2 | C_PM01] = ANTIC_cl[C_PF2 | C_PM1] = ANTIC_cl[C_PF2 | C_PM0] = ANTIC_cl[C_PF2];
3554 			ANTIC_cl[C_PF3 | C_PM01] = ANTIC_cl[C_PF3 | C_PM1] = ANTIC_cl[C_PF3 | C_PM0] = ANTIC_cl[C_PF3];
3555 			ANTIC_cl[C_HI2 | C_PM01] = ANTIC_cl[C_HI2 | C_PM1] = ANTIC_cl[C_HI2 | C_PM0] = ANTIC_cl[C_HI2];
3556 		}
3557 		else {
3558 			ANTIC_cl[C_PF3 | C_PM0] = ANTIC_cl[C_PF2 | C_PM0] = ANTIC_cl[C_PM0];
3559 			ANTIC_cl[C_PF3 | C_PM1] = ANTIC_cl[C_PF2 | C_PM1] = ANTIC_cl[C_PM1];
3560 			ANTIC_cl[C_PF3 | C_PM01] = ANTIC_cl[C_PF2 | C_PM01] = ANTIC_cl[C_PM01];
3561 			ANTIC_cl[C_HI2 | C_PM0] = colour_translation_table[(GTIA_COLPM0 & 0xf0) | (GTIA_COLPF1 & 0xf)];
3562 			ANTIC_cl[C_HI2 | C_PM1] = colour_translation_table[(GTIA_COLPM1 & 0xf0) | (GTIA_COLPF1 & 0xf)];
3563 			ANTIC_cl[C_HI2 | C_PM01] = colour_translation_table[((GTIA_COLPM0 | GTIA_COLPM1) & 0xf0) | (GTIA_COLPF1 & 0xf)];
3564 		}
3565 		col = col2 = 0;
3566 		hi = hi2 = GTIA_COLPF1 & 0xf;
3567 		ANTIC_cl[C_BLACK - C_PF2 + C_HI2] = colour_translation_table[hi];
3568 		if ((byte & 9) == 0) {
3569 			col = GTIA_COLPF2;
3570 			col2 = GTIA_COLPF3;
3571 			hi |= col & 0xf0;
3572 			hi2 |= col2 & 0xf0;
3573 		}
3574 		if ((byte & 6) == 0) {
3575 			ANTIC_cl[C_PF2 | C_PM2] = colour_translation_table[col | GTIA_COLPM2];
3576 			ANTIC_cl[C_PF2 | C_PM3] = colour_translation_table[col | GTIA_COLPM3];
3577 			ANTIC_cl[C_PF2 | C_PM23] = colour_translation_table[col | GTIA_COLPM2 | GTIA_COLPM3];
3578 			ANTIC_cl[C_PF3 | C_PM2] = colour_translation_table[col2 | GTIA_COLPM2];
3579 			ANTIC_cl[C_PF3 | C_PM3] = colour_translation_table[col2 | GTIA_COLPM3];
3580 			ANTIC_cl[C_PF3 | C_PM23] = colour_translation_table[col2 | GTIA_COLPM2 | GTIA_COLPM3];
3581 			ANTIC_cl[C_HI2 | C_PM2] = colour_translation_table[hi | (GTIA_COLPM2 & 0xf0)];
3582 			ANTIC_cl[C_HI2 | C_PM3] = colour_translation_table[hi | (GTIA_COLPM3 & 0xf0)];
3583 			ANTIC_cl[C_HI2 | C_PM23] = colour_translation_table[hi | ((GTIA_COLPM2 | GTIA_COLPM3) & 0xf0)];
3584 			ANTIC_cl[C_HI2 | C_PM25] = colour_translation_table[hi2 | (GTIA_COLPM2 & 0xf0)];
3585 			ANTIC_cl[C_HI2 | C_PM35] = colour_translation_table[hi2 | (GTIA_COLPM3 & 0xf0)];
3586 			ANTIC_cl[C_HI2 | C_PM235] = colour_translation_table[hi2 | ((GTIA_COLPM2 | GTIA_COLPM3) & 0xf0)];
3587 		}
3588 		else {
3589 			ANTIC_cl[C_PF2 | C_PM23] = ANTIC_cl[C_PF2 | C_PM3] = ANTIC_cl[C_PF2 | C_PM2] = colour_translation_table[col];
3590 			ANTIC_cl[C_PF3 | C_PM23] = ANTIC_cl[C_PF3 | C_PM3] = ANTIC_cl[C_PF3 | C_PM2] = colour_translation_table[col2];
3591 			ANTIC_cl[C_HI2 | C_PM23] = ANTIC_cl[C_HI2 | C_PM3] = ANTIC_cl[C_HI2 | C_PM2] = colour_translation_table[hi];
3592 		}
3593 #else /* USE_COLOUR_TRANSLATION_TABLE */
3594 		UWORD cword = 0;
3595 		UWORD cword2 = 0;
3596 		if ((byte & 3) == 0) {
3597 			cword = ANTIC_cl[C_PF0];
3598 			cword2 = ANTIC_cl[C_PF1];
3599 		}
3600 		if ((byte & 0xc) == 0) {
3601 			ANTIC_cl[C_PF0 | C_PM0] = cword | ANTIC_cl[C_PM0];
3602 			ANTIC_cl[C_PF0 | C_PM1] = cword | ANTIC_cl[C_PM1];
3603 			ANTIC_cl[C_PF0 | C_PM01] = cword | ANTIC_cl[C_PM01];
3604 			ANTIC_cl[C_PF1 | C_PM0] = cword2 | ANTIC_cl[C_PM0];
3605 			ANTIC_cl[C_PF1 | C_PM1] = cword2 | ANTIC_cl[C_PM1];
3606 			ANTIC_cl[C_PF1 | C_PM01] = cword2 | ANTIC_cl[C_PM01];
3607 		}
3608 		else {
3609 			ANTIC_cl[C_PF0 | C_PM01] = ANTIC_cl[C_PF0 | C_PM1] = ANTIC_cl[C_PF0 | C_PM0] = cword;
3610 			ANTIC_cl[C_PF1 | C_PM01] = ANTIC_cl[C_PF1 | C_PM1] = ANTIC_cl[C_PF1 | C_PM0] = cword2;
3611 		}
3612 		if (byte & 4) {
3613 			ANTIC_cl[C_PF2 | C_PM01] = ANTIC_cl[C_PF2 | C_PM1] = ANTIC_cl[C_PF2 | C_PM0] = ANTIC_cl[C_PF2];
3614 			ANTIC_cl[C_PF3 | C_PM01] = ANTIC_cl[C_PF3 | C_PM1] = ANTIC_cl[C_PF3 | C_PM0] = ANTIC_cl[C_PF3];
3615 		}
3616 		else {
3617 			ANTIC_cl[C_PF3 | C_PM0] = ANTIC_cl[C_PF2 | C_PM0] = ANTIC_cl[C_PM0];
3618 			ANTIC_cl[C_PF3 | C_PM1] = ANTIC_cl[C_PF2 | C_PM1] = ANTIC_cl[C_PM1];
3619 			ANTIC_cl[C_PF3 | C_PM01] = ANTIC_cl[C_PF2 | C_PM01] = ANTIC_cl[C_PM01];
3620 		}
3621 		cword = cword2 = 0;
3622 		if ((byte & 9) == 0) {
3623 			cword = ANTIC_cl[C_PF2];
3624 			cword2 = ANTIC_cl[C_PF3];
3625 		}
3626 		if ((byte & 6) == 0) {
3627 			ANTIC_cl[C_PF2 | C_PM2] = cword | ANTIC_cl[C_PM2];
3628 			ANTIC_cl[C_PF2 | C_PM3] = cword | ANTIC_cl[C_PM3];
3629 			ANTIC_cl[C_PF2 | C_PM23] = cword | ANTIC_cl[C_PM23];
3630 			ANTIC_cl[C_PF3 | C_PM2] = cword2 | ANTIC_cl[C_PM2];
3631 			ANTIC_cl[C_PF3 | C_PM3] = cword2 | ANTIC_cl[C_PM3];
3632 			ANTIC_cl[C_PF3 | C_PM23] = cword2 | ANTIC_cl[C_PM23];
3633 		}
3634 		else {
3635 			ANTIC_cl[C_PF2 | C_PM23] = ANTIC_cl[C_PF2 | C_PM3] = ANTIC_cl[C_PF2 | C_PM2] = cword;
3636 			ANTIC_cl[C_PF3 | C_PM23] = ANTIC_cl[C_PF3 | C_PM3] = ANTIC_cl[C_PF3 | C_PM2] = cword2;
3637 		}
3638 #endif /* USE_COLOUR_TRANSLATION_TABLE */
3639 		if (byte & 1) {
3640 			ANTIC_cl[C_PF1 | C_PM2] = ANTIC_cl[C_PF0 | C_PM2] = ANTIC_cl[C_PM2];
3641 			ANTIC_cl[C_PF1 | C_PM3] = ANTIC_cl[C_PF0 | C_PM3] = ANTIC_cl[C_PM3];
3642 			ANTIC_cl[C_PF1 | C_PM23] = ANTIC_cl[C_PF0 | C_PM23] = ANTIC_cl[C_PM23];
3643 		}
3644 		else {
3645 			ANTIC_cl[C_PF0 | C_PM23] = ANTIC_cl[C_PF0 | C_PM3] = ANTIC_cl[C_PF0 | C_PM2] = ANTIC_cl[C_PF0];
3646 			ANTIC_cl[C_PF1 | C_PM23] = ANTIC_cl[C_PF1 | C_PM3] = ANTIC_cl[C_PF1 | C_PM2] = ANTIC_cl[C_PF1];
3647 		}
3648 		if ((byte & 0xf) == 0xc) {
3649 			ANTIC_cl[C_PF0 | C_PM0123] = ANTIC_cl[C_PF0 | C_PM123] = ANTIC_cl[C_PF0 | C_PM023] = ANTIC_cl[C_PF0];
3650 			ANTIC_cl[C_PF1 | C_PM0123] = ANTIC_cl[C_PF1 | C_PM123] = ANTIC_cl[C_PF1 | C_PM023] = ANTIC_cl[C_PF1];
3651 		}
3652 		else
3653 			ANTIC_cl[C_PF0 | C_PM0123] = ANTIC_cl[C_PF0 | C_PM123] = ANTIC_cl[C_PF0 | C_PM023] =
3654 			ANTIC_cl[C_PF1 | C_PM0123] = ANTIC_cl[C_PF1 | C_PM123] = ANTIC_cl[C_PF1 | C_PM023] = GTIA_COLOUR_BLACK;
3655 		if (byte & 0xf) {
3656 			ANTIC_cl[C_PF0 | C_PM25] = ANTIC_cl[C_PF0];
3657 			ANTIC_cl[C_PF1 | C_PM25] = ANTIC_cl[C_PF1];
3658 			ANTIC_cl[C_PF3 | C_PM25] = ANTIC_cl[C_PF2 | C_PM25] = ANTIC_cl[C_PM25] = GTIA_COLOUR_BLACK;
3659 		}
3660 		else {
3661 			ANTIC_cl[C_PF0 | C_PM235] = ANTIC_cl[C_PF0 | C_PM35] = ANTIC_cl[C_PF0 | C_PM25] =
3662 			ANTIC_cl[C_PF1 | C_PM235] = ANTIC_cl[C_PF1 | C_PM35] = ANTIC_cl[C_PF1 | C_PM25] = ANTIC_cl[C_PF3];
3663 			ANTIC_cl[C_PF3 | C_PM25] = ANTIC_cl[C_PF2 | C_PM25] = ANTIC_cl[C_PM25] = ANTIC_cl[C_PF3 | C_PM2];
3664 			ANTIC_cl[C_PF3 | C_PM35] = ANTIC_cl[C_PF2 | C_PM35] = ANTIC_cl[C_PM35] = ANTIC_cl[C_PF3 | C_PM3];
3665 			ANTIC_cl[C_PF3 | C_PM235] = ANTIC_cl[C_PF2 | C_PM235] = ANTIC_cl[C_PM235] = ANTIC_cl[C_PF3 | C_PM23];
3666 		}
3667 	}
3668 	pm_lookup_ptr = pm_lookup_table[prior_to_pm_lookup[byte & 0x3f]];
3669 	draw_antic_0_ptr = byte < 0x80 ? draw_antic_0 : byte < 0xc0 ? draw_antic_0_gtia10 : draw_antic_0_gtia11;
3670 	if (byte < 0x40 && (GTIA_PRIOR >= 0x40 || gtia_bug_active) && (anticmode == 2 || anticmode == 3 || anticmode == 0xf) && ANTIC_XPOS >= ((ANTIC_DMACTL & 3) == 3 ? 16 : 18)) {
3671 		/* A GTIA Mode was active, and no longer is.  An ANTIC hi-res mode is being used. GTIA is no longer set in hi-res mode */
3672 		if (anticmode == 2 || anticmode == 3) draw_antic_ptr = draw_antic_2_gtia_bug;
3673 		else if (anticmode == 0xf) draw_antic_ptr = draw_antic_f_gtia_bug;
3674 		gtia_bug_active = TRUE;
3675 	}
3676 	else
3677 		draw_antic_ptr = draw_antic_table[byte >> 6][anticmode];
3678 }
3679 
3680 #endif /* !defined(BASIC) && !defined(CURSES_BASIC) */
3681 
ANTIC_PutByte(UWORD addr,UBYTE byte)3682 void ANTIC_PutByte(UWORD addr, UBYTE byte)
3683 {
3684 	switch (addr & 0xf) {
3685 	case ANTIC_OFFSET_DLISTL:
3686 		ANTIC_dlist = (ANTIC_dlist & 0xff00) | byte;
3687 		break;
3688 	case ANTIC_OFFSET_DLISTH:
3689 		ANTIC_dlist = (ANTIC_dlist & 0x00ff) | (byte << 8);
3690 		break;
3691 	case ANTIC_OFFSET_DMACTL:
3692 /* TODO: make this truly cycle-exact, update cpu2antic and antic2cpu,
3693 add support for wider->narrow glitches including the interesting mode 6
3694 glitch */
3695 #ifdef NEW_CYCLE_EXACT
3696 		dmactl_changed=0;
3697 		/* has DMACTL width changed?  */
3698 		if ((byte & 3) != (ANTIC_DMACTL & 3) ){
3699 			/* DMACTL width changed from 0 */
3700 			if ((ANTIC_DMACTL & 3) == 0) {
3701 				int glitch_cycle = (3 + 32) - 8*(byte & 3);
3702 				int x = ANTIC_XPOS;
3703 				if((IR & 0x10) && ((byte & 3) != 3)){
3704 					/*adjust for narrow or std HSCROL*/
3705 				       	glitch_cycle -= 8;
3706 				}
3707 				/*ANTIC doesn't fetch and display data if the*/
3708 				/*DMACTL width changes from zero after this */
3709 				/*cycle.  Instead, it displays a blank scan */
3710 				/*line for modes other than 23F and for 23F */
3711 				/*it displays a glitched line after the change*/
3712 				if(x >= glitch_cycle){
3713 					if(ANTIC_DRAWING_SCREEN){
3714 						ANTIC_UpdateScanline();
3715 					        set_dmactl_bug();
3716 					}
3717 				}
3718 				else {
3719 					if (ANTIC_DRAWING_SCREEN) {
3720 						ANTIC_UpdateScanline();
3721 					}
3722 				}
3723 			}
3724 			/* DMACTL width changed to 0 */
3725 			else if ((byte & 3)==0)  {
3726 				/* TODO: this is not 100% correct */
3727 				if (ANTIC_DRAWING_SCREEN) {
3728 					int actual_xpos = ANTIC_cpu2antic_ptr[ANTIC_xpos];
3729 					int antic_limit = ANTIC_cpu2antic_ptr[ANTIC_xpos_limit];
3730 					ANTIC_UpdateScanline();
3731 					/*fix for a minor glitch in fasteddie*/
3732 					/*don't steal cycles after DMACTL off*/
3733 					ANTIC_cpu2antic_ptr = &CYCLE_MAP_cpu2antic[0];
3734 					ANTIC_antic2cpu_ptr = &CYCLE_MAP_antic2cpu[0];
3735 					ANTIC_xpos = ANTIC_antic2cpu_ptr[actual_xpos];
3736 					ANTIC_xpos_limit = ANTIC_antic2cpu_ptr[antic_limit];
3737 				}
3738 			/* DMACTL width has changed and not to 0 and not from 0 */
3739 			}
3740 			else {
3741 				/* DMACTL width has increased and no HSCROL */
3742 				if (((byte & 3) > (ANTIC_DMACTL & 3)) && !(IR & 0x10)) {
3743 					int x; /* the change cycle */
3744 					int left_glitch_cycle = 0;
3745 					int right_glitch_cycle = 0;
3746 					x = ANTIC_XPOS;
3747 					if (((ANTIC_DMACTL & 3) == 2) && ((byte & 3) == 3)) { /* Normal->Wide */
3748 						left_glitch_cycle = 11;
3749 						right_glitch_cycle = 18;
3750 					}
3751 					else if (((ANTIC_DMACTL & 3) == 1) && ((byte & 3) == 3)) { /* Narrow->Wide */
3752 						left_glitch_cycle = 11;
3753 						right_glitch_cycle = 26;
3754 					}
3755 					else if (((ANTIC_DMACTL & 3) == 1) && ((byte & 3) == 2)) { /* Narrow->Normal */
3756 						left_glitch_cycle = 19;
3757 						right_glitch_cycle = 27;
3758 					}
3759 					/* change occurs during drawing of line */
3760 					/* delay change till next line */
3761 					if (x > right_glitch_cycle) {
3762 						dmactl_changed = 1;
3763 						delayed_DMACTL = byte;
3764 						break;
3765 					/* change occurs during 'glitch' region */
3766 					}
3767 					else if (x >= left_glitch_cycle && x <= right_glitch_cycle && anticmode > 1) {
3768 						set_dmactl_bug();
3769 					}
3770 				}
3771 				else {
3772 					/* DMACTL width has decreased or HSCROL */
3773 					/* TODO: this is not 100% correct */
3774 					if (ANTIC_DRAWING_SCREEN) {
3775 						ANTIC_UpdateScanline();
3776 					}
3777 				}
3778 			}
3779 		}
3780 #endif /* NEW_CYCLE_EXACT */
3781 		ANTIC_DMACTL = byte;
3782 #if defined(BASIC) || defined(CURSES_BASIC)
3783 		break;
3784 #else
3785 		switch (byte & 0x03) {
3786 		case 0x00:
3787 			/* no antic_load when screen off */
3788 			/* chars_read[NORMAL0] = 0;
3789 			chars_read[NORMAL1] = 0;
3790 			chars_read[NORMAL2] = 0;
3791 			chars_read[SCROLL0] = 0;
3792 			chars_read[SCROLL1] = 0;
3793 			chars_read[SCROLL2] = 0; */
3794 			/* no draw_antic_* when screen off */
3795 			/* chars_displayed[NORMAL0] = 0;
3796 			chars_displayed[NORMAL1] = 0;
3797 			chars_displayed[NORMAL2] = 0;
3798 			chars_displayed[SCROLL0] = 0;
3799 			chars_displayed[SCROLL1] = 0;
3800 			chars_displayed[SCROLL2] = 0;
3801 			x_min[NORMAL0] = 0;
3802 			x_min[NORMAL1] = 0;
3803 			x_min[NORMAL2] = 0;
3804 			x_min[SCROLL0] = 0;
3805 			x_min[SCROLL1] = 0;
3806 			x_min[SCROLL2] = 0;
3807 			ch_offset[NORMAL0] = 0;
3808 			ch_offset[NORMAL1] = 0;
3809 			ch_offset[NORMAL2] = 0;
3810 			ch_offset[SCROLL0] = 0;
3811 			ch_offset[SCROLL1] = 0;
3812 			ch_offset[SCROLL2] = 0; */
3813 			/* no borders when screen off, only background */
3814 			/* left_border_chars = 48 - LCHOP - RCHOP;
3815 			right_border_start = 0; */
3816 			break;
3817 		case 0x01:
3818 			chars_read[NORMAL0] = 32;
3819 			chars_read[NORMAL1] = 16;
3820 			chars_read[NORMAL2] = 8;
3821 			chars_read[SCROLL0] = 40;
3822 			chars_read[SCROLL1] = 20;
3823 			chars_read[SCROLL2] = 10;
3824 			chars_displayed[NORMAL0] = 32;
3825 			chars_displayed[NORMAL1] = 16;
3826 			chars_displayed[NORMAL2] = 8;
3827 			x_min[NORMAL0] = 32;
3828 			x_min[NORMAL1] = 32;
3829 			x_min[NORMAL2] = 32;
3830 			ch_offset[NORMAL0] = 0;
3831 			ch_offset[NORMAL1] = 0;
3832 			ch_offset[NORMAL2] = 0;
3833 			font_cycles[NORMAL0] = load_cycles[NORMAL0] = 32;
3834 			font_cycles[NORMAL1] = load_cycles[NORMAL1] = 16;
3835 			load_cycles[NORMAL2] = 8;
3836 			before_cycles[NORMAL0] = BEFORE_CYCLES;
3837 			before_cycles[SCROLL0] = BEFORE_CYCLES + 8;
3838 			extra_cycles[NORMAL0] = 7 + BEFORE_CYCLES;
3839 			extra_cycles[SCROLL0] = 8 + BEFORE_CYCLES + 8;
3840 			left_border_chars = 8 - LCHOP;
3841 			right_border_start = (Screen_WIDTH - 64) / 2;
3842 			break;
3843 		case 0x02:
3844 			chars_read[NORMAL0] = 40;
3845 			chars_read[NORMAL1] = 20;
3846 			chars_read[NORMAL2] = 10;
3847 			chars_read[SCROLL0] = 48;
3848 			chars_read[SCROLL1] = 24;
3849 			chars_read[SCROLL2] = 12;
3850 			chars_displayed[NORMAL0] = 40;
3851 			chars_displayed[NORMAL1] = 20;
3852 			chars_displayed[NORMAL2] = 10;
3853 			x_min[NORMAL0] = 16;
3854 			x_min[NORMAL1] = 16;
3855 			x_min[NORMAL2] = 16;
3856 			ch_offset[NORMAL0] = 0;
3857 			ch_offset[NORMAL1] = 0;
3858 			ch_offset[NORMAL2] = 0;
3859 			font_cycles[NORMAL0] = load_cycles[NORMAL0] = 40;
3860 			font_cycles[NORMAL1] = load_cycles[NORMAL1] = 20;
3861 			load_cycles[NORMAL2] = 10;
3862 			before_cycles[NORMAL0] = BEFORE_CYCLES + 8;
3863 			before_cycles[SCROLL0] = BEFORE_CYCLES + 16;
3864 			extra_cycles[NORMAL0] = 8 + BEFORE_CYCLES + 8;
3865 			extra_cycles[SCROLL0] = 7 + BEFORE_CYCLES + 16;
3866 			left_border_chars = 4 - LCHOP;
3867 			right_border_start = (Screen_WIDTH - 32) / 2;
3868 			break;
3869 		case 0x03:
3870 			chars_read[NORMAL0] = 48;
3871 			chars_read[NORMAL1] = 24;
3872 			chars_read[NORMAL2] = 12;
3873 			chars_read[SCROLL0] = 48;
3874 			chars_read[SCROLL1] = 24;
3875 			chars_read[SCROLL2] = 12;
3876 			chars_displayed[NORMAL0] = 42;
3877 			chars_displayed[NORMAL1] = 22;
3878 			chars_displayed[NORMAL2] = 12;
3879 			x_min[NORMAL0] = 12;
3880 			x_min[NORMAL1] = 8;
3881 			x_min[NORMAL2] = 0;
3882 			ch_offset[NORMAL0] = 3;
3883 			ch_offset[NORMAL1] = 1;
3884 			ch_offset[NORMAL2] = 0;
3885 			font_cycles[NORMAL0] = load_cycles[NORMAL0] = 47;
3886 			font_cycles[NORMAL1] = load_cycles[NORMAL1] = 24;
3887 			load_cycles[NORMAL2] = 12;
3888 			before_cycles[NORMAL0] = BEFORE_CYCLES + 16;
3889 			before_cycles[SCROLL0] = BEFORE_CYCLES + 16;
3890 			extra_cycles[NORMAL0] = 7 + BEFORE_CYCLES + 16;
3891 			extra_cycles[SCROLL0] = 7 + BEFORE_CYCLES + 16;
3892 			left_border_chars = 3 - LCHOP;
3893 			right_border_start = (Screen_WIDTH - 8) / 2;
3894 			break;
3895 		}
3896 
3897 		ANTIC_missile_dma_enabled = (byte & 0x0c);	/* no player dma without missile */
3898 		ANTIC_player_dma_enabled = (byte & 0x08);
3899 		singleline = (byte & 0x10);
3900 		ANTIC_player_flickering = ((ANTIC_player_dma_enabled | ANTIC_player_gra_enabled) == 0x02);
3901 		ANTIC_missile_flickering = ((ANTIC_missile_dma_enabled | ANTIC_missile_gra_enabled) == 0x01);
3902 
3903 		byte = ANTIC_HSCROL;	/* update horizontal scroll data */
3904 /* ******* FALLTHROUGH ******* */
3905 	case ANTIC_OFFSET_HSCROL:
3906 /* TODO: make this truely cycle exact, and update cpu2antic and antic2cpu */
3907 #ifdef NEW_CYCLE_EXACT
3908 		if (ANTIC_DRAWING_SCREEN) {
3909 			ANTIC_UpdateScanline();
3910 		}
3911 #endif
3912 		ANTIC_HSCROL = byte &= 0x0f;
3913 		if (ANTIC_DMACTL & 3) {
3914 			chars_displayed[SCROLL0] = chars_displayed[NORMAL0];
3915 			ch_offset[SCROLL0] = 4 - (byte >> 2);
3916 			x_min[SCROLL0] = x_min[NORMAL0];
3917 			if (byte & 3) {
3918 				x_min[SCROLL0] += (byte & 3) - 4;
3919 				chars_displayed[SCROLL0]++;
3920 				ch_offset[SCROLL0]--;
3921 			}
3922 			chars_displayed[SCROLL2] = chars_displayed[NORMAL2];
3923 			if ((ANTIC_DMACTL & 3) == 3) {	/* wide playfield */
3924 				ch_offset[SCROLL0]--;
3925 				if (byte == 4 || byte == 12)
3926 					chars_displayed[SCROLL1] = 21;
3927 				else
3928 					chars_displayed[SCROLL1] = 22;
3929 				if (byte <= 4) {
3930 					x_min[SCROLL1] = byte + 8;
3931 					ch_offset[SCROLL1] = 1;
3932 				}
3933 				else if (byte <= 12) {
3934 					x_min[SCROLL1] = byte;
3935 					ch_offset[SCROLL1] = 0;
3936 				}
3937 				else {
3938 					x_min[SCROLL1] = byte - 8;
3939 					ch_offset[SCROLL1] = -1;
3940 				}
3941 				/* technically, the part below is wrong */
3942 				/* scrolling in mode 8,9 with HSCROL=13,14,15 */
3943 				/* will set x_min=13,14,15 > 4*LCHOP = 12 */
3944 				/* so that nothing is drawn on the far left side */
3945 				/* of the screen.  We could fix this, but only */
3946 				/* by setting x_min to be negative. */
3947 				x_min[SCROLL2] = byte;
3948 				ch_offset[SCROLL2] = 0;
3949 			}
3950 			else {
3951 				chars_displayed[SCROLL1] = chars_displayed[NORMAL1];
3952 				ch_offset[SCROLL1] = 2 - (byte >> 3);
3953 				x_min[SCROLL1] = x_min[NORMAL0];
3954 				if (byte) {
3955 					if (byte & 7) {
3956 						x_min[SCROLL1] += (byte & 7) - 8;
3957 						chars_displayed[SCROLL1]++;
3958 						ch_offset[SCROLL1]--;
3959 					}
3960 					x_min[SCROLL2] = x_min[NORMAL2] + byte - 16;
3961 					chars_displayed[SCROLL2]++;
3962 					ch_offset[SCROLL2] = 0;
3963 				}
3964 				else {
3965 					x_min[SCROLL2] = x_min[NORMAL2];
3966 					ch_offset[SCROLL2] = 1;
3967 				}
3968 			}
3969 
3970 			if (ANTIC_DMACTL & 2) {		/* normal & wide playfield */
3971 				load_cycles[SCROLL0] = 47 - (byte >> 2);
3972 				font_cycles[SCROLL0] = (47 * 4 + 1 - byte) >> 2;
3973 				load_cycles[SCROLL1] = (24 * 8 + 3 - byte) >> 3;
3974 				font_cycles[SCROLL1] = (24 * 8 + 1 - byte) >> 3;
3975 				load_cycles[SCROLL2] = byte < 0xc ? 12 : 11;
3976 			}
3977 			else {					/* narrow playfield */
3978 				font_cycles[SCROLL0] = load_cycles[SCROLL0] = 40;
3979 				font_cycles[SCROLL1] = load_cycles[SCROLL1] = 20;
3980 				load_cycles[SCROLL2] = 16;
3981 			}
3982 		}
3983 		break;
3984 	case ANTIC_OFFSET_VSCROL:
3985 		ANTIC_VSCROL = byte & 0x0f;
3986 		if (vscrol_off) {
3987 			lastline = ANTIC_VSCROL;
3988 			if (ANTIC_XPOS < VSCOF_C)
3989 				need_dl = dctr == lastline;
3990 		}
3991 		break;
3992 	case ANTIC_OFFSET_PMBASE:
3993 		ANTIC_PMBASE = byte;
3994 		pmbase_d = (byte & 0xfc) << 8;
3995 		pmbase_s = pmbase_d & 0xf8ff;
3996 		break;
3997 	case ANTIC_OFFSET_CHACTL:
3998 #ifdef NEW_CYCLE_EXACT
3999 		if (ANTIC_DRAWING_SCREEN) {
4000 			update_scanline_invert();
4001 		}
4002 #endif
4003 		invert_mask = byte & 2 ? 0x80 : 0;
4004 #ifdef NEW_CYCLE_EXACT
4005 		if (ANTIC_DRAWING_SCREEN) {
4006 			update_scanline_blank();
4007 		}
4008 #endif
4009 		blank_mask = byte & 1 ? 0xe0 : 0x60;
4010 		if ((ANTIC_CHACTL ^ byte) & 4) {
4011 #ifdef NEW_CYCLE_EXACT
4012 			if (ANTIC_DRAWING_SCREEN) {
4013 				/* timing for flip is the same as chbase */
4014 				update_scanline_chbase();
4015 			}
4016 #endif
4017 			chbase_20 ^= 7;
4018 		}
4019 		ANTIC_CHACTL = byte;
4020 		break;
4021 	case ANTIC_OFFSET_CHBASE:
4022 #ifdef NEW_CYCLE_EXACT
4023 		if (ANTIC_DRAWING_SCREEN) {
4024 			update_scanline_chbase();
4025 		}
4026 #endif
4027 		ANTIC_CHBASE = byte;
4028 		chbase_20 = (byte & 0xfe) << 8;
4029 		if (ANTIC_CHACTL & 4)
4030 			chbase_20 ^= 7;
4031 		break;
4032 #endif /* defined(BASIC) || defined(CURSES_BASIC) */
4033 	case ANTIC_OFFSET_WSYNC:
4034 #ifdef NEW_CYCLE_EXACT
4035 		if (ANTIC_DRAWING_SCREEN) {
4036 			if (ANTIC_xpos <= ANTIC_antic2cpu_ptr[ANTIC_WSYNC_C] && ANTIC_xpos_limit >= ANTIC_antic2cpu_ptr[ANTIC_WSYNC_C])
4037 				if (ANTIC_cpu2antic_ptr[ANTIC_xpos + 1] == ANTIC_cpu2antic_ptr[ANTIC_xpos] + 1) {
4038 					/* antic does not steal the current cycle */
4039 /* note that if ANTIC_WSYNC_C is a stolen cycle, then ANTIC_antic2cpu_ptr[ANTIC_WSYNC_C+1]-1 corresponds
4040 to the last cpu cycle < ANTIC_WSYNC_C.  Then the cpu will see this cycle if WSYNC
4041 is not delayed, since it really occurred one cycle after the STA WSYNC.  But if
4042 WSYNC is "delayed" then ANTIC_xpos is the next cpu cycle after ANTIC_WSYNC_C (which was stolen
4043 ), so it is one greater than the above value.  EG if ANTIC_WSYNC_C=10 and is stolen
4044 (and let us say cycle 9,11 are also stolen, and 8,12 are not), then in the first
4045 case we have ANTIC_cpu2antic_ptr[ANTIC_WSYNC_C+1]-1 = 8 and in the 2nd =12  */
4046 					ANTIC_xpos = ANTIC_antic2cpu_ptr[ANTIC_WSYNC_C + 1] - 1;
4047 				}
4048 				else {
4049 					ANTIC_xpos = ANTIC_antic2cpu_ptr[ANTIC_WSYNC_C + 1];
4050 				}
4051 			else {
4052 				ANTIC_wsync_halt = TRUE;
4053 				ANTIC_xpos = ANTIC_xpos_limit;
4054 				if (ANTIC_cpu2antic_ptr[ANTIC_xpos + 1] == ANTIC_cpu2antic_ptr[ANTIC_xpos] + 1) {
4055 					/* antic does not steal the current cycle */
4056 					ANTIC_delayed_wsync = 0;
4057 				}
4058 				else {
4059 					ANTIC_delayed_wsync = 1;
4060 				}
4061 			}
4062 		}
4063 		else {
4064 			ANTIC_delayed_wsync = 0;
4065 #endif /* NEW_CYCLE_EXACT */
4066 			if (ANTIC_xpos <= ANTIC_WSYNC_C && ANTIC_xpos_limit >= ANTIC_WSYNC_C)
4067 				ANTIC_xpos = ANTIC_WSYNC_C;
4068 			else {
4069 				ANTIC_wsync_halt = TRUE;
4070 				ANTIC_xpos = ANTIC_xpos_limit;
4071 			}
4072 #ifdef NEW_CYCLE_EXACT
4073 		}
4074 #endif /* NEW_CYCLE_EXACT */
4075 		break;
4076 	case ANTIC_OFFSET_NMIEN:
4077 		ANTIC_NMIEN = byte;
4078 		break;
4079 	case ANTIC_OFFSET_NMIRES:
4080 		ANTIC_NMIST = 0x1f;
4081 		break;
4082 	default:
4083 		break;
4084 	}
4085 }
4086 
4087 /* State ------------------------------------------------------------------- */
4088 
4089 #ifndef BASIC
4090 
ANTIC_StateSave(void)4091 void ANTIC_StateSave(void)
4092 {
4093 	StateSav_SaveUBYTE(&ANTIC_DMACTL, 1);
4094 	StateSav_SaveUBYTE(&ANTIC_CHACTL, 1);
4095 	StateSav_SaveUBYTE(&ANTIC_HSCROL, 1);
4096 	StateSav_SaveUBYTE(&ANTIC_VSCROL, 1);
4097 	StateSav_SaveUBYTE(&ANTIC_PMBASE, 1);
4098 	StateSav_SaveUBYTE(&ANTIC_CHBASE, 1);
4099 	StateSav_SaveUBYTE(&ANTIC_NMIEN, 1);
4100 	StateSav_SaveUBYTE(&ANTIC_NMIST, 1);
4101 	StateSav_SaveUBYTE(&IR, 1);
4102 	StateSav_SaveUBYTE(&anticmode, 1);
4103 	StateSav_SaveUBYTE(&dctr, 1);
4104 	StateSav_SaveUBYTE(&lastline, 1);
4105 	StateSav_SaveUBYTE(&need_dl, 1);
4106 	StateSav_SaveUBYTE(&vscrol_off, 1);
4107 
4108 	StateSav_SaveUWORD(&ANTIC_dlist, 1);
4109 	StateSav_SaveUWORD(&screenaddr, 1);
4110 
4111 	StateSav_SaveINT(&ANTIC_xpos, 1);
4112 	StateSav_SaveINT(&ANTIC_xpos_limit, 1);
4113 	StateSav_SaveINT(&ANTIC_ypos, 1);
4114 }
4115 
ANTIC_StateRead(void)4116 void ANTIC_StateRead(void)
4117 {
4118 	StateSav_ReadUBYTE(&ANTIC_DMACTL, 1);
4119 	StateSav_ReadUBYTE(&ANTIC_CHACTL, 1);
4120 	StateSav_ReadUBYTE(&ANTIC_HSCROL, 1);
4121 	StateSav_ReadUBYTE(&ANTIC_VSCROL, 1);
4122 	StateSav_ReadUBYTE(&ANTIC_PMBASE, 1);
4123 	StateSav_ReadUBYTE(&ANTIC_CHBASE, 1);
4124 	StateSav_ReadUBYTE(&ANTIC_NMIEN, 1);
4125 	StateSav_ReadUBYTE(&ANTIC_NMIST, 1);
4126 	StateSav_ReadUBYTE(&IR, 1);
4127 	StateSav_ReadUBYTE(&anticmode, 1);
4128 	StateSav_ReadUBYTE(&dctr, 1);
4129 	StateSav_ReadUBYTE(&lastline, 1);
4130 	StateSav_ReadUBYTE(&need_dl, 1);
4131 	StateSav_ReadUBYTE(&vscrol_off, 1);
4132 
4133 	StateSav_ReadUWORD(&ANTIC_dlist, 1);
4134 	StateSav_ReadUWORD(&screenaddr, 1);
4135 
4136 	StateSav_ReadINT(&ANTIC_xpos, 1);
4137 	StateSav_ReadINT(&ANTIC_xpos_limit, 1);
4138 	StateSav_ReadINT(&ANTIC_ypos, 1);
4139 
4140 	ANTIC_PutByte(ANTIC_OFFSET_DMACTL, ANTIC_DMACTL);
4141 	ANTIC_PutByte(ANTIC_OFFSET_CHACTL, ANTIC_CHACTL);
4142 	ANTIC_PutByte(ANTIC_OFFSET_PMBASE, ANTIC_PMBASE);
4143 	ANTIC_PutByte(ANTIC_OFFSET_CHBASE, ANTIC_CHBASE);
4144 }
4145 
4146 #endif /* BASIC */
4147