mirror of
https://github.com/holub/mame
synced 2025-06-04 03:46:29 +03:00

(for now, simulating the state). Improved the memory map fixing the RAM amount and offset, and added the correct offset for the HCGA status. Also hooked 2 debug handlers on ports e000-e001 that spit some random graphics after 30 seconds of the game execution (clue to figure out). [Roberto Fresca]
468 lines
13 KiB
C
468 lines
13 KiB
C
/*************************************************************************
|
|
|
|
Cuatro en Linea.
|
|
System I.
|
|
1991, Compumatic
|
|
|
|
|
|
1x Z84C00HB6 CPU @ 8 MHz for program.
|
|
1x Z84C00AB6 CPU @ 4 MHz for sound.
|
|
1x AY-3-8910 A
|
|
1x UMC UM487F (HCGA Controller)
|
|
|
|
2x NEC D41464C (64K x 4-bit Dynamic NMOS RAM).
|
|
1x UMC UM6264A (8K x 8-bit CMOS SRAM).
|
|
|
|
2x 27512 EPROMS.
|
|
1x X24C16P Serial EEPROM.
|
|
|
|
1x GAL16V8AS
|
|
|
|
1x ES2 CM3080 (unknown DIP-18 IC)
|
|
1x ES2 9046 (unknown PLCC-84 IC)
|
|
1x 8952 CM 32 (unknown DIP-40 IC)
|
|
|
|
1x 16.0000 MHz crystal. ; Divided by 2 (through CM3080) for main CPU Z84C00HB6.
|
|
1x 8.000 MHz crystal. ; Divided by 2 for audio CPU Z84C00AB6.
|
|
1x 14.31818 MHz crystal ; For HMCGA video controller.
|
|
|
|
**************************************************************************
|
|
|
|
UM487F Notes...
|
|
|
|
The fact that there is a 14.318 MHz crystal tied to pin 65, just point
|
|
that the video controller is working in CGA mode. MGA mode needs a
|
|
16.257 MHz crystal instead, and tied to pin 64 (currently tied to GND).
|
|
|
|
Also a signal of 8Mhz (shared with the program CPU is entering from the
|
|
pin 1 (CLK) needed for clock the UM6845 mode.
|
|
|
|
UM487F Access:
|
|
|
|
Offsets are for sure the CGA mode. MGA mode has different ones.
|
|
|
|
3D4h: W CRTC index register.
|
|
3D5h: RW CRTC data register.
|
|
3D8h: W Mode control register.
|
|
3D9h: W Color select register.
|
|
3DAh: R Status register.
|
|
3BFh: W Config register.
|
|
|
|
Mode CTRL (3D8h) 6Ah:
|
|
----- bits -----
|
|
7 6 5 4 3 2 1 0 For CGA Mode.
|
|
- x x - x - x -
|
|
| | | | | | | |
|
|
| | | | | | | '-- 40*25 text.
|
|
| | | | | | '---- Graphics.
|
|
| | | | | '------ Color Mode.
|
|
| | | | '-------- Enable Video.
|
|
| | | '----------- 320x200 Graphics.
|
|
| | '------------- Enable Blink.
|
|
| '--------------- Enable Change Mode.
|
|
'----------------- (not for CGA)
|
|
|
|
Color Sel (3D9h): 00
|
|
|
|
Index register (3D4h): 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
|
|
Data register (3D5h): 38 28 2D 0A 7F 06 64 70 02 01 06 07 10 00 00 00
|
|
|
|
Config Register (3BFh): 0x40
|
|
(bit 6 active means CGA Mode)
|
|
|
|
|
|
So... Screen size is set to 320x200.
|
|
but...
|
|
|
|
The embedded CRT controller is set to:
|
|
Screen Total: 0x38+1 * 0x7F+1 = (57 * 128) chars.
|
|
Screen Visible: 0x28 * 0x64 = (40 * 100) chars.
|
|
|
|
**************************************************************************
|
|
|
|
TODO:
|
|
|
|
- Proper UM487F device emulation.
|
|
- Interlaced video mode.
|
|
- Sound.
|
|
- More work...
|
|
|
|
*************************************************************************/
|
|
|
|
#define MAIN_CLOCK XTAL_16MHz
|
|
#define SEC_CLOCK XTAL_8MHz
|
|
#define HCGA_CLOCK XTAL_14_31818MHz
|
|
|
|
#define PRG_CPU_CLOCK MAIN_CLOCK /2 /* 8 MHz. */
|
|
#define SND_CPU_CLOCK SEC_CLOCK /2 /* 4 MHz. */
|
|
#define SND_AY_CLOCK SEC_CLOCK /4 /* 2 MHz. */
|
|
#define CRTC_CLOCK SEC_CLOCK /2 /* 8 MHz. */
|
|
|
|
|
|
#include "emu.h"
|
|
#include "cpu/z80/z80.h"
|
|
#include "video/mc6845.h"
|
|
#include "sound/ay8910.h"
|
|
|
|
class _4enlinea_state : public driver_device
|
|
{
|
|
public:
|
|
_4enlinea_state(const machine_config &mconfig, device_type type, const char *tag)
|
|
: driver_device(mconfig, type, tag),
|
|
m_ay(*this, "aysnd"),
|
|
m_videoram(*this, "videoram"),
|
|
m_maincpu(*this, "maincpu"),
|
|
m_gfxdecode(*this, "gfxdecode"),
|
|
m_palette(*this, "palette") { }
|
|
|
|
|
|
required_device<ay8910_device> m_ay;
|
|
required_shared_ptr<UINT8> m_videoram;
|
|
|
|
DECLARE_WRITE8_MEMBER(crtc_config_w);
|
|
DECLARE_WRITE8_MEMBER(crtc_mode_ctrl_w);
|
|
DECLARE_WRITE8_MEMBER(crtc_colormode_w);
|
|
DECLARE_READ8_MEMBER(crtc_status_r);
|
|
DECLARE_READ8_MEMBER(unk_e000_r);
|
|
DECLARE_READ8_MEMBER(unk_e001_r);
|
|
|
|
virtual void machine_start();
|
|
virtual void machine_reset();
|
|
virtual void video_start();
|
|
DECLARE_PALETTE_INIT(_4enlinea);
|
|
UINT32 screen_update_4enlinea(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
|
required_device<cpu_device> m_maincpu;
|
|
required_device<gfxdecode_device> m_gfxdecode;
|
|
required_device<palette_device> m_palette;
|
|
|
|
DECLARE_WRITE8_MEMBER(vram_w);
|
|
};
|
|
|
|
|
|
/***********************************
|
|
* Video Hardware *
|
|
***********************************/
|
|
|
|
void _4enlinea_state::video_start()
|
|
{
|
|
m_gfxdecode->gfx(0)->set_source(m_videoram);
|
|
}
|
|
|
|
UINT32 _4enlinea_state::screen_update_4enlinea(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
|
{
|
|
/* note: chars are 16*12 pixels */
|
|
|
|
int offset = 0;
|
|
|
|
for (int y = 0; y < 200; y++)
|
|
{
|
|
UINT16* dstptr_bitmap = &bitmap.pix16(y);
|
|
|
|
for (int x = 0; x < 320; x += 4)
|
|
{
|
|
UINT8 pix = m_videoram[offset++];
|
|
|
|
dstptr_bitmap[x + 3] = (pix >> 0) & 0x3;
|
|
dstptr_bitmap[x + 2] = (pix >> 2) & 0x3;
|
|
dstptr_bitmap[x + 1] = (pix >> 4) & 0x3;
|
|
dstptr_bitmap[x + 0] = (pix >> 6) & 0x3;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
WRITE8_MEMBER(_4enlinea_state::vram_w)
|
|
{
|
|
m_videoram[offset] = data;
|
|
m_gfxdecode->gfx(0)->mark_dirty(offset/16);
|
|
}
|
|
|
|
|
|
WRITE8_MEMBER(_4enlinea_state::crtc_config_w)
|
|
{
|
|
if(data & 0x40)
|
|
{
|
|
logerror("CRTC config mode (3BFh): CGA\n");
|
|
}
|
|
else
|
|
{
|
|
logerror("CRTC config mode (3BFh): MGA\n");
|
|
}
|
|
}
|
|
|
|
WRITE8_MEMBER(_4enlinea_state::crtc_mode_ctrl_w)
|
|
{
|
|
logerror("CRTC mode control (3D8h): %02x\n", data);
|
|
}
|
|
|
|
WRITE8_MEMBER(_4enlinea_state::crtc_colormode_w)
|
|
{
|
|
logerror("CRTC color mode (3D9h): %02x\n", data);
|
|
}
|
|
|
|
READ8_MEMBER(_4enlinea_state::crtc_status_r)
|
|
{
|
|
/*----- bits -----
|
|
7 6 5 4 3 2 1 0 For CGA Mode.
|
|
x x x x - - - - (bits 4-5-6-7 are unused)
|
|
| | | |
|
|
| | | '-- 0: Display active period.
|
|
| | | 1: Non-display period.
|
|
| | |
|
|
| | '---- 0: Light pen reset.
|
|
| | 1: Light pen set.
|
|
| |
|
|
| '------ 0: Light pen switch off.
|
|
| 1: Light pen switch on.
|
|
|
|
|
'-------- 0: Non-vertical sync period.
|
|
1: Vertical sync period.
|
|
|
|
*/
|
|
logerror("CRTC status read\n");
|
|
return (machine().rand() & 0x80); /* bit 7 ??? (is suppossed to be unused inCGA mode) */
|
|
}
|
|
|
|
READ8_MEMBER(_4enlinea_state::unk_e000_r)
|
|
{
|
|
logerror("read e000\n");
|
|
// return (machine().rand() & 0xff);
|
|
return 0xff;
|
|
}
|
|
|
|
READ8_MEMBER(_4enlinea_state::unk_e001_r)
|
|
{
|
|
logerror("read e001\n");
|
|
// return (machine().rand() & 0xff); // after 30 seconds, random strings and gfx appear on the screen.
|
|
return (machine().rand() & 0x0f); // after 30 seconds, random gfx appear on the screen.
|
|
}
|
|
|
|
|
|
/***********************************
|
|
* Memory Map Information *
|
|
***********************************/
|
|
|
|
static ADDRESS_MAP_START( main_map, AS_PROGRAM, 8, _4enlinea_state )
|
|
AM_RANGE(0x0000, 0x7fff) AM_ROM
|
|
AM_RANGE(0x8000, 0xbfff) AM_RAM_WRITE(vram_w) AM_SHARE("videoram")
|
|
AM_RANGE(0xc000, 0xdfff) AM_RAM
|
|
|
|
AM_RANGE(0xe000, 0xe000) AM_READ(unk_e000_r)
|
|
AM_RANGE(0xe001, 0xe001) AM_READ(unk_e001_r)
|
|
|
|
ADDRESS_MAP_END
|
|
|
|
|
|
static ADDRESS_MAP_START( main_portmap, AS_IO, 8, _4enlinea_state )
|
|
ADDRESS_MAP_GLOBAL_MASK(0xff)
|
|
|
|
AM_RANGE(0xd4, 0xd4) AM_DEVWRITE("crtc", mc6845_device, address_w)
|
|
AM_RANGE(0xd5, 0xd5) AM_DEVWRITE("crtc", mc6845_device, register_w)
|
|
AM_RANGE(0xd8, 0xd8) AM_WRITE(crtc_mode_ctrl_w)
|
|
AM_RANGE(0xd9, 0xd9) AM_WRITE(crtc_colormode_w)
|
|
AM_RANGE(0xda, 0xda) AM_READ(crtc_status_r)
|
|
AM_RANGE(0xbf, 0xbf) AM_WRITE(crtc_config_w)
|
|
|
|
ADDRESS_MAP_END
|
|
|
|
|
|
|
|
static ADDRESS_MAP_START( audio_map, AS_PROGRAM, 8, _4enlinea_state )
|
|
AM_RANGE(0x0000, 0x7fff) AM_ROM
|
|
AM_RANGE(0xe000, 0xffff) AM_RAM
|
|
ADDRESS_MAP_END
|
|
|
|
|
|
static ADDRESS_MAP_START( audio_portmap, AS_IO, 8, _4enlinea_state )
|
|
ADDRESS_MAP_GLOBAL_MASK(0xff)
|
|
ADDRESS_MAP_END
|
|
|
|
|
|
/***********************************
|
|
* Input Ports *
|
|
***********************************/
|
|
|
|
static INPUT_PORTS_START( 4enlinea )
|
|
PORT_START("DSW1")
|
|
PORT_DIPNAME( 0x01, 0x00, "0-0")
|
|
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
|
PORT_DIPSETTING( 0x01, DEF_STR( On ) )
|
|
PORT_DIPNAME( 0x02, 0x00, "0-1")
|
|
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
|
PORT_DIPSETTING( 0x02, DEF_STR( On ) )
|
|
PORT_DIPNAME( 0x04, 0x00, "0-2")
|
|
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
|
PORT_DIPSETTING( 0x04, DEF_STR( On ) )
|
|
PORT_DIPNAME( 0x08, 0x00, "0-3")
|
|
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
|
PORT_DIPSETTING( 0x08, DEF_STR( On ) )
|
|
PORT_DIPNAME( 0x10, 0x00, "0-4")
|
|
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
|
PORT_DIPSETTING( 0x10, DEF_STR( On ) )
|
|
PORT_DIPNAME( 0x20, 0x00, "0-5")
|
|
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
|
PORT_DIPSETTING( 0x20, DEF_STR( On ) )
|
|
PORT_DIPNAME( 0x40, 0x00, "0-6")
|
|
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
|
PORT_DIPSETTING( 0x40, DEF_STR( On ) )
|
|
PORT_DIPNAME( 0x80, 0x00, "0-7")
|
|
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
|
PORT_DIPSETTING( 0x80, DEF_STR( On ) )
|
|
INPUT_PORTS_END
|
|
|
|
|
|
/***********************************
|
|
* Graphics Layouts *
|
|
***********************************/
|
|
|
|
static const gfx_layout charlayout =
|
|
{
|
|
8,8,
|
|
0x4000/16,
|
|
2,
|
|
{ 0, 1 },
|
|
{ 0, 2, 4, 6, 8, 10, 12, 14 },
|
|
{ 0*16, 1*16, 2*16, 3*16, 4*16, 5*16, 6*16, 7*16 },
|
|
8*16
|
|
};
|
|
|
|
/****************************************
|
|
* Graphics Decode Information *
|
|
****************************************/
|
|
|
|
static GFXDECODE_START( 4enlinea )
|
|
GFXDECODE_ENTRY( NULL, 0, charlayout, 0, 1 )
|
|
GFXDECODE_END
|
|
|
|
|
|
/****************************************
|
|
* Machine Start/Reset *
|
|
****************************************/
|
|
|
|
void _4enlinea_state::machine_start()
|
|
{
|
|
|
|
}
|
|
|
|
void _4enlinea_state::machine_reset()
|
|
{
|
|
|
|
}
|
|
|
|
|
|
/**********************************
|
|
* CRTC Interface *
|
|
**********************************/
|
|
|
|
static MC6845_ON_UPDATE_ADDR_CHANGED(crtc_addr)
|
|
{
|
|
|
|
}
|
|
|
|
static MC6845_INTERFACE( mc6845_intf )
|
|
{
|
|
false, /* show border area */
|
|
0,0,0,0, /* visarea adjustment */
|
|
8, /* number of pixels per video memory address */
|
|
NULL, /* before pixel update callback */
|
|
NULL, /* row update callback */
|
|
NULL, /* after pixel update callback */
|
|
DEVCB_NULL, /* callback for display state changes */
|
|
DEVCB_NULL, /* callback for cursor state changes */
|
|
DEVCB_NULL, /* HSYNC callback */
|
|
DEVCB_NULL, /* VSYNC callback */
|
|
crtc_addr /* update address callback */
|
|
};
|
|
|
|
|
|
/***********************************
|
|
* Sound Interface *
|
|
***********************************/
|
|
|
|
static const ay8910_interface ay8910_intf =
|
|
{
|
|
AY8910_LEGACY_OUTPUT,
|
|
AY8910_DEFAULT_LOADS,
|
|
DEVCB_NULL,
|
|
DEVCB_NULL,
|
|
DEVCB_NULL,
|
|
DEVCB_NULL
|
|
};
|
|
|
|
|
|
/***********************************
|
|
* Machine Drivers *
|
|
***********************************/
|
|
|
|
static MACHINE_CONFIG_START( 4enlinea, _4enlinea_state )
|
|
|
|
/* basic machine hardware */
|
|
MCFG_CPU_ADD("maincpu", Z80, PRG_CPU_CLOCK)
|
|
MCFG_CPU_PROGRAM_MAP(main_map)
|
|
MCFG_CPU_IO_MAP(main_portmap)
|
|
MCFG_CPU_VBLANK_INT_DRIVER("screen", _4enlinea_state, nmi_line_pulse)
|
|
MCFG_CPU_PERIODIC_INT_DRIVER(_4enlinea_state, irq0_line_hold, 4*60)
|
|
|
|
MCFG_CPU_ADD("audiocpu", Z80, SND_CPU_CLOCK)
|
|
MCFG_CPU_PROGRAM_MAP(audio_map)
|
|
MCFG_CPU_IO_MAP(audio_portmap)
|
|
|
|
/* video hardware */
|
|
MCFG_SCREEN_ADD("screen", RASTER)
|
|
MCFG_SCREEN_REFRESH_RATE(60)
|
|
MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0))
|
|
MCFG_SCREEN_SIZE(320, 200)
|
|
MCFG_SCREEN_VISIBLE_AREA(0, 320-1, 0, 200-1)
|
|
MCFG_SCREEN_UPDATE_DRIVER(_4enlinea_state, screen_update_4enlinea)
|
|
MCFG_SCREEN_PALETTE("palette")
|
|
|
|
MCFG_GFXDECODE_ADD("gfxdecode", "palette", 4enlinea)
|
|
MCFG_PALETTE_ADD("palette", 256)
|
|
|
|
/* 6845 clock is a guess, since it's a UM6845R embedded in the UM487F.
|
|
CRTC_CLOCK is 8MHz, entering for pin 1 of UM487F. This clock is used
|
|
only for UM6845R embedded mode. The frequency divisor is unknown.
|
|
|
|
CRTC_CLOCK / 4.0 = 66.961296 Hz.
|
|
CRTC_CLOCK / 4.5 = 59.521093 Hz.
|
|
CRTC_CLOCK / 5.0 = 53.569037 Hz.
|
|
*/
|
|
// MCFG_MC6845_ADD("crtc", MC6845, "screen", CRTC_CLOCK / 2, mc6845_intf) // seems that MC6845 doesn't support the game mode
|
|
MCFG_MC6845_ADD("crtc", R6545_1, "screen", CRTC_CLOCK / 4.5, mc6845_intf)
|
|
|
|
/* sound hardware */
|
|
MCFG_SPEAKER_STANDARD_MONO("mono")
|
|
MCFG_SOUND_ADD("aysnd", AY8910, SND_AY_CLOCK)
|
|
MCFG_SOUND_CONFIG(ay8910_intf)
|
|
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
|
|
MACHINE_CONFIG_END
|
|
|
|
|
|
/***********************************
|
|
* Rom Load *
|
|
***********************************/
|
|
|
|
ROM_START( 4enlinea )
|
|
ROM_REGION( 0x10000, "maincpu", 0 )
|
|
ROM_LOAD( "cuatro_en_linea_27c256__cicplay-2.ic6", 0x0000, 0x8000, CRC(f8f14bf8) SHA1(e48fbedbd1b9be6fb56a0f65db80eddbedb487c7) )
|
|
|
|
ROM_REGION( 0x10000, "audiocpu", 0 )
|
|
ROM_LOAD( "cuatro_en_linea_27c256__cicplay-1.ic19", 0x0000, 0x8000, CRC(307a57a3) SHA1(241329d919ec43d0eeb1dad0a4db6cf6de06e7e1) )
|
|
|
|
ROM_REGION( 0x0800, "eeprom", 0 ) /* default serial EEPROM */
|
|
ROM_LOAD( "cuatro_en_linea_x24c16p__nosticker.ic17", 0x000, 0x800, CRC(21f81f5a) SHA1(00b10eee5af1ca79ced2878f4be4cac2bb8d26a0) )
|
|
|
|
ROM_REGION( 0x200, "plds", 0 )
|
|
ROM_LOAD( "cuatro_en_linea_gal16v8as__nosticker.ic04", 0x000, 0x117, CRC(094edf29) SHA1(428a2f6568ac1032833ee0c65fa8304967a58607) )
|
|
ROM_END
|
|
|
|
|
|
/***********************************
|
|
* Game Drivers *
|
|
***********************************/
|
|
|
|
/* YEAR NAME PARENT MACHINE INPUT STATE INIT ROT COMPANY FULLNAME FLAGS */
|
|
GAME( 1991, 4enlinea, 0, 4enlinea, 4enlinea, driver_device, 0, ROT0, "Compumatic", "Cuatro en Linea", GAME_NOT_WORKING )
|
|
|