diff options
Diffstat (limited to 'src/mame/video/gtia.c')
-rw-r--r-- | src/mame/video/gtia.c | 1135 |
1 files changed, 1135 insertions, 0 deletions
diff --git a/src/mame/video/gtia.c b/src/mame/video/gtia.c new file mode 100644 index 00000000000..1ac255bd66c --- /dev/null +++ b/src/mame/video/gtia.c @@ -0,0 +1,1135 @@ +/*************************************************************************** + + Atari 400/800 + + GTIA graphics television interface adapter + + Juergen Buchmueller, June 1998 + +***************************************************************************/ + +#include "driver.h" +#include "cpu/m6502/m6502.h" +#include "includes/atari.h" +#include "video/gtia.h" + +gtia_struct gtia; + +#define P0 0x01 +#define P1 0x02 +#define P2 0x04 +#define P3 0x08 +#define M0 0x10 +#define M1 0x20 +#define M2 0x40 +#define M3 0x80 + +#define CHECK_GRACTL 0 +#define VERBOSE 0 + +static void gtia_reset(running_machine *machine); +static void gtia_state(void); +static void gtia_state_postload(void); + +/********************************************** + * split a color into hue and luminance values + **********************************************/ +#define SPLIT_HUE_LUM(data,hue,lum) \ + hue = (data & HUE); lum = (data & LUM) + +/********************************************** + * set both color clocks equal for one color + **********************************************/ +#define SETCOL_B(o,d) \ + antic.color_lookup[o] = (Machine->remapped_colortable[d] << 8) | Machine->remapped_colortable[d] + +/********************************************** + * set left color clock for one color + **********************************************/ +#define SETCOL_L(o,d) \ + *((UINT8*)&antic.color_lookup[o] + 0) = Machine->remapped_colortable[d] + +/********************************************** + * set right color clock for one color + **********************************************/ +#define SETCOL_R(o,d) \ + *((UINT8*)&antic.color_lookup[o] + 1) = Machine->remapped_colortable[d] + + + +/************************************* + * + * Initialization/Reset + * + *************************************/ + +void gtia_init(const gtia_interface *intf) +{ + memset(>ia, 0, sizeof(gtia)); + gtia.intf = *intf; + + add_reset_callback(Machine, gtia_reset); + + /* state saves */ + gtia_state(); +} + + + +static void gtia_state(void) +{ + state_save_register_global(gtia.r.m0pf); + state_save_register_global(gtia.r.m1pf); + state_save_register_global(gtia.r.m2pf); + state_save_register_global(gtia.r.m3pf); + state_save_register_global(gtia.r.p0pf); + state_save_register_global(gtia.r.p1pf); + state_save_register_global(gtia.r.p2pf); + state_save_register_global(gtia.r.p3pf); + state_save_register_global(gtia.r.m0pl); + state_save_register_global(gtia.r.m1pl); + state_save_register_global(gtia.r.m2pl); + state_save_register_global(gtia.r.m3pl); + state_save_register_global(gtia.r.p0pl); + state_save_register_global(gtia.r.p1pl); + state_save_register_global(gtia.r.p2pl); + state_save_register_global(gtia.r.p3pl); + state_save_register_global_array(gtia.r.but); + state_save_register_global(gtia.r.pal); + state_save_register_global(gtia.r.gtia15); + state_save_register_global(gtia.r.gtia16); + state_save_register_global(gtia.r.gtia17); + state_save_register_global(gtia.r.gtia18); + state_save_register_global(gtia.r.gtia19); + state_save_register_global(gtia.r.gtia1a); + state_save_register_global(gtia.r.gtia1b); + state_save_register_global(gtia.r.gtia1c); + state_save_register_global(gtia.r.gtia1d); + state_save_register_global(gtia.r.gtia1e); + state_save_register_global(gtia.r.cons); + state_save_register_global(gtia.w.hposp0); + state_save_register_global(gtia.w.hposp1); + state_save_register_global(gtia.w.hposp2); + state_save_register_global(gtia.w.hposp3); + state_save_register_global(gtia.w.hposm0); + state_save_register_global(gtia.w.hposm1); + state_save_register_global(gtia.w.hposm2); + state_save_register_global(gtia.w.hposm3); + state_save_register_global(gtia.w.sizep0); + state_save_register_global(gtia.w.sizep1); + state_save_register_global(gtia.w.sizep2); + state_save_register_global(gtia.w.sizep3); + state_save_register_global(gtia.w.sizem); + state_save_register_global_array(gtia.w.grafp0); + state_save_register_global_array(gtia.w.grafp1); + state_save_register_global_array(gtia.w.grafp2); + state_save_register_global_array(gtia.w.grafp3); + state_save_register_global_array(gtia.w.grafm); + state_save_register_global(gtia.w.colpm0); + state_save_register_global(gtia.w.colpm1); + state_save_register_global(gtia.w.colpm2); + state_save_register_global(gtia.w.colpm3); + state_save_register_global(gtia.w.colpf0); + state_save_register_global(gtia.w.colpf1); + state_save_register_global(gtia.w.colpf2); + state_save_register_global(gtia.w.colpf3); + state_save_register_global(gtia.w.colbk); + state_save_register_global(gtia.w.prior); + state_save_register_global(gtia.w.vdelay); + state_save_register_global(gtia.w.gractl); + state_save_register_global(gtia.w.hitclr); + state_save_register_global(gtia.w.cons); + state_save_register_func_postload(gtia_state_postload); +} + + + +static int is_ntsc(void) +{ + return ATTOSECONDS_TO_HZ(Machine->screen[0].refresh) > 55; +} + + + +static void gtia_reset(running_machine *machine) +{ + int i; + /* reset the GTIA read/write/helper registers */ + for (i = 0; i < 32; i++) + atari_gtia_w(i,0); + memset(>ia.r, 0, sizeof(gtia.r)); + if (is_ntsc()) + gtia.r.pal = 0xff; + else + gtia.r.pal = 0xf1; + gtia.r.gtia15 = 0xff; + gtia.r.gtia16 = 0xff; + gtia.r.gtia17 = 0xff; + gtia.r.gtia18 = 0xff; + gtia.r.gtia19 = 0xff; + gtia.r.gtia1a = 0xff; + gtia.r.gtia1b = 0xff; + gtia.r.gtia1c = 0xff; + gtia.r.gtia1d = 0xff; + gtia.r.gtia1e = 0xff; + gtia.r.cons = 0x07; /* console keys */ + SETCOL_B(ILL,0x3e); /* bright red */ + SETCOL_B(EOR,0xff); /* yellow */ +} + + + +/************************************************************** + * + * Read GTIA hardware registers + * + **************************************************************/ + +READ8_HANDLER( atari_gtia_r ) +{ + switch (offset & 31) + { + case 0: return gtia.r.m0pf; + case 1: return gtia.r.m1pf; + case 2: return gtia.r.m2pf; + case 3: return gtia.r.m3pf; + case 4: return gtia.r.p0pf; + case 5: return gtia.r.p1pf; + case 6: return gtia.r.p2pf; + case 7: return gtia.r.p3pf; + case 8: return gtia.r.m0pl; + case 9: return gtia.r.m1pl; + case 10: return gtia.r.m2pl; + case 11: return gtia.r.m3pl; + case 12: return gtia.r.p0pl; + case 13: return gtia.r.p1pl; + case 14: return gtia.r.p2pl; + case 15: return gtia.r.p3pl; + + case 16: return gtia.r.but[0]; + case 17: return gtia.r.but[1]; + case 18: return gtia.r.but[2]; + case 19: return gtia.r.but[3]; + + case 20: return gtia.r.pal; + + case 21: return gtia.r.gtia15; + case 22: return gtia.r.gtia16; + case 23: return gtia.r.gtia17; + case 24: return gtia.r.gtia18; + case 25: return gtia.r.gtia19; + case 26: return gtia.r.gtia1a; + case 27: return gtia.r.gtia1b; + case 28: return gtia.r.gtia1c; + case 29: return gtia.r.gtia1d; + case 30: return gtia.r.gtia1e; + + case 31: + gtia.r.cons = gtia.intf.console_read ? (gtia.intf.console_read() & 0x0F) : 0x00; + return gtia.r.cons; + } + return 0xff; +} + + + +static void recalc_p0(void) +{ + if ( +#if CHECK_GRACTL + (gtia.w.gractl & GTIA_PLAYER) == 0 || +#endif + gtia.w.grafp0[gtia.h.vdelay_p0] == 0 || gtia.w.hposp0 >= 224 ) + { + gtia.h.grafp0 = 0; + gtia.h.usedp &= ~0x10; + } + else + { + gtia.h.grafp0 = gtia.w.grafp0[gtia.h.vdelay_p0]; + gtia.h.usedp |= 0x10; + } +} + +static void recalc_p1(void) +{ + if ( +#if CHECK_GRACTL + (gtia.w.gractl & GTIA_PLAYER) == 0 || +#endif + gtia.w.grafp1[gtia.h.vdelay_p1] == 0 || gtia.w.hposp1 >= 224 ) + { + gtia.h.grafp1 = 0; + gtia.h.usedp &= ~0x20; + } + else + { + gtia.h.grafp1 = gtia.w.grafp1[gtia.h.vdelay_p1]; + gtia.h.usedp |= 0x20; + } +} + +static void recalc_p2(void) +{ + if ( +#if CHECK_GRACTL + (gtia.w.gractl & GTIA_PLAYER) == 0 || +#endif + gtia.w.grafp2[gtia.h.vdelay_p2] == 0 || gtia.w.hposp2 >= 224 ) + { + gtia.h.grafp2 = 0; + gtia.h.usedp &= ~0x40; + } + else + { + gtia.h.grafp2 = gtia.w.grafp2[gtia.h.vdelay_p2]; + gtia.h.usedp |= 0x40; + } +} + +static void recalc_p3(void) +{ + if ( +#if CHECK_GRACTL + (gtia.w.gractl & GTIA_PLAYER) == 0 || +#endif + gtia.w.grafp3[gtia.h.vdelay_p3] == 0 || gtia.w.hposp3 >= 224 ) + { + gtia.h.grafp3 = 0; + gtia.h.usedp &= ~0x80; + } + else + { + gtia.h.grafp3 = gtia.w.grafp3[gtia.h.vdelay_p3]; + gtia.h.usedp |= 0x80; + } +} + +static void recalc_m0(void) +{ + if ( +#if CHECK_GRACTL + (gtia.w.gractl & GTIA_MISSILE) == 0 || +#endif + (gtia.w.grafm[gtia.h.vdelay_m0] & 0x03) == 0 || gtia.w.hposm0 >= 224 ) + { + gtia.h.grafm0 = 0; + gtia.h.usedm0 = 0; + } + else + { + gtia.h.grafm0 = (gtia.w.grafm[gtia.h.vdelay_m0] << 6) & 0xc0; + gtia.h.usedm0 = (gtia.w.prior & 0x10) ? 0x08 : 0x10; + } +} + +static void recalc_m1(void) +{ + if ( +#if CHECK_GRACTL + (gtia.w.gractl & GTIA_MISSILE) == 0 || +#endif + (gtia.w.grafm[gtia.h.vdelay_m1] & 0x0c) == 0 || gtia.w.hposm1 >= 224 ) + { + gtia.h.grafm1 = 0; + gtia.h.usedm1 = 0; + } + else + { + gtia.h.grafm1 = (gtia.w.grafm[gtia.h.vdelay_m1] << 4) & 0xc0; + gtia.h.usedm1 = (gtia.w.prior & 0x10) ? 0x08 : 0x20; + } +} + +static void recalc_m2(void) +{ + if ( +#if CHECK_GRACTL + (gtia.w.gractl & GTIA_MISSILE) == 0 || +#endif + (gtia.w.grafm[gtia.h.vdelay_m2] & 0x30) == 0 || gtia.w.hposm2 >= 224 ) + { + gtia.h.grafm2 = 0; + gtia.h.usedm2 = 0; + } + else + { + gtia.h.grafm2 = (gtia.w.grafm[gtia.h.vdelay_m2] << 2) & 0xc0; + gtia.h.usedm2 = (gtia.w.prior & 0x10) ? 0x08 : 0x40; + } +} + +static void recalc_m3(void) +{ + if ( +#if CHECK_GRACTL + (gtia.w.gractl & GTIA_MISSILE) == 0 || +#endif + (gtia.w.grafm[gtia.h.vdelay_m3] & 0xc0) == 0 || gtia.w.hposm3 >= 224) + { + gtia.h.grafm3 = 0; + gtia.h.usedm3 = 0; + } + else + { + gtia.h.grafm3 = (gtia.w.grafm[gtia.h.vdelay_m3] << 0) & 0xc0; + gtia.h.usedm3 = (gtia.w.prior & 0x10) ? 0x08 : 0x80; + } +} + + + +WRITE8_HANDLER( atari_gtia_w ) +{ + /* used for mixing hue/lum of different colors */ + static UINT8 lumpm0=0,lumpm1=0,lumpm2=0,lumpm3=0,lumpm4=0; + static UINT8 lumpf1=0,lumpf2=0,lumbk= 0; + static UINT8 huepm0=0,huepm1=0,huepm2=0,huepm3=0,huepm4=0; + static UINT8 huepf1=0,huepf2=0,huebk= 0; + + switch (offset & 31) + { + case 0: + gtia.w.hposp0 = data; + recalc_p0(); + break; + case 1: + gtia.w.hposp1 = data; + recalc_p1(); + break; + case 2: + gtia.w.hposp2 = data; + recalc_p2(); + break; + case 3: + gtia.w.hposp3 = data; + recalc_p3(); + break; + + case 4: + gtia.w.hposm0 = data; + recalc_m0(); + break; + case 5: + gtia.w.hposm1 = data; + recalc_m1(); + break; + case 6: + gtia.w.hposm2 = data; + recalc_m2(); + break; + case 7: + gtia.w.hposm3 = data; + recalc_m3(); + break; + + case 8: + data &= 3; + gtia.w.sizep0 = data; + recalc_p0(); + break; + case 9: + data &= 3; + gtia.w.sizep1 = data; + recalc_p1(); + break; + case 10: + data &= 3; + gtia.w.sizep2 = data; + recalc_p2(); + break; + case 11: + data &= 3; + gtia.w.sizep3 = data; + recalc_p3(); + break; + + case 12: + data &= 3; + gtia.w.sizem = data; + recalc_m0(); + recalc_m1(); + recalc_m2(); + recalc_m3(); + break; + + case 13: + gtia.w.grafp0[0] = data; + recalc_p0(); + break; + case 14: + gtia.w.grafp1[0] = data; + recalc_p1(); + break; + case 15: + gtia.w.grafp2[0] = data; + recalc_p2(); + break; + case 16: + gtia.w.grafp3[0] = data; + recalc_p3(); + break; + + case 17: + gtia.w.grafm[0] = data; + recalc_m0(); + recalc_m1(); + recalc_m2(); + recalc_m3(); + break; + + case 18: /* color for player/missile #0 */ + if (data == gtia.w.colpm0) + break; + gtia.w.colpm0 = data; + if (VERBOSE) + logerror("atari colpm0 $%02x\n", data); + + SETCOL_B(PL0,data); /* set player 0 color */ + SETCOL_B(MI0,data); /* set missile 0 color */ + SETCOL_B(GT2,data); /* set GTIA mode 2 color 0 */ + SETCOL_B(P000,data); /* set player 0 both pixels 0 */ + SETCOL_L(P001,data); /* set player 0 left pixel 0 */ + SETCOL_R(P010,data); /* set player 0 right pixel 0 */ + SPLIT_HUE_LUM(data,huepm0,lumpm0); + data = huepm0 | lumpf1; + SETCOL_R(P001,data); /* set player 0 right pixel 1 */ + SETCOL_L(P010,data); /* set player 0 left pixel 1 */ + SETCOL_B(P011,data); /* set player 0 both pixels 1 */ + break; + + case 19: /* color for player/missile #1 */ + if (data == gtia.w.colpm1) + break; + gtia.w.colpm1 = data; + if (VERBOSE) + logerror("atari colpm1 $%02x\n", data); + + SETCOL_B(PL1,data); /* set player color 1 */ + SETCOL_B(MI1,data); /* set missile color 1 */ + SETCOL_B(GT2+1,data); /* set GTIA mode 2 color 1 */ + SETCOL_B(P100,data); /* set player 1 both pixels 0 */ + SETCOL_L(P101,data); /* set player 1 left pixel 0 */ + SETCOL_R(P110,data); /* set player 1 right pixel 0 */ + SPLIT_HUE_LUM(data,huepm1,lumpm1); + data = huepm1 | lumpf1; + SETCOL_R(P101,data); /* set player 1 right pixel 1 */ + SETCOL_L(P110,data); /* set player 1 left pixel 1 */ + SETCOL_B(P111,data); /* set player 1 both pixels 1 */ + break; + + case 20: /* color for player/missile #2 */ + if (data == gtia.w.colpm2) + break; + gtia.w.colpm2 = data; + if (VERBOSE) + logerror("atari colpm2 $%02x\n", data); + + SETCOL_B(PL2,data); /* set player 2 color */ + SETCOL_B(MI2,data); /* set missile 2 color */ + SETCOL_B(GT2+2,data); /* set GTIA mode 2 color 2 */ + SETCOL_B(P200,data); /* set player 2 both pixels 0 */ + SETCOL_L(P201,data); /* set player 2 left pixel 0 */ + SETCOL_R(P210,data); /* set player 2 right pixel 0 */ + SPLIT_HUE_LUM(data,huepm2,lumpm2); + data = huepm2 | lumpf1; + SETCOL_R(P201,data); /* set player 2 right pixel 1 */ + SETCOL_L(P210,data); /* set player 2 left pixel 1 */ + SETCOL_B(P211,data); /* set player 2 both pixels 1 */ + break; + + case 21: /* color for player/missile #3 */ + if (data == gtia.w.colpm3) + break; + gtia.w.colpm3 = data; + if (VERBOSE) + logerror("atari colpm3 $%02x\n", data); + + SETCOL_B(PL3,data); /* set player 3 color */ + SETCOL_B(MI3,data); /* set missile 3 color */ + SETCOL_B(GT2+3,data); /* set GTIA mode 2 color 3 */ + SETCOL_B(P300,data); /* set player 3 both pixels 0 */ + SETCOL_L(P301,data); /* set player 3 left pixel 0 */ + SETCOL_R(P310,data); /* set player 3 right pixel 0 */ + SPLIT_HUE_LUM(data,huepm3,lumpm3); + data = huepm3 | lumpf1; + SETCOL_R(P301,data); /* set player 3 right pixel 1 */ + SETCOL_L(P310,data); /* set player 3 left pixel 1 */ + SETCOL_B(P311,data); /* set player 3 both pixels 1 */ + break; + + case 22: /* playfield color #0 */ + if (data == gtia.w.colpf0) + break; + gtia.w.colpf0 = data; + if (VERBOSE) + logerror("atari colpf0 $%02x\n", data); + + SETCOL_B(PF0,data); /* set playfield 0 color */ + SETCOL_B(GT2+4,data); /* set GTIA mode 2 color 4 */ + break; + + case 23: /* playfield color #1 */ + if (data == gtia.w.colpf1) + break; + gtia.w.colpf1 = data; + if (VERBOSE) + logerror("atari colpf1 $%02x\n", data); + + SETCOL_B(PF1,data); /* set playfield 1 color */ + SETCOL_B(GT2+5,data); /* set GTIA mode 2 color 5 */ + SPLIT_HUE_LUM(data,huepf1,lumpf1); + data = huepf2 | lumpf1; + SETCOL_R(T01,data); /* set text mode right pixel 1 */ + SETCOL_L(T10,data); /* set text mode left pixel 1 */ + SETCOL_B(T11,data); /* set text mode both pixels 1 */ + data = huebk | lumpf1; + SETCOL_R(G01,data); /* set graphics mode right pixel 1 */ + SETCOL_L(G10,data); /* set graphics mode left pixel 1 */ + SETCOL_B(G11,data); /* set graphics mode both pixels 1 */ + data = huepm0 | lumpf1; + SETCOL_R(P001,data); /* set player 0 right pixel 1 */ + SETCOL_L(P010,data); /* set player 0 left pixel 1 */ + SETCOL_B(P011,data); /* set player 0 both pixels 1 */ + data = huepm1 | lumpf1; + SETCOL_R(P101,data); /* set player 1 right pixel 1 */ + SETCOL_L(P110,data); /* set player 1 left pixel 1 */ + SETCOL_B(P111,data); /* set player 1 both pixels 1 */ + data = huepm2 | lumpf1; + SETCOL_R(P201,data); /* set player 2 right pixel 1 */ + SETCOL_L(P210,data); /* set player 2 left pixel 1 */ + SETCOL_B(P211,data); /* set player 2 both pixels 1 */ + data = huepm3 | lumpf1; + SETCOL_R(P301,data); /* set player 3 right pixel 1 */ + SETCOL_L(P310,data); /* set player 3 left pixel 1 */ + SETCOL_B(P311,data); /* set player 3 both pixels 1 */ + data = huepm4 | lumpf1; + SETCOL_R(P401,data); /* set missiles right pixel 1 */ + SETCOL_L(P410,data); /* set missiles left pixel 1 */ + SETCOL_B(P411,data); /* set missiles both pixels 1 */ + break; + + case 24: /* playfield color #2 */ + if (data == gtia.w.colpf2) + break; + gtia.w.colpf2 = data; + if (VERBOSE) + logerror("atari colpf2 $%02x\n", data); + + SETCOL_B(PF2,data); /* set playfield color 2 */ + SETCOL_B(GT2+6,data); /* set GTIA mode 2 color 6 */ + SETCOL_B(T00,data); /* set text mode both pixels 0 */ + SETCOL_L(T01,data); /* set text mode left pixel 0 */ + SETCOL_R(T10,data); /* set text mode right pixel 0 */ + SPLIT_HUE_LUM(data,huepf2,lumpf2); + data = huepf2 | lumpf1; + SETCOL_R(T01,data); /* set text mode right pixel 1 */ + SETCOL_L(T10,data); /* set text mode left pixel 1 */ + SETCOL_B(T11,data); /* set text mode both pixels 1 */ + break; + + case 25: /* playfield color #3 */ + if (data == gtia.w.colpf3) + break; + gtia.w.colpf3 = data; + if (VERBOSE) + logerror("atari colpf3 $%02x\n", data); + + SETCOL_B(PF3,data); /* set playfield color 3 */ + SETCOL_B(GT2+7,data); /* set GTIA mode 2 color 7 */ + SETCOL_B(P400,data); /* set p/m xor mode both pixels 0 */ + SETCOL_L(P401,data); /* set p/m xor mode left pixel 0 */ + SETCOL_R(P410,data); /* set p/m xor mode right pixel 0 */ + SPLIT_HUE_LUM(data,huepm4,lumpm4); + data = huepm4 | lumpf1; + SETCOL_R(P401,data); /* set p/m xor mode right pixel 1 */ + SETCOL_L(P410,data); /* set p/m xor mode left pixel 1 */ + SETCOL_B(P411,data); /* set p/m xor mode both pixels 1 */ + break; + + case 26: /* playfield background */ + if (data == gtia.w.colbk) + break; + gtia.w.colbk = data; + if (VERBOSE) + logerror("atari colbk $%02x\n", data); + + SETCOL_B(PBK,data); /* set background color */ + SETCOL_B(GT2+8,data); /* set GTIA mode 2 color 8 */ + SETCOL_B(GT2+9,data); /* set GTIA mode 2 color 9 */ + SETCOL_B(GT2+10,data); /* set GTIA mode 2 color 10 */ + SETCOL_B(GT2+11,data); /* set GTIA mode 2 color 11 */ + SETCOL_B(GT2+12,data); /* set GTIA mode 2 color 12 */ + SETCOL_B(GT2+13,data); /* set GTIA mode 2 color 13 */ + SETCOL_B(GT2+14,data); /* set GTIA mode 2 color 14 */ + SETCOL_B(GT2+15,data); /* set GTIA mode 2 color 15 */ + SETCOL_B(G00,data); /* set 2 color graphics both pixels 0 */ + SETCOL_L(G01,data); /* set 2 color graphics left pixel 0 */ + SETCOL_R(G10,data); /* set 2 color graphics right pixel 0 */ + SPLIT_HUE_LUM(data,huebk,lumbk); + data = huebk | lumpf1; + SETCOL_R(G01,data); /* set 2 color graphics right pixel 1 */ + SETCOL_L(G10,data); /* set 2 color graphics left pixel 1 */ + SETCOL_B(G11,data); /* set 2 color graphics both pixels 1 */ + SETCOL_B(GT1+ 0,(data&HUE)+(0x00&LUM)); /* set GTIA mode 1 HUE + LUM 0..15 */ + SETCOL_B(GT1+ 1,(data&HUE)+(0x11&LUM)); + SETCOL_B(GT1+ 2,(data&HUE)+(0x22&LUM)); + SETCOL_B(GT1+ 3,(data&HUE)+(0x33&LUM)); + SETCOL_B(GT1+ 4,(data&HUE)+(0x44&LUM)); + SETCOL_B(GT1+ 5,(data&HUE)+(0x55&LUM)); + SETCOL_B(GT1+ 6,(data&HUE)+(0x66&LUM)); + SETCOL_B(GT1+ 7,(data&HUE)+(0x77&LUM)); + SETCOL_B(GT1+ 8,(data&HUE)+(0x88&LUM)); + SETCOL_B(GT1+ 9,(data&HUE)+(0x99&LUM)); + SETCOL_B(GT1+10,(data&HUE)+(0xaa&LUM)); + SETCOL_B(GT1+11,(data&HUE)+(0xbb&LUM)); + SETCOL_B(GT1+12,(data&HUE)+(0xcc&LUM)); + SETCOL_B(GT1+13,(data&HUE)+(0xdd&LUM)); + SETCOL_B(GT1+14,(data&HUE)+(0xee&LUM)); + SETCOL_B(GT1+15,(data&HUE)+(0xff&LUM)); + SETCOL_B(GT3+ 0,(data&LUM)+(0x00&HUE)); /* set GTIA mode 3 LUM + HUE 0..15 */ + SETCOL_B(GT3+ 1,(data&LUM)+(0x11&HUE)); + SETCOL_B(GT3+ 2,(data&LUM)+(0x22&HUE)); + SETCOL_B(GT3+ 3,(data&LUM)+(0x33&HUE)); + SETCOL_B(GT3+ 4,(data&LUM)+(0x44&HUE)); + SETCOL_B(GT3+ 5,(data&LUM)+(0x55&HUE)); + SETCOL_B(GT3+ 6,(data&LUM)+(0x66&HUE)); + SETCOL_B(GT3+ 7,(data&LUM)+(0x77&HUE)); + SETCOL_B(GT3+ 8,(data&LUM)+(0x88&HUE)); + SETCOL_B(GT3+ 9,(data&LUM)+(0x99&HUE)); + SETCOL_B(GT3+10,(data&LUM)+(0xaa&HUE)); + SETCOL_B(GT3+11,(data&LUM)+(0xbb&HUE)); + SETCOL_B(GT3+12,(data&LUM)+(0xcc&HUE)); + SETCOL_B(GT3+13,(data&LUM)+(0xdd&HUE)); + SETCOL_B(GT3+14,(data&LUM)+(0xee&HUE)); + SETCOL_B(GT3+15,(data&LUM)+(0xff&HUE)); + break; + + case 27: + gtia.w.prior = data; + recalc_m0(); + recalc_m1(); + recalc_m2(); + recalc_m3(); + break; + + case 28: /* delay until vertical retrace */ + gtia.w.vdelay = data; + gtia.h.vdelay_m0 = (data >> 0) & 1; + gtia.h.vdelay_m1 = (data >> 1) & 1; + gtia.h.vdelay_m2 = (data >> 2) & 1; + gtia.h.vdelay_m3 = (data >> 3) & 1; + gtia.h.vdelay_p0 = (data >> 4) & 1; + gtia.h.vdelay_p1 = (data >> 5) & 1; + gtia.h.vdelay_p2 = (data >> 6) & 1; + gtia.h.vdelay_p3 = (data >> 7) & 1; + break; + + case 29: + gtia.w.gractl = data; + recalc_p0(); + recalc_p1(); + recalc_p2(); + recalc_p3(); + recalc_m0(); + recalc_m1(); + recalc_m2(); + recalc_m3(); + break; + + case 30: /* clear collisions */ + gtia.r.m0pf = gtia.r.m1pf = gtia.r.m2pf = gtia.r.m3pf = + gtia.r.p0pf = gtia.r.p1pf = gtia.r.p2pf = gtia.r.p3pf = + gtia.r.m0pl = gtia.r.m1pl = gtia.r.m2pl = gtia.r.m3pl = + gtia.r.p0pl = gtia.r.p1pl = gtia.r.p2pl = gtia.r.p3pl = 0; + gtia.w.hitclr = data; + break; + + case 31: /* write console (speaker) */ + if (data == gtia.w.cons) + break; + gtia.w.cons = data; + if (gtia.intf.console_write) + gtia.intf.console_write(gtia.w.cons); + break; + } +} + + + +static void gtia_state_postload(void) +{ + recalc_p0(); + recalc_p1(); + recalc_p2(); + recalc_p3(); + recalc_m0(); + recalc_m1(); + recalc_m2(); + recalc_m3(); +} + + + +static const UINT8 pf_collision[256] = { + 0,1,2,0,4,0,0,0,8,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +}; + +static const int pf_prioindex[256] = { +/* PBK PF0 PF1 PF2 PF3 */ +/* */ 0x000,0x100,0x100,0x000,0x200,0x000,0x000,0x000,0x200,0x000,0x000,0x000,0x000,0x000,0x000,0x000, +/* */ 0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000, +/* */ 0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000, +/* */ 0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000, +/* T00 */ 0x400,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000, +/* T01 */ 0x500,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000, +/* T10 */ 0x600,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000, +/* T11 */ 0x700,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000, +/* G00 */ 0x400,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000, +/* G01 */ 0x500,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000, +/* G10 */ 0x600,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000, +/* G11 */ 0x700,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000, +/* GT1 */ 0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000, +/* GT2 */ 0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000, +/* GT3 */ 0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000, +/* */ 0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000 +}; + +#define RENDER_PLAYER(player,color) \ +static void render_##player##_w1(UINT8 *dst) \ +{ \ + if( gtia.h.graf##player & 0x80 ) \ + dst[0] |= color; \ + if( gtia.h.graf##player & 0x40 ) \ + dst[1] |= color; \ + if( gtia.h.graf##player & 0x20 ) \ + dst[2] |= color; \ + if( gtia.h.graf##player & 0x10 ) \ + dst[3] |= color; \ + if( gtia.h.graf##player & 0x08 ) \ + dst[4] |= color; \ + if( gtia.h.graf##player & 0x04 ) \ + dst[5] |= color; \ + if( gtia.h.graf##player & 0x02 ) \ + dst[6] |= color; \ + if( gtia.h.graf##player & 0x01 ) \ + dst[7] |= color; \ +} \ +static void render_##player##_w2(UINT8 *dst) \ +{ \ + if( gtia.h.graf##player & 0x80 ) \ + { \ + dst[ 0] |= color; \ + dst[ 1] |= color; \ + } \ + if( gtia.h.graf##player & 0x40 ) \ + { \ + dst[ 2] |= color; \ + dst[ 3] |= color; \ + } \ + if( gtia.h.graf##player & 0x20 ) \ + { \ + dst[ 4] |= color; \ + dst[ 5] |= color; \ + } \ + if( gtia.h.graf##player & 0x10 ) \ + { \ + dst[ 6] |= color; \ + dst[ 7] |= color; \ + } \ + if( gtia.h.graf##player & 0x08 ) \ + { \ + dst[ 8] |= color; \ + dst[ 9] |= color; \ + } \ + if( gtia.h.graf##player & 0x04 ) \ + { \ + dst[10] |= color; \ + dst[11] |= color; \ + } \ + if( gtia.h.graf##player & 0x02 ) \ + { \ + dst[12] |= color; \ + dst[13] |= color; \ + } \ + if( gtia.h.graf##player & 0x01 ) \ + { \ + dst[14] |= color; \ + dst[15] |= color; \ + } \ +} \ +static void render_##player##_w4(UINT8 *dst) \ +{ \ + if( gtia.h.graf##player & 0x80 ) \ + { \ + dst[ 0] |= color; \ + dst[ 1] |= color; \ + dst[ 2] |= color; \ + dst[ 3] |= color; \ + } \ + if( gtia.h.graf##player & 0x40 ) \ + { \ + dst[ 4] |= color; \ + dst[ 5] |= color; \ + dst[ 6] |= color; \ + dst[ 7] |= color; \ + } \ + if( gtia.h.graf##player & 0x20 ) \ + { \ + dst[ 8] |= color; \ + dst[ 9] |= color; \ + dst[10] |= color; \ + dst[11] |= color; \ + } \ + if( gtia.h.graf##player & 0x10 ) \ + { \ + dst[12] |= color; \ + dst[13] |= color; \ + dst[14] |= color; \ + dst[15] |= color; \ + } \ + if( gtia.h.graf##player & 0x08 ) \ + { \ + dst[16] |= color; \ + dst[17] |= color; \ + dst[18] |= color; \ + dst[19] |= color; \ + } \ + if( gtia.h.graf##player & 0x04 ) \ + { \ + dst[20] |= color; \ + dst[21] |= color; \ + dst[22] |= color; \ + dst[23] |= color; \ + } \ + if( gtia.h.graf##player & 0x02 ) \ + { \ + dst[24] |= color; \ + dst[25] |= color; \ + dst[26] |= color; \ + dst[27] |= color; \ + } \ + if( gtia.h.graf##player & 0x01 ) \ + { \ + dst[28] |= color; \ + dst[29] |= color; \ + dst[30] |= color; \ + dst[31] |= color; \ + } \ +} \ +static void (*render_##player[4])(UINT8 *dst)={ \ + render_##player##_w1, \ + render_##player##_w2, \ + render_##player##_w2, \ + render_##player##_w4 \ +} + +#define RENDER_MISSILE(missile,color) \ +static void render_##missile##_w1(UINT8 *dst) \ +{ \ + if( gtia.h.graf##missile & 0x80 ) \ + dst[0] |= color; \ + if( gtia.h.graf##missile & 0x40 ) \ + dst[1] |= color; \ +} \ +static void render_##missile##_w2(UINT8 *dst) \ +{ \ + if( gtia.h.graf##missile & 0x80 ) \ + { \ + dst[ 0] |= color; \ + dst[ 1] |= color; \ + } \ + if( gtia.h.graf##missile & 0x40 ) \ + { \ + dst[ 2] |= color; \ + dst[ 3] |= color; \ + } \ +} \ +static void render_##missile##_w4(UINT8 *dst) \ +{ \ + if( gtia.h.graf##missile & 0x80 ) \ + { \ + dst[ 0] |= color; \ + dst[ 1] |= color; \ + dst[ 2] |= color; \ + dst[ 3] |= color; \ + } \ + if( gtia.h.graf##missile & 0x40 ) \ + { \ + dst[ 4] |= color; \ + dst[ 5] |= color; \ + dst[ 6] |= color; \ + dst[ 7] |= color; \ + } \ +} \ +static void (*render_##missile[4])(UINT8 *dst) = { \ + render_##missile##_w1, \ + render_##missile##_w2, \ + render_##missile##_w2, \ + render_##missile##_w4 \ +} + +RENDER_PLAYER(p0,P0); +RENDER_PLAYER(p1,P1); +RENDER_PLAYER(p2,P2); +RENDER_PLAYER(p3,P3); +RENDER_MISSILE(m0,M0); +RENDER_MISSILE(m1,M1); +RENDER_MISSILE(m2,M2); +RENDER_MISSILE(m3,M3); + + +void gtia_render(VIDEO *video) +{ + int x; + UINT8 *prio = antic.prio_table[gtia.w.prior & 0x3f]; + UINT8 *src, *dst; + + if( antic.scanline < VBL_END || antic.scanline >= 256 ) + return; + + if( gtia.h.grafp0 ) + (*render_p0[gtia.w.sizep0])(&antic.pmbits[gtia.w.hposp0]); + + if( gtia.h.grafp1 ) + (*render_p1[gtia.w.sizep1])(&antic.pmbits[gtia.w.hposp1]); + + if( gtia.h.grafp2 ) + (*render_p2[gtia.w.sizep2])(&antic.pmbits[gtia.w.hposp2]); + + if( gtia.h.grafp3 ) + (*render_p3[gtia.w.sizep3])(&antic.pmbits[gtia.w.hposp3]); + + if( gtia.h.grafm0 ) + (*render_m0[gtia.w.sizem])(&antic.pmbits[gtia.w.hposm0]); + + if( gtia.h.grafm1 ) + (*render_m1[gtia.w.sizem])(&antic.pmbits[gtia.w.hposm1]); + + if( gtia.h.grafm2 ) + (*render_m2[gtia.w.sizem])(&antic.pmbits[gtia.w.hposm2]); + + if( gtia.h.grafm3 ) + (*render_m3[gtia.w.sizem])(&antic.pmbits[gtia.w.hposm3]); + + src = antic.pmbits + PMOFFSET; + dst = antic.cclock + PMOFFSET - antic.hscrol_old; + + for( x = 0; x < HWIDTH*4; x++, src++, dst++ ) + { + UINT8 pm, pc, pf; + if( !*src ) + continue; + /* get the player/missile combination bits and reset the buffer */ + pm = *src; + *src = 0; + /* get the current playfield color */ + pc = *dst; + pf = pf_collision[pc]; + if (pm&P0) { gtia.r.p0pf |= pf; gtia.r.p0pl |= pm&( P1|P2|P3); } + if (pm&P1) { gtia.r.p1pf |= pf; gtia.r.p1pl |= pm&(P0| P2|P3); } + if (pm&P2) { gtia.r.p2pf |= pf; gtia.r.p2pl |= pm&(P0|P1| P3); } + if (pm&P3) { gtia.r.p3pf |= pf; gtia.r.p3pl |= pm&(P0|P1|P2 ); } + if (pm&M0) { gtia.r.m0pf |= pf; gtia.r.m0pl |= pm&(P0|P1|P2|P3); } + if (pm&M1) { gtia.r.m1pf |= pf; gtia.r.m1pl |= pm&(P0|P1|P2|P3); } + if (pm&M2) { gtia.r.m2pf |= pf; gtia.r.m2pl |= pm&(P0|P1|P2|P3); } + if (pm&M3) { gtia.r.m3pf |= pf; gtia.r.m3pl |= pm&(P0|P1|P2|P3); } + /* color with higher priority? change playfield */ + pc = prio[pf_prioindex[pc] | pm]; + if (pc) *dst = pc; + } + /* copy player/missile graphics in case of vdelay */ + gtia.w.grafp0[1] = gtia.w.grafp0[0]; + gtia.w.grafp1[1] = gtia.w.grafp1[0]; + gtia.w.grafp2[1] = gtia.w.grafp2[0]; + gtia.w.grafp3[1] = gtia.w.grafp3[0]; + gtia.w.grafm[1] = gtia.w.grafm[0]; +} + +/************* ANTIC mode 0F : GTIA mode 1 ******************** + * graphics mode 8x1:16 (32/40/48 byte per line) + ***************************************************************/ +#define GTIA1(s) COPY4(dst, antic.pf_gtia1[video->data[s]]) + +void gtia_mode_1_32(VIDEO *video) +{ + PREPARE_GFXG1(32); + REP32(GTIA1); + POST_GFX(32); +} +void gtia_mode_1_40(VIDEO *video) +{ + PREPARE_GFXG1(40); + REP40(GTIA1); + POST_GFX(40); +} +void gtia_mode_1_48(VIDEO *video) +{ + PREPARE_GFXG1(48); + REP48(GTIA1); + POST_GFX(48); +} + +/************* ANTIC mode 0F : GTIA mode 2 ******************** + * graphics mode 8x1:16 (32/40/48 byte per line) + ***************************************************************/ +#define GTIA2(s) COPY4(dst, antic.pf_gtia2[video->data[s]]) + +void gtia_mode_2_32(VIDEO *video) +{ + PREPARE_GFXG2(32); + REP32(GTIA2); + POST_GFX(32); +} +void gtia_mode_2_40(VIDEO *video) +{ + PREPARE_GFXG2(40); + REP40(GTIA2); + POST_GFX(40); +} +void gtia_mode_2_48(VIDEO *video) +{ + PREPARE_GFXG2(48); + REP48(GTIA2); + POST_GFX(48); +} + +/************* ANTIC mode 0F : GTIA mode 3 ******************** + * graphics mode 8x1:16 (32/40/48 byte per line) + ***************************************************************/ +#define GTIA3(s) COPY4(dst, antic.pf_gtia3[video->data[s]]) + +void gtia_mode_3_32(VIDEO *video) +{ + PREPARE_GFXG3(32); + REP32(GTIA3); + POST_GFX(32); +} +void gtia_mode_3_40(VIDEO *video) +{ + PREPARE_GFXG3(40); + REP40(GTIA3); + POST_GFX(40); +} +void gtia_mode_3_48(VIDEO *video) +{ + PREPARE_GFXG3(48); + REP48(GTIA3); + POST_GFX(48); +} + |