mirror of
https://github.com/holub/mame
synced 2025-06-14 08:26:57 +03:00
ti99: Reimplementation of the Horizon RAMdisk card with all config options of the real hardware.
This commit is contained in:
parent
8500209910
commit
45b19d2899
@ -24,6 +24,7 @@
|
||||
#define LOG_WRITE (1U<<7) // Write operation
|
||||
#define LOG_GROM (1U<<8) // GROM access
|
||||
#define LOG_RPK (1U<<9) // RPK handler
|
||||
#define LOG_WARNW (1U<<10) // Warn when writing to cartridge space
|
||||
|
||||
#define VERBOSE ( LOG_GENERAL | LOG_WARN )
|
||||
#include "logmacro.h"
|
||||
@ -538,7 +539,9 @@ void ti99_cartridge_pcb::write(offs_t offset, uint8_t data)
|
||||
{
|
||||
if (m_romspace_selected)
|
||||
{
|
||||
if (m_ram_ptr == nullptr) LOGMASKED(LOG_WARN, "Cannot write to cartridge ROM space at %04x\n", offset | 0x6000);
|
||||
// Do not warn by default; devices like Horizon will create a lot of
|
||||
// meaningless warnings at this point
|
||||
if (m_ram_ptr == nullptr) LOGMASKED(LOG_WARNW, "Cannot write to cartridge ROM space at %04x\n", offset | 0x6000);
|
||||
else
|
||||
{
|
||||
// Check if we have RAM in the ROM socket
|
||||
|
@ -4,54 +4,122 @@
|
||||
|
||||
Horizon Ramdisk
|
||||
|
||||
This emulation realizes the latest development, the HRD 4000, which could
|
||||
host up to 16 MiB of SRAM. Real cards rarely had more than 1.5 MiB since
|
||||
the SRAM used on the card is rather expensive.
|
||||
This emulation realizes the latest development, the HRD 4000B, which can
|
||||
host up to 16 MiB of SRAM. The SRAM is buffered with a battery pack. Also,
|
||||
there is an option for an additional 32 KiB of unbuffered memory.
|
||||
|
||||
The SRAM is buffered with a battery pack. Also, there is an option for
|
||||
an additional 32 KiB of unbuffered memory.
|
||||
|
||||
The driver (ROS) of the ramdisk is stored in another buffered 8 KiB SRAM.
|
||||
The driver (ROS) of the ramdisk is stored in another buffered SRAM.
|
||||
Originally set to be 8 KiB, the 4000B offers four banks of 8 KiB storage
|
||||
for the driver.
|
||||
|
||||
The Horizon RAMdisk comes with a disk containing the ROS and a configuration
|
||||
program (CFG). The latest version is ROS 8.14.
|
||||
program (CFG).
|
||||
|
||||
Technical details:
|
||||
|
||||
In the tradition (Horizon) mode, memory is organized as 2 KiB pages. The
|
||||
pages are selected via CRU bits and visible in the address area 5800 - 5fff.
|
||||
The area 4000-57ff is occupied by the ROS. As with all peripheral cards,
|
||||
the 4000-5fff area requires a CRU bit to be set (usually bit 0 of this
|
||||
card's CRU base).
|
||||
|
||||
Next releases of the HRD included new modes. The RAMBO (RAM Block operator)
|
||||
mode gathers four pages to a single 8 KiB page that is visible in the
|
||||
area 6000-7fff (cartridge space). Note that due to a possible design glitch,
|
||||
each RAMBO page n covers Horizon pages 4n, 4n+2, 4n+1, 4n+3 in this sequence.
|
||||
We emulate this by swapping two CRU lines.
|
||||
|
||||
The RAMDisk may be split in two separate drives, which is called the
|
||||
Phoenix extension. This is particularly important for use in the Geneve.
|
||||
As a bootable drive, the RAMdisk must not
|
||||
exceed 256 KiB; consequently, the RAM area is split, and one part realizes
|
||||
the boot drive while the other is still available for data. Also, there
|
||||
is a mechanism for selecting the parts of the card: The TI setting allows
|
||||
to select two CRU addresses, one for each part. In the Geneve mode, only
|
||||
one CRU address is used (1400 or 1600), and the part is selected by the
|
||||
fact that one disk uses CRU bits higher than 8, while the other uses the
|
||||
bits lower than 8.
|
||||
|
||||
The card is able to handle 128K*8 and 512K*8 SRAM chips, allowing a total
|
||||
of 16 MiB memory space. Unfortunately, a bug causes the configuration
|
||||
program to crash when used with more than 2 MiB. Although the card was
|
||||
quite popular, this bug was not found because most cards were sold with
|
||||
less than 2 MiB onboard. As the community is still alive we can hope for
|
||||
a fix for this problem; so we make the size configurable.
|
||||
of 16 MiB memory space. The card may be equipped with 0 to 32 SRAM chips;
|
||||
in this implementation, a multiple of 4 can be selected in that range.
|
||||
|
||||
According to the Genmod setup instructions, the Horizon Ramdisks do not
|
||||
decode the AMA/AMB/AMC lines, so it is important to modify them when
|
||||
running with the Genmod system. This can be done with the configuration
|
||||
setting "Genmod fix".
|
||||
The Horizon 4000(B) implements the AMA decoding, unlike the the earlier
|
||||
models.
|
||||
|
||||
Sockets must be populated contiguously from 0 to 15. Only when all sockets
|
||||
are populated, further SRAM circuits may be soldered on top of the bottom
|
||||
layer chips, again contiguously from 0 to 15.
|
||||
|
||||
The respective CS* lines of the SRAM chips on the top layer must be
|
||||
connected with separate wires to the selector chip.
|
||||
|
||||
=== Normal mode ===
|
||||
|
||||
In the normal (Horizon) mode, memory is organized as 2 KiB pages. The
|
||||
pages are selected via CRU bits and visible in the address area 5800 - 5fff.
|
||||
The area 4000-57ff is occupied by the ROS. As with most peripheral cards,
|
||||
the 4000-5fff area requires CRU bit 0 to be set.
|
||||
|
||||
CRU bits:
|
||||
|
||||
15 14 13 12 11 10 9 8 7 6 1 0
|
||||
+-----------------------------------------------------------------+
|
||||
| RAMBO | DSR | SRAM | B | B | B | B | P | P | P ... | P | Ena | 512Kx8
|
||||
| | bank | Layer | Bank (0-15) | Page (0-255) | ble | RAM
|
||||
+-----------------------------------------------------------------+
|
||||
|
||||
15 14 13 12 11 10 9 8 7 6 1 0
|
||||
+-----------------------------------------------------------------+
|
||||
| RAMBO | DSR | - | - | SRAM | B | B | B | B | P | ... | P | Ena | 128Kx8
|
||||
| | bank | | | Layer| Bank (0-15) | Page(0-63) | ble | RAM
|
||||
+-----------------------------------------------------------------+
|
||||
|
||||
The difference between layer, banks, and pages results from the board
|
||||
design. Logically, the layer, bank, and page information can be seen as a
|
||||
13-bit page number for 512Kx8 RAMs or a 11-bit page number for 128Kx8 SRAMs.
|
||||
|
||||
The 8-bit page number results from the capacity of a 512Kx8 chip (256 pages
|
||||
of 2 KiB), while the 6-bit number applies to 128Kx8 chips (64 pages of
|
||||
2 KiB). The bank selects the chip socket. The layer allows for selecting
|
||||
the second layer of chips, piggy-backed on the bottom layer.
|
||||
|
||||
=== RAMBO ===
|
||||
|
||||
The RAMBO (RAM Block operator) mode gathers four pages to a single 8 KiB
|
||||
page in the area 6000-7fff (cartridge space). Due to an arguable design
|
||||
glitch in the real hardware (swapped A3/A4 lines), the four pages do not
|
||||
appear in their original order but as the base number plus 0 / 2 / 1 / 3.
|
||||
This can only be noticed when working in both modes (writing to pages in the
|
||||
normal mode, then mapping the group of pages via RAMBO).
|
||||
|
||||
The above CRU bit chart also applies here, but bits 1 and 2 (least signi-
|
||||
ficant page number bits) are ignored.
|
||||
|
||||
=== Phoenix ===
|
||||
|
||||
Using jumper JP2 and a DIP switch setting, the card can be configured to the
|
||||
Phoenix mode. This mode was originally intended to allow the Geneve to boot
|
||||
from the Horizon card, because the early boot ROMs did not support a boot
|
||||
drive larger than 256 KiB. Consequently, the RAM area is split, and one part
|
||||
realizes the boot drive while the other is still available for data.
|
||||
|
||||
The Phoenix configuration splits the card in the middle, assigning the
|
||||
lower 8 sockets (bottom M0-M7, top M16-M23) to the Phoenix part, and the
|
||||
upper 8 sockets (bottom M8-M15, top M24-M31) to the normal part.
|
||||
|
||||
The most significant bank selection bit (12 or 10) is ignored, because this
|
||||
bit determines the choice of upper and lower part. The selection is done
|
||||
in this way instead:
|
||||
|
||||
In "TI mode", two separate CRU base addresses must be selected by the DIP
|
||||
switches. When an access occurs on the normal CRU address, the bit is set,
|
||||
while an access to the Phoenix CRU address resets the bit. Accesses occur
|
||||
when the page is set.
|
||||
|
||||
In the "Geneve mode", only one CRU address is used. A CRU write access
|
||||
to bits 8-15 sets the bit to 0, and a CRU write access to bits 0-7 sets
|
||||
the bit to 1. Since the bits keep their semantics, care must be taken in
|
||||
which order the bits are written to. For this reason, the Phoenix mode is
|
||||
rarely used.
|
||||
|
||||
Later investigations proved that the GeneveOS could be loaded normally from
|
||||
the large ramdisk, and the Phoenix mode became obsolete. It is included for
|
||||
test purposes and for the sake of completeness.
|
||||
|
||||
The "Split mode" for TI and Geneve can be used without splitting the RAM
|
||||
space, i.e. a Phoenix address may be set without JP2 set to split. In that
|
||||
case, only the DSR RAM is split in two halves (if its size is 32KiB).
|
||||
|
||||
References
|
||||
|
||||
[1] Software Developer's Guide to the HRD4000B, Sept. 2020
|
||||
[2] Schematics for the HRD4000B
|
||||
[3] Horizon 4000 Ramdisk Construction Guide, Bud Mills Services, 1992
|
||||
|
||||
Original design of the hardware (2000) by Horizon Computer, Ltd., 1986
|
||||
Extensions (3000, 4000) by Bud Mills Services, 1989, 1992
|
||||
HRD 4000B by Jim Fetzner et al., 2019
|
||||
|
||||
Michael Zapf
|
||||
November 2020
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
@ -60,360 +128,369 @@
|
||||
|
||||
#define LOG_WARN (1U<<1) // Warnings
|
||||
#define LOG_CONFIG (1U<<2) // Configuration
|
||||
#define LOG_READ (1U<<3)
|
||||
#define LOG_WRITE (1U<<4)
|
||||
#define LOG_CRU (1U<<5)
|
||||
#define LOG_32K (1U<<3) // 32K optional RAM r/w
|
||||
#define LOG_DSR (1U<<4) // DSR
|
||||
#define LOG_RAM (1U<<5) // RAM chips
|
||||
#define LOG_ORAM (1U<<6) // outside of RAM chips
|
||||
#define LOG_CRU (1U<<7) // CRU
|
||||
#define LOG_PAGE (1U<<8) // Page access
|
||||
|
||||
#define VERBOSE ( LOG_CONFIG | LOG_WARN )
|
||||
#define VERBOSE ( LOG_GENERAL | LOG_CONFIG | LOG_WARN )
|
||||
|
||||
#include "logmacro.h"
|
||||
|
||||
DEFINE_DEVICE_TYPE_NS(TI99_HORIZON, bus::ti99::peb, horizon_ramdisk_device, "ti99_horizon", "Horizon 4000 Ramdisk")
|
||||
DEFINE_DEVICE_TYPE_NS(TI99_HORIZON, bus::ti99::peb, horizon_ramdisk_device, "ti99_horizon", "Horizon 4000B RAMdisk")
|
||||
|
||||
namespace bus { namespace ti99 { namespace peb {
|
||||
|
||||
#define RAMREGION "ram32k"
|
||||
#define ROSREGION "ros8k"
|
||||
#define NVRAMREGION "nvram"
|
||||
#define CRULATCH1_TAG "u4_latch"
|
||||
#define CRULATCH2_TAG "u3_latch"
|
||||
|
||||
#define MAXSIZE 16777216
|
||||
#define ROSSIZE 8192
|
||||
#define DSRRAM_TAG "u9_dsrram"
|
||||
#define OPT32K_TAG "m32_ram"
|
||||
#define RAM16M_TAG "m31_m0_ram"
|
||||
|
||||
horizon_ramdisk_device::horizon_ramdisk_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock):
|
||||
device_t(mconfig, TI99_HORIZON, tag, owner, clock),
|
||||
device_ti99_peribox_card_interface(mconfig, *this),
|
||||
device_nvram_interface(mconfig, *this),
|
||||
m_ram(*this, RAMREGION),
|
||||
m_nvram(*this, NVRAMREGION),
|
||||
m_ros(*this, ROSREGION),
|
||||
m_page(0),
|
||||
m_cru_horizon(0),
|
||||
m_cru_phoenix(0),
|
||||
m_timode(false),
|
||||
m_32k_installed(false),
|
||||
m_split_mode(false),
|
||||
m_rambo_mode(false),
|
||||
m_ram(*this, RAM16M_TAG),
|
||||
m_dsrram(*this, DSRRAM_TAG),
|
||||
m_optram(*this, OPT32K_TAG),
|
||||
m_crulatch_u4(*this, CRULATCH1_TAG),
|
||||
m_crulatch_u3(*this, CRULATCH2_TAG),
|
||||
m_32k_installed(true),
|
||||
m_phoenix_accessed(false),
|
||||
m_dsr32k(true),
|
||||
m_128kx8(true),
|
||||
m_geneve_mode(false),
|
||||
m_phoenix_split(false),
|
||||
m_hideswitch(false),
|
||||
m_use_rambo(false),
|
||||
m_genmod_fix(false)
|
||||
m_rambo_supported(false),
|
||||
m_page(0),
|
||||
m_bank(0),
|
||||
m_ramsize(0),
|
||||
m_cru_base_horizon(0),
|
||||
m_cru_base_phoenix(0)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// nvram_default - called to initialize NVRAM to
|
||||
// its default state
|
||||
//-------------------------------------------------
|
||||
|
||||
void horizon_ramdisk_device::nvram_default()
|
||||
{
|
||||
int size = 2097152*(1 << ioport("HORIZONSIZE")->read());
|
||||
memset(m_nvram->pointer(), 0, size);
|
||||
memset(m_ros->pointer(), 0, ROSSIZE);
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// nvram_read - called to read NVRAM from the
|
||||
// .nv file
|
||||
//-------------------------------------------------
|
||||
|
||||
void horizon_ramdisk_device::nvram_read(emu_file &file)
|
||||
{
|
||||
int size = 2097152*(1 << ioport("HORIZONSIZE")->read());
|
||||
|
||||
// NVRAM plus ROS
|
||||
auto buffer = make_unique_clear<uint8_t []>(MAXSIZE + ROSSIZE);
|
||||
|
||||
memset(m_nvram->pointer(), 0, size);
|
||||
memset(m_ros->pointer(), 0, ROSSIZE);
|
||||
|
||||
// We assume the last 8K is ROS
|
||||
int filesize = file.read(&buffer[0], MAXSIZE+ROSSIZE);
|
||||
int nvramsize = filesize - ROSSIZE;
|
||||
|
||||
// If there is a reasonable size
|
||||
if (nvramsize >= 0)
|
||||
{
|
||||
// Copy from buffer to NVRAM and ROS
|
||||
memcpy(m_nvram->pointer(), &buffer[0], nvramsize);
|
||||
memcpy(m_ros->pointer(), &buffer[nvramsize], ROSSIZE);
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// nvram_write - called to write NVRAM to the
|
||||
// .nv file
|
||||
//-------------------------------------------------
|
||||
|
||||
void horizon_ramdisk_device::nvram_write(emu_file &file)
|
||||
{
|
||||
int nvramsize = 2097152*(1 << ioport("HORIZONSIZE")->read());
|
||||
|
||||
auto buffer = make_unique_clear<uint8_t []>(nvramsize + ROSSIZE);
|
||||
memcpy(&buffer[0], m_nvram->pointer(), nvramsize);
|
||||
memcpy(&buffer[nvramsize], m_ros->pointer(), ROSSIZE);
|
||||
|
||||
file.write(buffer.get(), nvramsize + ROSSIZE);
|
||||
}
|
||||
|
||||
void horizon_ramdisk_device::readz(offs_t offset, uint8_t *value)
|
||||
{
|
||||
// 32K expansion
|
||||
// According to the manual, "this memory is not affected by the HIDE switch"
|
||||
if (m_32k_installed)
|
||||
{
|
||||
switch((offset & 0xe000)>>13)
|
||||
{
|
||||
case 1: // 2000-3fff
|
||||
*value = m_ram->pointer()[offset & 0x1fff];
|
||||
return;
|
||||
case 5: // a000-bfff
|
||||
*value = m_ram->pointer()[(offset & 0x1fff) | 0x2000];
|
||||
return;
|
||||
case 6: // c000-dfff
|
||||
*value = m_ram->pointer()[(offset & 0x1fff) | 0x4000];
|
||||
return;
|
||||
case 7: // e000-ffff
|
||||
*value = m_ram->pointer()[(offset & 0x1fff) | 0x6000];
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_hideswitch) return;
|
||||
|
||||
// I think RAMBO mode does not need the card to be selected
|
||||
if (!m_selected && !m_rambo_mode) return;
|
||||
|
||||
if (!m_rambo_mode)
|
||||
{
|
||||
if (in_dsr_space(offset, m_genmod_fix))
|
||||
{
|
||||
if ((offset & 0x1800) == 0x1800)
|
||||
{
|
||||
// NVRAM page of size 2 KiB
|
||||
*value = m_nvram->pointer()[(m_page << 11)|(offset & 0x07ff)];
|
||||
LOGMASKED(LOG_READ, "offset=%04x, page=%04x -> %02x\n", offset&0xffff, m_page, *value);
|
||||
}
|
||||
else
|
||||
{
|
||||
// ROS
|
||||
*value = m_ros->pointer()[offset & 0x1fff];
|
||||
LOGMASKED(LOG_READ, "offset=%04x (ROS) -> %02x\n", offset&0xffff, *value);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (in_dsr_space(offset, m_genmod_fix))
|
||||
{
|
||||
*value = m_ros->pointer()[offset & 0x1fff];
|
||||
LOGMASKED(LOG_READ, "offset=%04x (Rambo) -> %02x\n", offset&0xffff, *value);
|
||||
}
|
||||
if (in_cart_space(offset, m_genmod_fix))
|
||||
{
|
||||
// In RAMBO mode the page numbers are multiples of 4
|
||||
// (encompassing 4 Horizon pages)
|
||||
// We clear away the rightmost two bits
|
||||
*value = m_nvram->pointer()[((m_page&0xfffc)<<11) | (offset & 0x1fff)];
|
||||
LOGMASKED(LOG_READ, "offset=%04x, page=%04x (Rambo) -> %02x\n", offset&0xffff, m_page, *value);
|
||||
}
|
||||
}
|
||||
read_write(offset, value, false);
|
||||
}
|
||||
|
||||
void horizon_ramdisk_device::write(offs_t offset, uint8_t data)
|
||||
{
|
||||
read_write(offset, &data, true);
|
||||
}
|
||||
|
||||
/*
|
||||
Read from or write to the card. This can involve the
|
||||
a) optional 32K RAM (M32)
|
||||
b) DSR RAM (U9)
|
||||
c) set of RAM chips (M0-M31)
|
||||
*/
|
||||
void horizon_ramdisk_device::read_write(offs_t offset, uint8_t *value, bool write)
|
||||
{
|
||||
// If AMA/B/C != 111, do not allow access. This "AMA decoding" was done
|
||||
// by default by TI cards, but third-party cards did not comply in all cases.
|
||||
|
||||
// HRD4000(B) used this decoding (U13); earlier Horizon cards did not
|
||||
// implement it
|
||||
if ((offset & 0x70000) != 0x70000) return;
|
||||
|
||||
// 32K expansion
|
||||
// According to the manual, "this memory is not affected by the HIDE switch"
|
||||
// According to [3], this memory is not affected by the HIDE switch
|
||||
// Also, it cannot be mapped out by a CRU bit
|
||||
//
|
||||
// offset a14 a13
|
||||
// ----------------
|
||||
// | E000 | 0 0
|
||||
// ----------------
|
||||
// | C000 | 0 1
|
||||
// ----------------
|
||||
// | A000 | 1 0
|
||||
// ----------------
|
||||
// | 2000 | 1 1
|
||||
// ----------------
|
||||
//
|
||||
// a14=/c*/e, a13=/a*/e (pins of the memory chip, not the address bus)
|
||||
|
||||
int sect = (offset>>13) & 0x07; // 8K sections in the 64K address space
|
||||
int offset8k = (offset & 0x1fff);
|
||||
int offset2k = (offset & 0x07ff);
|
||||
|
||||
if (m_32k_installed)
|
||||
{
|
||||
switch((offset & 0xe000)>>13)
|
||||
// Decoding by U12 and U11
|
||||
int a14 = ((sect != 6) && (sect != 7))? 0x4000 : 0; // a14: 11x
|
||||
int a13 = ((sect != 5) && (sect != 7))? 0x2000 : 0; // a13: 1x1
|
||||
|
||||
if ((sect == 1) || (sect == 5) || (sect == 6) || (sect == 7))
|
||||
{
|
||||
case 1: // 2000-3fff
|
||||
m_ram->pointer()[offset & 0x1fff] = data;
|
||||
return;
|
||||
case 5: // a000-bfff
|
||||
m_ram->pointer()[(offset & 0x1fff) | 0x2000] = data;
|
||||
return;
|
||||
case 6: // c000-dfff
|
||||
m_ram->pointer()[(offset & 0x1fff) | 0x4000] = data;
|
||||
return;
|
||||
case 7: // e000-ffff
|
||||
m_ram->pointer()[(offset & 0x1fff) | 0x6000] = data;
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_hideswitch) return;
|
||||
|
||||
// I think RAMBO mode does not need the card to be selected
|
||||
if (!m_selected && !m_rambo_mode) return;
|
||||
|
||||
if (!m_rambo_mode)
|
||||
{
|
||||
if (in_dsr_space(offset, m_genmod_fix))
|
||||
{
|
||||
if ((offset & 0x1800) == 0x1800)
|
||||
{
|
||||
// NVRAM page of size 2 KiB
|
||||
m_nvram->pointer()[(m_page << 11)|(offset & 0x07ff)] = data;
|
||||
LOGMASKED(LOG_WRITE, "offset=%04x, page=%04x <- %02x\n", offset&0xffff, m_page, data);
|
||||
}
|
||||
if (write)
|
||||
m_optram->write(offset8k | a14 | a13, *value);
|
||||
else
|
||||
{
|
||||
// ROS
|
||||
m_ros->pointer()[offset & 0x1fff] = data;
|
||||
LOGMASKED(LOG_WRITE, "offset=%04x (ROS) <- %02x\n", offset&0xffff, data);
|
||||
}
|
||||
*value = m_optram->read(offset8k | a14 | a13);
|
||||
|
||||
LOGMASKED(LOG_32K, "offset=%04x (32K) %s %02x\n", offset&0xffff, write? "<-" : "->", *value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
// DSR RAM is not affected by SW2 either.
|
||||
// CRU bit 0 must be set to 1 to activate it.
|
||||
// Decoding by U12 and U7
|
||||
int b_a = offset & 0x1800;
|
||||
if (m_rambo_supported && m_crulatch_u3->q7_r()) b_a &= 0x0f00; // clear A3 (RAMBO mode)
|
||||
|
||||
bool dsr = m_crulatch_u4->q0_r() && (sect == 2);
|
||||
|
||||
if (dsr && (b_a != 0x1800))
|
||||
{
|
||||
if (in_dsr_space(offset, m_genmod_fix))
|
||||
// DSR access
|
||||
// All cards 2000-4000 have 8K RAM here
|
||||
// The 4000B supports up to 32K; 4 banks can be selected
|
||||
int a13 = (m_crulatch_u3->q6_r())? 0x2000 : 0;
|
||||
int a14 = (!m_phoenix_accessed)? 0x4000 : 0;
|
||||
|
||||
if (write)
|
||||
m_dsrram->write(offset8k | (m_dsr32k? (a13 | a14) : 0), *value);
|
||||
else
|
||||
*value = m_dsrram->read(offset8k | (m_dsr32k? (a13 | a14) : 0));
|
||||
|
||||
LOGMASKED(LOG_DSR, "offset=%04x (DSR) %s %02x\n", offset&0xffff, write? "<-" : "->", *value);
|
||||
return;
|
||||
}
|
||||
|
||||
// Lower part of U7
|
||||
if ((dsr && (b_a == 0x1800)) || ((sect == 3) && m_rambo_supported && m_crulatch_u3->q7_r()))
|
||||
{
|
||||
// Access to a selected RAM
|
||||
// Either in normal mode (on 5800) or in RAMBO mode (6000-7fff)
|
||||
int page = m_page;
|
||||
int ramaddress = offset2k;
|
||||
|
||||
// RAMBO mode
|
||||
// If we are here in RAMBO mode, we are accessing 6000-7fff,
|
||||
// because for sect 2 (4000-5fff), b_a was changed to be != 1800
|
||||
if (m_rambo_supported && m_crulatch_u3->q7_r())
|
||||
{
|
||||
m_ros->pointer()[offset & 0x1fff] = data;
|
||||
LOGMASKED(LOG_WRITE, "offset=%04x (Rambo) <- %02x\n", offset&0xffff, data);
|
||||
// Replace the last two bits of the page number by address bits A3 and A4
|
||||
// ...xx...........
|
||||
// According to the specs, the lines must be swapped
|
||||
// Hence, the 2k page number sequence in the 6000 space is
|
||||
// base + 0 2 1 3
|
||||
int a3_4 = (((offset & 0x0800)>>10) | ((offset & 0x1000)>>12));
|
||||
page = (page & 0xfc) | a3_4;
|
||||
}
|
||||
if (in_cart_space(offset, m_genmod_fix))
|
||||
|
||||
// Just debugging stuff
|
||||
if (page != m_current_page || m_bank != m_current_bank)
|
||||
{
|
||||
// In RAMBO mode the page numbers are multiples of 4
|
||||
// (encompassing 4 Horizon pages)
|
||||
// We clear away the rightmost two bits
|
||||
m_nvram->pointer()[((m_page&0xfffc)<<11) | (offset & 0x1fff)] = data;
|
||||
LOGMASKED(LOG_WRITE, "offset=%04x, page=%04x (Rambo) <- %02x\n", offset&0xffff, m_page, data);
|
||||
LOGMASKED(LOG_PAGE, "Bank %02x, page %02x\n", m_bank, page);
|
||||
m_current_bank = m_bank;
|
||||
m_current_page = page;
|
||||
}
|
||||
|
||||
if (m_128kx8)
|
||||
// bb bbbp pppp p... .... ....
|
||||
ramaddress |= ((page << 11) | (m_bank << 17));
|
||||
else
|
||||
// bbbb bppp pppp p... .... ....
|
||||
ramaddress |= ((page << 11) | (m_bank << 19));
|
||||
|
||||
if (ramaddress < m_ramsize)
|
||||
{
|
||||
if (write)
|
||||
m_ram->write(ramaddress, *value);
|
||||
else
|
||||
*value = m_ram->read(ramaddress);
|
||||
|
||||
LOGMASKED(LOG_RAM, "offset=%04x, page=%02x, bank=%02x %s %02x\n", offset&0xffff, page, m_bank, write? "<-" : "->", *value);
|
||||
}
|
||||
else
|
||||
LOGMASKED(LOG_ORAM, "offset=%04x, page=%02x, bank=%02x %s outside of RAM space\n", offset&0xffff, page, m_bank, write? "write" : "read");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
CRU read operation. There is not such read feature on the Horizon.
|
||||
*/
|
||||
void horizon_ramdisk_device::crureadz(offs_t offset, uint8_t *value)
|
||||
{
|
||||
// There is no CRU read operation for the Horizon.
|
||||
return;
|
||||
}
|
||||
|
||||
void horizon_ramdisk_device::setbit(int& page, int pattern, bool set)
|
||||
/*
|
||||
CRU write operation.
|
||||
*/
|
||||
void horizon_ramdisk_device::cruwrite(offs_t offset, uint8_t data)
|
||||
{
|
||||
if (set)
|
||||
// Horizon and Phoenix set to off = ff00 will never match
|
||||
if (((offset & 0x1f00) != m_cru_base_horizon) && ((offset & 0x1f00) != m_cru_base_phoenix))
|
||||
return;
|
||||
|
||||
int bit = (offset >> 1) & 0x0f;
|
||||
|
||||
// Set the latch U5
|
||||
// For Geneve mode, it is set when a bit 8-15 is accessed; for the TI mode
|
||||
// it is set for an access to the Phoenix CRU area
|
||||
m_phoenix_accessed = m_geneve_mode? (bit >= 8) : ((offset & 0x1f00) == m_cru_base_phoenix);
|
||||
|
||||
// Set the latches U4 and U3 (unless the SW2 hideswitch is turned on)
|
||||
if (m_hideswitch==false)
|
||||
{
|
||||
page |= pattern;
|
||||
}
|
||||
else
|
||||
{
|
||||
page &= ~pattern;
|
||||
if (bit < 8)
|
||||
{
|
||||
m_crulatch_u4->write_bit(bit & 7, data & 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_crulatch_u3->write_bit(bit & 7, data & 1);
|
||||
}
|
||||
get_address_prefix();
|
||||
}
|
||||
}
|
||||
|
||||
void horizon_ramdisk_device::cruwrite(offs_t offset, uint8_t data)
|
||||
/*
|
||||
Translate latch settings to page and bank.
|
||||
Also called after savestate load.
|
||||
This method is used to avoid reading all settings every time that a memory
|
||||
access occurs.
|
||||
*/
|
||||
void horizon_ramdisk_device::get_address_prefix()
|
||||
{
|
||||
int size = ioport("HORIZONSIZE")->read();
|
||||
int split_bit = size + 10;
|
||||
int splitpagebit = 0x0200 << size;
|
||||
u8 latch1 = m_crulatch_u4->output_state();
|
||||
u8 latch2 = m_crulatch_u3->output_state();
|
||||
|
||||
if (((offset & 0xff00)==m_cru_horizon)||((offset & 0xff00)==m_cru_phoenix))
|
||||
// Latch 2 Latch 1
|
||||
// ..lbbbbp ppppppp. 512k
|
||||
// ....lbbb bpppppp. 128k
|
||||
// l=layer b=bank p=page
|
||||
|
||||
if (m_128kx8)
|
||||
{
|
||||
int bit = (offset >> 1) & 0x0f;
|
||||
LOGMASKED(LOG_CRU, "CRU write bit %d <- %d\n", bit, data);
|
||||
switch (bit)
|
||||
{
|
||||
case 0:
|
||||
m_selected = (data!=0);
|
||||
LOGMASKED(LOG_CRU, "Activate ROS = %d\n", m_selected);
|
||||
break;
|
||||
case 1:
|
||||
// Swap the lines so that the access with RAMBO is consistent
|
||||
if (!m_rambo_mode) setbit(m_page, 0x0002, data!=0);
|
||||
break;
|
||||
case 2:
|
||||
// Swap the lines so that the access with RAMBO is consistent
|
||||
if (!m_rambo_mode) setbit(m_page, 0x0001, data!=0);
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
setbit(m_page, 0x0001 << (bit-1), data!=0);
|
||||
break;
|
||||
case 14:
|
||||
break;
|
||||
case 15:
|
||||
if (m_use_rambo)
|
||||
{
|
||||
m_rambo_mode = (data != 0);
|
||||
LOGMASKED(LOG_CRU, "RAMBO = %d\n", m_rambo_mode);
|
||||
}
|
||||
break;
|
||||
m_page = (latch1 >> 1) & 0x3f;
|
||||
m_bank = ((latch1 >> 7) & 0x01) | ((latch2 << 1) & 0x1e);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_page = ((latch1 >> 1) & 0x7f) | ((latch2 << 7) & 0x80);
|
||||
m_bank = (latch2 >> 1) & 0x1f;
|
||||
}
|
||||
|
||||
default: // bits 10-13
|
||||
if (bit != split_bit || !m_split_mode)
|
||||
{
|
||||
if (bit <= split_bit) setbit(m_page, 0x0200<<(bit-10), data!=0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_split_mode)
|
||||
{
|
||||
if (m_timode)
|
||||
{
|
||||
// In TI mode, switch between both RAMDisks using the CRU address
|
||||
setbit(m_page, splitpagebit, ((offset & 0xff00)==m_cru_phoenix));
|
||||
}
|
||||
else
|
||||
{
|
||||
// In Geneve mode, switch between both RAMdisks by
|
||||
// using the bit number of the last CRU access
|
||||
setbit(m_page, splitpagebit, (bit>7));
|
||||
}
|
||||
}
|
||||
// Phoenix jumper JP2
|
||||
if (m_phoenix_split)
|
||||
{
|
||||
m_bank &= 0x08; // Clear the D bit
|
||||
if (!m_phoenix_accessed) m_bank |= 0x08;
|
||||
}
|
||||
}
|
||||
|
||||
void horizon_ramdisk_device::device_start(void)
|
||||
{
|
||||
m_cru_horizon = 0;
|
||||
m_cru_phoenix = 0;
|
||||
|
||||
save_item(NAME(m_page));
|
||||
save_item(NAME(m_cru_horizon));
|
||||
save_item(NAME(m_cru_phoenix));
|
||||
save_item(NAME(m_timode));
|
||||
save_item(NAME(m_32k_installed));
|
||||
save_item(NAME(m_split_mode));
|
||||
save_item(NAME(m_rambo_mode));
|
||||
save_item(NAME(m_hideswitch));
|
||||
save_item(NAME(m_use_rambo));
|
||||
machine().save().register_postload(save_prepost_delegate(FUNC(horizon_ramdisk_device::get_address_prefix),this));
|
||||
}
|
||||
|
||||
void horizon_ramdisk_device::device_reset(void)
|
||||
{
|
||||
m_cru_horizon = ioport("CRUHOR")->read();
|
||||
m_cru_phoenix = ioport("CRUPHOE")->read();
|
||||
m_cru_base_horizon = ioport("CRUHOR")->read();
|
||||
m_cru_base_phoenix = ioport("CRUPHOE")->read();
|
||||
m_32k_installed = (ioport("OPT32K")->read()!=0);
|
||||
m_phoenix_split = (ioport("PHOENIX")->read()!=0);
|
||||
m_hideswitch = (ioport("HIDESW2")->read()!=0);
|
||||
m_dsr32k = (ioport("DSRSIZE")->read()!=0);
|
||||
m_128kx8 = (ioport("CHIPTYPE")->read()==0);
|
||||
m_geneve_mode = (ioport("MODE")->read()!=0);
|
||||
m_rambo_supported = (ioport("RAMBO")->read()!=0);
|
||||
|
||||
m_32k_installed = (ioport("HORIZON32")->read()!=0);
|
||||
|
||||
m_split_mode = (ioport("HORIZONDUAL")->read()!=0);
|
||||
m_timode = (ioport("HORIZONDUAL")->read()==1);
|
||||
|
||||
m_rambo_mode = false;
|
||||
m_hideswitch = (ioport("HORIZONACT")->read()!=0);
|
||||
|
||||
m_use_rambo = (ioport("RAMBO")->read()!=0);
|
||||
|
||||
m_genmod_fix = (ioport("GENMODFIX")->read()!=0);
|
||||
|
||||
m_page = 0;
|
||||
m_selected = false;
|
||||
int dsrsize = 0;
|
||||
get_mem_size(m_ramsize, dsrsize);
|
||||
LOGMASKED(LOG_CONFIG, "Horizon card memory: %d bytes\n", m_ramsize);
|
||||
}
|
||||
|
||||
INPUT_CHANGED_MEMBER( horizon_ramdisk_device::hs_changed )
|
||||
{
|
||||
LOGMASKED(LOG_CONFIG, "hideswitch changed %d\n", newval);
|
||||
m_hideswitch = (newval!=0);
|
||||
if (param == 0)
|
||||
{
|
||||
LOGMASKED(LOG_CONFIG, "Hideswitch changed to %d\n", newval);
|
||||
m_hideswitch = (newval!=0);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGMASKED(LOG_CONFIG, "Phoenix split setting changed to %d\n", newval);
|
||||
m_phoenix_split = (newval!=0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
NVRAM support
|
||||
The size of the file is num_chips * mem_per_chip + dsr_size
|
||||
The contents of the RAM banks are stored first, then the
|
||||
DSR chip contents are appended
|
||||
|
||||
0 end
|
||||
____________________
|
||||
| RAM | DSR |
|
||||
--------------------
|
||||
*/
|
||||
void horizon_ramdisk_device::nvram_default()
|
||||
{
|
||||
int ramsize, dsrsize;
|
||||
get_mem_size(ramsize, dsrsize);
|
||||
|
||||
if (ramsize > 0) memset(m_ram->pointer(), 0, ramsize);
|
||||
memset(m_dsrram->pointer(), 0, dsrsize);
|
||||
}
|
||||
|
||||
|
||||
void horizon_ramdisk_device::nvram_read(emu_file &file)
|
||||
{
|
||||
int ramsize, dsrsize;
|
||||
get_mem_size(ramsize, dsrsize);
|
||||
|
||||
// NVRAM plus ROS, according to the current configuration
|
||||
auto buffer = make_unique_clear<uint8_t []>(ramsize + dsrsize);
|
||||
|
||||
if (ramsize > 0) memset(m_ram->pointer(), 0, ramsize);
|
||||
memset(m_dsrram->pointer(), 0, dsrsize);
|
||||
|
||||
// Read complete file, at most ramsize+dsrsize
|
||||
// Mind that the configuration may have changed
|
||||
int filesize = file.read(&buffer[0], ramsize + dsrsize);
|
||||
int nvramsize = filesize - dsrsize;
|
||||
|
||||
// At least the DSR must be complete
|
||||
if (nvramsize >= 0)
|
||||
{
|
||||
// Copy from buffer to NVRAM and ROS
|
||||
if (nvramsize > 0) memcpy(m_ram->pointer(), &buffer[0], nvramsize);
|
||||
memcpy(m_dsrram->pointer(), &buffer[nvramsize], dsrsize);
|
||||
}
|
||||
}
|
||||
|
||||
void horizon_ramdisk_device::nvram_write(emu_file &file)
|
||||
{
|
||||
int ramsize, dsrsize;
|
||||
get_mem_size(ramsize, dsrsize);
|
||||
|
||||
// NVRAM plus ROS, according to the current configuration
|
||||
auto buffer = make_unique_clear<uint8_t []>(ramsize + dsrsize);
|
||||
|
||||
memcpy(&buffer[0], m_ram->pointer(), ramsize);
|
||||
memcpy(&buffer[ramsize], m_dsrram->pointer(), dsrsize);
|
||||
|
||||
// Store both parts in one file
|
||||
file.write(buffer.get(), ramsize + dsrsize);
|
||||
}
|
||||
|
||||
void horizon_ramdisk_device::get_mem_size(int& ramsize, int& dsrsize)
|
||||
{
|
||||
int chipsize = 128*1024*((ioport("CHIPTYPE")->read()*3)+1);
|
||||
ramsize = (ioport("CHIPCOUNT")->read()*4) * chipsize;
|
||||
dsrsize = ((ioport("DSRSIZE")->read()*3)+1)*8192;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -421,9 +498,9 @@ INPUT_CHANGED_MEMBER( horizon_ramdisk_device::hs_changed )
|
||||
*/
|
||||
INPUT_PORTS_START( horizon )
|
||||
PORT_START( "CRUHOR" )
|
||||
PORT_DIPNAME( 0x1f00, 0x1200, "Horizon CRU base" )
|
||||
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
|
||||
PORT_DIPSETTING( 0x1000, "1000" )
|
||||
PORT_DIPNAME( 0xff00, 0x1200, "SW1 Horizon CRU base" )
|
||||
PORT_DIPSETTING( 0xff00, DEF_STR( Off ) )
|
||||
PORT_DIPSETTING( 0x1000, "1000" ) // 1100 and 1300 not available
|
||||
PORT_DIPSETTING( 0x1200, "1200" )
|
||||
PORT_DIPSETTING( 0x1400, "1400" )
|
||||
PORT_DIPSETTING( 0x1500, "1500" )
|
||||
@ -431,41 +508,57 @@ INPUT_PORTS_START( horizon )
|
||||
PORT_DIPSETTING( 0x1700, "1700" )
|
||||
|
||||
PORT_START( "CRUPHOE" )
|
||||
PORT_DIPNAME( 0x1f00, 0x0000, "Phoenix CRU base" )
|
||||
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
|
||||
PORT_DIPSETTING( 0x1400, "1400" )
|
||||
PORT_DIPNAME( 0xff00, 0xff00, "SW1 Phoenix CRU base" )
|
||||
PORT_DIPSETTING( 0xff00, DEF_STR( Off ) )
|
||||
PORT_DIPSETTING( 0x1400, "1400" ) // must not be used when selected for Horizon
|
||||
PORT_DIPSETTING( 0x1600, "1600" )
|
||||
|
||||
PORT_START( "HORIZONDUAL" )
|
||||
PORT_DIPNAME( 0x03, 0x00, "Horizon ramdisk split" )
|
||||
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
||||
PORT_DIPSETTING( 0x01, "TI mode" )
|
||||
PORT_DIPSETTING( 0x02, "Geneve mode" )
|
||||
PORT_START( "MODE" )
|
||||
PORT_DIPNAME( 0x01, 0x00, "JP4 Split mode" )
|
||||
PORT_DIPSETTING( 0x00, "TI mode" )
|
||||
PORT_DIPSETTING( 0x01, "Geneve mode" )
|
||||
|
||||
PORT_START( "HORIZONACT" )
|
||||
PORT_DIPNAME( 0x01, 0x00, "Horizon hideswitch" ) PORT_CHANGED_MEMBER(DEVICE_SELF, horizon_ramdisk_device, hs_changed, 0)
|
||||
PORT_START( "HIDESW2" )
|
||||
PORT_DIPNAME( 0x01, 0x00, "SW2 Hideswitch" ) PORT_CHANGED_MEMBER(DEVICE_SELF, horizon_ramdisk_device, hs_changed, 0)
|
||||
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
||||
PORT_DIPSETTING( 0x01, DEF_STR( On ) )
|
||||
|
||||
PORT_START( "HORIZON32" )
|
||||
PORT_CONFNAME( 0x01, 0x00, "Horizon 32 KiB upgrade" )
|
||||
PORT_START( "PHOENIX" )
|
||||
PORT_DIPNAME( 0x01, 0x00, "JP2 Phoenix split" ) PORT_CHANGED_MEMBER(DEVICE_SELF, horizon_ramdisk_device, hs_changed, 1)
|
||||
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
||||
PORT_DIPSETTING( 0x01, DEF_STR( On ) )
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
PORT_START( "CHIPTYPE" )
|
||||
PORT_CONFNAME( 0x01, 0x00, "Memory circuit type" )
|
||||
PORT_CONFSETTING( 0x00, "128Kx8")
|
||||
PORT_CONFSETTING( 0x01, "512Kx8")
|
||||
|
||||
PORT_START( "CHIPCOUNT" )
|
||||
PORT_CONFNAME( 0x0f, 0x04, "Memory circuit count" )
|
||||
PORT_CONFSETTING( 0x00, "0")
|
||||
PORT_CONFSETTING( 0x01, "4")
|
||||
PORT_CONFSETTING( 0x02, "8")
|
||||
PORT_CONFSETTING( 0x03, "12")
|
||||
PORT_CONFSETTING( 0x04, "16")
|
||||
PORT_CONFSETTING( 0x05, "20")
|
||||
PORT_CONFSETTING( 0x06, "24")
|
||||
PORT_CONFSETTING( 0x07, "28")
|
||||
PORT_CONFSETTING( 0x08, "32")
|
||||
|
||||
PORT_START( "DSRSIZE" )
|
||||
PORT_CONFNAME( 0x01, 0x00, "DSR memory size" )
|
||||
PORT_CONFSETTING( 0x00, "8 KiB" )
|
||||
PORT_CONFSETTING( 0x01, "32 KiB" )
|
||||
|
||||
PORT_START( "OPT32K" )
|
||||
PORT_CONFNAME( 0x01, 0x00, "Optional 32 KiB memory" )
|
||||
PORT_CONFSETTING( 0x00, DEF_STR( Off ))
|
||||
PORT_CONFSETTING( 0x01, DEF_STR( On ))
|
||||
|
||||
PORT_START( "RAMBO" )
|
||||
PORT_CONFNAME( 0x01, 0x01, "Horizon RAMBO" )
|
||||
PORT_CONFSETTING( 0x00, DEF_STR( Off ))
|
||||
PORT_CONFSETTING( 0x01, DEF_STR( On ))
|
||||
|
||||
PORT_START( "HORIZONSIZE" )
|
||||
PORT_CONFNAME( 0x03, 0x00, "Horizon size" )
|
||||
PORT_CONFSETTING( 0x00, "2 MiB")
|
||||
PORT_CONFSETTING( 0x01, "4 MiB")
|
||||
PORT_CONFSETTING( 0x02, "8 MiB")
|
||||
PORT_CONFSETTING( 0x03, "16 MiB")
|
||||
|
||||
PORT_START( "GENMODFIX" )
|
||||
PORT_CONFNAME( 0x01, 0x00, "Horizon Genmod fix" )
|
||||
PORT_CONFNAME( 0x01, 0x00, "RAMBO support" )
|
||||
PORT_CONFSETTING( 0x00, DEF_STR( Off ))
|
||||
PORT_CONFSETTING( 0x01, DEF_STR( On ))
|
||||
|
||||
@ -473,9 +566,19 @@ INPUT_PORTS_END
|
||||
|
||||
void horizon_ramdisk_device::device_add_mconfig(machine_config &config)
|
||||
{
|
||||
RAM(config, NVRAMREGION).set_default_size("16M");
|
||||
RAM(config, ROSREGION).set_default_size("8K");
|
||||
RAM(config, RAMREGION).set_default_size("32K").set_default_value(0);
|
||||
// It could make sense to use buffered_ram (BUFF_RAM) for the 16M RAM and
|
||||
// the DSR RAM which has its own NVRAM handler. However, we want to have
|
||||
// a configurable emulation, and the config switches are not available
|
||||
// before the NVRAM handlers of the subdevices kick in. It could be done
|
||||
// if the NVRAM files always use the same (maximum) size.
|
||||
|
||||
RAM(config, RAM16M_TAG).set_default_size("16M");
|
||||
RAM(config, DSRRAM_TAG).set_default_size("32K");
|
||||
RAM(config, OPT32K_TAG).set_default_size("32K").set_default_value(0);
|
||||
|
||||
// CRU latches
|
||||
LS259(config, m_crulatch_u4);
|
||||
LS259(config, m_crulatch_u3);
|
||||
}
|
||||
|
||||
ioport_constructor horizon_ramdisk_device::device_input_ports() const
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include "peribox.h"
|
||||
#include "machine/ram.h"
|
||||
#include "machine/74259.h"
|
||||
|
||||
namespace bus { namespace ti99 { namespace peb {
|
||||
|
||||
@ -45,23 +46,35 @@ protected:
|
||||
void nvram_write(emu_file &file) override;
|
||||
|
||||
private:
|
||||
void setbit(int& page, int pattern, bool set);
|
||||
|
||||
required_device<ram_device> m_ram;
|
||||
required_device<ram_device> m_nvram;
|
||||
required_device<ram_device> m_ros;
|
||||
required_device<ram_device> m_dsrram;
|
||||
required_device<ram_device> m_optram;
|
||||
required_device<ls259_device> m_crulatch_u4;
|
||||
required_device<ls259_device> m_crulatch_u3;
|
||||
|
||||
void get_mem_size(int& ramsize, int& dsrsize);
|
||||
void get_address_prefix();
|
||||
void read_write(offs_t offset, uint8_t *value, bool write);
|
||||
|
||||
bool m_32k_installed;
|
||||
bool m_phoenix_accessed;
|
||||
bool m_dsr32k;
|
||||
bool m_128kx8;
|
||||
bool m_geneve_mode;
|
||||
bool m_phoenix_split;
|
||||
bool m_hideswitch;
|
||||
bool m_rambo_supported;
|
||||
|
||||
int m_page;
|
||||
int m_bank;
|
||||
int m_ramsize;
|
||||
|
||||
int m_cru_horizon;
|
||||
int m_cru_phoenix;
|
||||
bool m_timode;
|
||||
bool m_32k_installed;
|
||||
bool m_split_mode;
|
||||
bool m_rambo_mode;
|
||||
bool m_hideswitch;
|
||||
bool m_use_rambo;
|
||||
bool m_genmod_fix;
|
||||
int m_cru_base_horizon;
|
||||
int m_cru_base_phoenix;
|
||||
|
||||
// Debugging
|
||||
int m_current_bank;
|
||||
int m_current_page;
|
||||
};
|
||||
|
||||
} } } // end namespace bus::ti99::peb
|
||||
|
Loading…
Reference in New Issue
Block a user