mirror of
https://github.com/holub/mame
synced 2025-04-21 07:52:35 +03:00
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:
parent
18966159a0
commit
ac245e3ff7
@ -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--;
|
||||
}
|
||||
}
|
||||
|
@ -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__ */
|
||||
|
@ -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 */
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
{
|
||||
|
@ -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++ )
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user