summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/drivers/cedar_magnet_sprite.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/drivers/cedar_magnet_sprite.cpp')
-rw-r--r--src/mame/drivers/cedar_magnet_sprite.cpp336
1 files changed, 336 insertions, 0 deletions
diff --git a/src/mame/drivers/cedar_magnet_sprite.cpp b/src/mame/drivers/cedar_magnet_sprite.cpp
new file mode 100644
index 00000000000..e79b83faf84
--- /dev/null
+++ b/src/mame/drivers/cedar_magnet_sprite.cpp
@@ -0,0 +1,336 @@
+// license:BSD-3-Clause
+// copyright-holders:David Haywood
+
+/*
+
+ todo: sometimes sprites get left onscreen (xain)
+
+*/
+#include "emu.h"
+#include "cedar_magnet_sprite.h"
+
+
+extern const device_type CEDAR_MAGNET_SPRITE = &device_creator<cedar_magnet_sprite_device>;
+
+
+cedar_magnet_sprite_device::cedar_magnet_sprite_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : cedar_magnet_board_device(mconfig, CEDAR_MAGNET_SPRITE, "Cedar Sprite", tag, owner, clock, "cedmag_sprite", __FILE__),
+ m_sprite_ram_bankdev(*this, "sp_sub_ram"),
+ m_pio0(*this, "z80pio0"),
+ m_pio1(*this, "z80pio1"),
+ m_pio2(*this, "z80pio2")
+{
+}
+
+static ADDRESS_MAP_START( cedar_magnet_sprite_sub_ram_map, AS_PROGRAM, 8, cedar_magnet_sprite_device )
+// these are 8x SIEMENS HYB 41256-15 AA - 262,144 bit DRAM (32kbytes)
+// these are on the sprite board memory sub-board
+ AM_RANGE(0x00000, 0x3ffff) AM_RAM AM_SHARE("ram")
+ADDRESS_MAP_END
+
+READ8_MEMBER(cedar_magnet_sprite_device::exzisus_hack_r)
+{
+ //printf("exzisus_hack_r\n");
+ int pc = m_cpu->pc();
+
+ // exzisus has startup code outside of the first 0x400 bytes
+ // but the main cpu only transfers 0x400 bytes of the code to the other banks?!
+ if ((pc >= 0x3e0) && (pc <= 0x800))
+ {
+ return m_ram[0x400 + offset];
+ }
+ else
+ {
+ return m_ram[0x400 + offset + (pio2_pb_data & 0x3)*0x10000];
+ }
+
+}
+
+
+static ADDRESS_MAP_START( cedar_magnet_sprite_map, AS_PROGRAM, 8, cedar_magnet_sprite_device )
+ AM_RANGE(0x00400, 0x007ff) AM_READ(exzisus_hack_r)
+
+ AM_RANGE(0x00000, 0x0ffff) AM_DEVICE("sp_sub_ram", address_map_bank_device, amap8)
+
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( cedar_magnet_sprite_io, AS_IO, 8, cedar_magnet_sprite_device )
+ ADDRESS_MAP_GLOBAL_MASK(0xff)
+
+ AM_RANGE(0xc0, 0xc3) AM_DEVREADWRITE("z80pio0", z80pio_device, read_alt, write_alt)
+ AM_RANGE(0xc4, 0xc7) AM_DEVREADWRITE("z80pio1", z80pio_device, read_alt, write_alt)
+ AM_RANGE(0xc8, 0xcb) AM_DEVREADWRITE("z80pio2", z80pio_device, read_alt, write_alt)
+
+ AM_RANGE(0x80, 0x80) AM_WRITE(sprite_port80_w)
+ AM_RANGE(0x84, 0x84) AM_WRITE(sprite_port84_w)
+
+ AM_RANGE(0x88, 0x88) AM_WRITE(sprite_port88_w) // increasing values // upper address?
+
+ AM_RANGE(0x8c, 0x8c) AM_WRITE(sprite_port8c_w) // written after 88 (possible data upload?)
+
+ AM_RANGE(0x9c, 0x9c) AM_WRITE(sprite_port9c_w) // ?
+
+ADDRESS_MAP_END
+
+void cedar_magnet_sprite_device::do_blit()
+{
+// printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
+// printf("~~~~~~~~~~~~~~~~~ drawing sprite with x:%02x y:%02x code:%04x size:%02x unk:%02x\n", m_loweraddr, m_upperaddr, (m_spritecodehigh << 8) | m_spritecodelow, m_spritesize, pio0_pb_data);
+// printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
+
+ int ysize;
+ int xsize;
+ int erase = 0;
+
+ // bit 0x80 is always set
+ if ((m_spritesize & 0x7f) == 0x00)
+ ysize = xsize = 8;
+
+ if ((m_spritesize & 0x7f) == 0x01)
+ ysize = xsize = 16;
+
+ if ((m_spritesize & 0x7f) == 0x02)
+ ysize = xsize = 32;
+
+ if ((m_spritesize & 0x7f) == 0x03)
+ ysize = xsize = 64;
+
+ // m_spritesize
+ // pio0_pb_data
+
+
+ int source = (m_spritecodehigh << 8) | m_spritecodelow;
+
+ if (source == 0)
+ erase = 1;
+
+ source &= ~0x3f;
+
+ for (int y = 0;y < ysize;y++)
+ {
+ for (int x = 0;x < xsize;x++)
+ {
+ int xpos = (m_loweraddr + x);
+ int ypos = (m_upperaddr + y);
+
+ UINT8 data = m_ram[source + ((m_uppersprite & 0x3) * 0x10000)];
+
+ if (!(pio0_pb_data & 0x02))
+ data = rand();
+
+ source++;
+
+ xpos &= 0xff;
+
+ // without this some sprites incorrectly wraparound on the volcano table.
+ if (!erase)
+ {
+ if (!(pio0_pb_data & 0x40))
+ {
+ if (xpos >= 0xff-64)
+ continue;
+ }
+ else
+ {
+ if (xpos < 64)
+ continue;
+ }
+ }
+
+ //if ((ypos >= 0) && (ypos < 0x100))
+ ypos &= 0xff;
+
+ {
+ int offset = (ypos * 256) + xpos;
+
+ if (erase == 1)
+ {
+ m_framebuffer[offset] = 0;
+ }
+ else
+ {
+ if (data) m_framebuffer[offset] = data;
+ }
+ }
+ }
+ }
+}
+
+WRITE8_MEMBER(cedar_magnet_sprite_device::sprite_port80_w)
+{
+ m_spritecodelow = data;
+// printf("%s:sprite numlow / trigger %02x\n", machine().describe_context(), data);
+
+ do_blit();
+}
+
+WRITE8_MEMBER(cedar_magnet_sprite_device::sprite_port84_w)
+{
+ m_spritecodehigh = data;
+ m_high_write = 1;
+// printf("%s:sprite numhigh %02x\n", machine().describe_context(), data);
+}
+
+WRITE8_MEMBER(cedar_magnet_sprite_device::sprite_port88_w)
+{
+// frequent
+// printf("%s:sprite_y_coordinate %02x\n", machine().describe_context(), data);
+ m_upperaddr = data;
+}
+
+WRITE8_MEMBER(cedar_magnet_sprite_device::pio2_pa_w)
+{
+// frequent
+// printf("%s:sprite_x_coordinate %02x\n", machine().describe_context(), data);
+ m_loweraddr = data;
+}
+
+WRITE8_MEMBER(cedar_magnet_sprite_device::sprite_port8c_w)
+{
+ int address = (m_upperaddr << 8) | m_loweraddr;
+ m_framebuffer[address] = data;
+ if (data!=0x00) printf("sprite_port8c_w write %04x %02x\n", address, data);
+}
+
+// possible watchdog?
+WRITE8_MEMBER(cedar_magnet_sprite_device::sprite_port9c_w)
+{
+// printf("%s:sprite_port9c_w %02x\n", machine().describe_context(), data);
+}
+
+static MACHINE_CONFIG_FRAGMENT( cedar_magnet_sprite )
+ MCFG_CPU_ADD("spritecpu", Z80,4000000)
+ MCFG_CPU_PROGRAM_MAP(cedar_magnet_sprite_map)
+ MCFG_CPU_IO_MAP(cedar_magnet_sprite_io)
+ MCFG_CPU_VBLANK_INT_DRIVER(":screen", cedar_magnet_board_device, irq)
+
+ MCFG_DEVICE_ADD("z80pio0", Z80PIO, 4000000/2)
+// MCFG_Z80PIO_OUT_INT_CB(INPUTLINE("maincpu", INPUT_LINE_IRQ0))
+ MCFG_Z80PIO_IN_PA_CB(READ8(cedar_magnet_sprite_device, pio0_pa_r))
+ MCFG_Z80PIO_OUT_PA_CB(WRITE8(cedar_magnet_sprite_device, pio0_pa_w))
+// MCFG_Z80PIO_IN_PB_CB(READ8(cedar_magnet_sprite_device, pio0_pb_r))
+ MCFG_Z80PIO_OUT_PB_CB(WRITE8(cedar_magnet_sprite_device, pio0_pb_w))
+
+ MCFG_DEVICE_ADD("z80pio1", Z80PIO, 4000000/2)
+// MCFG_Z80PIO_OUT_INT_CB(INPUTLINE("maincpu", INPUT_LINE_IRQ0))
+// MCFG_Z80PIO_IN_PA_CB(READ8(cedar_magnet_sprite_device, pio1_pa_r))
+ MCFG_Z80PIO_OUT_PA_CB(WRITE8(cedar_magnet_sprite_device, pio1_pa_w))
+// MCFG_Z80PIO_IN_PB_CB(READ8(cedar_magnet_sprite_device, pio1_pb_r))
+ MCFG_Z80PIO_OUT_PB_CB(WRITE8(cedar_magnet_sprite_device, pio1_pb_w))
+
+ MCFG_DEVICE_ADD("z80pio2", Z80PIO, 4000000/2)
+// MCFG_Z80PIO_OUT_INT_CB(INPUTLINE("maincpu", INPUT_LINE_IRQ0))
+// MCFG_Z80PIO_IN_PA_CB(READ8(cedar_magnet_sprite_device, pio2_pa_r))
+ MCFG_Z80PIO_OUT_PA_CB(WRITE8(cedar_magnet_sprite_device, pio2_pa_w))
+// MCFG_Z80PIO_IN_PB_CB(READ8(cedar_magnet_sprite_device, pio2_pb_r))
+ MCFG_Z80PIO_OUT_PB_CB(WRITE8(cedar_magnet_sprite_device, pio2_pb_w))
+
+ MCFG_DEVICE_ADD("sp_sub_ram", ADDRESS_MAP_BANK, 0)
+ MCFG_DEVICE_PROGRAM_MAP(cedar_magnet_sprite_sub_ram_map)
+ MCFG_ADDRESS_MAP_BANK_ENDIANNESS(ENDIANNESS_LITTLE)
+ MCFG_ADDRESS_MAP_BANK_DATABUS_WIDTH(8)
+ MCFG_ADDRESS_MAP_BANK_ADDRBUS_WIDTH(18)
+ MCFG_ADDRESS_MAP_BANK_STRIDE(0x10000)
+MACHINE_CONFIG_END
+
+
+READ8_MEMBER(cedar_magnet_sprite_device::pio0_pa_r)
+{
+// actually read
+// printf("%s: pio0_pa_r\n", machine().describe_context());
+ return 0x00;
+}
+
+
+
+WRITE8_MEMBER(cedar_magnet_sprite_device::pio0_pa_w)
+{
+ m_spritesize = data;
+}
+
+WRITE8_MEMBER(cedar_magnet_sprite_device::pio0_pb_w)
+{
+ pio0_pb_data = data;
+ //printf("%s: pio0_pb_w %02x\n", machine().describe_context(), data);
+}
+
+WRITE8_MEMBER(cedar_magnet_sprite_device::pio1_pa_w)
+{
+ //printf("%s: pio1_pa_w %02x\n", machine().describe_context(), data);
+}
+
+WRITE8_MEMBER(cedar_magnet_sprite_device::pio1_pb_w)
+{
+ //printf("%s: pio1_pb_w %02x\n", machine().describe_context(), data);
+}
+
+
+WRITE8_MEMBER(cedar_magnet_sprite_device::pio2_pb_w)
+{
+ // this feels like a hack
+ // the game writes here when creating the sprite list so that it can access the correct gfd data
+ // however the actual LIST data is always in bank 0 (it can't be in any other bank, those areas are occupied by actual gfx)
+ if (m_high_write)
+ {
+ m_uppersprite = data & 0x03;
+ m_high_write = 0;
+ return;
+
+ }
+
+ pio2_pb_data = data;
+ //printf("%s: ******************************************* BANK? **** pio2_pb_w %02x\n", machine().describe_context(), data);
+ // yes, it ends up banking the ram right out from under itself during startup execution...
+ // during this time the main cpu is waiting in a loop, after which it copies the startup code again, and reboots it.
+ m_sprite_ram_bankdev->set_bank(data & 0x03);
+}
+
+
+machine_config_constructor cedar_magnet_sprite_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( cedar_magnet_sprite );
+}
+
+void cedar_magnet_sprite_device::device_start()
+{
+ m_cpu = subdevice<z80_device>("spritecpu");
+ m_ram = (UINT8*)memshare("ram")->ptr();
+}
+
+
+
+void cedar_magnet_sprite_device::device_reset()
+{
+ halt_assert();
+ m_sprite_ram_bankdev->set_bank(0);
+ pio2_pb_data = 0x00;
+ m_spritesize = 0xff;
+}
+
+UINT32 cedar_magnet_sprite_device::draw(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int palbase)
+{
+// printf("-----------------------------------------------------------------------------------------------------------\n");
+// printf("--------------------------------------------- FRAME -------------------------------------------------------\n");
+// printf("-----------------------------------------------------------------------------------------------------------\n");
+
+ UINT8* mem = m_framebuffer;
+ int count = 0;
+
+// if (!(m_m_spritesize & 0x40))
+// return 0;
+
+ for (int y = 0;y < 256;y++)
+ {
+ UINT16 *dst = &bitmap.pix16((y)&0xff);
+
+ for (int x = 0; x < 256;x++)
+ {
+ UINT8 pix = mem[count];
+ count++;
+
+ if (pix) dst[(x)&0xff] = pix + palbase*0x100;
+ }
+ }
+
+ return 0;
+}