/* * gtia.c - GTIA chip emulation * * Copyright (C) 1995-1998 David Firth * Copyright (C) 1998-2015 Atari800 development team (see DOC/CREDITS) * * This file is part of the Atari800 emulator project which emulates * the Atari 400, 800, 800XL, 130XE, and 5200 8-bit computers. * * Atari800 is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Atari800 is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Atari800; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include "antic.h" #include "gtia.h" /* GTIA Registers ---------------------------------------------------------- */ UBYTE GTIA_M0PL; UBYTE GTIA_M1PL; UBYTE GTIA_M2PL; UBYTE GTIA_M3PL; UBYTE GTIA_P0PL; UBYTE GTIA_P1PL; UBYTE GTIA_P2PL; UBYTE GTIA_P3PL; UBYTE GTIA_HPOSP0; UBYTE GTIA_HPOSP1; UBYTE GTIA_HPOSP2; UBYTE GTIA_HPOSP3; UBYTE GTIA_HPOSM0; UBYTE GTIA_HPOSM1; UBYTE GTIA_HPOSM2; UBYTE GTIA_HPOSM3; UBYTE GTIA_SIZEP0; UBYTE GTIA_SIZEP1; UBYTE GTIA_SIZEP2; UBYTE GTIA_SIZEP3; UBYTE GTIA_SIZEM; UBYTE GTIA_GRAFP0; UBYTE GTIA_GRAFP1; UBYTE GTIA_GRAFP2; UBYTE GTIA_GRAFP3; UBYTE GTIA_GRAFM; UBYTE GTIA_COLPM0; UBYTE GTIA_COLPM1; UBYTE GTIA_COLPM2; UBYTE GTIA_COLPM3; UBYTE GTIA_COLPF0; UBYTE GTIA_COLPF1; UBYTE GTIA_COLPF2; UBYTE GTIA_COLPF3; UBYTE GTIA_COLBK; UBYTE GTIA_PRIOR; UBYTE GTIA_VDELAY; UBYTE GTIA_GRACTL; /* Internal GTIA state ----------------------------------------------------- */ int GTIA_speaker; int GTIA_consol_override = 0; static UBYTE consol; UBYTE consol_mask; UBYTE GTIA_TRIG[4]; UBYTE GTIA_TRIG_latch[4]; #if defined(BASIC) || defined(CURSES_BASIC) static UBYTE PF0PM = 0; static UBYTE PF1PM = 0; static UBYTE PF2PM = 0; static UBYTE PF3PM = 0; #define GTIA_collisions_mask_missile_playfield 0 #define GTIA_collisions_mask_player_playfield 0 #define GTIA_collisions_mask_missile_player 0 #define GTIA_collisions_mask_player_player 0 #else /* defined(BASIC) || defined(CURSES_BASIC) */ void set_prior(UBYTE byte); /* in antic.c */ /* Player/Missile stuff ---------------------------------------------------- */ /* change to 0x00 to disable collisions */ UBYTE GTIA_collisions_mask_missile_playfield = 0x0f; UBYTE GTIA_collisions_mask_player_playfield = 0x0f; UBYTE GTIA_collisions_mask_missile_player = 0x0f; UBYTE GTIA_collisions_mask_player_player = 0x0f; #ifdef NEW_CYCLE_EXACT /* temporary collision registers for the current scanline only */ UBYTE P1PL_T; UBYTE P2PL_T; UBYTE P3PL_T; UBYTE M0PL_T; UBYTE M1PL_T; UBYTE M2PL_T; UBYTE M3PL_T; /* If partial collisions have been generated during a scanline, this * is the position of the up-to-date collision point , otherwise it is 0 */ int collision_curpos; /* if hitclr has been written to during a scanline, this is the position * within pm_scaline at which it was written to, and collisions should * only be generated from this point on, otherwise it is 0 */ int hitclr_pos; #else #define P1PL_T GTIA_P1PL #define P2PL_T GTIA_P2PL #define P3PL_T GTIA_P3PL #define M0PL_T GTIA_M0PL #define M1PL_T GTIA_M1PL #define M2PL_T GTIA_M2PL #define M3PL_T GTIA_M3PL #endif /* NEW_CYCLE_EXACT */ static UBYTE *hposp_ptr[4]; static UBYTE *hposm_ptr[4]; static ULONG hposp_mask[4]; static ULONG grafp_lookup[4][256]; static ULONG *grafp_ptr[4]; static int global_sizem[4]; static const int PM_Width[4] = {1, 2, 1, 4}; /* Meaning of bits in GTIA_pm_scanline: bit 0 - Player 0 bit 1 - Player 1 bit 2 - Player 2 bit 3 - Player 3 bit 4 - Missile 0 bit 5 - Missile 1 bit 6 - Missile 2 bit 7 - Missile 3 */ UBYTE GTIA_pm_scanline[ATARI_WIDTH / 2 + 8]; /* there's a byte for every *pair* of pixels */ int GTIA_pm_dirty = TRUE; #define C_PM0 0x01 #define C_PM1 0x02 #define C_PM01 0x03 #define C_PM2 0x04 #define C_PM3 0x05 #define C_PM23 0x06 #define C_PM023 0x07 #define C_PM123 0x08 #define C_PM0123 0x09 #define C_PM25 0x0a #define C_PM35 0x0b #define C_PM235 0x0c #define C_COLLS 0x0d #define C_BAK 0x00 #define C_HI2 0x20 #define C_HI3 0x30 #define C_PF0 0x40 #define C_PF1 0x50 #define C_PF2 0x60 #define C_PF3 0x70 #define PF0PM (*(UBYTE *) &ANTIC_cl[C_PF0 | C_COLLS]) #define PF1PM (*(UBYTE *) &ANTIC_cl[C_PF1 | C_COLLS]) #define PF2PM (*(UBYTE *) &ANTIC_cl[C_PF2 | C_COLLS]) #define PF3PM (*(UBYTE *) &ANTIC_cl[C_PF3 | C_COLLS]) /* Colours ----------------------------------------------------------------- */ #ifdef USE_COLOUR_TRANSLATION_TABLE UWORD colour_translation_table[256]; #endif /* USE_COLOUR_TRANSLATION_TABLE */ static void setup_gtia9_11(void) { int i; #ifdef USE_COLOUR_TRANSLATION_TABLE UWORD temp; temp = colour_translation_table[GTIA_COLBK & 0xf0]; ANTIC_lookup_gtia11[0] = ((ULONG) temp << 16) + temp; for (i = 1; i < 16; i++) { temp = colour_translation_table[GTIA_COLBK | i]; ANTIC_lookup_gtia9[i] = ((ULONG) temp << 16) + temp; temp = colour_translation_table[GTIA_COLBK | (i << 4)]; ANTIC_lookup_gtia11[i] = ((ULONG) temp << 16) + temp; } #else ULONG count9 = 0; ULONG count11 = 0; ANTIC_lookup_gtia11[0] = ANTIC_lookup_gtia9[0] & 0xf0f0f0f0; for (i = 1; i < 16; i++) { ANTIC_lookup_gtia9[i] = ANTIC_lookup_gtia9[0] | (count9 += 0x01010101); ANTIC_lookup_gtia11[i] = ANTIC_lookup_gtia9[0] | (count11 += 0x10101010); } #endif } #endif /* defined(BASIC) || defined(CURSES_BASIC) */ /* Initialization ---------------------------------------------------------- */ int GTIA_Initialise(void) { #if !defined(BASIC) && !defined(CURSES_BASIC) int i; for (i = 0; i < 256; i++) { int tmp = i + 0x100; ULONG grafp1 = 0; ULONG grafp2 = 0; ULONG grafp4 = 0; do { grafp1 <<= 1; grafp2 <<= 2; grafp4 <<= 4; if (tmp & 1) { grafp1++; grafp2 += 3; grafp4 += 15; } tmp >>= 1; } while (tmp != 1); grafp_lookup[2][i] = grafp_lookup[0][i] = grafp1; grafp_lookup[1][i] = grafp2; grafp_lookup[3][i] = grafp4; } memset(ANTIC_cl, GTIA_COLOUR_BLACK, sizeof(ANTIC_cl)); for (i = 0; i < 32; i++) GTIA_PutByte((UWORD) i, 0); #endif /* !defined(BASIC) && !defined(CURSES_BASIC) */ return TRUE; } #ifdef NEW_CYCLE_EXACT /* generate updated PxPL and MxPL for part of a scanline */ /* slow, but should be called rarely */ static void generate_partial_pmpl_colls(int l, int r) { int i; if (r < 0 || l >= (int) sizeof(GTIA_pm_scanline) / (int) sizeof(GTIA_pm_scanline[0])) return; if (r >= (int) sizeof(GTIA_pm_scanline) / (int) sizeof(GTIA_pm_scanline[0])) { r = (int) sizeof(GTIA_pm_scanline) / (int) sizeof(GTIA_pm_scanline[0]); } if (l < 0) l = 0; for (i = l; i <= r; i++) { UBYTE p = GTIA_pm_scanline[i]; /* It is possible that some bits are set in PxPL/MxPL here, which would * not otherwise be set ever in GTIA_NewPmScanline. This is because the * player collisions are always generated in order in GTIA_NewPmScanline. * However this does not cause any problem because we never use those bits * of PxPL/MxPL in the collision reading code. */ GTIA_P1PL |= (p & (1 << 1)) ? p : 0; GTIA_P2PL |= (p & (1 << 2)) ? p : 0; GTIA_P3PL |= (p & (1 << 3)) ? p : 0; GTIA_M0PL |= (p & (0x10 << 0)) ? p : 0; GTIA_M1PL |= (p & (0x10 << 1)) ? p : 0; GTIA_M2PL |= (p & (0x10 << 2)) ? p : 0; GTIA_M3PL |= (p & (0x10 << 3)) ? p : 0; } } /* update pm->pl collisions for a partial scanline */ static void update_partial_pmpl_colls(void) { int l = collision_curpos; int r = ANTIC_XPOS * 2 - 37; generate_partial_pmpl_colls(l, r); collision_curpos = r; } /* update pm-> pl collisions at the end of a scanline */ void GTIA_UpdatePmplColls(void) { if (hitclr_pos != 0){ generate_partial_pmpl_colls(hitclr_pos, sizeof(GTIA_pm_scanline) / sizeof(GTIA_pm_scanline[0]) - 1); /* If hitclr was written to, then only part of GTIA_pm_scanline should be used * for collisions */ } else { /* otherwise the whole of pm_scaline can be used for collisions. This will * update the collision registers based on the generated collisions for the * current line */ GTIA_P1PL |= P1PL_T; GTIA_P2PL |= P2PL_T; GTIA_P3PL |= P3PL_T; GTIA_M0PL |= M0PL_T; GTIA_M1PL |= M1PL_T; GTIA_M2PL |= M2PL_T; GTIA_M3PL |= M3PL_T; } collision_curpos = 0; hitclr_pos = 0; } #else #define update_partial_pmpl_colls() #endif /* NEW_CYCLE_EXACT */ /* Prepare PMG scanline ---------------------------------------------------- */ #if !defined(BASIC) && !defined(CURSES_BASIC) void GTIA_NewPmScanline(void) { #ifdef NEW_CYCLE_EXACT /* reset temporary pm->pl collisions */ P1PL_T = P2PL_T = P3PL_T = 0; M0PL_T = M1PL_T = M2PL_T = M3PL_T = 0; #endif /* NEW_CYCLE_EXACT */ /* Clear if necessary */ if (GTIA_pm_dirty) { memset(GTIA_pm_scanline, 0, ATARI_WIDTH / 2); GTIA_pm_dirty = FALSE; } /* Draw Players */ #define DO_PLAYER(n) if (GTIA_GRAFP##n) { \ ULONG grafp = grafp_ptr[n][GTIA_GRAFP##n] & hposp_mask[n]; \ if (grafp) { \ UBYTE *ptr = hposp_ptr[n]; \ GTIA_pm_dirty = TRUE; \ do { \ if (grafp & 1) \ P##n##PL_T |= *ptr |= 1 << n; \ ptr++; \ grafp >>= 1; \ } while (grafp); \ } \ } /* optimized DO_PLAYER(0): GTIA_pm_scanline is clear and P0PL is unused */ if (GTIA_GRAFP0) { ULONG grafp = grafp_ptr[0][GTIA_GRAFP0] & hposp_mask[0]; if (grafp) { UBYTE *ptr = hposp_ptr[0]; GTIA_pm_dirty = TRUE; do { if (grafp & 1) *ptr = 1; ptr++; grafp >>= 1; } while (grafp); } } DO_PLAYER(1) DO_PLAYER(2) DO_PLAYER(3) /* Draw Missiles */ #define DO_MISSILE(n,p,m,r,l) if (GTIA_GRAFM & m) { \ int j = global_sizem[n]; \ UBYTE *ptr = hposm_ptr[n]; \ if (GTIA_GRAFM & r) { \ if (GTIA_GRAFM & l) \ j <<= 1; \ } \ else \ ptr += j; \ if (ptr < GTIA_pm_scanline + 2) { \ j += ptr - GTIA_pm_scanline - 2; \ ptr = GTIA_pm_scanline + 2; \ } \ else if (ptr + j > GTIA_pm_scanline + ATARI_WIDTH / 2 - 2) \ j = GTIA_pm_scanline + ATARI_WIDTH / 2 - 2 - ptr; \ if (j > 0) \ do \ M##n##PL_T |= *ptr++ |= p; \ while (--j); \ } if (GTIA_GRAFM) { GTIA_pm_dirty = TRUE; DO_MISSILE(3, 0x80, 0xc0, 0x80, 0x40) DO_MISSILE(2, 0x40, 0x30, 0x20, 0x10) DO_MISSILE(1, 0x20, 0x0c, 0x08, 0x04) DO_MISSILE(0, 0x10, 0x03, 0x02, 0x01) } } #endif /* !defined(BASIC) && !defined(CURSES_BASIC) */ /* GTIA registers ---------------------------------------------------------- */ void GTIA_Frame(void) { #ifdef BASIC consol = 0xf; #else consol = INPUT_key_consol | 0x08; #endif if (GTIA_GRACTL & 4) { GTIA_TRIG_latch[0] &= GTIA_TRIG[0]; GTIA_TRIG_latch[1] &= GTIA_TRIG[1]; GTIA_TRIG_latch[2] &= GTIA_TRIG[2]; GTIA_TRIG_latch[3] &= GTIA_TRIG[3]; } } UBYTE GTIA_GetByte(UWORD addr, int no_side_effects) { switch (addr & 0x1f) { case GTIA_OFFSET_M0PF: #ifdef NEW_CYCLE_EXACT if (ANTIC_DRAWING_SCREEN) { ANTIC_UpdateScanline(); } #endif return (((PF0PM & 0x10) >> 4) + ((PF1PM & 0x10) >> 3) + ((PF2PM & 0x10) >> 2) + ((PF3PM & 0x10) >> 1)) & GTIA_collisions_mask_missile_playfield; case GTIA_OFFSET_M1PF: #ifdef NEW_CYCLE_EXACT if (ANTIC_DRAWING_SCREEN) { ANTIC_UpdateScanline(); } #endif return (((PF0PM & 0x20) >> 5) + ((PF1PM & 0x20) >> 4) + ((PF2PM & 0x20) >> 3) + ((PF3PM & 0x20) >> 2)) & GTIA_collisions_mask_missile_playfield; case GTIA_OFFSET_M2PF: #ifdef NEW_CYCLE_EXACT if (ANTIC_DRAWING_SCREEN) { ANTIC_UpdateScanline(); } #endif return (((PF0PM & 0x40) >> 6) + ((PF1PM & 0x40) >> 5) + ((PF2PM & 0x40) >> 4) + ((PF3PM & 0x40) >> 3)) & GTIA_collisions_mask_missile_playfield; case GTIA_OFFSET_M3PF: #ifdef NEW_CYCLE_EXACT if (ANTIC_DRAWING_SCREEN) { ANTIC_UpdateScanline(); } #endif return (((PF0PM & 0x80) >> 7) + ((PF1PM & 0x80) >> 6) + ((PF2PM & 0x80) >> 5) + ((PF3PM & 0x80) >> 4)) & GTIA_collisions_mask_missile_playfield; case GTIA_OFFSET_P0PF: #ifdef NEW_CYCLE_EXACT if (ANTIC_DRAWING_SCREEN) { ANTIC_UpdateScanline(); } #endif return ((PF0PM & 0x01) + ((PF1PM & 0x01) << 1) + ((PF2PM & 0x01) << 2) + ((PF3PM & 0x01) << 3)) & GTIA_collisions_mask_player_playfield; case GTIA_OFFSET_P1PF: #ifdef NEW_CYCLE_EXACT if (ANTIC_DRAWING_SCREEN) { ANTIC_UpdateScanline(); } #endif return (((PF0PM & 0x02) >> 1) + (PF1PM & 0x02) + ((PF2PM & 0x02) << 1) + ((PF3PM & 0x02) << 2)) & GTIA_collisions_mask_player_playfield; case GTIA_OFFSET_P2PF: #ifdef NEW_CYCLE_EXACT if (ANTIC_DRAWING_SCREEN) { ANTIC_UpdateScanline(); } #endif return (((PF0PM & 0x04) >> 2) + ((PF1PM & 0x04) >> 1) + (PF2PM & 0x04) + ((PF3PM & 0x04) << 1)) & GTIA_collisions_mask_player_playfield; case GTIA_OFFSET_P3PF: #ifdef NEW_CYCLE_EXACT if (ANTIC_DRAWING_SCREEN) { ANTIC_UpdateScanline(); } #endif return (((PF0PM & 0x08) >> 3) + ((PF1PM & 0x08) >> 2) + ((PF2PM & 0x08) >> 1) + (PF3PM & 0x08)) & GTIA_collisions_mask_player_playfield; case GTIA_OFFSET_M0PL: update_partial_pmpl_colls(); return GTIA_M0PL & GTIA_collisions_mask_missile_player; case GTIA_OFFSET_M1PL: update_partial_pmpl_colls(); return GTIA_M1PL & GTIA_collisions_mask_missile_player; case GTIA_OFFSET_M2PL: update_partial_pmpl_colls(); return GTIA_M2PL & GTIA_collisions_mask_missile_player; case GTIA_OFFSET_M3PL: update_partial_pmpl_colls(); return GTIA_M3PL & GTIA_collisions_mask_missile_player; case GTIA_OFFSET_P0PL: update_partial_pmpl_colls(); return (((GTIA_P1PL & 0x01) << 1) /* mask in player 1 */ + ((GTIA_P2PL & 0x01) << 2) /* mask in player 2 */ + ((GTIA_P3PL & 0x01) << 3)) /* mask in player 3 */ & GTIA_collisions_mask_player_player; case GTIA_OFFSET_P1PL: update_partial_pmpl_colls(); return ((GTIA_P1PL & 0x01) /* mask in player 0 */ + ((GTIA_P2PL & 0x02) << 1) /* mask in player 2 */ + ((GTIA_P3PL & 0x02) << 2)) /* mask in player 3 */ & GTIA_collisions_mask_player_player; case GTIA_OFFSET_P2PL: update_partial_pmpl_colls(); return ((GTIA_P2PL & 0x03) /* mask in player 0 and 1 */ + ((GTIA_P3PL & 0x04) << 1)) /* mask in player 3 */ & GTIA_collisions_mask_player_player; case GTIA_OFFSET_P3PL: update_partial_pmpl_colls(); return (GTIA_P3PL & 0x07) /* mask in player 0,1, and 2 */ & GTIA_collisions_mask_player_player; case GTIA_OFFSET_TRIG0: return GTIA_TRIG[0] & GTIA_TRIG_latch[0]; case GTIA_OFFSET_TRIG1: return GTIA_TRIG[1] & GTIA_TRIG_latch[1]; case GTIA_OFFSET_TRIG2: return GTIA_TRIG[2] & GTIA_TRIG_latch[2]; case GTIA_OFFSET_TRIG3: return GTIA_TRIG[3] & GTIA_TRIG_latch[3]; case GTIA_OFFSET_PAL: return (tv_mode == TV_PAL) ? 0x01 : 0x0f; case GTIA_OFFSET_CONSOL: { UBYTE byte = consol & consol_mask; #if SKIP if (!no_side_effects && GTIA_consol_override > 0) { /* Check if we're called from outside OS. This avoids sending console keystrokes to diagnostic cartridges. */ if (CPU_regPC < 0xc000) /* Not from OS. Disable console override. */ GTIA_consol_override = 0; else { --GTIA_consol_override; if (Atari800_builtin_basic && Atari800_disable_basic && !BINLOAD_loading_basic) /* Only for XL/XE - hold Option during reboot. */ byte &= ~INPUT_CONSOL_OPTION; if (CASSETTE_hold_start && Atari800_machine_type != Atari800_MACHINE_5200) { /* Only for the computers - hold Start during reboot. */ byte &= ~INPUT_CONSOL_START; if (GTIA_consol_override == 0) { /* press Space after Start to start cassette boot. */ CASSETTE_press_space = 1; CASSETTE_hold_start = CASSETTE_hold_start_on_reboot; } } } } #endif return byte; } default: break; } return 0xf; } void GTIA_PutByte(UWORD addr, UBYTE byte) { #if !defined(BASIC) && !defined(CURSES_BASIC) UWORD cword; UWORD cword2; #ifdef NEW_CYCLE_EXACT int x; /* the cycle-exact update position in GTIA_pm_scanline */ if (ANTIC_DRAWING_SCREEN) { if ((addr & 0x1f) != GTIA_PRIOR) { ANTIC_UpdateScanline(); } else { ANTIC_UpdateScanlinePrior(byte); } } #define UPDATE_PM_CYCLE_EXACT if(ANTIC_DRAWING_SCREEN) GTIA_NewPmScanline(); #else #define UPDATE_PM_CYCLE_EXACT #endif #endif /* !defined(BASIC) && !defined(CURSES_BASIC) */ switch (addr & 0x1f) { case GTIA_OFFSET_CONSOL: GTIA_speaker = !(byte & 0x08); #ifdef CONSOLE_SOUND POKEYSND_UpdateConsol(1); #endif consol_mask = (~byte) & 0x0f; break; #if defined(BASIC) || defined(CURSES_BASIC) /* We use these for Antic modes 6, 7 on Curses */ case GTIA_OFFSET_COLPF0: GTIA_COLPF0 = byte; break; case GTIA_OFFSET_COLPF1: GTIA_COLPF1 = byte; break; case GTIA_OFFSET_COLPF2: GTIA_COLPF2 = byte; break; case GTIA_OFFSET_COLPF3: GTIA_COLPF3 = byte; break; #else #ifdef USE_COLOUR_TRANSLATION_TABLE case GTIA_OFFSET_COLBK: GTIA_COLBK = byte &= 0xfe; ANTIC_cl[C_BAK] = cword = colour_translation_table[byte]; if (cword != (UWORD) (ANTIC_lookup_gtia9[0]) ) { ANTIC_lookup_gtia9[0] = cword + (cword << 16); if (GTIA_PRIOR & 0x40) setup_gtia9_11(); } break; case GTIA_OFFSET_COLPF0: GTIA_COLPF0 = byte &= 0xfe; ANTIC_cl[C_PF0] = cword = GTIA_colour_translation_table[byte]; if ((GTIA_PRIOR & 1) == 0) { ANTIC_cl[C_PF0 | C_PM23] = ANTIC_cl[C_PF0 | C_PM3] = ANTIC_cl[C_PF0 | C_PM2] = cword; if ((GTIA_PRIOR & 3) == 0) { if (GTIA_PRIOR & 0xf) { ANTIC_cl[C_PF0 | C_PM01] = ANTIC_cl[C_PF0 | C_PM1] = ANTIC_cl[C_PF0 | C_PM0] = cword; if ((GTIA_PRIOR & 0xf) == 0xc) ANTIC_cl[C_PF0 | C_PM0123] = ANTIC_cl[C_PF0 | C_PM123] = ANTIC_cl[C_PF0 | C_PM023] = cword; } else { ANTIC_cl[C_PF0 | C_PM0] = colour_translation_table[byte | GTIA_COLPM0]; ANTIC_cl[C_PF0 | C_PM1] = colour_translation_table[byte | GTIA_COLPM1]; ANTIC_cl[C_PF0 | C_PM01] = colour_translation_table[byte | GTIA_COLPM0 | GTIA_COLPM1]; } } if ((GTIA_PRIOR & 0xf) >= 0xa) ANTIC_cl[C_PF0 | C_PM25] = cword; } break; case GTIA_OFFSET_COLPF1: GTIA_COLPF1 = byte &= 0xfe; ANTIC_cl[C_PF1] = cword = GTIA_colour_translation_table[byte]; if ((GTIA_PRIOR & 1) == 0) { ANTIC_cl[C_PF1 | C_PM23] = ANTIC_cl[C_PF1 | C_PM3] = ANTIC_cl[C_PF1 | C_PM2] = cword; if ((GTIA_PRIOR & 3) == 0) { if (GTIA_PRIOR & 0xf) { ANTIC_cl[C_PF1 | C_PM01] = ANTIC_cl[C_PF1 | C_PM1] = ANTIC_cl[C_PF1 | C_PM0] = cword; if ((GTIA_PRIOR & 0xf) == 0xc) ANTIC_cl[C_PF1 | C_PM0123] = ANTIC_cl[C_PF1 | C_PM123] = ANTIC_cl[C_PF1 | C_PM023] = cword; } else { ANTIC_cl[C_PF1 | C_PM0] = colour_translation_table[byte | GTIA_COLPM0]; ANTIC_cl[C_PF1 | C_PM1] = colour_translation_table[byte | GTIA_COLPM1]; ANTIC_cl[C_PF1 | C_PM01] = colour_translation_table[byte | GTIA_COLPM0 | GTIA_COLPM1]; } } } { UBYTE byte2 = (GTIA_COLPF2 & 0xf0) + (byte & 0xf); ANTIC_cl[C_HI2] = cword = colour_translation_table[byte2]; ANTIC_cl[C_HI3] = colour_translation_table[(GTIA_COLPF3 & 0xf0) | (byte & 0xf)]; if (GTIA_PRIOR & 4) ANTIC_cl[C_HI2 | C_PM01] = ANTIC_cl[C_HI2 | C_PM1] = ANTIC_cl[C_HI2 | C_PM0] = cword; if ((GTIA_PRIOR & 9) == 0) { if (GTIA_PRIOR & 0xf) ANTIC_cl[C_HI2 | C_PM23] = ANTIC_cl[C_HI2 | C_PM3] = ANTIC_cl[C_HI2 | C_PM2] = cword; else { ANTIC_cl[C_HI2 | C_PM2] = colour_translation_table[byte2 | (GTIA_COLPM2 & 0xf0)]; ANTIC_cl[C_HI2 | C_PM3] = colour_translation_table[byte2 | (GTIA_COLPM3 & 0xf0)]; ANTIC_cl[C_HI2 | C_PM23] = colour_translation_table[byte2 | ((GTIA_COLPM2 | GTIA_COLPM3) & 0xf0)]; } } } break; case GTIA_OFFSET_COLPF2: GTIA_COLPF2 = byte &= 0xfe; ANTIC_cl[C_PF2] = cword = GTIA_colour_translation_table[byte]; { UBYTE byte2 = (byte & 0xf0) + (GTIA_COLPF1 & 0xf); ANTIC_cl[C_HI2] = cword2 = colour_translation_table[byte2]; if (GTIA_PRIOR & 4) { ANTIC_cl[C_PF2 | C_PM01] = ANTIC_cl[C_PF2 | C_PM1] = ANTIC_cl[C_PF2 | C_PM0] = cword; ANTIC_cl[C_HI2 | C_PM01] = ANTIC_cl[C_HI2 | C_PM1] = ANTIC_cl[C_HI2 | C_PM0] = cword2; } if ((GTIA_PRIOR & 9) == 0) { if (GTIA_PRIOR & 0xf) { ANTIC_cl[C_PF2 | C_PM23] = ANTIC_cl[C_PF2 | C_PM3] = ANTIC_cl[C_PF2 | C_PM2] = cword; ANTIC_cl[C_HI2 | C_PM23] = ANTIC_cl[C_HI2 | C_PM3] = ANTIC_cl[C_HI2 | C_PM2] = cword2; } else { ANTIC_cl[C_PF2 | C_PM2] = colour_translation_table[byte | GTIA_COLPM2]; ANTIC_cl[C_PF2 | C_PM3] = colour_translation_table[byte | GTIA_COLPM3]; ANTIC_cl[C_PF2 | C_PM23] = colour_translation_table[byte | GTIA_COLPM2 | GTIA_COLPM3]; ANTIC_cl[C_HI2 | C_PM2] = colour_translation_table[byte2 | (GTIA_COLPM2 & 0xf0)]; ANTIC_cl[C_HI2 | C_PM3] = colour_translation_table[byte2 | (GTIA_COLPM3 & 0xf0)]; ANTIC_cl[C_HI2 | C_PM23] = colour_translation_table[byte2 | ((GTIA_COLPM2 | GTIA_COLPM3) & 0xf0)]; } } } break; case GTIA_OFFSET_COLPF3: GTIA_COLPF3 = byte &= 0xfe; ANTIC_cl[C_PF3] = cword = colour_translation_table[byte]; ANTIC_cl[C_HI3] = cword2 = colour_translation_table[(byte & 0xf0) | (GTIA_COLPF1 & 0xf)]; if (GTIA_PRIOR & 4) ANTIC_cl[C_PF3 | C_PM01] = ANTIC_cl[C_PF3 | C_PM1] = ANTIC_cl[C_PF3 | C_PM0] = cword; if ((GTIA_PRIOR & 9) == 0) { if (GTIA_PRIOR & 0xf) ANTIC_cl[C_PF3 | C_PM23] = ANTIC_cl[C_PF3 | C_PM3] = ANTIC_cl[C_PF3 | C_PM2] = cword; else { ANTIC_cl[C_PF3 | C_PM25] = ANTIC_cl[C_PF2 | C_PM25] = ANTIC_cl[C_PM25] = ANTIC_cl[C_PF3 | C_PM2] = colour_translation_table[byte | GTIA_COLPM2]; ANTIC_cl[C_PF3 | C_PM35] = ANTIC_cl[C_PF2 | C_PM35] = ANTIC_cl[C_PM35] = ANTIC_cl[C_PF3 | C_PM3] = colour_translation_table[byte | GTIA_COLPM3]; ANTIC_cl[C_PF3 | C_PM235] = ANTIC_cl[C_PF2 | C_PM235] = ANTIC_cl[C_PM235] = ANTIC_cl[C_PF3 | C_PM23] = colour_translation_table[byte | GTIA_COLPM2 | GTIA_COLPM3]; ANTIC_cl[C_PF0 | C_PM235] = ANTIC_cl[C_PF0 | C_PM35] = ANTIC_cl[C_PF0 | C_PM25] = ANTIC_cl[C_PF1 | C_PM235] = ANTIC_cl[C_PF1 | C_PM35] = ANTIC_cl[C_PF1 | C_PM25] = cword; } } break; case GTIA_OFFSET_COLPM0: GTIA_COLPM0 = byte &= 0xfe; ANTIC_cl[C_PM023] = ANTIC_cl[C_PM0] = cword = colour_translation_table[byte]; { UBYTE byte2 = byte | GTIA_COLPM1; ANTIC_cl[C_PM0123] = ANTIC_cl[C_PM01] = cword2 = colour_translation_table[byte2]; if ((GTIA_PRIOR & 4) == 0) { ANTIC_cl[C_PF2 | C_PM0] = ANTIC_cl[C_PF3 | C_PM0] = cword; ANTIC_cl[C_PF2 | C_PM01] = ANTIC_cl[C_PF3 | C_PM01] = cword2; ANTIC_cl[C_HI2 | C_PM0] = colour_translation_table[(byte & 0xf0) | (GTIA_COLPF1 & 0xf)]; ANTIC_cl[C_HI2 | C_PM01] = colour_translation_table[(byte2 & 0xf0) | (GTIA_COLPF1 & 0xf)]; if ((GTIA_PRIOR & 0xc) == 0) { if (GTIA_PRIOR & 3) { ANTIC_cl[C_PF0 | C_PM0] = ANTIC_cl[C_PF1 | C_PM0] = cword; ANTIC_cl[C_PF0 | C_PM01] = ANTIC_cl[C_PF1 | C_PM01] = cword2; } else { ANTIC_cl[C_PF0 | C_PM0] = colour_translation_table[byte | GTIA_COLPF0]; ANTIC_cl[C_PF1 | C_PM0] = colour_translation_table[byte | GTIA_COLPF1]; ANTIC_cl[C_PF0 | C_PM01] = colour_translation_table[byte2 | GTIA_COLPF0]; ANTIC_cl[C_PF1 | C_PM01] = colour_translation_table[byte2 | GTIA_COLPF1]; } } } } break; case GTIA_OFFSET_COLPM1: GTIA_COLPM1 = byte &= 0xfe; ANTIC_cl[C_PM123] = ANTIC_cl[C_PM1] = cword = colour_translation_table[byte]; { UBYTE byte2 = byte | GTIA_COLPM0; ANTIC_cl[C_PM0123] = ANTIC_cl[C_PM01] = cword2 = colour_translation_table[byte2]; if ((GTIA_PRIOR & 4) == 0) { ANTIC_cl[C_PF2 | C_PM1] = ANTIC_cl[C_PF3 | C_PM1] = cword; ANTIC_cl[C_PF2 | C_PM01] = ANTIC_cl[C_PF3 | C_PM01] = cword2; ANTIC_cl[C_HI2 | C_PM1] = colour_translation_table[(byte & 0xf0) | (GTIA_COLPF1 & 0xf)]; ANTIC_cl[C_HI2 | C_PM01] = colour_translation_table[(byte2 & 0xf0) | (GTIA_COLPF1 & 0xf)]; if ((GTIA_PRIOR & 0xc) == 0) { if (GTIA_PRIOR & 3) { ANTIC_cl[C_PF0 | C_PM1] = ANTIC_cl[C_PF1 | C_PM1] = cword; ANTIC_cl[C_PF0 | C_PM01] = ANTIC_cl[C_PF1 | C_PM01] = cword2; } else { ANTIC_cl[C_PF0 | C_PM1] = colour_translation_table[byte | GTIA_COLPF0]; ANTIC_cl[C_PF1 | C_PM1] = colour_translation_table[byte | GTIA_COLPF1]; ANTIC_cl[C_PF0 | C_PM01] = colour_translation_table[byte2 | GTIA_COLPF0]; ANTIC_cl[C_PF1 | C_PM01] = colour_translation_table[byte2 | GTIA_COLPF1]; } } } } break; case GTIA_OFFSET_COLPM2: GTIA_COLPM2 = byte &= 0xfe; ANTIC_cl[C_PM2] = cword = colour_translation_table[byte]; { UBYTE byte2 = byte | GTIA_COLPM3; ANTIC_cl[C_PM23] = cword2 = colour_translation_table[byte2]; if (GTIA_PRIOR & 1) { ANTIC_cl[C_PF0 | C_PM2] = ANTIC_cl[C_PF1 | C_PM2] = cword; ANTIC_cl[C_PF0 | C_PM23] = ANTIC_cl[C_PF1 | C_PM23] = cword2; } if ((GTIA_PRIOR & 6) == 0) { if (GTIA_PRIOR & 9) { ANTIC_cl[C_PF2 | C_PM2] = ANTIC_cl[C_PF3 | C_PM2] = cword; ANTIC_cl[C_PF2 | C_PM23] = ANTIC_cl[C_PF3 | C_PM23] = cword2; ANTIC_cl[C_HI2 | C_PM2] = colour_translation_table[(byte & 0xf0) | (GTIA_COLPF1 & 0xf)]; ANTIC_cl[C_HI2 | C_PM23] = colour_translation_table[(byte2 & 0xf0) | (GTIA_COLPF1 & 0xf)]; } else { ANTIC_cl[C_PF2 | C_PM2] = colour_translation_table[byte | GTIA_COLPF2]; ANTIC_cl[C_PF3 | C_PM25] = ANTIC_cl[C_PF2 | C_PM25] = ANTIC_cl[C_PM25] = ANTIC_cl[C_PF3 | C_PM2] = colour_translation_table[byte | GTIA_COLPF3]; ANTIC_cl[C_PF2 | C_PM23] = colour_translation_table[byte2 | GTIA_COLPF2]; ANTIC_cl[C_PF3 | C_PM235] = ANTIC_cl[C_PF2 | C_PM235] = ANTIC_cl[C_PM235] = ANTIC_cl[C_PF3 | C_PM23] = colour_translation_table[byte2 | GTIA_COLPF3]; ANTIC_cl[C_HI2 | C_PM2] = colour_translation_table[((byte | GTIA_COLPF2) & 0xf0) | (GTIA_COLPF1 & 0xf)]; ANTIC_cl[C_HI2 | C_PM25] = colour_translation_table[((byte | GTIA_COLPF3) & 0xf0) | (GTIA_COLPF1 & 0xf)]; ANTIC_cl[C_HI2 | C_PM23] = colour_translation_table[((byte2 | GTIA_COLPF2) & 0xf0) | (GTIA_COLPF1 & 0xf)]; ANTIC_cl[C_HI2 | C_PM235] = colour_translation_table[((byte2 | GTIA_COLPF3) & 0xf0) | (GTIA_COLPF1 & 0xf)]; } } } break; case GTIA_OFFSET_COLPM3: GTIA_COLPM3 = byte &= 0xfe; ANTIC_cl[C_PM3] = cword = colour_translation_table[byte]; { UBYTE byte2 = byte | GTIA_COLPM2; ANTIC_cl[C_PM23] = cword2 = colour_translation_table[byte2]; if (GTIA_PRIOR & 1) { ANTIC_cl[C_PF0 | C_PM3] = ANTIC_cl[C_PF1 | C_PM3] = cword; ANTIC_cl[C_PF0 | C_PM23] = ANTIC_cl[C_PF1 | C_PM23] = cword2; } if ((GTIA_PRIOR & 6) == 0) { if (GTIA_PRIOR & 9) { ANTIC_cl[C_PF2 | C_PM3] = ANTIC_cl[C_PF3 | C_PM3] = cword; ANTIC_cl[C_PF2 | C_PM23] = ANTIC_cl[C_PF3 | C_PM23] = cword2; } else { ANTIC_cl[C_PF2 | C_PM3] = colour_translation_table[byte | GTIA_COLPF2]; ANTIC_cl[C_PF3 | C_PM35] = ANTIC_cl[C_PF2 | C_PM35] = ANTIC_cl[C_PM35] = ANTIC_cl[C_PF3 | C_PM3] = colour_translation_table[byte | GTIA_COLPF3]; ANTIC_cl[C_PF2 | C_PM23] = colour_translation_table[byte2 | GTIA_COLPF2]; ANTIC_cl[C_PF3 | C_PM235] = ANTIC_cl[C_PF2 | C_PM235] = ANTIC_cl[C_PM235] = ANTIC_cl[C_PF3 | C_PM23] = colour_translation_table[byte2 | GTIA_COLPF3]; ANTIC_cl[C_HI2 | C_PM3] = colour_translation_table[((byte | GTIA_COLPF2) & 0xf0) | (GTIA_COLPF1 & 0xf)]; ANTIC_cl[C_HI2 | C_PM23] = colour_translation_table[((byte2 | GTIA_COLPF2) & 0xf0) | (GTIA_COLPF1 & 0xf)]; } } } break; #else /* USE_COLOUR_TRANSLATION_TABLE */ case GTIA_OFFSET_COLBK: GTIA_COLBK = byte &= 0xfe; GTIA_COLOUR_TO_WORD(cword,byte); ANTIC_cl[C_BAK] = cword; if (cword != (UWORD) (ANTIC_lookup_gtia9[0]) ) { ANTIC_lookup_gtia9[0] = cword + (cword << 16); if (GTIA_PRIOR & 0x40) setup_gtia9_11(); } break; case GTIA_OFFSET_COLPF0: GTIA_COLPF0 = byte &= 0xfe; GTIA_COLOUR_TO_WORD(cword,byte); ANTIC_cl[C_PF0] = cword; if ((GTIA_PRIOR & 1) == 0) { ANTIC_cl[C_PF0 | C_PM23] = ANTIC_cl[C_PF0 | C_PM3] = ANTIC_cl[C_PF0 | C_PM2] = cword; if ((GTIA_PRIOR & 3) == 0) { if (GTIA_PRIOR & 0xf) { ANTIC_cl[C_PF0 | C_PM01] = ANTIC_cl[C_PF0 | C_PM1] = ANTIC_cl[C_PF0 | C_PM0] = cword; if ((GTIA_PRIOR & 0xf) == 0xc) ANTIC_cl[C_PF0 | C_PM0123] = ANTIC_cl[C_PF0 | C_PM123] = ANTIC_cl[C_PF0 | C_PM023] = cword; } else ANTIC_cl[C_PF0 | C_PM01] = (ANTIC_cl[C_PF0 | C_PM0] = cword | ANTIC_cl[C_PM0]) | (ANTIC_cl[C_PF0 | C_PM1] = cword | ANTIC_cl[C_PM1]); } if ((GTIA_PRIOR & 0xf) >= 0xa) ANTIC_cl[C_PF0 | C_PM25] = cword; } break; case GTIA_OFFSET_COLPF1: GTIA_COLPF1 = byte &= 0xfe; GTIA_COLOUR_TO_WORD(cword,byte); ANTIC_cl[C_PF1] = cword; if ((GTIA_PRIOR & 1) == 0) { ANTIC_cl[C_PF1 | C_PM23] = ANTIC_cl[C_PF1 | C_PM3] = ANTIC_cl[C_PF1 | C_PM2] = cword; if ((GTIA_PRIOR & 3) == 0) { if (GTIA_PRIOR & 0xf) { ANTIC_cl[C_PF1 | C_PM01] = ANTIC_cl[C_PF1 | C_PM1] = ANTIC_cl[C_PF1 | C_PM0] = cword; if ((GTIA_PRIOR & 0xf) == 0xc) ANTIC_cl[C_PF1 | C_PM0123] = ANTIC_cl[C_PF1 | C_PM123] = ANTIC_cl[C_PF1 | C_PM023] = cword; } else ANTIC_cl[C_PF1 | C_PM01] = (ANTIC_cl[C_PF1 | C_PM0] = cword | ANTIC_cl[C_PM0]) | (ANTIC_cl[C_PF1 | C_PM1] = cword | ANTIC_cl[C_PM1]); } } ((UBYTE *)ANTIC_hires_lookup_l)[0x80] = ((UBYTE *)ANTIC_hires_lookup_l)[0x41] = (UBYTE) (ANTIC_hires_lookup_l[0x60] = cword & 0xf0f); break; case GTIA_OFFSET_COLPF2: GTIA_COLPF2 = byte &= 0xfe; GTIA_COLOUR_TO_WORD(cword,byte); ANTIC_cl[C_PF2] = cword; if (GTIA_PRIOR & 4) ANTIC_cl[C_PF2 | C_PM01] = ANTIC_cl[C_PF2 | C_PM1] = ANTIC_cl[C_PF2 | C_PM0] = cword; if ((GTIA_PRIOR & 9) == 0) { if (GTIA_PRIOR & 0xf) ANTIC_cl[C_PF2 | C_PM23] = ANTIC_cl[C_PF2 | C_PM3] = ANTIC_cl[C_PF2 | C_PM2] = cword; else ANTIC_cl[C_PF2 | C_PM23] = (ANTIC_cl[C_PF2 | C_PM2] = cword | ANTIC_cl[C_PM2]) | (ANTIC_cl[C_PF2 | C_PM3] = cword | ANTIC_cl[C_PM3]); } break; case GTIA_OFFSET_COLPF3: GTIA_COLPF3 = byte &= 0xfe; GTIA_COLOUR_TO_WORD(cword,byte); ANTIC_cl[C_PF3] = cword; if (GTIA_PRIOR & 4) ANTIC_cl[C_PF3 | C_PM01] = ANTIC_cl[C_PF3 | C_PM1] = ANTIC_cl[C_PF3 | C_PM0] = cword; if ((GTIA_PRIOR & 9) == 0) { if (GTIA_PRIOR & 0xf) ANTIC_cl[C_PF3 | C_PM23] = ANTIC_cl[C_PF3 | C_PM3] = ANTIC_cl[C_PF3 | C_PM2] = cword; else { ANTIC_cl[C_PF3 | C_PM25] = ANTIC_cl[C_PF2 | C_PM25] = ANTIC_cl[C_PM25] = ANTIC_cl[C_PF3 | C_PM2] = cword | ANTIC_cl[C_PM2]; ANTIC_cl[C_PF3 | C_PM35] = ANTIC_cl[C_PF2 | C_PM35] = ANTIC_cl[C_PM35] = ANTIC_cl[C_PF3 | C_PM3] = cword | ANTIC_cl[C_PM3]; ANTIC_cl[C_PF3 | C_PM235] = ANTIC_cl[C_PF2 | C_PM235] = ANTIC_cl[C_PM235] = ANTIC_cl[C_PF3 | C_PM23] = ANTIC_cl[C_PF3 | C_PM2] | ANTIC_cl[C_PF3 | C_PM3]; ANTIC_cl[C_PF0 | C_PM235] = ANTIC_cl[C_PF0 | C_PM35] = ANTIC_cl[C_PF0 | C_PM25] = ANTIC_cl[C_PF1 | C_PM235] = ANTIC_cl[C_PF1 | C_PM35] = ANTIC_cl[C_PF1 | C_PM25] = cword; } } break; case GTIA_OFFSET_COLPM0: GTIA_COLPM0 = byte &= 0xfe; GTIA_COLOUR_TO_WORD(cword,byte); ANTIC_cl[C_PM023] = ANTIC_cl[C_PM0] = cword; ANTIC_cl[C_PM0123] = ANTIC_cl[C_PM01] = cword2 = cword | ANTIC_cl[C_PM1]; if ((GTIA_PRIOR & 4) == 0) { ANTIC_cl[C_PF2 | C_PM0] = ANTIC_cl[C_PF3 | C_PM0] = cword; ANTIC_cl[C_PF2 | C_PM01] = ANTIC_cl[C_PF3 | C_PM01] = cword2; if ((GTIA_PRIOR & 0xc) == 0) { if (GTIA_PRIOR & 3) { ANTIC_cl[C_PF0 | C_PM0] = ANTIC_cl[C_PF1 | C_PM0] = cword; ANTIC_cl[C_PF0 | C_PM01] = ANTIC_cl[C_PF1 | C_PM01] = cword2; } else { ANTIC_cl[C_PF0 | C_PM0] = cword | ANTIC_cl[C_PF0]; ANTIC_cl[C_PF1 | C_PM0] = cword | ANTIC_cl[C_PF1]; ANTIC_cl[C_PF0 | C_PM01] = cword2 | ANTIC_cl[C_PF0]; ANTIC_cl[C_PF1 | C_PM01] = cword2 | ANTIC_cl[C_PF1]; } } } break; case GTIA_OFFSET_COLPM1: GTIA_COLPM1 = byte &= 0xfe; GTIA_COLOUR_TO_WORD(cword,byte); ANTIC_cl[C_PM123] = ANTIC_cl[C_PM1] = cword; ANTIC_cl[C_PM0123] = ANTIC_cl[C_PM01] = cword2 = cword | ANTIC_cl[C_PM0]; if ((GTIA_PRIOR & 4) == 0) { ANTIC_cl[C_PF2 | C_PM1] = ANTIC_cl[C_PF3 | C_PM1] = cword; ANTIC_cl[C_PF2 | C_PM01] = ANTIC_cl[C_PF3 | C_PM01] = cword2; if ((GTIA_PRIOR & 0xc) == 0) { if (GTIA_PRIOR & 3) { ANTIC_cl[C_PF0 | C_PM1] = ANTIC_cl[C_PF1 | C_PM1] = cword; ANTIC_cl[C_PF0 | C_PM01] = ANTIC_cl[C_PF1 | C_PM01] = cword2; } else { ANTIC_cl[C_PF0 | C_PM1] = cword | ANTIC_cl[C_PF0]; ANTIC_cl[C_PF1 | C_PM1] = cword | ANTIC_cl[C_PF1]; ANTIC_cl[C_PF0 | C_PM01] = cword2 | ANTIC_cl[C_PF0]; ANTIC_cl[C_PF1 | C_PM01] = cword2 | ANTIC_cl[C_PF1]; } } } break; case GTIA_OFFSET_COLPM2: GTIA_COLPM2 = byte &= 0xfe; GTIA_COLOUR_TO_WORD(cword,byte); ANTIC_cl[C_PM2] = cword; ANTIC_cl[C_PM23] = cword2 = cword | ANTIC_cl[C_PM3]; if (GTIA_PRIOR & 1) { ANTIC_cl[C_PF0 | C_PM2] = ANTIC_cl[C_PF1 | C_PM2] = cword; ANTIC_cl[C_PF0 | C_PM23] = ANTIC_cl[C_PF1 | C_PM23] = cword2; } if ((GTIA_PRIOR & 6) == 0) { if (GTIA_PRIOR & 9) { ANTIC_cl[C_PF2 | C_PM2] = ANTIC_cl[C_PF3 | C_PM2] = cword; ANTIC_cl[C_PF2 | C_PM23] = ANTIC_cl[C_PF3 | C_PM23] = cword2; } else { ANTIC_cl[C_PF2 | C_PM2] = cword | ANTIC_cl[C_PF2]; ANTIC_cl[C_PF3 | C_PM25] = ANTIC_cl[C_PF2 | C_PM25] = ANTIC_cl[C_PM25] = ANTIC_cl[C_PF3 | C_PM2] = cword | ANTIC_cl[C_PF3]; ANTIC_cl[C_PF2 | C_PM23] = cword2 | ANTIC_cl[C_PF2]; ANTIC_cl[C_PF3 | C_PM235] = ANTIC_cl[C_PF2 | C_PM235] = ANTIC_cl[C_PM235] = ANTIC_cl[C_PF3 | C_PM23] = cword2 | ANTIC_cl[C_PF3]; } } break; case GTIA_OFFSET_COLPM3: GTIA_COLPM3 = byte &= 0xfe; GTIA_COLOUR_TO_WORD(cword,byte); ANTIC_cl[C_PM3] = cword; ANTIC_cl[C_PM23] = cword2 = cword | ANTIC_cl[C_PM2]; if (GTIA_PRIOR & 1) { ANTIC_cl[C_PF0 | C_PM3] = ANTIC_cl[C_PF1 | C_PM3] = cword; ANTIC_cl[C_PF0 | C_PM23] = ANTIC_cl[C_PF1 | C_PM23] = cword2; } if ((GTIA_PRIOR & 6) == 0) { if (GTIA_PRIOR & 9) { ANTIC_cl[C_PF2 | C_PM3] = ANTIC_cl[C_PF3 | C_PM3] = cword; ANTIC_cl[C_PF2 | C_PM23] = ANTIC_cl[C_PF3 | C_PM23] = cword2; } else { ANTIC_cl[C_PF2 | C_PM3] = cword | ANTIC_cl[C_PF2]; ANTIC_cl[C_PF3 | C_PM35] = ANTIC_cl[C_PF2 | C_PM35] = ANTIC_cl[C_PM35] = ANTIC_cl[C_PF3 | C_PM3] = cword | ANTIC_cl[C_PF3]; ANTIC_cl[C_PF2 | C_PM23] = cword2 | ANTIC_cl[C_PF2]; ANTIC_cl[C_PF3 | C_PM235] = ANTIC_cl[C_PF2 | C_PM235] = ANTIC_cl[C_PM235] = ANTIC_cl[C_PF3 | C_PM23] = cword2 | ANTIC_cl[C_PF3]; } } break; #endif /* USE_COLOUR_TRANSLATION_TABLE */ case GTIA_OFFSET_GRAFM: GTIA_GRAFM = byte; UPDATE_PM_CYCLE_EXACT break; #ifdef NEW_CYCLE_EXACT #define CYCLE_EXACT_GRAFP(n) x = ANTIC_XPOS * 2 - 3;\ if (GTIA_HPOSP##n >= x) {\ /* hpos right of x */\ /* redraw */ \ UPDATE_PM_CYCLE_EXACT\ } #else #define CYCLE_EXACT_GRAFP(n) #endif /* NEW_CYCLE_EXACT */ #define DO_GRAFP(n) case GTIA_OFFSET_GRAFP##n:\ GTIA_GRAFP##n = byte;\ CYCLE_EXACT_GRAFP(n);\ break; DO_GRAFP(0) DO_GRAFP(1) DO_GRAFP(2) DO_GRAFP(3) case GTIA_OFFSET_HITCLR: GTIA_M0PL = GTIA_M1PL = GTIA_M2PL = GTIA_M3PL = 0; GTIA_P0PL = GTIA_P1PL = GTIA_P2PL = GTIA_P3PL = 0; PF0PM = PF1PM = PF2PM = PF3PM = 0; #ifdef NEW_CYCLE_EXACT hitclr_pos = ANTIC_XPOS * 2 - 37; collision_curpos = hitclr_pos; #endif break; /* TODO: cycle-exact missile HPOS, GRAF, SIZE */ /* this is only an approximation */ case GTIA_OFFSET_HPOSM0: GTIA_HPOSM0 = byte; hposm_ptr[0] = GTIA_pm_scanline + byte - 0x20; UPDATE_PM_CYCLE_EXACT break; case GTIA_OFFSET_HPOSM1: GTIA_HPOSM1 = byte; hposm_ptr[1] = GTIA_pm_scanline + byte - 0x20; UPDATE_PM_CYCLE_EXACT break; case GTIA_OFFSET_HPOSM2: GTIA_HPOSM2 = byte; hposm_ptr[2] = GTIA_pm_scanline + byte - 0x20; UPDATE_PM_CYCLE_EXACT break; case GTIA_OFFSET_HPOSM3: GTIA_HPOSM3 = byte; hposm_ptr[3] = GTIA_pm_scanline + byte - 0x20; UPDATE_PM_CYCLE_EXACT break; #ifdef NEW_CYCLE_EXACT #define CYCLE_EXACT_HPOSP(n) x = ANTIC_XPOS * 2 - 1;\ if (GTIA_HPOSP##n < x && byte < x) {\ /* case 1: both left of x */\ /* do nothing */\ }\ else if (GTIA_HPOSP##n >= x && byte >= x ) {\ /* case 2: both right of x */\ /* redraw, clearing first */\ UPDATE_PM_CYCLE_EXACT\ }\ else if (GTIA_HPOSP##n = x) {\ /* case 3: new value is right, old value is left */\ /* redraw without clearing first */\ /* note: a hack, we can get away with it unless another change occurs */\ /* before the original copy that wasn't erased due to changing */\ /* GTIA_pm_dirty is drawn */\ GTIA_pm_dirty = FALSE;\ UPDATE_PM_CYCLE_EXACT\ GTIA_pm_dirty = TRUE; /* can't trust that it was reset correctly */\ }\ else {\ /* case 4: new value is left, old value is right */\ /* remove old player and don't draw the new one */\ UBYTE save_graf = GTIA_GRAFP##n;\ GTIA_GRAFP##n = 0;\ UPDATE_PM_CYCLE_EXACT\ GTIA_GRAFP##n = save_graf;\ } #else #define CYCLE_EXACT_HPOSP(n) #endif /* NEW_CYCLE_EXACT */ #define DO_HPOSP(n) case GTIA_OFFSET_HPOSP##n: \ hposp_ptr[n] = GTIA_pm_scanline + byte - 0x20; \ if (byte >= 0x22) { \ if (byte > 0xbe) { \ if (byte >= 0xde) \ hposp_mask[n] = 0; \ else \ hposp_mask[n] = 0xffffffff >> (byte - 0xbe); \ } \ else \ hposp_mask[n] = 0xffffffff; \ } \ else if (byte > 2) \ hposp_mask[n] = 0xffffffff << (0x22 - byte); \ else \ hposp_mask[n] = 0; \ CYCLE_EXACT_HPOSP(n)\ GTIA_HPOSP##n = byte; \ break; DO_HPOSP(0) DO_HPOSP(1) DO_HPOSP(2) DO_HPOSP(3) /* TODO: cycle-exact size changes */ /* this is only an approximation */ case GTIA_OFFSET_SIZEM: GTIA_SIZEM = byte; global_sizem[0] = PM_Width[byte & 0x03]; global_sizem[1] = PM_Width[(byte & 0x0c) >> 2]; global_sizem[2] = PM_Width[(byte & 0x30) >> 4]; global_sizem[3] = PM_Width[(byte & 0xc0) >> 6]; UPDATE_PM_CYCLE_EXACT break; case GTIA_OFFSET_SIZEP0: GTIA_SIZEP0 = byte; grafp_ptr[0] = grafp_lookup[byte & 3]; UPDATE_PM_CYCLE_EXACT break; case GTIA_OFFSET_SIZEP1: GTIA_SIZEP1 = byte; grafp_ptr[1] = grafp_lookup[byte & 3]; UPDATE_PM_CYCLE_EXACT break; case GTIA_OFFSET_SIZEP2: GTIA_SIZEP2 = byte; grafp_ptr[2] = grafp_lookup[byte & 3]; UPDATE_PM_CYCLE_EXACT break; case GTIA_OFFSET_SIZEP3: GTIA_SIZEP3 = byte; grafp_ptr[3] = grafp_lookup[byte & 3]; UPDATE_PM_CYCLE_EXACT break; case GTIA_OFFSET_PRIOR: ANTIC_SetPrior(byte); GTIA_PRIOR = byte; if (byte & 0x40) setup_gtia9_11(); break; case GTIA_OFFSET_VDELAY: GTIA_VDELAY = byte; break; case GTIA_OFFSET_GRACTL: GTIA_GRACTL = byte; ANTIC_missile_gra_enabled = (byte & 0x01); ANTIC_player_gra_enabled = (byte & 0x02); ANTIC_player_flickering = ((ANTIC_player_dma_enabled | ANTIC_player_gra_enabled) == 0x02); ANTIC_missile_flickering = ((ANTIC_missile_dma_enabled | ANTIC_missile_gra_enabled) == 0x01); if ((byte & 4) == 0) GTIA_TRIG_latch[0] = GTIA_TRIG_latch[1] = GTIA_TRIG_latch[2] = GTIA_TRIG_latch[3] = 1; break; #endif /* defined(BASIC) || defined(CURSES_BASIC) */ } } /* State ------------------------------------------------------------------- */ #ifndef BASIC void GTIA_StateSave(void) { int next_console_value = 7; StateSav_SaveUBYTE(>IA_HPOSP0, 1); StateSav_SaveUBYTE(>IA_HPOSP1, 1); StateSav_SaveUBYTE(>IA_HPOSP2, 1); StateSav_SaveUBYTE(>IA_HPOSP3, 1); StateSav_SaveUBYTE(>IA_HPOSM0, 1); StateSav_SaveUBYTE(>IA_HPOSM1, 1); StateSav_SaveUBYTE(>IA_HPOSM2, 1); StateSav_SaveUBYTE(>IA_HPOSM3, 1); StateSav_SaveUBYTE(&PF0PM, 1); StateSav_SaveUBYTE(&PF1PM, 1); StateSav_SaveUBYTE(&PF2PM, 1); StateSav_SaveUBYTE(&PF3PM, 1); StateSav_SaveUBYTE(>IA_M0PL, 1); StateSav_SaveUBYTE(>IA_M1PL, 1); StateSav_SaveUBYTE(>IA_M2PL, 1); StateSav_SaveUBYTE(>IA_M3PL, 1); StateSav_SaveUBYTE(>IA_P0PL, 1); StateSav_SaveUBYTE(>IA_P1PL, 1); StateSav_SaveUBYTE(>IA_P2PL, 1); StateSav_SaveUBYTE(>IA_P3PL, 1); StateSav_SaveUBYTE(>IA_SIZEP0, 1); StateSav_SaveUBYTE(>IA_SIZEP1, 1); StateSav_SaveUBYTE(>IA_SIZEP2, 1); StateSav_SaveUBYTE(>IA_SIZEP3, 1); StateSav_SaveUBYTE(>IA_SIZEM, 1); StateSav_SaveUBYTE(>IA_GRAFP0, 1); StateSav_SaveUBYTE(>IA_GRAFP1, 1); StateSav_SaveUBYTE(>IA_GRAFP2, 1); StateSav_SaveUBYTE(>IA_GRAFP3, 1); StateSav_SaveUBYTE(>IA_GRAFM, 1); StateSav_SaveUBYTE(>IA_COLPM0, 1); StateSav_SaveUBYTE(>IA_COLPM1, 1); StateSav_SaveUBYTE(>IA_COLPM2, 1); StateSav_SaveUBYTE(>IA_COLPM3, 1); StateSav_SaveUBYTE(>IA_COLPF0, 1); StateSav_SaveUBYTE(>IA_COLPF1, 1); StateSav_SaveUBYTE(>IA_COLPF2, 1); StateSav_SaveUBYTE(>IA_COLPF3, 1); StateSav_SaveUBYTE(>IA_COLBK, 1); StateSav_SaveUBYTE(>IA_PRIOR, 1); StateSav_SaveUBYTE(>IA_VDELAY, 1); StateSav_SaveUBYTE(>IA_GRACTL, 1); StateSav_SaveUBYTE(&consol_mask, 1); StateSav_SaveINT(>IA_speaker, 1); StateSav_SaveINT(&next_console_value, 1); StateSav_SaveUBYTE(GTIA_TRIG_latch, 4); } void GTIA_StateRead(UBYTE version) { int next_console_value; /* ignored */ StateSav_ReadUBYTE(>IA_HPOSP0, 1); StateSav_ReadUBYTE(>IA_HPOSP1, 1); StateSav_ReadUBYTE(>IA_HPOSP2, 1); StateSav_ReadUBYTE(>IA_HPOSP3, 1); StateSav_ReadUBYTE(>IA_HPOSM0, 1); StateSav_ReadUBYTE(>IA_HPOSM1, 1); StateSav_ReadUBYTE(>IA_HPOSM2, 1); StateSav_ReadUBYTE(>IA_HPOSM3, 1); StateSav_ReadUBYTE(&PF0PM, 1); StateSav_ReadUBYTE(&PF1PM, 1); StateSav_ReadUBYTE(&PF2PM, 1); StateSav_ReadUBYTE(&PF3PM, 1); StateSav_ReadUBYTE(>IA_M0PL, 1); StateSav_ReadUBYTE(>IA_M1PL, 1); StateSav_ReadUBYTE(>IA_M2PL, 1); StateSav_ReadUBYTE(>IA_M3PL, 1); StateSav_ReadUBYTE(>IA_P0PL, 1); StateSav_ReadUBYTE(>IA_P1PL, 1); StateSav_ReadUBYTE(>IA_P2PL, 1); StateSav_ReadUBYTE(>IA_P3PL, 1); StateSav_ReadUBYTE(>IA_SIZEP0, 1); StateSav_ReadUBYTE(>IA_SIZEP1, 1); StateSav_ReadUBYTE(>IA_SIZEP2, 1); StateSav_ReadUBYTE(>IA_SIZEP3, 1); StateSav_ReadUBYTE(>IA_SIZEM, 1); StateSav_ReadUBYTE(>IA_GRAFP0, 1); StateSav_ReadUBYTE(>IA_GRAFP1, 1); StateSav_ReadUBYTE(>IA_GRAFP2, 1); StateSav_ReadUBYTE(>IA_GRAFP3, 1); StateSav_ReadUBYTE(>IA_GRAFM, 1); StateSav_ReadUBYTE(>IA_COLPM0, 1); StateSav_ReadUBYTE(>IA_COLPM1, 1); StateSav_ReadUBYTE(>IA_COLPM2, 1); StateSav_ReadUBYTE(>IA_COLPM3, 1); StateSav_ReadUBYTE(>IA_COLPF0, 1); StateSav_ReadUBYTE(>IA_COLPF1, 1); StateSav_ReadUBYTE(>IA_COLPF2, 1); StateSav_ReadUBYTE(>IA_COLPF3, 1); StateSav_ReadUBYTE(>IA_COLBK, 1); StateSav_ReadUBYTE(>IA_PRIOR, 1); StateSav_ReadUBYTE(>IA_VDELAY, 1); StateSav_ReadUBYTE(>IA_GRACTL, 1); StateSav_ReadUBYTE(&consol_mask, 1); StateSav_ReadINT(>IA_speaker, 1); StateSav_ReadINT(&next_console_value, 1); if (version >= 7) StateSav_ReadUBYTE(GTIA_TRIG_latch, 4); GTIA_PutByte(GTIA_OFFSET_HPOSP0, GTIA_HPOSP0); GTIA_PutByte(GTIA_OFFSET_HPOSP1, GTIA_HPOSP1); GTIA_PutByte(GTIA_OFFSET_HPOSP2, GTIA_HPOSP2); GTIA_PutByte(GTIA_OFFSET_HPOSP3, GTIA_HPOSP3); GTIA_PutByte(GTIA_OFFSET_HPOSM0, GTIA_HPOSM0); GTIA_PutByte(GTIA_OFFSET_HPOSM1, GTIA_HPOSM1); GTIA_PutByte(GTIA_OFFSET_HPOSM2, GTIA_HPOSM2); GTIA_PutByte(GTIA_OFFSET_HPOSM3, GTIA_HPOSM3); GTIA_PutByte(GTIA_OFFSET_SIZEP0, GTIA_SIZEP0); GTIA_PutByte(GTIA_OFFSET_SIZEP1, GTIA_SIZEP1); GTIA_PutByte(GTIA_OFFSET_SIZEP2, GTIA_SIZEP2); GTIA_PutByte(GTIA_OFFSET_SIZEP3, GTIA_SIZEP3); GTIA_PutByte(GTIA_OFFSET_SIZEM, GTIA_SIZEM); GTIA_PutByte(GTIA_OFFSET_GRAFP0, GTIA_GRAFP0); GTIA_PutByte(GTIA_OFFSET_GRAFP1, GTIA_GRAFP1); GTIA_PutByte(GTIA_OFFSET_GRAFP2, GTIA_GRAFP2); GTIA_PutByte(GTIA_OFFSET_GRAFP3, GTIA_GRAFP3); GTIA_PutByte(GTIA_OFFSET_GRAFM, GTIA_GRAFM); GTIA_PutByte(GTIA_OFFSET_COLPM0, GTIA_COLPM0); GTIA_PutByte(GTIA_OFFSET_COLPM1, GTIA_COLPM1); GTIA_PutByte(GTIA_OFFSET_COLPM2, GTIA_COLPM2); GTIA_PutByte(GTIA_OFFSET_COLPM3, GTIA_COLPM3); GTIA_PutByte(GTIA_OFFSET_COLPF0, GTIA_COLPF0); GTIA_PutByte(GTIA_OFFSET_COLPF1, GTIA_COLPF1); GTIA_PutByte(GTIA_OFFSET_COLPF2, GTIA_COLPF2); GTIA_PutByte(GTIA_OFFSET_COLPF3, GTIA_COLPF3); GTIA_PutByte(GTIA_OFFSET_COLBK, GTIA_COLBK); GTIA_PutByte(GTIA_OFFSET_PRIOR, GTIA_PRIOR); GTIA_PutByte(GTIA_OFFSET_GRACTL, GTIA_GRACTL); } #endif /* BASIC */