// license:BSD-3-Clause // copyright-holders:David Haywood, R.Belmont /* These use a 6502 derived CPU under a glob The CPU die is marked 'ELAN EU3A14' There is a second glob surrounded by TSOP48 pads this contains the ROM Known to be on this hardware Golden Tee Golf Home Edition (developed by FarSight Studios) Connectv Football (developed by Medialink) Also on this hardware name PCB ID ROM width TSOP pads ROM size SEEPROM die markings Real Swing Golf 74037 x16 48 not dumped no ELAN EU3A14 Play TV Basketball 75029 x16 48 not dumped no ELAN EU3A14 Baseball 3 ? x16 48 not dumped no ELAN EU3A14 Huntin’3 ? x16 48 not dumped no Elan ? In many ways this is similar to the rad_eu3a05.cpp hardware but the video system has changed, here the sprites are more traditional non-tile based, rather than coming from 'pages' */ #include "emu.h" #include "cpu/m6502/m6502.h" #include "emupal.h" #include "screen.h" #include "speaker.h" #include "machine/bankdev.h" #include "audio/rad_eu3a05.h" #include "machine/timer.h" /* ffb0 rti ffb4 rti ffb8 rti ffbc rti ffc0 rti ffc4 rti ffc8 rti ffcc rti ffd0 rti ffd4 main irq? ffd8 rti ffdc rti ffe0 something with 5045 bit 0x08 and 9d in ram (increase or decrease) (ADC interrupt) ffe4 something with 5045 bit 0x20 and 9c in ram (increase of decrease) (ADC interrupt) ffe8 rti ffec rti regular NMI (e3f0 - jump to ($19e2) which seems to point to rti, but could move..) regular IRQ (e3f3 - points to rti) */ class radica_eu3a14_state : public driver_device { public: radica_eu3a14_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag), m_maincpu(*this, "maincpu"), m_palram(*this, "palram"), m_scrollregs(*this, "scrollregs"), m_tilecfg(*this, "tilecfg"), m_tilebase(*this, "tilebase"), m_spritebase(*this, "spritebase"), m_mainram(*this, "mainram"), m_dmaparams(*this, "dmaparams"), m_bank(*this, "bank"), m_palette(*this, "palette"), m_gfxdecode(*this, "gfxdecode") { } void radica_eu3a14(machine_config &config); void radica_eu3a14_adc(machine_config &config); void init_rad_gtg(); void init_rad_foot(); private: READ8_MEMBER(irq_vector_r); // screen updates uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); int m_custom_irq; uint16_t m_custom_irq_vector; INTERRUPT_GEN_MEMBER(interrupt); DECLARE_READ8_MEMBER(radicasi_pal_ntsc_r); DECLARE_READ8_MEMBER(dma_trigger_r); DECLARE_WRITE8_MEMBER(dma_trigger_w); DECLARE_READ8_MEMBER(radicasi_rombank_lo_r); DECLARE_WRITE8_MEMBER(radicasi_rombank_lo_w); DECLARE_WRITE8_MEMBER(radicasi_rombank_hi_w); DECLARE_READ8_MEMBER(random_r) { return machine().rand(); }; TIMER_DEVICE_CALLBACK_MEMBER(scanline_cb); // for callback DECLARE_READ8_MEMBER(read_full_space); void bank_map(address_map &map); void radica_eu3a14_map(address_map &map); // driver_device overrides virtual void machine_start() override; virtual void machine_reset() override; virtual void video_start() override; double hue2rgb(double p, double q, double t); required_device m_maincpu; required_shared_ptr m_palram; required_shared_ptr m_scrollregs; required_shared_ptr m_tilecfg; required_shared_ptr m_tilebase; required_shared_ptr m_spritebase; required_shared_ptr m_mainram; required_shared_ptr m_dmaparams; required_device m_bank; required_device m_palette; required_device m_gfxdecode; uint8_t m_rombank_hi; uint8_t m_rombank_lo; int m_tilerambase; int m_spriterambase; void handle_palette(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); void draw_page(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int which, int xbase, int ybase, int size); void draw_background(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); void draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); }; void radica_eu3a14_state::video_start() { } double radica_eu3a14_state::hue2rgb(double p, double q, double t) { if (t < 0) t += 1; if (t > 1) t -= 1; if (t < 1 / 6.0f) return p + (q - p) * 6 * t; if (t < 1 / 2.0f) return q; if (t < 2 / 3.0f) return p + (q - p) * (2 / 3.0f - t) * 6; return p; } void radica_eu3a14_state::handle_palette(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { // Palette int offs = 0; for (int index = 0; index < 512; index++) { uint16_t dat = m_palram[offs++] << 8; dat |= m_palram[offs++]; // llll lsss ---h hhhh int l_raw = (dat & 0xf800) >> 11; int sl_raw = (dat & 0x0700) >> 8; int h_raw = (dat & 0x001f) >> 0; double l = (double)l_raw / 31.0f; double s = (double)sl_raw / 7.0f; double h = (double)h_raw / 24.0f; double r, g, b; if (s == 0) { r = g = b = l; // greyscale } else { double q = l < 0.5f ? l * (1 + s) : l + s - l * s; double p = 2 * l - q; r = hue2rgb(p, q, h + 1 / 3.0f); g = hue2rgb(p, q, h); b = hue2rgb(p, q, h - 1 / 3.0f); } int r_real = r * 255.0f; int g_real = g * 255.0f; int b_real = b * 255.0f; m_palette->set_pen_color(index, r_real, g_real, b_real); } } void radica_eu3a14_state::draw_page(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int which, int xbase, int ybase, int size) { gfx_element *gfx; int base = (m_tilebase[1] << 8) | m_tilebase[0]; if (m_tilecfg[2] & 0x04) { gfx = m_gfxdecode->gfx(4); base <<= 1; if (size == 8) { gfx = m_gfxdecode->gfx(5); base <<= 2; } } else { gfx = m_gfxdecode->gfx(3); } int xdraw = xbase; int ydraw = ybase; int count = 0; for (int i = m_tilerambase+0x1c0*which; i < m_tilerambase+0x1c0*(which+1); i+=2) { int tile = m_mainram[i+0] | (m_mainram[i+1] << 8); gfx->transpen(bitmap, cliprect, tile+base, 0, 0, 0, xdraw, ydraw, 0); xdraw+=size; count++; if (((count % 16) == 0)) { xdraw -= size*16; ydraw += size; } } } void radica_eu3a14_state::draw_background(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { int xscroll = m_scrollregs[0] | (m_scrollregs[1] << 8); int yscroll = m_scrollregs[2] | (m_scrollregs[3] << 8); int size = 16; // or 0x10? if (m_tilecfg[0] & 0x80) { size = 8; } draw_page(screen, bitmap, cliprect, 0, 0 - xscroll, 0 - yscroll, size); draw_page(screen, bitmap, cliprect, 1, (size * 16) - xscroll, 0 - yscroll, size); draw_page(screen, bitmap, cliprect, 2, 0 - xscroll, (size * 14) - yscroll, size); draw_page(screen, bitmap, cliprect, 3, (size * 16) - xscroll, (size * 14) - yscroll, size); draw_page(screen, bitmap, cliprect, 0, (size * 16 * 2) + 0 - xscroll, 0 - yscroll, size); draw_page(screen, bitmap, cliprect, 1, (size * 16 * 3) - xscroll, 0 - yscroll, size); draw_page(screen, bitmap, cliprect, 2, (size * 16 * 2) + 0 - xscroll, (size * 14) - yscroll, size); draw_page(screen, bitmap, cliprect, 3, (size * 16 * 3) - xscroll, (size * 14) - yscroll, size); draw_page(screen, bitmap, cliprect, 0, 0 - xscroll, (size * 14 * 2) + 0 - yscroll, size); draw_page(screen, bitmap, cliprect, 1, (size * 16) - xscroll, (size * 14 * 2) + 0 - yscroll, size); draw_page(screen, bitmap, cliprect, 2, 0 - xscroll, (size * 14 * 3) - yscroll, size); draw_page(screen, bitmap, cliprect, 3, (size * 16) - xscroll, (size * 14 * 3) - yscroll, size); draw_page(screen, bitmap, cliprect, 0, (size * 16 * 2) + 0 - xscroll, (size * 14 * 2) + 0 - yscroll, size); draw_page(screen, bitmap, cliprect, 1, (size * 16 * 3) - xscroll, (size * 14 * 2) + 0 - yscroll, size); draw_page(screen, bitmap, cliprect, 2, (size * 16 * 2) + 0 - xscroll, (size * 14 * 3) - yscroll, size); draw_page(screen, bitmap, cliprect, 3, (size * 16 * 3) - xscroll, (size * 14 * 3) - yscroll, size); } void radica_eu3a14_state::draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { // first 4 sprite entries seem to be garbage sprites, so we start at 0x20 // likely we're just interpreting them wrong and they're used for blanking things or clipping? for (int i = m_spriterambase; i < m_spriterambase + 0x7e0; i += 8) { /* +0 e--f hhww flip, enable, height, width +1 yyyy yyyy ypos +2 xxxx xxxx xpos +3 pppp ---- palette +4 tttt tttt tile bits +5 tttt tttt +6 --TT TPPP TTT = tile bank PPP = bpp select (+more?) +7 ---- ---- */ int attr = m_mainram[i + 0]; int y = m_mainram[i + 1]; int x = m_mainram[i + 2]; int attr2 = m_mainram[i + 3]; int h = attr & 0x0c; int w = attr & 0x03; int flipx = (attr & 0x10) >> 4; int height = 0; int width = 0; int pal = attr2 >> 4; // no idea if (attr2 & 0x08) pal += 0x10; switch (h) { case 0x0:height = 2; break; case 0x4:height = 4; break; case 0x8:height = 8; break; case 0xc:height = 16; break; } switch (w) { case 0x0:width = 1; break; case 0x1:width = 2; break; case 0x2:width = 4; break; case 0x3:width = 8; break; } y -= ((height * 2) - 4); x -= ((width * 4) - 4); height *= 4; x -= 8; y -= 4; int offset = ((m_mainram[i + 5] << 8) + (m_mainram[i + 4] << 0)); int extra = m_mainram[i + 6]; gfx_element *gfx; gfx = m_gfxdecode->gfx(1); int spritebase = (m_spritebase[1] << 8) | m_spritebase[0]; offset += (extra & 0xf8) << 13; extra &= ~0xf8; offset += spritebase << 7; switch (extra & 0x07) { case 0x00: // 8bpp case 0x07: // 8bpp offset >>= 1; gfx = m_gfxdecode->gfx(2); break; case 0x02: // 2bpp offset <<= 1; gfx = m_gfxdecode->gfx(0); pal = 0; break; case 0x04: // 4bpp break; case 0x01: // unknowns case 0x03: case 0x05: case 0x06: pal = machine().rand(); break; } offset = offset >> 1; if (attr & 0x80) { int count = 0; for (int yy = 0; yy < height; yy++) { for (int xx = 0; xx < width; xx++) { gfx->transpen(bitmap, cliprect, offset + count, pal, flipx, 0, x + xx * 8, y + yy, 0); count++; } } } } } uint32_t radica_eu3a14_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { bitmap.fill(0, cliprect); handle_palette(screen, bitmap, cliprect); draw_background(screen, bitmap, cliprect); draw_sprites(screen, bitmap, cliprect); return 0; } // sound callback READ8_MEMBER(radica_eu3a14_state::read_full_space) { address_space& fullbankspace = m_bank->space(AS_PROGRAM); return fullbankspace.read_byte(offset); } // irq controller seems to be like the Radica Space Invaders READ8_MEMBER(radica_eu3a14_state::irq_vector_r) { if (m_custom_irq) { return m_custom_irq_vector >> (offset*8); } else { uint8_t *rom = memregion("maincpu")->base(); return rom[0x001ffe + offset]; } } /* code at 0000 maps to e000 code at 1000 maps to f000 data at 2000 data at 3000 data at 4000 blank 5000 blank 6000 code at 7000 maps to 3000 code at 8000 maps to 6000 9000 maps to 7000 a000 maps to 8000 b000 maps to 9000 c000 maps to a000 d000 maps to b000 e000 maps to c000 */ WRITE8_MEMBER(radica_eu3a14_state::radicasi_rombank_hi_w) { // written with the banking? //logerror("%s: radicasi_rombank_hi_w (set ROM bank) %02x\n", machine().describe_context(), data); m_rombank_hi = data; m_bank->set_bank(m_rombank_lo | (m_rombank_hi << 8)); } WRITE8_MEMBER(radica_eu3a14_state::radicasi_rombank_lo_w) { //logerror("%s: radicasi_rombank_lo_w (select ROM bank) %02x\n", machine().describe_context(), data); m_rombank_lo = data; } READ8_MEMBER(radica_eu3a14_state::radicasi_rombank_lo_r) { return m_rombank_lo; } READ8_MEMBER(radica_eu3a14_state::radicasi_pal_ntsc_r) { // how best to handle this, we probably need to run the PAL machine at 50hz // the text under the radica logo differs between regions logerror("%s: radicasi_pal_ntsc_r (region + more?)\n", machine().describe_context()); return 0xff; // NTSC //return 0x00; // PAL } void radica_eu3a14_state::bank_map(address_map &map) { map(0x000000, 0x3fffff).rom().region("maincpu", 0); } void radica_eu3a14_state::radica_eu3a14_map(address_map &map) { map(0x0000, 0x01ff).ram(); map(0x0200, 0x3fff).ram().share("mainram"); // 200-9ff is sprites? a00 - ??? is tilemap? map(0x4800, 0x4bff).ram().share("palram"); // similar to eu3a05, at least for pal flags and rom banking map(0x5007, 0x5007).noprw(); map(0x5008, 0x5008).nopw(); // startup map(0x5009, 0x5009).noprw(); map(0x500a, 0x500a).nopw(); // startup map(0x500b, 0x500b).r(FUNC(radica_eu3a14_state::radicasi_pal_ntsc_r)).nopw(); // PAL / NTSC flag at least map(0x500c, 0x500c).w(FUNC(radica_eu3a14_state::radicasi_rombank_hi_w)); map(0x500d, 0x500d).rw(FUNC(radica_eu3a14_state::radicasi_rombank_lo_r), FUNC(radica_eu3a14_state::radicasi_rombank_lo_w)); // DMA is similar to, but not the same as eu3a05 map(0x500f, 0x5017).ram().share("dmaparams"); map(0x5018, 0x5018).rw(FUNC(radica_eu3a14_state::dma_trigger_r), FUNC(radica_eu3a14_state::dma_trigger_w)); // probably GPIO like eu3a05, although it access 47/48 as unknown instead of 48/49/4a map(0x5040, 0x5040).nopw(); map(0x5041, 0x5041).portr("IN0"); map(0x5042, 0x5042).nopw(); map(0x5043, 0x5043).noprw(); map(0x5044, 0x5044).nopw(); map(0x5045, 0x5045).portr("IN1").nopw(); map(0x5046, 0x5046).nopw(); map(0x5047, 0x5047).nopw(); map(0x5048, 0x5048).nopw(); // sound appears to be the same as eu3a05 map(0x5080, 0x5091).rw("6ch_sound", FUNC(radica6502_sound_device::radicasi_sound_addr_r), FUNC(radica6502_sound_device::radicasi_sound_addr_w)); map(0x5092, 0x50a3).rw("6ch_sound", FUNC(radica6502_sound_device::radicasi_sound_size_r), FUNC(radica6502_sound_device::radicasi_sound_size_w)); map(0x50a4, 0x50a4).rw("6ch_sound", FUNC(radica6502_sound_device::radicasi_sound_unk_r), FUNC(radica6502_sound_device::radicasi_sound_unk_w)); // read frequently on this map(0x50a5, 0x50a5).rw("6ch_sound", FUNC(radica6502_sound_device::radicasi_sound_trigger_r), FUNC(radica6502_sound_device::radicasi_sound_trigger_w)); map(0x50a6, 0x50a6).nopw(); // startup map(0x50a7, 0x50a7).nopw(); // startup map(0x50a8, 0x50a8).r("6ch_sound", FUNC(radica6502_sound_device::radicasi_50a8_r)); map(0x50a9, 0x50a9).nopw(); // startup // video regs are here this time map(0x5100, 0x5100).ram(); map(0x5103, 0x5106).ram(); map(0x5107, 0x5107).ram(); // on transitions, maybe layer disables? map(0x5110, 0x5112).ram().share("tilecfg"); map(0x5113, 0x5113).ram(); // written with tilebase? map(0x5114, 0x5115).ram().share("tilebase"); map(0x5116, 0x5117).ram(); map(0x5121, 0x5124).ram().share("scrollregs"); map(0x5150, 0x5150).ram(); // startup map(0x5151, 0x5152).ram().share("spritebase"); map(0x5153, 0x5153).ram(); // startup map(0x6000, 0xdfff).m(m_bank, FUNC(address_map_bank_device::amap8)); map(0xe000, 0xffff).rom().region("maincpu", 0x0000); map(0xfffe, 0xffff).r(FUNC(radica_eu3a14_state::irq_vector_r)); } READ8_MEMBER(radica_eu3a14_state::dma_trigger_r) { logerror("%s: dma_trigger_r\n", machine().describe_context()); return 0; } WRITE8_MEMBER(radica_eu3a14_state::dma_trigger_w) { uint32_t dmasrc = (m_dmaparams[2] << 16) | (m_dmaparams[1] << 8) | (m_dmaparams[0] << 0); uint32_t dmadst = (m_dmaparams[5] << 16) | (m_dmaparams[4] << 8) | (m_dmaparams[3] << 0); uint32_t dmalen = (m_dmaparams[8] << 16) | (m_dmaparams[7] << 8) | (m_dmaparams[6] << 0); //logerror("%s: dma_trigger_w %02x (src %08x dst %08x size %08x)\n", machine().describe_context(), data, dmasrc, dmadst, dmalen); address_space& fullbankspace = m_bank->space(AS_PROGRAM); address_space& destspace = m_maincpu->space(AS_PROGRAM); if (data == 0x08) { for (int i = 0; i < dmalen; i++) { uint8_t dat = fullbankspace.read_byte(dmasrc + i); destspace.write_byte(dmadst + i, dat); } } else { logerror("UNKNOWN DMA TRIGGER VALUE\n"); } } // hold back/backspin and left during power on for test mode static INPUT_PORTS_START( rad_gtg ) PORT_START("IN0") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_START1 ) PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON1 ) // back / backspin PORT_DIPNAME( 0x10, 0x10, DEF_STR( Unknown ) ) PORT_DIPSETTING( 0x10, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) ) PORT_DIPSETTING( 0x20, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) // up and down in the menus should be the trackball, maybe these are leftovers from real swing golf or just from development? PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_START("IN1") PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_DIPNAME( 0x08, 0x08, "Track Y test" ) // trackball up/down direction bit? (read in interrupt, increases / decreases a counter) PORT_DIPSETTING( 0x08, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_DIPNAME( 0x20, 0x20, "Track X test" ) // trackball left / right direction bit? (read in interrupt, increases / decreases a counter) PORT_DIPSETTING( 0x20, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) PORT_BIT( 0xc0, IP_ACTIVE_LOW, IPT_UNUSED ) INPUT_PORTS_END // hold enter and left during power on for test mode static INPUT_PORTS_START( radica_eu3a14 ) PORT_START("IN0") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON1 ) // enter? PORT_DIPNAME( 0x08, 0x08, DEF_STR( Unknown ) ) PORT_DIPSETTING( 0x08, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) PORT_DIPNAME( 0x10, 0x10, DEF_STR( Unknown ) ) PORT_DIPSETTING( 0x10, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) ) PORT_DIPSETTING( 0x20, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ) ) PORT_DIPSETTING( 0x40, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) PORT_DIPNAME( 0x80, 0x80, DEF_STR( Unknown ) ) PORT_DIPSETTING( 0x80, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) PORT_START("IN1") PORT_DIPNAME( 0x01, 0x01, "IN1" ) PORT_DIPSETTING( 0x01, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) PORT_DIPNAME( 0x02, 0x02, DEF_STR( Unknown ) ) PORT_DIPSETTING( 0x02, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) PORT_DIPNAME( 0x04, 0x04, DEF_STR( Unknown ) ) PORT_DIPSETTING( 0x04, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) PORT_DIPNAME( 0x08, 0x08, DEF_STR( Unknown ) ) PORT_DIPSETTING( 0x08, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) PORT_DIPNAME( 0x10, 0x10, DEF_STR( Unknown ) ) PORT_DIPSETTING( 0x10, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) ) PORT_DIPSETTING( 0x20, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ) ) PORT_DIPSETTING( 0x40, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) PORT_DIPNAME( 0x80, 0x80, DEF_STR( Unknown ) ) PORT_DIPSETTING( 0x80, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) INPUT_PORTS_END void radica_eu3a14_state::machine_start() { } void radica_eu3a14_state::machine_reset() { // rather be safe m_maincpu->set_state_int(M6502_S, 0x1ff); m_bank->set_bank(0x01); } TIMER_DEVICE_CALLBACK_MEMBER(radica_eu3a14_state::scanline_cb) { // these interrupts need to occur based on how fast the trackball is // being moved, the direction is read in a port. int scanline = param; if (scanline == 20) { // vertical trackball m_custom_irq_vector = 0xffe0; m_maincpu->set_input_line(INPUT_LINE_IRQ0,HOLD_LINE); } if (scanline == 40) { // horizontal trackball m_custom_irq_vector = 0xffe4; m_maincpu->set_input_line(INPUT_LINE_IRQ0,HOLD_LINE); } } INTERRUPT_GEN_MEMBER(radica_eu3a14_state::interrupt) { m_custom_irq = 1; m_custom_irq_vector = 0xffd4; m_maincpu->set_input_line(INPUT_LINE_IRQ0,HOLD_LINE); } static const gfx_layout helper8x1x2_layout = { 8,1, RGN_FRAC(1,1), 2, { STEP2(0,1) }, { STEP8(0,2) }, { 0 }, 8 * 2 }; static const gfx_layout helper8x1x4_layout = { 8,1, RGN_FRAC(1,1), 4, { STEP4(0,1) }, { STEP8(0,4) }, { 0 }, 8 * 4 }; static const gfx_layout helper8x1x8_layout = { 8,1, RGN_FRAC(1,1), 8, { STEP8(0,1) }, { STEP8(0,8) }, { 0 }, 8 * 8 }; // background static const gfx_layout helper16x16x8_layout = { 16,16, RGN_FRAC(1,1), 8, { STEP8(0,1) }, { STEP16(0,8) }, { STEP16(0,16*8) }, 16 * 16 * 8 }; static const gfx_layout helper16x16x4_layout = { 16,16, RGN_FRAC(1,1), 4, { STEP4(0,1) }, { STEP16(0,4) }, { STEP16(0,16*4) }, 16 * 16 * 4 }; static const gfx_layout helper8x8x4_layout = { 8,8, RGN_FRAC(1,1), 4, { STEP4(0,1) }, { STEP8(0,4) }, { STEP8(0,8*4) }, 8 * 8 * 4 }; static GFXDECODE_START( gfx_helper ) GFXDECODE_ENTRY( "maincpu", 0, helper8x1x2_layout, 0x0, 128 ) GFXDECODE_ENTRY( "maincpu", 0, helper8x1x4_layout, 0x0, 32 ) GFXDECODE_ENTRY( "maincpu", 0, helper8x1x8_layout, 0x0, 2 ) GFXDECODE_ENTRY( "maincpu", 0, helper16x16x8_layout, 0x0, 2 ) GFXDECODE_ENTRY( "maincpu", 0, helper16x16x4_layout, 0x0, 32 ) GFXDECODE_ENTRY( "maincpu", 0, helper8x8x4_layout, 0x0, 32 ) GFXDECODE_END MACHINE_CONFIG_START(radica_eu3a14_state::radica_eu3a14) /* basic machine hardware */ MCFG_DEVICE_ADD("maincpu",M6502,XTAL(21'477'272)/2) // marked as 21'477'270 MCFG_DEVICE_PROGRAM_MAP(radica_eu3a14_map) MCFG_DEVICE_VBLANK_INT_DRIVER("screen", radica_eu3a14_state, interrupt) ADDRESS_MAP_BANK(config, "bank").set_map(&radica_eu3a14_state::bank_map).set_options(ENDIANNESS_LITTLE, 8, 24, 0x8000); MCFG_DEVICE_ADD("gfxdecode", GFXDECODE, "palette", gfx_helper) /* video hardware */ MCFG_SCREEN_ADD("screen", RASTER) MCFG_SCREEN_REFRESH_RATE(60) MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) MCFG_SCREEN_UPDATE_DRIVER(radica_eu3a14_state, screen_update) MCFG_SCREEN_SIZE(32*8, 32*8) MCFG_SCREEN_VISIBLE_AREA(0*8, 32*8-1, 0*8, 28*8-1) MCFG_SCREEN_PALETTE("palette") MCFG_PALETTE_ADD("palette", 512) /* sound hardware */ SPEAKER(config, "mono").front_center(); radica6502_sound_device &sound(RADICA6502_SOUND(config, "6ch_sound", 8000)); sound.space_read_callback().set(FUNC(radica_eu3a14_state::read_full_space)); sound.add_route(ALL_OUTPUTS, "mono", 1.0); MACHINE_CONFIG_END MACHINE_CONFIG_START(radica_eu3a14_state::radica_eu3a14_adc) radica_eu3a14(config); MCFG_TIMER_DRIVER_ADD_SCANLINE("scantimer", radica_eu3a14_state, scanline_cb, "screen", 0, 1) MACHINE_CONFIG_END void radica_eu3a14_state::init_rad_gtg() { // must be registers to control this m_tilerambase = 0x0a00 - 0x200; m_spriterambase = 0x0220 - 0x200; } void radica_eu3a14_state::init_rad_foot() { // must be registers to control this m_tilerambase = 0x0200 - 0x200; m_spriterambase = 0x2800 - 0x200; } ROM_START( rad_gtg ) ROM_REGION( 0x400000, "maincpu", ROMREGION_ERASE00 ) ROM_LOAD16_WORD_SWAP( "goldentee.bin", 0x000000, 0x400000, CRC(b1985c63) SHA1(c42a59fcb665eb801d9ca5312b90e39333e52de4) ) ROM_END ROM_START( rad_foot ) ROM_REGION( 0x400000, "maincpu", ROMREGION_ERASE00 ) ROM_LOAD( "connectvfootball.bin", 0x000000, 0x400000, CRC(00ac4fc0) SHA1(2b60ae5c6bc7e9ef7cdbd3f6a0a0657ed3ab5afe) ) ROM_END CONS( 2006, rad_gtg, 0, 0, radica_eu3a14_adc, rad_gtg, radica_eu3a14_state, init_rad_gtg, "Radica (licensed from Incredible Technologies)", "Golden Tee Golf: Home Edition", MACHINE_NOT_WORKING ) // also has a Connectv Real Soccer logo in the roms, apparently unused, maybe that was to be the US title (without the logo being changed to Play TV) but Play TV Soccer ended up being a different game licensed from Epoch instead. CONS( 2006, rad_foot, 0, 0, radica_eu3a14, radica_eu3a14, radica_eu3a14_state, init_rad_foot, "Radica", "Connectv Football", MACHINE_NOT_WORKING )