Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 78 additions & 70 deletions src/mame/seibu/feversoc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ looping over a complex control structure. Could these be derived from the
- Layout including lamps
- Hopper only works in "COIN HOPPER" mode
- Do button 5 or remaining DIPs actually do anything outside service mode?
- Make device of RISE11 sprite hardware that also used in seibu/seibuspi.cpp
and seibu/seibucats.cpp

============================================================================

Expand Down Expand Up @@ -107,17 +109,20 @@ class feversoc_state : public driver_device
{ }

void init_feversoc();
void feversoc(machine_config &config);
void feversoc(machine_config &config) ATTR_COLD;

protected:
virtual void machine_start() override ATTR_COLD;

private:
uint16_t in_r(offs_t offset);
void output_w(uint16_t data);
void output2_w(uint16_t data);
void feversoc_map(address_map &map) ATTR_COLD;
uint32_t screen_update_feversoc(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
void feversoc_irq(int state);
void feversoc_irq_ack(uint16_t data);
virtual void machine_start() override ATTR_COLD;
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
void screen_vblank(int state);
void irq_ack_w(uint16_t data);

void main_map(address_map &map) ATTR_COLD;

required_shared_ptr<uint32_t> m_mainram1;
required_shared_ptr<uint32_t> m_mainram2;
Expand All @@ -136,110 +141,111 @@ class feversoc_state : public driver_device
};


#define MASTER_CLOCK XTAL(28'636'363)


uint32_t feversoc_state::screen_update_feversoc(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
uint32_t feversoc_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
uint32_t *spriteram32 = m_spriteram;
int offs,spr_offs,colour,sx,sy,h,w,dx,dy;

bitmap.fill(m_palette->pen(0), cliprect); //black pen

for(offs=(0x2000/4)-2;offs>-1;offs-=2)
for (int offs = (0x2000 / 4) - 2; offs >= 0; offs -= 2)
{
spr_offs = (spriteram32[offs+0] & 0x3fff);
if(spr_offs == 0)
u32 spr_offs = (m_spriteram[offs + 0] & 0x3fff);
if (spr_offs == 0)
continue;
sy = (spriteram32[offs+1] & 0x01ff);
sx = (spriteram32[offs+1] & 0x01ff0000)>>16;
colour = (spriteram32[offs+0] & 0x003f0000)>>16;
w = ((spriteram32[offs+0] & 0x07000000)>>24)+1;
h = ((spriteram32[offs+0] & 0x70000000)>>28)+1;

if( sy & 0x100)
sy-=0x200;

for(dx=0;dx<w;dx++)
for(dy=0;dy<h;dy++)
m_gfxdecode->gfx(0)->transpen(bitmap,cliprect,spr_offs++,colour,0,0,(sx+dx*16),(sy+dy*16),0x3f);
int sy = m_spriteram[offs + 1] & 0x01ff;
int sx = (m_spriteram[offs + 1] & 0x01ff0000) >> 16;
const u32 colour = (m_spriteram[offs + 0] & 0x003f0000) >> 16;
const u8 w = ((m_spriteram[offs + 0] & 0x07000000) >> 24) + 1;
const u8 h = ((m_spriteram[offs + 0] & 0x70000000) >> 28) + 1;
// TODO: flip sprite?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The unused bits could be anything in the Seibu portfolio, adding this note has no effective value.

Copy link
Contributor Author

@cam900 cam900 Oct 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That because original RISE11 (also used at rfjet and clones in seibu/seibuspi.cpp; including functionally compatible RISE10 and SEI252) has per-sprite flip X/Y bit in sprite RAM, but seems to not used in feversoc.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the note should be // TODO: merge implementation with Seibu SPI/Cats, and I don't think it's necessary because it's already repeated in header. Game probably also uses DMA start address etc. as per the norm since legionna.cpp anyway ...


if (sx >= 0x180)
sx -= 0x200;

if (sy >= 0x180)
sy -= 0x200;

for (int dx = 0; dx < w; dx++)
{
for (int dy = 0; dy < h; dy++)
{
m_gfxdecode->gfx(0)->transpen(bitmap, cliprect,
spr_offs++, colour,
0, 0,
(sx + dx * 16), (sy + dy * 16),
0x3f);
}
}
}

return 0;
}



uint16_t feversoc_state::in_r(offs_t offset)
{
return m_in[offset]->read() & 0xffff;
}

void feversoc_state::output_w(uint16_t data)
{
machine().bookkeeping().coin_lockout_w(0, ~data & 0x40);
machine().bookkeeping().coin_lockout_w(1, ~data & 0x40);
machine().bookkeeping().coin_counter_w(0, data & 1);
// data & 2 coin out counter
machine().bookkeeping().coin_counter_w(1, data & 4);
m_hopper->motor_w((data & 0x08) >> 3); // coin hopper or prize hopper
m_oki->set_rom_bank((data & 0x20) >> 5);

m_eeprom->di_write((data & 0x8000) ? 1 : 0);
m_eeprom->clk_write((data & 0x4000) ? ASSERT_LINE : CLEAR_LINE);
m_eeprom->cs_write((data & 0x2000) ? ASSERT_LINE : CLEAR_LINE);

m_rtc->data_w((data & 0x0800) ? 1 : 0);
m_rtc->wr_w((data & 0x0400) ? ASSERT_LINE : CLEAR_LINE);
m_rtc->clk_w((data & 0x0200) ? ASSERT_LINE : CLEAR_LINE);
m_rtc->ce_w((data & 0x0100) ? ASSERT_LINE : CLEAR_LINE);
machine().bookkeeping().coin_lockout_w(0, BIT(~data, 6));
machine().bookkeeping().coin_lockout_w(1, BIT(~data, 6));
machine().bookkeeping().coin_counter_w(0, BIT(data, 0));
// BIT(data, 1) coin out counter
machine().bookkeeping().coin_counter_w(1, BIT(data, 2));
m_hopper->motor_w(BIT(data, 3)); // coin hopper or prize hopper
m_oki->set_rom_bank(BIT(data, 5));

m_eeprom->di_write(BIT(data, 15));
m_eeprom->clk_write(BIT(data, 14) ? ASSERT_LINE : CLEAR_LINE);
m_eeprom->cs_write(BIT(data, 13) ? ASSERT_LINE : CLEAR_LINE);

m_rtc->data_w(BIT(data, 11));
m_rtc->wr_w(BIT(data, 10) ? ASSERT_LINE : CLEAR_LINE);
m_rtc->clk_w(BIT(data, 9) ? ASSERT_LINE : CLEAR_LINE);
m_rtc->ce_w(BIT(data, 8) ? ASSERT_LINE : CLEAR_LINE);
}

void feversoc_state::output2_w(uint16_t data)
{
for (int n = 0; n < 7; n++)
m_lamps[n] = BIT(data, n); // LAMP1-LAMP7

machine().bookkeeping().coin_counter_w(2, data & 0x2000); // key in
//data & 0x4000 key out
machine().bookkeeping().coin_counter_w(2, BIT(data, 13)); // key in
//BIT(data, 14) key out
}


void feversoc_state::feversoc_map(address_map &map)
void feversoc_state::main_map(address_map &map)
{
map(0x00000000, 0x0003ffff).rom();
map(0x02000000, 0x0202ffff).ram().share("workram1"); //work ram
map(0x02030000, 0x02033fff).ram().share("nvram");
map(0x02034000, 0x0203dfff).ram().share("workram2"); //work ram
map(0x0203e000, 0x0203ffff).ram().share("spriteram");
map(0x02000000, 0x0202ffff).ram().share(m_mainram1); //work ram
map(0x02030000, 0x02033fff).ram().share(m_nvram);
map(0x02034000, 0x0203dfff).ram().share(m_mainram2); //work ram
map(0x0203e000, 0x0203ffff).ram().share(m_spriteram);
map(0x06000000, 0x06000001).w(FUNC(feversoc_state::output_w));
map(0x06000002, 0x06000003).w(FUNC(feversoc_state::output2_w));
map(0x06000006, 0x06000007).w(FUNC(feversoc_state::feversoc_irq_ack));
map(0x06000006, 0x06000007).w(FUNC(feversoc_state::irq_ack_w));
map(0x06000008, 0x0600000b).r(FUNC(feversoc_state::in_r));
map(0x0600000d, 0x0600000d).rw(m_oki, FUNC(okim6295_device::read), FUNC(okim6295_device::write));
//map(0x06010000, 0x0601007f).rw("obj", FUNC(seibu_encrypted_sprite_device::read), FUNC(seibu_encrypted_sprite_device::write));
map(0x06010060, 0x06010063).nopw(); // sprite buffering
map(0x06018000, 0x06019fff).ram().w(m_palette, FUNC(palette_device::write32)).share("palette");
}

static const gfx_layout spi_spritelayout =
static const gfx_layout spritelayout =
{
16,16,
RGN_FRAC(1,3),
6,
{ RGN_FRAC(0,3)+0,RGN_FRAC(0,3)+8,RGN_FRAC(1,3)+0,RGN_FRAC(1,3)+8,RGN_FRAC(2,3)+0,RGN_FRAC(2,3)+8 },
{
7,6,5,4,3,2,1,0,23,22,21,20,19,18,17,16
},
{
0*32,1*32,2*32,3*32,4*32,5*32,6*32,7*32,8*32,9*32,10*32,11*32,12*32,13*32,14*32,15*32
},
{ STEP8(7,-1), STEP8(16+7,-1) },
{ STEP16(0,32) },
16*32
};


static GFXDECODE_START( gfx_feversoc )
GFXDECODE_ENTRY( "gfx1", 0, spi_spritelayout, 0, 0x40 )
GFXDECODE_ENTRY( "sprites", 0, spritelayout, 0, 0x40 )
GFXDECODE_END

static INPUT_PORTS_START( feversoc )
Expand Down Expand Up @@ -278,13 +284,13 @@ static INPUT_PORTS_START( feversoc )
PORT_BIT( 0xff00, IP_ACTIVE_LOW, IPT_UNUSED )
INPUT_PORTS_END

void feversoc_state::feversoc_irq(int state)
void feversoc_state::screen_vblank(int state)
{
if (state)
m_maincpu->set_input_line(8, ASSERT_LINE);
}

void feversoc_state::feversoc_irq_ack(uint16_t data)
void feversoc_state::irq_ack_w(uint16_t data)
{
m_maincpu->set_input_line(8, CLEAR_LINE);
}
Expand All @@ -296,28 +302,30 @@ void feversoc_state::machine_start()

void feversoc_state::feversoc(machine_config &config)
{
constexpr XTAL MASTER_CLOCK = XTAL(28'636'363);

/* basic machine hardware */
SH7604(config, m_maincpu, MASTER_CLOCK);
m_maincpu->set_addrmap(AS_PROGRAM, &feversoc_state::feversoc_map);
m_maincpu->set_addrmap(AS_PROGRAM, &feversoc_state::main_map);

/* 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(40*8, 32*8);
screen.set_visarea(0*8, 40*8-1, 0*8, 30*8-1); //dynamic resolution?
screen.set_screen_update(FUNC(feversoc_state::screen_update_feversoc));
screen.set_screen_update(FUNC(feversoc_state::screen_update));
screen.set_palette(m_palette);
screen.screen_vblank().set(FUNC(feversoc_state::feversoc_irq));
screen.screen_vblank().set(FUNC(feversoc_state::screen_vblank));

GFXDECODE(config, m_gfxdecode, m_palette, gfx_feversoc);
PALETTE(config, m_palette).set_format(palette_device::xBGR_555, 0x1000);

/* sound hardware */
SPEAKER(config, "mono").front_center();
OKIM6295(config, m_oki, MASTER_CLOCK/16, okim6295_device::PIN7_LOW).add_route(ALL_OUTPUTS, "mono", 0.6); //pin 7 & frequency not verified (clock should be 28,6363 / n)
OKIM6295(config, m_oki, MASTER_CLOCK / 16, okim6295_device::PIN7_LOW).add_route(ALL_OUTPUTS, "mono", 0.6); //pin 7 & frequency not verified (clock should be 28,6363 / n)

EEPROM_93C56_16BIT(config, "eeprom");
EEPROM_93C56_16BIT(config, m_eeprom);

JRC6355E(config, m_rtc, XTAL(32'768));

Expand All @@ -339,7 +347,7 @@ ROM_START( feversoc )
ROM_LOAD16_BYTE( "prog0.u0139", 0x00001, 0x20000, CRC(fa699503) SHA1(96a834d4f7d5b764aa51db745afc2cd9a7c9783d) )
ROM_LOAD16_BYTE( "prog1.u0140", 0x00000, 0x20000, CRC(fd4d7943) SHA1(d7d782f878656bc79d70589f9df2cbcfff0adb5e) )

ROM_REGION( 0x600000, "gfx1", 0) /* text */
ROM_REGION( 0x600000, "sprites", 0) /* text */
ROM_LOAD("obj1.u011", 0x000000, 0x200000, CRC(d8c8dde7) SHA1(3ef815fb1e21a0bd907ee835bc7a32d80f6a9d28) )
ROM_LOAD("obj2.u012", 0x200000, 0x200000, CRC(8e93bfda) SHA1(3b4740cefb164efc320fb69f58e8800d2646fea6) )
ROM_LOAD("obj3.u013", 0x400000, 0x200000, CRC(8c8c6e8b) SHA1(bed4990d6eebb7aefa200ad2bed9b7e71e6bd064) )
Expand All @@ -352,7 +360,7 @@ void feversoc_state::init_feversoc()
{
uint32_t *rom = (uint32_t *)memregion("maincpu")->base();

seibuspi_rise11_sprite_decrypt_feversoc(memregion("gfx1")->base(), 0x200000);
seibuspi_rise11_sprite_decrypt_feversoc(memregion("sprites")->base(), 0x200000);

m_maincpu->sh2drc_set_options(SH2DRC_FASTEST_OPTIONS);
m_maincpu->sh2drc_add_fastram(0x00000000, 0x0003ffff, 1, rom);
Expand Down
Loading