Geneve: Added boot flash ROM support (PFM)

This commit is contained in:
Michael Zapf 2015-08-22 01:26:39 +02:00
parent a9b74b1d6b
commit bcdecc179c
5 changed files with 334 additions and 166 deletions

View File

@ -168,17 +168,42 @@
Waitstate behavior (Nov 2013)
Almost perfect. Only video read access from code in DRAM is too fast by one WS
==========================
PFM expansion
==========================
The "Programmable Flash Memory expansion" is a replacement for the boot
EPROM.
PFM: Original version, 128 KiB
PFM+: Expansion of the original version, piggybacked, adds another 128KiB
PFM512: Using an AT29C040 (not A), 512 KiB
The PFM is visible as four banks in memory pages 0xF0 - 0xFF.
Bank switching is done by four 9901 pins:
0028: LSB of bank number
003A: MSB of bank number
Bank 0 is the boot code, while banks 1-3 can be used as flash drives
Michael Zapf, October 2011
February 2012: rewritten as class, restructured
Aug 2015: PFM added
***************************************************************************/
#include "genboard.h"
#define VERBOSE 1
#define LOG logerror
#define TRACE_READ 0
#define TRACE_WRITE 0
#define TRACE_DETAIL 0
#define TRACE_KEYBOARD 0
#define TRACE_CLOCK 0
#define TRACE_LINES 0
#define TRACE_SETTING 1
#define TRACE_PFM 0
geneve_mapper_device::geneve_mapper_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, GENEVE_MAPPER, "Geneve Gate Array", tag, owner, clock, "geneve_mapper", __FILE__),
@ -187,23 +212,30 @@ geneve_mapper_device::geneve_mapper_device(const machine_config &mconfig, const
m_eprom = NULL;
}
INPUT_CHANGED_MEMBER( geneve_mapper_device::gm_changed )
INPUT_CHANGED_MEMBER( geneve_mapper_device::settings_changed )
{
int number = (int)((UINT64)param&0x03);
int value = newval;
if (number==1)
switch (number)
{
case 1:
// Turbo switch. May be changed at any time.
if (VERBOSE>0) LOG("genboard: Setting turbo flag to %d\n", value);
if (TRACE_SETTING) logerror("%s: Setting turbo flag to %d\n", tag(), value);
m_turbo = (value!=0);
}
else
{
break;
case 2:
// TIMode switch. Causes reset when changed.
if (VERBOSE>0) LOG("genboard: Setting timode flag to %d\n", value);
if (TRACE_SETTING) logerror("%s: Setting timode flag to %d\n", tag(), value);
m_timode = (value!=0);
machine().schedule_hard_reset();
break;
case 3:
// Used when switching the boot ROMs during runtime, especially the PFM
set_boot_rom(value);
break;
default:
logerror("%s: Unknown setting %d ignored\n", tag(), number);
}
}
@ -294,7 +326,7 @@ void geneve_mapper_device::set_wait(int min)
m_waitcount = min + 1;
if (m_waitcount > 1)
{
if (VERBOSE>7) LOG("genboard: Pulling down READY line for %d cycles\n", min);
if (TRACE_LINES) logerror("%s: Pulling down READY line for %d cycles\n", tag(), min);
m_ready(CLEAR_LINE);
m_ready_asserted = false;
}
@ -306,6 +338,71 @@ void geneve_mapper_device::set_ext_wait(int min)
m_ext_waitcount = min;
}
void geneve_mapper_device::set_boot_rom(int selection)
{
switch (selection)
{
case GENEVE_098:
logerror("%s: Using 0.98 boot eprom\n", tag());
m_eprom = machine().root_device().memregion("maincpu")->base() + 0x4000;
m_pfm_mode = 0;
break;
case GENEVE_100:
logerror("%s: Using 1.00 boot eprom\n", tag());
m_eprom = machine().root_device().memregion("maincpu")->base();
m_pfm_mode = 0;
break;
case GENEVE_PFM512:
logerror("%s: Using PFM512 (AT29C040)\n", tag());
m_pfm_mode = 1;
break;
case GENEVE_PFM512A:
logerror("%s: Using PFM512A (AT29C040A)\n", tag());
m_pfm_mode = 2;
break;
default:
logerror("%s: Unknown boot ROM selection\n", tag());
}
}
void geneve_mapper_device::set_geneve_mode(bool geneve)
{
if (TRACE_SETTING) logerror("%s: Setting Geneve mode = %d\n", tag(), geneve);
m_geneve_mode = geneve;
}
void geneve_mapper_device::set_direct_mode(bool direct)
{
if (TRACE_SETTING) logerror("%s: Setting direct mode = %d\n", tag(), direct);
m_direct_mode = direct;
}
void geneve_mapper_device::set_cartridge_size(int size)
{
if (TRACE_SETTING) logerror("%s: Setting cartridge size to %d\n", tag(), size);
m_cartridge_size = size;
}
void geneve_mapper_device::set_cartridge_writable(int base, bool write)
{
if (TRACE_SETTING) logerror("%s: Cartridge %04x space writable = %d\n", tag(), base, write);
if (base==0x6000) m_cartridge6_writable = write;
else m_cartridge7_writable = write;
}
void geneve_mapper_device::set_video_waitstates(bool wait)
{
if (TRACE_SETTING) logerror("%s: Setting video waitstates = %d\n", tag(), wait);
m_video_waitstates = wait;
}
void geneve_mapper_device::set_extra_waitstates(bool wait)
{
if (TRACE_SETTING) logerror("%s: Setting extra waitstates = %d\n", tag(), wait);
m_extra_waitstates = wait;
}
/************************************************************************
Called by the address map
************************************************************************/
@ -347,7 +444,6 @@ enum
READ8_MEMBER( geneve_mapper_device::readm )
{
UINT8 value = 0;
assert (m_eprom!=NULL);
decdata *dec;
decdata debug;
@ -371,7 +467,7 @@ READ8_MEMBER( geneve_mapper_device::readm )
{
case MLGVIDEO:
m_video->readz(space, dec->offset, &value, 0xff);
if (VERBOSE>7) LOG("genboard: Read video %04x -> %02x\n", dec->offset, value);
if (TRACE_READ) logerror("%s: Read video %04x -> %02x\n", tag(), dec->offset, value);
// Video wait states are created *after* the access
// Accordingly, they have no effect when execution is in onchip RAM
if (m_video_waitstates) set_ext_wait(15);
@ -380,13 +476,13 @@ READ8_MEMBER( geneve_mapper_device::readm )
case MLGMAPPER:
// mapper
value = m_map[dec->offset];
if (VERBOSE>7) LOG("genboard: read mapper %04x -> %02x\n", dec->offset, value);
if (TRACE_READ) logerror("%s: read mapper %04x -> %02x\n", tag(), dec->offset, value);
break;
case MLGKEY:
// key
if (!space.debugger_access()) value = m_keyboard->get_recent_key();
if (VERBOSE>7) LOG("genboard: Read keyboard -> %02x\n", value);
if (TRACE_READ) logerror("%s: Read keyboard -> %02x\n", tag(), value);
break;
case MLGCLOCK:
@ -394,19 +490,19 @@ READ8_MEMBER( geneve_mapper_device::readm )
// tests on the real machine showed that
// upper nibble is 0xf (probably because of the location at 0xf130?)
value = m_clock->read(space, dec->offset) | 0xf0;
if (VERBOSE>7) LOG("genboard: Read clock %04x -> %02x\n", dec->offset, value);
if (TRACE_READ) logerror("%s: Read clock %04x -> %02x\n", tag(), dec->offset, value);
break;
case MLTMAPPER:
// mapper
value = m_map[dec->offset];
if (VERBOSE>7) LOG("genboard: Read mapper %04x -> %02x\n", dec->offset, value);
if (TRACE_READ) logerror("%s: Read mapper %04x -> %02x\n", tag(), dec->offset, value);
break;
case MLTKEY:
// key
if (!space.debugger_access()) value = m_keyboard->get_recent_key();
if (VERBOSE>7) LOG("genboard: Read keyboard -> %02x\n", value);
if (TRACE_READ) logerror("%s: Read keyboard -> %02x\n", tag(), value);
break;
case MLTCLOCK:
@ -420,7 +516,7 @@ READ8_MEMBER( geneve_mapper_device::readm )
// value floating around.
value = m_clock->read(space, dec->offset);
value |= (dec->offset==0x000f)? 0x20 : 0x10;
if (VERBOSE>7) LOG("genboard: Read clock %04x -> %02x\n", dec->offset, value);
if (TRACE_READ) logerror("%s: Read clock %04x -> %02x\n", tag(), dec->offset, value);
break;
case MLTVIDEO:
@ -428,7 +524,7 @@ READ8_MEMBER( geneve_mapper_device::readm )
// ++++ ++-- ---- ---+
// 1000 1000 0000 00x0
m_video->readz(space, dec->offset, &value, 0xff);
if (VERBOSE>7) LOG("genboard: Read video %04x -> %02x\n", dec->offset, value);
if (TRACE_READ) logerror("%s: Read video %04x -> %02x\n", tag(), dec->offset, value);
// See above
if (m_video_waitstates) set_ext_wait(15);
break;
@ -439,7 +535,7 @@ READ8_MEMBER( geneve_mapper_device::readm )
// 1001 0000 0000 0000
// We need to add the address prefix bits
m_peribox->readz(space, dec->offset, &value, 0xff);
if (VERBOSE>7) LOG("genboard: Read speech -> %02x\n", value);
if (TRACE_READ) logerror("%s: Read speech -> %02x\n", tag(), value);
break;
case MLTGROM:
@ -447,7 +543,7 @@ READ8_MEMBER( geneve_mapper_device::readm )
// ++++ ++-- ---- ---+
// 1001 1000 0000 00x0
if (!space.debugger_access()) value = read_grom(space, dec->offset, 0xff);
if (VERBOSE>7) LOG("genboard: Read GROM %04x -> %02x\n", dec->offset, value);
if (TRACE_READ) logerror("%s: Read GROM %04x -> %02x\n", tag(), dec->offset, value);
break;
case MLGSOUND:
@ -460,20 +556,25 @@ READ8_MEMBER( geneve_mapper_device::readm )
// DRAM.
value = m_dram[dec->physaddr];
// LOG("dram read physaddr = %06x logaddr = %04x value = %02x\n", dec->physaddr, dec->offset, value);
if (VERBOSE>7) LOG("genboard: Read DRAM %04x (%06x) -> %02x\n", dec->offset, dec->physaddr, value);
if (TRACE_READ) logerror("%s: Read DRAM %04x (%06x) -> %02x\n", tag(), dec->offset, dec->physaddr, value);
break;
case MPGEXP:
// On-board memory expansion for standard Geneve (never used)
if (VERBOSE>7) LOG("genboard: Read unmapped area %06x\n", dec->physaddr);
if (TRACE_READ) logerror("%s: Read unmapped area %06x\n", tag(), dec->physaddr);
value = 0;
break;
case MPGEPROM:
// 1 111. ..xx xxxx xxxx xxxx on-board eprom (16K)
// mirrored for f0, f2, f4, ...; f1, f3, f5, ...
value = m_eprom[dec->physaddr];
if (VERBOSE>7) LOG("genboard: Read EPROM %04x (%06x) -> %02x\n", dec->offset, dec->physaddr, value);
if (m_pfm_mode == 0)
{
value = m_eprom[dec->physaddr & 0x003fff];
if (TRACE_READ) logerror("%s: Read EPROM %04x (%06x) -> %02x\n", tag(), dec->offset, dec->physaddr, value);
}
else value = read_from_pfm(space, dec->physaddr, 0xff);
break;
case MPGSRAM:
@ -484,7 +585,7 @@ READ8_MEMBER( geneve_mapper_device::readm )
else value = 0;
// Return in any case
// LOG("sram read physaddr = %06x logaddr = %04x value = %02x\n", dec->physaddr, dec->offset, value);
if (VERBOSE>7) LOG("genboard: Read SRAM %04x (%06x) -> %02x\n", dec->offset, dec->physaddr, value);
if (TRACE_READ) logerror("%s: Read SRAM %04x (%06x) -> %02x\n", tag(), dec->offset, dec->physaddr, value);
break;
case MPGBOX:
@ -493,7 +594,7 @@ READ8_MEMBER( geneve_mapper_device::readm )
// 0x000000-0x1fffff for the GenMod.(AME,AMD,AMC,AMB,AMA,A0 ...,A15)
m_peribox->readz(space, dec->physaddr, &value, 0xff);
if (VERBOSE>7) LOG("genboard: Read P-Box %04x (%06x) -> %02x\n", dec->offset, dec->physaddr, value);
if (TRACE_READ) logerror("%s: Read P-Box %04x (%06x) -> %02x\n", tag(), dec->offset, dec->physaddr, value);
break;
case MPGMDRAM:
@ -504,7 +605,12 @@ READ8_MEMBER( geneve_mapper_device::readm )
case MPGMEPROM:
// 1 111. ..xx xxxx xxxx xxxx on-board eprom (16K)
// mirrored for f0, f2, f4, ...; f1, f3, f5, ...
value = m_eprom[dec->physaddr];
if (m_pfm_mode == 0)
{
value = m_eprom[dec->physaddr & 0x003fff];
if (TRACE_READ) logerror("%s: Read EPROM %04x (%06x) -> %02x\n", tag(), dec->offset, dec->physaddr, value);
}
else value = read_from_pfm(space, dec->physaddr, 0xff);
break;
case MPGMBOX:
@ -541,7 +647,7 @@ WRITE8_MEMBER( geneve_mapper_device::writem )
// ++++ ++++ ++++ ---+
// 1111 0001 0000 .cc0
m_video->write(space, dec->offset, data, 0xff);
if (VERBOSE>7) LOG("genboard: Write video %04x <- %02x\n", offset, data);
if (TRACE_WRITE) logerror("%s: Write video %04x <- %02x\n", tag(), offset, data);
// See above
if (m_video_waitstates) set_ext_wait(15);
break;
@ -549,33 +655,33 @@ WRITE8_MEMBER( geneve_mapper_device::writem )
case MLGMAPPER:
// mapper
m_map[dec->offset] = data;
if (VERBOSE>7) LOG("genboard: Write mapper %04x <- %02x\n", offset, data);
if (TRACE_WRITE) logerror("%s: Write mapper %04x <- %02x\n", tag(), offset, data);
break;
case MLGCLOCK:
// clock
// ++++ ++++ ++++ ----
m_clock->write(space, dec->offset, data);
if (VERBOSE>7) LOG("genboard: Write clock %04x <- %02x\n", offset, data);
if (TRACE_WRITE) logerror("%s: Write clock %04x <- %02x\n", tag(), offset, data);
break;
case MLGSOUND:
// sound
// ++++ ++++ ++++ ---+
m_sound->write(space, 0, data, 0xff);
if (VERBOSE>7) LOG("genboard: Write sound <- %02x\n", data);
if (TRACE_WRITE) logerror("%s: Write sound <- %02x\n", tag(), data);
break;
case MLTMAPPER:
// mapper
m_map[dec->offset] = data;
if (VERBOSE>7) LOG("genboard: Write mapper %04x <- %02x\n", offset, data);
if (TRACE_WRITE) logerror("%s: Write mapper %04x <- %02x\n", tag(), offset, data);
break;
case MLTCLOCK:
// clock
m_clock->write(space, dec->offset, data);
if (VERBOSE>7) LOG("genboard: Write clock %04x <- %02x\n", offset, data);
if (TRACE_WRITE) logerror("%s: Write clock %04x <- %02x\n", tag(), offset, data);
break;
case MLTVIDEO:
@ -584,7 +690,7 @@ WRITE8_MEMBER( geneve_mapper_device::writem )
// 1000 1100 0000 00c0
// Initialize waitstate timer
m_video->write(space, dec->offset, data, 0xff);
if (VERBOSE>7) LOG("genboard: Write video %04x <- %02x\n", offset, data);
if (TRACE_WRITE) logerror("%s: Write video %04x <- %02x\n", tag(), offset, data);
// See above
if (m_video_waitstates) set_ext_wait(15);
break;
@ -595,7 +701,7 @@ WRITE8_MEMBER( geneve_mapper_device::writem )
// 1001 0100 0000 0000
// We need to add the address prefix bits
m_peribox->write(space, dec->offset, data, 0xff);
if (VERBOSE>7) LOG("genboard: Write speech <- %02x\n", data);
if (TRACE_WRITE) logerror("%s: Write speech <- %02x\n", tag(), data);
break;
case MLTGROM:
@ -603,7 +709,7 @@ WRITE8_MEMBER( geneve_mapper_device::writem )
// ++++ ++-- ---- ---+
// 1001 1100 0000 00c0
write_grom(space, dec->offset, data, 0xff);
if (VERBOSE>7) LOG("genboard: Write GROM %04x <- %02x\n", offset, data);
if (TRACE_WRITE) logerror("%s: Write GROM %04x <- %02x\n", tag(), offset, data);
break;
case MLTSOUND:
@ -611,7 +717,7 @@ WRITE8_MEMBER( geneve_mapper_device::writem )
// ++++ ++-- ---- ---+
// 1000 0100 0000 0000
m_sound->write(space, 0, data, 0xff);
if (VERBOSE>7) LOG("genboard: Write sound <- %02x\n", data);
if (TRACE_WRITE) logerror("%s: Write sound <- %02x\n", tag(), data);
break;
case MLTKEY:
@ -621,19 +727,21 @@ WRITE8_MEMBER( geneve_mapper_device::writem )
case MPGDRAM:
// DRAM write. One wait state. (only for normal Geneve)
m_dram[dec->physaddr] = data;
if (VERBOSE>7) LOG("genboard: Write DRAM %04x (%06x) <- %02x\n", offset, dec->physaddr, data);
if (TRACE_WRITE) logerror("%s: Write DRAM %04x (%06x) <- %02x\n", tag(), offset, dec->physaddr, data);
break;
case MPGEXP:
// On-board memory expansion for standard Geneve (never used)
if (VERBOSE>7) LOG("genboard: Write unmapped area %06x\n", dec->physaddr);
if (TRACE_WRITE) logerror("%s: Write unmapped area %06x\n", tag(), dec->physaddr);
break;
case MPGEPROM:
// 1 111. ..xx xxxx xxxx xxxx on-board eprom (16K)
// mirrored for f0, f2, f4, ...; f1, f3, f5, ...
// Ignore EPROM write
if (VERBOSE>7) LOG("genboard: Write EPROM %04x (%06x) <- %02x, ignored\n", offset, dec->physaddr, data);
// Ignore EPROM write (unless PFM)
if (m_pfm_mode != 0) write_to_pfm(space, dec->physaddr, data, 0xff);
else
logerror("%s: Write EPROM %04x (%06x) <- %02x, ignored\n", tag(), offset, dec->physaddr, data);
break;
case MPGSRAM:
@ -641,12 +749,12 @@ WRITE8_MEMBER( geneve_mapper_device::writem )
{
m_sram[dec->physaddr & ~m_sram_mask] = data;
}
if (VERBOSE>7) LOG("genboard: Write SRAM %04x (%06x) <- %02x\n", offset, dec->physaddr, data);
if (TRACE_WRITE) logerror("%s: Write SRAM %04x (%06x) <- %02x\n", tag(), offset, dec->physaddr, data);
break;
case MPGBOX:
dec->physaddr = (dec->physaddr & 0x0007ffff); // 19 bit address
if (VERBOSE>7) LOG("genboard: Write P-Box %04x (%06x) <- %02x\n", offset, dec->physaddr, data);
if (TRACE_WRITE) logerror("%s: Write P-Box %04x (%06x) <- %02x\n", tag(), offset, dec->physaddr, data);
m_peribox->write(space, dec->physaddr, data, 0xff);
break;
@ -659,6 +767,9 @@ WRITE8_MEMBER( geneve_mapper_device::writem )
// 1 111. ..xx xxxx xxxx xxxx on-board eprom (16K)
// mirrored for f0, f2, f4, ...; f1, f3, f5, ...
// Ignore EPROM write
if (m_pfm_mode != 0) write_to_pfm(space, dec->physaddr, data, 0xff);
else
logerror("%s: Write EPROM %04x (%06x) <- %02x, ignored\n", tag(), offset, dec->physaddr, data);
break;
case MPGMBOX:
@ -784,7 +895,7 @@ void geneve_mapper_device::decode(address_space& space, offs_t offset, bool read
// Determine physical address
if (m_direct_mode)
{
dec->physaddr = 0x1e0000; // points to boot eprom
dec->physaddr = 0x1f0000; // points to boot eprom (page F8)
}
else
{
@ -822,9 +933,8 @@ void geneve_mapper_device::decode(address_space& space, offs_t offset, bool read
if ((dec->physaddr & 0x1e0000)==0x1e0000)
{
// 1 111. ..xx xxxx xxxx xxxx on-board eprom (16K)
// mirrored for f0, f2, f4, ...; f1, f3, f5, ...
// mirrored for f0, f2, f4, ...; f1, f3, f5, ... unless using PFM
dec->function = MPGEPROM;
dec->physaddr = dec->physaddr & 0x003fff;
set_wait(0);
return;
}
@ -862,9 +972,8 @@ void geneve_mapper_device::decode(address_space& space, offs_t offset, bool read
if ((dec->physaddr & 0x1e0000)==0x1e0000)
{
// 1 111. ..xx xxxx xxxx xxxx on-board eprom (16K)
// mirrored for f0, f2, f4, ...; f1, f3, f5, ...
// mirrored for f0, f2, f4, ...; f1, f3, f5, ... unless using PFM
dec->function = MPGMEPROM;
dec->physaddr = dec->physaddr & 0x003fff;
set_wait(0);
return;
}
@ -983,7 +1092,7 @@ void geneve_mapper_device::decode(address_space& space, offs_t offset, bool read
if (m_cartridge_size==0x4000)
{
m_cartridge_secondpage = ((dec->offset & 0x0002)!=0);
if (VERBOSE>7) LOG("genboard: Set cartridge page %02x\n", m_cartridge_secondpage);
if (TRACE_WRITE) logerror("%s: Set cartridge page %02x\n", tag(), m_cartridge_secondpage);
set_wait(1);
return;
}
@ -993,7 +1102,7 @@ void geneve_mapper_device::decode(address_space& space, offs_t offset, bool read
if ((((dec->offset & 0x1000)==0x0000) && !m_cartridge6_writable)
|| (((dec->offset & 0x1000)==0x1000) && !m_cartridge7_writable))
{
if (VERBOSE>0) LOG("genboard: Writing to protected cartridge space %04x ignored\n", dec->offset);
logerror("%s: Writing to protected cartridge space %04x ignored\n", tag(), dec->offset);
return;
}
else
@ -1049,7 +1158,7 @@ void geneve_mapper_device::decode(address_space& space, offs_t offset, bool read
{
// GenMod mode
if ((dec->physaddr & 0x1e0000)==0x1e0000)
{ // EPROM, ignore
{ // EPROM, ignore (unless PFM)
dec->function = MPGMEPROM;
set_wait(0);
return;
@ -1072,6 +1181,54 @@ void geneve_mapper_device::decode(address_space& space, offs_t offset, bool read
}
}
/*
Read from PFM.
*/
READ8_MEMBER( geneve_mapper_device::read_from_pfm )
{
UINT8 value = 0;
if (!m_pfm_output_enable) return 0;
int address = (offset & 0x01ffff) | (m_pfm_bank<<17);
switch (m_pfm_mode)
{
case 1:
value = m_pfm512->read(space, address, mem_mask);
break;
case 2:
value = m_pfm512a->read(space, address, mem_mask);
break;
default:
logerror("%s: Illegal mode for reading PFM: %d\n", tag(), m_pfm_mode);
return 0;
}
if (TRACE_PFM) logerror("%s: Reading from PFM at address %05x -> %02x\n", tag(), address, value);
return value;
}
WRITE8_MEMBER( geneve_mapper_device::write_to_pfm )
{
// Nota bene: The PFM must be write protected on startup, or the RESET
// of the 9995 will attempt to write the return vector into the flash EEPROM
int address = (offset & 0x01ffff) | (m_pfm_bank<<17);
if (TRACE_PFM) logerror("%s: Writing to PFM at address %05x <- %02x\n", tag(), address, data);
switch (m_pfm_mode)
{
case 1:
m_pfm512->write(space, address, data, mem_mask);
break;
case 2:
m_pfm512a->write(space, address, data, mem_mask);
break;
default:
logerror("%s: Illegal mode for writing to PFM: %d\n", tag(), m_pfm_mode);
}
}
/*
Accept the address passed over the address bus and decode it appropriately.
This decoding will later be used in the READ/WRITE member functions. Also,
@ -1079,7 +1236,7 @@ void geneve_mapper_device::decode(address_space& space, offs_t offset, bool read
*/
SETOFFSET_MEMBER( geneve_mapper_device::setoffset )
{
if (VERBOSE>7) LOG("genboard: setoffset = %04x\n", offset);
if (TRACE_DETAIL) logerror("%s: setoffset = %04x\n", tag(), offset);
m_debug_no_ws = false;
decode(space, offset, m_read_mode, &m_decoded);
}
@ -1108,14 +1265,14 @@ WRITE_LINE_MEMBER( geneve_mapper_device::clock_in )
m_waitcount--;
if (m_waitcount == 0)
{
if (VERBOSE>5) LOG("genboard: clock, READY asserted\n");
if (TRACE_CLOCK) logerror("%s: clock, READY asserted\n", tag());
m_ready(ASSERT_LINE);
m_ready_asserted = true;
}
else
{
if (VERBOSE>5) LOG("genboard: clock\n");
}
else
{
if (TRACE_CLOCK) logerror("%s: clock\n", tag());
}
}
else
{
@ -1124,13 +1281,13 @@ WRITE_LINE_MEMBER( geneve_mapper_device::clock_in )
m_ext_waitcount--;
if (m_ext_waitcount == 0)
{
if (VERBOSE>5) LOG("genboard: clock, READY asserted after video\n");
if (TRACE_CLOCK) logerror("%s: clock, READY asserted after video\n", tag());
m_ready(ASSERT_LINE);
m_ready_asserted = true;
}
else
{
if (VERBOSE>5) LOG("genboard: vclock, ew=%d\n", m_ext_waitcount);
if (TRACE_CLOCK) logerror("%s: vclock, ew=%d\n", tag(), m_ext_waitcount);
}
}
}
@ -1142,7 +1299,7 @@ WRITE_LINE_MEMBER( geneve_mapper_device::clock_in )
// Do we have video wait states? In that case, clear the line again
if ((m_waitcount == 0) && (m_ext_waitcount > 0) && m_ready_asserted)
{
if (VERBOSE>5) LOG("genboard: clock, READY cleared for video\n");
if (TRACE_CLOCK) logerror("%s: clock, READY cleared for video\n", tag());
m_ready(CLEAR_LINE);
m_ready_asserted = false;
}
@ -1155,14 +1312,39 @@ WRITE_LINE_MEMBER( geneve_mapper_device::clock_in )
WRITE_LINE_MEMBER( geneve_mapper_device::dbin_in )
{
m_read_mode = (state==ASSERT_LINE);
if (VERBOSE>7) LOG("genboard: dbin = %02x\n", m_read_mode? 1:0);
if (TRACE_DETAIL) logerror("%s: dbin = %02x\n", tag(), m_read_mode? 1:0);
}
/*** DEVICE LIFECYCLE FUNCTIONS ***/
/*
PFM expansion: Setting the bank.
*/
WRITE_LINE_MEMBER( geneve_mapper_device::pfm_select_lsb )
{
if (state==ASSERT_LINE) m_pfm_bank |= 1;
else m_pfm_bank &= 0xfe;
logerror("%s: Setting bank (l) = %d\n", tag(), m_pfm_bank);
}
WRITE_LINE_MEMBER( geneve_mapper_device::pfm_select_msb )
{
if (state==ASSERT_LINE) m_pfm_bank |= 2;
else m_pfm_bank &= 0xfd;
logerror("%s: Setting bank (u) = %d\n", tag(), m_pfm_bank);
}
WRITE_LINE_MEMBER( geneve_mapper_device::pfm_output_enable )
{
// Negative logic
m_pfm_output_enable = (state==CLEAR_LINE);
logerror("%s: PFM output %s\n", tag(), m_pfm_output_enable? "enable" : "disable");
}
//====================================================================
// Common device lifecycle
//====================================================================
void geneve_mapper_device::device_start()
{
if (VERBOSE>0) LOG("genboard: Starting Geneve mapper\n");
// Get pointers
m_peribox = machine().device<bus8z_device>(PERIBOX_TAG);
m_keyboard = machine().device<geneve_keyboard_device>(GKEYBOARD_TAG);
@ -1170,6 +1352,10 @@ void geneve_mapper_device::device_start()
m_sound = machine().device<bus8z_device>(TISOUND_TAG);
m_clock = machine().device<mm58274c_device>(GCLOCK_TAG);
// PFM expansion
m_pfm512 = machine().device<at29c040_device>(PFM512_TAG);
m_pfm512a = machine().device<at29c040a_device>(PFM512A_TAG);
m_ready.resolve();
m_sram = machine().root_device().memregion(SRAM_TAG)->base();
@ -1182,8 +1368,6 @@ void geneve_mapper_device::device_start()
void geneve_mapper_device::device_reset()
{
if (VERBOSE>1) LOG("genboard: Resetting mapper\n");
m_extra_waitstates = false;
m_video_waitstates = true;
m_read_mode = false;
@ -1198,33 +1382,25 @@ void geneve_mapper_device::device_reset()
m_cartridge6_writable = false;
m_cartridge7_writable = false;
m_grom_address = 0;
m_pfm_bank = 0;
m_pfm_output_enable = true;
// Clear map
for (int i=0; i < 8; i++) m_map[i] = 0;
m_genmod = false;
if (machine().root_device().ioport("MODE")->read()==0)
// Check which boot EPROM we are using (or PFM)
set_boot_rom(machine().root_device().ioport("BOOTROM")->read());
// Check for GenMod. We assume that GenMod can be combined with PFM.
if (machine().root_device().ioport("MODE")->read()!=0)
{
switch (machine().root_device().ioport("BOOTROM")->read())
{
case GENEVE_098:
if (VERBOSE>0) LOG("genboard: Using 0.98 boot eprom\n");
m_eprom = machine().root_device().memregion("maincpu")->base() + 0x4000;
break;
case GENEVE_100:
if (VERBOSE>0) LOG("genboard: Using 1.00 boot eprom\n");
m_eprom = machine().root_device().memregion("maincpu")->base();
break;
}
}
else
{
if (VERBOSE>0) LOG("genboard: Using GenMod modification\n");
logerror("%s: Using GenMod modification\n", tag());
m_eprom = machine().root_device().memregion("maincpu")->base() + 0x8000;
if (m_eprom[0] != 0xf0)
{
fatalerror("genboard: GenMod boot rom missing.\n");
fatalerror("genboard: GenMod boot ROM missing\n");
}
m_genmod = true;
m_turbo = ((machine().root_device().ioport("GENMODDIPS")->read() & GM_TURBO)!=0);
@ -1301,7 +1477,7 @@ void geneve_keyboard_device::post_in_key_queue(int keycode)
m_key_queue[(m_key_queue_head + m_key_queue_length) % KEYQUEUESIZE] = keycode;
m_key_queue_length++;
if (VERBOSE>5) LOG("genboard: posting keycode %02x\n", keycode);
if (TRACE_KEYBOARD) logerror("%s: Posting keycode %02x\n", tag(), keycode);
}
void geneve_keyboard_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
@ -1316,7 +1492,7 @@ void geneve_keyboard_device::poll()
int i, j;
int keycode;
int pressed;
if (VERBOSE>7) LOG("genboard: poll keyboard\n");
if (TRACE_KEYBOARD) logerror("%s: Poll keyboard\n", tag());
if (m_key_reset) return;
/* Poll keyboard */
@ -1522,7 +1698,7 @@ void geneve_keyboard_device::signal_when_key_available()
// buffer clear is disabled, and key queue is not empty. */
if ((!m_key_reset) && (m_keyboard_clock) && (m_keep_keybuf) && (m_key_queue_length != 0))
{
if (VERBOSE>6) LOG("genboard: signalling key available\n");
if (TRACE_KEYBOARD) logerror("%s: Signalling key available\n", tag());
m_interrupt(ASSERT_LINE);
m_key_in_buffer = true;
}
@ -1532,7 +1708,7 @@ WRITE_LINE_MEMBER( geneve_keyboard_device::clock_control )
{
bool rising_edge = (!m_keyboard_clock && (state==ASSERT_LINE));
m_keyboard_clock = (state==ASSERT_LINE);
if (VERBOSE>5) LOG("genboard: keyboard clock_control state=%d\n", m_keyboard_clock);
if (TRACE_KEYBOARD) logerror("%s: Keyboard clock_control state=%d\n", tag(), m_keyboard_clock);
if (rising_edge)
signal_when_key_available();
}
@ -1582,7 +1758,6 @@ WRITE_LINE_MEMBER( geneve_keyboard_device::reset_line )
void geneve_keyboard_device::device_start()
{
if (VERBOSE>2) LOG("genboard: Keyboard started\n");
m_timer = timer_alloc(0);
m_interrupt.resolve();
}

View File

@ -18,6 +18,7 @@
#include "machine/mm58274c.h"
#include "video/v9938.h"
#include "cpu/tms9900/tms9995.h"
#include "machine/at29x.h"
extern const device_type GENEVE_MOUSE;
extern const device_type GENEVE_KEYBOARD;
@ -109,25 +110,27 @@ class geneve_mapper_device : public device_t
{
public:
geneve_mapper_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
inline void set_geneve_mode(bool geneve) { m_geneve_mode = geneve; }
inline void set_direct_mode(bool direct) { m_direct_mode = direct; }
inline void set_cartridge_size(int size) { m_cartridge_size = size; }
inline void set_cartridge_writable(int base, bool write)
{
if (base==0x6000) m_cartridge6_writable = write;
else m_cartridge7_writable = write;
}
inline void set_video_waitstates(bool wait) { m_video_waitstates = wait; }
inline void set_extra_waitstates(bool wait) { m_extra_waitstates = wait; }
void set_geneve_mode(bool geneve);
void set_direct_mode(bool direct);
void set_cartridge_size(int size);
void set_cartridge_writable(int base, bool write);
void set_video_waitstates(bool wait);
void set_extra_waitstates(bool wait);
DECLARE_READ8_MEMBER( readm );
DECLARE_WRITE8_MEMBER( writem );
DECLARE_SETOFFSET_MEMBER( setoffset );
DECLARE_INPUT_CHANGED_MEMBER( gm_changed );
DECLARE_INPUT_CHANGED_MEMBER( settings_changed );
DECLARE_WRITE_LINE_MEMBER( clock_in );
DECLARE_WRITE_LINE_MEMBER( dbin_in );
// PFM support
DECLARE_WRITE_LINE_MEMBER( pfm_select_lsb );
DECLARE_WRITE_LINE_MEMBER( pfm_select_msb );
DECLARE_WRITE_LINE_MEMBER( pfm_output_enable );
template<class _Object> static devcb_base &static_set_ready_callback(device_t &device, _Object object) { return downcast<geneve_mapper_device &>(device).m_ready.set_callback(object); }
protected:
@ -177,6 +180,15 @@ private:
bool m_genmod;
bool m_timode;
// PFM mod (0 = none, 1 = AT29C040, 2 = AT29C040A)
DECLARE_READ8_MEMBER( read_from_pfm );
DECLARE_WRITE8_MEMBER( write_to_pfm );
void set_boot_rom(int selection);
int m_pfm_mode;
int m_pfm_bank;
bool m_pfm_output_enable;
// SRAM access
int m_sram_mask;
int m_sram_val;
@ -190,6 +202,8 @@ private:
// Devices
mm58274c_device* m_clock;
tms9995_device* m_cpu;
at29c040_device* m_pfm512;
at29c040a_device* m_pfm512a;
geneve_keyboard_device* m_keyboard;
bus8z_device* m_video;

View File

@ -51,6 +51,8 @@
#define GMAPPER_TAG "gmapper"
#define GMOUSE_TAG "gmouse"
#define GCLOCK_TAG "mm58274c"
#define PFM512_TAG "pfm512"
#define PFM512A_TAG "pfm512a"
#define READ16Z_MEMBER(name) void name(ATTR_UNUSED address_space &space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT16 *value, ATTR_UNUSED UINT16 mem_mask)
#define DECLARE_READ16Z_MEMBER(name) void name(ATTR_UNUSED address_space &space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT16 *value, ATTR_UNUSED UINT16 mem_mask = 0xffff)
@ -106,7 +108,9 @@ enum
enum
{
GENEVE_098 = 0,
GENEVE_100 = 1
GENEVE_100,
GENEVE_PFM512,
GENEVE_PFM512A
};
#endif

View File

@ -39,11 +39,11 @@
#include "at29x.h"
#define TRACE_PRG 1
#define TRACE_PRG 0
#define TRACE_READ 0
#define TRACE_WRITE 1
#define TRACE_CONFIG 1
#define TRACE_STATE 1
#define TRACE_WRITE 0
#define TRACE_CONFIG 0
#define TRACE_STATE 0
enum
{
@ -228,7 +228,7 @@ READ8_MEMBER( at29x_device::read )
break;
case 0x00001:
reply = 0xa4; // Device code
reply = m_device_id; // Device code
break;
// Boot block lockout detection [1]

View File

@ -215,9 +215,9 @@
#include "bus/ti99_peb/peribox.h"
#define VERBOSE 1
#define LOG logerror
#define TRACE_READY 0
#define TRACE_LINES 0
#define TRACE_CRU 0
#define SRAM_SIZE 384*1024 // maximum SRAM expansion on-board
#define DRAM_SIZE 512*1024
@ -318,9 +318,11 @@ static INPUT_PORTS_START(geneve)
PORT_CONFSETTING( GENMOD, "GenMod" )
PORT_START( "BOOTROM" )
PORT_CONFNAME( 0x01, GENEVE_098, "Boot ROM" ) PORT_CONDITION( "MODE", 0x01, EQUALS, 0x00 )
PORT_CONFNAME( 0x03, GENEVE_098, "Boot ROM" ) PORT_CHANGED_MEMBER(GMAPPER_TAG, geneve_mapper_device, settings_changed, 3)
PORT_CONFSETTING( GENEVE_098, "Version 0.98" )
PORT_CONFSETTING( GENEVE_100, "Version 1.00" )
PORT_CONFSETTING( GENEVE_PFM512, "PFM 512" )
PORT_CONFSETTING( GENEVE_PFM512A, "PFM 512A" )
PORT_START( "SRAM" )
PORT_CONFNAME( 0x03, 0x01, "Onboard SRAM" ) PORT_CONDITION( "MODE", 0x01, EQUALS, 0x00 )
@ -329,10 +331,10 @@ static INPUT_PORTS_START(geneve)
PORT_CONFSETTING( 0x02, "384 KiB" )
PORT_START( "GENMODDIPS" )
PORT_DIPNAME( GM_TURBO, 0x00, "Genmod Turbo mode") PORT_CONDITION( "MODE", 0x01, EQUALS, GENMOD ) PORT_CHANGED_MEMBER(GMAPPER_TAG, geneve_mapper_device, gm_changed, 1)
PORT_DIPNAME( GM_TURBO, 0x00, "Genmod Turbo mode") PORT_CONDITION( "MODE", 0x01, EQUALS, GENMOD ) PORT_CHANGED_MEMBER(GMAPPER_TAG, geneve_mapper_device, settings_changed, 1)
PORT_CONFSETTING( 0x00, DEF_STR( Off ))
PORT_CONFSETTING( GM_TURBO, DEF_STR( On ))
PORT_DIPNAME( GM_TIM, GM_TIM, "Genmod TI mode") PORT_CONDITION( "MODE", 0x01, EQUALS, GENMOD ) PORT_CHANGED_MEMBER(GMAPPER_TAG, geneve_mapper_device, gm_changed, 2)
PORT_DIPNAME( GM_TIM, GM_TIM, "Genmod TI mode") PORT_CONDITION( "MODE", 0x01, EQUALS, GENMOD ) PORT_CHANGED_MEMBER(GMAPPER_TAG, geneve_mapper_device, settings_changed, 2)
PORT_CONFSETTING( 0x00, DEF_STR( Off ))
PORT_CONFSETTING( GM_TIM, DEF_STR( On ))
@ -354,7 +356,7 @@ WRITE8_MEMBER ( geneve_state::cruwrite )
if ((addroff & 0xffc0) == CRU_SSTEP_BASE)
{
int bit = (addroff & 0x003e)>>1;
if (VERBOSE>0) LOG("geneve: Single step not implemented; bit %d set to %d\n", bit, data);
logerror("geneve: Single step not implemented; bit %d set to %d\n", bit, data);
return;
}
@ -365,47 +367,47 @@ WRITE8_MEMBER ( geneve_state::cruwrite )
{
case 5:
// No one really cares...
if (VERBOSE>8) LOG("geneve: Set PAL flag = %02x\n", data);
if (TRACE_CRU) logerror("geneve: Set PAL flag = %02x\n", data);
// m_palvideo = (data!=0);
break;
case 7:
// m_capslock = (data!=0);
if (VERBOSE>8) LOG("geneve: Set capslock flag = %02x\n", data);
if (TRACE_CRU) logerror("geneve: Set capslock flag = %02x\n", data);
break;
case 8:
if (VERBOSE>8) LOG("geneve: Set keyboard clock flag = %02x\n", data);
if (TRACE_CRU) logerror("geneve: Set keyboard clock flag = %02x\n", data);
m_keyboard->clock_control((data!=0)? ASSERT_LINE : CLEAR_LINE);
break;
case 9:
if (VERBOSE>8) LOG("geneve: Set keyboard scan flag = %02x\n", data);
if (TRACE_CRU) logerror("geneve: Set keyboard scan flag = %02x\n", data);
m_keyboard->send_scancodes((data!=0)? ASSERT_LINE : CLEAR_LINE);
break;
case 10:
if (VERBOSE>8) LOG("geneve: Geneve mode = %02x\n", data);
if (TRACE_CRU) logerror("geneve: Geneve mode = %02x\n", data);
m_mapper->set_geneve_mode(data!=0);
break;
case 11:
if (VERBOSE>8) LOG("geneve: Direct mode = %02x\n", data);
if (TRACE_CRU) logerror("geneve: Direct mode = %02x\n", data);
m_mapper->set_direct_mode(data!=0);
break;
case 12:
if (VERBOSE>8) LOG("geneve: Cartridge size 8K = %02x\n", data);
if (TRACE_CRU) logerror("geneve: Cartridge size 8K = %02x\n", data);
m_mapper->set_cartridge_size((data!=0)? 0x2000 : 0x4000);
break;
case 13:
if (VERBOSE>8) LOG("geneve: Cartridge writable 6000 = %02x\n", data);
if (TRACE_CRU) logerror("geneve: Cartridge writable 6000 = %02x\n", data);
m_mapper->set_cartridge_writable(0x6000, (data!=0));
break;
case 14:
if (VERBOSE>8) LOG("geneve: Cartridge writable 7000 = %02x\n", data);
if (TRACE_CRU) logerror("geneve: Cartridge writable 7000 = %02x\n", data);
m_mapper->set_cartridge_writable(0x7000, (data!=0));
break;
case 15:
if (VERBOSE>8) LOG("geneve: Extra wait states = %02x\n", data==0);
if (TRACE_CRU) logerror("geneve: Extra wait states = %02x\n", data==0);
m_mapper->set_extra_waitstates(data==0); // let's use the inverse semantics
break;
default:
if (VERBOSE>0) LOG("geneve: set CRU address %04x=%02x ignored\n", addroff, data);
logerror("geneve: set CRU address %04x=%02x ignored\n", addroff, data);
break;
}
}
@ -425,7 +427,7 @@ READ8_MEMBER( geneve_state::cruread )
if ((addroff & 0xffc0) == CRU_SSTEP_BASE)
{
int bit = (addroff & 0x003e)>>1;
if (VERBOSE>0) LOG("geneve: Single step not implemented; attempting to read bit %d\n", bit);
logerror("geneve: Single step not implemented; attempting to read bit %d\n", bit);
return value;
}
@ -477,7 +479,7 @@ READ8_MEMBER( geneve_state::read_by_9901 )
if (m_intb==CLEAR_LINE) answer |= 0x10;
if (m_video_wait==ASSERT_LINE) answer |= 0x20;
// TODO: PAL pin 5
if (VERBOSE>8) LOG("geneve: INT15-8 = %02x\n", answer);
if (TRACE_LINES) logerror("geneve: INT15-8 = %02x\n", answer);
break;
case TMS9901_P0_P7:
@ -505,7 +507,7 @@ READ8_MEMBER( geneve_state::read_by_9901 )
*/
WRITE_LINE_MEMBER( geneve_state::peripheral_bus_reset )
{
if (VERBOSE>0) LOG("geneve: peripheral bus reset request; not implemented yet.\n");
logerror("geneve: Peripheral bus reset request; not implemented yet.\n");
}
/*
@ -513,7 +515,7 @@ WRITE_LINE_MEMBER( geneve_state::peripheral_bus_reset )
*/
WRITE_LINE_MEMBER( geneve_state::VDP_reset )
{
if (VERBOSE>0) LOG("geneve: Video reset request; not implemented yet.\n");
logerror("geneve: Video reset request; not implemented yet.\n");
}
/*
@ -529,7 +531,7 @@ WRITE_LINE_MEMBER( geneve_state::joystick_select )
*/
WRITE_LINE_MEMBER( geneve_state::extbus_wait_states )
{
if (VERBOSE>0) LOG("geneve: external bus wait states set to %d, not implemented yet.\n", state);
logerror("geneve: External bus wait states set to %d, not implemented yet.\n", state);
}
/*
@ -538,7 +540,7 @@ WRITE_LINE_MEMBER( geneve_state::extbus_wait_states )
*/
WRITE_LINE_MEMBER( geneve_state::video_wait_states )
{
if (VERBOSE>1) LOG("geneve: video wait states set to %d\n", state);
if (TRACE_LINES) logerror("geneve: Video wait states set to %d\n", state);
m_mapper->set_video_waitstates(state==ASSERT_LINE);
m_video_wait = (state!=0)? ASSERT_LINE : CLEAR_LINE;
}
@ -555,39 +557,6 @@ WRITE8_MEMBER( geneve_state::tms9901_interrupt )
m_cpu->set_input_line(INT_9995_INT1, data);
}
/*
// tms9901 setup
const tms9901_interface tms9901_wiring_geneve =
{
TMS9901_INT1 | TMS9901_INT2 | TMS9901_INT8 | TMS9901_INTB | TMS9901_INTC,
// read handler
DEVCB_DRIVER_MEMBER(geneve_state, read_by_9901),
{ // write handlers
DEVCB_DRIVER_LINE_MEMBER(geneve_state, peripheral_bus_reset),
DEVCB_DRIVER_LINE_MEMBER(geneve_state, VDP_reset),
DEVCB_DRIVER_LINE_MEMBER(geneve_state, joystick_select),
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_DEVICE_LINE_MEMBER(GKEYBOARD_TAG, geneve_keyboard_device, reset_line),
DEVCB_DRIVER_LINE_MEMBER(geneve_state, extbus_wait_states),
DEVCB_NULL,
DEVCB_DRIVER_LINE_MEMBER(geneve_state, video_wait_states),
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL
},
// interrupt handler
DEVCB_DRIVER_MEMBER(geneve_state, tms9901_interrupt)
};
*/
/*******************************************************************
Signal lines
*******************************************************************/
@ -613,14 +582,14 @@ WRITE_LINE_MEMBER( geneve_state::intb )
WRITE_LINE_MEMBER( geneve_state::ext_ready )
{
if (VERBOSE>6) LOG("geneve: READY level (ext) = %02x\n", state);
if (TRACE_READY) logerror("geneve: READY level (ext) = %02x\n", state);
m_ready_line = state;
m_cpu->set_ready((m_ready_line == ASSERT_LINE && m_ready_line1 == ASSERT_LINE)? ASSERT_LINE : CLEAR_LINE);
}
WRITE_LINE_MEMBER( geneve_state::mapper_ready )
{
if (VERBOSE>6) LOG("geneve: READY level (mapper) = %02x\n", state);
if (TRACE_READY) logerror("geneve: READY level (mapper) = %02x\n", state);
m_ready_line1 = state;
m_cpu->set_ready((m_ready_line == ASSERT_LINE && m_ready_line1 == ASSERT_LINE)? ASSERT_LINE : CLEAR_LINE);
}
@ -667,8 +636,7 @@ TIMER_DEVICE_CALLBACK_MEMBER(geneve_state::geneve_hblank_interrupt)
WRITE8_MEMBER( geneve_state::external_operation )
{
static const char* extop[8] = { "inv1", "inv2", "IDLE", "RSET", "inv3", "CKON", "CKOF", "LREX" };
if (VERBOSE>1)
if (offset != IDLE_OP) LOG("geneve: External operation %s not implemented on Geneve board\n", extop[offset]);
if (offset != IDLE_OP) logerror("geneve: External operation %s not implemented on Geneve board\n", extop[offset]);
}
/*
@ -739,9 +707,12 @@ static MACHINE_CONFIG_START( geneve_60hz, geneve_state )
MCFG_TMS9901_P0_HANDLER( WRITELINE( geneve_state, peripheral_bus_reset) )
MCFG_TMS9901_P1_HANDLER( WRITELINE( geneve_state, VDP_reset) )
MCFG_TMS9901_P2_HANDLER( WRITELINE( geneve_state, joystick_select) )
MCFG_TMS9901_P4_HANDLER( DEVWRITELINE( GMAPPER_TAG, geneve_mapper_device, pfm_select_lsb) ) // new for PFM
MCFG_TMS9901_P5_HANDLER( DEVWRITELINE( GMAPPER_TAG, geneve_mapper_device, pfm_output_enable) ) // new for PFM
MCFG_TMS9901_P6_HANDLER( DEVWRITELINE( GKEYBOARD_TAG, geneve_keyboard_device, reset_line) )
MCFG_TMS9901_P7_HANDLER( WRITELINE( geneve_state, extbus_wait_states) )
MCFG_TMS9901_P9_HANDLER( WRITELINE( geneve_state, video_wait_states) )
MCFG_TMS9901_P13_HANDLER( DEVWRITELINE( GMAPPER_TAG, geneve_mapper_device, pfm_select_msb) ) // new for PFM
MCFG_TMS9901_INTLEVEL_HANDLER( WRITE8( geneve_state, tms9901_interrupt) )
// Mapper
@ -769,6 +740,10 @@ static MACHINE_CONFIG_START( geneve_60hz, geneve_state )
MCFG_GENEVE_MOUSE_ADD( GMOUSE_TAG )
MCFG_GENEVE_JOYPORT_ADD( JOYPORT_TAG )
// PFM expansion
MCFG_AT29C040_ADD( PFM512_TAG )
MCFG_AT29C040A_ADD( PFM512A_TAG )
MACHINE_CONFIG_END
/*