From ac245e3ff741bdb91bfc8c826c723f19a182d88b Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Thu, 10 Dec 2015 16:23:34 +1100 Subject: [PATCH] Re-write S2636 from scratch as needed for subhuntr: * Needs raw screen parameters and calls from scanline timer to work properly * Collision and completion bits generated correctly including duplicates * Supports background and score display * Generates audio tone from line frequency * Probably hurts performance when rendering per frame --- src/devices/machine/s2636.cpp | 684 ++++++++++++++++++++-------------- src/devices/machine/s2636.h | 112 ++++-- src/mame/drivers/cvs.cpp | 15 +- src/mame/drivers/galaxia.cpp | 12 +- src/mame/drivers/laserbat.cpp | 18 +- src/mame/drivers/malzak.cpp | 12 +- src/mame/drivers/quasar.cpp | 3 - src/mame/drivers/seabattl.cpp | 5 +- src/mame/drivers/zac2650.cpp | 1 - src/mame/video/cvs.cpp | 18 +- src/mame/video/galaxia.cpp | 14 +- src/mame/video/malzak.cpp | 4 +- src/mame/video/quasar.cpp | 6 +- src/mame/video/zac2650.cpp | 2 +- 14 files changed, 530 insertions(+), 376 deletions(-) diff --git a/src/devices/machine/s2636.cpp b/src/devices/machine/s2636.cpp index 142514d8a19..b2105b30dce 100644 --- a/src/devices/machine/s2636.cpp +++ b/src/devices/machine/s2636.cpp @@ -1,75 +1,123 @@ // license:BSD-3-Clause -// copyright-holders:Mariusz Wojcieszek, Peter Trauner +// copyright-holders:Vas Crabb /********************************************************************** - Signetics 2636 video chip + Signetics 2636 Programmable Video Interface - PVI REGISTER DESCRIPTION - ------------------------ + This emulation is pretty low-level. For the most part it models + the kinds of counters and flags you'd use if you were actually + implementing it in programmable logic or on silicon. It even + renders pixels sequentially without multiple passes or needing to + backtrack. This works pretty well, but it probably isn't the most + efficient way to do things. I'm sure there are potential + performance improvements in the drawing and collision detection + code. + + At present the entire internal space of 256 bytes can be read and + written. This isn't accurate as some registers are read- or write- + only, and there are several unused blocks in the address range. We + should be returning some fixed value on attempt to read unreadable + locations. + + This implementation really needs proper display timing information + information to work properly. Audio pitch will be wrong if the + screen's scan time is inaccurate. Positioning objects depends on + the screen's visible area representing the pixel clock periods + periods between blanking pulses. You also need to call the line + rendering function at appropriate times if something expects to see + collision or completion flags. + + The crude "offset" system for adjusting the position of the image + has been maintained, but it's clearly inadequate for what games are + doing with it, and it will inevitably lead to bugs. If an object + is positioned outside the visible area using the offset mechanism, + it won't be displayed and neither will its duplicates. + + If what's happening in the games right now is correct, the hardware + must be feeding something other than the actual vertical and + horizontal blanking signals to the S2623(s) so they start drawing + inside the blanking region and have advanced to the desired + location on reaching the visible area. Implementing this properly + would require decoupling the S2623 from the screen and giving it + some other means to determine when it believes the blanking periods + begin and end. + + Sorry, analog input isn't currently supported, and neither is + interrupt request/acknowledge. I have't got to them yet, and I'm + still not sure whether reading a status register clears a pending + interrupt. The address decoding features still aren't implemented + but they'd be pretty hard to fit in the MAME framework. + + + ADDRESS MAP + ----------- + start end description + F00 F0D object descriptor 1 + F0E F0F 2 bytes scratch + F10 F1D object descriptor 2 + F1E F1F 2 bytes scratch + F20 F2D object descriptor 3 + F2E F3F - + F40 F4D object descriptor 4 + F4E F6D 32 bytes scratch + F6E F7F - + F80 FA7 background vertical bar definition + FA8 FAC background horizontal bar definition + FAD FAD 1 byte scratch + FAE FBF - + FC0 FCF I/O and control + FD0 FDF I/O and control (mirror) + FE0 FEF I/O and control (mirror) + FF0 FFF I/O and control (mirror) + + + OBJECT DESCRIPTOR + ----------------- + 0 9 basic shape of object (10 lines of 8 horizontal clocks) + A A horizontal coordinate of object (HC) + B B horizontal coordinate of duplicates (HCB) + C C vertical coordinate of object (VC) + D D vertical offset of duplicates (VCB) + + + I/O AND CONTROL + --------------- | bit |R/W| description byte | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | | | | | - FC0 | size 4| size 3| size 2| size 1| W | size of the 4 objects(=sprites) + FC0 | size 4| size 3| size 2| size 1| W | size of 4 objects (scale 2^x) | | | - FC1 | |C1 |C2 |C3 |C1 |C2 |C3 | W | colors of the 4 objects + FC1 | |C1 |C2 |C3 |C1 |C2 |C3 | W | colors of 4 objects | | color 1 | color 2 | | FC2 | |C1 |C2 |C3 |C1 |C2 |C3 | W | | | color 3 | color 4 | | | | | - FC3 | |sh |pos| W | 1=shape 0=position - | | | display format and position - FC4 | (free) | | - FC5 | (free) | | + FC3 | |frm|pos| W | scroe format and position | | | - FC6 | |C1 |C2 |C3 |BG |scrn colr | W | background lock and color - | |backg colr |enb|C1 |C2 |C3 | | 3="enable" + FC4 | | - | + FC5 | | - | | | | - FC7 | sound | W | squarewave output + FC6 | |C1 |C2 |C3 |BG | scrn colr | W | background enable and color + | |backg colr |enb|C1 |C2 |C3 | | | | | - FC8 | N1 | N2 | W | range of the 4 display digits + FC7 | sound | W | sound square wave period + | | | + FC8 | N1 | N2 | W | values of the four score digits FC9 | N3 | N4 | W | | | | - |obj/backgrnd |complete object| R | - FCA | 1 | 2 | 3 | 4 | 1 | 2 | 3 | 4 | | + | obj/backgrnd |object complete| R | object/background and inter-object + FCA | 1 | 2 | 3 | 4 | 1 | 2 | 3 | 4 | | collision status and object display + | | | completion status + FCB | |VR-| object collisions | R | VRLE set at leading edge of VRST, + | |LE |1/2|1/3|1/3|1/4|2/4|3/4| | all bits reset when read or at + | | | trailing edge of VRST | | | - FCB | |VR-| object collisions | R | Composition of object and back- - | |LE |1/2|1/3|1/3|1/4|2/4|3/4| | ground,collision detection and - | | | object display as a state display - | | | for the status register.Set VRLE. - | | | wait for VRST.Read out or transmit - | | | [copy?] all bits until reset by - | | | VRST. + FCC | A/D POT 1 | R | POT1 and POT2 A/D conversion value + FCD | A/D POT 2 | R | valid during VRST only | | | - FCC | PORT1 | R | PORT1 and PORT2 for the range of - FCD | PORT2 | | the A/D conversion.Cleared by VRST - FCE | (free) | | - FCF | (free) | | - - - Size control by byte FC0 - - bit matrix - |0|0| 8x10 - |0|1| 16x20 - |1|0| 32x40 - |1|1| 64x80 - - CE1 and not-CE2 are outputs from the PVI.$E80..$EFF also controls the - analog multiplexer. - - - SPRITES - ------- - - each object field: (=sprite data structure) - - 0 \ 10 bytes of bitmap (Each object is 8 pixels wide.) - 9 / - A HC horizontal object coordinate - B HCB horizontal duplicate coordinate - C VC vertical object coordinate - D VCB vertical duplicate coordinate + FCE | | - | + FCF | | - | *************************************************************/ @@ -77,6 +125,31 @@ #include "machine/s2636.h" +int const s2636_device::OFFS_OBJ[s2636_device::OBJ_COUNT] = { 0x000, 0x010, 0x020, 0x040 }; + +int const s2636_device::SCORE_START_X[2][s2636_device::SCORE_DIGITS] { { 48, 64, 96, 112 }, { 48, 64, 80, 96 } }; +int const s2636_device::SCORE_START_Y[2] = { 20, 200 }; + +UINT16 const s2636_device::SCORE_FONT[16][5] = +{ + { 0x0fff, 0x0f0f, 0x0f0f, 0x0f0f, 0x0fff }, + { 0x0f00, 0x0f00, 0x0f00, 0x0f00, 0x0f00 }, + { 0x0fff, 0x0f00, 0x0fff, 0x000f, 0x0fff }, + { 0x0fff, 0x0f00, 0x0fff, 0x0f00, 0x0fff }, + { 0x0f0f, 0x0f0f, 0x0fff, 0x0f00, 0x0f00 }, + { 0x0fff, 0x000f, 0x0fff, 0x0f00, 0x0fff }, + { 0x0fff, 0x000f, 0x0fff, 0x0f0f, 0x0fff }, + { 0x0fff, 0x0f00, 0x0f00, 0x0f00, 0x0f00 }, + { 0x0fff, 0x0f0f, 0x0fff, 0x0f0f, 0x0fff }, + { 0x0fff, 0x0f0f, 0x0fff, 0x0f00, 0x0fff }, + { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, + { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, + { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, + { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, + { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, + { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 } +}; + /************************************* * * Device interface @@ -86,19 +159,23 @@ const device_type S2636 = &device_creator; s2636_device::s2636_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : device_t(mconfig, S2636, "Signetics 2636", tag, owner, clock, "s2636", __FILE__), - device_video_interface(mconfig, *this), - device_sound_interface(mconfig, *this), - m_channel(nullptr), - m_size(0), - m_pos(0), - m_level(0), - m_work_ram_size(0), - m_y_offset(0), - m_x_offset(0) + : device_t(mconfig, S2636, "Signetics 2636", tag, owner, clock, "s2636", __FILE__) + , device_video_interface(mconfig, *this) + , device_sound_interface(mconfig, *this) + , m_divider(1) + , m_y_offset(0) + , m_x_offset(0) + , m_vrst(false) + , m_screen_line(0) + , m_vis_line(0) + , m_stream(nullptr) + , m_sample_cnt(0) + , m_sound_lvl(false) { - for (auto & elem : m_reg) - elem = 0; + for (auto &elem : m_registers) elem = 0; + for (auto &elem : m_obj_cnt) elem = 0; + for (auto &elem : m_obj_disp) elem = false; + for (auto &elem : m_obj_dup) elem = false; } //------------------------------------------------- @@ -107,261 +184,292 @@ s2636_device::s2636_device(const machine_config &mconfig, const char *tag, devic void s2636_device::device_start() { - int width = m_screen->width(); - int height = m_screen->height(); + m_bitmap.resize(m_screen->width(), m_screen->height()); - m_work_ram.resize(m_work_ram_size); - memset(&m_work_ram[0], 0, m_work_ram_size); - m_bitmap.resize(width, height); - m_collision_bitmap.resize(width, height); - - save_item(NAME(m_work_ram)); save_item(NAME(m_bitmap)); - save_item(NAME(m_collision_bitmap)); - m_channel = machine().sound().stream_alloc(*this, 0, 1, machine().sample_rate()); - save_item(NAME(m_size)); - save_item(NAME(m_pos)); - save_item(NAME(m_level)); - save_item(NAME(m_reg)); + save_item(NAME(m_registers)); + + save_item(NAME(m_obj_cnt)); + save_item(NAME(m_obj_disp)); + save_item(NAME(m_obj_dup)); + + save_item(NAME(m_vrst)); + save_item(NAME(m_screen_line)); + save_item(NAME(m_vis_line)); + + m_stream = machine().sound().stream_alloc(*this, 0, 1, machine().sample_rate()); + save_item(NAME(m_sample_cnt)); + save_item(NAME(m_sound_lvl)); } -/************************************* - * - * Constants - * - *************************************/ +//------------------------------------------------- +// backwards-compatible update method +//------------------------------------------------- -#define SPRITE_WIDTH (8) -#define SPRITE_HEIGHT (10) - -static const int sprite_offsets[4] = { 0x00, 0x10, 0x20, 0x40 }; - - -/************************************* - * - * Draw a sprite - * - *************************************/ - -static void draw_sprite( UINT8 *gfx, int color, int y, int x, int expand, int or_mode, bitmap_ind16 &bitmap, const rectangle &cliprect ) +bitmap_ind16 const &s2636_device::update(const rectangle &cliprect) { - /* for each row */ - for (int sy = 0; sy < SPRITE_HEIGHT; sy++) - { - /* for each pixel on the row */ - for (int sx = 0; sx < SPRITE_WIDTH; sx++) - { - /* each pixel can be expanded */ - for (int ey = 0; ey <= expand; ey++) - { - for (int ex = 0; ex <= expand; ex++) - { - /* compute effective destination pixel */ - int ty = y + sy * (expand + 1) + ey; - int tx = x + sx * (expand + 1) + ex; - - /* get out if outside the drawing region */ - if (!cliprect.contains(tx, ty)) - continue; - - /* get out if current image bit is transparent */ - if (((gfx[sy] << sx) & 0x80) == 0x00) - continue; - - if (or_mode) - bitmap.pix16(ty, tx) = 0x08 | bitmap.pix16(ty, tx) | color; - else - bitmap.pix16(ty, tx) = 0x08 | color; - } - } - } - } -} - - -/************************************* - * - * Collision detection - * - *************************************/ - -int s2636_device::check_collision( int spriteno1, int spriteno2, const rectangle &cliprect ) -{ - int checksum = 0; - - UINT8* attr1 = &m_work_ram[sprite_offsets[spriteno1]]; - UINT8* attr2 = &m_work_ram[sprite_offsets[spriteno2]]; - - /* TODO: does not check shadow sprites yet */ - - m_collision_bitmap.fill(0, cliprect); - - if ((attr1[0x0a] != 0xff) && (attr2[0x0a] != 0xff)) - { - int x, y; - - int x1 = attr1[0x0a] + m_x_offset; - int y1 = attr1[0x0c] + m_y_offset; - int x2 = attr2[0x0a] + m_x_offset; - int y2 = attr2[0x0c] + m_y_offset; - - int expand1 = (m_work_ram[0xc0] >> (spriteno1 << 1)) & 0x03; - int expand2 = (m_work_ram[0xc0] >> (spriteno2 << 1)) & 0x03; - - /* draw first sprite */ - draw_sprite(attr1, 1, y1, x1, expand1, FALSE, m_collision_bitmap, cliprect); - - /* get fingerprint */ - for (x = x1; x < x1 + SPRITE_WIDTH; x++) - for (y = y1; y < y1 + SPRITE_HEIGHT; y++) - { - if (!cliprect.contains(x, y)) - continue; - - checksum = checksum + m_collision_bitmap.pix16(y, x); - } - - /* black out second sprite */ - draw_sprite(attr2, 0, y2, x2, expand2, FALSE, m_collision_bitmap, cliprect); - - /* remove fingerprint */ - for (x = x1; x < x1 + SPRITE_WIDTH; x++) - for (y = y1; y < y1 + SPRITE_HEIGHT; y++) - { - if (!cliprect.contains(x, y)) - continue; - - checksum = checksum - m_collision_bitmap.pix16(y, x); - } - } - - return (checksum != 0); -} - - - -/************************************* - * - * Main drawing - * - *************************************/ - -bitmap_ind16 &s2636_device::update( const rectangle &cliprect ) -{ - UINT8 collision = 0; - int spriteno; - - m_bitmap.fill(0, cliprect); - - for (spriteno = 0; spriteno < 4; spriteno++) - { - int color, expand, x, y; - UINT8* attr = &m_work_ram[sprite_offsets[spriteno]]; - - /* get out if sprite is turned off */ - if (attr[0x0a] == 0xff) - continue; - - x = attr[0x0a] + m_x_offset; - y = attr[0x0c] + m_y_offset; - - color = (m_work_ram[0xc1 + (spriteno >> 1)] >> ((spriteno & 1) ? 0 : 3)) & 0x07; - expand = (m_work_ram[0xc0] >> (spriteno << 1)) & 0x03; - - draw_sprite(attr, color, y, x, expand, TRUE, m_bitmap, cliprect); - - /* bail if no shadow sprites */ - if ((attr[0x0b] == 0xff) || (attr[0x0d] == 0xfe)) - continue; - - x = attr[0x0b] + m_x_offset; - - while (y < 0xff) - { - y = y + SPRITE_HEIGHT + attr[0x0d]; - - draw_sprite(attr, color, y, x, expand, TRUE, m_bitmap, cliprect); - } - } - - /* collision detection */ - if (check_collision(0, 1, cliprect)) collision |= 0x20; - if (check_collision(0, 2, cliprect)) collision |= 0x10; - if (check_collision(0, 3, cliprect)) collision |= 0x08; - if (check_collision(1, 2, cliprect)) collision |= 0x04; - if (check_collision(1, 3, cliprect)) collision |= 0x02; - if (check_collision(2, 3, cliprect)) collision |= 0x01; - - m_work_ram[0xcb] = collision; + m_vrst = true; + m_screen_line = m_screen->visible_area().min_y; + while (m_screen_line <= m_screen->visible_area().max_y) + render_next_line(); return m_bitmap; } -/************************************* - * - * Work RAM access handlers - * - *************************************/ - -WRITE8_MEMBER( s2636_device::work_ram_w ) +void s2636_device::render_first_line() { - assert(offset < m_work_ram_size); - - if ( offset == 0xc7 ) - { - soundport_w(0, data); - } - - m_work_ram[offset] = data; + m_screen_line = 0; + render_next_line(); } -READ8_MEMBER( s2636_device::work_ram_r ) +void s2636_device::render_next_line() { - assert(offset < m_work_ram_size); + rectangle const &vis_area = m_screen->visible_area(); + UINT16 *const row = &m_bitmap.pix16(m_screen_line); - return m_work_ram[offset]; -} - -/* Sound */ - -void s2636_device::soundport_w (int offset, int data) -{ - m_channel->update(); - m_reg[offset] = data; - switch (offset) + if ((vis_area.min_y > m_screen_line) || (vis_area.max_y < m_screen_line)) { - case 0: - m_pos = 0; - m_level = TRUE; - // frequency 7874/(data+1) - m_size = machine().sample_rate() * (data + 1) /7874; - break; + if (!m_vrst) + { + m_registers[REG_VBL_COL_OBJ] |= 0x40; + m_vrst = true; + } + for (int screen_col = 0; screen_col < m_bitmap.width(); screen_col++) + { + row[screen_col] = 0; + } } + else + { + // check for first visible line + if (m_vrst) + { + // latch vertical position primary objects + for (int i = 0; i < OBJ_COUNT; i++) + { + m_obj_cnt[i] = m_registers[OFFS_OBJ[i] + OFFS_VC] + m_y_offset; + m_obj_disp[i] = false; + m_obj_dup[i] = false; + } + + // collision, completion and vertical reset flags are cleared here + m_registers[REG_COL_BG_CMPL] = 0x00; + m_registers[REG_VBL_COL_OBJ] = 0x00; + + // set our internal tracking flags + m_vrst = false; + m_vis_line = 0; + } + + // work out what object pixels belong in this line + UINT16 obj_clr[OBJ_COUNT]; + int obj_h_cnt[OBJ_COUNT]; + int obj_inc[OBJ_COUNT]; + UINT8 obj_bits[OBJ_COUNT]; + for (int i = 0; i < OBJ_COUNT; i++) + { + obj_clr[i] = object_color(i) | 0x08; + obj_h_cnt[i] = m_registers[OFFS_OBJ[i] + (m_obj_dup[i] ? OFFS_HCB : OFFS_HC)] + m_x_offset; + obj_inc[i] = 1 << (3 - object_scale(i)); + + // repurpose counter and set flag when we've skipped enough lines + if (!m_obj_cnt[i]) + { + m_obj_cnt[i] = OBJ_HEIGHT << 3; + m_obj_disp[i] = true; + } + + if (m_obj_disp[i]) + { + // fetch appropriate line from object + m_obj_cnt[i] -= obj_inc[i]; + obj_bits[i] = m_registers[OFFS_OBJ[i] + OBJ_HEIGHT - 1 - (m_obj_cnt[i] >> 3)]; + + // if that's the last line of the object, flag completion and prepare for duplicates + if (!m_obj_cnt[i]) + { + m_registers[REG_COL_BG_CMPL] |= 0x01 << (3 - i); + m_obj_cnt[i] = 1 + m_registers[OFFS_OBJ[i] + OFFS_VCB]; + m_obj_disp[i] = false; + m_obj_dup[i] = true; + } + } + else + { + // count down lines to display object + m_obj_cnt[i]--; + obj_bits[i] = 0x00; + } + } + + // work out how the background pattern will be drawn + bool const bg_enable = bool(m_registers[REG_BG_ENB_CLR] & 0x08); + int const bg_row = m_vis_line - m_y_offset - BG_START_Y; + bool const bg_draw = bg_enable && (0 <= bg_row) && (BG_HEIGHT > bg_row); + int const bg_vbar_offs = OFFS_VBAR_DEF + ((bg_row / 20) << 2) + (((bg_row % 20) >= 2) ? 2 : 0); + int const bg_hbar_offs = OFFS_HBAR_DEF + (bg_row / 40); + UINT16 const bg_vbar_bits = (UINT16(m_registers[bg_vbar_offs]) << 8) | UINT16(m_registers[bg_vbar_offs + 1]); + UINT8 const bg_hbar_bits = m_registers[bg_hbar_offs]; + bool const bg_hbar_stretch = bool(bg_hbar_bits & (1 << ((((bg_row % 40) >= 20) ? 3 : 0) + (((bg_row % 20) >= 11) ? 2 : ((bg_row % 20) >= 2) ? 1 : 0)))); + int const bg_hbar_width = bg_hbar_stretch ? 8 : (0xc0 == (bg_hbar_bits & 0xc0)) ? 4 : (0x40 == (bg_hbar_bits & 0xc0)) ? 2 : 1; + UINT16 const bg_clr = m_registers[REG_BG_ENB_CLR] & 0x07; + UINT16 const scrn_clr = bg_enable ? ((m_registers[REG_BG_ENB_CLR] >> 4) & 0x07) : 0x00; + + // let's take a look at the score display + int const (&score_start_x)[SCORE_DIGITS] = SCORE_START_X[(m_registers[REG_SCORE_FMT] >> 1) & 0x01]; + int const score_row = m_vis_line - m_y_offset - SCORE_START_Y[m_registers[REG_SCORE_FMT] & 0x01]; + bool const score_draw = (0 <= score_row) && (SCORE_HEIGHT > score_row); + UINT16 score_bits[SCORE_DIGITS]; + for (int i = 0; i < SCORE_DIGITS; i++) + score_bits[i] = score_draw ? SCORE_FONT[score_digit(i)][score_row >> 2] : 0x0000; + + // clear leading horizontal blanking area + m_bitmap.plot_box(0, m_screen_line, m_bitmap.width(), 1, 0); + + bool obj_vis[4] = { false, false, false, false }; + for (int screen_col = vis_area.min_x, x = 0; vis_area.max_x >= screen_col; x++) + { + // render objects + bool obj[4]; + for (int i = 0; i < OBJ_COUNT; i++) + { + if (!obj_h_cnt[i]) + { + obj_h_cnt[i] = OBJ_WIDTH << 3; + obj_vis[i] = true; + } + if (obj_vis[i]) + { + obj_h_cnt[i] -= obj_inc[i]; + obj[i] = bool(obj_bits[i] & (1U << (obj_h_cnt[i] >> 3))); + if (obj[i]) row[screen_col] |= obj_clr[i]; + if (!obj_h_cnt[i]) + { + obj_h_cnt[i] = -1; + obj_vis[i] = 0; + } + } + else + { + obj_h_cnt[i]--; + obj[i] = false; + } + } + + // check object-object collisions + if (obj[0] && obj[1]) m_registers[REG_VBL_COL_OBJ] |= 0x20; + if (obj[0] && obj[2]) m_registers[REG_VBL_COL_OBJ] |= 0x10; + if (obj[0] && obj[3]) m_registers[REG_VBL_COL_OBJ] |= 0x08; + if (obj[1] && obj[2]) m_registers[REG_VBL_COL_OBJ] |= 0x04; + if (obj[1] && obj[3]) m_registers[REG_VBL_COL_OBJ] |= 0x02; + if (obj[2] && obj[3]) m_registers[REG_VBL_COL_OBJ] |= 0x01; + + // render scores + if (score_draw) + { + for (int i = 0; i < SCORE_DIGITS; i++) + { + int const score_col = x - m_x_offset - score_start_x[i]; + bool const score = bool(score_bits[i] & (1U << score_col)); + if ((0 <= score_col) && (SCORE_WIDTH > score_col) && score) + row[screen_col] |= bg_clr | 0x08; + } + } + + // work out if the background hits this pixel + int const bg_col = x - m_x_offset - BG_START_X; + bool const bg = bool(bg_vbar_bits & (1U << (15 - (bg_col >> 3)))); + if (bg_draw && (0 <= bg_col) && (BG_WIDTH > bg_col) && bg && (bg_hbar_width > (bg_col & 0x07))) + { + // do object-background collisions + if (obj[0]) m_registers[REG_COL_BG_CMPL] |= 0x80; + if (obj[1]) m_registers[REG_COL_BG_CMPL] |= 0x40; + if (obj[2]) m_registers[REG_COL_BG_CMPL] |= 0x20; + if (obj[3]) m_registers[REG_COL_BG_CMPL] |= 0x10; + if (!(row[screen_col] & 0x08)) row[screen_col] = bg_clr; + } + else if (!(row[screen_col] & 0x08)) + { + // draw screen background if not obscured + row[screen_col] = scrn_clr; + } + + // advance the screen column + screen_col++; + + // deal with pixel clock divider ratio + for (int i = 1; (i < m_divider) && (vis_area.max_x >= screen_col); i++, screen_col++) + { + row[screen_col] = row[screen_col - 1]; + } + } + } + + m_screen_line++; + m_vis_line++; } //------------------------------------------------- -// sound_stream_update - handle a stream update +// bus access handlers +//------------------------------------------------- + +READ8_MEMBER( s2636_device::read ) +{ + mask_offset(offset); + UINT8 data = m_registers[offset]; + + // TODO: some locations are not readable, should return some garbage + + switch (offset) + { + case REG_COL_BG_CMPL: + case REG_VBL_COL_OBJ: + m_registers[offset] = 0x00; // collision/completion/VRESET flags reset on read + break; + } + + return data; +} + +WRITE8_MEMBER( s2636_device::write ) +{ + mask_offset(offset); + + if (REG_SND_PERIOD == offset) + m_stream->update(); + + m_registers[offset] = data; +} + + +//------------------------------------------------- +// sound_stream_update - generate audio output //------------------------------------------------- void s2636_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) { - int i; stream_sample_t *buffer = outputs[0]; - - for (i = 0; i < samples; i++, buffer++) + while (samples--) { - *buffer = 0; - if (m_reg[0] && m_pos <= m_size / 2) + if (!m_sample_cnt) { - *buffer = 0x7fff; + if (m_registers[REG_SND_PERIOD]) + { + m_sample_cnt = (machine().sample_rate() * (m_registers[REG_SND_PERIOD] + 1) * m_screen->scan_period()).seconds(); + m_sound_lvl = !m_sound_lvl; + } + else + { + m_sample_cnt = 1; + m_sound_lvl = false; + } } - if (m_pos <= m_size) - m_pos++; - if (m_pos > m_size) - m_pos = 0; + + *buffer++ = m_sound_lvl ? 0x7fff : 0x0000; + m_sample_cnt--; } } diff --git a/src/devices/machine/s2636.h b/src/devices/machine/s2636.h index e6bbbfff32b..eb97a1b74b4 100644 --- a/src/devices/machine/s2636.h +++ b/src/devices/machine/s2636.h @@ -1,8 +1,8 @@ // license:BSD-3-Clause -// copyright-holders:Mariusz Wojcieszek, Peter Trauner +// copyright-holders:Vas Crabb /********************************************************************** - Signetics 2636 video chip + Signetics 2636 Programmable Video Interface **********************************************************************/ @@ -27,7 +27,6 @@ public: s2636_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); ~s2636_device() {} - static void set_workram_size(device_t &device, int size) { downcast(device).m_work_ram_size = size; } static void set_offsets(device_t &device, int y_offset, int x_offset) { s2636_device &dev = downcast(device); @@ -35,15 +34,27 @@ public: dev.m_y_offset = y_offset; } + static void set_divider(device_t &device, int divider) + { + s2636_device &dev = downcast(device); + dev.m_divider = divider; + } + // returns a BITMAP_FORMAT_IND16 bitmap the size of the screen // D0-D2 of each pixel is the pixel color - // D3 indicates whether the S2636 drew this pixel - 0 = not drawn, 1 = drawn - bitmap_ind16 &update(const rectangle &cliprect); + // D3 indicates how the S2636 drew this pixel - 0 = background, 1 = object/score + bitmap_ind16 const &bitmap() const { return m_bitmap; } - DECLARE_WRITE8_MEMBER( work_ram_w ); - DECLARE_READ8_MEMBER( work_ram_r ); + // this function is for backwards compatibility and will eventually be removed + // use the functions below for per-scanline drawing/collisions + bitmap_ind16 const &update(const rectangle &cliprect); - void soundport_w(int mode, int data); + // call render_first_line to render the first line of the display and render_next_line for each additional line + void render_first_line(); + void render_next_line(); + + DECLARE_READ8_MEMBER( read ); + DECLARE_WRITE8_MEMBER( write ); protected: // device-level overrides @@ -53,22 +64,77 @@ protected: virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override; private: - // internal state - dynamic_buffer m_work_ram; - bitmap_ind16 m_bitmap; - bitmap_ind16 m_collision_bitmap; + enum + { + OBJ_COUNT = 4, - sound_stream *m_channel; - UINT8 m_reg[1]; - int m_size; - int m_pos; - unsigned m_level; + OBJ_WIDTH = 8, + OBJ_HEIGHT = 10, - int m_work_ram_size; - int m_y_offset; - int m_x_offset; + BG_START_X = 32, + BG_START_Y = 20, + BG_WIDTH = 8 * 16, + BG_HEIGHT = 200, - int check_collision( int spriteno1, int spriteno2, const rectangle &cliprect ); + SCORE_DIGITS = 4, + + SCORE_WIDTH = 12, + SCORE_HEIGHT = 20, + + OFFS_HC = 0x00a, + OFFS_HCB = 0x00b, + OFFS_VC = 0x00c, + OFFS_VCB = 0x00d, + + OFFS_VBAR_DEF = 0x080, + OFFS_HBAR_DEF = 0x0a8, + + REG_OBJ_SIZE = 0x0c0, + REG_OBJ_CLR_1_2 = 0x0c1, + REG_OBJ_CLR_3_4 = 0x0c2, + REG_SCORE_FMT = 0x0c3, + REG_BG_ENB_CLR = 0x0c6, + REG_SND_PERIOD = 0x0c7, + REG_SCORE_1_2 = 0x0c8, + REG_SCORE_3_4 = 0x0c9, + REG_COL_BG_CMPL = 0x0ca, + REG_VBL_COL_OBJ = 0x0cb, + REG_AD_POT1 = 0x0cc, + REG_AD_POT2 = 0x0cd + }; + + static int const OFFS_OBJ[OBJ_COUNT]; + + static UINT16 const SCORE_FONT[16][5]; + + static int const SCORE_START_X[2][SCORE_DIGITS]; + static int const SCORE_START_Y[2]; + + static void mask_offset(offs_t &offset) { offset &= ((offset & 0x0c0) == 0x0c0) ? 0x0cf : 0x0ff; } + + UINT8 object_scale(int obj) const { return (m_registers[REG_OBJ_SIZE] >> (2 * obj)) & 0x03; } + UINT8 object_color(int obj) const { return (m_registers[REG_OBJ_CLR_1_2 + (obj >> 1)] >> ((obj & 1) ? 0 : 3)) & 0x07; } + UINT8 score_digit(int digit) const { return (m_registers[REG_SCORE_1_2 + (digit >> 1)] >> ((digit & 1) ? 0 : 4)) & 0x0f; } + + int m_divider; + int m_y_offset; + int m_x_offset; + + bitmap_ind16 m_bitmap; + + UINT8 m_registers[0x100]; + + int m_obj_cnt[OBJ_COUNT]; + bool m_obj_disp[OBJ_COUNT]; + bool m_obj_dup[OBJ_COUNT]; + + bool m_vrst; + int m_screen_line; + int m_vis_line; + + sound_stream *m_stream; + int m_sample_cnt; + bool m_sound_lvl; }; extern const device_type S2636; @@ -77,8 +143,8 @@ extern const device_type S2636; #define MCFG_S2636_OFFSETS(_yoffs, _xoffs) \ s2636_device::set_offsets(*device, _yoffs, _xoffs); -#define MCFG_S2636_WORKRAM_SIZE(_size) \ - s2636_device::set_workram_size(*device, _size); +#define MCFG_S2636_DIVIDER(_divider) \ + s2636_device::set_divider(*device, _divider); #endif /* __S2636_H__ */ diff --git a/src/mame/drivers/cvs.cpp b/src/mame/drivers/cvs.cpp index 4c013254dfa..f3ec7e6ed80 100644 --- a/src/mame/drivers/cvs.cpp +++ b/src/mame/drivers/cvs.cpp @@ -155,7 +155,7 @@ READ8_MEMBER(cvs_state::cvs_s2636_0_or_character_ram_r) if (m_s2650_flag) return m_character_ram[(0 * 0x800) | 0x400 | m_character_ram_page_start | offset]; else - return m_s2636_0->work_ram_r(space, offset); + return m_s2636_0->read(space, offset); } WRITE8_MEMBER(cvs_state::cvs_s2636_0_or_character_ram_w) @@ -167,7 +167,7 @@ WRITE8_MEMBER(cvs_state::cvs_s2636_0_or_character_ram_w) m_gfxdecode->gfx(1)->mark_dirty((offset / 8) % 256); } else - m_s2636_0->work_ram_w(space, offset, data); + m_s2636_0->write(space, offset, data); } @@ -176,7 +176,7 @@ READ8_MEMBER(cvs_state::cvs_s2636_1_or_character_ram_r) if (m_s2650_flag) return m_character_ram[(1 * 0x800) | 0x400 | m_character_ram_page_start | offset]; else - return m_s2636_1->work_ram_r(space, offset); + return m_s2636_1->read(space, offset); } WRITE8_MEMBER(cvs_state::cvs_s2636_1_or_character_ram_w) @@ -188,7 +188,7 @@ WRITE8_MEMBER(cvs_state::cvs_s2636_1_or_character_ram_w) m_gfxdecode->gfx(1)->mark_dirty((offset / 8) % 256); } else - m_s2636_1->work_ram_w(space, offset, data); + m_s2636_1->write(space, offset, data); } @@ -197,7 +197,7 @@ READ8_MEMBER(cvs_state::cvs_s2636_2_or_character_ram_r) if (m_s2650_flag) return m_character_ram[(2 * 0x800) | 0x400 | m_character_ram_page_start | offset]; else - return m_s2636_2->work_ram_r(space, offset); + return m_s2636_2->read(space, offset); } WRITE8_MEMBER(cvs_state::cvs_s2636_2_or_character_ram_w) @@ -209,7 +209,7 @@ WRITE8_MEMBER(cvs_state::cvs_s2636_2_or_character_ram_w) m_gfxdecode->gfx(1)->mark_dirty((offset / 8) % 256); } else - m_s2636_2->work_ram_w(space, offset, data); + m_s2636_2->write(space, offset, data); } @@ -1011,15 +1011,12 @@ static MACHINE_CONFIG_START( cvs, cvs_state ) MCFG_SCREEN_PALETTE("palette") MCFG_DEVICE_ADD("s2636_0", S2636, 0) - MCFG_S2636_WORKRAM_SIZE(0x100) MCFG_S2636_OFFSETS(CVS_S2636_Y_OFFSET, CVS_S2636_X_OFFSET) MCFG_DEVICE_ADD("s2636_1", S2636, 0) - MCFG_S2636_WORKRAM_SIZE(0x100) MCFG_S2636_OFFSETS(CVS_S2636_Y_OFFSET, CVS_S2636_X_OFFSET) MCFG_DEVICE_ADD("s2636_2", S2636, 0) - MCFG_S2636_WORKRAM_SIZE(0x100) MCFG_S2636_OFFSETS(CVS_S2636_Y_OFFSET, CVS_S2636_X_OFFSET) /* audio hardware */ diff --git a/src/mame/drivers/galaxia.cpp b/src/mame/drivers/galaxia.cpp index 1e52fa6f881..23723f1ffce 100644 --- a/src/mame/drivers/galaxia.cpp +++ b/src/mame/drivers/galaxia.cpp @@ -130,9 +130,9 @@ READ8_MEMBER(galaxia_state::galaxia_collision_clear) static ADDRESS_MAP_START( galaxia_mem_map, AS_PROGRAM, 8, galaxia_state ) AM_RANGE(0x0000, 0x13ff) AM_ROM AM_RANGE(0x1400, 0x14ff) AM_MIRROR(0x6000) AM_RAM AM_SHARE("bullet_ram") - AM_RANGE(0x1500, 0x15ff) AM_MIRROR(0x6000) AM_DEVREADWRITE("s2636_0", s2636_device, work_ram_r, work_ram_w) - AM_RANGE(0x1600, 0x16ff) AM_MIRROR(0x6000) AM_DEVREADWRITE("s2636_1", s2636_device, work_ram_r, work_ram_w) - AM_RANGE(0x1700, 0x17ff) AM_MIRROR(0x6000) AM_DEVREADWRITE("s2636_2", s2636_device, work_ram_r, work_ram_w) + AM_RANGE(0x1500, 0x15ff) AM_MIRROR(0x6000) AM_DEVREADWRITE("s2636_0", s2636_device, read, write) + AM_RANGE(0x1600, 0x16ff) AM_MIRROR(0x6000) AM_DEVREADWRITE("s2636_1", s2636_device, read, write) + AM_RANGE(0x1700, 0x17ff) AM_MIRROR(0x6000) AM_DEVREADWRITE("s2636_2", s2636_device, read, write) AM_RANGE(0x1800, 0x1bff) AM_MIRROR(0x6000) AM_READ(cvs_video_or_color_ram_r) AM_WRITE(galaxia_video_w) AM_SHARE("video_ram") AM_RANGE(0x1c00, 0x1fff) AM_MIRROR(0x6000) AM_RAM AM_RANGE(0x2000, 0x33ff) AM_ROM @@ -142,7 +142,7 @@ ADDRESS_MAP_END static ADDRESS_MAP_START( astrowar_mem_map, AS_PROGRAM, 8, galaxia_state ) AM_RANGE(0x0000, 0x13ff) AM_ROM AM_RANGE(0x1400, 0x14ff) AM_MIRROR(0x6000) AM_RAM - AM_RANGE(0x1500, 0x15ff) AM_MIRROR(0x6000) AM_DEVREADWRITE("s2636_0", s2636_device, work_ram_r, work_ram_w) + AM_RANGE(0x1500, 0x15ff) AM_MIRROR(0x6000) AM_DEVREADWRITE("s2636_0", s2636_device, read, write) AM_RANGE(0x1800, 0x1bff) AM_MIRROR(0x6000) AM_READ(cvs_video_or_color_ram_r) AM_WRITE(galaxia_video_w) AM_SHARE("video_ram") AM_RANGE(0x1c00, 0x1cff) AM_MIRROR(0x6000) AM_RAM AM_SHARE("bullet_ram") AM_RANGE(0x2000, 0x33ff) AM_ROM @@ -307,17 +307,14 @@ static MACHINE_CONFIG_START( galaxia, galaxia_state ) MCFG_VIDEO_START_OVERRIDE(galaxia_state,galaxia) MCFG_DEVICE_ADD("s2636_0", S2636, 0) - MCFG_S2636_WORKRAM_SIZE(0x100) MCFG_S2636_OFFSETS(3, -26) MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25) MCFG_DEVICE_ADD("s2636_1", S2636, 0) - MCFG_S2636_WORKRAM_SIZE(0x100) MCFG_S2636_OFFSETS(3, -26) MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25) MCFG_DEVICE_ADD("s2636_2", S2636, 0) - MCFG_S2636_WORKRAM_SIZE(0x100) MCFG_S2636_OFFSETS(3, -26) MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25) @@ -352,7 +349,6 @@ static MACHINE_CONFIG_START( astrowar, galaxia_state ) MCFG_VIDEO_START_OVERRIDE(galaxia_state,astrowar) MCFG_DEVICE_ADD("s2636_0", S2636, 0) - MCFG_S2636_WORKRAM_SIZE(0x100) MCFG_S2636_OFFSETS(3, 0) MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25) diff --git a/src/mame/drivers/laserbat.cpp b/src/mame/drivers/laserbat.cpp index 12d7da251bc..bf52a8c25dd 100644 --- a/src/mame/drivers/laserbat.cpp +++ b/src/mame/drivers/laserbat.cpp @@ -165,9 +165,9 @@ static ADDRESS_MAP_START( laserbat_map, AS_PROGRAM, 8, laserbat_state ) AM_RANGE(0x7800, 0x7bff) AM_ROM AM_RANGE(0x1400, 0x14ff) AM_MIRROR(0x6000) AM_WRITENOP // always 0 (bullet ram in Quasar) - AM_RANGE(0x1500, 0x15ff) AM_MIRROR(0x6000) AM_DEVREADWRITE("s2636_1", s2636_device, work_ram_r, work_ram_w) - AM_RANGE(0x1600, 0x16ff) AM_MIRROR(0x6000) AM_DEVREADWRITE("s2636_2", s2636_device, work_ram_r, work_ram_w) - AM_RANGE(0x1700, 0x17ff) AM_MIRROR(0x6000) AM_DEVREADWRITE("s2636_3", s2636_device, work_ram_r, work_ram_w) + AM_RANGE(0x1500, 0x15ff) AM_MIRROR(0x6000) AM_DEVREADWRITE("s2636_1", s2636_device, read, write) + AM_RANGE(0x1600, 0x16ff) AM_MIRROR(0x6000) AM_DEVREADWRITE("s2636_2", s2636_device, read, write) + AM_RANGE(0x1700, 0x17ff) AM_MIRROR(0x6000) AM_DEVREADWRITE("s2636_3", s2636_device, read, write) AM_RANGE(0x1800, 0x1bff) AM_MIRROR(0x6000) AM_WRITE(laserbat_videoram_w) AM_RANGE(0x1c00, 0x1fff) AM_MIRROR(0x6000) AM_RAM ADDRESS_MAP_END @@ -496,9 +496,9 @@ UINT32 laserbat_state::screen_update_laserbat(screen_device &screen, bitmap_ind1 m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0); /* update the S2636 chips */ - bitmap_ind16 &s2636_1_bitmap = m_s2636_1->update(cliprect); - bitmap_ind16 &s2636_2_bitmap = m_s2636_2->update(cliprect); - bitmap_ind16 &s2636_3_bitmap = m_s2636_3->update(cliprect); + bitmap_ind16 const &s2636_1_bitmap = m_s2636_1->update(cliprect); + bitmap_ind16 const &s2636_2_bitmap = m_s2636_2->update(cliprect); + bitmap_ind16 const &s2636_3_bitmap = m_s2636_3->update(cliprect); /* copy the S2636 images into the main bitmap */ for (y = cliprect.min_y; y <= cliprect.max_y; y++) @@ -670,15 +670,12 @@ static MACHINE_CONFIG_START( laserbat, laserbat_state ) MCFG_PALETTE_ADD("palette", 1024) MCFG_DEVICE_ADD("s2636_1", S2636, 0) - MCFG_S2636_WORKRAM_SIZE(0x100) MCFG_S2636_OFFSETS(0, -19) MCFG_DEVICE_ADD("s2636_2", S2636, 0) - MCFG_S2636_WORKRAM_SIZE(0x100) MCFG_S2636_OFFSETS(0, -19) MCFG_DEVICE_ADD("s2636_3", S2636, 0) - MCFG_S2636_WORKRAM_SIZE(0x100) MCFG_S2636_OFFSETS(0, -19) /* sound hardware */ @@ -738,15 +735,12 @@ static MACHINE_CONFIG_START( catnmous, laserbat_state ) MCFG_PALETTE_ADD("palette", 1024) MCFG_DEVICE_ADD("s2636_1", S2636, 0) - MCFG_S2636_WORKRAM_SIZE(0x100) MCFG_S2636_OFFSETS(0, -19) MCFG_DEVICE_ADD("s2636_2", S2636, 0) - MCFG_S2636_WORKRAM_SIZE(0x100) MCFG_S2636_OFFSETS(0, -19) MCFG_DEVICE_ADD("s2636_3", S2636, 0) - MCFG_S2636_WORKRAM_SIZE(0x100) MCFG_S2636_OFFSETS(0, -19) /* sound hardware */ diff --git a/src/mame/drivers/malzak.cpp b/src/mame/drivers/malzak.cpp index ae3997d1f4f..eb65b80951f 100644 --- a/src/mame/drivers/malzak.cpp +++ b/src/mame/drivers/malzak.cpp @@ -74,7 +74,7 @@ READ8_MEMBER(malzak_state::fake_VRLE_r) { - return (m_s2636_0->work_ram_r(space, 0xcb) & 0x3f) + (m_screen->vblank() * 0x40); + return (m_s2636_0->read(space, 0xcb) & 0x3f) + (m_screen->vblank() * 0x40); } READ8_MEMBER(malzak_state::s2636_portA_r) @@ -106,8 +106,8 @@ static ADDRESS_MAP_START( malzak_map, AS_PROGRAM, 8, malzak_state ) AM_RANGE(0x1200, 0x12ff) AM_MIRROR(0x6000) AM_RAM AM_RANGE(0x1300, 0x13ff) AM_MIRROR(0x6000) AM_RAM AM_RANGE(0x14cb, 0x14cb) AM_MIRROR(0x6000) AM_READ(fake_VRLE_r) - AM_RANGE(0x1400, 0x14ff) AM_MIRROR(0x6000) AM_DEVREADWRITE("s2636_0", s2636_device, work_ram_r, work_ram_w) - AM_RANGE(0x1500, 0x15ff) AM_MIRROR(0x6000) AM_DEVREADWRITE("s2636_1", s2636_device, work_ram_r, work_ram_w) + AM_RANGE(0x1400, 0x14ff) AM_MIRROR(0x6000) AM_DEVREADWRITE("s2636_0", s2636_device, read, write) + AM_RANGE(0x1500, 0x15ff) AM_MIRROR(0x6000) AM_DEVREADWRITE("s2636_1", s2636_device, read, write) AM_RANGE(0x1600, 0x16ff) AM_MIRROR(0x6000) AM_RAM_WRITE(malzak_playfield_w) AM_RANGE(0x1700, 0x17ff) AM_MIRROR(0x6000) AM_RAM AM_RANGE(0x1800, 0x1fff) AM_MIRROR(0x6000) AM_RAM AM_SHARE("videoram") @@ -127,8 +127,8 @@ static ADDRESS_MAP_START( malzak2_map, AS_PROGRAM, 8, malzak_state ) AM_RANGE(0x1300, 0x13ff) AM_MIRROR(0x6000) AM_RAM AM_RANGE(0x14cb, 0x14cb) AM_MIRROR(0x6000) AM_READ(fake_VRLE_r) AM_RANGE(0x14cc, 0x14cc) AM_MIRROR(0x6000) AM_READ(s2636_portA_r) - AM_RANGE(0x1400, 0x14ff) AM_MIRROR(0x6000) AM_DEVREADWRITE("s2636_0", s2636_device, work_ram_r, work_ram_w) - AM_RANGE(0x1500, 0x15ff) AM_MIRROR(0x6000) AM_DEVREADWRITE("s2636_1", s2636_device, work_ram_r, work_ram_w) + AM_RANGE(0x1400, 0x14ff) AM_MIRROR(0x6000) AM_DEVREADWRITE("s2636_0", s2636_device, read, write) + AM_RANGE(0x1500, 0x15ff) AM_MIRROR(0x6000) AM_DEVREADWRITE("s2636_1", s2636_device, read, write) AM_RANGE(0x1600, 0x16ff) AM_MIRROR(0x6000) AM_RAM_WRITE(malzak_playfield_w) AM_RANGE(0x1700, 0x17ff) AM_MIRROR(0x6000) AM_RAM AM_SHARE("nvram") AM_RANGE(0x1800, 0x1fff) AM_MIRROR(0x6000) AM_RAM AM_SHARE("videoram") @@ -317,12 +317,10 @@ static MACHINE_CONFIG_START( malzak, malzak_state ) MCFG_PALETTE_INIT_OWNER(malzak_state, malzak) MCFG_DEVICE_ADD("s2636_0", S2636, 0) - MCFG_S2636_WORKRAM_SIZE(0x100) MCFG_S2636_OFFSETS(0, -16) // -8, -16 MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25) MCFG_DEVICE_ADD("s2636_1", S2636, 0) - MCFG_S2636_WORKRAM_SIZE(0x100) MCFG_S2636_OFFSETS(0, -16) // -9, -16 MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25) diff --git a/src/mame/drivers/quasar.cpp b/src/mame/drivers/quasar.cpp index 75819f076a3..544c6c12ce3 100644 --- a/src/mame/drivers/quasar.cpp +++ b/src/mame/drivers/quasar.cpp @@ -327,15 +327,12 @@ static MACHINE_CONFIG_START( quasar, quasar_state ) MCFG_PALETTE_INIT_OWNER(quasar_state,quasar) MCFG_DEVICE_ADD("s2636_0", S2636, 0) - MCFG_S2636_WORKRAM_SIZE(0x100) MCFG_S2636_OFFSETS(CVS_S2636_Y_OFFSET, CVS_S2636_X_OFFSET) MCFG_DEVICE_ADD("s2636_1", S2636, 0) - MCFG_S2636_WORKRAM_SIZE(0x100) MCFG_S2636_OFFSETS(CVS_S2636_Y_OFFSET, CVS_S2636_X_OFFSET) MCFG_DEVICE_ADD("s2636_2", S2636, 0) - MCFG_S2636_WORKRAM_SIZE(0x100) MCFG_S2636_OFFSETS(CVS_S2636_Y_OFFSET, CVS_S2636_X_OFFSET) MCFG_VIDEO_START_OVERRIDE(quasar_state,quasar) diff --git a/src/mame/drivers/seabattl.cpp b/src/mame/drivers/seabattl.cpp index 1ad8b99ccc7..332a6966f91 100644 --- a/src/mame/drivers/seabattl.cpp +++ b/src/mame/drivers/seabattl.cpp @@ -190,7 +190,7 @@ UINT32 seabattl_state::screen_update_seabattl(screen_device &screen, bitmap_ind1 } } - bitmap_ind16 &s2636_0_bitmap = m_s2636->update(cliprect); + bitmap_ind16 const &s2636_0_bitmap = m_s2636->update(cliprect); // collisions for (y = cliprect.min_y; y <= cliprect.max_y; y++) @@ -261,7 +261,7 @@ static ADDRESS_MAP_START( seabattl_map, AS_PROGRAM, 8, seabattl_state ) AM_RANGE(0x1e06, 0x1e06) AM_MIRROR(0x20f0) AM_READ_PORT("DIPS1") AM_WRITE(sound_w) AM_RANGE(0x1e07, 0x1e07) AM_MIRROR(0x20f0) AM_READ_PORT("DIPS0") AM_WRITE(sound2_w) AM_RANGE(0x1fcc, 0x1fcc) AM_MIRROR(0x2000) AM_READ_PORT("IN1") - AM_RANGE(0x1f00, 0x1fff) AM_MIRROR(0x2000) AM_DEVREADWRITE("s2636", s2636_device, work_ram_r, work_ram_w) + AM_RANGE(0x1f00, 0x1fff) AM_MIRROR(0x2000) AM_DEVREADWRITE("s2636", s2636_device, read, write) ADDRESS_MAP_END static ADDRESS_MAP_START( seabattl_io_map, AS_IO, 8, seabattl_state ) @@ -483,7 +483,6 @@ static MACHINE_CONFIG_START( seabattl, seabattl_state ) MCFG_CPU_VBLANK_INT_DRIVER("screen", seabattl_state, seabattl_interrupt) MCFG_DEVICE_ADD("s2636", S2636, 0) - MCFG_S2636_WORKRAM_SIZE(0x100) MCFG_S2636_OFFSETS(3, -21) MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.10) diff --git a/src/mame/drivers/zac2650.cpp b/src/mame/drivers/zac2650.cpp index 33aaf20123c..0672bf1218a 100644 --- a/src/mame/drivers/zac2650.cpp +++ b/src/mame/drivers/zac2650.cpp @@ -261,7 +261,6 @@ static MACHINE_CONFIG_START( tinvader, zac2650_state ) MCFG_SPEAKER_STANDARD_MONO("mono") MCFG_DEVICE_ADD("s2636", S2636, 0) - MCFG_S2636_WORKRAM_SIZE(0x100) MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25) MACHINE_CONFIG_END diff --git a/src/mame/video/cvs.cpp b/src/mame/video/cvs.cpp index 543d7c1c54a..91a8dba64a8 100644 --- a/src/mame/video/cvs.cpp +++ b/src/mame/video/cvs.cpp @@ -190,9 +190,9 @@ UINT32 cvs_state::screen_update_cvs(screen_device &screen, bitmap_ind16 &bitmap, copyscrollbitmap(m_scrolled_collision_background, m_collision_background, 0, nullptr, 8, scroll, cliprect); /* update the S2636 chips */ - bitmap_ind16 *s2636_0_bitmap = &m_s2636_0->update(cliprect); - bitmap_ind16 *s2636_1_bitmap = &m_s2636_1->update(cliprect); - bitmap_ind16 *s2636_2_bitmap = &m_s2636_2->update(cliprect); + bitmap_ind16 const &s2636_0_bitmap = m_s2636_0->update(cliprect); + bitmap_ind16 const &s2636_1_bitmap = m_s2636_1->update(cliprect); + bitmap_ind16 const &s2636_2_bitmap = m_s2636_2->update(cliprect); /* Bullet Hardware */ for (offs = 8; offs < 256; offs++ ) @@ -205,9 +205,9 @@ UINT32 cvs_state::screen_update_cvs(screen_device &screen, bitmap_ind16 &bitmap, int bx = 255 - 7 - m_bullet_ram[offs] - ct; /* Bullet/Object Collision */ - if ((s2636_0_bitmap->pix16(offs, bx) != 0) || - (s2636_1_bitmap->pix16(offs, bx) != 0) || - (s2636_2_bitmap->pix16(offs, bx) != 0)) + if ((s2636_0_bitmap.pix16(offs, bx) != 0) || + (s2636_1_bitmap.pix16(offs, bx) != 0) || + (s2636_2_bitmap.pix16(offs, bx) != 0)) m_collision_register |= 0x08; /* Bullet/Background Collision */ @@ -230,9 +230,9 @@ UINT32 cvs_state::screen_update_cvs(screen_device &screen, bitmap_ind16 &bitmap, for (x = cliprect.min_x; x <= cliprect.max_x; x++) { - int pixel0 = s2636_0_bitmap->pix16(y, x); - int pixel1 = s2636_1_bitmap->pix16(y, x); - int pixel2 = s2636_2_bitmap->pix16(y, x); + int pixel0 = s2636_0_bitmap.pix16(y, x); + int pixel1 = s2636_1_bitmap.pix16(y, x); + int pixel2 = s2636_2_bitmap.pix16(y, x); int pixel = pixel0 | pixel1 | pixel2; diff --git a/src/mame/video/galaxia.cpp b/src/mame/video/galaxia.cpp index 1095f9ba1d3..4aba361e0fb 100644 --- a/src/mame/video/galaxia.cpp +++ b/src/mame/video/galaxia.cpp @@ -112,9 +112,9 @@ UINT32 galaxia_state::screen_update_galaxia(screen_device &screen, bitmap_ind16 { int x, y; - bitmap_ind16 *s2636_0_bitmap = &m_s2636_0->update(cliprect); - bitmap_ind16 *s2636_1_bitmap = &m_s2636_1->update(cliprect); - bitmap_ind16 *s2636_2_bitmap = &m_s2636_2->update(cliprect); + bitmap_ind16 const &s2636_0_bitmap = m_s2636_0->update(cliprect); + bitmap_ind16 const &s2636_1_bitmap = m_s2636_1->update(cliprect); + bitmap_ind16 const &s2636_2_bitmap = m_s2636_2->update(cliprect); bitmap.fill(0, cliprect); cvs_update_stars(bitmap, cliprect, STAR_PEN, 1); @@ -139,9 +139,9 @@ UINT32 galaxia_state::screen_update_galaxia(screen_device &screen, bitmap_ind16 } // copy the S2636 images into the main bitmap and check collision - int pixel0 = s2636_0_bitmap->pix16(y, x); - int pixel1 = s2636_1_bitmap->pix16(y, x); - int pixel2 = s2636_2_bitmap->pix16(y, x); + int pixel0 = s2636_0_bitmap.pix16(y, x); + int pixel1 = s2636_1_bitmap.pix16(y, x); + int pixel2 = s2636_2_bitmap.pix16(y, x); int pixel = pixel0 | pixel1 | pixel2; @@ -178,7 +178,7 @@ UINT32 galaxia_state::screen_update_astrowar(screen_device &screen, bitmap_ind16 // astrowar has only one S2636 int x, y; - bitmap_ind16 &s2636_0_bitmap = m_s2636_0->update(cliprect); + bitmap_ind16 const &s2636_0_bitmap = m_s2636_0->update(cliprect); bitmap.fill(0, cliprect); cvs_update_stars(bitmap, cliprect, STAR_PEN, 1); diff --git a/src/mame/video/malzak.cpp b/src/mame/video/malzak.cpp index 653e0c83628..a23623ec981 100644 --- a/src/mame/video/malzak.cpp +++ b/src/mame/video/malzak.cpp @@ -44,8 +44,8 @@ UINT32 malzak_state::screen_update_malzak(screen_device &screen, bitmap_rgb32 &b } /* update the S2636 chips */ - bitmap_ind16 &s2636_0_bitmap = m_s2636_0->update(cliprect); - bitmap_ind16 &s2636_1_bitmap = m_s2636_1->update(cliprect); + bitmap_ind16 const &s2636_0_bitmap = m_s2636_0->update(cliprect); + bitmap_ind16 const &s2636_1_bitmap = m_s2636_1->update(cliprect); /* copy the S2636 images into the main bitmap */ { diff --git a/src/mame/video/quasar.cpp b/src/mame/video/quasar.cpp index f3d5e89577c..cc89578a4b3 100644 --- a/src/mame/video/quasar.cpp +++ b/src/mame/video/quasar.cpp @@ -142,9 +142,9 @@ UINT32 quasar_state::screen_update_quasar(screen_device &screen, bitmap_ind16 &b } /* update the S2636 chips */ - bitmap_ind16 &s2636_0_bitmap = m_s2636_0->update(cliprect); - bitmap_ind16 &s2636_1_bitmap = m_s2636_1->update(cliprect); - bitmap_ind16 &s2636_2_bitmap = m_s2636_2->update(cliprect); + bitmap_ind16 const &s2636_0_bitmap = m_s2636_0->update(cliprect); + bitmap_ind16 const &s2636_1_bitmap = m_s2636_1->update(cliprect); + bitmap_ind16 const &s2636_2_bitmap = m_s2636_2->update(cliprect); /* Bullet Hardware */ for (offs = 8; offs < 256; offs++ ) diff --git a/src/mame/video/zac2650.cpp b/src/mame/video/zac2650.cpp index 2c87569b253..cfb6701d90b 100644 --- a/src/mame/video/zac2650.cpp +++ b/src/mame/video/zac2650.cpp @@ -35,7 +35,7 @@ WRITE8_MEMBER(zac2650_state::zac_s2636_w) m_gfxdecode->gfx(2)->mark_dirty(offset/8); if (offset == 0xc7) { - m_s2636->soundport_w(0, data); + m_s2636->write(space, offset, data); } }