From 9197eb14455bda51eb0e49de689592752ea2c12b Mon Sep 17 00:00:00 2001 From: MooglyGuy Date: Sat, 30 Nov 2024 01:11:08 +0100 Subject: Converted Williams SC1/SC2 blitter to a device. (#13030) * -williams: Converted SC1/SC2 blitter to a device. [Ryan Holtz] * Flipped some always-present optional finders to required. --- scripts/target/mame/tiny.lua | 2 + src/mame/midway/williams.cpp | 78 ++++------- src/mame/midway/williams.h | 48 +------ src/mame/midway/williams_m.cpp | 4 +- src/mame/midway/williams_v.cpp | 217 +------------------------------ src/mame/midway/williamsblitter.cpp | 251 ++++++++++++++++++++++++++++++++++++ src/mame/midway/williamsblitter.h | 130 +++++++++++++++++++ src/mame/midway/wmg.cpp | 5 +- 8 files changed, 422 insertions(+), 313 deletions(-) create mode 100644 src/mame/midway/williamsblitter.cpp create mode 100644 src/mame/midway/williamsblitter.h diff --git a/scripts/target/mame/tiny.lua b/scripts/target/mame/tiny.lua index 3b6b722b6b2..402027691c1 100644 --- a/scripts/target/mame/tiny.lua +++ b/scripts/target/mame/tiny.lua @@ -154,6 +154,8 @@ files{ MAME_DIR .. "src/mame/shared/s11c_bg.h", MAME_DIR .. "src/mame/shared/williamssound.cpp", MAME_DIR .. "src/mame/shared/williamssound.h", + MAME_DIR .. "src/mame/midway/williamsblitter.cpp", + MAME_DIR .. "src/mame/midway/williamsblitter.h", MAME_DIR .. "src/mame/midway/williams.cpp", MAME_DIR .. "src/mame/midway/williams.h", MAME_DIR .. "src/mame/midway/williams_m.cpp", diff --git a/src/mame/midway/williams.cpp b/src/mame/midway/williams.cpp index 13c1a14e446..fe2cb299380 100644 --- a/src/mame/midway/williams.cpp +++ b/src/mame/midway/williams.cpp @@ -41,25 +41,7 @@ **************************************************************************** - Blitter (Stargate and Defender do not have blitter) - --------------------------------------------------- - - CA00 start_blitter Each bits has a function - 1000 0000 Do not process half the byte 4-7 - 0100 0000 Do not process half the byte 0-3 - 0010 0000 Shift the shape one pixel right (to display a shape on an odd pixel) - 0001 0000 Remap, if shape != 0 then pixel = mask - 0000 1000 Source 1 = take source 0 = take Mask only - 0000 0100 ? - 0000 0010 Transparent - 0000 0001 - CA01 blitter_mask Not really a mask, more a remap color, see Blitter - CA02 blitter_source hi - CA03 blitter_source lo - CA04 blitter_dest hi - CA05 blitter_dest lo - CA06 blitter_w_h H Do a XOR with 4 to have the real value (Except Splat) - CA07 blitter_w_h W Do a XOR with 4 to have the real value (Except Splat) + CA00-CA07 blitter (Stargate and Defender do not have blitter) CB00 6 bits of the video counters bits 2-7 @@ -553,17 +535,21 @@ void williams_state::main_map(address_map &map) map(0xc804, 0xc807).mirror(0x00f0).rw(m_pia[0], FUNC(pia6821_device::read), FUNC(pia6821_device::write)); map(0xc80c, 0xc80f).mirror(0x00f0).rw(m_pia[1], FUNC(pia6821_device::read), FUNC(pia6821_device::write)); map(0xc900, 0xc9ff).w(FUNC(williams_state::vram_select_w)); - map(0xca00, 0xca07).mirror(0x00f8).w(FUNC(williams_state::blitter_w)); map(0xcb00, 0xcbff).r(FUNC(williams_state::video_counter_r)); map(0xcbff, 0xcbff).w(FUNC(williams_state::watchdog_reset_w)); map(0xcc00, 0xcfff).ram().w(FUNC(williams_state::cmos_4bit_w)).share("nvram"); map(0xd000, 0xffff).rom(); } +void williams_state::main_map_blitter(address_map &map) +{ + main_map(map); + map(0xca00, 0xca07).mirror(0x00f8).m(m_blitter, FUNC(williams_blitter_device::map)); +} void williams_state::sinistar_main_map(address_map &map) { - main_map(map); + main_map_blitter(map); map(0xc900, 0xc9ff).w(FUNC(williams_state::sinistar_vram_select_w)); @@ -574,7 +560,7 @@ void williams_state::sinistar_main_map(address_map &map) void williams_state::bubbles_main_map(address_map &map) { - main_map(map); + main_map_blitter(map); // bubbles has additional CMOS for a full 8 bits map(0xcc00, 0xcfff).ram().share("nvram"); @@ -583,7 +569,7 @@ void williams_state::bubbles_main_map(address_map &map) void williams_state::spdball_main_map(address_map &map) { - main_map(map); + main_map_blitter(map); // install extra input handlers map(0xc800, 0xc800).portr("AN0"); @@ -598,7 +584,7 @@ void williams_state::spdball_main_map(address_map &map) void williams_state::alienar_main_map(address_map &map) { - main_map(map); + main_map_blitter(map); map(0xcbff, 0xcbff).nopw(); } @@ -621,10 +607,10 @@ void blaster_state::blaster_main_map(address_map &map) map(0xc804, 0xc807).mirror(0x00f0).rw(m_pia[0], FUNC(pia6821_device::read), FUNC(pia6821_device::write)); map(0xc80c, 0xc80f).mirror(0x00f0).rw(m_pia[1], FUNC(pia6821_device::read), FUNC(pia6821_device::write)); map(0xc900, 0xc93f).w(FUNC(blaster_state::blaster_vram_select_w)); - map(0xc940, 0xc97f).w(FUNC(blaster_state::remap_select_w)); + map(0xc940, 0xc97f).w(m_blitter, FUNC(williams_blitter_device::remap_select_w)); map(0xc980, 0xc9bf).w(FUNC(blaster_state::bank_select_w)); map(0xc9c0, 0xc9ff).w(FUNC(blaster_state::video_control_w)); - map(0xca00, 0xca07).mirror(0x00f8).w(FUNC(blaster_state::blitter_w)); + map(0xca00, 0xca07).mirror(0x00f8).m(m_blitter, FUNC(williams_blitter_device::map)); map(0xcb00, 0xcbff).r(FUNC(blaster_state::video_counter_r)); map(0xcbff, 0xcbff).w(FUNC(blaster_state::watchdog_reset_w)); map(0xcc00, 0xcfff).ram().w(FUNC(blaster_state::cmos_4bit_w)).share("nvram"); @@ -648,7 +634,7 @@ void williams2_state::common_map(address_map &map) m_palette_view[0](0x8000, 0x87ff).ram().w(FUNC(williams2_state::paletteram_w)).share(m_paletteram); map(0xc000, 0xc7ff).ram().w(FUNC(williams2_state::tileram_w)).share(m_tileram); map(0xc800, 0xc87f).w(FUNC(williams2_state::bank_select_w)); - map(0xc880, 0xc887).mirror(0x0078).w(FUNC(williams2_state::blitter_w)); + map(0xc880, 0xc887).mirror(0x0078).m(m_blitter, FUNC(williams_blitter_device::map)); map(0xc900, 0xc97f).w(FUNC(williams2_state::watchdog_reset_w)); map(0xc980, 0xc983).mirror(0x0070).rw(m_pia[1], FUNC(pia6821_device::read), FUNC(pia6821_device::write)); map(0xc984, 0xc987).mirror(0x0070).rw(m_pia[0], FUNC(pia6821_device::read), FUNC(pia6821_device::write)); @@ -658,7 +644,7 @@ void williams2_state::common_map(address_map &map) map(0xcb40, 0xcb5f).w(FUNC(williams2_state::xscroll_low_w)); map(0xcb60, 0xcb7f).w(FUNC(williams2_state::xscroll_high_w)); map(0xcb80, 0xcb9f).w(FUNC(williams2_state::video_control_w)); - map(0xcba0, 0xcbbf).w(FUNC(williams2_state::blit_window_enable_w)); + map(0xcba0, 0xcbbf).w(m_blitter, FUNC(williams_blitter_device::window_enable_w)); map(0xcbe0, 0xcbef).r(FUNC(williams2_state::video_counter_r)); map(0xcc00, 0xcfff).ram().w(FUNC(williams2_state::cmos_4bit_w)).share("nvram"); } @@ -1596,31 +1582,17 @@ void williams_state::williams_base(machine_config &config) m_pia[2]->irqb_handler().set("soundirq", FUNC(input_merger_any_high_device::in_w<1>)); } -void williams_state::williams_b0(machine_config &config) -{ - williams_base(config); - m_blitter_config = WILLIAMS_BLITTER_NONE; - m_blitter_clip_address = 0x0000; -} - void williams_state::williams_b1(machine_config &config) { williams_base(config); - m_blitter_config = WILLIAMS_BLITTER_SC1; - m_blitter_clip_address = 0xc000; -} - -void williams_state::williams_b2(machine_config &config) -{ - williams_base(config); - m_blitter_config = WILLIAMS_BLITTER_SC2; - m_blitter_clip_address = 0xc000; + WILLIAMS_BLITTER_SC1(config, m_blitter, 0xc000, m_maincpu, m_videoram); + m_maincpu->set_addrmap(AS_PROGRAM, &williams_state::main_map_blitter); } void defender_state::defender(machine_config &config) { - williams_b0(config); + williams_base(config); m_maincpu->set_addrmap(AS_PROGRAM, &defender_state::defender_main_map); m_soundcpu->set_addrmap(AS_PROGRAM, &defender_state::defender_sound_map); @@ -1681,7 +1653,8 @@ void williams_state::joust(machine_config &config) void williams_state::splat(machine_config &config) { - williams_b2(config); + williams_base(config); + WILLIAMS_BLITTER_SC2(config, m_blitter, 0xc000, m_maincpu, m_videoram); williams_muxed(config); } @@ -1704,8 +1677,8 @@ void williams_state::bubbles(machine_config &config) void williams_state::sinistar_upright(machine_config &config) { // Sinistar: blitter window clip - williams_b1(config); - m_blitter_clip_address = 0x7400; + williams_base(config); + WILLIAMS_BLITTER_SC1(config, m_blitter, 0x7400, m_maincpu, m_videoram); m_maincpu->set_addrmap(AS_PROGRAM, &williams_state::sinistar_main_map); @@ -1786,8 +1759,8 @@ void williams_state::lottofun(machine_config &config) void blaster_state::blastkit(machine_config &config) { - williams_b2(config); - m_blitter_clip_address = 0x9700; + williams_base(config); + WILLIAMS_BLITTER_SC2(config, m_blitter, 0x9700, m_maincpu, m_videoram, "proms"); m_maincpu->set_addrmap(AS_PROGRAM, &blaster_state::blaster_main_map); @@ -1899,8 +1872,7 @@ void williams2_state::williams2_base(machine_config &config) m_pia[2]->irqa_handler().set("soundirq", FUNC(input_merger_any_high_device::in_w<0>)); m_pia[2]->irqb_handler().set("soundirq", FUNC(input_merger_any_high_device::in_w<1>)); - m_blitter_config = WILLIAMS_BLITTER_SC2; - m_blitter_clip_address = 0x9000; + WILLIAMS_BLITTER_SC2(config, m_blitter, 0x9000, m_maincpu, m_videoram); } @@ -3953,7 +3925,7 @@ GAME( 1982, jin, 0, jin, jin, defender_state, e // Standard Williams hardware -GAME( 1981, stargate, 0, williams_b0, stargate, williams_state, empty_init, ROT0, "Williams / Vid Kidz", "Stargate", MACHINE_SUPPORTS_SAVE ) +GAME( 1981, stargate, 0, williams_base, stargate, williams_state, empty_init, ROT0, "Williams / Vid Kidz", "Stargate", MACHINE_SUPPORTS_SAVE ) GAME( 1982, conquest, 0, williams_b1, conquest, conquest_state, empty_init, ROT270, "Williams / Vid Kidz", "Conquest (prototype)", MACHINE_IS_INCOMPLETE | MACHINE_SUPPORTS_SAVE ) diff --git a/src/mame/midway/williams.h b/src/mame/midway/williams.h index 1df94ba3a90..f736b07d9ed 100644 --- a/src/mame/midway/williams.h +++ b/src/mame/midway/williams.h @@ -12,6 +12,7 @@ #include "s11c_bg.h" #include "williamssound.h" +#include "williamsblitter.h" #include "cpu/m6800/m6800.h" #include "cpu/m6809/m6809.h" @@ -39,6 +40,7 @@ public: m_screen(*this, "screen"), m_palette(*this, "palette"), m_paletteram(*this, "paletteram"), + m_blitter(*this, "blitter"), m_pia(*this, "pia_%u", 0U), m_nvram(*this, "nvram"), m_videoram(*this, "videoram"), @@ -47,9 +49,8 @@ public: m_49way_y(*this, "49WAYY") { } - void williams_b0(machine_config &config); + void williams_base(machine_config &config); void williams_b1(machine_config &config); - void williams_b2(machine_config &config); void joust(machine_config &config); void bubbles(machine_config &config); @@ -71,33 +72,13 @@ public: void palette_init(palette_device &palette) const; protected: - // blitter type - enum - { - WILLIAMS_BLITTER_NONE = 0, // no blitter - WILLIAMS_BLITTER_SC1 = 1, // Special Chip 1 blitter - WILLIAMS_BLITTER_SC2 = 2 // Special Chip 2 "bugfixed" blitter - }; - - // controlbyte (0xCA00) bit definitions - enum - { - WMS_BLITTER_CONTROLBYTE_NO_EVEN = 0x80, - WMS_BLITTER_CONTROLBYTE_NO_ODD = 0x40, - WMS_BLITTER_CONTROLBYTE_SHIFT = 0x20, - WMS_BLITTER_CONTROLBYTE_SOLID = 0x10, - WMS_BLITTER_CONTROLBYTE_FOREGROUND_ONLY = 0x08, - WMS_BLITTER_CONTROLBYTE_SLOW = 0x04, // 2us blits instead of 1us - WMS_BLITTER_CONTROLBYTE_DST_STRIDE_256 = 0x02, - WMS_BLITTER_CONTROLBYTE_SRC_STRIDE_256 = 0x01 - }; - required_device m_maincpu; required_device m_soundcpu; required_device m_watchdog; required_device m_screen; - optional_device m_palette; - optional_shared_ptr m_paletteram; + required_device m_palette; + required_shared_ptr m_paletteram; + optional_device m_blitter; optional_device_array m_pia; required_shared_ptr m_nvram; @@ -108,16 +89,8 @@ protected: optional_ioport m_49way_x; optional_ioport m_49way_y; - uint8_t m_blitter_config; - uint16_t m_blitter_clip_address; - uint8_t m_blitter_window_enable; uint8_t m_cocktail; std::unique_ptr m_palette_lookup; - uint8_t m_blitterram[8]; - uint8_t m_blitter_xor; - uint8_t m_blitter_remap_index; - const uint8_t *m_blitter_remap; - std::unique_ptr m_blitter_remap_lookup; virtual void machine_reset() override ATTR_COLD; virtual void video_start() override ATTR_COLD; @@ -126,7 +99,6 @@ protected: void vram_select_w(u8 data); void sinistar_vram_select_w(u8 data); void cmos_4bit_w(offs_t offset, u8 data); - void blitter_w(address_space &space, offs_t offset, u8 data); template TIMER_CALLBACK_MEMBER(deferred_snd_cmd_w); @@ -134,15 +106,10 @@ protected: void playball_snd_cmd_w(u8 data); void cockpit_snd_cmd_w(u8 data); - void state_save_register(); - void blitter_init(int blitter_config, const uint8_t *remap_prom); - inline void blit_pixel(address_space &space, int dstaddr, int srcdata, int controlbyte); - int blitter_core(address_space &space, int sstart, int dstart, int w, int h, int data); - - void williams_base(machine_config &config); void williams_muxed(machine_config &config); void main_map(address_map &map) ATTR_COLD; + void main_map_blitter(address_map &map) ATTR_COLD; void bubbles_main_map(address_map &map) ATTR_COLD; void sinistar_main_map(address_map &map) ATTR_COLD; void spdball_main_map(address_map &map) ATTR_COLD; @@ -237,7 +204,6 @@ private: void blaster_vram_select_w(u8 data); void bank_select_w(u8 data); - void remap_select_w(u8 data); void video_control_w(u8 data); TIMER_CALLBACK_MEMBER(deferred_snd_cmd_w); void blaster_snd_cmd_w(u8 data); diff --git a/src/mame/midway/williams_m.cpp b/src/mame/midway/williams_m.cpp index 2eefd25075e..d7f60a1df0d 100644 --- a/src/mame/midway/williams_m.cpp +++ b/src/mame/midway/williams_m.cpp @@ -375,7 +375,7 @@ void williams_state::sinistar_vram_select_w(u8 data) vram_select_w(data); // window enable from bit 2 (clips to 0x7400) - m_blitter_window_enable = BIT(data, 2); + m_blitter->window_enable_w(BIT(data, 2)); } @@ -421,7 +421,7 @@ void blaster_state::blaster_vram_select_w(u8 data) m_cocktail = BIT(data, 1); // window enable from bit 2 (clips to 0x9700) - m_blitter_window_enable = BIT(data, 2); + m_blitter->window_enable_w(BIT(data, 2)); } diff --git a/src/mame/midway/williams_v.cpp b/src/mame/midway/williams_v.cpp index eea6f16fb9f..75eb1c7fa76 100644 --- a/src/mame/midway/williams_v.cpp +++ b/src/mame/midway/williams_v.cpp @@ -160,26 +160,15 @@ The full silkscreen markings of SC2 (under the "Special Chip 2" sticker, if it i * *************************************/ -void williams_state::state_save_register() -{ - save_item(NAME(m_blitter_window_enable)); - save_item(NAME(m_cocktail)); - save_item(NAME(m_blitterram)); - save_item(NAME(m_blitter_remap_index)); -} - - void williams_state::video_start() { - blitter_init(m_blitter_config, nullptr); - state_save_register(); + save_item(NAME(m_cocktail)); } void blaster_state::video_start() { - blitter_init(m_blitter_config, memregion("proms")->base()); - state_save_register(); + williams_state::video_start(); save_item(NAME(m_color0)); save_item(NAME(m_video_control)); } @@ -187,13 +176,12 @@ void blaster_state::video_start() void williams2_state::video_start() { - blitter_init(m_blitter_config, nullptr); + williams_state::video_start(); /* create the tilemap */ m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(williams2_state::get_tile_info)), TILEMAP_SCAN_COLS, 24,16, 128,16); m_bg_tilemap->set_scrolldx(2, 0); - state_save_register(); save_item(NAME(m_tilemap_xscroll)); save_item(NAME(m_fg_color)); save_item(NAME(m_gain)); @@ -313,7 +301,6 @@ uint32_t mysticm_state::screen_update(screen_device &screen, bitmap_rgb32 &bitma rgb_t pens[16]; /* draw the background */ - //printf("y %d %d %d\n", cliprect.min_y, cliprect.max_y, m_screen->vpos()); m_bg_tilemap->mark_all_dirty(); m_bg_tilemap->draw(screen, bitmap, cliprect, TILEMAP_DRAW_OPAQUE | TILEMAP_DRAW_ALL_CATEGORIES, 0); @@ -644,205 +631,7 @@ void williams2_state::xscroll_high_w(u8 data) * *************************************/ -void blaster_state::remap_select_w(u8 data) -{ - m_blitter_remap_index = data; - m_blitter_remap = m_blitter_remap_lookup.get() + data * 256; -} - - void blaster_state::video_control_w(u8 data) { m_video_control = data; } - - - -/************************************* - * - * Blitter setup and control - * - *************************************/ - -void williams_state::blitter_init(int blitter_config, const uint8_t *remap_prom) -{ - std::fill(std::begin(m_blitterram), std::end(m_blitterram), 0); - static const uint8_t dummy_table[] = { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }; - - /* by default, there is no clipping window - this will be touched only by games that have one */ - m_blitter_window_enable = 0; - - /* switch off the video config */ - m_blitter_xor = (blitter_config == WILLIAMS_BLITTER_SC1) ? 4 : 0; - - /* create the remap table; if no PROM, make an identity remap table */ - m_blitter_remap_lookup = std::make_unique(256 * 256); - m_blitter_remap_index = 0; - m_blitter_remap = m_blitter_remap_lookup.get(); - for (int i = 0; i < 256; i++) - { - const uint8_t *table = remap_prom ? (remap_prom + (i & 0x7f) * 16) : dummy_table; - for (int j = 0; j < 256; j++) - m_blitter_remap_lookup[i * 256 + j] = (table[j >> 4] << 4) | table[j & 0x0f]; - } -} - - -void williams_state::blitter_w(address_space &space, offs_t offset, u8 data) -{ - /* store the data */ - m_blitterram[offset] = data; - - /* only writes to location 0 trigger the blit */ - if (offset != 0) - return; - - /* compute the starting locations */ - int sstart = (m_blitterram[2] << 8) + m_blitterram[3]; - int dstart = (m_blitterram[4] << 8) + m_blitterram[5]; - - /* compute the width and height */ - int w = m_blitterram[6] ^ m_blitter_xor; - int h = m_blitterram[7] ^ m_blitter_xor; - - /* adjust the width and height */ - if (w == 0) w = 1; - if (h == 0) h = 1; - - /* do the actual blit */ - int const accesses = blitter_core(space, sstart, dstart, w, h, data); - - /* based on the number of memory accesses needed to do the blit, compute how long the blit will take */ - int estimated_clocks_at_4MHz = 4; - if(data & WMS_BLITTER_CONTROLBYTE_SLOW) - { - estimated_clocks_at_4MHz += 4 * (accesses + 2); - } - else - { - estimated_clocks_at_4MHz += 2 * (accesses + 3); - } - - m_maincpu->adjust_icount(-((estimated_clocks_at_4MHz + 3) / 4)); - - /* Log blits */ - logerror("%04X:Blit @ %3d : %02X%02X -> %02X%02X, %3dx%3d, mask=%02X, flags=%02X, icount=%d, win=%d\n", - m_maincpu->pc(), m_screen->vpos(), - m_blitterram[2], m_blitterram[3], - m_blitterram[4], m_blitterram[5], - m_blitterram[6], m_blitterram[7], - m_blitterram[1], m_blitterram[0], - ((estimated_clocks_at_4MHz + 3) / 4), m_blitter_window_enable); -} - - -void williams2_state::blit_window_enable_w(u8 data) -{ - m_blitter_window_enable = BIT(data, 0); -} - - - -/************************************* - * - * Blitter core - * - *************************************/ - -inline void williams_state::blit_pixel(address_space &space, int dstaddr, int srcdata, int controlbyte) -{ - /* always read from video RAM regardless of the bank setting */ - int curpix = (dstaddr < 0xc000) ? m_videoram[dstaddr] : space.read_byte(dstaddr); // current pixel values at dest - - int const solid = m_blitterram[1]; - unsigned char keepmask = 0xff; // what part of original dst byte should be kept, based on NO_EVEN and NO_ODD flags - - // even pixel (D7-D4) - if((controlbyte & WMS_BLITTER_CONTROLBYTE_FOREGROUND_ONLY) && !(srcdata & 0xf0)) // FG only and src even pixel=0 - { - if(controlbyte & WMS_BLITTER_CONTROLBYTE_NO_EVEN) - keepmask &= 0x0f; - } - else - { - if(!(controlbyte & WMS_BLITTER_CONTROLBYTE_NO_EVEN)) - keepmask &= 0x0f; - } - - // odd pixel (D3-D0) - if((controlbyte & WMS_BLITTER_CONTROLBYTE_FOREGROUND_ONLY) && !(srcdata & 0x0f)) // FG only and src odd pixel=0 - { - if(controlbyte & WMS_BLITTER_CONTROLBYTE_NO_ODD) - keepmask &= 0xf0; - } - else - { - if(!(controlbyte & WMS_BLITTER_CONTROLBYTE_NO_ODD)) - keepmask &= 0xf0; - } - - curpix &= keepmask; - if(controlbyte & WMS_BLITTER_CONTROLBYTE_SOLID) - curpix |= (solid & ~keepmask); - else - curpix |= (srcdata & ~keepmask); - - /* if the window is enabled, only blit to videoram below the clipping address */ - /* note that we have to allow blits to non-video RAM (e.g. tileram, Sinistar $DXXX SRAM) because those */ - /* are not blocked by the window enable */ - if (!m_blitter_window_enable || dstaddr < m_blitter_clip_address || dstaddr >= 0xc000) - space.write_byte(dstaddr, curpix); -} - - -int williams_state::blitter_core(address_space &space, int sstart, int dstart, int w, int h, int controlbyte) -{ - int accesses = 0; - - /* compute how much to advance in the x and y loops */ - int const sxadv = (controlbyte & WMS_BLITTER_CONTROLBYTE_SRC_STRIDE_256) ? 0x100 : 1; - int const syadv = (controlbyte & WMS_BLITTER_CONTROLBYTE_SRC_STRIDE_256) ? 1 : w; - int const dxadv = (controlbyte & WMS_BLITTER_CONTROLBYTE_DST_STRIDE_256) ? 0x100 : 1; - int const dyadv = (controlbyte & WMS_BLITTER_CONTROLBYTE_DST_STRIDE_256) ? 1 : w; - - int pixdata = 0; - - /* loop over the height */ - for (int y = 0; y < h; y++) - { - int source = sstart & 0xffff; - int dest = dstart & 0xffff; - - /* loop over the width */ - for (int x = 0; x < w; x++) - { - if (!(controlbyte & WMS_BLITTER_CONTROLBYTE_SHIFT)) // no shift - { - blit_pixel(space, dest, m_blitter_remap[space.read_byte(source)], controlbyte); - } - else - { - // shift one pixel right - pixdata = (pixdata << 8) | m_blitter_remap[space.read_byte(source)]; - blit_pixel(space, dest, (pixdata >> 4) & 0xff, controlbyte); - } - accesses += 2; - - /* advance src and dst pointers */ - source = (source + sxadv) & 0xffff; - dest = (dest + dxadv) & 0xffff; - } - - /* note that PlayBall! indicates the X coordinate doesn't wrap */ - if (controlbyte & WMS_BLITTER_CONTROLBYTE_DST_STRIDE_256) - dstart = (dstart & 0xff00) | ((dstart + dyadv) & 0xff); - else - dstart += dyadv; - - if (controlbyte & WMS_BLITTER_CONTROLBYTE_SRC_STRIDE_256) - sstart = (sstart & 0xff00) | ((sstart + syadv) & 0xff); - else - sstart += syadv; - } - return accesses; -} diff --git a/src/mame/midway/williamsblitter.cpp b/src/mame/midway/williamsblitter.cpp new file mode 100644 index 00000000000..ffda9b97799 --- /dev/null +++ b/src/mame/midway/williamsblitter.cpp @@ -0,0 +1,251 @@ +// license:BSD-3-Clause +// copyright-holders:Aaron Giles +/*************************************************************************** + + Williams first-generation blitter + + Register Description + -------------------- + + CA00 start_blitter Control bits + CA01 mask Solid color to optionally use instead of source + CA02 source Source address MSB + CA03 source Source address LSB + CA04 dest Destination address MSB + CA05 dest Destination address LSB + CA06 w_h Blit width (XOR with 4 to have the real value on first-rev blitter) + CA07 w_h Blit height (XOR with 4 to have the real value on first-rev blitter) + +***************************************************************************/ + +#include "emu.h" +#include "williamsblitter.h" + +#define VERBOSE (0) +#include "logmacro.h" + +DEFINE_DEVICE_TYPE(WILLIAMS_BLITTER_SC1, williams_blitter_sc1_device, "williams_blitter_sc1_device", "Williams Blitter (SC1)") +DEFINE_DEVICE_TYPE(WILLIAMS_BLITTER_SC2, williams_blitter_sc2_device, "williams_blitter_sc2_device", "Williams Blitter (SC2)") + +williams_blitter_device::williams_blitter_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock) : + device_t(mconfig, type, tag, owner, clock), + m_cpu(*this, finder_base::DUMMY_TAG), + m_vram(*this, finder_base::DUMMY_TAG), + m_proms(*this, finder_base::DUMMY_TAG) +{ +} + +williams_blitter_sc1_device::williams_blitter_sc1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : + williams_blitter_device(mconfig, WILLIAMS_BLITTER_SC1, tag, owner, clock) +{ +} + +williams_blitter_sc2_device::williams_blitter_sc2_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : + williams_blitter_device(mconfig, WILLIAMS_BLITTER_SC2, tag, owner, clock) +{ +} + +void williams_blitter_device::device_start() +{ + static const u8 dummy_table[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; + + m_window_enable = 0; + + // create the remap table; if no PROM, make an identity remap table + m_remap_lookup = std::make_unique(256 * 256); + m_remap = m_remap_lookup.get(); + for (int i = 0; i < 256; i++) + { + const u8 *table = m_proms.found() ? &m_proms[(i & 0x7f) * 16] : dummy_table; + for (int j = 0; j < 256; j++) + { + m_remap_lookup[i * 256 + j] = (table[j >> 4] << 4) | table[j & 0x0f]; + } + } + + save_item(NAME(m_window_enable)); + save_item(NAME(m_control)); + save_item(NAME(m_no_even)); + save_item(NAME(m_no_odd)); + save_item(NAME(m_solid)); + save_item(NAME(m_fg_only)); + save_item(NAME(m_solid_color)); + save_item(NAME(m_sstart)); + save_item(NAME(m_dstart)); + save_item(NAME(m_width)); + save_item(NAME(m_height)); + save_item(NAME(m_remap_index)); +} + +void williams_blitter_device::device_reset() +{ + m_control = 0; + m_no_even = false; + m_no_odd = false; + m_solid = false; + m_fg_only = false; + m_solid_color = 0; + m_sstart = 0; + m_dstart = 0; + m_width = 0; + m_height = 0; + m_remap_index = 0; +} + +void williams_blitter_device::map(address_map &map) +{ + map(0x0, 0x0).w(FUNC(williams_blitter_device::control_w)); + map(0x1, 0x1).lw8(NAME([this](u8 data) { m_solid_color = data; })); + map(0x2, 0x2).lw8(NAME([this](u8 data) { m_sstart = (m_sstart & 0x00ff) | ((u16)data << 8); })); + map(0x3, 0x3).lw8(NAME([this](u8 data) { m_sstart = (m_sstart & 0xff00) | data; })); + map(0x4, 0x4).lw8(NAME([this](u8 data) { m_dstart = (m_dstart & 0x00ff) | ((u16)data << 8); })); + map(0x5, 0x5).lw8(NAME([this](u8 data) { m_dstart = (m_dstart & 0xff00) | data; })); + map(0x6, 0x6).lw8(NAME([this](u8 data) { m_width = data; })); + map(0x7, 0x7).lw8(NAME([this](u8 data) { m_height = data; })); +} + +void williams_blitter_device::control_w(address_space &space, offs_t offset, u8 data) +{ + m_control = data; + m_no_even = BIT(data, CONTROLBYTE_NO_EVEN); + m_no_odd = BIT(data, CONTROLBYTE_NO_ODD); + m_solid = BIT(data, CONTROLBYTE_SOLID); + m_fg_only = BIT(data, CONTROLBYTE_FOREGROUND_ONLY); + + int w = m_width ^ m_size_xor; + int h = m_height ^ m_size_xor; + + if (w == 0) + w = 1; + if (h == 0) + h = 1; + + const int accesses = blit_core(space, w, h); + + // based on the number of memory accesses needed to do the blit, compute how long the blit will take + int estimated_clocks_at_4MHz = 4; + if (BIT(m_control, CONTROLBYTE_SLOW)) + estimated_clocks_at_4MHz += 4 * (accesses + 2); + else + estimated_clocks_at_4MHz += 2 * (accesses + 3); + + m_cpu->adjust_icount(-((estimated_clocks_at_4MHz + 3) / 4)); + + // log blits + LOG("%04X:Blit : %04X -> %04X, %3dx%3d, mask=%02X, flags=%02X, icount=%d, win=%d\n", + m_cpu->pc(), m_sstart, m_dstart, m_width, m_height, m_solid_color, m_control, + ((estimated_clocks_at_4MHz + 3) / 4), m_window_enable); +} + +void williams_blitter_device::remap_select_w(u8 data) +{ + m_remap_index = data; + if (m_proms != nullptr) + m_remap = m_remap_lookup.get() + data * 256; +} + +void williams_blitter_device::window_enable_w(u8 data) +{ + m_window_enable = BIT(data, 0); +} + +inline void williams_blitter_device::blit_pixel(address_space &space, int dstaddr, int srcdata) +{ + // always read from video RAM regardless of the bank setting + int curpix = (dstaddr < 0xc000) ? m_vram[dstaddr] : space.read_byte(dstaddr); // current pixel values at dest + + u8 keepmask = 0xff; // what part of original dst byte should be kept, based on NO_EVEN and NO_ODD flags + + // even pixel (D7-D4) + if (m_fg_only && !(srcdata & 0xf0)) // FG only and src even pixel=0 + { + if (m_no_even) + keepmask &= 0x0f; + } + else + { + if (!m_no_even) + keepmask &= 0x0f; + } + + // odd pixel (D3-D0) + if (m_fg_only && !(srcdata & 0x0f)) // FG only and src odd pixel=0 + { + if (m_no_odd) + keepmask &= 0xf0; + } + else + { + if (!m_no_odd) + keepmask &= 0xf0; + } + + curpix &= keepmask; + if (m_solid) + curpix |= m_solid_color & ~keepmask; + else + curpix |= srcdata & ~keepmask; + + /* if the window is enabled, only blit to videoram below the clipping address */ + /* note that we have to allow blits to non-video RAM (e.g. tileram, Sinistar $DXXX SRAM) because those */ + /* are not blocked by the window enable */ + if (!m_window_enable || dstaddr < m_clip_address || dstaddr >= 0xc000) + space.write_byte(dstaddr, curpix); +} + +int williams_blitter_device::blit_core(address_space &space, int w, int h) +{ + // compute how much to advance in the x and y loops + const bool dst_stride_256 = BIT(m_control, CONTROLBYTE_DST_STRIDE_256); + const bool src_stride_256 = BIT(m_control, CONTROLBYTE_SRC_STRIDE_256); + const int sxadv = src_stride_256 ? 0x100 : 1; + const int syadv = src_stride_256 ? 1 : w; + const int dxadv = dst_stride_256 ? 0x100 : 1; + const int dyadv = dst_stride_256 ? 1 : w; + + int accesses = 0; + int pixdata = 0; + + // loop over the height + const bool shift = BIT(m_control, CONTROLBYTE_SHIFT); + u16 sstart = m_sstart; + u16 dstart = m_dstart; + for (int y = 0; y < h; y++) + { + u16 source = sstart; + u16 dest = dstart; + + // loop over the width + for (int x = 0; x < w; x++) + { + const u8 rawval = m_remap[space.read_byte(source)]; + if (shift) + { + // shift one pixel right + pixdata = (pixdata << 8) | rawval; + blit_pixel(space, dest, (pixdata >> 4) & 0xff); + } + else + { + blit_pixel(space, dest, rawval); + } + accesses += 2; + + // advance src and dst pointers + source += sxadv; + dest += dxadv; + } + + // note that PlayBall! indicates the X coordinate doesn't wrap + if (dst_stride_256) + dstart = (dstart & 0xff00) | ((dstart + dyadv) & 0xff); + else + dstart += dyadv; + + if (src_stride_256) + sstart = (sstart & 0xff00) | ((sstart + syadv) & 0xff); + else + sstart += syadv; + } + return accesses; +} diff --git a/src/mame/midway/williamsblitter.h b/src/mame/midway/williamsblitter.h new file mode 100644 index 00000000000..98e2fe4391f --- /dev/null +++ b/src/mame/midway/williamsblitter.h @@ -0,0 +1,130 @@ +// license:BSD-3-Clause +// copyright-holders:Aaron Giles +/*************************************************************************** + + Williams first-generation blitter + +***************************************************************************/ + +#ifndef MAME_MIDWAY_WILLIAMSBLITTER_H +#define MAME_MIDWAY_WILLIAMSBLITTER_H + +#pragma once + +class williams_blitter_device : public device_t { +public: + template void set_cpu_tag(T &&cpu_tag) { m_cpu.set_tag(std::forward(cpu_tag)); } + template void set_vram_tag(T &&vram_tag) { m_vram.set_tag(std::forward(vram_tag)); } + template void set_proms_tag(T &&proms_tag) { m_proms.set_tag(std::forward(proms_tag)); } + + void map(address_map &map) ATTR_COLD; + + void remap_select_w(u8 data); + void window_enable_w(u8 data); + +protected: + williams_blitter_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock = 0); + + void set_clip_address(u16 clip_address) { m_clip_address = clip_address; } + void set_size_xor(u32 size_xor) { m_size_xor = size_xor; } + + virtual void device_start() override ATTR_COLD; + virtual void device_reset() override ATTR_COLD; + +private: + // control byte bit definitions + enum + { + CONTROLBYTE_NO_EVEN = 7, + CONTROLBYTE_NO_ODD = 6, + CONTROLBYTE_SHIFT = 5, + CONTROLBYTE_SOLID = 4, + CONTROLBYTE_FOREGROUND_ONLY = 3, + CONTROLBYTE_SLOW = 2, // 2us blits instead of 1us + CONTROLBYTE_DST_STRIDE_256 = 1, + CONTROLBYTE_SRC_STRIDE_256 = 0 + }; + + required_device m_cpu; + required_shared_ptr m_vram; + optional_region_ptr m_proms; + + void control_w(address_space &space, offs_t offset, u8 data); + inline void blit_pixel(address_space &space, int dstaddr, int srcdata); + int blit_core(address_space &space, int w, int h); + + u8 m_config; + u16 m_clip_address; + u8 m_window_enable; + u8 m_control; + bool m_no_even; + bool m_no_odd; + bool m_solid; + bool m_fg_only; + u8 m_solid_color; + u16 m_sstart; + u16 m_dstart; + u8 m_width; + u8 m_height; + u8 m_size_xor; + u8 m_remap_index; + const u8 *m_remap; + std::unique_ptr m_remap_lookup; +}; + +class williams_blitter_sc1_device : public williams_blitter_device { +public: + template + williams_blitter_sc1_device(const machine_config &mconfig, const char *tag, device_t *owner, u16 clip_address, T &&cpu_tag, U &&vram_tag) + : williams_blitter_sc1_device(mconfig, tag, owner) + { + set_size_xor(4); + set_clip_address(clip_address); + set_cpu_tag(std::forward(cpu_tag)); + set_vram_tag(std::forward(vram_tag)); + } + + template + williams_blitter_sc1_device(const machine_config &mconfig, const char *tag, device_t *owner, u16 clip_address, T &&cpu_tag, U &&vram_tag, V &&proms_tag) + : williams_blitter_sc1_device(mconfig, tag, owner) + { + set_size_xor(4); + set_clip_address(clip_address); + set_cpu_tag(std::forward(cpu_tag)); + set_vram_tag(std::forward(vram_tag)); + set_proms_tag(std::forward(proms_tag)); + } + + williams_blitter_sc1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); +}; + +class williams_blitter_sc2_device : public williams_blitter_device { +public: + template + williams_blitter_sc2_device(const machine_config &mconfig, const char *tag, device_t *owner, u16 clip_address, T &&cpu_tag, U &&vram_tag) + : williams_blitter_sc2_device(mconfig, tag, owner) + { + set_size_xor(0); + set_clip_address(clip_address); + set_cpu_tag(std::forward(cpu_tag)); + set_vram_tag(std::forward(vram_tag)); + } + + template + williams_blitter_sc2_device(const machine_config &mconfig, const char *tag, device_t *owner, u16 clip_address, T &&cpu_tag, U &&vram_tag, V &&proms_tag) + : williams_blitter_sc2_device(mconfig, tag, owner) + { + set_size_xor(0); + set_clip_address(clip_address); + set_cpu_tag(std::forward(cpu_tag)); + set_vram_tag(std::forward(vram_tag)); + set_proms_tag(std::forward(proms_tag)); + } + + williams_blitter_sc2_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); +}; + +DECLARE_DEVICE_TYPE(WILLIAMS_BLITTER_SC1, williams_blitter_sc1_device) +DECLARE_DEVICE_TYPE(WILLIAMS_BLITTER_SC2, williams_blitter_sc2_device) + +#endif // MAME_MIDWAY_WILLIAMSBLITTER_H diff --git a/src/mame/midway/wmg.cpp b/src/mame/midway/wmg.cpp index e5fc3178958..0a7cf9e787d 100644 --- a/src/mame/midway/wmg.cpp +++ b/src/mame/midway/wmg.cpp @@ -148,7 +148,7 @@ void wmg_state::wmg_cpu1(address_map &map) m_io_view[0](0xc804, 0xc807).r(FUNC(wmg_state::wmg_pia_0_r)).w(m_pia[0], FUNC(pia6821_device::write)); m_io_view[0](0xc80c, 0xc80f).rw(m_pia[1], FUNC(pia6821_device::read), FUNC(pia6821_device::write)); m_io_view[0](0xc900, 0xc9ff).nopr().w(FUNC(wmg_state::wmg_vram_select_w)); - m_io_view[0](0xca00, 0xca07).w(FUNC(wmg_state::blitter_w)); + m_io_view[0](0xca00, 0xca07).m(m_blitter, FUNC(williams_blitter_device::map)); m_io_view[0](0xcb00, 0xcbff).r(FUNC(wmg_state::video_counter_r)); m_io_view[0](0xcbff, 0xcbff).w(FUNC(wmg_state::watchdog_reset_w)); m_io_view[0](0xcc00, 0xcfff).bankrw(m_nvrambank); @@ -539,8 +539,7 @@ void wmg_state::wmg(machine_config &config) pia2.irqa_handler().set("soundirq", FUNC(input_merger_any_high_device::in_w<0>)); pia2.irqb_handler().set("soundirq", FUNC(input_merger_any_high_device::in_w<1>)); - m_blitter_config = WILLIAMS_BLITTER_SC1; - m_blitter_clip_address = 0xc000; + WILLIAMS_BLITTER_SC1(config, m_blitter, 0xc000, m_maincpu, m_videoram); } /************************************* -- cgit v1.2.3