Various ST0016 updates, Especially sound and interface functions (#8686)

* sound/st0016.cpp: Fix sound pitch, related to CPU clock
use struct for each voices, Minor fix in sample position, use device_memory_interface for fetching sample behavior, Add notes
machine/st0016.cpp: Use seperated address space for character RAM space, use device_video_interface for screen finder, use device_mixer_interface for sound output instead preinstalled speaker device, Fix spacing, Add notes, Use shorter/correct type values
speglsht.cpp, srmp5.cpp: Fix ST0016 clock (these are hasn't 8MHz or 48MHz XTAL), Fix naming
speglsht.cpp: Fix 1 pixel gap in ST0016 layer
srmp5.cpp: Reduce unnecessary line

* simple_st0016.cpp: Add notes of CPU clock
This commit is contained in:
cam900 2021-10-24 04:43:21 +09:00 committed by GitHub
parent 669b1f6ade
commit 71bfb683e7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 585 additions and 413 deletions

View File

@ -3,6 +3,9 @@
/************************************
Seta custom ST-0016 chip
sound emulation by R. Belmont, Tomasz Slanina, and David Haywood
TODO:
- Verify keyon/off flag behavior
************************************/
#include "emu.h"
@ -27,13 +30,10 @@ DEFINE_DEVICE_TYPE(ST0016, st0016_device, "st0016", "Seta ST0016 (Audio)")
st0016_device::st0016_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, ST0016, tag, owner, clock)
, device_sound_interface(mconfig, *this)
, device_memory_interface(mconfig, *this)
, m_data_config("data", ENDIANNESS_LITTLE, 8, 21) // shares character RAM area?
, m_stream(nullptr)
, m_ram_read_cb(*this)
, m_vpos{ 0, 0, 0, 0, 0, 0, 0, 0 }
, m_frac{ 0, 0, 0, 0, 0, 0, 0, 0 }
, m_lponce{ 0, 0, 0, 0, 0, 0, 0, 0 }
{
std::fill(std::begin(m_regs), std::end(m_regs), 0);
}
@ -43,13 +43,29 @@ st0016_device::st0016_device(const machine_config &mconfig, const char *tag, dev
void st0016_device::device_start()
{
m_stream = stream_alloc(0, 2, 44100);
m_ram_read_cb.resolve_safe(0);
// Find our direct access
space(0).cache(m_cache);
save_item(NAME(m_vpos));
save_item(NAME(m_frac));
save_item(NAME(m_lponce));
save_item(NAME(m_regs));
// allocate stream
m_stream = stream_alloc(0, 2, clock() / 128);
// set host device to each voices
for (auto & elem : m_voice)
elem.m_host = m_cache;
save_item(STRUCT_MEMBER(m_voice, m_regs));
save_item(STRUCT_MEMBER(m_voice, m_start));
save_item(STRUCT_MEMBER(m_voice, m_end));
save_item(STRUCT_MEMBER(m_voice, m_lpstart));
save_item(STRUCT_MEMBER(m_voice, m_lpend));
save_item(STRUCT_MEMBER(m_voice, m_freq));
save_item(STRUCT_MEMBER(m_voice, m_vol_l));
save_item(STRUCT_MEMBER(m_voice, m_vol_r));
save_item(STRUCT_MEMBER(m_voice, m_flags));
save_item(STRUCT_MEMBER(m_voice, m_pos));
save_item(STRUCT_MEMBER(m_voice, m_frac));
save_item(STRUCT_MEMBER(m_voice, m_lponce));
save_item(STRUCT_MEMBER(m_voice, m_out));
}
@ -59,106 +75,179 @@ void st0016_device::device_start()
void st0016_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
{
int v, i, snum;
unsigned char *slot;
int32_t mix[48000*2];
int32_t *mixp;
int16_t sample;
int sptr, eptr, freq, lsptr, leptr;
outputs[0].fill(0);
outputs[1].fill(0);
memset(mix, 0, sizeof(mix[0])*outputs[0].samples()*2);
for (v = 0; v < 8; v++)
for (int sampleind = 0; sampleind < outputs[0].samples(); sampleind++)
{
slot = (unsigned char *)&m_regs[v * 32];
if (slot[0x16] & 0x06)
for (int v = 0; v < 8; v++)
{
mixp = &mix[0];
sptr = slot[0x02]<<16 | slot[0x01]<<8 | slot[0x00];
eptr = slot[0x0e]<<16 | slot[0x0d]<<8 | slot[0x0c];
freq = slot[0x11]<<8 | slot[0x10];
lsptr = slot[0x06]<<16 | slot[0x05]<<8 | slot[0x04];
leptr = slot[0x0a]<<16 | slot[0x09]<<8 | slot[0x08];
for (snum = 0; snum < outputs[0].samples(); snum++)
// check if voice is activated
if (m_voice[v].update())
{
sample = m_ram_read_cb((sptr + m_vpos[v]) & 0x1fffff) << 8;
*mixp++ += (sample * (char)slot[0x14]) >> 8;
*mixp++ += (sample * (char)slot[0x15]) >> 8;
m_frac[v] += freq;
m_vpos[v] += (m_frac[v]>>16);
m_frac[v] &= 0xffff;
// stop if we're at the end
if (m_lponce[v])
{
// we've looped once, check loop end rather than sample end
if ((m_vpos[v] + sptr) >= leptr)
{
m_vpos[v] = (lsptr - sptr);
}
}
else
{
// not looped yet, check sample end
if ((m_vpos[v] + sptr) >= eptr)
{
if (slot[0x16] & 0x01) // loop?
{
m_vpos[v] = (lsptr - sptr);
m_lponce[v] = 1;
}
else
{
slot[0x16] = 0;
m_vpos[v] = m_frac[v] = 0;
}
}
}
outputs[0].add_int(sampleind, (m_voice[v].m_out * m_voice[v].m_vol_l) >> 8, 32768 << 4);
outputs[1].add_int(sampleind, (m_voice[v].m_out * m_voice[v].m_vol_r) >> 8, 32768 << 4);
}
}
}
}
mixp = &mix[0];
for (i = 0; i < outputs[0].samples(); i++)
//-------------------------------------------------
// memory_space_config - return a description of
// any address spaces owned by this device
//-------------------------------------------------
device_memory_interface::space_config_vector st0016_device::memory_space_config() const
{
return space_config_vector{ std::make_pair(0, &m_data_config) };
}
//-------------------------------------------------
// update - update single voice
//-------------------------------------------------
bool st0016_device::voice_t::update()
{
if (m_flags & 0x06) // TODO: keyon flag?
{
outputs[0].put_int(i, *mixp++, 32768<<4);
outputs[1].put_int(i, *mixp++, 32768<<4);
m_out = s16(s8(m_host.read_byte(m_pos & 0x1fffff))) << 8;
m_frac += m_freq;
m_pos += (m_frac >> 16);
m_frac &= 0xffff;
// stop if we're at the end
if (m_lponce)
{
// we've looped once, check loop end rather than sample end
if (m_pos >= m_lpend)
{
m_pos = m_lpstart;
}
}
else
{
// not looped yet, check sample end
if (m_pos >= m_end)
{
if (BIT(m_flags, 0)) // loop?
{
m_pos = m_lpstart;
m_lponce = true;
}
else
{
m_flags = 0;
m_pos = m_frac = 0;
}
}
}
return true;
}
else
{
m_out = 0;
return false;
}
}
//-------------------------------------------------
// snd_r - read sound registers
//-------------------------------------------------
uint8_t st0016_device::snd_r(offs_t offset)
u8 st0016_device::snd_r(offs_t offset)
{
return m_regs[offset];
if (offset < 0x100)
{
m_stream->update();
return m_voice[offset >> 5].reg_r(offset & 0x1f);
}
return 0;
}
void st0016_device::snd_w(offs_t offset, uint8_t data)
//-------------------------------------------------
// snd_w - write sound registers
//-------------------------------------------------
void st0016_device::snd_w(offs_t offset, u8 data)
{
int voice = offset/32;
int reg = offset & 0x1f;
int oldreg = m_regs[offset];
int vbase = offset & ~0x1f;
if (offset < 0x100)
{
m_stream->update();
m_voice[offset >> 5].reg_w(offset & 0x1f, data, offset >> 5);
}
}
//-------------------------------------------------
// reg_r - read single voice registers
//-------------------------------------------------
u8 st0016_device::voice_t::reg_r(offs_t offset)
{
return m_regs[offset & 0x1f];
}
//-------------------------------------------------
// reg_w - write single voice registers
//-------------------------------------------------
void st0016_device::voice_t::reg_w(offs_t offset, u8 data, int voice)
{
offset &= 0x1f;
m_regs[offset] = data;
if ((voice < 8) && (data != oldreg))
switch (offset)
{
if ((reg == 0x16) && (data != 0))
case 0x00: // Start position bit 0-7
case 0x01: // Start position bit 8-15
case 0x02: // Start position bit 16-23
m_start = (m_regs[0x02] << 16) | (m_regs[0x01] << 8) | m_regs[0x00];
break;
case 0x04: // Loop start position bit 0-7
case 0x05: // Loop start position bit 8-15
case 0x06: // Loop start position bit 16-23
m_lpstart = (m_regs[0x06] << 16) | (m_regs[0x05] << 8) | m_regs[0x04];
break;
case 0x08: // Loop end position bit 0-7
case 0x09: // Loop end position bit 8-15
case 0x0a: // Loop end position bit 16-23
m_lpend = (m_regs[0x0a] << 16) | (m_regs[0x09] << 8) | m_regs[0x08];
break;
case 0x0c: // End position bit 0-7
case 0x0d: // End position bit 8-15
case 0x0e: // End position bit 16-23
m_end = (m_regs[0x0e] << 16) | (m_regs[0x0d] << 8) | m_regs[0x0c];
break;
case 0x10: // Frequency bit 0-7
case 0x11: // Frequency bit 8-15
m_freq = (m_regs[0x11] << 8) | m_regs[0x10];
break;
case 0x14: // Left volume
m_vol_l = (char)data;
break;
case 0x15: // Right volume
m_vol_r = (char)data;
break;
case 0x16:
if (data != m_flags)
{
m_vpos[voice] = m_frac[voice] = m_lponce[voice] = 0;
if (data != 0)
{
m_pos = m_start;
m_frac = 0;
m_lponce = false;
LOG("Key on V%02d: st %06x-%06x lp %06x-%06x frq %x flg %x\n", voice,
m_regs[vbase+2]<<16 | m_regs[vbase+1]<<8 | m_regs[vbase+2],
m_regs[vbase+0xe]<<16 | m_regs[vbase+0xd]<<8 | m_regs[vbase+0xc],
m_regs[vbase+6]<<16 | m_regs[vbase+5]<<8 | m_regs[vbase+4],
m_regs[vbase+0xa]<<16 | m_regs[vbase+0x9]<<8 | m_regs[vbase+0x8],
m_regs[vbase+0x11]<<8 | m_regs[vbase+0x10],
m_regs[vbase+0x16]);
/*
LOG("Key on V%02d: st %06x-%06x lp %06x-%06x frq %x flg %x\n", voice,
m_start,
m_end,
m_lpstart,
m_lpend,
m_freq,
m_regs[0x16]);
*/
}
}
m_flags = m_regs[0x16];
break;
}
}

View File

@ -12,15 +12,13 @@
// ======================> st0016_device
class st0016_device : public device_t, public device_sound_interface
class st0016_device : public device_t, public device_sound_interface, public device_memory_interface
{
public:
st0016_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
auto ram_read() { return m_ram_read_cb.bind(); }
uint8_t snd_r(offs_t offset);
void snd_w(offs_t offset, uint8_t data);
u8 snd_r(offs_t offset);
void snd_w(offs_t offset, u8 data);
protected:
// device-level overrides
@ -29,13 +27,38 @@ protected:
// sound stream update overrides
virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override;
// device_memory_interface configuration
virtual space_config_vector memory_space_config() const override;
address_space_config m_data_config;
private:
struct voice_t
{
bool update();
u8 reg_r(offs_t offset);
void reg_w(offs_t offset, u8 data, int voice);
memory_access<21, 0, 0, ENDIANNESS_LITTLE>::cache m_host; // host device
u8 m_regs[0x20] = {0}; // 32 registers per voices
u32 m_start = 0; // Start position
u32 m_end = 0; // End position
u32 m_lpstart = 0; // Loop start position
u32 m_lpend = 0; // Loop end position
u16 m_freq = 0; // Frequency (.16 fixed point)
char m_vol_l = 0; // Left volume
char m_vol_r = 0; // Right volume
u8 m_flags = 0; // Flags
u32 m_pos = 0; // Current position
u32 m_frac = 0; // Position fraction
bool m_lponce = false; // Is looped once?
s16 m_out = 0; // output value
};
memory_access<21, 0, 0, ENDIANNESS_LITTLE>::cache m_cache;
sound_stream *m_stream;
devcb_read8 m_ram_read_cb;
int m_vpos[8];
int m_frac[8];
int m_lponce[8];
uint8_t m_regs[0x100];
voice_t m_voice[8]; // 8 Voice engines
};
DECLARE_DEVICE_TYPE(ST0016, st0016_device)

View File

@ -191,7 +191,7 @@ public:
m_soundbank(*this, "soundbank")
{ }
required_device<cpu_device> m_soundcpu;
required_device<st0016_cpu_device> m_soundcpu;
required_memory_bank m_soundbank;
void eeprom_s29290_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
@ -1177,6 +1177,13 @@ void jclub2o_state::jclub2o(machine_config &config)
// layout
config.set_default_layout(layout_jclub2o);
// TODO: Mono?
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
m_soundcpu->add_route(0, "lspeaker", 1.0);
m_soundcpu->add_route(1, "rspeaker", 1.0);
}

View File

@ -62,6 +62,7 @@ KISEKAE -- info
#include "bus/generic/slot.h"
#include "bus/generic/carts.h"
#include "speaker.h"
class macs_state : public driver_device
{
@ -509,6 +510,7 @@ void macs_state::macs(machine_config &config)
m_maincpu->set_memory_map(&macs_state::macs_mem);
m_maincpu->set_io_map(&macs_state::macs_io);
m_maincpu->set_dma_offs_callback(FUNC(macs_state::dma_offset));
m_maincpu->set_screen("screen");
/* video hardware */
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
@ -526,6 +528,13 @@ void macs_state::macs(machine_config &config)
generic_cartslot_device &slot_b(GENERIC_CARTSLOT(config, "slot_b", generic_plain_slot, "macs_cart"));
slot_b.set_default_option("rom");
slot_b.set_user_loadable(false);
// TODO: Mono?
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
m_maincpu->add_route(0, "lspeaker", 1.0);
m_maincpu->add_route(1, "rspeaker", 1.0);
}

View File

@ -25,6 +25,7 @@ Dips verified for Neratte Chu (nratechu) from manual
#include "machine/timer.h"
#include "sound/st0016.h"
#include "screen.h"
#include "speaker.h"
namespace {
@ -533,9 +534,10 @@ uint32_t st0016_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap
void st0016_state::st0016(machine_config &config)
{
// basic machine hardware
ST0016_CPU(config, m_maincpu, 8000000); // 8 MHz ?
ST0016_CPU(config, m_maincpu, XTAL(48'000'000) / 6); // 8 MHz (48 MHz / 6) verified from nratechu (https://www.youtube.com/watch?v=scKF95t4-lU)
m_maincpu->set_addrmap(AS_PROGRAM, &st0016_state::st0016_mem);
m_maincpu->set_addrmap(AS_IO, &st0016_state::st0016_io);
m_maincpu->set_screen(m_screen);
TIMER(config, "scantimer").configure_scanline(FUNC(st0016_state::interrupt), "screen", 0, 1);
@ -547,6 +549,13 @@ void st0016_state::st0016(machine_config &config)
m_screen->set_visarea(0*8, 48*8-1, 0*8, 48*8-1);
m_screen->set_screen_update(FUNC(st0016_state::screen_update));
m_screen->set_palette("maincpu:palette");
// TODO: Mono?
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
m_maincpu->add_route(0, "lspeaker", 1.0);
m_maincpu->add_route(1, "rspeaker", 1.0);
}
void st0016_state::mayjinsn(machine_config &config)

View File

@ -109,6 +109,7 @@ Notes:
#include "emupal.h"
#include "machine/st0016.h"
#include "cpu/mips/mips1.h"
#include "speaker.h"
#include <algorithm>
namespace {
@ -157,7 +158,7 @@ private:
uint32_t cop_r(offs_t offset);
uint32_t irq_ack_clear();
uint32_t screen_update_speglsht(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
void st0016_rom_bank_w(uint8_t data);
void speglsht_mem(address_map &map);
@ -380,7 +381,7 @@ void speglsht_state::video_start()
bitmap.pix(y, x) = (b) | ((g)<<8) | ((r)<<16); \
}
uint32_t speglsht_state::screen_update_speglsht(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
uint32_t speglsht_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
int dy=(m_videoreg&0x20)?(256*512):0; //visible frame
@ -398,10 +399,10 @@ uint32_t speglsht_state::screen_update_speglsht(screen_device &screen, bitmap_rg
m_maincpu->draw_screen(screen, *m_bitmap, cliprect);
//copy temporary bitmap to rgb 32 bit bitmap
for(int y=cliprect.min_y; y<cliprect.max_y;y++)
for(int y=cliprect.min_y; y<=cliprect.max_y;y++)
{
uint16_t const *const srcline = &m_bitmap->pix(y);
for(int x=cliprect.min_x; x<cliprect.max_x;x++)
for(int x=cliprect.min_x; x<=cliprect.max_x;x++)
{
if(srcline[x])
{
@ -417,12 +418,13 @@ uint32_t speglsht_state::screen_update_speglsht(screen_device &screen, bitmap_rg
void speglsht_state::speglsht(machine_config &config)
{
/* basic machine hardware */
ST0016_CPU(config, m_maincpu, 8000000); /* 8 MHz ? */
ST0016_CPU(config, m_maincpu, XTAL(42'954'545) / 6); // 7.159 MHz (42.9545 MHz / 6)
m_maincpu->set_addrmap(AS_PROGRAM, &speglsht_state::st0016_mem);
m_maincpu->set_addrmap(AS_IO, &speglsht_state::st0016_io);
m_maincpu->set_vblank_int("screen", FUNC(speglsht_state::irq0_line_hold));
m_maincpu->set_screen("screen");
R3051(config, m_subcpu, 25000000);
R3051(config, m_subcpu, XTAL(50'000'000) / 2); // 25 MHz (50 MHz / 2)
m_subcpu->set_endianness(ENDIANNESS_LITTLE);
m_subcpu->set_addrmap(AS_PROGRAM, &speglsht_state::speglsht_mem);
m_subcpu->set_vblank_int("screen", FUNC(speglsht_state::irq4_line_assert));
@ -435,10 +437,17 @@ void speglsht_state::speglsht(machine_config &config)
screen.set_vblank_time(ATTOSECONDS_IN_USEC(0));
screen.set_size(512, 512);
screen.set_visarea(0, 319, 8, 239-8);
screen.set_screen_update(FUNC(speglsht_state::screen_update_speglsht));
screen.set_screen_update(FUNC(speglsht_state::screen_update));
GFXDECODE(config, "gfxdecode", m_palette, gfx_speglsht);
PALETTE(config, m_palette).set_entries(16*16*4+1);
// TODO: Mono?
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
m_maincpu->add_route(0, "lspeaker", 1.0);
m_maincpu->add_route(1, "rspeaker", 1.0);
}
ROM_START( speglsht )

View File

@ -40,6 +40,7 @@ This is not a bug (real machine behaves the same).
#include "machine/st0016.h"
#include "cpu/mips/mips1.h"
#include "emupal.h"
#include "speaker.h"
#define DEBUG_CHAR
@ -126,7 +127,7 @@ private:
uint8_t cmd2_r();
uint8_t cmd_stat8_r();
virtual void machine_start() override;
uint32_t screen_update_srmp5(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
void st0016_rom_bank_w(uint8_t data);
void srmp5_mem(address_map &map);
@ -135,7 +136,7 @@ private:
};
uint32_t srmp5_state::screen_update_srmp5(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
uint32_t srmp5_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
int address,height,width,sizex,sizey;
uint16_t *sprite_list=m_sprram.get();
@ -568,12 +569,12 @@ GFXDECODE_END
void srmp5_state::srmp5(machine_config &config)
{
/* basic machine hardware */
R3051(config, m_maincpu, 25000000);
R3051(config, m_maincpu, XTAL(50'000'000) / 2); // 25 MHz (50 MHz / 2)
m_maincpu->set_endianness(ENDIANNESS_LITTLE);
m_maincpu->set_addrmap(AS_PROGRAM, &srmp5_state::srmp5_mem);
m_maincpu->set_vblank_int("screen", FUNC(srmp5_state::irq4_line_assert));
ST0016_CPU(config, m_soundcpu, 8000000);
ST0016_CPU(config, m_soundcpu, XTAL(42'954'545) / 6); // 7.159 MHz (42.9545 MHz / 6)
m_soundcpu->set_addrmap(AS_PROGRAM, &srmp5_state::st0016_mem);
m_soundcpu->set_addrmap(AS_IO, &srmp5_state::st0016_io);
m_soundcpu->set_vblank_int("screen", FUNC(srmp5_state::irq0_line_hold));
@ -585,7 +586,7 @@ void srmp5_state::srmp5(machine_config &config)
screen.set_refresh_hz(60);
screen.set_size(96*8, 64*8);
screen.set_visarea(0*8, 42*8-1, 2*8, 32*8-1);
screen.set_screen_update(FUNC(srmp5_state::screen_update_srmp5));
screen.set_screen_update(FUNC(srmp5_state::screen_update));
PALETTE(config, m_palette).set_format(palette_device::xBGR_555, 0x10000); // 0x20000? only first 0x1800 entries seem to be used outside memory test
m_palette->set_membits(16);
@ -593,6 +594,13 @@ void srmp5_state::srmp5(machine_config &config)
#ifdef DEBUG_CHAR
GFXDECODE(config, m_gfxdecode, m_palette, gfx_srmp5);
#endif
// TODO: Mono?
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
m_soundcpu->add_route(0, "lspeaker", 1.0);
m_soundcpu->add_route(1, "rspeaker", 1.0);
}
@ -623,8 +631,6 @@ ROM_END
void srmp5_state::init_srmp5()
{
m_soundcpu->set_game_flag(9);
m_tileram = std::make_unique<uint16_t[]>(0x100000/2);
m_sprram = std::make_unique<uint16_t[]>(0x080000/2);
#ifdef DEBUG_CHAR

View File

@ -5,7 +5,6 @@
#include "emu.h"
#include "st0016.h"
#include "emupal.h"
#include "speaker.h"
#include <algorithm>
@ -14,58 +13,78 @@ DEFINE_DEVICE_TYPE(ST0016_CPU, st0016_cpu_device, "st0016_cpu", "ST0016")
void st0016_cpu_device::cpu_internal_map(address_map &map)
{
//map(0x0000, 0x7fff).rom(); ROM, Fixed area
//map(0x8000, 0xbfff).bankr("rombank"); ROM, Bankswitched area
map(0xc000, 0xcfff).r(FUNC(st0016_cpu_device::sprite_ram_r)).w(FUNC(st0016_cpu_device::sprite_ram_w));
map(0xd000, 0xdfff).r(FUNC(st0016_cpu_device::sprite2_ram_r)).w(FUNC(st0016_cpu_device::sprite2_ram_w));
//map(0xe000, 0xe8ff).ram(); External area, commonly RAM
map(0xe900, 0xe9ff).rw("stsnd", FUNC(st0016_device::snd_r), FUNC(st0016_device::snd_w)); // sound regs 8 x $20 bytes, see notes
map(0xea00, 0xebff).r(FUNC(st0016_cpu_device::palette_ram_r)).w(FUNC(st0016_cpu_device::palette_ram_w));
map(0xec00, 0xec1f).r(FUNC(st0016_cpu_device::character_ram_r)).w(FUNC(st0016_cpu_device::character_ram_w));
map(0xe900, 0xe9ff).rw("stsnd", FUNC(st0016_device::snd_r), FUNC(st0016_device::snd_w)); /* sound regs 8 x $20 bytes, see notes */
map(0xec00, 0xec1f).r(FUNC(st0016_cpu_device::charam_bank_r)).w(FUNC(st0016_cpu_device::charam_bank_w));
//map(0xf000, 0xffff).ram(); External area, commonly RAM
}
void st0016_cpu_device::cpu_internal_io_map(address_map &map)
{
map.global_mask(0xff);
map(0x00, 0xbf).r(FUNC(st0016_cpu_device::vregs_r)).w(FUNC(st0016_cpu_device::vregs_w)); /* video/crt regs ? */
map(0x00, 0xbf).r(FUNC(st0016_cpu_device::vregs_r)).w(FUNC(st0016_cpu_device::vregs_w)); // video/crt regs ?
//map(0xe1, 0xe1) ROM bank
map(0xe2, 0xe2).w(FUNC(st0016_cpu_device::sprite_bank_w));
map(0xe3, 0xe4).w(FUNC(st0016_cpu_device::character_bank_w));
map(0xe5, 0xe5).w(FUNC(st0016_cpu_device::palette_bank_w));
map(0xf0, 0xf0).r(FUNC(st0016_cpu_device::dma_r));
}
// note: a lot of bits are left uninitialized by the games, the default values are uncertain
st0016_cpu_device::st0016_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: z80_device(mconfig, ST0016_CPU, tag, owner, clock)
, device_gfx_interface(mconfig, *this, nullptr, "palette")
, spr_bank(0)
, spr2_bank(0)
, pal_bank(0)
, char_bank(0)
, spr_dx(0)
, spr_dy(0)
, ramgfx(0)
, m_io_space_config("io", ENDIANNESS_LITTLE, 8, 16, 0, address_map_constructor(FUNC(st0016_cpu_device::cpu_internal_io_map), this))
, m_space_config("regs", ENDIANNESS_LITTLE, 8, 16, 0, address_map_constructor(FUNC(st0016_cpu_device::cpu_internal_map), this))
, m_screen(*this, ":screen")
, m_rom(*this, DEVICE_SELF)
, m_dma_offs_cb(*this)
, m_game_flag(-1)
void st0016_cpu_device::charam_map(address_map &map)
{
std::fill(std::begin(vregs), std::end(vregs), 0);
map(0x000000, 0x1fffff).rw(FUNC(st0016_cpu_device::character_ram_r), FUNC(st0016_cpu_device::character_ram_w));
}
// note: a lot of bits are left uninitialized by the games, the default values are uncertain
st0016_cpu_device::st0016_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: z80_device(mconfig, ST0016_CPU, tag, owner, clock)
, device_gfx_interface(mconfig, *this, nullptr, "palette")
, device_video_interface(mconfig, *this, false)
, device_mixer_interface(mconfig, *this, 2)
, m_io_space_config("io", ENDIANNESS_LITTLE, 8, 16, 0, address_map_constructor(FUNC(st0016_cpu_device::cpu_internal_io_map), this))
, m_space_config("regs", ENDIANNESS_LITTLE, 8, 16, 0, address_map_constructor(FUNC(st0016_cpu_device::cpu_internal_map), this))
, m_charam_space_config("charam", ENDIANNESS_LITTLE, 8, 21, 0, address_map_constructor(FUNC(st0016_cpu_device::charam_map), this))
, m_rom(*this, DEVICE_SELF)
, m_spriteram(*this, "spriteram", 0x10000, ENDIANNESS_LITTLE)
, m_charram(*this, "charam", 0x200000, ENDIANNESS_LITTLE)
, m_paletteram(*this, "paletteram", 0x800, ENDIANNESS_LITTLE)
, m_dma_offs_cb(*this)
, m_game_flag(-1)
, m_spr_bank(0)
, m_spr2_bank(0)
, m_pal_bank(0)
, m_char_bank(0)
, m_spr_dx(0)
, m_spr_dy(0)
, m_ramgfx(0)
{
std::fill(std::begin(m_vregs), std::end(m_vregs), 0);
}
//-------------------------------------------------
// memory_space_config - return a description of
// any address spaces owned by this device
//-------------------------------------------------
device_memory_interface::space_config_vector st0016_cpu_device::memory_space_config() const
{
return space_config_vector {
std::make_pair(AS_PROGRAM, &m_space_config),
std::make_pair(AS_IO, &m_io_space_config)
std::make_pair(AS_IO, &m_io_space_config),
std::make_pair(AS_CHARAM, &m_charam_space_config)
};
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
@ -75,6 +94,7 @@ void st0016_cpu_device::device_start()
z80_device::device_start();
startup();
m_dma_offs_cb.resolve();
space(AS_CHARAM).specific(m_charam_space);
}
@ -85,53 +105,48 @@ void st0016_cpu_device::device_start()
void st0016_cpu_device::device_reset()
{
z80_device::device_reset();
switch (m_game_flag & 0x3f)
if (has_screen())
{
case 0: //renju kizoku
m_screen->set_visible_area(0, 40*8-1, 0, 30*8-1);
spr_dx=0;
spr_dy=0;
break;
// TODO: move these into driver file?
switch (m_game_flag & 0x3f)
{
case 0: // renju kizoku
screen().set_visible_area(0, 40*8-1, 0, 30*8-1);
m_spr_dx = 0;
m_spr_dy = 0;
break;
case 1: //neratte chu!
m_screen->set_visible_area(8,41*8-1,0,30*8-1);
spr_dx=0;
spr_dy=8;
break;
case 1: // neratte chu!
screen().set_visible_area(8,41*8-1,0,30*8-1);
m_spr_dx = 0;
m_spr_dy = 8;
break;
case 4: //mayjinsen 1&2
m_screen->set_visible_area(0,32*8-1,0,28*8-1);
break;
case 4: // mayjinsen 1&2
screen().set_visible_area(0,32*8-1,0,28*8-1);
break;
case 10:
m_screen->set_visible_area(0,383,0,255);
break;
case 10:
screen().set_visible_area(0,383,0,255);
break;
case 11:
m_screen->set_visible_area(0,383,0,383);
break;
case 11:
screen().set_visible_area(0,383,0,383);
break;
}
}
}
uint8_t st0016_cpu_device::soundram_read(offs_t offset)
{
return m_charram[offset];
}
/* CPU interface */
// CPU interface
void st0016_cpu_device::device_add_mconfig(machine_config &config)
{
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
PALETTE(config, "palette").set_entries(16 * 16 * 4 + 1);
PALETTE(config, "palette").set_entries(16*16*4+1);
st0016_device &stsnd(ST0016(config, "stsnd", 0));
stsnd.ram_read().set(FUNC(st0016_cpu_device::soundram_read));
stsnd.add_route(0, "lspeaker", 1.0);
stsnd.add_route(1, "rspeaker", 1.0);
st0016_device &stsnd(ST0016(config, "stsnd", DERIVED_CLOCK(1,1)));
stsnd.set_addrmap(0, &st0016_cpu_device::charam_map);
stsnd.add_route(0, *this, 1.0, AUTO_ALLOC_INPUT, 0);
stsnd.add_route(1, *this, 1.0, AUTO_ALLOC_INPUT, 1);
}
@ -146,91 +161,101 @@ static const gfx_layout charlayout =
8*8*4
};
void st0016_cpu_device::sprite_bank_w(uint8_t data)
void st0016_cpu_device::sprite_bank_w(u8 data)
{
/*
76543210
xxxx - spriteram bank1
xxxx - spriteram bank2
*/
spr_bank=data&SPR_BANK_MASK;
spr2_bank=(data>>4)&SPR_BANK_MASK;
m_spr_bank = data & SPR_BANK_MASK;
m_spr2_bank = (data >> 4) & SPR_BANK_MASK;
}
void st0016_cpu_device::palette_bank_w(uint8_t data)
void st0016_cpu_device::palette_bank_w(u8 data)
{
/*
76543210
xx - palram bank
xxxxxx - unknown/unused
*/
pal_bank=data&PAL_BANK_MASK;
m_pal_bank = data & PAL_BANK_MASK;
}
void st0016_cpu_device::character_bank_w(offs_t offset, uint8_t data)
void st0016_cpu_device::character_bank_w(offs_t offset, u8 data)
{
/*
fedcba9876543210
xxxxxxxxxxxxxxxx - character (bank )
*/
if(offset&1)
char_bank=(char_bank&0xff)|(data<<8);
if (offset & 1)
m_char_bank = (m_char_bank & 0xff) | (data << 8);
else
char_bank=(char_bank&0xff00)|data;
m_char_bank = (m_char_bank & 0xff00) | data;
char_bank&=CHAR_BANK_MASK;
m_char_bank &= CHAR_BANK_MASK;
}
uint8_t st0016_cpu_device::sprite_ram_r(offs_t offset)
u8 st0016_cpu_device::sprite_ram_r(offs_t offset)
{
return spriteram[SPR_BANK_SIZE*spr_bank+offset];
return m_spriteram[SPR_BANK_SIZE * m_spr_bank + offset];
}
void st0016_cpu_device::sprite_ram_w(offs_t offset, uint8_t data)
void st0016_cpu_device::sprite_ram_w(offs_t offset, u8 data)
{
spriteram[SPR_BANK_SIZE*spr_bank+offset]=data;
m_spriteram[SPR_BANK_SIZE * m_spr_bank + offset] = data;
}
uint8_t st0016_cpu_device::sprite2_ram_r(offs_t offset)
u8 st0016_cpu_device::sprite2_ram_r(offs_t offset)
{
return spriteram[SPR_BANK_SIZE*spr2_bank+offset];
return m_spriteram[SPR_BANK_SIZE * m_spr2_bank + offset];
}
void st0016_cpu_device::sprite2_ram_w(offs_t offset, uint8_t data)
void st0016_cpu_device::sprite2_ram_w(offs_t offset, u8 data)
{
spriteram[SPR_BANK_SIZE*spr2_bank+offset]=data;
m_spriteram[SPR_BANK_SIZE * m_spr2_bank + offset] = data;
}
uint8_t st0016_cpu_device::palette_ram_r(offs_t offset)
u8 st0016_cpu_device::palette_ram_r(offs_t offset)
{
return paletteram[PAL_BANK_SIZE*pal_bank+offset];
return m_paletteram[PAL_BANK_SIZE * m_pal_bank + offset];
}
void st0016_cpu_device::palette_ram_w(offs_t offset, uint8_t data)
void st0016_cpu_device::palette_ram_w(offs_t offset, u8 data)
{
int color=(PAL_BANK_SIZE*pal_bank+offset)/2;
int val;
paletteram[PAL_BANK_SIZE*pal_bank+offset]=data;
val=paletteram[color*2]+(paletteram[color*2+1]<<8);
if(!color)
palette().set_pen_color(UNUSED_PEN,pal5bit(val >> 0),pal5bit(val >> 5),pal5bit(val >> 10)); /* same as color 0 - bg ? */
palette().set_pen_color(color,pal5bit(val >> 0),pal5bit(val >> 5),pal5bit(val >> 10));
offset += PAL_BANK_SIZE * m_pal_bank;
const pen_t color = offset >> 1;
m_paletteram[offset] = data;
const u16 val = m_paletteram[offset & ~1] | (m_paletteram[offset | 1] << 8);
if (!color)
palette().set_pen_color(UNUSED_PEN, pal5bit(val >> 0), pal5bit(val >> 5), pal5bit(val >> 10)); // same as color 0 - bg ?
palette().set_pen_color(color, pal5bit(val >> 0), pal5bit(val >> 5), pal5bit(val >> 10));
}
uint8_t st0016_cpu_device::character_ram_r(offs_t offset)
u8 st0016_cpu_device::charam_bank_r(offs_t offset)
{
return m_charram[CHAR_BANK_SIZE*char_bank+offset];
return m_charam_space.read_byte(CHAR_BANK_SIZE * m_char_bank + offset);
}
void st0016_cpu_device::character_ram_w(offs_t offset, uint8_t data)
void st0016_cpu_device::charam_bank_w(offs_t offset, u8 data)
{
m_charram[CHAR_BANK_SIZE*char_bank+offset]=data;
gfx(ramgfx)->mark_dirty(char_bank);
m_charam_space.write_byte(CHAR_BANK_SIZE * m_char_bank + offset, data);
}
uint8_t st0016_cpu_device::vregs_r(offs_t offset)
u8 st0016_cpu_device::character_ram_r(offs_t offset)
{
return m_charram[offset];
}
void st0016_cpu_device::character_ram_w(offs_t offset, u8 data)
{
m_charram[offset] = data;
gfx(m_ramgfx)->mark_dirty(offset >> 5);
}
u8 st0016_cpu_device::vregs_r(offs_t offset)
{
/*
$0, $1 = max scanline(including vblank)/timer? ($3e7)
@ -255,20 +280,20 @@ uint8_t st0016_cpu_device::vregs_r(offs_t offset)
return machine().rand();
}
return vregs[offset];
return m_vregs[offset];
}
uint8_t st0016_cpu_device::dma_r()
u8 st0016_cpu_device::dma_r()
{
/* bits 0 and 1 = 0 -> DMA transfer complete */
if(ismacs())
// bits 0 and 1 = 0 -> DMA transfer complete
if (ismacs())
return 0;
else
return 0;
}
void st0016_cpu_device::vregs_w(offs_t offset, uint8_t data)
void st0016_cpu_device::vregs_w(offs_t offset, u8 data)
{
/*
@ -298,35 +323,33 @@ void st0016_cpu_device::vregs_w(offs_t offset, uint8_t data)
*/
vregs[offset]=data;
if(offset==0xa8 && (data&0x20))
m_vregs[offset] = data;
if (offset == 0xa8 && (data & 0x20))
{
uint32_t srcadr=(vregs[0xa0]|(vregs[0xa1]<<8)|(vregs[0xa2]<<16))<<1;
uint32_t dstadr=(vregs[0xa3]|(vregs[0xa4]<<8)|(vregs[0xa5]<<16))<<1;
uint32_t length=((vregs[0xa6]|(vregs[0xa7]<<8)|((vregs[0xa8]&0x1f)<<16))+1)<<1;
u32 srcadr = (m_vregs[0xa0] | (m_vregs[0xa1] << 8) | (m_vregs[0xa2] << 16)) << 1;
u32 dstadr = (m_vregs[0xa3] | (m_vregs[0xa4] << 8) | (m_vregs[0xa5] << 16)) << 1;
u32 length = ((m_vregs[0xa6] | (m_vregs[0xa7] << 8) | ((m_vregs[0xa8] & 0x1f) << 16)) + 1) << 1;
uint32_t srclen = (m_rom->bytes());
uint8_t *mem = m_rom->base();
u32 srclen = (m_rom->bytes());
u8 *mem = m_rom->base();
int xfer_offs = m_dma_offset;
if (!m_dma_offs_cb.isnull())
xfer_offs = m_dma_offs_cb() * 0x400000;
srcadr += xfer_offs;
while(length>0)
while (length > 0)
{
if( srcadr < srclen && (dstadr < MAX_CHAR_BANK*CHAR_BANK_SIZE))
if (srcadr < srclen && (dstadr < MAX_CHAR_BANK*CHAR_BANK_SIZE))
{
char_bank=dstadr>>5;
character_ram_w(dstadr&0x1f,mem[srcadr]);
m_charam_space.write_byte(dstadr, mem[srcadr]);
srcadr++;
dstadr++;
length--;
}
else
{
/* samples ? sound dma ? */
// samples ? sound dma ?
// speaglsht: unknown DMA copy : src - 2B6740, dst - 4400, len - 1E400
logerror("%s unknown DMA copy : src - %X, dst - %X, len - %X\n", machine().describe_context(), srcadr, dstadr, length);
break;
@ -385,21 +408,20 @@ void st0016_cpu_device::draw_sprites(bitmap_ind16 &bitmap, const rectangle &clip
*/
gfx_element *gfx = this->gfx(ramgfx);
int i, j, lx, ly, x, y, code, offset, length, sx, sy, color, flipx, flipy, scrollx, scrolly/*,plx,ply*/;
gfx_element *gfx = this->gfx(m_ramgfx);
int i, j, lx, ly, x, y, code, offset, length, sx, sy, color, flipx, flipy, scrollx, scrolly/*, plx, ply*/;
for (i = 0; i < SPR_BANK_SIZE*MAX_SPR_BANK; i += 8)
for (i = 0; i < SPR_BANK_SIZE * MAX_SPR_BANK; i += 8)
{
x = spriteram[i + 4] + ((spriteram[i + 5] & 3) << 8);
y = spriteram[i + 6] + ((spriteram[i + 7] & 3) << 8);
x = m_spriteram[i + 4] + ((m_spriteram[i + 5] & 3) << 8);
y = m_spriteram[i + 6] + ((m_spriteram[i + 7] & 3) << 8);
int use_sizes = (spriteram[i + 1] & 0x10);
int globalx = (spriteram[i + 5] & 0x0c)>>2;
int globaly = (spriteram[i + 7] & 0x0c)>>2;
int use_sizes = (m_spriteram[i + 1] & 0x10);
int globalx = (m_spriteram[i + 5] & 0x0c)>>2;
int globaly = (m_spriteram[i + 7] & 0x0c)>>2;
scrollx = (vregs[(((spriteram[i + 1] & 0x0f) >> 1) << 2) + 0x40] + 256 * vregs[(((spriteram[i + 1] & 0x0f) >> 1) << 2) + 1 + 0x40]) & 0x3ff;
scrolly = (vregs[(((spriteram[i + 1] & 0x0f) >> 1) << 2) + 2 + 0x40] + 256 * vregs[(((spriteram[i + 1] & 0x0f) >> 1) << 2) + 3 + 0x40]) & 0x3ff;
scrollx = (m_vregs[(((m_spriteram[i + 1] & 0x0f) >> 1) << 2) + 0x40] + 256 * m_vregs[(((m_spriteram[i + 1] & 0x0f) >> 1) << 2) + 1 + 0x40]) & 0x3ff;
scrolly = (m_vregs[(((m_spriteram[i + 1] & 0x0f) >> 1) << 2) + 2 + 0x40] + 256 * m_vregs[(((m_spriteram[i + 1] & 0x0f) >> 1) << 2) + 3 + 0x40]) & 0x3ff;
if (!ismacs())
{
@ -427,24 +449,24 @@ void st0016_cpu_device::draw_sprites(bitmap_ind16 &bitmap, const rectangle &clip
y += 0x20;
}
if (spriteram[i + 3] & 0x80) /* end of list */
if (m_spriteram[i + 3] & 0x80) // end of list
break;
offset = spriteram[i + 2] + 256 * (spriteram[i + 3]);
offset = m_spriteram[i + 2] + 256 * (m_spriteram[i + 3]);
offset <<= 3;
length = spriteram[i + 0] + 1 + 256 * (spriteram[i + 1] & 1);
length = m_spriteram[i + 0] + 1 + 256 * (m_spriteram[i + 1] & 1);
//plx=(spriteram[i+5]>>2)&0x3;
//ply=(spriteram[i+7]>>2)&0x3;
//plx = (m_spriteram[i+5] >> 2) & 0x3;
//ply = (m_spriteram[i+7] >> 2) & 0x3;
if (offset < SPR_BANK_SIZE*MAX_SPR_BANK)
if (offset < SPR_BANK_SIZE * MAX_SPR_BANK)
{
for (j = 0; j < length; j++)
{
code = spriteram[offset] + 256 * spriteram[offset + 1];
sx = spriteram[offset + 4] + ((spriteram[offset + 5] & 1) << 8);
sy = spriteram[offset + 6] + ((spriteram[offset + 7] & 1) << 8);
code = m_spriteram[offset] + 256 * m_spriteram[offset + 1];
sx = m_spriteram[offset + 4] + ((m_spriteram[offset + 5] & 1) << 8);
sy = m_spriteram[offset + 6] + ((m_spriteram[offset + 7] & 1) << 8);
if (ismacs() && !ismacs1())
{
@ -458,12 +480,12 @@ void st0016_cpu_device::draw_sprites(bitmap_ind16 &bitmap, const rectangle &clip
sx += x;
sy += y;
color = spriteram[offset + 2] & 0x3f;
color = m_spriteram[offset + 2] & 0x3f;
if (use_sizes)
{
lx = (spriteram[offset + 5] >> 2) & 3;
ly = (spriteram[offset + 7] >> 2) & 3;
lx = (m_spriteram[offset + 5] >> 2) & 3;
ly = (m_spriteram[offset + 7] >> 2) & 3;
}
else
{
@ -473,15 +495,15 @@ void st0016_cpu_device::draw_sprites(bitmap_ind16 &bitmap, const rectangle &clip
}
/*
if(plx |ply) //parent
{
lx=plx;
ly=ply;
}
*/
if (plx | ply) //parent
{
lx = plx;
ly = ply;
}
*/
flipx = spriteram[offset + 3] & 0x80;
flipy = spriteram[offset + 3] & 0x40;
flipx = m_spriteram[offset + 3] & 0x80;
flipy = m_spriteram[offset + 3] & 0x40;
if (ismacs())
sy -= (1 << ly) * 8;
@ -489,74 +511,75 @@ void st0016_cpu_device::draw_sprites(bitmap_ind16 &bitmap, const rectangle &clip
{
int x0, y0, i0 = 0;
for (x0 = (flipx ? ((1 << lx) - 1) : 0); x0 != (flipx ? -1 : (1 << lx)); x0 += (flipx ? -1 : 1))
{
for (y0 = (flipy ? ((1 << ly) - 1) : 0); y0 != (flipy ? -1 : (1 << ly)); y0 += (flipy ? -1 : 1))
{
/* custom draw */
uint16_t *destline;
int yloop, xloop;
int ypos, xpos;
int tileno;
const uint8_t *srcgfx;
int gfxoffs;
ypos = sy + y0 * 8 + spr_dy;
xpos = sx + x0 * 8 + spr_dx;
tileno = (code + i0++)&CHAR_BANK_MASK;
// custom draw
u16 *destline;
int yloop, xloop;
int ypos, xpos;
int tileno;
const u8 *srcgfx;
int gfxoffs;
ypos = sy + y0 * 8 + m_spr_dy;
xpos = sx + x0 * 8 + m_spr_dx;
tileno = (code + i0++) & CHAR_BANK_MASK;
gfxoffs = 0;
srcgfx = gfx->get_data(tileno);
gfxoffs = 0;
srcgfx = gfx->get_data(tileno);
for (yloop = 0; yloop < 8; yloop++)
{
uint16_t drawypos;
if (!flipy) { drawypos = ypos + yloop; }
else { drawypos = (ypos + 8 - 1) - yloop; }
destline = &bitmap.pix(drawypos);
for (xloop = 0; xloop<8; xloop++)
for (yloop = 0; yloop < 8; yloop++)
{
uint16_t drawxpos;
int pixdata;
pixdata = srcgfx[gfxoffs];
u16 drawypos;
if (!flipx) { drawxpos = xpos + xloop; }
else { drawxpos = (xpos + 8 - 1) - xloop; }
if (!flipy) { drawypos = ypos + yloop; }
else { drawypos = (ypos + 8 - 1) - yloop; }
destline = &bitmap.pix(drawypos);
if (drawxpos > cliprect.max_x)
drawxpos -= 512; // wrap around
if (cliprect.contains(drawxpos, drawypos))
for (xloop = 0; xloop<8; xloop++)
{
if (spriteram[offset + 5] & 0x40)
u16 drawxpos;
int pixdata;
pixdata = srcgfx[gfxoffs];
if (!flipx) { drawxpos = xpos + xloop; }
else { drawxpos = (xpos + 8 - 1) - xloop; }
if (drawxpos > cliprect.max_x)
drawxpos -= 512; // wrap around
if (cliprect.contains(drawxpos, drawypos))
{
destline[drawxpos] = (destline[drawxpos] | pixdata << 4) & 0x3ff;
}
else
{
if (ismacs2())
if (m_spriteram[offset + 5] & 0x40)
{
if (pixdata)//|| destline[drawxpos]==UNUSED_PEN)
{
destline[drawxpos] = pixdata + (color * 16);
}
destline[drawxpos] = (destline[drawxpos] | pixdata << 4) & 0x3ff;
}
else
{
if (pixdata || destline[drawxpos] == UNUSED_PEN)
if (ismacs2())
{
destline[drawxpos] = pixdata + (color * 16);
if (pixdata)//|| destline[drawxpos]==UNUSED_PEN)
{
destline[drawxpos] = pixdata + (color * 16);
}
}
else
{
if (pixdata || destline[drawxpos] == UNUSED_PEN)
{
destline[drawxpos] = pixdata + (color * 16);
}
}
}
}
gfxoffs++;
}
gfxoffs++;
}
}
}
}
}
offset += 8;
if (offset >= SPR_BANK_SIZE*MAX_SPR_BANK)
if (offset >= SPR_BANK_SIZE * MAX_SPR_BANK)
break;
}
}
@ -566,41 +589,35 @@ void st0016_cpu_device::draw_sprites(bitmap_ind16 &bitmap, const rectangle &clip
void st0016_cpu_device::save_init()
{
save_item(NAME(spr_bank));
save_item(NAME(spr2_bank));
save_item(NAME(pal_bank));
save_item(NAME(char_bank));
save_item(NAME(m_spr_bank));
save_item(NAME(m_spr2_bank));
save_item(NAME(m_pal_bank));
save_item(NAME(m_char_bank));
save_item(NAME(m_dma_offset));
//save_item(NAME(rom_bank));
save_item(NAME(vregs));
save_pointer(NAME(m_charram), MAX_CHAR_BANK*CHAR_BANK_SIZE);
save_pointer(NAME(paletteram), MAX_PAL_BANK*PAL_BANK_SIZE);
save_pointer(NAME(spriteram), MAX_SPR_BANK*SPR_BANK_SIZE);
save_item(NAME(m_vregs));
}
void st0016_cpu_device::startup()
{
int gfx_index=0;
u8 gfx_index = 0;
m_dma_offset = 0;
m_charram=make_unique_clear<uint8_t[]>(MAX_CHAR_BANK*CHAR_BANK_SIZE);
spriteram=make_unique_clear<uint8_t[]>(MAX_SPR_BANK*SPR_BANK_SIZE);
paletteram=make_unique_clear<uint8_t[]>(MAX_PAL_BANK*PAL_BANK_SIZE);
/* find first empty slot to decode gfx */
// find first empty slot to decode gfx
for (gfx_index = 0; gfx_index < MAX_GFX_ELEMENTS; gfx_index++)
if (gfx(gfx_index) == nullptr)
break;
assert(gfx_index != MAX_GFX_ELEMENTS);
/* create the char set (gfx will then be updated dynamically from RAM) */
set_gfx(gfx_index, std::make_unique<gfx_element>(&palette(), charlayout, m_charram.get(), 0, 0x40, 0));
ramgfx = gfx_index;
// create the char set (gfx will then be updated dynamically from RAM)
set_gfx(gfx_index, std::make_unique<gfx_element>(&palette(), charlayout, m_charram.target(), 0, 0x40, 0));
m_ramgfx = gfx_index;
spr_dx=0;
spr_dy=0;
m_spr_dx = 0;
m_spr_dy = 0;
save_init();
}
@ -608,25 +625,25 @@ void st0016_cpu_device::startup()
void st0016_cpu_device::draw_bgmap(bitmap_ind16 &bitmap, const rectangle &cliprect, int priority)
{
gfx_element *gfx = this->gfx(ramgfx);
gfx_element *gfx = this->gfx(m_ramgfx);
int j;
//for(j=0x40-8;j>=0;j-=8)
//for (j = 0x40 - 8; j >= 0; j -= 8)
for (j = 0; j < 0x40; j += 8)
{
if (vregs[j + 1] && ((priority && (vregs[j + 3] == 0xff)) || ((!priority) && (vregs[j + 3] != 0xff))))
if (m_vregs[j + 1] && ((priority && (m_vregs[j + 3] == 0xff)) || ((!priority) && (m_vregs[j + 3] != 0xff))))
{
int x, y, code, color, flipx, flipy;
int i = vregs[j + 1] * 0x1000;
int i = m_vregs[j + 1] * 0x1000;
for (x = 0; x < 32 * 2; x++)
{
for (y = 0; y < 8 * 4; y++)
{
code = spriteram[i] + 256 * spriteram[i + 1];
color = spriteram[i + 2] & 0x3f;
code = m_spriteram[i] + 256 * m_spriteram[i + 1];
color = m_spriteram[i + 2] & 0x3f;
flipx = spriteram[i + 3] & 0x80;
flipy = spriteram[i + 3] & 0x40;
flipx = m_spriteram[i + 3] & 0x80;
flipy = m_spriteram[i + 3] & 0x40;
if (priority)
{
@ -634,31 +651,31 @@ void st0016_cpu_device::draw_bgmap(bitmap_ind16 &bitmap, const rectangle &clipre
code,
color,
flipx, flipy,
x * 8 + spr_dx, y * 8 + spr_dy, 0);
x * 8 + m_spr_dx, y * 8 + m_spr_dy, 0);
}
else
{
uint16_t *destline;
u16 *destline;
int yloop, xloop;
int ypos, xpos;
const uint8_t *srcgfx;
const u8 *srcgfx;
int gfxoffs;
ypos = y * 8 + spr_dy;//+((vregs[j+2]==0xaf)?0x50:0);//hack for mayjinsen title screen
xpos = x * 8 + spr_dx;
ypos = y * 8 + m_spr_dy;// + ((m_vregs[j + 2] == 0xaf) ? 0x50 : 0); //hack for mayjinsen title screen
xpos = x * 8 + m_spr_dx;
gfxoffs = 0;
srcgfx = gfx->get_data(code);
for (yloop = 0; yloop < 8; yloop++)
{
uint16_t drawypos;
u16 drawypos;
if (!flipy) { drawypos = ypos + yloop; }
else { drawypos = (ypos + 8 - 1) - yloop; }
destline = &bitmap.pix(drawypos);
for (xloop = 0; xloop<8; xloop++)
for (xloop = 0; xloop < 8; xloop++)
{
uint16_t drawxpos;
u16 drawxpos;
int pixdata;
pixdata = srcgfx[gfxoffs];
@ -670,7 +687,7 @@ void st0016_cpu_device::draw_bgmap(bitmap_ind16 &bitmap, const rectangle &clipre
if (cliprect.contains(drawxpos, drawypos))
{
if (vregs[j + 7] == 0x12)
if (m_vregs[j + 7] == 0x12)
destline[drawxpos] = (destline[drawxpos] | (pixdata << 4)) & 0x3ff;
else
{
@ -688,12 +705,9 @@ void st0016_cpu_device::draw_bgmap(bitmap_ind16 &bitmap, const rectangle &clipre
destline[drawxpos] = pixdata + (color * 16);
}
}
}
}
gfxoffs++;
}
}
}
@ -707,30 +721,30 @@ void st0016_cpu_device::draw_bgmap(bitmap_ind16 &bitmap, const rectangle &clipre
void st0016_cpu_device::draw_screen(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
draw_bgmap(bitmap,cliprect,0);
draw_sprites(bitmap,cliprect);
draw_bgmap(bitmap,cliprect,1);
draw_bgmap(bitmap, cliprect, 0);
draw_sprites(bitmap, cliprect);
draw_bgmap(bitmap, cliprect, 1);
}
uint32_t st0016_cpu_device::update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
u32 st0016_cpu_device::update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
#ifdef MAME_DEBUG
if(machine().input().code_pressed_once(KEYCODE_Z))
if (machine().input().code_pressed_once(KEYCODE_Z))
{
int h,j;
FILE *p=fopen("vram.bin","wb");
fwrite(spriteram.get(),1,0x1000*MAX_SPR_BANK,p);
int h, j;
FILE *p = fopen("vram.bin", "wb");
fwrite(m_spriteram.get(), 1, 0x1000 * MAX_SPR_BANK, p);
fclose(p);
p=fopen("vram.txt","wt");
for(h=0;h<0xc0;h++)
fprintf(p,"VREG %.4x - %.4x\n",h,vregs[h]);
for(h=0;h<0x1000*MAX_SPR_BANK;h+=8)
p = fopen("vram.txt","wt");
for (h = 0; h < 0xc0; h++)
fprintf(p,"VREG %.4x - %.4x\n",h,m_vregs[h]);
for (h = 0; h < 0x1000 * MAX_SPR_BANK; h += 8)
{
fprintf(p,"%.4x - %.4x - ",h,h>>3);
for(j=0;j<8;j++)
fprintf(p,"%.2x ",spriteram[h+j]);
fprintf(p,"\n");
fprintf(p, "%.4x - %.4x - ", h, h >> 3);
for (j = 0; j < 8; j++)
fprintf(p, "%.2x ", m_spriteram[h + j]);
fprintf(p, "\n");
}
fclose(p);
}

View File

@ -12,44 +12,42 @@
#include "screen.h"
class st0016_cpu_device : public z80_device, public device_gfx_interface
class st0016_cpu_device : public z80_device, public device_gfx_interface, public device_video_interface, public device_mixer_interface
{
public:
typedef device_delegate<uint8_t ()> dma_offs_delegate;
enum
{
AS_CHARAM = AS_OPCODES + 1
};
st0016_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t);
typedef device_delegate<u8 ()> dma_offs_delegate;
st0016_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32);
template <typename... T> void set_dma_offs_callback(T &&... args) { m_dma_offs_cb.set(std::forward<T>(args)...); }
void set_game_flag(uint32_t flag) { m_game_flag = flag; }
void set_game_flag(u32 flag) { m_game_flag = flag; }
void draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect);
void save_init();
void draw_bgmap(bitmap_ind16 &bitmap,const rectangle &cliprect, int priority);
void startup();
uint32_t update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
void draw_screen(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
u32 update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
std::unique_ptr<uint8_t[]> spriteram;
std::unique_ptr<uint8_t[]> paletteram;
int32_t spr_bank,spr2_bank,pal_bank,char_bank;
int spr_dx,spr_dy;
uint8_t vregs[0xc0];
int ramgfx;
std::unique_ptr<uint8_t[]> m_charram;
void cpu_internal_io_map(address_map &map);
void cpu_internal_map(address_map &map);
protected:
// device-level overrides
virtual void device_add_mconfig(machine_config &config) override;
virtual void device_start() override;
virtual void device_reset() override;
const address_space_config m_io_space_config;
const address_space_config m_space_config;
const address_space_config m_charam_space_config;
virtual space_config_vector memory_space_config() const override;
private:
bool ismacs() const { return m_game_flag & 0x80; }
bool ismacs1() const { return (m_game_flag & 0x180) == 0x180; }
bool ismacs2() const { return (m_game_flag & 0x180) == 0x080; }
static constexpr unsigned MAX_SPR_BANK = 0x10;
static constexpr unsigned MAX_CHAR_BANK = 0x10000;
static constexpr unsigned MAX_PAL_BANK = 4;
@ -64,41 +62,49 @@ protected:
static constexpr unsigned CHAR_BANK_MASK = MAX_CHAR_BANK - 1;
static constexpr unsigned PAL_BANK_MASK = MAX_PAL_BANK - 1;
// device-level overrides
virtual void device_add_mconfig(machine_config &config) override;
virtual void device_start() override;
virtual void device_reset() override;
const address_space_config m_io_space_config;
const address_space_config m_space_config;
virtual space_config_vector memory_space_config() const override;
required_device<screen_device> m_screen;
required_memory_region m_rom;
memory_share_creator<u8> m_spriteram;
memory_share_creator<u8> m_charram;
memory_share_creator<u8> m_paletteram;
private:
uint8_t m_dma_offset;
u8 m_dma_offset;
dma_offs_delegate m_dma_offs_cb;
uint32_t m_game_flag;
u32 m_game_flag;
uint8_t soundram_read(offs_t offset);
void sprite_bank_w(uint8_t data);
void palette_bank_w(uint8_t data);
void character_bank_w(offs_t offset, uint8_t data);
uint8_t sprite_ram_r(offs_t offset);
void sprite_ram_w(offs_t offset, uint8_t data);
uint8_t sprite2_ram_r(offs_t offset);
void sprite2_ram_w(offs_t offset, uint8_t data);
uint8_t palette_ram_r(offs_t offset);
void palette_ram_w(offs_t offset, uint8_t data);
uint8_t character_ram_r(offs_t offset);
void character_ram_w(offs_t offset, uint8_t data);
uint8_t vregs_r(offs_t offset);
uint8_t dma_r();
void vregs_w(offs_t offset, uint8_t data);
memory_access<21, 0, 0, ENDIANNESS_LITTLE>::specific m_charam_space;
void sprite_bank_w(u8 data);
void palette_bank_w(u8 data);
void character_bank_w(offs_t offset, u8 data);
u8 sprite_ram_r(offs_t offset);
void sprite_ram_w(offs_t offset, u8 data);
u8 sprite2_ram_r(offs_t offset);
void sprite2_ram_w(offs_t offset, u8 data);
u8 palette_ram_r(offs_t offset);
void palette_ram_w(offs_t offset, u8 data);
u8 charam_bank_r(offs_t offset);
void charam_bank_w(offs_t offset, u8 data);
u8 character_ram_r(offs_t offset);
void character_ram_w(offs_t offset, u8 data);
u8 vregs_r(offs_t offset);
u8 dma_r();
void vregs_w(offs_t offset, u8 data);
void draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect);
void save_init();
void draw_bgmap(bitmap_ind16 &bitmap,const rectangle &cliprect, int priority);
void startup();
u32 m_spr_bank, m_spr2_bank, m_pal_bank, m_char_bank;
int m_spr_dx, m_spr_dy;
u8 m_vregs[0xc0];
u8 m_ramgfx;
void cpu_internal_io_map(address_map &map);
void cpu_internal_map(address_map &map);
void charam_map(address_map &map);
};