mirror of
https://github.com/holub/mame
synced 2025-06-11 07:14:07 +03:00
sega/deniam.cpp, sega/kopunch.cpp, sega/stactics.cpp, sega/suprloco.cpp: consolidated drivers in single files, minor cleanups
This commit is contained in:
parent
94afa5a44a
commit
278ebb10d5
@ -1,5 +1,6 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Nicola Salmoria
|
||||
// copyright-holders: Nicola Salmoria
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
Deniam games
|
||||
@ -44,84 +45,566 @@ Notes:
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "deniam.h"
|
||||
|
||||
#include "cpu/m68000/m68000.h"
|
||||
#include "cpu/z80/z80.h"
|
||||
#include "machine/gen_latch.h"
|
||||
#include "sound/okim6295.h"
|
||||
#include "sound/ymopl.h"
|
||||
|
||||
#include "emupal.h"
|
||||
#include "screen.h"
|
||||
#include "speaker.h"
|
||||
#include "tilemap.h"
|
||||
|
||||
|
||||
void deniam_state::deniam16b_oki_rom_bank_w(u8 data)
|
||||
namespace {
|
||||
|
||||
class deniamc_state : public driver_device
|
||||
{
|
||||
public:
|
||||
deniamc_state(const machine_config &mconfig, device_type type, const char *tag) :
|
||||
driver_device(mconfig, type, tag),
|
||||
m_maincpu(*this, "maincpu"),
|
||||
m_oki(*this, "oki"),
|
||||
m_gfxdecode(*this, "gfxdecode"),
|
||||
m_palette(*this, "palette"),
|
||||
m_videoram(*this, "videoram"),
|
||||
m_textram(*this, "textram"),
|
||||
m_spriteram(*this, "spriteram"),
|
||||
m_spritegfx(*this, "spritegfx")
|
||||
{ }
|
||||
|
||||
void deniam16c(machine_config &config);
|
||||
|
||||
void init_logicpro();
|
||||
|
||||
protected:
|
||||
virtual void machine_start() override;
|
||||
virtual void machine_reset() override;
|
||||
virtual void video_start() override;
|
||||
|
||||
// devices
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<okim6295_device> m_oki;
|
||||
|
||||
// configuration
|
||||
u16 m_bg_scrollx_offs = 0;
|
||||
u8 m_bg_scrolly_offs = 0;
|
||||
u16 m_fg_scrollx_offs = 0;
|
||||
u8 m_fg_scrolly_offs = 0;
|
||||
u8 m_bg_scrollx_reg = 0;
|
||||
u8 m_bg_scrolly_reg = 0;
|
||||
u8 m_bg_page_reg = 0;
|
||||
u8 m_fg_scrollx_reg = 0;
|
||||
u8 m_fg_scrolly_reg = 0;
|
||||
u8 m_fg_page_reg = 0;
|
||||
|
||||
void common_init();
|
||||
void base_main_map(address_map &map);
|
||||
|
||||
private:
|
||||
// devices
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
required_device<palette_device> m_palette;
|
||||
|
||||
// memory pointers
|
||||
required_shared_ptr<u16> m_videoram;
|
||||
required_shared_ptr<u16> m_textram;
|
||||
required_shared_ptr<u16> m_spriteram;
|
||||
|
||||
required_memory_region m_spritegfx;
|
||||
|
||||
// video-related
|
||||
tilemap_t *m_fg_tilemap = nullptr;
|
||||
tilemap_t *m_bg_tilemap = nullptr;
|
||||
tilemap_t *m_tx_tilemap = nullptr;
|
||||
u8 m_display_enable = 0;
|
||||
int m_bg_page[4]{};
|
||||
int m_fg_page[4]{};
|
||||
u16 m_coinctrl = 0;
|
||||
|
||||
void irq_ack_w(u16 data);
|
||||
void videoram_w(offs_t offset, u16 data, u16 mem_mask = ~0);
|
||||
void textram_w(offs_t offset, u16 data, u16 mem_mask = ~0);
|
||||
u16 coinctrl_r();
|
||||
void coinctrl_w(offs_t offset, u16 data, u16 mem_mask = ~0);
|
||||
void oki_rom_bank_w(u8 data);
|
||||
TILEMAP_MAPPER_MEMBER(scan_pages);
|
||||
TILE_GET_INFO_MEMBER(get_bg_tile_info);
|
||||
TILE_GET_INFO_MEMBER(get_fg_tile_info);
|
||||
TILE_GET_INFO_MEMBER(get_tx_tile_info);
|
||||
u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
void draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
void set_bg_page(int page, int value);
|
||||
void set_fg_page(int page, int value);
|
||||
void main_map(address_map &map);
|
||||
};
|
||||
|
||||
class deniamb_state : public deniamc_state
|
||||
{
|
||||
public:
|
||||
deniamb_state(const machine_config &mconfig, device_type type, const char *tag) :
|
||||
deniamc_state(mconfig, type, tag),
|
||||
m_audiocpu(*this, "audiocpu"),
|
||||
m_soundlatch(*this, "soundlatch")
|
||||
{ }
|
||||
|
||||
void deniam16b(machine_config &config);
|
||||
|
||||
void init_karianx();
|
||||
|
||||
private:
|
||||
// devices
|
||||
required_device<cpu_device> m_audiocpu;
|
||||
required_device<generic_latch_8_device> m_soundlatch;
|
||||
|
||||
void oki_rom_bank_w(u8 data);
|
||||
|
||||
void main_map(address_map &map);
|
||||
void sound_io_map(address_map &map);
|
||||
void sound_map(address_map &map);
|
||||
};
|
||||
|
||||
|
||||
// video
|
||||
|
||||
void deniamc_state::common_init()
|
||||
{
|
||||
m_bg_scrollx_reg = 0x00a4/2;
|
||||
m_bg_scrolly_reg = 0x00a8/2;
|
||||
m_bg_page_reg = 0x00ac/2;
|
||||
m_fg_scrollx_reg = 0x00a2/2;
|
||||
m_fg_scrolly_reg = 0x00a6/2;
|
||||
m_fg_page_reg = 0x00aa/2;
|
||||
|
||||
m_display_enable = 0;
|
||||
m_coinctrl = 0;
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
m_bg_page[i] = 0;
|
||||
m_fg_page[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void deniamc_state::init_logicpro()
|
||||
{
|
||||
common_init();
|
||||
|
||||
m_bg_scrollx_offs = 0x00d;
|
||||
m_bg_scrolly_offs = 0x000;
|
||||
m_fg_scrollx_offs = 0x009;
|
||||
m_fg_scrolly_offs = 0x000;
|
||||
}
|
||||
|
||||
void deniamb_state::init_karianx()
|
||||
{
|
||||
common_init();
|
||||
|
||||
m_bg_scrollx_offs = 0x10d;
|
||||
m_bg_scrolly_offs = 0x080;
|
||||
m_fg_scrollx_offs = 0x109;
|
||||
m_fg_scrolly_offs = 0x080;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
Callbacks for the TileMap code
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
TILEMAP_MAPPER_MEMBER(deniamc_state::scan_pages)
|
||||
{
|
||||
// logical (col,row) -> memory offset
|
||||
return (col & 0x3f) + ((row & 0x1f) << 6) + ((col & 0x40) << 5) + ((row & 0x20) << 7);
|
||||
}
|
||||
|
||||
TILE_GET_INFO_MEMBER(deniamc_state::get_bg_tile_info)
|
||||
{
|
||||
const int page = tile_index >> 11;
|
||||
const u16 attr = m_videoram[m_bg_page[page] * 0x0800 + (tile_index & 0x7ff)];
|
||||
tileinfo.set(0,
|
||||
attr,
|
||||
(attr & 0x1fc0) >> 6,
|
||||
0);
|
||||
}
|
||||
|
||||
TILE_GET_INFO_MEMBER(deniamc_state::get_fg_tile_info)
|
||||
{
|
||||
const int page = tile_index >> 11;
|
||||
const u16 attr = m_videoram[m_fg_page[page] * 0x0800 + (tile_index & 0x7ff)];
|
||||
tileinfo.set(0,
|
||||
attr,
|
||||
(attr & 0x1fc0) >> 6,
|
||||
0);
|
||||
}
|
||||
|
||||
TILE_GET_INFO_MEMBER(deniamc_state::get_tx_tile_info)
|
||||
{
|
||||
const u16 attr = m_textram[tile_index];
|
||||
tileinfo.set(0,
|
||||
attr & 0xf1ff,
|
||||
(attr & 0x0e00) >> 9,
|
||||
0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
Start the video hardware emulation.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
void deniamc_state::video_start()
|
||||
{
|
||||
m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(deniamc_state::get_bg_tile_info)), tilemap_mapper_delegate(*this, FUNC(deniamc_state::scan_pages)), 8, 8, 128, 64);
|
||||
m_fg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(deniamc_state::get_fg_tile_info)), tilemap_mapper_delegate(*this, FUNC(deniamc_state::scan_pages)), 8, 8, 128, 64);
|
||||
m_tx_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(deniamc_state::get_tx_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 64, 32);
|
||||
|
||||
m_fg_tilemap->set_transparent_pen(0);
|
||||
m_tx_tilemap->set_transparent_pen(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
Memory handlers
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
void deniamc_state::videoram_w(offs_t offset, u16 data, u16 mem_mask)
|
||||
{
|
||||
COMBINE_DATA(&m_videoram[offset]);
|
||||
|
||||
const int page = offset >> 11;
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (m_bg_page[i] == page)
|
||||
m_bg_tilemap->mark_tile_dirty(i * 0x800 + (offset & 0x7ff));
|
||||
if (m_fg_page[i] == page)
|
||||
m_fg_tilemap->mark_tile_dirty(i * 0x800 + (offset & 0x7ff));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void deniamc_state::textram_w(offs_t offset, u16 data, u16 mem_mask)
|
||||
{
|
||||
COMBINE_DATA(&m_textram[offset]);
|
||||
m_tx_tilemap->mark_tile_dirty(offset);
|
||||
}
|
||||
|
||||
|
||||
u16 deniamc_state::coinctrl_r()
|
||||
{
|
||||
return m_coinctrl;
|
||||
}
|
||||
|
||||
void deniamc_state::coinctrl_w(offs_t offset, u16 data, u16 mem_mask)
|
||||
{
|
||||
COMBINE_DATA(&m_coinctrl);
|
||||
|
||||
// bit 0 is coin counter
|
||||
machine().bookkeeping().coin_counter_w(0, m_coinctrl & 0x01);
|
||||
|
||||
// bit 6 is display enable (0 freezes screen)
|
||||
m_display_enable = m_coinctrl & 0x20;
|
||||
|
||||
// other bits unknown (unused?)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
Display refresh
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
/*
|
||||
* Sprite Format
|
||||
* ------------------
|
||||
*
|
||||
* Word | Bit(s) | Use
|
||||
* -----+-fedcba9876543210-+----------------
|
||||
* 0 | --------xxxxxxxx | display y start
|
||||
* 0 | xxxxxxxx-------- | display y end
|
||||
* 2 | -------xxxxxxxxx | x position
|
||||
* 2 | ------x--------- | unknown (used in logicpr2, maybe just a bug?)
|
||||
* 2 | xxxxxx---------- | unused?
|
||||
* 4 | ---------xxxxxxx | width
|
||||
* 4 | --------x------- | is this flip y like in System 16?
|
||||
* 4 | -------x-------- | flip x
|
||||
* 4 | xxxxxxx--------- | unused?
|
||||
* 6 | xxxxxxxxxxxxxxxx | ROM address low bits
|
||||
* 8 | ----------xxxxxx | color
|
||||
* 8 | --------xx------ | priority
|
||||
* 8 | ---xxxxx-------- | ROM address high bits
|
||||
* 8 | xxx------------- | unused? (extra address bits for larger ROMs?)
|
||||
* a | ---------------- | zoomx like in System 16?
|
||||
* c | ---------------- | zoomy like in System 16?
|
||||
* e | ---------------- |
|
||||
*/
|
||||
void deniamc_state::draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
for (int offs = m_spriteram.bytes() / 2 - 8; offs >= 0; offs -= 8)
|
||||
{
|
||||
u8 *rom = m_spritegfx->base();
|
||||
|
||||
int sx = (m_spriteram[offs + 1] & 0x01ff) + 16 * 8 - 1;
|
||||
if (sx >= 512) sx -= 512;
|
||||
const int starty = m_spriteram[offs + 0] & 0xff;
|
||||
const int endy = m_spriteram[offs + 0] >> 8;
|
||||
|
||||
const int width = m_spriteram[offs + 2] & 0x007f;
|
||||
bool flipx = m_spriteram[offs + 2] & 0x0100;
|
||||
if (flipx) sx++;
|
||||
|
||||
const u32 color = 0x40 + (m_spriteram[offs + 4] & 0x3f);
|
||||
|
||||
int primask = 8;
|
||||
switch (m_spriteram[offs + 4] & 0xc0)
|
||||
{
|
||||
case 0x00: primask |= 4 | 2 | 1; break; // below everything
|
||||
case 0x40: primask |= 4 | 2; break; // below fg and tx
|
||||
case 0x80: primask |= 4; break; // below tx
|
||||
case 0xc0: break; // above everything
|
||||
}
|
||||
|
||||
const int start = m_spriteram[offs + 3] + ((m_spriteram[offs + 4] & 0x1f00) << 8);
|
||||
rom += 2 * start;
|
||||
|
||||
for (int y = starty + 1; y <= endy; y++)
|
||||
{
|
||||
bool drawing = false;
|
||||
int i = 0;
|
||||
|
||||
rom += 2 * width; // note that the first line is skipped
|
||||
int x = 0;
|
||||
while (i < 512) // safety check
|
||||
{
|
||||
if (flipx)
|
||||
{
|
||||
if ((rom[i] & 0x0f) == 0x0f)
|
||||
{
|
||||
if (!drawing) drawing = true;
|
||||
else break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rom[i] & 0x0f)
|
||||
{
|
||||
if (cliprect.contains(sx + x, y))
|
||||
{
|
||||
if ((screen.priority().pix(y, sx + x) & primask) == 0)
|
||||
bitmap.pix(y, sx + x) = color * 16 + (rom[i] & 0x0f);
|
||||
screen.priority().pix(y, sx + x) = 8;
|
||||
}
|
||||
}
|
||||
x++;
|
||||
}
|
||||
|
||||
if ((rom[i] & 0xf0) == 0xf0)
|
||||
{
|
||||
if (!drawing) drawing = true;
|
||||
else break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rom[i] & 0xf0)
|
||||
{
|
||||
if (cliprect.contains(sx + x, y))
|
||||
{
|
||||
if ((screen.priority().pix(y, sx + x) & primask) == 0)
|
||||
bitmap.pix(y, sx + x) = color * 16 + (rom[i] >> 4);
|
||||
screen.priority().pix(y, sx + x) = 8;
|
||||
}
|
||||
}
|
||||
x++;
|
||||
}
|
||||
|
||||
i--;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((rom[i] & 0xf0) == 0xf0)
|
||||
{
|
||||
if (!drawing) drawing = true;
|
||||
else break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rom[i] & 0xf0)
|
||||
{
|
||||
if (cliprect.contains(sx + x, y))
|
||||
{
|
||||
if ((screen.priority().pix(y, sx + x) & primask) == 0)
|
||||
bitmap.pix(y, sx + x) = color * 16 + (rom[i] >> 4);
|
||||
screen.priority().pix(y, sx + x) = 8;
|
||||
}
|
||||
}
|
||||
x++;
|
||||
}
|
||||
|
||||
if ((rom[i] & 0x0f) == 0x0f)
|
||||
{
|
||||
if (!drawing) drawing = true;
|
||||
else break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rom[i] & 0x0f)
|
||||
{
|
||||
if (cliprect.contains(sx + x, y))
|
||||
{
|
||||
if ((screen.priority().pix(y, sx + x) & primask) == 0)
|
||||
bitmap.pix(y, sx + x) = color * 16 + (rom[i] & 0x0f);
|
||||
screen.priority().pix(y, sx + x) = 8;
|
||||
}
|
||||
}
|
||||
x++;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void deniamc_state::set_bg_page(int page, int value)
|
||||
{
|
||||
if (m_bg_page[page] != value)
|
||||
{
|
||||
m_bg_page[page] = value;
|
||||
for (int tile_index = page * 0x800; tile_index < (page + 1) * 0x800; tile_index++)
|
||||
m_bg_tilemap->mark_tile_dirty(tile_index);
|
||||
}
|
||||
}
|
||||
|
||||
void deniamc_state::set_fg_page(int page, int value)
|
||||
{
|
||||
if (m_fg_page[page] != value)
|
||||
{
|
||||
m_fg_page[page] = value;
|
||||
for (int tile_index = page * 0x800; tile_index < (page + 1) * 0x800; tile_index++)
|
||||
m_fg_tilemap->mark_tile_dirty(tile_index);
|
||||
}
|
||||
}
|
||||
|
||||
u32 deniamc_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
int page;
|
||||
|
||||
if (!m_display_enable)
|
||||
{
|
||||
bitmap.fill(m_palette->black_pen(), cliprect);
|
||||
return 0; /* don't update (freeze display) */
|
||||
}
|
||||
|
||||
const int bg_scrollx = m_textram[m_bg_scrollx_reg] - m_bg_scrollx_offs;
|
||||
const int bg_scrolly = (m_textram[m_bg_scrolly_reg] & 0xff) - m_bg_scrolly_offs;
|
||||
page = m_textram[m_bg_page_reg];
|
||||
set_bg_page(3, (page >>12) & 0x0f);
|
||||
set_bg_page(2, (page >> 8) & 0x0f);
|
||||
set_bg_page(1, (page >> 4) & 0x0f);
|
||||
set_bg_page(0, (page >> 0) & 0x0f);
|
||||
|
||||
const int fg_scrollx = m_textram[m_fg_scrollx_reg] - m_fg_scrollx_offs;
|
||||
const int fg_scrolly = (m_textram[m_fg_scrolly_reg] & 0xff) - m_fg_scrolly_offs;
|
||||
page = m_textram[m_fg_page_reg];
|
||||
set_fg_page(3, (page >>12) & 0x0f);
|
||||
set_fg_page(2, (page >> 8) & 0x0f);
|
||||
set_fg_page(1, (page >> 4) & 0x0f);
|
||||
set_fg_page(0, (page >> 0) & 0x0f);
|
||||
|
||||
m_bg_tilemap->set_scrollx(0, bg_scrollx & 0x1ff);
|
||||
m_bg_tilemap->set_scrolly(0, bg_scrolly & 0x0ff);
|
||||
m_fg_tilemap->set_scrollx(0, fg_scrollx & 0x1ff);
|
||||
m_fg_tilemap->set_scrolly(0, fg_scrolly & 0x0ff);
|
||||
|
||||
screen.priority().fill(0, cliprect);
|
||||
|
||||
m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 1);
|
||||
m_fg_tilemap->draw(screen, bitmap, cliprect, 0, 2);
|
||||
m_tx_tilemap->draw(screen, bitmap, cliprect, 0, 4);
|
||||
|
||||
draw_sprites(screen, bitmap, cliprect);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// machine
|
||||
|
||||
void deniamb_state::oki_rom_bank_w(u8 data)
|
||||
{
|
||||
m_oki->set_rom_bank((data >> 6) & 1);
|
||||
}
|
||||
|
||||
void deniam_state::deniam16c_oki_rom_bank_w(u8 data)
|
||||
void deniamc_state::oki_rom_bank_w(u8 data)
|
||||
{
|
||||
if ((data&0xFE) != 0) popmessage("OKI bank was not 0 or 1! contact MAMEDEV!");
|
||||
if ((data & 0xfe) != 0) popmessage("OKI bank was not 0 or 1! contact MAMEDEV!");
|
||||
m_oki->set_rom_bank(data & 0x01);
|
||||
}
|
||||
|
||||
void deniam_state::irq_ack_w(u16 data)
|
||||
void deniamc_state::irq_ack_w(u16 data)
|
||||
{
|
||||
m_maincpu->set_input_line(4, CLEAR_LINE);
|
||||
}
|
||||
|
||||
void deniam_state::deniam16b_map(address_map &map)
|
||||
void deniamc_state::base_main_map(address_map &map)
|
||||
{
|
||||
map(0x000000, 0x0fffff).rom();
|
||||
map(0x400000, 0x40ffff).ram().w(FUNC(deniam_state::videoram_w)).share("videoram");
|
||||
map(0x410000, 0x410fff).ram().w(FUNC(deniam_state::textram_w)).share("textram");
|
||||
map(0x440000, 0x4407ff).writeonly().share("spriteram");
|
||||
map(0x400000, 0x40ffff).ram().w(FUNC(deniamb_state::videoram_w)).share(m_videoram);
|
||||
map(0x410000, 0x410fff).ram().w(FUNC(deniamb_state::textram_w)).share(m_textram);
|
||||
map(0x440000, 0x4407ff).writeonly().share(m_spriteram);
|
||||
map(0x840000, 0x840fff).w(m_palette, FUNC(palette_device::write16)).share("palette");
|
||||
map(0xc40000, 0xc40000).w(m_soundlatch, FUNC(generic_latch_8_device::write));
|
||||
map(0xc40002, 0xc40003).rw(FUNC(deniam_state::coinctrl_r), FUNC(deniam_state::coinctrl_w));
|
||||
map(0xc40004, 0xc40005).w(FUNC(deniam_state::irq_ack_w));
|
||||
map(0xc40002, 0xc40003).rw(FUNC(deniamb_state::coinctrl_r), FUNC(deniamb_state::coinctrl_w));
|
||||
map(0xc40004, 0xc40005).w(FUNC(deniamb_state::irq_ack_w));
|
||||
map(0xc44000, 0xc44001).portr("SYSTEM");
|
||||
map(0xc44002, 0xc44003).portr("P1");
|
||||
map(0xc44004, 0xc44005).portr("P2").nopw();
|
||||
map(0xc44006, 0xc44007).nopr(); /* unused? */
|
||||
map(0xc4400a, 0xc4400b).portr("DSW");
|
||||
map(0xff0000, 0xffffff).ram();
|
||||
}
|
||||
|
||||
void deniam_state::sound_map(address_map &map)
|
||||
void deniamb_state::main_map(address_map &map)
|
||||
{
|
||||
base_main_map(map);
|
||||
|
||||
map(0xc40000, 0xc40000).w(m_soundlatch, FUNC(generic_latch_8_device::write));
|
||||
map(0xc44006, 0xc44007).nopr(); // unused?
|
||||
map(0xc4400a, 0xc4400b).portr("DSW");
|
||||
}
|
||||
|
||||
void deniamb_state::sound_map(address_map &map)
|
||||
{
|
||||
map(0x0000, 0xf7ff).rom();
|
||||
map(0xf800, 0xffff).ram();
|
||||
}
|
||||
|
||||
void deniam_state::sound_io_map(address_map &map)
|
||||
void deniamb_state::sound_io_map(address_map &map)
|
||||
{
|
||||
map.global_mask(0xff);
|
||||
map(0x01, 0x01).r(m_soundlatch, FUNC(generic_latch_8_device::read));
|
||||
map(0x02, 0x03).w("ymsnd", FUNC(ym3812_device::write));
|
||||
map(0x05, 0x05).rw(m_oki, FUNC(okim6295_device::read), FUNC(okim6295_device::write));
|
||||
map(0x07, 0x07).w(FUNC(deniam_state::deniam16b_oki_rom_bank_w));
|
||||
map(0x07, 0x07).w(FUNC(deniamb_state::oki_rom_bank_w));
|
||||
}
|
||||
|
||||
/* identical to 16b, but handles sound directly */
|
||||
void deniam_state::deniam16c_map(address_map &map)
|
||||
// identical to 16b, but handles sound directly
|
||||
void deniamc_state::main_map(address_map &map)
|
||||
{
|
||||
map(0x000000, 0x0fffff).rom();
|
||||
map(0x400000, 0x40ffff).ram().w(FUNC(deniam_state::videoram_w)).share("videoram");
|
||||
map(0x410000, 0x410fff).ram().w(FUNC(deniam_state::textram_w)).share("textram");
|
||||
map(0x440000, 0x4407ff).writeonly().share("spriteram");
|
||||
map(0x840000, 0x840fff).w(m_palette, FUNC(palette_device::write16)).share("palette");
|
||||
base_main_map(map);
|
||||
|
||||
map(0xc40001, 0xc40001).rw(m_oki, FUNC(okim6295_device::read), FUNC(okim6295_device::write));
|
||||
map(0xc40002, 0xc40003).rw(FUNC(deniam_state::coinctrl_r), FUNC(deniam_state::coinctrl_w));
|
||||
map(0xc40004, 0xc40005).w(FUNC(deniam_state::irq_ack_w));
|
||||
map(0xc40007, 0xc40007).w(FUNC(deniam_state::deniam16c_oki_rom_bank_w));
|
||||
map(0xc44000, 0xc44001).portr("SYSTEM");
|
||||
map(0xc44002, 0xc44003).portr("P1");
|
||||
map(0xc44004, 0xc44005).portr("P2");
|
||||
map(0xc44006, 0xc44007).nopr(); /* read unused? extra input port/dipswitches? */
|
||||
map(0xc40007, 0xc40007).w(FUNC(deniamc_state::oki_rom_bank_w));
|
||||
map(0xc44006, 0xc44007).nopr(); // read unused? extra input port/dipswitches?
|
||||
map(0xc40008, 0xc4000b).w("ymsnd", FUNC(ym3812_device::write)).umask16(0xff00);
|
||||
map(0xc4400a, 0xc4400b).portr("DSW"); /* probably YM3812 input port */
|
||||
map(0xff0000, 0xffffff).ram();
|
||||
map(0xc4400a, 0xc4400b).portr("DSW"); // probably YM3812 input port
|
||||
}
|
||||
|
||||
|
||||
@ -201,32 +684,22 @@ INPUT_PORTS_END
|
||||
|
||||
|
||||
static GFXDECODE_START( gfx_deniam )
|
||||
GFXDECODE_ENTRY( "gfx1", 0, gfx_8x8x3_planar, 0, 128 ) /* colors 0-1023 */
|
||||
/* sprites use colors 1024-2047 */
|
||||
GFXDECODE_ENTRY( "chars", 0, gfx_8x8x3_planar, 0, 128 ) // colors 0-1023
|
||||
// sprites use colors 1024-2047
|
||||
GFXDECODE_END
|
||||
|
||||
|
||||
void deniam_state::machine_start()
|
||||
void deniamc_state::machine_start()
|
||||
{
|
||||
save_item(NAME(m_display_enable));
|
||||
save_item(NAME(m_coinctrl));
|
||||
|
||||
save_item(NAME(m_bg_scrollx_offs));
|
||||
save_item(NAME(m_bg_scrolly_offs));
|
||||
save_item(NAME(m_fg_scrollx_offs));
|
||||
save_item(NAME(m_fg_scrolly_offs));
|
||||
save_item(NAME(m_bg_scrollx_reg));
|
||||
save_item(NAME(m_bg_scrolly_reg));
|
||||
save_item(NAME(m_fg_scrollx_reg));
|
||||
save_item(NAME(m_fg_scrolly_reg));
|
||||
save_item(NAME(m_bg_page_reg));
|
||||
save_item(NAME(m_fg_page_reg));
|
||||
save_item(NAME(m_bg_page));
|
||||
save_item(NAME(m_fg_page));
|
||||
}
|
||||
|
||||
|
||||
void deniam_state::machine_reset()
|
||||
void deniamc_state::machine_reset()
|
||||
{
|
||||
/* logicpr2 does not reset the bank base on startup, though it probably
|
||||
doesn't matter since the coinup sfx (sample borrowed from 'tyrian' on PC)
|
||||
@ -235,72 +708,52 @@ void deniam_state::machine_reset()
|
||||
m_oki->set_rom_bank(0);
|
||||
}
|
||||
|
||||
void deniam_state::deniam16b(machine_config &config)
|
||||
void deniamc_state::deniam16c(machine_config &config)
|
||||
{
|
||||
/* basic machine hardware */
|
||||
M68000(config, m_maincpu, XTAL(25'000'000)/2); /* 12.5Mhz verified */
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &deniam_state::deniam16b_map);
|
||||
m_maincpu->set_vblank_int("screen", FUNC(deniam_state::irq4_line_assert));
|
||||
// basic machine hardware
|
||||
M68000(config, m_maincpu, XTAL(25'000'000) / 2); // 12.5Mhz verified
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &deniamc_state::main_map);
|
||||
m_maincpu->set_vblank_int("screen", FUNC(deniamb_state::irq4_line_assert));
|
||||
|
||||
Z80(config, m_audiocpu, XTAL(25'000'000)/4); /* 6.25Mhz verified */
|
||||
m_audiocpu->set_addrmap(AS_PROGRAM, &deniam_state::sound_map);
|
||||
m_audiocpu->set_addrmap(AS_IO, &deniam_state::sound_io_map);
|
||||
|
||||
/* video hardware */
|
||||
// video hardware
|
||||
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
|
||||
screen.set_refresh_hz(60);
|
||||
screen.set_vblank_time(ATTOSECONDS_IN_USEC(0));
|
||||
screen.set_size(512, 256);
|
||||
//screen.set_visarea(24*8, 64*8-1, 0*8, 28*8-1); // looks better but doesn't match hardware
|
||||
screen.set_visarea(24*8-4, 64*8-5, 0*8, 28*8-1);
|
||||
screen.set_screen_update(FUNC(deniam_state::screen_update));
|
||||
screen.set_screen_update(FUNC(deniamb_state::screen_update));
|
||||
screen.set_palette(m_palette);
|
||||
|
||||
GFXDECODE(config, m_gfxdecode, m_palette, gfx_deniam);
|
||||
PALETTE(config, m_palette).set_format(palette_device::xBGRBBBBGGGGRRRR_bit0, 2048); // bit 15 is toggle shadow / hilight?
|
||||
PALETTE(config, m_palette).set_format(palette_device::xBGRBBBBGGGGRRRR_bit0, 2048); // bit 15 is toggle shadow / highlight?
|
||||
|
||||
/* sound hardware */
|
||||
// sound hardware
|
||||
SPEAKER(config, "mono").front_center();
|
||||
|
||||
GENERIC_LATCH_8(config, m_soundlatch);
|
||||
m_soundlatch->data_pending_callback().set_inputline(m_audiocpu, INPUT_LINE_NMI);
|
||||
|
||||
ym3812_device &ymsnd(YM3812(config, "ymsnd", XTAL(25'000'000)/6)); /* "SM64" ym3812 clone; 4.166470 measured, = 4.166666Mhz verified */
|
||||
ymsnd.irq_handler().set_inputline(m_audiocpu, 0);
|
||||
ym3812_device &ymsnd(YM3812(config, "ymsnd", XTAL(25'000'000) / 6)); // "SM64" ym3812 clone; 4.166470 measured, = 4.166666Mhz verified
|
||||
ymsnd.add_route(ALL_OUTPUTS, "mono", 0.60);
|
||||
|
||||
OKIM6295(config, m_oki, XTAL(25'000'000)/24, okim6295_device::PIN7_HIGH); /* 1.041620 measured, = 1.0416666Mhz verified */
|
||||
OKIM6295(config, m_oki, XTAL(25'000'000) / 24, okim6295_device::PIN7_HIGH); // 1.041620 measured, = 1.0416666Mhz verified
|
||||
m_oki->add_route(ALL_OUTPUTS, "mono", 1.0);
|
||||
}
|
||||
|
||||
void deniam_state::deniam16c(machine_config &config)
|
||||
void deniamb_state::deniam16b(machine_config &config)
|
||||
{
|
||||
/* basic machine hardware */
|
||||
M68000(config, m_maincpu, XTAL(25'000'000)/2); /* 12.5Mhz verified */
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &deniam_state::deniam16c_map);
|
||||
m_maincpu->set_vblank_int("screen", FUNC(deniam_state::irq4_line_assert));
|
||||
deniam16c(config);
|
||||
|
||||
/* video hardware */
|
||||
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
|
||||
screen.set_refresh_hz(60);
|
||||
screen.set_vblank_time(ATTOSECONDS_IN_USEC(0));
|
||||
screen.set_size(512, 256);
|
||||
//screen.set_visarea(24*8, 64*8-1, 0*8, 28*8-1); // looks better but doesn't match hardware
|
||||
screen.set_visarea(24*8-4, 64*8-5, 0*8, 28*8-1);
|
||||
screen.set_screen_update(FUNC(deniam_state::screen_update));
|
||||
screen.set_palette(m_palette);
|
||||
// basic machine hardware
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &deniamb_state::main_map);
|
||||
|
||||
GFXDECODE(config, m_gfxdecode, m_palette, gfx_deniam);
|
||||
PALETTE(config, m_palette).set_format(palette_device::xBGRBBBBGGGGRRRR_bit0, 2048); // bit 15 is toggle shadow / hilight?
|
||||
Z80(config, m_audiocpu, XTAL(25'000'000) / 4); // 6.25Mhz verified
|
||||
m_audiocpu->set_addrmap(AS_PROGRAM, &deniamb_state::sound_map);
|
||||
m_audiocpu->set_addrmap(AS_IO, &deniamb_state::sound_io_map);
|
||||
|
||||
/* sound hardware */
|
||||
SPEAKER(config, "mono").front_center();
|
||||
// sound hardware
|
||||
GENERIC_LATCH_8(config, m_soundlatch);
|
||||
m_soundlatch->data_pending_callback().set_inputline(m_audiocpu, INPUT_LINE_NMI);
|
||||
|
||||
ym3812_device &ymsnd(YM3812(config, "ymsnd", XTAL(25'000'000)/6)); /* "SM64" ym3812 clone; 4.166470 measured, = 4.166666Mhz verified) */
|
||||
ymsnd.add_route(ALL_OUTPUTS, "mono", 0.60);
|
||||
|
||||
OKIM6295(config, m_oki, XTAL(25'000'000)/24, okim6295_device::PIN7_HIGH); /* 1.041620 measured, = 1.0416666Mhz verified */
|
||||
m_oki->add_route(ALL_OUTPUTS, "mono", 1.0);
|
||||
subdevice<ym3812_device>("ymsnd")->irq_handler().set_inputline(m_audiocpu, 0);
|
||||
}
|
||||
|
||||
|
||||
@ -316,20 +769,20 @@ ROM_START( croquis )
|
||||
ROM_LOAD16_BYTE( "sys_e0", 0x00000, 0x40000, CRC(b74cd4a9) SHA1(350557377bc5815d0e7f48a96898eba6374f65dd) ) // 27C020
|
||||
ROM_LOAD16_BYTE( "sys_o0", 0x00001, 0x40000, CRC(346e18f4) SHA1(0107ef7b5843a654f393d6f22ef6d52b5bf45fc0) ) // 27C020
|
||||
|
||||
ROM_REGION( 0x10000, "audiocpu", 0 ) /* sound */
|
||||
ROM_REGION( 0x10000, "audiocpu", 0 )
|
||||
ROM_LOAD( "logicpro.r2", 0x0000, 0x10000, CRC(000d624b) SHA1(c0da218ee81d01b3dcef2159bbaaff5d3ddb7619) ) // 27C512 - silkscreened: DSS
|
||||
|
||||
ROM_REGION( 0x180000, "gfx1", 0 ) /* chars */
|
||||
ROM_REGION( 0x180000, "chars", 0 )
|
||||
ROM_LOAD( "logicpro.r5", 0x000000, 0x080000, CRC(dedf18c9) SHA1(9725e096427f03ed5fd81584c0aa85a53f9681c9) ) // 27C040 - silkscreened: BG(00)
|
||||
ROM_LOAD( "logicpro.r6", 0x080000, 0x080000, CRC(3ecbd1c2) SHA1(dd6afacd58eaaa2562e007a92b6667ecc968377d) ) // 27C040 - silkscreened: BG(01)
|
||||
ROM_LOAD( "logicpro.r7", 0x100000, 0x080000, CRC(47135521) SHA1(ee6a93332190fc966f8e820430d652942f030b00) ) // 27C040 - silkscreened: BG(02)
|
||||
|
||||
ROM_REGION( 0x400000, "spritegfx", 0 ) /* sprites, used at run time */
|
||||
ROM_REGION( 0x400000, "spritegfx", 0 ) // used at run time
|
||||
ROM_LOAD16_BYTE( "logicpro.r9", 0x000000, 0x080000, CRC(a98bc1d2) SHA1(f4aed07cccca892f3d3a91546b3a98fbe3e66d9c) ) // 27C040 - silkscreened: OBJ(E0)
|
||||
ROM_LOAD16_BYTE( "logicpro.r8", 0x000001, 0x080000, CRC(1de46298) SHA1(3385a2956d9a427c85554f39c8d85922bbeb1ce1) ) // 27C040 - silkscreened: OBJ(O0)
|
||||
// OBJ(E1), OBJ(E2), OBJ(O1) & OBJ(O2) not populated
|
||||
|
||||
ROM_REGION( 0x100000, "oki", 0 ) /* OKIM6295 samples */
|
||||
ROM_REGION( 0x100000, "oki", 0 )
|
||||
ROM_LOAD( "logicpro.r1", 0x0000, 0x080000, CRC(a1fec4d4) SHA1(4390cd18b4a7de2d8cb68270180ea3de42fd2282) ) // 27C040 - silkscreened: V_ROM0
|
||||
// V_ROM1 not populated
|
||||
ROM_END
|
||||
@ -339,19 +792,19 @@ ROM_START( croquisg )
|
||||
ROM_LOAD16_BYTE( "r4.bin", 0x00000, 0x40000, CRC(03c9055e) SHA1(b1fa8e7a272887decca30eefe73ac782f296f0dd) )
|
||||
ROM_LOAD16_BYTE( "r3.bin", 0x00001, 0x40000, CRC(a98ae4f6) SHA1(80fcedb4ee0f35eb2d0b4a248c15f872af2e08f2) )
|
||||
|
||||
ROM_REGION( 0x10000, "audiocpu", 0 ) /* sound */
|
||||
ROM_REGION( 0x10000, "audiocpu", 0 )
|
||||
ROM_LOAD( "logicpro.r2", 0x0000, 0x10000, CRC(000d624b) SHA1(c0da218ee81d01b3dcef2159bbaaff5d3ddb7619) )
|
||||
|
||||
ROM_REGION( 0x180000, "gfx1", 0 ) /* chars */
|
||||
ROM_REGION( 0x180000, "chars", 0 )
|
||||
ROM_LOAD( "logicpro.r5", 0x000000, 0x080000, CRC(dedf18c9) SHA1(9725e096427f03ed5fd81584c0aa85a53f9681c9) )
|
||||
ROM_LOAD( "logicpro.r6", 0x080000, 0x080000, CRC(3ecbd1c2) SHA1(dd6afacd58eaaa2562e007a92b6667ecc968377d) )
|
||||
ROM_LOAD( "logicpro.r7", 0x100000, 0x080000, CRC(47135521) SHA1(ee6a93332190fc966f8e820430d652942f030b00) )
|
||||
|
||||
ROM_REGION( 0x400000, "spritegfx", 0 ) /* sprites, used at run time */
|
||||
ROM_REGION( 0x400000, "spritegfx", 0 ) // used at run time
|
||||
ROM_LOAD16_BYTE( "logicpro.r9", 0x000000, 0x080000, CRC(a98bc1d2) SHA1(f4aed07cccca892f3d3a91546b3a98fbe3e66d9c) )
|
||||
ROM_LOAD16_BYTE( "logicpro.r8", 0x000001, 0x080000, CRC(1de46298) SHA1(3385a2956d9a427c85554f39c8d85922bbeb1ce1) )
|
||||
|
||||
ROM_REGION( 0x100000, "oki", 0 ) /* OKIM6295 samples */
|
||||
ROM_REGION( 0x100000, "oki", 0 )
|
||||
ROM_LOAD( "logicpro.r1", 0x0000, 0x080000, CRC(a1fec4d4) SHA1(4390cd18b4a7de2d8cb68270180ea3de42fd2282) )
|
||||
ROM_END
|
||||
|
||||
@ -360,19 +813,19 @@ ROM_START( logicpro )
|
||||
ROM_LOAD16_BYTE( "logicpro.r4", 0x00000, 0x40000, CRC(c506d484) SHA1(5d662b109e1d2e09556bc4ecbc11bbf5ccb639d3) )
|
||||
ROM_LOAD16_BYTE( "logicpro.r3", 0x00001, 0x40000, CRC(d5a4cf62) SHA1(138ea4f1629e453c1a00410eda7086d3633240e3) )
|
||||
|
||||
ROM_REGION( 0x10000, "audiocpu", 0 ) /* sound */
|
||||
ROM_REGION( 0x10000, "audiocpu", 0 )
|
||||
ROM_LOAD( "logicpro.r2", 0x0000, 0x10000, CRC(000d624b) SHA1(c0da218ee81d01b3dcef2159bbaaff5d3ddb7619) )
|
||||
|
||||
ROM_REGION( 0x180000, "gfx1", 0 ) /* chars */
|
||||
ROM_REGION( 0x180000, "chars", 0 )
|
||||
ROM_LOAD( "logicpro.r5", 0x000000, 0x080000, CRC(dedf18c9) SHA1(9725e096427f03ed5fd81584c0aa85a53f9681c9) )
|
||||
ROM_LOAD( "logicpro.r6", 0x080000, 0x080000, CRC(3ecbd1c2) SHA1(dd6afacd58eaaa2562e007a92b6667ecc968377d) )
|
||||
ROM_LOAD( "logicpro.r7", 0x100000, 0x080000, CRC(47135521) SHA1(ee6a93332190fc966f8e820430d652942f030b00) )
|
||||
|
||||
ROM_REGION( 0x400000, "spritegfx", 0 ) /* sprites, used at run time */
|
||||
ROM_REGION( 0x400000, "spritegfx", 0 ) // used at run time
|
||||
ROM_LOAD16_BYTE( "logicpro.r9", 0x000000, 0x080000, CRC(a98bc1d2) SHA1(f4aed07cccca892f3d3a91546b3a98fbe3e66d9c) )
|
||||
ROM_LOAD16_BYTE( "logicpro.r8", 0x000001, 0x080000, CRC(1de46298) SHA1(3385a2956d9a427c85554f39c8d85922bbeb1ce1) )
|
||||
|
||||
ROM_REGION( 0x100000, "oki", 0 ) /* OKIM6295 samples */
|
||||
ROM_REGION( 0x100000, "oki", 0 )
|
||||
ROM_LOAD( "logicpro.r1", 0x0000, 0x080000, CRC(a1fec4d4) SHA1(4390cd18b4a7de2d8cb68270180ea3de42fd2282) )
|
||||
ROM_END
|
||||
|
||||
@ -381,15 +834,15 @@ ROM_START( karianx )
|
||||
ROM_LOAD16_BYTE( "even", 0x00000, 0x80000, CRC(fd0ce238) SHA1(4b727366c942c62187d8700666b42a85c059c060) )
|
||||
ROM_LOAD16_BYTE( "odd", 0x00001, 0x80000, CRC(be173cdc) SHA1(13230b6129fd1910257624a69a3a4b74696e982e) )
|
||||
|
||||
ROM_REGION( 0x10000, "audiocpu", 0 ) /* sound */
|
||||
ROM_REGION( 0x10000, "audiocpu", 0 )
|
||||
ROM_LOAD( "snd", 0x0000, 0x10000, CRC(fedd3375) SHA1(09fb2d5fc91704120f757acf9fa00d149f891a28) )
|
||||
|
||||
ROM_REGION( 0x180000, "gfx1", 0 ) /* chars */
|
||||
ROM_REGION( 0x180000, "chars", 0 )
|
||||
ROM_LOAD( "bkg1", 0x000000, 0x080000, CRC(5cb8558a) SHA1(9c6024c70a0f0cd529a0e2e853e467ec8d8ab446) )
|
||||
ROM_LOAD( "bkg2", 0x080000, 0x080000, CRC(95ff297c) SHA1(28f6c005e73e1680bd8be7ce355fa0d404827105) )
|
||||
ROM_LOAD( "bkg3", 0x100000, 0x080000, CRC(6c81f1b2) SHA1(14ef907a9c381b7ef45441d480bb4ccb015e474b) )
|
||||
|
||||
ROM_REGION( 0x400000, "spritegfx", 0 ) /* sprites, used at run time */
|
||||
ROM_REGION( 0x400000, "spritegfx", 0 ) // used at run time
|
||||
ROM_LOAD16_BYTE( "obj4", 0x000000, 0x080000, CRC(5f8d75a9) SHA1(0552d046742aeb2fee176887156e73480c75a1bd) )
|
||||
ROM_LOAD16_BYTE( "obj1", 0x000001, 0x080000, CRC(967ee97d) SHA1(689f2da67eab86653b846fada39139792cd4aee2) )
|
||||
ROM_LOAD16_BYTE( "obj5", 0x100000, 0x080000, CRC(e9fc22f9) SHA1(a1f7f779520346406949500e3224c0c42cbbe026) )
|
||||
@ -397,7 +850,7 @@ ROM_START( karianx )
|
||||
ROM_LOAD16_BYTE( "obj6", 0x200000, 0x080000, CRC(c1ec35a5) SHA1(bf59f4c3de081c8cc398c825fc1f3e8577641f10) )
|
||||
ROM_LOAD16_BYTE( "obj3", 0x200001, 0x080000, CRC(6ac1ac87) SHA1(1954e25ac5489a8eca137b86c89c415f1fed360c) )
|
||||
|
||||
ROM_REGION( 0x100000, "oki", 0 ) /* OKIM6295 samples */
|
||||
ROM_REGION( 0x100000, "oki", 0 )
|
||||
ROM_LOAD( "voi", 0x0000, 0x080000, CRC(c6506a80) SHA1(121229c501bd5678e55c7342619743c773a01a7e) )
|
||||
ROM_END
|
||||
|
||||
@ -406,22 +859,23 @@ ROM_START( logicpr2 )
|
||||
ROM_LOAD16_BYTE( "lp2-2", 0x00000, 0x80000, CRC(cc1880bf) SHA1(5ea542b63947a570aaf924f7ab739e060e359af8) )
|
||||
ROM_LOAD16_BYTE( "lp2-1", 0x00001, 0x80000, CRC(46d5e954) SHA1(7bf5ae19caeecd2123754698276bbc78d68984d9) )
|
||||
|
||||
ROM_REGION( 0x180000, "gfx1", 0 ) /* chars */
|
||||
ROM_REGION( 0x180000, "chars", 0 )
|
||||
ROM_LOAD( "log2-b01", 0x000000, 0x080000, CRC(fe789e07) SHA1(c3d542564519fd807bc605029f5a2cca571eec9f) )
|
||||
ROM_LOAD( "log2-b02", 0x080000, 0x080000, CRC(1e0c51cd) SHA1(c25b3259a173e77785dcee1407ddf191c3efad79) )
|
||||
ROM_LOAD( "log2-b03", 0x100000, 0x080000, CRC(916f2928) SHA1(8c73408664dcd3de42cb27fac0d22b87b540bf52) )
|
||||
|
||||
ROM_REGION( 0x400000, "spritegfx", 0 ) /* sprites, used at run time */
|
||||
ROM_REGION( 0x400000, "spritegfx", 0 ) // used at run time
|
||||
ROM_LOAD16_WORD_SWAP( "obj", 0x000000, 0x400000, CRC(f221f305) SHA1(aa1d3d86d13e009bfb44cbc6ff4401b811b19f97) )
|
||||
|
||||
ROM_REGION( 0x100000, "oki", 0 ) /* OKIM6295 samples */
|
||||
ROM_REGION( 0x100000, "oki", 0 )
|
||||
ROM_LOAD( "log2-s01", 0x0000, 0x100000, CRC(2875c435) SHA1(633538d9ac53228ea344605482ac387852c29193) )
|
||||
ROM_END
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
GAME( 1996, croquis, 0, deniam16b, logicpr2, deniam_state, init_logicpro, ROT0, "Deniam", "Croquis (Korea)", MACHINE_SUPPORTS_SAVE )
|
||||
GAME( 1996, croquisg, croquis, deniam16b, logicpr2, deniam_state, init_logicpro, ROT0, "Deniam", "Croquis (Germany)", MACHINE_SUPPORTS_SAVE )
|
||||
GAME( 1996, logicpro, croquis, deniam16b, logicpr2, deniam_state, init_logicpro, ROT0, "Deniam", "Logic Pro (Japan)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE )
|
||||
GAME( 1996, karianx, 0, deniam16b, karianx, deniam_state, init_karianx, ROT0, "Deniam", "Karian Cross (Rev. 1.0)", MACHINE_SUPPORTS_SAVE )
|
||||
GAME( 1997, logicpr2, 0, deniam16c, logicpr2, deniam_state, init_logicpro, ROT0, "Deniam", "Logic Pro 2 (Japan)", MACHINE_SUPPORTS_SAVE )
|
||||
GAME( 1996, croquis, 0, deniam16b, logicpr2, deniamb_state, init_logicpro, ROT0, "Deniam", "Croquis (Korea)", MACHINE_SUPPORTS_SAVE )
|
||||
GAME( 1996, croquisg, croquis, deniam16b, logicpr2, deniamb_state, init_logicpro, ROT0, "Deniam", "Croquis (Germany)", MACHINE_SUPPORTS_SAVE )
|
||||
GAME( 1996, logicpro, croquis, deniam16b, logicpr2, deniamb_state, init_logicpro, ROT0, "Deniam", "Logic Pro (Japan)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE )
|
||||
GAME( 1996, karianx, 0, deniam16b, karianx, deniamb_state, init_karianx, ROT0, "Deniam", "Karian Cross (Rev. 1.0)", MACHINE_SUPPORTS_SAVE )
|
||||
GAME( 1997, logicpr2, 0, deniam16c, logicpr2, deniamc_state, init_logicpro, ROT0, "Deniam", "Logic Pro 2 (Japan)", MACHINE_SUPPORTS_SAVE )
|
||||
|
@ -1,95 +0,0 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Nicola Salmoria
|
||||
|
||||
/*************************************************************************
|
||||
|
||||
Deniam games
|
||||
|
||||
*************************************************************************/
|
||||
|
||||
#include "machine/gen_latch.h"
|
||||
#include "sound/okim6295.h"
|
||||
#include "emupal.h"
|
||||
#include "tilemap.h"
|
||||
|
||||
class deniam_state : public driver_device
|
||||
{
|
||||
public:
|
||||
deniam_state(const machine_config &mconfig, device_type type, const char *tag) :
|
||||
driver_device(mconfig, type, tag),
|
||||
m_videoram(*this, "videoram"),
|
||||
m_textram(*this, "textram"),
|
||||
m_spriteram(*this, "spriteram"),
|
||||
m_spritegfx(*this, "spritegfx"),
|
||||
m_maincpu(*this, "maincpu"),
|
||||
m_audiocpu(*this, "audiocpu"),
|
||||
m_oki(*this, "oki"),
|
||||
m_gfxdecode(*this, "gfxdecode"),
|
||||
m_palette(*this, "palette"),
|
||||
m_soundlatch(*this, "soundlatch")
|
||||
{ }
|
||||
|
||||
void deniam16c(machine_config &config);
|
||||
void deniam16b(machine_config &config);
|
||||
|
||||
void init_karianx();
|
||||
void init_logicpro();
|
||||
|
||||
private:
|
||||
/* memory pointers */
|
||||
required_shared_ptr<u16> m_videoram;
|
||||
required_shared_ptr<u16> m_textram;
|
||||
required_shared_ptr<u16> m_spriteram;
|
||||
|
||||
required_memory_region m_spritegfx;
|
||||
|
||||
/* video-related */
|
||||
tilemap_t *m_fg_tilemap = nullptr;
|
||||
tilemap_t *m_bg_tilemap = nullptr;
|
||||
tilemap_t *m_tx_tilemap = nullptr;
|
||||
int m_display_enable = 0;
|
||||
int m_bg_scrollx_offs = 0;
|
||||
int m_bg_scrolly_offs = 0;
|
||||
int m_fg_scrollx_offs = 0;
|
||||
int m_fg_scrolly_offs = 0;
|
||||
int m_bg_scrollx_reg = 0;
|
||||
int m_bg_scrolly_reg = 0;
|
||||
int m_bg_page_reg = 0;
|
||||
int m_fg_scrollx_reg = 0;
|
||||
int m_fg_scrolly_reg = 0;
|
||||
int m_fg_page_reg = 0;
|
||||
int m_bg_page[4]{};
|
||||
int m_fg_page[4]{};
|
||||
u16 m_coinctrl = 0;
|
||||
|
||||
/* devices */
|
||||
void irq_ack_w(u16 data);
|
||||
void videoram_w(offs_t offset, u16 data, u16 mem_mask = ~0);
|
||||
void textram_w(offs_t offset, u16 data, u16 mem_mask = ~0);
|
||||
u16 coinctrl_r();
|
||||
void coinctrl_w(offs_t offset, u16 data, u16 mem_mask = ~0);
|
||||
void deniam16b_oki_rom_bank_w(u8 data);
|
||||
void deniam16c_oki_rom_bank_w(u8 data);
|
||||
TILEMAP_MAPPER_MEMBER(scan_pages);
|
||||
TILE_GET_INFO_MEMBER(get_bg_tile_info);
|
||||
TILE_GET_INFO_MEMBER(get_fg_tile_info);
|
||||
TILE_GET_INFO_MEMBER(get_tx_tile_info);
|
||||
virtual void machine_start() override;
|
||||
virtual void machine_reset() override;
|
||||
virtual void video_start() override;
|
||||
u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
void deniam_common_init( );
|
||||
void draw_sprites( screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect );
|
||||
void set_bg_page( int page, int value );
|
||||
void set_fg_page( int page, int value );
|
||||
required_device<cpu_device> m_maincpu;
|
||||
optional_device<cpu_device> m_audiocpu; // system 16c does not have sound CPU
|
||||
required_device<okim6295_device> m_oki;
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
required_device<palette_device> m_palette;
|
||||
optional_device<generic_latch_8_device> m_soundlatch;
|
||||
void deniam16b_map(address_map &map);
|
||||
void deniam16c_map(address_map &map);
|
||||
void sound_io_map(address_map &map);
|
||||
void sound_map(address_map &map);
|
||||
};
|
@ -1,374 +0,0 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Nicola Salmoria
|
||||
#include "emu.h"
|
||||
#include "deniam.h"
|
||||
#include "screen.h"
|
||||
|
||||
|
||||
void deniam_state::deniam_common_init( )
|
||||
{
|
||||
m_bg_scrollx_reg = 0x00a4/2;
|
||||
m_bg_scrolly_reg = 0x00a8/2;
|
||||
m_bg_page_reg = 0x00ac/2;
|
||||
m_fg_scrollx_reg = 0x00a2/2;
|
||||
m_fg_scrolly_reg = 0x00a6/2;
|
||||
m_fg_page_reg = 0x00aa/2;
|
||||
|
||||
m_display_enable = 0;
|
||||
m_coinctrl = 0;
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
m_bg_page[i] = 0;
|
||||
m_fg_page[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void deniam_state::init_logicpro()
|
||||
{
|
||||
deniam_common_init();
|
||||
|
||||
m_bg_scrollx_offs = 0x00d;
|
||||
m_bg_scrolly_offs = 0x000;
|
||||
m_fg_scrollx_offs = 0x009;
|
||||
m_fg_scrolly_offs = 0x000;
|
||||
}
|
||||
|
||||
void deniam_state::init_karianx()
|
||||
{
|
||||
deniam_common_init();
|
||||
|
||||
m_bg_scrollx_offs = 0x10d;
|
||||
m_bg_scrolly_offs = 0x080;
|
||||
m_fg_scrollx_offs = 0x109;
|
||||
m_fg_scrolly_offs = 0x080;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
Callbacks for the TileMap code
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
TILEMAP_MAPPER_MEMBER(deniam_state::scan_pages)
|
||||
{
|
||||
/* logical (col,row) -> memory offset */
|
||||
return (col & 0x3f) + ((row & 0x1f) << 6) + ((col & 0x40) << 5) + ((row & 0x20) << 7);
|
||||
}
|
||||
|
||||
TILE_GET_INFO_MEMBER(deniam_state::get_bg_tile_info)
|
||||
{
|
||||
const int page = tile_index >> 11;
|
||||
u16 attr = m_videoram[m_bg_page[page] * 0x0800 + (tile_index & 0x7ff)];
|
||||
tileinfo.set(0,
|
||||
attr,
|
||||
(attr & 0x1fc0) >> 6,
|
||||
0);
|
||||
}
|
||||
|
||||
TILE_GET_INFO_MEMBER(deniam_state::get_fg_tile_info)
|
||||
{
|
||||
const int page = tile_index >> 11;
|
||||
u16 attr = m_videoram[m_fg_page[page] * 0x0800 + (tile_index & 0x7ff)];
|
||||
tileinfo.set(0,
|
||||
attr,
|
||||
(attr & 0x1fc0) >> 6,
|
||||
0);
|
||||
}
|
||||
|
||||
TILE_GET_INFO_MEMBER(deniam_state::get_tx_tile_info)
|
||||
{
|
||||
u16 attr = m_textram[tile_index];
|
||||
tileinfo.set(0,
|
||||
attr & 0xf1ff,
|
||||
(attr & 0x0e00) >> 9,
|
||||
0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
Start the video hardware emulation.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
void deniam_state::video_start()
|
||||
{
|
||||
m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(deniam_state::get_bg_tile_info)), tilemap_mapper_delegate(*this, FUNC(deniam_state::scan_pages)), 8, 8, 128, 64);
|
||||
m_fg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(deniam_state::get_fg_tile_info)), tilemap_mapper_delegate(*this, FUNC(deniam_state::scan_pages)), 8, 8, 128, 64);
|
||||
m_tx_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(deniam_state::get_tx_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 64, 32);
|
||||
|
||||
m_fg_tilemap->set_transparent_pen(0);
|
||||
m_tx_tilemap->set_transparent_pen(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
Memory handlers
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
void deniam_state::videoram_w(offs_t offset, u16 data, u16 mem_mask)
|
||||
{
|
||||
COMBINE_DATA(&m_videoram[offset]);
|
||||
|
||||
const int page = offset >> 11;
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (m_bg_page[i] == page)
|
||||
m_bg_tilemap->mark_tile_dirty(i * 0x800 + (offset & 0x7ff));
|
||||
if (m_fg_page[i] == page)
|
||||
m_fg_tilemap->mark_tile_dirty(i * 0x800 + (offset & 0x7ff));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void deniam_state::textram_w(offs_t offset, u16 data, u16 mem_mask)
|
||||
{
|
||||
COMBINE_DATA(&m_textram[offset]);
|
||||
m_tx_tilemap->mark_tile_dirty(offset);
|
||||
}
|
||||
|
||||
|
||||
u16 deniam_state::coinctrl_r()
|
||||
{
|
||||
return m_coinctrl;
|
||||
}
|
||||
|
||||
void deniam_state::coinctrl_w(offs_t offset, u16 data, u16 mem_mask)
|
||||
{
|
||||
COMBINE_DATA(&m_coinctrl);
|
||||
|
||||
/* bit 0 is coin counter */
|
||||
machine().bookkeeping().coin_counter_w(0, m_coinctrl & 0x01);
|
||||
|
||||
/* bit 6 is display enable (0 freezes screen) */
|
||||
m_display_enable = m_coinctrl & 0x20;
|
||||
|
||||
/* other bits unknown (unused?) */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
Display refresh
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
/*
|
||||
* Sprite Format
|
||||
* ------------------
|
||||
*
|
||||
* Word | Bit(s) | Use
|
||||
* -----+-fedcba9876543210-+----------------
|
||||
* 0 | --------xxxxxxxx | display y start
|
||||
* 0 | xxxxxxxx-------- | display y end
|
||||
* 2 | -------xxxxxxxxx | x position
|
||||
* 2 | ------x--------- | unknown (used in logicpr2, maybe just a bug?)
|
||||
* 2 | xxxxxx---------- | unused?
|
||||
* 4 | ---------xxxxxxx | width
|
||||
* 4 | --------x------- | is this flip y like in System 16?
|
||||
* 4 | -------x-------- | flip x
|
||||
* 4 | xxxxxxx--------- | unused?
|
||||
* 6 | xxxxxxxxxxxxxxxx | ROM address low bits
|
||||
* 8 | ----------xxxxxx | color
|
||||
* 8 | --------xx------ | priority
|
||||
* 8 | ---xxxxx-------- | ROM address high bits
|
||||
* 8 | xxx------------- | unused? (extra address bits for larger ROMs?)
|
||||
* a | ---------------- | zoomx like in System 16?
|
||||
* c | ---------------- | zoomy like in System 16?
|
||||
* e | ---------------- |
|
||||
*/
|
||||
void deniam_state::draw_sprites( screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect )
|
||||
{
|
||||
for (int offs = m_spriteram.bytes() / 2 - 8; offs >= 0; offs -= 8)
|
||||
{
|
||||
u8 *rom = m_spritegfx->base();
|
||||
|
||||
int sx = (m_spriteram[offs + 1] & 0x01ff) + 16 * 8 - 1;
|
||||
if (sx >= 512) sx -= 512;
|
||||
const int starty = m_spriteram[offs + 0] & 0xff;
|
||||
const int endy = m_spriteram[offs + 0] >> 8;
|
||||
|
||||
const int width = m_spriteram[offs + 2] & 0x007f;
|
||||
bool flipx = m_spriteram[offs + 2] & 0x0100;
|
||||
if (flipx) sx++;
|
||||
|
||||
const u32 color = 0x40 + (m_spriteram[offs + 4] & 0x3f);
|
||||
|
||||
int primask = 8;
|
||||
switch (m_spriteram[offs + 4] & 0xc0)
|
||||
{
|
||||
case 0x00: primask |= 4 | 2 | 1; break; /* below everything */
|
||||
case 0x40: primask |= 4 | 2; break; /* below fg and tx */
|
||||
case 0x80: primask |= 4; break; /* below tx */
|
||||
case 0xc0: break; /* above everything */
|
||||
}
|
||||
|
||||
const int start = m_spriteram[offs + 3] + ((m_spriteram[offs + 4] & 0x1f00) << 8);
|
||||
rom += 2 * start;
|
||||
|
||||
for (int y = starty + 1; y <= endy; y++)
|
||||
{
|
||||
bool drawing = false;
|
||||
int i = 0;
|
||||
|
||||
rom += 2 * width; /* note that the first line is skipped */
|
||||
int x = 0;
|
||||
while (i < 512) /* safety check */
|
||||
{
|
||||
if (flipx)
|
||||
{
|
||||
if ((rom[i] & 0x0f) == 0x0f)
|
||||
{
|
||||
if (!drawing) drawing = true;
|
||||
else break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rom[i] & 0x0f)
|
||||
{
|
||||
if (cliprect.contains(sx + x, y))
|
||||
{
|
||||
if ((screen.priority().pix(y, sx + x) & primask) == 0)
|
||||
bitmap.pix(y, sx + x) = color * 16 + (rom[i] & 0x0f);
|
||||
screen.priority().pix(y, sx + x) = 8;
|
||||
}
|
||||
}
|
||||
x++;
|
||||
}
|
||||
|
||||
if ((rom[i] & 0xf0) == 0xf0)
|
||||
{
|
||||
if (!drawing) drawing = true;
|
||||
else break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rom[i] & 0xf0)
|
||||
{
|
||||
if (cliprect.contains(sx + x, y))
|
||||
{
|
||||
if ((screen.priority().pix(y, sx + x) & primask) == 0)
|
||||
bitmap.pix(y, sx + x) = color * 16+(rom[i] >> 4);
|
||||
screen.priority().pix(y, sx + x) = 8;
|
||||
}
|
||||
}
|
||||
x++;
|
||||
}
|
||||
|
||||
i--;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((rom[i] & 0xf0) == 0xf0)
|
||||
{
|
||||
if (!drawing) drawing = true;
|
||||
else break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rom[i] & 0xf0)
|
||||
{
|
||||
if (cliprect.contains(sx + x, y))
|
||||
{
|
||||
if ((screen.priority().pix(y, sx + x) & primask) == 0)
|
||||
bitmap.pix(y, sx + x) = color * 16 + (rom[i] >> 4);
|
||||
screen.priority().pix(y, sx + x) = 8;
|
||||
}
|
||||
}
|
||||
x++;
|
||||
}
|
||||
|
||||
if ((rom[i] & 0x0f) == 0x0f)
|
||||
{
|
||||
if (!drawing) drawing = true;
|
||||
else break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rom[i] & 0x0f)
|
||||
{
|
||||
if (cliprect.contains(sx + x, y))
|
||||
{
|
||||
if ((screen.priority().pix(y, sx + x) & primask) == 0)
|
||||
bitmap.pix(y, sx + x) = color * 16 + (rom[i] & 0x0f);
|
||||
screen.priority().pix(y, sx + x) = 8;
|
||||
}
|
||||
}
|
||||
x++;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void deniam_state::set_bg_page( int page, int value )
|
||||
{
|
||||
if (m_bg_page[page] != value)
|
||||
{
|
||||
m_bg_page[page] = value;
|
||||
for (int tile_index = page * 0x800; tile_index < (page + 1) * 0x800; tile_index++)
|
||||
m_bg_tilemap->mark_tile_dirty(tile_index);
|
||||
}
|
||||
}
|
||||
|
||||
void deniam_state::set_fg_page( int page, int value )
|
||||
{
|
||||
if (m_fg_page[page] != value)
|
||||
{
|
||||
m_fg_page[page] = value;
|
||||
for (int tile_index = page * 0x800; tile_index < (page + 1) * 0x800; tile_index++)
|
||||
m_fg_tilemap->mark_tile_dirty(tile_index);
|
||||
}
|
||||
}
|
||||
|
||||
u32 deniam_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
int page;
|
||||
|
||||
if (!m_display_enable)
|
||||
{
|
||||
bitmap.fill(m_palette->black_pen(), cliprect);
|
||||
return 0; /* don't update (freeze display) */
|
||||
}
|
||||
|
||||
int bg_scrollx = m_textram[m_bg_scrollx_reg] - m_bg_scrollx_offs;
|
||||
int bg_scrolly = (m_textram[m_bg_scrolly_reg] & 0xff) - m_bg_scrolly_offs;
|
||||
page = m_textram[m_bg_page_reg];
|
||||
set_bg_page(3, (page >>12) & 0x0f);
|
||||
set_bg_page(2, (page >> 8) & 0x0f);
|
||||
set_bg_page(1, (page >> 4) & 0x0f);
|
||||
set_bg_page(0, (page >> 0) & 0x0f);
|
||||
|
||||
int fg_scrollx = m_textram[m_fg_scrollx_reg] - m_fg_scrollx_offs;
|
||||
int fg_scrolly = (m_textram[m_fg_scrolly_reg] & 0xff) - m_fg_scrolly_offs;
|
||||
page = m_textram[m_fg_page_reg];
|
||||
set_fg_page(3, (page >>12) & 0x0f);
|
||||
set_fg_page(2, (page >> 8) & 0x0f);
|
||||
set_fg_page(1, (page >> 4) & 0x0f);
|
||||
set_fg_page(0, (page >> 0) & 0x0f);
|
||||
|
||||
m_bg_tilemap->set_scrollx(0, bg_scrollx & 0x1ff);
|
||||
m_bg_tilemap->set_scrolly(0, bg_scrolly & 0x0ff);
|
||||
m_fg_tilemap->set_scrollx(0, fg_scrollx & 0x1ff);
|
||||
m_fg_tilemap->set_scrolly(0, fg_scrolly & 0x0ff);
|
||||
|
||||
screen.priority().fill(0, cliprect);
|
||||
|
||||
m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 1);
|
||||
m_fg_tilemap->draw(screen, bitmap, cliprect, 0, 2);
|
||||
m_tx_tilemap->draw(screen, bitmap, cliprect, 0, 4);
|
||||
|
||||
draw_sprites(screen, bitmap, cliprect);
|
||||
return 0;
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Nicola Salmoria
|
||||
// copyright-holders: Nicola Salmoria
|
||||
|
||||
/********************************************************
|
||||
|
||||
KO Punch (c) 1981 Sega
|
||||
@ -32,12 +33,195 @@
|
||||
********************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "kopunch.h"
|
||||
|
||||
#include "cpu/i8085/i8085.h"
|
||||
#include "machine/i8255.h"
|
||||
#include "screen.h"
|
||||
|
||||
#include "emupal.h"
|
||||
#include "screen.h"
|
||||
#include "tilemap.h"
|
||||
|
||||
|
||||
// configurable logging
|
||||
#define LOG_PORT34 (1U << 1)
|
||||
|
||||
//#define VERBOSE (LOG_GENERAL | LOG_PORT34)
|
||||
|
||||
#include "logmacro.h"
|
||||
|
||||
#define LOGPORT34(...) LOGMASKED(LOG_PORT34, __VA_ARGS__)
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
class kopunch_state : public driver_device
|
||||
{
|
||||
public:
|
||||
kopunch_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: driver_device(mconfig, type, tag)
|
||||
, m_maincpu(*this, "maincpu")
|
||||
, m_gfxdecode(*this, "gfxdecode")
|
||||
, m_vram_fg(*this, "vram_fg")
|
||||
, m_vram_bg(*this, "vram_bg")
|
||||
, m_system(*this, "SYSTEM")
|
||||
, m_lamp(*this, "lamp0")
|
||||
{ }
|
||||
|
||||
void kopunch(machine_config &config);
|
||||
|
||||
DECLARE_INPUT_CHANGED_MEMBER(left_coin_inserted);
|
||||
DECLARE_INPUT_CHANGED_MEMBER(right_coin_inserted);
|
||||
|
||||
protected:
|
||||
virtual void machine_start() override;
|
||||
virtual void video_start() override;
|
||||
|
||||
private:
|
||||
uint8_t sensors1_r();
|
||||
uint8_t sensors2_r();
|
||||
void lamp_w(uint8_t data);
|
||||
void coin_w(uint8_t data);
|
||||
void vram_fg_w(offs_t offset, uint8_t data);
|
||||
void vram_bg_w(offs_t offset, uint8_t data);
|
||||
void scroll_x_w(uint8_t data);
|
||||
void scroll_y_w(uint8_t data);
|
||||
void gfxbank_w(uint8_t data);
|
||||
|
||||
TILE_GET_INFO_MEMBER(get_fg_tile_info);
|
||||
TILE_GET_INFO_MEMBER(get_bg_tile_info);
|
||||
void palette(palette_device &palette) const;
|
||||
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
|
||||
void io_map(address_map &map);
|
||||
void prg_map(address_map &map);
|
||||
|
||||
// devices
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
|
||||
// memory pointers
|
||||
required_shared_ptr<uint8_t> m_vram_fg;
|
||||
required_shared_ptr<uint8_t> m_vram_bg;
|
||||
|
||||
required_ioport m_system;
|
||||
output_finder<> m_lamp;
|
||||
|
||||
// video-related
|
||||
tilemap_t *m_bg_tilemap = nullptr;
|
||||
tilemap_t *m_fg_tilemap = nullptr;
|
||||
uint8_t m_gfxbank = 0U;
|
||||
uint8_t m_scrollx = 0U;
|
||||
};
|
||||
|
||||
|
||||
// video
|
||||
|
||||
void kopunch_state::palette(palette_device &palette) const
|
||||
{
|
||||
const uint8_t *color_prom = memregion("proms")->base();
|
||||
|
||||
color_prom += 24; // first 24 colors are black
|
||||
|
||||
for (int i = 0; i < palette.entries(); i++)
|
||||
{
|
||||
int bit0, bit1, bit2;
|
||||
|
||||
// red component
|
||||
bit0 = BIT(*color_prom, 0);
|
||||
bit1 = BIT(*color_prom, 1);
|
||||
bit2 = BIT(*color_prom, 2);
|
||||
int const r = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
|
||||
// green component
|
||||
bit0 = BIT(*color_prom, 3);
|
||||
bit1 = BIT(*color_prom, 4);
|
||||
bit2 = BIT(*color_prom, 5);
|
||||
int const g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
|
||||
// blue component
|
||||
bit0 = 0;
|
||||
bit1 = BIT(*color_prom, 6);
|
||||
bit2 = BIT(*color_prom, 7);
|
||||
int const b = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
|
||||
|
||||
palette.set_pen_color(i, rgb_t(r, g, b));
|
||||
color_prom++;
|
||||
}
|
||||
}
|
||||
|
||||
void kopunch_state::vram_fg_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
m_vram_fg[offset] = data;
|
||||
m_fg_tilemap->mark_tile_dirty(offset);
|
||||
}
|
||||
|
||||
void kopunch_state::vram_bg_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
m_vram_bg[offset] = data;
|
||||
m_bg_tilemap->mark_tile_dirty(offset);
|
||||
}
|
||||
|
||||
void kopunch_state::scroll_x_w(uint8_t data)
|
||||
{
|
||||
m_scrollx = data;
|
||||
m_bg_tilemap->set_scrollx(0, data);
|
||||
}
|
||||
|
||||
void kopunch_state::scroll_y_w(uint8_t data)
|
||||
{
|
||||
m_bg_tilemap->set_scrolly(0, data);
|
||||
}
|
||||
|
||||
void kopunch_state::gfxbank_w(uint8_t data)
|
||||
{
|
||||
// d0-d2: bg gfx bank
|
||||
if (m_gfxbank != (data & 0x07))
|
||||
{
|
||||
m_gfxbank = data & 0x07;
|
||||
m_bg_tilemap->mark_all_dirty();
|
||||
}
|
||||
|
||||
// d3: flip y, other bits: N/C
|
||||
m_bg_tilemap->set_flip((data & 0x08) ? TILEMAP_FLIPY : 0);
|
||||
}
|
||||
|
||||
TILE_GET_INFO_MEMBER(kopunch_state::get_fg_tile_info)
|
||||
{
|
||||
int const code = m_vram_fg[tile_index];
|
||||
|
||||
tileinfo.set(0, code, 0, 0);
|
||||
}
|
||||
|
||||
TILE_GET_INFO_MEMBER(kopunch_state::get_bg_tile_info)
|
||||
{
|
||||
// note: highest bit is unused
|
||||
int const code = (m_vram_bg[tile_index] & 0x7f) | m_gfxbank << 7;
|
||||
|
||||
tileinfo.set(1, code, 0, 0);
|
||||
}
|
||||
|
||||
void kopunch_state::video_start()
|
||||
{
|
||||
m_fg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(kopunch_state::get_fg_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 32, 32);
|
||||
m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(kopunch_state::get_bg_tile_info)), TILEMAP_SCAN_ROWS, 16, 16, 16, 16);
|
||||
|
||||
m_fg_tilemap->set_transparent_pen(0);
|
||||
}
|
||||
|
||||
uint32_t kopunch_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
bitmap.fill(0, cliprect);
|
||||
|
||||
// background does not wrap around horizontally
|
||||
rectangle bg_clip = cliprect;
|
||||
bg_clip.max_x = m_scrollx ^ 0xff;
|
||||
|
||||
m_bg_tilemap->draw(screen, bitmap, bg_clip, 0, 0);
|
||||
m_fg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// machine
|
||||
|
||||
/********************************************************
|
||||
|
||||
@ -66,17 +250,17 @@ INPUT_CHANGED_MEMBER(kopunch_state::right_coin_inserted)
|
||||
|
||||
********************************************************/
|
||||
|
||||
void kopunch_state::kopunch_map(address_map &map)
|
||||
void kopunch_state::prg_map(address_map &map)
|
||||
{
|
||||
map(0x0000, 0x1fff).rom();
|
||||
map(0x2000, 0x23ff).ram();
|
||||
map(0x6000, 0x63ff).ram().w(FUNC(kopunch_state::vram_fg_w)).share("vram_fg");
|
||||
map(0x7000, 0x70ff).ram().w(FUNC(kopunch_state::vram_bg_w)).share("vram_bg");
|
||||
map(0x6000, 0x63ff).ram().w(FUNC(kopunch_state::vram_fg_w)).share(m_vram_fg);
|
||||
map(0x7000, 0x70ff).ram().w(FUNC(kopunch_state::vram_bg_w)).share(m_vram_bg);
|
||||
map(0x7100, 0x73ff).ram(); // unused vram
|
||||
map(0x7400, 0x7bff).ram(); // more unused vram? or accidental writes?
|
||||
}
|
||||
|
||||
void kopunch_state::kopunch_io_map(address_map &map)
|
||||
void kopunch_state::io_map(address_map &map)
|
||||
{
|
||||
map(0x30, 0x33).rw("ppi8255_0", FUNC(i8255_device::read), FUNC(i8255_device::write));
|
||||
map(0x34, 0x37).rw("ppi8255_1", FUNC(i8255_device::read), FUNC(i8255_device::write));
|
||||
@ -106,7 +290,7 @@ uint8_t kopunch_state::sensors2_r()
|
||||
// d5: unknown sensor
|
||||
// d6: unknown sensor
|
||||
// d7: coin 1
|
||||
return (machine().rand() & 0x07) | ioport("SYSTEM")->read();
|
||||
return (machine().rand() & 0x07) | m_system->read();
|
||||
}
|
||||
|
||||
void kopunch_state::lamp_w(uint8_t data)
|
||||
@ -122,8 +306,8 @@ void kopunch_state::coin_w(uint8_t data)
|
||||
if (!BIT(data, 6))
|
||||
m_maincpu->set_input_line(I8085_RST55_LINE, CLEAR_LINE);
|
||||
|
||||
// if ((data & 0x3f) != 0x3e)
|
||||
// printf("port 34 = %02x ",data);
|
||||
if ((data & 0x3f) != 0x3e)
|
||||
LOGPORT34("port 34 = %02x ", data);
|
||||
}
|
||||
|
||||
/********************************************************
|
||||
@ -141,7 +325,7 @@ static INPUT_PORTS_START( kopunch )
|
||||
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON5 )
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON6 )
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON7 )
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN ) // related to above startbuttons
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN ) // related to above start buttons
|
||||
|
||||
PORT_START("SYSTEM")
|
||||
PORT_BIT( 0x07, IP_ACTIVE_HIGH, IPT_CUSTOM ) // punch strength (high 3 bits)
|
||||
@ -212,8 +396,8 @@ static const gfx_layout bg_layout =
|
||||
};
|
||||
|
||||
static GFXDECODE_START( gfx_kopunch )
|
||||
GFXDECODE_ENTRY( "gfx1", 0, fg_layout, 0, 1 )
|
||||
GFXDECODE_ENTRY( "gfx2", 0, bg_layout, 0, 1 )
|
||||
GFXDECODE_ENTRY( "fgtiles", 0, fg_layout, 0, 1 )
|
||||
GFXDECODE_ENTRY( "bgtiles", 0, bg_layout, 0, 1 )
|
||||
GFXDECODE_END
|
||||
|
||||
|
||||
@ -232,10 +416,10 @@ void kopunch_state::machine_start()
|
||||
|
||||
void kopunch_state::kopunch(machine_config &config)
|
||||
{
|
||||
/* basic machine hardware */
|
||||
I8085A(config, m_maincpu, 4000000); // 4 MHz?
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &kopunch_state::kopunch_map);
|
||||
m_maincpu->set_addrmap(AS_IO, &kopunch_state::kopunch_io_map);
|
||||
// basic machine hardware
|
||||
I8085A(config, m_maincpu, 4'000'000); // 4 MHz?
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &kopunch_state::prg_map);
|
||||
m_maincpu->set_addrmap(AS_IO, &kopunch_state::io_map);
|
||||
|
||||
i8255_device &ppi0(I8255A(config, "ppi8255_0"));
|
||||
// $30 - always $9b (PPI mode 0, ports A & B & C as input)
|
||||
@ -262,20 +446,20 @@ void kopunch_state::kopunch(machine_config &config)
|
||||
ppi3.in_pc_callback().set_ioport("P2");
|
||||
ppi3.out_pc_callback().set(FUNC(kopunch_state::gfxbank_w));
|
||||
|
||||
/* video hardware */
|
||||
// video hardware
|
||||
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
|
||||
screen.set_refresh_hz(60);
|
||||
screen.set_vblank_time(ATTOSECONDS_IN_USEC(0));
|
||||
screen.set_size(32*8, 32*8);
|
||||
screen.set_visarea(0*8, 32*8-1, 2*8, 28*8-1);
|
||||
screen.set_screen_update(FUNC(kopunch_state::screen_update_kopunch));
|
||||
screen.set_screen_update(FUNC(kopunch_state::screen_update));
|
||||
screen.set_palette("palette");
|
||||
screen.screen_vblank().set_inputline(m_maincpu, I8085_RST75_LINE);
|
||||
|
||||
GFXDECODE(config, m_gfxdecode, "palette", gfx_kopunch);
|
||||
PALETTE(config, "palette", FUNC(kopunch_state::kopunch_palette), 8);
|
||||
PALETTE(config, "palette", FUNC(kopunch_state::palette), 8);
|
||||
|
||||
/* sound hardware */
|
||||
// sound hardware
|
||||
// ...
|
||||
}
|
||||
|
||||
@ -292,12 +476,12 @@ ROM_START( kopunch )
|
||||
ROM_LOAD( "epr1105.x", 0x0000, 0x1000, CRC(34ef5e79) SHA1(2827c68f4c902f447a304d3ab0258c7819a0e4ca) )
|
||||
ROM_LOAD( "epr1106.x", 0x1000, 0x1000, CRC(25a5c68b) SHA1(9761418c6f3903f8aaceece658739fe5bf5c0803) )
|
||||
|
||||
ROM_REGION( 0x1800, "gfx1", 0 )
|
||||
ROM_REGION( 0x1800, "fgtiles", 0 )
|
||||
ROM_LOAD( "epr1103", 0x0000, 0x0800, CRC(bae5e054) SHA1(95373123ab64543cdffb7ee9e02d0613c5c494bf) )
|
||||
ROM_LOAD( "epr1104", 0x0800, 0x0800, CRC(7b119a0e) SHA1(454f01355fa9512a7442990cc92da7bc7a8d6b68) )
|
||||
ROM_LOAD( "epr1102", 0x1000, 0x0800, CRC(8a52de96) SHA1(5abdaa83c6bfea81395cb190f5364b72811927ba) )
|
||||
|
||||
ROM_REGION( 0x6000, "gfx2", 0 )
|
||||
ROM_REGION( 0x6000, "bgtiles", 0 )
|
||||
ROM_LOAD( "epr1107", 0x0000, 0x1000, CRC(ca00244d) SHA1(690931ea1bef9d80dcd7bd2ea2462b083c884a89) )
|
||||
ROM_LOAD( "epr1108", 0x1000, 0x1000, CRC(cc17c5ed) SHA1(693df076e16cc3a3dd54f6680691e658da3942fe) )
|
||||
ROM_LOAD( "epr1110", 0x2000, 0x1000, CRC(ae0aff15) SHA1(7f71c94bacdb444e5ed4f917c5a7de17012027a9) )
|
||||
@ -306,10 +490,12 @@ ROM_START( kopunch )
|
||||
ROM_LOAD( "epr1111", 0x5000, 0x1000, CRC(28530ec9) SHA1(1a8782d37128cdb43133fc891cde93d2bdd5476b) )
|
||||
|
||||
ROM_REGION( 0x0060, "proms", 0 )
|
||||
ROM_LOAD( "epr1101", 0x0000, 0x0020, CRC(15600f5d) SHA1(130179f79761cb16316c544e3c689bc10431db30) ) /* palette */
|
||||
ROM_LOAD( "epr1099", 0x0020, 0x0020, CRC(fc58c456) SHA1(f27c3ad669dfdc33bcd7e0481fa01bf34973e816) ) /* unknown */
|
||||
ROM_LOAD( "epr1100", 0x0040, 0x0020, CRC(bedb66b1) SHA1(8e78bb205d900075b761e1baa5f5813174ff28ba) ) /* unknown */
|
||||
ROM_LOAD( "epr1101", 0x0000, 0x0020, CRC(15600f5d) SHA1(130179f79761cb16316c544e3c689bc10431db30) ) // palette
|
||||
ROM_LOAD( "epr1099", 0x0020, 0x0020, CRC(fc58c456) SHA1(f27c3ad669dfdc33bcd7e0481fa01bf34973e816) ) // unknown
|
||||
ROM_LOAD( "epr1100", 0x0040, 0x0020, CRC(bedb66b1) SHA1(8e78bb205d900075b761e1baa5f5813174ff28ba) ) // unknown
|
||||
ROM_END
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
GAME( 1981, kopunch, 0, kopunch, kopunch, kopunch_state, empty_init, ROT270, "Sega", "KO Punch", MACHINE_NO_SOUND | MACHINE_NOT_WORKING | MACHINE_MECHANICAL | MACHINE_SUPPORTS_SAVE )
|
||||
|
@ -1,72 +0,0 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Nicola Salmoria
|
||||
/*************************************************************************
|
||||
|
||||
Sega KO Punch
|
||||
|
||||
*************************************************************************/
|
||||
#ifndef MAME_INCLUDES_KOPUNCH_H
|
||||
#define MAME_INCLUDES_KOPUNCH_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "emupal.h"
|
||||
#include "tilemap.h"
|
||||
|
||||
class kopunch_state : public driver_device
|
||||
{
|
||||
public:
|
||||
kopunch_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: driver_device(mconfig, type, tag)
|
||||
, m_maincpu(*this, "maincpu")
|
||||
, m_gfxdecode(*this, "gfxdecode")
|
||||
, m_vram_fg(*this, "vram_fg")
|
||||
, m_vram_bg(*this, "vram_bg")
|
||||
, m_lamp(*this, "lamp0")
|
||||
{ }
|
||||
|
||||
void kopunch(machine_config &config);
|
||||
|
||||
DECLARE_INPUT_CHANGED_MEMBER(left_coin_inserted);
|
||||
DECLARE_INPUT_CHANGED_MEMBER(right_coin_inserted);
|
||||
|
||||
private:
|
||||
uint8_t sensors1_r();
|
||||
uint8_t sensors2_r();
|
||||
void lamp_w(uint8_t data);
|
||||
void coin_w(uint8_t data);
|
||||
void vram_fg_w(offs_t offset, uint8_t data);
|
||||
void vram_bg_w(offs_t offset, uint8_t data);
|
||||
void scroll_x_w(uint8_t data);
|
||||
void scroll_y_w(uint8_t data);
|
||||
void gfxbank_w(uint8_t data);
|
||||
|
||||
TILE_GET_INFO_MEMBER(get_fg_tile_info);
|
||||
TILE_GET_INFO_MEMBER(get_bg_tile_info);
|
||||
void kopunch_palette(palette_device &palette) const;
|
||||
uint32_t screen_update_kopunch(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
|
||||
void kopunch_io_map(address_map &map);
|
||||
void kopunch_map(address_map &map);
|
||||
|
||||
virtual void machine_start() override;
|
||||
virtual void video_start() override;
|
||||
|
||||
/* devices */
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
|
||||
/* memory pointers */
|
||||
required_shared_ptr<uint8_t> m_vram_fg;
|
||||
required_shared_ptr<uint8_t> m_vram_bg;
|
||||
|
||||
output_finder<> m_lamp;
|
||||
|
||||
/* video-related */
|
||||
tilemap_t *m_bg_tilemap = nullptr;
|
||||
tilemap_t *m_fg_tilemap = nullptr;
|
||||
uint8_t m_gfxbank = 0U;
|
||||
uint8_t m_scrollx = 0U;
|
||||
};
|
||||
|
||||
#endif // MAME_INCLUDES_KOPUNCH_H
|
@ -1,117 +0,0 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Nicola Salmoria
|
||||
/*************************************************************************
|
||||
|
||||
Sega KO Punch
|
||||
|
||||
Functions to emulate the video hardware of the machine.
|
||||
|
||||
*************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "kopunch.h"
|
||||
|
||||
|
||||
void kopunch_state::kopunch_palette(palette_device &palette) const
|
||||
{
|
||||
const uint8_t *color_prom = memregion("proms")->base();
|
||||
|
||||
color_prom += 24; // first 24 colors are black
|
||||
|
||||
for (int i = 0; i < palette.entries(); i++)
|
||||
{
|
||||
int bit0, bit1, bit2;
|
||||
|
||||
// red component
|
||||
bit0 = BIT(*color_prom, 0);
|
||||
bit1 = BIT(*color_prom, 1);
|
||||
bit2 = BIT(*color_prom, 2);
|
||||
int const r = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
|
||||
// green component
|
||||
bit0 = BIT(*color_prom, 3);
|
||||
bit1 = BIT(*color_prom, 4);
|
||||
bit2 = BIT(*color_prom, 5);
|
||||
int const g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
|
||||
// blue component
|
||||
bit0 = 0;
|
||||
bit1 = BIT(*color_prom, 6);
|
||||
bit2 = BIT(*color_prom, 7);
|
||||
int const b = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
|
||||
|
||||
palette.set_pen_color(i, rgb_t(r, g, b));
|
||||
color_prom++;
|
||||
}
|
||||
}
|
||||
|
||||
void kopunch_state::vram_fg_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
m_vram_fg[offset] = data;
|
||||
m_fg_tilemap->mark_tile_dirty(offset);
|
||||
}
|
||||
|
||||
void kopunch_state::vram_bg_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
m_vram_bg[offset] = data;
|
||||
m_bg_tilemap->mark_tile_dirty(offset);
|
||||
}
|
||||
|
||||
void kopunch_state::scroll_x_w(uint8_t data)
|
||||
{
|
||||
m_scrollx = data;
|
||||
m_bg_tilemap->set_scrollx(0, data);
|
||||
}
|
||||
|
||||
void kopunch_state::scroll_y_w(uint8_t data)
|
||||
{
|
||||
m_bg_tilemap->set_scrolly(0, data);
|
||||
}
|
||||
|
||||
void kopunch_state::gfxbank_w(uint8_t data)
|
||||
{
|
||||
// d0-d2: bg gfx bank
|
||||
if (m_gfxbank != (data & 0x07))
|
||||
{
|
||||
m_gfxbank = data & 0x07;
|
||||
m_bg_tilemap->mark_all_dirty();
|
||||
}
|
||||
|
||||
// d3: flip y, other bits: N/C
|
||||
m_bg_tilemap->set_flip((data & 0x08) ? TILEMAP_FLIPY : 0);
|
||||
}
|
||||
|
||||
TILE_GET_INFO_MEMBER(kopunch_state::get_fg_tile_info)
|
||||
{
|
||||
int code = m_vram_fg[tile_index];
|
||||
|
||||
tileinfo.set(0, code, 0, 0);
|
||||
}
|
||||
|
||||
TILE_GET_INFO_MEMBER(kopunch_state::get_bg_tile_info)
|
||||
{
|
||||
// note: highest bit is unused
|
||||
int code = (m_vram_bg[tile_index] & 0x7f) | m_gfxbank << 7;
|
||||
|
||||
tileinfo.set(1, code, 0, 0);
|
||||
}
|
||||
|
||||
void kopunch_state::video_start()
|
||||
{
|
||||
m_fg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(kopunch_state::get_fg_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 32, 32);
|
||||
m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(kopunch_state::get_bg_tile_info)), TILEMAP_SCAN_ROWS, 16, 16, 16, 16);
|
||||
|
||||
m_fg_tilemap->set_transparent_pen(0);
|
||||
}
|
||||
|
||||
uint32_t kopunch_state::screen_update_kopunch(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
bitmap.fill(0, cliprect);
|
||||
|
||||
// background does not wrap around horizontally
|
||||
rectangle bg_clip = cliprect;
|
||||
bg_clip.max_x = m_scrollx ^ 0xff;
|
||||
|
||||
m_bg_tilemap->draw(screen, bitmap, bg_clip, 0, 0);
|
||||
m_fg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Frank Palazzolo
|
||||
// copyright-holders: Frank Palazzolo
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
Sega "Space Tactics" Driver
|
||||
@ -43,12 +44,531 @@ Verify Color PROM resistor values (Last 8 colors)
|
||||
****************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "stactics.h"
|
||||
|
||||
#include "stactics.lh"
|
||||
|
||||
#include "cpu/i8085/i8085.h"
|
||||
#include "machine/74259.h"
|
||||
|
||||
#include "emupal.h"
|
||||
#include "screen.h"
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
class stactics_state : public driver_device
|
||||
{
|
||||
public:
|
||||
stactics_state(const machine_config &mconfig, device_type type, const char *tag) :
|
||||
driver_device(mconfig, type, tag),
|
||||
m_maincpu(*this, "maincpu"),
|
||||
m_outlatch(*this, "outlatch"),
|
||||
m_display_buffer(*this, "display_buffer"),
|
||||
m_videoram_b(*this, "videoram_b"),
|
||||
m_videoram_d(*this, "videoram_d"),
|
||||
m_videoram_e(*this, "videoram_e"),
|
||||
m_videoram_f(*this, "videoram_f"),
|
||||
m_beam_region(*this, "beam"),
|
||||
m_base_lamps(*this, "base_lamp%u", 0U),
|
||||
m_beam_leds_left(*this, "beam_led_left%u", 0U),
|
||||
m_beam_leds_right(*this, "beam_led_right%u", 0U),
|
||||
m_score_digits(*this, "digit%u", 0U),
|
||||
m_credit_leds(*this, "credit_led%u", 0U),
|
||||
m_barrier_leds(*this, "barrier_led%u", 0U),
|
||||
m_round_leds(*this, "round_led%u", 0U),
|
||||
m_barrier_lamp(*this, "barrier_lamp"),
|
||||
m_start_lamp(*this, "start_lamp"),
|
||||
m_sight_led(*this, "sight_led"),
|
||||
m_in3(*this, "IN3"),
|
||||
m_fake(*this, "FAKE")
|
||||
{ }
|
||||
|
||||
void stactics(machine_config &config);
|
||||
|
||||
DECLARE_READ_LINE_MEMBER(frame_count_d3_r);
|
||||
DECLARE_READ_LINE_MEMBER(shot_standby_r);
|
||||
DECLARE_READ_LINE_MEMBER(not_shot_arrive_r);
|
||||
DECLARE_READ_LINE_MEMBER(motor_not_ready_r);
|
||||
DECLARE_CUSTOM_INPUT_MEMBER(get_rng);
|
||||
|
||||
protected:
|
||||
virtual void machine_start() override;
|
||||
virtual void video_start() override;
|
||||
|
||||
private:
|
||||
uint8_t vert_pos_r();
|
||||
uint8_t horiz_pos_r();
|
||||
template <uint8_t Which> DECLARE_WRITE_LINE_MEMBER(coin_lockout_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(palette_bank_w);
|
||||
void scroll_ram_w(offs_t offset, uint8_t data);
|
||||
void speed_latch_w(uint8_t data);
|
||||
void shot_trigger_w(uint8_t data);
|
||||
void shot_flag_clear_w(uint8_t data);
|
||||
DECLARE_WRITE_LINE_MEMBER(motor_w);
|
||||
|
||||
INTERRUPT_GEN_MEMBER(interrupt);
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER(barrier_lamp_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(start_lamp_w);
|
||||
template <unsigned N> DECLARE_WRITE_LINE_MEMBER(base_lamp_w) { m_base_lamps[N] = state; }
|
||||
|
||||
void palette(palette_device &palette) const;
|
||||
|
||||
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
void update_beam();
|
||||
inline int get_pixel_on_plane(uint8_t *videoram, uint8_t y, uint8_t x, uint8_t y_scroll);
|
||||
void draw_background(bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
template <unsigned N> void set_indicator_leds(unsigned offset, output_finder<N> &outputs, int base_index);
|
||||
void update_artwork();
|
||||
void move_motor();
|
||||
|
||||
void main_map(address_map &map);
|
||||
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<ls259_device> m_outlatch;
|
||||
|
||||
required_shared_ptr<uint8_t> m_display_buffer;
|
||||
required_shared_ptr<uint8_t> m_videoram_b;
|
||||
required_shared_ptr<uint8_t> m_videoram_d;
|
||||
required_shared_ptr<uint8_t> m_videoram_e;
|
||||
required_shared_ptr<uint8_t> m_videoram_f;
|
||||
required_region_ptr<uint8_t> m_beam_region;
|
||||
|
||||
output_finder<5> m_base_lamps;
|
||||
output_finder<0x40> m_beam_leds_left;
|
||||
output_finder<0x40> m_beam_leds_right;
|
||||
output_finder<6> m_score_digits;
|
||||
output_finder<8> m_credit_leds;
|
||||
output_finder<12> m_barrier_leds;
|
||||
output_finder<16> m_round_leds;
|
||||
output_finder<> m_barrier_lamp;
|
||||
output_finder<> m_start_lamp;
|
||||
output_finder<> m_sight_led;
|
||||
|
||||
required_ioport m_in3;
|
||||
required_ioport m_fake;
|
||||
|
||||
// machine state
|
||||
int32_t m_vert_pos = 0;
|
||||
int32_t m_horiz_pos = 0;
|
||||
bool m_motor_on = false;
|
||||
|
||||
// video state
|
||||
uint8_t m_y_scroll_d = 0;
|
||||
uint8_t m_y_scroll_e = 0;
|
||||
uint8_t m_y_scroll_f = 0;
|
||||
uint8_t m_frame_count = 0;
|
||||
uint8_t m_shot_standby = 0;
|
||||
uint8_t m_shot_arrive = 0;
|
||||
uint16_t m_beam_state = 0;
|
||||
uint16_t m_old_beam_state = 0;
|
||||
uint16_t m_beam_states_per_frame = 0;
|
||||
uint8_t m_palette_bank = 0;
|
||||
};
|
||||
|
||||
|
||||
// video
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
The Video system used in Space Tactics is unusual.
|
||||
Here are my notes on how the video system works:
|
||||
|
||||
There are 4, 4K pages of Video RAM. (B,D,E & F)
|
||||
|
||||
The first 1K of each VRAM page contains the following:
|
||||
0 0 V V V V V H H H H H offset value for each 8x8 bitmap
|
||||
(v-tile) (h-tile)
|
||||
|
||||
The offset values are used to generate an access into the
|
||||
last 2K of the VRAM page:
|
||||
1 D D D D D D D D V V V here we find 8x8 character data
|
||||
(offset) (line)
|
||||
|
||||
In addition, in Page B, the upper nibble of the offset is
|
||||
also used to select the color palette for the tile.
|
||||
|
||||
Page B, D, E, and F all work similarly, except that pages
|
||||
D, E, and F can be offset from Page B by a given
|
||||
number of scanlines, based on the contents of the offset
|
||||
RAM
|
||||
|
||||
The offset RAM is addressed in this format:
|
||||
1 0 0 0 P P P V V V V V V V V V
|
||||
(Page) (scanline)
|
||||
Page 4=D, 5=E, 6=F
|
||||
|
||||
Page D, E, and F are drawn offset from the top of the screen,
|
||||
starting on the first scanline which contains a 1 in the
|
||||
appropriate memory location
|
||||
|
||||
---
|
||||
|
||||
The composited monitor image is seen in a mirror. It appears
|
||||
to move when the player moves the handle, due to motors which
|
||||
tilt the mirror up and down, and the monitor left and right.
|
||||
|
||||
---
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* Palette
|
||||
*
|
||||
*************************************/
|
||||
|
||||
void stactics_state::palette(palette_device &palette) const
|
||||
{
|
||||
uint8_t const *const color_prom = memregion("proms")->base();
|
||||
|
||||
for (int i = 0; i < 0x400; i++)
|
||||
{
|
||||
int const bit0 = BIT(color_prom[i], 0);
|
||||
int const bit1 = BIT(color_prom[i], 1);
|
||||
int const bit2 = BIT(color_prom[i], 2);
|
||||
int const bit3 = BIT(color_prom[i], 3);
|
||||
|
||||
// red component
|
||||
int const r = 0xff * bit0;
|
||||
|
||||
// green component
|
||||
int const g = 0xff * bit1 - 0xcc * bit3;
|
||||
|
||||
// blue component
|
||||
int const b = 0xff * bit2;
|
||||
|
||||
palette.set_pen_color(i, rgb_t(r, g, b));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
WRITE_LINE_MEMBER(stactics_state::palette_bank_w)
|
||||
{
|
||||
m_palette_bank = m_outlatch->q6_r() | (m_outlatch->q7_r() << 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* Scrolling
|
||||
*
|
||||
*************************************/
|
||||
|
||||
void stactics_state::scroll_ram_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
if (data & 0x01)
|
||||
{
|
||||
switch (offset >> 8)
|
||||
{
|
||||
case 4: m_y_scroll_d = offset & 0xff; break;
|
||||
case 5: m_y_scroll_e = offset & 0xff; break;
|
||||
case 6: m_y_scroll_f = offset & 0xff; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* Frane counter
|
||||
*
|
||||
*************************************/
|
||||
|
||||
READ_LINE_MEMBER(stactics_state::frame_count_d3_r)
|
||||
{
|
||||
return (m_frame_count >> 3) & 0x01;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* Beam handling
|
||||
*
|
||||
*************************************/
|
||||
|
||||
void stactics_state::speed_latch_w(uint8_t data)
|
||||
{
|
||||
/* This writes to a shift register which is clocked by
|
||||
a 555 oscillator. This value determines the speed of
|
||||
the LED fire beams as follows:
|
||||
|
||||
555_freq / bits_in_SR * edges_in_SR / states_in_PR67 / frame_rate
|
||||
= num_led_states_per_frame
|
||||
36439 / 8 * x / 32 / 60 ~= 19/8*x
|
||||
|
||||
Here, we will count the number of rising edges in the shift register */
|
||||
|
||||
int num_rising_edges = 0;
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
if ((((data >> i) & 0x01) == 1) && (((data >> ((i + 1) % 8)) & 0x01) == 0))
|
||||
num_rising_edges++;
|
||||
}
|
||||
|
||||
m_beam_states_per_frame = num_rising_edges * 19 / 8;
|
||||
}
|
||||
|
||||
|
||||
void stactics_state::shot_trigger_w(uint8_t data)
|
||||
{
|
||||
m_shot_standby = 0;
|
||||
}
|
||||
|
||||
|
||||
void stactics_state::shot_flag_clear_w(uint8_t data)
|
||||
{
|
||||
m_shot_arrive = 0;
|
||||
}
|
||||
|
||||
|
||||
READ_LINE_MEMBER(stactics_state::shot_standby_r)
|
||||
{
|
||||
return m_shot_standby;
|
||||
}
|
||||
|
||||
|
||||
READ_LINE_MEMBER(stactics_state::not_shot_arrive_r)
|
||||
{
|
||||
return !m_shot_arrive;
|
||||
}
|
||||
|
||||
|
||||
void stactics_state::update_beam()
|
||||
{
|
||||
// first, update the firebeam state
|
||||
m_old_beam_state = m_beam_state;
|
||||
if (m_shot_standby == 0)
|
||||
m_beam_state = m_beam_state + m_beam_states_per_frame;
|
||||
|
||||
/* These are thresholds for the two shots from the LED fire ROM
|
||||
(Note: There are two more for sound triggers,
|
||||
whenever that gets implemented) */
|
||||
if ((m_old_beam_state < 0x8b) & (m_beam_state >= 0x8b))
|
||||
m_shot_arrive = 1;
|
||||
|
||||
if ((m_old_beam_state < 0xca) & (m_beam_state >= 0xca))
|
||||
m_shot_arrive = 1;
|
||||
|
||||
if (m_beam_state >= 0x100)
|
||||
{
|
||||
m_beam_state = 0;
|
||||
m_shot_standby = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* Video drawing
|
||||
*
|
||||
*************************************/
|
||||
|
||||
inline int stactics_state::get_pixel_on_plane(uint8_t *videoram, uint8_t y, uint8_t x, uint8_t y_scroll)
|
||||
{
|
||||
// compute effective row
|
||||
y = y - y_scroll;
|
||||
|
||||
// get the character code at the given pixel
|
||||
uint8_t const code = videoram[((y >> 3) << 5) | (x >> 3)];
|
||||
|
||||
// get the gfx byte
|
||||
uint8_t const gfx = videoram[0x800 | (code << 3) | (y & 0x07)];
|
||||
|
||||
// return the appropriate pixel within the byte
|
||||
return (gfx >> (~x & 0x07)) & 0x01;
|
||||
}
|
||||
|
||||
|
||||
void stactics_state::draw_background(bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
bitmap.fill(0, cliprect);
|
||||
|
||||
// for every row
|
||||
for (int y = 0; y < 0x100; y++)
|
||||
{
|
||||
// for every pixel on the row
|
||||
for (int x = 0; x < 0x100; x++)
|
||||
{
|
||||
// get the pixels for the four planes
|
||||
int const pixel_b = get_pixel_on_plane(m_videoram_b, y, x, 0);
|
||||
int const pixel_d = get_pixel_on_plane(m_videoram_d, y, x, m_y_scroll_d);
|
||||
int const pixel_e = get_pixel_on_plane(m_videoram_e, y, x, m_y_scroll_e);
|
||||
int const pixel_f = get_pixel_on_plane(m_videoram_f, y, x, m_y_scroll_f);
|
||||
|
||||
// get the color for this pixel
|
||||
uint8_t const color = m_videoram_b[((y >> 3) << 5) | (x >> 3)] >> 4;
|
||||
|
||||
// assemble the pen index
|
||||
int const pen = color |
|
||||
(pixel_b << 4) |
|
||||
(pixel_f << 5) |
|
||||
(pixel_e << 6) |
|
||||
(pixel_d << 7) |
|
||||
(m_palette_bank << 8);
|
||||
|
||||
/* compute the effective pixel coordinate after adjusting for the
|
||||
mirror movement - this is mechanical on the real machine */
|
||||
int const sy = y + m_vert_pos;
|
||||
int const sx = x - m_horiz_pos;
|
||||
|
||||
// plot if visible
|
||||
if ((sy >= 0) && (sy < 0x100) && (sx >= 0) && (sx < 0x100))
|
||||
bitmap.pix(sy, sx) = pen;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* Non-video artwork
|
||||
*
|
||||
*************************************/
|
||||
|
||||
// from 7448 datasheet
|
||||
static constexpr int to_7seg[0x10] =
|
||||
{
|
||||
0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7c, 0x07,
|
||||
0x7f, 0x67, 0x58, 0x4c, 0x62, 0x69, 0x78, 0x00
|
||||
};
|
||||
|
||||
|
||||
template <unsigned N> void stactics_state::set_indicator_leds(unsigned offset, output_finder<N> &outputs, int base_index)
|
||||
{
|
||||
// decode the data
|
||||
int const data = to_7seg[~m_display_buffer[offset] & 0x0f];
|
||||
|
||||
// set the 4 LEDs
|
||||
outputs[base_index + 0] = BIT(data, 2);
|
||||
outputs[base_index + 1] = BIT(data, 6);
|
||||
outputs[base_index + 2] = BIT(data, 5);
|
||||
outputs[base_index + 3] = BIT(data, 4);
|
||||
}
|
||||
|
||||
|
||||
WRITE_LINE_MEMBER(stactics_state::barrier_lamp_w)
|
||||
{
|
||||
// this needs to flash on/off, not implemented
|
||||
m_barrier_lamp = state;
|
||||
}
|
||||
|
||||
|
||||
WRITE_LINE_MEMBER(stactics_state::start_lamp_w)
|
||||
{
|
||||
m_start_lamp = state;
|
||||
}
|
||||
|
||||
|
||||
void stactics_state::update_artwork()
|
||||
{
|
||||
// laser beam - loop for each LED
|
||||
for (int i = 0; i < 0x40; i++)
|
||||
{
|
||||
offs_t const beam_data_offs = ((i & 0x08) << 7) | ((i & 0x30) << 4) | m_beam_state;
|
||||
uint8_t const beam_data = m_beam_region[beam_data_offs];
|
||||
int const on = BIT(beam_data, i & 0x07);
|
||||
|
||||
m_beam_leds_left[i] = on;
|
||||
m_beam_leds_right[i] = on;
|
||||
}
|
||||
|
||||
// sight LED
|
||||
m_sight_led = m_motor_on;
|
||||
|
||||
// score display
|
||||
for (int i = 0x01; i < 0x07; i++)
|
||||
m_score_digits[i - 1] = to_7seg[~m_display_buffer[i] & 0x0f];
|
||||
|
||||
// credits indicator
|
||||
set_indicator_leds(0x07, m_credit_leds, 0x00);
|
||||
set_indicator_leds(0x08, m_credit_leds, 0x04);
|
||||
|
||||
// barriers indicator
|
||||
set_indicator_leds(0x09, m_barrier_leds, 0x00);
|
||||
set_indicator_leds(0x0a, m_barrier_leds, 0x04);
|
||||
set_indicator_leds(0x0b, m_barrier_leds, 0x08);
|
||||
|
||||
// rounds indicator
|
||||
set_indicator_leds(0x0c, m_round_leds, 0x00);
|
||||
set_indicator_leds(0x0d, m_round_leds, 0x04);
|
||||
set_indicator_leds(0x0e, m_round_leds, 0x08);
|
||||
set_indicator_leds(0x0f, m_round_leds, 0x0c);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* Start
|
||||
*
|
||||
*************************************/
|
||||
|
||||
void stactics_state::video_start()
|
||||
{
|
||||
m_base_lamps.resolve();
|
||||
m_beam_leds_left.resolve();
|
||||
m_beam_leds_right.resolve();
|
||||
m_score_digits.resolve();
|
||||
m_credit_leds.resolve();
|
||||
m_barrier_leds.resolve();
|
||||
m_round_leds.resolve();
|
||||
m_barrier_lamp.resolve();
|
||||
m_start_lamp.resolve();
|
||||
m_sight_led.resolve();
|
||||
|
||||
m_y_scroll_d = 0;
|
||||
m_y_scroll_e = 0;
|
||||
m_y_scroll_f = 0;
|
||||
|
||||
m_frame_count = 0;
|
||||
m_shot_standby = 1;
|
||||
m_shot_arrive = 0;
|
||||
m_beam_state = 0;
|
||||
m_old_beam_state = 0;
|
||||
|
||||
m_palette_bank = 0;
|
||||
|
||||
save_item(NAME(m_y_scroll_d));
|
||||
save_item(NAME(m_y_scroll_e));
|
||||
save_item(NAME(m_y_scroll_f));
|
||||
save_item(NAME(m_frame_count));
|
||||
save_item(NAME(m_shot_standby));
|
||||
save_item(NAME(m_shot_arrive));
|
||||
save_item(NAME(m_beam_state));
|
||||
save_item(NAME(m_old_beam_state));
|
||||
save_item(NAME(m_beam_states_per_frame));
|
||||
save_item(NAME(m_palette_bank));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* Update
|
||||
*
|
||||
*************************************/
|
||||
|
||||
uint32_t stactics_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
update_beam();
|
||||
draw_background(bitmap, cliprect);
|
||||
update_artwork();
|
||||
|
||||
m_frame_count = (m_frame_count + 1) & 0x0f;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// machine
|
||||
|
||||
/*************************************
|
||||
*
|
||||
@ -89,24 +609,24 @@ void stactics_state::move_motor()
|
||||
const int in3 = m_in3->read();
|
||||
const int in4 = m_fake->read();
|
||||
|
||||
/* up */
|
||||
// up
|
||||
if (!(in4 & 0x01) && m_vert_pos > -128)
|
||||
m_vert_pos--;
|
||||
|
||||
/* down */
|
||||
// down
|
||||
if (!(in4 & 0x02) && m_vert_pos < 127)
|
||||
m_vert_pos++;
|
||||
|
||||
/* left */
|
||||
// left
|
||||
if (!(in3 & 0x20) && m_horiz_pos < 127)
|
||||
m_horiz_pos++;
|
||||
|
||||
/* right */
|
||||
// right
|
||||
if (!(in3 & 0x40) && m_horiz_pos > -128)
|
||||
m_horiz_pos--;
|
||||
}
|
||||
|
||||
/* monitor motor under self-centering control */
|
||||
// monitor motor under self-centering control
|
||||
else
|
||||
{
|
||||
if (m_horiz_pos > 0)
|
||||
@ -131,7 +651,7 @@ void stactics_state::move_motor()
|
||||
|
||||
CUSTOM_INPUT_MEMBER(stactics_state::get_rng)
|
||||
{
|
||||
/* this is a 555 timer, but cannot read one of the resistor values */
|
||||
// this is a 555 timer, but cannot read one of the resistor values
|
||||
return machine().rand() & 0x07;
|
||||
}
|
||||
|
||||
@ -143,15 +663,10 @@ CUSTOM_INPUT_MEMBER(stactics_state::get_rng)
|
||||
*
|
||||
*************************************/
|
||||
|
||||
WRITE_LINE_MEMBER(stactics_state::coin_lockout_1_w)
|
||||
template <uint8_t Which>
|
||||
WRITE_LINE_MEMBER(stactics_state::coin_lockout_w)
|
||||
{
|
||||
machine().bookkeeping().coin_lockout_w(0, !state);
|
||||
}
|
||||
|
||||
|
||||
WRITE_LINE_MEMBER(stactics_state::coin_lockout_2_w)
|
||||
{
|
||||
machine().bookkeeping().coin_lockout_w(1, !state);
|
||||
machine().bookkeeping().coin_lockout_w(Which, !state);
|
||||
}
|
||||
|
||||
|
||||
@ -189,20 +704,20 @@ void stactics_state::main_map(address_map &map)
|
||||
map(0x6030, 0x6030).mirror(0x0f0f).w(FUNC(stactics_state::speed_latch_w));
|
||||
map(0x6040, 0x6040).mirror(0x0f0f).w(FUNC(stactics_state::shot_trigger_w));
|
||||
map(0x6050, 0x6050).mirror(0x0f0f).w(FUNC(stactics_state::shot_flag_clear_w));
|
||||
map(0x6060, 0x606f).mirror(0x0f00).writeonly().share("display_buffer");
|
||||
map(0x6060, 0x606f).mirror(0x0f00).writeonly().share(m_display_buffer);
|
||||
map(0x6070, 0x609f).mirror(0x0f00).nopw();
|
||||
/* map(0x60a0, 0x60ef).mirror(0x0f00).w(FUNC(stactics_state::sound2_w)); */
|
||||
// map(0x60a0, 0x60ef).mirror(0x0f00).w(FUNC(stactics_state::sound2_w));
|
||||
map(0x60f0, 0x60ff).mirror(0x0f00).nopw();
|
||||
map(0x7000, 0x7000).mirror(0x0fff).portr("IN2");
|
||||
map(0x8000, 0x8000).mirror(0x0fff).portr("IN3");
|
||||
map(0x8000, 0x87ff).mirror(0x0800).w(FUNC(stactics_state::scroll_ram_w));
|
||||
map(0x9000, 0x9000).mirror(0x0fff).r(FUNC(stactics_state::vert_pos_r));
|
||||
map(0xa000, 0xa000).mirror(0x0fff).r(FUNC(stactics_state::horiz_pos_r));
|
||||
map(0xb000, 0xbfff).ram().share("videoram_b");
|
||||
map(0xb000, 0xbfff).ram().share(m_videoram_b);
|
||||
map(0xc000, 0xcfff).noprw();
|
||||
map(0xd000, 0xdfff).ram().share("videoram_d");
|
||||
map(0xe000, 0xefff).ram().share("videoram_e");
|
||||
map(0xf000, 0xffff).ram().share("videoram_f");
|
||||
map(0xd000, 0xdfff).ram().share(m_videoram_d);
|
||||
map(0xe000, 0xefff).ram().share(m_videoram_e);
|
||||
map(0xf000, 0xffff).ram().share(m_videoram_f);
|
||||
}
|
||||
|
||||
|
||||
@ -214,7 +729,7 @@ void stactics_state::main_map(address_map &map)
|
||||
*************************************/
|
||||
|
||||
static INPUT_PORTS_START( stactics )
|
||||
PORT_START("IN0") /* IN0 */
|
||||
PORT_START("IN0")
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON7 )
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON6 )
|
||||
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON5 )
|
||||
@ -224,7 +739,7 @@ static INPUT_PORTS_START( stactics )
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON2 )
|
||||
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_READ_LINE_MEMBER(stactics_state, motor_not_ready_r)
|
||||
|
||||
PORT_START("IN1") /* IN1 */
|
||||
PORT_START("IN1")
|
||||
PORT_DIPNAME( 0x07, 0x07, DEF_STR( Coin_B ) )
|
||||
PORT_DIPSETTING( 0x01, DEF_STR( 4C_1C ) )
|
||||
PORT_DIPSETTING( 0x05, DEF_STR( 2C_1C ) )
|
||||
@ -250,7 +765,7 @@ static INPUT_PORTS_START( stactics )
|
||||
PORT_DIPSETTING( 0x80, DEF_STR( Off ) )
|
||||
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
|
||||
|
||||
PORT_START("IN2") /* IN2 */
|
||||
PORT_START("IN2")
|
||||
PORT_BIT( 0x07, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(stactics_state, get_rng)
|
||||
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_READ_LINE_MEMBER(stactics_state, frame_count_d3_r)
|
||||
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_COIN1 )
|
||||
@ -260,7 +775,7 @@ static INPUT_PORTS_START( stactics )
|
||||
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
|
||||
PORT_SERVICE( 0x80, IP_ACTIVE_LOW )
|
||||
|
||||
PORT_START("IN3") /* IN3 */
|
||||
PORT_START("IN3")
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 )
|
||||
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_READ_LINE_MEMBER(stactics_state, shot_standby_r)
|
||||
PORT_DIPNAME( 0x04, 0x04, "Number of Barriers" )
|
||||
@ -276,7 +791,7 @@ static INPUT_PORTS_START( stactics )
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY
|
||||
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_READ_LINE_MEMBER(stactics_state, not_shot_arrive_r)
|
||||
|
||||
PORT_START("FAKE") /* FAKE */
|
||||
PORT_START("FAKE")
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY
|
||||
INPUT_PORTS_END
|
||||
@ -310,14 +825,14 @@ void stactics_state::machine_start()
|
||||
|
||||
void stactics_state::stactics(machine_config &config)
|
||||
{
|
||||
/* basic machine hardware */
|
||||
// basic machine hardware
|
||||
I8080(config, m_maincpu, 15.46848_MHz_XTAL / 8); // divider not verified
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &stactics_state::main_map);
|
||||
m_maincpu->set_vblank_int("screen", FUNC(stactics_state::interrupt));
|
||||
|
||||
LS259(config, m_outlatch); // 50
|
||||
m_outlatch->q_out_cb<0>().set(FUNC(stactics_state::coin_lockout_1_w)); // COIN REJECT 1
|
||||
m_outlatch->q_out_cb<1>().set(FUNC(stactics_state::coin_lockout_2_w)); // COIN REJECT 2
|
||||
m_outlatch->q_out_cb<0>().set(FUNC(stactics_state::coin_lockout_w<0>)); // COIN REJECT 1
|
||||
m_outlatch->q_out_cb<1>().set(FUNC(stactics_state::coin_lockout_w<1>)); // COIN REJECT 2
|
||||
m_outlatch->q_out_cb<6>().set(FUNC(stactics_state::palette_bank_w)); // FLM COL 0
|
||||
m_outlatch->q_out_cb<7>().set(FUNC(stactics_state::palette_bank_w)); // FLM COL 1
|
||||
|
||||
@ -340,10 +855,16 @@ void stactics_state::stactics(machine_config &config)
|
||||
lamplatch.q_out_cb<5>().set(FUNC(stactics_state::start_lamp_w));
|
||||
lamplatch.q_out_cb<6>().set(FUNC(stactics_state::barrier_lamp_w));
|
||||
|
||||
/* video hardware */
|
||||
stactics_video(config);
|
||||
// video hardware
|
||||
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
|
||||
screen.set_video_attributes(VIDEO_ALWAYS_UPDATE);
|
||||
screen.set_raw(15.46848_MHz_XTAL / 3, 328, 0, 256, 262, 0, 232);
|
||||
screen.set_screen_update(FUNC(stactics_state::screen_update));
|
||||
screen.set_palette("palette");
|
||||
|
||||
/* audio hardware */
|
||||
PALETTE(config, "palette", FUNC(stactics_state::palette), 0x400);
|
||||
|
||||
// audio hardware
|
||||
}
|
||||
|
||||
|
||||
@ -364,16 +885,17 @@ ROM_START( stactics )
|
||||
ROM_LOAD( "epr-223x", 0x2800, 0x0800, CRC(7fef0940) SHA1(5b2af55f75ef0130f9202b6a916a96dbd601fcfa) )
|
||||
|
||||
ROM_REGION( 0x1040, "proms", 0 )
|
||||
ROM_LOAD( "pr54", 0x0000, 0x0800, CRC(9640bd6e) SHA1(dd12952a6591f2056ac1b5688dca0a3a2ef69f2d) ) /* color/priority PROM */
|
||||
ROM_LOAD( "pr55", 0x0800, 0x0800, CRC(f162673b) SHA1(83743780b6c1f8014df24fa0650000b7cb137d92) ) /* timing PROM (unused) */
|
||||
ROM_LOAD( "pr65", 0x1000, 0x0020, CRC(a1506b9d) SHA1(037c3db2ea40eca459e8acba9d1506dd28d72d10) ) /* timing PROM (unused) */
|
||||
ROM_LOAD( "pr66", 0x1020, 0x0020, CRC(78dcf300) SHA1(37034cc0cfa4a8ec47937a2a34b77ec56b387a9b) ) /* timing PROM (unused) */
|
||||
ROM_LOAD( "pr54", 0x0000, 0x0800, CRC(9640bd6e) SHA1(dd12952a6591f2056ac1b5688dca0a3a2ef69f2d) ) // color/priority PROM
|
||||
ROM_LOAD( "pr55", 0x0800, 0x0800, CRC(f162673b) SHA1(83743780b6c1f8014df24fa0650000b7cb137d92) ) // timing PROM (unused)
|
||||
ROM_LOAD( "pr65", 0x1000, 0x0020, CRC(a1506b9d) SHA1(037c3db2ea40eca459e8acba9d1506dd28d72d10) ) // timing PROM (unused)
|
||||
ROM_LOAD( "pr66", 0x1020, 0x0020, CRC(78dcf300) SHA1(37034cc0cfa4a8ec47937a2a34b77ec56b387a9b) ) // timing PROM (unused)
|
||||
|
||||
ROM_REGION( 0x0820, "user1", 0 )
|
||||
ROM_LOAD( "epr-217", 0x0000, 0x0800, CRC(38259f5f) SHA1(1f4182ffc2d78fca22711526bb2ae2cfe040173c) ) /* LED fire beam data */
|
||||
ROM_LOAD( "pr67", 0x0800, 0x0020, CRC(b27874e7) SHA1(c24bc78c4b2ae01aaed5d994ce2e7c5e0f2eece8) ) /* LED timing ROM (unused) */
|
||||
ROM_REGION( 0x0820, "beam", 0 )
|
||||
ROM_LOAD( "epr-217", 0x0000, 0x0800, CRC(38259f5f) SHA1(1f4182ffc2d78fca22711526bb2ae2cfe040173c) ) // LED fire beam data
|
||||
ROM_LOAD( "pr67", 0x0800, 0x0020, CRC(b27874e7) SHA1(c24bc78c4b2ae01aaed5d994ce2e7c5e0f2eece8) ) // LED timing ROM (unused)
|
||||
ROM_END
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
/*************************************
|
||||
|
@ -1,130 +0,0 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Frank Palazzolo
|
||||
/****************************************************************************
|
||||
|
||||
Sega "Space Tactics" Driver
|
||||
|
||||
Frank Palazzolo (palazzol@home.com)
|
||||
|
||||
****************************************************************************/
|
||||
#ifndef MAME_INCLUDES_STACTICS_H
|
||||
#define MAME_INCLUDES_STACTICS_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "machine/74259.h"
|
||||
#include "emupal.h"
|
||||
|
||||
class stactics_state : public driver_device
|
||||
{
|
||||
public:
|
||||
stactics_state(const machine_config &mconfig, device_type type, const char *tag) :
|
||||
driver_device(mconfig, type, tag),
|
||||
m_maincpu(*this, "maincpu"),
|
||||
m_outlatch(*this, "outlatch"),
|
||||
m_display_buffer(*this, "display_buffer"),
|
||||
m_videoram_b(*this, "videoram_b"),
|
||||
m_videoram_d(*this, "videoram_d"),
|
||||
m_videoram_e(*this, "videoram_e"),
|
||||
m_videoram_f(*this, "videoram_f"),
|
||||
m_base_lamps(*this, "base_lamp%u", 0U),
|
||||
m_beam_leds_left(*this, "beam_led_left%u", 0U),
|
||||
m_beam_leds_right(*this, "beam_led_right%u", 0U),
|
||||
m_score_digits(*this, "digit%u", 0U),
|
||||
m_credit_leds(*this, "credit_led%u", 0U),
|
||||
m_barrier_leds(*this, "barrier_led%u", 0U),
|
||||
m_round_leds(*this, "round_led%u", 0U),
|
||||
m_barrier_lamp(*this, "barrier_lamp"),
|
||||
m_start_lamp(*this, "start_lamp"),
|
||||
m_sight_led(*this, "sight_led"),
|
||||
m_in3(*this, "IN3"),
|
||||
m_fake(*this, "FAKE")
|
||||
{ }
|
||||
|
||||
void stactics(machine_config &config);
|
||||
|
||||
DECLARE_READ_LINE_MEMBER(frame_count_d3_r);
|
||||
DECLARE_READ_LINE_MEMBER(shot_standby_r);
|
||||
DECLARE_READ_LINE_MEMBER(not_shot_arrive_r);
|
||||
DECLARE_READ_LINE_MEMBER(motor_not_ready_r);
|
||||
DECLARE_CUSTOM_INPUT_MEMBER(get_rng);
|
||||
|
||||
private:
|
||||
uint8_t vert_pos_r();
|
||||
uint8_t horiz_pos_r();
|
||||
DECLARE_WRITE_LINE_MEMBER(coin_lockout_1_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(coin_lockout_2_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(palette_bank_w);
|
||||
void scroll_ram_w(offs_t offset, uint8_t data);
|
||||
void speed_latch_w(uint8_t data);
|
||||
void shot_trigger_w(uint8_t data);
|
||||
void shot_flag_clear_w(uint8_t data);
|
||||
DECLARE_WRITE_LINE_MEMBER(motor_w);
|
||||
|
||||
INTERRUPT_GEN_MEMBER(interrupt);
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER(barrier_lamp_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(start_lamp_w);
|
||||
template <unsigned N> DECLARE_WRITE_LINE_MEMBER(base_lamp_w) { m_base_lamps[N] = state; }
|
||||
DECLARE_WRITE_LINE_MEMBER(base_2_lamp_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(base_3_lamp_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(base_4_lamp_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(base_5_lamp_w);
|
||||
|
||||
virtual void machine_start() override;
|
||||
virtual void video_start() override;
|
||||
void stactics_palette(palette_device &palette) const;
|
||||
|
||||
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
void update_beam();
|
||||
inline int get_pixel_on_plane(uint8_t *videoram, uint8_t y, uint8_t x, uint8_t y_scroll);
|
||||
void draw_background(bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
template <unsigned N> void set_indicator_leds(unsigned offset, output_finder<N> &outputs, int base_index);
|
||||
void update_artwork();
|
||||
void move_motor();
|
||||
|
||||
void stactics_video(machine_config &config);
|
||||
void main_map(address_map &map);
|
||||
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<ls259_device> m_outlatch;
|
||||
|
||||
required_shared_ptr<uint8_t> m_display_buffer;
|
||||
required_shared_ptr<uint8_t> m_videoram_b;
|
||||
required_shared_ptr<uint8_t> m_videoram_d;
|
||||
required_shared_ptr<uint8_t> m_videoram_e;
|
||||
required_shared_ptr<uint8_t> m_videoram_f;
|
||||
|
||||
output_finder<5> m_base_lamps;
|
||||
output_finder<0x40> m_beam_leds_left;
|
||||
output_finder<0x40> m_beam_leds_right;
|
||||
output_finder<6> m_score_digits;
|
||||
output_finder<8> m_credit_leds;
|
||||
output_finder<12> m_barrier_leds;
|
||||
output_finder<16> m_round_leds;
|
||||
output_finder<> m_barrier_lamp;
|
||||
output_finder<> m_start_lamp;
|
||||
output_finder<> m_sight_led;
|
||||
|
||||
required_ioport m_in3;
|
||||
required_ioport m_fake;
|
||||
|
||||
/* machine state */
|
||||
int m_vert_pos = 0;
|
||||
int m_horiz_pos = 0;
|
||||
bool m_motor_on = false;
|
||||
|
||||
/* video state */
|
||||
uint8_t m_y_scroll_d = 0;
|
||||
uint8_t m_y_scroll_e = 0;
|
||||
uint8_t m_y_scroll_f = 0;
|
||||
uint8_t m_frame_count = 0;
|
||||
uint8_t m_shot_standby = 0;
|
||||
uint8_t m_shot_arrive = 0;
|
||||
uint16_t m_beam_state = 0;
|
||||
uint16_t m_old_beam_state = 0;
|
||||
uint16_t m_beam_states_per_frame = 0;
|
||||
uint8_t m_palette_bank = 0;
|
||||
};
|
||||
|
||||
#endif // MAME_INCLUDES_STACTICS_H
|
@ -1,431 +0,0 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Frank Palazzolo
|
||||
/****************************************************************************
|
||||
|
||||
Sega "Space Tactics" Driver
|
||||
|
||||
Frank Palazzolo (palazzol@home.com)
|
||||
|
||||
|
||||
The Video system used in Space Tactics is unusual.
|
||||
Here are my notes on how the video system works:
|
||||
|
||||
There are 4, 4K pages of Video RAM. (B,D,E & F)
|
||||
|
||||
The first 1K of each VRAM page contains the following:
|
||||
0 0 V V V V V H H H H H offset value for each 8x8 bitmap
|
||||
(v-tile) (h-tile)
|
||||
|
||||
The offset values are used to generate an access into the
|
||||
last 2K of the VRAM page:
|
||||
1 D D D D D D D D V V V here we find 8x8 character data
|
||||
(offset) (line)
|
||||
|
||||
In addition, in Page B, the upper nibble of the offset is
|
||||
also used to select the color palette for the tile.
|
||||
|
||||
Page B, D, E, and F all work similarly, except that pages
|
||||
D, E, and F can be offset from Page B by a given
|
||||
number of scanlines, based on the contents of the offset
|
||||
RAM
|
||||
|
||||
The offset RAM is addressed in this format:
|
||||
1 0 0 0 P P P V V V V V V V V V
|
||||
(Page) (scanline)
|
||||
Page 4=D, 5=E, 6=F
|
||||
|
||||
Page D, E, and F are drawn offset from the top of the screen,
|
||||
starting on the first scanline which contains a 1 in the
|
||||
appropriate memory location
|
||||
|
||||
---
|
||||
|
||||
The composited monitor image is seen in a mirror. It appears
|
||||
to move when the player moves the handle, due to motors which
|
||||
tilt the mirror up and down, and the monitor left and right.
|
||||
|
||||
---
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "stactics.h"
|
||||
#include "screen.h"
|
||||
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* Palette
|
||||
*
|
||||
*************************************/
|
||||
|
||||
void stactics_state::stactics_palette(palette_device &palette) const
|
||||
{
|
||||
uint8_t const *const color_prom = memregion("proms")->base();
|
||||
|
||||
for (int i = 0; i < 0x400; i++)
|
||||
{
|
||||
int const bit0 = BIT(color_prom[i], 0);
|
||||
int const bit1 = BIT(color_prom[i], 1);
|
||||
int const bit2 = BIT(color_prom[i], 2);
|
||||
int const bit3 = BIT(color_prom[i], 3);
|
||||
|
||||
// red component
|
||||
int const r = 0xff * bit0;
|
||||
|
||||
// green component
|
||||
int const g = 0xff * bit1 - 0xcc * bit3;
|
||||
|
||||
// blue component
|
||||
int const b = 0xff * bit2;
|
||||
|
||||
palette.set_pen_color(i, rgb_t(r, g, b));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
WRITE_LINE_MEMBER(stactics_state::palette_bank_w)
|
||||
{
|
||||
m_palette_bank = m_outlatch->q6_r() | (m_outlatch->q7_r() << 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* Scrolling
|
||||
*
|
||||
*************************************/
|
||||
|
||||
void stactics_state::scroll_ram_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
if (data & 0x01)
|
||||
{
|
||||
switch (offset >> 8)
|
||||
{
|
||||
case 4: m_y_scroll_d = offset & 0xff; break;
|
||||
case 5: m_y_scroll_e = offset & 0xff; break;
|
||||
case 6: m_y_scroll_f = offset & 0xff; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* Frane counter
|
||||
*
|
||||
*************************************/
|
||||
|
||||
READ_LINE_MEMBER(stactics_state::frame_count_d3_r)
|
||||
{
|
||||
return (m_frame_count >> 3) & 0x01;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* Beam handling
|
||||
*
|
||||
*************************************/
|
||||
|
||||
void stactics_state::speed_latch_w(uint8_t data)
|
||||
{
|
||||
/* This writes to a shift register which is clocked by */
|
||||
/* a 555 oscillator. This value determines the speed of */
|
||||
/* the LED fire beams as follows: */
|
||||
|
||||
/* 555_freq / bits_in_SR * edges_in_SR / states_in_PR67 / frame_rate */
|
||||
/* = num_led_states_per_frame */
|
||||
/* 36439 / 8 * x / 32 / 60 ~= 19/8*x */
|
||||
|
||||
/* Here, we will count the number of rising edges in the shift register */
|
||||
|
||||
int i;
|
||||
int num_rising_edges = 0;
|
||||
|
||||
for(i=0;i<8;i++)
|
||||
{
|
||||
if ( (((data>>i)&0x01) == 1) && (((data>>((i+1)%8))&0x01) == 0))
|
||||
num_rising_edges++;
|
||||
}
|
||||
|
||||
m_beam_states_per_frame = num_rising_edges*19/8;
|
||||
}
|
||||
|
||||
|
||||
void stactics_state::shot_trigger_w(uint8_t data)
|
||||
{
|
||||
m_shot_standby = 0;
|
||||
}
|
||||
|
||||
|
||||
void stactics_state::shot_flag_clear_w(uint8_t data)
|
||||
{
|
||||
m_shot_arrive = 0;
|
||||
}
|
||||
|
||||
|
||||
READ_LINE_MEMBER(stactics_state::shot_standby_r)
|
||||
{
|
||||
return m_shot_standby;
|
||||
}
|
||||
|
||||
|
||||
READ_LINE_MEMBER(stactics_state::not_shot_arrive_r)
|
||||
{
|
||||
return !m_shot_arrive;
|
||||
}
|
||||
|
||||
|
||||
void stactics_state::update_beam()
|
||||
{
|
||||
/* first, update the firebeam state */
|
||||
m_old_beam_state = m_beam_state;
|
||||
if (m_shot_standby == 0)
|
||||
m_beam_state = m_beam_state + m_beam_states_per_frame;
|
||||
|
||||
/* These are thresholds for the two shots from the LED fire ROM */
|
||||
/* (Note: There are two more for sound triggers, */
|
||||
/* whenever that gets implemented) */
|
||||
if ((m_old_beam_state < 0x8b) & (m_beam_state >= 0x8b))
|
||||
m_shot_arrive = 1;
|
||||
|
||||
if ((m_old_beam_state < 0xca) & (m_beam_state >= 0xca))
|
||||
m_shot_arrive = 1;
|
||||
|
||||
if (m_beam_state >= 0x100)
|
||||
{
|
||||
m_beam_state = 0;
|
||||
m_shot_standby = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* Video drawing
|
||||
*
|
||||
*************************************/
|
||||
|
||||
inline int stactics_state::get_pixel_on_plane(uint8_t *videoram, uint8_t y, uint8_t x, uint8_t y_scroll)
|
||||
{
|
||||
/* compute effective row */
|
||||
y = y - y_scroll;
|
||||
|
||||
/* get the character code at the given pixel */
|
||||
uint8_t code = videoram[((y >> 3) << 5) | (x >> 3)];
|
||||
|
||||
/* get the gfx byte */
|
||||
uint8_t gfx = videoram[0x800 | (code << 3) | (y & 0x07)];
|
||||
|
||||
/* return the appropriate pixel within the byte */
|
||||
return (gfx >> (~x & 0x07)) & 0x01;
|
||||
}
|
||||
|
||||
|
||||
void stactics_state::draw_background(bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
bitmap.fill(0, cliprect);
|
||||
|
||||
/* for every row */
|
||||
for (int y = 0; y < 0x100; y++)
|
||||
{
|
||||
/* for every pixel on the row */
|
||||
for (int x = 0; x < 0x100; x++)
|
||||
{
|
||||
/* get the pixels for the four planes */
|
||||
int pixel_b = get_pixel_on_plane(m_videoram_b, y, x, 0);
|
||||
int pixel_d = get_pixel_on_plane(m_videoram_d, y, x, m_y_scroll_d);
|
||||
int pixel_e = get_pixel_on_plane(m_videoram_e, y, x, m_y_scroll_e);
|
||||
int pixel_f = get_pixel_on_plane(m_videoram_f, y, x, m_y_scroll_f);
|
||||
|
||||
/* get the color for this pixel */
|
||||
uint8_t color = m_videoram_b[((y >> 3) << 5) | (x >> 3)] >> 4;
|
||||
|
||||
/* assemble the pen index */
|
||||
int pen = color |
|
||||
(pixel_b << 4) |
|
||||
(pixel_f << 5) |
|
||||
(pixel_e << 6) |
|
||||
(pixel_d << 7) |
|
||||
(m_palette_bank << 8);
|
||||
|
||||
/* compute the effective pixel coordinate after adjusting for the
|
||||
mirror movement - this is mechanical on the real machine */
|
||||
int sy = y + m_vert_pos;
|
||||
int sx = x - m_horiz_pos;
|
||||
|
||||
/* plot if visible */
|
||||
if ((sy >= 0) && (sy < 0x100) && (sx >= 0) && (sx < 0x100))
|
||||
bitmap.pix(sy, sx) = pen;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* Non-video artwork
|
||||
*
|
||||
*************************************/
|
||||
|
||||
/* from 7448 datasheet */
|
||||
static constexpr int to_7seg[0x10] =
|
||||
{
|
||||
0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7c, 0x07,
|
||||
0x7f, 0x67, 0x58, 0x4c, 0x62, 0x69, 0x78, 0x00
|
||||
};
|
||||
|
||||
|
||||
template <unsigned N> void stactics_state::set_indicator_leds(unsigned offset, output_finder<N> &outputs, int base_index)
|
||||
{
|
||||
/* decode the data */
|
||||
int const data = to_7seg[~m_display_buffer[offset] & 0x0f];
|
||||
|
||||
/* set the 4 LEDs */
|
||||
outputs[base_index + 0] = BIT(data, 2);
|
||||
outputs[base_index + 1] = BIT(data, 6);
|
||||
outputs[base_index + 2] = BIT(data, 5);
|
||||
outputs[base_index + 3] = BIT(data, 4);
|
||||
}
|
||||
|
||||
|
||||
WRITE_LINE_MEMBER(stactics_state::barrier_lamp_w)
|
||||
{
|
||||
// this needs to flash on/off, not implemented
|
||||
m_barrier_lamp = state;
|
||||
}
|
||||
|
||||
|
||||
WRITE_LINE_MEMBER(stactics_state::start_lamp_w)
|
||||
{
|
||||
m_start_lamp = state;
|
||||
}
|
||||
|
||||
|
||||
void stactics_state::update_artwork()
|
||||
{
|
||||
uint8_t *beam_region = memregion("user1")->base();
|
||||
|
||||
/* laser beam - loop for each LED */
|
||||
for (int i = 0; i < 0x40; i++)
|
||||
{
|
||||
offs_t const beam_data_offs = ((i & 0x08) << 7) | ((i & 0x30) << 4) | m_beam_state;
|
||||
uint8_t const beam_data = beam_region[beam_data_offs];
|
||||
int const on = BIT(beam_data, i & 0x07);
|
||||
|
||||
m_beam_leds_left[i] = on;
|
||||
m_beam_leds_right[i] = on;
|
||||
}
|
||||
|
||||
/* sight LED */
|
||||
m_sight_led = m_motor_on;
|
||||
|
||||
/* score display */
|
||||
for (int i = 0x01; i < 0x07; i++)
|
||||
m_score_digits[i - 1] = to_7seg[~m_display_buffer[i] & 0x0f];
|
||||
|
||||
/* credits indicator */
|
||||
set_indicator_leds(0x07, m_credit_leds, 0x00);
|
||||
set_indicator_leds(0x08, m_credit_leds, 0x04);
|
||||
|
||||
/* barriers indicator */
|
||||
set_indicator_leds(0x09, m_barrier_leds, 0x00);
|
||||
set_indicator_leds(0x0a, m_barrier_leds, 0x04);
|
||||
set_indicator_leds(0x0b, m_barrier_leds, 0x08);
|
||||
|
||||
/* rounds indicator */
|
||||
set_indicator_leds(0x0c, m_round_leds, 0x00);
|
||||
set_indicator_leds(0x0d, m_round_leds, 0x04);
|
||||
set_indicator_leds(0x0e, m_round_leds, 0x08);
|
||||
set_indicator_leds(0x0f, m_round_leds, 0x0c);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* Start
|
||||
*
|
||||
*************************************/
|
||||
|
||||
void stactics_state::video_start()
|
||||
{
|
||||
m_base_lamps.resolve();
|
||||
m_beam_leds_left.resolve();
|
||||
m_beam_leds_right.resolve();
|
||||
m_score_digits.resolve();
|
||||
m_credit_leds.resolve();
|
||||
m_barrier_leds.resolve();
|
||||
m_round_leds.resolve();
|
||||
m_barrier_lamp.resolve();
|
||||
m_start_lamp.resolve();
|
||||
m_sight_led.resolve();
|
||||
|
||||
m_y_scroll_d = 0;
|
||||
m_y_scroll_e = 0;
|
||||
m_y_scroll_f = 0;
|
||||
|
||||
m_frame_count = 0;
|
||||
m_shot_standby = 1;
|
||||
m_shot_arrive = 0;
|
||||
m_beam_state = 0;
|
||||
m_old_beam_state = 0;
|
||||
|
||||
m_palette_bank = 0;
|
||||
|
||||
save_item(NAME(m_y_scroll_d));
|
||||
save_item(NAME(m_y_scroll_e));
|
||||
save_item(NAME(m_y_scroll_f));
|
||||
save_item(NAME(m_frame_count));
|
||||
save_item(NAME(m_shot_standby));
|
||||
save_item(NAME(m_shot_arrive));
|
||||
save_item(NAME(m_beam_state));
|
||||
save_item(NAME(m_old_beam_state));
|
||||
save_item(NAME(m_beam_states_per_frame));
|
||||
save_item(NAME(m_palette_bank));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* Update
|
||||
*
|
||||
*************************************/
|
||||
|
||||
uint32_t stactics_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
update_beam();
|
||||
draw_background(bitmap, cliprect);
|
||||
update_artwork();
|
||||
|
||||
m_frame_count = (m_frame_count + 1) & 0x0f;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* Machine driver
|
||||
*
|
||||
*************************************/
|
||||
|
||||
void stactics_state::stactics_video(machine_config &config)
|
||||
{
|
||||
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
|
||||
screen.set_video_attributes(VIDEO_ALWAYS_UPDATE);
|
||||
screen.set_raw(15.46848_MHz_XTAL / 3, 328, 0, 256, 262, 0, 232);
|
||||
screen.set_screen_update(FUNC(stactics_state::screen_update));
|
||||
screen.set_palette("palette");
|
||||
|
||||
PALETTE(config, "palette", FUNC(stactics_state::stactics_palette), 0x400);
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Zsolt Vasvari
|
||||
// copyright-holders: Zsolt Vasvari
|
||||
|
||||
/******************************************************************************
|
||||
|
||||
Super Locomotive
|
||||
@ -22,21 +23,324 @@ Sega PCB 834-5137
|
||||
******************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "suprloco.h"
|
||||
|
||||
#include "machine/segacrpt_device.h"
|
||||
#include "cpu/z80/z80.h"
|
||||
#include "machine/i8255.h"
|
||||
#include "machine/segacrpt_device.h"
|
||||
#include "sound/sn76496.h"
|
||||
|
||||
#include "emupal.h"
|
||||
#include "screen.h"
|
||||
#include "speaker.h"
|
||||
#include "tilemap.h"
|
||||
|
||||
|
||||
// configurable logging
|
||||
#define LOG_CTRLBIT4 (1U << 1)
|
||||
|
||||
//#define VERBOSE (LOG_GENERAL | LOG_CTRLBIT4)
|
||||
|
||||
#include "logmacro.h"
|
||||
|
||||
#define LOGCTRLBIT4(...) LOGMASKED(LOG_CTRLBIT4, __VA_ARGS__)
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
class suprloco_state : public driver_device
|
||||
{
|
||||
public:
|
||||
suprloco_state(const machine_config &mconfig, device_type type, const char *tag) :
|
||||
driver_device(mconfig, type, tag),
|
||||
m_maincpu(*this, "maincpu"),
|
||||
m_audiocpu(*this, "audiocpu"),
|
||||
m_gfxdecode(*this, "gfxdecode"),
|
||||
m_spriteram(*this, "spriteram"),
|
||||
m_videoram(*this, "videoram"),
|
||||
m_scrollram(*this, "scrollram"),
|
||||
m_decrypted_opcodes(*this, "decrypted_opcodes"),
|
||||
m_sprites_rom(*this, "sprites")
|
||||
{ }
|
||||
|
||||
void suprloco(machine_config &config);
|
||||
|
||||
void init_suprloco();
|
||||
|
||||
protected:
|
||||
virtual void video_start() override;
|
||||
|
||||
private:
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<cpu_device> m_audiocpu;
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
|
||||
required_shared_ptr<uint8_t> m_spriteram;
|
||||
required_shared_ptr<uint8_t> m_videoram;
|
||||
required_shared_ptr<uint8_t> m_scrollram;
|
||||
required_shared_ptr<uint8_t> m_decrypted_opcodes;
|
||||
required_region_ptr<uint8_t> m_sprites_rom;
|
||||
|
||||
tilemap_t *m_bg_tilemap = nullptr;
|
||||
uint8_t m_control = 0;
|
||||
|
||||
enum
|
||||
{
|
||||
SPR_Y_TOP = 0,
|
||||
SPR_Y_BOTTOM,
|
||||
SPR_X,
|
||||
SPR_COL,
|
||||
SPR_SKIP_LO,
|
||||
SPR_SKIP_HI,
|
||||
SPR_GFXOFS_LO,
|
||||
SPR_GFXOFS_HI
|
||||
};
|
||||
|
||||
void videoram_w(offs_t offset, uint8_t data);
|
||||
void scrollram_w(offs_t offset, uint8_t data);
|
||||
void control_w(uint8_t data);
|
||||
|
||||
TILE_GET_INFO_MEMBER(get_tile_info);
|
||||
|
||||
void palette(palette_device &palette) const;
|
||||
|
||||
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
inline void draw_pixel(bitmap_ind16 &bitmap, const rectangle &cliprect, int x, int y, int color, int flip);
|
||||
void draw_sprite(bitmap_ind16 &bitmap, const rectangle &cliprect, int spr_number);
|
||||
void draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
void decrypted_opcodes_map(address_map &map);
|
||||
void main_map(address_map &map);
|
||||
void sound_map(address_map &map);
|
||||
};
|
||||
|
||||
|
||||
// video
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
Convert the color PROMs into a more useable format.
|
||||
|
||||
I'm not sure about the resistor values, I'm using the Galaxian ones.
|
||||
|
||||
***************************************************************************/
|
||||
void suprloco_state::palette(palette_device &palette) const
|
||||
{
|
||||
const uint8_t *color_prom = memregion("proms")->base();
|
||||
|
||||
for (int i = 0; i < 512; i++)
|
||||
{
|
||||
int bit0, bit1, bit2;
|
||||
|
||||
// red component
|
||||
bit0 = BIT(color_prom[i], 0);
|
||||
bit1 = BIT(color_prom[i], 1);
|
||||
bit2 = BIT(color_prom[i], 2);
|
||||
int const r = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
|
||||
// green component
|
||||
bit0 = BIT(color_prom[i], 3);
|
||||
bit1 = BIT(color_prom[i], 4);
|
||||
bit2 = BIT(color_prom[i], 5);
|
||||
int const g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
|
||||
// blue component
|
||||
bit0 = 0;
|
||||
bit1 = BIT(color_prom[i], 6);
|
||||
bit2 = BIT(color_prom[i], 7);
|
||||
int const b = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
|
||||
|
||||
palette.set_pen_color(i, rgb_t(r, g, b));
|
||||
|
||||
// hack: generate a second bank of sprite palette with red changed to purple
|
||||
if (i >= 256)
|
||||
palette.set_pen_color(i + 256, rgb_t(r, g, ((i & 0x0f) == 0x09) ? 0xff : b));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
Callbacks for the TileMap code
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
TILE_GET_INFO_MEMBER(suprloco_state::get_tile_info)
|
||||
{
|
||||
uint8_t const attr = m_videoram[2 * tile_index + 1];
|
||||
tileinfo.set(0,
|
||||
m_videoram[2 * tile_index] | ((attr & 0x03) << 8),
|
||||
(attr & 0x1c) >> 2,
|
||||
0);
|
||||
tileinfo.category = (attr & 0x20) >> 5;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
Start the video hardware emulation.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
void suprloco_state::video_start()
|
||||
{
|
||||
m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(suprloco_state::get_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 32, 32);
|
||||
|
||||
m_bg_tilemap->set_scroll_rows(32);
|
||||
|
||||
save_item(NAME(m_control));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
Memory handlers
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
void suprloco_state::videoram_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
m_videoram[offset] = data;
|
||||
m_bg_tilemap->mark_tile_dirty(offset / 2);
|
||||
}
|
||||
|
||||
void suprloco_state::scrollram_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
int const adj = flip_screen() ? -8 : 8;
|
||||
|
||||
m_scrollram[offset] = data;
|
||||
m_bg_tilemap->set_scrollx(offset, data - adj);
|
||||
}
|
||||
|
||||
void suprloco_state::control_w(uint8_t data)
|
||||
{
|
||||
/* There is probably a palette select in here
|
||||
|
||||
Bit 0 - coin counter A
|
||||
Bit 1 - coin counter B (only used if coinage differs from A)
|
||||
Bit 2-3 - probably unused
|
||||
Bit 4 - ???
|
||||
Bit 5 - pulsated when loco turns "super"
|
||||
Bit 6 - probably unused
|
||||
Bit 7 - flip screen */
|
||||
|
||||
if ((m_control & 0x10) != (data & 0x10))
|
||||
LOGCTRLBIT4("Bit 4 = %d\n", (data >> 4) & 1);
|
||||
|
||||
machine().bookkeeping().coin_counter_w(0, data & 0x01);
|
||||
machine().bookkeeping().coin_counter_w(1, data & 0x02);
|
||||
|
||||
flip_screen_set(data & 0x80);
|
||||
|
||||
m_control = data;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline void suprloco_state::draw_pixel(bitmap_ind16 &bitmap, const rectangle &cliprect, int x, int y, int color, int flip)
|
||||
{
|
||||
if (flip)
|
||||
{
|
||||
x = bitmap.width() - x - 1;
|
||||
y = bitmap.height() - y - 1;
|
||||
}
|
||||
|
||||
if (cliprect.contains(x, y))
|
||||
bitmap.pix(y, x) = color;
|
||||
}
|
||||
|
||||
|
||||
void suprloco_state::draw_sprite(bitmap_ind16 &bitmap, const rectangle &cliprect, int spr_number)
|
||||
{
|
||||
int const flip = flip_screen();
|
||||
int adjy, dy;
|
||||
|
||||
const uint8_t *spr_reg = m_spriteram + 0x10 * spr_number;
|
||||
|
||||
int src = spr_reg[SPR_GFXOFS_LO] + (spr_reg[SPR_GFXOFS_HI] << 8);
|
||||
short const skip = spr_reg[SPR_SKIP_LO] + (spr_reg[SPR_SKIP_HI] << 8); // bytes to skip before drawing each row (can be negative)
|
||||
|
||||
int const height = spr_reg[SPR_Y_BOTTOM] - spr_reg[SPR_Y_TOP];
|
||||
pen_t const pen_base = 0x100 + 0x10 * (spr_reg[SPR_COL] & 0x03) + ((m_control & 0x20) ? 0x100 : 0);
|
||||
int const sx = spr_reg[SPR_X];
|
||||
int const sy = spr_reg[SPR_Y_TOP] + 1;
|
||||
|
||||
if (!flip)
|
||||
{
|
||||
adjy = sy;
|
||||
dy = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
adjy = sy + height - 1; // some of the sprites are still off by a pixel
|
||||
dy = -1;
|
||||
}
|
||||
|
||||
for (int row = 0; row < height; row++, adjy += dy)
|
||||
{
|
||||
int color1, color2;
|
||||
uint8_t data;
|
||||
|
||||
src += skip;
|
||||
|
||||
int col = 0;
|
||||
|
||||
// get pointer to packed sprite data
|
||||
const uint8_t *gfx = &(m_sprites_rom[src & 0x7fff]);
|
||||
int const flipx = src & 0x8000; // flip x
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (flipx) // flip x
|
||||
{
|
||||
data = *gfx--;
|
||||
color1 = data & 0x0f;
|
||||
color2 = data >> 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
data = *gfx++;
|
||||
color1 = data >> 4;
|
||||
color2 = data & 0x0f;
|
||||
}
|
||||
|
||||
if (color1 == 15) break;
|
||||
if (color1)
|
||||
draw_pixel(bitmap, cliprect,sx + col, adjy, pen_base + color1, flip);
|
||||
|
||||
if (color2 == 15) break;
|
||||
if (color2)
|
||||
draw_pixel(bitmap, cliprect,sx + col + 1, adjy, pen_base + color2, flip);
|
||||
|
||||
col += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void suprloco_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
for (int spr_number = 0; spr_number < (m_spriteram.bytes() >> 4); spr_number++)
|
||||
{
|
||||
const uint8_t *spr_reg = m_spriteram + 0x10 * spr_number;
|
||||
if (spr_reg[SPR_X] != 0xff)
|
||||
draw_sprite(bitmap, cliprect, spr_number);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t suprloco_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
|
||||
draw_sprites(bitmap, cliprect);
|
||||
m_bg_tilemap->draw(screen, bitmap, cliprect, 1, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// machine
|
||||
|
||||
void suprloco_state::main_map(address_map &map)
|
||||
{
|
||||
map(0x0000, 0xbfff).rom();
|
||||
map(0xc000, 0xc1ff).ram().share("spriteram");
|
||||
map(0xc000, 0xc1ff).ram().share(m_spriteram);
|
||||
map(0xc200, 0xc7ff).nopw();
|
||||
map(0xc800, 0xc800).portr("SYSTEM");
|
||||
map(0xd000, 0xd000).portr("P1");
|
||||
@ -44,15 +348,15 @@ void suprloco_state::main_map(address_map &map)
|
||||
map(0xe000, 0xe000).portr("DSW1");
|
||||
map(0xe001, 0xe001).portr("DSW2");
|
||||
map(0xe800, 0xe803).rw("ppi", FUNC(i8255_device::read), FUNC(i8255_device::write));
|
||||
map(0xf000, 0xf6ff).ram().w(FUNC(suprloco_state::videoram_w)).share("videoram");
|
||||
map(0xf700, 0xf7df).ram(); /* unused */
|
||||
map(0xf7e0, 0xf7ff).ram().w(FUNC(suprloco_state::scrollram_w)).share("scrollram");
|
||||
map(0xf000, 0xf6ff).ram().w(FUNC(suprloco_state::videoram_w)).share(m_videoram);
|
||||
map(0xf700, 0xf7df).ram(); // unused
|
||||
map(0xf7e0, 0xf7ff).ram().w(FUNC(suprloco_state::scrollram_w)).share(m_scrollram);
|
||||
map(0xf800, 0xffff).ram();
|
||||
}
|
||||
|
||||
void suprloco_state::decrypted_opcodes_map(address_map &map)
|
||||
{
|
||||
map(0x0000, 0x7fff).rom().share("decrypted_opcodes");
|
||||
map(0x0000, 0x7fff).rom().share(m_decrypted_opcodes);
|
||||
map(0x8000, 0xbfff).rom().region("maincpu", 0x8000);
|
||||
}
|
||||
|
||||
@ -149,10 +453,10 @@ INPUT_PORTS_END
|
||||
|
||||
static const gfx_layout charlayout =
|
||||
{
|
||||
8,8, /* 8 by 8 */
|
||||
1024, /* 1024 characters */
|
||||
4, /* 4 bits per pixel */
|
||||
{ 0, 1024*8*8, 2*1024*8*8, 3*1024*8*8 }, /* plane */
|
||||
8,8, // 8 by 8
|
||||
1024, // 1024 characters
|
||||
4, // 4 bits per pixel
|
||||
{ 0, 1024*8*8, 2*1024*8*8, 3*1024*8*8 }, // plane
|
||||
{ 0, 1, 2, 3, 4, 5, 6, 7 },
|
||||
{ 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 },
|
||||
8*8
|
||||
@ -160,23 +464,23 @@ static const gfx_layout charlayout =
|
||||
|
||||
|
||||
static GFXDECODE_START( gfx_suprloco )
|
||||
/* sprites use colors 256-511 + 512-767 */
|
||||
GFXDECODE_ENTRY( "gfx1", 0x6000, charlayout, 0, 16 )
|
||||
// sprites use colors 256-511 + 512-767
|
||||
GFXDECODE_ENTRY( "chars", 0x6000, charlayout, 0, 16 )
|
||||
GFXDECODE_END
|
||||
|
||||
|
||||
void suprloco_state::suprloco(machine_config &config)
|
||||
{
|
||||
/* basic machine hardware */
|
||||
sega_315_5015_device &maincpu(SEGA_315_5015(config, m_maincpu, 4000000)); /* 4 MHz (?) */
|
||||
// basic machine hardware
|
||||
sega_315_5015_device &maincpu(SEGA_315_5015(config, m_maincpu, 4'000'000)); // 4 MHz (?)
|
||||
maincpu.set_addrmap(AS_PROGRAM, &suprloco_state::main_map);
|
||||
maincpu.set_addrmap(AS_OPCODES, &suprloco_state::decrypted_opcodes_map);
|
||||
maincpu.set_vblank_int("screen", FUNC(suprloco_state::irq0_line_hold));
|
||||
maincpu.set_decrypted_tag(":decrypted_opcodes");
|
||||
|
||||
Z80(config, m_audiocpu, 4000000);
|
||||
Z80(config, m_audiocpu, 4'000'000);
|
||||
m_audiocpu->set_addrmap(AS_PROGRAM, &suprloco_state::sound_map);
|
||||
m_audiocpu->set_periodic_int(FUNC(suprloco_state::irq0_line_hold), attotime::from_hz(4*60)); /* NMIs are caused by the main CPU */
|
||||
m_audiocpu->set_periodic_int(FUNC(suprloco_state::irq0_line_hold), attotime::from_hz(4 * 60)); // NMIs are caused by the main CPU
|
||||
|
||||
i8255_device &ppi(I8255A(config, "ppi"));
|
||||
ppi.out_pb_callback().set(FUNC(suprloco_state::control_w));
|
||||
@ -184,7 +488,7 @@ void suprloco_state::suprloco(machine_config &config)
|
||||
ppi.out_pc_callback().set_output("lamp0").bit(0).invert(); // set by 8255 bit mode when no credits inserted
|
||||
ppi.out_pc_callback().append_inputline(m_audiocpu, INPUT_LINE_NMI).bit(7).invert();
|
||||
|
||||
/* video hardware */
|
||||
// video hardware
|
||||
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
|
||||
screen.set_refresh_hz(60);
|
||||
screen.set_vblank_time(ATTOSECONDS_IN_USEC(5000));
|
||||
@ -194,14 +498,14 @@ void suprloco_state::suprloco(machine_config &config)
|
||||
screen.set_palette("palette");
|
||||
|
||||
GFXDECODE(config, m_gfxdecode, "palette", gfx_suprloco);
|
||||
PALETTE(config, "palette", FUNC(suprloco_state::suprloco_palette), 512+256);
|
||||
PALETTE(config, "palette", FUNC(suprloco_state::palette), 512 + 256);
|
||||
|
||||
/* sound hardware */
|
||||
// sound hardware
|
||||
SPEAKER(config, "mono").front_center();
|
||||
|
||||
SN76496(config, "sn1", 4000000).add_route(ALL_OUTPUTS, "mono", 1.0);
|
||||
SN76496(config, "sn1", 4'000'000).add_route(ALL_OUTPUTS, "mono", 1.0);
|
||||
|
||||
SN76496(config, "sn2", 2000000).add_route(ALL_OUTPUTS, "mono", 1.0);
|
||||
SN76496(config, "sn2", 2'000'000).add_route(ALL_OUTPUTS, "mono", 1.0);
|
||||
}
|
||||
|
||||
|
||||
@ -213,66 +517,66 @@ void suprloco_state::suprloco(machine_config &config)
|
||||
|
||||
ROM_START( suprloco )
|
||||
ROM_REGION( 0xc000, "maincpu", 0 )
|
||||
ROM_LOAD( "epr-5226a.37", 0x0000, 0x4000, CRC(33b02368) SHA1(c6e3116ad4b52bcc3174de5770f7a7ce024790d5) ) /* encrypted */
|
||||
ROM_LOAD( "epr-5227a.15", 0x4000, 0x4000, CRC(a5e67f50) SHA1(1dd52e4cf00ce414fe1db8259c9976cdc23513b4) ) /* encrypted */
|
||||
ROM_LOAD( "epr-5226a.37", 0x0000, 0x4000, CRC(33b02368) SHA1(c6e3116ad4b52bcc3174de5770f7a7ce024790d5) ) // encrypted
|
||||
ROM_LOAD( "epr-5227a.15", 0x4000, 0x4000, CRC(a5e67f50) SHA1(1dd52e4cf00ce414fe1db8259c9976cdc23513b4) ) // encrypted
|
||||
ROM_LOAD( "epr-5228.28", 0x8000, 0x4000, CRC(a597828a) SHA1(61004d112591fd2d752c39df71c1304d9308daae) )
|
||||
|
||||
ROM_REGION( 0x10000, "audiocpu", 0 )
|
||||
ROM_LOAD( "epr-5222.64", 0x0000, 0x2000, CRC(0aa57207) SHA1(b29b533505cb5b47c90534f2f610baeb7265d030) )
|
||||
|
||||
ROM_REGION( 0xe000, "gfx1", 0 )
|
||||
ROM_REGION( 0xe000, "chars", 0 )
|
||||
ROM_LOAD( "epr-5225.63", 0x0000, 0x2000, CRC(e571fe81) SHA1(ac2b5914a445b89b7456b2c4290e4630b525f05d) )
|
||||
ROM_LOAD( "epr-5224.62", 0x2000, 0x2000, CRC(6130f93c) SHA1(ae0657f46c10e75eec994e75359a89b5d61baf68) )
|
||||
ROM_LOAD( "epr-5223.61", 0x4000, 0x2000, CRC(3b03004e) SHA1(805b51cb14d3ace97f2e0f306db28921b2f5e322) )
|
||||
/* 0x6000- 0xe000 will be created by init_suprloco */
|
||||
// 0x6000 - 0xe000 will be created by init_suprloco
|
||||
|
||||
ROM_REGION( 0x8000, "gfx2", 0 ) /* 32k for sprites data used at runtime */
|
||||
ROM_REGION( 0x8000, "sprites", 0 ) // used at runtime
|
||||
ROM_LOAD( "epr-5229.55", 0x0000, 0x4000, CRC(ee2d3ed3) SHA1(593f3cd5c4e7f20b5e31e6bac8864774442e4b75) )
|
||||
ROM_LOAD( "epr-5230.56", 0x4000, 0x2000, CRC(f04a4b50) SHA1(80363f0c508fb2a755bf684f9a6862c1e7285495) )
|
||||
/* 0x6000 empty */
|
||||
// 0x6000 empty
|
||||
|
||||
ROM_REGION( 0x0620, "proms", 0 )
|
||||
ROM_LOAD( "pr-5220.100", 0x0100, 0x0080, CRC(7b0c8ce5) SHA1(4e1ea5ce38198a3965dfeb609ba0c7e8211531c3) ) /* color PROM */
|
||||
ROM_LOAD( "pr-5220.100", 0x0100, 0x0080, CRC(7b0c8ce5) SHA1(4e1ea5ce38198a3965dfeb609ba0c7e8211531c3) ) // color PROM
|
||||
ROM_CONTINUE( 0x0000, 0x0080 )
|
||||
ROM_CONTINUE( 0x0180, 0x0080 )
|
||||
ROM_CONTINUE( 0x0080, 0x0080 )
|
||||
ROM_LOAD( "pr-5219.89", 0x0200, 0x0400, CRC(1d4b02cb) SHA1(00d822f1bc4f57f2f5d5a0615241f8136246a842) ) /* 3bpp to 4bpp table */
|
||||
ROM_LOAD( "pr-5221.7", 0x0600, 0x0020, CRC(89ba674f) SHA1(17c87840c8011968675a5a6f55966467df02364b) ) /* unknown */
|
||||
ROM_LOAD( "pr-5219.89", 0x0200, 0x0400, CRC(1d4b02cb) SHA1(00d822f1bc4f57f2f5d5a0615241f8136246a842) ) // 3bpp to 4bpp table
|
||||
ROM_LOAD( "pr-5221.7", 0x0600, 0x0020, CRC(89ba674f) SHA1(17c87840c8011968675a5a6f55966467df02364b) ) // unknown
|
||||
ROM_END
|
||||
|
||||
ROM_START( suprlocoo )
|
||||
ROM_REGION( 0xc000, "maincpu", 0 )
|
||||
ROM_LOAD( "epr-5226.37", 0x0000, 0x4000, CRC(57f514dd) SHA1(707800b90a22547a56b01d1e11775e9ee5555d23) ) /* encrypted */
|
||||
ROM_LOAD( "epr-5227.15", 0x4000, 0x4000, CRC(5a1d2fb0) SHA1(fdb9416e5530718245fd597073a63feddb233c3c) ) /* encrypted */
|
||||
ROM_LOAD( "epr-5226.37", 0x0000, 0x4000, CRC(57f514dd) SHA1(707800b90a22547a56b01d1e11775e9ee5555d23) ) // encrypted
|
||||
ROM_LOAD( "epr-5227.15", 0x4000, 0x4000, CRC(5a1d2fb0) SHA1(fdb9416e5530718245fd597073a63feddb233c3c) ) // encrypted
|
||||
ROM_LOAD( "epr-5228.28", 0x8000, 0x4000, CRC(a597828a) SHA1(61004d112591fd2d752c39df71c1304d9308daae) )
|
||||
|
||||
ROM_REGION( 0x10000, "audiocpu", 0 )
|
||||
ROM_LOAD( "epr-5222.64", 0x0000, 0x2000, CRC(0aa57207) SHA1(b29b533505cb5b47c90534f2f610baeb7265d030) )
|
||||
|
||||
ROM_REGION( 0xe000, "gfx1", 0 )
|
||||
ROM_REGION( 0xe000, "chars", 0 )
|
||||
ROM_LOAD( "epr-5225.63", 0x0000, 0x2000, CRC(e571fe81) SHA1(ac2b5914a445b89b7456b2c4290e4630b525f05d) )
|
||||
ROM_LOAD( "epr-5224.62", 0x2000, 0x2000, CRC(6130f93c) SHA1(ae0657f46c10e75eec994e75359a89b5d61baf68) )
|
||||
ROM_LOAD( "epr-5223.61", 0x4000, 0x2000, CRC(3b03004e) SHA1(805b51cb14d3ace97f2e0f306db28921b2f5e322) )
|
||||
/* 0x6000- 0xe000 will be created by init_suprloco */
|
||||
// 0x6000 - 0xe000 will be created by init_suprloco
|
||||
|
||||
ROM_REGION( 0x8000, "gfx2", 0 ) /* 32k for sprites data used at runtime */
|
||||
ROM_REGION( 0x8000, "sprites", 0 ) // used at runtime
|
||||
ROM_LOAD( "epr-5229.55", 0x0000, 0x4000, CRC(ee2d3ed3) SHA1(593f3cd5c4e7f20b5e31e6bac8864774442e4b75) )
|
||||
ROM_LOAD( "epr-5230.56", 0x4000, 0x2000, CRC(f04a4b50) SHA1(80363f0c508fb2a755bf684f9a6862c1e7285495) )
|
||||
/* 0x6000 empty */
|
||||
// 0x6000 empty
|
||||
|
||||
ROM_REGION( 0x0620, "proms", 0 )
|
||||
ROM_LOAD( "pr-5220.100", 0x0100, 0x0080, CRC(7b0c8ce5) SHA1(4e1ea5ce38198a3965dfeb609ba0c7e8211531c3) ) /* color PROM */
|
||||
ROM_LOAD( "pr-5220.100", 0x0100, 0x0080, CRC(7b0c8ce5) SHA1(4e1ea5ce38198a3965dfeb609ba0c7e8211531c3) ) // color PROM
|
||||
ROM_CONTINUE( 0x0000, 0x0080 )
|
||||
ROM_CONTINUE( 0x0180, 0x0080 )
|
||||
ROM_CONTINUE( 0x0080, 0x0080 )
|
||||
ROM_LOAD( "pr-5219.89", 0x0200, 0x0400, CRC(1d4b02cb) SHA1(00d822f1bc4f57f2f5d5a0615241f8136246a842) ) /* 3bpp to 4bpp table */
|
||||
ROM_LOAD( "pr-5221.7", 0x0600, 0x0020, CRC(89ba674f) SHA1(17c87840c8011968675a5a6f55966467df02364b) ) /* unknown */
|
||||
ROM_LOAD( "pr-5219.89", 0x0200, 0x0400, CRC(1d4b02cb) SHA1(00d822f1bc4f57f2f5d5a0615241f8136246a842) ) // 3bpp to 4bpp table
|
||||
ROM_LOAD( "pr-5221.7", 0x0600, 0x0020, CRC(89ba674f) SHA1(17c87840c8011968675a5a6f55966467df02364b) ) // unknown
|
||||
ROM_END
|
||||
|
||||
void suprloco_state::init_suprloco()
|
||||
{
|
||||
/* convert graphics to 4bpp from 3bpp */
|
||||
uint8_t *source = memregion("gfx1")->base();
|
||||
// convert graphics to 4bpp from 3bpp
|
||||
uint8_t *source = memregion("chars")->base();
|
||||
uint8_t *dest = source + 0x6000;
|
||||
uint8_t *lookup = memregion("proms")->base() + 0x0200;
|
||||
|
||||
@ -300,5 +604,8 @@ void suprloco_state::init_suprloco()
|
||||
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
GAME( 1982, suprloco, 0, suprloco, suprloco, suprloco_state, init_suprloco, ROT0, "Sega", "Super Locomotive (Rev.A)", MACHINE_SUPPORTS_SAVE )
|
||||
GAME( 1982, suprlocoo, suprloco, suprloco, suprloco, suprloco_state, init_suprloco, ROT0, "Sega", "Super Locomotive", MACHINE_SUPPORTS_SAVE )
|
||||
|
@ -1,60 +0,0 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Zsolt Vasvari
|
||||
#ifndef MAME_INCLUDES_SUPRLOCO_H
|
||||
#define MAME_INCLUDES_SUPRLOCO_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "emupal.h"
|
||||
#include "tilemap.h"
|
||||
|
||||
class suprloco_state : public driver_device
|
||||
{
|
||||
public:
|
||||
suprloco_state(const machine_config &mconfig, device_type type, const char *tag) :
|
||||
driver_device(mconfig, type, tag),
|
||||
m_maincpu(*this, "maincpu"),
|
||||
m_audiocpu(*this, "audiocpu"),
|
||||
m_gfxdecode(*this, "gfxdecode"),
|
||||
m_spriteram(*this, "spriteram"),
|
||||
m_videoram(*this, "videoram"),
|
||||
m_scrollram(*this, "scrollram"),
|
||||
m_decrypted_opcodes(*this, "decrypted_opcodes")
|
||||
{ }
|
||||
|
||||
void suprloco(machine_config &config);
|
||||
|
||||
void init_suprloco();
|
||||
|
||||
private:
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<cpu_device> m_audiocpu;
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
|
||||
required_shared_ptr<uint8_t> m_spriteram;
|
||||
required_shared_ptr<uint8_t> m_videoram;
|
||||
required_shared_ptr<uint8_t> m_scrollram;
|
||||
required_shared_ptr<uint8_t> m_decrypted_opcodes;
|
||||
|
||||
tilemap_t *m_bg_tilemap = nullptr;
|
||||
int m_control = 0;
|
||||
|
||||
void videoram_w(offs_t offset, uint8_t data);
|
||||
void scrollram_w(offs_t offset, uint8_t data);
|
||||
void control_w(uint8_t data);
|
||||
|
||||
TILE_GET_INFO_MEMBER(get_tile_info);
|
||||
|
||||
virtual void video_start() override;
|
||||
void suprloco_palette(palette_device &palette) const;
|
||||
|
||||
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
inline void draw_pixel(bitmap_ind16 &bitmap,const rectangle &cliprect,int x,int y,int color,int flip);
|
||||
void draw_sprite(bitmap_ind16 &bitmap,const rectangle &cliprect,int spr_number);
|
||||
void draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
void decrypted_opcodes_map(address_map &map);
|
||||
void main_map(address_map &map);
|
||||
void sound_map(address_map &map);
|
||||
};
|
||||
|
||||
#endif // MAME_INCLUDES_SUPRLOCO_H
|
@ -1,256 +0,0 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Zsolt Vasvari
|
||||
/***************************************************************************
|
||||
|
||||
suprloco.c
|
||||
|
||||
Functions to emulate the video hardware of the machine.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "suprloco.h"
|
||||
|
||||
|
||||
|
||||
#define SPR_Y_TOP 0
|
||||
#define SPR_Y_BOTTOM 1
|
||||
#define SPR_X 2
|
||||
#define SPR_COL 3
|
||||
#define SPR_SKIP_LO 4
|
||||
#define SPR_SKIP_HI 5
|
||||
#define SPR_GFXOFS_LO 6
|
||||
#define SPR_GFXOFS_HI 7
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
Convert the color PROMs into a more useable format.
|
||||
|
||||
I'm not sure about the resistor values, I'm using the Galaxian ones.
|
||||
|
||||
***************************************************************************/
|
||||
void suprloco_state::suprloco_palette(palette_device &palette) const
|
||||
{
|
||||
const uint8_t *color_prom = memregion("proms")->base();
|
||||
|
||||
for (int i = 0; i < 512; i++)
|
||||
{
|
||||
int bit0, bit1, bit2;
|
||||
|
||||
// red component
|
||||
bit0 = BIT(color_prom[i], 0);
|
||||
bit1 = BIT(color_prom[i], 1);
|
||||
bit2 = BIT(color_prom[i], 2);
|
||||
int const r = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
|
||||
// green component
|
||||
bit0 = BIT(color_prom[i], 3);
|
||||
bit1 = BIT(color_prom[i], 4);
|
||||
bit2 = BIT(color_prom[i], 5);
|
||||
int const g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
|
||||
// blue component
|
||||
bit0 = 0;
|
||||
bit1 = BIT(color_prom[i], 6);
|
||||
bit2 = BIT(color_prom[i], 7);
|
||||
int const b = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
|
||||
|
||||
palette.set_pen_color(i, rgb_t(r, g, b));
|
||||
|
||||
// hack: generate a second bank of sprite palette with red changed to purple
|
||||
if (i >= 256)
|
||||
palette.set_pen_color(i + 256, rgb_t(r, g, ((i & 0x0f) == 0x09) ? 0xff : b));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
Callbacks for the TileMap code
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
TILE_GET_INFO_MEMBER(suprloco_state::get_tile_info)
|
||||
{
|
||||
uint8_t attr = m_videoram[2*tile_index+1];
|
||||
tileinfo.set(0,
|
||||
m_videoram[2*tile_index] | ((attr & 0x03) << 8),
|
||||
(attr & 0x1c) >> 2,
|
||||
0);
|
||||
tileinfo.category = (attr & 0x20) >> 5;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
Start the video hardware emulation.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
void suprloco_state::video_start()
|
||||
{
|
||||
m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(suprloco_state::get_tile_info)), TILEMAP_SCAN_ROWS, 8,8, 32,32);
|
||||
|
||||
m_bg_tilemap->set_scroll_rows(32);
|
||||
|
||||
save_item(NAME(m_control));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
Memory handlers
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
void suprloco_state::videoram_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
m_videoram[offset] = data;
|
||||
m_bg_tilemap->mark_tile_dirty(offset/2);
|
||||
}
|
||||
|
||||
void suprloco_state::scrollram_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
int adj = flip_screen() ? -8 : 8;
|
||||
|
||||
m_scrollram[offset] = data;
|
||||
m_bg_tilemap->set_scrollx(offset, data - adj);
|
||||
}
|
||||
|
||||
void suprloco_state::control_w(uint8_t data)
|
||||
{
|
||||
/* There is probably a palette select in here */
|
||||
|
||||
/* Bit 0 - coin counter A */
|
||||
/* Bit 1 - coin counter B (only used if coinage differs from A) */
|
||||
/* Bit 2-3 - probably unused */
|
||||
/* Bit 4 - ??? */
|
||||
/* Bit 5 - pulsated when loco turns "super" */
|
||||
/* Bit 6 - probably unused */
|
||||
/* Bit 7 - flip screen */
|
||||
|
||||
if ((m_control & 0x10) != (data & 0x10))
|
||||
{
|
||||
/*logerror("Bit 4 = %d\n", (data >> 4) & 1); */
|
||||
}
|
||||
|
||||
machine().bookkeeping().coin_counter_w(0, data & 0x01);
|
||||
machine().bookkeeping().coin_counter_w(1, data & 0x02);
|
||||
|
||||
flip_screen_set(data & 0x80);
|
||||
|
||||
m_control = data;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline void suprloco_state::draw_pixel(bitmap_ind16 &bitmap,const rectangle &cliprect,int x,int y,int color,int flip)
|
||||
{
|
||||
if (flip)
|
||||
{
|
||||
x = bitmap.width() - x - 1;
|
||||
y = bitmap.height() - y - 1;
|
||||
}
|
||||
|
||||
if (cliprect.contains(x, y))
|
||||
bitmap.pix(y, x) = color;
|
||||
}
|
||||
|
||||
|
||||
void suprloco_state::draw_sprite(bitmap_ind16 &bitmap,const rectangle &cliprect,int spr_number)
|
||||
{
|
||||
int flip = flip_screen();
|
||||
int sx,sy,col,row,height,src,adjy,dy;
|
||||
uint8_t *spr_reg;
|
||||
uint8_t *gfx2;
|
||||
pen_t pen_base;
|
||||
short skip; /* bytes to skip before drawing each row (can be negative) */
|
||||
|
||||
|
||||
spr_reg = m_spriteram + 0x10 * spr_number;
|
||||
|
||||
src = spr_reg[SPR_GFXOFS_LO] + (spr_reg[SPR_GFXOFS_HI] << 8);
|
||||
skip = spr_reg[SPR_SKIP_LO] + (spr_reg[SPR_SKIP_HI] << 8);
|
||||
|
||||
height = spr_reg[SPR_Y_BOTTOM] - spr_reg[SPR_Y_TOP];
|
||||
pen_base = 0x100 + 0x10 * (spr_reg[SPR_COL]&0x03) + ((m_control & 0x20)?0x100:0);
|
||||
sx = spr_reg[SPR_X];
|
||||
sy = spr_reg[SPR_Y_TOP] + 1;
|
||||
|
||||
if (!flip_screen())
|
||||
{
|
||||
adjy = sy;
|
||||
dy = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
adjy = sy + height - 1; /* some of the sprites are still off by a pixel */
|
||||
dy = -1;
|
||||
}
|
||||
|
||||
gfx2 = memregion("gfx2")->base();
|
||||
for (row = 0;row < height;row++,adjy+=dy)
|
||||
{
|
||||
int color1,color2,flipx;
|
||||
uint8_t data;
|
||||
uint8_t *gfx;
|
||||
|
||||
src += skip;
|
||||
|
||||
col = 0;
|
||||
|
||||
/* get pointer to packed sprite data */
|
||||
gfx = &(gfx2[src & 0x7fff]);
|
||||
flipx = src & 0x8000; /* flip x */
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (flipx) /* flip x */
|
||||
{
|
||||
data = *gfx--;
|
||||
color1 = data & 0x0f;
|
||||
color2 = data >> 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
data = *gfx++;
|
||||
color1 = data >> 4;
|
||||
color2 = data & 0x0f;
|
||||
}
|
||||
|
||||
if (color1 == 15) break;
|
||||
if (color1)
|
||||
draw_pixel(bitmap,cliprect,sx+col, adjy,pen_base + color1, flip);
|
||||
|
||||
if (color2 == 15) break;
|
||||
if (color2)
|
||||
draw_pixel(bitmap,cliprect,sx+col+1,adjy,pen_base + color2, flip);
|
||||
|
||||
col += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void suprloco_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
int spr_number;
|
||||
uint8_t *spr_reg;
|
||||
|
||||
|
||||
for (spr_number = 0;spr_number < (m_spriteram.bytes() >> 4);spr_number++)
|
||||
{
|
||||
spr_reg = m_spriteram + 0x10 * spr_number;
|
||||
if (spr_reg[SPR_X] != 0xff)
|
||||
draw_sprite(bitmap, cliprect, spr_number);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t suprloco_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
m_bg_tilemap->draw(screen, bitmap, cliprect, 0,0);
|
||||
draw_sprites(bitmap,cliprect);
|
||||
m_bg_tilemap->draw(screen, bitmap, cliprect, 1,0);
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user