mirror of
https://github.com/holub/mame
synced 2025-04-22 08:22:15 +03:00
new WORKING Magnet System (prototype) [David Haywood, Ricky2001, ArcadeHacker, IFW]
with the following games Time Scanner (TS 2.0, Magnet System, prototype) Exzisus (EX 1.0, Magnet System, prototype) Xain'd Sleena (SC 3.0, Magnet System, prototype) this is a checkpoint, there is a sizeable ToDo list but I think this is a good enough state for initial inclusion before working out the remaining issues. ArcadeHacker has the hardware working for questions etc. I would especially appreciate help with sound (haven't a clue how it hooks up, tried lots of things, no luck) and some help in going over the CPU comms, especially with the sprite CPU as I think I must be missing something important. Likewise help from somebody more familiar with the floppy code from MESS so that it can use that, I had no luck in getting it to work with the copy protection or from a rom region, I've kept all floppy related code in a device so it's very easy to swap out so for now what I've got isn't intrusive. note, very weird idea for a system, they've ported 3 arcade games from other manufacturers, original titles were advertised, but it's likely nothing more of the system exists. the system uses 5 PCBs, one Z80 on each and instead of having dedicated sprite / tilemap chips they have the Z80s doing software rendering, using 8bpp framebuffers. 2 of the boards are for background planes, 1 of the boards is for sprites. The hardware has various memory expansions which look like afterthoughts as they're addressed in strange ways.
This commit is contained in:
parent
5df1518708
commit
a060de5062
@ -4331,6 +4331,12 @@ files {
|
||||
MAME_DIR .. "src/mame/machine/cdislave.h",
|
||||
MAME_DIR .. "src/mame/machine/cdicdic.cpp",
|
||||
MAME_DIR .. "src/mame/machine/cdicdic.h",
|
||||
MAME_DIR .. "src/mame/drivers/cedar_magnet.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/cedar_magnet_sound.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/cedar_magnet_plane.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/cedar_magnet_sprite.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/cedar_magnet_board.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/cedar_magnet_flop.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/cesclass.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/chance32.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/chexx.cpp",
|
||||
|
796
src/mame/drivers/cedar_magnet.cpp
Normal file
796
src/mame/drivers/cedar_magnet.cpp
Normal file
@ -0,0 +1,796 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:David Haywood
|
||||
// thanks to: Ricky2001, ArcadeHacker, IFW
|
||||
|
||||
/*
|
||||
todo:
|
||||
- fix sound emulation
|
||||
- fix sprite communication / banking
|
||||
* bit "output bit 0x02 %d (IC21)" at 0x42 might be important
|
||||
* mag_exzi currently requires a gross hack to stop the sprite CPU crashing on startup
|
||||
* mag_xain sometimes leaves old sprites on the screen, probably due to a lost clear
|
||||
command
|
||||
- fix flipscreen
|
||||
- verify behavior of unknown / unused ports / interrupt sources etc.
|
||||
- verify the disk images, convert to a better format that can natively store protection
|
||||
* RAW data also available if required
|
||||
* as mentioned, the disks are copy protected, see notes below
|
||||
* are the bad tiles shortly into the first level of mag_exzi caused by a bad dump or
|
||||
bad comms?
|
||||
- Use proper floppy drive emulation code that originally came from MESS (tied with above)
|
||||
- verify all clocks and screen params (50hz seems to match original videos)
|
||||
- work out why we need a protection hack and replace it with proper emulation
|
||||
* there are no per-game protection devices, so it's something to do with the base hardware
|
||||
* there seem to be 2 checks, one based on a weird sector on the discs, the other based on
|
||||
a port read
|
||||
- add additional hardware notes from ArcadeHacker
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Magnet System by
|
||||
|
||||
EFO SA (Electrónica Funcional Operativa SA).
|
||||
based on Cedar hardware
|
||||
|
||||
|
||||
http://retrolaser.es/cedar-computer-el-ordenador-profesional-de-efo-sa/
|
||||
http://www.recreativas.org/magnet-system-2427-efosa
|
||||
|
||||
A number of original games as well as conversions were advertised for this system, it is however
|
||||
believed that EFO went bankrupt before anything hit the market. The only 3 dumped games are
|
||||
conversions and appear to be in incomplete states (it is rather easy to break Time Scanner for
|
||||
example, the ball simply gets stuck in some places) These are not simply bootlegs, they're
|
||||
completely original pieces of code more akin to home computer ports.
|
||||
|
||||
The following were advertised
|
||||
Original Games
|
||||
- A Day in Space **
|
||||
- Crazy Driver
|
||||
- Jungle Trophy
|
||||
- Quadrum
|
||||
- War Mission **
|
||||
- The Burning Cave
|
||||
- Scorpio
|
||||
- Paris Dakar **
|
||||
- Sailing Race
|
||||
- Formula
|
||||
|
||||
Ports / Conversions
|
||||
- Exzisus *
|
||||
- Double Dragon
|
||||
- Flying Shark
|
||||
- Time Scanner *
|
||||
- Xain d'Sleena *
|
||||
- Boody Kids (Booby Kids?)
|
||||
|
||||
** screenshots present on flyer
|
||||
* dumps exist
|
||||
|
||||
|
||||
|
||||
Disk Protection
|
||||
|
||||
Sectors are 1024 (0x400) bytes long but marked on the disc as 512 bytes as a copy protection
|
||||
Sector numbering for each track starts at 200 (0xC8) again, presumably as a protection.
|
||||
Each track has 6 sectors (200 - 205)
|
||||
The drive runs at 240 RPM allowing for ~25% extra data. (attempting to dump at other speeds won't work)
|
||||
|
||||
data order / sector marking
|
||||
track 0, side 0, sector 200...205 (instead of sector 0...5)
|
||||
track 0, side 1, sector 200...205
|
||||
track 1, side 0, sector 200...205
|
||||
track 1, side 1, sector 200...205
|
||||
|
||||
Note, the games store settings / scores to the disk and don't provide any kind of 'factory reset'
|
||||
option, so if used the data will not be pristine.
|
||||
|
||||
PCB Setup
|
||||
|
||||
The hardware consists of 5 main PCBs in a cage.
|
||||
1x Audio PCB (on top)
|
||||
1x Master PCB
|
||||
2x Plane PCBs (both identical aside from jumper settings)
|
||||
1x Sprite PCB
|
||||
|
||||
There are small memory sub-boards on the Master PCB and Sprite PCB; due to the awkwardness of
|
||||
the banking at times (and the fact that even with 4 banks of 256 colours, only one can be active)
|
||||
I suspect the additional memory was an afterthought.
|
||||
|
||||
(put more details hardware notes here)
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "cedar_magnet.h"
|
||||
|
||||
/***********************
|
||||
|
||||
Memory maps
|
||||
|
||||
***********************/
|
||||
|
||||
static ADDRESS_MAP_START( cedar_magnet_mainboard_sub_pal_map, AS_PROGRAM, 8, cedar_magnet_state )
|
||||
// these are 3x MOTOROLA MM2114N SRAM 4096 bit RAM (twice the size because we map bytes, but only 4 bits are used)
|
||||
// these are on the master board memory sub-board
|
||||
AM_RANGE(0x2400, 0x27ff) AM_RAM_WRITE(palette_r_w) AM_SHARE("pal_r")
|
||||
AM_RANGE(0x2800, 0x2bff) AM_RAM_WRITE(palette_g_w) AM_SHARE("pal_g")
|
||||
AM_RANGE(0x3000, 0x33ff) AM_RAM_WRITE(palette_b_w) AM_SHARE("pal_b")
|
||||
ADDRESS_MAP_END
|
||||
|
||||
static ADDRESS_MAP_START( cedar_magnet_mainboard_sub_ram_map, AS_PROGRAM, 8, cedar_magnet_state )
|
||||
// these are 8x SIEMENS HYB 41256-15 AA - 262,144 bit DRAM (32kbytes)
|
||||
// these are on the master board memory sub-board
|
||||
AM_RANGE(0x00000, 0x3ffff) AM_RAM AM_SHARE("ram0")
|
||||
ADDRESS_MAP_END
|
||||
|
||||
static ADDRESS_MAP_START( cedar_magnet_map, AS_PROGRAM, 8, cedar_magnet_state )
|
||||
AM_RANGE(0x0000, 0xffff) AM_DEVICE("bank0", address_map_bank_device, amap8)
|
||||
ADDRESS_MAP_END
|
||||
|
||||
static ADDRESS_MAP_START( cedar_magnet_io, AS_IO, 8, cedar_magnet_state )
|
||||
ADDRESS_MAP_GLOBAL_MASK(0xff)
|
||||
|
||||
AM_RANGE(0x18, 0x18) AM_READWRITE(port18_r, port18_w)
|
||||
AM_RANGE(0x19, 0x19) AM_READWRITE(port19_r, port19_w)
|
||||
AM_RANGE(0x1a, 0x1a) AM_READ(port1a_r)
|
||||
AM_RANGE(0x1b, 0x1b) AM_WRITE(port1b_w)
|
||||
|
||||
AM_RANGE(0x20, 0x23) AM_DEVREADWRITE("z80pio_ic48", z80pio_device, read_alt, write_alt)
|
||||
AM_RANGE(0x40, 0x43) AM_DEVREADWRITE("z80pio_ic49", z80pio_device, read_alt, write_alt)
|
||||
|
||||
AM_RANGE(0x60, 0x63) AM_DEVREADWRITE("flop", cedar_magnet_flop_device, read, write)
|
||||
|
||||
AM_RANGE(0x64, 0x64) AM_READ_PORT("P1_IN")
|
||||
AM_RANGE(0x68, 0x68) AM_READ_PORT("P2_IN")
|
||||
AM_RANGE(0x6c, 0x6c) AM_READ_PORT("TEST")
|
||||
|
||||
// banking / access controls to the sub-board memory
|
||||
AM_RANGE(0x70, 0x70) AM_WRITE(rambank_palbank_w)
|
||||
AM_RANGE(0x74, 0x74) AM_WRITE(palupload_w)
|
||||
AM_RANGE(0x78, 0x78) AM_READWRITE(watchdog_r, paladdr_w)
|
||||
AM_RANGE(0x7c, 0x7c) AM_READ(port7c_r) // protection??
|
||||
|
||||
AM_RANGE(0xff, 0xff) AM_WRITE(soundlatch_w)
|
||||
ADDRESS_MAP_END
|
||||
|
||||
static ADDRESS_MAP_START( cedar_bank0, AS_PROGRAM, 8, cedar_magnet_state )
|
||||
/* memory configuration 0 */
|
||||
AM_RANGE(0x00000, 0x0ffff) AM_DEVICE("mb_sub_ram", address_map_bank_device, amap8)
|
||||
|
||||
/* memory configuration 1 */
|
||||
AM_RANGE(0x10000, 0x1dfff) AM_DEVICE("mb_sub_ram", address_map_bank_device, amap8)
|
||||
AM_RANGE(0x1e000, 0x1ffff) AM_ROM AM_REGION("maincpu", 0x0000)
|
||||
|
||||
/* memory configuration 2*/
|
||||
AM_RANGE(0x20000, 0x2bfff) AM_DEVICE("mb_sub_ram", address_map_bank_device, amap8)
|
||||
AM_RANGE(0x2c000, 0x2ffff) AM_READWRITE(other_cpu_r, other_cpu_w)
|
||||
|
||||
/* memory configuration 3*/
|
||||
AM_RANGE(0x30000, 0x31fff) AM_ROM AM_REGION("maincpu", 0x0000) AM_MIRROR(0x0e000)
|
||||
ADDRESS_MAP_END
|
||||
|
||||
|
||||
/***********************
|
||||
|
||||
7x - ports
|
||||
Main board RAM sub-board
|
||||
|
||||
***********************/
|
||||
|
||||
WRITE8_MEMBER(cedar_magnet_state::rambank_palbank_w)
|
||||
{
|
||||
// ---- --xx
|
||||
// xx = program bank
|
||||
m_sub_ram_bankdev->set_bank(data & 0x03);
|
||||
|
||||
// yyy? yy-- palette bank
|
||||
m_palbank = data;
|
||||
int palbank = ((data & 0xc0) >> 6) | (data & 0x3c);
|
||||
m_sub_pal_bankdev->set_bank(palbank);
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(cedar_magnet_state::palupload_w)
|
||||
{
|
||||
m_sub_pal_bankdev->write8(space, m_paladdr, data);
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(cedar_magnet_state::paladdr_w)
|
||||
{
|
||||
m_paladdr = data;
|
||||
}
|
||||
|
||||
READ8_MEMBER(cedar_magnet_state::watchdog_r)
|
||||
{
|
||||
// watchdog
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
|
||||
/***********************
|
||||
|
||||
7c - protection??
|
||||
|
||||
***********************/
|
||||
|
||||
READ8_MEMBER(cedar_magnet_state::port7c_r)
|
||||
{
|
||||
//printf("%s: port7c_r\n", device().machine().describe_context());
|
||||
return 0x01;
|
||||
}
|
||||
|
||||
|
||||
/***********************
|
||||
|
||||
1x ports
|
||||
Unknown, debug? protection?
|
||||
|
||||
***********************/
|
||||
|
||||
READ8_MEMBER(cedar_magnet_state::port18_r)
|
||||
{
|
||||
// printf("%s: port18_r\n", device().machine().describe_context());
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(cedar_magnet_state::port18_w)
|
||||
{
|
||||
// printf("%s: port18_w %02x\n", device().machine().describe_context(), data);
|
||||
}
|
||||
|
||||
READ8_MEMBER(cedar_magnet_state::port19_r)
|
||||
{
|
||||
UINT8 ret = 0x00;
|
||||
// printf("%s: port19_r\n", device().machine().describe_context());
|
||||
|
||||
// 9496 in a,($19)
|
||||
// 9498 bit 2,a
|
||||
|
||||
ret |= 0x04;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
READ8_MEMBER(cedar_magnet_state::port1a_r)
|
||||
{
|
||||
// printf("%s: port1a_r\n", device().machine().describe_context());
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
|
||||
WRITE8_MEMBER(cedar_magnet_state::port19_w)
|
||||
{
|
||||
// printf("%s: port19_w %02x\n", device().machine().describe_context(), data);
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(cedar_magnet_state::port1b_w)
|
||||
{
|
||||
// printf("%s: port1b_w %02x\n", device().machine().describe_context(), data);
|
||||
}
|
||||
|
||||
/***********************
|
||||
|
||||
Palette / Video
|
||||
|
||||
***********************/
|
||||
|
||||
void cedar_magnet_state::set_palette(int offset)
|
||||
{
|
||||
m_palette->set_pen_color(offset^0xff, pal4bit(m_pal_r[offset]), pal4bit(m_pal_g[offset]), pal4bit(m_pal_b[offset]));
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(cedar_magnet_state::palette_r_w)
|
||||
{
|
||||
m_pal_r[offset] = data;
|
||||
set_palette(offset);
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(cedar_magnet_state::palette_g_w)
|
||||
{
|
||||
m_pal_g[offset] = data;
|
||||
set_palette(offset);
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(cedar_magnet_state::palette_b_w)
|
||||
{
|
||||
m_pal_b[offset] = data;
|
||||
set_palette(offset);
|
||||
}
|
||||
|
||||
UINT32 cedar_magnet_state::screen_update_cedar_magnet(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
|
||||
bitmap.fill(m_palette->black_pen(), cliprect);
|
||||
|
||||
int pal = (m_palbank >> 6);
|
||||
|
||||
m_cedplane1->draw(screen, bitmap, cliprect,pal);
|
||||
m_cedplane0->draw(screen, bitmap, cliprect,pal);
|
||||
m_cedsprite->draw(screen, bitmap, cliprect,pal);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cedar_magnet_state::video_start()
|
||||
{
|
||||
}
|
||||
|
||||
/***********************
|
||||
|
||||
Access to other CPUs
|
||||
|
||||
***********************/
|
||||
|
||||
WRITE8_MEMBER(cedar_magnet_state::soundlatch_w)
|
||||
{
|
||||
// printf("%s: writing soundlatch_w! %02x\n", device().machine().describe_context(), data);
|
||||
portff_data = data;
|
||||
m_cedsound->write_command(data);
|
||||
}
|
||||
|
||||
READ8_MEMBER(cedar_magnet_state::other_cpu_r)
|
||||
{
|
||||
int bankbit0 = (m_ic48_pio_pa_val & 0x60) >> 5;
|
||||
int plane0select = (m_ic48_pio_pa_val & 0x07) >> 0;
|
||||
int plane1select = (m_ic48_pio_pb_val & 0x07) >> 0;
|
||||
int spriteselect = (m_ic48_pio_pb_val & 0x70) >> 4;
|
||||
int soundselect = (m_ic49_pio_pb_val & 0x70) >> 4;
|
||||
int windowbank = (m_ic49_pio_pb_val & 0x0c) >> 2;
|
||||
int unk2 = (m_ic49_pio_pb_val & 0x03) >> 0;
|
||||
|
||||
int cpus_accessed = 0;
|
||||
UINT8 ret = 0x00;
|
||||
|
||||
int offset2 = offset + windowbank * 0x4000;
|
||||
|
||||
if (spriteselect == 0x1)
|
||||
{
|
||||
cpus_accessed++;
|
||||
ret |= m_cedsprite->read_cpu_bus(offset2);
|
||||
}
|
||||
|
||||
if (plane0select == 0x1)
|
||||
{
|
||||
cpus_accessed++;
|
||||
ret |= m_cedplane0->read_cpu_bus(offset2);
|
||||
}
|
||||
|
||||
if (plane1select == 0x1)
|
||||
{
|
||||
cpus_accessed++;
|
||||
ret |= m_cedplane1->read_cpu_bus(offset2);
|
||||
}
|
||||
|
||||
if (soundselect == 0x1)
|
||||
{
|
||||
cpus_accessed++;
|
||||
ret |= m_cedsound->read_cpu_bus(offset2);
|
||||
logerror("%s: reading soundselect! %04x - bank bits %d %d %d %d %d %d %d\n", device().machine().describe_context(), offset,bankbit0, plane0select, plane1select, spriteselect, soundselect, windowbank, unk2);
|
||||
}
|
||||
|
||||
if (cpus_accessed != 1)
|
||||
logerror("%s: reading multiple CPUS!!! %04x - bank bits %d %d %d %d %d %d %d\n", device().machine().describe_context(), offset,bankbit0, plane0select, plane1select, spriteselect, soundselect, windowbank, unk2);
|
||||
|
||||
// if ((offset==0) || (offset2 == 0xe) || (offset2 == 0xf) || (offset2 == 0x68))
|
||||
// logerror("%s: reading banked bus area %04x - bank bits %d %d %d %d %d %d %d\n", device().machine().describe_context(), offset,bankbit0, plane0select, plane1select, spriteselect, soundselect, windowbank, unk2);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(cedar_magnet_state::other_cpu_w)
|
||||
{
|
||||
int bankbit0 = (m_ic48_pio_pa_val & 0x60) >> 5;
|
||||
int plane0select = (m_ic48_pio_pa_val & 0x07) >> 0;
|
||||
int plane1select = (m_ic48_pio_pb_val & 0x07) >> 0;
|
||||
int spriteselect = (m_ic48_pio_pb_val & 0x70) >> 4;
|
||||
int soundselect = (m_ic49_pio_pb_val & 0x70) >> 4;
|
||||
int windowbank = (m_ic49_pio_pb_val & 0x0c) >> 2;
|
||||
int unk2 = (m_ic49_pio_pb_val & 0x03) >> 0;
|
||||
|
||||
int cpus_accessed = 0;
|
||||
|
||||
int offset2 = offset + windowbank * 0x4000;
|
||||
|
||||
if (spriteselect == 0x1)
|
||||
{
|
||||
cpus_accessed++;
|
||||
m_cedsprite->write_cpu_bus(offset2, data);
|
||||
}
|
||||
|
||||
if (plane0select == 0x1)
|
||||
{
|
||||
cpus_accessed++;
|
||||
m_cedplane0->write_cpu_bus(offset2, data);
|
||||
}
|
||||
|
||||
if (plane1select == 0x1)
|
||||
{
|
||||
cpus_accessed++;
|
||||
m_cedplane1->write_cpu_bus(offset2, data);
|
||||
}
|
||||
|
||||
if (soundselect == 0x1)
|
||||
{
|
||||
cpus_accessed++;
|
||||
m_cedsound->write_cpu_bus(offset2, data);
|
||||
// printf("%s: sound cpu write %04x %02x - bank bits %d %d %d %d %d %d %d\n", device().machine().describe_context(), offset,data, bankbit0, plane0select, plane1select, spriteselect, soundselect, windowbank, unk2);
|
||||
}
|
||||
|
||||
if (cpus_accessed != 1)
|
||||
logerror("%s: writing multiple CPUS!!! %04x %02x - bank bits %d %d %d %d %d %d %d\n", device().machine().describe_context(), offset,data, bankbit0, plane0select, plane1select, spriteselect, soundselect, windowbank, unk2);
|
||||
|
||||
// if ((offset==0) || (offset2 == 0xe) || (offset2 == 0xf) || (offset2 == 0x68))
|
||||
// printf("%s: other cpu write %04x %02x - bank bits %d %d %d %d %d %d %d\n", device().machine().describe_context(), offset,data, bankbit0, plane0select, plane1select, spriteselect, soundselect, windowbank, unk2);
|
||||
}
|
||||
|
||||
|
||||
void cedar_magnet_state::handle_sub_board_cpu_lines(cedar_magnet_board_device* dev, int old_data, int data)
|
||||
{
|
||||
if (old_data != data)
|
||||
{
|
||||
if (data & 0x04)
|
||||
dev->reset_assert();
|
||||
else
|
||||
dev->reset_clear();
|
||||
|
||||
if (data & 0x02)
|
||||
dev->halt_clear();
|
||||
else
|
||||
dev->halt_assert();
|
||||
}
|
||||
}
|
||||
|
||||
/***********************
|
||||
|
||||
IC 48 PIO handlers
|
||||
(mapped at 0x20 / 0x22)
|
||||
|
||||
***********************/
|
||||
|
||||
READ8_MEMBER( cedar_magnet_state::ic48_pio_pa_r ) // 0x20
|
||||
{
|
||||
UINT8 ret = m_ic48_pio_pa_val & ~0x08;
|
||||
|
||||
ret |= ioport("COIN1")->read()<<3;
|
||||
if (!m_cedplane0->is_running()) ret &= ~0x01;
|
||||
|
||||
// interrupt source stuff??
|
||||
ret &= ~0x10;
|
||||
|
||||
if (LOG_IC48_PIO_PA) printf("%s: ic48_pio_pa_r (returning %02x)\n", device().machine().describe_context(), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER( cedar_magnet_state::ic48_pio_pa_w ) // 0x20
|
||||
{
|
||||
int oldplane0select = (m_ic48_pio_pa_val & 0x07) >> 0;
|
||||
|
||||
// bits 19 are set to input?
|
||||
m_ic48_pio_pa_val = data;
|
||||
|
||||
// address 0x20 - pio ic48 port a
|
||||
if (LOG_IC48_PIO_PA) printf("%s: ic48_pio_pa_w %02x (memory banking etc.)\n", device().machine().describe_context(), data);
|
||||
|
||||
if (LOG_IC48_PIO_PA) printf("output bit 0x80 %d (unused)\n", (data >> 7)&1); // A7 -> 12 J4 unpopulated
|
||||
if (LOG_IC48_PIO_PA) printf("output bit 0x40 %d (bank)\n", (data >> 6)&1); // A6 -> 2 74HC10 3NAND IC19
|
||||
if (LOG_IC48_PIO_PA) printf("output bit 0x20 %d (bank)\n", (data >> 5)&1); // A5 -> 4 74HC10 3NAND IC19
|
||||
if (LOG_IC48_PIO_PA) printf("input bit 0x10 %d (interrupt source related?)\n", (data >> 4)&1); // 10 in // A4 <- 9 74HC74 IC20 <- input from 18 74LS244 IC61
|
||||
if (LOG_IC48_PIO_PA) printf("input bit 0x08 %d (COIN1)\n", (data >> 3)&1); // 08 in // A3 <- 4 74HC14P (inverter) IC4 <- EDGE 21 COIN1
|
||||
if (LOG_IC48_PIO_PA) printf("output bit 0x04 %d (plane0 CPU/bus related?)\n", (data >> 2)&1); // A2 -> 45 J6
|
||||
if (LOG_IC48_PIO_PA) printf("output bit 0x02 %d (plane0 CPU/bus related?)\n", (data >> 1)&1); // A1 -> 47 J6
|
||||
if (LOG_IC48_PIO_PA) printf("input bit 0x01 %d (plane0 CPU/bus related?)\n", (data >> 0)&1); // A0 -> 49 J6
|
||||
|
||||
int bankbit0 = (m_ic48_pio_pa_val & 0x60) >> 5;
|
||||
m_bank0->set_bank(bankbit0);
|
||||
|
||||
int plane0select = (m_ic48_pio_pa_val & 0x07) >> 0;
|
||||
|
||||
handle_sub_board_cpu_lines(m_cedplane0, oldplane0select, plane0select);
|
||||
}
|
||||
|
||||
|
||||
READ8_MEMBER( cedar_magnet_state::ic48_pio_pb_r ) // 0x22
|
||||
{
|
||||
UINT8 ret = m_ic48_pio_pb_val & ~0x80;
|
||||
|
||||
ret |= ioport("COIN2")->read()<<7;
|
||||
|
||||
if (!m_cedsprite->is_running()) ret &= ~0x10;
|
||||
if (!m_cedplane1->is_running()) ret &= ~0x01;
|
||||
|
||||
if (LOG_IC48_PIO_PB) printf("%s: ic48_pio_pb_r (returning %02x)\n", device().machine().describe_context(), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(cedar_magnet_state::ic48_pio_pb_w) // 0x22
|
||||
{
|
||||
int oldplane1select = (m_ic48_pio_pb_val & 0x07) >> 0;
|
||||
int oldspriteselect = (m_ic48_pio_pb_val & 0x70) >> 4;
|
||||
|
||||
m_ic48_pio_pb_val = data;
|
||||
|
||||
if (LOG_IC48_PIO_PB) printf("%s: ic48_pio_pb_w %02x\n", device().machine().describe_context(), data);
|
||||
|
||||
// address 0x22 - pio ic48 port b
|
||||
if (LOG_IC48_PIO_PB) printf("input bit 0x80 %d (COIN2)\n", (data >> 7)&1); // B7 <- 2 74HC14P (inverter) IC4 <- EDGE 22 COIN2
|
||||
if (LOG_IC48_PIO_PB) printf("output bit 0x40 (J6) (sprite CPU/bus related?) %d\n", (data >> 6)&1); // B6 -> 41 J6
|
||||
if (LOG_IC48_PIO_PB) printf("output bit 0x20 (J6) (sprite CPU/bus related?) %d\n", (data >> 5)&1); // B5 -> 43 J6
|
||||
if (LOG_IC48_PIO_PB) printf("input bit 0x10 (J6) (sprite CPU/bus related?) %d\n", (data >> 4)&1); // B4 -> 44 J6
|
||||
if (LOG_IC48_PIO_PB) printf("output bit 0x08 (Q8) %d\n", (data >> 3)&1); // B3 -> Q8 transistor
|
||||
if (LOG_IC48_PIO_PB) printf("output bit 0x04 (J6) (plane1 CPU/bus related?) %d\n", (data >> 2)&1); // B2 -> 46 J6
|
||||
if (LOG_IC48_PIO_PB) printf("output bit 0x02 (J6) (plane1 CPU/bus related?) %d\n", (data >> 1)&1); // B1 -> 48 J6
|
||||
if (LOG_IC48_PIO_PB) printf("input bit 0x01 (J6) (plane1 CPU/bus related?) %d\n", (data >> 0)&1); // B0 -> 50 J6
|
||||
|
||||
int plane1select = (m_ic48_pio_pb_val & 0x07) >> 0;
|
||||
int spriteselect = (m_ic48_pio_pb_val & 0x70) >> 4;
|
||||
|
||||
handle_sub_board_cpu_lines(m_cedplane1, oldplane1select, plane1select);
|
||||
handle_sub_board_cpu_lines(m_cedsprite, oldspriteselect, spriteselect);
|
||||
}
|
||||
|
||||
/***********************
|
||||
|
||||
IC 49 PIO handlers
|
||||
(mapped at 0x42)
|
||||
|
||||
***********************/
|
||||
|
||||
READ8_MEMBER( cedar_magnet_state::ic49_pio_pb_r ) // 0x42
|
||||
{
|
||||
UINT8 ret = m_ic49_pio_pb_val;
|
||||
|
||||
if (!m_cedsound->is_running()) ret &= ~0x10;
|
||||
|
||||
if (LOG_IC49_PIO_PB) printf("%s: ic49_pio_pb_r (returning %02x)\n", device().machine().describe_context(), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER( cedar_magnet_state::ic49_pio_pb_w ) // 0x42
|
||||
{
|
||||
int oldsoundselect = (m_ic49_pio_pb_val & 0x70) >> 4;
|
||||
|
||||
m_ic49_pio_pb_val = data;
|
||||
|
||||
//printf("%s: ic49_pio_pb_w %02x\n", device().machine().describe_context(), data);
|
||||
|
||||
// address 0x42 - pio ic49 port b
|
||||
if (LOG_IC49_PIO_PB) printf("output bit 0x80 %d (Q9)\n", (data >> 7)&1); // B7 -> Q9 transistor
|
||||
if (LOG_IC49_PIO_PB) printf("output bit 0x40 %d (sound CPU bus related) (J3)\n", (data >> 6)&1); // B6 -> 9 J3
|
||||
if (LOG_IC49_PIO_PB) printf("output bit 0x20 %d (sound CPU bus related) (J3)\n", (data >> 5)&1); // B5 -> 8 J3
|
||||
if (LOG_IC49_PIO_PB) printf("input bit 0x10 %d (sound CPU bus related) (J3)\n", (data >> 4)&1); // B4 -> 7 J3 // input?
|
||||
if (LOG_IC49_PIO_PB) printf("output bit 0x08 %d (J7)\n", (data >> 3)&1); // B3 -> 35 J7 bank bits
|
||||
if (LOG_IC49_PIO_PB) printf("output bit 0x04 %d (J7)\n", (data >> 2)&1); // B2 -> 36 J7 bank bits
|
||||
// there is code to mask out both bottom bits here before load operations?
|
||||
if (LOG_IC49_PIO_PB) printf("output bit 0x02 %d (IC21)\n", (data >> 1)&1); // B1 -> 3 74HC04 IC21 (set before some SPRITE cpu operations, possibly halts the blitter?)
|
||||
if (LOG_IC49_PIO_PB) printf("output bit 0x01 (LED) %d\n", (data >> 0)&1); // B0 -> LED LD1
|
||||
|
||||
|
||||
|
||||
int soundselect = (m_ic49_pio_pb_val & 0x70) >> 4;
|
||||
|
||||
handle_sub_board_cpu_lines(m_cedsound, oldsoundselect, soundselect);
|
||||
}
|
||||
|
||||
/***********************
|
||||
|
||||
Init / Inputs / Machine
|
||||
|
||||
***********************/
|
||||
|
||||
void cedar_magnet_state::machine_start()
|
||||
{
|
||||
save_item(NAME(m_paladdr));
|
||||
}
|
||||
|
||||
void cedar_magnet_state::machine_reset()
|
||||
{
|
||||
m_ic48_pio_pa_val = 0xff;
|
||||
portff_data = 0x00;
|
||||
|
||||
int bankbit0 = (m_ic48_pio_pa_val & 0x60) >> 5;
|
||||
m_bank0->set_bank(bankbit0);
|
||||
m_sub_ram_bankdev->set_bank(3);
|
||||
m_sub_pal_bankdev->set_bank(0);
|
||||
}
|
||||
|
||||
|
||||
static INPUT_PORTS_START( cedar_magnet )
|
||||
PORT_START("COIN1")
|
||||
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_COIN1 )
|
||||
|
||||
PORT_START("COIN2")
|
||||
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_COIN2 )
|
||||
|
||||
PORT_START("P1_IN")
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY
|
||||
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY
|
||||
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY
|
||||
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 )
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 )
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON3 )
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_START1 )
|
||||
|
||||
PORT_START("P2_IN")
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2)
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2)
|
||||
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2)
|
||||
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(2)
|
||||
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2)
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2)
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2)
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_START2 )
|
||||
|
||||
PORT_START("TEST")
|
||||
PORT_BIT( 0x7f, IP_ACTIVE_LOW, IPT_UNUSED )
|
||||
PORT_SERVICE_NO_TOGGLE( 0x80, IP_ACTIVE_LOW )
|
||||
INPUT_PORTS_END
|
||||
|
||||
INTERRUPT_GEN_MEMBER(cedar_magnet_state::irq)
|
||||
{
|
||||
if (m_prothack)
|
||||
m_prothack(this);
|
||||
|
||||
m_maincpu->set_input_line(0, HOLD_LINE);
|
||||
// maybe generate the irqs for the other PCBs here?
|
||||
}
|
||||
|
||||
static MACHINE_CONFIG_START( cedar_magnet, cedar_magnet_state )
|
||||
|
||||
/* basic machine hardware */
|
||||
MCFG_CPU_ADD("maincpu", Z80,4000000) /* ? MHz */
|
||||
MCFG_CPU_PROGRAM_MAP(cedar_magnet_map)
|
||||
MCFG_CPU_IO_MAP(cedar_magnet_io)
|
||||
MCFG_CPU_VBLANK_INT_DRIVER("screen", cedar_magnet_state, irq)
|
||||
|
||||
MCFG_DEVICE_ADD("bank0", ADDRESS_MAP_BANK, 0)
|
||||
MCFG_DEVICE_PROGRAM_MAP(cedar_bank0)
|
||||
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)
|
||||
|
||||
MCFG_DEVICE_ADD("mb_sub_ram", ADDRESS_MAP_BANK, 0)
|
||||
MCFG_DEVICE_PROGRAM_MAP(cedar_magnet_mainboard_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)
|
||||
|
||||
MCFG_DEVICE_ADD("mb_sub_pal", ADDRESS_MAP_BANK, 0)
|
||||
MCFG_DEVICE_PROGRAM_MAP(cedar_magnet_mainboard_sub_pal_map)
|
||||
MCFG_ADDRESS_MAP_BANK_ENDIANNESS(ENDIANNESS_LITTLE)
|
||||
MCFG_ADDRESS_MAP_BANK_DATABUS_WIDTH(8)
|
||||
MCFG_ADDRESS_MAP_BANK_ADDRBUS_WIDTH(8+6)
|
||||
MCFG_ADDRESS_MAP_BANK_STRIDE(0x100)
|
||||
|
||||
MCFG_DEVICE_ADD("z80pio_ic48", Z80PIO, 4000000/2)
|
||||
// MCFG_Z80PIO_OUT_INT_CB(INPUTLINE("maincpu", INPUT_LINE_IRQ0))
|
||||
MCFG_Z80PIO_IN_PA_CB(READ8(cedar_magnet_state, ic48_pio_pa_r))
|
||||
MCFG_Z80PIO_OUT_PA_CB(WRITE8(cedar_magnet_state, ic48_pio_pa_w))
|
||||
MCFG_Z80PIO_IN_PB_CB(READ8(cedar_magnet_state, ic48_pio_pb_r))
|
||||
MCFG_Z80PIO_OUT_PB_CB(WRITE8(cedar_magnet_state, ic48_pio_pb_w))
|
||||
|
||||
MCFG_DEVICE_ADD("z80pio_ic49", Z80PIO, 4000000/2)
|
||||
// MCFG_Z80PIO_OUT_INT_CB(INPUTLINE("maincpu", INPUT_LINE_IRQ0))
|
||||
// MCFG_Z80PIO_IN_PA_CB(READ8(cedar_magnet_state, ic49_pio_pa_r)) // NOT USED
|
||||
// MCFG_Z80PIO_OUT_PA_CB(WRITE8(cedar_magnet_state, ic49_pio_pa_w)) // NOT USED
|
||||
MCFG_Z80PIO_IN_PB_CB(READ8(cedar_magnet_state, ic49_pio_pb_r))
|
||||
MCFG_Z80PIO_OUT_PB_CB(WRITE8(cedar_magnet_state, ic49_pio_pb_w))
|
||||
|
||||
/* video hardware */
|
||||
MCFG_SCREEN_ADD("screen", RASTER)
|
||||
MCFG_SCREEN_REFRESH_RATE(50)
|
||||
MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0))
|
||||
MCFG_SCREEN_SIZE(256, 256)
|
||||
MCFG_SCREEN_VISIBLE_AREA(0, 256-8-1, 0, 192-1)
|
||||
MCFG_SCREEN_UPDATE_DRIVER(cedar_magnet_state, screen_update_cedar_magnet)
|
||||
MCFG_SCREEN_PALETTE("palette")
|
||||
|
||||
MCFG_PALETTE_ADD("palette", 0x400)
|
||||
|
||||
MCFG_CEDAR_MAGNET_SOUND_ADD("cedtop")
|
||||
MCFG_CEDAR_MAGNET_PLANE_ADD("cedplane0")
|
||||
MCFG_CEDAR_MAGNET_PLANE_ADD("cedplane1")
|
||||
MCFG_CEDAR_MAGNET_SPRITE_ADD("cedsprite")
|
||||
|
||||
MCFG_CEDAR_MAGNET_FLOP_ADD("flop")
|
||||
|
||||
MCFG_QUANTUM_PERFECT_CPU("maincpu")
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
|
||||
#define BIOS_ROM \
|
||||
ROM_REGION( 0x10000, "maincpu", 0 ) \
|
||||
ROM_LOAD( "Magnet-Master-VID-E03.BIN", 0x00000, 0x02000, CRC(86c4a4f0) SHA1(6db1a006b2e0b2a7cc9748ade881debb098b6757) )
|
||||
|
||||
|
||||
|
||||
ROM_START( cedmag )
|
||||
BIOS_ROM
|
||||
|
||||
ROM_REGION( 0x100000, "flop:disk", ROMREGION_ERASE00 )
|
||||
// no disk inserted
|
||||
ROM_END
|
||||
|
||||
ROM_START( mag_time )
|
||||
BIOS_ROM
|
||||
|
||||
ROM_REGION( 0x100000, "flop:disk", 0 )
|
||||
ROM_LOAD( "timescanner.img", 0x00000, 0xf0000, CRC(214c558c) SHA1(9c71fce35acaf17ac685f77aebb1b0a930060f0b) )
|
||||
ROM_END
|
||||
|
||||
ROM_START( mag_exzi )
|
||||
BIOS_ROM
|
||||
|
||||
ROM_REGION( 0x100000, "flop:disk", ROMREGION_ERASE00 ) // I don't 100% trust this one
|
||||
ROM_LOAD( "exzisus.img", 0x00000, 0xf0000, BAD_DUMP CRC(1ac7409e) SHA1(b894bd65b0b9699e18a1ab49f309c460488f0ef8) )
|
||||
ROM_END
|
||||
|
||||
ROM_START( mag_xain )
|
||||
BIOS_ROM
|
||||
|
||||
ROM_REGION( 0x100000, "flop:disk", ROMREGION_ERASE00 )
|
||||
ROM_LOAD( "xain.img", 0x00000, 0xf0000, CRC(5647849f) SHA1(edd2f3f6359424583bf526bf4601476dc849e617) )
|
||||
ROM_END
|
||||
|
||||
/*
|
||||
protection? (Time Scanner note)
|
||||
|
||||
one part of the code is a weird loop checking values from port 0x7c while doing other nonsensical stuff, a flag gets set to 0xff if it fails
|
||||
|
||||
the other part is after reading the weird extra block on the disk (score / protection data at 0xea400 in the disk image*) and again a flag
|
||||
gets set to 0xff in certain conditions there's then a check after inserting a coin, these values can't be 0xff at that point, and there
|
||||
doesn't appear to be any code to reset them.
|
||||
|
||||
*0xea400 is/was track 4e, side 00, sector 01 for future reference if the floppy format changes
|
||||
|
||||
all games have the same code in them but at different addresses
|
||||
*/
|
||||
|
||||
|
||||
void protection_hack(UINT8* ram, int address1, int address2)
|
||||
{
|
||||
if ((ram[address1] == 0x3e) && (ram[address1+1] == 0xff)) ram[address1] = 0xc9;
|
||||
if ((ram[address2] == 0x3e) && (ram[address2+1] == 0xff)) ram[address2] = 0xc9;
|
||||
}
|
||||
|
||||
void mag_time_protection_hack(cedar_magnet_state* state)
|
||||
{
|
||||
protection_hack(state->m_ram0, 0x8bc, 0x905);
|
||||
}
|
||||
|
||||
void mag_xain_protection_hack(cedar_magnet_state* state)
|
||||
{
|
||||
protection_hack(state->m_ram0, 0x796, 0x7df);
|
||||
}
|
||||
|
||||
void mag_exzi_protection_hack(cedar_magnet_state* state)
|
||||
{
|
||||
protection_hack(state->m_ram0, 0x8b6, 0x8ff);
|
||||
}
|
||||
|
||||
|
||||
|
||||
DRIVER_INIT_MEMBER(cedar_magnet_state, mag_time)
|
||||
{
|
||||
m_prothack = mag_time_protection_hack;
|
||||
}
|
||||
|
||||
DRIVER_INIT_MEMBER(cedar_magnet_state, mag_xain)
|
||||
{
|
||||
m_prothack = mag_xain_protection_hack;
|
||||
}
|
||||
|
||||
DRIVER_INIT_MEMBER(cedar_magnet_state, mag_exzi)
|
||||
{
|
||||
m_prothack = mag_exzi_protection_hack;
|
||||
}
|
||||
|
||||
GAME( 1987, cedmag, 0, cedar_magnet, cedar_magnet, driver_device, 0, ROT0, "EFO SA / Cedar", "Magnet System (prototype)", MACHINE_IS_BIOS_ROOT )
|
||||
|
||||
GAME( 1987, mag_time, cedmag, cedar_magnet, cedar_magnet, cedar_magnet_state, mag_time, ROT90, "EFO SA / Cedar", "Time Scanner (TS 2.0, Magnet System, prototype)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_NO_SOUND ) // original game was by Sega
|
||||
GAME( 1987, mag_exzi, cedmag, cedar_magnet, cedar_magnet, cedar_magnet_state, mag_exzi, ROT0, "EFO SA / Cedar", "Exzisus (EX 1.0, Magnet System, prototype)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_NO_SOUND ) // original game was by Taito
|
||||
GAME( 1987, mag_xain, cedmag, cedar_magnet, cedar_magnet, cedar_magnet_state, mag_xain, ROT0, "EFO SA / Cedar", "Xain'd Sleena (SC 3.0, Magnet System, prototype)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_NO_SOUND ) // original game was by Technos
|
131
src/mame/drivers/cedar_magnet.h
Normal file
131
src/mame/drivers/cedar_magnet.h
Normal file
@ -0,0 +1,131 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:David Haywood
|
||||
/*
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "emu.h"
|
||||
#include "cpu/z80/z80.h"
|
||||
#include "cpu/z80/z80daisy.h"
|
||||
#include "machine/z80pio.h"
|
||||
#include "machine/bankdev.h"
|
||||
#include "machine/z80ctc.h"
|
||||
#include "sound/ay8910.h"
|
||||
|
||||
#include "cedar_magnet_sound.h"
|
||||
#include "cedar_magnet_plane.h"
|
||||
#include "cedar_magnet_sprite.h"
|
||||
#include "cedar_magnet_flop.h"
|
||||
|
||||
#define LOG_IC49_PIO_PB 0
|
||||
#define LOG_IC48_PIO_PB 0
|
||||
#define LOG_IC48_PIO_PA 0
|
||||
|
||||
class cedar_magnet_state : public driver_device
|
||||
{
|
||||
public:
|
||||
cedar_magnet_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: driver_device(mconfig, type, tag),
|
||||
m_bank0(*this, "bank0"),
|
||||
m_sub_ram_bankdev(*this, "mb_sub_ram"),
|
||||
m_sub_pal_bankdev(*this, "mb_sub_pal"),
|
||||
m_ram0(*this, "ram0"),
|
||||
m_pal_r(*this, "pal_r"),
|
||||
m_pal_g(*this, "pal_g"),
|
||||
m_pal_b(*this, "pal_b"),
|
||||
|
||||
m_ic48_pio(*this, "z80pio_ic48"),
|
||||
m_ic49_pio(*this, "z80pio_ic49"),
|
||||
m_palette(*this, "palette"),
|
||||
m_maincpu(*this, "maincpu"),
|
||||
m_cedsound(*this, "cedtop"),
|
||||
m_cedplane0(*this, "cedplane0"),
|
||||
m_cedplane1(*this, "cedplane1"),
|
||||
m_cedsprite(*this, "cedsprite")
|
||||
{
|
||||
m_ic48_pio_pa_val = 0xff;
|
||||
m_ic48_pio_pb_val = 0xff;
|
||||
m_ic49_pio_pb_val = 0xff;
|
||||
m_prothack = nullptr;
|
||||
}
|
||||
|
||||
required_device<address_map_bank_device> m_bank0;
|
||||
required_device<address_map_bank_device> m_sub_ram_bankdev;
|
||||
required_device<address_map_bank_device> m_sub_pal_bankdev;
|
||||
|
||||
required_shared_ptr<UINT8> m_ram0;
|
||||
required_shared_ptr<UINT8> m_pal_r;
|
||||
required_shared_ptr<UINT8> m_pal_g;
|
||||
required_shared_ptr<UINT8> m_pal_b;
|
||||
|
||||
required_device<z80pio_device> m_ic48_pio;
|
||||
required_device<z80pio_device> m_ic49_pio;
|
||||
|
||||
DECLARE_READ8_MEMBER(ic48_pio_pa_r);
|
||||
DECLARE_WRITE8_MEMBER(ic48_pio_pa_w);
|
||||
|
||||
DECLARE_READ8_MEMBER(ic48_pio_pb_r);
|
||||
DECLARE_WRITE8_MEMBER(ic48_pio_pb_w);
|
||||
|
||||
DECLARE_READ8_MEMBER(ic49_pio_pb_r);
|
||||
DECLARE_WRITE8_MEMBER(ic49_pio_pb_w);
|
||||
|
||||
// 1x range ports
|
||||
DECLARE_WRITE8_MEMBER(port18_w);
|
||||
DECLARE_WRITE8_MEMBER(port19_w);
|
||||
DECLARE_WRITE8_MEMBER(port1b_w);
|
||||
|
||||
DECLARE_READ8_MEMBER(port18_r);
|
||||
DECLARE_READ8_MEMBER(port19_r);
|
||||
DECLARE_READ8_MEMBER(port1a_r);
|
||||
|
||||
// 7x range ports
|
||||
DECLARE_WRITE8_MEMBER(rambank_palbank_w);
|
||||
DECLARE_WRITE8_MEMBER(palupload_w);
|
||||
DECLARE_WRITE8_MEMBER(paladdr_w);
|
||||
DECLARE_READ8_MEMBER(watchdog_r);
|
||||
DECLARE_READ8_MEMBER(port7c_r);
|
||||
|
||||
// other ports
|
||||
DECLARE_WRITE8_MEMBER(soundlatch_w);
|
||||
UINT8 portff_data;
|
||||
|
||||
DECLARE_READ8_MEMBER(other_cpu_r);
|
||||
DECLARE_WRITE8_MEMBER(other_cpu_w);
|
||||
|
||||
UINT8 m_paladdr;
|
||||
int m_palbank;
|
||||
|
||||
UINT8 m_ic48_pio_pa_val;
|
||||
UINT8 m_ic48_pio_pb_val;
|
||||
UINT8 m_ic49_pio_pb_val;
|
||||
|
||||
void set_palette(int offset);
|
||||
DECLARE_WRITE8_MEMBER(palette_r_w);
|
||||
DECLARE_WRITE8_MEMBER(palette_g_w);
|
||||
DECLARE_WRITE8_MEMBER(palette_b_w);
|
||||
|
||||
void handle_sub_board_cpu_lines(cedar_magnet_board_device* dev, int old_data, int data);
|
||||
INTERRUPT_GEN_MEMBER(irq);
|
||||
void (*m_prothack)(cedar_magnet_state*);
|
||||
|
||||
virtual void machine_start() override;
|
||||
virtual void machine_reset() override;
|
||||
virtual void video_start() override;
|
||||
UINT32 screen_update_cedar_magnet(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
required_device<palette_device> m_palette;
|
||||
required_device<cpu_device> m_maincpu;
|
||||
|
||||
required_device<cedar_magnet_sound_device> m_cedsound;
|
||||
required_device<cedar_magnet_plane_device> m_cedplane0;
|
||||
required_device<cedar_magnet_plane_device> m_cedplane1;
|
||||
required_device<cedar_magnet_sprite_device> m_cedsprite;
|
||||
|
||||
DECLARE_DRIVER_INIT(mag_time);
|
||||
DECLARE_DRIVER_INIT(mag_xain);
|
||||
DECLARE_DRIVER_INIT(mag_exzi);
|
||||
|
||||
};
|
||||
|
||||
|
90
src/mame/drivers/cedar_magnet_board.cpp
Normal file
90
src/mame/drivers/cedar_magnet_board.cpp
Normal file
@ -0,0 +1,90 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:David Haywood
|
||||
|
||||
|
||||
#include "emu.h"
|
||||
#include "cedar_magnet_plane.h"
|
||||
|
||||
|
||||
//const device_type CEDAR_MAGNET_BASE = &device_creator<cedar_magnet_board_device>;
|
||||
|
||||
cedar_magnet_board_device::cedar_magnet_board_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source)
|
||||
: device_t(mconfig, type, name, tag, owner, clock, shortname, source)
|
||||
// m_ram(*this, "ram")
|
||||
{
|
||||
}
|
||||
|
||||
INTERRUPT_GEN_MEMBER(cedar_magnet_board_device::irq)
|
||||
{
|
||||
m_cpu->set_input_line(0, HOLD_LINE);
|
||||
}
|
||||
|
||||
void cedar_magnet_board_device::device_start()
|
||||
{
|
||||
}
|
||||
|
||||
void cedar_magnet_board_device::write_cpu_bus(int offset, UINT8 data)
|
||||
{
|
||||
device_t* cpu = m_cpu;
|
||||
address_space& ap = cpu->memory().space(AS_PROGRAM);
|
||||
ap.write_byte(offset, data);
|
||||
}
|
||||
|
||||
UINT8 cedar_magnet_board_device::read_cpu_bus(int offset)
|
||||
{
|
||||
device_t* cpu = m_cpu;
|
||||
address_space& ap = cpu->memory().space(AS_PROGRAM);
|
||||
return ap.read_byte(offset);
|
||||
}
|
||||
|
||||
bool cedar_magnet_board_device::is_running(void)
|
||||
{
|
||||
return m_is_running;
|
||||
}
|
||||
|
||||
TIMER_CALLBACK_MEMBER(cedar_magnet_board_device::reset_assert_callback)
|
||||
{
|
||||
m_cpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
|
||||
}
|
||||
|
||||
TIMER_CALLBACK_MEMBER(cedar_magnet_board_device::reset_clear_callback)
|
||||
{
|
||||
m_cpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
|
||||
}
|
||||
|
||||
TIMER_CALLBACK_MEMBER(cedar_magnet_board_device::halt_assert_callback)
|
||||
{
|
||||
m_cpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
|
||||
m_is_running = false;
|
||||
}
|
||||
|
||||
TIMER_CALLBACK_MEMBER(cedar_magnet_board_device::halt_clear_callback)
|
||||
{
|
||||
m_cpu->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
|
||||
m_is_running = true;
|
||||
}
|
||||
|
||||
void cedar_magnet_board_device::halt_assert(void)
|
||||
{
|
||||
machine().scheduler().timer_set(attotime::from_usec(2), timer_expired_delegate(FUNC(cedar_magnet_board_device::halt_assert_callback),this));
|
||||
}
|
||||
|
||||
void cedar_magnet_board_device::halt_clear(void)
|
||||
{
|
||||
machine().scheduler().timer_set(attotime::from_usec(2), timer_expired_delegate(FUNC(cedar_magnet_board_device::halt_clear_callback),this));
|
||||
}
|
||||
|
||||
void cedar_magnet_board_device::reset_assert(void)
|
||||
{
|
||||
machine().scheduler().timer_set(attotime::from_usec(1), timer_expired_delegate(FUNC(cedar_magnet_board_device::reset_assert_callback),this));
|
||||
}
|
||||
|
||||
void cedar_magnet_board_device::reset_clear(void)
|
||||
{
|
||||
machine().scheduler().timer_set(attotime::from_usec(1), timer_expired_delegate(FUNC(cedar_magnet_board_device::reset_clear_callback),this));
|
||||
}
|
||||
|
||||
void cedar_magnet_board_device::device_reset()
|
||||
{
|
||||
halt_assert();
|
||||
}
|
50
src/mame/drivers/cedar_magnet_board.h
Normal file
50
src/mame/drivers/cedar_magnet_board.h
Normal file
@ -0,0 +1,50 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:David Haywood
|
||||
|
||||
// just a base device to hold some common functions of the EFO / Cedar Magnet System PCBs
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef CEDAR_MAGNET_BOARD_DEF
|
||||
#define CEDAR_MAGNET_BOARD_DEF
|
||||
|
||||
#include "cpu/z80/z80.h"
|
||||
#include "cpu/z80/z80daisy.h"
|
||||
#include "machine/z80pio.h"
|
||||
|
||||
extern const device_type CEDAR_MAGNET_PLANE;
|
||||
|
||||
class cedar_magnet_board_device : public device_t
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
cedar_magnet_board_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
|
||||
|
||||
UINT8* m_ram;
|
||||
z80_device* m_cpu;
|
||||
|
||||
virtual UINT8 read_cpu_bus(int offset);
|
||||
virtual void write_cpu_bus(int offset, UINT8 data);
|
||||
|
||||
TIMER_CALLBACK_MEMBER(halt_assert_callback);
|
||||
TIMER_CALLBACK_MEMBER(halt_clear_callback);
|
||||
TIMER_CALLBACK_MEMBER(reset_assert_callback);
|
||||
TIMER_CALLBACK_MEMBER(reset_clear_callback);
|
||||
|
||||
void halt_assert(void);
|
||||
void halt_clear(void);
|
||||
void reset_assert(void);
|
||||
void reset_clear(void);
|
||||
bool is_running(void);
|
||||
bool m_is_running;
|
||||
|
||||
INTERRUPT_GEN_MEMBER(irq);
|
||||
|
||||
protected:
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
#endif
|
232
src/mame/drivers/cedar_magnet_flop.cpp
Normal file
232
src/mame/drivers/cedar_magnet_flop.cpp
Normal file
@ -0,0 +1,232 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:David Haywood
|
||||
|
||||
// todo, scrap this and use the core SAB 2797B emulation
|
||||
// (FM - MFM type) @ 1.25mhz (oscillates 1.250~1.251)
|
||||
|
||||
|
||||
#include "emu.h"
|
||||
#include "cedar_magnet_flop.h"
|
||||
|
||||
extern const device_type CEDAR_MAGNET_FLOP = &device_creator<cedar_magnet_flop_device>;
|
||||
|
||||
cedar_magnet_flop_device::cedar_magnet_flop_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: device_t(mconfig, CEDAR_MAGNET_FLOP, "Cedar Floppy Simulation", tag, owner, clock, "cedmag_flop", __FILE__)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
static MACHINE_CONFIG_FRAGMENT( cedar_magnet_flop )
|
||||
MCFG_NVRAM_ADD_NO_FILL("floppy_nvram")
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
machine_config_constructor cedar_magnet_flop_device::device_mconfig_additions() const
|
||||
{
|
||||
return MACHINE_CONFIG_NAME( cedar_magnet_flop );
|
||||
}
|
||||
|
||||
void cedar_magnet_flop_device::device_start()
|
||||
{
|
||||
subdevice<nvram_device>("floppy_nvram")->set_base(memregion("disk")->base(), 0xf0000);
|
||||
}
|
||||
|
||||
void cedar_magnet_flop_device::device_reset()
|
||||
{
|
||||
m_flopdat = 0;
|
||||
m_flopcmd = 0;
|
||||
m_flopsec = 0;
|
||||
m_flopstat = 0;
|
||||
m_floptrk = 0;
|
||||
}
|
||||
|
||||
READ8_MEMBER(cedar_magnet_flop_device::port60_r)
|
||||
{
|
||||
UINT8 ret = m_flopstat;
|
||||
return ret;
|
||||
}
|
||||
|
||||
READ8_MEMBER(cedar_magnet_flop_device::port61_r)
|
||||
{
|
||||
UINT8 ret = m_curtrack;
|
||||
return ret;
|
||||
}
|
||||
|
||||
READ8_MEMBER(cedar_magnet_flop_device::port63_r)
|
||||
{
|
||||
UINT8 ret = rand();
|
||||
|
||||
// printf("%s: port63_r (DATA) (%02x)\n", device().machine().describe_context(), ret);
|
||||
|
||||
if ((m_flopcmd&0xf0) == 0x90) // reading data
|
||||
{
|
||||
UINT8 *flop = memregion("disk")->base();
|
||||
int side = (m_flopcmd & 0x02)>>1;
|
||||
int read_offset_base = (m_flopsec * 0x400) + (m_curtrack * 0x3000) + (side * 0x1800);
|
||||
|
||||
int sector_size = 1024;
|
||||
|
||||
if (m_secoffs < sector_size)
|
||||
{
|
||||
m_flopstat |= 0x05;
|
||||
|
||||
int read_offset = read_offset_base + m_secoffs;
|
||||
ret = flop[read_offset];
|
||||
|
||||
if (m_secoffs == 0)
|
||||
{
|
||||
// this is weird data, protection??
|
||||
if(read_offset_base==0xea400)
|
||||
printf("reading sector %d offset %d (from disk image at %04x) (cur track %02x cur side %02x cur sector %02x)\n", m_flopsec, m_secoffs, read_offset, m_curtrack, side, m_flopsec);
|
||||
}
|
||||
|
||||
m_secoffs++;
|
||||
|
||||
if (m_secoffs == sector_size)
|
||||
{
|
||||
//printf("finished sector read\n");
|
||||
m_flopstat &= ~0x05;
|
||||
|
||||
m_secoffs = 0;
|
||||
m_flopsec++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("read past sector!! %d\n", m_secoffs);
|
||||
m_secoffs++;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
fatalerror("read data in non-read mode?\n");
|
||||
}
|
||||
//
|
||||
return ret;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(cedar_magnet_flop_device::port60_w)
|
||||
{
|
||||
//printf("%s: port60_w (COMMAND) %02x\n", device().machine().describe_context(), data);
|
||||
m_flopcmd = data;
|
||||
|
||||
|
||||
switch (m_flopcmd & 0xf0)
|
||||
{
|
||||
case 0x00:
|
||||
//printf("restore\n");
|
||||
m_flopstat = 0x06;
|
||||
m_curtrack = 0x00;
|
||||
break;
|
||||
|
||||
case 0x10:
|
||||
//printf("seek track\n");
|
||||
m_curtrack = m_flopdat;
|
||||
break;
|
||||
|
||||
|
||||
case 0x90:
|
||||
//printf("read sector\n");
|
||||
m_flopstat |= 0x07;
|
||||
m_secoffs = 0;
|
||||
break;
|
||||
|
||||
case 0xb0:
|
||||
//printf("write sector\n");
|
||||
m_flopstat |= 0x07;
|
||||
m_secoffs = 0;
|
||||
break;
|
||||
|
||||
case 0xd0:
|
||||
//printf("force interrupt?\n");
|
||||
// m_flopstat = 0x06;
|
||||
// m_flopstat &= ~0x07;
|
||||
// m_maincpu->set_input_line(0, HOLD_LINE);
|
||||
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
printf("unhandled disk command %02x\n", m_flopcmd);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(cedar_magnet_flop_device::port62_w)
|
||||
{
|
||||
//printf("%s: port62_w (SECTOR) %02x\n", device().machine().describe_context(), data);
|
||||
m_flopsec = data;
|
||||
|
||||
if (m_flopsec < 200)
|
||||
{
|
||||
printf("sector specified <200!\n");
|
||||
}
|
||||
|
||||
m_flopsec -= 200;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(cedar_magnet_flop_device::port63_w)
|
||||
{
|
||||
//printf("%s: port63_w (DATA) %02x\n", device().machine().describe_context(), data);
|
||||
m_flopdat = data;
|
||||
|
||||
if ((m_flopcmd & 0xf0) == 0xb0) // writing data
|
||||
{
|
||||
UINT8 *flop = memregion("disk")->base();
|
||||
int side = (m_flopcmd & 0x02)>>1;
|
||||
int read_offset_base = (m_flopsec * 0x400) + (m_curtrack * 0x3000) + (side * 0x1800);
|
||||
|
||||
int sector_size = 1024;
|
||||
|
||||
if (m_secoffs < sector_size)
|
||||
{
|
||||
m_flopstat |= 0x05;
|
||||
|
||||
int read_offset = read_offset_base + m_secoffs;
|
||||
flop[read_offset] = data;
|
||||
|
||||
if (m_secoffs == 0)
|
||||
{
|
||||
printf("writing sector %d offset %d (from disk image at %04x) (cur track %02x cur side %02x cur sector %02x)\n", m_flopsec, m_secoffs, read_offset, m_curtrack, side, m_flopsec);
|
||||
}
|
||||
|
||||
m_secoffs++;
|
||||
|
||||
if (m_secoffs == sector_size)
|
||||
{
|
||||
//printf("finished sector read\n");
|
||||
m_flopstat &= ~0x05;
|
||||
|
||||
m_secoffs = 0;
|
||||
m_flopsec++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(cedar_magnet_flop_device::write)
|
||||
{
|
||||
switch (offset & 3)
|
||||
{
|
||||
case 0x00:port60_w(space, offset, data);break;
|
||||
// case 0x01:port61_w(space, offset, data);break;
|
||||
case 0x02:port62_w(space, offset, data);break;
|
||||
case 0x03:port63_w(space, offset, data);break;
|
||||
default:break;
|
||||
}
|
||||
}
|
||||
|
||||
READ8_MEMBER(cedar_magnet_flop_device::read)
|
||||
{
|
||||
switch (offset & 3)
|
||||
{
|
||||
case 0x00: return port60_r(space, offset);
|
||||
case 0x01: return port61_r(space, offset);
|
||||
//case 0x02: return port62_r(space, offset);
|
||||
case 0x03: return port63_r(space, offset);
|
||||
default: return 0x00;
|
||||
}
|
||||
|
||||
return 0x00;
|
||||
}
|
49
src/mame/drivers/cedar_magnet_flop.h
Normal file
49
src/mame/drivers/cedar_magnet_flop.h
Normal file
@ -0,0 +1,49 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:David Haywood
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef CEDAR_MAGNET_FLOP_DEF
|
||||
#define CEDAR_MAGNET_FLOP_DEF
|
||||
|
||||
extern const device_type CEDAR_MAGNET_FLOP;
|
||||
|
||||
#define MCFG_CEDAR_MAGNET_FLOP_ADD(_tag) \
|
||||
MCFG_DEVICE_ADD(_tag, CEDAR_MAGNET_FLOP, 0)
|
||||
|
||||
#include "machine/nvram.h"
|
||||
|
||||
class cedar_magnet_flop_device : public device_t
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
cedar_magnet_flop_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
|
||||
UINT8 m_flopdat;
|
||||
UINT8 m_flopcmd;
|
||||
UINT8 m_flopsec;
|
||||
UINT8 m_flopstat;
|
||||
UINT8 m_floptrk;
|
||||
|
||||
UINT8 m_curtrack;
|
||||
int m_secoffs;
|
||||
|
||||
DECLARE_READ8_MEMBER(port60_r);
|
||||
DECLARE_READ8_MEMBER(port61_r);
|
||||
DECLARE_READ8_MEMBER(port63_r);
|
||||
|
||||
DECLARE_WRITE8_MEMBER(port60_w);
|
||||
DECLARE_WRITE8_MEMBER(port62_w);
|
||||
DECLARE_WRITE8_MEMBER(port63_w);
|
||||
|
||||
DECLARE_READ8_MEMBER(read);
|
||||
DECLARE_WRITE8_MEMBER(write);
|
||||
|
||||
protected:
|
||||
virtual machine_config_constructor device_mconfig_additions() const override;
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
private:
|
||||
};
|
||||
|
||||
#endif
|
162
src/mame/drivers/cedar_magnet_plane.cpp
Normal file
162
src/mame/drivers/cedar_magnet_plane.cpp
Normal file
@ -0,0 +1,162 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:David Haywood
|
||||
|
||||
|
||||
#include "emu.h"
|
||||
#include "cedar_magnet_plane.h"
|
||||
|
||||
|
||||
extern const device_type CEDAR_MAGNET_PLANE = &device_creator<cedar_magnet_plane_device>;
|
||||
|
||||
|
||||
cedar_magnet_plane_device::cedar_magnet_plane_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: cedar_magnet_board_device(mconfig, CEDAR_MAGNET_PLANE, "Cedar Plane", tag, owner, clock, "cedmag_plane", __FILE__)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
static ADDRESS_MAP_START( cedar_magnet_plane_map, AS_PROGRAM, 8, cedar_magnet_plane_device )
|
||||
AM_RANGE(0x0000, 0xffff) AM_RAM AM_SHARE("ram")
|
||||
ADDRESS_MAP_END
|
||||
|
||||
static ADDRESS_MAP_START( cedar_magnet_plane_io, AS_IO, 8, cedar_magnet_plane_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(0xcc, 0xcc) AM_WRITE(plane_portcc_w)
|
||||
AM_RANGE(0xcd, 0xcd) AM_WRITE(plane_portcd_w)
|
||||
AM_RANGE(0xce, 0xce) AM_WRITE(plane_portce_w)
|
||||
AM_RANGE(0xcf, 0xcf) AM_WRITE(plane_portcf_w)
|
||||
|
||||
ADDRESS_MAP_END
|
||||
|
||||
|
||||
|
||||
|
||||
WRITE8_MEMBER(cedar_magnet_plane_device::plane_portcc_w)
|
||||
{
|
||||
m_framebuffer[((m_curline&0xff)*0x100)+(m_lineoffset&0xff)] = data;
|
||||
|
||||
// counters simply wrap when they reach the maximum, don't move onto next row/colummn (confirmed by xain)
|
||||
if (m_pio0_pa_data&0x01)
|
||||
{
|
||||
m_lineoffset++;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_curline++;
|
||||
}
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(cedar_magnet_plane_device::plane_portcd_w)
|
||||
{
|
||||
m_lineoffset = data;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(cedar_magnet_plane_device::plane_portce_w)
|
||||
{
|
||||
m_curline = data;
|
||||
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(cedar_magnet_plane_device::plane_portcf_w)
|
||||
{
|
||||
// does it have a meaning or is it just some kind of watchdog?
|
||||
m_cf_data = data;
|
||||
}
|
||||
|
||||
static MACHINE_CONFIG_FRAGMENT( cedar_magnet_plane )
|
||||
MCFG_CPU_ADD("planecpu", Z80,4000000)
|
||||
MCFG_CPU_PROGRAM_MAP(cedar_magnet_plane_map)
|
||||
MCFG_CPU_IO_MAP(cedar_magnet_plane_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_plane_device, pio0_pa_r))
|
||||
MCFG_Z80PIO_OUT_PA_CB(WRITE8(cedar_magnet_plane_device, pio0_pa_w))
|
||||
// MCFG_Z80PIO_IN_PB_CB(READ8(cedar_magnet_plane_device, pio0_pb_r))
|
||||
MCFG_Z80PIO_OUT_PB_CB(WRITE8(cedar_magnet_plane_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_plane_device, pio1_pa_r))
|
||||
MCFG_Z80PIO_OUT_PA_CB(WRITE8(cedar_magnet_plane_device, pio1_pa_w))
|
||||
// MCFG_Z80PIO_IN_PB_CB(READ8(cedar_magnet_plane_device, pio1_pb_r))
|
||||
MCFG_Z80PIO_OUT_PB_CB(WRITE8(cedar_magnet_plane_device, pio1_pb_w))
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
|
||||
READ8_MEMBER(cedar_magnet_plane_device::pio0_pa_r)
|
||||
{
|
||||
// this is read
|
||||
// logerror("%s: pio0_pa_r\n", machine().describe_context());
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
|
||||
WRITE8_MEMBER(cedar_magnet_plane_device::pio0_pa_w)
|
||||
{
|
||||
m_pio0_pa_data = data;
|
||||
|
||||
// 7ex- 321d
|
||||
//
|
||||
// e = video enable
|
||||
// d = draw direction
|
||||
// x = done? gets set at end of each frame at least, but unlike video enable, also when video shouldn't be enabled
|
||||
// 7 = always set?
|
||||
// 321 = always set after startup?
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(cedar_magnet_plane_device::pio0_pb_w)
|
||||
{
|
||||
m_pio0_pb_data = data;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(cedar_magnet_plane_device::pio1_pa_w)
|
||||
{
|
||||
m_scrollx = data;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(cedar_magnet_plane_device::pio1_pb_w)
|
||||
{
|
||||
m_scrolly = data;
|
||||
}
|
||||
|
||||
machine_config_constructor cedar_magnet_plane_device::device_mconfig_additions() const
|
||||
{
|
||||
return MACHINE_CONFIG_NAME( cedar_magnet_plane );
|
||||
}
|
||||
|
||||
void cedar_magnet_plane_device::device_start()
|
||||
{
|
||||
m_cpu = subdevice<z80_device>("planecpu");
|
||||
m_ram = (UINT8*)memshare("ram")->ptr();
|
||||
save_item(NAME(m_framebuffer));
|
||||
}
|
||||
|
||||
UINT32 cedar_magnet_plane_device::draw(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int palbase)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
if (!(m_pio0_pa_data & 0x40))
|
||||
return 0;
|
||||
|
||||
for (int y = 0;y < 256;y++)
|
||||
{
|
||||
UINT16 *dst = &bitmap.pix16((y-m_scrolly)&0xff);
|
||||
|
||||
for (int x = 0; x < 256;x++)
|
||||
{
|
||||
UINT8 pix = m_framebuffer[count];
|
||||
count++;
|
||||
|
||||
if (pix) dst[(x-m_scrollx)&0xff] = pix + palbase*0x100;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
59
src/mame/drivers/cedar_magnet_plane.h
Normal file
59
src/mame/drivers/cedar_magnet_plane.h
Normal file
@ -0,0 +1,59 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:David Haywood
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef CEDAR_MAGNET_PLANE_DEF
|
||||
#define CEDAR_MAGNET_PLANE_DEF
|
||||
|
||||
#include "cedar_magnet_board.h"
|
||||
|
||||
extern const device_type CEDAR_MAGNET_PLANE;
|
||||
|
||||
#define MCFG_CEDAR_MAGNET_PLANE_ADD(_tag) \
|
||||
MCFG_DEVICE_ADD(_tag, CEDAR_MAGNET_PLANE, 0)
|
||||
|
||||
|
||||
class cedar_magnet_plane_device : public cedar_magnet_board_device
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
cedar_magnet_plane_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
|
||||
DECLARE_READ8_MEMBER(pio0_pa_r);
|
||||
DECLARE_WRITE8_MEMBER(pio0_pa_w);
|
||||
// DECLARE_READ8_MEMBER(pio0_pb_r);
|
||||
DECLARE_WRITE8_MEMBER(pio0_pb_w);
|
||||
|
||||
// DECLARE_READ8_MEMBER(pio1_pa_r);
|
||||
DECLARE_WRITE8_MEMBER(pio1_pa_w);
|
||||
// DECLARE_READ8_MEMBER(pio1_pb_r);
|
||||
DECLARE_WRITE8_MEMBER(pio1_pb_w);
|
||||
|
||||
DECLARE_WRITE8_MEMBER(plane_portcc_w);
|
||||
DECLARE_WRITE8_MEMBER(plane_portcd_w);
|
||||
DECLARE_WRITE8_MEMBER(plane_portce_w);
|
||||
DECLARE_WRITE8_MEMBER(plane_portcf_w);
|
||||
|
||||
UINT8 m_framebuffer[0x10000];
|
||||
int m_curline;
|
||||
int m_lineoffset;
|
||||
|
||||
UINT8 m_pio0_pa_data;
|
||||
UINT8 m_pio0_pb_data;
|
||||
UINT8 m_scrollx;
|
||||
UINT8 m_scrolly;
|
||||
int m_direction;
|
||||
|
||||
UINT8 m_cd_data;
|
||||
UINT8 m_cf_data;
|
||||
UINT32 draw(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int palbase);
|
||||
protected:
|
||||
virtual machine_config_constructor device_mconfig_additions() const override;
|
||||
virtual void device_start() override;
|
||||
// virtual void device_reset() override;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
#endif
|
168
src/mame/drivers/cedar_magnet_sound.cpp
Normal file
168
src/mame/drivers/cedar_magnet_sound.cpp
Normal file
@ -0,0 +1,168 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:David Haywood
|
||||
|
||||
/*
|
||||
THIS IMPLEMENTATION IS ENTIRELY INCORRECT AND SHOULD NOT BE TRUSTED!
|
||||
*/
|
||||
|
||||
#include "emu.h"
|
||||
#include "cedar_magnet_sound.h"
|
||||
|
||||
|
||||
extern const device_type CEDAR_MAGNET_SOUND = &device_creator<cedar_magnet_sound_device>;
|
||||
|
||||
|
||||
cedar_magnet_sound_device::cedar_magnet_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: cedar_magnet_board_device(mconfig, CEDAR_MAGNET_SOUND, "Cedar Sound", tag, owner, clock, "cedmag_sound", __FILE__),
|
||||
m_ctc0(*this, "ctc0"),
|
||||
m_ctc1(*this, "ctc1")
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
READ8_MEMBER(cedar_magnet_sound_device::top_port14_r)
|
||||
{
|
||||
// UINT8 ret = m_command;
|
||||
// m_command = 0;
|
||||
return rand();
|
||||
}
|
||||
|
||||
void cedar_magnet_sound_device::write_command(UINT8 data)
|
||||
{
|
||||
m_command = data;
|
||||
m_cpu->set_input_line(0, HOLD_LINE);
|
||||
}
|
||||
|
||||
|
||||
static ADDRESS_MAP_START( cedar_magnet_sound_map, AS_PROGRAM, 8, cedar_magnet_sound_device )
|
||||
AM_RANGE(0x0000, 0xffff) AM_RAM AM_SHARE("ram")
|
||||
ADDRESS_MAP_END
|
||||
|
||||
static ADDRESS_MAP_START( cedar_magnet_sound_io, AS_IO, 8, cedar_magnet_sound_device )
|
||||
ADDRESS_MAP_GLOBAL_MASK(0xff)
|
||||
|
||||
AM_RANGE(0x00, 0x03) AM_DEVREADWRITE("ctc0", z80ctc_device, read, write)
|
||||
AM_RANGE(0x04, 0x07) AM_DEVREADWRITE("ctc1", z80ctc_device, read, write)
|
||||
|
||||
AM_RANGE(0x0c, 0x0c) AM_DEVWRITE("aysnd0", ay8910_device, address_w)
|
||||
AM_RANGE(0x0d, 0x0d) AM_DEVWRITE("aysnd0", ay8910_device, data_w)
|
||||
|
||||
AM_RANGE(0x10, 0x10) AM_DEVWRITE("aysnd1", ay8910_device, address_w)
|
||||
AM_RANGE(0x11, 0x11) AM_DEVWRITE("aysnd1", ay8910_device, data_w)
|
||||
|
||||
AM_RANGE(0x14, 0x14) AM_READ(top_port14_r)
|
||||
|
||||
ADDRESS_MAP_END
|
||||
|
||||
|
||||
WRITE_LINE_MEMBER(cedar_magnet_sound_device::ctc0_z0_w)
|
||||
{
|
||||
// printf("USED ctc0_z0_w %d\n", state);
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(cedar_magnet_sound_device::ctc0_z1_w)
|
||||
{
|
||||
// printf("USED ctc0_z1_w %d\n", state);
|
||||
}
|
||||
|
||||
|
||||
// I don't think any of the below are used
|
||||
|
||||
WRITE_LINE_MEMBER(cedar_magnet_sound_device::ctc1_z0_w)
|
||||
{
|
||||
printf("ctc1_z0_w %d\n", state);
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(cedar_magnet_sound_device::ctc1_z1_w)
|
||||
{
|
||||
printf("ctc1_z1_w %d\n", state);
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(cedar_magnet_sound_device::ctc1_z2_w)
|
||||
{
|
||||
printf("ctc1_z2_w %d\n", state);
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(cedar_magnet_sound_device::ctc0_z2_w)
|
||||
{
|
||||
printf("ctc0_z2_w %d\n", state);
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(cedar_magnet_sound_device::ctc0_int_w)
|
||||
{
|
||||
//printf("ctc0_int_w %d\n", state);
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(cedar_magnet_sound_device::ctc1_int_w)
|
||||
{
|
||||
/*
|
||||
switch (rand()&0x1)
|
||||
{
|
||||
case 0x00:
|
||||
m_ctc0->trg0(rand()&1);
|
||||
break;
|
||||
case 0x01:
|
||||
m_ctc0->trg1(rand()&1);
|
||||
break;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
#if 0
|
||||
static const z80_daisy_config daisy_chain[] =
|
||||
{
|
||||
{ "ctc1" },
|
||||
{ "ctc0" },
|
||||
{ nullptr }
|
||||
};
|
||||
#endif
|
||||
|
||||
static MACHINE_CONFIG_FRAGMENT( cedar_magnet_sound )
|
||||
MCFG_CPU_ADD("topcpu", Z80,4000000)
|
||||
MCFG_CPU_PROGRAM_MAP(cedar_magnet_sound_map)
|
||||
MCFG_CPU_IO_MAP(cedar_magnet_sound_io)
|
||||
// MCFG_Z80_DAISY_CHAIN(daisy_chain)
|
||||
|
||||
MCFG_DEVICE_ADD("ctc0", Z80CTC, 4000000/8 )
|
||||
MCFG_Z80CTC_INTR_CB(WRITELINE(cedar_magnet_sound_device, ctc0_int_w))
|
||||
MCFG_Z80CTC_ZC0_CB(WRITELINE(cedar_magnet_sound_device, ctc0_z0_w))
|
||||
MCFG_Z80CTC_ZC1_CB(WRITELINE(cedar_magnet_sound_device, ctc0_z1_w))
|
||||
MCFG_Z80CTC_ZC2_CB(WRITELINE(cedar_magnet_sound_device, ctc0_z2_w))
|
||||
|
||||
MCFG_DEVICE_ADD("ctc1", Z80CTC, 4000000/8 )
|
||||
MCFG_Z80CTC_INTR_CB(INPUTLINE("topcpu", INPUT_LINE_IRQ0))
|
||||
// MCFG_Z80CTC_INTR_CB(DEVWRITELINE("ctc0", z80ctc_device, trg0))
|
||||
MCFG_Z80CTC_INTR_CB(WRITELINE(cedar_magnet_sound_device, ctc1_int_w))
|
||||
MCFG_Z80CTC_ZC0_CB(WRITELINE(cedar_magnet_sound_device, ctc1_z0_w))
|
||||
MCFG_Z80CTC_ZC1_CB(WRITELINE(cedar_magnet_sound_device, ctc1_z1_w))
|
||||
MCFG_Z80CTC_ZC2_CB(WRITELINE(cedar_magnet_sound_device, ctc1_z2_w))
|
||||
|
||||
MCFG_SPEAKER_STANDARD_MONO("mono")
|
||||
|
||||
MCFG_SOUND_ADD("aysnd0", AY8910, 4000000/2)
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.5)
|
||||
|
||||
MCFG_SOUND_ADD("aysnd1", AY8910, 4000000/2)
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.5)
|
||||
|
||||
MCFG_SOUND_ADD("adpcm", MSM5205, 4000000/16)
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
|
||||
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
machine_config_constructor cedar_magnet_sound_device::device_mconfig_additions() const
|
||||
{
|
||||
return MACHINE_CONFIG_NAME( cedar_magnet_sound );
|
||||
}
|
||||
|
||||
void cedar_magnet_sound_device::device_start()
|
||||
{
|
||||
m_cpu = subdevice<z80_device>("topcpu");
|
||||
m_ram = (UINT8*)memshare("ram")->ptr();
|
||||
}
|
||||
|
||||
void cedar_magnet_sound_device::device_reset()
|
||||
{
|
||||
m_command = 0;
|
||||
cedar_magnet_board_device::device_reset();
|
||||
}
|
53
src/mame/drivers/cedar_magnet_sound.h
Normal file
53
src/mame/drivers/cedar_magnet_sound.h
Normal file
@ -0,0 +1,53 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:David Haywood
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef CEDAR_MAGNET_SOUND_DEF
|
||||
#define CEDAR_MAGNET_SOUND_DEF
|
||||
|
||||
#include "cpu/z80/z80.h"
|
||||
#include "cpu/z80/z80daisy.h"
|
||||
#include "machine/z80ctc.h"
|
||||
#include "sound/ay8910.h"
|
||||
#include "sound/msm5205.h"
|
||||
#include "cedar_magnet_board.h"
|
||||
|
||||
extern const device_type CEDAR_MAGNET_SOUND;
|
||||
|
||||
#define MCFG_CEDAR_MAGNET_SOUND_ADD(_tag) \
|
||||
MCFG_DEVICE_ADD(_tag, CEDAR_MAGNET_SOUND, 0)
|
||||
|
||||
|
||||
class cedar_magnet_sound_device : public cedar_magnet_board_device
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
cedar_magnet_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
|
||||
required_device<z80ctc_device> m_ctc0;
|
||||
required_device<z80ctc_device> m_ctc1;
|
||||
|
||||
DECLARE_READ8_MEMBER(top_port14_r);
|
||||
|
||||
void write_command(UINT8 data);
|
||||
UINT8 m_command;
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER(ctc1_z0_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(ctc1_z1_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(ctc1_z2_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(ctc0_z0_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(ctc0_z1_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(ctc0_z2_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(ctc0_int_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(ctc1_int_w);
|
||||
|
||||
protected:
|
||||
virtual machine_config_constructor device_mconfig_additions() const override;
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
#endif
|
336
src/mame/drivers/cedar_magnet_sprite.cpp
Normal file
336
src/mame/drivers/cedar_magnet_sprite.cpp
Normal file
@ -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;
|
||||
}
|
83
src/mame/drivers/cedar_magnet_sprite.h
Normal file
83
src/mame/drivers/cedar_magnet_sprite.h
Normal file
@ -0,0 +1,83 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:David Haywood
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef CEDAR_MAGNET_SPRITE_DEF
|
||||
#define CEDAR_MAGNET_SPRITE_DEF
|
||||
|
||||
#include "cpu/z80/z80.h"
|
||||
#include "cpu/z80/z80daisy.h"
|
||||
#include "machine/z80pio.h"
|
||||
#include "machine/bankdev.h"
|
||||
#include "cedar_magnet_board.h"
|
||||
|
||||
extern const device_type CEDAR_MAGNET_SPRITE;
|
||||
|
||||
#define MCFG_CEDAR_MAGNET_SPRITE_ADD(_tag) \
|
||||
MCFG_DEVICE_ADD(_tag, CEDAR_MAGNET_SPRITE, 0)
|
||||
|
||||
|
||||
class cedar_magnet_sprite_device : public cedar_magnet_board_device
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
cedar_magnet_sprite_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
|
||||
UINT8 m_framebuffer[0x10000];
|
||||
UINT8 pio2_pb_data;
|
||||
|
||||
required_device<address_map_bank_device> m_sprite_ram_bankdev;
|
||||
|
||||
DECLARE_READ8_MEMBER(pio0_pa_r);
|
||||
DECLARE_WRITE8_MEMBER(pio0_pa_w);
|
||||
// DECLARE_READ8_MEMBER(pio0_pb_r);
|
||||
DECLARE_WRITE8_MEMBER(pio0_pb_w);
|
||||
|
||||
// DECLARE_READ8_MEMBER(pio1_pa_r);
|
||||
DECLARE_WRITE8_MEMBER(pio1_pa_w);
|
||||
// DECLARE_READ8_MEMBER(pio1_pb_r);
|
||||
DECLARE_WRITE8_MEMBER(pio1_pb_w);
|
||||
|
||||
// DECLARE_READ8_MEMBER(pio2_pa_r);
|
||||
DECLARE_WRITE8_MEMBER(pio2_pa_w);
|
||||
// DECLARE_READ8_MEMBER(pio2_pb_r);
|
||||
DECLARE_WRITE8_MEMBER(pio2_pb_w);
|
||||
|
||||
DECLARE_WRITE8_MEMBER(sprite_port80_w);
|
||||
DECLARE_WRITE8_MEMBER(sprite_port84_w);
|
||||
DECLARE_WRITE8_MEMBER(sprite_port88_w);
|
||||
DECLARE_WRITE8_MEMBER(sprite_port8c_w);
|
||||
DECLARE_WRITE8_MEMBER(sprite_port9c_w);
|
||||
|
||||
DECLARE_READ8_MEMBER(exzisus_hack_r);
|
||||
|
||||
UINT8 m_upperaddr;
|
||||
UINT8 m_loweraddr;
|
||||
|
||||
void do_blit();
|
||||
|
||||
UINT8 m_spritesize;
|
||||
UINT8 pio0_pb_data;
|
||||
UINT8 m_spritecodelow;
|
||||
UINT8 m_spritecodehigh;
|
||||
|
||||
int m_high_write;
|
||||
UINT8 m_uppersprite;
|
||||
|
||||
INTERRUPT_GEN_MEMBER(irq);
|
||||
|
||||
required_device<z80pio_device> m_pio0;
|
||||
required_device<z80pio_device> m_pio1;
|
||||
required_device<z80pio_device> m_pio2;
|
||||
|
||||
UINT32 draw(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int palbase);
|
||||
protected:
|
||||
virtual machine_config_constructor device_mconfig_additions() const override;
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
#endif
|
@ -9272,6 +9272,12 @@ quizard4 // (c) TAB Austria 1998
|
||||
quizard4_40 // (c) TAB Austria 1997
|
||||
quizard4_41 // (c) TAB Austria 1998
|
||||
|
||||
@source:cedar_magnet.cpp
|
||||
cedmag
|
||||
mag_time
|
||||
mag_exzi
|
||||
mag_xain
|
||||
|
||||
@source:centiped.cpp
|
||||
bullsdrt // (c) 1985 Shinkai
|
||||
caterplr // (bootleg)
|
||||
|
Loading…
Reference in New Issue
Block a user