/*************************************************************************** Tatsumi TX-1/Buggy Boy video hardware ****************************************************************************/ #include "emu.h" #include "render.h" #include "video/resnet.h" #include "cpu/i86/i86.h" #include "includes/tx1.h" /************************************* * * HD46505S-2 CRT Controller * *************************************/ #define CURSOR_YPOS 239 #define CURSOR_XPOS 168 #define PRINT_CRTC_DATA 0 /* 6845 cursor output is connected to the main CPU interrupt pin. The CRTC is programmed to provide a rudimentary VBLANK interrupt. TODO: Calc TX-1 values... */ /* TODO: Check interrupt timing from CRT config. Probably different between games. */ static TIMER_CALLBACK( interrupt_callback ) { tx1_state *state = machine.driver_data(); cputag_set_input_line_and_vector(machine, "main_cpu", 0, HOLD_LINE, 0xff); state->m_interrupt_timer->adjust(machine.primary_screen->time_until_pos(CURSOR_YPOS, CURSOR_XPOS)); } READ16_HANDLER( tx1_crtc_r ) { return 0xffff; } WRITE16_HANDLER( tx1_crtc_w ) { if (PRINT_CRTC_DATA) { data &= 0xff; if (offset == 0) { switch (data) { case 0x00: mame_printf_debug("Horizontal Total "); break; case 0x01: mame_printf_debug("Horizontal displayed "); break; case 0x02: mame_printf_debug("Horizontal sync position "); break; case 0x03: mame_printf_debug("Horizontal sync width "); break; case 0x04: mame_printf_debug("Vertical total "); break; case 0x05: mame_printf_debug("Vertical total adjust "); break; case 0x06: mame_printf_debug("Vertical displayed "); break; case 0x07: mame_printf_debug("Vertical sync position "); break; case 0x08: mame_printf_debug("Interlace mode "); break; case 0x09: mame_printf_debug("Max. scan line address "); break; case 0x0a: mame_printf_debug("Cursror start "); break; case 0x0b: mame_printf_debug("Cursor end "); break; case 0x0c: mame_printf_debug("Start address (h) "); break; case 0x0d: mame_printf_debug("Start address (l) "); break; case 0x0e: mame_printf_debug("Cursor (h) "); break; case 0x0f: mame_printf_debug("Cursor (l) "); break; case 0x10: mame_printf_debug("Light pen (h)) "); break; case 0x11: mame_printf_debug("Light pen (l) "); break; } } else if (offset == 1) { mame_printf_debug("0x%.2x, (%d)\n",data, data); } } } /*************************************************************************** TX-1 ***************************************************************************/ enum { TX1_RDFLAG_RVA8 = 0, TX1_RDFLAG_RVA9, TX1_RDFLAG_RVA7, TX1_RDFLAG_TNLF, TX1_RDFLAG_STLF, TX1_RDFLAG_SCCHGF }; /*************************************************************************** Palette initialisation bit 3 -- 220 ohm resistor -- RED/GREEN/BLUE -- 470 ohm resistor -- RED/GREEN/BLUE -- 1.0kohm resistor -- RED/GREEN/BLUE bit 0 -- 2.2kohm resistor -- RED/GREEN/BLUE ***************************************************************************/ PALETTE_INIT( tx1 ) { int i; static const res_net_info tx1_net_info = { RES_NET_VCC_5V | RES_NET_VIN_TTL_OUT, { { RES_NET_AMP_NONE, 0, 0, 4, { 2200, 1000, 470, 220 } }, { RES_NET_AMP_NONE, 0, 0, 4, { 2200, 1000, 470, 220 } }, { RES_NET_AMP_NONE, 0, 0, 4, { 2200, 1000, 470, 220 } } } }; for (i = 0; i < 256; ++i) { int r, g, b; r = compute_res_net(color_prom[i + 0x300] & 0xf, 0, &tx1_net_info); g = compute_res_net(color_prom[i + 0x400] & 0xf, 1, &tx1_net_info); b = compute_res_net(color_prom[i + 0x500] & 0xf, 2, &tx1_net_info); palette_set_color(machine, i, MAKE_RGB(r, g, b)); } } /************************************* * * Video Control Registers * *************************************/ WRITE16_HANDLER( tx1_bankcs_w ) { tx1_state *state = space->machine().driver_data(); vregs_t &tx1_vregs = state->m_vregs; // AAB2 = /BASET0 // AAB3 = /BASET // AAB4 = /BSET // AAB5 = /HASET // AAB6 = /HSET offset <<= 1; if (offset & 0x04) { tx1_vregs.ba_inc &= ~0x0000ffff; tx1_vregs.ba_inc |= data; if (!(offset & 2)) tx1_vregs.ba_val &= ~0x000ffff; } if (offset & 0x08) { data &= 0xff; tx1_vregs.ba_inc &= ~0xffff0000; tx1_vregs.ba_inc |= data << 16; // TODO: Schems say D15. tx1_vregs.bank_mode = BIT(data, 1); if (!(offset & 2)) tx1_vregs.ba_val &= ~0xffff0000; } if ( !(offset & 0x10) ) { /* Ignore data */ if (offset & 2) tx1_vregs.ba_val = (tx1_vregs.ba_inc + tx1_vregs.ba_val) & 0x00ffffff; } if (offset & 0x20) { tx1_vregs.h_inc = data; if ( !(offset & 2) ) tx1_vregs.h_val = 0; } if (!(offset & 0x40)) { /* TODO: Looks safe to remove this */ // if ( offset & 2 ) tx1_vregs.h_val += tx1_vregs.h_inc; } } WRITE16_HANDLER( tx1_slincs_w ) { tx1_state *state = space->machine().driver_data(); if (offset == 1) state->m_vregs.slin_inc = data; else state->m_vregs.slin_inc = state->m_vregs.slin_val = 0; } WRITE16_HANDLER( tx1_slock_w ) { tx1_state *state = space->machine().driver_data(); state->m_vregs.slock = data & 1; } WRITE16_HANDLER( tx1_scolst_w ) { tx1_state *state = space->machine().driver_data(); state->m_vregs.scol = data & 0x0707; } WRITE16_HANDLER( tx1_flgcs_w ) { tx1_state *state = space->machine().driver_data(); state->m_vregs.flags = data & 0xff; } /************************************* * * Characters * *************************************/ static void tx1_draw_char(running_machine &machine, UINT8 *bitmap) { tx1_state *state = machine.driver_data(); UINT16 *tx1_vram = state->m_vram; INT32 x, y; UINT32 scroll_x; UINT8 *chars, *gfx2; /* 2bpp characters */ chars = machine.region("char_tiles")->base(); gfx2 = chars + 0x4000; /* X scroll value is the last word in char RAM */ scroll_x = tx1_vram[0xfff] & 0x3ff; for (y = 0; y < 240; ++y) { UINT32 d0 = 0, d1 = 0; UINT32 colour = 0; UINT32 y_offs; UINT32 x_offs; UINT32 y_gran; /* No y-scrolling? */ y_offs = y; if ((y_offs >= 64) && (y_offs < 128)) x_offs = state->m_vregs.slock ? scroll_x : 0; else x_offs = 0; y_gran = y_offs & 7; if (x_offs & 7) { UINT32 tilenum; UINT16 ram_val = tx1_vram[((y_offs << 4) & 0xf80) + ((x_offs >> 3) & 0x7f)]; tilenum = (ram_val & 0x03ff) | ((ram_val & 0x8000) >> 5); colour = (ram_val & 0xfc00) >> 8; d0 = *(gfx2 + (tilenum << 3) + y_gran); d1 = *(chars + (tilenum << 3) + y_gran); } for (x = 0; x < 256 * 3; ++x) { UINT32 x_gran = x_offs & 7; if (!x_gran) { UINT32 tilenum; UINT16 ram_val = tx1_vram[((y_offs << 4) & 0xf80) + ((x_offs >> 3) & 0x7f)]; tilenum = (ram_val & 0x03ff) | ((ram_val & 0x8000) >> 5); colour = (ram_val & 0xfc00) >> 8; d0 = *(gfx2 + (tilenum << 3) + y_gran); d1 = *(chars + (tilenum << 3) + y_gran); } *bitmap++ = colour | (((d1 >> (7 ^ x_gran)) & 1) << 1) | ((d0 >> (7 ^ x_gran)) & 1); x_offs = (x_offs + 1) & 0x3ff; } } } /************************************* * * Road * *************************************/ #define TX1_GET_ROADPIX(NUM) \ { \ UINT32 addr = (rva6_0 << 5) | (road##NUM##_hcnt & 0x1f); \ UINT8 promaddr1, promaddr2, promaddr3; \ promaddr1 = rom_a[addr]; \ promaddr2 = rom_b[addr]; \ promaddr3 = rom_c[addr]; \ pix[NUM][0][0] = prom_a[promaddr1]; pix[NUM][0][1] = prom_b[promaddr1]; pix[NUM][0][2] = prom_c[promaddr1]; \ pix[NUM][1][0] = prom_a[promaddr2]; pix[NUM][1][1] = prom_b[promaddr2]; pix[NUM][1][2] = prom_c[promaddr2]; \ pix[NUM][2][0] = prom_a[promaddr3]; pix[NUM][2][1] = prom_b[promaddr3]; pix[NUM][2][2] = prom_c[promaddr3]; \ pix[NUM][3][0] = prom_a[0]; pix[NUM][3][1] = prom_b[0]; pix[NUM][3][2] = prom_c[0]; \ } INLINE void tx1_draw_road_pixel(running_machine &machine, int screen, UINT8 *bmpaddr, UINT8 apix[3], UINT8 bpix[3], UINT32 pixnuma, UINT32 pixnumb, UINT8 stl, UINT8 sld, UINT8 selb, UINT8 bnk, UINT8 rorev, UINT8 eb, UINT8 r, UINT8 delr) { tx1_state *state = machine.driver_data(); vregs_t &tx1_vregs = state->m_vregs; UINT8 a0 = BIT(apix[0], pixnuma); UINT8 a1 = BIT(apix[1], pixnuma); UINT8 a2 = BIT(apix[2], pixnuma); UINT8 b0 = BIT(bpix[0], pixnumb); UINT8 b1 = BIT(bpix[1], pixnumb); UINT8 b2 = BIT(bpix[2], pixnumb); UINT8 d3; UINT8 d2; UINT8 d1; UINT8 d0; UINT8 sel; UINT8 c6 = BIT(sld, 6); UINT8 c5 = BIT(sld, 5); UINT8 c4 = BIT(sld, 4); UINT8 c3 = BIT(sld, 2); UINT32 addr_offset = screen * 256; sel = !bnk && ( (a2 && !b0) || (!a0 && b2) || !a1 || !a2 || !b1 || !b2 ); d3 = (a2 && a1 && a0 && b2 && b1 && b0 && !rorev) || (a1 && b1 && !b0 && stl && !bnk && !c6) || (a1 && !a0 && b1 && stl && !bnk && !c6) || (a1 && !b2 && b1 && stl && !bnk && !c6) || (a2 && b2 && !b1 && stl && !bnk && !c4) || (a2 && !a1 && b2 && stl && !bnk && !c4) || (!a2 && a1 && b2 && stl && !bnk && !c6) || (a2 && !b2 && b1 && stl && !bnk && !c6) || (!a2 && !a1 && stl && !bnk && !c5) || (!b2 && !b1 && stl && !bnk && !c5) || (!b0 && !stl && !bnk && !c3) || (!b1 && !stl && !bnk && !c3) || (!a0 && !stl && !bnk && !c3) || (!a1 && !stl && !bnk && !c3) || (!a2 && !stl && !bnk && !c3) || (!b2 && !stl && !bnk && !c3) || (bnk && !rorev); if (eb == 0) { if (sel == 1) { d2 = stl && (!a2 || !b2); d1 = !stl || (!a2 && !a1) || (!b1 && !b2) || (a2 && !b1) || (b2 && !a1); d0 = !stl || (!a2 && !a0 && b1) || (a1 && !b2 && !b0) || (!a2 && !a1 && !a0) || (!b2 && !b1 && !b0) || (a2 && a1 && !b0) || (!a0 && b2 && b1) || (a2 && !b1 && !b0) || (!a1 && !a0 && b2) || (!a2 && !a0 && b2) || (a2 && !b2 && !b0); } else { d2 = BIT(tx1_vregs.scol, selb ? 2 : 10); d1 = BIT(tx1_vregs.scol, selb ? 1 : 9); d0 = BIT(tx1_vregs.scol, selb ? 0 : 8); } } else d2 = d1 = d0 = 0; *(bmpaddr + addr_offset) = (bnk << 6) | (r << 5) | (!(sel && delr) << 4 ) | (d3 << 3) | (d2 << 2) | (d1 << 1) | d0; } /* This could do with a tidy up and more comments... */ static void tx1_draw_road(running_machine &machine, UINT8 *bitmap) { tx1_state *state = machine.driver_data(); UINT16 *tx1_rcram = state->m_rcram; vregs_t &tx1_vregs = state->m_vregs; INT32 y; UINT32 rva9_8; UINT32 rva7; UINT32 tnlf; UINT32 stlf; UINT32 scchgf; UINT32 vc = 0; UINT16 road0_hcnt; UINT8 road0_pcnt; UINT16 road1_hcnt; UINT8 road1_pcnt; UINT8 pix[2][4][3]; /* Road slice map ROMs */ const UINT8 *const gfx3 = machine.region("gfx3")->base(); const UINT8 *const rom_a = gfx3; const UINT8 *const rom_b = gfx3 + 0x2000; const UINT8 *const rom_c = gfx3 + 0x4000; /* Pixel data */ const UINT8 *const proms = machine.region("proms")->base(); const UINT8 *const prom_a = proms + 0x1100; const UINT8 *const prom_b = proms + 0x1300; const UINT8 *const prom_c = proms + 0x1500; const UINT8 *const vprom = proms + 0x1700; rva9_8 = (tx1_vregs.flags & 3) << 8; rva7 = !BIT(tx1_vregs.flags, TX1_RDFLAG_RVA7) << 7; tnlf = BIT(tx1_vregs.flags, TX1_RDFLAG_TNLF); scchgf = BIT(tx1_vregs.flags, TX1_RDFLAG_SCCHGF); stlf = BIT(tx1_vregs.flags, TX1_RDFLAG_STLF); for (y = 0; y < 240; ++y) { UINT32 x; UINT8 sld; UINT8 rva6_0; UINT16 rcrdb15_0; UINT16 rva_addr; UINT32 bank_cnt; UINT16 vat; UINT16 vp0; UINT16 vp1; UINT16 vp2; UINT16 vp3; UINT16 vp4; UINT32 va8, va9, va10, va11, va12, va13, va14, va15; UINT32 v0, v1, v2; UINT8 hc1_u, hc1_l; UINT8 hc0_u, hc0_l; UINT32 bnkls, bnkcs, bnkrs; UINT32 rl, rc, rr; UINT32 stl; UINT32 selb; UINT32 ebls, ebcs, ebrs; UINT8 *bmpaddr = bitmap + (y * 768); UINT32 rltmp, rctmp, rrtmp; UINT32 eltmp, ectmp, ertmp; UINT32 tmpm; UINT32 tmpn; UINT32 tmpc; UINT32 tmpd; UINT8 scrcnt0; UINT8 scrcnt1; UINT8 rorevls = 0; UINT8 rorevcs = 0; UINT8 rorevrs = 0; int febl[2] = { 0, 0 }; int febr[2] = { 0, 0 }; int febc[2] = { 0, 0 }; /* Road vertical address */ if (BIT(tx1_vregs.h_val, 15)) rva6_0 = 0x7f; else rva6_0 = (~tx1_vregs.h_val >> 7) & 0x7f; rva_addr = rva9_8 | rva6_0; /* Get the stripe data also */ sld = vprom[rva6_0] + tx1_vregs.slin_val; /* Load the left road h-counter */ rcrdb15_0 = tx1_rcram[(0x80 + rva_addr) ^ 0x7ff]; road0_pcnt = rcrdb15_0 & 0x7; road0_hcnt = (rcrdb15_0 >> 3) & 0x7f; road0_hcnt |= rcrdb15_0 & 0xfc00 ? 0x80 : 0; road0_hcnt |= (rcrdb15_0 & 0xfc00) == 0xfc00 ? 0x100 : 0x000; /* Load the second road h-counter */ rcrdb15_0 = tx1_rcram[(rva7 + rva_addr) ^ 0x7ff]; road1_pcnt = rcrdb15_0 & 0x7; road1_hcnt = (rcrdb15_0 >> 3) & 0x7f; road1_hcnt |= rcrdb15_0 & 0xfc00 ? 0x80 : 0; road1_hcnt |= (rcrdb15_0 & 0xfc00) == 0xfc00 ? 0x100 : 0x000; road1_hcnt |= (rcrdb15_0 & 0x800); scrcnt0 = (road0_hcnt >> 5) & 0xf; scrcnt1 = (road1_hcnt >> 5) & 0xf; if (road0_pcnt & 7) { TX1_GET_ROADPIX(0); febl[0] = (scrcnt0 + 0) & 0xc; febc[0] = (scrcnt0 + 1) & 0xc; febr[0] = (scrcnt0 + 2) & 0xc; } if (road1_pcnt & 7) { UINT32 y4 = (road1_hcnt >> 4) & 1; UINT32 temp = (road1_hcnt >> 5) & 0xf; UINT32 x, u; UINT32 fl11 = BIT(road1_hcnt, 15); TX1_GET_ROADPIX(1); x = (temp & 0xc); u = !(((temp & 1) && y4) || (temp & 2)); rorevls = ((fl11 && !x) || (fl11 && x && u)); febl[1] = x; temp += 1; x = (temp & 0xc); u = !(((temp & 1) && y4) || (temp & 2)); rorevcs = ((fl11 && !x) || (fl11 && x && u)); febc[1] = x; temp += 1; x = (temp & 0xc); u = !(((temp & 1) && y4) || (temp & 2)); rorevrs = ((fl11 && !x) || (fl11 && x && u)); febr[1] = x; } /* Load the bank counter with accumulator bits 14-5 */ bank_cnt = (tx1_vregs.ba_val >> 5) & 0x3ff; /* Load vertical position data */ vat = tx1_rcram[(rva9_8 + 7) ^ 0x7f8]; vp0 = tx1_rcram[(rva9_8 + 6) ^ 0x7f8]; vp1 = tx1_rcram[(rva9_8 + 5) ^ 0x7f8]; vp2 = tx1_rcram[(rva9_8 + 4) ^ 0x7f8]; vp3 = tx1_rcram[(rva9_8 + 3) ^ 0x7f8]; vp4 = tx1_rcram[(rva9_8 + 2) ^ 0x7f8]; /* */ if (y-1 == vp0) vc++; if (y-1 == vp1) vc++; if (y-1 == vp2) vc++; if (y-1 == vp3) vc++; if (y-1 == vp4) vc++; /* */ va8 = BIT(vat, 8); va9 = BIT(vat, 9); va10 = BIT(vat, 10); va11 = BIT(vat, 11); va12 = BIT(vat, 12); va13 = BIT(vat, 13); va14 = BIT(vat, 14); va15 = BIT(vat, 15); v0 = BIT(vc, 0); v1 = BIT(vc, 1); v2 = BIT(vc, 2); /* Load the horizontal tunnel position counters */ hc1_u = tx1_rcram[(rva9_8 + 1) ^ 0x7f8] >> 8; hc1_l = tx1_rcram[(rva9_8 + 1) ^ 0x7f8] & 0xff; hc0_u = tx1_rcram[(rva9_8 + 0) ^ 0x7f8] >> 8; hc0_l = tx1_rcram[(rva9_8 + 0) ^ 0x7f8] & 0xff; stl = !stlf || v0 || (!v2 && !scchgf) || scchgf; selb = (!v2 && !scchgf) || v2; rltmp = (v2 && !v0 && !va10) || (!v2 && v0 && !va10) || (v2 && !v0 && !va11) || (v2 && !v1 && !v0) || (!v2 && v0 && !va11) || (!v2 && v1 && !v0) || (!v2 && !v1 && v0); rctmp = (v2 && !v0 && va9 && va8) || (!v2 && v0 && va9 && va8) || (v2 && !v0 && !va11) || (v2 && !v1 && !v0) || (!v2 && v0 && !va11) || (!v2 && v1 && !v0) || (!v2 && !v1 && v0); rrtmp = (v2 && !v0 && !va11 && !va10) || (!v2 && v0 && !va11 && !va10) || (v2 && !v0 && va9) || (!v2 && v0 && va9) || (v2 && !v1 && !v0) || (!v2 && v1 && !v0) || (!v2 && !v1 && v0); ectmp = (v2 && !v0 && va13 && va12) || (!v2 && v1 && va13 && va12) || (!v2 && !v1 && v0) || (v2 && !v0 && !va15) || (!v2 && v1 && !va15); eltmp = (v2 && !v0 && !va14) || (!v2 && v1 && !va14) || (!v2 && !v1 && v0) || (v2 && !v0 && !va15) || (!v2 && v1 && !va15); ertmp = (v2 && !v0 && !va15 && !va14) || (!v2 && v1 && !va15 && !va14) || (v2 && !v0 && va13) || (!v2 && v1 && va13) || (!v2 && !v1 && v0); tmpn = (v2 && !v0) || (!v2 && v0); tmpm = (v2 && !v0) || (!v2 && v1); tmpc = (!v1 && !v0) || (v2); tmpd = v1 && v0 && va11; for (x = 0; x < 256; x++) { UINT32 pixnum0 = (road0_pcnt & 7) ^ 7; UINT32 pixnum1 = (road1_pcnt & 7) ^ 7; UINT32 cyu, cyl; UINT32 delrl, delrc, delrr; /* */ scrcnt0 = (road0_hcnt >> 5) & 0xf; scrcnt1 = (road1_hcnt >> 5) & 0xf; /* Get new pixel data? */ if (!(road0_pcnt & 7)) { TX1_GET_ROADPIX(0); /* Road 0 enables */ febl[0] = (scrcnt0 + 0) & 0xc; febc[0] = (scrcnt0 + 1) & 0xc; febr[0] = (scrcnt0 + 2) & 0xc; } if (!(road1_pcnt & 7)) { UINT32 y4 = (road1_hcnt >> 4) & 1; UINT32 temp = (road1_hcnt >> 5) & 0xf; UINT32 x, u; UINT32 fl11 = BIT(road1_hcnt, 15); TX1_GET_ROADPIX(1); x = (temp & 0xc); u = !(((temp & 1) && y4) || (temp & 2)); rorevls = ((fl11 && !x) || (fl11 && x && u)); febl[1] = x; temp += 1; x = (temp & 0xc); u = !(((temp & 1) && y4) || (temp & 2)); rorevcs = ((fl11 && !x) || (fl11 && x && u)); febc[1] = x; temp += 1; x = (temp & 0xc); u = !(((temp & 1) && y4) || (temp & 2)); rorevrs = ((fl11 && !x) || (fl11 && x && u)); febr[1] = x; } /* Road camber/banking */ if (BIT(tx1_vregs.ba_val, 23)) { bnkls = 1; bnkcs = 1; bnkrs = 1; } else if (tx1_vregs.ba_val & 0x007f8000) { bnkls = 0; bnkcs = 0; bnkrs = 0; } else { bnkls = bank_cnt < 0x400; bnkcs = bank_cnt < 0x300; bnkrs = bank_cnt < 0x200; } if (tx1_vregs.bank_mode) { bnkls ^= 1; bnkcs ^= 1; bnkrs ^= 1; } cyu = hc1_u == 0xff; cyl = hc1_l == 0xff; rl = tnlf && ( rltmp || (tmpn && (!cyl || (va8 && va9 && cyu))) ); rc = tnlf && ( rctmp || (tmpn && ((!va10 && !cyl) || (va9 && cyu))) ); rr = tnlf && ( rrtmp || (tmpn && ((!va11 && !cyl) || (va8 && cyu))) ); /* Evaluates to 0 for tunnels */ delrl = !tnlf || tmpc || ((tmpd && va10) && ((!va8 && cyl) || (!va9 && cyl) || (!cyu && !cyl))); delrr = !tnlf || tmpc || (v1 && v0 && va10 && !va9 && !va8 && cyl) || (v1 && v0 && va10 && !va9 && cyl && !cyu) || (tmpd && !va9 && !cyu) || (tmpd && !va9 && !va8); delrc = !tnlf || tmpc || (tmpd && ((!va8 && cyl && !cyu) || (!va8 && va10 && !cyu) || (!va9 && cyl) || (va10 && !va9))); cyu = hc0_u == 0xff; cyl = hc0_l == 0xff; ebls = tnlf && ( eltmp || (tmpm && (!cyl || (va12 && va13 && cyu)))); ebcs = tnlf && ( ectmp || (tmpm && ((!va14 && !cyl) || (va13 && cyu)))); ebrs = tnlf && ( ertmp || (tmpm && ((!va15 && !cyl) || (va12 && cyu)))); /* Carry for horizontal position counters */ cyu = hc0_u == 0xff; cyl = hc0_l == 0xff; if (!(bnkls && !rl)) { int a, b; if (!febl[0]) a = (scrcnt0) & 3; else a = 3; if (!febl[1]) b = (scrcnt1) & 3; else b = 3; tx1_draw_road_pixel(machine, 0, bmpaddr, &pix[0][a][0], &pix[1][b][0], pixnum0, pixnum1, stl, sld, selb, bnkls, rorevls, ebls, rl, delrl); } else *(bmpaddr) = (bnkls << 6) | (rl << 5); if (!(bnkcs && !rc)) { int a, b; if (!febc[0]) a = (scrcnt0 + 1) & 3; else a = 3; if (!febc[1]) b = (scrcnt1 + 1) & 3; else b = 3; tx1_draw_road_pixel(machine, 1, bmpaddr, &pix[0][a][0], &pix[1][b][0], pixnum0, pixnum1, stl, sld, selb, bnkcs, rorevcs, ebcs, rc, delrc); } else *(bmpaddr + 256) = (bnkcs << 6) | (rc << 5); if (!(bnkrs && !rr)) { int a, b; if (!febr[0]) a = (scrcnt0 + 2) & 3; else a = 3; if (!febr[1]) b = (scrcnt1 + 2) & 3; else b = 3; tx1_draw_road_pixel(machine, 2, bmpaddr, &pix[0][a][0], &pix[1][b][0], pixnum0, pixnum1, stl, sld, selb, bnkrs, rorevrs, ebrs, rr, delrr); } else *(bmpaddr + 512) = (bnkrs << 6) | (rr << 5); ++bmpaddr; /* Update road counters */ if (!(++road0_pcnt & 7)) ++road0_hcnt; if (!(++road1_pcnt & 7)) ++road1_hcnt; /* Increment horizontal counters (stop at 0xff) */ if (hc0_u != 0xff) ++hc0_u; if (hc0_l != 0xff) ++hc0_l; if (hc1_u != 0xff) ++hc1_u; if (hc1_l != 0xff) ++hc1_l; /* Update bank counter */ bank_cnt = (bank_cnt + 1) & 0x7ff; } tx1_vregs.h_val += tx1_vregs.h_inc; /* Finally, increment the bank accumulator */ tx1_vregs.ba_val = (tx1_vregs.ba_val + tx1_vregs.ba_inc) & 0x00ffffff; } } /************************************* * * Objects * *************************************/ static void tx1_draw_objects(running_machine &machine, UINT8 *bitmap) { tx1_state *state = machine.driver_data(); UINT16 *tx1_objram = state->m_objram; #define FRAC 16 UINT32 offs; /* The many lookup table ROMs */ const UINT8 *const ic48 = machine.region("user3")->base(); const UINT8 *const ic281 = ic48 + 0x2000; const UINT8 *const proms = machine.region("proms")->base(); const UINT8 *const ic190 = proms + 0xc00; const UINT8 *const ic162 = proms + 0xe00; const UINT8 *const ic25 = proms + 0x1000; const UINT8 *const ic106 = machine.region("obj_map")->base(); const UINT8 *const ic73 = ic106 + 0x4000; const UINT8 *const pixdata_rgn = machine.region("obj_tiles")->base(); for (offs = 0x0; offs <= 0x300; offs += 8) { UINT32 x; UINT32 y; UINT32 gxflip; UINT32 x_scale; UINT32 x_step; UINT16 y_scale; UINT16 y_step; UINT8 pctmp0_7; UINT8 code; /* Check for end of object list */ if ((tx1_objram[offs] & 0xff00) == 0xff00) break; /* X scale */ x_scale = tx1_objram[offs + 2] & 0xff; /* TODO: Confirm against hardware? */ if (x_scale == 0) continue; /* 16-bit y-scale accumulator */ y_scale = tx1_objram[offs + 1]; y_step = tx1_objram[offs + 3]; /* Object number */ code = tx1_objram[offs] & 0xff; /* Attributes */ pctmp0_7 = tx1_objram[offs + 2] >> 8; /* Global x-flip */ gxflip = (pctmp0_7 & 0x80) >> 7; /* Add 1 to account for line buffering */ y = (tx1_objram[offs] >> 8) + 1; for (; y < 240; ++y) { UINT32 rom_addr2 = 0; UINT8 ic106_data = 0; UINT8 ic73_data; /* Are we drawing on this line? */ /* TODO: See big lampposts. */ if (y_scale & 0x8000) break; { UINT32 psa0_11; UINT32 ic48_addr; UINT32 ic48_data; UINT32 rom_addr; UINT32 x_acc; UINT32 newtile = 1; UINT32 dataend = 0; UINT8 data1 = 0; UINT8 data2 = 0; UINT32 xflip = 0; UINT32 opcd0_7 = 0; UINT32 lasttile = 0; /* Use the object code to lookup the tile sequence data in ROM */ ic48_addr = code << 4; ic48_addr |= ((y_scale >> 11) & 0xf); ic48_data = ic48[ic48_addr]; /* Reached the bottom of the object? (/PASS2E) */ if (ic48_data == 0xff) break; /* Combine ROM and PROM data */ psa0_11 = ((ic25[code] << 8) | ic48_data) & 0xfff; /* psa8_11 */ rom_addr = (psa0_11 & ~0xff) << 2; /* Prepare the x-scaling */ x_step = (128 << FRAC) / x_scale; x_acc = (psa0_11 & 0xff) << (FRAC + 5); #define TX1_MASK 0xfff x = tx1_objram[offs + 4] & TX1_MASK; for (;;) { if (newtile) { UINT32 psbb0_12; UINT32 pscb0_14; UINT32 pscb11; UINT8 *romptr; UINT32 ic281_addr; UINT32 grom_addr; UINT32 lut_data; UINT32 low_addr = ((x_acc >> (FRAC + 3)) & TX1_MASK); if (gxflip) { UINT32 xor_mask; if (BIT(psa0_11, 11) && BIT(psa0_11, 10)) xor_mask = 0xf; else if (BIT(psa0_11, 11) || BIT(psa0_11, 10) || BIT(psa0_11, 9)) xor_mask = 0x7; else xor_mask = 0x3; rom_addr2 = rom_addr + (xor_mask ^ low_addr); } else rom_addr2 = rom_addr + low_addr; ic106_data = ic106[rom_addr2 & 0x3fff]; if ((ic106_data & 0x40) && dataend) lasttile = 1; dataend |= ic106_data & 0x40; /* Retrieve data for an 8x8 tile */ ic73_data = ic73[rom_addr2]; /* This is the data from the LUT pair */ lut_data = (ic106_data << 8) | ic73_data; psbb0_12 = lut_data & 0x1fff; pscb0_14 = (psbb0_12 & 0xc3f); /* Bits 9_6 are from PCTMP11-8 or PSBB9-6 */ if (BIT(psbb0_12, 12)) pscb0_14 |= psbb0_12 & 0x3c0; else pscb0_14 |= (pctmp0_7 & 0xf) << 6; if (BIT(lut_data, 13)) pscb0_14 |= BIT(psbb0_12, 10) << 12; else pscb0_14 |= ((pctmp0_7 & 0x70) << 8); /* Bit 12 is bit 10 duplicated. */ pscb0_14 &= ~(1 << 12); pscb0_14 |= BIT(psbb0_12, 10) << 12; pscb11 = BIT(pscb0_14, 11); /* TODO: Remove this - it's constant. */ romptr = (UINT8*)(pixdata_rgn + pscb11 * (0x4000 * 2)); grom_addr = ((pscb0_14 << 3) | ((y_scale >> 8) & 7)) & 0x3fff; /* Get raw 8x8 2bpp pixel row data */ data1 = *(grom_addr + romptr); data2 = *(grom_addr + romptr + 0x4000); /* Determine flip state (global XOR local) */ xflip = gxflip ^ !BIT(lut_data, 15); ic281_addr = pscb0_14 & 0x3ff; ic281_addr |= ((pscb0_14 & 0x7000) >> 2); ic281_addr |= pscb11 << 13; opcd0_7 = ic281[ic281_addr]; newtile = 0; } /* Draw a pixel? */ if (x < 768) { UINT8 pix; UINT8 bit; bit = (x_acc >> FRAC) & 7; if (xflip) bit ^= 7; pix = (((data1 >> bit) & 1) << 1) | ((data2 >> bit) & 1); /* Draw pixel, if not transparent */ if ( !(!(opcd0_7 & 0x80) && !pix) ) { UINT8 color; UINT32 prom_addr; prom_addr = ((opcd0_7 << 2) | pix) & 0x1ff; /* Inverted on schematic */ if (x & 1) color = ~ic190[prom_addr] & 0x3f; else color = ~ic162[prom_addr] & 0x3f; *(bitmap + 768*y + x) = 0x40 | color; } } /* Check if we've stepped into a new 8x8 tile */ if ((((x_acc + x_step) >> (FRAC + 3)) & TX1_MASK) != ((x_acc >> (FRAC + 3)) & TX1_MASK)) { if (lasttile) break; newtile = 1; } x = (x + 1) & TX1_MASK; x_acc += x_step; } } y_scale += y_step; } } } /************************************* * * Core Functions * *************************************/ VIDEO_START( tx1 ) { tx1_state *state = machine.driver_data(); /* Allocate a large bitmap that covers the three screens */ state->m_bitmap = auto_bitmap_alloc(machine, 768, 256, BITMAP_FORMAT_INDEXED16); /* Allocate some bitmaps */ state->m_chr_bmp = auto_alloc_array(machine, UINT8, 256 * 3 * 240); state->m_obj_bmp = auto_alloc_array(machine, UINT8, 256 * 3 * 240); state->m_rod_bmp = auto_alloc_array(machine, UINT8, 256 * 3 * 240); /* Set a timer to run the interrupts */ state->m_interrupt_timer = machine.scheduler().timer_alloc(FUNC(interrupt_callback)); /* /CUDISP CRTC interrupt */ state->m_interrupt_timer->adjust(machine.primary_screen->time_until_pos(CURSOR_YPOS, CURSOR_XPOS)); } SCREEN_EOF( tx1 ) { tx1_state *state = machine.driver_data(); /* /VSYNC: Update TZ113 */ state->m_vregs.slin_val += state->m_vregs.slin_inc; } static void tx1_combine_layers(running_machine &machine, bitmap_t *bitmap, int screen) { tx1_state *state = machine.driver_data(); int x, y; UINT8 *chr_pal = machine.region("proms")->base() + 0x900; int x_offset = screen * 256; for (y = 0; y < 240; ++y) { UINT16 *bmp_addr = BITMAP_ADDR16(bitmap, y, 0); UINT32 bmp_offset = y * 768 + x_offset; UINT8 *chr_addr = state->m_chr_bmp + bmp_offset; UINT8 *rod_addr = state->m_rod_bmp + bmp_offset; UINT8 *obj_addr = state->m_obj_bmp + bmp_offset; for (x = 0; x < 256; ++x) { UINT8 out_val; UINT32 char_val = chr_addr[x]; UINT32 c7 = BIT(char_val, 7); UINT32 c1 = BIT(char_val, 1); UINT32 c0 = BIT(char_val, 0); UINT32 road_val = rod_addr[x]; UINT32 r6 = BIT(road_val, 6); UINT32 r5 = BIT(road_val, 5); UINT32 obj_val = obj_addr[x]; UINT32 obj6 = BIT(obj_val, 6); UINT32 term1 = !(c7 && c1); UINT32 term2 = !(c7 && c0); UINT32 term3 = r5 || !r6; UINT32 p12 = !(term1 && term2 && term3); UINT32 p6 = !(obj6 && term1 && term2); UINT32 sel = p12 | (p6 << 1); UINT32 psel = (!(p6 && p12) << 1) | p6; if (sel == 3) out_val = ((char_val & 0xc0) >> 2) | (chr_pal[char_val] & 0xf); else if (sel == 2) out_val = road_val & 0x3f; else out_val = obj_val & 0x3f; *bmp_addr++ = (psel << 6) | out_val; } } } SCREEN_UPDATE( tx1 ) { tx1_state *state = screen->machine().driver_data(); device_t *left_screen = screen->machine().device("lscreen"); device_t *centre_screen = screen->machine().device("cscreen"); device_t *right_screen = screen->machine().device("rscreen"); if (screen == left_screen) { memset(state->m_obj_bmp, 0, 768*240); tx1_draw_char(screen->machine(), state->m_chr_bmp); tx1_draw_road(screen->machine(), state->m_rod_bmp); tx1_draw_objects(screen->machine(), state->m_obj_bmp); tx1_combine_layers(screen->machine(), bitmap, 0); } else if (screen == centre_screen) { tx1_combine_layers(screen->machine(), bitmap, 1); } else if (screen == right_screen) { tx1_combine_layers(screen->machine(), bitmap, 2); } return 0; } /*************************************************************************** Buggy Boy ***************************************************************************/ /* Road register bits */ #define BB_RDFLAG_WAVE1 7 #define BB_RDFLAG_WAVE0 6 #define BB_RDFLAG_TNLMD1 5 #define BB_RDFLAG_TNLMD0 4 #define BB_RDFLAG_TNLF 3 #define BB_RDFLAG_LINF 2 #define BB_RDFLAG_RVA7 1 #define BB_RDFLAG_WANGL 0 /*************************************************************************** Convert the color PROMs into a more useable format. IC39, BB12 = Blue IC40, BB11 = Green IC41, BB10 = Red IC42, BB13 = Brightness bit 3 -- 220 ohm resistor -- RED/GREEN/BLUE -- 470 ohm resistor -- RED/GREEN/BLUE -- 1.0kohm resistor -- RED/GREEN/BLUE bit 0 -- 2.2kohm resistor -- RED/GREEN/BLUE bit 0 -- 4.7kohm resistor -- BLUE bit 1 -- 4.7kohm resistor -- GREEN bit 2 -- 4.7kohm resistor -- RED ***************************************************************************/ PALETTE_INIT( buggyboy ) { int i; for (i = 0; i < 0x100; i++) { int bit0, bit1, bit2, bit3, bit4; int r, g, b; bit0 = BIT(color_prom[i + 0x000], 0); bit1 = BIT(color_prom[i + 0x000], 1); bit2 = BIT(color_prom[i + 0x000], 2); bit3 = BIT(color_prom[i + 0x000], 3); bit4 = BIT(color_prom[i + 0x300], 2); r = 0x06 * bit4 + 0x0d * bit0 + 0x1e * bit1 + 0x41 * bit2 + 0x8a * bit3; bit0 = BIT(color_prom[i + 0x100], 0); bit1 = BIT(color_prom[i + 0x100], 1); bit2 = BIT(color_prom[i + 0x100], 2); bit3 = BIT(color_prom[i + 0x100], 3); bit4 = BIT(color_prom[i + 0x300], 1); g = 0x06 * bit4 + 0x0d * bit0 + 0x1e * bit1 + 0x41 * bit2 + 0x8a * bit3; bit0 = BIT(color_prom[i + 0x200], 0); bit1 = BIT(color_prom[i + 0x200], 1); bit2 = BIT(color_prom[i + 0x200], 2); bit3 = BIT(color_prom[i + 0x200], 3); bit4 = BIT(color_prom[i + 0x300], 0); b = 0x06 * bit4 + 0x0d * bit0 + 0x1e * bit1 + 0x41 * bit2 + 0x8a * bit3; palette_set_color(machine, i, MAKE_RGB(r, g, b)); } } /************************************* * * Characters * *************************************/ static void buggyboy_draw_char(running_machine &machine, UINT8 *bitmap, int wide) { tx1_state *state = machine.driver_data(); UINT16 *buggyboy_vram = state->m_vram; INT32 x, y; UINT32 scroll_x, scroll_y; UINT8 *chars, *gfx2; UINT32 total_width; UINT32 x_mask; /* 2bpp characters */ chars = machine.region("char_tiles")->base(); gfx2 = machine.region("char_tiles")->base() + 0x4000; /* X/Y scroll values are the last word in char RAM */ if (wide) { scroll_y = (buggyboy_vram[0xfff] >> 10) & 0x3f; scroll_x = buggyboy_vram[0xfff] & 0x3ff; total_width = 768; x_mask = 0x3ff; } else { scroll_y = (buggyboy_vram[0x7ff] >> 10) & 0x3f; scroll_x = buggyboy_vram[0x7ff] & 0x1ff; total_width = 256; x_mask = 0x1ff; } for (y = 0; y < 240; ++y) { UINT32 d0 = 0, d1 = 0; UINT32 colour = 0; UINT32 y_offs; UINT32 x_offs; UINT32 y_gran; /* There's no y-scrolling between scanlines 0 and 63 */ if (y < 64) y_offs = y; else { y_offs = (y + (scroll_y | 0xc0) + 1) & 0xff; /* Clamp */ if (y_offs < 64) y_offs |= 0xc0; } if ((y_offs >= 64) && (y_offs < 128)) x_offs = scroll_x; else x_offs = 0; y_gran = y_offs & 7; if (x_offs & 7) { UINT32 tilenum; UINT16 ram_val; if (wide) ram_val = buggyboy_vram[((y_offs << 4) & 0xf80) + ((x_offs >> 3) & 0x7f)]; else ram_val = buggyboy_vram[((y_offs << 3) & 0x7c0) + ((x_offs >> 3) & 0x3f)]; tilenum = (ram_val & 0x03ff) | ((ram_val & 0x8000) >> 5); colour = (ram_val & 0xfc00) >> 8; d0 = *(gfx2 + (tilenum << 3) + y_gran); d1 = *(chars + (tilenum << 3) + y_gran); } for (x = 0; x < total_width; ++x) { UINT32 x_gran = x_offs & 7; if (!x_gran) { UINT32 tilenum; UINT16 ram_val; if (wide) ram_val = buggyboy_vram[((y_offs << 4) & 0xf80) + ((x_offs >> 3) & 0x7f)]; else ram_val = buggyboy_vram[((y_offs << 3) & 0x7c0) + ((x_offs >> 3) & 0x3f)]; tilenum = (ram_val & 0x03ff) | ((ram_val & 0x8000) >> 5); colour = (ram_val & 0xfc00) >> 8; d0 = *(gfx2 + (tilenum << 3) + y_gran); d1 = *(chars + (tilenum << 3) + y_gran); } *bitmap++ = colour | (((d1 >> (7 ^ x_gran)) & 1) << 1) | ((d0 >> (7 ^ x_gran)) & 1); x_offs = (x_offs + 1) & x_mask; } } } /*************************************************************************** Buggy Boy Road Hardware A hacked up version of TX-1 but without the second road. There are two lists in road/common RAM (double buffered) starting at 0x800 and 0xa00: 0x1800 - 0x18ff: Road line horizontal position word (128 entries). 0x19e0 - 0x19ef: Vertical positions (starting line, water, tunnels etc) 0x19f0 - 0x19ff: Horizontal positions (walls and tunnels) Three TZ1113 accumulators are used to vary: * Road camber (update per pixel) * Road vertical scale/position (update per scanline) * Road 'speed' (update per frame) Road flags register (0x24E0): 7 : Water sparkle control 1 6 : Water sparkle control 0 ('WAVE0,1') 5 : Tunnel mode 1 4 : Tunnel mode 0 ('TNLMD0,1') 3 : Tunnel flag ('TNLF') 2 : Starting Line flag ('LINF') 1 : Road list select 0 : Wall angle enable ('WANGL') Buggy Boy Jr. Road PAL equations: http://philwip.mameworld.info/buggyboy/PAL14H4.149.htm http://philwip.mameworld.info/buggyboy/PAL14L4.151.htm http://philwip.mameworld.info/buggyboy/PAL16H2.3.htm http://philwip.mameworld.info/buggyboy/PAL16L8.4.htm http://philwip.mameworld.info/buggyboy/PAL16L8.150.htm ***************************************************************************/ static void buggyboy_get_roadpix(int screen, int ls161, UINT8 rva0_6, UINT8 sld, UINT32 *_rorev, UINT8 *rc0, UINT8 *rc1, UINT8 *rc2, UINT8 *rc3, const UINT8 *rom, const UINT8 *prom0, const UINT8 *prom1, const UINT8 *prom2) { /* Counter Q10-7 are added to 384 */ UINT16 ls283_159 = (ls161 & 0x780) + 128 + (256 * screen); UINT32 ls283_159_co = ls283_159 & 0x800; UINT32 rom_flip = ls283_159 & 0x200 ? 0 : 1; UINT32 rom_en = !(ls283_159 & 0x400) && !(ls283_159_co ^ (ls161 & 0x800)); UINT8 d0 = 0; UINT8 d1 = 0; /* Latch road reverse bit */ *_rorev = !( (rom_en && rom_flip) || (!rom_en && (ls161 & 0x4000)) ); /* TODO: ROM data is 0xff if not enabled. */ if (rom_en) { UINT8 rom_data; UINT16 prom_addr; /* 6 bit road horizontal address */ UINT16 rha = (ls283_159 & 0x180) | (ls161 & 0x78); if (rom_flip) rha ^= 0x1f8; /* Get road chunk first */ rom_data = rom[(1 << 13) | (rha << 4) | rva0_6]; prom_addr = (rom_flip ? 0x80 : 0) | (rom_data & 0x7f); *rc0 = prom0[prom_addr]; *rc1 = prom1[prom_addr]; *rc2 = prom2[prom_addr]; /* Now get the dirt chunk */ rom_data = rom[(rha << 4) | rva0_6]; prom_addr = 0x100 | rom_data; d0 = prom0[prom_addr]; d1 = prom1[prom_addr]; } else { /* TODO: When ROM is not enabled, data = 0xff But does anybody care? */ *rc0 = *rc1 = *rc2 = *rc3 = 0; } /* The data is mixed by two TZ0314 PALs */ if (BIT(sld, 4)) { if (BIT(sld, 5)) d1 = ~d1; *rc3 = d0 & d1; if (rom_flip) *rc3 = BITSWAP8(*rc3, 0, 1, 2, 3, 4, 5, 6, 7); } else *rc3 = 0; } #define LOAD_HPOS_COUNTER(NUM) \ ram_val = buggyboy_rcram[(rva_offs + 0x1f8 + (2*NUM)) >> 1]; \ rcrs10 = ram_val & 0xfc00 ? 0x0400 : 0x0000; \ hp = vregs.wa8 + ((BIT(ram_val, 15) << 11) | rcrs10 | (ram_val & 0x03ff)); \ hp##NUM = hp & 0xff; \ hp >>= 8; \ hps##NUM##0 = (BIT(hp, 0) || BIT(hp, 2)) && !BIT(hp, 3); \ hps##NUM##1 = (BIT(hp, 1) || BIT(hp, 2)) && !BIT(hp, 3); \ hps##NUM##2 = BIT(hp, 2); \ #define UPDATE_HPOS(NUM) \ if (hp##NUM##_en) \ { \ if ((hp##NUM & 0xff) == 0xff) \ hp##NUM##_cy = 1; \ else \ hp##NUM = hp##NUM + 1; \ } \ static void buggyboy_draw_road(running_machine &machine, UINT8 *bitmap) { tx1_state *state = machine.driver_data(); UINT16 *buggyboy_rcram = state->m_rcram; vregs_t &vregs = state->m_vregs; INT32 x; UINT32 y; UINT16 rva_offs; UINT32 tnlmd0; UINT32 tnlmd1; UINT32 linf; UINT32 tnlf; UINT32 wangl; UINT32 tcmd; UINT32 wave0; UINT32 wave1; UINT32 rva20_6; /* ROM/PROM lookup tables */ const UINT8 *rcols = (UINT8*)(machine.region("proms")->base() + 0x1500); const UINT8 *rom = machine.region("road")->base(); const UINT8 *prom0 = rom + 0x4000; const UINT8 *prom1 = rom + 0x4200; const UINT8 *prom2 = rom + 0x4400; const UINT8 *vprom = rom + 0x4600; /* Extract constant values */ tcmd = ((vregs.scol & 0xc000) >> 12) | ((vregs.scol & 0x00c0) >> 6); tnlmd0 = BIT(vregs.flags, BB_RDFLAG_TNLMD0); tnlmd1 = BIT(vregs.flags, BB_RDFLAG_TNLMD1); linf = BIT(vregs.flags, BB_RDFLAG_LINF); tnlf = BIT(vregs.flags, BB_RDFLAG_TNLF); wangl = BIT(vregs.flags, BB_RDFLAG_WANGL); wave0 = BIT(vregs.flags, BB_RDFLAG_WAVE0); wave1 = BIT(vregs.flags, BB_RDFLAG_WAVE1); rva_offs = BIT(vregs.flags, BB_RDFLAG_RVA7) ? 0x800 : 0xc00; for (y = 0; y < 240; ++y) { UINT8 rva0_6; UINT8 ram_addr; UINT16 rcrdb0_15; UINT16 rcrs10; UINT16 ls161_156_a; UINT16 ls161; UINT8 sld; UINT32 rva8; UINT32 rm0, rm1; UINT32 rcmd; UINT32 bnkls = 1; UINT32 bnkcs = 1; UINT32 bnkrs = 1; // UINT32 x_offs; UINT8 sf; /* Vertical positions shift register */ UINT32 ram_val; UINT32 hp; UINT32 vp1, vp2, vp3, vp4, vp5, vp6, vp7; /* Horizontal positions */ UINT32 hp0, hp1, hp2, hp3; UINT8 hps00, hps01, hps02; UINT8 hps10, hps11, hps12; UINT8 hps20, hps21, hps22; UINT8 hps30, hps31, hps32; /* Road pixel data planes */ UINT8 rc0[3] = {0, 0, 0}; UINT8 rc1[3] = {0, 0, 0}; UINT8 rc2[3] = {0, 0, 0}; UINT8 rc3[3] = {0, 0, 0}; /* Horizontal position counter carry out */ UINT8 hp0_cy = 0, hp1_cy = 0, hp2_cy = 0, hp3_cy = 0; UINT8 *bmpaddr = bitmap + (y * 256 * 3); UINT32 bank_cnt; UINT32 _rorevls = 0; UINT32 _rorevcs = 0; UINT32 _rorevrs = 0; UINT32 ic96_o17; UINT32 ic96_term1; UINT32 ic97_o12; UINT32 ic97_o13; UINT32 ic79_p19; rva8 = (vregs.h_val & 0x8000) || !(vregs.shift & 0x80); /* Get RVA0_6 from TZ113 accumulator chain @ 122/123 */ rva0_6 = (vregs.h_val >> 7) & 0x7f; /* For /WAVE bit logic later */ rva20_6 = ((rva0_6 >> 3) & 0xe) | ((rva0_6 & 2) >> 1); /* RVA is inverted! */ ram_addr = (~rva0_6 & 0x7f) << 1; /* Get the road RAM data for this line */ rcrdb0_15 = buggyboy_rcram[(rva_offs + ram_addr) >> 1]; /* If 15-10 == 000000, then 0 */ rcrs10 = rcrdb0_15 & 0xfc00 ? 0x0400 : 0x0000; /* If 15-10 == 111111, then 1 */ ls161_156_a = (rcrdb0_15 & 0xfc00) == 0xfc00 ? 0x800 : 0x0000; /* LS161 15-bit counter chain - loaded with RAM data (bar bits 10-13) */ ls161 = ((rcrdb0_15 & 0x8000) >> 1) | ls161_156_a | rcrs10 | (rcrdb0_15 & 0x03ff); /* SLD */ sld = (vprom[rva0_6] + vregs.slin_val) & 0x38; /* Determine the x-offset */ // x_offs = ls161 & 7; /* Fill vertical position shift register with bits for this line */ /* TODO; cheated slightly to shift stuff up one pixel*/ vp1 = buggyboy_rcram[(rva_offs + 0x1e2) >> 1] >= y ? 0 : 1; vp2 = buggyboy_rcram[(rva_offs + 0x1e4) >> 1] >= y ? 0 : 1; vp3 = buggyboy_rcram[(rva_offs + 0x1e6) >> 1] >= y ? 0 : 1; vp4 = buggyboy_rcram[(rva_offs + 0x1e8) >> 1] >= y ? 0 : 1; vp5 = buggyboy_rcram[(rva_offs + 0x1ea) >> 1] >= y ? 0 : 1; vp6 = buggyboy_rcram[(rva_offs + 0x1ec) >> 1] >= y ? 0 : 1; vp7 = buggyboy_rcram[(rva_offs + 0x1ee) >> 1] >= y ? 0 : 1; /* Stuff */ rm0 = vp7 ? BIT(vregs.scol, 4) : BIT(vregs.scol, 12); rm1 = vp7 ? BIT(vregs.scol, 5) : BIT(vregs.scol, 13); /* Wall/tunnel control */ rcmd = (vp7 ? vregs.scol : vregs.scol >> 8) & 0xf; /* Load 'em up */ LOAD_HPOS_COUNTER(0); LOAD_HPOS_COUNTER(1); LOAD_HPOS_COUNTER(2); LOAD_HPOS_COUNTER(3); /* Load the bank counter with accumulator bits 14-5 */ bank_cnt = (vregs.ba_val >> 5) & 0x3ff; /* Have we crossed a road gfx strip boundary? */ if (ls161 & 7) { buggyboy_get_roadpix(0, ls161, rva0_6, sld, &_rorevls, &rc0[0], &rc1[0], &rc2[0], &rc3[0], rom, prom0, prom1, prom2); buggyboy_get_roadpix(1, ls161, rva0_6, sld, &_rorevcs, &rc0[1], &rc1[1], &rc2[1], &rc3[1], rom, prom0, prom1, prom2); buggyboy_get_roadpix(2, ls161, rva0_6, sld, &_rorevrs, &rc0[2], &rc1[2], &rc2[2], &rc3[2], rom, prom0, prom1, prom2); } /* We can evaluate some of the pixel logic outside of the x-loop */ ic96_term1 = !tnlf || (vp5 && vp6) || (!vp3 && vp6) || (!vp4 && vp5) || (!vp3 && !vp4); ic96_o17 = (vp3 && vp4) || tnlmd0 || tnlmd1 || !vp1 || !tnlf; ic97_o12 = (!vp1 && !vp2 && !vp6) || (!vp1 && !vp2 && vp7) || (vp4 && !vp6) || (vp4 && vp7); ic97_o13 = (!vp1 && !vp2 && !vp5) || (!vp1 && !vp2 && vp7) || (vp3 && !vp5) || (vp3 && vp7); ic79_p19 = !(!(vp5 || vp6) || vp7) && !(tnlmd0 || tnlmd1); for (x = 0; x < 256; ++x) { UINT32 pix; UINT32 hp0_en, hp1_en, hp2_en, hp3_en; UINT32 ic97_o17; UINT32 ic97_o18; UINT32 ic97_o19; UINT32 ic96_o14; UINT32 ic96_o15; UINT32 ic96_o16; UINT32 ic79_o15; UINT32 ic79_o16; UINT32 ic79_o17; UINT32 ic82_o17; UINT32 ic82_o16; UINT32 ic82_o15; UINT32 ic82_o14; UINT32 ic80_o17; UINT32 ic80_o16; UINT32 ic80_o15; UINT32 ic80_o14; UINT32 ic78_o17; UINT32 ic78_o16; UINT32 ic78_o15; UINT32 ic78_o14; UINT32 ic48_o12, ic50_o12, ic52_o12; UINT32 ic48_o16, ic50_o16, ic52_o16; UINT32 ic48_o17, ic50_o17, ic52_o17; UINT32 ic48_o18, ic50_o18, ic52_o18; UINT32 ic48_o19, ic50_o19, ic52_o19; UINT32 tmp; UINT8 px0[3]; UINT8 px1[3]; UINT8 px2[3]; UINT8 px3[3]; UINT32 lfsr = vregs.wave_lfsr; UINT32 wave = (wave0 ^ BIT(lfsr, 0)) && (wave1 ^ BIT(lfsr, 3)) && BIT(lfsr, 5) && !BIT(lfsr, 15) && BIT(lfsr, 11) && BIT(lfsr, 13) && (rva20_6 < ((lfsr >> 8) & 0xf)); /* Strip pixel number */ pix = (ls161 & 7) ^ 7; /* Horizontal position counter enables - also used as PAL inputs */ hp0_en = !(hp0_cy || hps02); hp1_en = !(hp1_cy || hps12); hp2_en = !(hp2_cy || hps22); hp3_en = !(hp3_cy || hps32); /* Load in a new road gfx strip? */ if (!(ls161 & 7)) { buggyboy_get_roadpix(0, ls161, rva0_6, sld, &_rorevls, &rc0[0], &rc1[0], &rc2[0], &rc3[0], rom, prom0, prom1, prom2); buggyboy_get_roadpix(1, ls161, rva0_6, sld, &_rorevcs, &rc0[1], &rc1[1], &rc2[1], &rc3[1], rom, prom0, prom1, prom2); buggyboy_get_roadpix(2, ls161, rva0_6, sld, &_rorevrs, &rc0[2], &rc1[2], &rc2[2], &rc3[2], rom, prom0, prom1, prom2); } /* Road camber/banking */ if (BIT(vregs.ba_val, 23)) { bnkls = 1; bnkcs = 1; bnkrs = 1; } else if (vregs.ba_val & 0x007f8000) { bnkls = 0; bnkcs = 0; bnkrs = 0; } else { bnkls = bank_cnt < 0x400; bnkcs = bank_cnt < 0x300; bnkrs = bank_cnt < 0x200; } if (vregs.bank_mode) { bnkls ^= 1; bnkcs ^= 1; bnkrs ^= 1; } px0[0] = BIT(rc0[0], pix); px1[0] = BIT(rc1[0], pix); px2[0] = BIT(rc2[0], pix); px3[0] = BIT(rc3[0], pix); px0[1] = BIT(rc0[1], pix); px1[1] = BIT(rc1[1], pix); px2[1] = BIT(rc2[1], pix); px3[1] = BIT(rc3[1], pix); px0[2] = BIT(rc0[2], pix); px1[2] = BIT(rc1[2], pix); px2[2] = BIT(rc2[2], pix); px3[2] = BIT(rc3[2], pix); /* Now evaluate the pixel logic for each of the three screens TODO: A lot of this could be macrofied to avoid repetition. Shuffling the equations around would squeeze out some extra speed. */ /* Left */ ic96_o14 = ic96_term1 || (!hp1_en && hps10 && vp4 && !hps20 && !hps21) || (!hp1_en && hps10 && vp4 && hp2_en && !hps21) || (!hp1_en && hps10 && vp4 && vp6) || (hps11 && vp4 && !hps20 && !hps21) || (hps11 && vp4 && hp2_en && !hps21) || (vp5 && !hps20 && !hps21) || (!vp3 && !hps20 && !hps21) || (vp5 && hp2_en && !hps21) || (!vp3 && hp2_en && !hps21) || (!hp1_en && hps10 && !vp4) || (hps11 && vp4 && vp6) || (hps11 && !vp4); /* Centre */ ic96_o15 = ic96_term1 || (hps10 && hps11 && vp4 && hp2_en && !hps20) ||(!hp1_en && hps11 && vp4 && hp2_en && !hps20) || (hps10 && hps11 && vp6) || (!hp1_en && hps11 && vp6) || (hps10 && hps11 && vp4 && !hps21) || (!hp1_en && hps11 && vp4 && !hps21) || (vp5 && hp2_en && !hps20) || (!vp3 && hp2_en && !hps20) || (hps10 && hps11 && !vp4) || (!hp1_en && hps11 && !vp4) || (vp5 && !hps21) || (!vp3 && !hps21); /* Right */ ic96_o16 = ic96_term1 || (!hp1_en && hps10 && hps11 && vp6) || (!hp1_en && hps10 && hps11 && !vp4) || (!hp1_en && hps10 && hps11 && !hps20) || (!hp1_en && hps10 && hps11 && hp2_en) || (!hp1_en && hps10 && hps11 && !hps21) || (vp5 && !hps20) || (!vp3 && !hps20) || (vp5 && hp2_en) || (!vp3 && hp2_en) || (vp5 && !hps21) || (!vp3 && !hps21); tmp = (!vp1 && !vp2) || (vp2 && vp7); ic97_o17 = tmp || (!hp0_en && hps00 && vp2 && !hps30 && !hps31) || (!hp0_en && hps00 && vp2 && hp3_en && !hps31) || (hps01 && vp2 && !hps30 && !hps31) || (hps01 && vp2 && hp3_en && !hps31); ic97_o18 = tmp || (hps00 && hps01 && vp2 && hp3_en && !hps30) || (!hp0_en && hps01 && vp2 && hp3_en && !hps30) || (hps00 && hps01 && vp2 && !hps31) || (!hp0_en && hps01 && vp2 && !hps31); ic97_o19 = tmp || (!hp0_en && hps00 && hps01 && vp2 && !hps30) || (!hp0_en && hps00 && hps01 && vp2 && hp3_en) || (!hp0_en && hps00 && hps01 && vp2 && !hps31); /* Left */ { UINT32 P4, P6, P7, P18, P19; P4 = !(ic96_o16 && ic96_o17 && ic97_o19); P6 = BIT(sld, 3); P7 = (!vp5 && !vp6) || vp7 || !linf; P19 = wangl && bnkls; ic78_o17 = (_rorevls && !tnlmd1 && tnlmd0) || (!_rorevls && tnlmd1 && !tnlmd0) || (_rorevls && ic97_o12) || (!_rorevls && ic97_o13); P18 = ic78_o17; ic78_o16 = P7 || (px1[0] && !px0[0] && tnlmd1 && !tnlmd0) || (px2[0] && tnlmd1 && tnlmd0); ic78_o15 = !tnlf || (!P4 && px0[0] && P19) || (!P4 && px1[0] && P19) || (!P4 && P18) || (!P4 && px2[0]); ic78_o14 = !P6 || tnlmd0 || tnlmd1 || P7; } /* Centre */ { UINT32 P4, P6, P7, P18, P19; P4 = !(ic96_o15 && ic96_o17 && ic97_o18); P6 = BIT(sld, 3); P7 = (!vp5 && !vp6) || vp7 || !linf; P19 = wangl && bnkcs; ic80_o17 = (_rorevcs && !tnlmd1 && tnlmd0) || (!_rorevcs && tnlmd1 && !tnlmd0) || (_rorevcs && ic97_o12) || (!_rorevcs && ic97_o13); P18 = ic80_o17; ic80_o16 = P7 || (px1[1] && !px0[1] && tnlmd1 && !tnlmd0) || (px2[1] && tnlmd1 && tnlmd0); ic80_o15 = !tnlf || (!P4 && px0[1] && P19) || (!P4 && px1[1] && P19) || (!P4 && P18) || (!P4 && px2[1]); ic80_o14 = !P6 || tnlmd0 || tnlmd1 || P7; } /* Right */ { UINT32 P4, P6, P7, P18, P19; P4 = !(ic96_o14 && ic96_o17 && ic97_o17); P6 = BIT(sld, 3); P7 = (!vp5 && !vp6) || vp7 || !linf; P19 = wangl && bnkrs; ic82_o17 = (_rorevrs && !tnlmd1 && tnlmd0) || (!_rorevrs && tnlmd1 && !tnlmd0) || (_rorevrs && ic97_o12) || (!_rorevrs && ic97_o13); P18 = ic82_o17; ic82_o16 = P7 || (px1[2] && !px0[2] && tnlmd1 && !tnlmd0) || (px2[2] && tnlmd1 && tnlmd0); ic82_o15 = !tnlf || (!P4 && px0[2] && P19) || (!P4 && px1[2] && P19) || (!P4 && P18) || (!P4 && px2[2]); ic82_o14 = !P6 || tnlmd0 || tnlmd1 || P7; } ic79_o17 = (!px2[0] && _rorevls && ic78_o15) || (tnlf && !ic97_o19) || (tnlf && ic79_p19 && px2[0] && ic78_o15); ic79_o16 = (!px2[1] && _rorevcs && ic80_o15) || (tnlf && !ic97_o18) || (tnlf && ic79_p19 && px2[1] && ic80_o15); ic79_o15 = (!px2[2] && _rorevrs && ic82_o15) || (tnlf && !ic97_o17) || (tnlf && ic79_p19 && px2[2] && ic82_o15); /* Left */ { UINT32 P5,P7, P8; UINT32 rcsd0_3; UINT32 cprom_addr; P5 = BIT(tcmd, 3) ? ((!vp5 && !vp6) || vp7 || !linf) : ic78_o16; P7 = BIT(sld, 5); P8 = BIT(sld, 4); ic48_o19 = (px2[0] && !rva8) || !bnkls || !P5 || !ic78_o15; if (ic48_o19) { ic48_o12 = ic78_o14 && ( (px2[0] && px1[0] && px0[0] && rm1 && !rm0) || (!px2[0] && px1[0] && px0[0] && !P8 && rm0) || (px2[0] && px0[0] && !P7 && !rm1 && !rm0) || (px2[0] && !px1[0] && px0[0] && !P7 && !rm1) || (px2[0] && px1[0] && px0[0] && !P7 && !P8) || (px2[0] && px1[0] && px0[0] && !P8 && rm1) || (!px2[0] && !px3[0] && !rm0) || (!px1[0] && !px3[0] && rm1) || (!px2[0] && !px1[0] && !px3[0]) || (rva8) || (!px0[0] && !px3[0]) || (!ic78_o15) || (!P5) ); ic48_o16 = (px2[0] && P5 && rm1) || (P5 && rva8 && ic78_o15) || (!px0[0] && P5) || !ic78_o15; ic48_o17 = (px0[0] && P5 && !rm0 && ic78_o15) || (!px1[0] && P5 && ic78_o15) || (P5 && rva8 && ic78_o15); ic48_o18 = (!px2[0] && P5 && ic78_o15) || (P5 && rva8 && ic78_o15); if (vp6 || ic78_o16) { if (!(ic78_o15 && P5)) cprom_addr = (tcmd & 0x7) | (ic78_o16 << 3); else cprom_addr = rcmd; cprom_addr = (~cprom_addr & 0xf) << 4; } else cprom_addr = 0xf0; cprom_addr |= (ic79_o17 << 3) | (ic48_o18 << 2) | (ic48_o17 << 1) | ic48_o16; rcsd0_3 = rcols[cprom_addr] & 0xf; *(bmpaddr + 0) = 0x40 | (!wave << 5) | (ic48_o12 << 4) | rcsd0_3; } else *(bmpaddr + 0) = 0; } /* Centre */ { UINT32 rcsd0_3; UINT32 cprom_addr; UINT32 P5, P7, P8; P5 = BIT(tcmd, 3) ? ((!vp5 && !vp6) || vp7 || !linf) : ic80_o16; P7 = BIT(sld, 5); P8 = BIT(sld, 4); ic50_o19 = (px2[1] && !rva8) || !bnkcs || !P5 || !ic80_o15; if (ic50_o19) { if (ic80_o14) ic50_o12 = (px2[1] && px1[1] && px0[1] && rm1 && !rm0) || (!px2[1] && px1[1] && px0[1] && !P8 && rm0) || (px2[1] && px0[1] && !P7 && !rm1 && !rm0) || (px2[1] && !px1[1] && px0[1] && !P7 && !rm1) || (px2[1] && px1[1] && px0[1] && !P7 && !P8) || (px2[1] && px1[1] && px0[1] && !P8 && rm1) || (!px2[1] && !px3[1] && !rm0) || (!px1[1] && !px3[1] && rm1) || (!px2[1] && !px1[1] && !px3[1]) || (rva8) || (!px0[1] && !px3[1]) || (!ic80_o15) || (!P5); else ic50_o12 = 0; ic50_o16 = (P5 && px2[1] && rm1) || (P5 && rva8 && ic80_o15) || (P5 && !px0[1]) || !ic80_o15; ic50_o17 = (P5 && px0[1] && !rm0 && ic80_o15) || (P5 && !px1[1] && ic80_o15) || (P5 && rva8 && ic80_o15); ic50_o18 = (P5 && !px2[1] && ic80_o15) || (P5 && rva8 && ic80_o15); if (vp6 || ic80_o16) { if (!(ic80_o15 && P5)) cprom_addr = (tcmd & 0x7) | (ic80_o16 << 3); else cprom_addr = rcmd; cprom_addr = ((~cprom_addr) & 0xf) << 4; } else cprom_addr = 0xf0; cprom_addr |= (ic79_o16 << 3) | (ic50_o18 << 2) | (ic50_o17 << 1) | ic50_o16; rcsd0_3 = rcols[cprom_addr] & 0xf; *(bmpaddr + 256) = 0x40 | (!wave << 5) | (ic50_o12 << 4) | rcsd0_3; } else *(bmpaddr + 256) = 0; } /* Right */ { UINT32 rcsd0_3; UINT32 cprom_addr; UINT32 P5, P7, P8; P5 = BIT(tcmd, 3) ? ((!vp5 && !vp6) || vp7 || !linf) : ic82_o16; P7 = BIT(sld, 5); P8 = BIT(sld, 4); ic52_o19 = (px2[2] && !rva8) || !bnkrs || !P5 || !ic82_o15; if (ic52_o19) { ic52_o12 = ic82_o14 && ( (px2[2] && px1[2] && px0[2] && rm1 && !rm0) || (!px2[2] && px1[2] && px0[2] && !P8 && rm0) || (px2[2] && px0[2] && !P7 && !rm1 && !rm0) || (px2[2] && !px1[2] && px0[2] && !P7 && !rm1) || (px2[2] && px1[2] && px0[2] && !P7 && !P8) || (px2[2] && px1[2] && px0[2] && !P8 && rm1) || (!px2[2] && !px3[2] && !rm0) || (!px1[2] && !px3[2] && rm1) || (!px2[2] && !px1[2] && !px3[2]) || (rva8) || (!px0[2] && !px3[2]) || (!ic82_o15) || (!P5) ); ic52_o16 = (px2[2] && P5 && rm1) || (P5 && rva8 && ic82_o15) || (!px0[2] && P5) || !ic82_o15; ic52_o17 = (px0[2] && P5 && !rm0 && ic82_o15) || (!px1[2] && P5 && ic82_o15) || (P5 && rva8 && ic82_o15); ic52_o18 = (P5 && ic82_o15 && !px2[2]) || (P5 && ic82_o15 && rva8); if (vp6 || ic82_o16) { if (!(ic82_o15 && P5)) cprom_addr = (tcmd & 0x7) | (ic82_o16 << 3); else cprom_addr = rcmd; cprom_addr = (~cprom_addr & 0xf) << 4; } else cprom_addr = 0xf0; cprom_addr |= (ic79_o15 << 3) | (ic52_o18 << 2) | (ic52_o17 << 1) | ic52_o16; rcsd0_3 = rcols[cprom_addr] & 0xf; *(bmpaddr + 512) = 0x40 | (!wave << 5) | (ic52_o12 ? 0x10 : 0) | rcsd0_3; } else *(bmpaddr + 512) = 0; } /* Now update counters and whatnot */ ++bmpaddr; UPDATE_HPOS(0); UPDATE_HPOS(1); UPDATE_HPOS(2); UPDATE_HPOS(3); /* Update the wave LFSR */ vregs.wave_lfsr = (vregs.wave_lfsr << 1) | (BIT(vregs.wave_lfsr, 6) ^ !BIT(vregs.wave_lfsr, 15)); /* Increment the bank counter */ bank_cnt = (bank_cnt + 1) & 0x7ff; /* X pos */ ls161 = (ls161 + 1) & 0x7fff; } /* WANGL active? Update the 8-bit counter */ if (wangl) { if (BIT(vregs.flags, BB_RDFLAG_TNLMD0)) --vregs.wa8; else ++vregs.wa8; } /* No carry out - just increment */ if (vregs.wa4 != 0xf) ++vregs.wa4; else { /* Carry out; increment again on /TMG2S rise */ if (wangl) { if (BIT(vregs.flags, BB_RDFLAG_TNLMD0)) --vregs.wa8; else ++vregs.wa8; } vregs.wa4 = 1; } /* Update accumulator */ vregs.h_val += vregs.h_inc; /* Seems correct */ sf = vregs.shift; if ((vregs.shift & 0x80) == 0) { vregs.shift <<= 1; if ((sf & 0x08) == 0) vregs.shift |= BIT(vregs.h_val, 15); } if ((sf & 0x08) && !(vregs.shift & 0x08)) vregs.h_inc = vregs.gas; /* Finally, increment the banking accumulator */ vregs.ba_val = (vregs.ba_val + vregs.ba_inc) & 0x00ffffff; } } static void buggybjr_draw_road(running_machine &machine, UINT8 *bitmap, int wide) { tx1_state *state = machine.driver_data(); UINT16 *buggyboy_rcram = state->m_rcram; vregs_t &vregs = state->m_vregs; INT32 x; UINT32 y; UINT16 rva_offs; UINT32 tnlmd0; UINT32 tnlmd1; UINT32 linf; UINT32 tnlf; UINT32 wangl; UINT32 tcmd; UINT32 wave0; UINT32 wave1; UINT32 rva20_6; /* ROM/PROM lookup tables */ const UINT8 *rcols = (UINT8*)(machine.region("proms")->base() + 0x1500); const UINT8 *rom = machine.region("road")->base(); const UINT8 *prom0 = rom + 0x4000; const UINT8 *prom1 = rom + 0x4200; const UINT8 *prom2 = rom + 0x4400; const UINT8 *vprom = rom + 0x4600; /* Extract constant values */ tcmd = ((vregs.scol & 0xc000) >> 12) | ((vregs.scol & 0x00c0) >> 6); tnlmd0 = BIT(vregs.flags, BB_RDFLAG_TNLMD0); tnlmd1 = BIT(vregs.flags, BB_RDFLAG_TNLMD1); linf = BIT(vregs.flags, BB_RDFLAG_LINF); tnlf = BIT(vregs.flags, BB_RDFLAG_TNLF); wangl = BIT(vregs.flags, BB_RDFLAG_WANGL); wave0 = BIT(vregs.flags, BB_RDFLAG_WAVE0); wave1 = BIT(vregs.flags, BB_RDFLAG_WAVE1); rva_offs = BIT(vregs.flags, BB_RDFLAG_RVA7) ? 0x800 : 0xc00; for (y = 0; y < 240; ++y) { UINT8 rva0_6; UINT8 ram_addr; UINT16 rcrdb0_15; UINT16 rcrs10; UINT16 ls161_156_a; UINT16 ls161; UINT8 sld; UINT32 rva8; UINT32 rm0, rm1; UINT32 rcmd; UINT32 bnkcs = 1; // UINT32 x_offs; UINT8 sf; /* Vertical positions shift register */ UINT32 ram_val; UINT32 hp; UINT32 vp1, vp2, vp3, vp4, vp5, vp6, vp7; /* PAL outputs */ UINT32 ic4_o12; UINT32 ic4_o13; UINT32 ic149_o15; UINT32 ic151_o14; /* Horizontal positions */ UINT32 hp0, hp1, hp2, hp3; UINT8 hps00, hps01, hps02; UINT8 hps10, hps11, hps12; UINT8 hps20, hps21, hps22; UINT8 hps30, hps31, hps32; /* Road pixel data planes */ UINT8 rc0 = 0, rc1 = 0, rc2 = 0, rc3 = 0; /* Horizontal position counter carry out */ UINT8 hp0_cy = 0, hp1_cy = 0, hp2_cy = 0, hp3_cy = 0; UINT8 *bmpaddr = bitmap + (y * 256); UINT32 bank_cnt; UINT32 _rorevcs = 0; rva8 = (vregs.h_val & 0x8000) || !(vregs.shift & 0x80); /* Get RVA0_6 from TZ113 accumulator chain @ 122/123 */ rva0_6 = (vregs.h_val >> 7) & 0x7f; /* For /WAVE bit logic later */ rva20_6 = ((rva0_6 >> 3) & 0xe) | ((rva0_6 & 2) >> 1); /* RVA is inverted! */ ram_addr = (~rva0_6 & 0x7f) << 1; /* Get the road RAM data for this line */ rcrdb0_15 = buggyboy_rcram[(rva_offs + ram_addr) >> 1]; /* If 15-10 == 000000, then 0 */ rcrs10 = rcrdb0_15 & 0xfc00 ? 0x0400 : 0x0000; /* If 15-10 == 111111, then 1 */ ls161_156_a = (rcrdb0_15 & 0xfc00) == 0xfc00 ? 0x800 : 0x0000; /* LS161 15-bit counter chain - loaded with RAM data (bar bits 10-13) */ ls161 = ((rcrdb0_15 & 0x8000) >> 1) | ls161_156_a | rcrs10 | (rcrdb0_15 & 0x03ff); /* SLD */ sld = (vprom[rva0_6] + vregs.slin_val) & 0x38; /* Determine the x-offset */ // x_offs = ls161 & 7; /* Fill vertical position shift register with bits for this line */ /* TODO; cheated slightly to shift stuff up one pixel*/ vp1 = buggyboy_rcram[(rva_offs + 0x1e2) >> 1] >= y ? 0 : 1; vp2 = buggyboy_rcram[(rva_offs + 0x1e4) >> 1] >= y ? 0 : 1; vp3 = buggyboy_rcram[(rva_offs + 0x1e6) >> 1] >= y ? 0 : 1; vp4 = buggyboy_rcram[(rva_offs + 0x1e8) >> 1] >= y ? 0 : 1; vp5 = buggyboy_rcram[(rva_offs + 0x1ea) >> 1] >= y ? 0 : 1; vp6 = buggyboy_rcram[(rva_offs + 0x1ec) >> 1] >= y ? 0 : 1; vp7 = buggyboy_rcram[(rva_offs + 0x1ee) >> 1] >= y ? 0 : 1; /* Stuff */ rm0 = vp7 ? BIT(vregs.scol, 4) : BIT(vregs.scol, 12); rm1 = vp7 ? BIT(vregs.scol, 5) : BIT(vregs.scol, 13); /* Wall/tunnel control */ rcmd = (vp7 ? vregs.scol : vregs.scol >> 8) & 0xf; /* Load 'em up */ LOAD_HPOS_COUNTER(0); LOAD_HPOS_COUNTER(1); LOAD_HPOS_COUNTER(2); LOAD_HPOS_COUNTER(3); /* Some PAL equations that we can evaluate outside of the x-loop */ ic4_o12 = (!vp1 && !vp2 && !vp6) || (!vp1 && !vp2 && vp7) || (vp4 && !vp6) || (vp4 && vp7); ic4_o13 = (!vp1 && !vp2 && !vp5) || (!vp1 && !vp2 && vp7) || (vp3 && !vp5) || (vp3 && vp7); ic149_o15 = (!vp5 && !vp6) || vp7 || !linf; ic151_o14 = !BIT(sld, 3) || tnlmd0 || tnlmd1 || ic149_o15; /* Load the bank counter with accumulator bits 14-5 */ bank_cnt = (vregs.ba_val >> 5) & 0x3ff; /* Have we crossed a road gfx strip boundary? */ if (ls161 & 7) buggyboy_get_roadpix(1, ls161, rva0_6, sld, &_rorevcs, &rc0, &rc1, &rc2, &rc3, rom, prom0, prom1, prom2); for (x = 0; x < 256; ++x) { UINT32 pix; UINT32 hp0_en, hp1_en, hp2_en, hp3_en; UINT32 ic149_o16; UINT32 ic4_o18; UINT32 ic3_o15; UINT32 ic150_o12 = 0; UINT32 ic150_o16; UINT32 ic150_o17; UINT32 ic150_o18; UINT32 ic150_o19; UINT32 ic151_o15; UINT32 ic151_o16; UINT32 ic151_o17; UINT32 rcsd0_3 = 0; UINT32 sld5 = BIT(sld, 5); UINT32 sld4 = BIT(sld, 4); UINT32 mux; UINT32 cprom_addr; UINT8 px0, px1, px2, px3; /* Strip pixel number */ pix = (ls161 & 7) ^ 7; /* Horizontal position counter enables - also used as PAL inputs */ hp0_en = !(hp0_cy || hps02); hp1_en = !(hp1_cy || hps12); hp2_en = !(hp2_cy || hps22); hp3_en = !(hp3_cy || hps32); /* Load in a new road gfx strip? */ if (!(ls161 & 7)) buggyboy_get_roadpix(1, ls161, rva0_6, sld, &_rorevcs, &rc0, &rc1, &rc2, &rc3, rom, prom0, prom1, prom2); /* Road camber */ if (vregs.bank_mode == 0) { if (BIT(vregs.ba_val, 23)) bnkcs = 1; else if (vregs.ba_val & 0x007f8000) bnkcs = 0; else bnkcs = bank_cnt < 0x300; } else { if (BIT(vregs.ba_val, 23)) bnkcs = 0; else if (vregs.ba_val & 0x007f8000) bnkcs = 1; else bnkcs = bank_cnt >= 0x300; } px0 = BIT(rc0, pix); px1 = BIT(rc1, pix); px2 = BIT(rc2, pix); px3 = BIT(rc3, pix); /* Now go through and evaluate all the pixel logic */ if (vp2) ic4_o18 = (hps00 && hps01 && hp3_en && !hps30) || (!hp0_en && hps01 && hp3_en && !hps30) || (hps00 && hps01 && !hps31) || (!hp0_en && hps01 && !hps31) || vp7; else ic4_o18 = !vp1; if (tnlf) ic3_o15 = (vp4 && !vp6 && !hp2_en && hps21) || (vp4 && !vp6 && hps20 && hps21) || (vp1 && !vp4 && !tnlmd1 && !tnlmd0) || (vp1 && !vp3 && !tnlmd1 && !tnlmd0) || (hp1_en && !hps10 && vp3 && !vp5) || (!hps11 && vp3 && !vp5); else ic3_o15 = !ic4_o18; ic151_o17 = (_rorevcs && !tnlmd1 && tnlmd0) || (!_rorevcs && tnlmd1 && !tnlmd0) || (_rorevcs && ic4_o12) || (!_rorevcs && ic4_o13); if (!ic3_o15) ic151_o15 = (px0 && (bnkcs && wangl)) || (px1 && (bnkcs && wangl)) || ic151_o17 || px2 || !tnlf; else ic151_o15 = !tnlf; ic151_o16 = (px1 && !px0 && tnlmd1 && !tnlmd0) || (px2 && tnlmd1 && tnlmd0) || ic149_o15; mux = BIT(tcmd, 3) ? ic149_o15 : ic151_o16; ic150_o19 = (px2 && !rva8) || !bnkcs || !mux || !ic151_o15; /* Don't calculate the pixel colour if not visible */ if (ic150_o19) { ic149_o16 = (_rorevcs && !px2 && ic151_o15) || (tnlf && vp5 && !vp7 && px2 && !tnlmd0 && !tnlmd1 && ic151_o15) || (tnlf && vp6 && !vp7 && px2 && !tnlmd0 && !tnlmd1 && ic151_o15) || (tnlf && !ic4_o18); ic150_o16 = (px2 && mux && rm1) || (mux && rva8 && ic151_o15) || (!px0 && mux) || !ic151_o15; { UINT32 a = mux && ic151_o15; ic150_o17 = (a && !rm0 && px0) || (a && !px1) || (rva8 && a); ic150_o18 = (a && !px2) || (rva8 && a); } if (ic151_o14) ic150_o12 = rva8 || !mux || !ic151_o15 || (px2 && px1 && px0 && rm1 && !rm0) || (!px2 && px1 && px0 && !sld4 && rm0) || (px2 && px0 && !sld5 && !rm1 && !rm0) || (px2 && !px1 && px0 && !sld5 && !rm1) || (px2 && px1 && px0 && !sld5 && !sld4) || (px2 && px1 && px0 && !sld4 && rm1) || (!px2 && !px3 && !rm0) || (!px1 && !px3 && rm1) || (!px2 && !px1 && !px3) || (!px0 && !px3); else ic150_o12 = 0; if (vp6 || ic151_o16) { UINT32 ic150_i5 = BIT(tcmd, 3) ? ic149_o15 : ic151_o16; if (!(ic151_o15 && ic150_i5)) cprom_addr = (tcmd & 0x7) | (ic151_o16 ? 0x08 : 0); else cprom_addr = rcmd; /* Inverted! */ cprom_addr = ((~cprom_addr) & 0xf) << 4; } else cprom_addr = 0xf0; cprom_addr |= (ic149_o16 ? 0x8 : 0) | (ic150_o18 ? 0x4 : 0) | (ic150_o17 ? 0x2 : 0) | (ic150_o16 ? 0x1 : 0); /* Lower four bits of colour output come from PROM BB7 @ 188 */ rcsd0_3 = rcols[cprom_addr] & 0xf; { UINT32 lfsr = vregs.wave_lfsr; UINT32 wave = (wave0 ^ BIT(lfsr, 0)) && (wave1 ^ BIT(lfsr, 3)) && BIT(lfsr, 5) && !BIT(lfsr, 15) && BIT(lfsr, 11) && BIT(lfsr, 13) && (rva20_6 < ((lfsr >> 8) & 0xf)); *bmpaddr++ = 0x40 | (wave ? 0 : 0x20) | (ic150_o12 ? 0x10 : 0) | rcsd0_3; } } else *bmpaddr++ = 0; /* Update the various horizontal counters */ UPDATE_HPOS(0); UPDATE_HPOS(1); UPDATE_HPOS(2); UPDATE_HPOS(3); /* Update the LFSR */ vregs.wave_lfsr = (vregs.wave_lfsr << 1) | (BIT(vregs.wave_lfsr, 6) ^ !BIT(vregs.wave_lfsr, 15)); /* Increment the bank counter */ bank_cnt = (bank_cnt + 1) & 0x7ff; /* X pos */ ls161 = (ls161 + 1) & 0x7fff; } /* WANGL active? Then update the 8-bit counter */ if (wangl) { if (BIT(vregs.flags, BB_RDFLAG_TNLMD0)) --vregs.wa8; else ++vregs.wa8; } /* No carry out - just increment */ if (vregs.wa4 != 0xf) ++vregs.wa4; else { /* Carry out; increment again on /TMG2S rise */ if (wangl) { if (BIT(vregs.flags, BB_RDFLAG_TNLMD0)) --vregs.wa8; else ++vregs.wa8; } vregs.wa4 = 1; } /* Update accumulator */ vregs.h_val += vregs.h_inc; /* Seems correct */ sf = vregs.shift; if ((vregs.shift & 0x80) == 0) { vregs.shift <<= 1; if ((sf & 0x08) == 0) vregs.shift |= BIT(vregs.h_val, 15); } if ((sf & 0x08) && !(vregs.shift & 0x08)) vregs.h_inc = vregs.gas; /* Finally, increment the banking accumulator */ vregs.ba_val = (vregs.ba_val + vregs.ba_inc) & 0x00ffffff; } } /*************************************************************************** Buggy Boy Object Drawing X-scaling isn't quite right but you wouldn't notice... -------- xxxxxxxx Object number xxxxxxxx -------- Y position xxxxxxxx xxxxxxxx Y scale value -------- xxxxxxxx X scale 00 = Invisible? 80 = 1:1 FF = Double size xxxxxxxx -------- Attributes xxxxxxxx xxxxxxxx Y scale delta ------xx xxxxxxxx X position **************************************************************************/ static void buggyboy_draw_objs(running_machine &machine, UINT8 *bitmap, int wide) { tx1_state *state = machine.driver_data(); UINT16 *buggyboy_objram = state->m_objram; #define FRAC 16 UINT32 offs; UINT32 x_mask; UINT32 x_stride; /* The many lookup table ROMs */ const UINT8 *const bug13 = (UINT8*)machine.region("obj_luts")->base(); const UINT8 *const bug18s = bug13 + 0x2000; const UINT8 *const bb8 = (UINT8*)machine.region("proms")->base() + 0x1600; const UINT8 *const bug16s = (UINT8*)machine.region("obj_map")->base(); const UINT8 *const bug17s = bug16s + 0x8000; const UINT8 *const bb9o = (UINT8*)machine.region("proms")->base() + 0x500; const UINT8 *const bb9e = bb9o + 0x800; const UINT8 *const pixdata_rgn = (UINT8*)machine.region("obj_tiles")->base(); if (wide) { x_mask = 0x7ff; x_stride = 768; } else { x_mask = 0x3ff; x_stride = 256; } for (offs = 0; offs <= 0x300; offs += 8) { UINT32 x; UINT32 y; UINT32 gxflip; UINT32 x_scale; UINT32 x_step; UINT16 y_scale; UINT16 y_step; UINT8 pctmp0_7; UINT8 code; /* Check for end of object list */ if ((buggyboy_objram[offs] & 0xff00) == 0xff00) break; /* X scale */ x_scale = buggyboy_objram[offs + 2] & 0xff; /* TODO: Confirm against hardware? */ if (x_scale == 0) continue; /* 16-bit y-scale accumulator */ y_scale = buggyboy_objram[offs + 1]; y_step = buggyboy_objram[offs + 3]; /* Object number */ code = buggyboy_objram[offs] & 0xff; /* Attributes */ pctmp0_7 = buggyboy_objram[offs + 2] >> 8; /* Global x-flip */ gxflip = (pctmp0_7 & 0x80) >> 7; /* Add 1 to account for line buffering */ y = (buggyboy_objram[offs] >> 8) + 1; for (; y < 240; ++y) { UINT32 rom_addr2 = 0; UINT8 bug17s_data = 0; UINT8 bug16s_data; /* Are we drawing on this line? */ // TODO: See big lampposts. if (y_scale & 0x8000) break; { UINT32 psa0_12; UINT32 bug13_addr; UINT32 bug13_data; UINT32 rom_addr; UINT32 x_acc; UINT32 newtile = 1; UINT32 dataend = 0; UINT8 data1 = 0; UINT8 data2 = 0; UINT32 xflip = 0; UINT32 opcd10_11; UINT32 opcd8_9; UINT32 opcd0_11 = 0; UINT32 lasttile = 0; /* Use the object code to lookup the tile sequence data */ bug13_addr = code << 4; bug13_addr |= ((y_scale >> 11) & 0xf); bug13_data = bug13[bug13_addr]; /* Reached the bottom of the object */ if (bug13_data == 0xff) break; psa0_12 = (((code & 0x80) << 5) | ((code & 0x40) << 6)) & 0x1000; psa0_12 |= ((bb8[code] << 8) | bug13_data) & 0x1fff; /* Static part of the BUG17S/BUG16S ROM address */ rom_addr = (psa0_12 & ~0xff) << 2; /* Prepare the x-scaling */ x_step = (128 << FRAC) / x_scale; x_acc = (psa0_12 & 0xff) << (FRAC + 5); /* TODO Add note */ x = buggyboy_objram[offs + 4] & x_mask; for (;;) { /* Get data and attributes for an 8x8 tile */ if (newtile) { UINT32 pscb0_11; UINT32 psbb0_15; UINT32 psbb6_7; UINT32 rombank; UINT8 *romptr; UINT32 bug18s_data; UINT32 low_addr = ((x_acc >> (FRAC + 3)) & x_mask); /* Objects are grouped by width (either 16, 8 or 4 tiles) in the LUT ROMs. The ROM address lines therefore indicate width and are used to determine the correct scan order when x-flip is set. */ if (gxflip) { UINT32 xor_mask; if (BIT(psa0_12, 11) || !BIT(psa0_12, 12)) xor_mask = 0xf; else if (!BIT(psa0_12, 9)) xor_mask = 0x7; else xor_mask = 0x3; rom_addr2 = rom_addr + (low_addr ^ xor_mask); } else rom_addr2 = rom_addr + low_addr; bug17s_data = bug17s[rom_addr2 & 0x7fff]; if ((bug17s_data & 0x40) && dataend) lasttile = 1; dataend |= (bug17s_data & 0x40); /* Retrieve data for an 8x8 tile */ bug16s_data = bug16s[rom_addr2 & 0x7fff]; psbb0_15 = (bug17s_data << 8) | bug16s_data; psbb6_7 = (BIT(psbb0_15, 12) ? psbb0_15 : (pctmp0_7 << 6)) & 0xc0; /* Form the tile ROM address */ pscb0_11 = ((((psbb0_15 & ~0xc0) | psbb6_7) << 3) | ((y_scale >> 8) & 7)) & 0x7fff; /* Choose from one of three banks */ rombank = ((BIT(pctmp0_7, 4) << 1) | BIT(psbb0_15, 13)) & 3; romptr = (UINT8*)(pixdata_rgn + rombank * (0x8000 * 2)); /* Get raw 8x8 pixel row data */ data1 = *(pscb0_11 + romptr); data2 = *(pscb0_11 + romptr + 0x8000); /* Determine flip state (global XOR local) */ xflip = gxflip ^ !BIT(psbb0_15, 15); bug18s_data = bug18s[ (BIT(pctmp0_7, 4) << 13) | (BIT(psbb0_15, 13) << 12) | (psbb0_15 & ~0xf0c0) | psbb6_7 ]; /* Get the colour data. Note that bits 11 and 10 are inverted */ opcd10_11 = ((pctmp0_7 << 8) & 0xc00) ^ 0xc00; opcd8_9 = ((pctmp0_7 & 0x60) << 3); opcd0_11 = (opcd10_11 | opcd8_9 | bug18s_data) & 0xfff; newtile = 0; } /* Draw a pixel? */ if (x < x_stride) { UINT8 pix; UINT8 bit; bit = (x_acc >> FRAC) & 7; if (xflip) bit ^= 7; pix = (((data1 >> bit) & 1) << 1) | ((data2 >> bit) & 1); /* Write the pixel if not transparent */ if (!(!(opcd0_11 & 0x80) && !pix)) { UINT8 color; UINT32 bb9_addr; bb9_addr = ((opcd0_11 << 1) & 0x600) | ((opcd0_11 & 0x7f) << 2) | pix; color = ((opcd0_11 >> 6) & 0x30); /* Inverted on schematic */ if (x & 1) color = ~(color | bb9o[bb9_addr]) & 0x3f; else color = ~(color | bb9e[bb9_addr]) & 0x3f; *(bitmap + x_stride*y + x) = 0x40 | color; } } /* Check if we've stepped into a new 8x8 tile */ if ((((x_acc + x_step) >> (FRAC + 3)) & x_mask) != ((x_acc >> (FRAC + 3)) & x_mask)) { if (lasttile) break; newtile = 1; } x = (x + 1) & x_mask; x_acc += x_step; } }// if (yscale) y_scale += y_step; } /* for (y) */ }/* for (offs) */ } /************************************* * * Video Control Registers * *************************************/ /* 2400-24FF is road control (R/W) /GAS = 24XX: /BASET0 = 2400-F, 2410-F /BASET1 = 2420-F, 2430-F /BSET = 2440-F, 2450-F /HASET = 2460-F, 2470-F /HSET = 2480-F, 2490-F /WASET = 24A0-F, 24B0-F /FLAGS = 24E0-F, 24F0-F */ WRITE16_HANDLER( buggyboy_gas_w ) { tx1_state *state = space->machine().driver_data(); vregs_t &vregs = state->m_vregs; offset <<= 1; switch (offset & 0xe0) { case 0x00: { vregs.ba_inc &= ~0x0000ffff; vregs.ba_inc |= data; if (!(offset & 2)) vregs.ba_val &= ~0x0000ffff; break; } case 0x20: { data &= 0xff; vregs.ba_inc &= ~0xffff0000; vregs.ba_inc |= data << 16; vregs.bank_mode = data & 1; if (!(offset & 2)) vregs.ba_val &= ~0xffff0000; break; } case 0x40: { /* Ignore data? */ if (offset & 2) vregs.ba_val = (vregs.ba_inc + vregs.ba_val) & 0x00ffffff; break; } case 0x60: { vregs.h_inc = data; vregs.shift = 0; if (!(offset & 2)) vregs.h_val = 0; break; } case 0x80: { /* Ignore data? */ if (offset & 2) vregs.h_val += vregs.h_inc; break; } case 0xa0: { vregs.wa8 = data >> 8; vregs.wa4 = 0; break; } case 0xe0: { cputag_set_input_line(space->machine(), "math_cpu", INPUT_LINE_TEST, CLEAR_LINE); vregs.flags = data; break; } } /* Value is latched by LS373 76/77 */ vregs.gas = data; } WRITE16_HANDLER( buggyboy_sky_w ) { tx1_state *state = space->machine().driver_data(); state->m_vregs.sky = data; } WRITE16_HANDLER( buggyboy_scolst_w ) { tx1_state *state = space->machine().driver_data(); state->m_vregs.scol = data; } /************************************* * * Core Functions * *************************************/ static void bb_combine_layers(running_machine &machine, bitmap_t *bitmap, int screen) { tx1_state *state = machine.driver_data(); UINT8 *chr_pal = machine.region("proms")->base() + 0x400; UINT32 bmp_stride; UINT32 x_offset; UINT32 y; if (screen < 0) { bmp_stride = 256; x_offset = 0; } else { bmp_stride = 768; x_offset = 256 * screen; } for (y = 0; y < 240; ++y) { UINT32 x; UINT32 bmp_offset = y * bmp_stride + x_offset; UINT8 *chr_addr = state->m_chr_bmp + bmp_offset; UINT8 *rod_addr = state->m_rod_bmp + bmp_offset; UINT8 *obj_addr = state->m_obj_bmp + bmp_offset; UINT32 sky_en = BIT(state->m_vregs.sky, 7); UINT32 sky_val = (((state->m_vregs.sky & 0x7f) + y) >> 2) & 0x3f; UINT16 *bmp_addr = BITMAP_ADDR16(bitmap, y, 0); for (x = 0; x < 256; ++x) { UINT32 out_val; UINT32 char_val = *chr_addr++; UINT32 char_6_7 = (char_val & 0xc0) >> 2; UINT32 obj_val = *obj_addr++; UINT32 obj6 = BIT(obj_val, 6); UINT32 rod_val = *rod_addr++; UINT32 rod6 = BIT(rod_val, 6); UINT32 chr = !(BIT(char_val, 7) && (char_val & 3) ); UINT32 sel = ( ( BIT(obj_val, 6) && chr) || ( sky_en && !(char_val & 3) && (!obj6 && !rod6) ) ) ? 0 : 1; sel |= (!(obj6 || rod6) || !chr) ? 2 : 0; /* Select the layer */ if (sel == 0) out_val = obj_val & 0x3f; else if (sel == 1) out_val = rod_val & 0x3f; else if (sel == 2) out_val = sky_val; else out_val = char_6_7 + chr_pal[char_val]; *bmp_addr++ = (sel << 6) + out_val; } } } VIDEO_START( buggyboy ) { tx1_state *state = machine.driver_data(); /* Allocate some bitmaps */ state->m_chr_bmp = auto_alloc_array(machine, UINT8, 3 * 256 * 240); state->m_obj_bmp = auto_alloc_array(machine, UINT8, 3 * 256 * 240); state->m_rod_bmp = auto_alloc_array(machine, UINT8, 3 * 256 * 240); /* Set a timer to run the interrupts */ state->m_interrupt_timer = machine.scheduler().timer_alloc(FUNC(interrupt_callback)); /* /CUDISP CRTC interrupt */ state->m_interrupt_timer->adjust(machine.primary_screen->time_until_pos(CURSOR_YPOS, CURSOR_XPOS)); } VIDEO_START( buggybjr ) { tx1_state *state = machine.driver_data(); /* Allocate some bitmaps */ state->m_chr_bmp = auto_alloc_array(machine, UINT8, 256 * 240); state->m_obj_bmp = auto_alloc_array(machine, UINT8, 256 * 240); state->m_rod_bmp = auto_alloc_array(machine, UINT8, 256 * 240); /* Set a timer to run the interrupts */ state->m_interrupt_timer = machine.scheduler().timer_alloc(FUNC(interrupt_callback)); /* /CUDISP CRTC interrupt */ state->m_interrupt_timer->adjust(machine.primary_screen->time_until_pos(CURSOR_YPOS, CURSOR_XPOS)); } SCREEN_EOF( buggyboy ) { tx1_state *state = machine.driver_data(); /* /VSYNC: Update TZ113 @ 219 */ state->m_vregs.slin_val += state->m_vregs.slin_inc; /* /VSYNC: Clear wave LFSR */ state->m_vregs.wave_lfsr = 0; } SCREEN_UPDATE( buggyboy ) { tx1_state *state = screen->machine().driver_data(); device_t *left_screen = screen->machine().device("lscreen"); device_t *center_screen = screen->machine().device("cscreen"); device_t *right_screen = screen->machine().device("rscreen"); if (screen == left_screen) { memset(state->m_obj_bmp, 0, 768*240); memset(state->m_rod_bmp, 0, 768*240); buggyboy_draw_char(screen->machine(), state->m_chr_bmp, 1); buggyboy_draw_road(screen->machine(), state->m_rod_bmp); buggyboy_draw_objs(screen->machine(), state->m_obj_bmp, 1); bb_combine_layers(screen->machine(), bitmap, 0); } else if (screen == center_screen) { bb_combine_layers(screen->machine(), bitmap, 1); } else if (screen == right_screen) { bb_combine_layers(screen->machine(), bitmap, 2); } return 0; } SCREEN_UPDATE( buggybjr ) { tx1_state *state = screen->machine().driver_data(); memset(state->m_obj_bmp, 0, 256*240); buggyboy_draw_char(screen->machine(), state->m_chr_bmp, 0); buggybjr_draw_road(screen->machine(), state->m_rod_bmp, 0); buggyboy_draw_objs(screen->machine(), state->m_obj_bmp, 0); bb_combine_layers(screen->machine(), bitmap, -1); return 0; }