summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/video/gtia.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/video/gtia.c')
-rw-r--r--src/mame/video/gtia.c1135
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(&gtia, 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(&gtia.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);
+}
+