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
This commit is contained in:
Vas Crabb 2015-12-10 16:23:34 +11:00
parent 18966159a0
commit ac245e3ff7
14 changed files with 530 additions and 376 deletions

View File

@ -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::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--;
}
}

View File

@ -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<s2636_device &>(device).m_work_ram_size = size; }
static void set_offsets(device_t &device, int y_offset, int x_offset)
{
s2636_device &dev = downcast<s2636_device &>(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<s2636_device &>(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__ */

View File

@ -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 */

View File

@ -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)

View File

@ -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 */

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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 */
{

View File

@ -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++ )

View File

@ -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);
}
}