1996 lines
41 KiB
C
1996 lines
41 KiB
C
/*
|
|
|
|
Luxor ABC 1600
|
|
|
|
Skeleton driver
|
|
*/
|
|
|
|
/*
|
|
|
|
How to create HDD image:
|
|
------------------------
|
|
chdman -createblankhd necd5126a.chd 615 4 17 512
|
|
|
|
How to format HDD:
|
|
------------------
|
|
mf(2,0)
|
|
mf(2,0)
|
|
abcenix
|
|
sas/format/format
|
|
sa(40,0)
|
|
y
|
|
5
|
|
necd5126a
|
|
|
|
How to install OS:
|
|
------------------
|
|
mf(2,0)
|
|
mf(2,0)
|
|
abcenix
|
|
loadsys1
|
|
<enter>
|
|
<enter>
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
TODO:
|
|
|
|
- segment/page RAM addresses are not correctly decoded, "sas/format/format" can't find the SASI interface because of this
|
|
forcetask0 1 t0 0 t1 0 t2 0 t3 0
|
|
sega19 0 task 0
|
|
sega 000 segd 00 pga 008 pgd 4058 virtual 02c730 (should be 004730)
|
|
|
|
- floppy
|
|
- internal floppy is really drive 2, but wd17xx.c doesn't like having NULL drives
|
|
- short/long reset (RSTBUT)
|
|
- CIO
|
|
- optimize timers!
|
|
- port C, open drain output bit PC1 (RTC/NVRAM data)
|
|
- hard disk
|
|
- 4105 SASI interface card
|
|
- SASI interface (scsibus.c)
|
|
|
|
*/
|
|
|
|
#include "includes/abc1600.h"
|
|
|
|
|
|
|
|
//**************************************************************************
|
|
// CONSTANTS / MACROS
|
|
//**************************************************************************
|
|
|
|
#define LOG 0
|
|
|
|
|
|
// MAC
|
|
#define A0 BIT(offset, 0)
|
|
#define A1 BIT(offset, 1)
|
|
#define A2 BIT(offset, 2)
|
|
#define A4 BIT(offset, 4)
|
|
#define A7 BIT(offset, 7)
|
|
#define A8 BIT(offset, 8)
|
|
#define X11 BIT(offset, 11)
|
|
#define X12 BIT(offset, 12)
|
|
#define A17 BIT(offset, 17)
|
|
#define A18 BIT(offset, 18)
|
|
#define A19 BIT(offset, 19)
|
|
|
|
#define A10_A9_A8 ((offset >> 8) & 0x07)
|
|
#define A2_A1_A0 (offset & 0x07)
|
|
#define A1_A2 ((A1 << 1) | A2)
|
|
#define A2_A1 ((offset >> 1) & 0x03)
|
|
|
|
#define FC0 BIT(fc, 0)
|
|
#define FC1 BIT(fc, 1)
|
|
#define FC2 BIT(fc, 2)
|
|
|
|
#define PAGE_WP BIT(page_data, 14)
|
|
#define PAGE_NONX BIT(page_data, 15)
|
|
|
|
|
|
// task register
|
|
#define BOOTE BIT(m_task, 6)
|
|
#define MAGIC BIT(m_task, 7)
|
|
#define READ_MAGIC !MAGIC
|
|
|
|
|
|
// DMA map
|
|
enum
|
|
{
|
|
DMAMAP_R2_LO = 0,
|
|
DMAMAP_R2_HI,
|
|
DMAMAP_R1_LO = 4,
|
|
DMAMAP_R1_HI,
|
|
DMAMAP_R0_LO,
|
|
DMAMAP_R0_HI
|
|
};
|
|
|
|
|
|
// internal I/O registers
|
|
enum
|
|
{
|
|
FLP = 0,
|
|
CRT,
|
|
DRT,
|
|
DMA0,
|
|
DMA1,
|
|
DMA2,
|
|
SCC,
|
|
CIO
|
|
};
|
|
|
|
|
|
// internal I/O registers
|
|
enum
|
|
{
|
|
IORD0 = 0
|
|
};
|
|
|
|
|
|
// internal I/O registers
|
|
enum
|
|
{
|
|
IOWR0 = 0,
|
|
IOWR1,
|
|
IOWR2,
|
|
FW,
|
|
DMAMAP = 5,
|
|
SPEC_CONTR_REG
|
|
};
|
|
|
|
|
|
// external I/O
|
|
enum
|
|
{
|
|
INP = 0,
|
|
STAT,
|
|
OPS
|
|
};
|
|
|
|
enum
|
|
{
|
|
OUT = 0,
|
|
C1 = 2,
|
|
C2,
|
|
C3,
|
|
C4
|
|
};
|
|
|
|
|
|
|
|
//**************************************************************************
|
|
// MEMORY ACCESS CONTROLLER
|
|
//**************************************************************************
|
|
|
|
//-------------------------------------------------
|
|
// read_ram -
|
|
//-------------------------------------------------
|
|
|
|
UINT8 abc1600_state::read_ram(offs_t offset)
|
|
{
|
|
UINT8 data = 0;
|
|
|
|
if (offset < 0x100000)
|
|
{
|
|
// main RAM
|
|
UINT8 *ram = m_ram->pointer();
|
|
data = ram[offset];
|
|
}
|
|
else if (offset < 0x180000)
|
|
{
|
|
// video RAM
|
|
address_space &program = m_maincpu->space(AS_PROGRAM);
|
|
data = video_ram_r(program, offset);
|
|
}
|
|
else
|
|
{
|
|
logerror("%s Unmapped read from virtual memory %06x\n", machine().describe_context(), offset);
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// write_ram -
|
|
//-------------------------------------------------
|
|
|
|
void abc1600_state::write_ram(offs_t offset, UINT8 data)
|
|
{
|
|
if (offset < 0x100000)
|
|
{
|
|
// main RAM
|
|
UINT8 *ram = m_ram->pointer();
|
|
ram[offset] = data;
|
|
}
|
|
else if (offset < 0x180000)
|
|
{
|
|
// video RAM
|
|
address_space &program = m_maincpu->space(AS_PROGRAM);
|
|
video_ram_w(program, offset, data);
|
|
}
|
|
else
|
|
{
|
|
logerror("%s Unmapped write to virtual memory %06x : %02x\n", machine().describe_context(), offset, data);
|
|
}
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// read_io -
|
|
//-------------------------------------------------
|
|
|
|
UINT8 abc1600_state::read_io(offs_t offset)
|
|
{
|
|
if (X12)
|
|
{
|
|
return read_internal_io(offset);
|
|
}
|
|
else
|
|
{
|
|
return read_external_io(offset);
|
|
}
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// read_internal_io -
|
|
//-------------------------------------------------
|
|
|
|
UINT8 abc1600_state::read_internal_io(offs_t offset)
|
|
{
|
|
address_space &program = m_maincpu->space(AS_PROGRAM);
|
|
UINT8 data = 0;
|
|
|
|
if (X11)
|
|
{
|
|
switch (A10_A9_A8)
|
|
{
|
|
case IORD0:
|
|
data = iord0_r(program, offset);
|
|
break;
|
|
|
|
default:
|
|
logerror("%s Unmapped read from virtual I/O %06x\n", machine().describe_context(), offset);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (A10_A9_A8)
|
|
{
|
|
case FLP:
|
|
data = wd17xx_r(m_fdc, program, A2_A1);
|
|
break;
|
|
|
|
case CRT:
|
|
if (A0)
|
|
data = m_crtc->register_r(program, offset);
|
|
else
|
|
data = m_crtc->status_r(program, offset);
|
|
break;
|
|
|
|
case DRT:
|
|
data = z80dart_ba_cd_r(m_dart, program, A2_A1 ^ 0x03);
|
|
break;
|
|
|
|
case DMA0:
|
|
data = m_dma0->read();
|
|
break;
|
|
|
|
case DMA1:
|
|
data = m_dma1->read();
|
|
break;
|
|
|
|
case DMA2:
|
|
data = m_dma2->read();
|
|
break;
|
|
|
|
case SCC:
|
|
data = m_scc->reg_r(program, A1_A2);
|
|
break;
|
|
|
|
case CIO:
|
|
data = m_cio->read(program, A2_A1);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// read_external_io -
|
|
//-------------------------------------------------
|
|
|
|
UINT8 abc1600_state::read_external_io(offs_t offset)
|
|
{
|
|
UINT8 data = 0;
|
|
|
|
// card select pulse
|
|
UINT8 cs = (m_cs7 << 7) | ((offset >> 5) & 0x3f);
|
|
|
|
m_bus0i->cs_w(cs);
|
|
m_bus0x->cs_w(cs);
|
|
m_bus1->cs_w(cs);
|
|
m_bus2->cs_w(cs);
|
|
|
|
// card select b?
|
|
m_csb = m_bus2->csb_r();
|
|
m_csb |= m_bus1->csb_r() << 1;
|
|
m_csb |= m_bus0x->xcsb2_r() << 2;
|
|
m_csb |= m_bus0x->xcsb3_r() << 3;
|
|
m_csb |= m_bus0x->xcsb4_r() << 4;
|
|
m_csb |= m_bus0x->xcsb5_r() << 5;
|
|
m_csb |= m_bus0x->csb_r() << 6;
|
|
m_csb |= m_bus0i->csb_r() << 7;
|
|
|
|
m_bus0 = !((m_csb & 0xfc) == 0xfc);
|
|
|
|
if (X11)
|
|
{
|
|
if (A4)
|
|
{
|
|
// EXP
|
|
data = m_bus0x->exp_r();
|
|
|
|
logerror("%s EXP %02x: %02x\n", machine().describe_context(), cs, data);
|
|
}
|
|
else
|
|
{
|
|
// RCSB
|
|
if (m_bus0)
|
|
{
|
|
/*
|
|
|
|
bit description
|
|
|
|
0 1
|
|
1 1
|
|
2 LXCSB2*
|
|
3 LXCSB3*
|
|
4 LXCSB4*
|
|
5 LXCSB5*
|
|
6 LCSB*-0
|
|
7 LCSB*-0I
|
|
|
|
*/
|
|
|
|
data = (m_csb & 0xfc) | 0x03;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
|
|
bit description
|
|
|
|
0 LCSB*-2
|
|
1 LCSB*-1
|
|
2 1
|
|
3 1
|
|
4 1
|
|
5 1
|
|
6 1
|
|
7 1
|
|
|
|
*/
|
|
|
|
data = 0xfc | (m_csb & 0x03);
|
|
}
|
|
|
|
logerror("%s RCSB %02x\n", machine().describe_context(), data);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
data = 0xff;
|
|
|
|
switch ((offset >> 1) & 0x07)
|
|
{
|
|
case INP:
|
|
if (m_bus0)
|
|
{
|
|
data &= m_bus0i->inp_r();
|
|
data &= m_bus0x->inp_r();
|
|
}
|
|
else
|
|
{
|
|
data &= m_bus1->inp_r();
|
|
data &= m_bus2->inp_r();
|
|
}
|
|
|
|
logerror("%s INP %02x: %02x\n", machine().describe_context(), cs, data);
|
|
break;
|
|
|
|
case STAT:
|
|
if (m_bus0)
|
|
{
|
|
data &= m_bus0i->stat_r();
|
|
data &= m_bus0x->stat_r();
|
|
}
|
|
else
|
|
{
|
|
data &= m_bus1->stat_r();
|
|
data &= m_bus2->stat_r();
|
|
}
|
|
|
|
logerror("%s STAT %02x: %02x\n", machine().describe_context(), cs, data);
|
|
break;
|
|
|
|
case OPS:
|
|
if (m_bus0)
|
|
{
|
|
data &= m_bus0i->ops_r();
|
|
data &= m_bus0x->ops_r();
|
|
}
|
|
else
|
|
{
|
|
data &= m_bus1->ops_r();
|
|
data &= m_bus2->ops_r();
|
|
}
|
|
|
|
logerror("%s OPS %02x: %02x\n", machine().describe_context(), cs, data);
|
|
break;
|
|
|
|
default:
|
|
logerror("%s Unmapped read from virtual I/O %06x\n", machine().describe_context(), offset);
|
|
}
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// write_io -
|
|
//-------------------------------------------------
|
|
|
|
void abc1600_state::write_io(offs_t offset, UINT8 data)
|
|
{
|
|
if (X12)
|
|
{
|
|
write_internal_io(offset, data);
|
|
}
|
|
else
|
|
{
|
|
write_external_io(offset, data);
|
|
}
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// write_internal_io -
|
|
//-------------------------------------------------
|
|
|
|
void abc1600_state::write_internal_io(offs_t offset, UINT8 data)
|
|
{
|
|
address_space &program = m_maincpu->space(AS_PROGRAM);
|
|
|
|
if (X11)
|
|
{
|
|
switch (A10_A9_A8)
|
|
{
|
|
case IOWR0:
|
|
iowr0_w(program, offset, data);
|
|
break;
|
|
|
|
case IOWR1:
|
|
iowr1_w(program, offset, data);
|
|
break;
|
|
|
|
case IOWR2:
|
|
iowr2_w(program, offset, data);
|
|
break;
|
|
|
|
case FW:
|
|
if (!A7)
|
|
{
|
|
if (A0)
|
|
fw1_w(program, offset, data);
|
|
else
|
|
fw0_w(program, offset, data);
|
|
}
|
|
else
|
|
{
|
|
logerror("%s Unmapped write to virtual I/O %06x : %02x\n", machine().describe_context(), offset, data);
|
|
}
|
|
break;
|
|
|
|
case DMAMAP:
|
|
dmamap_w(program, offset, data);
|
|
break;
|
|
|
|
case SPEC_CONTR_REG:
|
|
spec_contr_reg_w(program, offset, data);
|
|
break;
|
|
|
|
default:
|
|
logerror("%s Unmapped write to virtual I/O %06x : %02x\n", machine().describe_context(), offset, data);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (A10_A9_A8)
|
|
{
|
|
case FLP:
|
|
wd17xx_w(m_fdc, program, A2_A1, data);
|
|
break;
|
|
|
|
case CRT:
|
|
if (A0)
|
|
m_crtc->register_w(program, offset, data);
|
|
else
|
|
m_crtc->address_w(program, offset, data);
|
|
break;
|
|
|
|
case DRT:
|
|
z80dart_ba_cd_w(m_dart, program, A2_A1 ^ 0x03, data);
|
|
break;
|
|
|
|
case DMA0:
|
|
m_dma0->write(data);
|
|
break;
|
|
|
|
case DMA1:
|
|
m_dma1->write(data);
|
|
break;
|
|
|
|
case DMA2:
|
|
m_dma2->write(data);
|
|
break;
|
|
|
|
case SCC:
|
|
m_scc->reg_w(program, A1_A2, data);
|
|
break;
|
|
|
|
case CIO:
|
|
m_cio->write(program, A2_A1, data);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// write_external_io -
|
|
//-------------------------------------------------
|
|
|
|
void abc1600_state::write_external_io(offs_t offset, UINT8 data)
|
|
{
|
|
UINT8 cs = (m_cs7 << 7) | ((offset >> 5) & 0x3f);
|
|
|
|
m_bus0i->cs_w(cs);
|
|
m_bus0x->cs_w(cs);
|
|
m_bus1->cs_w(cs);
|
|
m_bus2->cs_w(cs);
|
|
|
|
switch ((offset >> 1) & 0x07)
|
|
{
|
|
case OUT:
|
|
logerror("%s OUT %02x: %02x\n", machine().describe_context(), cs, data);
|
|
|
|
if (m_bus0)
|
|
{
|
|
m_bus0i->out_w(data);
|
|
m_bus0x->out_w(data);
|
|
}
|
|
else
|
|
{
|
|
m_bus1->out_w(data);
|
|
m_bus2->out_w(data);
|
|
}
|
|
break;
|
|
|
|
case C1:
|
|
logerror("%s C1 %02x: %02x\n", machine().describe_context(), cs, data);
|
|
|
|
if (m_bus0)
|
|
{
|
|
m_bus0i->c1_w(data);
|
|
m_bus0x->c1_w(data);
|
|
}
|
|
else
|
|
{
|
|
m_bus1->c1_w(data);
|
|
m_bus2->c1_w(data);
|
|
}
|
|
break;
|
|
|
|
case C2:
|
|
logerror("%s C2 %02x: %02x\n", machine().describe_context(), cs, data);
|
|
|
|
if (m_bus0)
|
|
{
|
|
m_bus0i->c2_w(data);
|
|
m_bus0x->c2_w(data);
|
|
}
|
|
else
|
|
{
|
|
m_bus1->c2_w(data);
|
|
m_bus2->c2_w(data);
|
|
}
|
|
break;
|
|
|
|
case C3:
|
|
logerror("%s C3 %02x: %02x\n", machine().describe_context(), cs, data);
|
|
|
|
if (m_bus0)
|
|
{
|
|
m_bus0i->c3_w(data);
|
|
m_bus0x->c3_w(data);
|
|
}
|
|
else
|
|
{
|
|
m_bus1->c3_w(data);
|
|
m_bus2->c3_w(data);
|
|
}
|
|
break;
|
|
|
|
case C4:
|
|
logerror("%s C4 %02x: %02x\n", machine().describe_context(), cs, data);
|
|
|
|
if (m_bus0)
|
|
{
|
|
m_bus0i->c4_w(data);
|
|
m_bus0x->c4_w(data);
|
|
}
|
|
else
|
|
{
|
|
m_bus1->c4_w(data);
|
|
m_bus2->c4_w(data);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
logerror("%s Unmapped write %02x to virtual I/O %06x\n", machine().describe_context(), data, offset);
|
|
}
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// get_current_task -
|
|
//-------------------------------------------------
|
|
|
|
int abc1600_state::get_current_task(offs_t offset)
|
|
{
|
|
int force_task0 = !(m_ifc2 || A19);
|
|
int t0 = !(BIT(m_task, 0) || force_task0);
|
|
int t1 = !(BIT(m_task, 1) || force_task0);
|
|
int t2 = !(BIT(m_task, 2) || force_task0);
|
|
int t3 = !(BIT(m_task, 3) || force_task0);
|
|
|
|
return (t3 << 3) | (t2 << 2) | (t1 << 1) | t0;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// get_segment_address -
|
|
//-------------------------------------------------
|
|
|
|
offs_t abc1600_state::get_segment_address(offs_t offset)
|
|
{
|
|
int sega19 = !(!(A8 || m_ifc2) || !A19);
|
|
int task = get_current_task(offset);
|
|
|
|
return (task << 5) | (sega19 << 4) | ((offset >> 15) & 0x0f);
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// get_page_address -
|
|
//-------------------------------------------------
|
|
|
|
offs_t abc1600_state::get_page_address(offs_t offset, UINT8 segd)
|
|
{
|
|
return ((segd & 0x3f) << 4) | ((offset >> 11) & 0x0f);
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// translate_address -
|
|
//-------------------------------------------------
|
|
|
|
offs_t abc1600_state::translate_address(offs_t offset, int *nonx, int *wp)
|
|
{
|
|
// segment
|
|
offs_t sega = get_segment_address(offset);
|
|
UINT8 segd = m_segment_ram[sega];
|
|
|
|
// page
|
|
offs_t pga = get_page_address(offset, segd);
|
|
UINT16 page_data = m_page_ram[pga];
|
|
|
|
offs_t virtual_offset = ((page_data & 0x3ff) << 11) | (offset & 0x7ff);
|
|
|
|
if (PAGE_NONX)
|
|
{
|
|
//logerror("Bus error %06x : %06x\n", offset, virtual_offset);
|
|
//m_maincpu->set_input_line(M68K_LINE_BUSERROR, ASSERT_LINE);
|
|
//m_maincpu->set_input_line(M68K_LINE_BUSERROR, CLEAR_LINE);
|
|
}
|
|
|
|
*nonx = PAGE_NONX;
|
|
*wp = PAGE_WP;
|
|
|
|
return virtual_offset;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// read_user_memory -
|
|
//-------------------------------------------------
|
|
|
|
UINT8 abc1600_state::read_user_memory(offs_t offset)
|
|
{
|
|
int nonx = 0, wp = 0;
|
|
offs_t virtual_offset = translate_address(offset, &nonx, &wp);
|
|
UINT8 data = 0;
|
|
|
|
if (virtual_offset < 0x1fe000)
|
|
{
|
|
data = read_ram(virtual_offset);
|
|
}
|
|
else
|
|
{
|
|
data = read_io(virtual_offset);
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// write_user_memory -
|
|
//-------------------------------------------------
|
|
|
|
void abc1600_state::write_user_memory(offs_t offset, UINT8 data)
|
|
{
|
|
int nonx = 0, wp = 0;
|
|
offs_t virtual_offset = translate_address(offset, &nonx, &wp);
|
|
|
|
//if (nonx || !wp) return;
|
|
|
|
if (virtual_offset < 0x1fe000)
|
|
{
|
|
write_ram(virtual_offset, data);
|
|
}
|
|
else
|
|
{
|
|
write_io(virtual_offset, data);
|
|
}
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// read_supervisor_memory -
|
|
//-------------------------------------------------
|
|
|
|
UINT8 abc1600_state::read_supervisor_memory(offs_t offset)
|
|
{
|
|
address_space &program = m_maincpu->space(AS_PROGRAM);
|
|
UINT8 data = 0;
|
|
|
|
if (!A2 && !A1)
|
|
{
|
|
// _EP
|
|
data = page_r(program, offset);
|
|
}
|
|
else if (!A2 && A1 && A0)
|
|
{
|
|
// _ES
|
|
data = segment_r(program, offset);
|
|
}
|
|
else if (A2 && A1 && A0)
|
|
{
|
|
// _CAUSE
|
|
data = cause_r(program, offset);
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// write_supervisor_memory -
|
|
//-------------------------------------------------
|
|
|
|
void abc1600_state::write_supervisor_memory(offs_t offset, UINT8 data)
|
|
{
|
|
address_space &program = m_maincpu->space(AS_PROGRAM);
|
|
|
|
if (!A2 && !A1)
|
|
{
|
|
// _WEP
|
|
page_w(program, offset, data);
|
|
}
|
|
else if (!A2 && A1 && A0)
|
|
{
|
|
// _WES
|
|
segment_w(program, offset, data);
|
|
}
|
|
else if (A2 && !A1 && A0)
|
|
{
|
|
// W(C)
|
|
task_w(program, offset, data);
|
|
}
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// get_fc -
|
|
//-------------------------------------------------
|
|
|
|
int abc1600_state::get_fc()
|
|
{
|
|
UINT16 fc = m68k_get_fc(m_maincpu);
|
|
|
|
m_ifc2 = !(!(MAGIC || FC0) || FC2);
|
|
|
|
return fc;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// mac_r -
|
|
//-------------------------------------------------
|
|
|
|
READ8_MEMBER( abc1600_state::mac_r )
|
|
{
|
|
int fc = get_fc();
|
|
|
|
UINT8 data = 0;
|
|
|
|
if (!BOOTE && !A19 && !A18 && !A17)
|
|
{
|
|
// _BOOTCE
|
|
UINT8 *rom = memregion(MC68008P8_TAG)->base();
|
|
data = rom[offset & 0x3fff];
|
|
}
|
|
else if (A19 && !m_ifc2 && !FC1)
|
|
{
|
|
data = read_supervisor_memory(offset);
|
|
}
|
|
else
|
|
{
|
|
data = read_user_memory(offset);
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// mac_w -
|
|
//-------------------------------------------------
|
|
|
|
WRITE8_MEMBER( abc1600_state::mac_w )
|
|
{
|
|
int fc = get_fc();
|
|
|
|
if (A19 && !m_ifc2 && !FC1)
|
|
{
|
|
write_supervisor_memory(offset, data);
|
|
}
|
|
else
|
|
{
|
|
write_user_memory(offset, data);
|
|
}
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// cause_r -
|
|
//-------------------------------------------------
|
|
|
|
READ8_MEMBER( abc1600_state::cause_r )
|
|
{
|
|
/*
|
|
|
|
bit description
|
|
|
|
0 RSTBUT
|
|
1 1
|
|
2 DMAOK
|
|
3 X16
|
|
4 X17
|
|
5 X18
|
|
6 X19
|
|
7 X20
|
|
|
|
*/
|
|
|
|
UINT8 data = 0x02;
|
|
|
|
// DMA status
|
|
data |= m_cause;
|
|
|
|
machine().watchdog_reset();
|
|
|
|
return data;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// task_w -
|
|
//-------------------------------------------------
|
|
|
|
WRITE8_MEMBER( abc1600_state::task_w )
|
|
{
|
|
/*
|
|
|
|
bit description
|
|
|
|
0 TASKD0* (inverted SEGA5)
|
|
1 TASKD1* (inverted SEGA6)
|
|
2 TASKD2* (inverted SEGA7)
|
|
3 TASKD3* (inverted SEGA8)
|
|
4
|
|
5
|
|
6 BOOTE*
|
|
7 MAGIC*
|
|
|
|
*/
|
|
|
|
m_task = data ^ 0xff;
|
|
|
|
if (LOG) logerror("%s: %06x Task %u BOOTE %u MAGIC %u\n", machine().describe_context(), offset, get_current_task(offset), BOOTE, MAGIC);
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// segment_r -
|
|
//-------------------------------------------------
|
|
|
|
READ8_MEMBER( abc1600_state::segment_r )
|
|
{
|
|
/*
|
|
|
|
bit description
|
|
|
|
0 SEGD0
|
|
1 SEGD1
|
|
2 SEGD2
|
|
3 SEGD3
|
|
4 SEGD4
|
|
5 SEGD5
|
|
6 SEGD6
|
|
7 READ_MAGIC
|
|
|
|
*/
|
|
|
|
offs_t sega = get_segment_address(offset);
|
|
UINT8 segd = m_segment_ram[sega];
|
|
|
|
return (READ_MAGIC << 7) | (segd & 0x7f);
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// segment_w -
|
|
//-------------------------------------------------
|
|
|
|
WRITE8_MEMBER( abc1600_state::segment_w )
|
|
{
|
|
/*
|
|
|
|
bit description
|
|
|
|
0 SEGD0
|
|
1 SEGD1
|
|
2 SEGD2
|
|
3 SEGD3
|
|
4 SEGD4
|
|
5 SEGD5
|
|
6 SEGD6
|
|
7 0
|
|
|
|
*/
|
|
|
|
offs_t sega = get_segment_address(offset);
|
|
|
|
m_segment_ram[sega] = data & 0x7f;
|
|
|
|
if (LOG) logerror("%s: %06x Task %u Segment %03x : %02x\n", machine().describe_context(), offset, get_current_task(offset), sega, data);
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// page_r -
|
|
//-------------------------------------------------
|
|
|
|
READ8_MEMBER( abc1600_state::page_r )
|
|
{
|
|
/*
|
|
|
|
bit description
|
|
|
|
0 X11
|
|
1 X12
|
|
2 X13
|
|
3 X14
|
|
4 X15
|
|
5 X16
|
|
6 X17
|
|
7 X18
|
|
|
|
8 X19
|
|
9 X20
|
|
10 X20
|
|
11 X20
|
|
12 X20
|
|
13 X20
|
|
14 _WP
|
|
15 NONX
|
|
|
|
*/
|
|
|
|
// segment
|
|
offs_t sega = get_segment_address(offset);
|
|
UINT8 segd = m_segment_ram[sega];
|
|
|
|
// page
|
|
offs_t pga = get_page_address(offset, segd);
|
|
UINT16 pgd = m_page_ram[pga];
|
|
|
|
UINT8 data = 0;
|
|
|
|
if (A0)
|
|
{
|
|
data = pgd & 0xff;
|
|
}
|
|
else
|
|
{
|
|
int x20 = BIT(pgd, 9);
|
|
|
|
data = (pgd >> 8) | (x20 << 2) | (x20 << 3) | (x20 << 4) | (x20 << 5);
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// page_w -
|
|
//-------------------------------------------------
|
|
|
|
WRITE8_MEMBER( abc1600_state::page_w )
|
|
{
|
|
/*
|
|
|
|
bit description
|
|
|
|
0 X11
|
|
1 X12
|
|
2 X13
|
|
3 X14
|
|
4 X15
|
|
5 X16
|
|
6 X17
|
|
7 X18
|
|
|
|
8 X19
|
|
9 X20
|
|
10
|
|
11
|
|
12
|
|
13
|
|
14 _WP
|
|
15 NONX
|
|
|
|
*/
|
|
|
|
// segment
|
|
offs_t sega = get_segment_address(offset);
|
|
UINT8 segd = m_segment_ram[sega];
|
|
|
|
// page
|
|
offs_t pga = get_page_address(offset, segd);
|
|
|
|
if (A0)
|
|
{
|
|
m_page_ram[pga] = (m_page_ram[pga] & 0xff00) | data;
|
|
}
|
|
else
|
|
{
|
|
m_page_ram[pga] = ((data & 0xc3) << 8) | (m_page_ram[pga] & 0xff);
|
|
}
|
|
|
|
if (LOG) logerror("%s: %06x Task %u Segment %03x Page %03x : %02x -> %04x\n", machine().describe_context(), offset, get_current_task(offset), sega, pga, data, m_page_ram[pga]);
|
|
}
|
|
|
|
|
|
|
|
//**************************************************************************
|
|
// DMA
|
|
//**************************************************************************
|
|
|
|
//-------------------------------------------------
|
|
// update_drdy0 -
|
|
//-------------------------------------------------
|
|
|
|
inline void abc1600_state::update_drdy0()
|
|
{
|
|
if (m_sysfs)
|
|
{
|
|
// floppy
|
|
m_dma0->rdy_w(!wd17xx_drq_r(m_fdc));
|
|
}
|
|
else
|
|
{
|
|
// BUS0I/BUS0X
|
|
int trrq0 = m_bus0i->trrq_r() && m_bus0x->trrq_r();
|
|
|
|
m_dma0->rdy_w(trrq0);
|
|
}
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// update_drdy1 -
|
|
//-------------------------------------------------
|
|
|
|
inline void abc1600_state::update_drdy1()
|
|
{
|
|
if (m_sysscc)
|
|
{
|
|
// SCC
|
|
m_dma1->rdy_w(1);
|
|
}
|
|
else
|
|
{
|
|
// BUS1
|
|
m_dma1->rdy_w(m_bus1->trrq_r());
|
|
}
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// update_drdy2 -
|
|
//-------------------------------------------------
|
|
|
|
inline void abc1600_state::update_drdy2()
|
|
{
|
|
// Winchester
|
|
m_dma2->rdy_w(1);
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// get_dma_address -
|
|
//-------------------------------------------------
|
|
|
|
inline offs_t abc1600_state::get_dma_address(int index, UINT16 offset)
|
|
{
|
|
// A0 = DMA15, A1 = BA1, A2 = BA2
|
|
UINT8 dmamap_addr = index | BIT(offset, 15);
|
|
UINT8 dmamap = m_dmamap[dmamap_addr];
|
|
|
|
m_cause = (dmamap & 0x1f) << 3;
|
|
|
|
return ((dmamap & 0x1f) << 16) | offset;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// dma_mreq_r - DMA memory read
|
|
//-------------------------------------------------
|
|
|
|
inline UINT8 abc1600_state::dma_mreq_r(int index, UINT16 offset)
|
|
{
|
|
offs_t virtual_offset = get_dma_address(index, offset);
|
|
|
|
return read_ram(virtual_offset);
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// dma_mreq_w - DMA memory write
|
|
//-------------------------------------------------
|
|
|
|
inline void abc1600_state::dma_mreq_w(int index, UINT16 offset, UINT8 data)
|
|
{
|
|
offs_t virtual_offset = get_dma_address(index, offset);
|
|
|
|
write_ram(virtual_offset, data);
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// dma_iorq_r - DMA I/O read
|
|
//-------------------------------------------------
|
|
|
|
inline UINT8 abc1600_state::dma_iorq_r(int index, UINT16 offset)
|
|
{
|
|
offs_t virtual_offset = get_dma_address(index, offset);
|
|
|
|
return read_io(virtual_offset);
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// dma_iorq_w - DMA I/O write
|
|
//-------------------------------------------------
|
|
|
|
inline void abc1600_state::dma_iorq_w(int index, UINT16 offset, UINT8 data)
|
|
{
|
|
offs_t virtual_offset = get_dma_address(index, offset);
|
|
|
|
write_io(virtual_offset, data);
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// dmamap_w - DMA map write
|
|
//-------------------------------------------------
|
|
|
|
WRITE8_MEMBER( abc1600_state::dmamap_w )
|
|
{
|
|
/*
|
|
|
|
bit description
|
|
|
|
0 X16
|
|
1 X17
|
|
2 X18
|
|
3 X19
|
|
4 X20
|
|
5
|
|
6
|
|
7 _R/W
|
|
|
|
*/
|
|
|
|
if (LOG) logerror("DMAMAP %u %02x\n", offset & 7, data);
|
|
|
|
m_dmamap[offset & 7] = data;
|
|
}
|
|
|
|
|
|
|
|
//**************************************************************************
|
|
// READ/WRITE HANDLERS
|
|
//**************************************************************************
|
|
|
|
//-------------------------------------------------
|
|
// fw0_w -
|
|
//-------------------------------------------------
|
|
|
|
WRITE8_MEMBER( abc1600_state::fw0_w )
|
|
{
|
|
/*
|
|
|
|
bit description
|
|
|
|
0 SEL1
|
|
1 SEL2
|
|
2 SEL3
|
|
3 MOTOR
|
|
4 LC/PC
|
|
5 LC/PC
|
|
6
|
|
7
|
|
|
|
*/
|
|
|
|
if (LOG) logerror("FW0 %02x\n", data);
|
|
|
|
// drive select
|
|
if (BIT(data, 0)) wd17xx_set_drive(m_fdc, 0);
|
|
if (BIT(data, 1)) wd17xx_set_drive(m_fdc, 1);
|
|
if (BIT(data, 2)) wd17xx_set_drive(m_fdc, 2);
|
|
|
|
// floppy motor
|
|
floppy_mon_w(m_floppy, !BIT(data, 3));
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// fw1_w -
|
|
//-------------------------------------------------
|
|
|
|
WRITE8_MEMBER( abc1600_state::fw1_w )
|
|
{
|
|
/*
|
|
|
|
bit description
|
|
|
|
0 MR
|
|
1 DDEN
|
|
2 HLT
|
|
3 MINI
|
|
4 HLD
|
|
5 P0
|
|
6 P1
|
|
7 P2
|
|
|
|
*/
|
|
|
|
if (LOG) logerror("FW1 %02x\n", data);
|
|
|
|
// FDC master reset
|
|
wd17xx_mr_w(m_fdc, BIT(data, 0));
|
|
|
|
// density select
|
|
wd17xx_dden_w(m_fdc, BIT(data, 1));
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// spec_contr_reg_w -
|
|
//-------------------------------------------------
|
|
|
|
WRITE8_MEMBER( abc1600_state::spec_contr_reg_w )
|
|
{
|
|
int state = BIT(data, 3);
|
|
|
|
switch (data & 0x07)
|
|
{
|
|
case 0: // CS7
|
|
m_cs7 = state;
|
|
break;
|
|
|
|
case 1:
|
|
break;
|
|
|
|
case 2: // _BTCE
|
|
m_btce = state;
|
|
break;
|
|
|
|
case 3: // _ATCE
|
|
m_atce = state;
|
|
break;
|
|
|
|
case 4: // PARTST
|
|
m_partst = state;
|
|
break;
|
|
|
|
case 5: // _DMADIS
|
|
m_dmadis = state;
|
|
break;
|
|
|
|
case 6: // SYSSCC
|
|
m_sysscc = state;
|
|
|
|
m_cio->pb5_w(!state);
|
|
m_bus1->pren_w(!state);
|
|
|
|
update_drdy1();
|
|
break;
|
|
|
|
case 7: // SYSFS
|
|
m_sysfs = state;
|
|
|
|
m_cio->pb6_w(!state);
|
|
m_bus0i->pren_w(!state);
|
|
m_bus0x->pren_w(!state);
|
|
|
|
update_drdy0();
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//**************************************************************************
|
|
// ADDRESS MAPS
|
|
//**************************************************************************
|
|
|
|
//-------------------------------------------------
|
|
// ADDRESS_MAP( abc1600_mem )
|
|
//-------------------------------------------------
|
|
|
|
static ADDRESS_MAP_START( abc1600_mem, AS_PROGRAM, 8, abc1600_state )
|
|
AM_RANGE(0x00000, 0xfffff) AM_READWRITE(mac_r, mac_w)
|
|
ADDRESS_MAP_END
|
|
|
|
|
|
|
|
//**************************************************************************
|
|
// INPUT PORTS
|
|
//**************************************************************************
|
|
|
|
//-------------------------------------------------
|
|
// INPUT_PORTS( abc1600 )
|
|
//-------------------------------------------------
|
|
|
|
static INPUT_PORTS_START( abc1600 )
|
|
// inputs defined in machine/abc99.c
|
|
INPUT_PORTS_END
|
|
|
|
|
|
|
|
//**************************************************************************
|
|
// DEVICE CONFIGURATION
|
|
//**************************************************************************
|
|
|
|
//-------------------------------------------------
|
|
// Z80DMA_INTERFACE( dma0_intf )
|
|
//-------------------------------------------------
|
|
|
|
WRITE_LINE_MEMBER( abc1600_state::dbrq_w )
|
|
{
|
|
m_maincpu->set_input_line(INPUT_LINE_HALT, state && m_dmadis);
|
|
}
|
|
|
|
READ8_MEMBER( abc1600_state::dma0_mreq_r )
|
|
{
|
|
return dma_mreq_r(DMAMAP_R0_LO, offset);
|
|
}
|
|
|
|
WRITE8_MEMBER( abc1600_state::dma0_mreq_w )
|
|
{
|
|
dma_mreq_w(DMAMAP_R0_LO, offset, data);
|
|
}
|
|
|
|
READ8_MEMBER( abc1600_state::dma0_iorq_r )
|
|
{
|
|
return dma_iorq_r(DMAMAP_R0_LO, offset);
|
|
}
|
|
|
|
WRITE8_MEMBER( abc1600_state::dma0_iorq_w )
|
|
{
|
|
dma_iorq_w(DMAMAP_R0_LO, offset, data);
|
|
}
|
|
|
|
static Z80DMA_INTERFACE( dma0_intf )
|
|
{
|
|
DEVCB_DRIVER_LINE_MEMBER(abc1600_state, dbrq_w),
|
|
DEVCB_NULL,
|
|
DEVCB_DEVICE_LINE(Z8410AB1_1_TAG, z80dma_bai_w),
|
|
DEVCB_DRIVER_MEMBER(abc1600_state, dma0_mreq_r),
|
|
DEVCB_DRIVER_MEMBER(abc1600_state, dma0_mreq_w),
|
|
DEVCB_DRIVER_MEMBER(abc1600_state, dma0_iorq_r),
|
|
DEVCB_DRIVER_MEMBER(abc1600_state, dma0_iorq_w)
|
|
};
|
|
|
|
|
|
//-------------------------------------------------
|
|
// Z80DMA_INTERFACE( dma1_intf )
|
|
//-------------------------------------------------
|
|
|
|
READ8_MEMBER( abc1600_state::dma1_mreq_r )
|
|
{
|
|
return dma_mreq_r(DMAMAP_R1_LO, offset);
|
|
}
|
|
|
|
WRITE8_MEMBER( abc1600_state::dma1_mreq_w )
|
|
{
|
|
dma_mreq_w(DMAMAP_R1_LO, offset, data);
|
|
}
|
|
|
|
READ8_MEMBER( abc1600_state::dma1_iorq_r )
|
|
{
|
|
return dma_iorq_r(DMAMAP_R1_LO, offset);
|
|
}
|
|
|
|
WRITE8_MEMBER( abc1600_state::dma1_iorq_w )
|
|
{
|
|
dma_iorq_w(DMAMAP_R1_LO, offset, data);
|
|
}
|
|
|
|
static Z80DMA_INTERFACE( dma1_intf )
|
|
{
|
|
DEVCB_DRIVER_LINE_MEMBER(abc1600_state, dbrq_w),
|
|
DEVCB_NULL,
|
|
DEVCB_DEVICE_LINE(Z8410AB1_2_TAG, z80dma_bai_w),
|
|
DEVCB_DRIVER_MEMBER(abc1600_state, dma1_mreq_r),
|
|
DEVCB_DRIVER_MEMBER(abc1600_state, dma1_mreq_w),
|
|
DEVCB_DRIVER_MEMBER(abc1600_state, dma1_iorq_r),
|
|
DEVCB_DRIVER_MEMBER(abc1600_state, dma1_iorq_w)
|
|
};
|
|
|
|
|
|
//-------------------------------------------------
|
|
// Z80DMA_INTERFACE( dma2_intf )
|
|
//-------------------------------------------------
|
|
|
|
READ8_MEMBER( abc1600_state::dma2_mreq_r )
|
|
{
|
|
return dma_mreq_r(DMAMAP_R2_LO, offset);
|
|
}
|
|
|
|
WRITE8_MEMBER( abc1600_state::dma2_mreq_w )
|
|
{
|
|
dma_mreq_w(DMAMAP_R2_LO, offset, data);
|
|
}
|
|
|
|
READ8_MEMBER( abc1600_state::dma2_iorq_r )
|
|
{
|
|
return dma_iorq_r(DMAMAP_R2_LO, offset);
|
|
}
|
|
|
|
WRITE8_MEMBER( abc1600_state::dma2_iorq_w )
|
|
{
|
|
dma_iorq_w(DMAMAP_R2_LO, offset, data);
|
|
}
|
|
|
|
static Z80DMA_INTERFACE( dma2_intf )
|
|
{
|
|
DEVCB_DRIVER_LINE_MEMBER(abc1600_state, dbrq_w),
|
|
DEVCB_NULL,
|
|
DEVCB_NULL,
|
|
DEVCB_DRIVER_MEMBER(abc1600_state, dma2_mreq_r),
|
|
DEVCB_DRIVER_MEMBER(abc1600_state, dma2_mreq_w),
|
|
DEVCB_DRIVER_MEMBER(abc1600_state, dma2_iorq_r),
|
|
DEVCB_DRIVER_MEMBER(abc1600_state, dma2_iorq_w)
|
|
};
|
|
|
|
|
|
//-------------------------------------------------
|
|
// Z80DART_INTERFACE( dart_intf )
|
|
//-------------------------------------------------
|
|
|
|
static Z80DART_INTERFACE( dart_intf )
|
|
{
|
|
0, 0, 0, 0,
|
|
|
|
DEVCB_NULL,
|
|
DEVCB_NULL,
|
|
DEVCB_NULL,
|
|
DEVCB_NULL,
|
|
DEVCB_NULL,
|
|
DEVCB_NULL,
|
|
|
|
DEVCB_DEVICE_LINE_MEMBER(ABC99_TAG, abc99_device, txd_r),
|
|
DEVCB_DEVICE_LINE_MEMBER(ABC99_TAG, abc99_device, rxd_w),
|
|
DEVCB_NULL,
|
|
DEVCB_NULL,
|
|
DEVCB_NULL,
|
|
DEVCB_NULL,
|
|
|
|
DEVCB_CPU_INPUT_LINE(MC68008P8_TAG, M68K_IRQ_5) // shared with SCC
|
|
};
|
|
|
|
|
|
//-------------------------------------------------
|
|
// SCC8530_INTERFACE( sc_intf )
|
|
//-------------------------------------------------
|
|
|
|
void abc1600_state::scc_irq(bool status)
|
|
{
|
|
m_maincpu->set_input_line(M68K_IRQ_5, status ? ASSERT_LINE : CLEAR_LINE);
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// Z8536_INTERFACE( cio_intf )
|
|
//-------------------------------------------------
|
|
|
|
READ8_MEMBER( abc1600_state::cio_pa_r )
|
|
{
|
|
/*
|
|
|
|
bit description
|
|
|
|
PA0 BUS2
|
|
PA1 BUS1
|
|
PA2 BUS0X*2
|
|
PA3 BUS0X*3
|
|
PA4 BUS0X*4
|
|
PA5 BUS0X*5
|
|
PA6 BUS0X
|
|
PA7 BUS0I
|
|
|
|
*/
|
|
|
|
UINT8 data = 0;
|
|
|
|
data |= m_bus2->int_r();
|
|
data |= m_bus1->int_r() << 1;
|
|
data |= m_bus0x->xint2_r() << 2;
|
|
data |= m_bus0x->xint3_r() << 3;
|
|
data |= m_bus0x->xint4_r() << 4;
|
|
data |= m_bus0x->xint5_r() << 5;
|
|
data |= m_bus0x->int_r() << 6;
|
|
data |= m_bus0i->int_r() << 7;
|
|
|
|
return data;
|
|
}
|
|
|
|
READ8_MEMBER( abc1600_state::cio_pb_r )
|
|
{
|
|
/*
|
|
|
|
bit description
|
|
|
|
PB0
|
|
PB1 POWERFAIL
|
|
PB2
|
|
PB3
|
|
PB4 MINT
|
|
PB5 _PREN-1
|
|
PB6 _PREN-0
|
|
PB7 FINT
|
|
|
|
*/
|
|
|
|
UINT8 data = 0;
|
|
|
|
data |= !m_sysscc << 5;
|
|
data |= !m_sysfs << 6;
|
|
|
|
// floppy interrupt
|
|
data |= wd17xx_intrq_r(m_fdc) << 7;
|
|
|
|
return data;
|
|
}
|
|
|
|
WRITE8_MEMBER( abc1600_state::cio_pb_w )
|
|
{
|
|
/*
|
|
|
|
bit description
|
|
|
|
PB0 PRBR
|
|
PB1
|
|
PB2
|
|
PB3
|
|
PB4
|
|
PB5
|
|
PB6
|
|
PB7
|
|
|
|
*/
|
|
|
|
// printer baudrate
|
|
int prbr = BIT(data, 0);
|
|
|
|
z80dart_txca_w(m_dart, prbr);
|
|
z80dart_rxca_w(m_dart, prbr);
|
|
}
|
|
|
|
READ8_MEMBER( abc1600_state::cio_pc_r )
|
|
{
|
|
/*
|
|
|
|
bit description
|
|
|
|
PC0 1
|
|
PC1 DATA IN
|
|
PC2 1
|
|
PC3 1
|
|
|
|
*/
|
|
|
|
UINT8 data = 0x0d;
|
|
|
|
// data in
|
|
data |= (m_rtc->dio_r() || m_nvram->do_r()) << 1;
|
|
|
|
return data;
|
|
}
|
|
|
|
WRITE8_MEMBER( abc1600_state::cio_pc_w )
|
|
{
|
|
/*
|
|
|
|
bit description
|
|
|
|
PC0 CLOCK
|
|
PC1 DATA OUT
|
|
PC2 RTC CS
|
|
PC3 NVRAM CS
|
|
|
|
*/
|
|
|
|
int clock = BIT(data, 0);
|
|
int data_out = BIT(data, 1);
|
|
int rtc_cs = BIT(data, 2);
|
|
int nvram_cs = BIT(data, 3);
|
|
|
|
if (LOG) logerror("CLK %u DATA %u RTC %u NVRAM %u\n", clock, data_out, rtc_cs, nvram_cs);
|
|
|
|
m_rtc->cs_w(rtc_cs);
|
|
m_rtc->dio_w(data_out);
|
|
m_rtc->clk_w(clock);
|
|
|
|
m_nvram->cs_w(nvram_cs);
|
|
m_nvram->di_w(data_out);
|
|
m_nvram->sk_w(clock);
|
|
}
|
|
|
|
static Z8536_INTERFACE( cio_intf )
|
|
{
|
|
DEVCB_CPU_INPUT_LINE(MC68008P8_TAG, M68K_IRQ_2),
|
|
DEVCB_DRIVER_MEMBER(abc1600_state, cio_pa_r),
|
|
DEVCB_NULL,
|
|
DEVCB_DRIVER_MEMBER(abc1600_state, cio_pb_r),
|
|
DEVCB_DRIVER_MEMBER(abc1600_state, cio_pb_w),
|
|
DEVCB_DRIVER_MEMBER(abc1600_state, cio_pc_r),
|
|
DEVCB_DRIVER_MEMBER(abc1600_state, cio_pc_w)
|
|
};
|
|
|
|
|
|
//-------------------------------------------------
|
|
// wd17xx_interface fdc_intf
|
|
//-------------------------------------------------
|
|
|
|
static LEGACY_FLOPPY_OPTIONS_START( abc1600 )
|
|
LEGACY_FLOPPY_OPTION(abc1600, "dsk", "Luxor ABC 1600", basicdsk_identify_default, basicdsk_construct_default, NULL,
|
|
HEADS([2])
|
|
TRACKS([80])
|
|
SECTORS([16])
|
|
SECTOR_LENGTH([256])
|
|
FIRST_SECTOR_ID([1]))
|
|
LEGACY_FLOPPY_OPTIONS_END
|
|
|
|
static const floppy_interface abc1600_floppy_interface =
|
|
{
|
|
DEVCB_NULL,
|
|
DEVCB_NULL,
|
|
DEVCB_NULL,
|
|
DEVCB_NULL,
|
|
DEVCB_NULL,
|
|
FLOPPY_STANDARD_5_25_DSQD,
|
|
LEGACY_FLOPPY_OPTIONS_NAME(abc1600),
|
|
"floppy_5_25",
|
|
NULL
|
|
};
|
|
|
|
WRITE_LINE_MEMBER( abc1600_state::drq_w )
|
|
{
|
|
update_drdy0();
|
|
}
|
|
|
|
static const wd17xx_interface fdc_intf =
|
|
{
|
|
DEVCB_NULL,
|
|
DEVCB_DEVICE_LINE_MEMBER(Z8536B1_TAG, z8536_device, pb7_w),
|
|
DEVCB_DRIVER_LINE_MEMBER(abc1600_state, drq_w),
|
|
{ FLOPPY_0, NULL, NULL, NULL } // TODO should be { NULL, NULL, FLOPPY_2, NULL }
|
|
};
|
|
|
|
|
|
//-------------------------------------------------
|
|
// ABC99_INTERFACE( abc99_intf )
|
|
//-------------------------------------------------
|
|
|
|
static ABC99_INTERFACE( abc99_intf )
|
|
{
|
|
DEVCB_DEVICE_LINE(Z8470AB1_TAG, z80dart_rxtxcb_w),
|
|
DEVCB_DEVICE_LINE(Z8470AB1_TAG, z80dart_dcdb_w)
|
|
};
|
|
|
|
|
|
//-------------------------------------------------
|
|
// ABC1600BUS_INTERFACE( abcbus_intf )
|
|
//-------------------------------------------------
|
|
|
|
static SLOT_INTERFACE_START( abc1600bus_cards )
|
|
SLOT_INTERFACE("4105", LUXOR_4105) // SASI interface
|
|
// SLOT_INTERFACE("4077", LUXOR_4077) // Winchester controller
|
|
// SLOT_INTERFACE("4004", LUXOR_4004) // ICOM I/O (Z80, Z80PIO, Z80SIO/2, Z80CTC, 2 Z80DMAs, 2 PROMs, 64KB RAM)
|
|
SLOT_INTERFACE_END
|
|
|
|
static ABC1600BUS_INTERFACE( bus0i_intf )
|
|
{
|
|
DEVCB_DEVICE_LINE_MEMBER(Z8536B1_TAG, z8536_device, pa7_w), // really inverted but ASSERT_LINE takes care of that
|
|
DEVCB_NULL,
|
|
DEVCB_NULL
|
|
};
|
|
|
|
WRITE_LINE_MEMBER( abc1600_state::nmi_w )
|
|
{
|
|
if (state == ASSERT_LINE)
|
|
{
|
|
m_maincpu->set_input_line(M68K_IRQ_7, ASSERT_LINE);
|
|
}
|
|
}
|
|
|
|
static ABC1600BUS_INTERFACE( bus0x_intf )
|
|
{
|
|
DEVCB_DEVICE_LINE_MEMBER(Z8536B1_TAG, z8536_device, pa6_w), // really inverted but ASSERT_LINE takes care of that
|
|
DEVCB_NULL,
|
|
DEVCB_NULL,
|
|
DEVCB_DRIVER_LINE_MEMBER(abc1600_state, nmi_w),
|
|
DEVCB_DEVICE_LINE_MEMBER(Z8536B1_TAG, z8536_device, pa2_w), // really inverted but ASSERT_LINE takes care of that
|
|
DEVCB_DEVICE_LINE_MEMBER(Z8536B1_TAG, z8536_device, pa3_w), // really inverted but ASSERT_LINE takes care of that
|
|
DEVCB_DEVICE_LINE_MEMBER(Z8536B1_TAG, z8536_device, pa4_w), // really inverted but ASSERT_LINE takes care of that
|
|
DEVCB_DEVICE_LINE_MEMBER(Z8536B1_TAG, z8536_device, pa5_w) // really inverted but ASSERT_LINE takes care of that
|
|
};
|
|
|
|
static ABC1600BUS_INTERFACE( bus1_intf )
|
|
{
|
|
DEVCB_DEVICE_LINE_MEMBER(Z8536B1_TAG, z8536_device, pa1_w), // really inverted but ASSERT_LINE takes care of that
|
|
DEVCB_NULL,
|
|
DEVCB_NULL
|
|
};
|
|
|
|
static ABC1600BUS_INTERFACE( bus2_intf )
|
|
{
|
|
DEVCB_DEVICE_LINE_MEMBER(Z8536B1_TAG, z8536_device, pa0_w), // really inverted but ASSERT_LINE takes care of that
|
|
DEVCB_NULL, // DEVCB_DEVICE_LINE_MEMBER(Z8410AB1_2_TAG, z80dma_device, iei_w) inverted
|
|
DEVCB_DEVICE_LINE_MEMBER(Z8410AB1_2_TAG, z80dma_device, rdy_w)
|
|
};
|
|
|
|
|
|
|
|
//**************************************************************************
|
|
// MACHINE INITIALIZATION
|
|
//**************************************************************************
|
|
|
|
//-------------------------------------------------
|
|
// IRQ_CALLBACK( abc1600_int_ack )
|
|
//-------------------------------------------------
|
|
|
|
static IRQ_CALLBACK( abc1600_int_ack )
|
|
{
|
|
abc1600_state *state = device->machine().driver_data<abc1600_state>();
|
|
int data = 0;
|
|
|
|
switch (irqline)
|
|
{
|
|
case M68K_IRQ_2:
|
|
data = state->m_cio->intack_r();
|
|
break;
|
|
|
|
case M68K_IRQ_5:
|
|
data = state->m_dart->m1_r();
|
|
break;
|
|
|
|
case M68K_IRQ_7:
|
|
state->m_maincpu->set_input_line(M68K_IRQ_7, CLEAR_LINE);
|
|
|
|
data = M68K_INT_ACK_AUTOVECTOR;
|
|
break;
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// MACHINE_START( abc1600 )
|
|
//-------------------------------------------------
|
|
|
|
void abc1600_state::machine_start()
|
|
{
|
|
// interrupt callback
|
|
m_maincpu->set_irq_acknowledge_callback(abc1600_int_ack);
|
|
|
|
// allocate memory
|
|
m_segment_ram.allocate(0x400);
|
|
m_page_ram.allocate(0x400);
|
|
|
|
// HACK fill segment RAM with non-zero values or no boot
|
|
memset(m_segment_ram, 0xcd, 0x400);
|
|
|
|
// state saving
|
|
save_item(NAME(m_ifc2));
|
|
save_item(NAME(m_task));
|
|
save_item(NAME(m_dmamap));
|
|
save_item(NAME(m_dmadis));
|
|
save_item(NAME(m_sysscc));
|
|
save_item(NAME(m_sysfs));
|
|
save_item(NAME(m_cause));
|
|
save_item(NAME(m_partst));
|
|
save_item(NAME(m_cs7));
|
|
save_item(NAME(m_bus0));
|
|
save_item(NAME(m_csb));
|
|
save_item(NAME(m_atce));
|
|
save_item(NAME(m_btce));
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// MACHINE_RESET( abc1600 )
|
|
//-------------------------------------------------
|
|
|
|
void abc1600_state::machine_reset()
|
|
{
|
|
address_space &program = m_maincpu->space(AS_PROGRAM);
|
|
|
|
// clear special control register
|
|
for (int i = 0; i < 8; i++)
|
|
{
|
|
spec_contr_reg_w(program, 0, i);
|
|
}
|
|
|
|
// clear floppy registers
|
|
fw0_w(program, 0, 0);
|
|
fw1_w(program, 0, 0);
|
|
|
|
// clear task register
|
|
m_task = 0;
|
|
|
|
// disable display
|
|
m_clocks_disabled = 1;
|
|
m_endisp = 0;
|
|
|
|
// clear NMI
|
|
m_maincpu->set_input_line(M68K_IRQ_7, CLEAR_LINE);
|
|
}
|
|
|
|
|
|
|
|
//**************************************************************************
|
|
// MACHINE CONFIGURATION
|
|
//**************************************************************************
|
|
|
|
//-------------------------------------------------
|
|
// MACHINE_CONFIG( abc1600 )
|
|
//-------------------------------------------------
|
|
|
|
static MACHINE_CONFIG_START( abc1600, abc1600_state )
|
|
// basic machine hardware
|
|
MCFG_CPU_ADD(MC68008P8_TAG, M68008, XTAL_64MHz/8)
|
|
MCFG_CPU_PROGRAM_MAP(abc1600_mem)
|
|
MCFG_WATCHDOG_TIME_INIT(attotime::from_msec(1600)) // XTAL_64MHz/8/10/20000/8/8
|
|
|
|
// video hardware
|
|
MCFG_FRAGMENT_ADD(abc1600_video)
|
|
|
|
// devices
|
|
MCFG_Z80DMA_ADD(Z8410AB1_0_TAG, XTAL_64MHz/16, dma0_intf)
|
|
MCFG_Z80DMA_ADD(Z8410AB1_1_TAG, XTAL_64MHz/16, dma1_intf)
|
|
MCFG_Z80DMA_ADD(Z8410AB1_2_TAG, XTAL_64MHz/16, dma2_intf)
|
|
MCFG_Z80DART_ADD(Z8470AB1_TAG, XTAL_64MHz/16, dart_intf)
|
|
MCFG_SCC8530_ADD(Z8530B1_TAG, XTAL_64MHz/16, line_cb_t(FUNC(abc1600_state::scc_irq), static_cast<abc1600_state *>(owner)))
|
|
MCFG_Z8536_ADD(Z8536B1_TAG, XTAL_64MHz/16, cio_intf)
|
|
MCFG_NMC9306_ADD(NMC9306_TAG)
|
|
MCFG_E0516_ADD(E050_C16PC_TAG, XTAL_32_768kHz)
|
|
MCFG_FD1797_ADD(SAB1797_02P_TAG, fdc_intf)
|
|
MCFG_LEGACY_FLOPPY_DRIVE_ADD(FLOPPY_0, abc1600_floppy_interface)
|
|
MCFG_ABC99_ADD(abc99_intf)
|
|
|
|
MCFG_ABC1600BUS_SLOT_ADD("bus0i", bus0i_intf, abc1600bus_cards, NULL, NULL)
|
|
MCFG_ABC1600BUS_SLOT_ADD("bus0x", bus0x_intf, abc1600bus_cards, NULL, NULL)
|
|
MCFG_ABC1600BUS_SLOT_ADD("bus1", bus1_intf, abc1600bus_cards, NULL, NULL)
|
|
MCFG_ABC1600BUS_SLOT_ADD("bus2", bus2_intf, abc1600bus_cards, "4105", NULL)
|
|
|
|
// internal ram
|
|
MCFG_RAM_ADD(RAM_TAG)
|
|
MCFG_RAM_DEFAULT_SIZE("1M")
|
|
|
|
// software list
|
|
MCFG_SOFTWARE_LIST_ADD("flop_list", "abc1600")
|
|
MACHINE_CONFIG_END
|
|
|
|
|
|
|
|
//**************************************************************************
|
|
// ROMS
|
|
//**************************************************************************
|
|
|
|
//-------------------------------------------------
|
|
// ROM( abc1600 )
|
|
//-------------------------------------------------
|
|
|
|
ROM_START( abc1600 )
|
|
ROM_REGION( 0x4000, MC68008P8_TAG, 0 )
|
|
ROM_LOAD( "boot 6490356-04.1f", 0x0000, 0x4000, CRC(9372f6f2) SHA1(86f0681f7ef8dd190b49eda5e781881582e0c2a4) )
|
|
|
|
ROM_REGION( 0x2000, "wrmsk", 0 )
|
|
ROM_LOAD( "wrmskl 6490362-01.1g", 0x0000, 0x1000, CRC(bc737538) SHA1(80e2c3757eb7f713018808d6e41ebef612425028) )
|
|
ROM_LOAD( "wrmskh 6490363-01.1j", 0x1000, 0x1000, CRC(6b7c9f0b) SHA1(7155a993adcf08a5a8a2f22becf9fd66fda698be) )
|
|
|
|
ROM_REGION( 0x200, "shinf", 0 )
|
|
ROM_LOAD( "shinf 6490361-01.1f", 0x000, 0x200, CRC(20260f8f) SHA1(29bf49c64e7cc7592e88cde2768ac57c7ce5e085) )
|
|
|
|
ROM_REGION( 0x40, "drmsk", 0 )
|
|
ROM_LOAD( "drmskl 6490359-01.1k", 0x00, 0x20, CRC(6e71087c) SHA1(0acf67700d6227f4b315cf8fb0fb31c0e7fb9496) )
|
|
ROM_LOAD( "drmskh 6490358-01.1l", 0x20, 0x20, CRC(a4a9a9dc) SHA1(d8575c0335d6021cbb5f7bcd298b41c35294a80a) )
|
|
|
|
ROM_REGION( 0x71c, "plds", 0 )
|
|
ROM_LOAD( "drmsk 6490360-01.1m", 0x000, 0x104, CRC(5f7143c1) SHA1(1129917845f8e505998b15288f02bf907487e4ac) ) // mover word mixer @ 1m,1n,1t,2t
|
|
ROM_LOAD( "1020 6490349-01.8b", 0x104, 0x104, CRC(1fa065eb) SHA1(20a95940e39fa98e97e59ea1e548ac2e0c9a3444) ) // expansion bus strobes
|
|
ROM_LOAD( "1021 6490350-01.5d", 0x208, 0x104, CRC(96f6f44b) SHA1(12d1cd153dcc99d1c4a6c834122f370d49723674) ) // interrupt encoder and ROM/RAM control
|
|
ROM_LOAD( "1022 6490351-01.17e", 0x30c, 0x104, CRC(5dd00d43) SHA1(a3871f0d796bea9df8f25d41b3169dd4b8ef65ab) ) // MAC register address decoder
|
|
ROM_LOAD( "1023 6490352-01.11e", 0x410, 0x104, CRC(a2f350ac) SHA1(77e08654a197080fa2111bc3031cd2c7699bf82b) ) // interrupt acknowledge
|
|
ROM_LOAD( "1024 6490353-01.12e", 0x514, 0x104, CRC(67f1328a) SHA1(b585495fe14a7ae2fbb29f722dca106d59325002) ) // expansion bus timing and control
|
|
ROM_LOAD( "1025 6490354-01.6e", 0x618, 0x104, CRC(9bda0468) SHA1(ad373995dcc18532274efad76fa80bd13c23df25) ) // DMA transfer
|
|
//ROM_LOAD( "pal16r4.10c", 0x71c, 0x104, NO_DUMP ) // SCC read/write, mentioned in the preliminary service manual, but not present on the PCB
|
|
ROM_END
|
|
|
|
|
|
|
|
//**************************************************************************
|
|
// SYSTEM DRIVERS
|
|
//**************************************************************************
|
|
|
|
// YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME FLAGS
|
|
COMP( 1985, abc1600, 0, 0, abc1600, abc1600, driver_device, 0, "Luxor", "ABC 1600", GAME_NOT_WORKING )
|