diff options
| author | 2024-07-23 20:19:17 +0200 | |
|---|---|---|
| committer | 2024-07-23 20:20:22 +0200 | |
| commit | c8777b7d3dcd67b99bd52a0aabd985376acfb7f1 (patch) | |
| tree | e58dc3705e5b8c4396a7da7288db9badc78e8f97 /src | |
| parent | 134dc5924ecc254e344433e039226c231f2abb53 (diff) | |
ces/cesclass.cpp: break LCD output in two screens, implement bitmap DMA trigger (fix screen tearing)
Diffstat (limited to 'src')
| -rw-r--r-- | src/mame/ces/cesclass.cpp | 162 |
1 files changed, 102 insertions, 60 deletions
diff --git a/src/mame/ces/cesclass.cpp b/src/mame/ces/cesclass.cpp index 286061a47c9..4139d4865e0 100644 --- a/src/mame/ces/cesclass.cpp +++ b/src/mame/ces/cesclass.cpp @@ -1,25 +1,25 @@ // license:BSD-3-Clause // copyright-holders:Angelo Salese -/* - - CES Classic wall games +/************************************************************************************************** - driver by Angelo Salese +CES Classic wall games - Notes: - - to play Home Run Classic you have to select a pitcher shot and keep pressed the - wall strobe. When you release the strobe, batter does the swing. +Notes: +- to play Home Run Classic you have to select a pitcher shot and hold the remote button. + When you release the strobe, batter does the swing. - TODO: - - custom layout for dual LCDs - - artwork and lamps position needed to make progresses - - U43 and U44 bad in Trap Shoot Classic - - games are incredibly sluggish by now - - irq sources are unknown - - sound doesn't play most samples - - Trap Shoot Classic runs on a single LCD, needs mods +TODO: +- artwork; +- hookup extra DMD sections; +- extra lamps, cfr. hrclass reference; +- irq sources & timings are unknown +\- cfr. ccclass, being really slow on continue screen; +- sound doesn't play most samples; +- hookup m68681 + 2x max232; +- tsclass: runs on a single LCD, needs mods +- tsclass: throws bad U43 and U44 at POST, should also be two roms not one. -*/ +**************************************************************************************************/ #include "emu.h" @@ -40,8 +40,9 @@ public: : driver_device(mconfig, type, tag) , m_maincpu(*this, "maincpu") , m_oki(*this, "oki") - , m_vram(*this, "vram") + , m_workram(*this, "work_ram") , m_palette(*this, "palette") + , m_screen(*this, { "l_lcd", "r_lcd" }) { } void irq2_ack_w(uint16_t data); @@ -49,50 +50,80 @@ public: void lamps_w(uint16_t data); void outputs_w(uint16_t data); - - uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); - void cesclassic_palette(palette_device &palette) const; + void palette_init(palette_device &palette) const; void cesclassic(machine_config &config); - void cesclassic_map(address_map &map); + void main_map(address_map &map); protected: + virtual void video_start() override; + virtual void video_reset() override; - // devices +private: required_device<cpu_device> m_maincpu; required_device<okim6295_device> m_oki; - required_shared_ptr<uint16_t> m_vram; + required_shared_ptr<uint16_t> m_workram; required_device<palette_device> m_palette; - // driver_device overrides - virtual void video_start() override; + required_device_array<screen_device, 2> m_screen; + + bitmap_rgb32 m_lcd_bitmap[2]{}; + bool m_lcd_display = false; + void dma_trigger_w(offs_t offset, u16 data, u16 mem_mask=~0); + + template <unsigned N> uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); }; void cesclassic_state::video_start() { + m_screen[0]->register_screen_bitmap(m_lcd_bitmap[0]); + m_screen[1]->register_screen_bitmap(m_lcd_bitmap[1]); } -uint32_t cesclassic_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +void cesclassic_state::video_reset() { - bitmap.fill(m_palette->black_pen(), cliprect); + m_lcd_display = false; +} + +// selects the start offset from work RAM and triggers +// TODO: not instant +void cesclassic_state::dma_trigger_w(offs_t offset, u16 data, u16 mem_mask) +{ + // all games just pings here with $d + if (data != 0xd) + popmessage("dma_trigger_w %04x & %04x", data, mem_mask); - for(int y=0;y<64;y++) + const u16 *vram = &m_workram[(data & 0xf) << 11]; + + for (unsigned N = 0; N < 2; N++) { - for(int x=0;x<16;x++) - { - for(int xi=0;xi<16;xi++) - { - uint8_t color; + const u32 base_screen = N * 0x80; - color = (((m_vram[x+y*16+0x400])>>(15-xi)) & 1); - color |= (((m_vram[x+y*16])>>(15-xi)) & 1)<<1; + rectangle cliprect = m_screen[N]->visible_area(); - if((x*16+xi)<256 && ((y)+0)<256) - bitmap.pix(y, x*16+xi) = m_palette->pen(color); + for(int y = cliprect.min_y; y <= cliprect.max_y; y++) + { + for(int x = cliprect.min_x; x <= cliprect.max_x; x+= 16) + { + const u32 base_offset = ((x + base_screen) >> 4) + y * 16; + const u16 cell_high = vram[base_offset]; + const u16 cell_low = vram[(base_offset + 0x400) >> 0]; + for(int xi = 0; xi < 16; xi++) + { + const u8 color = BIT(cell_low, 15 - xi) | (BIT(cell_high, 15 - xi) << 1); + + m_lcd_bitmap[N].pix(y, x + xi) = m_palette->pen(color); + } } } } +} +template <unsigned N> uint32_t cesclassic_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + bitmap.fill(m_palette->black_pen(), cliprect); + if (m_lcd_display) + copybitmap(bitmap, m_lcd_bitmap[N], 0, 0, 0, 0, cliprect); return 0; } @@ -111,27 +142,29 @@ void cesclassic_state::lamps_w(uint16_t data) //popmessage("%04x",data); } +/* + * -x-- ---- OKI bankswitch + * --x- ---- enable screen transfers? + * ---- --x- coin counter + */ void cesclassic_state::outputs_w(uint16_t data) { - /* - -x-- ---- OKI bankswitch - --x- ---- probably screen enable - ---- --x- coin counter - */ m_oki->set_rom_bank((data & 0x40) >> 6); + m_lcd_display = bool(BIT(data, 5)); machine().bookkeeping().coin_counter_w(0, data & 2); if(data & ~0x62) - logerror("Output: %02x\n",data); + logerror("Output: %02x\n",data); } -void cesclassic_state::cesclassic_map(address_map &map) +void cesclassic_state::main_map(address_map &map) { map(0x000000, 0x0fffff).rom(); - map(0x400000, 0x40cfff).ram(); - map(0x40d000, 0x40ffff).ram().share("vram"); - map(0x410000, 0x410001).portr("VBLANK"); //probably m68681 lies there instead - map(0x410004, 0x410005).w(FUNC(cesclassic_state::irq3_ack_w)); - map(0x410006, 0x410007).w(FUNC(cesclassic_state::irq2_ack_w)); + map(0x400000, 0x40ffff).ram().share("work_ram"); + // xC5202 FPGA + map(0x410000, 0x410001).portr("VBLANK"); + map(0x410002, 0x410003).w(FUNC(cesclassic_state::dma_trigger_w)); + map(0x410004, 0x410005).nopr().w(FUNC(cesclassic_state::irq3_ack_w)); + map(0x410006, 0x410007).nopr().w(FUNC(cesclassic_state::irq2_ack_w)); map(0x480000, 0x481fff).ram().share("nvram"); //8k according to schematics (games doesn't use that much tho) map(0x600000, 0x600001).portr("SYSTEM"); map(0x610000, 0x610001).w(FUNC(cesclassic_state::outputs_w)); @@ -238,33 +271,42 @@ static INPUT_PORTS_START( cesclassic ) PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) PORT_START("VBLANK") - PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_VBLANK("l_lcd") + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_VBLANK("l_lcd") // TODO: most likely tied to "DONE" from FPGA INPUT_PORTS_END -void cesclassic_state::cesclassic_palette(palette_device &palette) const +void cesclassic_state::palette_init(palette_device &palette) const { for (int i = 0; i < 4; i++) palette.set_pen_color(i, pal2bit(i), 0, 0); } + + void cesclassic_state::cesclassic(machine_config &config) { M68000(config, m_maincpu, 24000000/2); - m_maincpu->set_addrmap(AS_PROGRAM, &cesclassic_state::cesclassic_map); + m_maincpu->set_addrmap(AS_PROGRAM, &cesclassic_state::main_map); m_maincpu->set_vblank_int("l_lcd", FUNC(cesclassic_state::irq2_line_assert)); // TODO: unknown sources m_maincpu->set_periodic_int(FUNC(cesclassic_state::irq3_line_assert), attotime::from_hz(60*8)); NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0); /* video hardware */ - screen_device &screen(SCREEN(config, "l_lcd", SCREEN_TYPE_LCD)); - screen.set_refresh_hz(60); - screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); - screen.set_screen_update(FUNC(cesclassic_state::screen_update)); - screen.set_size(8*16*2, 8*8+3*8); - screen.set_visarea(0*8, 8*16*2-1, 0*8, 8*8-1); - - PALETTE(config, m_palette, FUNC(cesclassic_state::cesclassic_palette), 4); + screen_device &l_screen(SCREEN(config, "l_lcd", SCREEN_TYPE_LCD)); + l_screen.set_refresh_hz(60); + l_screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); + l_screen.set_screen_update(FUNC(cesclassic_state::screen_update<0>)); + l_screen.set_size(256+128, 64+24); + l_screen.set_visarea(0, 128 - 1, 0, 64 - 1); + + screen_device &r_screen(SCREEN(config, "r_lcd", SCREEN_TYPE_LCD)); + r_screen.set_refresh_hz(60); + r_screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); + r_screen.set_screen_update(FUNC(cesclassic_state::screen_update<1>)); + r_screen.set_size(256+128, 64+24); + r_screen.set_visarea(0, 128 - 1, 0, 64 - 1); + + PALETTE(config, m_palette, FUNC(cesclassic_state::palette_init), 4); SPEAKER(config, "mono").front_center(); OKIM6295(config, m_oki, 24000000/16, okim6295_device::PIN7_LOW).add_route(ALL_OUTPUTS, "mono", 0.5); |
