mirror of
https://github.com/wavemotion-dave/A5200DS.git
synced 2025-04-02 10:52:40 -04:00
712 lines
26 KiB
C
712 lines
26 KiB
C
/*
|
|
* gtia.c - GTIA chip emulation
|
|
*
|
|
* Copyright (C) 1995-1998 David Firth
|
|
* Copyright (C) 1998-2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
#include <nds.h>
|
|
#include "config.h"
|
|
#include "a5200utils.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include "atari.h"
|
|
#include "antic.h"
|
|
#include "gtia.h"
|
|
#include "input.h"
|
|
#include "pokeysnd.h"
|
|
|
|
/* GTIA Registers ---------------------------------------------------------- */
|
|
|
|
UBYTE M0PL __attribute__((section(".dtcm")));
|
|
UBYTE M1PL __attribute__((section(".dtcm")));
|
|
UBYTE M2PL __attribute__((section(".dtcm")));
|
|
UBYTE M3PL __attribute__((section(".dtcm")));
|
|
UBYTE P0PL __attribute__((section(".dtcm")));
|
|
UBYTE P1PL __attribute__((section(".dtcm")));
|
|
UBYTE P2PL __attribute__((section(".dtcm")));
|
|
UBYTE P3PL __attribute__((section(".dtcm")));
|
|
UBYTE HPOSP0 __attribute__((section(".dtcm")));
|
|
UBYTE HPOSP1 __attribute__((section(".dtcm")));
|
|
UBYTE HPOSP2 __attribute__((section(".dtcm")));
|
|
UBYTE HPOSP3 __attribute__((section(".dtcm")));
|
|
UBYTE HPOSM0 __attribute__((section(".dtcm")));
|
|
UBYTE HPOSM1 __attribute__((section(".dtcm")));
|
|
UBYTE HPOSM2 __attribute__((section(".dtcm")));
|
|
UBYTE HPOSM3 __attribute__((section(".dtcm")));
|
|
UBYTE SIZEP0 __attribute__((section(".dtcm")));
|
|
UBYTE SIZEP1 __attribute__((section(".dtcm")));
|
|
UBYTE SIZEP2 __attribute__((section(".dtcm")));
|
|
UBYTE SIZEP3 __attribute__((section(".dtcm")));
|
|
UBYTE SIZEM __attribute__((section(".dtcm")));
|
|
UBYTE GRAFP0 __attribute__((section(".dtcm")));
|
|
UBYTE GRAFP1 __attribute__((section(".dtcm")));
|
|
UBYTE GRAFP2 __attribute__((section(".dtcm")));
|
|
UBYTE GRAFP3 __attribute__((section(".dtcm")));
|
|
UBYTE GRAFM __attribute__((section(".dtcm")));
|
|
UBYTE COLPM0 __attribute__((section(".dtcm")));
|
|
UBYTE COLPM1 __attribute__((section(".dtcm")));
|
|
UBYTE COLPM2 __attribute__((section(".dtcm")));
|
|
UBYTE COLPM3 __attribute__((section(".dtcm")));
|
|
UBYTE COLPF0 __attribute__((section(".dtcm")));
|
|
UBYTE COLPF1 __attribute__((section(".dtcm")));
|
|
UBYTE COLPF2 __attribute__((section(".dtcm")));
|
|
UBYTE COLPF3 __attribute__((section(".dtcm")));
|
|
UBYTE COLBK __attribute__((section(".dtcm")));
|
|
UBYTE PRIOR __attribute__((section(".dtcm")));
|
|
UBYTE VDELAY __attribute__((section(".dtcm")));
|
|
UBYTE GRACTL __attribute__((section(".dtcm")));
|
|
UBYTE POTENA __attribute__((section(".dtcm")));
|
|
|
|
/* Internal GTIA state ----------------------------------------------------- */
|
|
|
|
UBYTE consol_index __attribute__((section(".dtcm"))) = 0;
|
|
UBYTE consol_table[3] __attribute__((section(".dtcm")));
|
|
UBYTE consol_mask __attribute__((section(".dtcm")));
|
|
UBYTE TRIG[4] __attribute__((section(".dtcm")));
|
|
UBYTE TRIG_latch[4] __attribute__((section(".dtcm")));
|
|
|
|
void set_prior(UBYTE byte); /* in antic.c */
|
|
|
|
/* Player/Missile stuff ---------------------------------------------------- */
|
|
|
|
/* change to 0x00 to disable collisions */
|
|
#define collisions_mask_missile_playfield 0x0f
|
|
#define collisions_mask_player_playfield 0x0f
|
|
#define collisions_mask_missile_player 0x0f
|
|
#define collisions_mask_player_player 0x0f
|
|
|
|
#define P1PL_T P1PL
|
|
#define P2PL_T P2PL
|
|
#define P3PL_T P3PL
|
|
#define M0PL_T M0PL
|
|
#define M1PL_T M1PL
|
|
#define M2PL_T M2PL
|
|
#define M3PL_T M3PL
|
|
|
|
extern UBYTE player_dma_enabled;
|
|
extern UBYTE missile_dma_enabled;
|
|
extern UBYTE player_gra_enabled;
|
|
extern UBYTE missile_gra_enabled;
|
|
extern UBYTE player_flickering;
|
|
extern UBYTE missile_flickering;
|
|
|
|
static UBYTE *hposp_ptr[4] __attribute__((section(".dtcm")));
|
|
static UBYTE *hposm_ptr[4] __attribute__((section(".dtcm")));
|
|
static ULONG hposp_mask[4] __attribute__((section(".dtcm")));
|
|
|
|
static ULONG *grafp_ptr[4] __attribute__((section(".dtcm")));
|
|
static UBYTE global_sizem[4] __attribute__((section(".dtcm")));
|
|
static UBYTE PM_Width[4] __attribute__((section(".dtcm"))) = {1, 2, 1, 4};
|
|
|
|
ULONG *grafp_lookup = (ULONG*)0x068A0000; // Using 4K here for lookup table... ULONG[4][256]
|
|
|
|
/* Meaning of bits in 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 pm_scanline[ATARI_WIDTH / 2 + 8] __attribute__((section(".dtcm"))); /* there's a byte for every *pair* of pixels */
|
|
UBYTE pm_dirty __attribute__((section(".dtcm"))) = 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
|
|
|
|
extern UWORD cl_lookup[128];
|
|
|
|
#define PF0PM (*(UBYTE *) &cl_lookup[C_PF0 | C_COLLS])
|
|
#define PF1PM (*(UBYTE *) &cl_lookup[C_PF1 | C_COLLS])
|
|
#define PF2PM (*(UBYTE *) &cl_lookup[C_PF2 | C_COLLS])
|
|
#define PF3PM (*(UBYTE *) &cl_lookup[C_PF3 | C_COLLS])
|
|
|
|
/* Colours ----------------------------------------------------------------- */
|
|
|
|
extern UWORD hires_lookup_l[128];
|
|
extern ULONG lookup_gtia9[16];
|
|
extern ULONG lookup_gtia11[16];
|
|
|
|
void setup_gtia9_11(void) {
|
|
int i;
|
|
ULONG count9 = 0;
|
|
ULONG count11 = 0;
|
|
lookup_gtia11[0] = lookup_gtia9[0] & 0xf0f0f0f0;
|
|
for (i = 1; i < 16; i++) {
|
|
lookup_gtia9[i] = lookup_gtia9[0] | (count9 += 0x01010101);
|
|
lookup_gtia11[i] = lookup_gtia9[0] | (count11 += 0x10101010);
|
|
}
|
|
}
|
|
|
|
|
|
/* Initialization ---------------------------------------------------------- */
|
|
|
|
void GTIA_Initialise(void)
|
|
{
|
|
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*256+i] = grafp_lookup[0*256+i] = grafp1;
|
|
grafp_lookup[1*256+i] = grafp2;
|
|
grafp_lookup[3*256+i] = grafp4;
|
|
}
|
|
memset(cl_lookup, COLOUR_BLACK, sizeof(cl_lookup));
|
|
for (i = 0; i < 32; i++)
|
|
GTIA_PutByte((UWORD) i, 0);
|
|
|
|
POTENA=0;
|
|
}
|
|
|
|
#define update_partial_pmpl_colls()
|
|
|
|
/* Prepare PMG scanline ---------------------------------------------------- */
|
|
|
|
ITCM_CODE void new_pm_scanline(void)
|
|
{
|
|
/* Clear if necessary */
|
|
if (pm_dirty) {
|
|
memset(pm_scanline, 0, ATARI_WIDTH / 2);
|
|
pm_dirty = FALSE;
|
|
}
|
|
|
|
/* Draw Players */
|
|
|
|
#define DO_PLAYER(n) if (GRAFP##n) { \
|
|
ULONG grafp = grafp_ptr[n][GRAFP##n] & hposp_mask[n]; \
|
|
if (grafp) { \
|
|
UBYTE *ptr = hposp_ptr[n]; \
|
|
pm_dirty = TRUE; \
|
|
do { \
|
|
if (grafp & 1) \
|
|
P##n##PL_T |= *ptr |= 1 << n; \
|
|
ptr++; \
|
|
grafp >>= 1; \
|
|
} while (grafp); \
|
|
} \
|
|
}
|
|
|
|
/* optimized DO_PLAYER(0): pm_scanline is clear and P0PL is unused */
|
|
if (GRAFP0) {
|
|
ULONG grafp = grafp_ptr[0][GRAFP0] & hposp_mask[0];
|
|
if (grafp) {
|
|
UBYTE *ptr = hposp_ptr[0];
|
|
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 (GRAFM & m) { \
|
|
int j = global_sizem[n]; \
|
|
UBYTE *ptr = hposm_ptr[n]; \
|
|
if (GRAFM & r) { \
|
|
if (GRAFM & l) \
|
|
j <<= 1; \
|
|
} \
|
|
else \
|
|
ptr += j; \
|
|
if (ptr < pm_scanline + 2) { \
|
|
j += ptr - pm_scanline - 2; \
|
|
ptr = pm_scanline + 2; \
|
|
} \
|
|
else if (ptr + j > pm_scanline + ATARI_WIDTH / 2 - 2) \
|
|
j = pm_scanline + ATARI_WIDTH / 2 - 2 - ptr; \
|
|
if (j > 0) \
|
|
do \
|
|
M##n##PL_T |= *ptr++ |= p; \
|
|
while (--j); \
|
|
}
|
|
|
|
if (GRAFM) {
|
|
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)
|
|
}
|
|
}
|
|
|
|
/* GTIA registers ---------------------------------------------------------- */
|
|
|
|
void GTIA_Frame(void)
|
|
{
|
|
int consol = key_consol | 0x08;
|
|
|
|
consol_table[0] = consol;
|
|
consol_table[1] = consol_table[2] &= consol;
|
|
|
|
if (GRACTL & 4) {
|
|
TRIG_latch[0] &= TRIG[0];
|
|
TRIG_latch[1] &= TRIG[1];
|
|
TRIG_latch[2] &= TRIG[2];
|
|
TRIG_latch[3] &= TRIG[3];
|
|
}
|
|
}
|
|
|
|
UBYTE GTIA_GetByte(UWORD addr)
|
|
{
|
|
switch (addr & 0x1f) {
|
|
case _M0PF:
|
|
return (((PF0PM & 0x10) >> 4)
|
|
+ ((PF1PM & 0x10) >> 3)
|
|
+ ((PF2PM & 0x10) >> 2)
|
|
+ ((PF3PM & 0x10) >> 1)) & collisions_mask_missile_playfield;
|
|
case _M1PF:
|
|
return (((PF0PM & 0x20) >> 5)
|
|
+ ((PF1PM & 0x20) >> 4)
|
|
+ ((PF2PM & 0x20) >> 3)
|
|
+ ((PF3PM & 0x20) >> 2)) & collisions_mask_missile_playfield;
|
|
case _M2PF:
|
|
return (((PF0PM & 0x40) >> 6)
|
|
+ ((PF1PM & 0x40) >> 5)
|
|
+ ((PF2PM & 0x40) >> 4)
|
|
+ ((PF3PM & 0x40) >> 3)) & collisions_mask_missile_playfield;
|
|
case _M3PF:
|
|
return (((PF0PM & 0x80) >> 7)
|
|
+ ((PF1PM & 0x80) >> 6)
|
|
+ ((PF2PM & 0x80) >> 5)
|
|
+ ((PF3PM & 0x80) >> 4)) & collisions_mask_missile_playfield;
|
|
case _P0PF:
|
|
return ((PF0PM & 0x01)
|
|
+ ((PF1PM & 0x01) << 1)
|
|
+ ((PF2PM & 0x01) << 2)
|
|
+ ((PF3PM & 0x01) << 3)) & collisions_mask_player_playfield;
|
|
case _P1PF:
|
|
return (((PF0PM & 0x02) >> 1)
|
|
+ (PF1PM & 0x02)
|
|
+ ((PF2PM & 0x02) << 1)
|
|
+ ((PF3PM & 0x02) << 2)) & collisions_mask_player_playfield;
|
|
case _P2PF:
|
|
return (((PF0PM & 0x04) >> 2)
|
|
+ ((PF1PM & 0x04) >> 1)
|
|
+ (PF2PM & 0x04)
|
|
+ ((PF3PM & 0x04) << 1)) & collisions_mask_player_playfield;
|
|
case _P3PF:
|
|
return (((PF0PM & 0x08) >> 3)
|
|
+ ((PF1PM & 0x08) >> 2)
|
|
+ ((PF2PM & 0x08) >> 1)
|
|
+ (PF3PM & 0x08)) & collisions_mask_player_playfield;
|
|
case _M0PL:
|
|
update_partial_pmpl_colls();
|
|
return M0PL & collisions_mask_missile_player;
|
|
case _M1PL:
|
|
update_partial_pmpl_colls();
|
|
return M1PL & collisions_mask_missile_player;
|
|
case _M2PL:
|
|
update_partial_pmpl_colls();
|
|
return M2PL & collisions_mask_missile_player;
|
|
case _M3PL:
|
|
update_partial_pmpl_colls();
|
|
return M3PL & collisions_mask_missile_player;
|
|
case _P0PL:
|
|
update_partial_pmpl_colls();
|
|
return (((P1PL & 0x01) << 1) /* mask in player 1 */
|
|
+ ((P2PL & 0x01) << 2) /* mask in player 2 */
|
|
+ ((P3PL & 0x01) << 3)) /* mask in player 3 */
|
|
& collisions_mask_player_player;
|
|
case _P1PL:
|
|
update_partial_pmpl_colls();
|
|
return ((P1PL & 0x01) /* mask in player 0 */
|
|
+ ((P2PL & 0x02) << 1) /* mask in player 2 */
|
|
+ ((P3PL & 0x02) << 2)) /* mask in player 3 */
|
|
& collisions_mask_player_player;
|
|
case _P2PL:
|
|
update_partial_pmpl_colls();
|
|
return ((P2PL & 0x03) /* mask in player 0 and 1 */
|
|
+ ((P3PL & 0x04) << 1)) /* mask in player 3 */
|
|
& collisions_mask_player_player;
|
|
case _P3PL:
|
|
update_partial_pmpl_colls();
|
|
return (P3PL & 0x07) /* mask in player 0,1, and 2 */
|
|
& collisions_mask_player_player;
|
|
case _TRIG0:
|
|
return TRIG[0] & TRIG_latch[0];
|
|
case _TRIG1:
|
|
return TRIG[1] & TRIG_latch[1];
|
|
case _TRIG2:
|
|
return TRIG[2] & TRIG_latch[2];
|
|
case _TRIG3:
|
|
return TRIG[3] & TRIG_latch[3];
|
|
case _PAL:
|
|
return 0x0f; // Force NTSC
|
|
case _CONSOL:
|
|
{
|
|
UBYTE byte = consol_table[consol_index] & consol_mask;
|
|
if (consol_index > 0) {
|
|
consol_index--;
|
|
}
|
|
return byte;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return 0xf;
|
|
}
|
|
|
|
#define UPDATE_PM_CYCLE_EXACT {}
|
|
void GTIA_PutByte(UWORD addr, UBYTE byte)
|
|
{
|
|
UWORD cword;
|
|
UWORD cword2;
|
|
|
|
switch (addr & 0x1f)
|
|
{
|
|
case _CONSOL:
|
|
consol_mask = (~byte) & 0x0f;
|
|
POTENA = byte & 0x04;
|
|
break;
|
|
|
|
case _COLBK:
|
|
COLBK = byte &= 0xfe;
|
|
COLOUR_TO_WORD(cword,byte);
|
|
cl_lookup[C_BAK] = cword;
|
|
if (cword != (UWORD) (lookup_gtia9[0]) ) {
|
|
lookup_gtia9[0] = cword + (cword << 16);
|
|
if (PRIOR & 0x40)
|
|
setup_gtia9_11();
|
|
}
|
|
break;
|
|
case _COLPF0:
|
|
COLPF0 = byte &= 0xfe;
|
|
COLOUR_TO_WORD(cword,byte);
|
|
cl_lookup[C_PF0] = cword;
|
|
if ((PRIOR & 1) == 0) {
|
|
cl_lookup[C_PF0 | C_PM23] = cl_lookup[C_PF0 | C_PM3] = cl_lookup[C_PF0 | C_PM2] = cword;
|
|
if ((PRIOR & 3) == 0) {
|
|
if (PRIOR & 0xf) {
|
|
cl_lookup[C_PF0 | C_PM01] = cl_lookup[C_PF0 | C_PM1] = cl_lookup[C_PF0 | C_PM0] = cword;
|
|
if ((PRIOR & 0xf) == 0xc)
|
|
cl_lookup[C_PF0 | C_PM0123] = cl_lookup[C_PF0 | C_PM123] = cl_lookup[C_PF0 | C_PM023] = cword;
|
|
}
|
|
else
|
|
cl_lookup[C_PF0 | C_PM01] = (cl_lookup[C_PF0 | C_PM0] = cword | cl_lookup[C_PM0]) | (cl_lookup[C_PF0 | C_PM1] = cword | cl_lookup[C_PM1]);
|
|
}
|
|
if ((PRIOR & 0xf) >= 0xa)
|
|
cl_lookup[C_PF0 | C_PM25] = cword;
|
|
}
|
|
break;
|
|
case _COLPF1:
|
|
COLPF1 = byte &= 0xfe;
|
|
COLOUR_TO_WORD(cword,byte);
|
|
cl_lookup[C_PF1] = cword;
|
|
if ((PRIOR & 1) == 0) {
|
|
cl_lookup[C_PF1 | C_PM23] = cl_lookup[C_PF1 | C_PM3] = cl_lookup[C_PF1 | C_PM2] = cword;
|
|
if ((PRIOR & 3) == 0) {
|
|
if (PRIOR & 0xf) {
|
|
cl_lookup[C_PF1 | C_PM01] = cl_lookup[C_PF1 | C_PM1] = cl_lookup[C_PF1 | C_PM0] = cword;
|
|
if ((PRIOR & 0xf) == 0xc)
|
|
cl_lookup[C_PF1 | C_PM0123] = cl_lookup[C_PF1 | C_PM123] = cl_lookup[C_PF1 | C_PM023] = cword;
|
|
}
|
|
else
|
|
cl_lookup[C_PF1 | C_PM01] = (cl_lookup[C_PF1 | C_PM0] = cword | cl_lookup[C_PM0]) | (cl_lookup[C_PF1 | C_PM1] = cword | cl_lookup[C_PM1]);
|
|
}
|
|
}
|
|
((UBYTE *)hires_lookup_l)[0x80] = ((UBYTE *)hires_lookup_l)[0x41] = (UBYTE)
|
|
(hires_lookup_l[0x60] = cword & 0xf0f);
|
|
break;
|
|
case _COLPF2:
|
|
COLPF2 = byte &= 0xfe;
|
|
COLOUR_TO_WORD(cword,byte);
|
|
cl_lookup[C_PF2] = cword;
|
|
if (PRIOR & 4)
|
|
cl_lookup[C_PF2 | C_PM01] = cl_lookup[C_PF2 | C_PM1] = cl_lookup[C_PF2 | C_PM0] = cword;
|
|
if ((PRIOR & 9) == 0) {
|
|
if (PRIOR & 0xf)
|
|
cl_lookup[C_PF2 | C_PM23] = cl_lookup[C_PF2 | C_PM3] = cl_lookup[C_PF2 | C_PM2] = cword;
|
|
else
|
|
cl_lookup[C_PF2 | C_PM23] = (cl_lookup[C_PF2 | C_PM2] = cword | cl_lookup[C_PM2]) | (cl_lookup[C_PF2 | C_PM3] = cword | cl_lookup[C_PM3]);
|
|
}
|
|
break;
|
|
case _COLPF3:
|
|
COLPF3 = byte &= 0xfe;
|
|
COLOUR_TO_WORD(cword,byte);
|
|
cl_lookup[C_PF3] = cword;
|
|
if (PRIOR & 4)
|
|
cl_lookup[C_PF3 | C_PM01] = cl_lookup[C_PF3 | C_PM1] = cl_lookup[C_PF3 | C_PM0] = cword;
|
|
if ((PRIOR & 9) == 0) {
|
|
if (PRIOR & 0xf)
|
|
cl_lookup[C_PF3 | C_PM23] = cl_lookup[C_PF3 | C_PM3] = cl_lookup[C_PF3 | C_PM2] = cword;
|
|
else {
|
|
cl_lookup[C_PF3 | C_PM25] = cl_lookup[C_PF2 | C_PM25] = cl_lookup[C_PM25] = cl_lookup[C_PF3 | C_PM2] = cword | cl_lookup[C_PM2];
|
|
cl_lookup[C_PF3 | C_PM35] = cl_lookup[C_PF2 | C_PM35] = cl_lookup[C_PM35] = cl_lookup[C_PF3 | C_PM3] = cword | cl_lookup[C_PM3];
|
|
cl_lookup[C_PF3 | C_PM235] = cl_lookup[C_PF2 | C_PM235] = cl_lookup[C_PM235] = cl_lookup[C_PF3 | C_PM23] = cl_lookup[C_PF3 | C_PM2] | cl_lookup[C_PF3 | C_PM3];
|
|
cl_lookup[C_PF0 | C_PM235] = cl_lookup[C_PF0 | C_PM35] = cl_lookup[C_PF0 | C_PM25] =
|
|
cl_lookup[C_PF1 | C_PM235] = cl_lookup[C_PF1 | C_PM35] = cl_lookup[C_PF1 | C_PM25] = cword;
|
|
}
|
|
}
|
|
break;
|
|
case _COLPM0:
|
|
COLPM0 = byte &= 0xfe;
|
|
COLOUR_TO_WORD(cword,byte);
|
|
cl_lookup[C_PM023] = cl_lookup[C_PM0] = cword;
|
|
cl_lookup[C_PM0123] = cl_lookup[C_PM01] = cword2 = cword | cl_lookup[C_PM1];
|
|
if ((PRIOR & 4) == 0) {
|
|
cl_lookup[C_PF2 | C_PM0] = cl_lookup[C_PF3 | C_PM0] = cword;
|
|
cl_lookup[C_PF2 | C_PM01] = cl_lookup[C_PF3 | C_PM01] = cword2;
|
|
if ((PRIOR & 0xc) == 0) {
|
|
if (PRIOR & 3) {
|
|
cl_lookup[C_PF0 | C_PM0] = cl_lookup[C_PF1 | C_PM0] = cword;
|
|
cl_lookup[C_PF0 | C_PM01] = cl_lookup[C_PF1 | C_PM01] = cword2;
|
|
}
|
|
else {
|
|
cl_lookup[C_PF0 | C_PM0] = cword | cl_lookup[C_PF0];
|
|
cl_lookup[C_PF1 | C_PM0] = cword | cl_lookup[C_PF1];
|
|
cl_lookup[C_PF0 | C_PM01] = cword2 | cl_lookup[C_PF0];
|
|
cl_lookup[C_PF1 | C_PM01] = cword2 | cl_lookup[C_PF1];
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case _COLPM1:
|
|
COLPM1 = byte &= 0xfe;
|
|
COLOUR_TO_WORD(cword,byte);
|
|
cl_lookup[C_PM123] = cl_lookup[C_PM1] = cword;
|
|
cl_lookup[C_PM0123] = cl_lookup[C_PM01] = cword2 = cword | cl_lookup[C_PM0];
|
|
if ((PRIOR & 4) == 0) {
|
|
cl_lookup[C_PF2 | C_PM1] = cl_lookup[C_PF3 | C_PM1] = cword;
|
|
cl_lookup[C_PF2 | C_PM01] = cl_lookup[C_PF3 | C_PM01] = cword2;
|
|
if ((PRIOR & 0xc) == 0) {
|
|
if (PRIOR & 3) {
|
|
cl_lookup[C_PF0 | C_PM1] = cl_lookup[C_PF1 | C_PM1] = cword;
|
|
cl_lookup[C_PF0 | C_PM01] = cl_lookup[C_PF1 | C_PM01] = cword2;
|
|
}
|
|
else {
|
|
cl_lookup[C_PF0 | C_PM1] = cword | cl_lookup[C_PF0];
|
|
cl_lookup[C_PF1 | C_PM1] = cword | cl_lookup[C_PF1];
|
|
cl_lookup[C_PF0 | C_PM01] = cword2 | cl_lookup[C_PF0];
|
|
cl_lookup[C_PF1 | C_PM01] = cword2 | cl_lookup[C_PF1];
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case _COLPM2:
|
|
COLPM2 = byte &= 0xfe;
|
|
COLOUR_TO_WORD(cword,byte);
|
|
cl_lookup[C_PM2] = cword;
|
|
cl_lookup[C_PM23] = cword2 = cword | cl_lookup[C_PM3];
|
|
if (PRIOR & 1) {
|
|
cl_lookup[C_PF0 | C_PM2] = cl_lookup[C_PF1 | C_PM2] = cword;
|
|
cl_lookup[C_PF0 | C_PM23] = cl_lookup[C_PF1 | C_PM23] = cword2;
|
|
}
|
|
if ((PRIOR & 6) == 0) {
|
|
if (PRIOR & 9) {
|
|
cl_lookup[C_PF2 | C_PM2] = cl_lookup[C_PF3 | C_PM2] = cword;
|
|
cl_lookup[C_PF2 | C_PM23] = cl_lookup[C_PF3 | C_PM23] = cword2;
|
|
}
|
|
else {
|
|
cl_lookup[C_PF2 | C_PM2] = cword | cl_lookup[C_PF2];
|
|
cl_lookup[C_PF3 | C_PM25] = cl_lookup[C_PF2 | C_PM25] = cl_lookup[C_PM25] = cl_lookup[C_PF3 | C_PM2] = cword | cl_lookup[C_PF3];
|
|
cl_lookup[C_PF2 | C_PM23] = cword2 | cl_lookup[C_PF2];
|
|
cl_lookup[C_PF3 | C_PM235] = cl_lookup[C_PF2 | C_PM235] = cl_lookup[C_PM235] = cl_lookup[C_PF3 | C_PM23] = cword2 | cl_lookup[C_PF3];
|
|
}
|
|
}
|
|
break;
|
|
case _COLPM3:
|
|
COLPM3 = byte &= 0xfe;
|
|
COLOUR_TO_WORD(cword,byte);
|
|
cl_lookup[C_PM3] = cword;
|
|
cl_lookup[C_PM23] = cword2 = cword | cl_lookup[C_PM2];
|
|
if (PRIOR & 1) {
|
|
cl_lookup[C_PF0 | C_PM3] = cl_lookup[C_PF1 | C_PM3] = cword;
|
|
cl_lookup[C_PF0 | C_PM23] = cl_lookup[C_PF1 | C_PM23] = cword2;
|
|
}
|
|
if ((PRIOR & 6) == 0) {
|
|
if (PRIOR & 9) {
|
|
cl_lookup[C_PF2 | C_PM3] = cl_lookup[C_PF3 | C_PM3] = cword;
|
|
cl_lookup[C_PF2 | C_PM23] = cl_lookup[C_PF3 | C_PM23] = cword2;
|
|
}
|
|
else {
|
|
cl_lookup[C_PF2 | C_PM3] = cword | cl_lookup[C_PF2];
|
|
cl_lookup[C_PF3 | C_PM35] = cl_lookup[C_PF2 | C_PM35] = cl_lookup[C_PM35] = cl_lookup[C_PF3 | C_PM3] = cword | cl_lookup[C_PF3];
|
|
cl_lookup[C_PF2 | C_PM23] = cword2 | cl_lookup[C_PF2];
|
|
cl_lookup[C_PF3 | C_PM235] = cl_lookup[C_PF2 | C_PM235] = cl_lookup[C_PM235] = cl_lookup[C_PF3 | C_PM23] = cword2 | cl_lookup[C_PF3];
|
|
}
|
|
}
|
|
break;
|
|
|
|
case _GRAFM:
|
|
GRAFM = byte;
|
|
UPDATE_PM_CYCLE_EXACT
|
|
break;
|
|
|
|
#define CYCLE_EXACT_GRAFP(n)
|
|
|
|
#define DO_GRAFP(n) case _GRAFP##n:\
|
|
GRAFP##n = byte;\
|
|
CYCLE_EXACT_GRAFP(n);\
|
|
break;
|
|
|
|
DO_GRAFP(0)
|
|
DO_GRAFP(1)
|
|
DO_GRAFP(2)
|
|
DO_GRAFP(3)
|
|
|
|
case _HITCLR:
|
|
M0PL = M1PL = M2PL = M3PL = 0;
|
|
P0PL = P1PL = P2PL = P3PL = 0;
|
|
PF0PM = PF1PM = PF2PM = PF3PM = 0;
|
|
break;
|
|
/* TODO: cycle-exact missile HPOS, GRAF, SIZE */
|
|
/* this is only an approximation */
|
|
case _HPOSM0:
|
|
HPOSM0 = byte;
|
|
hposm_ptr[0] = pm_scanline + byte - 0x20;
|
|
UPDATE_PM_CYCLE_EXACT
|
|
break;
|
|
case _HPOSM1:
|
|
HPOSM1 = byte;
|
|
hposm_ptr[1] = pm_scanline + byte - 0x20;
|
|
UPDATE_PM_CYCLE_EXACT
|
|
break;
|
|
case _HPOSM2:
|
|
HPOSM2 = byte;
|
|
hposm_ptr[2] = pm_scanline + byte - 0x20;
|
|
UPDATE_PM_CYCLE_EXACT
|
|
break;
|
|
case _HPOSM3:
|
|
HPOSM3 = byte;
|
|
hposm_ptr[3] = pm_scanline + byte - 0x20;
|
|
UPDATE_PM_CYCLE_EXACT
|
|
break;
|
|
|
|
#define CYCLE_EXACT_HPOSP(n)
|
|
|
|
#define DO_HPOSP(n) case _HPOSP##n: \
|
|
hposp_ptr[n] = 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)\
|
|
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 _SIZEM:
|
|
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 _SIZEP0:
|
|
SIZEP0 = byte;
|
|
grafp_ptr[0] = &grafp_lookup[(byte & 3)*256];
|
|
UPDATE_PM_CYCLE_EXACT
|
|
break;
|
|
case _SIZEP1:
|
|
SIZEP1 = byte;
|
|
grafp_ptr[1] = &grafp_lookup[(byte & 3)*256];
|
|
UPDATE_PM_CYCLE_EXACT
|
|
break;
|
|
case _SIZEP2:
|
|
SIZEP2 = byte;
|
|
grafp_ptr[2] = &grafp_lookup[(byte & 3)*256];
|
|
UPDATE_PM_CYCLE_EXACT
|
|
break;
|
|
case _SIZEP3:
|
|
SIZEP3 = byte;
|
|
grafp_ptr[3] = &grafp_lookup[(byte & 3)*256];
|
|
UPDATE_PM_CYCLE_EXACT
|
|
break;
|
|
case _PRIOR:
|
|
set_prior(byte);
|
|
PRIOR = byte;
|
|
if (byte & 0x40)
|
|
setup_gtia9_11();
|
|
break;
|
|
case _VDELAY:
|
|
VDELAY = byte;
|
|
break;
|
|
case _GRACTL:
|
|
GRACTL = byte;
|
|
missile_gra_enabled = (byte & 0x01);
|
|
player_gra_enabled = (byte & 0x02);
|
|
player_flickering = ((player_dma_enabled | player_gra_enabled) == 0x02);
|
|
missile_flickering = ((missile_dma_enabled | missile_gra_enabled) == 0x01);
|
|
if ((byte & 4) == 0)
|
|
TRIG_latch[0] = TRIG_latch[1] = TRIG_latch[2] = TRIG_latch[3] = 1;
|
|
break;
|
|
}
|
|
}
|