summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Michael Zapf <Michael.Zapf@mizapf.de>2018-06-10 18:14:05 +0200
committer Michael Zapf <Michael.Zapf@mizapf.de>2018-06-10 18:43:09 +0200
commit02e37f561f38f4c1b30f52e9f8c6b4a249328356 (patch)
tree7fe8d0f34cd877e1c169c530e5cb3092a04c6ea2
parentae25eeb9112784ca8aa743562a5efc4bcf327ec0 (diff)
geneve: Using bios selection; split genmod as a separate driver
-rw-r--r--src/devices/bus/ti99/internal/genboard.cpp1038
-rw-r--r--src/devices/bus/ti99/internal/genboard.h145
-rw-r--r--src/devices/bus/ti99/peb/peribox.cpp51
-rw-r--r--src/devices/bus/ti99/peb/peribox.h21
-rw-r--r--src/mame/drivers/geneve.cpp178
-rw-r--r--src/mame/mame.lst3
6 files changed, 598 insertions, 838 deletions
diff --git a/src/devices/bus/ti99/internal/genboard.cpp b/src/devices/bus/ti99/internal/genboard.cpp
index 4d8b5935b26..a9ed0e9e1bb 100644
--- a/src/devices/bus/ti99/internal/genboard.cpp
+++ b/src/devices/bus/ti99/internal/genboard.cpp
@@ -81,7 +81,7 @@
Genmod's double switch box is also emulated. There are two switches:
- Turbo mode: Activates or deactivates the wait state logic on the Geneve
board. This switch may be changed at any time.
- - TI mode: Selects between the on-board memory, which is obviously required
+ - TI mode: Selects between the on-board memory, which is required
for the GPL interpreter, and the external Memex memory. This switch
triggers a reset when changed.
@@ -92,27 +92,41 @@
Logical address space: 64 KiB
- Geneve mode:
+ Geneve mode
+ -----------
+ Video: F100 (port 0, rw),
+ F102 (port 1, rw),
+ F104 (port 2, w),
+ F106 (port 3, w)
+ 1111 0001 0000 .xx0
+ Mapper: F110 - F117 1111 0001 0001 0xxx
+ Keyboard: F118 1111 0001 0001 1...
+ Clock: F130 - F13F 1111 0001 0011 xxxx
+ Sound: F120 1111 0001 0010 ...0
- Video: F100, F102, F104, F106 (mirror: +8)
- Mapper: F110 - F117
- Keyboard: F118
- Clock: F130 - F13F
- Sound: F120
-
- TI mode:
-
- Video: 8800, 8802, 8804, 8806
- Mapper: 8000 - 8007
- Keyboard: 8008 - 800F
- Clock: 8010 - 801F
- Speech: 9000 / 9400
- Grom: 9800 / 9802
-
- Physical address space: 2 MiB
-
- Start End Banks
+ TI mode
+ -------
+ Video: 8800 (port 0, r), 8c00 (port 0, w),
+ 8802 (port 1, r), 8c02 (port 0, w),
+ 8c04 (port 2, w),
+ 8c06 (port 3, w)
+
+ 1000 1w.. .... .xx0
+ Mapper: 8000 - 8007 1000 0000 0000 0xxx
+ Keyboard: 8008 - 800F 1000 0000 0000 1...
+ Clock: 8010 - 801F 1000 0000 0001 xxxx
+ Speech: 9000 / 9400 1001 0w.. .... ...0
+ Grom: 9800 / 9802 1001 1w.. .... ..x0
+ 9c00 / 9c02
+
+ Physical address space
+ ----------------------
+ Address space size = 2 MiB
+
+ Start End Phys.pages
000000 - 07FFFF 00-3F 512 KiB DRAM on-board
+ 06C000 - 06DFFF 36 Cartridge space first 8K
+ 06E000 - 06FFFF 37 Cartridge space second 8K
080000 - 0FFFFF 40-7F 512 KiB on-board expansion (never used)
100000 - 16FFFF 80-B7 448 KiB P-Box space (special cards, like MEMEX)
170000 - 17FFFF B8-BF 64 KiB P-Box space (current cards)
@@ -120,10 +134,12 @@
1E0000 - 1FFFFF F0-FF 128 KiB EPROM space; 16 KiB actually used, 8 mirrors
- GenMod modification:
-
+ GenMod modification
+ -------------------
TI mode
000000 - 07FFFF 00-3F 512 KiB DRAM on-board
+ 06C000 - 06DFFF 36 Cartridge space first 8K
+ 06E000 - 06FFFF 37 Cartridge space second 8K
080000 - 1DFFFF 40-EF 1408 KiB P-Box space
1E0000 - 1FFFFF F0-FF 128 KiB EPROM space; 16 KiB actually used, 8 mirrors
@@ -147,16 +163,15 @@
- accesses to the peripheral expansion box: 1 WS
- accesses to on-board DRAM: 1 WS
- accesses to video: 15 WS
- - accesses to sound: ~25 WS
- accesses to SRAM: 0 WS
Additional waitstates are created when one of the CRU bits is set. In that
case, all delays are extended to 2 WS (including SRAM).
Sound waitstates are somewhat unpredictable. It seems as if they depend
- on the clock of the sound chip; the theory is that the READY line is
- pulled down until the next clock pulse, which may take some value between
- 18 CPU cycles and 30 CPU cycles.
+ on the clock of the sound chip; the READY line is pulled down until the
+ next clock pulse, which may take some value between 18 CPU cycles and
+ 30 CPU cycles.
The gate array is able to create wait states for video accesses. However,
these wait states are effective after the video access has been completed.
@@ -165,7 +180,8 @@
Without additional wait states, the video access takes the usual 1 or 2 WS.
Waitstate behavior (Nov 2013)
- Almost perfect. Only video read access from code in DRAM is too fast by one WS
+ Almost perfect. Only video read access from code in DRAM is too fast
+ by one WS
==========================
PFM expansion
@@ -204,20 +220,22 @@
#define LOG_SETTING (1U<<8)
#define LOG_VIDEOWS (1U<<9)
#define LOG_PFM (1U<<10)
+#define LOG_DECODE (1U<<11)
// Minimum log should be settings and warnings
-#define VERBOSE (LOG_GENERAL | LOG_SETTING | LOG_WARN)
+#define VERBOSE ( LOG_SETTING | LOG_WARN )
#include "genboard.h"
#include "logmacro.h"
DEFINE_DEVICE_TYPE_NS(GENEVE_KEYBOARD, bus::ti99::internal, geneve_keyboard_device, "geneve_keyboard", "Geneve XT-style keyboard")
DEFINE_DEVICE_TYPE_NS(GENEVE_MAPPER, bus::ti99::internal, geneve_mapper_device, "geneve_mapper", "Geneve Gate Array")
+DEFINE_DEVICE_TYPE_NS(GENMOD_MAPPER, bus::ti99::internal, genmod_mapper_device, "genmod_mapper", "Geneve Mod Gate Array")
namespace bus { namespace ti99 { namespace internal {
-geneve_mapper_device::geneve_mapper_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, GENEVE_MAPPER, tag, owner, clock), m_gromwaddr_LSB(false),
+geneve_mapper_device::geneve_mapper_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, type, tag, owner, clock), m_gromwaddr_LSB(false),
m_gromraddr_LSB(false),
m_grom_address(0),
m_video_waitstates(false),
@@ -231,17 +249,14 @@ geneve_mapper_device::geneve_mapper_device(const machine_config &mconfig, const
m_cartridge_secondpage(false),
m_cartridge6_writable(false),
m_cartridge7_writable(false),
- m_turbo(false),
- m_genmod(false),
- m_timode(false),
- m_pfm_mode(0),
+ m_boot_rom(0),
m_pfm_bank(0),
m_pfm_output_enable(false),
m_sram_mask(0),
m_sram_val(0),
m_ready(*this),
m_waitcount(0),
- m_ext_waitcount(0),
+ m_video_waitcount(0),
m_clock(*owner, GENEVE_CLOCK_TAG),
m_cpu(*owner, "maincpu"),
m_pfm512(*owner, GENEVE_PFM512_TAG),
@@ -253,11 +268,32 @@ geneve_mapper_device::geneve_mapper_device(const machine_config &mconfig, const
m_sram(*this, GENEVE_SRAM_PAR_TAG),
m_dram(*this, GENEVE_DRAM_PAR_TAG)
{
+}
+
+geneve_mapper_device::geneve_mapper_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : geneve_mapper_device(mconfig, GENEVE_MAPPER, tag, owner, clock)
+{
m_eprom = nullptr;
+ m_pbox_prefix = 0x070000;
+}
+
+genmod_mapper_device::genmod_mapper_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : geneve_mapper_device(mconfig, GENMOD_MAPPER, tag, owner, clock),
+ m_gm_timode(false),
+ m_turbo(false)
+{
+ m_eprom = nullptr;
+ m_pbox_prefix = 0x170000;
}
INPUT_CHANGED_MEMBER( geneve_mapper_device::settings_changed )
{
+ // Used when switching the boot ROMs during runtime, especially the PFM
+ m_boot_rom = newval;
+}
+
+INPUT_CHANGED_MEMBER( genmod_mapper_device::setgm_changed )
+{
int number = (int)((uint64_t)param&0x03);
int value = newval;
@@ -271,12 +307,12 @@ INPUT_CHANGED_MEMBER( geneve_mapper_device::settings_changed )
case 2:
// TIMode switch. Causes reset when changed.
LOGMASKED(LOG_SETTING, "Setting timode flag to %d\n", value);
- m_timode = (value!=0);
+ m_gm_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);
+ m_boot_rom = value;
break;
default:
LOGMASKED(LOG_WARN, "Unknown setting %d ignored\n", number);
@@ -316,8 +352,8 @@ READ8_MEMBER( geneve_mapper_device::read_grom )
{
// GROM data handling
// GROMs are stored in pages 38..3f
- int page = 0x38;
- reply = m_dram->pointer()[(page<<13) + m_grom_address];
+ int physpage = 0x38;
+ reply = m_dram->pointer()[(physpage<<13) + m_grom_address];
m_grom_address = (m_grom_address + 1) & 0xffff;
m_gromraddr_LSB = m_gromwaddr_LSB = false;
}
@@ -349,8 +385,8 @@ WRITE8_MEMBER( geneve_mapper_device::write_grom )
else
{ // write GPL data
// The Geneve GROM simulator allows for GROM writing (verified with a real system)
- int page = 0x38;
- m_dram->pointer()[(page<<13) + m_grom_address] = data;
+ int physpage = 0x38;
+ m_dram->pointer()[(physpage<<13) + m_grom_address] = data;
m_grom_address = (m_grom_address + 1) & 0xffff;
m_gromraddr_LSB = m_gromwaddr_LSB = false;
@@ -359,12 +395,11 @@ WRITE8_MEMBER( geneve_mapper_device::write_grom )
void geneve_mapper_device::set_wait(int min)
{
- if (m_debug_no_ws) return;
if (m_extra_waitstates && min < 2) min = 2;
// if we still have video wait states, do not set this counter
// (or it will assert READY when expiring)
- if (m_ext_waitcount > min) return;
+ if (m_video_waitcount > min) return;
// need one more pass so that READY will be asserted again
m_waitcount = min + 1;
@@ -376,37 +411,10 @@ void geneve_mapper_device::set_wait(int min)
}
}
-void geneve_mapper_device::set_ext_wait(int min)
+void geneve_mapper_device::set_video_waitcount(int min)
{
if (m_debug_no_ws) return;
- m_ext_waitcount = min;
-}
-
-void geneve_mapper_device::set_boot_rom(int selection)
-{
- switch (selection)
- {
- case GENEVE_098:
- LOGMASKED(LOG_SETTING, "Using 0.98 boot eprom\n");
- m_eprom = machine().root_device().memregion("maincpu")->base() + 0x4000;
- m_pfm_mode = 0;
- break;
- case GENEVE_100:
- LOGMASKED(LOG_SETTING, "Using 1.00 boot eprom\n");
- m_eprom = machine().root_device().memregion("maincpu")->base();
- m_pfm_mode = 0;
- break;
- case GENEVE_PFM512:
- LOGMASKED(LOG_SETTING, "Using PFM512 (AT29C040)\n");
- m_pfm_mode = 1;
- break;
- case GENEVE_PFM512A:
- LOGMASKED(LOG_SETTING, "Using PFM512A (AT29C040A)\n");
- m_pfm_mode = 2;
- break;
- default:
- LOGMASKED(LOG_WARN, "Unknown boot ROM selection\n");
- }
+ m_video_waitcount = min;
}
void geneve_mapper_device::set_geneve_mode(bool geneve)
@@ -454,35 +462,6 @@ void geneve_mapper_device::set_extra_waitstates(bool wait)
/************************************************************************
Called by the address map
************************************************************************/
-/*
- Constants for mapper decoding. Naming scheme:
- M=mapper
- L=Logical space; P=Physical space
- G=Geneve mode; T=TI mode; GM=GenMod
-*/
-enum
-{
- MLGVIDEO=1,
- MLGMAPPER,
- MLGKEY,
- MLGCLOCK,
- MLGSOUND,
- MLTMAPPER,
- MLTKEY,
- MLTCLOCK,
- MLTVIDEO,
- MLTSPEECH,
- MLTGROM,
- MLTSOUND,
- MPGDRAM,
- MPGEXP,
- MPGEPROM,
- MPGSRAM,
- MPGBOX,
- MPGMDRAM,
- MPGMEPROM,
- MPGMBOX
-};
/*
Read a byte via the data bus. The decoding has already been done in the
@@ -502,7 +481,19 @@ READ8_MEMBER( geneve_mapper_device::readm )
if (m_cpu->is_onchip(offset)) return m_cpu->debug_read_onchip_memory(offset&0xff);
dec = &debug;
m_debug_no_ws = true;
- decode(space, offset, true, dec);
+ dec->offset = offset;
+ decode_logical(true, dec);
+ if (dec->function == MUNDEF)
+ {
+ map_address(m_read_mode, dec);
+ decode_physical(dec);
+ decode_mod(dec);
+ }
+ if (dec->function == MBOX)
+ {
+ m_peribox->memen_in(ASSERT_LINE);
+ m_peribox->setaddress_dbin(space, dec->physaddr, true);
+ }
}
else
{
@@ -511,89 +502,49 @@ READ8_MEMBER( geneve_mapper_device::readm )
m_debug_no_ws = false;
}
+ // Logical space
+
switch (dec->function)
{
- case MLGVIDEO:
+ case MLVIDEO:
if (!machine().side_effects_disabled())
{
value = m_video->read(space, dec->offset>>1);
LOGMASKED(LOG_READ, "Read video %04x -> %02x\n", 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);
+ if (m_video_waitstates) set_video_waitcount(15);
}
break;
- case MLGMAPPER:
+ case MLMAPPER:
// mapper
- value = m_map[dec->offset];
- LOGMASKED(LOG_READ, "read mapper %04x -> %02x\n", dec->offset, value);
- break;
-
- case MLGKEY:
- // key
- if (!machine().side_effects_disabled()) value = m_keyboard->get_recent_key();
- LOGMASKED(LOG_READ, "Read keyboard -> %02x\n", value);
- break;
-
- case MLGCLOCK:
- // clock
- // 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;
- LOGMASKED(LOG_READ, "Read clock %04x -> %02x\n", dec->offset, value);
- break;
-
- case MLTMAPPER:
- // mapper
- value = m_map[dec->offset];
+ value = m_map[dec->offset & 0x0007];
LOGMASKED(LOG_READ, "Read mapper %04x -> %02x\n", dec->offset, value);
break;
- case MLTKEY:
+ case MLKEY:
// key
if (!machine().side_effects_disabled()) value = m_keyboard->get_recent_key();
LOGMASKED(LOG_READ, "Read keyboard -> %02x\n", value);
break;
- case MLTCLOCK:
+ case MLCLOCK:
// clock
- // upper nibble is 1, only last byte gets a 2
- // probably because of the location at 8010...8020?
- // (TI mode used swapped byte order)
- // unless we use a workspace at >F000, in which case we get 8x values
- // Obscure, needs more investigation. We might as well ignore this,
+ // Tests on the real machine showed that the upper nibble is 0xf
+ // (probably because of the location at f130-f13f?)
+ // In TI mode, however, the upper nibble is 1, unless we read 801f,
+ // in which case the nibble is 2. Here the location is 8010-801f.
+ // Needs more investigation. We might as well ignore this,
// as the high nibble is obviously undefined and takes some past
// value floating around.
- value = m_clock->read(space, dec->offset);
- value |= (dec->offset==0x000f)? 0x20 : 0x10;
+ value = m_clock->read(space, dec->offset & 0x000f);
+ if (m_geneve_mode) value |= 0xf0;
+ else value |= ((dec->offset & 0x000f)==0x000f)? 0x20 : 0x10;
LOGMASKED(LOG_READ, "Read clock %04x -> %02x\n", dec->offset, value);
break;
- case MLTVIDEO:
- // video
- // ++++ ++-- ---- ---+
- // 1000 1000 0000 00x0
- if (!machine().side_effects_disabled())
- {
- value = m_video->read(space, dec->offset>>1);
- LOGMASKED(LOG_READ, "Read video %04x -> %02x\n", dec->offset, value);
- // See above
- if (m_video_waitstates) set_ext_wait(15);
- }
- break;
-
- case MLTSPEECH:
- // speech
- // ++++ ++-- ---- ---+
- // 1001 0000 0000 0000
- // We need to add the address prefix bits
- m_peribox->readz(space, dec->offset, &value, 0xff);
- m_peribox->memen_in(CLEAR_LINE);
- LOGMASKED(LOG_READ, "Read speech -> %02x\n", value);
- break;
-
- case MLTGROM:
+ case MLGROM:
// grom simulation
// ++++ ++-- ---- ---+
// 1001 1000 0000 00x0
@@ -601,49 +552,43 @@ READ8_MEMBER( geneve_mapper_device::readm )
LOGMASKED(LOG_READ, "Read GROM %04x -> %02x\n", dec->offset, value);
break;
- case MLGSOUND:
- case MLTSOUND:
+ case MLSOUND:
value = 0;
break;
-
- case MPGDRAM:
- // DRAM.
+ case MPDRAM:
+ // DRAM. One wait state.
value = m_dram->pointer()[dec->physaddr];
-// LOG("dram read physaddr = %06x logaddr = %04x value = %02x\n", dec->physaddr, dec->offset, value);
LOGMASKED(LOG_READ, "Read DRAM %04x (%06x) -> %02x\n", dec->offset, dec->physaddr, value);
break;
- case MPGEXP:
+ case MPEXP:
// On-board memory expansion for standard Geneve (never used)
- LOGMASKED(LOG_READ, "Read unmapped area %06x\n", dec->physaddr);
+ LOGMASKED(LOG_READ, "Read on-board expansion (not available) %06x -> 00\n", dec->physaddr);
value = 0;
break;
- case MPGEPROM:
+ case MPEPROM:
// 1 111. ..xx xxxx xxxx xxxx on-board eprom (16K)
// mirrored for f0, f2, f4, ...; f1, f3, f5, ...
- if (m_pfm_mode == 0)
- {
- value = m_eprom[dec->physaddr & 0x003fff];
- LOGMASKED(LOG_READ, "Read EPROM %04x (%06x) -> %02x\n", dec->offset, dec->physaddr, value);
- }
- else value = read_from_pfm(space, dec->physaddr, 0xff);
-
+ value = boot_rom(space, dec->physaddr, 0xff);
break;
- case MPGSRAM:
+ case MPSRAM:
if ((dec->physaddr & m_sram_mask)==m_sram_val)
{
value = m_sram->pointer()[dec->physaddr & ~m_sram_mask];
+ LOGMASKED(LOG_READ, "Read SRAM %04x (%06x) -> %02x\n", dec->offset, dec->physaddr, value);
+ }
+ else
+ {
+ LOGMASKED(LOG_WARN, "Decoded as SRAM read, but no SRAM at %06x\n", dec->physaddr);
+ value = 0;
}
- else value = 0;
// Return in any case
-// LOG("sram read physaddr = %06x logaddr = %04x value = %02x\n", dec->physaddr, dec->offset, value);
- LOGMASKED(LOG_READ, "Read SRAM %04x (%06x) -> %02x\n", dec->offset, dec->physaddr, value);
break;
- case MPGBOX:
+ case MBOX:
// Route everything else to the P-Box
// 0x000000-0x07ffff for the stock Geneve (AMC,AMB,AMA,A0 ...,A15)
// 0x000000-0x1fffff for the GenMod.(AME,AMD,AMC,AMB,AMA,A0 ...,A15)
@@ -653,26 +598,8 @@ READ8_MEMBER( geneve_mapper_device::readm )
LOGMASKED(LOG_READ, "Read P-Box %04x (%06x) -> %02x\n", dec->offset, dec->physaddr, value);
break;
- case MPGMDRAM:
- // DRAM. One wait state.
- value = m_dram->pointer()[dec->physaddr];
- break;
-
- case MPGMEPROM:
- // 1 111. ..xx xxxx xxxx xxxx on-board eprom (16K)
- // mirrored for f0, f2, f4, ...; f1, f3, f5, ...
- if (m_pfm_mode == 0)
- {
- value = m_eprom[dec->physaddr & 0x003fff];
- LOGMASKED(LOG_READ, "Read EPROM %04x (%06x) -> %02x\n", dec->offset, dec->physaddr, value);
- }
- else value = read_from_pfm(space, dec->physaddr, 0xff);
- break;
-
- case MPGMBOX:
- // Route everything else to the P-Box
- m_peribox->readz(space, dec->physaddr, &value, 0xff);
- m_peribox->memen_in(CLEAR_LINE);
+ default:
+ LOGMASKED(LOG_WARN, "Unknown decoding result type: %d\n", dec->function);
break;
}
return value;
@@ -686,598 +613,271 @@ WRITE8_MEMBER( geneve_mapper_device::writem )
// For the debugger, do the decoding here with no wait states
if (machine().side_effects_disabled())
{
+ // TODO: add debug_write_onchip_memory
dec = &debug;
m_debug_no_ws = true;
- decode(space, offset, false, dec);
+ dec->offset = offset;
+ decode_logical(false, dec);
+ if (dec->function == MUNDEF)
+ {
+ map_address(m_read_mode, dec);
+ decode_physical(dec);
+ decode_mod(dec);
+ }
+ if (dec->function == MBOX)
+ {
+ m_peribox->memen_in(ASSERT_LINE);
+ m_peribox->setaddress_dbin(space, dec->physaddr, false);
+ }
}
else
{
// Use the values found in the setaddress phase
- m_debug_no_ws = false;
dec = &m_decoded;
+ m_debug_no_ws = false;
}
+
+ // Logical space
+
switch (dec->function)
{
- case MLGVIDEO:
+ case MLVIDEO:
// video
// ++++ ++++ ++++ ---+
// 1111 0001 0000 .cc0
+ // Initialize waitstate timer
if (!machine().side_effects_disabled())
{
m_video->write(space, dec->offset>>1, data);
LOGMASKED(LOG_WRITE, "Write video %04x <- %02x\n", offset, data);
// See above
- if (m_video_waitstates) set_ext_wait(15);
+ if (m_video_waitstates) set_video_waitcount(15);
}
break;
- case MLGMAPPER:
+ case MLMAPPER:
// mapper
- m_map[dec->offset] = data;
+ m_map[dec->offset & 0x0007] = data;
LOGMASKED(LOG_WRITE, "Write mapper %04x <- %02x\n", offset, data);
break;
- case MLGCLOCK:
+ case MLCLOCK:
// clock
// ++++ ++++ ++++ ----
- m_clock->write(space, dec->offset, data);
+ m_clock->write(space, dec->offset & 0x000f, data);
LOGMASKED(LOG_WRITE, "Write clock %04x <- %02x\n", offset, data);
break;
- case MLGSOUND:
+ case MLSOUND:
// sound
// ++++ ++++ ++++ ---+
m_sound->write(data);
LOGMASKED(LOG_WRITE, "Write sound <- %02x\n", data);
break;
- case MLTMAPPER:
- // mapper
- m_map[dec->offset] = data;
- LOGMASKED(LOG_WRITE, "Write mapper %04x <- %02x\n", offset, data);
- break;
-
- case MLTCLOCK:
- // clock
- m_clock->write(space, dec->offset, data);
- LOGMASKED(LOG_WRITE, "Write clock %04x <- %02x\n", offset, data);
- break;
-
- case MLTVIDEO:
- // video
- // ++++ ++-- ---- ---+
- // 1000 1100 0000 00c0
- // Initialize waitstate timer
- if (!machine().side_effects_disabled())
- {
- m_video->write(space, dec->offset>>1, data);
- LOGMASKED(LOG_WRITE, "Write video %04x <- %02x\n", offset, data);
- // See above
- if (m_video_waitstates) set_ext_wait(15);
- }
- break;
-
- case MLTSPEECH:
- // speech
- // ++++ ++-- ---- ---+
- // 1001 0100 0000 0000
- // We need to add the address prefix bits
- m_peribox->write(space, dec->offset, data, 0xff);
- m_peribox->memen_in(CLEAR_LINE);
- LOGMASKED(LOG_WRITE, "Write speech <- %02x\n", data);
- break;
-
- case MLTGROM:
- // grom simulation
- // ++++ ++-- ---- ---+
- // 1001 1100 0000 00c0
+ case MLGROM:
+ // The GROM simulator is only available in TI Mode
write_grom(space, dec->offset, data, 0xff);
LOGMASKED(LOG_WRITE, "Write GROM %04x <- %02x\n", offset, data);
break;
- case MLTSOUND:
- // sound
- // ++++ ++-- ---- ---+
- // 1000 0100 0000 0000
- m_sound->write(data);
- LOGMASKED(LOG_WRITE, "Write sound <- %02x\n", data);
- break;
-
- case MLTKEY:
- case MLGKEY:
- break;
-
- case MPGDRAM:
- // DRAM write. One wait state. (only for normal Geneve)
+ // Physical space
+ case MPDRAM:
+ // DRAM write
m_dram->pointer()[dec->physaddr] = data;
LOGMASKED(LOG_WRITE, "Write DRAM %04x (%06x) <- %02x\n", offset, dec->physaddr, data);
break;
- case MPGEXP:
- // On-board memory expansion for standard Geneve (never used)
- LOGMASKED(LOG_WRITE, "Write unmapped area %06x\n", dec->physaddr);
+ case MPEXP:
+ // On-board memory expansion for standard Geneve
+ // Actually never built, so we show it as unmapped
+ LOGMASKED(LOG_WRITE, "Write on-board expansion (not available) %06x <- %02x\n", dec->physaddr, data);
break;
- case MPGEPROM:
+ case MPEPROM:
// 1 111. ..xx xxxx xxxx xxxx on-board eprom (16K)
// mirrored for f0, f2, f4, ...; f1, f3, f5, ...
// Ignore EPROM write (unless PFM)
- if (m_pfm_mode != 0) write_to_pfm(space, dec->physaddr, data, 0xff);
+ if (m_boot_rom != GENEVE_EPROM) write_to_pfm(space, dec->physaddr, data, 0xff);
else
LOGMASKED(LOG_WARN, "Write EPROM %04x (%06x) <- %02x, ignored\n", offset, dec->physaddr, data);
break;
- case MPGSRAM:
+ case MPSRAM:
if ((dec->physaddr & m_sram_mask)==m_sram_val)
{
m_sram->pointer()[dec->physaddr & ~m_sram_mask] = data;
+ LOGMASKED(LOG_WRITE, "Write SRAM %04x (%06x) <- %02x\n", offset, dec->physaddr, data);
+ }
+ else
+ {
+ LOGMASKED(LOG_WARN, "Decoded as SRAM write, but no SRAM at %06x\n", dec->physaddr);
}
- LOGMASKED(LOG_WRITE, "Write SRAM %04x (%06x) <- %02x\n", offset, dec->physaddr, data);
break;
- case MPGBOX:
- dec->physaddr = (dec->physaddr & 0x0007ffff); // 19 bit address
+ case MBOX:
+ // Route everything else to the P-Box
LOGMASKED(LOG_WRITE, "Write P-Box %04x (%06x) <- %02x\n", offset, dec->physaddr, data);
m_peribox->write(space, dec->physaddr, data, 0xff);
m_peribox->memen_in(CLEAR_LINE);
break;
- case MPGMDRAM:
- // DRAM. One wait state.
- m_dram->pointer()[dec->physaddr] = data;
- break;
-
- case MPGMEPROM:
- // 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
- LOGMASKED(LOG_WARN, "Write EPROM %04x (%06x) <- %02x, ignored\n", offset, dec->physaddr, data);
- break;
-
- case MPGMBOX:
- // Route everything else to the P-Box
- m_peribox->write(space, dec->physaddr, data, 0xff);
- m_peribox->memen_in(CLEAR_LINE);
+ default:
+ LOGMASKED(LOG_WARN, "Unknown decoding result type: %d\n", dec->function);
break;
}
}
-void geneve_mapper_device::decode(address_space& space, offs_t offset, bool read_mode, geneve_mapper_device::decdata* dec)
+void geneve_mapper_device::decode_logical(bool reading, geneve_mapper_device::decdata* dec)
{
- dec->function = 0;
- dec->offset = offset;
- dec->physaddr = 0;
+ dec->function = MUNDEF;
+ dec->physaddr = m_pbox_prefix | dec->offset;
+ dec->wait = 1;
- int page;
-
- if (read_mode) // got this from DBIN
+ int i = 0;
+ while (i < 7)
{
- // Logical addresses
if (m_geneve_mode)
{
- // TODO: shortcut offset & 0xffc0 = 0xf100
- if ((offset & 0xfff5)==0xf100)
- {
- // video
- // ++++ ++++ ++++ -+-+
- // 1111 0001 0000 0000
- // 1111 0001 0000 0010
- // 1111 0001 0000 1000
- // 1111 0001 0000 1010
-
- dec->function = MLGVIDEO;
- set_wait(1);
- return;
- }
- if ((offset & 0xfff8)==0xf110)
- {
- // mapper
- dec->function = MLGMAPPER;
- dec->offset = dec->offset & 0x0007;
- set_wait(1);
- return;
- }
- if ((offset & 0xfff8) == 0xf118)
- {
- // key
- dec->function = MLGKEY;
- set_wait(1);
- return;
- }
- if ((offset & 0xfff0)==0xf130)
- {
- // clock
- // tests on the real machine showed that
- // upper nibble is 0xf (probably because of the location at 0xf130?)
- dec->function = MLGCLOCK;
- dec->offset = dec->offset & 0x000f;
- set_wait(1);
- return;
- }
- }
- else
- {
- if ((offset & 0xfff8)==0x8000)
- {
- // mapper
- dec->function = MLTMAPPER;
- dec->offset = dec->offset & 0x0007;
- set_wait(1);
- return;
- }
- if ((offset & 0xfff8)== 0x8008)
- {
- // key
- dec->function = MLTKEY;
- set_wait(1);
- return;
- }
- if ((offset & 0xfff0)==0x8010)
- {
- // clock
- dec->function = MLTCLOCK;
- dec->offset = dec->offset & 0x000f;
- set_wait(1);
- return;
- }
- if ((offset & 0xfc01)==0x8800)
- {
- // video
- // ++++ ++-- ---- ---+
- // 1000 1000 0000 00x0
- // 1 WS is always added; any pending video waitstates are canceled
- dec->function = MLTVIDEO;
- set_wait(1);
- return;
- }
- if ((offset & 0xfc01)==0x9000)
- {
- // speech
- // ++++ ++-- ---- ---+
- // 1001 0000 0000 0000
- // We need to add the address prefix bits
- dec->function = MLTSPEECH;
- dec->offset = offset | ((m_genmod)? 0x170000 : 0x070000);
- m_peribox->memen_in(ASSERT_LINE);
- m_peribox->setaddress_dbin(space, dec->offset, read_mode);
- set_wait(1);
- return;
- }
- if ((offset & 0xfc01)==0x9800)
- {
- // grom simulation
- // ++++ ++-- ---- ---+
- // 1001 1000 0000 00x0
- dec->function = MLTGROM;
- set_wait(1);
- return;
- }
- }
- // still here? Then go via mapping.
- page = (offset & 0xe000) >> 13;
-
- // Determine physical address
- if (m_direct_mode)
- {
- dec->physaddr = 0x1f0000; // points to boot eprom (page F8)
+ // Skip when genbase is 0
+ if ((m_logmap[i].genbase != 0) && ((dec->offset & ~m_logmap[i].genmask) == m_logmap[i].genbase))
+ break;
}
else
{
- if (!m_geneve_mode && page==3)
+ if (reading)
{
- if (m_cartridge_size==0x4000 && m_cartridge_secondpage) dec->physaddr = 0x06e000;
- else dec->physaddr = 0x06c000;
+ if ((dec->offset & ~m_logmap[i].timask) == m_logmap[i].tibase)
+ break;
}
else
{
- dec->physaddr = (m_map[page] << 13);
+ if ((dec->offset & ~m_logmap[i].timask) == (m_logmap[i].tibase | m_logmap[i].writeoff))
+ break;
}
}
- dec->physaddr |= (offset & 0x1fff);
-
- if (!m_genmod) // Standard Geneve
- {
- if ((dec->physaddr & 0x180000)==0x000000)
- {
- // DRAM.
- dec->physaddr = dec->physaddr & 0x07ffff;
- dec->function = MPGDRAM;
- set_wait(1);
- return;
- }
-
- if ((dec->physaddr & 0x180000)==0x080000)
- {
- // On-board memory expansion for standard Geneve (never used)
- dec->function = MPGEXP;
- set_wait(1);
- return;
- }
-
- if ((dec->physaddr & 0x1e0000)==0x1e0000)
- {
- // 1 111. ..xx xxxx xxxx xxxx on-board eprom (16K)
- // mirrored for f0, f2, f4, ...; f1, f3, f5, ... unless using PFM
- dec->function = MPGEPROM;
- set_wait(0);
- return;
- }
-
- if ((dec->physaddr & 0x180000)==0x180000)
- {
- dec->function = MPGSRAM;
- set_wait(0);
- return;
- }
-
- // Route everything else to the P-Box
- // 0x000000-0x07ffff for the stock Geneve (AMC,AMB,AMA,A0 ...,A15)
- // 0x000000-0x1fffff for the GenMod.(AME,AMD,AMC,AMB,AMA,A0 ...,A15)
- // Add a wait state
- set_wait(1);
- dec->function = MPGBOX;
-
- dec->physaddr = (dec->physaddr & 0x0007ffff); // 19 bit address (with AMA..AMC)
- m_peribox->memen_in(ASSERT_LINE);
- m_peribox->setaddress_dbin(space, dec->physaddr, read_mode);
- return;
- }
- else
- {
- // GenMod mode
- if ((m_timode) && ((dec->physaddr & 0x180000)==0x000000))
- {
- // DRAM. One wait state.
- dec->function = MPGMDRAM;
- dec->physaddr = dec->physaddr & 0x07ffff;
- if (!m_turbo) set_wait(1);
- return;
- }
-
- if ((dec->physaddr & 0x1e0000)==0x1e0000)
- {
- // 1 111. ..xx xxxx xxxx xxxx on-board eprom (16K)
- // mirrored for f0, f2, f4, ...; f1, f3, f5, ... unless using PFM
- dec->function = MPGMEPROM;
- set_wait(0);
- return;
- }
-
- // Route everything else to the P-Box
- dec->physaddr = (dec->physaddr & 0x001fffff); // 21 bit address for Genmod
- dec->function = MPGMBOX;
+ i++;
+ }
+ if (i != 7)
+ {
+ LOGMASKED(LOG_DECODE, "Decoded as %s: %04x\n", m_logmap[i].description, dec->offset);
+ dec->function = m_logmap[i].function;
+ }
+}
- if (!m_turbo) set_wait(1);
- // Check: Are waitstates completely turned off for turbo mode, or
- // merely the waitstates for DRAM memory access and box access?
+void geneve_mapper_device::map_address(bool reading, geneve_mapper_device::decdata* dec)
+{
+ int logpage = (dec->offset & 0xe000) >> 13;
+ int physpage = 0;
- m_peribox->memen_in(ASSERT_LINE);
- m_peribox->setaddress_dbin(space, dec->physaddr, read_mode);
- return;
- }
- }
+ // Determine physical address
+ if (m_direct_mode) physpage = 0xf8; // points to boot eprom
else
- { // Write access
- // Logical addresses
- if (m_geneve_mode)
- {
- if ((offset & 0xfff1)==0xf100)
- {
- // 1 WS is always added; any pending video waitstates are canceled
- dec->function = MLGVIDEO;
- set_wait(1);
- return;
- }
- if ((offset & 0xfff8)==0xf110)
- {
- dec->function = MLGMAPPER;
- dec->offset = dec->offset & 0x0007;
- set_wait(1);
- return;
- }
- if ((offset & 0xfff1)==0xf120)
- {
- // Add 24 waitstates. This is an average value, as the
- // waitstate generation seems to depend on an external timer of
- // the sound chip
- // TODO: do it properly with the use of READY
- dec->function = MLGSOUND;
- set_wait(24);
- return;
- }
- if ((offset & 0xfff0)==0xf130)
- {
- dec->function = MLGCLOCK;
- dec->offset = dec->offset & 0x00f;
- set_wait(1);
- return;
- }
- }
- else
+ {
+ // TI mode, accessing logical addresses 6000-7fff
+ if (!m_geneve_mode && logpage==3)
{
- // TI mode
- if ((offset & 0xfff8)==0x8000)
- {
- dec->function = MLTMAPPER;
- dec->offset = dec->offset & 0x0007;
- set_wait(1);
- return;
- }
- if ((offset & 0xfff0)==0x8010)
- {
- dec->function = MLTCLOCK;
- dec->offset = dec->offset & 0x00f;
- set_wait(1);
- return;
- }
- if ((offset & 0xfc01)==0x9c00)
- {
- dec->function = MLTGROM;
- set_wait(1);
- return;
- }
- if ((offset & 0xfc01)==0x8400)
- {
- // Add 24 waitstates. This is an approximation, as the
- // waitstate generation seems to depend on an external timer of
- // the sound chip
- // TODO: do it properly with the use of READY-
- dec->function = MLTSOUND;
- set_wait(24);
- return;
- }
- if ((offset & 0xfc01)==0x8c00)
+ if (reading)
{
- // 1 WS is always added; any pending video waitstates are canceled
- dec->function = MLTVIDEO;
- set_wait(1);
- return;
+ physpage = (m_cartridge_size==0x4000 && m_cartridge_secondpage)? 0x37 : 0x36;
}
-
- if ((offset & 0xfc01)==0x9400)
- {
- dec->function = MLTSPEECH;
- dec->offset = dec->offset | ((m_genmod)? 0x170000 : 0x070000);
- m_peribox->memen_in(ASSERT_LINE);
- m_peribox->setaddress_dbin(space, dec->offset, read_mode);
- set_wait(1);
- return;
- }
- }
-
- // Determine physical address
- page = (dec->offset & 0xe000) >> 13;
-
- if (m_direct_mode)
- {
- dec->physaddr = 0x1e0000; // points to boot eprom
- }
- else
- {
- if (!m_geneve_mode && page==3)
+ else
{
+ // Emulate the cartridge bank switch feature of Extended Basic
+ // TODO: Is this the right place? Or writem()?
if (m_cartridge_size==0x4000)
{
m_cartridge_secondpage = ((dec->offset & 0x0002)!=0);
LOGMASKED(LOG_WRITE, "Set cartridge page %02x\n", m_cartridge_secondpage);
- set_wait(1);
- return;
}
else
{
- // writing into cartridge rom space (no bankswitching)
+ // writing into cartridge rom space (no bank switching)
if ((((dec->offset & 0x1000)==0x0000) && !m_cartridge6_writable)
|| (((dec->offset & 0x1000)==0x1000) && !m_cartridge7_writable))
{
LOGMASKED(LOG_WARN, "Writing to protected cartridge space %04x ignored\n", dec->offset);
- return;
}
else
// TODO: Check whether secondpage is really ignored
- dec->physaddr = 0x06c000;
+ physpage = 0x36;
}
}
- else
- dec->physaddr = (m_map[page] << 13);
- }
-
- dec->physaddr |= dec->offset & 0x1fff;
-
- if (!m_genmod)
- {
- if ((dec->physaddr & 0x180000)==0x000000)
- {
- dec->function = MPGDRAM;
- dec->physaddr = dec->physaddr & 0x07ffff;
- set_wait(1);
- return;
- }
- if ((dec->physaddr & 0x180000)==0x080000)
- {
- dec->function = MPGEXP;
- set_wait(1);
- return;
- }
-
- if ((dec->physaddr & 0x1e0000)==0x1e0000)
- {
- dec->function = MPGEPROM;
- set_wait(0); // EPROM
- return;
- }
- if ((dec->physaddr & 0x180000)==0x180000)
- {
- dec->function = MPGSRAM;
- set_wait(0); // SRAM
- return;
- }
-
- // Route everything else to the P-Box
- // Add a wait state
-
- // only AMA, AMB, AMC are used; AMD and AME are not used
- dec->function = MPGBOX;
- dec->physaddr = (dec->physaddr & 0x0007ffff); // 19 bit address
- m_peribox->memen_in(ASSERT_LINE);
- m_peribox->setaddress_dbin(space, dec->physaddr, read_mode);
- set_wait(1);
}
else
- {
- // GenMod mode
- if ((dec->physaddr & 0x1e0000)==0x1e0000)
- { // EPROM, ignore (unless PFM)
- dec->function = MPGMEPROM;
- set_wait(0);
- return;
- }
+ physpage = m_map[logpage];
+ }
+ dec->physaddr = ((physpage << 13) | (dec->offset & 0x1fff)) & 0x1fffff;
+}
- if (m_timode && ((dec->physaddr & 0x180000)==0x000000))
- {
- dec->function = MPGMDRAM;
- dec->physaddr = dec->physaddr & 0x07ffff;
- if (!m_turbo) set_wait(1);
- return;
- }
+void geneve_mapper_device::decode_physical(geneve_mapper_device::decdata* dec)
+{
+ dec->function = MUNDEF;
- // Route everything else to the P-Box
- dec->function = MPGMBOX;
- dec->physaddr = (dec->physaddr & 0x001fffff); // 21 bit address for Genmod
- m_peribox->memen_in(ASSERT_LINE);
- m_peribox->setaddress_dbin(space, dec->physaddr, read_mode);
- if (!m_turbo) set_wait(1);
- }
+ int i = 0;
+ while (i < 4)
+ {
+ if ((dec->physaddr & ~m_physmap[i].mask) == m_physmap[i].base)
+ break;
+ i++;
+ }
+ if (i != 4)
+ {
+ LOGMASKED(LOG_DECODE, "Decoded as %s: %06x\n", m_physmap[i].description, dec->physaddr);
+ dec->function = m_physmap[i].function;
+ dec->wait = m_physmap[i].wait;
}
+ else
+ {
+ // Route everything else to the P-Box
+ dec->function = MBOX;
+ dec->wait = 1;
+ }
+}
+
+void genmod_mapper_device::decode_mod(geneve_mapper_device::decdata* dec)
+{
+ // GenMod mode
+ // The TI Mode switch activates the DRAM on the board (1 WS)
+ // for the first 512K (000000-07ffff)
+ if (((dec->function == MPDRAM) && !m_gm_timode) || dec->function==MPSRAM || dec->function==MPEXP)
+ {
+ dec->function = MBOX;
+ }
+
+ if ((dec->function != MPDRAM) && m_turbo)
+ dec->wait = 0;
}
/*
- Read from PFM.
+ Boot ROM handling, from EPROM or PFM.
*/
-READ8_MEMBER( geneve_mapper_device::read_from_pfm )
+READ8_MEMBER( geneve_mapper_device::boot_rom )
{
uint8_t value;
- if (!m_pfm_output_enable) return 0;
+ int pfmaddress = (offset & 0x01ffff) | (m_pfm_bank<<17);
- int address = (offset & 0x01ffff) | (m_pfm_bank<<17);
-
- switch (m_pfm_mode)
+ switch (m_boot_rom)
{
- case 1:
- value = m_pfm512->read(space, address, mem_mask);
+ case GENEVE_EPROM:
+ value = m_eprom[offset & 0x003fff];
+ LOGMASKED(LOG_READ, "Read EPROM %04x -> %02x\n", offset & 0x003fff, value);
+ return value;
+ case GENEVE_PFM512:
+ value = m_pfm512->read(space, pfmaddress, mem_mask);
break;
- case 2:
- value = m_pfm512a->read(space, address, mem_mask);
+ case GENEVE_PFM512A:
+ value = m_pfm512a->read(space, pfmaddress, mem_mask);
break;
default:
- LOGMASKED(LOG_WARN, "Illegal mode for reading PFM: %d\n", m_pfm_mode);
- return 0;
+ LOGMASKED(LOG_WARN, "Illegal mode for reading boot ROM: %d\n", m_boot_rom);
+ value = 0;
}
- LOGMASKED(LOG_PFM, "Reading from PFM at address %05x -> %02x\n", address, value);
+ if (!m_pfm_output_enable) value = 0;
+ LOGMASKED(LOG_PFM, "Reading from PFM at address %05x -> %02x\n", pfmaddress, value);
return value;
}
@@ -1288,16 +888,16 @@ WRITE8_MEMBER( geneve_mapper_device::write_to_pfm )
int address = (offset & 0x01ffff) | (m_pfm_bank<<17);
LOGMASKED(LOG_PFM, "Writing to PFM at address %05x <- %02x\n", address, data);
- switch (m_pfm_mode)
+ switch (m_boot_rom)
{
- case 1:
+ case GENEVE_PFM512:
m_pfm512->write(space, address, data, mem_mask);
break;
- case 2:
+ case GENEVE_PFM512A:
m_pfm512a->write(space, address, data, mem_mask);
break;
default:
- LOGMASKED(LOG_WARN, "Illegal mode for writing to PFM: %d\n", m_pfm_mode);
+ LOGMASKED(LOG_WARN, "Illegal mode for writing to PFM: %d\n", m_boot_rom);
}
}
@@ -1311,7 +911,23 @@ SETOFFSET_MEMBER( geneve_mapper_device::setoffset )
{
LOGMASKED(LOG_DETAIL, "setoffset = %04x\n", offset);
m_debug_no_ws = false;
- decode(space, offset, m_read_mode, &m_decoded);
+ m_decoded.offset = offset;
+
+ decode_logical(m_read_mode, &m_decoded);
+ if (m_decoded.function == MUNDEF)
+ {
+ map_address(m_read_mode, &m_decoded);
+ decode_physical(&m_decoded);
+ decode_mod(&m_decoded);
+ }
+
+ set_wait(m_decoded.wait);
+
+ if (m_decoded.function == MBOX)
+ {
+ m_peribox->memen_in(ASSERT_LINE);
+ m_peribox->setaddress_dbin(space, m_decoded.physaddr, m_read_mode);
+ }
}
/*
@@ -1349,10 +965,10 @@ WRITE_LINE_MEMBER( geneve_mapper_device::clock_in )
}
else
{
- if (m_ext_waitcount > 0)
+ if (m_video_waitcount > 0)
{
- m_ext_waitcount--;
- if (m_ext_waitcount == 0)
+ m_video_waitcount--;
+ if (m_video_waitcount == 0)
{
LOGMASKED(LOG_CLOCK, "clock, READY asserted after video\n");
m_ready(ASSERT_LINE);
@@ -1360,7 +976,7 @@ WRITE_LINE_MEMBER( geneve_mapper_device::clock_in )
}
else
{
- LOGMASKED(LOG_CLOCK, "vclock, ew=%d\n", m_ext_waitcount);
+ LOGMASKED(LOG_CLOCK, "vclock, ew=%d\n", m_video_waitcount);
}
}
}
@@ -1370,7 +986,7 @@ WRITE_LINE_MEMBER( geneve_mapper_device::clock_in )
{
// Falling edge
// 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 ((m_waitcount == 0) && (m_video_waitcount > 0) && m_ready_asserted)
{
LOGMASKED(LOG_CLOCK, "clock, READY cleared for video\n");
m_ready(CLEAR_LINE);
@@ -1442,25 +1058,22 @@ void geneve_mapper_device::device_start()
save_item(NAME(m_decoded.function));
save_item(NAME(m_decoded.offset));
save_item(NAME(m_decoded.physaddr));
- save_item(NAME(m_turbo));
- save_item(NAME(m_genmod));
- save_item(NAME(m_timode));
- save_item(NAME(m_pfm_mode));
+ save_item(NAME(m_boot_rom));
save_item(NAME(m_pfm_bank));
save_item(NAME(m_pfm_output_enable));
save_item(NAME(m_sram_mask));
save_item(NAME(m_sram_val));
save_item(NAME(m_waitcount));
- save_item(NAME(m_ext_waitcount));
+ save_item(NAME(m_video_waitcount));
}
-void geneve_mapper_device::device_reset()
+void geneve_mapper_device::common_reset()
{
m_extra_waitstates = false;
m_video_waitstates = true;
m_read_mode = false;
m_waitcount = 0;
- m_ext_waitcount = 0;
+ m_video_waitcount = 0;
m_ready_asserted = true;
m_geneve_mode =false;
@@ -1476,25 +1089,22 @@ void geneve_mapper_device::device_reset()
// Clear map
for (auto & elem : m_map) elem = 0;
- m_genmod = false;
-
// Check which boot EPROM we are using (or PFM)
- set_boot_rom(machine().root_device().ioport("BOOTROM")->read());
+ m_boot_rom = machine().root_device().ioport("BOOTROM")->read();
+ m_eprom = machine().root_device().memregion("maincpu")->base();
- // Check for GenMod. We assume that GenMod can be combined with PFM.
- if (machine().root_device().ioport("MODE")->read()!=0)
- {
- LOGMASKED(LOG_SETTING, "Using GenMod modification\n");
- m_eprom = machine().root_device().memregion("maincpu")->base() + 0x8000;
- if (m_eprom[0] != 0xf0)
- {
- fatalerror("genboard: GenMod boot ROM missing\n");
- }
- m_genmod = true;
- m_turbo = ((machine().root_device().ioport("GENMODDIPS")->read() & GENEVE_GM_TURBO)!=0);
- m_timode = ((machine().root_device().ioport("GENMODDIPS")->read() & GENEVE_GM_TIM)!=0);
- }
+ // Allow for configuring the VRAM size
+ uint32_t videoram = (machine().root_device().ioport("VRAM")->read()!=0)? 0x30000 : 0x20000;
+ downcast<v99x8_device &>(*m_video.target()).set_vram_size(videoram);
+ LOGMASKED(LOG_SETTING, "Video RAM set to %d KiB\n", videoram / 1024);
+}
+
+void geneve_mapper_device::device_reset()
+{
+ common_reset();
+ // SRAM is only separately handled for the standard Geneve; Genmod uses
+ // the Memex instead
switch (machine().root_device().ioport("SRAM")->read())
{
/* 1 100. .... .... .... .... on-board sram (128K) -+
@@ -1516,15 +1126,35 @@ void geneve_mapper_device::device_reset()
m_sram_val = 0x180000;
break;
}
+}
- // Allow for configuring the VRAM size
- uint32_t videoram = (machine().root_device().ioport("VRAM")->read()!=0)? 0x30000 : 0x20000;
- downcast<v99x8_device &>(*m_video.target()).set_vram_size(videoram);
- LOGMASKED(LOG_SETTING, "Video RAM set to %d KiB\n", videoram / 1024);
+void genmod_mapper_device::device_reset()
+{
+ common_reset();
+ LOGMASKED(LOG_SETTING, "Using GenMod modification\n");
+ m_turbo = ((machine().root_device().ioport("GENMODDIPS")->read() & GENEVE_GM_TURBO)!=0);
+ m_gm_timode = ((machine().root_device().ioport("GENMODDIPS")->read() & GENEVE_GM_TIM)!=0);
}
/****************************************************************************
Keyboard support
+
+ The XT keyboard interface is described in various places on the internet,
+ like (http://www-2.cs.cmu.edu/afs/cs/usr/jmcm/www/info/key2.txt). It is a
+ synchronous unidirectional serial interface: the data line is driven by the
+ keyboard to send data to the CPU; the CTS/clock line has a pull up resistor
+ and can be driven low by both keyboard and CPU. To send data to the CPU,
+ the keyboard pulses the clock line low 9 times, and the Geneve samples all
+ 8 bits of data (plus one start bit) on each falling edge of the clock.
+ When the key code buffer is full, the Geneve gate array asserts the kbdint*
+ line (connected to 9901 int8_t*). The Geneve gate array will hold the
+ CTS/clock line low as long as the keyboard buffer is full or CRU bit @>F78
+ is 0. Writing a 0 to >F79 will clear the Geneve keyboard buffer, and
+ writing a 1 will resume normal operation: you need to write a 0 to >F78
+ before clearing >F79, or the keyboard will be enabled to send data the gate
+ array when >F79 is is set to 0, and any such incoming data from the
+ keyboard will be cleared as soon as it is buffered by the gate array.
+
****************************************************************************/
static const uint8_t MF1_CODE[0xe] =
diff --git a/src/devices/bus/ti99/internal/genboard.h b/src/devices/bus/ti99/internal/genboard.h
index 26e6766adef..baac4db69de 100644
--- a/src/devices/bus/ti99/internal/genboard.h
+++ b/src/devices/bus/ti99/internal/genboard.h
@@ -32,8 +32,7 @@ enum
enum
{
- GENEVE_098 = 0,
- GENEVE_100,
+ GENEVE_EPROM = 0,
GENEVE_PFM512,
GENEVE_PFM512A
};
@@ -117,6 +116,7 @@ class geneve_mapper_device : public device_t
{
public:
geneve_mapper_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
void set_geneve_mode(bool geneve);
void set_direct_mode(bool direct);
void set_cartridge_size(int size);
@@ -141,10 +141,11 @@ public:
template <class Object> devcb_base &set_ready_callback(Object &&cb) { return m_ready.set_callback(std::forward<Object>(cb)); }
protected:
+ geneve_mapper_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
void device_start() override;
- void device_reset() override;
+ virtual void device_reset() override;
+ void common_reset();
-private:
// GROM simulation
bool m_gromwaddr_LSB;
bool m_gromraddr_LSB;
@@ -153,24 +154,15 @@ private:
DECLARE_WRITE8_MEMBER( write_grom );
// wait states
- void set_wait(int min);
- void set_ext_wait(int min);
- bool m_video_waitstates;
- bool m_extra_waitstates;
- bool m_ready_asserted;
-
- bool m_read_mode;
+ void set_wait(int min);
+ void set_video_waitcount(int min);
+ bool m_video_waitstates;
+ bool m_extra_waitstates;
+ bool m_ready_asserted;
- bool m_debug_no_ws;
-
- // Mapper function
- typedef struct
- {
- int function;
- offs_t offset;
- offs_t physaddr;
- } decdata;
+ bool m_read_mode;
+ bool m_debug_no_ws;
bool m_geneve_mode;
bool m_direct_mode;
int m_cartridge_size;
@@ -179,22 +171,102 @@ private:
bool m_cartridge7_writable;
int m_map[8];
- void decode(address_space& space, offs_t offset, bool read_mode, decdata* dec);
+ /*
+ Constants for mapper decoding. Naming scheme:
+ M=Mapper, L=Logical space; P=Physical space
+ */
+ typedef enum
+ {
+ MUNDEF=0,
+
+ MLVIDEO,
+ MLMAPPER,
+ MLKEY,
+ MLSOUND,
+ MLCLOCK,
+ MLGROM,
+
+ MPDRAM,
+ MPEXP,
+ MPEPROM,
+ MPSRAM,
+
+ MBOX
+ } decfunct_t;
+
+ // Mapper function
+ typedef struct
+ {
+ int function; // must be a fundamental type to be saveable
+ offs_t offset; // Logical address
+ offs_t physaddr; // Physical address
+ int wait; // Wait states
+ } decdata;
+
+ // The result of decoding
decdata m_decoded;
- // Genmod modifications
- bool m_turbo;
- bool m_genmod;
- bool m_timode;
+ // Static decoder entry for the logical space
+ // Not all entries apply for native mode, e.g. there is no GROM in native
+ // mode. In that case the base and mask are 0000, and the entry must be
+ // skipped. Speech is accessible in the physical space in native mode.
+ // All entries have a wait state count of 1.
+ typedef struct
+ {
+ offs_t genbase; // Base address in native mode
+ int genmask; // Bits that also match this entry
+ offs_t tibase; // Base address in TI mode
+ int timask; // Bits that also match this entry
+ int writeoff; // Additional offset in TI mode for writing
+ decfunct_t function; // Decoded function
+ const char* description; // Good for logging
+ } logentry_t;
+
+ logentry_t m_logmap[7] =
+ {
+ { 0xf100, 0x000e, 0x8800, 0x03fe, 0x0400, MLVIDEO, "video" },
+ { 0xf110, 0x0007, 0x8000, 0x0007, 0x0000, MLMAPPER, "mapper" },
+ { 0xf118, 0x0007, 0x8008, 0x0007, 0x0000, MLKEY, "keyboard" },
+ { 0xf120, 0x000e, 0x8400, 0x03fe, 0x0000, MLSOUND, "sound" },
+ { 0xf130, 0x000f, 0x8010, 0x000f, 0x0000, MLCLOCK, "clock" },
+ { 0x0000, 0x0000, 0x9000, 0x03fe, 0x0400, MBOX, "speech (in P-Box)" },
+ { 0x0000, 0x0000, 0x9800, 0x03fe, 0x0400, MLGROM, "GROM" },
+ };
+
+ // Static decoder entry for the physical space
+ // There are no differences between native mode and TI mode.
+ typedef struct
+ {
+ offs_t base; // Base address
+ int mask; // Bits that also match this entry
+ decfunct_t function; // Decoded function
+ int wait; // Wait states
+ const char* description; // Good for logging
+ } physentry_t;
+
+ physentry_t m_physmap[4] =
+ {
+ { 0x000000, 0x07ffff, MPDRAM, 1, "DRAM" },
+ { 0x080000, 0x07ffff, MPEXP, 1, "on-board expansion" },
+ { 0x1e0000, 0x01ffff, MPEPROM, 0, "EPROM" },
+ { 0x180000, 0x07ffff, MPSRAM, 0, "SRAM" }
+ };
+
+ void decode_logical(bool reading, decdata* dec);
+ void map_address(bool reading, decdata* dec);
+ void decode_physical(decdata* dec);
+ // This is the hook for Genmod. The normal Geneve just does nothing here.
+ virtual void decode_mod(decdata* dec) { };
// PFM mod (0 = none, 1 = AT29C040, 2 = AT29C040A)
- DECLARE_READ8_MEMBER( read_from_pfm );
+ DECLARE_READ8_MEMBER( boot_rom );
DECLARE_WRITE8_MEMBER( write_to_pfm );
- void set_boot_rom(int selection);
- int m_pfm_mode;
+ int m_boot_rom;
int m_pfm_bank;
bool m_pfm_output_enable;
+ int m_pbox_prefix;
+
// SRAM access
int m_sram_mask;
int m_sram_val;
@@ -204,7 +276,7 @@ private:
// Counter for the wait states.
int m_waitcount;
- int m_ext_waitcount;
+ int m_video_waitcount;
// Devices
required_device<mm58274c_device> m_clock;
@@ -221,6 +293,20 @@ private:
required_device<ram_device> m_dram;
};
+class genmod_mapper_device : public geneve_mapper_device
+{
+public:
+ genmod_mapper_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ void decode_mod(decdata* dec) override;
+ void device_reset() override;
+ DECLARE_INPUT_CHANGED_MEMBER( setgm_changed );
+
+private:
+ // Genmod modifications
+ bool m_gm_timode;
+ bool m_turbo;
+};
+
#define MCFG_GENEVE_READY_HANDLER( _intcallb ) \
devcb = &downcast<bus::ti99::internal::geneve_mapper_device &>(*device).set_ready_callback(DEVCB_##_intcallb);
@@ -228,5 +314,6 @@ private:
DECLARE_DEVICE_TYPE_NS(GENEVE_KEYBOARD, bus::ti99::internal, geneve_keyboard_device)
DECLARE_DEVICE_TYPE_NS(GENEVE_MAPPER, bus::ti99::internal, geneve_mapper_device)
+DECLARE_DEVICE_TYPE_NS(GENMOD_MAPPER, bus::ti99::internal, genmod_mapper_device)
#endif // MAME_BUS_TI99_INTERNAL_GENBOARD_H
diff --git a/src/devices/bus/ti99/peb/peribox.cpp b/src/devices/bus/ti99/peb/peribox.cpp
index 1ada6e9a75f..6e81dc6886b 100644
--- a/src/devices/bus/ti99/peb/peribox.cpp
+++ b/src/devices/bus/ti99/peb/peribox.cpp
@@ -208,6 +208,9 @@ DEFINE_DEVICE_TYPE_NS(TI99_PERIBOX_SG, bus::ti99::peb, peribox_sg_device, "p
// Peripheral box which hosts the Geneve 9640 in slot 1
DEFINE_DEVICE_TYPE_NS(TI99_PERIBOX_GEN, bus::ti99::peb, peribox_gen_device, "peribox_gen", "Peripheral expansion box Geneve")
+// Peripheral box which hosts the Geneve 9640 in slot 1 with Genmod
+DEFINE_DEVICE_TYPE_NS(TI99_PERIBOX_GENMOD, bus::ti99::peb, peribox_genmod_device, "peribox_genmod", "Peripheral expansion box Genmod")
+
// Single slot of the PEB
DEFINE_DEVICE_TYPE_NS(TI99_PERIBOX_SLOT, bus::ti99::peb, peribox_slot_device, "peribox_slot", "TI P-Box slot")
@@ -251,6 +254,7 @@ peribox_device::peribox_device(const machine_config &mconfig, const char *tag, d
// The address prefix is actually created by the "Flex cable interface"
// which sits in slot 1.
m_address_prefix = 0x70000;
+ m_genmod = false;
}
/*
@@ -364,23 +368,6 @@ WRITE_LINE_MEMBER(peribox_device::clock_in)
}
/*
- The Genmod modification is only of interest for the Geneve. It requires
- to modify the decoding of each single card.
-*/
-INPUT_CHANGED_MEMBER( peribox_device::genmod_changed )
-{
- set_genmod(newval==1);
-}
-
-void peribox_device::set_genmod(bool set)
-{
- for (int i=2; i <= 8; i++)
- {
- if (m_slot[i]!=nullptr) m_slot[i]->set_genmod(set);
- }
-}
-
-/*
The INTA*, INTB*, and READY* lines are connected to each PEB card and are
pulled up when inactive. If any card asserts the line (pulling down), the
line state goes down. So we must keep a record which cards pull down the
@@ -449,6 +436,8 @@ void peribox_device::ready_join(int slot, int state)
void peribox_device::set_slot_loaded(int slot, peribox_slot_device* slotdev)
{
m_slot[slot] = slotdev;
+ if (slotdev != nullptr)
+ slotdev->set_genmod(m_genmod);
}
void peribox_device::device_start()
@@ -521,6 +510,7 @@ peribox_ev_device::peribox_ev_device(const machine_config &mconfig, const char *
: peribox_device(mconfig, TI99_PERIBOX_EV, tag, owner, clock)
{
m_address_prefix = 0x70000;
+ m_genmod = false;
}
void peribox_slotv(device_slot_interface &device)
@@ -555,8 +545,8 @@ MACHINE_CONFIG_END
A variant of the box used for the Geneve.
*****************************************************************************/
-peribox_gen_device::peribox_gen_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : peribox_device(mconfig, TI99_PERIBOX_GEN, tag, owner, clock)
+peribox_gen_device::peribox_gen_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock):
+ peribox_device(mconfig, type, tag, owner, clock)
{
// The Geneve sits in slot 1; there is no prefix here - it can control
// a maximum address space of 512 KiB in the box. With the Genmod
@@ -564,6 +554,18 @@ peribox_gen_device::peribox_gen_device(const machine_config &mconfig, const char
m_address_prefix = 0x00000;
}
+peribox_gen_device::peribox_gen_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : peribox_gen_device(mconfig, TI99_PERIBOX_GEN, tag, owner, clock)
+{
+ m_genmod = false;
+}
+
+peribox_genmod_device::peribox_genmod_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : peribox_gen_device(mconfig, TI99_PERIBOX_GENMOD, tag, owner, clock)
+{
+ m_genmod = true;
+}
+
// The BwG controller will not run with the Geneve due to its wait state
// logic (see bwg.c)
@@ -589,6 +591,16 @@ MACHINE_CONFIG_START(peribox_gen_device::device_add_mconfig)
MCFG_PERIBOX_SLOT_ADD( PEBSLOT8, peribox_slotg )
MACHINE_CONFIG_END
+MACHINE_CONFIG_START(peribox_genmod_device::device_add_mconfig)
+ MCFG_PERIBOX_SLOT_ADD_DEF( PEBSLOT2, peribox_slotg, "memex" )
+ MCFG_PERIBOX_SLOT_ADD( PEBSLOT3, peribox_slotv )
+ MCFG_PERIBOX_SLOT_ADD( PEBSLOT4, peribox_slotv )
+ MCFG_PERIBOX_SLOT_ADD( PEBSLOT5, peribox_slotv )
+ MCFG_PERIBOX_SLOT_ADD( PEBSLOT6, peribox_slotv )
+ MCFG_PERIBOX_SLOT_ADD( PEBSLOT7, peribox_slotv )
+ MCFG_PERIBOX_SLOT_ADD( PEBSLOT8, peribox_slotv )
+MACHINE_CONFIG_END
+
/****************************************************************************
A variant of the box used for the SGCPU (aka TI-99/4P).
*****************************************************************************/
@@ -597,6 +609,7 @@ peribox_sg_device::peribox_sg_device(const machine_config &mconfig, const char *
: peribox_device(mconfig, TI99_PERIBOX_SG, tag, owner, clock)
{
m_address_prefix = 0x70000;
+ m_genmod = false;
}
void peribox_slotp(device_slot_interface &device)
diff --git a/src/devices/bus/ti99/peb/peribox.h b/src/devices/bus/ti99/peb/peribox.h
index 00be0795d10..71ad9eb589b 100644
--- a/src/devices/bus/ti99/peb/peribox.h
+++ b/src/devices/bus/ti99/peb/peribox.h
@@ -58,10 +58,6 @@ public:
// Part of configuration
void set_prefix(int prefix) { m_address_prefix = prefix; }
- // Genmod support
- DECLARE_INPUT_CHANGED_MEMBER( genmod_changed );
- void set_genmod(bool set);
-
protected:
peribox_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
@@ -102,6 +98,9 @@ protected:
// Configured as a slot device (of the ioport)
bool m_ioport_connected;
+
+ // Used for Genmod
+ bool m_genmod;
};
/************************************************************************
@@ -139,12 +138,25 @@ protected:
class peribox_gen_device : public peribox_device
{
public:
+ peribox_gen_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
peribox_gen_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
virtual void device_add_mconfig(machine_config &config) override;
};
+/*
+ Variation for Geneve with Genmod
+*/
+class peribox_genmod_device : public peribox_gen_device
+{
+public:
+ peribox_genmod_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ void device_add_mconfig(machine_config &config) override;
+};
+
/*****************************************************************************
The parent class for all expansion cards.
******************************************************************************/
@@ -256,5 +268,6 @@ DECLARE_DEVICE_TYPE_NS(TI99_PERIBOX_EV, bus::ti99::peb, peribox_ev_device)
DECLARE_DEVICE_TYPE_NS(TI99_PERIBOX_SLOT, bus::ti99::peb, peribox_slot_device)
DECLARE_DEVICE_TYPE_NS(TI99_PERIBOX_SG, bus::ti99::peb, peribox_sg_device)
DECLARE_DEVICE_TYPE_NS(TI99_PERIBOX_GEN, bus::ti99::peb, peribox_gen_device)
+DECLARE_DEVICE_TYPE_NS(TI99_PERIBOX_GENMOD, bus::ti99::peb, peribox_genmod_device)
#endif // MAME_BUS_TI99_PEB_PERIBOX_H
diff --git a/src/mame/drivers/geneve.cpp b/src/mame/drivers/geneve.cpp
index 8d8ded314bd..ce0285bdd7c 100644
--- a/src/mame/drivers/geneve.cpp
+++ b/src/mame/drivers/geneve.cpp
@@ -178,25 +178,6 @@
Bit 14: 0 = protect cartridge range >7000->7fff
bit 15: 1 = add 1 extra wait state when accessing 0-wait-state SRAM???
-
- Keyboard interface:
-
- The XT keyboard interface is described in various places on the internet,
- like (http://www-2.cs.cmu.edu/afs/cs/usr/jmcm/www/info/key2.txt). It is a
- synchronous unidirectional serial interface: the data line is driven by the
- keyboard to send data to the CPU; the CTS/clock line has a pull up resistor
- and can be driven low by both keyboard and CPU. To send data to the CPU,
- the keyboard pulses the clock line low 9 times, and the Geneve samples all
- 8 bits of data (plus one start bit) on each falling edge of the clock.
- When the key code buffer is full, the Geneve gate array asserts the kbdint*
- line (connected to 9901 int8_t*). The Geneve gate array will hold the
- CTS/clock line low as long as the keyboard buffer is full or CRU bit @>F78
- is 0. Writing a 0 to >F79 will clear the Geneve keyboard buffer, and
- writing a 1 will resume normal operation: you need to write a 0 to >F78
- before clearing >F79, or the keyboard will be enabled to send data the gate
- array when >F79 is is set to 0, and any such incoming data from the
- keyboard will be cleared as soon as it is buffered by the gate array.
-
Original version 2003 by Raphael Nabet
Rewritten 2012 by Michael Zapf
@@ -216,11 +197,15 @@
#include "speaker.h"
-#define TRACE_READY 0
-#define TRACE_LINES 0
-#define TRACE_CRU 0
+#define LOG_WARN (1U<<1)
+#define LOG_READY (1U<<2)
+#define LOG_LINES (1U<<3)
+#define LOG_CRU (1U<<4)
-#define GENMOD 0x01
+// Minimum log should be settings and warnings
+#define VERBOSE (LOG_GENERAL | LOG_WARN)
+
+#include "logmacro.h"
class geneve_state : public driver_device
{
@@ -285,7 +270,10 @@ public:
int m_ready_line;
int m_ready_line1;
- void geneve_60hz(machine_config &config);
+ void geneve_common(machine_config &config);
+ void geneve(machine_config &config);
+ void genmod(machine_config &config);
+
void crumap(address_map &map);
void memmap(address_map &map);
};
@@ -316,42 +304,46 @@ void geneve_state::crumap(address_map &map)
map(0x0000, 0x001f).w(m_tms9901, FUNC(tms9901_device::write));
}
-/* TI joysticks. The keyboard is implemented in genboard.c. */
-static INPUT_PORTS_START(geneve)
-
- PORT_START( "MODE" )
- PORT_CONFNAME( 0x01, 0x00, "Operating mode" ) PORT_CHANGED_MEMBER(TI_PERIBOX_TAG, bus::ti99::peb::peribox_device, genmod_changed, 0)
- PORT_CONFSETTING( 0x00, "Standard" )
- PORT_CONFSETTING( GENMOD, "GenMod" )
+static INPUT_PORTS_START(geneve_common)
PORT_START( "BOOTROM" )
- PORT_CONFNAME( 0x03, GENEVE_098, "Boot ROM" ) PORT_CHANGED_MEMBER(GENEVE_MAPPER_TAG, bus::ti99::internal::geneve_mapper_device, settings_changed, 3)
- PORT_CONFSETTING( GENEVE_098, "Version 0.98" )
- PORT_CONFSETTING( GENEVE_100, "Version 1.00" )
+ PORT_CONFNAME( 0x03, GENEVE_EPROM, "Boot from" ) PORT_CHANGED_MEMBER(GENEVE_MAPPER_TAG, bus::ti99::internal::geneve_mapper_device, settings_changed, 3)
+ PORT_CONFSETTING( GENEVE_EPROM, "EPROM" )
PORT_CONFSETTING( GENEVE_PFM512, "PFM 512" )
PORT_CONFSETTING( GENEVE_PFM512A, "PFM 512A" )
+ PORT_START( "VRAM" )
+ PORT_CONFNAME( 0x01, 0x00, "Video RAM" )
+ PORT_CONFSETTING( 0x00, "128 KiB" )
+ PORT_CONFSETTING( 0x01, "192 KiB" )
+
+INPUT_PORTS_END
+
+static INPUT_PORTS_START(geneve)
+ PORT_INCLUDE(geneve_common)
+
PORT_START( "SRAM" )
- PORT_CONFNAME( 0x03, 0x01, "Onboard SRAM" ) PORT_CONDITION( "MODE", 0x01, EQUALS, 0x00 )
+ PORT_CONFNAME( 0x03, 0x01, "Onboard SRAM" )
PORT_CONFSETTING( 0x00, "32 KiB" )
PORT_CONFSETTING( 0x01, "64 KiB" )
PORT_CONFSETTING( 0x02, "384 KiB" )
- PORT_START( "VRAM" )
- PORT_CONFNAME( 0x01, 0x00, "Video RAM" )
- PORT_CONFSETTING( 0x00, "128 KiB" )
- PORT_CONFSETTING( 0x01, "192 KiB" )
+INPUT_PORTS_END
+
+static INPUT_PORTS_START(genmod)
+ PORT_INCLUDE(geneve_common)
PORT_START( "GENMODDIPS" )
- PORT_DIPNAME( GENEVE_GM_TURBO, 0x00, "Genmod Turbo mode") PORT_CONDITION( "MODE", 0x01, EQUALS, GENMOD ) PORT_CHANGED_MEMBER(GENEVE_MAPPER_TAG, bus::ti99::internal::geneve_mapper_device, settings_changed, 1)
+ PORT_DIPNAME( GENEVE_GM_TURBO, 0x00, "Genmod Turbo mode") PORT_CHANGED_MEMBER(GENEVE_MAPPER_TAG, bus::ti99::internal::genmod_mapper_device, setgm_changed, 1)
PORT_CONFSETTING( 0x00, DEF_STR( Off ))
PORT_CONFSETTING( GENEVE_GM_TURBO, DEF_STR( On ))
- PORT_DIPNAME( GENEVE_GM_TIM, GENEVE_GM_TIM, "Genmod TI mode") PORT_CONDITION( "MODE", 0x01, EQUALS, GENMOD ) PORT_CHANGED_MEMBER(GENEVE_MAPPER_TAG, bus::ti99::internal::geneve_mapper_device, settings_changed, 2)
+ PORT_DIPNAME( GENEVE_GM_TIM, GENEVE_GM_TIM, "Genmod TI mode") PORT_CHANGED_MEMBER(GENEVE_MAPPER_TAG, bus::ti99::internal::genmod_mapper_device, setgm_changed, 2)
PORT_CONFSETTING( 0x00, DEF_STR( Off ))
PORT_CONFSETTING( GENEVE_GM_TIM, DEF_STR( On ))
INPUT_PORTS_END
+
/****************************************************************************
CRU handling
*****************************************************************************/
@@ -368,10 +360,11 @@ WRITE8_MEMBER ( geneve_state::cruwrite )
if ((addroff & 0xffc0) == CRU_SSTEP_BASE)
{
int bit = (addroff & 0x003e)>>1;
- logerror("Single step not implemented; bit %d set to %d\n", bit, data);
+ LOGMASKED(LOG_WARN, "Single step not implemented; bit %d set to %d\n", bit, data);
return;
}
+ // This is just mirroring the internal flags of the 9995
if ((addroff & 0xffe0) == CRU_CONTROL_BASE)
{
int bit = (addroff & 0x001e)>>1;
@@ -379,47 +372,47 @@ WRITE8_MEMBER ( geneve_state::cruwrite )
{
case 5:
// No one really cares...
- if (TRACE_CRU) logerror("Set PAL flag = %02x\n", data);
+ LOGMASKED(LOG_CRU, "Set PAL flag = %02x\n", data);
// m_palvideo = (data!=0);
break;
case 7:
// m_capslock = (data!=0);
- if (TRACE_CRU) logerror("Set capslock flag = %02x\n", data);
+ LOGMASKED(LOG_CRU, "Set capslock flag = %02x\n", data);
break;
case 8:
- if (TRACE_CRU) logerror("Set keyboard clock flag = %02x\n", data);
+ LOGMASKED(LOG_CRU, "Set keyboard clock flag = %02x\n", data);
m_keyboard->clock_control((data!=0)? ASSERT_LINE : CLEAR_LINE);
break;
case 9:
- if (TRACE_CRU) logerror("Set keyboard scan flag = %02x\n", data);
+ LOGMASKED(LOG_CRU, "Set keyboard scan flag = %02x\n", data);
m_keyboard->send_scancodes((data!=0)? ASSERT_LINE : CLEAR_LINE);
break;
case 10:
- if (TRACE_CRU) logerror("Geneve mode = %02x\n", data);
+ LOGMASKED(LOG_CRU, "Geneve mode = %02x\n", data);
m_mapper->set_geneve_mode(data!=0);
break;
case 11:
- if (TRACE_CRU) logerror("Direct mode = %02x\n", data);
+ LOGMASKED(LOG_CRU, "Direct mode = %02x\n", data);
m_mapper->set_direct_mode(data!=0);
break;
case 12:
- if (TRACE_CRU) logerror("Cartridge size 8K = %02x\n", data);
+ LOGMASKED(LOG_CRU, "Cartridge size 8K = %02x\n", data);
m_mapper->set_cartridge_size((data!=0)? 0x2000 : 0x4000);
break;
case 13:
- if (TRACE_CRU) logerror("Cartridge writable 6000 = %02x\n", data);
+ LOGMASKED(LOG_CRU, "Cartridge writable 6000 = %02x\n", data);
m_mapper->set_cartridge_writable(0x6000, (data!=0));
break;
case 14:
- if (TRACE_CRU) logerror("Cartridge writable 7000 = %02x\n", data);
+ LOGMASKED(LOG_CRU, "Cartridge writable 7000 = %02x\n", data);
m_mapper->set_cartridge_writable(0x7000, (data!=0));
break;
case 15:
- if (TRACE_CRU) logerror("Extra wait states = %02x\n", data==0);
+ LOGMASKED(LOG_CRU, "Extra wait states = %02x\n", data==0);
m_mapper->set_extra_waitstates(data==0); // let's use the inverse semantics
break;
default:
- logerror("set CRU address %04x=%02x ignored\n", addroff, data);
+ LOGMASKED(LOG_WARN, "set CRU address %04x=%02x ignored\n", addroff, data);
break;
}
}
@@ -439,7 +432,7 @@ READ8_MEMBER( geneve_state::cruread )
if ((addroff & 0xffc0) == CRU_SSTEP_BASE)
{
int bit = (addroff & 0x003e)>>1;
- logerror("Single step not implemented; attempting to read bit %d\n", bit);
+ LOGMASKED(LOG_WARN, "Single step not implemented; attempting to read bit %d\n", bit);
return value;
}
@@ -491,7 +484,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 (TRACE_LINES) logerror("INT15-8 = %02x\n", answer);
+ LOGMASKED(LOG_LINES, "INT15-8 = %02x\n", answer);
break;
case tms9901_device::P0_P7:
@@ -519,7 +512,7 @@ READ8_MEMBER( geneve_state::read_by_9901 )
*/
WRITE_LINE_MEMBER( geneve_state::peripheral_bus_reset )
{
- logerror("Peripheral bus reset request; not implemented yet.\n");
+ LOGMASKED(LOG_WARN, "Peripheral bus reset request; not implemented yet.\n");
}
/*
@@ -527,7 +520,7 @@ WRITE_LINE_MEMBER( geneve_state::peripheral_bus_reset )
*/
WRITE_LINE_MEMBER( geneve_state::VDP_reset )
{
- logerror("Video reset request; not implemented yet.\n");
+ LOGMASKED(LOG_WARN, "Video reset request; not implemented yet.\n");
}
/*
@@ -543,7 +536,7 @@ WRITE_LINE_MEMBER( geneve_state::joystick_select )
*/
WRITE_LINE_MEMBER( geneve_state::extbus_wait_states )
{
- logerror("External bus wait states set to %d, not implemented yet.\n", state);
+ LOGMASKED(LOG_WARN, "External bus wait states set to %d, not implemented yet.\n", state);
}
/*
@@ -552,7 +545,7 @@ WRITE_LINE_MEMBER( geneve_state::extbus_wait_states )
*/
WRITE_LINE_MEMBER( geneve_state::video_wait_states )
{
- if (TRACE_LINES) logerror("Video wait states set to %d\n", state);
+ LOGMASKED(LOG_LINES, "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;
}
@@ -594,14 +587,14 @@ WRITE_LINE_MEMBER( geneve_state::intb )
WRITE_LINE_MEMBER( geneve_state::ext_ready )
{
- if (TRACE_READY) logerror("READY level (ext) = %02x\n", state);
+ LOGMASKED(LOG_READY, "READY level (ext) = %02x\n", state);
m_ready_line = state;
m_cpu->ready_line((m_ready_line == ASSERT_LINE && m_ready_line1 == ASSERT_LINE)? ASSERT_LINE : CLEAR_LINE);
}
WRITE_LINE_MEMBER( geneve_state::mapper_ready )
{
- if (TRACE_READY) logerror("READY level (mapper) = %02x\n", state);
+ LOGMASKED(LOG_READY, "READY level (mapper) = %02x\n", state);
m_ready_line1 = state;
m_cpu->ready_line((m_ready_line == ASSERT_LINE && m_ready_line1 == ASSERT_LINE)? ASSERT_LINE : CLEAR_LINE);
}
@@ -636,7 +629,8 @@ WRITE_LINE_MEMBER( geneve_state::keyboard_interrupt )
WRITE8_MEMBER( geneve_state::external_operation )
{
static const char* extop[8] = { "inv1", "inv2", "IDLE", "RSET", "inv3", "CKON", "CKOF", "LREX" };
- if (offset != IDLE_OP) logerror("External operation %s not implemented on Geneve board\n", extop[offset]);
+ if (offset != IDLE_OP)
+ LOGMASKED(LOG_WARN, "External operation %s not implemented on Geneve board\n", extop[offset]);
}
/*
@@ -688,12 +682,35 @@ void geneve_state::machine_reset()
m_ready_line = m_ready_line1 = ASSERT_LINE;
- m_peribox->set_genmod(ioport("MODE")->read()==GENMOD);
-
m_joyport->write_port(0x01); // select Joystick 1
}
-MACHINE_CONFIG_START(geneve_state::geneve_60hz)
+MACHINE_CONFIG_START(geneve_state::geneve)
+ geneve_common(config);
+ // Mapper
+ MCFG_DEVICE_ADD(GENEVE_MAPPER_TAG, GENEVE_MAPPER, 0)
+ MCFG_GENEVE_READY_HANDLER( WRITELINE(*this, geneve_state, mapper_ready) )
+ // Peripheral expansion box (Geneve composition)
+ MCFG_DEVICE_ADD( TI_PERIBOX_TAG, TI99_PERIBOX_GEN, 0)
+ MCFG_PERIBOX_INTA_HANDLER( WRITELINE(*this, geneve_state, inta) )
+ MCFG_PERIBOX_INTB_HANDLER( WRITELINE(*this, geneve_state, intb) )
+ MCFG_PERIBOX_READY_HANDLER( WRITELINE(*this, geneve_state, ext_ready) )
+
+MACHINE_CONFIG_END
+
+MACHINE_CONFIG_START(geneve_state::genmod)
+ geneve_common(config);
+ // Mapper
+ MCFG_DEVICE_ADD(GENEVE_MAPPER_TAG, GENMOD_MAPPER, 0)
+ MCFG_GENEVE_READY_HANDLER( WRITELINE(*this, geneve_state, mapper_ready) )
+ // Peripheral expansion box (Geneve composition with Genmod and plugged-in Memex)
+ MCFG_DEVICE_ADD( TI_PERIBOX_TAG, TI99_PERIBOX_GENMOD, 0)
+ MCFG_PERIBOX_INTA_HANDLER( WRITELINE(*this, geneve_state, inta) )
+ MCFG_PERIBOX_INTB_HANDLER( WRITELINE(*this, geneve_state, intb) )
+ MCFG_PERIBOX_READY_HANDLER( WRITELINE(*this, geneve_state, ext_ready) )
+MACHINE_CONFIG_END
+
+MACHINE_CONFIG_START(geneve_state::geneve_common)
// basic machine hardware
// TMS9995 CPU @ 12.0 MHz
MCFG_TMS99xx_ADD("maincpu", TMS9995, 12000000, memmap, crumap)
@@ -720,21 +737,11 @@ MACHINE_CONFIG_START(geneve_state::geneve_60hz)
MCFG_TMS9901_P13_HANDLER( WRITELINE( GENEVE_MAPPER_TAG, bus::ti99::internal::geneve_mapper_device, pfm_select_msb) ) // new for PFM
MCFG_TMS9901_INTLEVEL_HANDLER( WRITE8( *this, geneve_state, tms9901_interrupt) )
- // Mapper
- MCFG_DEVICE_ADD(GENEVE_MAPPER_TAG, GENEVE_MAPPER, 0)
- MCFG_GENEVE_READY_HANDLER( WRITELINE(*this, geneve_state, mapper_ready) )
-
// Clock
MCFG_DEVICE_ADD(GENEVE_CLOCK_TAG, MM58274C, 0)
MCFG_MM58274C_MODE24(1) // 24 hour
MCFG_MM58274C_DAY1(0) // sunday
- // Peripheral expansion box (Geneve composition)
- MCFG_DEVICE_ADD( TI_PERIBOX_TAG, TI99_PERIBOX_GEN, 0)
- MCFG_PERIBOX_INTA_HANDLER( WRITELINE(*this, geneve_state, inta) )
- MCFG_PERIBOX_INTB_HANDLER( WRITELINE(*this, geneve_state, intb) )
- MCFG_PERIBOX_READY_HANDLER( WRITELINE(*this, geneve_state, ext_ready) )
-
// Sound hardware
SPEAKER(config, "sound_out").front_center();
MCFG_DEVICE_ADD(TI_SOUNDCHIP_TAG, SN76496, 3579545) /* 3.579545 MHz */
@@ -756,7 +763,7 @@ MACHINE_CONFIG_START(geneve_state::geneve_60hz)
MCFG_RAM_DEFAULT_SIZE("512K")
MCFG_RAM_DEFAULT_VALUE(0)
- // SRAM 384K (max; stock Geneve: 32K)
+ // SRAM 384K (max; stock Geneve: 32K, but later MDOS releases require 64K)
MCFG_RAM_ADD(GENEVE_SRAM_TAG)
MCFG_RAM_DEFAULT_SIZE("384K")
MCFG_RAM_DEFAULT_VALUE(0)
@@ -769,11 +776,20 @@ MACHINE_CONFIG_END
ROM_START(geneve)
/*CPU memory space*/
- ROM_REGION(0xc000, "maincpu", 0)
- ROM_LOAD("genbt100.bin", 0x0000, 0x4000, CRC(8001e386) SHA1(b44618b54dabac3882543e18555d482b299e0109)) /* CPU ROMs v1.0 */
- ROM_LOAD_OPTIONAL("genbt098.bin", 0x4000, 0x4000, CRC(b2e20df9) SHA1(2d5d09177afe97d63ceb3ad59b498b1c9e2153f7)) /* CPU ROMs v0.98 */
- ROM_LOAD_OPTIONAL("gnmbt100.bin", 0x8000, 0x4000, CRC(19b89479) SHA1(6ef297eda78dc705946f6494e9d7e95e5216ec47)) /* CPU ROMs GenMod */
+ ROM_REGION(0x4000, "maincpu", 0)
+ ROM_DEFAULT_BIOS("0.98")
+ ROM_SYSTEM_BIOS(0, "0.98", "Geneve Boot ROM 0.98")
+ ROMX_LOAD("genbt098.bin", 0x0000, 0x4000, CRC(b2e20df9) SHA1(2d5d09177afe97d63ceb3ad59b498b1c9e2153f7), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "1.00", "Geneve Boot ROM 1.00")
+ ROMX_LOAD("genbt100.bin", 0x0000, 0x4000, CRC(8001e386) SHA1(b44618b54dabac3882543e18555d482b299e0109), ROM_BIOS(1))
+ROM_END
+
+ROM_START(genmod)
+ /*CPU memory space*/
+ ROM_REGION(0x4000, "maincpu", 0)
+ ROM_LOAD("gnmbt100.bin", 0x0000, 0x4000, CRC(19b89479) SHA1(6ef297eda78dc705946f6494e9d7e95e5216ec47))
ROM_END
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
-COMP( 1987, geneve, 0, 0, geneve_60hz, geneve, geneve_state, init_geneve, "Myarc", "Geneve 9640", MACHINE_SUPPORTS_SAVE)
+COMP( 1987, geneve, 0, 0, geneve, geneve, geneve_state, init_geneve, "Myarc", "Geneve 9640", MACHINE_SUPPORTS_SAVE)
+COMP( 1990, genmod, 0, 0, genmod, genmod, geneve_state, init_geneve, "Myarc / Ron G. Walters", "Geneve 9640 Mod", MACHINE_SUPPORTS_SAVE)
diff --git a/src/mame/mame.lst b/src/mame/mame.lst
index 7ab004726e9..ddb5ae412fd 100644
--- a/src/mame/mame.lst
+++ b/src/mame/mame.lst
@@ -13836,7 +13836,8 @@ suprpokra // (c) 1986 Grayhound Electronics
suprpokrb // (c) 1986 Grayhound Electronics
@source:geneve.cpp
-geneve // 1987? Myarc Geneve 9640
+geneve // 1987 Myarc Geneve 9640
+genmod // 1990 Myarc / Ron G. Walters Geneve 9640 Mod
@source:geniusiq.cpp
iq128 // 1997 Genius IQ 128 (Germany)