mirror of
https://github.com/holub/mame
synced 2025-10-04 16:34:53 +03:00
(MESS) New driver added: Xerox Alto 2 [Juergen Buchmueller]
out of whatsnew: Did not add Unicode support for debugger from branch yet, for now few special chars are converted to be plain ASCII
This commit is contained in:
parent
92d6b69712
commit
c046734f76
45
.gitattributes
vendored
45
.gitattributes
vendored
@ -1430,6 +1430,46 @@ src/emu/cpu/adsp2100/adsp2100.h svneol=native#text/plain
|
||||
src/emu/cpu/alph8201/8201dasm.c svneol=native#text/plain
|
||||
src/emu/cpu/alph8201/alph8201.c svneol=native#text/plain
|
||||
src/emu/cpu/alph8201/alph8201.h svneol=native#text/plain
|
||||
src/emu/cpu/alto2/a2curt.c svneol=native#text/plain
|
||||
src/emu/cpu/alto2/a2curt.h svneol=native#text/plain
|
||||
src/emu/cpu/alto2/a2dht.c svneol=native#text/plain
|
||||
src/emu/cpu/alto2/a2dht.h svneol=native#text/plain
|
||||
src/emu/cpu/alto2/a2disk.c svneol=native#text/plain
|
||||
src/emu/cpu/alto2/a2disk.h svneol=native#text/plain
|
||||
src/emu/cpu/alto2/a2disp.c svneol=native#text/plain
|
||||
src/emu/cpu/alto2/a2disp.h svneol=native#text/plain
|
||||
src/emu/cpu/alto2/a2dvt.c svneol=native#text/plain
|
||||
src/emu/cpu/alto2/a2dvt.h svneol=native#text/plain
|
||||
src/emu/cpu/alto2/a2dwt.c svneol=native#text/plain
|
||||
src/emu/cpu/alto2/a2dwt.h svneol=native#text/plain
|
||||
src/emu/cpu/alto2/a2emu.c svneol=native#text/plain
|
||||
src/emu/cpu/alto2/a2emu.h svneol=native#text/plain
|
||||
src/emu/cpu/alto2/a2ether.c svneol=native#text/plain
|
||||
src/emu/cpu/alto2/a2ether.h svneol=native#text/plain
|
||||
src/emu/cpu/alto2/a2hw.c svneol=native#text/plain
|
||||
src/emu/cpu/alto2/a2hw.h svneol=native#text/plain
|
||||
src/emu/cpu/alto2/a2jkff.h svneol=native#text/plain
|
||||
src/emu/cpu/alto2/a2kbd.c svneol=native#text/plain
|
||||
src/emu/cpu/alto2/a2kbd.h svneol=native#text/plain
|
||||
src/emu/cpu/alto2/a2ksec.c svneol=native#text/plain
|
||||
src/emu/cpu/alto2/a2ksec.h svneol=native#text/plain
|
||||
src/emu/cpu/alto2/a2kwd.c svneol=native#text/plain
|
||||
src/emu/cpu/alto2/a2kwd.h svneol=native#text/plain
|
||||
src/emu/cpu/alto2/a2mem.c svneol=native#text/plain
|
||||
src/emu/cpu/alto2/a2mem.h svneol=native#text/plain
|
||||
src/emu/cpu/alto2/a2mouse.c svneol=native#text/plain
|
||||
src/emu/cpu/alto2/a2mouse.h svneol=native#text/plain
|
||||
src/emu/cpu/alto2/a2mrt.c svneol=native#text/plain
|
||||
src/emu/cpu/alto2/a2mrt.h svneol=native#text/plain
|
||||
src/emu/cpu/alto2/a2part.c svneol=native#text/plain
|
||||
src/emu/cpu/alto2/a2part.h svneol=native#text/plain
|
||||
src/emu/cpu/alto2/a2ram.c svneol=native#text/plain
|
||||
src/emu/cpu/alto2/a2ram.h svneol=native#text/plain
|
||||
src/emu/cpu/alto2/a2roms.c svneol=native#text/plain
|
||||
src/emu/cpu/alto2/a2roms.h svneol=native#text/plain
|
||||
src/emu/cpu/alto2/alto2cpu.c svneol=native#text/plain
|
||||
src/emu/cpu/alto2/alto2cpu.h svneol=native#text/plain
|
||||
src/emu/cpu/alto2/alto2dsm.c svneol=native#text/plain
|
||||
src/emu/cpu/am29000/am29000.c svneol=native#text/plain
|
||||
src/emu/cpu/am29000/am29000.h svneol=native#text/plain
|
||||
src/emu/cpu/am29000/am29dasm.c svneol=native#text/plain
|
||||
@ -2192,6 +2232,8 @@ src/emu/imagedev/cassette.c svneol=native#text/plain
|
||||
src/emu/imagedev/cassette.h svneol=native#text/plain
|
||||
src/emu/imagedev/chd_cd.c svneol=native#text/plain
|
||||
src/emu/imagedev/chd_cd.h svneol=native#text/plain
|
||||
src/emu/imagedev/diablo.c svneol=native#text/plain
|
||||
src/emu/imagedev/diablo.h svneol=native#text/plain
|
||||
src/emu/imagedev/flopdrv.c svneol=native#text/plain
|
||||
src/emu/imagedev/flopdrv.h svneol=native#text/plain
|
||||
src/emu/imagedev/floppy.c svneol=native#text/plain
|
||||
@ -2352,6 +2394,8 @@ src/emu/machine/cs4031.c svneol=native#text/plain
|
||||
src/emu/machine/cs4031.h svneol=native#text/plain
|
||||
src/emu/machine/cs8221.c svneol=native#text/plain
|
||||
src/emu/machine/cs8221.h svneol=native#text/plain
|
||||
src/emu/machine/diablo_hd.c svneol=native#text/plain
|
||||
src/emu/machine/diablo_hd.h svneol=native#text/plain
|
||||
src/emu/machine/dp8390.c svneol=native#text/plain
|
||||
src/emu/machine/dp8390.h svneol=native#text/plain
|
||||
src/emu/machine/ds1204.c svneol=native#text/plain
|
||||
@ -7534,6 +7578,7 @@ src/mess/drivers/alesis.c svneol=native#text/plain
|
||||
src/mess/drivers/alphasma.c svneol=native#text/plain
|
||||
src/mess/drivers/alphatro.c svneol=native#text/plain
|
||||
src/mess/drivers/altair.c svneol=native#text/plain
|
||||
src/mess/drivers/alto2.c svneol=native#text/plain
|
||||
src/mess/drivers/altos5.c svneol=native#text/plain
|
||||
src/mess/drivers/amico2k.c svneol=native#text/plain
|
||||
src/mess/drivers/amiga.c svneol=native#text/plain
|
||||
|
90
src/emu/cpu/alto2/a2curt.c
Normal file
90
src/emu/cpu/alto2/a2curt.c
Normal file
@ -0,0 +1,90 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Xerox AltoII cursor task
|
||||
*
|
||||
* Copyright Juergen Buchmueller <pullmoll@t-online.de>
|
||||
*
|
||||
* Licenses: MAME, GPLv2
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include "alto2cpu.h"
|
||||
|
||||
/**
|
||||
* @brief disable the cursor task and set the curt_blocks flag
|
||||
*/
|
||||
void alto2_cpu_device::f1_early_curt_block()
|
||||
{
|
||||
m_dsp.curt_blocks = true;
|
||||
m_task_wakeup &= ~(1 << m_task);
|
||||
LOG((LOG_CURT,2," BLOCK %s\n", task_name(m_task)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief f2_load_xpreg late: load the x position register from BUS[6-15]
|
||||
*/
|
||||
void alto2_cpu_device::f2_late_load_xpreg()
|
||||
{
|
||||
m_dsp.xpreg = X_RDBITS(m_bus,16,6,15);
|
||||
LOG((LOG_CURT, 9," XPREG<- BUS[6-15] (%#o)\n", m_dsp.xpreg));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief f2_load_csr late: load the cursor shift register from BUS[0-15]
|
||||
*
|
||||
* Shift CSR to xpreg % 16 position to make it easier to
|
||||
* to handle the word xor in unload_word().
|
||||
* <PRE>
|
||||
* xpreg % 16 cursor bits
|
||||
* [ first word ][ second word ]
|
||||
* ----------------------------------------------
|
||||
* 0 xxxxxxxxxxxxxxxx0000000000000000
|
||||
* 1 0xxxxxxxxxxxxxxxx000000000000000
|
||||
* 2 00xxxxxxxxxxxxxxxx00000000000000
|
||||
* ...
|
||||
* 14 00000000000000xxxxxxxxxxxxxxxx00
|
||||
* 15 000000000000000xxxxxxxxxxxxxxxx0
|
||||
* </PRE>
|
||||
*/
|
||||
void alto2_cpu_device::f2_late_load_csr()
|
||||
{
|
||||
m_dsp.csr = m_bus;
|
||||
LOG((LOG_CURT, m_dsp.csr ? 2 : 9," CSR<- BUS (%#o)\n", m_dsp.csr));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief curt_activate: called by the CPU when the cursor task becomes active
|
||||
*/
|
||||
void alto2_cpu_device::activate_curt()
|
||||
{
|
||||
m_task_wakeup &= ~(1 << m_task);
|
||||
m_dsp.curt_wakeup = false;
|
||||
|
||||
int x = 01777 - m_dsp.xpreg;
|
||||
UINT32 bits = m_dsp.csr << (16 - (x & 15));
|
||||
m_dsp.cursor0 = static_cast<UINT16>(bits >> 16);
|
||||
m_dsp.cursor1 = static_cast<UINT16>(bits);
|
||||
m_dsp.curxpos = x / 16;
|
||||
}
|
||||
|
||||
/** @brief initialize the cursor task F1 and F2 functions */
|
||||
void alto2_cpu_device::init_curt(int task)
|
||||
{
|
||||
set_f1(task, f1_block, &alto2_cpu_device::f1_early_curt_block, 0);
|
||||
set_f2(task, f2_curt_load_xpreg, 0, &alto2_cpu_device::f2_late_load_xpreg);
|
||||
set_f2(task, f2_curt_load_csr, 0, &alto2_cpu_device::f2_late_load_csr);
|
||||
m_active_callback[task] = &alto2_cpu_device::activate_curt;
|
||||
}
|
||||
|
||||
void alto2_cpu_device::exit_curt()
|
||||
{
|
||||
// nothing to do yet
|
||||
}
|
||||
|
||||
void alto2_cpu_device::reset_curt()
|
||||
{
|
||||
m_dsp.curt_blocks = false;
|
||||
m_dsp.xpreg = 0;
|
||||
m_dsp.csr = 0;
|
||||
m_dsp.curxpos = 0;
|
||||
m_dsp.cursor0 = m_dsp.cursor1 = 0;
|
||||
}
|
30
src/emu/cpu/alto2/a2curt.h
Normal file
30
src/emu/cpu/alto2/a2curt.h
Normal file
@ -0,0 +1,30 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Xerox AltoII cursor task (CURT)
|
||||
*
|
||||
* Copyright Juergen Buchmueller <pullmoll@t-online.de>
|
||||
*
|
||||
* Licenses: MAME, GPLv2
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifdef ALTO2_DEFINE_CONSTANTS
|
||||
|
||||
#else // ALTO2_DEFINE_CONSTANTS
|
||||
#ifndef _A2CURT_H_
|
||||
#define _A2CURT_H_
|
||||
|
||||
//! F2 functions for cursor task
|
||||
enum {
|
||||
f2_curt_load_xpreg = f2_task_10, //!< f2 10: load x position register
|
||||
f2_curt_load_csr = f2_task_11, //!< f2 11: load cursor shift register
|
||||
};
|
||||
|
||||
void f1_early_curt_block(); //!< f1_curt_block early: disable the cursor task and set the curt_blocks flag
|
||||
void f2_late_load_xpreg(); //!< f2_load_xpreg late: load the x position register from BUS[6-15]
|
||||
void f2_late_load_csr(); //!< f2_load_csr late: load the cursor shift register from BUS[0-15]
|
||||
void activate_curt(); //!< curt_activate: called by the CPU when the cursor task becomes active
|
||||
void init_curt(int task = task_curt); //!< initialize cursor task
|
||||
void exit_curt(); //!< deinitialize cursor task
|
||||
void reset_curt(); //!< reset cursor task
|
||||
#endif // _A2CURT_H_
|
||||
#endif // ALTO2_DEFINE_CONSTANTS
|
69
src/emu/cpu/alto2/a2dht.c
Normal file
69
src/emu/cpu/alto2/a2dht.c
Normal file
@ -0,0 +1,69 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Xerox AltoII display horizontal task
|
||||
*
|
||||
* Copyright Juergen Buchmueller <pullmoll@t-online.de>
|
||||
*
|
||||
* Licenses: MAME, GPLv2
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include "alto2cpu.h"
|
||||
|
||||
/**
|
||||
* @brief f1_dht_block early: disable the display word task
|
||||
*/
|
||||
void alto2_cpu_device::f1_early_dht_block()
|
||||
{
|
||||
m_dsp.dht_blocks = true;
|
||||
// clear the wakeup for the display horizontal task
|
||||
m_task_wakeup &= ~(1 << m_task);
|
||||
LOG((LOG_DHT,2," BLOCK %s\n", task_name(m_task)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief f2_dht_setmode late: set the next scanline's mode inverse and half clock and branch
|
||||
*
|
||||
* BUS[0] selects the pixel clock (0), or half pixel clock (1)
|
||||
* BUS[1] selects normal mode (0), or inverse mode (1)
|
||||
*
|
||||
* The current BUS[0] drives the NEXT[09] line, i.e. branches to 0 or 1
|
||||
*/
|
||||
void alto2_cpu_device::f2_late_dht_setmode()
|
||||
{
|
||||
UINT16 r = X_RDBITS(m_bus,16,0,0);
|
||||
m_dsp.setmode = m_bus;
|
||||
LOG((LOG_DHT,2," SETMODE<- BUS (%#o), branch on BUS[0] (%#o | %#o)\n", m_bus, m_next2, r));
|
||||
m_next2 |= r;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief called by the CPU when the display horizontal task becomes active
|
||||
*/
|
||||
void alto2_cpu_device::activate_dht()
|
||||
{
|
||||
m_task_wakeup &= ~(1 << m_task);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief initialize the display horizontal task
|
||||
*
|
||||
* @param task task number
|
||||
*/
|
||||
void alto2_cpu_device::init_dht(int task)
|
||||
{
|
||||
set_f1(task, f1_block, &alto2_cpu_device::f1_early_dht_block, 0);
|
||||
set_f2(task, f2_dht_evenfield, 0, &alto2_cpu_device::f2_late_evenfield);
|
||||
set_f2(task, f2_dht_setmode, 0, &alto2_cpu_device::f2_late_dht_setmode);
|
||||
m_active_callback[task] = &alto2_cpu_device::activate_dht;
|
||||
}
|
||||
|
||||
void alto2_cpu_device::exit_dht()
|
||||
{
|
||||
// nothing to do yet
|
||||
}
|
||||
|
||||
void alto2_cpu_device::reset_dht()
|
||||
{
|
||||
m_dsp.dht_blocks = true;
|
||||
m_dsp.setmode = 0;
|
||||
}
|
29
src/emu/cpu/alto2/a2dht.h
Normal file
29
src/emu/cpu/alto2/a2dht.h
Normal file
@ -0,0 +1,29 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Xerox AltoII display horizontal task (DHT)
|
||||
*
|
||||
* Copyright Juergen Buchmueller <pullmoll@t-online.de>
|
||||
*
|
||||
* Licenses: MAME, GPLv2
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifdef ALTO2_DEFINE_CONSTANTS
|
||||
|
||||
#else // ALTO2_DEFINE_CONSTANTS
|
||||
#ifndef _A2DHT_H_
|
||||
#define _A2DHT_H_
|
||||
|
||||
//! F2 functions for display horizontal task
|
||||
enum {
|
||||
f2_dht_evenfield = f2_task_10, //!< f2 10: load even field
|
||||
f2_dht_setmode = f2_task_11, //!< f2 11: set mode
|
||||
};
|
||||
|
||||
void f1_early_dht_block(); //!< F1 func: disable the display word task
|
||||
void f2_late_dht_setmode(); //!< F2 func: set the next scanline's mode inverse and half clock and branch
|
||||
void activate_dht(); //!< called by the CPU when the display horizontal task becomes active
|
||||
void init_dht(int task = task_dht); //!< initialize display horizontal task
|
||||
void exit_dht(); //!< deinitialize display horizontal task
|
||||
void reset_dht(); //!< reset the display horizontal task
|
||||
#endif // _A2DHT_H_
|
||||
#endif // ALTO2_DEFINE_CONSTANTS
|
1897
src/emu/cpu/alto2/a2disk.c
Normal file
1897
src/emu/cpu/alto2/a2disk.c
Normal file
File diff suppressed because it is too large
Load Diff
109
src/emu/cpu/alto2/a2disk.h
Normal file
109
src/emu/cpu/alto2/a2disk.h
Normal file
@ -0,0 +1,109 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Xerox AltoII disk controller block
|
||||
*
|
||||
* Copyright Juergen Buchmueller <pullmoll@t-online.de>
|
||||
*
|
||||
* Licenses: MAME, GPLv2
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifdef ALTO2_DEFINE_CONSTANTS
|
||||
|
||||
#else // ALTO2_DEFINE_CONSTANTS
|
||||
#ifndef _A2DISK_H_
|
||||
#define _A2DISK_H_
|
||||
|
||||
diablo_hd_device* m_drive[2]; //!< two diablo_hd_device drives
|
||||
|
||||
//! disk controller context
|
||||
struct {
|
||||
UINT8 drive; //!< selected drive from KADDR[14] (written to data out with SENDADR)
|
||||
UINT16 kaddr; //!< A[0-15] disk hardware address (sector, cylinder, head, drive, restore)
|
||||
UINT16 kadr; //!< C[0-15] with read/write/check modes for header, label and data
|
||||
UINT16 kstat; //!< S[0-15] disk status
|
||||
UINT16 kcom; //!< disk command (5 bits kcom[1-5])
|
||||
UINT8 krecno; //!< record number (2 bits indexing header, label, data, -/-)
|
||||
UINT8 egate; //!< current erase gate signal to the DIABLO hd
|
||||
UINT8 wrgate; //!< current write gate signal to the DIABLO hd
|
||||
UINT8 rdgate; //!< current read gate signal to the DIABLO hd
|
||||
UINT32 shiftin; //!< input shift register
|
||||
UINT32 shiftout; //!< output shift register
|
||||
UINT32 datain; //!< disk data in latch
|
||||
UINT32 dataout; //!< disk data out latch
|
||||
UINT8 krwc; //!< read/write/check for current record
|
||||
UINT8 kfer; //!< disk fatal error signal state
|
||||
UINT8 wdtskena; //!< disk word task enable (active low)
|
||||
UINT8 wddone; //!< previous state of WDDONE
|
||||
UINT8 wdinit0; //!< disk word task init at the early microcycle
|
||||
UINT8 wdinit; //!< disk word task init at the late microcycle
|
||||
UINT8 strobe; //!< strobe (still) active
|
||||
emu_timer* strobon_timer; //!< set strobe on timer
|
||||
UINT8 bitclk; //!< current bitclk state (either crystal clock, or rdclk from the drive)
|
||||
#if USE_BITCLK_TIMER
|
||||
emu_timer* bitclk_timer; //!< bit clock timer
|
||||
#else
|
||||
int bitclk_time[2]; //!< per drive time in clocks per bit
|
||||
#endif
|
||||
UINT8 datin; //!< current datin from the drive
|
||||
UINT8 bitcount; //!< bit counter
|
||||
UINT8 carry; //!< carry output of the bitcounter
|
||||
UINT8 seclate; //!< sector late (monoflop output)
|
||||
emu_timer* seclate_timer; //!< sector late timer
|
||||
UINT8 seekok; //!< seekok state (SKINC' & LAI' & ff_44a.Q')
|
||||
UINT8 ok_to_run; //!< ok to run signal (set to 1 some time after reset)
|
||||
emu_timer* ok_to_run_timer; //!< ok to run timer
|
||||
UINT8 ready_mf31a; //!< ready monoflop 31a
|
||||
emu_timer* ready_timer; //!< ready timer
|
||||
UINT8 seclate_mf31b; //!< seclate monoflop 31b
|
||||
jkff_t ff_21a; //!< JK flip-flop 21a (sector task)
|
||||
jkff_t ff_21a_old; //!< -"- previous state
|
||||
jkff_t ff_21b; //!< JK flip-flop 21b (sector task)
|
||||
jkff_t ff_22a; //!< JK flip-flop 22a (sector task)
|
||||
jkff_t ff_22b; //!< JK flip-flop 22b (sector task)
|
||||
jkff_t ff_43b; //!< JK flip-flop 43b (word task)
|
||||
jkff_t ff_53a; //!< JK flip-flop 53a (word task)
|
||||
jkff_t ff_43a; //!< JK flip-flop 43a (word task)
|
||||
jkff_t ff_53b; //!< brief JK flip-flop 53b (word task)
|
||||
jkff_t ff_44a; //!< JK flip-flop 44a (LAI' clocked)
|
||||
jkff_t ff_44b; //!< JK flip-flop 44b (CKSUM)
|
||||
jkff_t ff_45a; //!< JK flip-flop 45a (ready latch)
|
||||
jkff_t ff_45b; //!< JK flip-flop 45b (seqerr latch)
|
||||
} m_dsk;
|
||||
|
||||
jkff_t m_sysclka0[4]; //!< simulate previous sysclka
|
||||
jkff_t m_sysclka1[4]; //!< simulate current sysclka
|
||||
jkff_t m_sysclkb0[4]; //!< simulate previous sysclkb
|
||||
jkff_t m_sysclkb1[4]; //!< simulate current sysclkb
|
||||
|
||||
void kwd_timing(int bitclk, int datin, int block); //!< disk word timing
|
||||
TIMER_CALLBACK_MEMBER( disk_seclate ); //!< timer callback to take away the SECLATE pulse (monoflop)
|
||||
TIMER_CALLBACK_MEMBER( disk_ok_to_run ); //!< timer callback to take away the OK TO RUN pulse (reset)
|
||||
TIMER_CALLBACK_MEMBER( disk_strobon ); //!< timer callback to pulse the STROBE' signal to the drive
|
||||
TIMER_CALLBACK_MEMBER( disk_ready_mf31a ); //!< timer callback to change the READY monoflop 31a
|
||||
#if USE_BITCLK_TIMER
|
||||
TIMER_CALLBACK_MEMBER( disk_bitclk ); //!< callback to update the disk controller with a new bitclk
|
||||
#else
|
||||
void disk_bitclk(void *ptr, int arg); //!< function to update the disk controller with a new bitclk
|
||||
#endif
|
||||
void disk_block(int task); //!< called if one of the disk tasks (task_kwd or task_ksec) blocks
|
||||
void bs_early_read_kstat(); //!< bus source: bus driven by disk status register KSTAT
|
||||
void bs_early_read_kdata(); //!< bus source: bus driven by disk data register KDATA input
|
||||
void f1_late_strobe(); //!< F1 func: initiates a disk seek
|
||||
void f1_late_load_kstat(); //!< F1 func: load disk status register
|
||||
void f1_late_load_kdata(); //!< F1 func: load data out register, or the disk address register
|
||||
void f1_late_increcno(); //!< F1 func: advances shift registers holding KADR
|
||||
void f1_late_clrstat(); //!< F1 func: reset all error latches
|
||||
void f1_late_load_kcom(); //!< F1 func: load the KCOM register from bus
|
||||
void f1_late_load_kadr(); //!< F1 func: load the KADR register from bus
|
||||
void f2_late_init(); //!< F2 func: branch on disk word task active and init
|
||||
void f2_late_rwc(); //!< F2 func: branch on read/write/check state of the current record
|
||||
void f2_late_recno(); //!< F2 func: branch on the current record number by a lookup table
|
||||
void f2_late_xfrdat(); //!< F2 func: branch on the data transfer state
|
||||
void f2_late_swrnrdy(); //!< F2 func: branch on the disk ready signal
|
||||
void f2_late_nfer(); //!< f2_nfer late: branch on the disk fatal error condition
|
||||
void f2_late_strobon(); //!< f2_strobon late: branch on the seek busy status
|
||||
void init_disk(); //!< initialize the disk controller
|
||||
void exit_disk(); //!< deinitialize the disk controller
|
||||
void reset_disk(); //!< reset the disk controller
|
||||
#endif // _A2DISK_H_
|
||||
#endif // ALTO2_DEFINE_CONSTANTS
|
876
src/emu/cpu/alto2/a2disp.c
Normal file
876
src/emu/cpu/alto2/a2disp.c
Normal file
@ -0,0 +1,876 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Xerox AltoII display interface
|
||||
*
|
||||
* Copyright Juergen Buchmueller <pullmoll@t-online.de>
|
||||
*
|
||||
* Licenses: MAME, GPLv2
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include "alto2cpu.h"
|
||||
#include "a2roms.h"
|
||||
|
||||
/**
|
||||
* @brief PROM a38 contains the STOPWAKE' and MBEMBPTY' signals for the FIFO
|
||||
* <PRE>
|
||||
* The inputs to a38 are the UNLOAD counter RA[0-3] and the DDR<- counter
|
||||
* WA[0-3], and the designer decided to reverse the address lines :-)
|
||||
*
|
||||
* a38 counter
|
||||
* -------------
|
||||
* A0 RA[0]
|
||||
* A1 RA[1]
|
||||
* A2 RA[2]
|
||||
* A3 RA[3]
|
||||
* A4 WA[0]
|
||||
* A5 WA[1]
|
||||
* A6 WA[2]
|
||||
* A7 WA[3]
|
||||
*
|
||||
* Only two bits of a38 are used:
|
||||
* O1 (002) = STOPWAKE'
|
||||
* O3 (010) = MBEMPTY'
|
||||
* </PRE>
|
||||
*/
|
||||
|
||||
//! P3601 256x4 BPROM; display FIFO control: STOPWAKE, MBEMPTY
|
||||
static const prom_load_t pl_displ_a38 =
|
||||
{
|
||||
"displ.a38",
|
||||
0,
|
||||
"fd30beb7",
|
||||
"65e4a19ba4ff748d525122128c514abedd55d866",
|
||||
/* size */ 0400,
|
||||
/* amap */ AMAP_REVERSE_0_7, // reverse address lines A0-A7
|
||||
/* axor */ 0,
|
||||
/* dxor */ 0,
|
||||
/* width */ 4,
|
||||
/* shift */ 0,
|
||||
/* dmap */ DMAP_DEFAULT,
|
||||
/* dand */ ZERO,
|
||||
/* type */ sizeof(UINT8)
|
||||
};
|
||||
|
||||
//! PROM a38 bit O1 is STOPWAKE' (stop DWT if bit is zero)
|
||||
#define FIFO_STOPWAKE(a38) (0 == (a38 & disp_a38_STOPWAKE) ? true : false)
|
||||
|
||||
//! PROM a38 bit O3 is MBEMPTY' (FIFO is empty if bit is zero)
|
||||
#define FIFO_MBEMPTY(a38) (0 == (a38 & disp_a38_MBEMPTY) ? true : false)
|
||||
|
||||
/**
|
||||
* @brief emulation of PROM a63 in the display schematics page 8
|
||||
* <PRE>
|
||||
* The PROM's address lines are driven by a clock CLK, which is
|
||||
* pixel clock / 24, and an inverted half-scanline signal H[1]'.
|
||||
*
|
||||
* It is 32x8 bits and its output bits (B) are connected to the
|
||||
* signals, as well as its own address lines (A) through a latch
|
||||
* of the type SN74774 like this:
|
||||
*
|
||||
* PROM 174 A others
|
||||
* ------------------------
|
||||
* B0 D5 - HBLANK
|
||||
* B1 D0 - HSYNC
|
||||
* B2 D4 A0 -
|
||||
* B3 D1 A1 -
|
||||
* B4 D3 A2 -
|
||||
* B5 D2 A3 -
|
||||
* B6 - - SCANEND
|
||||
* B7 - - HLCGATE
|
||||
* ------------------------
|
||||
* H[1]' - A4 -
|
||||
*
|
||||
* The display_state_machine() is called at a rate of pixelclock/24.
|
||||
*
|
||||
* Decoded states of this PROM:
|
||||
*
|
||||
* STATE PROM binary HBLANK HSYNC NEXT SCANEND HLCGATE
|
||||
* ----------------------------------------------------------
|
||||
* 000 0007 00000111 1 1 001 0 0
|
||||
* 001 0013 00001011 1 1 002 0 0
|
||||
* 002 0015 00001101 1 0 003 0 0
|
||||
* 003 0021 00010001 1 0 004 0 0
|
||||
* 004 0024 00010100 0 0 005 0 0
|
||||
* 005 0030 00011000 0 0 006 0 0
|
||||
* 006 0034 00011100 0 0 007 0 0
|
||||
* 007 0040 00100000 0 0 010 0 0
|
||||
* 010 0044 00100100 0 0 011 0 0
|
||||
* 011 0050 00101000 0 0 012 0 0
|
||||
* 012 0054 00101100 0 0 013 0 0
|
||||
* 013 0060 00110000 0 0 014 0 0
|
||||
* 014 0064 00110100 0 0 015 0 0
|
||||
* 015 0070 00111000 0 0 016 0 0
|
||||
* 016 0074 00111100 0 0 017 0 0
|
||||
* 017 0200 10000000 0 0 000 0 1
|
||||
* 020 0004 00000100 0 0 001 0 0
|
||||
* 021 0010 00001000 0 0 002 0 0
|
||||
* 022 0014 00001100 0 0 003 0 0
|
||||
* 023 0020 00010000 0 0 004 0 0
|
||||
* 024 0024 00010100 0 0 005 0 0
|
||||
* 025 0030 00011000 0 0 006 0 0
|
||||
* 026 0034 00011100 0 0 007 0 0
|
||||
* 027 0040 00100000 0 0 010 0 0
|
||||
* 030 0044 00100100 0 0 011 0 0
|
||||
* 031 0050 00101000 0 0 012 0 0
|
||||
* 032 0054 00101100 0 0 013 0 0
|
||||
* 033 0060 00110000 0 0 014 0 0
|
||||
* 034 0064 00110100 0 0 015 0 0
|
||||
* 035 0070 00111000 0 0 016 0 0
|
||||
* 036 0175 01111101 1 0 017 1 0
|
||||
* 037 0203 10000011 1 1 000 0 1
|
||||
* </PRE>
|
||||
*/
|
||||
|
||||
//! 82S23 32x8 BPROM; display HBLANK, HSYNC, SCANEND, HLCGATE ...
|
||||
static const prom_load_t pl_displ_a63 =
|
||||
{
|
||||
"displ.a63",
|
||||
0,
|
||||
"82a20d60",
|
||||
"39d90703568be5419ada950e112d99227873fdea",
|
||||
/* size */ 0040,
|
||||
/* amap */ AMAP_DEFAULT,
|
||||
/* axor */ 0,
|
||||
/* dxor */ 0,
|
||||
/* width */ 8,
|
||||
/* shift */ 0,
|
||||
/* dmap */ DMAP_DEFAULT,
|
||||
/* dand */ ZERO,
|
||||
/* type */ sizeof(UINT8)
|
||||
};
|
||||
|
||||
//!< test the HBLANK (horizontal blanking) signal in PROM a63 being high
|
||||
#define A63_HBLANK(a) ((a & disp_a63_HBLANK) ? true : false)
|
||||
|
||||
//!< test the HSYNC (horizontal synchonisation) signal in PROM a63 being high
|
||||
#define A63_HSYNC(a) ((a & disp_a63_HSYNC) ? true : false)
|
||||
|
||||
//!< test the SCANEND (scanline end) signal in PROM a63 being high
|
||||
#define A63_SCANEND(a) ((a & disp_a63_SCANEND) ? true : false)
|
||||
|
||||
//!< test the HLCGATE (horz. line counter gate) signal in PROM a63 being high
|
||||
#define A63_HLCGATE(a) ((a & disp_a63_HLCGATE) ? true : false)
|
||||
|
||||
/**
|
||||
* @brief PROM a66 is a 256x4 bit (type 3601)
|
||||
* <PRE>
|
||||
* Address lines are driven by H[1] to H[128] of the the horz. line counters.
|
||||
* PROM is enabled when H[256] and H[512] are both 0.
|
||||
*
|
||||
* Q1 is VSYNC for the odd field (with H1024=0)
|
||||
* Q2 is VSYNC for the even field (with H1024=1)
|
||||
* Q3 is VBLANK for the odd field (with H1024=0)
|
||||
* Q4 is VBLANK for the even field (with H1024=1)
|
||||
* </PRE>
|
||||
*/
|
||||
|
||||
//! P3601 256x4 BPROM; display VSYNC and VBLANK
|
||||
static const prom_load_t pl_displ_a66 =
|
||||
{
|
||||
"displ.a66",
|
||||
0,
|
||||
"9f91aad9",
|
||||
"69b1d4c71f4e18103112e8601850c2654e9265cf",
|
||||
/* size */ 0400,
|
||||
/* amap */ AMAP_DEFAULT,
|
||||
/* axor */ 0,
|
||||
/* dxor */ 0,
|
||||
/* width */ 4,
|
||||
/* shift */ 0,
|
||||
/* dmap */ DMAP_DEFAULT,
|
||||
/* dand */ ZERO,
|
||||
/* type */ sizeof(UINT8)
|
||||
};
|
||||
|
||||
//! test the VSYNC (vertical synchronisation) signal in PROM a66 being high
|
||||
#define A66_VSYNC(a) (a & (HLC1024 ? disp_a66_VSYNC_ODD : disp_a66_VSYNC_EVEN) ? false : true)
|
||||
|
||||
//! test the VBLANK (vertical blanking) signal in PROM a66 being high
|
||||
#define A66_VBLANK(a) (a & (HLC1024 ? disp_a66_VBLANK_ODD : disp_a66_VBLANK_EVEN) ? false : true)
|
||||
|
||||
/**
|
||||
* @brief double the bits for a byte (left and right of display word) to a word
|
||||
*/
|
||||
static const UINT16 double_bits[256] = {
|
||||
0x0000,0x0003,0x000c,0x000f,0x0030,0x0033,0x003c,0x003f,
|
||||
0x00c0,0x00c3,0x00cc,0x00cf,0x00f0,0x00f3,0x00fc,0x00ff,
|
||||
0x0300,0x0303,0x030c,0x030f,0x0330,0x0333,0x033c,0x033f,
|
||||
0x03c0,0x03c3,0x03cc,0x03cf,0x03f0,0x03f3,0x03fc,0x03ff,
|
||||
0x0c00,0x0c03,0x0c0c,0x0c0f,0x0c30,0x0c33,0x0c3c,0x0c3f,
|
||||
0x0cc0,0x0cc3,0x0ccc,0x0ccf,0x0cf0,0x0cf3,0x0cfc,0x0cff,
|
||||
0x0f00,0x0f03,0x0f0c,0x0f0f,0x0f30,0x0f33,0x0f3c,0x0f3f,
|
||||
0x0fc0,0x0fc3,0x0fcc,0x0fcf,0x0ff0,0x0ff3,0x0ffc,0x0fff,
|
||||
0x3000,0x3003,0x300c,0x300f,0x3030,0x3033,0x303c,0x303f,
|
||||
0x30c0,0x30c3,0x30cc,0x30cf,0x30f0,0x30f3,0x30fc,0x30ff,
|
||||
0x3300,0x3303,0x330c,0x330f,0x3330,0x3333,0x333c,0x333f,
|
||||
0x33c0,0x33c3,0x33cc,0x33cf,0x33f0,0x33f3,0x33fc,0x33ff,
|
||||
0x3c00,0x3c03,0x3c0c,0x3c0f,0x3c30,0x3c33,0x3c3c,0x3c3f,
|
||||
0x3cc0,0x3cc3,0x3ccc,0x3ccf,0x3cf0,0x3cf3,0x3cfc,0x3cff,
|
||||
0x3f00,0x3f03,0x3f0c,0x3f0f,0x3f30,0x3f33,0x3f3c,0x3f3f,
|
||||
0x3fc0,0x3fc3,0x3fcc,0x3fcf,0x3ff0,0x3ff3,0x3ffc,0x3fff,
|
||||
0xc000,0xc003,0xc00c,0xc00f,0xc030,0xc033,0xc03c,0xc03f,
|
||||
0xc0c0,0xc0c3,0xc0cc,0xc0cf,0xc0f0,0xc0f3,0xc0fc,0xc0ff,
|
||||
0xc300,0xc303,0xc30c,0xc30f,0xc330,0xc333,0xc33c,0xc33f,
|
||||
0xc3c0,0xc3c3,0xc3cc,0xc3cf,0xc3f0,0xc3f3,0xc3fc,0xc3ff,
|
||||
0xcc00,0xcc03,0xcc0c,0xcc0f,0xcc30,0xcc33,0xcc3c,0xcc3f,
|
||||
0xccc0,0xccc3,0xcccc,0xcccf,0xccf0,0xccf3,0xccfc,0xccff,
|
||||
0xcf00,0xcf03,0xcf0c,0xcf0f,0xcf30,0xcf33,0xcf3c,0xcf3f,
|
||||
0xcfc0,0xcfc3,0xcfcc,0xcfcf,0xcff0,0xcff3,0xcffc,0xcfff,
|
||||
0xf000,0xf003,0xf00c,0xf00f,0xf030,0xf033,0xf03c,0xf03f,
|
||||
0xf0c0,0xf0c3,0xf0cc,0xf0cf,0xf0f0,0xf0f3,0xf0fc,0xf0ff,
|
||||
0xf300,0xf303,0xf30c,0xf30f,0xf330,0xf333,0xf33c,0xf33f,
|
||||
0xf3c0,0xf3c3,0xf3cc,0xf3cf,0xf3f0,0xf3f3,0xf3fc,0xf3ff,
|
||||
0xfc00,0xfc03,0xfc0c,0xfc0f,0xfc30,0xfc33,0xfc3c,0xfc3f,
|
||||
0xfcc0,0xfcc3,0xfccc,0xfccf,0xfcf0,0xfcf3,0xfcfc,0xfcff,
|
||||
0xff00,0xff03,0xff0c,0xff0f,0xff30,0xff33,0xff3c,0xff3f,
|
||||
0xffc0,0xffc3,0xffcc,0xffcf,0xfff0,0xfff3,0xfffc,0xffff
|
||||
};
|
||||
|
||||
#define HLC1 ((m_dsp.hlc >> 0) & 1) //!< horizontal line counter bit 0 (mid of the scanline)
|
||||
#define HLC2 ((m_dsp.hlc >> 1) & 1) //!< horizontal line counter bit 1
|
||||
#define HLC4 ((m_dsp.hlc >> 2) & 1) //!< horizontal line counter bit 2
|
||||
#define HLC8 ((m_dsp.hlc >> 3) & 1) //!< horizontal line counter bit 3
|
||||
#define HLC16 ((m_dsp.hlc >> 4) & 1) //!< horizontal line counter bit 4
|
||||
#define HLC32 ((m_dsp.hlc >> 5) & 1) //!< horizontal line counter bit 5
|
||||
#define HLC64 ((m_dsp.hlc >> 6) & 1) //!< horizontal line counter bit 6
|
||||
#define HLC128 ((m_dsp.hlc >> 7) & 1) //!< horizontal line counter bit 7
|
||||
#define HLC256 ((m_dsp.hlc >> 8) & 1) //!< horizontal line counter bit 8
|
||||
#define HLC512 ((m_dsp.hlc >> 9) & 1) //!< horizontal line counter bit 9
|
||||
#define HLC1024 ((m_dsp.hlc >> 10) & 1) //!< horizontal line counter bit 10 (odd/even field)
|
||||
|
||||
#define GET_SETMODE_SPEEDY(mode) X_RDBITS(mode,16,0,0) //!< get the pixel clock speed from a SETMODE<- bus value
|
||||
#define GET_SETMODE_INVERSE(mode) X_RDBITS(mode,16,1,1) //!< get the inverse video flag from a SETMODE<- bus value
|
||||
|
||||
//!< helper to extract A3-A0 from a PROM a63 value
|
||||
#define A63_NEXT(n) ((n >> 2) & 017)
|
||||
|
||||
//! update the internal bitmap to a byte array
|
||||
void alto2_cpu_device::update_bitmap_word(UINT16* bitmap, int x, int y, UINT16 word)
|
||||
{
|
||||
// mixing with the cursor
|
||||
if (x == m_dsp.curxpos + 0)
|
||||
word ^= m_dsp.cursor0;
|
||||
if (x == m_dsp.curxpos + 1)
|
||||
word ^= m_dsp.cursor1;
|
||||
// no change?
|
||||
if (word == bitmap[x])
|
||||
return;
|
||||
bitmap[x] = word;
|
||||
UINT8* pix = m_dsp.scanline[y] + x * 16;
|
||||
*pix++ = (word >> 15) & 1;
|
||||
*pix++ = (word >> 14) & 1;
|
||||
*pix++ = (word >> 13) & 1;
|
||||
*pix++ = (word >> 12) & 1;
|
||||
*pix++ = (word >> 11) & 1;
|
||||
*pix++ = (word >> 10) & 1;
|
||||
*pix++ = (word >> 9) & 1;
|
||||
*pix++ = (word >> 8) & 1;
|
||||
*pix++ = (word >> 7) & 1;
|
||||
*pix++ = (word >> 6) & 1;
|
||||
*pix++ = (word >> 5) & 1;
|
||||
*pix++ = (word >> 4) & 1;
|
||||
*pix++ = (word >> 3) & 1;
|
||||
*pix++ = (word >> 2) & 1;
|
||||
*pix++ = (word >> 1) & 1;
|
||||
*pix++ = (word >> 0) & 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief unload the next word from the display FIFO and shift it to the screen
|
||||
*/
|
||||
void alto2_cpu_device::unload_word()
|
||||
{
|
||||
int x = m_unload_word;
|
||||
int y = ((m_dsp.hlc - m_dsp.vblank) & ~02001) ^ HLC1024;
|
||||
|
||||
if (y < 0 || y >= ALTO2_DISPLAY_HEIGHT || x >= ALTO2_DISPLAY_VISIBLE_WORDS)
|
||||
{
|
||||
m_unload_time = -1;
|
||||
return;
|
||||
}
|
||||
UINT16* bitmap = m_dsp.raw_bitmap + y * ALTO2_DISPLAY_SCANLINE_WORDS;
|
||||
UINT16 word = m_dsp.inverse;
|
||||
UINT8 a38 = m_disp_a38[m_dsp.ra * 16 + m_dsp.wa];
|
||||
if (FIFO_MBEMPTY(a38))
|
||||
{
|
||||
LOG((LOG_DISPL,1, " DSP FIFO underrun y:%d x:%d\n", y, x));
|
||||
}
|
||||
else
|
||||
{
|
||||
word ^= m_dsp.fifo[m_dsp.ra];
|
||||
m_dsp.ra = (m_dsp.ra + 1) % ALTO2_DISPLAY_FIFO;
|
||||
LOG((LOG_DISPL,3, " DSP pull %04x from FIFO[%02o] y:%d x:%d\n",
|
||||
word, (m_dsp.ra - 1) & (ALTO2_DISPLAY_FIFO - 1), y, x));
|
||||
}
|
||||
|
||||
if (m_dsp.halfclock)
|
||||
{
|
||||
UINT16 word1 = double_bits[word / 256];
|
||||
UINT16 word2 = double_bits[word % 256];
|
||||
update_bitmap_word(bitmap, x, y, word1);
|
||||
x++;
|
||||
if (x < ALTO2_DISPLAY_VISIBLE_WORDS)
|
||||
{
|
||||
update_bitmap_word(bitmap, x, y, word2);
|
||||
x++;
|
||||
}
|
||||
m_unload_time += ALTO2_DISPLAY_BITTIME(32);
|
||||
}
|
||||
else
|
||||
{
|
||||
update_bitmap_word(bitmap, x, y, word);
|
||||
x++;
|
||||
m_unload_time += ALTO2_DISPLAY_BITTIME(16);
|
||||
}
|
||||
if (x < ALTO2_DISPLAY_VISIBLE_WORDS)
|
||||
m_unload_word = x;
|
||||
else
|
||||
m_unload_time = -1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief function called by the CPU to enter the next display state
|
||||
*
|
||||
* There are 32 states per scanline and 875 scanlines per frame.
|
||||
*/
|
||||
void alto2_cpu_device::display_state_machine()
|
||||
{
|
||||
LOG((LOG_DISPL,5,"DSP%03o:", m_dsp.state));
|
||||
if (020 == m_dsp.state)
|
||||
{
|
||||
LOG((LOG_DISPL,2," HLC=%d", m_dsp.hlc));
|
||||
}
|
||||
|
||||
UINT8 a63 = m_disp_a63[m_dsp.state];
|
||||
if (A63_HLCGATE(a63))
|
||||
{
|
||||
// count horizontal line counters and wrap
|
||||
m_dsp.hlc += 1;
|
||||
if (m_dsp.hlc > ALTO2_DISPLAY_HLC_END)
|
||||
m_dsp.hlc = ALTO2_DISPLAY_HLC_START;
|
||||
// wake up the memory refresh task _twice_ on each scanline
|
||||
m_task_wakeup |= 1 << task_mrt;
|
||||
}
|
||||
// PROM a66 is disabled, if any of HLC256 or HLC512 are high
|
||||
UINT8 a66 = (HLC256 || HLC512) ? 017 : m_disp_a66[m_dsp.hlc & 0377];
|
||||
|
||||
// next address from PROM a63, use A4 from HLC1
|
||||
UINT8 next = ((HLC1 ^ 1) << 4) | A63_NEXT(a63);
|
||||
|
||||
if (A66_VBLANK(a66))
|
||||
{
|
||||
// Rising edge of VBLANK: remember HLC[1-10] where the VBLANK starts
|
||||
m_dsp.vblank = m_dsp.hlc & ~02000;
|
||||
|
||||
LOG((LOG_DISPL,1, " VBLANK"));
|
||||
|
||||
// VSYNC is always within VBLANK, thus we handle it only here
|
||||
if (A66_VSYNC(a66))
|
||||
{
|
||||
if (!A66_VSYNC(m_dsp.a66))
|
||||
{
|
||||
LOG((LOG_DISPL,1, " VSYNC/ (wake DVT)"));
|
||||
/*
|
||||
* The display vertical task DVT is woken once per field
|
||||
* at the beginning of vertical retrace.
|
||||
*/
|
||||
m_task_wakeup |= 1 << task_dvt;
|
||||
// TODO: upade odd or even field of the internal bitmap now?
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Falling edge of VBLANK?
|
||||
if (A66_VBLANK(m_dsp.a66))
|
||||
{
|
||||
/*
|
||||
* VBLANKPULSE:
|
||||
* The display horizontal task DHT is woken once at the
|
||||
* beginning of each field, and thereafter whenever the
|
||||
* display word task blocks.
|
||||
*
|
||||
* The DHT can block itself, in which case neither it nor
|
||||
* the word task can be woken until the start of the
|
||||
* next field.
|
||||
*/
|
||||
LOG((LOG_DISPL,1, " VBLANKPULSE (wake DHT)"));
|
||||
m_dsp.dht_blocks = false;
|
||||
m_dsp.dwt_blocks = false;
|
||||
m_task_wakeup |= 1 << task_dht;
|
||||
/*
|
||||
* VBLANKPULSE also resets the cursor task block flip flop,
|
||||
* which is built from two NAND gates a40c and a40d (74H01).
|
||||
*/
|
||||
m_dsp.curt_blocks = false;
|
||||
}
|
||||
if (!A63_HBLANK(a63) && A63_HBLANK(m_dsp.a63))
|
||||
{
|
||||
// Falling edge of a63 HBLANK starts unloading of FIFO words
|
||||
LOG((LOG_DISPL,1, " HBLANK\\ UNLOAD"));
|
||||
m_unload_time = ALTO2_DISPLAY_BITTIME(m_dsp.halfclock ? 32 : 16);
|
||||
m_unload_word = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The wakeup request for the display word task (DWT) is controlled by
|
||||
* the state of the 16 word FIFO. If DWT has not executed a BLOCK,
|
||||
* if DHT is not blocked, and if the buffer is not full, DWT wakeups
|
||||
* are generated.
|
||||
*/
|
||||
UINT8 a38 = m_disp_a38[m_dsp.ra * 16 + m_dsp.wa];
|
||||
if (!m_dsp.dwt_blocks && !m_dsp.dht_blocks && !FIFO_STOPWAKE(a38))
|
||||
{
|
||||
m_task_wakeup |= 1 << task_dwt;
|
||||
LOG((LOG_DISPL,1, " (wake DWT)"));
|
||||
}
|
||||
|
||||
// Stop waking up the DWT when SCANEND is active
|
||||
if (A63_SCANEND(a63))
|
||||
{
|
||||
m_task_wakeup &= ~(1 << task_dwt);
|
||||
LOG((LOG_DISPL,1, " SCANEND"));
|
||||
}
|
||||
|
||||
LOG((LOG_DISPL,1, "%s", A63_HBLANK(a63) ? " HBLANK": ""));
|
||||
|
||||
if (A63_HSYNC(a63))
|
||||
{
|
||||
// Active HSYNC
|
||||
if (!A63_HSYNC(m_dsp.a63))
|
||||
{
|
||||
// Rising edge of HSYNC => CLRBUF
|
||||
LOG((LOG_DISPL,1, " HSYNC/ (CLRBUF)"));
|
||||
/*
|
||||
* The hardware sets the buffer empty and clears the DWT block
|
||||
* flip-flop at the beginning of horizontal retrace for
|
||||
* every scanline.
|
||||
*/
|
||||
m_dsp.wa = 0;
|
||||
m_dsp.ra = 0;
|
||||
m_dsp.dwt_blocks = false;
|
||||
// now take the new values from the last SETMODE<-
|
||||
m_dsp.inverse = GET_SETMODE_INVERSE(m_dsp.setmode) ? 0xffff : 0x0000;
|
||||
m_dsp.halfclock = GET_SETMODE_SPEEDY(m_dsp.setmode) ? true : false;
|
||||
// stop the CPU execution loop from calling unload_word()
|
||||
m_unload_time = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG((LOG_DISPL,1, " HSYNC"));
|
||||
}
|
||||
}
|
||||
else
|
||||
// Falling edge of HSYNC?
|
||||
if (A63_HSYNC(m_dsp.a63))
|
||||
{
|
||||
/*
|
||||
* CLRBUF' also resets the 2nd cursor task block flip flop,
|
||||
* which is built from two NAND gates a30c and a30d (74H00).
|
||||
* If both flip flops are reset, the NOR gate a20d (74S02)
|
||||
* decodes this as WAKECURT signal.
|
||||
*/
|
||||
m_dsp.curt_wakeup = true;
|
||||
if (!m_dsp.curt_blocks)
|
||||
m_task_wakeup |= 1 << task_curt;
|
||||
}
|
||||
|
||||
LOG((LOG_DISPL,1, " NEXT:%03o\n", next));
|
||||
|
||||
m_dsp.a63 = a63;
|
||||
m_dsp.a66 = a66;
|
||||
m_dsp.state = next;
|
||||
m_dsp_time += ALTO2_DISPLAY_BITTIME(32);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief branch on evenfield
|
||||
*
|
||||
* NEXT(09) = even field ? 1 : 0
|
||||
*/
|
||||
void alto2_cpu_device::f2_late_evenfield()
|
||||
{
|
||||
UINT16 r = HLC1024 ^ 1;
|
||||
LOG((LOG_DISPL,2," EVENFIELD branch (%#o | %#o)\n", m_next2, r));
|
||||
m_next2 |= r;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief initialize the display context to useful values
|
||||
*
|
||||
* Zap the display context to all 0s.
|
||||
* Allocate a bitmap array to save blitting to the screen when
|
||||
* there is no change in the data words.
|
||||
*/
|
||||
void alto2_cpu_device::init_disp()
|
||||
{
|
||||
memset(&m_dsp, 0, sizeof(m_dsp));
|
||||
save_item(NAME(m_dsp.state));
|
||||
save_item(NAME(m_dsp.hlc));
|
||||
save_item(NAME(m_dsp.setmode));
|
||||
save_item(NAME(m_dsp.inverse));
|
||||
save_item(NAME(m_dsp.halfclock));
|
||||
save_item(NAME(m_dsp.fifo));
|
||||
save_item(NAME(m_dsp.wa));
|
||||
save_item(NAME(m_dsp.ra));
|
||||
save_item(NAME(m_dsp.a63));
|
||||
save_item(NAME(m_dsp.a66));
|
||||
save_item(NAME(m_dsp.dht_blocks));
|
||||
save_item(NAME(m_dsp.dwt_blocks));
|
||||
save_item(NAME(m_dsp.curt_blocks));
|
||||
save_item(NAME(m_dsp.curt_wakeup));
|
||||
save_item(NAME(m_dsp.vblank));
|
||||
save_item(NAME(m_dsp.xpreg));
|
||||
save_item(NAME(m_dsp.csr));
|
||||
save_item(NAME(m_dsp.curxpos));
|
||||
save_item(NAME(m_dsp.cursor0));
|
||||
save_item(NAME(m_dsp.cursor1));
|
||||
|
||||
m_disp_a38 = prom_load(machine(), &pl_displ_a38, memregion("displ_a38")->base());
|
||||
m_disp_a63 = prom_load(machine(), &pl_displ_a63, memregion("displ_a63")->base());
|
||||
m_disp_a66 = prom_load(machine(), &pl_displ_a66, memregion("displ_a66")->base());
|
||||
|
||||
m_dsp.hlc = ALTO2_DISPLAY_HLC_START;
|
||||
|
||||
m_dsp.raw_bitmap = auto_alloc_array(machine(), UINT16, ALTO2_DISPLAY_HEIGHT * ALTO2_DISPLAY_SCANLINE_WORDS);
|
||||
m_dsp.scanline = auto_alloc_array(machine(), UINT8*, ALTO2_DISPLAY_HEIGHT + ALTO2_FAKE_STATUS_H);
|
||||
for (int y = 0; y < ALTO2_DISPLAY_HEIGHT + ALTO2_FAKE_STATUS_H; y++)
|
||||
m_dsp.scanline[y] = auto_alloc_array(machine(), UINT8, ALTO2_DISPLAY_TOTAL_WIDTH);
|
||||
|
||||
m_dsp.bitmap = auto_bitmap_ind16_alloc(machine(), ALTO2_DISPLAY_WIDTH, ALTO2_DISPLAY_HEIGHT + ALTO2_FAKE_STATUS_H);
|
||||
m_dsp.state = 0;
|
||||
}
|
||||
|
||||
void alto2_cpu_device::exit_disp()
|
||||
{
|
||||
// nothing to do yet
|
||||
}
|
||||
|
||||
void alto2_cpu_device::reset_disp()
|
||||
{
|
||||
m_dsp.state = 0;
|
||||
m_dsp.hlc = ALTO2_DISPLAY_HLC_START;
|
||||
m_dsp.a63 = 0;
|
||||
m_dsp.a66 = 0;
|
||||
m_dsp.setmode = 0;
|
||||
m_dsp.inverse = 0;
|
||||
m_dsp.halfclock = false;
|
||||
m_dsp.wa = 0;
|
||||
m_dsp.ra = 0;
|
||||
m_dsp.dht_blocks = false;
|
||||
m_dsp.dwt_blocks = false;
|
||||
m_dsp.curt_blocks = false;
|
||||
m_dsp.curt_wakeup = false;
|
||||
m_dsp.vblank = 0;
|
||||
m_dsp.xpreg = 0;
|
||||
m_dsp.csr = 0;
|
||||
m_dsp.curxpos = 0;
|
||||
m_dsp.cursor0 = 0;
|
||||
m_dsp.cursor1 = 0;
|
||||
memset(m_dsp.raw_bitmap, 0, sizeof(UINT16) * ALTO2_DISPLAY_HEIGHT * ALTO2_DISPLAY_SCANLINE_WORDS);
|
||||
for (int y = 0; y < ALTO2_DISPLAY_HEIGHT; y++)
|
||||
memset(m_dsp.scanline[y], 0, sizeof(UINT8) * ALTO2_DISPLAY_TOTAL_WIDTH);
|
||||
m_dsp.odd_frame = false;
|
||||
|
||||
for (int y = ALTO2_DISPLAY_HEIGHT; y < ALTO2_DISPLAY_HEIGHT + ALTO2_FAKE_STATUS_H; y++)
|
||||
memset(m_dsp.scanline[y], 1, sizeof(UINT8) * ALTO2_DISPLAY_TOTAL_WIDTH);
|
||||
fake_status_printf(1, "* Fake Status *");
|
||||
}
|
||||
|
||||
/* Video update */
|
||||
UINT32 alto2_cpu_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
pen_t palette_bw[2];
|
||||
palette_bw[0] = screen.palette()->white_pen();
|
||||
palette_bw[1] = screen.palette()->black_pen();
|
||||
// copy even or odd field
|
||||
for (int y = m_dsp.odd_frame ? 0 : 1; y < ALTO2_DISPLAY_HEIGHT; y += 2)
|
||||
draw_scanline8(*m_dsp.bitmap, 0, y, ALTO2_DISPLAY_WIDTH, m_dsp.scanline[y], palette_bw);
|
||||
// copy fake status scanlines
|
||||
for (int y = ALTO2_DISPLAY_HEIGHT; y < ALTO2_DISPLAY_HEIGHT + ALTO2_FAKE_STATUS_H; y++)
|
||||
draw_scanline8(*m_dsp.bitmap, 0, y, ALTO2_DISPLAY_WIDTH, m_dsp.scanline[y], palette_bw);
|
||||
// copy bitmap
|
||||
copybitmap(bitmap, *m_dsp.bitmap, 0, 0, 0, 0, cliprect);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void alto2_cpu_device::screen_eof(screen_device &screen, bool state)
|
||||
{
|
||||
if (state)
|
||||
m_dsp.odd_frame = !m_dsp.odd_frame;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* FAKE STATUS LINE
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
UINT8 code;
|
||||
UINT8 bits[10];
|
||||
} bdf_6x10_t;
|
||||
|
||||
/**
|
||||
* STARTFONT 2.1
|
||||
* COMMENT "$ucs-fonts: 6x10.bdf,v 1.34 2002-11-10 19:12:30+00 mgk25 Rel $"
|
||||
* COMMENT "Send bug reports to Markus Kuhn <http://www.cl.cam.ac.uk/~mgk25/>"
|
||||
* FONT -Misc-Fixed-Medium-R-Normal--10-100-75-75-C-60-ISO10646-1
|
||||
* SIZE 10 75 75
|
||||
* FONTBOUNDINGBOX 6 10 0 -2
|
||||
* STARTPROPERTIES 22
|
||||
* FONTNAME_REGISTRY ""
|
||||
* FOUNDRY "Misc"
|
||||
* FAMILY_NAME "Fixed"
|
||||
* WEIGHT_NAME "Medium"
|
||||
* SLANT "R"
|
||||
* SETWIDTH_NAME "Normal"
|
||||
* ADD_STYLE_NAME ""
|
||||
* PIXEL_SIZE 10
|
||||
* POINT_SIZE 100
|
||||
* RESOLUTION_X 75
|
||||
* RESOLUTION_Y 75
|
||||
* SPACING "C"
|
||||
* AVERAGE_WIDTH 60
|
||||
* CHARSET_REGISTRY "ISO10646"
|
||||
* CHARSET_ENCODING "1"
|
||||
* FONT_ASCENT 8
|
||||
* FONT_DESCENT 2
|
||||
* DEFAULT_CHAR 0
|
||||
* COPYRIGHT "Public domain terminal emulator font. Share and enjoy."
|
||||
* _XMBDFED_INFO "Edited with xmbdfed 4.5."
|
||||
* CAP_HEIGHT 7
|
||||
* X_HEIGHT 5
|
||||
* ENDPROPERTIES
|
||||
* CHARS 1597
|
||||
*/
|
||||
static const bdf_6x10_t bdf_6x10[] = {
|
||||
/* space */ { 32, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
|
||||
/* exclam */ { 33, {0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x20, 0x00, 0x00 }},
|
||||
/* quotedbl */ { 34, {0x00, 0x50, 0x50, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
|
||||
/* numbersign */ { 35, {0x00, 0x50, 0x50, 0xF8, 0x50, 0xF8, 0x50, 0x50, 0x00, 0x00 }},
|
||||
/* dollar */ { 36, {0x00, 0x20, 0x70, 0xA0, 0x70, 0x28, 0x70, 0x20, 0x00, 0x00 }},
|
||||
/* percent */ { 37, {0x00, 0x48, 0xA8, 0x50, 0x20, 0x50, 0xA8, 0x90, 0x00, 0x00 }},
|
||||
/* ampersand */ { 38, {0x00, 0x40, 0xA0, 0xA0, 0x40, 0xA8, 0x90, 0x68, 0x00, 0x00 }},
|
||||
/* quotesingle */ { 39, {0x00, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
|
||||
/* parenleft */ { 40, {0x00, 0x10, 0x20, 0x40, 0x40, 0x40, 0x20, 0x10, 0x00, 0x00 }},
|
||||
/* parenright */ { 41, {0x00, 0x40, 0x20, 0x10, 0x10, 0x10, 0x20, 0x40, 0x00, 0x00 }},
|
||||
/* asterisk */ { 42, {0x00, 0x00, 0x88, 0x50, 0xF8, 0x50, 0x88, 0x00, 0x00, 0x00 }},
|
||||
/* plus */ { 43, {0x00, 0x00, 0x20, 0x20, 0xF8, 0x20, 0x20, 0x00, 0x00, 0x00 }},
|
||||
/* comma */ { 44, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x20, 0x40, 0x00 }},
|
||||
/* hyphen */ { 45, {0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00 }},
|
||||
/* period */ { 46, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x70, 0x20, 0x00 }},
|
||||
/* slash */ { 47, {0x00, 0x08, 0x08, 0x10, 0x20, 0x40, 0x80, 0x80, 0x00, 0x00 }},
|
||||
/* zero */ { 48, {0x00, 0x20, 0x50, 0x88, 0x88, 0x88, 0x50, 0x20, 0x00, 0x00 }},
|
||||
/* one */ { 49, {0x00, 0x20, 0x60, 0xA0, 0x20, 0x20, 0x20, 0xF8, 0x00, 0x00 }},
|
||||
/* two */ { 50, {0x00, 0x70, 0x88, 0x08, 0x30, 0x40, 0x80, 0xF8, 0x00, 0x00 }},
|
||||
/* three */ { 51, {0x00, 0xF8, 0x08, 0x10, 0x30, 0x08, 0x88, 0x70, 0x00, 0x00 }},
|
||||
/* four */ { 52, {0x00, 0x10, 0x30, 0x50, 0x90, 0xF8, 0x10, 0x10, 0x00, 0x00 }},
|
||||
/* five */ { 53, {0x00, 0xF8, 0x80, 0xB0, 0xC8, 0x08, 0x88, 0x70, 0x00, 0x00 }},
|
||||
/* six */ { 54, {0x00, 0x30, 0x40, 0x80, 0xB0, 0xC8, 0x88, 0x70, 0x00, 0x00 }},
|
||||
/* seven */ { 55, {0x00, 0xF8, 0x08, 0x10, 0x10, 0x20, 0x40, 0x40, 0x00, 0x00 }},
|
||||
/* eight */ { 56, {0x00, 0x70, 0x88, 0x88, 0x70, 0x88, 0x88, 0x70, 0x00, 0x00 }},
|
||||
/* nine */ { 57, {0x00, 0x70, 0x88, 0x98, 0x68, 0x08, 0x10, 0x60, 0x00, 0x00 }},
|
||||
/* colon */ { 58, {0x00, 0x00, 0x20, 0x70, 0x20, 0x00, 0x20, 0x70, 0x20, 0x00 }},
|
||||
/* semicolon */ { 59, {0x00, 0x00, 0x20, 0x70, 0x20, 0x00, 0x30, 0x20, 0x40, 0x00 }},
|
||||
/* less */ { 60, {0x00, 0x08, 0x10, 0x20, 0x40, 0x20, 0x10, 0x08, 0x00, 0x00 }},
|
||||
/* equal */ { 61, {0x00, 0x00, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00 }},
|
||||
/* greater */ { 62, {0x00, 0x40, 0x20, 0x10, 0x08, 0x10, 0x20, 0x40, 0x00, 0x00 }},
|
||||
/* question */ { 63, {0x00, 0x70, 0x88, 0x10, 0x20, 0x20, 0x00, 0x20, 0x00, 0x00 }},
|
||||
/* at */ { 64, {0x00, 0x70, 0x88, 0x98, 0xA8, 0xB0, 0x80, 0x70, 0x00, 0x00 }},
|
||||
/* A */ { 65, {0x00, 0x20, 0x50, 0x88, 0x88, 0xF8, 0x88, 0x88, 0x00, 0x00 }},
|
||||
/* B */ { 66, {0x00, 0xF0, 0x48, 0x48, 0x70, 0x48, 0x48, 0xF0, 0x00, 0x00 }},
|
||||
/* C */ { 67, {0x00, 0x70, 0x88, 0x80, 0x80, 0x80, 0x88, 0x70, 0x00, 0x00 }},
|
||||
/* D */ { 68, {0x00, 0xF0, 0x48, 0x48, 0x48, 0x48, 0x48, 0xF0, 0x00, 0x00 }},
|
||||
/* E */ { 69, {0x00, 0xF8, 0x80, 0x80, 0xF0, 0x80, 0x80, 0xF8, 0x00, 0x00 }},
|
||||
/* F */ { 70, {0x00, 0xF8, 0x80, 0x80, 0xF0, 0x80, 0x80, 0x80, 0x00, 0x00 }},
|
||||
/* G */ { 71, {0x00, 0x70, 0x88, 0x80, 0x80, 0x98, 0x88, 0x70, 0x00, 0x00 }},
|
||||
/* H */ { 72, {0x00, 0x88, 0x88, 0x88, 0xF8, 0x88, 0x88, 0x88, 0x00, 0x00 }},
|
||||
/* I */ { 73, {0x00, 0x70, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x00, 0x00 }},
|
||||
/* J */ { 74, {0x00, 0x38, 0x10, 0x10, 0x10, 0x10, 0x90, 0x60, 0x00, 0x00 }},
|
||||
/* K */ { 75, {0x00, 0x88, 0x90, 0xA0, 0xC0, 0xA0, 0x90, 0x88, 0x00, 0x00 }},
|
||||
/* L */ { 76, {0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xF8, 0x00, 0x00 }},
|
||||
/* M */ { 77, {0x00, 0x88, 0x88, 0xD8, 0xA8, 0x88, 0x88, 0x88, 0x00, 0x00 }},
|
||||
/* N */ { 78, {0x00, 0x88, 0x88, 0xC8, 0xA8, 0x98, 0x88, 0x88, 0x00, 0x00 }},
|
||||
/* O */ { 79, {0x00, 0x70, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00 }},
|
||||
/* P */ { 80, {0x00, 0xF0, 0x88, 0x88, 0xF0, 0x80, 0x80, 0x80, 0x00, 0x00 }},
|
||||
/* Q */ { 81, {0x00, 0x70, 0x88, 0x88, 0x88, 0x88, 0xA8, 0x70, 0x08, 0x00 }},
|
||||
/* R */ { 82, {0x00, 0xF0, 0x88, 0x88, 0xF0, 0xA0, 0x90, 0x88, 0x00, 0x00 }},
|
||||
/* S */ { 83, {0x00, 0x70, 0x88, 0x80, 0x70, 0x08, 0x88, 0x70, 0x00, 0x00 }},
|
||||
/* T */ { 84, {0x00, 0xF8, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00 }},
|
||||
/* U */ { 85, {0x00, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00 }},
|
||||
/* V */ { 86, {0x00, 0x88, 0x88, 0x88, 0x50, 0x50, 0x50, 0x20, 0x00, 0x00 }},
|
||||
/* W */ { 87, {0x00, 0x88, 0x88, 0x88, 0xA8, 0xA8, 0xD8, 0x88, 0x00, 0x00 }},
|
||||
/* X */ { 88, {0x00, 0x88, 0x88, 0x50, 0x20, 0x50, 0x88, 0x88, 0x00, 0x00 }},
|
||||
/* Y */ { 89, {0x00, 0x88, 0x88, 0x50, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00 }},
|
||||
/* Z */ { 90, {0x00, 0xF8, 0x08, 0x10, 0x20, 0x40, 0x80, 0xF8, 0x00, 0x00 }},
|
||||
/* bracketleft */ { 91, {0x00, 0x70, 0x40, 0x40, 0x40, 0x40, 0x40, 0x70, 0x00, 0x00 }},
|
||||
/* backslash */ { 92, {0x00, 0x80, 0x80, 0x40, 0x20, 0x10, 0x08, 0x08, 0x00, 0x00 }},
|
||||
/* bracketright */ { 93, {0x00, 0x70, 0x10, 0x10, 0x10, 0x10, 0x10, 0x70, 0x00, 0x00 }},
|
||||
/* asciicircum */ { 94, {0x00, 0x20, 0x50, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
|
||||
/* underscore */ { 95, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00 }},
|
||||
/* grave */ { 96, {0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
|
||||
/* a */ { 97, {0x00, 0x00, 0x00, 0x70, 0x08, 0x78, 0x88, 0x78, 0x00, 0x00 }},
|
||||
/* b */ { 98, {0x00, 0x80, 0x80, 0xB0, 0xC8, 0x88, 0xC8, 0xB0, 0x00, 0x00 }},
|
||||
/* c */ { 99, {0x00, 0x00, 0x00, 0x70, 0x88, 0x80, 0x88, 0x70, 0x00, 0x00 }},
|
||||
/* d */ { 100, {0x00, 0x08, 0x08, 0x68, 0x98, 0x88, 0x98, 0x68, 0x00, 0x00 }},
|
||||
/* e */ { 101, {0x00, 0x00, 0x00, 0x70, 0x88, 0xF8, 0x80, 0x70, 0x00, 0x00 }},
|
||||
/* f */ { 102, {0x00, 0x30, 0x48, 0x40, 0xF0, 0x40, 0x40, 0x40, 0x00, 0x00 }},
|
||||
/* g */ { 103, {0x00, 0x00, 0x00, 0x78, 0x88, 0x88, 0x78, 0x08, 0x88, 0x70 }},
|
||||
/* h */ { 104, {0x00, 0x80, 0x80, 0xB0, 0xC8, 0x88, 0x88, 0x88, 0x00, 0x00 }},
|
||||
/* i */ { 105, {0x00, 0x20, 0x00, 0x60, 0x20, 0x20, 0x20, 0x70, 0x00, 0x00 }},
|
||||
/* j */ { 106, {0x00, 0x08, 0x00, 0x18, 0x08, 0x08, 0x08, 0x48, 0x48, 0x30 }},
|
||||
/* k */ { 107, {0x00, 0x80, 0x80, 0x88, 0x90, 0xE0, 0x90, 0x88, 0x00, 0x00 }},
|
||||
/* l */ { 108, {0x00, 0x60, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x00, 0x00 }},
|
||||
/* m */ { 109, {0x00, 0x00, 0x00, 0xD0, 0xA8, 0xA8, 0xA8, 0x88, 0x00, 0x00 }},
|
||||
/* n */ { 110, {0x00, 0x00, 0x00, 0xB0, 0xC8, 0x88, 0x88, 0x88, 0x00, 0x00 }},
|
||||
/* o */ { 111, {0x00, 0x00, 0x00, 0x70, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00 }},
|
||||
/* p */ { 112, {0x00, 0x00, 0x00, 0xB0, 0xC8, 0x88, 0xC8, 0xB0, 0x80, 0x80 }},
|
||||
/* q */ { 113, {0x00, 0x00, 0x00, 0x68, 0x98, 0x88, 0x98, 0x68, 0x08, 0x08 }},
|
||||
/* r */ { 114, {0x00, 0x00, 0x00, 0xB0, 0xC8, 0x80, 0x80, 0x80, 0x00, 0x00 }},
|
||||
/* s */ { 115, {0x00, 0x00, 0x00, 0x70, 0x80, 0x70, 0x08, 0xF0, 0x00, 0x00 }},
|
||||
/* t */ { 116, {0x00, 0x40, 0x40, 0xF0, 0x40, 0x40, 0x48, 0x30, 0x00, 0x00 }},
|
||||
/* u */ { 117, {0x00, 0x00, 0x00, 0x88, 0x88, 0x88, 0x98, 0x68, 0x00, 0x00 }},
|
||||
/* v */ { 118, {0x00, 0x00, 0x00, 0x88, 0x88, 0x50, 0x50, 0x20, 0x00, 0x00 }},
|
||||
/* w */ { 119, {0x00, 0x00, 0x00, 0x88, 0x88, 0xA8, 0xA8, 0x50, 0x00, 0x00 }},
|
||||
/* x */ { 120, {0x00, 0x00, 0x00, 0x88, 0x50, 0x20, 0x50, 0x88, 0x00, 0x00 }},
|
||||
/* y */ { 121, {0x00, 0x00, 0x00, 0x88, 0x88, 0x98, 0x68, 0x08, 0x88, 0x70 }},
|
||||
/* z */ { 122, {0x00, 0x00, 0x00, 0xF8, 0x10, 0x20, 0x40, 0xF8, 0x00, 0x00 }},
|
||||
/* braceleft */ { 123, {0x00, 0x18, 0x20, 0x10, 0x60, 0x10, 0x20, 0x18, 0x00, 0x00 }},
|
||||
/* bar */ { 124, {0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00 }},
|
||||
/* braceright */ { 125, {0x00, 0x60, 0x10, 0x20, 0x18, 0x20, 0x10, 0x60, 0x00, 0x00 }},
|
||||
/* asciitilde */ { 126, {0x00, 0x48, 0xA8, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
|
||||
/* space */ { 160, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
|
||||
/* exclamdown */ { 161, {0x00, 0x20, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00 }},
|
||||
/* cent */ { 162, {0x00, 0x00, 0x20, 0x78, 0xA0, 0xA0, 0xA0, 0x78, 0x20, 0x00 }},
|
||||
/* sterling */ { 163, {0x00, 0x30, 0x48, 0x40, 0xE0, 0x40, 0x48, 0xB0, 0x00, 0x00 }},
|
||||
/* currency */ { 164, {0x00, 0x00, 0x00, 0x88, 0x70, 0x50, 0x70, 0x88, 0x00, 0x00 }},
|
||||
/* yen */ { 165, {0x00, 0x88, 0x88, 0x50, 0x20, 0xF8, 0x20, 0x20, 0x20, 0x00 }},
|
||||
/* brokenbar */ { 166, {0x00, 0x20, 0x20, 0x20, 0x00, 0x20, 0x20, 0x20, 0x00, 0x00 }},
|
||||
/* section */ { 167, {0x00, 0x70, 0x80, 0xE0, 0x90, 0x48, 0x38, 0x08, 0x70, 0x00 }},
|
||||
/* dieresis */ { 168, {0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
|
||||
/* copyright */ { 169, {0x00, 0x70, 0x88, 0xA8, 0xC8, 0xA8, 0x88, 0x70, 0x00, 0x00 }},
|
||||
/* ordfeminine */ { 170, {0x00, 0x38, 0x48, 0x58, 0x28, 0x00, 0x78, 0x00, 0x00, 0x00 }},
|
||||
/* guillemotleft */ { 171, {0x00, 0x00, 0x00, 0x24, 0x48, 0x90, 0x48, 0x24, 0x00, 0x00 }},
|
||||
/* logicalnot */ { 172, {0x00, 0x00, 0x00, 0x00, 0x78, 0x08, 0x00, 0x00, 0x00, 0x00 }},
|
||||
/* hyphen */ { 173, {0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00 }},
|
||||
/* registered */ { 174, {0x00, 0x70, 0x88, 0xE8, 0xC8, 0xC8, 0x88, 0x70, 0x00, 0x00 }},
|
||||
/* macron */ { 175, {0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
|
||||
/* degree */ { 176, {0x00, 0x20, 0x50, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
|
||||
/* plusminus */ { 177, {0x00, 0x00, 0x20, 0x20, 0xF8, 0x20, 0x20, 0xF8, 0x00, 0x00 }},
|
||||
/* twosuperior */ { 178, {0x30, 0x48, 0x10, 0x20, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00 }},
|
||||
/* threesuperior */ { 179, {0x70, 0x08, 0x30, 0x08, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00 }},
|
||||
/* acute */ { 180, {0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
|
||||
/* mu */ { 181, {0x00, 0x00, 0x00, 0x88, 0x88, 0x88, 0xC8, 0xB0, 0x80, 0x00 }},
|
||||
/* paragraph */ { 182, {0x00, 0x78, 0xE8, 0xE8, 0x68, 0x28, 0x28, 0x28, 0x00, 0x00 }},
|
||||
/* periodcentered */ { 183, {0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00 }},
|
||||
/* cedilla */ { 184, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20 }},
|
||||
/* onesuperior */ { 185, {0x20, 0x60, 0x20, 0x20, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00 }},
|
||||
/* ordmasculine */ { 186, {0x00, 0x30, 0x48, 0x48, 0x30, 0x00, 0x78, 0x00, 0x00, 0x00 }},
|
||||
/* guillemotright */ { 187, {0x00, 0x00, 0x00, 0x90, 0x48, 0x24, 0x48, 0x90, 0x00, 0x00 }},
|
||||
/* onequarter */ { 188, {0x40, 0xC0, 0x40, 0x40, 0xE4, 0x0C, 0x14, 0x3C, 0x04, 0x00 }},
|
||||
/* onehalf */ { 189, {0x40, 0xC0, 0x40, 0x40, 0xE8, 0x14, 0x04, 0x08, 0x1C, 0x00 }},
|
||||
/* threequarters */ { 190, {0xC0, 0x20, 0x40, 0x20, 0xC8, 0x18, 0x28, 0x78, 0x08, 0x00 }},
|
||||
/* questiondown */ { 191, {0x00, 0x20, 0x00, 0x20, 0x20, 0x40, 0x88, 0x70, 0x00, 0x00 }},
|
||||
/* Agrave */ { 192, {0x40, 0x20, 0x70, 0x88, 0x88, 0xF8, 0x88, 0x88, 0x00, 0x00 }},
|
||||
/* Aacute */ { 193, {0x10, 0x20, 0x70, 0x88, 0x88, 0xF8, 0x88, 0x88, 0x00, 0x00 }},
|
||||
/* Acircumflex */ { 194, {0x20, 0x50, 0x70, 0x88, 0x88, 0xF8, 0x88, 0x88, 0x00, 0x00 }},
|
||||
/* Atilde */ { 195, {0x48, 0xB0, 0x70, 0x88, 0x88, 0xF8, 0x88, 0x88, 0x00, 0x00 }},
|
||||
/* Adieresis */ { 196, {0x50, 0x00, 0x70, 0x88, 0x88, 0xF8, 0x88, 0x88, 0x00, 0x00 }},
|
||||
/* Aring */ { 197, {0x20, 0x50, 0x70, 0x88, 0x88, 0xF8, 0x88, 0x88, 0x00, 0x00 }},
|
||||
/* AE */ { 198, {0x00, 0x3C, 0x50, 0x90, 0x9C, 0xF0, 0x90, 0x9C, 0x00, 0x00 }},
|
||||
/* Ccedilla */ { 199, {0x00, 0x70, 0x88, 0x80, 0x80, 0x80, 0x88, 0x70, 0x20, 0x40 }},
|
||||
/* Egrave */ { 200, {0x40, 0xF8, 0x80, 0x80, 0xF0, 0x80, 0x80, 0xF8, 0x00, 0x00 }},
|
||||
/* Eacute */ { 201, {0x10, 0xF8, 0x80, 0x80, 0xF0, 0x80, 0x80, 0xF8, 0x00, 0x00 }},
|
||||
/* Ecircumflex */ { 202, {0x20, 0xF8, 0x80, 0x80, 0xF0, 0x80, 0x80, 0xF8, 0x00, 0x00 }},
|
||||
/* Edieresis */ { 203, {0x50, 0xF8, 0x80, 0x80, 0xF0, 0x80, 0x80, 0xF8, 0x00, 0x00 }},
|
||||
/* Igrave */ { 204, {0x40, 0x20, 0x70, 0x20, 0x20, 0x20, 0x20, 0x70, 0x00, 0x00 }},
|
||||
/* Iacute */ { 205, {0x10, 0x20, 0x70, 0x20, 0x20, 0x20, 0x20, 0x70, 0x00, 0x00 }},
|
||||
/* Icircumflex */ { 206, {0x20, 0x50, 0x70, 0x20, 0x20, 0x20, 0x20, 0x70, 0x00, 0x00 }},
|
||||
/* Idieresis */ { 207, {0x50, 0x00, 0x70, 0x20, 0x20, 0x20, 0x20, 0x70, 0x00, 0x00 }},
|
||||
/* Eth */ { 208, {0x00, 0xF0, 0x48, 0x48, 0xE8, 0x48, 0x48, 0xF0, 0x00, 0x00 }},
|
||||
/* Ntilde */ { 209, {0x28, 0x50, 0x88, 0xC8, 0xA8, 0x98, 0x88, 0x88, 0x00, 0x00 }},
|
||||
/* Ograve */ { 210, {0x40, 0x20, 0x70, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00 }},
|
||||
/* Oacute */ { 211, {0x10, 0x20, 0x70, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00 }},
|
||||
/* Ocircumflex */ { 212, {0x20, 0x50, 0x70, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00 }},
|
||||
/* Otilde */ { 213, {0x28, 0x50, 0x70, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00 }},
|
||||
/* Odieresis */ { 214, {0x50, 0x00, 0x70, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00 }},
|
||||
/* multiply */ { 215, {0x00, 0x00, 0x00, 0x88, 0x50, 0x20, 0x50, 0x88, 0x00, 0x00 }},
|
||||
/* Oslash */ { 216, {0x00, 0x70, 0x98, 0x98, 0xA8, 0xC8, 0xC8, 0x70, 0x00, 0x00 }},
|
||||
/* Ugrave */ { 217, {0x40, 0x20, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00 }},
|
||||
/* Uacute */ { 218, {0x10, 0x20, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00 }},
|
||||
/* Ucircumflex */ { 219, {0x20, 0x50, 0x00, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00 }},
|
||||
/* Udieresis */ { 220, {0x50, 0x00, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00 }},
|
||||
/* Yacute */ { 221, {0x10, 0x20, 0x88, 0x88, 0x50, 0x20, 0x20, 0x20, 0x00, 0x00 }},
|
||||
/* Thorn */ { 222, {0x00, 0x80, 0xF0, 0x88, 0xF0, 0x80, 0x80, 0x80, 0x00, 0x00 }},
|
||||
/* germandbls */ { 223, {0x00, 0x70, 0x88, 0x90, 0xA0, 0x90, 0x88, 0xB0, 0x00, 0x00 }},
|
||||
/* agrave */ { 224, {0x40, 0x20, 0x00, 0x70, 0x08, 0x78, 0x88, 0x78, 0x00, 0x00 }},
|
||||
/* aacute */ { 225, {0x10, 0x20, 0x00, 0x70, 0x08, 0x78, 0x88, 0x78, 0x00, 0x00 }},
|
||||
/* acircumflex */ { 226, {0x20, 0x50, 0x00, 0x70, 0x08, 0x78, 0x88, 0x78, 0x00, 0x00 }},
|
||||
/* atilde */ { 227, {0x28, 0x50, 0x00, 0x70, 0x08, 0x78, 0x88, 0x78, 0x00, 0x00 }},
|
||||
/* adieresis */ { 228, {0x00, 0x50, 0x00, 0x70, 0x08, 0x78, 0x88, 0x78, 0x00, 0x00 }},
|
||||
/* aring */ { 229, {0x20, 0x50, 0x20, 0x70, 0x08, 0x78, 0x88, 0x78, 0x00, 0x00 }},
|
||||
/* ae */ { 230, {0x00, 0x00, 0x00, 0x78, 0x14, 0x7C, 0x90, 0x7C, 0x00, 0x00 }},
|
||||
/* ccedilla */ { 231, {0x00, 0x00, 0x00, 0x70, 0x88, 0x80, 0x88, 0x70, 0x20, 0x40 }},
|
||||
/* egrave */ { 232, {0x40, 0x20, 0x00, 0x70, 0x88, 0xF8, 0x80, 0x70, 0x00, 0x00 }},
|
||||
/* eacute */ { 233, {0x10, 0x20, 0x00, 0x70, 0x88, 0xF8, 0x80, 0x70, 0x00, 0x00 }},
|
||||
/* ecircumflex */ { 234, {0x20, 0x50, 0x00, 0x70, 0x88, 0xF8, 0x80, 0x70, 0x00, 0x00 }},
|
||||
/* edieresis */ { 235, {0x00, 0x50, 0x00, 0x70, 0x88, 0xF8, 0x80, 0x70, 0x00, 0x00 }},
|
||||
/* igrave */ { 236, {0x40, 0x20, 0x00, 0x60, 0x20, 0x20, 0x20, 0x70, 0x00, 0x00 }},
|
||||
/* iacute */ { 237, {0x20, 0x40, 0x00, 0x60, 0x20, 0x20, 0x20, 0x70, 0x00, 0x00 }},
|
||||
/* icircumflex */ { 238, {0x20, 0x50, 0x00, 0x60, 0x20, 0x20, 0x20, 0x70, 0x00, 0x00 }},
|
||||
/* idieresis */ { 239, {0x00, 0x50, 0x00, 0x60, 0x20, 0x20, 0x20, 0x70, 0x00, 0x00 }},
|
||||
/* eth */ { 240, {0x00, 0xC0, 0x30, 0x70, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00 }},
|
||||
/* ntilde */ { 241, {0x28, 0x50, 0x00, 0xB0, 0xC8, 0x88, 0x88, 0x88, 0x00, 0x00 }},
|
||||
/* ograve */ { 242, {0x40, 0x20, 0x00, 0x70, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00 }},
|
||||
/* oacute */ { 243, {0x10, 0x20, 0x00, 0x70, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00 }},
|
||||
/* ocircumflex */ { 244, {0x20, 0x50, 0x00, 0x70, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00 }},
|
||||
/* otilde */ { 245, {0x28, 0x50, 0x00, 0x70, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00 }},
|
||||
/* odieresis */ { 246, {0x00, 0x50, 0x00, 0x70, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00 }},
|
||||
/* divide */ { 247, {0x00, 0x00, 0x20, 0x00, 0xF8, 0x00, 0x20, 0x00, 0x00, 0x00 }},
|
||||
/* oslash */ { 248, {0x00, 0x00, 0x00, 0x78, 0x98, 0xA8, 0xC8, 0xF0, 0x00, 0x00 }},
|
||||
/* ugrave */ { 249, {0x40, 0x20, 0x00, 0x88, 0x88, 0x88, 0x98, 0x68, 0x00, 0x00 }},
|
||||
/* uacute */ { 250, {0x10, 0x20, 0x00, 0x88, 0x88, 0x88, 0x98, 0x68, 0x00, 0x00 }},
|
||||
/* ucircumflex */ { 251, {0x20, 0x50, 0x00, 0x88, 0x88, 0x88, 0x98, 0x68, 0x00, 0x00 }},
|
||||
/* udieresis */ { 252, {0x00, 0x50, 0x00, 0x88, 0x88, 0x88, 0x98, 0x68, 0x00, 0x00 }},
|
||||
/* yacute */ { 253, {0x00, 0x10, 0x20, 0x88, 0x88, 0x98, 0x68, 0x08, 0x88, 0x70 }},
|
||||
/* thorn */ { 254, {0x00, 0x00, 0x80, 0xF0, 0x88, 0x88, 0x88, 0xF0, 0x80, 0x80 }},
|
||||
/* ydieresis */ { 255, {0x00, 0x50, 0x00, 0x88, 0x88, 0x98, 0x68, 0x08, 0x88, 0x70 }},
|
||||
/* char0 */ { 0, {0x00, 0xA8, 0x00, 0x88, 0x00, 0x88, 0x00, 0xA8, 0x00, 0x00 }}
|
||||
};
|
||||
|
||||
void alto2_cpu_device::fake_status_putch(int x, UINT8 ch)
|
||||
{
|
||||
const bdf_6x10_t* pf = bdf_6x10;
|
||||
while (pf->code != ch && pf->code != 0)
|
||||
pf++;
|
||||
int dx = 6 * x;
|
||||
if (dx >= ALTO2_DISPLAY_WIDTH)
|
||||
return;
|
||||
for (int dy = 0; dy < 10; dy++)
|
||||
{
|
||||
UINT8* pix = m_dsp.scanline[ALTO2_DISPLAY_HEIGHT + 1 + dy] + dx;
|
||||
UINT8 bits = ~pf->bits[dy];
|
||||
pix[0] = (bits >> 7) & 1;
|
||||
pix[1] = (bits >> 6) & 1;
|
||||
pix[2] = (bits >> 5) & 1;
|
||||
pix[3] = (bits >> 4) & 1;
|
||||
pix[4] = (bits >> 3) & 1;
|
||||
pix[5] = (bits >> 2) & 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void alto2_cpu_device::fake_status_printf(int x, const char* format, ...)
|
||||
{
|
||||
static char buff[256];
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
vsnprintf(buff, sizeof(buff), format, ap);
|
||||
va_end(ap);
|
||||
char* src = buff;
|
||||
while (*src)
|
||||
fake_status_putch(x++, *src++);
|
||||
}
|
303
src/emu/cpu/alto2/a2disp.h
Normal file
303
src/emu/cpu/alto2/a2disp.h
Normal file
@ -0,0 +1,303 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Xerox AltoII display block
|
||||
*
|
||||
* Copyright Juergen Buchmueller <pullmoll@t-online.de>
|
||||
*
|
||||
* Licenses: MAME, GPLv2
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifdef ALTO2_DEFINE_CONSTANTS
|
||||
|
||||
/**
|
||||
* @brief start value for the horizontal line counter
|
||||
*
|
||||
* This value is loaded into the three 4 bit counters (type 9316)
|
||||
* with numbers 65, 67, and 75.
|
||||
* 65: A=0 B=1 C=1 D=0
|
||||
* 67: A=1 B=0 C=0 D=1
|
||||
* 75: A=0 B=0 C=0 D=0
|
||||
*
|
||||
* The value is 150
|
||||
*/
|
||||
#define ALTO2_DISPLAY_HLC_START (2+4+16+128)
|
||||
|
||||
/**
|
||||
* @brief end value for the horizontal line counter
|
||||
*
|
||||
* This is decoded by H30, an 8 input NAND gate.
|
||||
* The value is 1899; horz. line count range 150...1899 = 1750.
|
||||
*
|
||||
* There are 1750 / 2 = 875 total scanlines.
|
||||
*/
|
||||
#define ALTO2_DISPLAY_HLC_END (1+2+8+32+64+256+512+1024)
|
||||
|
||||
/**
|
||||
* @brief display total height, including overscan (vertical blanking and synch)
|
||||
*
|
||||
* The display is interleaved in two fields, alternatingly drawing the even and odd
|
||||
* scanlines to the monitor. The frame rate is 60Hz, which is actually the rate
|
||||
* of the half-frames. The rate for full frames is thus 30Hz.
|
||||
*/
|
||||
#define ALTO2_DISPLAY_TOTAL_HEIGHT ((ALTO2_DISPLAY_HLC_END + 1 - ALTO2_DISPLAY_HLC_START) / 2)
|
||||
|
||||
/**
|
||||
* @brief display total width, including horizontal blanking
|
||||
*
|
||||
* Known facts:
|
||||
*
|
||||
* We have 606x808 visible pixels, and the pixel clock is said to be 50ns
|
||||
* (20MHz), while the crystal in the schematics is labeled 20.16 MHz,
|
||||
* so the pixel clock would actually be 49.6031ns.
|
||||
*
|
||||
* The total number of scanlines is, according to the docs, 875.
|
||||
*
|
||||
* 875 scanlines at 30 frames per second, thus the scanline rate is 26.250 kHz.
|
||||
*
|
||||
* If I divide 20.16 MHz by 26.250 kHz, I get 768 pixels for the total width
|
||||
* of a scanline in pixels.
|
||||
*
|
||||
* The horizontal blanking period would then be 768 - 606 = 162 pixels, and
|
||||
* thus 162 * 49.6031ns ~= 8036ns = 8.036us for the HBLANK time.
|
||||
*
|
||||
* In the display schematics there is a divide by 24 logic, and when
|
||||
* dividing the 768 pixels per scanline by 24, we have 32 phases of a scanline.
|
||||
*
|
||||
* A S8223 PROM (a63) with 32x8 bits contains the status of the HBLANK and
|
||||
* HSYNC signals for these phases, the SCANEND and HLCGATE signals, as well
|
||||
* as its own next address A0-A3!
|
||||
*
|
||||
*/
|
||||
#define ALTO2_DISPLAY_TOTAL_WIDTH 768
|
||||
|
||||
|
||||
#define ALTO2_DISPLAY_FIFO 16 //!< the display fifo has 16 words
|
||||
#define ALTO2_DISPLAY_SCANLINE_WORDS (ALTO2_DISPLAY_TOTAL_WIDTH/16) //!< words per scanline
|
||||
#define ALTO2_DISPLAY_HEIGHT 808 //!< number of visible scanlines per frame; 808 really, but there are some empty lines?
|
||||
#define ALTO2_DISPLAY_WIDTH 606 //!< visible width of the display; 38 x 16 bit words - 2 pixels
|
||||
#define ALTO2_DISPLAY_VISIBLE_WORDS ((ALTO2_DISPLAY_WIDTH+15)/16) //!< visible words per scanline
|
||||
#define ALTO2_DISPLAY_BITCLOCK 20160000ll //!< display bit clock in in Hertz (20.16MHz)
|
||||
#define ALTO2_DISPLAY_BITTIME(n) (U64(1000000000000)*(n)/ALTO2_DISPLAY_BITCLOCK) //!< display bit time in in pico seconds (~= 49.6031ns)
|
||||
#define ALTO2_DISPLAY_SCANLINE_TIME ALTO2_DISPLAY_BITTIME(ALTO2_DISPLAY_TOTAL_WIDTH)//!< time for a scanline in pico seconds (768 * 49.6031ns ~= 38095.1808ns)
|
||||
#define ALTO2_DISPLAY_VISIBLE_TIME ALTO2_DISPLAY_BITTIME(ALTO2_DISPLAY_WIDTH) //!< time of the visible part of a scanline in pico seconds (606 * 49.6031ns ~= 30059.4786ns)
|
||||
#define ALTO2_DISPLAY_WORD_TIME ALTO2_DISPLAY_BITTIME(16) //!< time for a word in pico seconds (16 pixels * 49.6031ns ~= 793.6496ns)
|
||||
#define ALTO2_DISPLAY_VBLANK_TIME ((ALTO2_DISPLAY_TOTAL_HEIGHT-ALTO2_DISPLAY_HEIGHT)*HZ_TO_ATTOSECONDS(26250)/2)
|
||||
|
||||
#else // ALTO2_DEFINE_CONSTANTS
|
||||
/**
|
||||
* @brief structure of the display context
|
||||
*
|
||||
* Schematics of the task clear and wakeup signal generators
|
||||
* <PRE>
|
||||
* A quote (') appended to a signal name means inverted signal.
|
||||
*
|
||||
* AND | NAND| NOR | FF | Q N174
|
||||
* -----+--- -----+--- -----+--- -----+--- -----
|
||||
* 0 0 | 0 0 0 | 1 0 0 | 1 S'\0| 1 delay
|
||||
* 0 1 | 0 0 1 | 1 0 1 | 0 R'\0| 0
|
||||
* 1 0 | 0 1 0 | 1 1 0 | 0
|
||||
* 1 1 | 1 1 1 | 0 1 1 | 0
|
||||
*
|
||||
*
|
||||
* DVTAC'
|
||||
* >-------+ +-----+
|
||||
* | | FF |
|
||||
* VBLANK'+----+ DELVBLANK' +---+ DELVBLANK +----+ +--|S' |
|
||||
* >------|N174|------+-----|inv|--------------|NAND| VBLANKPULSE | | WAKEDVT'
|
||||
* +----+ | +---+ | o--+-----------|R' Q|---------------------->
|
||||
* | +-| | | | |
|
||||
* +----+ | DDELVBLANK' | +----+ | +-----+
|
||||
* +-|N174|-----------------------------+ | +---+
|
||||
* | +----+ | +------oAND|
|
||||
* | | DSP07.01 | | o----------+
|
||||
* +-------------+ >---------|------o | |
|
||||
* | +---+ |
|
||||
* | |
|
||||
* | +-----+ |
|
||||
* | | FF | | +-----+
|
||||
* DHTAC' +---+ | | | | | FF |
|
||||
* >--------------oNOR| *07.25 +----+ +-|S' | DHTBLK' | | |
|
||||
* BLOCK' | |---------------|NAND| | Q|--+----------|--|S1' | WAKEDHT'
|
||||
* >--------------o | DCSYSCLK | o--------|R' | | >--------|--|S2' Q|--------->
|
||||
* +---+ >---------| | +-----+ | DHTAC' +--|R' |
|
||||
* +----+ | +-----+
|
||||
* +------------+
|
||||
* |
|
||||
* DWTAC' +---+ | +-----+
|
||||
* >--------------oNOR| *07.26 +----+ | | FF |
|
||||
* BLOCK' | |---------|NAND| DSP07.01 | | |
|
||||
* >--------------o | DCSYSCLK| o----------|---|S1' | DWTCN' +---+ DWTCN
|
||||
* +---+ >-------| | +---|S2' Q|--------|inv|-----------+----
|
||||
* +----+ +---|R' | +---+ |
|
||||
* | +-----+ |
|
||||
* SCANEND +----+ | |
|
||||
* >-------------|NAND| CLRBUF' | .----------------------+
|
||||
* DCLK | o----------------+ |
|
||||
* >-------------| | | +-----+
|
||||
* +----+ +--| NAND|
|
||||
* STOPWAKE' | |preWake +----+ WAKEDWT'
|
||||
* >-----------| o--------|N174|--------->
|
||||
* VBLANK' | | +----+
|
||||
* >-----------| |
|
||||
* +-----+
|
||||
* a40c
|
||||
* VBLANKPULSE +----+
|
||||
* -------------|NAND|
|
||||
* | o--+
|
||||
* +--| | |
|
||||
* | +----+ |
|
||||
* +----------|-+
|
||||
* +----------+ |
|
||||
* CURTAC' +---+ | +----+ | a20d
|
||||
* >--------------oNOR| *07.27 +----+ +--|NAND| | +----+
|
||||
* BLOCK' | |---------|NAND| DSP07.07 | o----+----o NOR| preWK +----+ WAKECURT'
|
||||
* >--------------o | DCSYSCLK| o-----------| | | |--------|N174|--------->
|
||||
* +---+ >-------| | +----+ +----o | +----+
|
||||
* +----+ a40d | +----+
|
||||
* a30c |
|
||||
* CURTAC' +----+ |
|
||||
* >------------|NAND| DSP07.03 |
|
||||
* | o--+------------+
|
||||
* +--| | |
|
||||
* | +----+ |
|
||||
* +----------|-+
|
||||
* +----------+ |
|
||||
* | +----+ |
|
||||
* +--|NAND| |
|
||||
* CLRBUF' | o----+
|
||||
* >------------| |
|
||||
* +----+
|
||||
* a30d
|
||||
* </PRE>
|
||||
*/
|
||||
|
||||
#ifndef _A2DISP_H_
|
||||
#define _A2DISP_H_
|
||||
struct {
|
||||
UINT16 state; //!< current state of the display_state_machine()
|
||||
UINT16 hlc; //!< horizontal line counter
|
||||
UINT16 setmode; //!< value written by last SETMODE<-
|
||||
UINT16 inverse; //!< set to 0xffff if line is inverse, 0x0000 otherwise
|
||||
bool halfclock; //!< set 0 for normal pixel clock, 1 for half pixel clock
|
||||
UINT16 fifo[ALTO2_DISPLAY_FIFO]; //!< display word fifo
|
||||
UINT8 wa; //!< fifo input pointer (write address; 4-bit)
|
||||
UINT8 ra; //!< fifo output pointer (read address; 4-bit)
|
||||
UINT8 a63; //!< most recent value read from the PROM a63
|
||||
UINT8 a66; //!< most recent value read from the PROM a66
|
||||
bool dht_blocks; //!< set non-zero, if the DHT executed BLOCK
|
||||
bool dwt_blocks; //!< set non-zero, if the DWT executed BLOCK
|
||||
bool curt_blocks; //!< set non-zero, if the CURT executed BLOCK
|
||||
bool curt_wakeup; //!< set non-zero, if CURT wakeups are generated
|
||||
UINT16 vblank; //!< most recent HLC with VBLANK still high (11-bit)
|
||||
UINT16 xpreg; //!< cursor cursor x position register (10-bit)
|
||||
UINT16 csr; //!< cursor shift register (16-bit)
|
||||
UINT32 curxpos; //!< helper: first cursor word in scanline
|
||||
UINT16 cursor0; //!< helper: shifted cursor data for left word
|
||||
UINT16 cursor1; //!< helper: shifted cursor data for right word
|
||||
UINT16 *raw_bitmap; //!< array of words of the raw bitmap that is displayed
|
||||
UINT8 **scanline; //!< array of scanlines with 1 byte per pixel
|
||||
bitmap_ind16 *bitmap; //!< MAME bitmap with 16 bit indices
|
||||
bool odd_frame; //!< true, if odd frame is drawn
|
||||
} m_dsp;
|
||||
|
||||
/**
|
||||
* @brief PROM a38 contains the STOPWAKE' and MBEMBPTY' signals for the FIFO
|
||||
* <PRE>
|
||||
* The inputs to a38 are the UNLOAD counter RA[0-3] and the DDR<- counter
|
||||
* WA[0-3], and the designer decided to reverse the address lines :-)
|
||||
*
|
||||
* a38 counter FIFO counter
|
||||
* --------------------------
|
||||
* A0 RA[0] fifo_rd
|
||||
* A1 RA[1]
|
||||
* A2 RA[2]
|
||||
* A3 RA[3]
|
||||
* A4 WA[0] fifo_wr
|
||||
* A5 WA[1]
|
||||
* A6 WA[2]
|
||||
* A7 WA[3]
|
||||
*
|
||||
* Only two bits of a38 are used:
|
||||
* O1 (002) = STOPWAKE'
|
||||
* O3 (010) = MBEMPTY'
|
||||
* </PRE>
|
||||
*/
|
||||
UINT8* m_disp_a38;
|
||||
|
||||
//! output bits of PROM A38
|
||||
enum {
|
||||
disp_a38_STOPWAKE = (1 << 1),
|
||||
disp_a38_MBEMPTY = (1 << 3)
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief emulation of PROM a63 in the display schematics page 8
|
||||
* <PRE>
|
||||
* The PROM's address lines are driven by a clock CLK, which is
|
||||
* pixel clock / 24, and an inverted half-scanline signal H[1]'.
|
||||
*
|
||||
* It is 32x8 bits and its output bits (B) are connected to the
|
||||
* signals, as well as its own address lines (A) through a latch
|
||||
* of the type SN74774 like this:
|
||||
*
|
||||
* B 174 A others
|
||||
* ------------------------
|
||||
* 0 5 - HBLANK
|
||||
* 1 0 - HSYNC
|
||||
* 2 4 0
|
||||
* 3 1 1
|
||||
* 4 3 2
|
||||
* 5 2 3
|
||||
* 6 - - SCANEND
|
||||
* 7 - - HLCGATE
|
||||
* ------------------------
|
||||
* H[1]' - 4
|
||||
*
|
||||
* The display_state_machine() is called by the CPU at a rate of pixelclock/24,
|
||||
* which happens to be very close to every 7th CPU micrcocycle.
|
||||
* </PRE>
|
||||
*/
|
||||
UINT8* m_disp_a63;
|
||||
|
||||
enum {
|
||||
disp_a63_HBLANK = (1 << 0), //!< PROM a63 B0 is latched as HBLANK signal
|
||||
disp_a63_HSYNC = (1 << 1), //!< PROM a63 B1 is latched as HSYNC signal
|
||||
disp_a63_A0 = (1 << 2), //!< PROM a63 B2 is the latched next address bit A0
|
||||
disp_a63_A1 = (1 << 3), //!< PROM a63 B3 is the latched next address bit A1
|
||||
disp_a63_A2 = (1 << 4), //!< PROM a63 B4 is the latched next address bit A2
|
||||
disp_a63_A3 = (1 << 5), //!< PROM a63 B5 is the latched next address bit A3
|
||||
disp_a63_SCANEND = (1 << 6), //!< PROM a63 B6 SCANEND signal, which resets the FIFO counters
|
||||
disp_a63_HLCGATE = (1 << 7) //!< PROM a63 B7 HLCGATE signal, which enables counting the HLC
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief vertical blank and synch PROM
|
||||
*
|
||||
* PROM a66 is a 256x4 bit (type 3601), containing the vertical blank + synch.
|
||||
* Address lines are driven by H[1] to H[128] of the the horz. line counters.
|
||||
* The PROM is enabled whenever H[256] and H[512] are both 0.
|
||||
*/
|
||||
UINT8* m_disp_a66;
|
||||
|
||||
enum {
|
||||
disp_a66_VSYNC_ODD = (1 << 0), //!< Q1 (001) is VSYNC for the odd field (with H1024=1)
|
||||
disp_a66_VSYNC_EVEN = (1 << 1), //!< Q2 (002) is VSYNC for the even field (with H1024=0)
|
||||
disp_a66_VBLANK_ODD = (1 << 2), //!< Q3 (004) is VBLANK for the odd field (with H1024=1)
|
||||
disp_a66_VBLANK_EVEN = (1 << 3) //!< Q4 (010) is VBLANK for the even field (with H1024=0)
|
||||
};
|
||||
|
||||
void update_bitmap_word(UINT16* bitmap, int x, int y, UINT16 word); //!< update a word in the screen bitmap
|
||||
void unload_word(); //!< unload the next word from the display FIFO and shift it to the screen
|
||||
void display_state_machine(); //!< function called by the CPU to enter the next display state
|
||||
|
||||
void f2_late_evenfield(void); //!< branch on the evenfield flip-flop
|
||||
|
||||
void init_disp(); //!< initialize the display context
|
||||
void exit_disp(); //!< deinitialize the display context
|
||||
void reset_disp(); //!< reset the display context
|
||||
|
||||
void fake_status_putch(int x, UINT8 ch);
|
||||
void fake_status_printf(int x, const char* format, ...);
|
||||
|
||||
#endif // _A2DISP_H_
|
||||
#endif // ALTO2_DEFINE_CONSTANTS
|
48
src/emu/cpu/alto2/a2dvt.c
Normal file
48
src/emu/cpu/alto2/a2dvt.c
Normal file
@ -0,0 +1,48 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Xerox AltoII display vertical task
|
||||
*
|
||||
* Copyright Juergen Buchmueller <pullmoll@t-online.de>
|
||||
*
|
||||
* Licenses: MAME, GPLv2
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include "alto2cpu.h"
|
||||
|
||||
/**
|
||||
* @brief f1_dvt_block early: disable the display word task
|
||||
*/
|
||||
void alto2_cpu_device::f1_early_dvt_block()
|
||||
{
|
||||
// m_task_wakeup &= ~(1 << m_task);
|
||||
LOG((LOG_DVT,2," BLOCK %s\n", task_name(m_task)));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief called by the CPU when the display vertical task becomes active
|
||||
*/
|
||||
void alto2_cpu_device::activate_dvt()
|
||||
{
|
||||
m_task_wakeup &= ~(1 << m_task);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief initialize display vertical task
|
||||
*/
|
||||
void alto2_cpu_device::init_dvt(int task)
|
||||
{
|
||||
set_f1(task, f1_block, &alto2_cpu_device::f1_early_dvt_block, 0);
|
||||
set_f2(task, f2_dvt_evenfield, 0, &alto2_cpu_device::f2_late_evenfield);
|
||||
m_active_callback[task] = &alto2_cpu_device::activate_dvt;
|
||||
}
|
||||
|
||||
void alto2_cpu_device::exit_dvt()
|
||||
{
|
||||
// nothing to do yet
|
||||
}
|
||||
|
||||
void alto2_cpu_device::reset_dvt()
|
||||
{
|
||||
// nothing to do yet
|
||||
}
|
27
src/emu/cpu/alto2/a2dvt.h
Normal file
27
src/emu/cpu/alto2/a2dvt.h
Normal file
@ -0,0 +1,27 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Xerox AltoII display vertical task (DVT)
|
||||
*
|
||||
* Copyright Juergen Buchmueller <pullmoll@t-online.de>
|
||||
*
|
||||
* Licenses: MAME, GPLv2
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifdef ALTO2_DEFINE_CONSTANTS
|
||||
|
||||
#else // ALTO2_DEFINE_CONSTANTS
|
||||
#ifndef _A2DVT_H_
|
||||
#define _A2DVT_H_
|
||||
|
||||
//! F2 functions for display vertical task
|
||||
enum {
|
||||
f2_dvt_evenfield = f2_task_10 //!< f2 10: load even field
|
||||
};
|
||||
|
||||
void f1_early_dvt_block(); //!< F1 func: disable the display word task
|
||||
void activate_dvt(); //!< called by the CPU when the display vertical task becomes active
|
||||
void init_dvt(int task = task_dvt); //!< initialize the display vertical task
|
||||
void exit_dvt(); //!< deinitialize the display vertical task
|
||||
void reset_dvt(); //!< reset the display vertical task
|
||||
#endif // _A2DVT_H_
|
||||
#endif // ALTO2_DEFINE_CONSTANTS
|
64
src/emu/cpu/alto2/a2dwt.c
Normal file
64
src/emu/cpu/alto2/a2dwt.c
Normal file
@ -0,0 +1,64 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Xerox AltoII display word task
|
||||
*
|
||||
* Copyright Juergen Buchmueller <pullmoll@t-online.de>
|
||||
*
|
||||
* Licenses: MAME, GPLv2
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include "alto2cpu.h"
|
||||
|
||||
//! PROM a38 bit O1 is STOPWAKE' (stop DWT if bit is zero)
|
||||
#define FIFO_STOPWAKE(a38) (0 == (a38 & disp_a38_STOPWAKE) ? true : false)
|
||||
|
||||
/**
|
||||
* @brief block the display word task
|
||||
*/
|
||||
void alto2_cpu_device::f1_early_dwt_block()
|
||||
{
|
||||
m_dsp.dwt_blocks = true;
|
||||
|
||||
/* clear the wakeup for the display word task */
|
||||
m_task_wakeup &= ~(1 << m_task);
|
||||
LOG((LOG_DWT,2," BLOCK %s\n", task_name(m_task)));
|
||||
|
||||
/* wakeup the display horizontal task, if it didn't block itself */
|
||||
if (!m_dsp.dht_blocks)
|
||||
m_task_wakeup |= 1 << task_dht;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief load the display data register
|
||||
*/
|
||||
void alto2_cpu_device::f2_late_dwt_load_ddr()
|
||||
{
|
||||
LOG((LOG_DWT,2," DDR<- BUS (%#o)\n", m_bus));
|
||||
m_dsp.fifo[m_dsp.wa] = m_bus;
|
||||
m_dsp.wa = (m_dsp.wa + 1) % ALTO2_DISPLAY_FIFO;
|
||||
UINT8 a38 = m_disp_a38[m_dsp.ra * 16 + m_dsp.wa];
|
||||
if (FIFO_STOPWAKE(a38))
|
||||
m_task_wakeup &= ~(1 << task_dwt);
|
||||
LOG((LOG_DWT,2, " DWT push %04x into FIFO[%02o]%s\n",
|
||||
m_bus, (m_dsp.wa - 1) & (ALTO2_DISPLAY_FIFO - 1),
|
||||
FIFO_STOPWAKE(a38) ? " STOPWAKE" : ""));
|
||||
}
|
||||
|
||||
void alto2_cpu_device::init_dwt(int task)
|
||||
{
|
||||
set_f1(task, f1_block, &alto2_cpu_device::f1_early_dwt_block, 0);
|
||||
set_f2(task, f2_dwt_load_ddr, 0, &alto2_cpu_device::f2_late_dwt_load_ddr);
|
||||
}
|
||||
|
||||
void alto2_cpu_device::exit_dwt()
|
||||
{
|
||||
// nothing to do yet
|
||||
}
|
||||
|
||||
void alto2_cpu_device::reset_dwt()
|
||||
{
|
||||
m_dsp.dwt_blocks = false;
|
||||
memset(m_dsp.fifo, 0, sizeof(m_dsp.fifo));
|
||||
m_dsp.wa = 0;
|
||||
m_dsp.ra = 0;
|
||||
}
|
27
src/emu/cpu/alto2/a2dwt.h
Normal file
27
src/emu/cpu/alto2/a2dwt.h
Normal file
@ -0,0 +1,27 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Xerox AltoII display word task (DWT)
|
||||
*
|
||||
* Copyright Juergen Buchmueller <pullmoll@t-online.de>
|
||||
*
|
||||
* Licenses: MAME, GPLv2
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifdef ALTO2_DEFINE_CONSTANTS
|
||||
|
||||
#else // ALTO2_DEFINE_CONSTANTS
|
||||
#ifndef _A2DWT_H_
|
||||
#define _A2DWT_H_
|
||||
|
||||
//! F2 functions for display word task
|
||||
enum {
|
||||
f2_dwt_load_ddr = f2_task_10 //!< f2 10: load display data register
|
||||
};
|
||||
|
||||
void f1_early_dwt_block(); //!< F1 func: block the display word task
|
||||
void f2_late_dwt_load_ddr(); //!< F2 func: load the display data register
|
||||
void init_dwt(int task = task_dwt); //!< initialize the display word task
|
||||
void exit_dwt(); //!< deinitialize the display word task
|
||||
void reset_dwt(); //!< reset the display word task
|
||||
#endif // _A2DWT_H_
|
||||
#endif // ALTO2_DEFINE_CONSTANTS
|
690
src/emu/cpu/alto2/a2emu.c
Normal file
690
src/emu/cpu/alto2/a2emu.c
Normal file
@ -0,0 +1,690 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Xerox AltoII emulator task
|
||||
*
|
||||
* Copyright Juergen Buchmueller <pullmoll@t-online.de>
|
||||
*
|
||||
* Licenses: MAME, GPLv2
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include "alto2cpu.h"
|
||||
|
||||
/** @brief CTL2K_U3 address line for F2 function */
|
||||
#define CTL2K_U3(f2) (f2 == f2_emu_idisp ? 0x80 : 0x00)
|
||||
|
||||
/**
|
||||
* width,from,to of the 16 bit instruction register
|
||||
* 1 1 1 1 1 1
|
||||
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
|
||||
* =============================================================
|
||||
* x - - - - - - - - - - - - - - - arithmetic operation
|
||||
* 0 m m - - - - - - - - - - - - - memory function
|
||||
* 0 0 0 - - - - - - - - - - - - - jump functions
|
||||
* 0 0 1 d d - - - - - - - - - - - LDA dstAC
|
||||
* 0 1 0 d d - - - - - - - - - - - STA dstAC
|
||||
* 0 1 1 - - - - - - - - - - - - - augmented functions
|
||||
* 1 s s - - - - - - - - - - - - - source accumulator (0-3)
|
||||
* 1 - - d d - - - - - - - - - - - destination accumulator (0-3)
|
||||
* 1 s s d d x x x - - - - - - - - accumulator function
|
||||
* 1 s s d d 0 0 0 - - - - - - - - COM dstAC, srcAC
|
||||
* 1 s s d d 0 0 1 - - - - - - - - NEG dstAC, srcAC
|
||||
* 1 s s d d 0 1 0 - - - - - - - - MOV dstAC, srcAC
|
||||
* 1 s s d d 0 1 1 - - - - - - - - INC dstAC, srcAC
|
||||
* 1 s s d d 1 0 0 - - - - - - - - ADC dstAC, srcAC
|
||||
* 1 s s d d 1 0 1 - - - - - - - - SUB dstAC, srcAC
|
||||
* 1 s s d d 1 1 0 - - - - - - - - ADD dstAC, srcAC
|
||||
* 1 s s d d 1 1 1 - - - - - - - - AND dstAC, srcAC
|
||||
* 1 - - - - - - - x x - - - - - - shift operation
|
||||
* 1 - - - - - - - 0 0 - - - - - - nothing
|
||||
* 1 - - - - - - - 0 1 - - - - - - rotate left through carry
|
||||
* 1 - - - - - - - 1 0 - - - - - - rotate right through carry
|
||||
* 1 - - - - - - - 1 1 - - - - - - swap byte halves
|
||||
* 1 - - - - - - - - - x x - - - - carry in mode
|
||||
* 1 - - - - - - - - - 0 0 - - - - nothing
|
||||
* 1 - - - - - - - - - 0 1 - - - - Z carry in is zero
|
||||
* 1 - - - - - - - - - 1 0 - - - - O carry in is one
|
||||
* 1 - - - - - - - - - 1 1 - - - - C carry in is complemented carry
|
||||
* 1 - - - - - - - - - - - x - - - NL
|
||||
* - - - - - - - - - - - - - x x x conditional execution
|
||||
* - - - - - - - - - - - - - 0 0 0 NVR never skip
|
||||
* - - - - - - - - - - - - - 0 0 1 SKP always skip
|
||||
* - - - - - - - - - - - - - 0 1 0 SZC skip if carry result is zero
|
||||
* - - - - - - - - - - - - - 0 1 1 SNC skip if carry result is non-zero
|
||||
* - - - - - - - - - - - - - 1 0 0 SZR skip if 16 bit result is zero
|
||||
* - - - - - - - - - - - - - 1 0 1 SNR skip if 16 bit result is non-zero
|
||||
* - - - - - - - - - - - - - 1 1 0 SEZ skip if either result is zero
|
||||
* - - - - - - - - - - - - - 1 1 1 SBN skip if both results are non-zero
|
||||
*/
|
||||
#define IR_ARITH(ir) X_RDBITS(ir,16, 0, 0)
|
||||
#define IR_SrcAC(ir) X_RDBITS(ir,16, 1, 2)
|
||||
#define IR_DstAC(ir) X_RDBITS(ir,16, 3, 4)
|
||||
#define IR_AFunc(ir) X_RDBITS(ir,16, 5, 7)
|
||||
#define IR_SH(ir) X_RDBITS(ir,16, 8, 9)
|
||||
#define IR_CY(ir) X_RDBITS(ir,16,10,11)
|
||||
#define IR_NL(ir) X_RDBITS(ir,16,12,12)
|
||||
#define IR_SK(ir) X_RDBITS(ir,16,13,15)
|
||||
|
||||
#define IR_MFunc(ir) X_RDBITS(ir,16, 1, 2)
|
||||
#define IR_JFunc(ir) X_RDBITS(ir,16, 3, 4)
|
||||
#define IR_I(ir) X_RDBITS(ir,16, 5, 5)
|
||||
#define IR_X(ir) X_RDBITS(ir,16, 6, 7)
|
||||
#define IR_DISP(ir) X_RDBITS(ir,16, 8,15)
|
||||
#define IR_AUGFUNC(ir) X_RDBITS(ir,16, 3, 7)
|
||||
|
||||
#define op_MFUNC_MASK 0060000 //!< instruction register memory function mask
|
||||
#define op_MFUNC_JUMP 0000000 //!< jump functions value
|
||||
#define op_JUMP_MASK 0014000 //!< jump functions mask
|
||||
#define op_JMP 0000000 //!< jump
|
||||
#define op_JSR 0004000 //!< jump to subroutine
|
||||
#define op_ISZ 0010000 //!< increment and skip if zero
|
||||
#define op_DSZ 0014000 //!< decrement and skip if zero
|
||||
#define op_LDA 0020000 //!< load accu functions value
|
||||
#define op_STA 0040000 //!< store accu functions value
|
||||
#define op_AUGMENTED 0060000 //!< store accu functions value
|
||||
#define op_AUGM_MASK 0077400 //!< mask covering all augmented functions
|
||||
#define op_AUGM_NODISP 0061000 //!< augmented functions w/o displacement
|
||||
#define op_AUGM_SUBFUNC 0000037 //!< mask for augmented subfunctions in DISP
|
||||
#define op_CYCLE 0060000 //!< cycle AC0
|
||||
#define op_NODISP 0061000 //!< NODISP: opcodes without displacement
|
||||
#define op_DIR 0061000 //!< disable interrupts
|
||||
#define op_EIR 0061001 //!< enable interrupts
|
||||
#define op_BRI 0061002 //!< branch and return from interrupt
|
||||
#define op_RCLK 0061003 //!< read clock to AC0, AC1
|
||||
#define op_SIO 0061004 //!< start I/O
|
||||
#define op_BLT 0061005 //!< block transfer
|
||||
#define op_BLKS 0061006 //!< block set value
|
||||
#define op_SIT 0061007 //!< start interval timer
|
||||
#define op_JMPRAM 0061010 //!< jump to microcode RAM (actually ROM, too)
|
||||
#define op_RDRAM 0061011 //!< read microcode RAM
|
||||
#define op_WRTRAM 0061012 //!< write microcode RAM
|
||||
#define op_DIRS 0061013 //!< disable interrupts, and skip, if already disabled
|
||||
#define op_VERS 0061014 //!< get microcode version in AC0
|
||||
#define op_DREAD 0061015 //!< double word read (Alto II)
|
||||
#define op_DWRITE 0061016 //!< double word write (Alto II)
|
||||
#define op_DEXCH 0061017 //!< double word exchange (Alto II)
|
||||
#define op_MUL 0061020 //!< unsigned multiply
|
||||
#define op_DIV 0061021 //!< unsigned divide
|
||||
#define op_DIAGNOSE1 0061022 //!< write two different accus in fast succession
|
||||
#define op_DIAGNOSE2 0061023 //!< write Hamming code and memory
|
||||
#define op_BITBLT 0061024 //!< bit-aligned block transfer
|
||||
#define op_XMLDA 0061025 //!< load accu AC0 from extended memory (Alto II/XM)
|
||||
#define op_XMSTA 0061026 //!< store accu AC0 to extended memory (Alto II/XM)
|
||||
#define op_JSRII 0064400 //!< jump to subroutine PC relative, doubly indirect
|
||||
#define op_JSRIS 0065000 //!< jump to subroutine AC2 relative, doubly indirect
|
||||
#define op_CONVERT 0067000 //!< convert bitmapped font to bitmap
|
||||
#define op_ARITH_MASK 0103400 //!< mask for arithmetic functions
|
||||
#define op_COM 0100000 //!< one's complement
|
||||
#define op_NEG 0100400 //!< two's complement
|
||||
#define op_MOV 0101000 //!< accu transfer
|
||||
#define op_INC 0101400 //!< increment
|
||||
#define op_ADC 0102000 //!< add one's complement
|
||||
#define op_SUB 0102400 //!< subtract by adding two's complement
|
||||
#define op_ADD 0103000 //!< add
|
||||
#define op_AND 0103400 //!< logical and
|
||||
|
||||
#define ea_DIRECT 0000000 //!< effective address is direct
|
||||
#define ea_INDIRECT 0002000 //!< effective address is indirect
|
||||
#define ea_MASK 0001400 //!< mask for effective address modes
|
||||
#define ea_PAGE0 0000000 //!< e is page 0 address
|
||||
#define ea_PCREL 0000400 //!< e is PC + signed displacement
|
||||
#define ea_AC2REL 0001000 //!< e is AC2 + signed displacement
|
||||
#define ea_AC3REL 0001400 //!< e is AC3 + signed displacement
|
||||
|
||||
|
||||
#define sh_MASK 0000300 //!< shift mode mask (do novel shifts)
|
||||
#define sh_L 0000100 //!< rotate left through carry
|
||||
#define sh_R 0000200 //!< rotate right through carry
|
||||
#define sh_S 0000300 //!< swap byte halves
|
||||
|
||||
#define cy_MASK 0000060 //!< carry in mode mask
|
||||
#define cy_Z 0000020 //!< carry in is zero
|
||||
#define cy_O 0000040 //!< carry in is one
|
||||
#define cy_C 0000060 //!< carry in is complemented carry
|
||||
|
||||
#define nl_MASK 0000010 //!< no-load mask
|
||||
#define nl_NONE 0000010 //!< do not load DstAC nor carry
|
||||
|
||||
#define sk_MASK 0000007 //!< skip mask
|
||||
#define sk_NVR 0000000 //!< never skip
|
||||
#define sk_SKP 0000001 //!< always skip
|
||||
#define sk_SZC 0000002 //!< skip if carry result is zero
|
||||
#define sk_SNC 0000003 //!< skip if carry result is non-zero
|
||||
#define sk_SZR 0000004 //!< skip if 16-bit result is zero
|
||||
#define sk_SNR 0000005 //!< skip if 16-bit result is non-zero
|
||||
#define sk_SEZ 0000006 //!< skip if either result is zero
|
||||
#define sk_SBN 0000007 //!< skip if both results are non-zero
|
||||
|
||||
/**
|
||||
* @brief register selection
|
||||
*
|
||||
* <PRE>
|
||||
* From the schematics: 08_ALU, page 6 (PDF page 4)
|
||||
*
|
||||
* EMACT emulator task active
|
||||
* F2[0-2]=111b <-ACSOURCE and F2_17
|
||||
* F2[0-2]=101b DNS<- and ACDEST<-
|
||||
*
|
||||
* u49 (8 input NAND 74S30)
|
||||
* ----------------------------------------------
|
||||
* F2[0] & F2[2] & F2[1]' & IR[03]' & EMACT
|
||||
*
|
||||
* F2[0-2] IR[03] EMACT output u49pin8
|
||||
* --------------------------------------
|
||||
* 101 0 1 0
|
||||
* all others 1
|
||||
*
|
||||
*
|
||||
* u59 (8 input NAND 74S30)
|
||||
* ----------------------------------------------
|
||||
* F2[0] & F2[2] & F2[1] & IR[01]' & EMACT
|
||||
*
|
||||
* F2[0-2] IR[01] EMACT output u59pin8
|
||||
* --------------------------------------
|
||||
* 111 0 1 0
|
||||
* all others 1
|
||||
*
|
||||
* u70d (2 input NOR 74S02 used as inverter)
|
||||
* ---------------------------------------------
|
||||
* RSEL3 -> RSEL3'
|
||||
*
|
||||
* u79b (3 input NAND 74S10)
|
||||
* ---------------------------------------------
|
||||
* u49pin8 u59pin8 RSEL3' output 6RA3
|
||||
* -------------------------------------
|
||||
* 1 1 1 0
|
||||
* 0 x x 1
|
||||
* x 0 x 1
|
||||
* x x 0 1
|
||||
*
|
||||
*
|
||||
* u60 (8 input NAND 74S30)
|
||||
* ----------------------------------------------
|
||||
* F2[0] & F2[2] & F2[1]' & IR[02]' & EMACT
|
||||
*
|
||||
* F2[0-2] IR[02] EMACT output u60pin8
|
||||
* --------------------------------------
|
||||
* 101 0 1 0
|
||||
* all others 1
|
||||
*
|
||||
* u50 (8 input NAND 74S30)
|
||||
* ----------------------------------------------
|
||||
* F2[0] & F2[2] & F2[1] & IR[04]' & EMACT
|
||||
*
|
||||
* F2[0-2] IR[04] EMACT output u50pin8
|
||||
* --------------------------------------
|
||||
* 111 0 1 0
|
||||
* all others 1
|
||||
*
|
||||
* u70c (2 input NOR 74S02 used as inverter)
|
||||
* ---------------------------------------------
|
||||
* RSEL4 -> RSEL4'
|
||||
*
|
||||
*
|
||||
* u79c (3 input NAND 74S10)
|
||||
* ---------------------------------------------
|
||||
* u60pin8 u50pin8 RSEL4' output 8RA4
|
||||
* -------------------------------------
|
||||
* 1 1 1 0
|
||||
* 0 x x 1
|
||||
* x 0 x 1
|
||||
* x x 0 1
|
||||
*
|
||||
* BUG?: schematics seem to have swapped IR(04)' and IR(02)' inputs for the
|
||||
* RA4 decoding, because SrcAC is selected from IR[1-2]?
|
||||
* </PRE>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief bs_disp early: drive bus by IR[8-15], possibly sign extended
|
||||
*
|
||||
* The high order bits of IR cannot be read directly, but the
|
||||
* displacement field of IR (8 low order bits) may be read with
|
||||
* the <-DISP bus source. If the X field of the instruction is
|
||||
* zero (i.e., it specifies page 0 addressing), then the DISP
|
||||
* field of the instruction is put on BUS[8-15] and BUS[0-7]
|
||||
* is zeroed. If the X field of the instruction is non-zero
|
||||
* (i.e. it specifies PC-relative or base-register addressing)
|
||||
* then the DISP field is sign-extended and put on the bus.
|
||||
*
|
||||
*/
|
||||
void alto2_cpu_device::bs_early_emu_disp()
|
||||
{
|
||||
UINT16 r = IR_DISP(m_emu.ir);
|
||||
if (IR_X(m_emu.ir)) {
|
||||
r = ((signed char)r) & 0177777;
|
||||
}
|
||||
LOG((LOG_EMU,2, " <-DISP (%06o)\n", r));
|
||||
m_bus &= r;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief f1_block early: block task
|
||||
*
|
||||
* The task request for the active task is cleared
|
||||
*/
|
||||
void alto2_cpu_device::f1_early_emu_block()
|
||||
{
|
||||
#if 0
|
||||
CPU_CLR_TASK_WAKEUP(m_task);
|
||||
LOG((LOG_EMU,2, " BLOCK %02o:%s\n", m_task, task_name(m_task)));
|
||||
#elif 0
|
||||
fatal(1, "Emulator task want's to BLOCK.\n" \
|
||||
"%s-%04o: r:%02o af:%02o bs:%02o f1:%02o f2:%02o" \
|
||||
" t:%o l:%o next:%05o next2:%05o cycle:%lld\n",
|
||||
task_name(m_task), m_mpc,
|
||||
m_rsel, m_daluf, m_dbs, m_df1, mdf2,
|
||||
m_dloadt, m_dloatl, m_next, m_next2,
|
||||
ntime() / CPU_MICROCYCLE_TIME);
|
||||
#else
|
||||
/* just ignore (?) */
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief f1_load_rmr late: load the reset mode register
|
||||
*/
|
||||
void alto2_cpu_device::f1_late_emu_load_rmr()
|
||||
{
|
||||
LOG((LOG_EMU,2," RMR<-; BUS (%#o)\n", m_bus));
|
||||
m_reset_mode = m_bus;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief f1_load_esrb late: load the extended S register bank from BUS[12-14]
|
||||
*/
|
||||
void alto2_cpu_device::f1_late_emu_load_esrb()
|
||||
{
|
||||
LOG((LOG_EMU,2," ESRB<-; BUS[12-14] (%#o)\n", m_bus));
|
||||
m_s_reg_bank[m_task] = X_RDBITS(m_bus,16,12,14);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief f1_rsnf early: drive the bus from the Ethernet node ID
|
||||
*
|
||||
* TODO: move this to the Ethernet code? It's really a emulator
|
||||
* specific function that is decoded by the Ethernet card.
|
||||
*/
|
||||
void alto2_cpu_device::f1_early_rsnf()
|
||||
{
|
||||
UINT16 r = 0177400 | m_ether_id;
|
||||
LOG((LOG_EMU,2," <-RSNF; (%#o)\n", r));
|
||||
m_bus &= r;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief f1_startf early: defines commands for for I/O hardware, including Ethernet
|
||||
* <PRE>
|
||||
* (SIO) Start I/O is included to facilitate I/O control, It places the contents of
|
||||
* AC0 on the processor bus and executes the STARTF function (F1 = 17B). By convention,
|
||||
* bits of AC0 must be "1" in order to signal devices. See Appendix C for a summary of
|
||||
* assigned bits.
|
||||
* Bit 0 100000B Standard Alto: Software boot feature
|
||||
* Bit 14 000002B Standard Alto: Ethernet
|
||||
* Bit 15 000001B Standard Alto: Ethernet
|
||||
* If bit 0 of AC0 is 1, and if an Ethernet board is plugged into the Alto, the machine
|
||||
* will boot, just as if the "boot button" were pressed (see sections 3.4, 8.4 and 9.2.2
|
||||
* for discussions of bootstrapping).
|
||||
*
|
||||
* SIO also returns a result in AC0. If the Ethernet hardware is installed, the serial
|
||||
* number and/or Ethernet host address of the machine (0-377B) is loaded into AC0[8-15].
|
||||
* (On Alto I, the serial number and Ethernet host address are equivalent; on Alto II,
|
||||
* the value loaded into AC0 is the Ethernet host address only.) If Ethernet hardware
|
||||
* is missing, AC0[8-15] = 377B. Microcode installed after June 1976, which this manual
|
||||
* describes, returns AC0[0] = 0. Microcode installed prior to June 1976 returns
|
||||
* AC0[0] = 1; this is a quick way to acquire the approximate vintage of a machine's
|
||||
* microcode.
|
||||
* </PRE>
|
||||
*
|
||||
* TODO: move this to the Ethernet code? It's really a emulator
|
||||
* specific function that is decoded by the Ethernet card.
|
||||
*/
|
||||
void alto2_cpu_device::f1_early_startf()
|
||||
{
|
||||
LOG((LOG_EMU,2," STARTF (BUS is %06o)\n", m_bus));
|
||||
/* TODO: what do we do here? reset the CPU on bit 0? */
|
||||
if (X_BIT(m_bus,16,0)) {
|
||||
LOG((LOG_EMU,2,"**** Software boot feature\n"));
|
||||
soft_reset();
|
||||
} else {
|
||||
LOG((LOG_EMU,2,"**** Ethernet start function\n"));
|
||||
eth_startf();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief branch on odd bus
|
||||
*/
|
||||
void alto2_cpu_device::f2_late_busodd()
|
||||
{
|
||||
UINT16 r = m_bus & 1;
|
||||
LOG((LOG_EMU,2," BUSODD; %sbranch (%#o|%#o)\n", r ? "" : "no ", m_next2, r));
|
||||
m_next2 |= r;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief f2_magic late: shift and use T[0] or T[15] for bit 15 or 0
|
||||
*/
|
||||
void alto2_cpu_device::f2_late_magic()
|
||||
{
|
||||
int XC;
|
||||
switch (m_d_f1) {
|
||||
case f1_l_lsh_1: // <-L MLSH 1
|
||||
XC = (m_t >> 15) & 1;
|
||||
m_shifter = (m_l << 1) | XC;
|
||||
LOG((LOG_EMU,2," <-L MLSH 1 (shifer:%06o XC:%o)", m_shifter, XC));
|
||||
break;
|
||||
case f1_l_rsh_1: // <-L MRSH 1
|
||||
XC = (m_t & 1) << 15;
|
||||
m_shifter = (m_l >> 1) | XC;
|
||||
LOG((LOG_EMU,2," <-L MRSH 1 (shifter:%06o XC:%o)", m_shifter, XC));
|
||||
break;
|
||||
case f1_l_lcy_8: // <-L LCY 8
|
||||
m_shifter = (m_l >> 8) | (m_l << 8);
|
||||
break;
|
||||
default: // other
|
||||
m_shifter = m_l;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief do novel shifts: modify RESELECT with DstAC = (3 - IR[3-4])
|
||||
*/
|
||||
void alto2_cpu_device::f2_early_load_dns()
|
||||
{
|
||||
X_WRBITS(m_rsel, 5, 3, 4, IR_DstAC(m_emu.ir) ^ 3);
|
||||
LOG((LOG_EMU,2," DNS<-; rsel := DstAC (%#o %s)\n", m_rsel, r_name(m_rsel)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief do novel shifts
|
||||
*
|
||||
* <PRE>
|
||||
* New emulator carry is selected by instruction register
|
||||
* bits CY = IR[10-11]. R register and emulator carry are
|
||||
* loaded only if NL = IR[12] is 0 (NL = no load).
|
||||
* SKIP is set according to SK = IR[13-15].
|
||||
*
|
||||
* CARRY = !m_emu.cy
|
||||
* exorB = IR11 ^ IR10
|
||||
* ORA = !(exorB | CARRY)
|
||||
* = (exorB | CARRY) ^ 1
|
||||
* exorC = ORA ^ !IR11
|
||||
* = ORA ^ IR11 ^ 1
|
||||
* exorD = exorC ^ LALUC0
|
||||
* XC = !(!(DNS & exorD) & !(MAGIC & OUTza))
|
||||
* = (DNS & exorD) | (MAGIC & OUTza)
|
||||
* = exorD, because this is DNS
|
||||
* NEWCARRY = [XC, L(00), L(15), XC] for F1 = no shift, <-L RSH 1, <-L LSH 1, LCY 8
|
||||
* SHZERO = shifter == 0
|
||||
* DCARRY = !((!IR12 & NEWCARRY) | (IR12 & CARRY))
|
||||
* = (((IR12 ^ 1) & NEWCARRY) | (IR12 & CARRY)) ^ 1
|
||||
* DSKIP = !((!NEWCARRY & IR14) | (SHZERO & IR13)) ^ !IR15
|
||||
* = ((((NEWCARRY ^ 1) & IR14) | (SHZERO & IR13)) ^ 1) ^ (IR15 ^ 1)
|
||||
* = (((NEWCARRY ^ 1) & IR14) | (SHZERO & IR13)) ^ IR15
|
||||
* </PRE>
|
||||
*/
|
||||
void alto2_cpu_device::f2_late_load_dns()
|
||||
{
|
||||
UINT8 IR10 = X_BIT(m_emu.ir,16,10);
|
||||
UINT8 IR11 = X_BIT(m_emu.ir,16,11);
|
||||
UINT8 IR12 = X_BIT(m_emu.ir,16,12);
|
||||
UINT8 IR13 = X_BIT(m_emu.ir,16,13);
|
||||
UINT8 IR14 = X_BIT(m_emu.ir,16,14);
|
||||
UINT8 IR15 = X_BIT(m_emu.ir,16,15);
|
||||
UINT8 exorB = IR11 ^ IR10;
|
||||
UINT8 CARRY = m_emu.cy ^ 1;
|
||||
UINT8 ORA = (exorB | CARRY) ^ 1;
|
||||
UINT8 exorC = ORA ^ (IR11 ^ 1);
|
||||
UINT8 exorD = exorC ^ m_laluc0;
|
||||
UINT8 XC = exorD;
|
||||
UINT8 NEWCARRY;
|
||||
UINT8 DCARRY;
|
||||
UINT8 DSKIP;
|
||||
UINT8 SHZERO;
|
||||
|
||||
switch (m_d_f1) {
|
||||
case f1_l_rsh_1: // <-L RSH 1
|
||||
NEWCARRY = m_l & 1;
|
||||
m_shifter = ((m_l >> 1) | (XC << 15)) & 0177777;
|
||||
LOG((LOG_EMU,2," DNS; <-L RSH 1 (shifter:%06o XC:%o NEWCARRY:%o)", m_shifter, XC, NEWCARRY));
|
||||
break;
|
||||
case f1_l_lsh_1: // <-L LSH 1
|
||||
NEWCARRY = (m_l >> 15) & 1;
|
||||
m_shifter = ((m_l << 1) | XC) & 0177777;
|
||||
LOG((LOG_EMU,2," DNS; <-L LSH 1 (shifter:%06o XC:%o NEWCARRY:%o)", m_shifter, XC, NEWCARRY));
|
||||
break;
|
||||
case f1_l_lcy_8: // <-L LCY 8
|
||||
NEWCARRY = XC;
|
||||
m_shifter = (m_l >> 8) | (m_l << 8);
|
||||
LOG((LOG_EMU,2," DNS; (shifter:%06o NEWCARRY:%o)", m_shifter, NEWCARRY));
|
||||
break;
|
||||
default: // other
|
||||
NEWCARRY = XC;
|
||||
m_shifter = m_l;
|
||||
LOG((LOG_EMU,2," DNS; (shifter:%06o NEWCARRY:%o)", m_shifter, NEWCARRY));
|
||||
break;
|
||||
}
|
||||
SHZERO = (m_shifter == 0);
|
||||
DCARRY = (((IR12 ^ 1) & NEWCARRY) | (IR12 & CARRY)) ^ 1;
|
||||
DSKIP = (((NEWCARRY ^ 1) & IR14) | (SHZERO & IR13)) ^ IR15;
|
||||
|
||||
m_emu.cy = DCARRY; // DCARRY is latched as new m_emu.cy
|
||||
m_emu.skip = DSKIP; // DSKIP is latched as new m_emu.skip
|
||||
|
||||
/* !(IR12 & DNS) -> WR' = 0 for the register file */
|
||||
if (!IR12) {
|
||||
m_r[m_rsel] = m_shifter;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief destiantion accu: modify RSELECT with DstAC = (3 - IR[3-4])
|
||||
*/
|
||||
void alto2_cpu_device::f2_early_acdest()
|
||||
{
|
||||
X_WRBITS(m_rsel, 5, 3, 4, IR_DstAC(m_emu.ir) ^ 3);
|
||||
LOG((LOG_EMU,2," ACDEST<-; mux (rsel:%#o %s)\n", m_rsel, r_name(m_rsel)));
|
||||
}
|
||||
|
||||
#if ALTO2_DEBUG
|
||||
void alto2_cpu_device::bitblt_info()
|
||||
{
|
||||
static const char *type_name[4] = {"bitmap","complement","and gray","gray"};
|
||||
static const char *oper_name[4] = {"replace","paint","invert","erase"};
|
||||
int bbt = m_r[rsel_ac2];
|
||||
int val = debug_read_mem(bbt);
|
||||
|
||||
LOG((LOG_EMU,3," BITBLT AC1:%06o AC2:%06o\n", m_r[rsel_ac1], m_r[rsel_ac2]));
|
||||
LOG((LOG_EMU,3," function : %06o\n", val));
|
||||
LOG((LOG_EMU,3," src extRAM: %o\n", X_BIT(val,16,10)));
|
||||
LOG((LOG_EMU,3," dst extRAM: %o\n", X_BIT(val,16,11)));
|
||||
LOG((LOG_EMU,3," src type : %o (%s)\n", X_RDBITS(val,16,12,13), type_name[X_RDBITS(val,16,12,13)]));
|
||||
LOG((LOG_EMU,3," operation : %o (%s)\n", X_RDBITS(val,16,14,15), oper_name[X_RDBITS(val,16,14,15)]));
|
||||
val = debug_read_mem(bbt+1);
|
||||
LOG((LOG_EMU,3," unused AC2: %06o (%d)\n", val, val));
|
||||
val = debug_read_mem(bbt+2);
|
||||
LOG((LOG_EMU,3," DBCA : %06o (%d)\n", val, val));
|
||||
val = debug_read_mem(bbt+3);
|
||||
LOG((LOG_EMU,3," DBMR : %06o (%d words)\n", val, val));
|
||||
val = debug_read_mem(bbt+4);
|
||||
LOG((LOG_EMU,3," DLX : %06o (%d bits)\n", val, val));
|
||||
val = debug_read_mem(bbt+5);
|
||||
LOG((LOG_EMU,3," DTY : %06o (%d scanlines)\n", val, val));
|
||||
val = debug_read_mem(bbt+6);
|
||||
LOG((LOG_EMU,3," DW : %06o (%d bits)\n", val, val));
|
||||
val = debug_read_mem(bbt+7);
|
||||
LOG((LOG_EMU,3," DH : %06o (%d scanlines)\n", val, val));
|
||||
val = debug_read_mem(bbt+8);
|
||||
LOG((LOG_EMU,3," SBCA : %06o (%d)\n", val, val));
|
||||
val = debug_read_mem(bbt+9);
|
||||
LOG((LOG_EMU,3," SBMR : %06o (%d words)\n", val, val));
|
||||
val = debug_read_mem(bbt+10);
|
||||
LOG((LOG_EMU,3," SLX : %06o (%d bits)\n", val, val));
|
||||
val = debug_read_mem(bbt+11);
|
||||
LOG((LOG_EMU,3," STY : %06o (%d scanlines)\n", val, val));
|
||||
LOG((LOG_EMU,3," GRAY0-3 : %06o %06o %06o %06o\n",
|
||||
debug_read_mem(bbt+12), debug_read_mem(bbt+13),
|
||||
debug_read_mem(bbt+14), debug_read_mem(bbt+15)));
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
/**
|
||||
* @brief load instruction register IR and branch on IR[0,5-7]
|
||||
*
|
||||
* Loading the IR clears the skip latch.
|
||||
*/
|
||||
void alto2_cpu_device::f2_late_load_ir()
|
||||
{
|
||||
UINT16 r = (X_BIT(m_bus,16,0) << 3) | X_RDBITS(m_bus,16,5,7);
|
||||
|
||||
#if ALTO2_DEBUG
|
||||
/* special logging of some opcodes */
|
||||
switch (m_bus) {
|
||||
case op_CYCLE:
|
||||
LOG((LOG_EMU,3," CYCLE AC0:#o\n", m_r[rsel_ac0]));
|
||||
break;
|
||||
case op_CYCLE + 1: case op_CYCLE + 2: case op_CYCLE + 3: case op_CYCLE + 4:
|
||||
case op_CYCLE + 5: case op_CYCLE + 6: case op_CYCLE + 7: case op_CYCLE + 8:
|
||||
case op_CYCLE + 9: case op_CYCLE +10: case op_CYCLE +11: case op_CYCLE +12:
|
||||
case op_CYCLE +13: case op_CYCLE +14: case op_CYCLE +15:
|
||||
LOG((LOG_EMU,3," CYCLE %#o\n", m_bus - op_CYCLE));
|
||||
break;
|
||||
case op_BLT:
|
||||
LOG((LOG_EMU,3," BLT dst:%#o src:%#o size:%#o\n",
|
||||
(m_r[rsel_ac1] + m_r[rsel_ac3] + 1) & 0177777,
|
||||
(m_r[rsel_ac0] + 1) & 017777, -m_r[rsel_ac3] & 0177777));
|
||||
break;
|
||||
case op_BLKS:
|
||||
LOG((LOG_EMU,3," BLKS dst:%#o val:%#o size:%#o\n",
|
||||
(m_r[rsel_ac1] + m_r[rsel_ac3] + 1) & 0177777,
|
||||
m_r[rsel_ac0], -m_r[rsel_ac3] & 0177777));
|
||||
break;
|
||||
case op_DIAGNOSE1:
|
||||
LOG((LOG_EMU,3," DIAGNOSE1 AC0:%06o AC1:%06o AC2:%06o AC3:%06o\n",
|
||||
m_r[rsel_ac0], m_r[rsel_ac1],
|
||||
m_r[rsel_ac2], m_r[rsel_ac3]));
|
||||
break;
|
||||
case op_DIAGNOSE2:
|
||||
LOG((LOG_EMU,3," DIAGNOSE2 AC0:%06o AC1:%06o AC2:%06o AC3:%06o\n",
|
||||
m_r[rsel_ac0], m_r[rsel_ac1],
|
||||
m_r[rsel_ac2], m_r[rsel_ac3]));
|
||||
break;
|
||||
case op_BITBLT:
|
||||
bitblt_info();
|
||||
break;
|
||||
case op_RDRAM:
|
||||
LOG((LOG_EMU,3," RDRAM addr:%#o\n", m_r[rsel_ac1]));
|
||||
break;
|
||||
case op_WRTRAM:
|
||||
LOG((LOG_EMU,3," WRTAM addr:%#o upper:%06o lower:%06o\n", m_r[rsel_ac1], m_r[rsel_ac0], m_r[rsel_ac3]));
|
||||
break;
|
||||
case op_JMPRAM:
|
||||
LOG((LOG_EMU,3," JMPRAM addr:%#o\n", m_r[rsel_ac1]));
|
||||
break;
|
||||
case op_XMLDA:
|
||||
LOG((LOG_EMU,3," XMLDA AC0 = [bank:%o AC1:#o]\n", m_bank_reg[m_task] & 3, m_r[rsel_ac1]));
|
||||
break;
|
||||
case op_XMSTA:
|
||||
LOG((LOG_EMU,3," XMSTA [bank:%o AC1:#o] = AC0 (%#o)\n", m_bank_reg[m_task] & 3, m_r[rsel_ac1], m_r[rsel_ac0]));
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
m_emu.ir = m_bus;
|
||||
m_emu.skip = 0;
|
||||
m_next2 |= r;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief branch on: arithmetic IR_SH, others PROM ctl2k_u3[IR[1-7]]
|
||||
*/
|
||||
void alto2_cpu_device::f2_late_idisp()
|
||||
{
|
||||
UINT16 r;
|
||||
|
||||
if (IR_ARITH(m_emu.ir)) {
|
||||
/* 1xxxxxxxxxxxxxxx */
|
||||
r = IR_SH(m_emu.ir) ^ 3; /* complement of SH */
|
||||
LOG((LOG_EMU,2," IDISP<-; branch on SH^3 (%#o|%#o)\n", m_next2, r));
|
||||
} else {
|
||||
int addr = CTL2K_U3(f2_emu_idisp) + X_RDBITS(m_emu.ir,16,1,7);
|
||||
/* 0???????xxxxxxxx */
|
||||
r = m_ctl2k_u3[addr];
|
||||
LOG((LOG_EMU,2," IDISP<-; IR (%#o) branch on PROM ctl2k_u3[%03o] (%#o|%#o)\n", m_emu.ir, addr, m_next2, r));
|
||||
}
|
||||
m_next2 |= r;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief source accu: modify RSELECT with SrcAC = (3 - IR[1-2])
|
||||
*/
|
||||
void alto2_cpu_device::f2_early_acsource()
|
||||
{
|
||||
X_WRBITS(m_rsel, 5, 3, 4, IR_SrcAC(m_emu.ir) ^ 3);
|
||||
LOG((LOG_EMU,2," <-ACSOURCE; rsel := SrcAC (%#o %s)\n", m_rsel, r_name(m_rsel)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief branch on: arithmetic IR_SH, others PROM ctl2k_u3[IR[1-7]]
|
||||
*/
|
||||
void alto2_cpu_device::f2_late_acsource()
|
||||
{
|
||||
UINT16 r;
|
||||
|
||||
if (IR_ARITH(m_emu.ir)) {
|
||||
/* 1xxxxxxxxxxxxxxx */
|
||||
r = IR_SH(m_emu.ir) ^ 3; /* complement of SH */
|
||||
LOG((LOG_EMU,2," <-ACSOURCE; branch on SH^3 (%#o|%#o)\n", m_next2, r));
|
||||
} else {
|
||||
int addr = CTL2K_U3(f2_emu_acsource) + X_RDBITS(m_emu.ir,16,1,7);
|
||||
/* 0???????xxxxxxxx */
|
||||
r = m_ctl2k_u3[addr];
|
||||
LOG((LOG_EMU,2," <-ACSOURCE; branch on PROM ctl2k_u3[%03o] (%#o|%#o)\n", addr, m_next2, r));
|
||||
}
|
||||
m_next2 |= r;
|
||||
}
|
||||
|
||||
void alto2_cpu_device::init_emu(int task)
|
||||
{
|
||||
memset(&m_emu, 0, sizeof(m_emu));
|
||||
save_item(NAME(m_emu.ir));
|
||||
save_item(NAME(m_emu.skip));
|
||||
save_item(NAME(m_emu.cy));
|
||||
|
||||
init_ram(task);
|
||||
|
||||
set_bs(task, bs_emu_read_sreg, &alto2_cpu_device::bs_early_read_sreg, 0);
|
||||
set_bs(task, bs_emu_load_sreg, &alto2_cpu_device::bs_early_load_sreg, &alto2_cpu_device::bs_late_load_sreg);
|
||||
set_bs(task, bs_disp, &alto2_cpu_device::bs_early_emu_disp, 0);
|
||||
|
||||
set_f1(task, f1_block, &alto2_cpu_device::f1_early_emu_block, 0); // catch the emulator task trying to block (wrong branch)
|
||||
set_f1(task, f1_emu_swmode, 0, &alto2_cpu_device::f1_late_swmode);
|
||||
set_f1(task, f1_emu_wrtram, 0, &alto2_cpu_device::f1_late_wrtram);
|
||||
set_f1(task, f1_emu_rdram, 0, &alto2_cpu_device::f1_late_rdram);
|
||||
set_f1(task, f1_emu_load_rmr, 0, &alto2_cpu_device::f1_late_emu_load_rmr);
|
||||
set_f1(task, f1_task_14, 0, 0); // F1 014 is undefined (?)
|
||||
set_f1(task, f1_emu_load_esrb, 0, &alto2_cpu_device::f1_late_emu_load_esrb);
|
||||
set_f1(task, f1_emu_rsnf, &alto2_cpu_device::f1_early_rsnf, 0);
|
||||
set_f1(task, f1_emu_startf, &alto2_cpu_device::f1_early_startf, 0);
|
||||
|
||||
set_f2(task, f2_emu_busodd, 0, &alto2_cpu_device::f2_late_busodd);
|
||||
set_f2(task, f2_emu_magic, 0, &alto2_cpu_device::f2_late_magic);
|
||||
set_f2(task, f2_emu_load_dns, &alto2_cpu_device::f2_early_load_dns, &alto2_cpu_device::f2_late_load_dns);
|
||||
set_f2(task, f2_emu_acdest, &alto2_cpu_device::f2_early_acdest, 0);
|
||||
set_f2(task, f2_emu_load_ir, 0, &alto2_cpu_device::f2_late_load_ir);
|
||||
set_f2(task, f2_emu_idisp, 0, &alto2_cpu_device::f2_late_idisp);
|
||||
set_f2(task, f2_emu_acsource, &alto2_cpu_device::f2_early_acsource, &alto2_cpu_device::f2_late_acsource);
|
||||
}
|
||||
|
||||
void alto2_cpu_device::exit_emu()
|
||||
{
|
||||
// nothing to do yet
|
||||
}
|
||||
|
||||
void alto2_cpu_device::reset_emu()
|
||||
{
|
||||
m_emu.ir = 0;
|
||||
m_emu.skip = 0;
|
||||
m_emu.cy = 0;
|
||||
}
|
71
src/emu/cpu/alto2/a2emu.h
Normal file
71
src/emu/cpu/alto2/a2emu.h
Normal file
@ -0,0 +1,71 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Xerox AltoII emulator task (EMU)
|
||||
*
|
||||
* Copyright Juergen Buchmueller <pullmoll@t-online.de>
|
||||
*
|
||||
* Licenses: MAME, GPLv2
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifdef ALTO2_DEFINE_CONSTANTS
|
||||
|
||||
#else // ALTO2_DEFINE_CONSTANTS
|
||||
#ifndef _A2EMU_H_
|
||||
#define _A2EMU_H_
|
||||
|
||||
//! BUS source for emulator task
|
||||
enum {
|
||||
bs_emu_read_sreg = bs_task_3, //!< bus source: read S register
|
||||
bs_emu_load_sreg = bs_task_4 //!< bus source: load S register from BUS
|
||||
};
|
||||
|
||||
//! F1 functions for emulator task
|
||||
enum {
|
||||
f1_emu_swmode = f1_task_10, //!< f1 (1000): switch mode; branch to ROM/RAM microcode
|
||||
f1_emu_wrtram = f1_task_11, //!< f1 (1001): write microcode RAM cycle
|
||||
f1_emu_rdram = f1_task_12, //!< f1 (1010): read microcode RAM cycle
|
||||
f1_emu_load_rmr = f1_task_13, //!< f1 (1011): load reset mode register
|
||||
//!< f1 (1100): undefined
|
||||
f1_emu_load_esrb = f1_task_15, //!< f1 (1101): load extended S register bank
|
||||
f1_emu_rsnf = f1_task_16, //!< f1 (1110): read serial number (Ethernet ID)
|
||||
f1_emu_startf = f1_task_17 //!< f1 (1111): start I/O hardware (Ethernet)
|
||||
};
|
||||
|
||||
//! F2 functions for emulator task
|
||||
enum {
|
||||
f2_emu_busodd = f2_task_10, //!< f2 (1000): branch on bus odd
|
||||
f2_emu_magic = f2_task_11, //!< f2 (1001): magic shifter (MRSH 1: shifter[15]=T[0], MLSH 1: shifter[015])
|
||||
f2_emu_load_dns = f2_task_12, //!< f2 (1010): do novel shift (RSH 1: shifter[15]=XC, LSH 1: shifer[0]=XC)
|
||||
f2_emu_acdest = f2_task_13, //!< f2 (1011): destination accu
|
||||
f2_emu_load_ir = f2_task_14, //!< f2 (1100): load instruction register and branch
|
||||
f2_emu_idisp = f2_task_15, //!< f2 (1101): load instruction displacement and branch
|
||||
f2_emu_acsource = f2_task_16 //!< f2 (1110): source accu
|
||||
//!< f2 (1111): undefined
|
||||
};
|
||||
|
||||
struct {
|
||||
UINT16 ir; //!< emulator instruction register
|
||||
UINT8 skip; //!< emulator skip
|
||||
UINT8 cy; //!< emulator carry
|
||||
} m_emu;
|
||||
void bs_early_emu_disp(); //!< bus source: drive bus by IR[8-15], possibly sign extended
|
||||
void f1_early_emu_block(); //!< F1 func: block task
|
||||
void f1_late_emu_load_rmr(); //!< F1 func: load the reset mode register
|
||||
void f1_late_emu_load_esrb(); //!< F1 func: load the extended S register bank from BUS[12-14]
|
||||
void f1_early_rsnf(); //!< F1 func: drive the bus from the Ethernet node ID
|
||||
void f1_early_startf(); //!< F1 func: defines commands for for I/O hardware, including Ethernet
|
||||
void f2_late_busodd(); //!< F2 func: branch on odd bus
|
||||
void f2_late_magic(); //!< F2 func: shift and use T
|
||||
void f2_early_load_dns(); //!< F2 func: modify RESELECT with DstAC = (3 - IR[3-4])
|
||||
void f2_late_load_dns(); //!< F2 func: do novel shifts
|
||||
void f2_early_acdest(); //!< F2 func: modify RSELECT with DstAC = (3 - IR[3-4])
|
||||
void bitblt_info(); //!< debug bitblt opcode
|
||||
void f2_late_load_ir(); //!< F2 func: load instruction register IR and branch on IR[0,5-7]
|
||||
void f2_late_idisp(); //!< F2 func: branch on: arithmetic IR_SH, others PROM ctl2k_u3[IR[1-7]]
|
||||
void f2_early_acsource(); //!< F2 func: modify RSELECT with SrcAC = (3 - IR[1-2])
|
||||
void f2_late_acsource(); //!< F2 func: branch on arithmetic IR_SH, others PROM ctl2k_u3[IR[1-7]]
|
||||
void init_emu(int task = task_emu); //!< initialize the emulator task
|
||||
void exit_emu(); //!< deinitialize the emulator task
|
||||
void reset_emu(); //!< reset the emulator task
|
||||
#endif // _A2EMU_H_
|
||||
#endif // ALTO2_DEFINE_CONSTANTS
|
1382
src/emu/cpu/alto2/a2ether.c
Normal file
1382
src/emu/cpu/alto2/a2ether.c
Normal file
File diff suppressed because it is too large
Load Diff
118
src/emu/cpu/alto2/a2ether.h
Normal file
118
src/emu/cpu/alto2/a2ether.h
Normal file
@ -0,0 +1,118 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Xerox AltoII ethernet task (ETHER)
|
||||
*
|
||||
* Copyright Juergen Buchmueller <pullmoll@t-online.de>
|
||||
*
|
||||
* Licenses: MAME, GPLv2
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifdef ALTO2_DEFINE_CONSTANTS
|
||||
|
||||
#define ALTO2_ETHER_FIFO_SIZE 16 //!< number of words in the ethernet FIFO
|
||||
#define ALTO2_ETHER_PACKET_SIZE 0400 //!< size of a packet in words
|
||||
|
||||
#else // ALTO2_DEFINE_CONSTANTS
|
||||
#ifndef _A2ETHER_H_
|
||||
#define _A2ETHER_H_
|
||||
//! BUS source for ethernet task
|
||||
enum {
|
||||
bs_ether_eidfct = bs_task_3 //!< ethernet task: Ethernet input data function
|
||||
};
|
||||
|
||||
//! F1 functions for ethernet task
|
||||
enum {
|
||||
f1_ether_eilfct = f1_task_13, //!< f1 (1011): ethernet input look function
|
||||
f1_ether_epfct = f1_task_14, //!< f1 (1100): ethernet post function
|
||||
f1_ether_ewfct = f1_task_15 //!< f1 (1101): ethernet countdown wakeup function
|
||||
};
|
||||
|
||||
//! F2 functions for ethernet task
|
||||
enum {
|
||||
f2_ether_eodfct = f2_task_10, //!< f2 (1000): ethernet output data function
|
||||
f2_ether_eosfct = f2_task_11, //!< f2 (1001): ethernet output start function
|
||||
f2_ether_erbfct = f2_task_12, //!< f2 (1010): ethernet reset branch function
|
||||
f2_ether_eefct = f2_task_13, //!< f2 (1011): ethernet end of transmission function
|
||||
f2_ether_ebfct = f2_task_14, //!< f2 (1100): ethernet branch function
|
||||
f2_ether_ecbfct = f2_task_15, //!< f2 (1101): ethernet countdown branch function
|
||||
f2_ether_eisfct = f2_task_16 //!< f2 (1110): ethernet input start function
|
||||
//!< f2 (1111): undefined
|
||||
};
|
||||
|
||||
UINT8* m_ether_a41; //!< BPROM; P3601-1; 256x4; enet.a41 "PE1"
|
||||
UINT8* m_ether_a42; //!< BPROM; P3601-1; 256x4; enet.a42 "PE2"
|
||||
UINT8* m_ether_a49; //!< BPROM; P3601-1; 265x4 enet.a49 "AFIFO"
|
||||
enum {
|
||||
ether_a49_BE = (1 << 0), //!< buffer empty
|
||||
ether_a49_BNE = (1 << 1), //!< buffer next empty
|
||||
ether_a49_BNNE = (1 << 2), //!< buffer next next empty
|
||||
ether_a49_BF = (1 << 3) //!< buffer full
|
||||
};
|
||||
|
||||
struct {
|
||||
UINT32 serin; //!< serial input shift registers 74164 #37 and #33
|
||||
UINT16 fifo[ALTO2_ETHER_FIFO_SIZE]; //!< FIFO buffer
|
||||
UINT16 fifo_rd; //!< FIFO input pointer
|
||||
UINT16 fifo_wr; //!< FIFO output pointer
|
||||
UINT16 status; //!< status word
|
||||
UINT16 rx_crc; //!< receiver CRC
|
||||
UINT16 tx_crc; //!< transmitter CRC
|
||||
UINT32 rx_count; //!< received words count
|
||||
UINT32 tx_count; //!< transmitted words count
|
||||
UINT16* rx_packet; //!< buffer to collect received words
|
||||
UINT16* tx_packet; //!< buffer to collect transmitted words
|
||||
emu_timer* rx_timer; //!< receiver timer
|
||||
emu_timer* tx_timer; //!< transmitter timer
|
||||
jkff_t ff_10a; //!< JK flip-flop 10a IBUSY (Sheet 13)
|
||||
jkff_t ff_10b; //!< JK flip-flop 10b OBUSY (Sheet 13)
|
||||
jkff_t ff_21a; //!< JK flip-flop 21a OUTON (Sheet 19)
|
||||
jkff_t ff_21b; //!< JK flip-flop 21b COLL (Sheet 19)
|
||||
jkff_t ff_31a; //!< JK flip-flop 31a OUTGONE (Sheet 19)
|
||||
jkff_t ff_31b; //!< JK flip-flop 31b OEOT (Sheet 19)
|
||||
jkff_t ff_35a; //!< JK flip-flop 35a OCMD (Sheet 7)
|
||||
jkff_t ff_35b; //!< JK flip-flop 35b ICMD (Sheet 7)
|
||||
jkff_t ff_47a; //!< JK flip-flop 47a ISR14 (Sheet 15)
|
||||
jkff_t ff_47b; //!< JK flip-flop 47b ISR15 (Sheet 15)
|
||||
jkff_t ff_51a; //!< JK flip-flop 51a EWFCT latch (Sheet 19)
|
||||
jkff_t ff_51b; //!< JK flip-flop 51b OCDW (Sheet 19)
|
||||
jkff_t ff_52b; //!< JK flip-flop 52b OSLOAD (Sheet 17)
|
||||
jkff_t ff_61a; //!< JK flip-flop 61a CRCGO (Sheet 21)
|
||||
jkff_t ff_61b; //!< JK flip-flop 61b OUTRGO (Sheet 21)
|
||||
jkff_t ff_62a; //!< JK flip-flop 62a OUTON (Sheet 21)
|
||||
jkff_t ff_62b; //!< JK flip-flop 62b OUTGO (Sheet 21)
|
||||
jkff_t ff_65a; //!< JK flip-flop 65a IDL (Sheet 10)
|
||||
jkff_t ff_65b; //!< JK flip-flop 65b IO (Sheet 10)
|
||||
jkff_t ff_69a; //!< JK flip-flop 69a IT (Sheet 14)
|
||||
jkff_t ff_69b; //!< JK flip-flop 69b INON (Sheet 14)
|
||||
jkff_t ff_70a; //!< JK flip-flop 70a IMID (Sheet 14)
|
||||
jkff_t ff_70b; //!< JK flip-flop 70b ILOC (Sheet 14)
|
||||
jkff_t ff_77a; //!< JK flip-flop 77a WR (Sheet 10)
|
||||
jkff_t ff_77b; //!< JK flip-flop 77b WLF (Sheet 10)
|
||||
int breath_of_life; //!< if non-zero, interval in seconds at which to broadcast the breath-of-life
|
||||
} m_eth;
|
||||
|
||||
TIMER_CALLBACK_MEMBER( rx_breath_of_life ); //!< HACK: pull the next word from the breath-of-life in the fifo
|
||||
TIMER_CALLBACK_MEMBER( tx_packet ); //!< transmit data from the FIFO to <nirvana for now>
|
||||
void eth_wakeup(); //!< check for the various reasons to wakeup the Ethernet task
|
||||
void eth_startf(); //!< start input or output depending on m_bus
|
||||
void bs_early_eidfct(); //!< bus source: Ethernet input data function
|
||||
void f1_early_eth_block(); //!< F1 func: block the Ether task
|
||||
void f1_early_eilfct(); //!< F1 func: Ethernet input look function
|
||||
void f1_early_epfct(); //!< F1 func: Ethernet post function
|
||||
void f1_late_ewfct(); //!< F1 func: Ethernet countdown wakeup function
|
||||
void f2_late_eodfct(); //!< F2 func: Ethernet output data function
|
||||
void f2_late_eosfct(); //!< F2 func: Ethernet output start function
|
||||
void f2_late_erbfct(); //!< F2 func: Ethernet reset branch function
|
||||
void f2_late_eefct(); //!< F2 func: Ethernet end of transmission function
|
||||
void f2_late_ebfct(); //!< F2 func: Ethernet branch function
|
||||
void f2_late_ecbfct(); //!< F2 func: Ethernet countdown branch function
|
||||
void f2_late_eisfct(); //!< F2 func: Ethernet input start function
|
||||
void activate_eth(); //!< called by the CPU when the Ethernet task becomes active
|
||||
void update_sysclk(int sysclk); //!< update all JK flip-flops for one cycle of SYSCLK
|
||||
void update_rclk(int rclk); //!< update all JK flip-flops for one cycle of RCLK
|
||||
void update_tclk(int tclk); //!< update all JK flip-flops for one cycle of TCLK
|
||||
void init_ether(int task = task_ether); //!< initialize the ethernet task
|
||||
void exit_ether(); //!< deinitialize the ethernet task
|
||||
void reset_ether(); //!< reset the ethernet task
|
||||
#endif // _A2ETHER_H_
|
||||
#endif // ALTO2_DEFINE_CONSTANTS
|
424
src/emu/cpu/alto2/a2hw.c
Normal file
424
src/emu/cpu/alto2/a2hw.c
Normal file
@ -0,0 +1,424 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Xerox AltoII memory mapped I/O hardware
|
||||
*
|
||||
* Copyright Juergen Buchmueller <pullmoll@t-online.de>
|
||||
*
|
||||
* Licenses: MAME, GPLv2
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include "alto2cpu.h"
|
||||
#include "a2roms.h"
|
||||
|
||||
/**
|
||||
* @brief read printer paper ready bit
|
||||
* Paper ready bit. 0 when the printer is ready for a paper scrolling operation.
|
||||
*/
|
||||
READ16_MEMBER ( alto2_cpu_device::pprdy_r ) { return X_RDBITS(m_hw.utilin,16,0,0); }
|
||||
|
||||
/**
|
||||
* @brief read printer check bit
|
||||
* Printer check bit bit.
|
||||
* Should the printer find itself in an abnormal state, it sets this bit to 0
|
||||
*/
|
||||
READ16_MEMBER ( alto2_cpu_device::pcheck_r ) { return X_RDBITS(m_hw.utilin,16,1,1); }
|
||||
|
||||
/**
|
||||
* @brief read unused bit 2
|
||||
*/
|
||||
READ16_MEMBER ( alto2_cpu_device::unused2_r ) { return X_RDBITS(m_hw.utilin,16,2,2); }
|
||||
|
||||
/**
|
||||
* @brief read printer daisy ready bit
|
||||
* Daisy ready bit. 0 when the printer is ready to print a character.
|
||||
*/
|
||||
READ16_MEMBER ( alto2_cpu_device::pchrdy_r ) { return X_RDBITS(m_hw.utilin,16,3,3); }
|
||||
|
||||
/**
|
||||
* @brief read printer carriage ready bit
|
||||
* Carriage ready bit. 0 when the printer is ready for horizontal positioning.
|
||||
*/
|
||||
READ16_MEMBER ( alto2_cpu_device::parrdy_r ) { return X_RDBITS(m_hw.utilin,16,4,4); }
|
||||
|
||||
/**
|
||||
* @brief read printer ready bit
|
||||
* Ready bit. Both this bit and the appropriate other ready bit (carriage,
|
||||
* daisy, etc.) must be 0 before attempting any output operation.
|
||||
*/
|
||||
READ16_MEMBER ( alto2_cpu_device::pready_r ) { return X_RDBITS(m_hw.utilin,16,5,5); }
|
||||
|
||||
/**
|
||||
* @brief memory configuration switch
|
||||
*/
|
||||
READ16_MEMBER ( alto2_cpu_device::memconfig_r ) { return X_RDBITS(m_hw.utilin,16,6,6); }
|
||||
|
||||
/**
|
||||
* @brief get unused bit 7
|
||||
*/
|
||||
READ16_MEMBER ( alto2_cpu_device::unused7_r ) { return X_RDBITS(m_hw.utilin,16,7,7); }
|
||||
|
||||
/**
|
||||
* @brief get key set key 0
|
||||
*/
|
||||
READ16_MEMBER ( alto2_cpu_device::keyset_key0_r ) { return X_RDBITS(m_hw.utilin,16,8,8); }
|
||||
|
||||
/**
|
||||
* @brief get key set key 1
|
||||
*/
|
||||
READ16_MEMBER ( alto2_cpu_device::keyset_key1_r ) { return X_RDBITS(m_hw.utilin,16,9,9); }
|
||||
|
||||
/**
|
||||
* @brief get key set key 2
|
||||
*/
|
||||
READ16_MEMBER ( alto2_cpu_device::keyset_key2_r ) { return X_RDBITS(m_hw.utilin,16,10,10); }
|
||||
|
||||
/**
|
||||
* @brief get key set key 3
|
||||
*/
|
||||
READ16_MEMBER ( alto2_cpu_device::keyset_key3_r ) { return X_RDBITS(m_hw.utilin,16,11,11); }
|
||||
|
||||
/**
|
||||
* @brief get key set key 4
|
||||
*/
|
||||
READ16_MEMBER ( alto2_cpu_device::keyset_key4_r ) { return X_RDBITS(m_hw.utilin,16,12,12); }
|
||||
|
||||
/**
|
||||
* @brief get mouse red button bit
|
||||
*/
|
||||
READ16_MEMBER ( alto2_cpu_device::mouse_red_r ) { return X_RDBITS(m_hw.utilin,16,13,13); }
|
||||
|
||||
/**
|
||||
* @brief get mouse blue button bit
|
||||
*/
|
||||
READ16_MEMBER ( alto2_cpu_device::mouse_blue_r ) { return X_RDBITS(m_hw.utilin,16,14,14); }
|
||||
|
||||
/**
|
||||
* @brief get mouse yellow button bit
|
||||
*/
|
||||
READ16_MEMBER ( alto2_cpu_device::mouse_yellow_r ) { return X_RDBITS(m_hw.utilin,16,15,15); }
|
||||
|
||||
/**
|
||||
* @brief write printer paper ready bit
|
||||
*/
|
||||
WRITE16_MEMBER( alto2_cpu_device::pprdy_w ) { X_WRBITS(m_hw.utilin,16,0,0,data); }
|
||||
|
||||
/**
|
||||
* @brief write printer check bit
|
||||
*/
|
||||
WRITE16_MEMBER( alto2_cpu_device::pcheck_w ) { X_WRBITS(m_hw.utilin,16,1,1,data); }
|
||||
|
||||
/**
|
||||
* @brief read unused bit 2
|
||||
*/
|
||||
WRITE16_MEMBER( alto2_cpu_device::unused2_w ) { X_WRBITS(m_hw.utilin,16,2,2,data); }
|
||||
|
||||
/**
|
||||
* @brief write printer daisy ready bit
|
||||
*/
|
||||
WRITE16_MEMBER( alto2_cpu_device::pchrdy_w ) { X_WRBITS(m_hw.utilin,16,3,3,data); }
|
||||
|
||||
/**
|
||||
* @brief write printer carriage ready bit
|
||||
*/
|
||||
WRITE16_MEMBER( alto2_cpu_device::parrdy_w ) { X_WRBITS(m_hw.utilin,16,4,4,data); }
|
||||
|
||||
/**
|
||||
* @brief write printer ready bit
|
||||
*/
|
||||
WRITE16_MEMBER( alto2_cpu_device::pready_w ) { X_WRBITS(m_hw.utilin,16,5,5,data); }
|
||||
|
||||
/**
|
||||
* @brief write memory configuration switch
|
||||
*/
|
||||
WRITE16_MEMBER( alto2_cpu_device::memconfig_w ) { X_WRBITS(m_hw.utilin,16,6,6,data); }
|
||||
|
||||
/**
|
||||
* @brief write unused bit 7
|
||||
*/
|
||||
WRITE16_MEMBER( alto2_cpu_device::unused7_w ) { X_WRBITS(m_hw.utilin,16,7,7,data); }
|
||||
|
||||
/**
|
||||
* @brief write key set key 0
|
||||
*/
|
||||
WRITE16_MEMBER( alto2_cpu_device::keyset_key0_w ) { X_WRBITS(m_hw.utilin,16,8,8,data); }
|
||||
|
||||
/**
|
||||
* @brief write key set key 1
|
||||
*/
|
||||
WRITE16_MEMBER( alto2_cpu_device::keyset_key1_w ) { X_WRBITS(m_hw.utilin,16,9,9,data); }
|
||||
|
||||
/**
|
||||
* @brief write key set key 2
|
||||
*/
|
||||
WRITE16_MEMBER( alto2_cpu_device::keyset_key2_w ) { X_WRBITS(m_hw.utilin,16,10,10,data); }
|
||||
|
||||
/**
|
||||
* @brief write key set key 3
|
||||
*/
|
||||
WRITE16_MEMBER( alto2_cpu_device::keyset_key3_w ) { X_WRBITS(m_hw.utilin,16,11,11,data); }
|
||||
|
||||
/**
|
||||
* @brief write key set key 4
|
||||
*/
|
||||
WRITE16_MEMBER( alto2_cpu_device::keyset_key4_w ) { X_WRBITS(m_hw.utilin,16,12,12,data); }
|
||||
|
||||
/**
|
||||
* @brief write mouse red button bit
|
||||
*/
|
||||
WRITE16_MEMBER( alto2_cpu_device::mouse_red_w ) { X_WRBITS(m_hw.utilin,16,13,13,data); }
|
||||
|
||||
/**
|
||||
* @brief write mouse blue button bit
|
||||
*/
|
||||
WRITE16_MEMBER( alto2_cpu_device::mouse_blue_w ) { X_WRBITS(m_hw.utilin,16,14,14,data); }
|
||||
|
||||
/**
|
||||
* @brief write mouse yellow button bit
|
||||
*/
|
||||
WRITE16_MEMBER( alto2_cpu_device::mouse_yellow_w ) { X_WRBITS(m_hw.utilin,16,15,15,data); }
|
||||
|
||||
/**
|
||||
* @brief write mouse buttons bits
|
||||
*/
|
||||
WRITE16_MEMBER( alto2_cpu_device::mouse_buttons_w ) { X_WRBITS(m_hw.utilin,16,13,15,data); }
|
||||
|
||||
/**
|
||||
* @brief printer paper strobe bit
|
||||
* Paper strobe bit. Toggling this bit causes a paper scrolling operation.
|
||||
*/
|
||||
static inline UINT16 GET_PPPSTR(UINT16 utilout) { return X_RDBITS(utilout,16,0,0); }
|
||||
|
||||
/**
|
||||
* @brief printer retstore bit
|
||||
* Restore bit. Toggling this bit resets the printer (including clearing
|
||||
* the "check" condition if present) and moves the carriage to the
|
||||
* left margin.
|
||||
*/
|
||||
static inline UINT16 GET_PREST(UINT16 utilout) { return X_RDBITS(utilout,16,1,1); }
|
||||
|
||||
/**
|
||||
* @brief printer ribbon bit
|
||||
* Ribbon bit. When this bit is 1 the ribbon is up (in printing
|
||||
* position); when 0, it is down.
|
||||
*/
|
||||
static inline UINT16 GET_PRIB(UINT16 utilout) { return X_RDBITS(utilout,16,2,2); }
|
||||
|
||||
/**
|
||||
* @brief printer daisy strobe bit
|
||||
* Daisy strobe bit. Toggling this bit causes a character to be printed.
|
||||
*/
|
||||
static inline UINT16 GET_PCHSTR(UINT16 utilout) { return X_RDBITS(utilout,16,3,3); }
|
||||
|
||||
/**
|
||||
* @brief printer carriage strobe bit
|
||||
* Carriage strobe bit. Toggling this bit causes a horizontal position operation.
|
||||
*/
|
||||
static inline UINT16 GET_PCARSTR(UINT16 utilout) { return X_RDBITS(utilout,16,4,4); }
|
||||
|
||||
/**
|
||||
* @brief printer data
|
||||
* Argument to various output operations:
|
||||
* 1. Printing characters. When the daisy bit is toggled bits 9-15 of this field
|
||||
* are interpreted as an ASCII character code to be printed (it should be noted
|
||||
* that all codes less than 040 print as lower case "w").
|
||||
* 2. For paper and carriage operations the field is interpreted as a displacement
|
||||
* (-1024 to +1023), in units of 1/48 inch for paper and 1/60 inch for carriage.
|
||||
* Positive is down or to the right, negative up or to the left. The value is
|
||||
* represented as sign-magnitude (i.e., bit 5 is 1 for negative numbers, 0 for
|
||||
* positive; bits 6-15 are the absolute value of the number).
|
||||
*/
|
||||
static inline UINT16 GET_PDATA(UINT16 utilout) { return X_RDBITS(utilout,16,5,15); }
|
||||
|
||||
/**
|
||||
* @brief read the UTILIN port
|
||||
*
|
||||
* @param addr memory mapped I/O address to be read
|
||||
* @return current value on the UTILIN port
|
||||
*/
|
||||
READ16_MEMBER( alto2_cpu_device::utilin_r )
|
||||
{
|
||||
UINT16 data;
|
||||
// FIXME: update the printer status
|
||||
// printer_read();
|
||||
|
||||
data = m_hw.utilin;
|
||||
|
||||
if (!space.debugger_access()) {
|
||||
LOG((LOG_HW,2," UTILIN rd %#o (%#o)\n", offset, data));
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief read the XBUS port
|
||||
*
|
||||
* @param addr memory mapped I/O address to be read
|
||||
* @return current value on the XBUS port latch
|
||||
*/
|
||||
READ16_MEMBER( alto2_cpu_device::xbus_r )
|
||||
{
|
||||
UINT16 data = m_hw.xbus[offset & 3];
|
||||
|
||||
if (!space.debugger_access()) {
|
||||
LOG((LOG_HW,2," XBUS[%d] rd %#o (%#o)\n", offset & 3, offset, data));
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief write the XBUS port
|
||||
*
|
||||
* The actual outputs are active-low.
|
||||
*
|
||||
* @param addr memory mapped I/O address to be read
|
||||
* @param data value to write to the XBUS port latch
|
||||
*/
|
||||
WRITE16_MEMBER( alto2_cpu_device::xbus_w )
|
||||
{
|
||||
if (!space.debugger_access()) {
|
||||
LOG((LOG_HW,2," XBUS[%d] wr %#o (%#o)\n", offset & 3, offset, data));
|
||||
}
|
||||
m_hw.xbus[offset&3] = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief read the UTILOUT port
|
||||
*
|
||||
* @param addr memory mapped I/O address to be read
|
||||
* @return current value on the UTILOUT port latch
|
||||
*/
|
||||
READ16_MEMBER( alto2_cpu_device::utilout_r )
|
||||
{
|
||||
UINT16 data = m_hw.utilout ^ 0177777;
|
||||
if (!space.debugger_access()) {
|
||||
LOG((0,2," UTILOUT rd %#o (%#o)\n", offset, data));
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief write the UTILOUT port
|
||||
*
|
||||
* The actual outputs are active-low.
|
||||
*
|
||||
* @param addr memory mapped I/O address to be read
|
||||
* @param data value to write to the UTILOUT port latch
|
||||
*/
|
||||
WRITE16_MEMBER( alto2_cpu_device::utilout_w )
|
||||
{
|
||||
if (!space.debugger_access()) {
|
||||
LOG((LOG_HW,2," UTILOUT wr %#o (%#o)\n", offset, data));
|
||||
}
|
||||
m_hw.utilout = data ^ 0177777;
|
||||
|
||||
// FIXME: write printer data
|
||||
// printer_write();
|
||||
}
|
||||
|
||||
/**
|
||||
* <PRE>
|
||||
* TODO: use madr.a65 and madr.a64 to determine the actual I/O address ranges
|
||||
*
|
||||
* madr.a65
|
||||
* address line connected to
|
||||
* -------------------------------
|
||||
* A0 MAR[11]
|
||||
* A1 KEYSEL
|
||||
* A2 MAR[7-10] == 0
|
||||
* A3 MAR[12]
|
||||
* A4 MAR[13]
|
||||
* A5 MAR[14]
|
||||
* A6 MAR[15]
|
||||
* A7 IOREF (MAR[0-6] == 1)
|
||||
*
|
||||
* output data connected to
|
||||
* -------------------------------
|
||||
* D0 IOSEL0
|
||||
* D1 IOSEL1
|
||||
* D2 IOSEL2
|
||||
* D3 INTIO
|
||||
*
|
||||
* madr.a64
|
||||
* address line connected to
|
||||
* -------------------------------
|
||||
* A0 STORE
|
||||
* A1 MAR[11]
|
||||
* A2 MAR[7-10] == 0
|
||||
* A3 MAR[12]
|
||||
* A4 MAR[13]
|
||||
* A5 MAR[14]
|
||||
* A6 MAR[15]
|
||||
* A7 IOREF (MAR[0-6] == 1)
|
||||
*
|
||||
* output data connected to
|
||||
* -------------------------------
|
||||
* D0 & MISYSCLK -> SELP
|
||||
* D1 ^ INTIO -> INTIOX
|
||||
* " ^ 1 -> NERRSEL
|
||||
* " & WRTCLK -> NRSTE
|
||||
* D2 XREG'
|
||||
* D3 & MISYSCLK -> LOADERC
|
||||
* </PRE>
|
||||
*/
|
||||
|
||||
static const prom_load_t pl_madr_a64 =
|
||||
{
|
||||
"madr.a64",
|
||||
0,
|
||||
"a66b0eda",
|
||||
"4d9088f592caa3299e90966b17765be74e523144",
|
||||
/* size */ 0400,
|
||||
/* amap */ AMAP_DEFAULT,
|
||||
/* axor */ 0,
|
||||
/* dxor */ 017, // invert D0-D3
|
||||
/* width */ 4,
|
||||
/* shift */ 0,
|
||||
/* dmap */ DMAP_DEFAULT,
|
||||
/* dand */ ZERO,
|
||||
/* type */ sizeof(UINT8)
|
||||
};
|
||||
|
||||
static const prom_load_t pl_madr_a65 =
|
||||
{
|
||||
"madr.a65",
|
||||
0,
|
||||
"ba37febd",
|
||||
"82e9db1cb65f451755295f0d179e6f8fe3349d4d",
|
||||
/* size */ 0400,
|
||||
/* amap */ AMAP_DEFAULT,
|
||||
/* axor */ 0,
|
||||
/* dxor */ 017, // invert D0-D3
|
||||
/* width */ 4,
|
||||
/* shift */ 0,
|
||||
/* dmap */ DMAP_DEFAULT,
|
||||
/* dand */ ZERO,
|
||||
/* type */ sizeof(UINT8)
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief clear all keys and install the mmio handler for KBDAD to KBDAD+3
|
||||
*/
|
||||
void alto2_cpu_device::init_hw()
|
||||
{
|
||||
memset(&m_hw, 0, sizeof(m_hw));
|
||||
m_madr_a64 = prom_load(machine(), &pl_madr_a64, memregion("madr_a64")->base());
|
||||
m_madr_a65 = prom_load(machine(), &pl_madr_a65, memregion("madr_a65")->base());
|
||||
}
|
||||
|
||||
void alto2_cpu_device::exit_hw()
|
||||
{
|
||||
// nothing to do yet
|
||||
}
|
||||
|
||||
void alto2_cpu_device::reset_hw()
|
||||
{
|
||||
m_hw.eia = 0;
|
||||
m_hw.utilout = 0;
|
||||
// open inputs on the XBUS (?)
|
||||
m_hw.xbus[0] = 0177777;
|
||||
m_hw.xbus[1] = 0177777;
|
||||
m_hw.xbus[2] = 0177777;
|
||||
m_hw.xbus[3] = 0177777;
|
||||
// open inputs on UTILIN
|
||||
m_hw.utilin = 0177777;
|
||||
}
|
68
src/emu/cpu/alto2/a2hw.h
Normal file
68
src/emu/cpu/alto2/a2hw.h
Normal file
@ -0,0 +1,68 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Xerox AltoII memory mapped i/o stuff (HW)
|
||||
*
|
||||
* Copyright Juergen Buchmueller <pullmoll@t-online.de>
|
||||
*
|
||||
* Licenses: MAME, GPLv2
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifdef ALTO2_DEFINE_CONSTANTS
|
||||
|
||||
#else // ALTO2_DEFINE_CONSTANTS
|
||||
#ifndef _A2HW_H_
|
||||
#define _A2HW_H_
|
||||
//! miscellaneous hardware registers in the memory mapped I/O range
|
||||
struct {
|
||||
UINT16 eia; //!< the EIA port at 0177001
|
||||
UINT16 utilout; //!< the UTILOUT port at 0177016 (active-low outputs)
|
||||
UINT16 xbus[4]; //!< the XBUS port at 0177020 to 0177023
|
||||
UINT16 utilin; //!< the UTILIN port at 0177030 to 0177033 (same value on all addresses)
|
||||
} m_hw;
|
||||
|
||||
DECLARE_READ16_MEMBER ( pprdy_r ); //!< read UTILIN[0] printer paper ready bit
|
||||
DECLARE_READ16_MEMBER ( pcheck_r ); //!< read UTILIN[1] printer check bit
|
||||
DECLARE_READ16_MEMBER ( unused2_r ); //!< read UTILIN[2] unused bit
|
||||
DECLARE_READ16_MEMBER ( pchrdy_r ); //!< read UTILIN[3] printer daisy ready bit
|
||||
DECLARE_READ16_MEMBER ( parrdy_r ); //!< read UTILIN[4] printer carriage ready bit
|
||||
DECLARE_READ16_MEMBER ( pready_r ); //!< read UTILIN[5] printer ready bit
|
||||
DECLARE_READ16_MEMBER ( memconfig_r ); //!< read UTILIN[6] memory config switch
|
||||
DECLARE_READ16_MEMBER ( unused7_r ); //!< read UTILIN[7] unused bit
|
||||
DECLARE_READ16_MEMBER ( keyset_key0_r ); //!< read UTILIN[8] keyset key #0
|
||||
DECLARE_READ16_MEMBER ( keyset_key1_r ); //!< read UTILIN[9] keyset key #1
|
||||
DECLARE_READ16_MEMBER ( keyset_key2_r ); //!< read UTILIN[10] keyset key #2
|
||||
DECLARE_READ16_MEMBER ( keyset_key3_r ); //!< read UTILIN[11] keyset key #3
|
||||
DECLARE_READ16_MEMBER ( keyset_key4_r ); //!< read UTILIN[12] keyset key #4
|
||||
DECLARE_READ16_MEMBER ( mouse_red_r ); //!< read UTILIN[13] mouse red button bit
|
||||
DECLARE_READ16_MEMBER ( mouse_blue_r ); //!< read UTILIN[14] mouse blue button bit
|
||||
DECLARE_READ16_MEMBER ( mouse_yellow_r ); //!< read UTILIN[15] mouse yellow button bit
|
||||
|
||||
DECLARE_WRITE16_MEMBER( pprdy_w ); //!< write UTILIN[0] printer paper ready bit
|
||||
DECLARE_WRITE16_MEMBER( pcheck_w ); //!< write UTILIN[1] printer check bit
|
||||
DECLARE_WRITE16_MEMBER( unused2_w ); //!< write UTILIN[2] unused bit
|
||||
DECLARE_WRITE16_MEMBER( pchrdy_w ); //!< write UTILIN[3] printer daisy ready bit
|
||||
DECLARE_WRITE16_MEMBER( parrdy_w ); //!< write UTILIN[4] carriage ready bit
|
||||
DECLARE_WRITE16_MEMBER( pready_w ); //!< write UTILIN[5] printer ready bit
|
||||
DECLARE_WRITE16_MEMBER( memconfig_w ); //!< write UTILIN[6] memory config switch
|
||||
DECLARE_WRITE16_MEMBER( unused7_w ); //!< write UTILIN[7] unused bit
|
||||
DECLARE_WRITE16_MEMBER( keyset_key0_w ); //!< write UTILIN[8] keyset key #0
|
||||
DECLARE_WRITE16_MEMBER( keyset_key1_w ); //!< write UTILIN[9] keyset key #1
|
||||
DECLARE_WRITE16_MEMBER( keyset_key2_w ); //!< write UTILIN[10] keyset key #2
|
||||
DECLARE_WRITE16_MEMBER( keyset_key3_w ); //!< write UTILIN[11] keyset key #3
|
||||
DECLARE_WRITE16_MEMBER( keyset_key4_w ); //!< write UTILIN[12] keyset key #4
|
||||
DECLARE_WRITE16_MEMBER( mouse_red_w ); //!< write UTILIN[13] mouse red button bit
|
||||
DECLARE_WRITE16_MEMBER( mouse_blue_w ); //!< write UTILIN[14] mouse blue button bit
|
||||
DECLARE_WRITE16_MEMBER( mouse_yellow_w ); //!< write UTILIN[15] mouse yellow button bit
|
||||
DECLARE_WRITE16_MEMBER( mouse_buttons_w ); //!< write UTILIN[13-15] mouse buttons bits
|
||||
|
||||
DECLARE_READ16_MEMBER ( utilin_r ); //!< read an UTILIN address
|
||||
DECLARE_READ16_MEMBER ( utilout_r ); //!< read the UTILOUT address
|
||||
DECLARE_WRITE16_MEMBER( utilout_w ); //!< write the UTILOUT address
|
||||
DECLARE_READ16_MEMBER ( xbus_r ); //!< read an XBUS address
|
||||
DECLARE_WRITE16_MEMBER( xbus_w ); //!< write an XBUS address (?)
|
||||
|
||||
void init_hw(); //!< initialize miscellaneous hardware
|
||||
void exit_hw(); //!< deinitialize miscellaneous hardware
|
||||
void reset_hw(); //!< reset miscellaneous hardware
|
||||
#endif // _A2HW_H_
|
||||
#endif // ALTO2_DEFINE_CONSTANTS
|
194
src/emu/cpu/alto2/a2jkff.h
Normal file
194
src/emu/cpu/alto2/a2jkff.h
Normal file
@ -0,0 +1,194 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Xerox AltoII Dual J/K flip-flop 74109 emulation
|
||||
*
|
||||
* Copyright Juergen Buchmueller <pullmoll@t-online.de>
|
||||
*
|
||||
* Licenses: MAME, GPLv2
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifdef ALTO2_DEFINE_CONSTANTS
|
||||
|
||||
#define JKFF_DEBUG 0 //!< define 1 to debug the transitions
|
||||
|
||||
/**
|
||||
* @brief enumeration of the inputs and outputs of a JK flip-flop type 74109
|
||||
* <PRE>
|
||||
* 74109
|
||||
* Dual J-/K flip-flops with set and reset.
|
||||
*
|
||||
* +----------+ +-----------------------------+
|
||||
* /1RST |1 +--+ 16| VCC | J |/K |CLK|/SET|/RST| Q |/Q |
|
||||
* 1J |2 15| /2RST |---+---+---+----+----+---+---|
|
||||
* /1K |3 14| 2J | X | X | X | 0 | 0 | 1 | 1 |
|
||||
* 1CLK |4 74 13| /2K | X | X | X | 0 | 1 | 1 | 0 |
|
||||
* /1SET |5 109 12| 2CLK | X | X | X | 1 | 0 | 0 | 1 |
|
||||
* 1Q |6 11| /2SET | 0 | 0 | / | 1 | 1 | 0 | 1 |
|
||||
* /1Q |7 10| 2Q | 0 | 1 | / | 1 | 1 | - | - |
|
||||
* GND |8 9| /2Q | 1 | 0 | / | 1 | 1 |/Q | Q |
|
||||
* +----------+ | 1 | 1 | / | 1 | 1 | 1 | 0 |
|
||||
* | X | X |!/ | 1 | 1 | - | - |
|
||||
* +-----------------------------+
|
||||
*
|
||||
* [This information is part of the GIICM]
|
||||
* </PRE>
|
||||
*/
|
||||
typedef enum {
|
||||
JKFF_0, //!< no inputs or outputs
|
||||
JKFF_CLK = (1 << 0), //!< clock signal
|
||||
JKFF_J = (1 << 1), //!< J input
|
||||
JKFF_K = (1 << 2), //!< K' input
|
||||
JKFF_S = (1 << 3), //!< S' input
|
||||
JKFF_C = (1 << 4), //!< C' input
|
||||
JKFF_Q = (1 << 5), //!< Q output
|
||||
JKFF_Q0 = (1 << 6) //!< Q' output
|
||||
} jkff_t;
|
||||
|
||||
#else // ALTO2_DEFINE_CONSTANTS
|
||||
|
||||
#ifndef _A2JKFF_H_
|
||||
#define _A2JKFF_H_
|
||||
|
||||
#if JKFF_DEBUG
|
||||
/**
|
||||
* @brief simulate a 74109 J-K flip-flop with set and reset inputs
|
||||
*
|
||||
* @param s0 is the previous state of the FF's in- and outputs
|
||||
* @param s1 is the next state
|
||||
* @return returns the next state and probably modified Q output
|
||||
*/
|
||||
static inline jkff_t update_jkff(UINT8 s0, UINT8 s1, const char* jkff_name)
|
||||
{
|
||||
switch (s1 & (JKFF_C | JKFF_S))
|
||||
{
|
||||
case JKFF_C | JKFF_S: /* C' is 1, and S' is 1 */
|
||||
if (((s0 ^ s1) & s1) & JKFF_CLK) {
|
||||
/* rising edge of the clock */
|
||||
switch (s1 & (JKFF_J | JKFF_K))
|
||||
{
|
||||
case 0:
|
||||
/* both J and K' are 0: set Q to 0, Q' to 1 */
|
||||
s1 = (s1 & ~JKFF_Q) | JKFF_Q0;
|
||||
if (s0 & JKFF_Q) {
|
||||
LOG((LOG_DISK,9,"\t\t%s J:0 K':0 -> Q:0\n", jkff_name));
|
||||
}
|
||||
break;
|
||||
case JKFF_J:
|
||||
/* J is 1, and K' is 0: toggle Q */
|
||||
if (s0 & JKFF_Q)
|
||||
s1 = (s1 & ~JKFF_Q) | JKFF_Q0;
|
||||
else
|
||||
s1 = (s1 | JKFF_Q) & ~JKFF_Q0;
|
||||
LOG((LOG_DISK,9,"\t\t%s J:0 K':1 flip-flop Q:%d\n", jkff_name, (s1 & JKFF_Q) ? 1 : 0));
|
||||
break;
|
||||
case JKFF_K:
|
||||
if ((s0 ^ s1) & JKFF_Q) {
|
||||
LOG((LOG_DISK,9,"\t\t%s J:0 K':1 keep Q:%d\n", jkff_name, (s1 & JKFF_Q) ? 1 : 0));
|
||||
}
|
||||
/* J is 0, and K' is 1: keep Q as is */
|
||||
if (s0 & JKFF_Q)
|
||||
s1 = (s1 | JKFF_Q) & ~JKFF_Q0;
|
||||
else
|
||||
s1 = (s1 & ~JKFF_Q) | JKFF_Q0;
|
||||
break;
|
||||
case JKFF_J | JKFF_K:
|
||||
/* both J and K' are 1: set Q to 1 */
|
||||
s1 = (s1 | JKFF_Q) & ~JKFF_Q0;
|
||||
if (!(s0 & JKFF_Q)) {
|
||||
LOG((LOG_DISK,9,"\t\t%s J:1 K':1 -> Q:1\n", jkff_name));
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* keep Q */
|
||||
s1 = (s1 & ~JKFF_Q) | (s0 & JKFF_Q);
|
||||
}
|
||||
break;
|
||||
case JKFF_S:
|
||||
/* S' is 1, C' is 0: set Q to 0, Q' to 1 */
|
||||
s1 = (s1 & ~JKFF_Q) | JKFF_Q0;
|
||||
if (s0 & JKFF_Q) {
|
||||
LOG((LOG_DISK,9,"\t\t%s C':0 -> Q:0\n", jkff_name));
|
||||
}
|
||||
break;
|
||||
case JKFF_C:
|
||||
/* S' is 0, C' is 1: set Q to 1, Q' to 0 */
|
||||
s1 = (s1 | JKFF_Q) & ~JKFF_Q0;
|
||||
if (!(s0 & JKFF_Q)) {
|
||||
LOG((LOG_DISK,9,"\t\t%s S':0 -> Q:1\n", jkff_name));
|
||||
}
|
||||
break;
|
||||
case 0:
|
||||
default:
|
||||
/* unstable state (what to do?) */
|
||||
s1 = s1 | JKFF_Q | JKFF_Q0;
|
||||
LOG((LOG_DISK,9,"\t\t%s C':0 S':0 -> Q:1 and Q':1 <unstable>\n", jkff_name));
|
||||
break;
|
||||
}
|
||||
return static_cast<jkff_t>(s1);
|
||||
}
|
||||
#else // JKFF_DEBUG
|
||||
/**
|
||||
* @brief simulate a 74109 J-K flip-flop with set and reset inputs
|
||||
*
|
||||
* @param s0 is the previous state of the FF's in- and outputs
|
||||
* @param s1 is the next state
|
||||
* @return returns the next state and probably modified Q output
|
||||
*/
|
||||
static inline jkff_t update_jkff(UINT8 s0, UINT8 s1, const char*)
|
||||
{
|
||||
switch (s1 & (JKFF_C | JKFF_S))
|
||||
{
|
||||
case JKFF_C | JKFF_S: /* C' is 1, and S' is 1 */
|
||||
if (((s0 ^ s1) & s1) & JKFF_CLK) {
|
||||
/* rising edge of the clock */
|
||||
switch (s1 & (JKFF_J | JKFF_K))
|
||||
{
|
||||
case 0:
|
||||
/* both J and K' are 0: set Q to 0, Q' to 1 */
|
||||
s1 = (s1 & ~JKFF_Q) | JKFF_Q0;
|
||||
break;
|
||||
case JKFF_J:
|
||||
/* J is 1, and K' is 0: toggle Q */
|
||||
if (s0 & JKFF_Q)
|
||||
s1 = (s1 & ~JKFF_Q) | JKFF_Q0;
|
||||
else
|
||||
s1 = (s1 | JKFF_Q) & ~JKFF_Q0;
|
||||
break;
|
||||
case JKFF_K:
|
||||
/* J is 0, and K' is 1: keep Q as is */
|
||||
if (s0 & JKFF_Q)
|
||||
s1 = (s1 | JKFF_Q) & ~JKFF_Q0;
|
||||
else
|
||||
s1 = (s1 & ~JKFF_Q) | JKFF_Q0;
|
||||
break;
|
||||
case JKFF_J | JKFF_K:
|
||||
/* both J and K' are 1: set Q to 1 */
|
||||
s1 = (s1 | JKFF_Q) & ~JKFF_Q0;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* keep Q */
|
||||
s1 = (s1 & ~JKFF_Q) | (s0 & JKFF_Q);
|
||||
}
|
||||
break;
|
||||
case JKFF_S:
|
||||
/* S' is 1, C' is 0: set Q to 0, Q' to 1 */
|
||||
s1 = (s1 & ~JKFF_Q) | JKFF_Q0;
|
||||
break;
|
||||
case JKFF_C:
|
||||
/* S' is 0, C' is 1: set Q to 1, Q' to 0 */
|
||||
s1 = (s1 | JKFF_Q) & ~JKFF_Q0;
|
||||
break;
|
||||
case 0:
|
||||
default:
|
||||
/* unstable state (what to do?) */
|
||||
s1 = s1 | JKFF_Q | JKFF_Q0;
|
||||
break;
|
||||
}
|
||||
return static_cast<jkff_t>(s1);
|
||||
}
|
||||
#endif // JKFF_DEBUG
|
||||
|
||||
#endif // _A2JKFF_H_
|
||||
#endif // ALTO2_DEFINE_CONSTANTS
|
65
src/emu/cpu/alto2/a2kbd.c
Normal file
65
src/emu/cpu/alto2/a2kbd.c
Normal file
@ -0,0 +1,65 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Xerox AltoII memory mapped I/O keyboard
|
||||
*
|
||||
* Copyright Juergen Buchmueller <pullmoll@t-online.de>
|
||||
*
|
||||
* Licenses: MAME, GPLv2
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include "alto2cpu.h"
|
||||
|
||||
/**
|
||||
* @brief read the keyboard address matrix
|
||||
*
|
||||
* @param addr memory mapped I/O address to be read
|
||||
* @return keyboard matrix value for address modulo 4
|
||||
*/
|
||||
READ16_MEMBER( alto2_cpu_device::kbd_ad_r )
|
||||
{
|
||||
UINT16 data = 0177777;
|
||||
switch (offset & 3) {
|
||||
case 0:
|
||||
data = machine().root_device().ioport("ROW0")->read();
|
||||
break;
|
||||
case 1:
|
||||
data = machine().root_device().ioport("ROW1")->read();
|
||||
break;
|
||||
case 2:
|
||||
data = machine().root_device().ioport("ROW2")->read();
|
||||
break;
|
||||
case 3:
|
||||
data = machine().root_device().ioport("ROW3")->read();
|
||||
break;
|
||||
}
|
||||
m_kbd.matrix[offset & 03] = data;
|
||||
if (!space.debugger_access()) {
|
||||
LOG((LOG_KBD,2," read KBDAD+%o (%#o)\n", offset & 3, data));
|
||||
}
|
||||
if (0 == (offset & 3) && (m_kbd.bootkey != 0177777)) {
|
||||
if (!space.debugger_access()) {
|
||||
LOG((0,2," boot keys (%#o & %#o)\n", data, m_kbd.bootkey));
|
||||
}
|
||||
data &= m_kbd.bootkey;
|
||||
m_kbd.bootkey = 0177777;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
void alto2_cpu_device::init_kbd(UINT16 bootkey)
|
||||
{
|
||||
m_kbd.bootkey = bootkey;
|
||||
}
|
||||
|
||||
void alto2_cpu_device::exit_kbd()
|
||||
{
|
||||
// nothing to do yet
|
||||
}
|
||||
|
||||
void alto2_cpu_device::reset_kbd()
|
||||
{
|
||||
m_kbd.matrix[0] = 0177777;
|
||||
m_kbd.matrix[1] = 0177777;
|
||||
m_kbd.matrix[2] = 0177777;
|
||||
m_kbd.matrix[3] = 0177777;
|
||||
}
|
111
src/emu/cpu/alto2/a2kbd.h
Normal file
111
src/emu/cpu/alto2/a2kbd.h
Normal file
@ -0,0 +1,111 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Xerox AltoII keyboard hardware (KBD)
|
||||
*
|
||||
* Copyright Juergen Buchmueller <pullmoll@t-online.de>
|
||||
*
|
||||
* Licenses: MAME, GPLv2
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifdef ALTO2_DEFINE_CONSTANTS
|
||||
|
||||
//! make an Xerox AltoII key bit mask
|
||||
#define MAKE_KEY(a,b) (1 << (b))
|
||||
|
||||
#define A2_KEY_5 MAKE_KEY(0,017) //!< normal: 5 shifted: %
|
||||
#define A2_KEY_4 MAKE_KEY(0,016) //!< normal: 4 shifted: $
|
||||
#define A2_KEY_6 MAKE_KEY(0,015) //!< normal: 6 shifted: ~
|
||||
#define A2_KEY_E MAKE_KEY(0,014) //!< normal: e shifted: E
|
||||
#define A2_KEY_7 MAKE_KEY(0,013) //!< normal: 7 shifted: &
|
||||
#define A2_KEY_D MAKE_KEY(0,012) //!< normal: d shifted: D
|
||||
#define A2_KEY_U MAKE_KEY(0,011) //!< normal: u shifted: U
|
||||
#define A2_KEY_V MAKE_KEY(0,010) //!< normal: v shifted: V
|
||||
#define A2_KEY_0 MAKE_KEY(0,007) //!< normal: 0 shifted: )
|
||||
#define A2_KEY_K MAKE_KEY(0,006) //!< normal: k shifted: K
|
||||
#define A2_KEY_MINUS MAKE_KEY(0,005) //!< normal: - shifted: _
|
||||
#define A2_KEY_P MAKE_KEY(0,004) //!< normal: p shifted: P
|
||||
#define A2_KEY_SLASH MAKE_KEY(0,003) //!< normal: / shifted: ?
|
||||
#define A2_KEY_BACKSLASH MAKE_KEY(0,002) //!< normal: \ shifted: |
|
||||
#define A2_KEY_LF MAKE_KEY(0,001) //!< normal: LF
|
||||
#define A2_KEY_BS MAKE_KEY(0,000) //!< normal: BS
|
||||
|
||||
#define A2_KEY_3 MAKE_KEY(1,017) //!< normal: 3 shifted: #
|
||||
#define A2_KEY_2 MAKE_KEY(1,016) //!< normal: 2 shifted: @
|
||||
#define A2_KEY_W MAKE_KEY(1,015) //!< normal: w shifted: W
|
||||
#define A2_KEY_Q MAKE_KEY(1,014) //!< normal: q shifted: Q
|
||||
#define A2_KEY_S MAKE_KEY(1,013) //!< normal: s shifted: S
|
||||
#define A2_KEY_A MAKE_KEY(1,012) //!< normal: a shifted: A
|
||||
#define A2_KEY_9 MAKE_KEY(1,011) //!< normal: 9 shifted: (
|
||||
#define A2_KEY_I MAKE_KEY(1,010) //!< normal: i shifted: I
|
||||
#define A2_KEY_X MAKE_KEY(1,007) //!< normal: x shifted: X
|
||||
#define A2_KEY_O MAKE_KEY(1,006) //!< normal: o shifted: O
|
||||
#define A2_KEY_L MAKE_KEY(1,005) //!< normal: l shifted: L
|
||||
#define A2_KEY_COMMA MAKE_KEY(1,004) //!< normal: , shifted: <
|
||||
#define A2_KEY_QUOTE MAKE_KEY(1,003) //!< normal: ' shifted: "
|
||||
#define A2_KEY_RBRACKET MAKE_KEY(1,002) //!< normal: ] shifted: }
|
||||
#define A2_KEY_BLANK_MID MAKE_KEY(1,001) //!< middle blank key
|
||||
#define A2_KEY_BLANK_TOP MAKE_KEY(1,000) //!< top blank key
|
||||
|
||||
#define A2_KEY_1 MAKE_KEY(2,017) //!< normal: 1 shifted: !
|
||||
#define A2_KEY_ESCAPE MAKE_KEY(2,016) //!< normal: ESC shifted: ?
|
||||
#define A2_KEY_TAB MAKE_KEY(2,015) //!< normal: TAB shifted: ?
|
||||
#define A2_KEY_F MAKE_KEY(2,014) //!< normal: f shifted: F
|
||||
#define A2_KEY_CTRL MAKE_KEY(2,013) //!< CTRL
|
||||
#define A2_KEY_C MAKE_KEY(2,012) //!< normal: c shifted: C
|
||||
#define A2_KEY_J MAKE_KEY(2,011) //!< normal: j shifted: J
|
||||
#define A2_KEY_B MAKE_KEY(2,010) //!< normal: b shifted: B
|
||||
#define A2_KEY_Z MAKE_KEY(2,007) //!< normal: z shifted: Z
|
||||
#define A2_KEY_LSHIFT MAKE_KEY(2,006) //!< LSHIFT
|
||||
#define A2_KEY_PERIOD MAKE_KEY(2,005) //!< normal: . shifted: >
|
||||
#define A2_KEY_SEMICOLON MAKE_KEY(2,004) //!< normal: ; shifted: :
|
||||
#define A2_KEY_RETURN MAKE_KEY(2,003) //!< RETURN
|
||||
#define A2_KEY_LEFTARROW MAKE_KEY(2,002) //!< normal: <- shifted: ^ (caret?)
|
||||
#define A2_KEY_DEL MAKE_KEY(2,001) //!< normal: DEL
|
||||
#define A2_KEY_MSW_2_17 MAKE_KEY(2,000) //!< unused on Microswitch KDB
|
||||
|
||||
#define A2_KEY_R MAKE_KEY(3,017) //!< normal: r shifted: R
|
||||
#define A2_KEY_T MAKE_KEY(3,016) //!< normal: t shifted: T
|
||||
#define A2_KEY_G MAKE_KEY(3,015) //!< normal: g shifted: G
|
||||
#define A2_KEY_Y MAKE_KEY(3,014) //!< normal: y shifted: Y
|
||||
#define A2_KEY_H MAKE_KEY(3,013) //!< normal: h shifted: H
|
||||
#define A2_KEY_8 MAKE_KEY(3,012) //!< normal: 8 shifted: *
|
||||
#define A2_KEY_N MAKE_KEY(3,011) //!< normal: n shifted: N
|
||||
#define A2_KEY_M MAKE_KEY(3,010) //!< normal: m shifted: M
|
||||
#define A2_KEY_LOCK MAKE_KEY(3,007) //!< LOCK
|
||||
#define A2_KEY_SPACE MAKE_KEY(3,006) //!< SPACE
|
||||
#define A2_KEY_LBRACKET MAKE_KEY(3,005) //!< normal: [ shifted: {
|
||||
#define A2_KEY_EQUALS MAKE_KEY(3,004) //!< normal: = shifted: +
|
||||
#define A2_KEY_RSHIFT MAKE_KEY(3,003) //!< RSHIFT
|
||||
#define A2_KEY_BLANK_BOT MAKE_KEY(3,002) //!< bottom blank key
|
||||
#define A2_KEY_MSW_3_16 MAKE_KEY(3,001) //!< unused on Microswitch KDB
|
||||
#define A2_KEY_MSW_3_17 MAKE_KEY(3,000) //!< unused on Microswitch KDB
|
||||
|
||||
#define A2_KEY_FR2 MAKE_KEY(0,002) //!< ADL right function key 2
|
||||
#define A2_KEY_FL2 MAKE_KEY(0,001) //!< ADL left function key 1
|
||||
|
||||
#define A2_KEY_FR4 MAKE_KEY(1,001) //!< ADL right funtion key 4
|
||||
#define A2_KEY_BW MAKE_KEY(1,000) //!< ADL BW (?)
|
||||
|
||||
#define A2_KEY_FR3 MAKE_KEY(2,002) //!< ADL right function key 3
|
||||
#define A2_KEY_FL1 MAKE_KEY(2,001) //!< ADL left function key 1
|
||||
#define A2_KEY_FL3 MAKE_KEY(2,000) //!< ADL left function key 3
|
||||
|
||||
#define A2_KEY_FR1 MAKE_KEY(3,002) //!< ADL right function key 4
|
||||
#define A2_KEY_FL4 MAKE_KEY(3,001) //!< ADL left function key 4
|
||||
#define A2_KEY_FR5 MAKE_KEY(3,000) //!< ADL right function key 5
|
||||
|
||||
#else // ALTO2_DEFINE_CONSTANTS
|
||||
#ifndef _A2KBD_H_
|
||||
#define _A2KBD_H_
|
||||
struct {
|
||||
UINT16 bootkey; //!< boot key - key code pressed before power on
|
||||
UINT16 matrix[4]; //!< a bit map of the keys pressed (ioports ROW0 ... ROW3)
|
||||
} m_kbd;
|
||||
|
||||
DECLARE_READ16_MEMBER( kbd_ad_r ); //!< read the keyboard matrix
|
||||
|
||||
void init_kbd(UINT16 bootkey = 0177777); //!< initialize the keyboard hardware, optinally set the boot key
|
||||
void exit_kbd(); //!< deinitialize the keyboard hardware
|
||||
void reset_kbd(); //!< reset the keyboard hardware
|
||||
#endif // _A2KBD_H_
|
||||
#endif // ALTO2_DEFINE_CONSTANTS
|
56
src/emu/cpu/alto2/a2ksec.c
Normal file
56
src/emu/cpu/alto2/a2ksec.c
Normal file
@ -0,0 +1,56 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Xerox AltoII disk sector task
|
||||
*
|
||||
* Copyright Juergen Buchmueller <pullmoll@t-online.de>
|
||||
*
|
||||
* Licenses: MAME, GPLv2
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include "alto2cpu.h"
|
||||
|
||||
//! f1_ksec_block early: block the disk sector task
|
||||
void alto2_cpu_device::f1_early_ksec_block()
|
||||
{
|
||||
LOG((LOG_KSEC,2," BLOCK %s\n", task_name(m_task)));
|
||||
disk_block(m_task);
|
||||
}
|
||||
|
||||
//! disk sector task slot initialization
|
||||
void alto2_cpu_device::init_ksec(int task)
|
||||
{
|
||||
set_bs(task, bs_ksec_read_kstat, &alto2_cpu_device::bs_early_read_kstat, 0);
|
||||
set_bs(task, bs_ksec_read_kdata, &alto2_cpu_device::bs_early_read_kdata, 0);
|
||||
|
||||
set_f1(task, f1_block, &alto2_cpu_device::f1_early_ksec_block, 0);
|
||||
|
||||
set_f1(task, f1_task_10, 0, 0);
|
||||
set_f1(task, f1_ksec_strobe, 0, &alto2_cpu_device::f1_late_strobe);
|
||||
set_f1(task, f1_ksec_load_kstat, 0, &alto2_cpu_device::f1_late_load_kstat);
|
||||
set_f1(task, f1_ksec_increcno, 0, &alto2_cpu_device::f1_late_increcno);
|
||||
set_f1(task, f1_ksec_clrstat, 0, &alto2_cpu_device::f1_late_clrstat);
|
||||
set_f1(task, f1_ksec_load_kcom, 0, &alto2_cpu_device::f1_late_load_kcom);
|
||||
set_f1(task, f1_ksec_load_kadr, 0, &alto2_cpu_device::f1_late_load_kadr);
|
||||
set_f1(task, f1_ksec_load_kdata, 0, &alto2_cpu_device::f1_late_load_kdata);
|
||||
|
||||
set_f2(task, f2_ksec_init, 0, &alto2_cpu_device::f2_late_init);
|
||||
set_f2(task, f2_ksec_rwc, 0, &alto2_cpu_device::f2_late_rwc);
|
||||
set_f2(task, f2_ksec_recno, 0, &alto2_cpu_device::f2_late_recno);
|
||||
set_f2(task, f2_ksec_xfrdat, 0, &alto2_cpu_device::f2_late_xfrdat);
|
||||
set_f2(task, f2_ksec_swrnrdy, 0, &alto2_cpu_device::f2_late_swrnrdy);
|
||||
set_f2(task, f2_ksec_nfer, 0, &alto2_cpu_device::f2_late_nfer);
|
||||
set_f2(task, f2_ksec_strobon, 0, &alto2_cpu_device::f2_late_strobon);
|
||||
set_f2(task, f2_task_17, 0, 0);
|
||||
|
||||
m_task_wakeup |= 1 << task;
|
||||
}
|
||||
|
||||
void alto2_cpu_device::exit_ksec()
|
||||
{
|
||||
// nothing to do yet
|
||||
}
|
||||
|
||||
void alto2_cpu_device::reset_ksec()
|
||||
{
|
||||
// nothing to do yet
|
||||
}
|
50
src/emu/cpu/alto2/a2ksec.h
Normal file
50
src/emu/cpu/alto2/a2ksec.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Xerox AltoII disk sector task (KSEC)
|
||||
*
|
||||
* Copyright Juergen Buchmueller <pullmoll@t-online.de>
|
||||
*
|
||||
* Licenses: MAME, GPLv2
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifdef ALTO2_DEFINE_CONSTANTS
|
||||
|
||||
#else // ALTO2_DEFINE_CONSTANTS
|
||||
#ifndef _A2KSEC_H_
|
||||
#define _A2KSEC_H_
|
||||
//! BUS source for disk sector task
|
||||
enum {
|
||||
bs_ksec_read_kstat = bs_task_3, //!< bus source: read disk status register
|
||||
bs_ksec_read_kdata = bs_task_4 //!< bus source: read disk data register
|
||||
};
|
||||
|
||||
//! F1 functions for disk sector task
|
||||
enum {
|
||||
//!< f1 10: undefined
|
||||
f1_ksec_strobe = f1_task_11, //!< f1 11: strobe
|
||||
f1_ksec_load_kstat = f1_task_12, //!< f1 12: load kstat register
|
||||
f1_ksec_increcno = f1_task_13, //!< f1 13: increment record number
|
||||
f1_ksec_clrstat = f1_task_14, //!< f1 14: clear status register
|
||||
f1_ksec_load_kcom = f1_task_15, //!< f1 15: load kcom register
|
||||
f1_ksec_load_kadr = f1_task_16, //!< f1 16: load kadr register
|
||||
f1_ksec_load_kdata = f1_task_17 //!< f1 17: load kdata register
|
||||
};
|
||||
|
||||
//! F2 functions for disk sector task
|
||||
enum {
|
||||
f2_ksec_init = f2_task_10, //!< f2 10: branches NEXT[5-9] on WDTASKACT && WDINIT
|
||||
f2_ksec_rwc = f2_task_11, //!< f2 11: branches NEXT[8-9] on READ/WRITE/CHECK for record
|
||||
f2_ksec_recno = f2_task_12, //!< f2 12: branches NEXT[8-9] on RECNO[0-1]
|
||||
f2_ksec_xfrdat = f2_task_13, //!< f2 13: branches NEXT[9] on !SEEKONLY
|
||||
f2_ksec_swrnrdy = f2_task_14, //!< f2 14: branches NEXT[9] on !SWRDY
|
||||
f2_ksec_nfer = f2_task_15, //!< f2 15: branches NEXT[9] on !KFER
|
||||
f2_ksec_strobon = f2_task_16, //!< f2 16: branches NEXT[9] on STROBE
|
||||
//!< f2 17: undefined
|
||||
};
|
||||
|
||||
void f1_early_ksec_block(void); //!< block ksec task
|
||||
void init_ksec(int task = task_ksec); //!< initialize the disk sector task
|
||||
void exit_ksec(); //!< deinitialize the disk sector task
|
||||
void reset_ksec(); //!< reset the disk sector task
|
||||
#endif // _A2KSEC_H_
|
||||
#endif // ALTO2_DEFINE_CONSTANTS
|
54
src/emu/cpu/alto2/a2kwd.c
Normal file
54
src/emu/cpu/alto2/a2kwd.c
Normal file
@ -0,0 +1,54 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Xerox AltoII disk word task
|
||||
*
|
||||
* Copyright Juergen Buchmueller <pullmoll@t-online.de>
|
||||
*
|
||||
* Licenses: MAME, GPLv2
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include "alto2cpu.h"
|
||||
|
||||
//! f1_kwd_block early: block the disk word task
|
||||
void alto2_cpu_device::f1_early_kwd_block()
|
||||
{
|
||||
LOG((LOG_KWD,2," BLOCK %s\n", task_name(m_task)));
|
||||
disk_block(m_task);
|
||||
}
|
||||
|
||||
//! disk word task slot initialization
|
||||
void alto2_cpu_device::init_kwd(int task)
|
||||
{
|
||||
set_bs(task, bs_kwd_read_kstat, &alto2_cpu_device::bs_early_read_kstat, 0);
|
||||
set_bs(task, bs_kwd_read_kdata, &alto2_cpu_device::bs_early_read_kdata, 0);
|
||||
|
||||
set_f1(task, f1_block, &alto2_cpu_device::f1_early_kwd_block, 0);
|
||||
|
||||
set_f1(task, f1_task_10, 0, 0);
|
||||
set_f1(task, f1_kwd_strobe, 0, &alto2_cpu_device::f1_late_strobe);
|
||||
set_f1(task, f1_kwd_load_kstat, 0, &alto2_cpu_device::f1_late_load_kstat);
|
||||
set_f1(task, f1_kwd_increcno, 0, &alto2_cpu_device::f1_late_increcno);
|
||||
set_f1(task, f1_kwd_clrstat, 0, &alto2_cpu_device::f1_late_clrstat);
|
||||
set_f1(task, f1_kwd_load_kcom, 0, &alto2_cpu_device::f1_late_load_kcom);
|
||||
set_f1(task, f1_kwd_load_kadr, 0, &alto2_cpu_device::f1_late_load_kadr);
|
||||
set_f1(task, f1_kwd_load_kdata, 0, &alto2_cpu_device::f1_late_load_kdata);
|
||||
|
||||
set_f2(task, f2_kwd_init, 0, &alto2_cpu_device::f2_late_init);
|
||||
set_f2(task, f2_kwd_rwc, 0, &alto2_cpu_device::f2_late_rwc);
|
||||
set_f2(task, f2_kwd_recno, 0, &alto2_cpu_device::f2_late_recno);
|
||||
set_f2(task, f2_kwd_xfrdat, 0, &alto2_cpu_device::f2_late_xfrdat);
|
||||
set_f2(task, f2_kwd_swrnrdy, 0, &alto2_cpu_device::f2_late_swrnrdy);
|
||||
set_f2(task, f2_kwd_nfer, 0, &alto2_cpu_device::f2_late_nfer);
|
||||
set_f2(task, f2_kwd_strobon, 0, &alto2_cpu_device::f2_late_strobon);
|
||||
set_f2(task, f2_task_17, 0, 0);
|
||||
}
|
||||
|
||||
void alto2_cpu_device::exit_kwd()
|
||||
{
|
||||
// nothing to do yet
|
||||
}
|
||||
|
||||
void alto2_cpu_device::reset_kwd()
|
||||
{
|
||||
// nothing to do yet
|
||||
}
|
51
src/emu/cpu/alto2/a2kwd.h
Normal file
51
src/emu/cpu/alto2/a2kwd.h
Normal file
@ -0,0 +1,51 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Xerox AltoII disk word task (KWD)
|
||||
*
|
||||
* Copyright Juergen Buchmueller <pullmoll@t-online.de>
|
||||
*
|
||||
* Licenses: MAME, GPLv2
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifdef ALTO2_DEFINE_CONSTANTS
|
||||
|
||||
#else // ALTO2_DEFINE_CONSTANTS
|
||||
#ifndef _A2KWD_H_
|
||||
#define _A2KWD_H_
|
||||
|
||||
//! BUS source for disk word task
|
||||
enum {
|
||||
bs_kwd_read_kstat = bs_task_3, //!< bus source: read disk status register
|
||||
bs_kwd_read_kdata = bs_task_4 //!< bus source: read disk data register
|
||||
};
|
||||
|
||||
//! F1 functions for disk word task
|
||||
enum {
|
||||
//!< f1 10: undefined
|
||||
f1_kwd_strobe = f1_task_11, //!< f1 11: strobe
|
||||
f1_kwd_load_kstat = f1_task_12, //!< f1 12: load kstat register
|
||||
f1_kwd_increcno = f1_task_13, //!< f1 13: increment record number
|
||||
f1_kwd_clrstat = f1_task_14, //!< f1 14: clear status register
|
||||
f1_kwd_load_kcom = f1_task_15, //!< f1 15: load kcom register
|
||||
f1_kwd_load_kadr = f1_task_16, //!< f1 16: load kadr register
|
||||
f1_kwd_load_kdata = f1_task_17, //!< f1 17: load kdata register
|
||||
};
|
||||
|
||||
//! F2 functions for disk word task
|
||||
enum {
|
||||
f2_kwd_init = f2_task_10, //!< f2 10: branches NEXT[5-9] on WDTASKACT && WDINIT
|
||||
f2_kwd_rwc = f2_task_11, //!< f2 11: branches NEXT[8-9] on READ/WRITE/CHECK for record
|
||||
f2_kwd_recno = f2_task_12, //!< f2 12: branches NEXT[8-9] on RECNO[0-1]
|
||||
f2_kwd_xfrdat = f2_task_13, //!< f2 13: branches NEXT[9] on !SEEKONLY
|
||||
f2_kwd_swrnrdy = f2_task_14, //!< f2 14: branches NEXT[9] on !SWRDY
|
||||
f2_kwd_nfer = f2_task_15, //!< f2 15: branches NEXT[9] on !KFER
|
||||
f2_kwd_strobon = f2_task_16, //!< f2 16: branches NEXT[9] on STROBE
|
||||
//!< f2 17: undefined
|
||||
};
|
||||
|
||||
void f1_early_kwd_block(); //!< F1 func: disable the disk word task
|
||||
void init_kwd(int task = task_kwd); //!< initialize the disk word task
|
||||
void exit_kwd(); //!< deinitialize the disk word task
|
||||
void reset_kwd(); //!< reset the disk word task
|
||||
#endif // _A2KWD_H_
|
||||
#endif // ALTO2_DEFINE_CONSTANTS
|
879
src/emu/cpu/alto2/a2mem.c
Normal file
879
src/emu/cpu/alto2/a2mem.c
Normal file
@ -0,0 +1,879 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Xerox AltoII memory interface
|
||||
*
|
||||
* Copyright Juergen Buchmueller <pullmoll@t-online.de>
|
||||
*
|
||||
* Licenses: MAME, GPLv2
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include "alto2cpu.h"
|
||||
|
||||
#define PUT_EVEN(dword,word) X_WRBITS(dword,32, 0,15,word)
|
||||
#define GET_EVEN(dword) X_RDBITS(dword,32, 0,15)
|
||||
#define PUT_ODD(dword,word) X_WRBITS(dword,32,16,31,word)
|
||||
#define GET_ODD(dword) X_RDBITS(dword,32,16,31)
|
||||
|
||||
#define GET_MESR_HAMMING(mesr) X_RDBITS(mesr,16,0,5)
|
||||
#define PUT_MESR_HAMMING(mesr,val) X_WRBITS(mesr,16,0,5,val)
|
||||
#define GET_MESR_PERR(mesr) X_RDBITS(mesr,16,6,6)
|
||||
#define PUT_MESR_PERR(mesr,val) X_WRBITS(mesr,16,6,6,val)
|
||||
#define GET_MESR_PARITY(mesr) X_RDBITS(mesr,16,7,7)
|
||||
#define PUT_MESR_PARITY(mesr,val) X_WRBITS(mesr,16,7,7,val)
|
||||
#define GET_MESR_SYNDROME(mesr) X_RDBITS(mesr,16,8,13)
|
||||
#define PUT_MESR_SYNDROME(mesr,val) X_WRBITS(mesr,16,8,13,val)
|
||||
#define GET_MESR_BANK(mesr) X_RDBITS(mesr,16,14,15)
|
||||
#define PUT_MESR_BANK(mesr,val) X_WRBITS(mesr,16,14,15,val)
|
||||
|
||||
#define GET_MECR_SPARE1(mecr,val) X_RDBITS(mecr,16,0,3)
|
||||
#define PUT_MECR_SPARE1(mecr,val) X_WRBITS(mecr,16,0,3,val)
|
||||
#define GET_MECR_TEST_CODE(mecr) X_RDBITS(mecr,16,4,10)
|
||||
#define PUT_MECR_TEST_CODE(mecr,val) X_WRBITS(mecr,16,4,10,val)
|
||||
#define GET_MECR_TEST_MODE(mecr) X_RDBITS(mecr,16,11,11)
|
||||
#define PUT_MECR_TEST_MODE(mecr,val) X_WRBITS(mecr,16,11,11,val)
|
||||
#define GET_MECR_INT_SBERR(mecr) X_RDBITS(mecr,16,12,12)
|
||||
#define PUT_MECR_INT_SBERR(mecr,val) X_WRBITS(mecr,16,12,12,val)
|
||||
#define GET_MECR_INT_DBERR(mecr) X_RDBITS(mecr,16,13,13)
|
||||
#define PUT_MECR_INT_DBERR(mecr,val) X_WRBITS(mecr,16,13,13,val)
|
||||
#define GET_MECR_ERRCORR(mecr) X_RDBITS(mecr,16,14,14)
|
||||
#define PUT_MECR_ERRCORR(mecr,val) X_WRBITS(mecr,16,14,14,val)
|
||||
#define GET_MECR_SPARE2(mecr) X_RDBITS(mecr,16,15,15)
|
||||
#define PUT_MECR_SPARE2(mecr,val) X_WRBITS(mecr,16,15,15,val)
|
||||
|
||||
/**
|
||||
* <PRE>
|
||||
* AltoII Memory
|
||||
*
|
||||
* Address mapping
|
||||
*
|
||||
* The mapping of addresses to memory chips can be altered by the setting of
|
||||
* the "memory configuration switch". This switch is located at the top of the
|
||||
* backplane of the AltoII. If the switch is in the alternate position, the
|
||||
* first and second 32K portions of memory are exchanged.
|
||||
*
|
||||
* The AltoII memory system is organized around 32-bit doublewords. Stored
|
||||
* along with each doubleword is 6 bits of Hamming code and a Parity bit for
|
||||
* a total of 39 bits:
|
||||
*
|
||||
* bits 0-15 even data word
|
||||
* bits 16-31 odd data word
|
||||
* bits 32-37 Hamming code
|
||||
* bit 38 Parity bit
|
||||
*
|
||||
* Things are further complicated by the fact that two types of memory chips
|
||||
* are used: 16K chips in machines with extended memory and 4K chips for all
|
||||
* others.
|
||||
*
|
||||
* The bits in a 1-word deep slice of memory are called a group. A group
|
||||
* contains 4K oder 16K doublewords, depending on the chip type. The bits of
|
||||
* a group on a single board are called a subgroup. Thus a subgroup contains
|
||||
* 10 of the 40 bits in a group. There are 8 subgroups on a memory board.
|
||||
* Subgroups are numbered from the high 3 bits of the address; for 4K chips
|
||||
* this means MAR[0-2]; for 16K chips (i.e., an Alto with extended memory)
|
||||
* this means BANK,MAR[0]:
|
||||
*
|
||||
* Subgroup Chip Positions
|
||||
* 7 81-90
|
||||
* 6 71-80
|
||||
* 5 61-70
|
||||
* 4 51-60
|
||||
* 3 41-50
|
||||
* 2 31-40
|
||||
* 1 21-30
|
||||
* 0 11-20
|
||||
*
|
||||
* The location of the bits in group 0 is:
|
||||
*
|
||||
* CARD 1 CARD2 CARD3 CARD4
|
||||
* 32 24 16 08 00 33 25 17 09 01 34 26 18 10 02 35 27 19 11 03
|
||||
* 36 28 20 12 04 37 29 21 13 05 38 30 22 14 06 xx 31 23 25 07
|
||||
*
|
||||
* Chips 15, 25, 35, 45, 65, 75 and 85 on board 4 aren't used. If you are out
|
||||
* of replacement memory chips, you can use one of these, but then the board
|
||||
* with the missing chips will only work in Slot 4.
|
||||
*
|
||||
* o WORD = 16 BITS
|
||||
* o ACCESS -> 2 WORDS AT A TIME
|
||||
* o -> 32 BITS + 6 BITS EC + PARITY + SPARE = 40 BITS
|
||||
* o 10 BITS/MODULE 80 DRAMS/MODULE
|
||||
* o 4 MODULES/ALTO 320 DRAMS/ALTO
|
||||
*
|
||||
* ADDRESS A0-6, WE, CAS'
|
||||
* | TO ALL DEVICES
|
||||
* v
|
||||
* +-----------------------------------------+
|
||||
* | ^ 8 DEVICES (32K OR 128K FOR XM) |
|
||||
* | | | CARD 1
|
||||
* /| v <------------ DATA OUT ----------> |
|
||||
* / | 0 1 2 3 4 5 6 7 8 9 |
|
||||
* / +-----------------------------------------+
|
||||
* | H4 H0 28 24 20 16 12 8 4 0
|
||||
* |
|
||||
* | +-----------------------------------------+
|
||||
* | /| | CARD 2
|
||||
* | / +-----------------------------------------+
|
||||
* RAS H5 H1 29 25 21 17 13 9 5 1
|
||||
* 0-7
|
||||
* | \ +-----------------------------------------+
|
||||
* | \| | CARD 3
|
||||
* | +-----------------------------------------+
|
||||
* | P H2 30 26 22 18 14 10 6 2
|
||||
* \
|
||||
* \ +-----------------------------------------+
|
||||
* \| | CARD 4
|
||||
* +-----------------------------------------+
|
||||
* X H3 31 27 23 19 15 11 7 3
|
||||
*
|
||||
* [ ODD WORD ] [ EVEN WORD ]
|
||||
*
|
||||
* <HR>
|
||||
*
|
||||
* 32K x 10 STORAGE MODULE
|
||||
*
|
||||
* Table I
|
||||
*
|
||||
* +-------+-------+-------+---------------+-------+
|
||||
* |CIRCUIT| INPUT | SIGNAL| INVERTER | |
|
||||
* | NO. | PINS | NAME | DEF?? ??? |RESIST.|
|
||||
* +-------+-------+-------+---------------+-------+
|
||||
* | | 71 | RAS0 | A1 1 -> 2 | ?? R2 |
|
||||
* | 1 +-------+-------+---------------+-------+
|
||||
* | | 110 | CS0 | A1 3 -> 4 | ?? R3 |
|
||||
* +-------+-------+-------+---------------+-------+
|
||||
* | | 79 | RAS1 | A2 1 -> 2 | ?? R4 |
|
||||
* | 2 +-------+-------+---------------+-------+
|
||||
* | | 110 | CS1 | A2 3 -> 4 | ?? R5 |
|
||||
* +-------+-------+-------+---------------+-------+
|
||||
* | | 90 | RAS2 | A3 1 -> 2 | ?? R7 |
|
||||
* | 3 +-------+-------+---------------+-------+
|
||||
* | | 110 | CS2 | A3 3 -> 4 | ?? R8 |
|
||||
* +-------+-------+-------+---------------+-------+
|
||||
* | | 86 | RAS3 | A3 11 -> 10 | ?? R9 |
|
||||
* | 4 +-------+-------+---------------+-------+
|
||||
* | | 110 | CS3 | A4 11 -> 10 | ?? R7 |
|
||||
* +-------+-------+-------+---------------+-------+
|
||||
* | | 102 | RAS4 | A4 1 -> 2 | ?? R4 |
|
||||
* | 5 +-------+-------+---------------+-------+
|
||||
* | | 110 | CS4 | A3 13 -> 12 | ?? R5 |
|
||||
* +-------+-------+-------+---------------+-------+
|
||||
* | | 106 | RAS5 | A5 11 -> 10 | ?? R3 |
|
||||
* | 6 +-------+-------+---------------+-------+
|
||||
* | | 110 | CS5 | A5 3 -> 4 | ?? R2 |
|
||||
* +-------+-------+-------+---------------+-------+
|
||||
* | | 111 | RAS6 | A5 1 -> 2 | ?? R8 |
|
||||
* | 7 +-------+-------+---------------+-------+
|
||||
* | | 110 | CS6 | A5 13 -> 12 | ?? R9 |
|
||||
* +-------+-------+-------+---------------+-------+
|
||||
* | | 99 | RAS7 | A4 13 -> 12 | ?? R5 |
|
||||
* | 8 +-------+-------+---------------+-------+
|
||||
* | | 110 | CS7 | A4 3 -> 4 | ?? R5 |
|
||||
* +-------+-------+-------+---------------+-------+
|
||||
*
|
||||
* Table II
|
||||
*
|
||||
* MEMORY CHIP REFERENCE DESIGNATOR
|
||||
*
|
||||
* CIRCUIT NO.
|
||||
* ROW NO. 1 2 3 4 5 6 7 8
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
* | 1 | 15 20 | 25 30 | 35 40 | 45 50 | 55 60 | 65 70 | 75 80 | 85 90 |
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
* | 2 | 14 19 | 24 29 | 34 39 | 44 49 | 54 59 | 64 69 | 64 79 | 84 89 |
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
* | 3 | 13 18 | 23 28 | 33 38 | 43 48 | 53 58 | 63 68 | 73 78 | 83 88 |
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
* | 4 | 12 17 | 22 27 | 32 37 | 42 47 | 52 57 | 62 67 | 72 77 | 82 87 |
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
* | 5 | 11 16 | 21 26 | 31 36 | 41 46 | 52 56 | 61 66 | 71 76 | 81 86 |
|
||||
* +-------+-------+-------+-------+-------+-------+-------+-------+-------+
|
||||
*
|
||||
*
|
||||
* The Hamming code generator:
|
||||
*
|
||||
* WDxx is write data bit xx.
|
||||
* H(x) is Hammming code bit x.
|
||||
* HC(x) is generated Hamming code bit x.
|
||||
* HC(x/y) is an intermediate value.
|
||||
* HC(x)A and HC(x)B are also intermediate values.
|
||||
*
|
||||
* Chips used are:
|
||||
* 74S280 9-bit parity generator (A-I inputs, even and odd outputs)
|
||||
* 74S135 EX-OR/EX-NOR gates (5 inputs, 2 outputs)
|
||||
* 74S86 EX-OR gates (2 inputs, 1 output)
|
||||
*
|
||||
* chip A B C D E F G H I even odd
|
||||
* ---------------------------------------------------------------------------------
|
||||
* a75: WD01 WD04 WD08 WD11 WD15 WD19 WD23 WD26 WD30 --- HC(0)A
|
||||
* a76: WD00 WD03 WD06 WD10 WD13 WD17 WD21 WD25 WD28 HC(0B1) ---
|
||||
* a86: WD02 WD05 WD09 WD12 WD16 WD20 WD24 WD27 WD31 HC(1)A ---
|
||||
* a64: WD01 WD02 WD03 WD07 WD08 WD09 WD10 WD14 WD15 --- HC(2)A
|
||||
* a85: WD16 WD17 WD22 WD23 WD24 WD25 WD29 WD30 WD31 HC(2)B ---
|
||||
*
|
||||
* H(0) ^ HC(0)A ^ HC(0B1) -> HC(0)
|
||||
* H(1) ^ HC(1)A ^ HC(0B1) -> HC(1)
|
||||
* HC(2)A ^ HC(2)B ^ H(2) -> HC(2)
|
||||
* H(0) ^ H(1) ^ H(2) -> H(0/2)
|
||||
*
|
||||
* chip A B C D E F G H I even odd
|
||||
* ---------------------------------------------------------------------------------
|
||||
* a66: WD04 WD05 WD06 WD07 WD08 WD09 WD10 H(3) 0 --- HC(3)A
|
||||
* a84: WD18 WD19 WD20 WD21 WD22 WD23 WD24 WD25 0 HC(3/4) HCPA
|
||||
* a63: WD11 WD12 WD13 WD14 WD15 WD16 WD17 H(4) 0 --- HC(4)A
|
||||
* a87: WD26 WD27 WD28 WD29 WD30 WD31 H(5) 0 0 HC(5) HCPB
|
||||
*
|
||||
* HC(3)A ^ HC(3/4) -> HC(3)
|
||||
* HC(4)A ^ HC(3/4) -> HC(4)
|
||||
*
|
||||
* WD00 ^ WD01 -> XX01
|
||||
*
|
||||
* chip A B C D E F G H I even odd
|
||||
* ---------------------------------------------------------------------------------
|
||||
* a54: HC(3)A HC(4)A HCPA HCPB H(0/2) XX01 WD02 WD03 RP PERR ---
|
||||
* a65: WD00 WD01 WD02 WD04 WD05 WD07 WD10 WD11 WD12 --- PCA
|
||||
* a74: WD14 WD17 WD18 WD21 WD23 WD24 WD26 WD27 WD29 PCB ---
|
||||
*
|
||||
* PCA ^ PCB -> PC
|
||||
*
|
||||
* Whoa ;-)
|
||||
* </PRE>
|
||||
*/
|
||||
#if USE_HAMMING_CHECK
|
||||
|
||||
#define WD(x) (1ul<<(31-x))
|
||||
|
||||
/* a75: WD01 WD04 WD08 WD11 WD15 WD19 WD23 WD26 WD30 --- HC(0)A */
|
||||
#define A75 (WD( 1)|WD( 4)|WD( 8)|WD(11)|WD(15)|WD(19)|WD(23)|WD(26)|WD(30))
|
||||
|
||||
/* a76: WD00 WD03 WD06 WD10 WD13 WD17 WD21 WD25 WD29 HC(0B1) --- */
|
||||
#define A76 (WD( 0)|WD( 3)|WD( 6)|WD(10)|WD(13)|WD(17)|WD(21)|WD(25)|WD(28))
|
||||
|
||||
/* a86: WD02 WD05 WD09 WD12 WD16 WD20 WD24 WD27 WD31 HC(1)A --- */
|
||||
#define A86 (WD( 2)|WD( 5)|WD( 9)|WD(12)|WD(16)|WD(20)|WD(24)|WD(27)|WD(31))
|
||||
|
||||
/* a64: WD01 WD02 WD03 WD07 WD08 WD09 WD10 WD14 WD15 --- HC(2)A */
|
||||
#define A64 (WD( 1)|WD( 2)|WD( 3)|WD( 7)|WD( 8)|WD( 9)|WD(10)|WD(14)|WD(15))
|
||||
|
||||
/* a85: WD16 WD17 WD22 WD23 WD24 WD25 WD29 WD30 WD31 HC(2)B --- */
|
||||
#define A85 (WD(16)|WD(17)|WD(22)|WD(23)|WD(24)|WD(25)|WD(29)|WD(30)|WD(31))
|
||||
|
||||
/* a66: WD04 WD05 WD06 WD07 WD08 WD09 WD10 H(3) 0 --- HC(3)A */
|
||||
#define A66 (WD( 4)|WD( 5)|WD( 6)|WD( 7)|WD( 8)|WD( 9)|WD(10))
|
||||
|
||||
/* a84: WD18 WD19 WD20 WD21 WD22 WD23 WD24 WD25 0 HC(3/4) HCPA */
|
||||
#define A84 (WD(18)|WD(19)|WD(20)|WD(21)|WD(22)|WD(23)|WD(24)|WD(25))
|
||||
|
||||
/* a63: WD11 WD12 WD13 WD14 WD15 WD16 WD17 H(4) 0 --- HC(4)A */
|
||||
#define A63 (WD(11)|WD(12)|WD(13)|WD(14)|WD(15)|WD(16)|WD(17))
|
||||
|
||||
/* a87: WD26 WD27 WD28 WD29 WD30 WD31 H(5) 0 0 HC(5) HCPB */
|
||||
#define A87 (WD(26)|WD(27)|WD(28)|WD(29)|WD(30)|WD(31))
|
||||
|
||||
/* a54: HC(3)A HC(4)A HCPA HCPB H(0/2) XX01 WD02 WD03 P PERR --- */
|
||||
#define A54 (WD( 2)|WD( 3))
|
||||
|
||||
/* a65: WD00 WD01 WD02 WD04 WD05 WD07 WD10 WD11 WD12 --- PCA */
|
||||
#define A65 (WD( 0)|WD( 1)|WD( 2)|WD( 4)|WD( 5)|WD( 7)|WD(10)|WD(11)|WD(12))
|
||||
|
||||
/* a74: WD14 WD17 WD18 WD21 WD23 WD24 WD26 WD27 WD29 PCB --- */
|
||||
#define A74 (WD(14)|WD(17)|WD(18)|WD(21)|WD(23)|WD(24)|WD(26)|WD(27)|WD(29))
|
||||
|
||||
#define H0(hpb) X_BIT(hpb,8,0) //!< get Hamming code bit 0 from hpb data (really bit 32)
|
||||
#define H1(hpb) X_BIT(hpb,8,1) //!< get Hamming code bit 1 from hpb data (really bit 33)
|
||||
#define H2(hpb) X_BIT(hpb,8,2) //!< get Hamming code bit 2 from hpb data (really bit 34)
|
||||
#define H3(hpb) X_BIT(hpb,8,3) //!< get Hamming code bit 3 from hpb data (really bit 35)
|
||||
#define H4(hpb) X_BIT(hpb,8,4) //!< get Hamming code bit 4 from hpb data (really bit 36)
|
||||
#define H5(hpb) X_BIT(hpb,8,5) //!< get Hamming code bit 5 from hpb data (really bit 37)
|
||||
#define RH(hpb) X_RDBITS(hpb,8,0,5) //!< get Hamming code from hpb data (bits 32 to 37)
|
||||
#define RP(hpb) X_BIT(hpb,8,6) //!< get parity bit from hpb data (really bit 38)
|
||||
|
||||
/** @brief return even parity of a (masked) 32 bit value */
|
||||
static __inline UINT8 parity_even(UINT32 val)
|
||||
{
|
||||
val -= ((val >> 1) & 0x55555555);
|
||||
val = (((val >> 2) & 0x33333333) + (val & 0x33333333));
|
||||
val = (((val >> 4) + val) & 0x0f0f0f0f);
|
||||
val += (val >> 8);
|
||||
val += (val >> 16);
|
||||
return (val & 1);
|
||||
}
|
||||
|
||||
/** @brief return odd parity of a (masked) 32 bit value */
|
||||
#define parity_odd(val) (parity_even(val)^1)
|
||||
|
||||
/**
|
||||
* @brief lookup table to convert a Hamming syndrome into a bit number to correct
|
||||
*/
|
||||
static const int hamming_lut[64] = {
|
||||
-1, -1, -1, 0, -1, 1, 2, 3, /* A69: HR(5):0 HR(4):0 HR(3):0 */
|
||||
-1, 4, 5, 6, 7, 8, 9, 10, /* A79: HR(5):0 HR(4):0 HR(3):1 */
|
||||
-1, 11, 12, 13, 14, 15, 16, 17, /* A67: HR(5):0 HR(4):1 HR(3):0 */
|
||||
-1, -1, -1, -1, -1, 1, -1, -1, /* non chip selected */
|
||||
-1, 26, 27, 28, 29, 30, 31, -1, /* A68: HR(5):1 HR(4):0 HR(3):0 */
|
||||
-1, -1, -1, -1, -1, 1, -1, -1, /* non chip selected */
|
||||
18, 19, 20, 21, 22, 23, 24, 25, /* A78: HR(5):1 HR(4):1 HR(3):0 */
|
||||
-1, -1, -1, -1, -1, 1, -1, -1 /* non chip selected */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief read or write a memory double-word and caluclate its Hamming code
|
||||
*
|
||||
* Hamming code generation according to the schematics described above.
|
||||
* It's certainly overkill to do this on a modern PC, but I think we'll
|
||||
* need it for perfect emulation anyways (Hamming code hardware checking).
|
||||
*
|
||||
* @param write non-zero if this is a memory write (don't check for error)
|
||||
* @param dw_addr the double-word address
|
||||
* @param dw_data the double-word data to write
|
||||
* @return dw_data
|
||||
*/
|
||||
UINT32 alto2_cpu_device::hamming_code(int write, UINT32 dw_addr, UINT32 dw_data)
|
||||
{
|
||||
register UINT8 hpb = write ? 0 : m_mem.hpb[dw_addr];
|
||||
register UINT8 hc_0_a;
|
||||
register UINT8 hc_0b1;
|
||||
register UINT8 hc_1_a;
|
||||
register UINT8 hc_2_a;
|
||||
register UINT8 hc_2_b;
|
||||
register UINT8 hc_0;
|
||||
register UINT8 hc_1;
|
||||
register UINT8 hc_2;
|
||||
register UINT8 h_0_2;
|
||||
register UINT8 hc_3_a;
|
||||
register UINT8 hc_3_4;
|
||||
register UINT8 hcpa;
|
||||
register UINT8 hc_4_a;
|
||||
register UINT8 hc_3;
|
||||
register UINT8 hc_4;
|
||||
register UINT8 hc_5;
|
||||
register UINT8 hcpb;
|
||||
register UINT8 perr;
|
||||
register UINT8 pca;
|
||||
register UINT8 pcb;
|
||||
register UINT8 pc;
|
||||
register int syndrome;
|
||||
|
||||
/* a75: WD01 WD04 WD08 WD11 WD15 WD19 WD23 WD26 WD30 --- HC(0)A */
|
||||
hc_0_a = parity_odd (dw_data & A75);
|
||||
/* a76: WD00 WD03 WD06 WD10 WD13 WD17 WD21 WD25 WD29 HC(0B1) --- */
|
||||
hc_0b1 = parity_even(dw_data & A76);
|
||||
/* a86: WD02 WD05 WD09 WD12 WD16 WD20 WD24 WD27 WD31 HC(1)A --- */
|
||||
hc_1_a = parity_even(dw_data & A86);
|
||||
/* a64: WD01 WD02 WD03 WD07 WD08 WD09 WD10 WD14 WD15 --- HC(2)A */
|
||||
hc_2_a = parity_odd (dw_data & A64);
|
||||
/* a85: WD16 WD17 WD22 WD23 WD24 WD25 WD29 WD30 WD31 HC(2)B --- */
|
||||
hc_2_b = parity_even(dw_data & A85);
|
||||
|
||||
hc_0 = H0(hpb) ^ hc_0_a ^ hc_0b1;
|
||||
hc_1 = H1(hpb) ^ hc_1_a ^ hc_0b1;
|
||||
hc_2 = hc_2_a ^ hc_2_b ^ H2(hpb);
|
||||
h_0_2 = H0(hpb) ^ H1(hpb) ^ H2(hpb);
|
||||
|
||||
/* a66: WD04 WD05 WD06 WD07 WD08 WD09 WD10 H(3) 0 --- HC(3)A */
|
||||
hc_3_a = parity_odd ((dw_data & A66) ^ H3(hpb));
|
||||
/* a84: WD18 WD19 WD20 WD21 WD22 WD23 WD24 WD25 0 HC(3/4) HCPA */
|
||||
hcpa = parity_odd (dw_data & A84);
|
||||
hc_3_4 = hcpa ^ 1;
|
||||
/* a63: WD11 WD12 WD13 WD14 WD15 WD16 WD17 H(4) 0 --- HC(4)A */
|
||||
hc_4_a = parity_odd ((dw_data & A63) ^ H4(hpb));
|
||||
|
||||
/* a87: WD26 WD27 WD28 WD29 WD30 WD31 H(5) 0 0 HC(5) HCPB */
|
||||
hcpb = parity_odd ((dw_data & A87) ^ H5(hpb));
|
||||
hc_3 = hc_3_a ^ hc_3_4;
|
||||
hc_4 = hc_4_a ^ hc_3_4;
|
||||
hc_5 = hcpb ^ 1;
|
||||
|
||||
syndrome = (hc_0<<5)|(hc_1<<4)|(hc_2<<3)|(hc_3<<2)|(hc_4<<1)|(hc_5);
|
||||
|
||||
/*
|
||||
* Note: Here I XOR all the non dw_data inputs into bit 0,
|
||||
* which has the same effect as spreading them over some bits
|
||||
* and then counting them... I hope ;-)
|
||||
*/
|
||||
/* a54: HC(3)A HC(4)A HCPA HCPB H(0/2) XX01 WD02 WD03 P PERR --- */
|
||||
perr = parity_even(
|
||||
hc_3_a ^
|
||||
hc_4_a ^
|
||||
hcpa ^
|
||||
hcpb ^
|
||||
h_0_2 ^
|
||||
(X_RDBITS(dw_data,32,0,0) ^ X_RDBITS(dw_data,32,1,1)) ^
|
||||
(dw_data & A54) ^
|
||||
RP(hpb) ^
|
||||
1);
|
||||
|
||||
/* a65: WD00 WD01 WD02 WD04 WD05 WD07 WD10 WD11 WD12 --- PCA */
|
||||
pca = parity_odd (dw_data & A65);
|
||||
/* a74: WD14 WD17 WD18 WD21 WD23 WD24 WD26 WD27 WD29 PCB --- */
|
||||
pcb = parity_even(dw_data & A74);
|
||||
pc = pca ^ pcb;
|
||||
|
||||
if (write) {
|
||||
/* update the hamming code and parity bit store */
|
||||
m_mem.hpb[dw_addr] = (syndrome << 2) | (pc << 1);
|
||||
return dw_data;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* <PRE>
|
||||
* A22 (74H30) 8-input NAND to check for error
|
||||
* input signal
|
||||
* -------------------------
|
||||
* 1 POK = PERR'
|
||||
* 4 NER(08) = HC(0)'
|
||||
* 3 NER(09) = HC(1)'
|
||||
* 2 NER(10) = HC(2)'
|
||||
* 6 NER(11) = HC(3)'
|
||||
* 5 NER(12) = HC(4)'
|
||||
* 12 NER(13) = HC(5)'
|
||||
* 11 1 (VPUL3)
|
||||
*
|
||||
* output signal
|
||||
* -------------------------
|
||||
* 8 ERROR
|
||||
*
|
||||
* Remembering De Morgan this can be simplified:
|
||||
* ERROR is 0, whenever all of PERR and HC(0) to HC(5) are 0.
|
||||
* Or the other way round: any of perr or syndrome non-zero means ERROR=1.
|
||||
* </PRE>
|
||||
*/
|
||||
if (perr || syndrome) {
|
||||
/* latch data on the first error */
|
||||
if (!m_mem.error) {
|
||||
m_mem.error = true;
|
||||
PUT_MESR_HAMMING(m_mem.mesr, RH(hpb));
|
||||
PUT_MESR_PERR(m_mem.mesr, perr);
|
||||
PUT_MESR_PARITY(m_mem.mesr, RP(hpb));
|
||||
PUT_MESR_SYNDROME(m_mem.mesr, syndrome);
|
||||
PUT_MESR_BANK(m_mem.mesr, (dw_addr >> 15));
|
||||
/* latch memory address register */
|
||||
m_mem.mear = m_mem.mar & 0177777;
|
||||
LOG((LOG_MEM,5," memory error at dword addr:%07o data:%011o check:%03o\n", dw_addr * 2, dw_data, hpb));
|
||||
LOG((LOG_MEM,6," MEAR: %06o\n", m_mem.mear));
|
||||
LOG((LOG_MEM,6," MESR: %06o\n", m_mem.mesr ^ 0177777));
|
||||
LOG((LOG_MEM,7," Hamming code read : %#o\n", GET_MESR_HAMMING(m_mem.mesr)));
|
||||
LOG((LOG_MEM,7," Parity error : %o\n", GET_MESR_PERR(m_mem.mesr)));
|
||||
LOG((LOG_MEM,7," Memory parity bit : %o\n", GET_MESR_PARITY(m_mem.mesr)));
|
||||
LOG((LOG_MEM,7," Hamming syndrome : %#o (bit #%d)\n", GET_MESR_SYNDROME(m_mem.mesr), hamming_lut[GET_MESR_SYNDROME(m_mem.mesr)]));
|
||||
LOG((LOG_MEM,7," Memory bank : %#o\n", GET_MESR_BANK(m_mem.mesr)));
|
||||
LOG((LOG_MEM,6," MECR: %06o\n", m_mem.mecr ^ 0177777));
|
||||
LOG((LOG_MEM,7," Test Hamming code : %#o\n", GET_MECR_TEST_CODE(m_mem.mecr)));
|
||||
LOG((LOG_MEM,7," Test mode : %s\n", GET_MECR_TEST_MODE(m_mem.mecr) ? "on" : "off"));
|
||||
LOG((LOG_MEM,7," INT on single-bit err: %s\n", GET_MECR_INT_SBERR(m_mem.mecr) ? "on" : "off"));
|
||||
LOG((LOG_MEM,7," INT on double-bit err: %s\n", GET_MECR_INT_DBERR(m_mem.mecr) ? "on" : "off"));
|
||||
LOG((LOG_MEM,7," Error correction : %s\n", GET_MECR_ERRCORR(m_mem.mecr) ? "off" : "on"));
|
||||
}
|
||||
if (-1 == hamming_lut[syndrome]) {
|
||||
/* double-bit error: wake task_part, if we're told so */
|
||||
if (GET_MECR_INT_DBERR(m_mem.mecr))
|
||||
m_task_wakeup |= 1 << task_part;
|
||||
} else {
|
||||
/* single-bit error: wake task_part, if we're told so */
|
||||
if (GET_MECR_INT_SBERR(m_mem.mecr))
|
||||
m_task_wakeup |= 1 << task_part;
|
||||
/* should we correct the single bit error ? */
|
||||
if (0 == GET_MECR_ERRCORR(m_mem.mecr)) {
|
||||
LOG((LOG_MEM,0," correct bit #%d addr:%07o data:%011o check:%03o\n", hamming_lut[syndrome], dw_addr * 2, dw_data, hpb));
|
||||
dw_data ^= 1ul << hamming_lut[syndrome];
|
||||
}
|
||||
}
|
||||
}
|
||||
return dw_data;
|
||||
}
|
||||
#endif /* USE_HAMMING_CHECK */
|
||||
|
||||
/**
|
||||
* @brief memory error address register read
|
||||
*
|
||||
* This register is a 'shadow MAR'; it holds the address of the
|
||||
* first error since the error status was last reset. If no error
|
||||
* has occured, MEAR reports the address of the most recent
|
||||
* memory access. Note that MEAR is set whenever an error of
|
||||
* _any kind_ (single-bit or double-bit) is detected.
|
||||
*/
|
||||
READ16_MEMBER( alto2_cpu_device::mear_r )
|
||||
{
|
||||
int data = m_mem.error ? m_mem.mear : m_mem.mar;
|
||||
if (!space.debugger_access()) {
|
||||
LOG((LOG_MEM,2," MEAR read %07o\n", data));
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief memory error status register read
|
||||
*
|
||||
* This register reports specifics of the first error that
|
||||
* occured since MESR was last reset. Storing anything into
|
||||
* this register resets the error logic and enables it to
|
||||
* detect a new error. Bits are "low true", i.e. if the bit
|
||||
* is 0, the conidition is true.
|
||||
* <PRE>
|
||||
* MESR[0-5] Hamming code reported from error
|
||||
* MESR[6] Parity error
|
||||
* MESR[7] Memory parity bit
|
||||
* MESR[8-13] Syndrome bits
|
||||
* MESR[14-15] Bank number in which error occured
|
||||
* </PRE>
|
||||
*/
|
||||
READ16_MEMBER( alto2_cpu_device::mesr_r )
|
||||
{
|
||||
UINT16 data = m_mem.mesr ^ 0177777;
|
||||
if (!space.debugger_access()) {
|
||||
LOG((LOG_MEM,2," MESR read %07o\n", data));
|
||||
LOG((LOG_MEM,6," Hamming code read : %#o\n", GET_MESR_HAMMING(data)));
|
||||
LOG((LOG_MEM,6," Parity error : %o\n", GET_MESR_PERR(data)));
|
||||
LOG((LOG_MEM,6," Memory parity bit : %o\n", GET_MESR_PARITY(data)));
|
||||
#if USE_HAMMING_CHECK
|
||||
LOG((LOG_MEM,6," Hamming syndrome : %#o (bit #%d)\n", GET_MESR_SYNDROME(data), hamming_lut[GET_MESR_SYNDROME(data)]));
|
||||
#else
|
||||
LOG((LOG_MEM,6," Hamming syndrome : %#o\n", GET_MESR_SYNDROME(data)));
|
||||
#endif
|
||||
LOG((LOG_MEM,6," Memory bank : %#o\n", GET_MESR_BANK(data)));
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
WRITE16_MEMBER( alto2_cpu_device::mesr_w )
|
||||
{
|
||||
if (!space.debugger_access()) {
|
||||
LOG((LOG_MEM,2," MESR write %07o (clear MESR; was %07o)\n", data, m_mem.mesr));
|
||||
}
|
||||
m_mem.mesr = 0; // set all bits to 0
|
||||
m_mem.error = 0; // reset the error flag
|
||||
m_task_wakeup &= ~(1 << task_part); // clear the task wakeup for the parity error task
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief memory error control register write
|
||||
*
|
||||
* Storing into this register is the means for controlling
|
||||
* the memory error logic. This register is set to all ones
|
||||
* (disable all interrupts) when the alto is bootstrapped
|
||||
* and when the parity error task first detects an error.
|
||||
* When an error has occured, MEAR and MESR should be read
|
||||
* before setting MECR. Bits are "low true", i.e. a 0 bit
|
||||
* enables the condition.
|
||||
*
|
||||
* <PRE>
|
||||
* MECR[0-3] Spare
|
||||
* MECR[4-10] Test hamming code (used only for special diagnostics)
|
||||
* MECR[11] Test mode (used only for special diagnostics)
|
||||
* MECR[12] Cause interrupt on single-bit errors if zero
|
||||
* MECR[13] Cause interrupt on double-bit errors if zero
|
||||
* MECR[14] Do not use error correction if zero
|
||||
* MECR[15] Spare
|
||||
* </PRE>
|
||||
*/
|
||||
WRITE16_MEMBER( alto2_cpu_device::mecr_w )
|
||||
{
|
||||
m_mem.mecr = data ^ 0177777;
|
||||
X_WRBITS(m_mem.mecr,16, 0, 3,0);
|
||||
X_WRBITS(m_mem.mecr,16,15,15,0);
|
||||
if (!space.debugger_access()) {
|
||||
LOG((LOG_MEM,2," MECR write %07o\n", data));
|
||||
LOG((LOG_MEM,6," Test Hamming code : %#o\n", GET_MECR_TEST_CODE(m_mem.mecr)));
|
||||
LOG((LOG_MEM,6," Test mode : %s\n", GET_MECR_TEST_MODE(m_mem.mecr) ? "on" : "off"));
|
||||
LOG((LOG_MEM,6," INT on single-bit err: %s\n", GET_MECR_INT_SBERR(m_mem.mecr) ? "on" : "off"));
|
||||
LOG((LOG_MEM,6," INT on double-bit err: %s\n", GET_MECR_INT_DBERR(m_mem.mecr) ? "on" : "off"));
|
||||
LOG((LOG_MEM,6," Error correction : %s\n", GET_MECR_ERRCORR(m_mem.mecr) ? "off" : "on"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief memory error control register read
|
||||
*/
|
||||
READ16_MEMBER( alto2_cpu_device::mecr_r )
|
||||
{
|
||||
UINT16 data = m_mem.mecr ^ 0177777;
|
||||
/* set all spare bits */
|
||||
if (!space.debugger_access()) {
|
||||
LOG((LOG_MEM,2," MECR read %07o\n", data));
|
||||
LOG((LOG_MEM,6," Test Hamming code : %#o\n", GET_MECR_TEST_CODE(data)));
|
||||
LOG((LOG_MEM,6," Test mode : %s\n", GET_MECR_TEST_MODE(data) ? "on" : "off"));
|
||||
LOG((LOG_MEM,6," INT on single-bit err: %s\n", GET_MECR_INT_SBERR(data) ? "on" : "off"));
|
||||
LOG((LOG_MEM,6," INT on double-bit err: %s\n", GET_MECR_INT_DBERR(data) ? "on" : "off"));
|
||||
LOG((LOG_MEM,6," Error correction : %s\n", GET_MECR_ERRCORR(data) ? "off" : "on"));
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
//! read i/o space RAM
|
||||
READ16_MEMBER ( alto2_cpu_device::ioram_r )
|
||||
{
|
||||
offs_t dword_addr = offset / 2;
|
||||
return static_cast<UINT16>(offset & 1 ? GET_ODD(m_mem.ram[dword_addr]) : GET_EVEN(m_mem.ram[dword_addr]));
|
||||
}
|
||||
|
||||
//! write i/o space RAM
|
||||
WRITE16_MEMBER( alto2_cpu_device::ioram_w )
|
||||
{
|
||||
offs_t dword_addr = offset / 2;
|
||||
if (offset & 1)
|
||||
PUT_ODD(m_mem.ram[dword_addr], data);
|
||||
else
|
||||
PUT_EVEN(m_mem.ram[dword_addr], data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief load the memory address register with some value
|
||||
*
|
||||
* @param rsel selected register (to detect refresh cycles)
|
||||
* @param addr memory address
|
||||
*/
|
||||
void alto2_cpu_device::load_mar(UINT8 rsel, UINT32 addr)
|
||||
{
|
||||
if (rsel == 037) {
|
||||
/*
|
||||
* starting a memory refresh cycle
|
||||
* currently we don't do anything special
|
||||
*/
|
||||
LOG((LOG_MEM,5, " MAR<-; refresh cycle @ %#o\n", addr));
|
||||
m_mem.mar = addr;
|
||||
m_mem.access = ALTO2_MEM_REFRESH;
|
||||
m_mem.cycle = cycle();
|
||||
return;
|
||||
}
|
||||
|
||||
m_mem.mar = addr;
|
||||
if (addr < m_mem.size) {
|
||||
LOG((LOG_MEM,2, " MAR<-; mar = %#o\n", addr));
|
||||
m_mem.access = ALTO2_MEM_RAM;
|
||||
// fetch the memory double-word to the read/write latches
|
||||
m_mem.rmdd = m_mem.wmdd = m_mem.ram[m_mem.mar/2];
|
||||
// keep track of the current CPU cycle
|
||||
m_mem.cycle = cycle();
|
||||
} else {
|
||||
m_mem.access = ALTO2_MEM_INVALID;
|
||||
m_mem.rmdd = m_mem.wmdd = ~0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief read memory or memory mapped I/O from the address in mar to md
|
||||
*
|
||||
* @result returns value from memory (RAM or MMIO)
|
||||
*/
|
||||
UINT16 alto2_cpu_device::read_mem()
|
||||
{
|
||||
UINT32 base_addr;
|
||||
|
||||
if (ALTO2_MEM_NONE == m_mem.access) {
|
||||
LOG((LOG_MEM,0," fatal: mem read with no preceding address\n"));
|
||||
return 0177777;
|
||||
}
|
||||
|
||||
if (cycle() > m_mem.cycle + 4) {
|
||||
LOG((LOG_MEM,0," fatal: mem read (MAR %#o) too late (+%lld cyc)\n", m_mem.mar, cycle() - m_mem.cycle));
|
||||
m_mem.access = ALTO2_MEM_NONE;
|
||||
return 0177777;
|
||||
}
|
||||
|
||||
base_addr = m_mem.mar & 0177777;
|
||||
if (base_addr >= ALTO2_IO_PAGE_BASE && m_mem.mar < ALTO2_RAM_SIZE) {
|
||||
m_mem.md = m_iomem->read_word(m_iomem->address_to_byte(base_addr));
|
||||
LOG((LOG_MEM,6," MD = MMIO[%#o] (%#o)\n", base_addr, m_mem.md));
|
||||
m_mem.access = ALTO2_MEM_NONE;
|
||||
#if ALTO2_DEBUG
|
||||
watch_read(m_mem.mar, m_mem.md);
|
||||
#endif
|
||||
return m_mem.md;
|
||||
}
|
||||
|
||||
#if USE_HAMMING_CHECK
|
||||
/* check for errors on the first access */
|
||||
if (!(m_mem.access & ALTO2_MEM_ODD))
|
||||
m_mem.rmdd = hamming_code(0, m_mem.mar/2, m_mem.rmdd);
|
||||
#endif
|
||||
m_mem.md = (m_mem.mar & ALTO2_MEM_ODD) ? GET_ODD(m_mem.rmdd) : GET_EVEN(m_mem.rmdd);
|
||||
LOG((LOG_MEM,6," MD = RAM[%#o] (%#o)\n", m_mem.mar, m_mem.md));
|
||||
|
||||
#if ALTO2_DEBUG
|
||||
watch_read(m_mem.mar, m_mem.md);
|
||||
#endif
|
||||
|
||||
if (m_mem.access & ALTO2_MEM_ODD) {
|
||||
// after reading the odd word, reset the access flag
|
||||
m_mem.access = ALTO2_MEM_NONE;
|
||||
} else {
|
||||
// after reading the even word word, toggle access flag (and address) to the odd word
|
||||
m_mem.mar ^= ALTO2_MEM_ODD;
|
||||
m_mem.access ^= ALTO2_MEM_ODD;
|
||||
// extend the read succeeds window by one cycle
|
||||
m_mem.cycle++;
|
||||
}
|
||||
return m_mem.md;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief write memory or memory mapped I/O from md to the address in mar
|
||||
*
|
||||
* @param data data to write to RAM or MMIO
|
||||
*/
|
||||
void alto2_cpu_device::write_mem(UINT16 data)
|
||||
{
|
||||
int base_addr;
|
||||
|
||||
m_mem.md = data & 0177777;
|
||||
if (ALTO2_MEM_NONE == m_mem.access) {
|
||||
LOG((LOG_MEM,0," fatal: mem write with no preceding address\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (cycle() > m_mem.cycle + 4) {
|
||||
LOG((LOG_MEM,0," fatal: mem write (MAR %#o, data %#o) too late (+%lld cyc)\n", m_mem.mar, data, cycle() - m_mem.cycle));
|
||||
m_mem.access = ALTO2_MEM_NONE;
|
||||
return;
|
||||
}
|
||||
|
||||
base_addr = m_mem.mar & 0177777;
|
||||
if (base_addr >= ALTO2_IO_PAGE_BASE && m_mem.mar < ALTO2_RAM_SIZE) {
|
||||
m_iomem->write_word(m_iomem->address_to_byte(base_addr), m_mem.md);
|
||||
LOG((LOG_MEM,6, " MMIO[%#o] = MD (%#o)\n", base_addr, m_mem.md));
|
||||
m_mem.access = ALTO2_MEM_NONE;
|
||||
#if ALTO2_DEBUG
|
||||
watch_write(m_mem.mar, m_mem.md);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
LOG((LOG_MEM,6, " RAM[%#o] = MD (%#o)\n", m_mem.mar, m_mem.md));
|
||||
if (m_mem.mar & ALTO2_MEM_ODD)
|
||||
PUT_ODD(m_mem.wmdd, m_mem.md);
|
||||
else
|
||||
PUT_EVEN(m_mem.wmdd, m_mem.md);
|
||||
|
||||
#if USE_HAMMING_CHECK
|
||||
if (m_mem.access & ALTO2_MEM_RAM)
|
||||
m_mem.ram[m_mem.mar/2] = hamming_code(1, m_mem.mar/2, m_mem.wmdd);
|
||||
#else
|
||||
if (m_mem.access & ALTO2_MEM_RAM)
|
||||
m_mem.ram[m_mem.mar/2] = m_mem.wmdd;
|
||||
#endif
|
||||
|
||||
#if ALTO2_DEBUG
|
||||
watch_write(m_mem.mar, m_mem.md);
|
||||
#endif
|
||||
// Toggle the odd/even word access flag
|
||||
// NB: don't reset mem.access to permit double word exchange
|
||||
m_mem.mar ^= ALTO2_MEM_ODD;
|
||||
m_mem.access ^= ALTO2_MEM_ODD;
|
||||
// extend the write succeeds window by one cycle
|
||||
m_mem.cycle++;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief debugger interface to read memory
|
||||
*
|
||||
* @param addr address to read
|
||||
* @return memory contents at address (16 bits)
|
||||
*/
|
||||
UINT16 alto2_cpu_device::debug_read_mem(UINT32 addr)
|
||||
{
|
||||
space(AS_2).set_debugger_access(true);
|
||||
int base_addr = addr & 0177777;
|
||||
int data = 0177777;
|
||||
if (base_addr >= ALTO2_IO_PAGE_BASE && addr < ALTO2_RAM_SIZE) {
|
||||
data = m_iomem->read_word(m_iomem->address_to_byte(base_addr));
|
||||
} else {
|
||||
data = (addr & ALTO2_MEM_ODD) ? GET_ODD(m_mem.ram[addr/2]) : GET_EVEN(m_mem.ram[addr/2]);
|
||||
}
|
||||
space(AS_2).set_debugger_access(false);
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief debugger interface to write memory
|
||||
*
|
||||
* @param addr address to write
|
||||
* @param data data to write (16 bits used)
|
||||
*/
|
||||
void alto2_cpu_device::debug_write_mem(UINT32 addr, UINT16 data)
|
||||
{
|
||||
space(AS_2).set_debugger_access(true);
|
||||
int base_addr = addr & 0177777;
|
||||
if (base_addr >= ALTO2_IO_PAGE_BASE && addr < ALTO2_RAM_SIZE) {
|
||||
m_iomem->write_word(m_iomem->address_to_byte(base_addr), data);
|
||||
} else if (addr & ALTO2_MEM_ODD) {
|
||||
PUT_ODD(m_mem.ram[addr/2], data);
|
||||
} else {
|
||||
PUT_EVEN(m_mem.ram[addr/2], data);
|
||||
}
|
||||
space(AS_2).set_debugger_access(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief initialize the memory system
|
||||
*
|
||||
* Zeroes the memory context, including RAM and installs dummy
|
||||
* handlers for the memory mapped I/O area.
|
||||
* Sets handlers for access to the memory error address, status,
|
||||
* and control registers at 0177024 to 0177026.
|
||||
*/
|
||||
void alto2_cpu_device::init_memory()
|
||||
{
|
||||
memset(&m_mem, 0, sizeof(m_mem));
|
||||
save_item(NAME(m_mem.mar));
|
||||
save_item(NAME(m_mem.rmdd));
|
||||
save_item(NAME(m_mem.wmdd));
|
||||
save_item(NAME(m_mem.md));
|
||||
save_item(NAME(m_mem.cycle));
|
||||
save_item(NAME(m_mem.access));
|
||||
save_item(NAME(m_mem.error));
|
||||
save_item(NAME(m_mem.mear));
|
||||
save_item(NAME(m_mem.mecr));
|
||||
}
|
||||
|
||||
void alto2_cpu_device::exit_memory()
|
||||
{
|
||||
// no need for this since it free on exit by itself
|
||||
// if (m_mem.ram) {
|
||||
// auto_free(machine(), m_mem.ram);
|
||||
// m_mem.ram = 0;
|
||||
// }
|
||||
// if (m_mem.hpb) {
|
||||
// auto_free(machine(), m_mem.hpb);
|
||||
// m_mem.hpb = 0;
|
||||
// }
|
||||
}
|
||||
|
||||
void alto2_cpu_device::reset_memory()
|
||||
{
|
||||
if (m_mem.ram) {
|
||||
auto_free(machine(), m_mem.ram);
|
||||
m_mem.ram = 0;
|
||||
}
|
||||
if (m_mem.hpb) {
|
||||
auto_free(machine(), m_mem.hpb);
|
||||
m_mem.hpb = 0;
|
||||
}
|
||||
// allocate 64K or 128K words of main memory
|
||||
ioport_port* config = ioport(":CONFIG");
|
||||
// config should be valid, unless the driver doesn't define it
|
||||
if (config)
|
||||
m_mem.size = config->read() & 1 ? ALTO2_RAM_SIZE : 2 * ALTO2_RAM_SIZE;
|
||||
else
|
||||
m_mem.size = ALTO2_RAM_SIZE;
|
||||
logerror("Main memory %u KiB\n", static_cast<UINT32>(sizeof(UINT16) * m_mem.size / 1024));
|
||||
|
||||
m_mem.ram = auto_alloc_array_clear(machine(), UINT32, sizeof(UINT16) * m_mem.size);
|
||||
m_mem.hpb = auto_alloc_array_clear(machine(), UINT8, sizeof(UINT16) * m_mem.size);
|
||||
|
||||
#if USE_HAMMING_CHECK
|
||||
// Initialize the hamming codes and parity bit
|
||||
for (UINT32 addr = 0; addr < ALTO2_IO_PAGE_BASE; addr++) {
|
||||
hamming_code(1, addr, 0);
|
||||
hamming_code(1, 0200000 + addr, 0);
|
||||
}
|
||||
#endif
|
||||
m_mem.mar = 0;
|
||||
m_mem.rmdd = 0;
|
||||
m_mem.wmdd = 0;
|
||||
m_mem.md = 0;
|
||||
m_mem.cycle = 0;
|
||||
m_mem.access = 0;
|
||||
m_mem.error = false;
|
||||
m_mem.mear = 0;
|
||||
m_mem.mesr = 0;
|
||||
m_mem.mecr = 0;
|
||||
}
|
140
src/emu/cpu/alto2/a2mem.h
Normal file
140
src/emu/cpu/alto2/a2mem.h
Normal file
@ -0,0 +1,140 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Xerox AltoII memory block (MEM)
|
||||
*
|
||||
* Copyright Juergen Buchmueller <pullmoll@t-online.de>
|
||||
*
|
||||
* Licenses: MAME, GPLv2
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifdef ALTO2_DEFINE_CONSTANTS
|
||||
|
||||
#define ALTO2_RAM_SIZE 0200000 //!< size of main memory in words
|
||||
#define ALTO2_IO_PAGE_BASE 0177000 //!< base address of the memory mapped io range
|
||||
#define ALTO2_IO_PAGE_SIZE 0001000 //!< size of the memory mapped io range
|
||||
|
||||
#else // ALTO2_DEFINE_CONSTANTS
|
||||
#ifndef _A2MEM_H_
|
||||
#define _A2MEM_H_
|
||||
//! memory access mode
|
||||
enum {
|
||||
ALTO2_MEM_NONE,
|
||||
ALTO2_MEM_ODD = (1 << 0),
|
||||
ALTO2_MEM_RAM = (1 << 1),
|
||||
ALTO2_MEM_REFRESH = (1 << 2),
|
||||
ALTO2_MEM_INVALID = (1 << 3)
|
||||
};
|
||||
|
||||
struct {
|
||||
UINT32 size; //!< main memory size (64K or 128K)
|
||||
UINT32* ram; //!< main memory organized as double-words
|
||||
UINT8* hpb; //!< Hamming Code bits (6) and Parity bits (1) per double word
|
||||
UINT32 mar; //!< memory address register
|
||||
UINT32 rmdd; //!< read memory data double-word
|
||||
UINT32 wmdd; //!< write memory data double-word
|
||||
UINT16 md; //!< memory data register
|
||||
UINT64 cycle; //!< cycle when the memory address register was loaded
|
||||
|
||||
/**
|
||||
* @brief memory access under the way if non-zero
|
||||
* 0: no memory access (MEM_NONE)
|
||||
* 1: invalid
|
||||
* 2: memory access even word (MEM_RAM)
|
||||
* 3: memory access odd word (MEM_RAM | MEM_ODD)
|
||||
*/
|
||||
int access;
|
||||
bool error; //!< non-zero after a memory error was detected
|
||||
UINT32 mear; //!< memory error address register
|
||||
UINT16 mesr; //!< memory error status register
|
||||
UINT16 mecr; //!< memory error control register
|
||||
} m_mem;
|
||||
|
||||
/**
|
||||
* @brief check if memory address register load is yet possible
|
||||
* suspend if accessing RAM and previous MAR<- was less than 5 cycles ago
|
||||
*
|
||||
* 1. MAR<- ANY
|
||||
* 2. REQUIRED
|
||||
* 3. MD<- whatever
|
||||
* 4. SUSPEND
|
||||
* 5. SUSPEND
|
||||
* 6. MAR<- ANY
|
||||
*
|
||||
* @return false, if memory address can be loaded
|
||||
*/
|
||||
inline bool check_mem_load_mar_stall(UINT8 rsel) {
|
||||
if (ALTO2_MEM_NONE == m_mem.access)
|
||||
return false;
|
||||
return cycle() < m_mem.cycle+5;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief check if memory read is yet possible
|
||||
* MAR<- = cycle #1, earliest read at cycle #5, i.e. + 4
|
||||
*
|
||||
* 1. MAR<- ANY
|
||||
* 2. REQUIRED
|
||||
* 3. SUSPEND
|
||||
* 4. SUSPEND
|
||||
* 5. whereever <-MD
|
||||
*
|
||||
* @return false, if memory can be read without wait cycle
|
||||
*/
|
||||
inline bool check_mem_read_stall() {
|
||||
if (ALTO2_MEM_NONE == m_mem.access)
|
||||
return false;
|
||||
return cycle() < m_mem.cycle+4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief check if memory write is yet possible
|
||||
* MAR<- = cycle #1, earliest write at cycle #3, i.e. + 2
|
||||
*
|
||||
* 1. MAR<- ANY
|
||||
* 2. REQUIRED
|
||||
* 3. OPTIONAL
|
||||
* 4. MD<- whatever
|
||||
*
|
||||
* @return false, if memory can be written without wait cycle
|
||||
*/
|
||||
inline bool check_mem_write_stall() {
|
||||
if (ALTO2_MEM_NONE == m_mem.access)
|
||||
return false;
|
||||
return cycle() < m_mem.cycle+2;
|
||||
}
|
||||
|
||||
|
||||
DECLARE_READ16_MEMBER ( mear_r ); //!< memory error address register read
|
||||
DECLARE_READ16_MEMBER ( mesr_r ); //!< memory error status register read
|
||||
DECLARE_WRITE16_MEMBER( mesr_w ); //!< memory error status register write (clear)
|
||||
DECLARE_READ16_MEMBER ( mecr_r ); //!< memory error control register read
|
||||
DECLARE_WRITE16_MEMBER( mecr_w ); //!< memory error control register write
|
||||
|
||||
//! read or write a memory double-word and caluclate its Hamming code
|
||||
UINT32 hamming_code(int write, UINT32 dw_addr, UINT32 dw_data);
|
||||
|
||||
//! load the memory address register with some value
|
||||
void load_mar(UINT8 rsel, UINT32 addr);
|
||||
|
||||
//! read memory or memory mapped I/O from the address in mar to md
|
||||
UINT16 read_mem();
|
||||
|
||||
//! write memory or memory mapped I/O from md to the address in mar
|
||||
void write_mem(UINT16 data);
|
||||
|
||||
//! debugger interface to read memory
|
||||
UINT16 debug_read_mem(UINT32 addr);
|
||||
|
||||
//! debugger interface to write memory
|
||||
void debug_write_mem(UINT32 addr, UINT16 data);
|
||||
|
||||
#if ALTO2_DEBUG
|
||||
void watch_write(UINT32 addr, UINT32 data);
|
||||
void watch_read(UINT32 addr, UINT32 data);
|
||||
#endif
|
||||
|
||||
void init_memory(); //!< initialize the memory system
|
||||
void exit_memory(); //!< deinitialize the memory system
|
||||
void reset_memory(); //!< reset the memory system
|
||||
#endif // _A2MEM_H_
|
||||
#endif // ALTO2_DEFINE_CONSTANTS
|
273
src/emu/cpu/alto2/a2mouse.c
Normal file
273
src/emu/cpu/alto2/a2mouse.c
Normal file
@ -0,0 +1,273 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Xerox AltoII mouse interface
|
||||
*
|
||||
* Copyright Juergen Buchmueller <pullmoll@t-online.de>
|
||||
*
|
||||
* Licenses: MAME, GPLv2
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include "alto2cpu.h"
|
||||
#include "a2roms.h"
|
||||
|
||||
#define MOUSE_DIRTY_HACK 0
|
||||
|
||||
enum {
|
||||
MX1 = (1<<0), //!< MX1 signal is bit 0 (latch bit 1)
|
||||
LMX1 = (1<<1),
|
||||
MX2 = (1<<2), //!< MX2 signal is bit 2 (latch bit 3)
|
||||
LMX2 = (1<<3),
|
||||
MY1 = (1<<4), //!< MY1 signal is bit 4 (latch bit 5)
|
||||
LMY1 = (1<<5),
|
||||
MY2 = (1<<6), //!< MY2 signal is bit 6 (latch bit 7)
|
||||
LMY2 = (1<<7),
|
||||
MACTIVE = (MX1|MX2|MY1|MY2), //!< mask for the active bits
|
||||
MLATCH = (LMX1|LMX2|LMY1|LMY2) //!< mask for the latched bits
|
||||
};
|
||||
|
||||
/**
|
||||
* <PRE>
|
||||
* The mouse inputs from the shutters are connected to a quad
|
||||
* 2/3 input RS flip flop (SN74279).
|
||||
*
|
||||
* 74279
|
||||
* +---+--+---+
|
||||
* | +--+ |
|
||||
* R1 -|1 16|- Vcc
|
||||
* | |
|
||||
* S1a -|2 15|- S4
|
||||
* | |
|
||||
* S1b -|3 14|- R4
|
||||
* | |
|
||||
* Q1 -|4 13|- Q4
|
||||
* | |
|
||||
* R2 -|5 12|- S3a
|
||||
* | |
|
||||
* S2 -|6 11|- S3b
|
||||
* | |
|
||||
* Q2 -|7 10|- R3
|
||||
* | |
|
||||
* GND -|8 9|- Q3
|
||||
* | |
|
||||
* +----------+
|
||||
*
|
||||
* The 'Y' Encoder signals are connected to IC1:
|
||||
* shutter pin(s) R/S output
|
||||
* ------------------------------------
|
||||
* 0 2,3 S1a,b Q1 MX2 -> 1
|
||||
* 1 1 R1 Q1 MX2 -> 0
|
||||
* 2 5 R2 Q2 MX1 -> 0
|
||||
* 3 6 S2 Q2 MX1 -> 1
|
||||
*
|
||||
* The 'X' Encoder signals are connected to IC2:
|
||||
* shutter pin(s) R/S output
|
||||
* ------------------------------------
|
||||
* 0 2,3 S1a,b Q1 MY2 -> 1
|
||||
* 1 1 R1 Q1 MY2 -> 0
|
||||
* 2 5 R2 Q2 MY1 -> 0
|
||||
* 3 6 S2 Q2 MY1 -> 1
|
||||
*
|
||||
*
|
||||
* The pulse train generated by a left or up rotation is:
|
||||
*
|
||||
* +---+ +---+ +---+
|
||||
* MX1/MY1 | | | | | |
|
||||
* ---+ +---+ +---+ +---
|
||||
*
|
||||
* +---+ +---+ +---+ +-
|
||||
* MX2/MY2 | | | | | | |
|
||||
* -+ +---+ +---+ +---+
|
||||
*
|
||||
*
|
||||
* The pulse train generated by a right or down rotation is:
|
||||
*
|
||||
* +---+ +---+ +---+ +-
|
||||
* MX1/MY1 | | | | | | |
|
||||
* -+ +---+ +---+ +---+
|
||||
*
|
||||
* +---+ +---+ +---+
|
||||
* MX2/MY2 | | | | | |
|
||||
* ---+ +---+ +---+ +---
|
||||
*
|
||||
* In order to simulate the shutter sequence for the mouse motions
|
||||
* we have to generate a sequence of pulses on MX1/MX2 and MY1/MY2
|
||||
* that have their phases shifted by 90 degree.
|
||||
* </PRE>
|
||||
*/
|
||||
|
||||
|
||||
#define MOVEX(x) ((((x) < 0) ? MY2 : ((x) > 0) ? MY1 : 0))
|
||||
#define MOVEY(y) ((((y) < 0) ? MX2 : ((y) > 0) ? MX1 : 0))
|
||||
#define SIGN(a) ((a) < 0 ? -1 : (a) > 0 ? 1 : 0)
|
||||
|
||||
/**
|
||||
* @brief return the mouse motion flags
|
||||
*
|
||||
* Advance the mouse x and y coordinates to the dx and dy
|
||||
* coordinates by either toggling MX2 or MX1 first for a
|
||||
* y movement, or MY2 or MY1 for x movement.
|
||||
* There are four read phases counted by m_mouse.phase
|
||||
*
|
||||
* @return lookup value from madr_a32
|
||||
*/
|
||||
UINT16 alto2_cpu_device::mouse_read()
|
||||
{
|
||||
UINT16 data;
|
||||
|
||||
m_mouse.latch = (m_mouse.latch << 1) & MLATCH;
|
||||
data = m_madr_a32[m_mouse.latch];
|
||||
|
||||
switch (m_mouse.phase) {
|
||||
case 0:
|
||||
m_mouse.latch |= MOVEX(m_mouse.dx - m_mouse.x);
|
||||
m_mouse.latch |= MOVEY(m_mouse.dy - m_mouse.y);
|
||||
break;
|
||||
case 1:
|
||||
m_mouse.latch |= MACTIVE;
|
||||
m_mouse.x -= SIGN(m_mouse.x - m_mouse.dx);
|
||||
m_mouse.y -= SIGN(m_mouse.y - m_mouse.dy);
|
||||
break;
|
||||
case 2:
|
||||
m_mouse.latch ^= MOVEX(m_mouse.dx - m_mouse.x);
|
||||
m_mouse.latch ^= MOVEY(m_mouse.dy - m_mouse.y);
|
||||
break;
|
||||
default:
|
||||
m_mouse.latch &= ~MACTIVE;
|
||||
m_mouse.x -= SIGN(m_mouse.x - m_mouse.dx);
|
||||
m_mouse.y -= SIGN(m_mouse.y - m_mouse.dy);
|
||||
}
|
||||
m_mouse.phase = (m_mouse.phase + 1) % 4;
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief register a mouse motion in x direction
|
||||
* @param ioport_field reference to the field
|
||||
* @param param pointer passed in PORT_CHANGED_MEMBER last parameter
|
||||
* @param oldval the old ioport_value
|
||||
* @param newval the new ioport_value
|
||||
*/
|
||||
INPUT_CHANGED_MEMBER( alto2_cpu_device::mouse_motion_x )
|
||||
{
|
||||
// set new destination (absolute) mouse x coordinate
|
||||
INT32 x = m_mouse.dx + newval - oldval;
|
||||
x = x < 0 ? 0 : x > 605 ? 605 : x;
|
||||
m_mouse.dx = x;
|
||||
#if MOUSE_DIRTY_HACK
|
||||
/* XXX: dirty, dirty, hack */
|
||||
#if USE_HAMMING_CHECK
|
||||
m_mem.ram[0424/2] = hamming_code(1, 0424 / 2, (m_mouse.dx << 16) | m_mouse.dy);
|
||||
#else
|
||||
m_mem.ram[0424/2] = (m_mouse.dx << 16) | m_mouse.dy;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief register a mouse motion in y direction
|
||||
* @param ioport_field reference to the field
|
||||
* @param param pointer passed in PORT_CHANGED_MEMBER last parameter
|
||||
* @param oldval the old ioport_value
|
||||
* @param newval the new ioport_value
|
||||
*/
|
||||
INPUT_CHANGED_MEMBER( alto2_cpu_device::mouse_motion_y )
|
||||
{
|
||||
// set new destination (absolute) mouse y coordinate
|
||||
INT32 y = m_mouse.dy + newval - oldval;
|
||||
y = y < 0 ? 0 : y > 807 ? 807 : y;
|
||||
m_mouse.dy = y;
|
||||
#if MOUSE_DIRTY_HACK
|
||||
/* XXX: dirty, dirty, hack */
|
||||
#if USE_HAMMING_CHECK
|
||||
m_mem.ram[0424/2] = hamming_code(1, 0424 / 2, (m_mouse.dx << 16) | m_mouse.dy);
|
||||
#else
|
||||
m_mem.ram[0424/2] = (m_mouse.dx << 16) | m_mouse.dy;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief register a mouse button change
|
||||
*
|
||||
* convert button bit to UTILIN[13-15]
|
||||
*
|
||||
* @param ioport_field reference to the field
|
||||
* @param param pointer passed in PORT_CHANGED_MEMBER last parameter
|
||||
* @param oldval the old ioport_value
|
||||
* @param newval the new ioport_value
|
||||
*/
|
||||
INPUT_CHANGED_MEMBER( alto2_cpu_device::mouse_button_0 )
|
||||
{
|
||||
X_WRBITS(m_hw.utilin,16,13,13,newval);
|
||||
}
|
||||
|
||||
INPUT_CHANGED_MEMBER( alto2_cpu_device::mouse_button_1 )
|
||||
{
|
||||
X_WRBITS(m_hw.utilin,16,14,14,newval);
|
||||
}
|
||||
|
||||
INPUT_CHANGED_MEMBER( alto2_cpu_device::mouse_button_2 )
|
||||
{
|
||||
X_WRBITS(m_hw.utilin,16,15,15,newval);
|
||||
}
|
||||
|
||||
static const prom_load_t pl_madr_a32 =
|
||||
{
|
||||
"madr.a32",
|
||||
0,
|
||||
"a0e3b4a7",
|
||||
"24e50afdeb637a6a8588f8d3a3493c9188b8da2c",
|
||||
/* size */ 0400,
|
||||
/* amap */ AMAP_DEFAULT,
|
||||
/* axor */ 0,
|
||||
/* dxor */ 017, // invert D0-D3
|
||||
/* width */ 4,
|
||||
/* shift */ 0,
|
||||
/* dmap */ DMAP_REVERSE_0_3, // reverse D0-D3 to D3-D0
|
||||
/* dand */ ZERO,
|
||||
/* type */ sizeof(UINT8)
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief initialize the mouse context to useful values
|
||||
*
|
||||
* From the Alto Hardware Manual:
|
||||
* <PRE>
|
||||
* The mouse is a hand-held pointing device which contains two encoders
|
||||
* which digitize its position as it is rolled over a table-top. It also
|
||||
* has three buttons which may be read as the three low order bits of
|
||||
* memory location UTILIN (0177030), iin the manner of the keyboard.
|
||||
* The bit/button correspondence in UTILIN are (depressed keys
|
||||
* correspond to 0's in memory):
|
||||
*
|
||||
* UTILIN[13] TOP or LEFT button (RED)
|
||||
* UTILIN[14] BOTTOM or RIGHT button (BLUE)
|
||||
* UTILIN[15] MIDDLE button (YELLOW)
|
||||
*
|
||||
* The mouse coordinates are maintained by the MRT microcode in locations
|
||||
* MOUSELOC(0424)=X and MOUSELOC+1(0425)=Y in page one of the Alto memory.
|
||||
* These coordinates are relative, i.e., the hardware only increments and
|
||||
* decrements them. The resolution of the mouse is approximately 100 points
|
||||
* per inch.
|
||||
* </PRE>
|
||||
*/
|
||||
void alto2_cpu_device::init_mouse()
|
||||
{
|
||||
memset(&m_mouse, 0, sizeof(m_mouse));
|
||||
m_madr_a32 = prom_load(machine(), &pl_madr_a32, memregion("madr_a32")->base());
|
||||
}
|
||||
|
||||
void alto2_cpu_device::exit_mouse()
|
||||
{
|
||||
// nothing to do yet
|
||||
}
|
||||
|
||||
void alto2_cpu_device::reset_mouse()
|
||||
{
|
||||
m_mouse.x = 0;
|
||||
m_mouse.y = 0;
|
||||
m_mouse.dx = 0;
|
||||
m_mouse.dy = 0;
|
||||
m_mouse.latch = 0;
|
||||
m_mouse.phase = 0;
|
||||
}
|
73
src/emu/cpu/alto2/a2mouse.h
Normal file
73
src/emu/cpu/alto2/a2mouse.h
Normal file
@ -0,0 +1,73 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Xerox AltoII mouse hardware (MOUSE)
|
||||
*
|
||||
* Copyright Juergen Buchmueller <pullmoll@t-online.de>
|
||||
*
|
||||
* Licenses: MAME, GPLv2
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifdef ALTO2_DEFINE_CONSTANTS
|
||||
|
||||
#else // ALTO2_DEFINE_CONSTANTS
|
||||
#ifndef _A2MOUSE_H_
|
||||
#define _A2MOUSE_H_
|
||||
/**
|
||||
* @brief PROM madr.a32 contains a lookup table to translate mouse motions
|
||||
*
|
||||
* <PRE>
|
||||
* The 4 mouse motion signals MX1, MX2, MY1, and MY2 are connected
|
||||
* to a 256x4 PROM's (3601, SN74387) address lines A0, A2, A4, and A6.
|
||||
* The previous (latched) state of the 4 signals is connected to the
|
||||
* address lines A1, A3, A5, and A7.
|
||||
*
|
||||
* SN74387
|
||||
* +---+--+---+
|
||||
* | +--+ |
|
||||
* MY2 A6 -|1 16|- Vcc
|
||||
* | |
|
||||
* LMY1 A5 -|2 15|- A7 LMY2
|
||||
* | |
|
||||
* MY1 A4 -|3 14|- FE1' 0
|
||||
* | |
|
||||
* LMX2 A3 -|4 13|- FE2' 0
|
||||
* | |
|
||||
* MX1 A0 -|5 12|- D0 BUS[12]
|
||||
* | |
|
||||
* LMX1 A1 -|6 11|- D1 BUS[13]
|
||||
* | |
|
||||
* MX2 A2 -|7 10|- D2 BUS[14]
|
||||
* | |
|
||||
* GND -|8 9|- D3 BUS[15]
|
||||
* | |
|
||||
* +----------+
|
||||
*
|
||||
* A motion to the west will first toggle MX2, then MX1.
|
||||
* sequence: 04 -> 0d -> 0b -> 02
|
||||
* A motion to the east will first toggle MX1, then MX2.
|
||||
* sequence: 01 -> 07 -> 0e -> 08
|
||||
*
|
||||
* A motion to the north will first toggle MY2, then MY1.
|
||||
* sequence: 40 -> d0 -> b0 -> 20
|
||||
* A motion to the south will first toggle MY1, then MY2.
|
||||
* sequence: 10 -> 70 -> e0 -> 80
|
||||
* </PRE>
|
||||
*/
|
||||
UINT8* m_madr_a32;
|
||||
|
||||
//! mouse context
|
||||
struct {
|
||||
int x; //!< current X coordinate
|
||||
int y; //!< current Y coordinate
|
||||
int dx; //!< destination X coordinate (real mouse X)
|
||||
int dy; //!< destination Y coordinate (real mouse Y)
|
||||
UINT8 latch; //!< current latch value
|
||||
UINT8 phase; //!< current read latch phase
|
||||
} m_mouse;
|
||||
|
||||
UINT16 mouse_read(); //!< return the mouse motion flags
|
||||
void init_mouse(); //!< initialize the mouse context
|
||||
void exit_mouse(); //!< deinitialize the mouse context
|
||||
void reset_mouse(); //!< reset the mouse context
|
||||
#endif // _A2MOUSE_H_
|
||||
#endif // ALTO2_DEFINE_CONSTANTS
|
47
src/emu/cpu/alto2/a2mrt.c
Normal file
47
src/emu/cpu/alto2/a2mrt.c
Normal file
@ -0,0 +1,47 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Xerox AltoII memory refresh task
|
||||
*
|
||||
* Copyright Juergen Buchmueller <pullmoll@t-online.de>
|
||||
*
|
||||
* Licenses: MAME, GPLv2
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include "alto2cpu.h"
|
||||
|
||||
//! f1_mrt_block early: block the display word task
|
||||
void alto2_cpu_device::f1_early_mrt_block()
|
||||
{
|
||||
/* clear the wakeup for the memory refresh task */
|
||||
m_task_wakeup &= ~(1 << m_task);
|
||||
LOG((LOG_MRT,2," BLOCK %s\n", task_name(m_task)));
|
||||
}
|
||||
|
||||
//! called by the CPU when MRT becomes active
|
||||
void alto2_cpu_device::activate_mrt()
|
||||
{
|
||||
m_task_wakeup &= ~(1 << m_task);
|
||||
if (m_ewfct)
|
||||
{
|
||||
// The Ether task wants a wakeup, too
|
||||
m_task_wakeup |= 1 << task_ether;
|
||||
}
|
||||
}
|
||||
|
||||
//! memory refresh task slots initialization
|
||||
void alto2_cpu_device::init_mrt(int task)
|
||||
{
|
||||
set_f1(task, f1_block, &alto2_cpu_device::f1_early_mrt_block, 0);
|
||||
/* auto block */
|
||||
m_active_callback[task] = &alto2_cpu_device::activate_mrt;
|
||||
}
|
||||
|
||||
void alto2_cpu_device::exit_mrt()
|
||||
{
|
||||
// nothing to do yet
|
||||
}
|
||||
|
||||
void alto2_cpu_device::reset_mrt()
|
||||
{
|
||||
// nothing to do yet
|
||||
}
|
21
src/emu/cpu/alto2/a2mrt.h
Normal file
21
src/emu/cpu/alto2/a2mrt.h
Normal file
@ -0,0 +1,21 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Xerox AltoII memory refresh task (MRT)
|
||||
*
|
||||
* Copyright Juergen Buchmueller <pullmoll@t-online.de>
|
||||
*
|
||||
* Licenses: MAME, GPLv2
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifdef ALTO2_DEFINE_CONSTANTS
|
||||
|
||||
#else // ALTO2_DEFINE_CONSTANTS
|
||||
#ifndef _A2MRT_H_
|
||||
#define _A2MRT_H_
|
||||
void f1_early_mrt_block(); //!< F1 func: block the display word task
|
||||
void activate_mrt(); //!< called by the CPU when MRT becomes active
|
||||
void init_mrt(int task = task_mrt); //!< initialize the memory refresh task
|
||||
void exit_mrt(); //!< deinitialize the memory refresh task
|
||||
void reset_mrt(); //!< reset the memory refresh task
|
||||
#endif // _A2MRT_H_
|
||||
#endif // ALTO2_DEFINE_CONSTANTS
|
32
src/emu/cpu/alto2/a2part.c
Normal file
32
src/emu/cpu/alto2/a2part.c
Normal file
@ -0,0 +1,32 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Xerox AltoII parity task
|
||||
*
|
||||
* Copyright Juergen Buchmueller <pullmoll@t-online.de>
|
||||
*
|
||||
* Licenses: MAME, GPLv2
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include "alto2cpu.h"
|
||||
|
||||
//! called by the CPU when the parity task becomes active
|
||||
void alto2_cpu_device::activate_part()
|
||||
{
|
||||
m_task_wakeup &= ~(1 << m_task);
|
||||
}
|
||||
|
||||
//! parity task slots initialization
|
||||
void alto2_cpu_device::init_part(int task)
|
||||
{
|
||||
m_active_callback[task] = &alto2_cpu_device::activate_part;
|
||||
}
|
||||
|
||||
void alto2_cpu_device::exit_part()
|
||||
{
|
||||
// nothing to do yet
|
||||
}
|
||||
|
||||
void alto2_cpu_device::reset_part()
|
||||
{
|
||||
// nothing to do yet
|
||||
}
|
20
src/emu/cpu/alto2/a2part.h
Normal file
20
src/emu/cpu/alto2/a2part.h
Normal file
@ -0,0 +1,20 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Xerox AltoII parity task (PART)
|
||||
*
|
||||
* Copyright Juergen Buchmueller <pullmoll@t-online.de>
|
||||
*
|
||||
* Licenses: MAME, GPLv2
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifdef ALTO2_DEFINE_CONSTANTS
|
||||
|
||||
#else // ALTO2_DEFINE_CONSTANTS
|
||||
#ifndef _A2PART_H_
|
||||
#define _A2PART_H_
|
||||
void activate_part();
|
||||
void init_part(int task = task_part); //!< initialize the parity task
|
||||
void exit_part(); //!< deinitialize the parity task
|
||||
void reset_part(); //!< reset the parity task
|
||||
#endif // _A2PART_H_
|
||||
#endif // ALTO2_DEFINE_CONSTANTS
|
440
src/emu/cpu/alto2/a2ram.c
Normal file
440
src/emu/cpu/alto2/a2ram.c
Normal file
@ -0,0 +1,440 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Xerox AltoII RAM related functions
|
||||
*
|
||||
* Copyright Juergen Buchmueller <pullmoll@t-online.de>
|
||||
*
|
||||
* Licenses: MAME, GPLv2
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include "alto2cpu.h"
|
||||
|
||||
#define DEBUG_WRTRAM 0 //!< define to 1 to printf disassembled CRAM writes
|
||||
|
||||
//! direct read access to the microcode CRAM
|
||||
#define RD_CRAM(addr) (*reinterpret_cast<UINT32 *>(m_ucode_cram + addr * 4))
|
||||
|
||||
//! direct write access to the microcode CRAM
|
||||
#define WR_CRAM(addr,data) do { \
|
||||
*reinterpret_cast<UINT32 *>(m_ucode_cram + addr * 4) = data; \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* @brief read the microcode ROM/RAM halfword
|
||||
*
|
||||
* Note: HALFSEL is selecting the even (0) or odd (1) half of the
|
||||
* microcode RAM 32-bit word. Here's how the demultiplexers (74298)
|
||||
* u8, u18, u28 and u38 select the bits:
|
||||
*
|
||||
* SN74298
|
||||
* +---+-+---+
|
||||
* | +-+ |
|
||||
* B2 -|1 16|- Vcc
|
||||
* | |
|
||||
* A2 -|2 15|- QA
|
||||
* | |
|
||||
* A1 -|3 14|- QB
|
||||
* | |
|
||||
* B1 -|4 13|- QC
|
||||
* | |
|
||||
* C2 -|5 12|- QD
|
||||
* | |
|
||||
* D2 -|6 11|- CLK
|
||||
* | |
|
||||
* D1 -|7 10|- SEL
|
||||
* | |
|
||||
* GND -|8 9|- C1
|
||||
* | |
|
||||
* +---------+
|
||||
*
|
||||
* chip out pin BUS in pin HSEL=0 in pin HSEL=1
|
||||
* --------------------------------------------------------------
|
||||
* u8 QA 15 0 A1 3 DRSEL(0)' A2 2 DF2(0)
|
||||
* u8 QB 14 1 B1 4 DRSEL(1)' B2 1 DF2(1)'
|
||||
* u8 QC 13 2 C1 9 DRSEL(2)' C2 5 DF2(2)'
|
||||
* u8 QD 12 3 D1 7 DRSEL(3)' D2 6 DF2(3)'
|
||||
*
|
||||
* u18 QA 15 4 A1 3 DRSEL(4)' A2 2 LOADT'
|
||||
* u18 QB 14 5 B1 4 DALUF(0)' B2 1 LOADL
|
||||
* u18 QC 13 6 C1 9 DALUF(1)' C2 5 NEXT(00)'
|
||||
* u18 QD 12 7 D1 7 DALUF(2)' D2 6 NEXT(01)'
|
||||
*
|
||||
* u28 QA 15 8 A1 3 DALUF(3)' A2 2 NEXT(02)'
|
||||
* u28 QB 14 9 B1 4 DBS(0)' B2 1 NEXT(03)'
|
||||
* u28 QC 13 10 C1 9 DBS(1)' C2 5 NEXT(04)'
|
||||
* u28 QD 12 11 D1 7 DBS(2)' D2 6 NEXT(05)'
|
||||
*
|
||||
* u38 QA 15 12 A1 3 DF1(0) A2 2 NEXT(06)'
|
||||
* u38 QB 14 13 B1 4 DF1(1)' B2 1 NEXT(07)'
|
||||
* u38 QC 13 14 C1 9 DF1(2)' C2 5 NEXT(08)'
|
||||
* u38 QD 12 15 D1 7 DF1(3)' D2 6 NEXT(09)'
|
||||
*
|
||||
* The HALFSEL signal to the demultiplexers is the inverted bit BUS(5):
|
||||
* BUS(5)=1, HALFSEL=0, A1,B1,C1,D1 inputs, upper half of the 32-bit word
|
||||
* BUS(5)=0, HALFSEL=1, A2,B2,C2,D2 inputs, lower half of the 32-bit word
|
||||
*/
|
||||
void alto2_cpu_device::rdram()
|
||||
{
|
||||
UINT32 addr, value;
|
||||
UINT32 bank = GET_CRAM_BANKSEL(m_cram_addr);
|
||||
UINT32 wordaddr = GET_CRAM_WORDADDR(m_cram_addr);
|
||||
|
||||
if (GET_CRAM_RAMROM(m_cram_addr)) {
|
||||
/* read CROM 0 at current mpc */
|
||||
addr = m_mpc & ALTO2_UCODE_PAGE_MASK;
|
||||
LOG((LOG_CPU,0," rdram: ROM [%05o] ", addr));
|
||||
} else {
|
||||
/* read CRAM[bank] */
|
||||
addr = bank * ALTO2_UCODE_PAGE_SIZE + wordaddr;
|
||||
LOG((LOG_CPU,0," rdram: RAM%d [%04o] ", bank, wordaddr));
|
||||
}
|
||||
|
||||
m_rdram_flag = false;
|
||||
if (ALTO2_UCODE_RAM_BASE + addr >= ALTO2_UCODE_SIZE) {
|
||||
value = 0177777; /* ??? */
|
||||
LOG((LOG_CPU,0,"invalid address (%06o)\n", addr));
|
||||
return;
|
||||
}
|
||||
value = RD_CRAM(addr) ^ ALTO2_UCODE_INVERTED;
|
||||
if (GET_CRAM_HALFSEL(m_cram_addr)) {
|
||||
value = value >> 16;
|
||||
LOG((LOG_CPU,0,"upper:%06o\n", value & 0177777));
|
||||
} else {
|
||||
LOG((LOG_CPU,0,"lower:%06o\n", value & 0177777));
|
||||
}
|
||||
m_bus &= value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief write the microcode RAM from M register and ALU
|
||||
*
|
||||
* Note: M is a latch (MYL, i.e. memory L) on the CRAM board that latches
|
||||
* the ALU whenever LOADL and GOODTASK are met. GOODTASK is the Emulator
|
||||
* task and something I have not yet found out about: TASKA' and TASKB'.
|
||||
*
|
||||
* There's also an undumped PROM u21 which is addressed by GOODTASK and
|
||||
* 7 other signals...
|
||||
*/
|
||||
void alto2_cpu_device::wrtram()
|
||||
{
|
||||
UINT32 bank = GET_CRAM_BANKSEL(m_cram_addr);
|
||||
UINT32 wordaddr = GET_CRAM_WORDADDR(m_cram_addr);
|
||||
UINT32 value = ((m_m << 16) | m_alu) ^ ALTO2_UCODE_INVERTED;
|
||||
|
||||
UINT32 addr = bank * ALTO2_UCODE_PAGE_SIZE + wordaddr; // write RAM 0,1,2
|
||||
LOG((LOG_CPU,0," wrtram: RAM%d [%04o] upper:%06o lower:%06o", bank, wordaddr, m_m, m_alu));
|
||||
|
||||
#if DEBUG_WRTRAM
|
||||
char buff[128];
|
||||
UINT8 oprom[4];
|
||||
oprom[0] = m_m / 256;
|
||||
oprom[1] = m_m % 256;
|
||||
oprom[2] = m_m / 256;
|
||||
oprom[3] = m_m % 256;
|
||||
disasm_disassemble(buff, addr, oprom, oprom, 0);
|
||||
printf("WR CRAM_BANKSEL=%d RAM%d [%04o] upper:%06o lower:%06o *** %s\n",
|
||||
GET_CRAM_BANKSEL(m_cram_addr), bank, wordaddr, m_m, m_alu, buff);
|
||||
#endif
|
||||
|
||||
m_wrtram_flag = false;
|
||||
if (ALTO2_UCODE_RAM_BASE + addr >= ALTO2_UCODE_SIZE) {
|
||||
LOG((LOG_CPU,0," invalid address %06o\n", addr));
|
||||
return;
|
||||
}
|
||||
LOG((LOG_CPU,0,"\n"));
|
||||
WR_CRAM(addr, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief bs_read_sreg early: drive bus by S register or M (MYL), if rsel is = 0
|
||||
*
|
||||
* Note: RSEL == 0 can't be read, because it is decoded as
|
||||
* access to the M register (MYL latch access, LREF' in the schematics)
|
||||
*/
|
||||
void alto2_cpu_device::bs_early_read_sreg()
|
||||
{
|
||||
UINT16 r;
|
||||
|
||||
if (m_d_rsel) {
|
||||
UINT8 bank = m_s_reg_bank[m_task];
|
||||
r = m_s[bank][m_d_rsel];
|
||||
LOG((LOG_RAM,2," <-S%02o; bus &= S[%o][%02o] (%#o)\n", m_d_rsel, bank, m_d_rsel, r));
|
||||
} else {
|
||||
r = m_m;
|
||||
LOG((LOG_RAM,2," <-S%02o; bus &= M (%#o)\n", m_d_rsel, r));
|
||||
}
|
||||
m_bus &= r;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief bs_load_sreg early: load S register puts garbage on the bus
|
||||
*/
|
||||
void alto2_cpu_device::bs_early_load_sreg()
|
||||
{
|
||||
int r = 0; /* ??? */
|
||||
LOG((LOG_RAM,2," S%02o<- BUS &= garbage (%#o)\n", m_d_rsel, r));
|
||||
m_bus &= r;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief bs_load_sreg late: load S register from M
|
||||
*/
|
||||
void alto2_cpu_device::bs_late_load_sreg()
|
||||
{
|
||||
UINT8 bank = m_s_reg_bank[m_task];
|
||||
m_s[bank][m_d_rsel] = m_m;
|
||||
LOG((LOG_RAM,2," S%02o<- S[%o][%02o] := %#o\n", m_d_rsel, bank, m_d_rsel, m_m));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief branch to ROM page
|
||||
*/
|
||||
void alto2_cpu_device::branch_ROM(const char *from, int page)
|
||||
{
|
||||
(void)from;
|
||||
m_next2 = (m_next2 & ALTO2_UCODE_PAGE_MASK) + page * ALTO2_UCODE_PAGE_SIZE;
|
||||
LOG((LOG_RAM,2," SWMODE: branch from %s to ROM%d (%#o)\n", from, page, m_next2));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief branch to RAM page
|
||||
*/
|
||||
void alto2_cpu_device::branch_RAM(const char *from, int page)
|
||||
{
|
||||
(void)from;
|
||||
m_next2 = (m_next2 & ALTO2_UCODE_PAGE_MASK) + ALTO2_UCODE_RAM_BASE + page * ALTO2_UCODE_PAGE_SIZE;
|
||||
LOG((LOG_RAM,2," SWMODE: branch from %s to RAM%d\n", from, page, m_next2));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief f1_swmode early: switch to micro program counter BUS[6-15] in other bank
|
||||
*
|
||||
* Note: Jumping to uninitialized CRAM
|
||||
*
|
||||
* When jumping to uninitialized RAM, which, because of the inverted bits of the
|
||||
* microcode words F1(0), F2(0) and LOADL, it is then read as F1=010 (SWMODE),
|
||||
* F2=010 (BUSODD) and LOADL=1, loading the M register (MYL latch), too.
|
||||
* This causes control to go back to the Emulator task at 0, because the
|
||||
* NEXT[0-9] of uninitialized RAM is 0.
|
||||
*
|
||||
*/
|
||||
void alto2_cpu_device::f1_late_swmode()
|
||||
{
|
||||
/* currently executing in what page? */
|
||||
UINT16 current = m_mpc / ALTO2_UCODE_PAGE_SIZE;
|
||||
|
||||
#if (ALTO2_UCODE_ROM_PAGES == 1 && ALTO2_UCODE_RAM_PAGES == 1)
|
||||
switch (current) {
|
||||
case 0:
|
||||
branch_RAM("ROM0", 0);
|
||||
break;
|
||||
case 1:
|
||||
branch_ROM("RAM0", 0);
|
||||
break;
|
||||
default:
|
||||
fatal(1, "Impossible current mpc %d\n", current);
|
||||
}
|
||||
#endif
|
||||
#if (ALTO2_UCODE_ROM_PAGES == 2 && ALTO2_UCODE_RAM_PAGES == 1)
|
||||
UINT16 next = X_RDBITS(m_next2,10,1,1);
|
||||
|
||||
switch (current) {
|
||||
case 0: /* ROM0 to RAM0 or ROM1 */
|
||||
switch (next) {
|
||||
case 0:
|
||||
branch_RAM("ROM0", 0);
|
||||
break;
|
||||
case 1:
|
||||
branch_ROM("ROM0", 1);
|
||||
break;
|
||||
default:
|
||||
fatal(1, "Impossible next %d\n", next);
|
||||
}
|
||||
break;
|
||||
case 1: /* ROM1 to ROM0 or RAM0 */
|
||||
switch (next) {
|
||||
case 0:
|
||||
branch_ROM("ROM1", 0);
|
||||
break;
|
||||
case 1:
|
||||
branch_RAM("ROM1", 0);
|
||||
break;
|
||||
default:
|
||||
fatal(1, "Impossible next %d\n", next);
|
||||
}
|
||||
break;
|
||||
case 2: /* RAM0 to ROM0 or ROM1 */
|
||||
switch (next) {
|
||||
case 0:
|
||||
branch_ROM("RAM0", 0);
|
||||
break;
|
||||
case 1:
|
||||
branch_ROM("RAM0", 1);
|
||||
break;
|
||||
default:
|
||||
fatal(1, "Impossible next %d\n", next);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fatal(1, "Impossible current mpc %d\n", current);
|
||||
}
|
||||
#endif
|
||||
#if (ALTO2_UCODE_ROM_PAGES == 1 && ALTO2_UCODE_RAM_PAGES == 3)
|
||||
UINT16 next = X_RDBITS(m_next2,10,1,2);
|
||||
|
||||
switch (current) {
|
||||
case 0: /* ROM0 to RAM0, RAM2, RAM1, RAM0 */
|
||||
switch (next) {
|
||||
case 0:
|
||||
branch_RAM("ROM0", 0);
|
||||
break;
|
||||
case 1:
|
||||
branch_RAM("ROM0", 2);
|
||||
break;
|
||||
case 2:
|
||||
branch_RAM("ROM0", 1);
|
||||
break;
|
||||
case 3:
|
||||
branch_RAM("ROM0", 0);
|
||||
break;
|
||||
default:
|
||||
fatal(1, "Impossible next %d\n", next);
|
||||
}
|
||||
break;
|
||||
case 1: /* RAM0 to ROM0, RAM2, RAM1, RAM1 */
|
||||
switch (next) {
|
||||
case 0:
|
||||
branch_ROM("RAM0", 0);
|
||||
break;
|
||||
case 1:
|
||||
branch_RAM("RAM0", 2);
|
||||
break;
|
||||
case 2:
|
||||
branch_RAM("RAM0", 1);
|
||||
break;
|
||||
case 3:
|
||||
branch_RAM("RAM0", 1);
|
||||
break;
|
||||
default:
|
||||
fatal(1, "Impossible next %d\n", next);
|
||||
}
|
||||
break;
|
||||
case 2: /* RAM1 to ROM0, RAM2, RAM0, RAM0 */
|
||||
switch (next) {
|
||||
case 0:
|
||||
branch_ROM("RAM1", 0);
|
||||
break;
|
||||
case 1:
|
||||
branch_RAM("RAM1", 2);
|
||||
break;
|
||||
case 2:
|
||||
branch_RAM("RAM1", 0);
|
||||
break;
|
||||
case 3:
|
||||
branch_RAM("RAM1", 0);
|
||||
break;
|
||||
default:
|
||||
fatal(1, "Impossible next %d\n", next);
|
||||
}
|
||||
break;
|
||||
case 3: /* RAM2 to ROM0, RAM1, RAM0, RAM0 */
|
||||
switch (next) {
|
||||
case 0:
|
||||
branch_ROM("RAM2", 0);
|
||||
break;
|
||||
case 1:
|
||||
branch_RAM("RAM2", 1);
|
||||
break;
|
||||
case 2:
|
||||
branch_RAM("RAM2", 0);
|
||||
break;
|
||||
case 3:
|
||||
branch_RAM("RAM2", 0);
|
||||
break;
|
||||
default:
|
||||
fatal(1, "Impossible next %d\n", next);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fatal(1, "Impossible current mpc %d\n", current);
|
||||
}
|
||||
#else
|
||||
fatal(1, "Impossible control ROM/RAM combination %d/%d\n", ALTO2_UCODE_ROM_PAGES, ALTO2_UCODE_RAM_PAGES);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief f1_wrtram late: start WRTRAM cycle
|
||||
*/
|
||||
void alto2_cpu_device::f1_late_wrtram()
|
||||
{
|
||||
m_wrtram_flag = true;
|
||||
LOG((LOG_RAM,2," WRTRAM\n"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief f1_rdram late: start RDRAM cycle
|
||||
*/
|
||||
void alto2_cpu_device::f1_late_rdram()
|
||||
{
|
||||
m_rdram_flag = true;
|
||||
LOG((LOG_RAM,2," RDRAM\n"));
|
||||
}
|
||||
|
||||
#if (ALTO2_UCODE_RAM_PAGES == 3)
|
||||
|
||||
/**
|
||||
* @brief f1_load_rmr late: load the reset mode register
|
||||
*
|
||||
* F1=013 corresponds to RMR<- in the emulator. In Altos with the 3K
|
||||
* RAM option, F1=013 performs RMR<- in all RAM-related tasks, including
|
||||
* the emulator.
|
||||
*/
|
||||
void alto2_cpu_device::f1_late_load_rmr()
|
||||
{
|
||||
LOG((LOG_RAM,2," RMR<-; BUS (%#o)\n", m_bus));
|
||||
m_reset_mode = m_bus;
|
||||
}
|
||||
#else // ALTO2_UCODE_RAM_PAGES != 3
|
||||
/**
|
||||
* @brief f1_load_srb late: load the S register bank from BUS[12-14]
|
||||
*/
|
||||
void alto2_cpu_device::f1_late_load_srb()
|
||||
{
|
||||
m_s_reg_bank[m_task] = X_RDBITS(m_bus,16,12,14) % ALTO2_SREG_BANKS;
|
||||
LOG((LOG_RAM,2," SRB<-; srb[%d] := %#o\n", m_task, m_s_reg_bank[m_task]));
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief RAM related task slots initialization
|
||||
*/
|
||||
void alto2_cpu_device::init_ram(int task)
|
||||
{
|
||||
m_ram_related[task] = true;
|
||||
|
||||
set_bs(task, bs_ram_read_slocation, &alto2_cpu_device::bs_early_read_sreg, 0);
|
||||
set_bs(task, bs_ram_load_slocation, &alto2_cpu_device::bs_early_load_sreg, &alto2_cpu_device::bs_late_load_sreg);
|
||||
|
||||
set_f1(task, f1_ram_swmode, 0, &alto2_cpu_device::f1_late_swmode);
|
||||
set_f1(task, f1_ram_wrtram, 0, &alto2_cpu_device::f1_late_wrtram);
|
||||
set_f1(task, f1_ram_rdram, 0, &alto2_cpu_device::f1_late_rdram);
|
||||
#if (ALTO2_UCODE_RAM_PAGES == 3)
|
||||
set_f1(task, f1_ram_load_rmr, 0, &alto2_cpu_device::f1_late_load_rmr);
|
||||
#else // ALTO2_UCODE_RAM_PAGES != 3
|
||||
set_f1(task, f1_ram_load_srb, 0, &alto2_cpu_device::f1_late_load_srb);
|
||||
#endif
|
||||
}
|
||||
|
||||
void alto2_cpu_device::exit_ram()
|
||||
{
|
||||
// nothing to do yet
|
||||
}
|
||||
|
||||
void alto2_cpu_device::reset_ram()
|
||||
{
|
||||
m_rdram_flag = false;
|
||||
m_wrtram_flag = false;
|
||||
m_m = 0;
|
||||
memset(m_s, 0, sizeof(m_s));
|
||||
}
|
80
src/emu/cpu/alto2/a2ram.h
Normal file
80
src/emu/cpu/alto2/a2ram.h
Normal file
@ -0,0 +1,80 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Xerox AltoII RAM related tasks
|
||||
*
|
||||
* Copyright Juergen Buchmueller <pullmoll@t-online.de>
|
||||
*
|
||||
* Licenses: MAME, GPLv2
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifdef ALTO2_DEFINE_CONSTANTS
|
||||
|
||||
#if (ALTO2_CRAM_CONFIG==1)
|
||||
#define ALTO2_UCODE_ROM_PAGES 1 //!< number of microcode ROM pages
|
||||
#define ALTO2_UCODE_RAM_PAGES 1 //!< number of microcode RAM pages
|
||||
#elif (ALTO2_CRAM_CONFIG==2)
|
||||
#define ALTO2_UCODE_ROM_PAGES 2 //!< number of microcode ROM pages
|
||||
#define ALTO2_UCODE_RAM_PAGES 1 //!< number of microcode RAM pages
|
||||
#elif (ALTO2_CRAM_CONFIG==3)
|
||||
#define ALTO2_UCODE_ROM_PAGES 1 //!< number of microcode ROM pages
|
||||
#define ALTO2_UCODE_RAM_PAGES 3 //!< number of microcode RAM pages
|
||||
#else
|
||||
#error "Undefined CROM/CRAM configuration"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief number of S register banks
|
||||
* This depends on the number of RAM pages
|
||||
* 8 pages in 3K CRAM configuration
|
||||
* 1 page in 1K CRAM configurations
|
||||
*/
|
||||
#if (ALTO2_UCODE_RAM_PAGES == 3)
|
||||
#define ALTO2_SREG_BANKS 8
|
||||
#else
|
||||
#define ALTO2_SREG_BANKS 1
|
||||
#endif
|
||||
|
||||
#define ALTO2_UCODE_PAGE_SIZE 02000 //!< number of words of microcode
|
||||
#define ALTO2_UCODE_PAGE_MASK (ALTO2_UCODE_PAGE_SIZE-1) //!< mask for microcode ROM/RAM address
|
||||
#define ALTO2_UCODE_SIZE ((ALTO2_UCODE_ROM_PAGES + ALTO2_UCODE_RAM_PAGES) * ALTO2_UCODE_PAGE_SIZE) //!< total number of words of microcode
|
||||
#define ALTO2_UCODE_RAM_BASE (ALTO2_UCODE_ROM_PAGES * ALTO2_UCODE_PAGE_SIZE) //!< base offset for the RAM page(s)
|
||||
|
||||
#else // ALTO2_DEFINE_CONSTANTS
|
||||
#ifndef _A2RAM_H_
|
||||
#define _A2RAM_H_
|
||||
//! BUS source for RAM related tasks
|
||||
enum {
|
||||
bs_ram_read_slocation= bs_task_3, //!< ram related: read S register
|
||||
bs_ram_load_slocation= bs_task_4 //!< ram related: load S register
|
||||
};
|
||||
|
||||
//!< F1 functions for RAM related tasks
|
||||
enum {
|
||||
f1_ram_swmode = f1_task_10, //!< f1 10: switch mode to CROM/CRAM in same page
|
||||
f1_ram_wrtram = f1_task_11, //!< f1 11: start WRTRAM cycle
|
||||
f1_ram_rdram = f1_task_12, //!< f1 12: start RDRAM cycle
|
||||
#if (ALTO2_UCODE_RAM_PAGES == 3)
|
||||
f1_ram_load_rmr = f1_task_13, //!< f1 13: load the reset mode register
|
||||
#else // ALTO2_UCODE_RAM_PAGES != 3
|
||||
f1_ram_load_srb = f1_task_13 //!< f1 14: load the S register bank from BUS[12-14]
|
||||
#endif
|
||||
};
|
||||
|
||||
void bs_early_read_sreg(); //!< bus source: drive bus by S register or M (MYL), if rsel is = 0
|
||||
void bs_early_load_sreg(); //!< bus source: load S register puts garbage on the bus
|
||||
void bs_late_load_sreg(); //!< bus source: load S register from M
|
||||
void branch_ROM(const char *from, int page); //!< branch to ROM page
|
||||
void branch_RAM(const char *from, int page); //!< branch to RAM page
|
||||
void f1_late_swmode(); //!< F1 func: switch to micro program counter BUS[6-15] in other bank
|
||||
void f1_late_wrtram(); //!< F1 func: start WRTRAM cycle
|
||||
void f1_late_rdram(); //!< F1 func: start RDRAM cycle
|
||||
#if (ALTO2_UCODE_RAM_PAGES == 3)
|
||||
void f1_late_load_rmr(); //!< F1 func: load the reset mode register
|
||||
#else // ALTO2_UCODE_RAM_PAGES != 3
|
||||
void f1_late_load_srb(); //!< F1 func: load the S register bank from BUS[12-14]
|
||||
#endif
|
||||
void init_ram(int task); //!< called by RAM related tasks
|
||||
void exit_ram(); //!< deinitialize the RAM related tasks
|
||||
void reset_ram(); //!< reset the RAM related tasks
|
||||
#endif // A2RAM_H
|
||||
#endif // ALTO2_DEFINE_CONSTANTS
|
198
src/emu/cpu/alto2/a2roms.c
Normal file
198
src/emu/cpu/alto2/a2roms.c
Normal file
@ -0,0 +1,198 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Xerox AltoII PROM loading and decoding
|
||||
*
|
||||
* Copyright Juergen Buchmueller <pullmoll@t-online.de>
|
||||
*
|
||||
* Licenses: MAME, GPLv2
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include "alto2cpu.h"
|
||||
#include "a2roms.h"
|
||||
|
||||
#define DEBUG_PROM_LOAD 0 //!< define to 1 to dump PROMs after loading
|
||||
|
||||
/**
|
||||
* @brief return number of 1 bits in a 32 bit value
|
||||
*
|
||||
* 32-bit recursive reduction using SWAR,
|
||||
* but first step is mapping 2-bit values
|
||||
* into sum of 2 1-bit values in sneaky way.
|
||||
*/
|
||||
static UINT32 ones_u32(UINT32 val)
|
||||
{
|
||||
val -= ((val >> 1) & 0x55555555);
|
||||
val = (((val >> 2) & 0x33333333) + (val & 0x33333333));
|
||||
val = (((val >> 4) + val) & 0x0f0f0f0f);
|
||||
val += (val >> 8);
|
||||
val += (val >> 16);
|
||||
return (val & 0x0000003f);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief return the log2 of an integer value
|
||||
*/
|
||||
static UINT32 log2_u32(UINT32 val)
|
||||
{
|
||||
val |= (val >> 1);
|
||||
val |= (val >> 2);
|
||||
val |= (val >> 4);
|
||||
val |= (val >> 8);
|
||||
val |= (val >> 16);
|
||||
return ones_u32(val >> 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief map a number of data or address lines using a lookup table
|
||||
*
|
||||
* @param map pointer to an array of values, or NULL for default
|
||||
* @param lines number of data or address lines
|
||||
* @param val value to map
|
||||
* @result returns the remapped value, or just val, if map was NULL
|
||||
*/
|
||||
static UINT32 map_lines(const UINT8 *map, int lines, UINT32 val)
|
||||
{
|
||||
if (NULL == map)
|
||||
return val;
|
||||
|
||||
UINT32 res = 0;
|
||||
for (int i = 0; i < lines; i++)
|
||||
if (val & (1 << i))
|
||||
res |= 1 << map[i];
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief write to a ROM base + address of type 'type', ANDing with and, ORing with or
|
||||
*
|
||||
* @param base ROM base address in memory
|
||||
* @param type one of 1 for UINT8, 2 for UINT16, 4 for UINT32
|
||||
* @param addr address offset into base
|
||||
* @param dand value to AND to contents before XORing
|
||||
* @param dxor value to XOR before writing back
|
||||
*/
|
||||
static void write_type_and_xor(void *base, int type, UINT32 addr, UINT32 dand, UINT32 dxor)
|
||||
{
|
||||
switch (type) {
|
||||
case sizeof(UINT8):
|
||||
{
|
||||
UINT8 *base8 = reinterpret_cast<UINT8 *>(base);
|
||||
base8[addr] = (base8[addr] & dand) ^ dxor;
|
||||
}
|
||||
break;
|
||||
case sizeof(UINT16):
|
||||
{
|
||||
UINT16 *base16 = reinterpret_cast<UINT16 *>(base);
|
||||
base16[addr] = (base16[addr] & dand) ^ dxor;
|
||||
}
|
||||
break;
|
||||
case sizeof(UINT32):
|
||||
{
|
||||
UINT32 *base32 = reinterpret_cast<UINT32 *>(base);
|
||||
base32[addr] = (base32[addr] & dand) ^ dxor;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fatalerror("write_type_and_xor() invalid type size (%d) in ROM definitions\n", type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief load a PROM from a (list of) source region(s) shifting, swapping and inverting address and data bits
|
||||
* @param prom PROM loading definition
|
||||
* @param src source ROM region where to load data from
|
||||
* @param pages number of pages of definitions
|
||||
* @param segments number of segments in one page of the result
|
||||
* @return pointer to the newly allocated memory filled with source bits
|
||||
*/
|
||||
UINT8* prom_load(running_machine& machine, const prom_load_t* prom, const UINT8* src, int pages, int segments)
|
||||
{
|
||||
void* array = 0;
|
||||
size_t type = prom->type;
|
||||
size_t size = prom->size;
|
||||
#if DEBUG_PROM_LOAD
|
||||
UINT8 width = prom->width;
|
||||
#endif
|
||||
|
||||
switch (type) {
|
||||
case sizeof(UINT8):
|
||||
array = auto_alloc_array(machine, UINT8, pages * size);
|
||||
break;
|
||||
case sizeof(UINT16):
|
||||
array = auto_alloc_array(machine, UINT16, pages * size);
|
||||
break;
|
||||
case sizeof(UINT32):
|
||||
array = auto_alloc_array(machine, UINT32, pages * size);
|
||||
break;
|
||||
}
|
||||
|
||||
UINT8* dst = reinterpret_cast<UINT8*>(array);
|
||||
for (int page = 0; page < pages; page++)
|
||||
{
|
||||
for (int segment = 0; segment < segments; segment++, prom++)
|
||||
{
|
||||
for (UINT32 src_addr = 0; src_addr < prom->size; src_addr++)
|
||||
{
|
||||
// map destination address lines
|
||||
UINT32 dst_addr = map_lines(prom->amap, log2_u32(prom->size) + 1, src_addr);
|
||||
// fetch data bits
|
||||
UINT32 data = src[src_addr ^ prom->axor] ^ prom->dxor;
|
||||
// mask width bits
|
||||
data = data & ((1 << prom->width) - 1);
|
||||
// map destination data lines
|
||||
data = map_lines(prom->dmap, prom->width, data);
|
||||
// shift to destination position
|
||||
data = data << prom->shift;
|
||||
// and destination width dand then xor data
|
||||
write_type_and_xor(dst, prom->type, dst_addr, prom->dand, data);
|
||||
}
|
||||
src += prom->size;
|
||||
}
|
||||
dst += prom->type * prom->size;
|
||||
}
|
||||
|
||||
#if DEBUG_PROM_LOAD
|
||||
switch (type) {
|
||||
case sizeof(UINT8):
|
||||
{
|
||||
UINT8* data = reinterpret_cast<UINT8*>(array);
|
||||
for (int addr = 0; addr < pages*size; addr++) {
|
||||
if (0 == (addr % 16))
|
||||
printf("%04x:", addr);
|
||||
if (width <= 4)
|
||||
printf(" %x", data[addr]);
|
||||
else
|
||||
printf(" %02x", data[addr]);
|
||||
if (15 == (addr % 16))
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case sizeof(UINT16):
|
||||
{
|
||||
UINT16* data = reinterpret_cast<UINT16*>(array);
|
||||
for (int addr = 0; addr < pages*size; addr++) {
|
||||
if (0 == (addr % 8))
|
||||
printf("%04x:", addr);
|
||||
printf(" %04x", data[addr]);
|
||||
if (7 == (addr % 8))
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case sizeof(UINT32):
|
||||
{
|
||||
UINT32* data = reinterpret_cast<UINT32*>(array);
|
||||
for (int addr = 0; addr < pages*size; addr++) {
|
||||
if (0 == (addr % 4))
|
||||
printf("%04x:", addr);
|
||||
printf(" %08x", data[addr]);
|
||||
if (3 == (addr % 4))
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
return reinterpret_cast<UINT8 *>(array);
|
||||
}
|
45
src/emu/cpu/alto2/a2roms.h
Normal file
45
src/emu/cpu/alto2/a2roms.h
Normal file
@ -0,0 +1,45 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Xerox AltoII RAM PROM loading and decoding
|
||||
*
|
||||
* Copyright Juergen Buchmueller <pullmoll@t-online.de>
|
||||
*
|
||||
* Licenses: MAME, GPLv2
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifndef _CPU_A2ROMS_H_
|
||||
#define _CPU_A2ROMS_H_
|
||||
|
||||
#include "emu.h"
|
||||
|
||||
/**
|
||||
* @brief structure to define a ROM's or PROM's loading options
|
||||
*/
|
||||
typedef struct {
|
||||
const char *name; //!< default filename of the ROM image
|
||||
const char *altname; //!< alternate filename of the ROM image
|
||||
const char *crc32; //!< CRC32 hash of the file
|
||||
const char *sha1; //!< SHA1 hash of the file
|
||||
size_t size; //!< size of the file, and elements in destination memory
|
||||
const UINT8 amap[16]; //!< address bit mapping
|
||||
UINT32 axor; //!< address XOR mask (applied to source address)
|
||||
UINT32 dxor; //!< data XOR mask (applied before shifting and mapping)
|
||||
UINT8 width; //!< width in bits
|
||||
UINT8 shift; //!< left shift in bits
|
||||
const UINT8 dmap[16]; //!< data bit mapping
|
||||
UINT32 dand; //!< ANDing destination with this value, before XORing the data
|
||||
size_t type; //!< type of the destination, i.e. sizeof(type)
|
||||
} prom_load_t;
|
||||
|
||||
#define ZERO 0
|
||||
#define KEEP ~0
|
||||
|
||||
#define AMAP_DEFAULT {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}
|
||||
#define AMAP_CONST_PROM {3,2,1,4,5,6,7,0,}
|
||||
#define AMAP_REVERSE_0_7 {7,6,5,4,3,2,1,0,}
|
||||
|
||||
#define DMAP_DEFAULT {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}
|
||||
#define DMAP_REVERSE_0_3 {3,2,1,0,}
|
||||
|
||||
extern UINT8* prom_load(running_machine& machine, const prom_load_t* prom, const UINT8* src, int pages = 1, int segments = 1);
|
||||
#endif // _CPU_A2ROMS_H_
|
2814
src/emu/cpu/alto2/alto2cpu.c
Normal file
2814
src/emu/cpu/alto2/alto2cpu.c
Normal file
File diff suppressed because it is too large
Load Diff
948
src/emu/cpu/alto2/alto2cpu.h
Normal file
948
src/emu/cpu/alto2/alto2cpu.h
Normal file
@ -0,0 +1,948 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Xerox AltoII CPU core interface
|
||||
*
|
||||
* Copyright Juergen Buchmueller <pullmoll@t-online.de>
|
||||
*
|
||||
* Licenses: MAME, GPLv2
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifndef _CPU_ALTO2_H_
|
||||
#define _CPU_ALTO2_H
|
||||
|
||||
#define ALTO2_TAG "alto2"
|
||||
|
||||
#include "emu.h"
|
||||
#include "debugger.h"
|
||||
#include "machine/diablo_hd.h"
|
||||
|
||||
/**
|
||||
* \brief AltoII register names
|
||||
*/
|
||||
enum {
|
||||
// micro code task, micro program counter, next and next2
|
||||
A2_TASK, A2_MPC, A2_NEXT, A2_NEXT2,
|
||||
// BUS, ALU, temp, latch, memory latch and carry flags
|
||||
A2_BUS, A2_T, A2_ALU, A2_ALUC0, A2_L, A2_SHIFTER, A2_LALUC0, A2_M,
|
||||
A2_R, // 32 R registers
|
||||
A2_AC3 = A2_R, A2_AC2, A2_AC1, A2_AC0, A2_R04, A2_R05, A2_PC, A2_R07,
|
||||
A2_R10, A2_R11, A2_R12, A2_R13, A2_R14, A2_R15, A2_R16, A2_R17,
|
||||
A2_R20, A2_R21, A2_R22, A2_R23, A2_R24, A2_R25, A2_R26, A2_R27,
|
||||
A2_R30, A2_R31, A2_R32, A2_R33, A2_R34, A2_R35, A2_R36, A2_R37,
|
||||
A2_S, // 32 S registers
|
||||
A2_S00 = A2_S, A2_S01, A2_S02, A2_S03, A2_S04, A2_S05, A2_S06, A2_S07,
|
||||
A2_S10, A2_S11, A2_S12, A2_S13, A2_S14, A2_S15, A2_S16, A2_S17,
|
||||
A2_S20, A2_S21, A2_S22, A2_S23, A2_S24, A2_S25, A2_S26, A2_S27,
|
||||
A2_S30, A2_S31, A2_S32, A2_S33, A2_S34, A2_S35, A2_S36, A2_S37,
|
||||
// DISK controller registers
|
||||
A2_DRIVE, A2_KADDR, A2_KADR, A2_KSTAT, A2_KCOM, A2_KRECNO,
|
||||
A2_SHIFTIN, A2_SHIFTOUT, A2_DATAIN, A2_DATAOUT, A2_KRWC,
|
||||
A2_KFER, A2_WDTSKENA, A2_WDINIT0, A2_WDINIT, A2_STROBE,
|
||||
A2_BITCLK, A2_DATIN, A2_BITCNT, A2_CARRY, A2_SECLATE,
|
||||
A2_SEEKOK, A2_OKTORUN, A2_READY
|
||||
};
|
||||
|
||||
#ifndef ALTO2_DEBUG
|
||||
#define ALTO2_DEBUG 1 //!< define to 1 to enable logerror() output
|
||||
#endif
|
||||
|
||||
#ifndef ALTO2_CRAM_CONFIG
|
||||
#define ALTO2_CRAM_CONFIG 2 //!< use default CROM/CRAM configuration 2
|
||||
#endif
|
||||
|
||||
#define ALTO2_FAKE_STATUS_H 12 //!< number of extra scanlines to display some status info
|
||||
|
||||
#define USE_PRIO_F9318 0 //!< define to 1 to use the F9318 priority encoder code
|
||||
#define USE_ALU_74181 1 //!< define to 1 to use the SN74181 ALU code
|
||||
#define USE_BITCLK_TIMER 0 //!< define to 1 to use a very high rate timer for the disk bit clock
|
||||
#define USE_HAMMING_CHECK 1 //!< define to 1 to use the Hamming code and Parity check in a2mem
|
||||
|
||||
#define ALTO2_TASKS 16 //!< 16 task slots
|
||||
#define ALTO2_REGS 32 //!< 32 16-bit words in the R register file
|
||||
#define ALTO2_ALUF 16 //!< 16 ALU functions (74181)
|
||||
#define ALTO2_BUSSRC 8 //!< 8 bus sources
|
||||
#define ALTO2_F1MAX 16 //!< 16 F1 functions
|
||||
#define ALTO2_F2MAX 16 //!< 16 F2 functions
|
||||
#define ALTO2_UCYCLE 169542 //!< time in pico seconds for a CPU micro cycle: 29.4912MHz/5 -> 5.898240Hz ~= 169.542ns/clock
|
||||
|
||||
#define ALTO2_CONST_SIZE 256 //!< number words in the constant ROM
|
||||
|
||||
//! inverted bits in the micro instruction 32 bit word
|
||||
#define ALTO2_UCODE_INVERTED ((1 << 10) | (1 << 15) | (1 << 19))
|
||||
|
||||
/********************************************************************************
|
||||
* Bit field primitives
|
||||
* These are some macros to make it easier to access variable by the bit-
|
||||
* reversed notation that the Xerox Alto documents use all over the place.
|
||||
* Bit number 0 is the most significant there,
|
||||
* and bit number (width - 1) is the least significant.
|
||||
* The X_ is for Xerox and to avoid collisions with MAME generic macros.
|
||||
********************************************************************************/
|
||||
|
||||
//! get the left shift required to access bit %to in a word of %width bits
|
||||
#define X_BITSHIFT(width,to) ((width) - 1 - (to))
|
||||
|
||||
//! build a least significant bit mask for bits %from to %to (inclusive)
|
||||
#define X_BITMASK(from,to) ((1ul << ((to) + 1 - (from))) - 1)
|
||||
|
||||
//! get a single bit number %bit value from %reg, a word of %width bits
|
||||
#define X_BIT(reg,width,bit) (((reg) >> X_BITSHIFT(width,bit)) & 1)
|
||||
|
||||
//! get a bit field from %reg, a word of %width bits, starting at bit %from until bit %to
|
||||
#define X_RDBITS(reg,width,from,to) (((reg) >> X_BITSHIFT(width,to)) & X_BITMASK(from,to))
|
||||
|
||||
//! put a value %val into %reg, a word of %width bits, starting at bit %from until bit %to
|
||||
#define X_WRBITS(reg,width,from,to,val) do { \
|
||||
UINT32 mask = X_BITMASK(from,to) << X_BITSHIFT(width,to); \
|
||||
reg = ((reg) & ~mask) | (((val) << X_BITSHIFT(width,to)) & mask); \
|
||||
} while (0)
|
||||
|
||||
#if ALTO2_DEBUG
|
||||
enum LOG_TYPE_ENUM {
|
||||
LOG_0,
|
||||
LOG_CPU = (1 << 0),
|
||||
LOG_EMU = (1 << 1),
|
||||
LOG_T01 = (1 << 2),
|
||||
LOG_T02 = (1 << 3),
|
||||
LOG_T03 = (1 << 4),
|
||||
LOG_KSEC = (1 << 5),
|
||||
LOG_T05 = (1 << 6),
|
||||
LOG_T06 = (1 << 7),
|
||||
LOG_ETH = (1 << 8),
|
||||
LOG_MRT = (1 << 9),
|
||||
LOG_DWT = (1 << 10),
|
||||
LOG_CURT = (1 << 11),
|
||||
LOG_DHT = (1 << 12),
|
||||
LOG_DVT = (1 << 13),
|
||||
LOG_PART = (1 << 14),
|
||||
LOG_KWD = (1 << 15),
|
||||
LOG_T17 = (1 << 16),
|
||||
LOG_MEM = (1 << 17),
|
||||
LOG_RAM = (1 << 18),
|
||||
LOG_DRIVE = (1 << 19),
|
||||
LOG_DISK = (1 << 20),
|
||||
LOG_DISPL = (1 << 21),
|
||||
LOG_MOUSE = (1 << 22),
|
||||
LOG_HW = (1 << 23),
|
||||
LOG_KBD = (1 << 24),
|
||||
LOG_ALL = ((1 << 25) - 1)
|
||||
};
|
||||
extern int m_log_types;
|
||||
extern int m_log_level;
|
||||
extern bool m_log_newline;
|
||||
void logprintf(int type, int level, const char* format, ...);
|
||||
# define LOG(x) logprintf x
|
||||
#else
|
||||
# define LOG(x)
|
||||
#endif
|
||||
|
||||
//*******************************************
|
||||
// define constants from the sub-devices
|
||||
//*******************************************
|
||||
#define ALTO2_DEFINE_CONSTANTS 1
|
||||
#include "a2jkff.h"
|
||||
#include "a2ram.h"
|
||||
#include "a2hw.h"
|
||||
#include "a2kbd.h"
|
||||
#include "a2mouse.h"
|
||||
#include "a2disk.h"
|
||||
#include "a2disp.h"
|
||||
#include "a2mem.h"
|
||||
#include "a2emu.h"
|
||||
#include "a2ksec.h"
|
||||
#include "a2ether.h"
|
||||
#include "a2mrt.h"
|
||||
#include "a2dwt.h"
|
||||
#include "a2curt.h"
|
||||
#include "a2dht.h"
|
||||
#include "a2dvt.h"
|
||||
#include "a2part.h"
|
||||
#include "a2dwt.h"
|
||||
#include "a2kwd.h"
|
||||
#undef ALTO2_DEFINE_CONSTANTS
|
||||
|
||||
class alto2_cpu_device : public cpu_device
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
alto2_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
~alto2_cpu_device();
|
||||
|
||||
//! driver interface to set diablo_hd_device
|
||||
void set_diablo(int unit, diablo_hd_device* ptr);
|
||||
|
||||
//! call in for the next sector callback
|
||||
void next_sector(int unit);
|
||||
|
||||
//! update the screen bitmap
|
||||
UINT32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
|
||||
//! screen VBLANK handler
|
||||
void screen_eof(screen_device &screen, bool state);
|
||||
|
||||
DECLARE_ADDRESS_MAP( ucode_map, 32 );
|
||||
DECLARE_ADDRESS_MAP( const_map, 16 );
|
||||
DECLARE_ADDRESS_MAP( iomem_map, 16 );
|
||||
|
||||
//! register a mouse motion in x direction
|
||||
DECLARE_INPUT_CHANGED_MEMBER( mouse_motion_x );
|
||||
//! register a mouse motion in y direction
|
||||
DECLARE_INPUT_CHANGED_MEMBER( mouse_motion_y );
|
||||
//! register a mouse button change
|
||||
DECLARE_INPUT_CHANGED_MEMBER( mouse_button_0 );
|
||||
DECLARE_INPUT_CHANGED_MEMBER( mouse_button_1 );
|
||||
DECLARE_INPUT_CHANGED_MEMBER( mouse_button_2 );
|
||||
|
||||
protected:
|
||||
//! device-level override for start
|
||||
virtual void device_start();
|
||||
//! device-level override for reset
|
||||
virtual void device_reset();
|
||||
|
||||
//! device-level override for post reset
|
||||
void interface_post_reset();
|
||||
|
||||
//! device_execute_interface overrides
|
||||
virtual UINT32 execute_min_cycles() const { return 1; }
|
||||
virtual UINT32 execute_max_cycles() const { return 1; }
|
||||
virtual UINT32 execute_input_lines() const { return 1; }
|
||||
virtual void execute_run();
|
||||
virtual void execute_set_input(int inputnum, int state);
|
||||
|
||||
//! device_memory_interface overrides
|
||||
virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const;
|
||||
|
||||
//! device (P)ROMs
|
||||
virtual const rom_entry *device_rom_region() const;
|
||||
//! device_state_interface overrides
|
||||
void state_string_export(const device_state_entry &entry, astring &string);
|
||||
|
||||
//! device_disasm_interface overrides
|
||||
virtual UINT32 disasm_min_opcode_bytes() const { return 4; }
|
||||
virtual UINT32 disasm_max_opcode_bytes() const { return 4; }
|
||||
virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options);
|
||||
|
||||
private:
|
||||
|
||||
void fatal(int level, const char *format, ...);
|
||||
|
||||
address_space_config m_ucode_config;
|
||||
address_space_config m_const_config;
|
||||
address_space_config m_iomem_config;
|
||||
|
||||
address_space* m_iomem;
|
||||
|
||||
UINT8* m_ucode_crom;
|
||||
UINT8* m_ucode_cram;
|
||||
UINT8* m_const_data;
|
||||
|
||||
//! read microcode CROM
|
||||
DECLARE_READ32_MEMBER ( crom_r );
|
||||
|
||||
//! read microcode CRAM
|
||||
DECLARE_READ32_MEMBER ( cram_r );
|
||||
|
||||
//! write microcode CRAM
|
||||
DECLARE_WRITE32_MEMBER( cram_w );
|
||||
|
||||
//! read constants PROM
|
||||
DECLARE_READ16_MEMBER ( const_r );
|
||||
|
||||
//! read i/o space RAM
|
||||
DECLARE_READ16_MEMBER ( ioram_r );
|
||||
|
||||
//!< write i/o space RAM
|
||||
DECLARE_WRITE16_MEMBER( ioram_w );
|
||||
|
||||
//!< read memory mapped i/o
|
||||
DECLARE_READ16_MEMBER ( mmio_r );
|
||||
|
||||
//!< write memory mapped i/o
|
||||
DECLARE_WRITE16_MEMBER( mmio_w );
|
||||
|
||||
int m_icount;
|
||||
|
||||
typedef void (alto2_cpu_device::*a2func)();
|
||||
|
||||
//! task numbers
|
||||
enum {
|
||||
task_emu, //!< emulator task
|
||||
task_1, //!< unused
|
||||
task_2, //!< unused
|
||||
task_3, //!< unused
|
||||
task_ksec, //!< disk sector task
|
||||
task_5, //!< unused
|
||||
task_6, //!< unused
|
||||
task_ether, //!< ethernet task
|
||||
task_mrt, //!< memory refresh task
|
||||
task_dwt, //!< display word task
|
||||
task_curt, //!< cursor task
|
||||
task_dht, //!< display horizontal task
|
||||
task_dvt, //!< display vertical task
|
||||
task_part, //!< parity task
|
||||
task_kwd, //!< disk word task
|
||||
task_17 //!< unused task slot 017
|
||||
};
|
||||
|
||||
//! register select values accessing R (Note: register numbers are octal)
|
||||
enum {
|
||||
rsel_ac3, //!< AC3 used by emulator as accu 3. Also used by Mesa emulator to keep bytecode to execute after breakpoint
|
||||
rsel_ac2, //!< AC2 used by emulator as accu 2. Also used by Mesa emulator as x register for xfer
|
||||
rsel_ac1, //!< AC1 used by emulator as accu 1. Also used by Mesa emulator as r-temporary for return indices and values
|
||||
rsel_ac0, //!< AC0 used by emulator as accu 0. Also used by Mesa emulator as new field bits for WF and friends
|
||||
rsel_r04, //!< NWW state of the interrupt system
|
||||
rsel_r05, //!< SAD. Also used by Mesa emulator as scratch R-register for counting
|
||||
rsel_pc, //!< PC used by emulator as program counter
|
||||
rsel_r07, //!< XREG. Also used by Mesa emulator as task hole, i.e. pigeonhole for saving things across tasks.
|
||||
rsel_r10, //!< XH. Also used by Mesa emulator as instruction byte register
|
||||
rsel_r11, //!< CLOCKTEMP - used in the MRT
|
||||
rsel_r12, //!< ECNTR remaining words in buffer - ETHERNET
|
||||
rsel_r13, //!< EPNTR points BEFORE next word in buffer - ETHERNET
|
||||
rsel_r14,
|
||||
rsel_r15, //!< MPC. Used by the Mesa emulator as program counter
|
||||
rsel_r16, //!< STKP. Used by the Mesa emulator as stack pointer [0-10] 0 empty, 10 full
|
||||
rsel_r17, //!< XTSreg. Used by the Mesa emulator to xfer trap state
|
||||
rsel_r20, //!< CURX. Holds cursor X; used by the cursor task
|
||||
rsel_r21, //!< CURDATA. Holds the cursor data; used by the cursor task
|
||||
rsel_r22, //!< CBA. Holds the address of the currently active DCB+1
|
||||
rsel_r23, //!< AECL. Holds the address of the end of the current scanline's bitmap
|
||||
rsel_r24, //!< SLC. Holds the number of scanlines remaining in currently active DCB
|
||||
rsel_r25, //!< MTEMP. Holds the temporary cell
|
||||
rsel_r26, //!< HTAB. Holds the number of tab words remaining on current scanline
|
||||
rsel_r27, //!< YPOS
|
||||
rsel_r30, //!< DWA. Holds the address of the bit map doubleword currently being fetched for transmission to the hardware buffer.
|
||||
rsel_r31, //!< KWDCT. Used by the disk tasks as word counter
|
||||
rsel_r32, //!< CKSUMR. Used by the disk tasks as checksum register (and *amble counter?)
|
||||
rsel_r33, //!< KNMAR. Used by the disk tasks as transfer memory address register
|
||||
rsel_r34, //!< DCBR. Used by the disk tasks to keep the current device control block
|
||||
rsel_r35, //!< TEMP. Used by the Mesa emulator, and also by BITBLT
|
||||
rsel_r36, //!< TEMP2. Used by the Mesa emulator, and also by BITBLT
|
||||
rsel_r37 //!< CLOCKREG. Low order bits of the real time clock
|
||||
};
|
||||
|
||||
//! ALU function numbers
|
||||
enum {
|
||||
/**
|
||||
* \brief 00: ALU <- BUS
|
||||
* PROM data for S3-0,M,C,T: 1111/1/0/0
|
||||
* function F=A
|
||||
* T source is ALU
|
||||
*/
|
||||
aluf_bus__alut,
|
||||
/**
|
||||
* \brief 01: ALU <- T
|
||||
* PROM data for S3-0,M,C,T: 1010/1/0/0
|
||||
* function F=B
|
||||
* T source is BUS
|
||||
*/
|
||||
aluf_treg,
|
||||
/**
|
||||
* \brief 02: ALU <- BUS | T
|
||||
* PROM data for S3-0,M,C,T: 1110/1/0/1
|
||||
* function F=A|B
|
||||
* T source is ALU
|
||||
*/
|
||||
aluf_bus_or_t__alut,
|
||||
/**
|
||||
* \brief 03: ALU <- BUS & T
|
||||
* PROM data for S3-0,M,C,T: 1011/1/0/0
|
||||
* function F=A&B
|
||||
* T source is BUS
|
||||
*/
|
||||
aluf_bus_and_t,
|
||||
/**
|
||||
* \brief 04: ALU <- BUS ^ T
|
||||
* PROM data for S3-0,M,C,T: 0110/1/0/0
|
||||
* function F=A^B
|
||||
* T source is BUS
|
||||
*/
|
||||
aluf_bus_xor_t,
|
||||
/**
|
||||
* \brief 05: ALU <- BUS + 1
|
||||
* PROM data for S3-0,M,C,T: 0000/0/0/1
|
||||
* function F=A+1
|
||||
* T source is ALU
|
||||
*/
|
||||
aluf_bus_plus_1__alut,
|
||||
/**
|
||||
* \brief 06: ALU <- BUS - 1
|
||||
* PROM data for S3-0,M,C,T: 1111/0/1/1
|
||||
* function F=A-1
|
||||
* T source is ALU
|
||||
*/
|
||||
aluf_bus_minus_1__alut,
|
||||
/**
|
||||
* \brief 07: ALU <- BUS + T
|
||||
* PROM data for S3-0,M,C,T: 1001/0/1/0
|
||||
* function F=A+B
|
||||
* T source is BUS
|
||||
*/
|
||||
aluf_bus_plus_t,
|
||||
/**
|
||||
* \brief 10: ALU <- BUS - T
|
||||
* PROM data for S3-0,M,C,T: 0110/0/0/0
|
||||
* function F=A-B
|
||||
* T source is BUS
|
||||
*/
|
||||
aluf_bus_minus_t,
|
||||
/**
|
||||
* \brief 11: ALU <- BUS - T - 1
|
||||
* PROM data for S3-0,M,C,T: 0110/0/1/0
|
||||
* function F=A-B-1
|
||||
* T source is BUS
|
||||
*/
|
||||
aluf_bus_minus_t_minus_1,
|
||||
/**
|
||||
* \brief 12: ALU <- BUS + T + 1
|
||||
* PROM data for S3-0,M,C: 1001/0/0
|
||||
* function F=A+B+1
|
||||
* T source is ALU
|
||||
*/
|
||||
aluf_bus_plus_t_plus_1__alut,
|
||||
/**
|
||||
* \brief 13: ALU <- BUS + SKIP
|
||||
* PROM data for S3-0,M,C,T: 0000/0/SKIP/1
|
||||
* function F=A (SKIP=1) or F=A+1 (SKIP=0)
|
||||
* T source is ALU
|
||||
*/
|
||||
aluf_bus_plus_skip__alut,
|
||||
/**
|
||||
* \brief 14: ALU <- BUS & T
|
||||
* PROM data for S3-0,M,C,T: 1011/1/0/1
|
||||
* function F=A&B
|
||||
* T source is ALU
|
||||
*/
|
||||
aluf_bus_and_t__alut,
|
||||
/**
|
||||
* \brief 15: ALU <- BUS & ~T
|
||||
* PROM data for S3-0,M,C,T: 0111/1/0/0
|
||||
* function F=A&~B
|
||||
* T source is BUS
|
||||
*/
|
||||
aluf_bus_and_not_t,
|
||||
/**
|
||||
* \brief 16: ALU <- BUS
|
||||
* PROM data for S3-0,M,C,T: 1111/1/0/1
|
||||
* function F=A
|
||||
* T source is ALU
|
||||
*/
|
||||
aluf_undef_16,
|
||||
/**
|
||||
* \brief 17: ALU <- BUS
|
||||
* PROM data for S3-0,M,C,T: 1111/1/0/1
|
||||
* function F=A
|
||||
* T source is ALU
|
||||
*/
|
||||
aluf_undef_17
|
||||
};
|
||||
|
||||
//! BUS source selection numbers
|
||||
enum {
|
||||
bs_read_r, //!< BUS source is R register
|
||||
bs_load_r, //!< load R register from BUS
|
||||
bs_no_source, //!< BUS is open (0177777)
|
||||
bs_task_3, //!< BUS source is task specific
|
||||
bs_task_4, //!< BUS source is task specific
|
||||
bs_read_md, //!< BUS source is memory data
|
||||
bs_mouse, //!< BUS source is mouse data
|
||||
bs_disp //!< BUS source displacement (emulator task)
|
||||
};
|
||||
|
||||
//! Function 1 numbers
|
||||
enum {
|
||||
f1_nop, //!< f1 00 no operation
|
||||
f1_load_mar, //!< f1 01 load memory address register
|
||||
f1_task, //!< f1 02 task switch
|
||||
f1_block, //!< f1 03 task block
|
||||
f1_l_lsh_1, //!< f1 04 left shift L once
|
||||
f1_l_rsh_1, //!< f1 05 right shift L once
|
||||
f1_l_lcy_8, //!< f1 06 cycle L 8 times
|
||||
f1_const, //!< f1 07 constant from PROM
|
||||
|
||||
f1_task_10, //!< f1 10 task specific
|
||||
f1_task_11, //!< f1 11 task specific
|
||||
f1_task_12, //!< f1 12 task specific
|
||||
f1_task_13, //!< f1 13 task specific
|
||||
f1_task_14, //!< f1 14 task specific
|
||||
f1_task_15, //!< f1 15 task specific
|
||||
f1_task_16, //!< f1 16 task specific
|
||||
f1_task_17 //!< f1 17 task specific
|
||||
};
|
||||
|
||||
//! Function 2 numbers
|
||||
enum {
|
||||
f2_nop, //!< f2 00 no operation
|
||||
f2_bus_eq_zero, //!< f2 01 branch on bus equals 0
|
||||
f2_shifter_lt_zero, //!< f2 02 branch on shifter less than 0
|
||||
f2_shifter_eq_zero, //!< f2 03 branch on shifter equals 0
|
||||
f2_bus, //!< f2 04 branch on BUS[6-15]
|
||||
f2_alucy, //!< f2 05 branch on (latched) ALU carry
|
||||
f2_load_md, //!< f2 06 load memory data
|
||||
f2_const, //!< f2 07 constant from PROM
|
||||
|
||||
f2_task_10, //!< f2 10 task specific
|
||||
f2_task_11, //!< f2 11 task specific
|
||||
f2_task_12, //!< f2 12 task specific
|
||||
f2_task_13, //!< f2 13 task specific
|
||||
f2_task_14, //!< f2 14 task specific
|
||||
f2_task_15, //!< f2 15 task specific
|
||||
f2_task_16, //!< f2 16 task specific
|
||||
f2_task_17 //!< f2 17 task specific
|
||||
};
|
||||
|
||||
//! enumeration of the micro code word bits
|
||||
//! Note: The Alto documents enumerate bits from left (MSB = 0) to right (LSB = 31)
|
||||
enum {
|
||||
DRSEL0, DRSEL1, DRSEL2, DRSEL3, DRSEL4,
|
||||
DALUF0, DALUF1, DALUF2, DALUF3,
|
||||
DBS0, DBS1, DBS2,
|
||||
DF1_0, DF1_1, DF1_2, DF1_3,
|
||||
DF2_0, DF2_1, DF2_2, DF2_3,
|
||||
DLOADT,
|
||||
DLOADL,
|
||||
NEXT0, NEXT1, NEXT2, NEXT3, NEXT4, NEXT5, NEXT6, NEXT7, NEXT8, NEXT9
|
||||
};
|
||||
|
||||
//! get the normally accessed bank number from a bank register
|
||||
static inline UINT16 GET_BANK_NORMAL(UINT16 breg) { return X_RDBITS(breg,16,12,13); }
|
||||
|
||||
//! get the extended bank number (accessed via XMAR) from a bank register
|
||||
static inline UINT16 GET_BANK_EXTENDED(UINT16 breg) { return X_RDBITS(breg,16,14,15); }
|
||||
|
||||
//! get an ignored bit field from a control RAM address
|
||||
static inline UINT16 GET_CRAM_IGNORE(UINT16 addr) { return X_RDBITS(addr,16,0,1); }
|
||||
|
||||
//! get the bank select bit field from a control RAM address
|
||||
static inline UINT16 GET_CRAM_BANKSEL(UINT16 addr) { return X_RDBITS(addr,16,2,3); }
|
||||
|
||||
//! get the ROM/RAM flag from a control RAM address
|
||||
static inline UINT16 GET_CRAM_RAMROM(UINT16 addr) { return X_RDBITS(addr,16,4,4); }
|
||||
|
||||
//! get the half select flag from a control RAM address
|
||||
static inline UINT16 GET_CRAM_HALFSEL(UINT16 addr) { return X_RDBITS(addr,16,5,5); }
|
||||
|
||||
//! get the word address bit field from a control RAM address
|
||||
static inline UINT16 GET_CRAM_WORDADDR(UINT16 addr) { return X_RDBITS(addr,16,6,15); }
|
||||
|
||||
UINT16 m_task_mpc[ALTO2_TASKS]; //!< per task micro program counter
|
||||
UINT16 m_task_next2[ALTO2_TASKS]; //!< per task address modifier
|
||||
UINT8 m_task; //!< active task
|
||||
UINT8 m_next_task; //!< next micro instruction's task
|
||||
UINT8 m_next2_task; //!< next but one micro instruction's task
|
||||
UINT16 m_mpc; //!< micro program counter
|
||||
UINT32 m_mir; //!< micro instruction register
|
||||
|
||||
/**
|
||||
* \brief current micro instruction's register selection
|
||||
* The emulator F2s ACSOURCE and ACDEST modify this.
|
||||
* Note: The S registers are addressed by the original RSEL[0-4],
|
||||
* even when the the emulator modifies this.
|
||||
*/
|
||||
UINT8 m_rsel;
|
||||
UINT8 m_d_rsel; //!< decoded RSEL[0-4]
|
||||
UINT8 m_d_aluf; //!< decoded ALUF[0-3] function
|
||||
UINT8 m_d_bs; //!< decoded BS[0-2] bus source
|
||||
UINT8 m_d_f1; //!< decoded F1[0-3] function
|
||||
UINT8 m_d_f2; //!< decoded F2[0-3] function
|
||||
UINT8 m_d_loadt; //!< decoded LOADT flag
|
||||
UINT8 m_d_loadl; //!< decoded LOADL flag
|
||||
UINT16 m_next; //!< current micro instruction's next
|
||||
UINT16 m_next2; //!< next micro instruction's next
|
||||
UINT16 m_r[ALTO2_REGS]; //!< R register file
|
||||
UINT16 m_s[ALTO2_SREG_BANKS][ALTO2_REGS]; //!< S register file(s)
|
||||
UINT16 m_bus; //!< wired-AND bus
|
||||
UINT16 m_t; //!< T register
|
||||
UINT16 m_alu; //!< the current ALU
|
||||
UINT16 m_aluc0; //!< the current ALU carry output
|
||||
UINT16 m_l; //!< L register
|
||||
UINT16 m_shifter; //!< shifter output
|
||||
UINT16 m_laluc0; //!< the latched ALU carry output
|
||||
UINT16 m_m; //!< M register of RAM related tasks (MYL latch in the schematics)
|
||||
UINT16 m_cram_addr; //!< constant RAM address
|
||||
UINT16 m_task_wakeup; //!< task wakeup: bit 1<<n set if task n requesting service
|
||||
a2func m_active_callback[ALTO2_TASKS]; //!< task activation callbacks
|
||||
|
||||
UINT16 m_reset_mode; //!< reset mode register: bit 1<<n set if task n starts in ROM
|
||||
bool m_rdram_flag; //!< set by rdram, action happens on next cycle
|
||||
bool m_wrtram_flag; //!< set by wrtram, action happens on next cycle
|
||||
|
||||
UINT8 m_s_reg_bank[ALTO2_TASKS]; //!< active S register bank per task
|
||||
UINT8 m_bank_reg[ALTO2_TASKS]; //!< normal and extended RAM banks per task
|
||||
bool m_ether_enable; //!< set to true, if the ethernet should be simulated
|
||||
bool m_ewfct; //!< set by Ether task when it want's a wakeup at switch to task_mrt
|
||||
int m_dsp_time; //!< display_state_machine() time accu
|
||||
int m_unload_time; //!< unload word time accu
|
||||
int m_unload_word; //!< unload word number
|
||||
#if (USE_BITCLK_TIMER == 0)
|
||||
int m_bitclk_time; //!< bitclk call time accu
|
||||
int m_bitclk_index; //!< bitclk index (bit number)
|
||||
#endif
|
||||
|
||||
static const char *task_name(int task); //!< human readable task names
|
||||
static const char *r_name(UINT8 reg); //!< human readable register names
|
||||
static const char *aluf_name(UINT8 aluf); //!< human readable ALU function names
|
||||
static const char *bs_name(UINT8 bs); //!< human readable bus source names
|
||||
static const char *f1_name(UINT8 f1); //!< human readable F1 function names
|
||||
static const char *f2_name(UINT8 f2); //!< human readable F2 function names
|
||||
|
||||
/**
|
||||
* @brief 2KCTL PROM u3 - 256x4
|
||||
* <PRE>
|
||||
* PROM u3 is 256x4 type 3601-1, looks like SN74387, and it
|
||||
* controls NEXT[6-9]', i.e. the outputs are wire-AND to NEXT
|
||||
*
|
||||
* SN74387
|
||||
* +---+-+---+
|
||||
* | +-+ |
|
||||
* A6 -|1 16|- Vcc
|
||||
* | |
|
||||
* A5 -|2 15|- A7
|
||||
* | |
|
||||
* A4 -|3 14|- FE1'
|
||||
* | |
|
||||
* A3 -|4 13|- FE2'
|
||||
* | |
|
||||
* A0 -|5 12|- D0
|
||||
* | |
|
||||
* A1 -|6 11|- D1
|
||||
* | |
|
||||
* A2 -|7 10|- D2
|
||||
* | |
|
||||
* GND -|8 9|- D3
|
||||
* | |
|
||||
* +---------+
|
||||
*
|
||||
*
|
||||
* It is enabled whenever the Emulator task is active and:
|
||||
* both F2[0] and F2[1] are 1 F2 functions 014, 015, 016, 017
|
||||
* F2=14 is 0 not for F2 = 14 (load IR<-)
|
||||
* IR[0] is 0 not for arithmetic group
|
||||
*
|
||||
* This means it controls the F2 functions 015:IDISP<- and 016:<-ACSOURCE
|
||||
*
|
||||
* Its address lines are:
|
||||
* line pin connected to load swap
|
||||
* -------------------------------------------------------------------
|
||||
* A0 5 F2[2] (i.e. MIR[18]) IR[07]
|
||||
* A1 6 IR[01] IR[06]
|
||||
* A2 7 IR[02] IR[05]
|
||||
* A3 4 IR[03] IR[04]
|
||||
* A4 3 IR[04] IR[03]
|
||||
* A5 2 IR[05] IR[02]
|
||||
* A6 1 IR[06] IR[01]
|
||||
* A7 15 IR[07] F2[2]
|
||||
*
|
||||
* Its data lines are:
|
||||
* line pin connected to load
|
||||
* -------------------------------------------------------------------
|
||||
* D3 9 NEXT[06]' NEXT[06]
|
||||
* D2 10 NEXT[07]' NEXT[07]
|
||||
* D1 11 NEXT[08]' NEXT[08]
|
||||
* D0 12 NEXT[09]' NEXT[09]
|
||||
*
|
||||
* Its address lines are reversed at load time to make it easier to
|
||||
* access it. Also both, address and data lines, are inverted.
|
||||
* </PRE>
|
||||
*/
|
||||
UINT8* m_ctl2k_u3;
|
||||
|
||||
/**
|
||||
* @brief 2KCTL PROM u38; 82S23; 32x8 bit
|
||||
* <PRE>
|
||||
*
|
||||
* 82S23
|
||||
* +---+-+---+
|
||||
* | +-+ |
|
||||
* B0 -|1 16|- Vcc
|
||||
* | |
|
||||
* B1 -|2 15|- EN'
|
||||
* | |
|
||||
* B2 -|3 14|- A4
|
||||
* | |
|
||||
* B3 -|4 13|- A3
|
||||
* | |
|
||||
* B4 -|5 12|- A2
|
||||
* | |
|
||||
* B5 -|6 11|- A1
|
||||
* | |
|
||||
* B6 -|7 10|- A0
|
||||
* | |
|
||||
* GND -|8 9|- B7
|
||||
* | |
|
||||
* +---------+
|
||||
*
|
||||
* Task priority encoder
|
||||
*
|
||||
* line pin signal
|
||||
* -------------------------------
|
||||
* A0 10 CT1 (current task LSB)
|
||||
* A1 11 CT2
|
||||
* A2 12 CT4
|
||||
* A3 13 CT8 (current task MSB)
|
||||
* A4 14 0 (GND)
|
||||
*
|
||||
* line pin signal
|
||||
* -------------------------------
|
||||
* B0 1 RDCT8'
|
||||
* B1 2 RDCT4'
|
||||
* B2 3 RDCT2'
|
||||
* B3 4 RDCT1'
|
||||
* B4 5 NEXT[09]'
|
||||
* B5 6 NEXT[08]'
|
||||
* B6 7 NEXT[07]'
|
||||
* B7 9 NEXT[06]'
|
||||
* </PRE>
|
||||
*/
|
||||
UINT8* m_ctl2k_u38;
|
||||
|
||||
//! output lines of the 2KCTL U38 PROM
|
||||
enum {
|
||||
U38_RDCT8,
|
||||
U38_RDCT4,
|
||||
U38_RDCT2,
|
||||
U38_RDCT1,
|
||||
U38_NEXT09,
|
||||
U38_NEXT08,
|
||||
U38_NEXT07,
|
||||
U38_NEXT06
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 2KCTL PROM u76; P3601-1; 256x4; PC0I and PC1I decoding
|
||||
* <PRE>
|
||||
* Replacement for u51, which is used in 1KCTL
|
||||
*
|
||||
* SN74387
|
||||
* +---+-+---+
|
||||
* | +-+ |
|
||||
* A6 -|1 16|- Vcc
|
||||
* | |
|
||||
* A5 -|2 15|- A7
|
||||
* | |
|
||||
* A4 -|3 14|- FE1'
|
||||
* | |
|
||||
* A3 -|4 13|- FE2'
|
||||
* | |
|
||||
* A0 -|5 12|- D0
|
||||
* | |
|
||||
* A1 -|6 11|- D1
|
||||
* | |
|
||||
* A2 -|7 10|- D2
|
||||
* | |
|
||||
* GND -|8 9|- D3
|
||||
* | |
|
||||
* +---------+
|
||||
*
|
||||
* input line signal
|
||||
* ----------------------------
|
||||
* A7 15 EMACT'
|
||||
* A6 1 F1(0)
|
||||
* A5 2 F1(1)'
|
||||
* A4 3 F1(2)'
|
||||
* A3 4 F1(3)'
|
||||
* A2 7 0 (GND)
|
||||
* A1 6 PC1O
|
||||
* A0 5 PC0O
|
||||
*
|
||||
* output line signal
|
||||
* ----------------------------
|
||||
* D0 12 PC1T
|
||||
* D1 11 PC1F
|
||||
* D2 10 PC0T
|
||||
* D3 9 PC0F
|
||||
*
|
||||
* The outputs are connected to a dual 4:1 demultiplexer 74S153, so that
|
||||
* depending on NEXT01' and RESET the following signals are passed through:
|
||||
*
|
||||
* RESET NEXT[01]' PC0I PC1I
|
||||
* --------------------------------------
|
||||
* 0 0 PC0T PC1T
|
||||
* 0 1 PC0F PC1F
|
||||
* 1 0 PC0I4 T14 (?)
|
||||
* 1 1 -"- -"-
|
||||
*
|
||||
* This selects the microcode "page" to jump to on SWMODE (F1 = 010)
|
||||
* depending on the current NEXT[01]' level.
|
||||
* </PRE>
|
||||
*/
|
||||
UINT8* m_ctl2k_u76;
|
||||
|
||||
/**
|
||||
* @brief 3k CRAM PROM a37
|
||||
*/
|
||||
UINT8* m_cram3k_a37;
|
||||
|
||||
/**
|
||||
* @brief memory addressing PROM a64
|
||||
*/
|
||||
UINT8* m_madr_a64;
|
||||
|
||||
/**
|
||||
* @brief memory addressing PROM a65
|
||||
*/
|
||||
UINT8* m_madr_a65;
|
||||
|
||||
/**
|
||||
* @brief unused PROM a90
|
||||
* Data sheet 05a_AIM.pdf page 14
|
||||
* inputs A0-A7 from R0-R7 (?)
|
||||
* output signal
|
||||
* -------------------
|
||||
* Q0 KP3
|
||||
* Q1 KP4
|
||||
* Q2 KP5
|
||||
* Q3 unused
|
||||
*
|
||||
* I haven't found yet where KP3-KP5 are used
|
||||
*/
|
||||
UINT8* m_madr_a90;
|
||||
|
||||
/**
|
||||
* @brief unused PROM a91
|
||||
* Data sheet 05a_AIM.pdf page 14
|
||||
* inputs A0-A7 from R0-R7 (?)
|
||||
*
|
||||
* Output Signal
|
||||
* -------------------
|
||||
* Q0 KP0
|
||||
* Q1 KP1
|
||||
* Q2 KP2
|
||||
* Q3 unused
|
||||
* KP0-KP3 are decoded using 7442 a78 to select
|
||||
* the keyboard row enable
|
||||
*
|
||||
* Enable Key[0] Key[1] Key[2] Key[3] Key[4] Key[5] Key[6] Key[7]
|
||||
* ------------------------------------------------------------------------
|
||||
* KE(0) KB(R) KB(1) KB(3) KB(5) KB(T) KB(ESC) KB(2) KB(4)
|
||||
* KE(1) KB(G) KB(TAB) KB(W) KB(6) KB(Y) KB(F) KB(0) KB(E)
|
||||
* KE(2) KB(H) KB(CTL) KB(S) KB(7) KB(8) KB(C) KB(A) KB(D)
|
||||
* KE(3) KB(N) KB(J) KB(9) KB(U) KB(M) KB(B) KB(I) KB(V)
|
||||
* KE(4) KB(LCK) KB(Z) KB(X) KB(Q) KB(SPC) KB(^R) KB(O) KB(K)
|
||||
* KE(5) KB([) KB(.) KB(L) KB(-) KB(+) KB(;) KB(,) KB(P)
|
||||
* KE(6) KB(^L) KB(RTN) KB(") KB(/) KB(S3) KB(<-) KB(]) KB(\)
|
||||
* KE(7) KB(S1) KB(DEL) KB(S2) KB(LF) KB(S4) KB(S5) KB(BW) KB(BS)
|
||||
*/
|
||||
UINT8* m_madr_a91;
|
||||
|
||||
/**
|
||||
* @brief ALU function to 74181 operation lookup PROM
|
||||
*/
|
||||
UINT8* m_alu_a10;
|
||||
|
||||
//! output lines of the ALU a10 PROM
|
||||
enum {
|
||||
A10_UNUSED = (1 << 0),
|
||||
A10_TSELECT = (1 << 1),
|
||||
A10_ALUCI = (1 << 2),
|
||||
A10_ALUM = (1 << 3),
|
||||
A10_ALUS0 = (1 << 4),
|
||||
A10_ALUS1 = (1 << 5),
|
||||
A10_ALUS2 = (1 << 6),
|
||||
A10_ALUS3 = (1 << 7),
|
||||
A10_ALUIN = (A10_ALUM|A10_ALUCI|A10_ALUS0|A10_ALUS1|A10_ALUS2|A10_ALUS3)
|
||||
};
|
||||
|
||||
//! no operating function to put in the m_bs, m_f1 and m_f2 slots
|
||||
void noop() {}
|
||||
|
||||
//! per task bus source function pointers, early (0) and late (1)
|
||||
a2func m_bs[2][ALTO2_TASKS][ALTO2_BUSSRC];
|
||||
void set_bs(UINT8 task, UINT8 fn, a2func f0, a2func f1) {
|
||||
m_bs[0][task][fn] = f0 ? f0 : &alto2_cpu_device::noop;
|
||||
m_bs[1][task][fn] = f1 ? f1 : &alto2_cpu_device::noop;
|
||||
}
|
||||
|
||||
//! per task f1 function pointers, early (0) and late (1)
|
||||
a2func m_f1[2][ALTO2_TASKS][ALTO2_F1MAX];
|
||||
void set_f1(UINT8 task, UINT8 fn, a2func f0, a2func f1) {
|
||||
m_f1[0][task][fn] = f0 ? f0 : &alto2_cpu_device::noop;
|
||||
m_f1[1][task][fn] = f1 ? f1 : &alto2_cpu_device::noop;
|
||||
}
|
||||
|
||||
//! per task f2 function pointers, early (0) and late (1)
|
||||
a2func m_f2[2][ALTO2_TASKS][ALTO2_F2MAX];
|
||||
void set_f2(UINT8 task, UINT8 fn, a2func f0, a2func f1) {
|
||||
m_f2[0][task][fn] = f0 ? f0 : &alto2_cpu_device::noop;
|
||||
m_f2[1][task][fn] = f1 ? f1 : &alto2_cpu_device::noop;
|
||||
}
|
||||
|
||||
bool m_ram_related[ALTO2_TASKS]; //!< set when task is RAM related
|
||||
|
||||
UINT64 m_cycle; //!< number of cycles executed in the current slice
|
||||
|
||||
UINT64 cycle() { return m_cycle; } //!< return the current CPU cycle
|
||||
UINT64 ntime() { return m_cycle*ALTO2_UCYCLE/1000; } //!< return the current nano seconds
|
||||
|
||||
void hard_reset(); //!< reset the various registers
|
||||
void soft_reset(); //!< soft reset
|
||||
|
||||
void fn_bs_bad_0(); //! bs dummy early function
|
||||
void fn_bs_bad_1(); //! bs dummy late function
|
||||
|
||||
void fn_f1_bad_0(); //! f1 dummy early function
|
||||
void fn_f1_bad_1(); //! f1 dummy late function
|
||||
|
||||
void fn_f2_bad_0(); //! f2 dummy early function
|
||||
void fn_f2_bad_1(); //! f2 dummy late function
|
||||
|
||||
DECLARE_READ16_MEMBER( noop_r ); //!< read open bus (0177777)
|
||||
DECLARE_WRITE16_MEMBER( noop_w ); //!< write open bus
|
||||
|
||||
DECLARE_READ16_MEMBER( bank_reg_r ); //!< read bank register in memory mapped I/O range
|
||||
DECLARE_WRITE16_MEMBER( bank_reg_w ); //!< write bank register in memory mapped I/O range
|
||||
|
||||
void bs_early_read_r(); //!< bus source: drive bus by R register
|
||||
void bs_early_load_r(); //!< bus source: load R places 0 on the BUS
|
||||
void bs_late_load_r(); //!< bus source: load R from SHIFTER
|
||||
void bs_early_read_md(); //!< bus source: drive BUS from read memory data
|
||||
void bs_early_mouse(); //!< bus source: drive bus by mouse
|
||||
void bs_early_disp(); //!< bus source: drive bus by displacement (which?)
|
||||
void f1_early_block(); //!< F1 func: block active task
|
||||
void f1_late_load_mar(); //!< F1 func: load memory address register
|
||||
void f1_early_task(); //!< F1 func: task switch
|
||||
void f1_late_l_lsh_1(); //!< F1 func: SHIFTER = left shift L once
|
||||
void f1_late_l_rsh_1(); //!< F1 func: SHIFTER = right shift L once
|
||||
void f1_late_l_lcy_8(); //!< F1 func: SHIFTER = byte swap L
|
||||
void f2_late_bus_eq_zero(); //!< F2 func: branch on bus equals zero
|
||||
void f2_late_shifter_lt_zero(); //!< F2 func: branch on shifter less than zero
|
||||
void f2_late_shifter_eq_zero(); //!< F2 func: branch on shifter equals zero
|
||||
void f2_late_bus(); //!< F2 func: branch on bus bits BUS[6-15]
|
||||
void f2_late_alucy(); //!< F2 func: branch on latched ALU carry
|
||||
void f2_late_load_md(); //!< F2 func: load memory data
|
||||
|
||||
#if USE_ALU_74181
|
||||
UINT32 alu_74181(UINT32 a, UINT32 b, UINT8 smc);
|
||||
#endif
|
||||
void rdram(); //!< read the microcode ROM/RAM halfword
|
||||
void wrtram(); //!< write the microcode RAM from M register and ALU
|
||||
|
||||
UINT8 m_ether_id; //!< configured Ethernet ID for this machine
|
||||
|
||||
//*******************************************
|
||||
// inline the sub-devices
|
||||
//*******************************************
|
||||
#include "a2jkff.h"
|
||||
#include "a2ram.h"
|
||||
#include "a2hw.h"
|
||||
#include "a2kbd.h"
|
||||
#include "a2mouse.h"
|
||||
#include "a2disk.h"
|
||||
#include "a2disp.h"
|
||||
#include "a2mem.h"
|
||||
#include "a2emu.h"
|
||||
#include "a2ksec.h"
|
||||
#include "a2ether.h"
|
||||
#include "a2mrt.h"
|
||||
#include "a2dwt.h"
|
||||
#include "a2curt.h"
|
||||
#include "a2dht.h"
|
||||
#include "a2dvt.h"
|
||||
#include "a2part.h"
|
||||
#include "a2dwt.h"
|
||||
#include "a2kwd.h"
|
||||
};
|
||||
|
||||
extern const device_type ALTO2;
|
||||
|
||||
|
||||
#endif /* _CPU_ALTO2_H_ */
|
391
src/emu/cpu/alto2/alto2dsm.c
Normal file
391
src/emu/cpu/alto2/alto2dsm.c
Normal file
@ -0,0 +1,391 @@
|
||||
/**********************************************************
|
||||
* Xerox AltoII disassembler
|
||||
*
|
||||
* Copyright Juergen Buchmueller <pullmoll@t-online.de>
|
||||
*
|
||||
* Licenses: MAME, GPLv2
|
||||
**********************************************************/
|
||||
#include "alto2cpu.h"
|
||||
|
||||
#define loc_DASTART 0000420 // display list header
|
||||
#define loc_DVIBITS 0000421 // display vertical field interrupt bitword
|
||||
#define loc_ITQUAN 0000422 // interval timer stored quantity
|
||||
#define loc_ITBITS 0000423 // interval timer bitword
|
||||
#define loc_MOUSEX 0000424 // mouse X coordinate
|
||||
#define loc_MOUSEY 0000425 // mouse Y coordinate
|
||||
#define loc_CURSORX 0000426 // cursor X coordinate
|
||||
#define loc_CURSORY 0000427 // cursor Y coordinate
|
||||
#define loc_RTC 0000430 // real time clock
|
||||
#define loc_CURMAP 0000431 // cursor bitmap (16 words up to 00450)
|
||||
#define loc_WW 0000452 // interrupt wakeups waiting
|
||||
#define loc_ACTIVE 0000453 // active interrupt bitword
|
||||
#define loc_MASKTAB 0000460 // mask table for convert
|
||||
#define loc_PCLOC 0000500 // saved interrupt PC
|
||||
#define loc_INTVEC 0000501 // interrupt transfer vector (15 words up to 00517)
|
||||
#define loc_KBLK 0000521 // disk command block address
|
||||
#define loc_KSTAT 0000522 // disk status at start of current sector
|
||||
#define loc_KADDR 0000523 // disk address of latest disk command
|
||||
#define loc_KSIBITS 0000524 // sector interrupt bit mask
|
||||
#define loc_ITTIME 0000525 // interval timer timer
|
||||
#define loc_TRAPPC 0000527 // trap saved PC
|
||||
#define loc_TRAPVEC 0000530 // trap vectors (up to 0567)
|
||||
#define loc_TIMERDATA 0000570 // timer data (OS; up to 0577)
|
||||
#define loc_EPLOC 0000600 // ethernet post location
|
||||
#define loc_EBLOC 0000601 // ethernet interrupt bitmask
|
||||
#define loc_EELOC 0000602 // ethernet ending count
|
||||
#define loc_ELLOC 0000603 // ethernet load location
|
||||
#define loc_EICLOC 0000604 // ethernet input buffer count
|
||||
#define loc_EIPLOC 0000605 // ethernet input buffer pointer
|
||||
#define loc_EOCLOC 0000606 // ethernet output buffer count
|
||||
#define loc_EOPLOC 0000607 // ethernet output buffer pointer
|
||||
#define loc_EHLOC 0000610 // ethernet host address
|
||||
#define loc_ERSVD 0000611 // reserved for ethernet expansion (up to 00612)
|
||||
#define loc_ALTOV 0000613 // Alto I/II indication that microcode caninterrogate (0 = Alto I, -1 = Alto II)
|
||||
#define loc_DCBR 0000614 // posted by parity task (main memory parity error)
|
||||
#define loc_KNMAR 0000615 // -"-
|
||||
#define loc_DWA 0000616 // -"-
|
||||
#define loc_CBA 0000617 // -"-
|
||||
#define loc_PC 0000620 // -"-
|
||||
#define loc_SAD 0000621 // -"-
|
||||
#define loc_SWATR 0000700 // saved registers (Swat; up to 00707)
|
||||
#define loc_UTILOUT 0177016 // printer output (up to 177017)
|
||||
#define loc_XBUS 0177020 // untility input bus (up to 177023)
|
||||
#define loc_MEAR 0177024 // memory error address register
|
||||
#define loc_MESR 0177025 // memory error status register
|
||||
#define loc_MECR 0177026 // memory error control register
|
||||
#define loc_UTILIN 0177030 // printer status, mouse keyset
|
||||
#define loc_KBDAD 0177034 // undecoded keyboard (up to 177037)
|
||||
#define loc_BANKREGS 0177740 // extended memory option bank registers
|
||||
|
||||
/**
|
||||
* @brief Microcode and constants PROM size
|
||||
*/
|
||||
#define MCODE_PAGE 1024
|
||||
#define MCODE_SIZE (2*MCODE_PAGE) /* Alto II may have 2 pages (or even 4?) */
|
||||
#define MCODE_MASK (MCODE_SIZE - 1)
|
||||
#define PROM_SIZE 256
|
||||
|
||||
/**
|
||||
* @brief short names for the 16 tasks
|
||||
*/
|
||||
static const char *taskname[16] = {
|
||||
"EMU", // emulator task
|
||||
"T01",
|
||||
"T02",
|
||||
"T03",
|
||||
"DSC", // disk sector task
|
||||
"T05",
|
||||
"T06",
|
||||
"ETH", // ethernet task
|
||||
"MRT", // memory refresh task
|
||||
"DWT", // display word task
|
||||
"CUR", // cursor task
|
||||
"DHT", // display horizontal task
|
||||
"DVT", // display vertical task
|
||||
"PAR", // parity task
|
||||
"DWD", // disk word task
|
||||
"T17"
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief names for the 32 R registers
|
||||
*/
|
||||
static const char *regname[32] = {
|
||||
"AC(3)", // emulator accu 3
|
||||
"AC(2)", // emulator accu 2
|
||||
"AC(1)", // emulator accu 1
|
||||
"AC(0)", // emulator accu 0
|
||||
"R04",
|
||||
"R05",
|
||||
"PC", // emulator program counter
|
||||
"R07",
|
||||
"R10",
|
||||
"R11",
|
||||
"R12",
|
||||
"R13",
|
||||
"R14",
|
||||
"R15",
|
||||
"R16",
|
||||
"R17",
|
||||
"R20",
|
||||
"R21",
|
||||
"CBA", // address of the currently active DCB+1
|
||||
"AECL", // address of end of current scanline's bitmap
|
||||
"SLC", // scan line count
|
||||
"HTAB", // number of tab words remaining on current scanline
|
||||
"DWA", // address of the bit map double word being fetched
|
||||
"MTEMP", // temporary cell
|
||||
"R30",
|
||||
"R31",
|
||||
"R32",
|
||||
"R33",
|
||||
"R34",
|
||||
"R35",
|
||||
"R36",
|
||||
"R37"
|
||||
};
|
||||
|
||||
//! for ALUF which is the value loaded into T, if t flags is set
|
||||
static const char* t_bus_alu[16] = {
|
||||
"ALU",
|
||||
"BUS",
|
||||
"ALU",
|
||||
"BUS",
|
||||
"BUS",
|
||||
"ALU",
|
||||
"ALU",
|
||||
"BUS",
|
||||
"BUS",
|
||||
"BUS",
|
||||
"ALU",
|
||||
"ALU",
|
||||
"ALU",
|
||||
"BUS",
|
||||
"BUS",
|
||||
"BUS",
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief copy of the constant PROM, which this disassembler may not have access to
|
||||
*/
|
||||
static UINT16 const_prom[PROM_SIZE] = {
|
||||
/* 0000 */ 0x0000, 0x0001, 0x0002, 0xfffe, 0xffff, 0xffff, 0x000f, 0xffff,
|
||||
/* 0008 */ 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0xfff8, 0xfff8,
|
||||
/* 0010 */ 0x0010, 0x001f, 0x0020, 0x003f, 0x0040, 0x007f, 0x0080, 0x0007,
|
||||
/* 0018 */ 0x00ff, 0xff00, 0x0400, 0x0100, 0x0110, 0x0151, 0x0114, 0x000f,
|
||||
/* 0020 */ 0x0116, 0x0118, 0x0ffa, 0xf000, 0x4000, 0xfffc, 0xfff6, 0xffeb,
|
||||
/* 0028 */ 0x4800, 0x6c00, 0x0800, 0x1000, 0xfe00, 0x7fff, 0x7fe0, 0x7f00,
|
||||
/* 0030 */ 0xffbd, 0x0f00, 0x0f0f, 0xf0f0, 0x6048, 0x3000, 0x7159, 0x2109,
|
||||
/* 0038 */ 0x6a3c, 0x4213, 0xa5a5, 0xfe1c, 0x3f00, 0xffc0, 0x012a, 0x0140,
|
||||
/* 0040 */ 0x8000, 0xffe0, 0x00bf, 0xfff9, 0xfff0, 0xfffd, 0x0970, 0x5d20,
|
||||
/* 0048 */ 0x3844, 0x6814, 0xfc00, 0xfe20, 0xfe22, 0x0083, 0x00f0, 0xff80,
|
||||
/* 0050 */ 0xf800, 0xe000, 0xc000, 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff,
|
||||
/* 0058 */ 0x3fff, 0x0200, 0x2000, 0xfff1, 0x0156, 0x0157, 0x0138, 0x0c00,
|
||||
/* 0060 */ 0x0130, 0x1813, 0x0180, 0x0181, 0x0182, 0x0183, 0x0184, 0x0185,
|
||||
/* 0068 */ 0x0186, 0x0187, 0x0188, 0x018a, 0x0112, 0x0113, 0x0102, 0xfff0,
|
||||
/* 0070 */ 0x0153, 0x0154, 0xffef, 0xffe4, 0xfffb, 0x000a, 0xffc1, 0x001f,
|
||||
/* 0078 */ 0x0e00, 0x007e, 0xff7e, 0x0018, 0x000d, 0x03f8, 0x83f9, 0xffe0,
|
||||
/* 0080 */ 0xfbff, 0x0009, 0x000b, 0x000c, 0x000e, 0x0030, 0x01fe, 0xff7f,
|
||||
/* 0088 */ 0x81ff, 0xffbf, 0xffcc, 0x0557, 0x0041, 0x0198, 0x0199, 0x01a2,
|
||||
/* 0090 */ 0xfe72, 0xfe58, 0x0012, 0x0014, 0x00dd, 0x02ff, 0x0101, 0x0001,
|
||||
/* 0098 */ 0x0401, 0x0011, 0x0013, 0x0015, 0x0016, 0x0017, 0x0019, 0x0003,
|
||||
/* 00a0 */ 0x03bd, 0x01de, 0xfe50, 0x00c0, 0x0c01, 0x6200, 0x6300, 0x0008,
|
||||
/* 00a8 */ 0x6400, 0x6500, 0x6e00, 0x6700, 0x6900, 0x6d00, 0x6600, 0x000c,
|
||||
/* 00b0 */ 0x6b00, 0x6b01, 0x6b02, 0x6b03, 0x6b04, 0x6b05, 0x6b06, 0x0010,
|
||||
/* 00b8 */ 0x6b07, 0x6b08, 0x6b09, 0x6b0a, 0x6b0b, 0x6b0c, 0x6b0d, 0x0020,
|
||||
/* 00c0 */ 0x6b0e, 0x6b0f, 0xfff3, 0xfe14, 0xfe15, 0xfe16, 0x0ffc, 0x0040,
|
||||
/* 00c8 */ 0x04ff, 0x05ff, 0x06ff, 0x013f, 0x017e, 0xfe7d, 0xffff, 0x0080,
|
||||
/* 00d0 */ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x00c0,
|
||||
/* 00d8 */ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x00ff,
|
||||
/* 00e0 */ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
/* 00e8 */ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
/* 00f0 */ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
/* 00f8 */ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief print a symbolic name for an mpc address
|
||||
*
|
||||
* @param a microcode address (mpc)
|
||||
* @return pointer to const string with the address or symbolic name
|
||||
*/
|
||||
static const char *addrname(int a)
|
||||
{
|
||||
static char buffer[4][32];
|
||||
static int which = 0;
|
||||
char *dst;
|
||||
|
||||
which = (which + 1) % 4;
|
||||
dst = buffer[which];
|
||||
|
||||
if (a < 020) {
|
||||
// start value for mpc per task is the task number
|
||||
snprintf(dst, sizeof(buffer[0]), "*%s", taskname[a]);
|
||||
} else {
|
||||
snprintf(dst, sizeof(buffer[0]), "%04o", a);
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
offs_t alto2_cpu_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options)
|
||||
{
|
||||
size_t len = 128;
|
||||
|
||||
UINT32 mir = (static_cast<UINT32>(oprom[0]) << 24) |
|
||||
(static_cast<UINT32>(oprom[1]) << 16) |
|
||||
(static_cast<UINT32>(oprom[2]) << 8) |
|
||||
(static_cast<UINT32>(oprom[3]) << 0);
|
||||
UINT8 rsel = static_cast<UINT8>((mir >> 27) & 31);
|
||||
UINT8 aluf = static_cast<UINT8>((mir >> 23) & 15);
|
||||
UINT8 bs = static_cast<UINT8>((mir >> 20) & 7);
|
||||
UINT8 f1 = static_cast<UINT8>((mir >> 16) & 15);
|
||||
UINT8 f2 = static_cast<UINT8>((mir >> 12) & 15);
|
||||
UINT8 t = static_cast<UINT8>((mir >> 11) & 1);
|
||||
UINT8 l = static_cast<UINT8>((mir >> 10) & 1);
|
||||
offs_t next = static_cast<offs_t>(mir & 1023);
|
||||
const UINT8* src = oprom - 4 * pc + 4 * next;
|
||||
UINT32 next2 = (static_cast<UINT32>(src[0]) << 24) |
|
||||
(static_cast<UINT32>(src[1]) << 16) |
|
||||
(static_cast<UINT32>(src[2]) << 8) |
|
||||
(static_cast<UINT32>(src[3]) << 0);
|
||||
UINT16 prefetch = next2 & 1023;
|
||||
char *dst = buffer;
|
||||
offs_t result = 1 | DASMFLAG_SUPPORTED;
|
||||
UINT8 pa;
|
||||
|
||||
if (next != pc + 1)
|
||||
result |= DASMFLAG_STEP_OUT;
|
||||
|
||||
if (t)
|
||||
dst += snprintf(dst, len - (size_t)(dst - buffer), "T<-%s ", t_bus_alu[aluf]);
|
||||
if (l)
|
||||
dst += snprintf(dst, len - (size_t)(dst - buffer), "L<- ");
|
||||
if (bs == 1)
|
||||
dst += snprintf(dst, len - (size_t)(dst - buffer), "%s<- ", regname[rsel]);
|
||||
switch (aluf) {
|
||||
case 0: // T?: BUS
|
||||
// this is somehow redundant and just wasting space
|
||||
dst += snprintf(dst, len - (size_t)(dst - buffer), "ALUF(BUS) ");
|
||||
break;
|
||||
case 1: // : T
|
||||
dst += snprintf(dst, len - (size_t)(dst - buffer), "ALUF(T) ");
|
||||
break;
|
||||
case 2: // T?: BUS OR T
|
||||
dst += snprintf(dst, len - (size_t)(dst - buffer), "ALUF(BUS|T) ");
|
||||
break;
|
||||
case 3: // : BUS AND T
|
||||
dst += snprintf(dst, len - (size_t)(dst - buffer), "ALUF(BUS&T) ");
|
||||
break;
|
||||
case 4: // : BUS XOR T
|
||||
dst += snprintf(dst, len - (size_t)(dst - buffer), "ALUF(BUS^T) ");
|
||||
break;
|
||||
case 5: // T?: BUS + 1
|
||||
dst += snprintf(dst, len - (size_t)(dst - buffer), "ALUF(BUS+1) ");
|
||||
break;
|
||||
case 6: // T?: BUS - 1
|
||||
dst += snprintf(dst, len - (size_t)(dst - buffer), "ALUF(BUS-1) ");
|
||||
break;
|
||||
case 7: // : BUS + T
|
||||
dst += snprintf(dst, len - (size_t)(dst - buffer), "ALUF(BUS+T) ");
|
||||
break;
|
||||
case 8: // : BUS - T
|
||||
dst += snprintf(dst, len - (size_t)(dst - buffer), "ALUF(BUS-T) ");
|
||||
break;
|
||||
case 9: // : BUS - T - 1
|
||||
dst += snprintf(dst, len - (size_t)(dst - buffer), "ALUF(BUS-T-1) ");
|
||||
break;
|
||||
case 10: // T?: BUS + T + 1
|
||||
dst += snprintf(dst, len - (size_t)(dst - buffer), "ALUF(BUS+T+1) ");
|
||||
break;
|
||||
case 11: // T?: BUS + SKIP
|
||||
dst += snprintf(dst, len - (size_t)(dst - buffer), "ALUF(BUS+SKIP) ");
|
||||
break;
|
||||
case 12: // T?: BUS, T (AND)
|
||||
dst += snprintf(dst, len - (size_t)(dst - buffer), "ALUF(BUS,T) ");
|
||||
break;
|
||||
case 13: // : BUS AND NOT T
|
||||
dst += snprintf(dst, len - (size_t)(dst - buffer), "ALUF(BUS&~T) ");
|
||||
break;
|
||||
case 14: // : undefined
|
||||
dst += snprintf(dst, len - (size_t)(dst - buffer), "*ALUF(BUS) ");
|
||||
break;
|
||||
case 15: // : undefined
|
||||
dst += snprintf(dst, len - (size_t)(dst - buffer), "*ALUF(BUS) ");
|
||||
break;
|
||||
}
|
||||
|
||||
switch (bs) {
|
||||
case 0: // read R
|
||||
dst += snprintf(dst, len - (size_t)(dst - buffer), "BUS<-%s ", regname[rsel]);
|
||||
break;
|
||||
case 1: // load R from shifter output
|
||||
// dst += snprintf(dst, len - (size_t)(dst - buffer), "; %s<-", regname[rsel]);
|
||||
break;
|
||||
case 2: // enables no source to the BUS, leaving it all ones
|
||||
dst += snprintf(dst, len - (size_t)(dst - buffer), "BUS<-177777 ");
|
||||
break;
|
||||
case 3: // performs different functions in different tasks
|
||||
dst += snprintf(dst, len - (size_t)(dst - buffer), "BUS<-BS3 ");
|
||||
break;
|
||||
case 4: // performs different functions in different tasks
|
||||
dst += snprintf(dst, len - (size_t)(dst - buffer), "BUS<-BS4 ");
|
||||
break;
|
||||
case 5: // memory data
|
||||
dst += snprintf(dst, len - (size_t)(dst - buffer), "BUS<-MD ");
|
||||
break;
|
||||
case 6: // BUS[3-0] <- MOUSE; BUS[15-4] <- -1
|
||||
dst += snprintf(dst, len - (size_t)(dst - buffer), "BUS<-MOUSE ");
|
||||
break;
|
||||
case 7: // IR[7-0], possibly sign extended
|
||||
dst += snprintf(dst, len - (size_t)(dst - buffer), "BUS<-DISP ");
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
switch (f1) {
|
||||
case 0: // no operation
|
||||
break;
|
||||
case 1: // load MAR from ALU output; start main memory reference
|
||||
dst += snprintf(dst, len - (size_t)(dst - buffer), "MAR<-ALU ");
|
||||
break;
|
||||
case 2: // switch tasks if higher priority wakeup is pending
|
||||
dst += snprintf(dst, len - (size_t)(dst - buffer), "TASK ");
|
||||
break;
|
||||
case 3: // disable the current task until re-enabled by a hardware-generated condition
|
||||
dst += snprintf(dst, len - (size_t)(dst - buffer), "BLOCK ");
|
||||
break;
|
||||
case 4: // SHIFTER output will be L shifted left one place
|
||||
dst += snprintf(dst, len - (size_t)(dst - buffer), "SHIFTER<-L(LSH1) ");
|
||||
break;
|
||||
case 5: // SHIFTER output will be L shifted right one place
|
||||
dst += snprintf(dst, len - (size_t)(dst - buffer), "SHIFTER<-L(RSH1) ");
|
||||
break;
|
||||
case 6: // SHIFTER output will be L rotated left 8 places
|
||||
dst += snprintf(dst, len - (size_t)(dst - buffer), "SHIFTER<-L(LCY8) ");
|
||||
break;
|
||||
case 7: // put the constant from PROM (RSELECT,BS) on the bus
|
||||
pa = (rsel << 3) | bs;
|
||||
dst += snprintf(dst, len - (size_t)(dst - buffer), "BUS<-%05o CONST[%03o]", const_prom[pa], pa);
|
||||
break;
|
||||
default:
|
||||
dst += snprintf(dst, len - (size_t)(dst - buffer), "F1_%02o ", f1);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (f2) {
|
||||
case 0: // no operation
|
||||
break;
|
||||
case 1: // NEXT <- NEXT OR (BUS==0 ? 1 : 0)
|
||||
dst += snprintf(dst, len - (size_t)(dst - buffer), "[BUS==0 ? %s:%s] ",
|
||||
addrname((prefetch | 1) & MCODE_MASK), addrname(prefetch & MCODE_MASK));
|
||||
break;
|
||||
case 2: // NEXT <- NEXT OR (SHIFTER==0 ? 1 : 0)
|
||||
dst += snprintf(dst, len - (size_t)(dst - buffer), "[SH==0 ? %s:%s] ",
|
||||
addrname((prefetch | 1) & MCODE_MASK), addrname(prefetch & MCODE_MASK));
|
||||
break;
|
||||
case 3: // NEXT <- NEXT OR (SHIFTER<0 ? 1 : 0)
|
||||
dst += snprintf(dst, len - (size_t)(dst - buffer), "[SH<0 ? %s:%s] ",
|
||||
addrname((prefetch | 1) & MCODE_MASK), addrname(prefetch & MCODE_MASK));
|
||||
break;
|
||||
case 4: // NEXT <- NEXT OR BUS
|
||||
dst += snprintf(dst, len - (size_t)(dst - buffer), "NEXT<-BUS ");
|
||||
break;
|
||||
case 5: // NEXT <- NEXT OR ALUC0. ALUC0 is the carry produced by last L loading microinstruction.
|
||||
dst += snprintf(dst, len - (size_t)(dst - buffer), "[ALUC0 ? %s:%s] ",
|
||||
addrname((prefetch | 1) & MCODE_MASK), addrname(prefetch & MCODE_MASK));
|
||||
break;
|
||||
case 6: // deliver BUS data to memory
|
||||
dst += snprintf(dst, len - (size_t)(dst - buffer), "MD<-BUS ");
|
||||
break;
|
||||
case 7: // put on the bus the constant from PROM (RSELECT,BS)
|
||||
if (f1 != 7) {
|
||||
pa = 8 * rsel + bs;
|
||||
dst += snprintf(dst, len - (size_t)(dst - buffer), "BUS<-%05o CONST[%03o]", const_prom[pa], pa);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
dst += snprintf(dst, len - (size_t)(dst - buffer), "BUS<-F2_%02o ", f2);
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
@ -2388,3 +2388,112 @@ $(CPUOBJ)/score/score.o: $(CPUSRC)/score/score.c \
|
||||
$(CPUOBJ)/score/scoredsm.o: $(CPUSRC)/score/scoredsm.c \
|
||||
$(CPUSRC)/score/scorem.h
|
||||
|
||||
|
||||
#-------------------------------------------------
|
||||
# Xerox Alto-II
|
||||
#@src/emu/cpu/alto2/alto2cpu.h,CPUS += ALTO2
|
||||
#-------------------------------------------------
|
||||
|
||||
ifneq ($(filter ALTO2,$(CPUS)),)
|
||||
OBJDIRS += $(CPUOBJ)/alto2
|
||||
CPUOBJS += $(CPUOBJ)/alto2/alto2cpu.o \
|
||||
$(CPUOBJ)/alto2/a2disk.o \
|
||||
$(CPUOBJ)/alto2/a2disp.o \
|
||||
$(CPUOBJ)/alto2/a2curt.o \
|
||||
$(CPUOBJ)/alto2/a2dht.o \
|
||||
$(CPUOBJ)/alto2/a2dvt.o \
|
||||
$(CPUOBJ)/alto2/a2dwt.o \
|
||||
$(CPUOBJ)/alto2/a2emu.o \
|
||||
$(CPUOBJ)/alto2/a2ether.o \
|
||||
$(CPUOBJ)/alto2/a2hw.o \
|
||||
$(CPUOBJ)/alto2/a2kbd.o \
|
||||
$(CPUOBJ)/alto2/a2ksec.o \
|
||||
$(CPUOBJ)/alto2/a2kwd.o \
|
||||
$(CPUOBJ)/alto2/a2mem.o \
|
||||
$(CPUOBJ)/alto2/a2mouse.o \
|
||||
$(CPUOBJ)/alto2/a2mrt.o \
|
||||
$(CPUOBJ)/alto2/a2part.o \
|
||||
$(CPUOBJ)/alto2/a2ram.o \
|
||||
$(CPUOBJ)/alto2/a2roms.o
|
||||
|
||||
DASMOBJS += $(CPUOBJ)/alto2/alto2dsm.o
|
||||
endif
|
||||
|
||||
$(CPUOBJ)/alto2/alto2cpu.o: $(CPUSRC)/alto2/alto2cpu.c \
|
||||
$(CPUSRC)/alto2/alto2cpu.h
|
||||
|
||||
$(CPUOBJ)/alto2/a2disk.o: $(CPUSRC)/alto2/a2disk.c \
|
||||
$(CPUSRC)/alto2/a2disk.h \
|
||||
$(CPUSRC)/alto2/alto2cpu.h
|
||||
|
||||
$(CPUOBJ)/alto2/a2disp.o: $(CPUSRC)/alto2/a2disp.c \
|
||||
$(CPUSRC)/alto2/a2disp.h \
|
||||
$(CPUSRC)/alto2/alto2cpu.h
|
||||
|
||||
$(CPUOBJ)/alto2/a2curt.o: $(CPUSRC)/alto2/a2curt.c \
|
||||
$(CPUSRC)/alto2/a2curt.h \
|
||||
$(CPUSRC)/alto2/alto2cpu.h
|
||||
|
||||
$(CPUOBJ)/alto2/a2dht.o: $(CPUSRC)/alto2/a2dht.c \
|
||||
$(CPUSRC)/alto2/a2dht.h \
|
||||
$(CPUSRC)/alto2/alto2cpu.h
|
||||
|
||||
$(CPUOBJ)/alto2/a2dvt.o: $(CPUSRC)/alto2/a2dvt.c \
|
||||
$(CPUSRC)/alto2/a2dvt.h \
|
||||
$(CPUSRC)/alto2/alto2cpu.h
|
||||
|
||||
$(CPUOBJ)/alto2/a2dwt.o: $(CPUSRC)/alto2/a2dwt.c \
|
||||
$(CPUSRC)/alto2/a2dwt.h \
|
||||
$(CPUSRC)/alto2/alto2cpu.h
|
||||
|
||||
$(CPUOBJ)/alto2/a2emu.o: $(CPUSRC)/alto2/a2emu.c \
|
||||
$(CPUSRC)/alto2/a2emu.h \
|
||||
$(CPUSRC)/alto2/alto2cpu.h
|
||||
|
||||
$(CPUOBJ)/alto2/a2ether.o: $(CPUSRC)/alto2/a2ether.c \
|
||||
$(CPUSRC)/alto2/a2ether.h \
|
||||
$(CPUSRC)/alto2/alto2cpu.h
|
||||
|
||||
$(CPUOBJ)/alto2/a2hw.o: $(CPUSRC)/alto2/a2hw.c \
|
||||
$(CPUSRC)/alto2/a2hw.h \
|
||||
$(CPUSRC)/alto2/alto2cpu.h
|
||||
|
||||
$(CPUOBJ)/alto2/a2kbd.o: $(CPUSRC)/alto2/a2kbd.c \
|
||||
$(CPUSRC)/alto2/a2kbd.h \
|
||||
$(CPUSRC)/alto2/alto2cpu.h
|
||||
|
||||
$(CPUOBJ)/alto2/a2ksec.o: $(CPUSRC)/alto2/a2ksec.c \
|
||||
$(CPUSRC)/alto2/a2ksec.h \
|
||||
$(CPUSRC)/alto2/alto2cpu.h
|
||||
|
||||
$(CPUOBJ)/alto2/a2kwd.o: $(CPUSRC)/alto2/a2kwd.c \
|
||||
$(CPUSRC)/alto2/a2kwd.h \
|
||||
$(CPUSRC)/alto2/alto2cpu.h
|
||||
|
||||
$(CPUOBJ)/alto2/a2mem.o: $(CPUSRC)/alto2/a2mem.c \
|
||||
$(CPUSRC)/alto2/a2mem.h \
|
||||
$(CPUSRC)/alto2/alto2cpu.h
|
||||
|
||||
$(CPUOBJ)/alto2/a2mouse.o: $(CPUSRC)/alto2/a2mouse.c \
|
||||
$(CPUSRC)/alto2/a2mouse.h \
|
||||
$(CPUSRC)/alto2/alto2cpu.h
|
||||
|
||||
$(CPUOBJ)/alto2/a2mrt.o: $(CPUSRC)/alto2/a2mrt.c \
|
||||
$(CPUSRC)/alto2/a2mrt.h \
|
||||
$(CPUSRC)/alto2/alto2cpu.h
|
||||
|
||||
$(CPUOBJ)/alto2/a2part.o: $(CPUSRC)/alto2/a2part.c \
|
||||
$(CPUSRC)/alto2/a2part.h \
|
||||
$(CPUSRC)/alto2/alto2cpu.h
|
||||
|
||||
$(CPUOBJ)/alto2/a2ram.o: $(CPUSRC)/alto2/a2ram.c \
|
||||
$(CPUSRC)/alto2/a2ram.h \
|
||||
$(CPUSRC)/alto2/alto2cpu.h
|
||||
|
||||
$(CPUOBJ)/alto2/a2roms.o: $(CPUSRC)/alto2/a2roms.c \
|
||||
$(CPUSRC)/alto2/a2roms.h \
|
||||
$(CPUSRC)/alto2/alto2cpu.h
|
||||
|
||||
$(CPUOBJ)/alto2/alto2dsm.o: $(CPUSRC)/alto2/alto2dsm.c \
|
||||
$(CPUSRC)/alto2/alto2cpu.h
|
||||
|
||||
|
@ -176,6 +176,7 @@ enum
|
||||
XTAL_28_48MHz = 28480000, /* Chromatics CGC-7900 */
|
||||
XTAL_28_63636MHz = 28636363, /* Later Leland games and Atari GT, Amiga NTSC, Raiden2 h/w (8x NTSC subcarrier)*/
|
||||
XTAL_28_7MHz = 28700000,
|
||||
XTAL_29_4912MHz = 29491200, /* Xerox Alto-II system clock (tagged 29.4MHz in the schematics) */
|
||||
XTAL_30MHz = 30000000, /* Impera Magic Card */
|
||||
XTAL_30_4761MHz = 30476100, /* Taito JC */
|
||||
XTAL_30_8MHz = 30800000, /* 15IE-00-013 */
|
||||
|
@ -178,6 +178,7 @@ EMUIMAGEDEVOBJS = \
|
||||
$(EMUIMAGEDEV)/cartslot.o \
|
||||
$(EMUIMAGEDEV)/cassette.o \
|
||||
$(EMUIMAGEDEV)/chd_cd.o \
|
||||
$(EMUIMAGEDEV)/diablo.o \
|
||||
$(EMUIMAGEDEV)/flopdrv.o \
|
||||
$(EMUIMAGEDEV)/floppy.o \
|
||||
$(EMUIMAGEDEV)/harddriv.o \
|
||||
|
288
src/emu/imagedev/diablo.c
Normal file
288
src/emu/imagedev/diablo.c
Normal file
@ -0,0 +1,288 @@
|
||||
/**********************************************************
|
||||
* DIABLO drive image to hard disk interface
|
||||
*
|
||||
* Copyright Juergen Buchmueller <pullmoll@t-online.de>
|
||||
*
|
||||
* Licenses: MAME, GPLv2
|
||||
**********************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "emuopts.h"
|
||||
#include "harddisk.h"
|
||||
#include "diablo.h"
|
||||
|
||||
|
||||
static OPTION_GUIDE_START(dsk_option_guide)
|
||||
OPTION_INT('C', "cylinders", "Cylinders")
|
||||
OPTION_INT('H', "heads", "Heads")
|
||||
OPTION_INT('S', "sectors", "Sectors")
|
||||
OPTION_INT('L', "sectorlength", "Sector Words")
|
||||
OPTION_INT('K', "hunksize", "Hunk Bytes")
|
||||
OPTION_GUIDE_END
|
||||
|
||||
static const char *dsk_option_spec =
|
||||
"C1-[203]-1024;H1/[2]/4/8;S1-[12]-64;L267;K6408";
|
||||
|
||||
|
||||
// device type definition
|
||||
const device_type DIABLO = &device_creator<diablo_image_device>;
|
||||
|
||||
//-------------------------------------------------
|
||||
// diablo_image_device - constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
diablo_image_device::diablo_image_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: device_t(mconfig, DIABLO, "Diablo", tag, owner, clock, "diablo_image", __FILE__),
|
||||
device_image_interface(mconfig, *this),
|
||||
m_chd(NULL),
|
||||
m_hard_disk_handle(NULL),
|
||||
m_device_image_load(device_image_load_delegate()),
|
||||
m_device_image_unload(device_image_func_delegate())
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// diablo_image_device - destructor
|
||||
//-------------------------------------------------
|
||||
|
||||
diablo_image_device::~diablo_image_device()
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_config_complete - perform any
|
||||
// operations now that the configuration is
|
||||
// complete
|
||||
//-------------------------------------------------
|
||||
|
||||
void diablo_image_device::device_config_complete()
|
||||
{
|
||||
// inherit a copy of the static data
|
||||
const diablo_interface *intf = reinterpret_cast<const diablo_interface *>(static_config());
|
||||
if (intf != NULL)
|
||||
*static_cast<diablo_interface *>(this) = *intf;
|
||||
|
||||
// or initialize to defaults if none provided
|
||||
else
|
||||
{
|
||||
memset(&m_interface, 0, sizeof(m_interface));
|
||||
memset(&m_device_displayinfo, 0, sizeof(m_device_displayinfo));
|
||||
}
|
||||
|
||||
m_formatlist.append(*global_alloc(image_device_format("chd", "CHD Hard drive", "chd,dsk", dsk_option_spec)));
|
||||
|
||||
// set brief and instance name
|
||||
update_names();
|
||||
}
|
||||
|
||||
const option_guide *diablo_image_device::create_option_guide() const
|
||||
{
|
||||
return dsk_option_guide;
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
|
||||
void diablo_image_device::device_start()
|
||||
{
|
||||
m_chd = NULL;
|
||||
|
||||
// try to locate the CHD from a DISK_REGION
|
||||
chd_file *handle = get_disk_handle(machine(), tag());
|
||||
if (handle != NULL)
|
||||
{
|
||||
m_hard_disk_handle = hard_disk_open(handle);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_hard_disk_handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void diablo_image_device::device_stop()
|
||||
{
|
||||
if (m_hard_disk_handle)
|
||||
hard_disk_close(m_hard_disk_handle);
|
||||
}
|
||||
|
||||
bool diablo_image_device::call_load()
|
||||
{
|
||||
int our_result;
|
||||
|
||||
our_result = internal_load_dsk();
|
||||
/* Check if there is an image_load callback defined */
|
||||
if (!m_device_image_load.isnull())
|
||||
{
|
||||
/* Let the override do some additional work/checks */
|
||||
our_result = m_device_image_load(*this);
|
||||
}
|
||||
return our_result;
|
||||
|
||||
}
|
||||
|
||||
bool diablo_image_device::call_create(int create_format, option_resolution *create_args)
|
||||
{
|
||||
int err;
|
||||
UINT32 sectorsize, hunksize;
|
||||
UINT32 cylinders, heads, sectors, totalsectors;
|
||||
astring metadata;
|
||||
|
||||
cylinders = option_resolution_lookup_int(create_args, 'C');
|
||||
heads = option_resolution_lookup_int(create_args, 'H');
|
||||
sectors = option_resolution_lookup_int(create_args, 'S');
|
||||
sectorsize = option_resolution_lookup_int(create_args, 'L') * sizeof(UINT16);
|
||||
hunksize = option_resolution_lookup_int(create_args, 'K');
|
||||
|
||||
totalsectors = cylinders * heads * sectors;
|
||||
|
||||
/* create the CHD file */
|
||||
chd_codec_type compression[4] = { CHD_CODEC_NONE };
|
||||
err = m_origchd.create(*image_core_file(), (UINT64)totalsectors * (UINT64)sectorsize, hunksize, sectorsize, compression);
|
||||
if (err != CHDERR_NONE)
|
||||
goto error;
|
||||
|
||||
/* if we created the image and hence, have metadata to set, set the metadata */
|
||||
metadata.format(HARD_DISK_METADATA_FORMAT, cylinders, heads, sectors, sectorsize);
|
||||
err = m_origchd.write_metadata(HARD_DISK_METADATA_TAG, 0, metadata);
|
||||
m_origchd.close();
|
||||
|
||||
if (err != CHDERR_NONE)
|
||||
goto error;
|
||||
|
||||
return internal_load_dsk();
|
||||
|
||||
error:
|
||||
return IMAGE_INIT_FAIL;
|
||||
}
|
||||
|
||||
void diablo_image_device::call_unload()
|
||||
{
|
||||
/* Check if there is an image_unload callback defined */
|
||||
if ( !m_device_image_unload.isnull() )
|
||||
{
|
||||
m_device_image_unload(*this);
|
||||
}
|
||||
|
||||
if (m_hard_disk_handle != NULL)
|
||||
{
|
||||
hard_disk_close(m_hard_disk_handle);
|
||||
m_hard_disk_handle = NULL;
|
||||
}
|
||||
|
||||
m_origchd.close();
|
||||
m_diffchd.close();
|
||||
m_chd = NULL;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------
|
||||
open_disk_diff - open a DISK diff file
|
||||
-------------------------------------------------*/
|
||||
|
||||
static chd_error open_disk_diff(emu_options &options, const char *name, chd_file &source, chd_file &diff_chd)
|
||||
{
|
||||
astring fname(name, ".dif");
|
||||
|
||||
/* try to open the diff */
|
||||
//printf("Opening differencing image file: %s\n", fname.cstr());
|
||||
emu_file diff_file(options.diff_directory(), OPEN_FLAG_READ | OPEN_FLAG_WRITE);
|
||||
file_error filerr = diff_file.open(fname);
|
||||
if (filerr == FILERR_NONE)
|
||||
{
|
||||
astring fullpath(diff_file.fullpath());
|
||||
diff_file.close();
|
||||
|
||||
//printf("Opening differencing image file: %s\n", fullpath.cstr());
|
||||
return diff_chd.open(fullpath, true, &source);
|
||||
}
|
||||
|
||||
/* didn't work; try creating it instead */
|
||||
//printf("Creating differencing image: %s\n", fname.cstr());
|
||||
diff_file.set_openflags(OPEN_FLAG_READ | OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
|
||||
filerr = diff_file.open(fname);
|
||||
if (filerr == FILERR_NONE)
|
||||
{
|
||||
astring fullpath(diff_file.fullpath());
|
||||
diff_file.close();
|
||||
|
||||
/* create the CHD */
|
||||
//printf("Creating differencing image file: %s\n", fullpath.cstr());
|
||||
chd_codec_type compression[4] = { CHD_CODEC_NONE };
|
||||
chd_error err = diff_chd.create(fullpath, source.logical_bytes(), source.hunk_bytes(), compression, source);
|
||||
if (err != CHDERR_NONE)
|
||||
return err;
|
||||
|
||||
return diff_chd.clone_all_metadata(source);
|
||||
}
|
||||
|
||||
return CHDERR_FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
int diablo_image_device::internal_load_dsk()
|
||||
{
|
||||
astring tempstring;
|
||||
chd_error err = CHDERR_NONE;
|
||||
|
||||
m_chd = NULL;
|
||||
|
||||
if (m_hard_disk_handle)
|
||||
hard_disk_close(m_hard_disk_handle);
|
||||
|
||||
/* open the CHD file */
|
||||
if (software_entry() != NULL)
|
||||
{
|
||||
m_chd = get_disk_handle(device().machine(), device().subtag(tempstring,"harddriv"));
|
||||
}
|
||||
else
|
||||
{
|
||||
err = m_origchd.open(*image_core_file(), true);
|
||||
if (err == CHDERR_NONE)
|
||||
{
|
||||
m_chd = &m_origchd;
|
||||
}
|
||||
else if (err == CHDERR_FILE_NOT_WRITEABLE)
|
||||
{
|
||||
err = m_origchd.open(*image_core_file(), false);
|
||||
if (err == CHDERR_NONE)
|
||||
{
|
||||
err = open_disk_diff(device().machine().options(), basename_noext(), m_origchd, m_diffchd);
|
||||
if (err == CHDERR_NONE)
|
||||
{
|
||||
m_chd = &m_diffchd;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_chd != NULL)
|
||||
{
|
||||
/* open the hard disk file */
|
||||
m_hard_disk_handle = hard_disk_open(m_chd);
|
||||
if (m_hard_disk_handle != NULL)
|
||||
return IMAGE_INIT_PASS;
|
||||
}
|
||||
|
||||
/* if we had an error, close out the CHD */
|
||||
m_origchd.close();
|
||||
m_diffchd.close();
|
||||
m_chd = NULL;
|
||||
seterror(IMAGE_ERROR_UNSPECIFIED, chd_file::error_string(err));
|
||||
|
||||
return IMAGE_INIT_FAIL;
|
||||
}
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* Get the CHD file (from the src/chd.c core)
|
||||
* after an image has been opened with the hd core
|
||||
*
|
||||
*************************************/
|
||||
|
||||
chd_file *diablo_image_device::get_chd_file()
|
||||
{
|
||||
chd_file *result = NULL;
|
||||
hard_disk_file *hd_file = get_hard_disk_file();
|
||||
if (hd_file)
|
||||
result = hard_disk_get_chd(hd_file);
|
||||
return result;
|
||||
}
|
100
src/emu/imagedev/diablo.h
Normal file
100
src/emu/imagedev/diablo.h
Normal file
@ -0,0 +1,100 @@
|
||||
/**********************************************************
|
||||
* DIABLO drive image to hard disk interface
|
||||
*
|
||||
* Copyright Juergen Buchmueller <pullmoll@t-online.de>
|
||||
*
|
||||
* Licenses: MAME, GPLv2
|
||||
**********************************************************/
|
||||
|
||||
#ifndef _IMAGEDEV_DIABLO_H_
|
||||
#define _IMAGEDEV_DIABLO_H_
|
||||
|
||||
#include "harddisk.h"
|
||||
|
||||
#define DIABLO_TAG(_id) "diablo"#_id
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
||||
// ======================> diablo_interface
|
||||
|
||||
struct diablo_interface
|
||||
{
|
||||
const char * m_interface;
|
||||
device_image_display_info_func m_device_displayinfo;
|
||||
};
|
||||
|
||||
// ======================> diablo_image_device
|
||||
|
||||
class diablo_image_device : public device_t,
|
||||
public diablo_interface,
|
||||
public device_image_interface
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
diablo_image_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
virtual ~diablo_image_device();
|
||||
|
||||
void set_device_load(device_image_load_delegate _load) { m_device_image_load = _load; }
|
||||
void set_device_unload(device_image_func_delegate _unload) { m_device_image_unload = _unload; }
|
||||
|
||||
// image-level overrides
|
||||
virtual bool call_load();
|
||||
virtual bool call_create(int create_format, option_resolution *create_args);
|
||||
virtual void call_unload();
|
||||
virtual void call_display_info() { if (m_device_displayinfo) m_device_displayinfo(*this); }
|
||||
virtual bool call_softlist_load(software_list_device &swlist, const char *swname, const rom_entry *start_entry) { load_software_part_region(*this, swlist, swname, start_entry ); return TRUE; }
|
||||
|
||||
virtual iodevice_t image_type() const { return IO_HARDDISK; }
|
||||
|
||||
virtual bool is_readable() const { return 1; }
|
||||
virtual bool is_writeable() const { return 1; }
|
||||
virtual bool is_creatable() const { return 0; }
|
||||
virtual bool must_be_loaded() const { return 0; }
|
||||
virtual bool is_reset_on_load() const { return 0; }
|
||||
virtual const char *image_interface() const { return m_interface; }
|
||||
virtual const char *file_extensions() const { return "chd,dsk"; }
|
||||
virtual const option_guide *create_option_guide() const;
|
||||
|
||||
// specific implementation
|
||||
hard_disk_file *get_hard_disk_file() { return m_hard_disk_handle; }
|
||||
chd_file *get_chd_file();
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_config_complete();
|
||||
virtual void device_start();
|
||||
virtual void device_stop();
|
||||
|
||||
int internal_load_dsk();
|
||||
|
||||
chd_file *m_chd;
|
||||
chd_file m_origchd; /* handle to the original CHD */
|
||||
chd_file m_diffchd; /* handle to the diff CHD */
|
||||
hard_disk_file *m_hard_disk_handle;
|
||||
|
||||
device_image_load_delegate m_device_image_load;
|
||||
device_image_func_delegate m_device_image_unload;
|
||||
};
|
||||
|
||||
// device type definition
|
||||
extern const device_type DIABLO;
|
||||
|
||||
/***************************************************************************
|
||||
DEVICE CONFIGURATION MACROS
|
||||
***************************************************************************/
|
||||
|
||||
#define MCFG_DIABLO_ADD(_tag) \
|
||||
MCFG_DEVICE_ADD(_tag, DIABLO, 0)
|
||||
#define MCFG_DIABLO_CONFIG_ADD(_tag,_config) \
|
||||
MCFG_DEVICE_ADD(_tag, DIABLO, 0) \
|
||||
MCFG_DEVICE_CONFIG(_config)
|
||||
|
||||
#define MCFG_DIABLO_LOAD(_class,_load) \
|
||||
static_cast<diablo_image_device *>(device)->set_device_load( DEVICE_IMAGE_LOAD_DELEGATE(_class,_load));
|
||||
|
||||
#define MCFG_DIABLO_UNLOAD(_class,_unload) \
|
||||
static_cast<diablo_image_device *>(device)->set_device_unload( DEVICE_IMAGE_UNLOAD_DELEGATE(_class,_unload));
|
||||
|
||||
#endif /* _IMAGEDEV_DIABLO_H_ */
|
1466
src/emu/machine/diablo_hd.c
Normal file
1466
src/emu/machine/diablo_hd.c
Normal file
File diff suppressed because it is too large
Load Diff
180
src/emu/machine/diablo_hd.h
Normal file
180
src/emu/machine/diablo_hd.h
Normal file
@ -0,0 +1,180 @@
|
||||
/**********************************************************
|
||||
* DIABLO31 and DIABLO44 hard drive support
|
||||
*
|
||||
* Copyright Juergen Buchmueller <pullmoll@t-online.de>
|
||||
*
|
||||
* Licenses: MAME, GPLv2
|
||||
**********************************************************/
|
||||
|
||||
#if !defined(_DIABLO_HD_DEVICE_)
|
||||
#define _DIABLO_HD_DEVICE_
|
||||
|
||||
#include "emu.h"
|
||||
#include "imagedev/diablo.h"
|
||||
|
||||
#ifndef DIABLO_DEBUG
|
||||
#define DIABLO_DEBUG 1 //!< set to 1 to enable debug log output
|
||||
#endif
|
||||
|
||||
#define DIABLO_HD_0 "diablo0"
|
||||
#define DIABLO_HD_1 "diablo1"
|
||||
|
||||
extern const device_type DIABLO_HD;
|
||||
|
||||
class diablo_hd_device : public device_t
|
||||
{
|
||||
public:
|
||||
diablo_hd_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
~diablo_hd_device();
|
||||
|
||||
static const int DIABLO_UNIT_MAX = 2; //!< max number of drive units
|
||||
static const int DIABLO_CYLINDERS = 203; //!< number of cylinders per drive
|
||||
static const int DIABLO_CYLINDER_MASK = 0777; //!< bit maks for cylinder number (9 bits)
|
||||
static const int DIABLO_SPT = 12; //!< number of sectors per track
|
||||
static const int DIABLO_SECTOR_MASK = 017; //!< bit maks for sector number (4 bits)
|
||||
static const int DIABLO_HEADS = 2; //!< number of heads per drive
|
||||
static const int DIABLO_HEAD_MASK = 1; //!< bit maks for head number (1 bit)
|
||||
static const int DIABLO_PAGES = 203*2*12; //!< number of pages per drive
|
||||
//! convert a cylinder/head/sector to a logical block address (page)
|
||||
static inline int DIABLO_PAGE(int c, int h, int s) { return (c * DIABLO_HEADS + h) * DIABLO_SPT + s; }
|
||||
|
||||
void set_sector_callback(void* cookie, void(*callback)(void*, int));
|
||||
|
||||
int bits_per_sector() const;
|
||||
const char* description() const;
|
||||
int unit() const;
|
||||
attotime rotation_time() const;
|
||||
attotime sector_time() const;
|
||||
attotime bit_time() const;
|
||||
|
||||
int get_seek_read_write_0() const;
|
||||
int get_ready_0() const;
|
||||
int get_sector_mark_0() const;
|
||||
int get_addx_acknowledge_0() const;
|
||||
int get_log_addx_interlock_0() const;
|
||||
int get_seek_incomplete_0() const;
|
||||
int get_cylinder() const;
|
||||
int get_head() const;
|
||||
int get_sector() const;
|
||||
int get_page() const;
|
||||
void select(int unit);
|
||||
void set_head(int head);
|
||||
void set_cylinder(int cylinder);
|
||||
void set_restore(int restore);
|
||||
void set_strobe(int strobe);
|
||||
void set_egate(int gate);
|
||||
void set_wrgate(int gate);
|
||||
void set_rdgate(int gate);
|
||||
void wr_data(int index, int wrdata);
|
||||
int rd_data(int index);
|
||||
int rd_clock(int index);
|
||||
|
||||
protected:
|
||||
virtual void device_start();
|
||||
virtual void device_reset();
|
||||
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
|
||||
virtual machine_config_constructor device_mconfig_additions() const;
|
||||
|
||||
private:
|
||||
#if DIABLO_DEBUG
|
||||
int m_log_level;
|
||||
void logprintf(int level, const char* format, ...);
|
||||
# define LOG_DRIVE(x) logprintf x
|
||||
|
||||
#else
|
||||
# define LOG_DRIVE(x)
|
||||
#endif
|
||||
bool m_diablo31; //!< true, if this is a DIABLO31 drive
|
||||
int m_unit; //!< drive unit number (0 or 1)
|
||||
char m_description[32]; //!< description of the drive(s)
|
||||
int m_packs; //!< number of packs in drive (1 or 2)
|
||||
attotime m_rotation_time; //!< rotation time in atto seconds
|
||||
attotime m_sector_time; //!< sector time in atto seconds
|
||||
attotime m_sector_mark_0_time; //!< sector mark going 0 before sector pulse time
|
||||
attotime m_sector_mark_1_time; //!< sector mark going 1 after sector pulse time
|
||||
attotime m_bit_time; //!< bit time in atto seconds
|
||||
int m_s_r_w_0; //!< drive seek/read/write signal (active 0)
|
||||
int m_ready_0; //!< drive ready signal (active 0)
|
||||
int m_sector_mark_0; //!< sector mark (0 if new sector)
|
||||
int m_addx_acknowledge_0; //!< address acknowledge, i.e. seek successful (active 0)
|
||||
int m_log_addx_interlock_0; //!< log address interlock, i.e. seek in progress (active 0)
|
||||
int m_seek_incomplete_0; //!< seek incomplete, i.e. seek in progress (active 0)
|
||||
int m_egate_0; //!< erase gate
|
||||
int m_wrgate_0; //!< write gate
|
||||
int m_rdgate_0; //!< read gate
|
||||
int m_cylinders; //!< total number of cylinders
|
||||
int m_pages; //!< total number of pages
|
||||
int m_seekto; //!< seek to cylinder number
|
||||
int m_restore; //!< restore to cylinder 0 flag
|
||||
int m_cylinder; //!< current cylinder number
|
||||
int m_head; //!< current head (track) number on cylinder
|
||||
int m_sector; //!< current sector number in track
|
||||
int m_page; //!< current page (derived from cylinder, head and sector)
|
||||
UINT8** m_cache; //!< pages raw bytes
|
||||
UINT32** m_bits; //!< pages expanded to bits
|
||||
int m_rdfirst; //!< set to first bit of a sector that is read from
|
||||
int m_rdlast; //!< set to last bit of a sector that was read from
|
||||
int m_wrfirst; //!< set to non-zero if a sector is written to
|
||||
int m_wrlast; //!< set to last bit of a sector that was written to
|
||||
void *m_sector_callback_cookie; //!< cookie to pass to callback
|
||||
void (*m_sector_callback)(void*,int); //!< callback to call at the start of each sector
|
||||
emu_timer* m_timer; //!< sector timer
|
||||
diablo_image_device* m_image; //!< diablo_image_device interfacing the CHD
|
||||
chd_file* m_handle; //!< underlying CHD handle
|
||||
hard_disk_file* m_disk; //!< underlying hard disk file
|
||||
|
||||
//! translate C/H/S to a page and read the sector
|
||||
void read_sector();
|
||||
|
||||
//! compute the checksum of a record
|
||||
int cksum(UINT8 *src, size_t size, int start);
|
||||
|
||||
//! expand a series of clock bits and 0 data bits
|
||||
size_t expand_zeroes(UINT32 *bits, size_t dst, size_t size);
|
||||
|
||||
//! expand a series of 0 words and write a final sync bit
|
||||
size_t expand_sync(UINT32 *bits, size_t dst, size_t size);
|
||||
|
||||
//! expand a record of words into a array of bits at dst
|
||||
size_t expand_record(UINT32 *bits, size_t dst, UINT8 *field, size_t size);
|
||||
|
||||
//! expand a record's checksum word to 32 bits
|
||||
size_t expand_cksum(UINT32 *bits, size_t dst, UINT8 *field, size_t size);
|
||||
|
||||
//! expand a sector into an array of clock and data bits
|
||||
UINT32* expand_sector();
|
||||
|
||||
#if DIABLO_DEBUG
|
||||
//! dump a number of words as ASCII characters
|
||||
void dump_ascii(UINT8 *src, size_t size);
|
||||
|
||||
//! dump a record's contents
|
||||
size_t dump_record(UINT8 *src, size_t addr, size_t size, const char *name, int cr);
|
||||
#endif
|
||||
|
||||
//! find a sync bit in an array of clock and data bits
|
||||
size_t squeeze_sync(UINT32 *bits, size_t src, size_t size);
|
||||
|
||||
//! find a 16 x 0 bits sequence in an array of clock and data bits
|
||||
size_t squeeze_unsync(UINT32 *bits, size_t src, size_t size);
|
||||
|
||||
//! squeeze an array of clock and data bits into a sector's record
|
||||
size_t squeeze_record(UINT32 *bits, size_t src, UINT8 *field, size_t size);
|
||||
|
||||
//! squeeze an array of 32 clock and data bits into a checksum word
|
||||
size_t squeeze_cksum(UINT32 *bits, size_t src, int *cksum);
|
||||
|
||||
//! squeeze a array of clock and data bits into a sector's data
|
||||
void squeeze_sector();
|
||||
|
||||
//! deassert the sector mark
|
||||
void sector_mark_1();
|
||||
|
||||
//! assert the sector mark and read the next sector
|
||||
void sector_mark_0();
|
||||
};
|
||||
|
||||
#define MCFG_DIABLO_DRIVES_ADD() \
|
||||
MCFG_DEVICE_ADD(DIABLO_HD_0, DIABLO_HD, ATTOSECONDS_TO_HZ(attotime::from_nsec(300).as_double())) \
|
||||
MCFG_DEVICE_ADD(DIABLO_HD_1, DIABLO_HD, ATTOSECONDS_TO_HZ(attotime::from_nsec(300).as_double()))
|
||||
#endif // !defined(_DIABLO_HD_DEVICE_)
|
@ -1829,3 +1829,11 @@ ifneq ($(filter WOZFDC,$(MACHINES)),)
|
||||
MACHINEOBJS += $(MACHINEOBJ)/wozfdc.o
|
||||
endif
|
||||
|
||||
#-------------------------------------------------
|
||||
#
|
||||
#@src/emu/machine/diablo_hd.h,MACHINES += DIABLO_HD
|
||||
#-------------------------------------------------
|
||||
ifneq ($(filter DIABLO_HD,$(MACHINES)),)
|
||||
MACHINEOBJS += $(MACHINEOBJ)/diablo_hd.o
|
||||
endif
|
||||
|
||||
|
@ -219,8 +219,19 @@ void CLIB_DECL logerror(const char *format, ...)
|
||||
{
|
||||
va_list arg;
|
||||
va_start(arg, format);
|
||||
if (global_machine != NULL)
|
||||
global_machine->vlogerror(format, arg);
|
||||
vlogerror(format, arg);
|
||||
va_end(arg);
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
vlogerror - log to the debugger and any other
|
||||
OSD-defined output streams
|
||||
-------------------------------------------------*/
|
||||
|
||||
void CLIB_DECL vlogerror(const char *format, va_list arg)
|
||||
{
|
||||
if (global_machine != NULL)
|
||||
global_machine->vlogerror(format, arg);
|
||||
}
|
||||
|
||||
|
@ -101,6 +101,7 @@ void CLIB_DECL popmessage(const char *format, ...) ATTR_PRINTF(1,2);
|
||||
|
||||
// log to the standard error.log file
|
||||
void CLIB_DECL logerror(const char *format, ...) ATTR_PRINTF(1,2);
|
||||
void CLIB_DECL vlogerror(const char *format, va_list arg);
|
||||
|
||||
|
||||
#endif /* __MAME_H__ */
|
||||
|
304
src/mess/drivers/alto2.c
Normal file
304
src/mess/drivers/alto2.c
Normal file
@ -0,0 +1,304 @@
|
||||
/***************************************************************************
|
||||
* Xerox AltoII driver for MESS
|
||||
*
|
||||
* Copyright Juergen Buchmueller <pullmoll@t-online.de>
|
||||
*
|
||||
* Licenses: MAME, GPLv2
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "rendlay.h"
|
||||
#include "cpu/alto2/alto2cpu.h"
|
||||
#include "machine/diablo_hd.h"
|
||||
|
||||
class alto2_state : public driver_device
|
||||
{
|
||||
public:
|
||||
alto2_state(const machine_config &mconfig, device_type type, const char *tag) :
|
||||
driver_device(mconfig, type, tag),
|
||||
m_maincpu(*this, "maincpu"),
|
||||
m_io_row0(*this, "ROW0"),
|
||||
m_io_row1(*this, "ROW1"),
|
||||
m_io_row2(*this, "ROW2"),
|
||||
m_io_row3(*this, "ROW3"),
|
||||
m_io_row4(*this, "ROW4"),
|
||||
m_io_row5(*this, "ROW5"),
|
||||
m_io_row6(*this, "ROW6"),
|
||||
m_io_row7(*this, "ROW7"),
|
||||
m_io_config(*this, "CONFIG")
|
||||
{ }
|
||||
|
||||
DECLARE_DRIVER_INIT(alto2);
|
||||
DECLARE_MACHINE_RESET(alto2);
|
||||
|
||||
protected:
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_ioport m_io_row0;
|
||||
required_ioport m_io_row1;
|
||||
required_ioport m_io_row2;
|
||||
required_ioport m_io_row3;
|
||||
required_ioport m_io_row4;
|
||||
required_ioport m_io_row5;
|
||||
required_ioport m_io_row6;
|
||||
required_ioport m_io_row7;
|
||||
optional_ioport m_io_config;
|
||||
};
|
||||
|
||||
/* Input Ports */
|
||||
|
||||
#define PORT_KEY(_bit,_code,_char1,_char2,_name) \
|
||||
PORT_BIT(_bit, IP_ACTIVE_LOW, IPT_KEYBOARD) \
|
||||
PORT_CODE(_code) PORT_NAME(_name) \
|
||||
PORT_CHAR(_char1) PORT_CHAR(_char2)
|
||||
#define SPACING " "
|
||||
|
||||
static INPUT_PORTS_START( alto2 )
|
||||
PORT_START("ROW0")
|
||||
PORT_KEY(A2_KEY_5, KEYCODE_5, '5', '%', "5" SPACING "%") //!< normal: 5 shifted: %
|
||||
PORT_KEY(A2_KEY_4, KEYCODE_4, '4', '$', "4" SPACING "$") //!< normal: 4 shifted: $
|
||||
PORT_KEY(A2_KEY_6, KEYCODE_6, '6', '~', "6" SPACING "~") //!< normal: 6 shifted: ~
|
||||
PORT_KEY(A2_KEY_E, KEYCODE_E, 'e', 'E', "e" SPACING "E") //!< normal: e shifted: E
|
||||
PORT_KEY(A2_KEY_7, KEYCODE_7, '7', '&', "7" SPACING "&") //!< normal: 7 shifted: &
|
||||
PORT_KEY(A2_KEY_D, KEYCODE_D, 'd', 'D', "d" SPACING "D") //!< normal: d shifted: D
|
||||
PORT_KEY(A2_KEY_U, KEYCODE_U, 'u', 'U', "u" SPACING "U") //!< normal: u shifted: U
|
||||
PORT_KEY(A2_KEY_V, KEYCODE_V, 'v', 'V', "v" SPACING "V") //!< normal: v shifted: V
|
||||
PORT_KEY(A2_KEY_0, KEYCODE_0, '0', ')', "0" SPACING ")") //!< normal: 0 shifted: )
|
||||
PORT_KEY(A2_KEY_K, KEYCODE_K, 'k', 'K', "k" SPACING "K") //!< normal: k shifted: K
|
||||
PORT_KEY(A2_KEY_MINUS, KEYCODE_MINUS, '-', '_', "-" SPACING "_") //!< normal: - shifted: _
|
||||
PORT_KEY(A2_KEY_P, KEYCODE_P, 'p', 'P', "p" SPACING "P") //!< normal: p shifted: P
|
||||
PORT_KEY(A2_KEY_SLASH, KEYCODE_SLASH, '/', '?', "/" SPACING "?") //!< normal: / shifted: ?
|
||||
PORT_KEY(A2_KEY_BACKSLASH, KEYCODE_BACKSLASH, '\\', '|', "\\" SPACING "|") //!< normal: \ shifted: |
|
||||
PORT_KEY(A2_KEY_LF, KEYCODE_DOWN, 10, 10, "LF" ) //!< normal: LF shifted: ?
|
||||
PORT_KEY(A2_KEY_BS, KEYCODE_BACKSPACE, 8, 8, "BS" ) //!< normal: BS shifted: ?
|
||||
|
||||
PORT_START("ROW1")
|
||||
PORT_KEY(A2_KEY_3, KEYCODE_3, '3', '#', "3" SPACING "#") //!< normal: 3 shifted: #
|
||||
PORT_KEY(A2_KEY_2, KEYCODE_2, '2', '@', "2" SPACING "@") //!< normal: 2 shifted: @
|
||||
PORT_KEY(A2_KEY_W, KEYCODE_W, 'w', 'W', "w" SPACING "W") //!< normal: w shifted: W
|
||||
PORT_KEY(A2_KEY_Q, KEYCODE_Q, 'q', 'Q', "q" SPACING "Q") //!< normal: q shifted: Q
|
||||
PORT_KEY(A2_KEY_S, KEYCODE_S, 's', 'S', "s" SPACING "S") //!< normal: s shifted: S
|
||||
PORT_KEY(A2_KEY_A, KEYCODE_A, 'a', 'A', "a" SPACING "A") //!< normal: a shifted: A
|
||||
PORT_KEY(A2_KEY_9, KEYCODE_9, '9', '(', "9" SPACING "(") //!< normal: 9 shifted: (
|
||||
PORT_KEY(A2_KEY_I, KEYCODE_I, 'i', 'I', "i" SPACING "I") //!< normal: i shifted: I
|
||||
PORT_KEY(A2_KEY_X, KEYCODE_X, 'x', 'X', "x" SPACING "X") //!< normal: x shifted: X
|
||||
PORT_KEY(A2_KEY_O, KEYCODE_O, 'o', 'O', "o" SPACING "O") //!< normal: o shifted: O
|
||||
PORT_KEY(A2_KEY_L, KEYCODE_L, 'l', 'L', "l" SPACING "L") //!< normal: l shifted: L
|
||||
PORT_KEY(A2_KEY_COMMA, KEYCODE_COMMA, ',', '<', "," SPACING "<") //!< normal: , shifted: <
|
||||
PORT_KEY(A2_KEY_QUOTE, KEYCODE_QUOTE, 39, 34, "'" SPACING "\"") //!< normal: ' shifted: "
|
||||
PORT_KEY(A2_KEY_RBRACKET, KEYCODE_CLOSEBRACE, ']', '}', "]" SPACING "}") //!< normal: ] shifted: }
|
||||
PORT_KEY(A2_KEY_BLANK_MID, KEYCODE_END, 0, 0, "MID" ) //!< middle blank key
|
||||
PORT_KEY(A2_KEY_BLANK_TOP, KEYCODE_PGUP, 0, 0, "TOP" ) //!< top blank key
|
||||
|
||||
PORT_START("ROW2")
|
||||
PORT_KEY(A2_KEY_1, KEYCODE_1, '1', '!', "1" SPACING "!") //!< normal: 1 shifted: !
|
||||
PORT_KEY(A2_KEY_ESCAPE, KEYCODE_ESC, 27, 0, "ESC" ) //!< normal: ESC shifted: ?
|
||||
PORT_KEY(A2_KEY_TAB, KEYCODE_TAB, 9, 0, "TAB" ) //!< normal: TAB shifted: ?
|
||||
PORT_KEY(A2_KEY_F, KEYCODE_F, 'f', 'F', "f" SPACING "F") //!< normal: f shifted: F
|
||||
PORT_KEY(A2_KEY_CTRL, KEYCODE_LCONTROL, 0, 0, "CTRL" ) //!< CTRL
|
||||
PORT_KEY(A2_KEY_C, KEYCODE_C, 'c', 'C', "c" SPACING "C") //!< normal: c shifted: C
|
||||
PORT_KEY(A2_KEY_J, KEYCODE_J, 'j', 'J', "j" SPACING "J") //!< normal: j shifted: J
|
||||
PORT_KEY(A2_KEY_B, KEYCODE_B, 'b', 'B', "b" SPACING "B") //!< normal: b shifted: B
|
||||
PORT_KEY(A2_KEY_Z, KEYCODE_Z, 'z', 'Z', "z" SPACING "Z") //!< normal: z shifted: Z
|
||||
PORT_KEY(A2_KEY_LSHIFT, KEYCODE_LSHIFT, UCHAR_SHIFT_1, 0, "LSHIFT" ) //!< LSHIFT
|
||||
PORT_KEY(A2_KEY_PERIOD, KEYCODE_STOP, '.', '>', "." SPACING ">") //!< normal: . shifted: >
|
||||
PORT_KEY(A2_KEY_SEMICOLON, KEYCODE_COLON, ';', ':', ";" SPACING ":") //!< normal: ; shifted: :
|
||||
PORT_KEY(A2_KEY_RETURN, KEYCODE_ENTER, 13, 0, "RETURN" ) //!< RETURN
|
||||
PORT_KEY(A2_KEY_LEFTARROW, KEYCODE_LEFT, 0, 0, "???" SPACING "???") //!< normal: left arrow shifted: up arrow (caret)
|
||||
PORT_KEY(A2_KEY_DEL, KEYCODE_DEL, UCHAR_MAMEKEY(DEL), 0, "DEL" ) //!< normal: DEL shifted: ?
|
||||
PORT_KEY(A2_KEY_MSW_2_17, KEYCODE_MENU, 0, 0, "MSW2/17" ) //!< unused on Microswitch KDB
|
||||
|
||||
PORT_START("ROW3")
|
||||
PORT_KEY(A2_KEY_R, KEYCODE_R, 'r', 'R', "r" SPACING "R") //!< normal: r shifted: R
|
||||
PORT_KEY(A2_KEY_T, KEYCODE_T, 't', 'T', "t" SPACING "T") //!< normal: t shifted: T
|
||||
PORT_KEY(A2_KEY_G, KEYCODE_G, 'g', 'G', "g" SPACING "G") //!< normal: g shifted: G
|
||||
PORT_KEY(A2_KEY_Y, KEYCODE_Y, 'y', 'Y', "y" SPACING "Y") //!< normal: y shifted: Y
|
||||
PORT_KEY(A2_KEY_H, KEYCODE_H, 'h', 'H', "h" SPACING "H") //!< normal: h shifted: H
|
||||
PORT_KEY(A2_KEY_8, KEYCODE_8, '8', '*', "8" SPACING "*") //!< normal: 8 shifted: *
|
||||
PORT_KEY(A2_KEY_N, KEYCODE_N, 'n', 'N', "n" SPACING "N") //!< normal: n shifted: N
|
||||
PORT_KEY(A2_KEY_M, KEYCODE_M, 'm', 'M', "m" SPACING "M") //!< normal: m shifted: M
|
||||
PORT_KEY(A2_KEY_LOCK, KEYCODE_SCRLOCK, 0, 0, "LOCK" ) //!< LOCK
|
||||
PORT_KEY(A2_KEY_SPACE, KEYCODE_SPACE, 32, 0, "SPACE" ) //!< SPACE
|
||||
PORT_KEY(A2_KEY_LBRACKET, KEYCODE_OPENBRACE, '[', '{', "[" SPACING "{") //!< normal: [ shifted: {
|
||||
PORT_KEY(A2_KEY_EQUALS, KEYCODE_EQUALS, '=', '+', "=" SPACING "+") //!< normal: = shifted: +
|
||||
PORT_KEY(A2_KEY_RSHIFT, KEYCODE_RSHIFT, UCHAR_SHIFT_2, 0, "RSHIFT" ) //!< RSHIFT
|
||||
PORT_KEY(A2_KEY_BLANK_BOT, KEYCODE_PGDN, 0, 0, "BOT" ) //!< bottom blank key
|
||||
PORT_KEY(A2_KEY_MSW_3_16, KEYCODE_HOME, 0, 0, "MSW3/16" ) //!< unused on Microswitch KDB
|
||||
PORT_KEY(A2_KEY_MSW_3_17, KEYCODE_INSERT, 0, 0, "MSW3/17" ) //!< unused on Microswitch KDB
|
||||
|
||||
PORT_START("ROW4")
|
||||
PORT_KEY(A2_KEY_FR2, KEYCODE_F6, 0, 0, "FR2" ) //!< ADL right function key 2
|
||||
PORT_KEY(A2_KEY_FL2, KEYCODE_F2, 0, 0, "FL2" ) //!< ADL left function key 2
|
||||
|
||||
PORT_START("ROW5")
|
||||
PORT_KEY(A2_KEY_FR4, KEYCODE_F8, 0, 0, "FR4" ) //!< ADL right funtion key 4
|
||||
PORT_KEY(A2_KEY_BW, KEYCODE_F10, 0, 0, "BW" ) //!< ADL BW (?)
|
||||
|
||||
PORT_START("ROW6")
|
||||
PORT_KEY(A2_KEY_FR3, KEYCODE_F7, 0, 0, "FR3" ) //!< ADL right function key 3
|
||||
PORT_KEY(A2_KEY_FL1, KEYCODE_F1, 0, 0, "FL1" ) //!< ADL left function key 1
|
||||
PORT_KEY(A2_KEY_FL3, KEYCODE_F3, 0, 0, "FL3" ) //!< ADL left function key 3
|
||||
|
||||
PORT_START("ROW7")
|
||||
PORT_KEY(A2_KEY_FR1, KEYCODE_F5, 0, 0, "FR1" ) //!< ADL right function key 1
|
||||
PORT_KEY(A2_KEY_FL4, KEYCODE_F4, 0, 0, "FL4" ) //!< ADL left function key 4
|
||||
PORT_KEY(A2_KEY_FR5, KEYCODE_F9, 0, 0, "FR5" ) //!< ADL right function key 5
|
||||
|
||||
PORT_START("mouseb0") // Mouse button 0
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("Mouse RED (left)") PORT_PLAYER(1) PORT_CODE(MOUSECODE_BUTTON1) PORT_CHANGED_MEMBER( ":maincpu", alto2_cpu_device, mouse_button_0, 0 )
|
||||
PORT_START("mouseb1") // Mouse button 1
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_NAME("Mouse BLUE (right)") PORT_PLAYER(1) PORT_CODE(MOUSECODE_BUTTON2) PORT_CHANGED_MEMBER( ":maincpu", alto2_cpu_device, mouse_button_1, 0 )
|
||||
PORT_START("mouseb2") // Mouse button 2
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON3) PORT_NAME("Mouse YELLOW (middle)") PORT_PLAYER(1) PORT_CODE(MOUSECODE_BUTTON3) PORT_CHANGED_MEMBER( ":maincpu", alto2_cpu_device, mouse_button_2, 0 )
|
||||
|
||||
PORT_START("mousex") // Mouse - X AXIS
|
||||
PORT_BIT( 0xffff, 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(100) PORT_KEYDELTA(1) PORT_CHANGED_MEMBER( ":maincpu", alto2_cpu_device, mouse_motion_x, 0 )
|
||||
|
||||
PORT_START("mousey") // Mouse - Y AXIS
|
||||
PORT_BIT( 0xffff, 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(100) PORT_KEYDELTA(1) PORT_CHANGED_MEMBER( ":maincpu", alto2_cpu_device, mouse_motion_y, 0 )
|
||||
|
||||
PORT_START("CONFIG") /* Memory switch on AIM board */
|
||||
PORT_CONFNAME( 0x01, 0x01, "Memory switch")
|
||||
PORT_CONFSETTING( 0x00, "on")
|
||||
PORT_CONFSETTING( 0x01, "off")
|
||||
PORT_CONFNAME( 0x70, 0x00, "Ethernet breath-of-life")
|
||||
PORT_CONFSETTING( 0x00, "off")
|
||||
PORT_CONFSETTING( 0x10, "5 seconds")
|
||||
PORT_CONFSETTING( 0x20, "10 seconds")
|
||||
PORT_CONFSETTING( 0x30, "15 seconds")
|
||||
PORT_CONFSETTING( 0x40, "30 seconds")
|
||||
PORT_CONFSETTING( 0x50, "60 seconds")
|
||||
PORT_CONFSETTING( 0x60, "90 seconds")
|
||||
PORT_CONFSETTING( 0x70, "120 seconds")
|
||||
|
||||
PORT_START("ETHERID")
|
||||
PORT_DIPNAME( 0377, 0042, "Ethernet ID")
|
||||
PORT_DIPSETTING( 0000, "No ether") PORT_DIPSETTING( 0001, "ID 001") PORT_DIPSETTING( 0002, "ID 002") PORT_DIPSETTING( 0003, "ID 003")
|
||||
PORT_DIPSETTING( 0004, "ID 004") PORT_DIPSETTING( 0005, "ID 005") PORT_DIPSETTING( 0006, "ID 006") PORT_DIPSETTING( 0007, "ID 007")
|
||||
PORT_DIPSETTING( 0010, "ID 010") PORT_DIPSETTING( 0011, "ID 011") PORT_DIPSETTING( 0012, "ID 012") PORT_DIPSETTING( 0013, "ID 013")
|
||||
PORT_DIPSETTING( 0014, "ID 014") PORT_DIPSETTING( 0015, "ID 015") PORT_DIPSETTING( 0016, "ID 016") PORT_DIPSETTING( 0017, "ID 017")
|
||||
PORT_DIPSETTING( 0020, "ID 020") PORT_DIPSETTING( 0021, "ID 021") PORT_DIPSETTING( 0022, "ID 022") PORT_DIPSETTING( 0023, "ID 023")
|
||||
PORT_DIPSETTING( 0024, "ID 024") PORT_DIPSETTING( 0025, "ID 025") PORT_DIPSETTING( 0026, "ID 026") PORT_DIPSETTING( 0027, "ID 027")
|
||||
PORT_DIPSETTING( 0030, "ID 030") PORT_DIPSETTING( 0031, "ID 031") PORT_DIPSETTING( 0032, "ID 032") PORT_DIPSETTING( 0033, "ID 033")
|
||||
PORT_DIPSETTING( 0034, "ID 034") PORT_DIPSETTING( 0035, "ID 035") PORT_DIPSETTING( 0036, "ID 036") PORT_DIPSETTING( 0037, "ID 037")
|
||||
PORT_DIPSETTING( 0040, "ID 040") PORT_DIPSETTING( 0041, "ID 041") PORT_DIPSETTING( 0042, "ID 042") PORT_DIPSETTING( 0043, "ID 043")
|
||||
PORT_DIPSETTING( 0044, "ID 044") PORT_DIPSETTING( 0045, "ID 045") PORT_DIPSETTING( 0046, "ID 046") PORT_DIPSETTING( 0047, "ID 047")
|
||||
PORT_DIPSETTING( 0050, "ID 050") PORT_DIPSETTING( 0051, "ID 051") PORT_DIPSETTING( 0052, "ID 052") PORT_DIPSETTING( 0053, "ID 053")
|
||||
PORT_DIPSETTING( 0054, "ID 054") PORT_DIPSETTING( 0055, "ID 055") PORT_DIPSETTING( 0056, "ID 056") PORT_DIPSETTING( 0057, "ID 057")
|
||||
PORT_DIPSETTING( 0060, "ID 060") PORT_DIPSETTING( 0061, "ID 061") PORT_DIPSETTING( 0062, "ID 062") PORT_DIPSETTING( 0063, "ID 063")
|
||||
PORT_DIPSETTING( 0064, "ID 064") PORT_DIPSETTING( 0065, "ID 065") PORT_DIPSETTING( 0066, "ID 066") PORT_DIPSETTING( 0067, "ID 067")
|
||||
PORT_DIPSETTING( 0070, "ID 070") PORT_DIPSETTING( 0071, "ID 071") PORT_DIPSETTING( 0072, "ID 072") PORT_DIPSETTING( 0073, "ID 073")
|
||||
PORT_DIPSETTING( 0074, "ID 074") PORT_DIPSETTING( 0075, "ID 075") PORT_DIPSETTING( 0076, "ID 076") PORT_DIPSETTING( 0077, "ID 077")
|
||||
PORT_DIPSETTING( 0100, "ID 100") PORT_DIPSETTING( 0101, "ID 101") PORT_DIPSETTING( 0102, "ID 102") PORT_DIPSETTING( 0103, "ID 103")
|
||||
PORT_DIPSETTING( 0104, "ID 104") PORT_DIPSETTING( 0105, "ID 105") PORT_DIPSETTING( 0106, "ID 106") PORT_DIPSETTING( 0107, "ID 107")
|
||||
PORT_DIPSETTING( 0110, "ID 110") PORT_DIPSETTING( 0111, "ID 111") PORT_DIPSETTING( 0112, "ID 112") PORT_DIPSETTING( 0113, "ID 113")
|
||||
PORT_DIPSETTING( 0114, "ID 114") PORT_DIPSETTING( 0115, "ID 115") PORT_DIPSETTING( 0116, "ID 116") PORT_DIPSETTING( 0117, "ID 117")
|
||||
PORT_DIPSETTING( 0120, "ID 120") PORT_DIPSETTING( 0121, "ID 121") PORT_DIPSETTING( 0122, "ID 122") PORT_DIPSETTING( 0123, "ID 123")
|
||||
PORT_DIPSETTING( 0124, "ID 124") PORT_DIPSETTING( 0125, "ID 125") PORT_DIPSETTING( 0126, "ID 126") PORT_DIPSETTING( 0127, "ID 127")
|
||||
PORT_DIPSETTING( 0130, "ID 130") PORT_DIPSETTING( 0131, "ID 131") PORT_DIPSETTING( 0132, "ID 132") PORT_DIPSETTING( 0133, "ID 133")
|
||||
PORT_DIPSETTING( 0134, "ID 134") PORT_DIPSETTING( 0135, "ID 135") PORT_DIPSETTING( 0136, "ID 136") PORT_DIPSETTING( 0137, "ID 137")
|
||||
PORT_DIPSETTING( 0140, "ID 140") PORT_DIPSETTING( 0141, "ID 141") PORT_DIPSETTING( 0142, "ID 142") PORT_DIPSETTING( 0143, "ID 143")
|
||||
PORT_DIPSETTING( 0144, "ID 144") PORT_DIPSETTING( 0145, "ID 145") PORT_DIPSETTING( 0146, "ID 146") PORT_DIPSETTING( 0147, "ID 147")
|
||||
PORT_DIPSETTING( 0150, "ID 150") PORT_DIPSETTING( 0151, "ID 151") PORT_DIPSETTING( 0152, "ID 152") PORT_DIPSETTING( 0153, "ID 153")
|
||||
PORT_DIPSETTING( 0154, "ID 154") PORT_DIPSETTING( 0155, "ID 155") PORT_DIPSETTING( 0156, "ID 156") PORT_DIPSETTING( 0157, "ID 157")
|
||||
PORT_DIPSETTING( 0160, "ID 160") PORT_DIPSETTING( 0161, "ID 161") PORT_DIPSETTING( 0162, "ID 162") PORT_DIPSETTING( 0163, "ID 163")
|
||||
PORT_DIPSETTING( 0164, "ID 164") PORT_DIPSETTING( 0165, "ID 165") PORT_DIPSETTING( 0166, "ID 166") PORT_DIPSETTING( 0167, "ID 167")
|
||||
PORT_DIPSETTING( 0170, "ID 170") PORT_DIPSETTING( 0171, "ID 171") PORT_DIPSETTING( 0172, "ID 172") PORT_DIPSETTING( 0173, "ID 173")
|
||||
PORT_DIPSETTING( 0174, "ID 174") PORT_DIPSETTING( 0175, "ID 175") PORT_DIPSETTING( 0176, "ID 176") PORT_DIPSETTING( 0177, "ID 177")
|
||||
PORT_DIPSETTING( 0200, "ID 200") PORT_DIPSETTING( 0201, "ID 201") PORT_DIPSETTING( 0202, "ID 202") PORT_DIPSETTING( 0203, "ID 203")
|
||||
PORT_DIPSETTING( 0204, "ID 204") PORT_DIPSETTING( 0205, "ID 205") PORT_DIPSETTING( 0206, "ID 206") PORT_DIPSETTING( 0207, "ID 207")
|
||||
PORT_DIPSETTING( 0210, "ID 210") PORT_DIPSETTING( 0211, "ID 211") PORT_DIPSETTING( 0212, "ID 212") PORT_DIPSETTING( 0213, "ID 213")
|
||||
PORT_DIPSETTING( 0214, "ID 214") PORT_DIPSETTING( 0215, "ID 215") PORT_DIPSETTING( 0216, "ID 216") PORT_DIPSETTING( 0217, "ID 217")
|
||||
PORT_DIPSETTING( 0220, "ID 220") PORT_DIPSETTING( 0221, "ID 221") PORT_DIPSETTING( 0222, "ID 222") PORT_DIPSETTING( 0223, "ID 223")
|
||||
PORT_DIPSETTING( 0224, "ID 224") PORT_DIPSETTING( 0225, "ID 225") PORT_DIPSETTING( 0226, "ID 226") PORT_DIPSETTING( 0227, "ID 227")
|
||||
PORT_DIPSETTING( 0230, "ID 230") PORT_DIPSETTING( 0231, "ID 231") PORT_DIPSETTING( 0232, "ID 232") PORT_DIPSETTING( 0233, "ID 233")
|
||||
PORT_DIPSETTING( 0234, "ID 234") PORT_DIPSETTING( 0235, "ID 235") PORT_DIPSETTING( 0236, "ID 236") PORT_DIPSETTING( 0237, "ID 237")
|
||||
PORT_DIPSETTING( 0240, "ID 240") PORT_DIPSETTING( 0241, "ID 241") PORT_DIPSETTING( 0242, "ID 242") PORT_DIPSETTING( 0243, "ID 243")
|
||||
PORT_DIPSETTING( 0244, "ID 244") PORT_DIPSETTING( 0245, "ID 245") PORT_DIPSETTING( 0246, "ID 246") PORT_DIPSETTING( 0247, "ID 247")
|
||||
PORT_DIPSETTING( 0250, "ID 250") PORT_DIPSETTING( 0251, "ID 251") PORT_DIPSETTING( 0252, "ID 252") PORT_DIPSETTING( 0253, "ID 253")
|
||||
PORT_DIPSETTING( 0254, "ID 254") PORT_DIPSETTING( 0255, "ID 255") PORT_DIPSETTING( 0256, "ID 256") PORT_DIPSETTING( 0257, "ID 257")
|
||||
PORT_DIPSETTING( 0260, "ID 260") PORT_DIPSETTING( 0261, "ID 261") PORT_DIPSETTING( 0262, "ID 262") PORT_DIPSETTING( 0263, "ID 263")
|
||||
PORT_DIPSETTING( 0264, "ID 264") PORT_DIPSETTING( 0265, "ID 265") PORT_DIPSETTING( 0266, "ID 266") PORT_DIPSETTING( 0267, "ID 267")
|
||||
PORT_DIPSETTING( 0270, "ID 270") PORT_DIPSETTING( 0271, "ID 271") PORT_DIPSETTING( 0272, "ID 272") PORT_DIPSETTING( 0273, "ID 273")
|
||||
PORT_DIPSETTING( 0274, "ID 274") PORT_DIPSETTING( 0275, "ID 275") PORT_DIPSETTING( 0276, "ID 276") PORT_DIPSETTING( 0277, "ID 277")
|
||||
PORT_DIPSETTING( 0300, "ID 300") PORT_DIPSETTING( 0301, "ID 301") PORT_DIPSETTING( 0302, "ID 302") PORT_DIPSETTING( 0303, "ID 303")
|
||||
PORT_DIPSETTING( 0304, "ID 304") PORT_DIPSETTING( 0305, "ID 305") PORT_DIPSETTING( 0306, "ID 306") PORT_DIPSETTING( 0307, "ID 307")
|
||||
PORT_DIPSETTING( 0310, "ID 310") PORT_DIPSETTING( 0311, "ID 311") PORT_DIPSETTING( 0312, "ID 312") PORT_DIPSETTING( 0313, "ID 313")
|
||||
PORT_DIPSETTING( 0314, "ID 314") PORT_DIPSETTING( 0315, "ID 315") PORT_DIPSETTING( 0316, "ID 316") PORT_DIPSETTING( 0317, "ID 317")
|
||||
PORT_DIPSETTING( 0320, "ID 320") PORT_DIPSETTING( 0321, "ID 321") PORT_DIPSETTING( 0322, "ID 322") PORT_DIPSETTING( 0323, "ID 323")
|
||||
PORT_DIPSETTING( 0324, "ID 324") PORT_DIPSETTING( 0325, "ID 325") PORT_DIPSETTING( 0326, "ID 326") PORT_DIPSETTING( 0327, "ID 327")
|
||||
PORT_DIPSETTING( 0330, "ID 330") PORT_DIPSETTING( 0331, "ID 331") PORT_DIPSETTING( 0332, "ID 332") PORT_DIPSETTING( 0333, "ID 333")
|
||||
PORT_DIPSETTING( 0334, "ID 334") PORT_DIPSETTING( 0335, "ID 335") PORT_DIPSETTING( 0336, "ID 336") PORT_DIPSETTING( 0337, "ID 337")
|
||||
PORT_DIPSETTING( 0340, "ID 340") PORT_DIPSETTING( 0341, "ID 341") PORT_DIPSETTING( 0342, "ID 342") PORT_DIPSETTING( 0343, "ID 343")
|
||||
PORT_DIPSETTING( 0344, "ID 344") PORT_DIPSETTING( 0345, "ID 345") PORT_DIPSETTING( 0346, "ID 346") PORT_DIPSETTING( 0347, "ID 347")
|
||||
PORT_DIPSETTING( 0350, "ID 350") PORT_DIPSETTING( 0351, "ID 351") PORT_DIPSETTING( 0352, "ID 352") PORT_DIPSETTING( 0353, "ID 353")
|
||||
PORT_DIPSETTING( 0354, "ID 354") PORT_DIPSETTING( 0355, "ID 355") PORT_DIPSETTING( 0356, "ID 356") PORT_DIPSETTING( 0357, "ID 357")
|
||||
PORT_DIPSETTING( 0360, "ID 360") PORT_DIPSETTING( 0361, "ID 361") PORT_DIPSETTING( 0362, "ID 362") PORT_DIPSETTING( 0363, "ID 363")
|
||||
PORT_DIPSETTING( 0364, "ID 364") PORT_DIPSETTING( 0365, "ID 365") PORT_DIPSETTING( 0366, "ID 366") PORT_DIPSETTING( 0367, "ID 367")
|
||||
PORT_DIPSETTING( 0370, "ID 370") PORT_DIPSETTING( 0371, "ID 371") PORT_DIPSETTING( 0372, "ID 372") PORT_DIPSETTING( 0373, "ID 373")
|
||||
PORT_DIPSETTING( 0374, "ID 374") PORT_DIPSETTING( 0375, "ID 375")
|
||||
INPUT_PORTS_END
|
||||
|
||||
/* ROM */
|
||||
ROM_START( alto2 )
|
||||
// dummy region for the maincpu - this is not used in any way
|
||||
ROM_REGION( 0400, "maincpu", 0 )
|
||||
ROM_FILL(0, 0400, ALTO2_UCODE_INVERTED)
|
||||
ROM_END
|
||||
|
||||
//**************************************************************************
|
||||
// ADDRESS MAPS
|
||||
//**************************************************************************
|
||||
|
||||
ADDRESS_MAP_START( alto2_ucode_map, AS_0, 32, alto2_state )
|
||||
AM_RANGE(0, ALTO2_UCODE_SIZE-1) AM_DEVICE32( "maincpu", alto2_cpu_device, ucode_map, 0xffffffffUL )
|
||||
ADDRESS_MAP_END
|
||||
|
||||
ADDRESS_MAP_START( alto2_const_map, AS_1, 16, alto2_state )
|
||||
AM_RANGE(0, ALTO2_CONST_SIZE-1) AM_DEVICE16( "maincpu", alto2_cpu_device, const_map, 0xffffU )
|
||||
ADDRESS_MAP_END
|
||||
|
||||
ADDRESS_MAP_START( alto2_iomem_map, AS_2, 16, alto2_state )
|
||||
AM_RANGE(0, 2*ALTO2_RAM_SIZE-1) AM_DEVICE16( "maincpu", alto2_cpu_device, iomem_map, 0xffffU )
|
||||
ADDRESS_MAP_END
|
||||
|
||||
static MACHINE_CONFIG_START( alto2, alto2_state )
|
||||
/* basic machine hardware */
|
||||
// SYSCLK is Display Control part A51 (tagged 29.4MHz) divided by 5(?)
|
||||
// 5.8MHz according to de.wikipedia.org/wiki/Xerox_Alto
|
||||
MCFG_CPU_ADD("maincpu", ALTO2, XTAL_29_4912MHz/5)
|
||||
MCFG_CPU_PROGRAM_MAP(alto2_ucode_map)
|
||||
MCFG_CPU_DATA_MAP(alto2_const_map)
|
||||
MCFG_CPU_IO_MAP(alto2_iomem_map)
|
||||
|
||||
/* video hardware */
|
||||
MCFG_SCREEN_ADD("screen", RASTER)
|
||||
MCFG_SCREEN_RAW_PARAMS(XTAL_20_16MHz,
|
||||
ALTO2_DISPLAY_TOTAL_WIDTH, 0, ALTO2_DISPLAY_WIDTH,
|
||||
ALTO2_DISPLAY_TOTAL_HEIGHT, 0, ALTO2_DISPLAY_HEIGHT + ALTO2_FAKE_STATUS_H)
|
||||
MCFG_SCREEN_REFRESH_RATE(60) // two interlaced fields
|
||||
MCFG_SCREEN_VBLANK_TIME(ALTO2_DISPLAY_VBLANK_TIME)
|
||||
MCFG_SCREEN_UPDATE_DEVICE("maincpu", alto2_cpu_device, screen_update)
|
||||
MCFG_SCREEN_VBLANK_DEVICE("maincpu", alto2_cpu_device, screen_eof)
|
||||
MCFG_SCREEN_PALETTE("palette")
|
||||
|
||||
MCFG_DEFAULT_LAYOUT( layout_vertical )
|
||||
|
||||
MCFG_PALETTE_ADD_WHITE_AND_BLACK("palette")
|
||||
|
||||
MCFG_DIABLO_DRIVES_ADD()
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
/* Driver Init */
|
||||
|
||||
DRIVER_INIT_MEMBER( alto2_state, alto2 )
|
||||
{
|
||||
// make the diablo drives known to the CPU core
|
||||
alto2_cpu_device* cpu = downcast<alto2_cpu_device *>(m_maincpu.target());
|
||||
cpu->set_diablo(0, downcast<diablo_hd_device *>(machine().device(DIABLO_HD_0)));
|
||||
cpu->set_diablo(1, downcast<diablo_hd_device *>(machine().device(DIABLO_HD_1)));
|
||||
}
|
||||
|
||||
/* Game Drivers */
|
||||
|
||||
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
|
||||
COMP( 1977, alto2, 0, 0, alto2, alto2, alto2_state, alto2, "Xerox", "Alto-II", GAME_NO_SOUND )
|
@ -2362,3 +2362,4 @@ mx2178
|
||||
hunter2
|
||||
amust
|
||||
fc100
|
||||
alto2
|
||||
|
@ -128,6 +128,7 @@ CPUS += ES5510
|
||||
CPUS += SCUDSP
|
||||
CPUS += IE15
|
||||
CPUS += 8X300
|
||||
CPUS += ALTO2
|
||||
|
||||
#-------------------------------------------------
|
||||
# specify available sound cores; some of these are
|
||||
@ -515,6 +516,7 @@ MACHINES += TI99_HD
|
||||
MACHINES += STRATA
|
||||
MACHINES += CORVUSHD
|
||||
MACHINES += WOZFDC
|
||||
MACHINES += DIABLO_HD
|
||||
|
||||
#-------------------------------------------------
|
||||
# specify available bus cores
|
||||
@ -1992,6 +1994,7 @@ $(MESSOBJ)/wavemate.a: \
|
||||
$(MESSOBJ)/xerox.a: \
|
||||
$(MESS_DRIVERS)/xerox820.o \
|
||||
$(MESS_DRIVERS)/bigbord2.o \
|
||||
$(MESS_DRIVERS)/alto2.o \
|
||||
|
||||
$(MESSOBJ)/xussrpc.a: \
|
||||
$(MESS_DRIVERS)/ec184x.o \
|
||||
|
Loading…
Reference in New Issue
Block a user