(MESS) exelv.c [Gilles Fétis]

Improved emulation in driver to the point where exl100 will successfully load and execute cartridges.  Still lacking any input at the moment.
This commit is contained in:
Scott Stone 2014-06-02 17:16:56 +00:00
parent d82ee5722e
commit 4c281269f8
5 changed files with 311 additions and 236 deletions

View File

@ -43,6 +43,7 @@
#define WM(Addr,Value) (m_program->write_byte(Addr, Value))
#define IMMBYTE(b) b = ((unsigned)m_direct->read_raw_byte(pPC)); pPC++
#define SKIPBYTE() ((unsigned)m_direct->read_raw_byte(pPC)); pPC++
#define SIMMBYTE(b) b = ((signed)m_direct->read_raw_byte(pPC)); pPC++
#define IMMWORD(w) w.b.h = (unsigned)m_direct->read_raw_byte(pPC++); w.b.l = (unsigned)m_direct->read_raw_byte(pPC++)
@ -59,7 +60,7 @@ const device_type TMS7000_EXL = &device_creator<tms7000_exl_device>;
static ADDRESS_MAP_START(tms7000_mem, AS_PROGRAM, 8, tms7000_device )
AM_RANGE(0x0000, 0x007f) AM_READWRITE(tms7000_internal_r, tms7000_internal_w) /* tms7000 internal RAM */
AM_RANGE(0x0080, 0x00ff) AM_NOP /* reserved */
AM_RANGE(0x0100, 0x01ff) AM_READWRITE(tms70x0_pf_r, tms70x0_pf_w) /* tms7000 internal I/O ports */
AM_RANGE(0x0100, 0x010f) AM_READWRITE(tms70x0_pf_r, tms70x0_pf_w) /* tms7000 internal I/O ports */
ADDRESS_MAP_END
@ -119,6 +120,8 @@ offs_t tms7000_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *
#define SET_Z16(a) SET_Z((UINT8)a>>8)
#define GET_C (pSR >> 7)
#define SET_N16(a) pSR|=(((a)&0x008000)>>9)
/* Not working */
#define SET_C16(a) pSR|=((a&0x010000)>>9)

View File

@ -761,7 +761,7 @@ void tms7000_device::btjz_b2a()
{
UINT8 t;
t = RDB & ~RDA;
t = RDB & (~RDA);
CLR_NZC;
SET_N8(t);
@ -787,7 +787,7 @@ void tms7000_device::btjz_r2a()
UINT8 t,r;
IMMBYTE( r );
t = RM( r ) & ~RDA;
t = RM( r ) & (~RDA);
CLR_NZC;
SET_N8(t);
@ -813,7 +813,7 @@ void tms7000_device::btjz_r2b()
UINT8 t,r;
IMMBYTE(r);
t = RM(r) & ~RDB;
t = RM(r) & (~RDB);
CLR_NZC;
SET_N8(t);
@ -840,7 +840,7 @@ void tms7000_device::btjz_r2r()
IMMBYTE(r);
IMMBYTE(s);
t = RM(r) & ~RM(s);
t = RM(r) & (~RM(s));
CLR_NZC;
SET_N8(t);
@ -866,7 +866,7 @@ void tms7000_device::btjz_i2a()
UINT8 t,r;
IMMBYTE(r);
t = r & ~RDA;
t = r & (~RDA);
CLR_NZC;
SET_N8(t);
@ -892,7 +892,7 @@ void tms7000_device::btjz_i2b()
UINT8 t,i;
IMMBYTE(i);
t = i & ~RDB;
t = i & (~RDB);
CLR_NZC;
SET_N8(t);
@ -919,7 +919,7 @@ void tms7000_device::btjz_i2r()
IMMBYTE(i);
IMMBYTE(r);
t = i & ~RM(r);
t = i & (~RM(r));
CLR_NZC;
SET_N8(t);
@ -946,7 +946,7 @@ void tms7000_device::btjzp_ap()
IMMBYTE(p);
t = RDA & ~RM(0x100+p);
t = RDA & (~RM(0x100+p));
CLR_NZC;
SET_N8(t);
@ -973,7 +973,7 @@ void tms7000_device::btjzp_bp()
IMMBYTE(p);
t = RDB & ~RM(0x100+p);
t = RDB & (~RM(0x100+p));
CLR_NZC;
SET_N8(t);
@ -1001,7 +1001,7 @@ void tms7000_device::btjzp_ip()
IMMBYTE(i);
IMMBYTE(p);
t = i & ~RM(0x100+p);
t = i & (~RM(0x100+p));
CLR_NZC;
SET_N8(t);
@ -1057,12 +1057,16 @@ void tms7000_device::call_inx()
void tms7000_device::clr_a()
{
WRA(0);
CLR_NZC;
SETZ;
m_icount -= 5;
}
void tms7000_device::clr_b()
{
WRB(0);
CLR_NZC;
SETZ;
m_icount -= 5;
}
@ -1072,6 +1076,8 @@ void tms7000_device::clr_r()
IMMBYTE(r);
WM(r,0);
CLR_NZC;
SETZ;
m_icount -= 7;
}
@ -1098,11 +1104,7 @@ void tms7000_device::cmp_ba()
SET_N8(t);
SET_Z8(t);
if( t==0 )
SETC;
else
SET_C8( ~t );
SET_C8( ~t );
m_icount -= 5;
}
@ -1118,10 +1120,7 @@ void tms7000_device::cmp_ra()
SET_N8(t);
SET_Z8(t);
if( t==0 )
SETC;
else
SET_C8( ~t );
SET_C8( ~t );
m_icount -= 8;
}
@ -1137,11 +1136,8 @@ void tms7000_device::cmp_rb()
CLR_NZC;
SET_N8(t);
SET_Z8(t);
if( t==0 )
SETC;
else
SET_C8( ~t );
SET_C8( ~t );
m_icount -= 8;
}
@ -1159,10 +1155,7 @@ void tms7000_device::cmp_rr()
SET_N8(t);
SET_Z8(t);
if( t==0 )
SETC;
else
SET_C8( ~t );
SET_C8( ~t );
m_icount -= 10;
}
@ -1179,10 +1172,7 @@ void tms7000_device::cmp_ia()
SET_N8(t);
SET_Z8(t);
if( t==0 )
SETC;
else
SET_C8( ~t );
SET_C8( ~t );
m_icount -= 7;
}
@ -1198,11 +1188,7 @@ void tms7000_device::cmp_ib()
CLR_NZC;
SET_N8(t);
SET_Z8(t);
if( t==0 )
SETC;
else
SET_C8( ~t );
SET_C8( ~t );
m_icount -= 7;
}
@ -1219,11 +1205,7 @@ void tms7000_device::cmp_ir()
CLR_NZC;
SET_N8(t);
SET_Z8(t);
if( t==0 )
SETC;
else
SET_C8( ~t );
SET_C8( ~t );
m_icount -= 9;
}
@ -1239,11 +1221,7 @@ void tms7000_device::cmpa_dir()
CLR_NZC;
SET_N8(t);
SET_Z8(t);
if( t==0 )
SETC;
else
SET_C8( ~t );
SET_C8( ~t );
m_icount -= 12;
}
@ -1261,11 +1239,7 @@ void tms7000_device::cmpa_ind()
CLR_NZC;
SET_N8(t);
SET_Z8(t);
if( t==0 )
SETC;
else
SET_C8( ~t );
SET_C8( ~t );
m_icount -= 11;
}
@ -1281,11 +1255,7 @@ void tms7000_device::cmpa_inx()
CLR_NZC;
SET_N8(t);
SET_Z8(t);
if( t==0 )
SETC;
else
SET_C8( ~t );
SET_C8( ~t );
m_icount -= 14;
}
@ -1370,7 +1340,7 @@ void tms7000_device::dec_a()
CLR_NZC;
SET_N8(t);
SET_Z8(t);
SET_C8(~t);
if ((t&0xFF)!=0xFF) SETC;
m_icount -= 5;
}
@ -1386,7 +1356,7 @@ void tms7000_device::dec_b()
CLR_NZC;
SET_N8(t);
SET_Z8(t);
SET_C8(~t);
if ((t&0xFF)!=0xFF) SETC;
m_icount -= 5;
}
@ -1405,7 +1375,7 @@ void tms7000_device::dec_r()
CLR_NZC;
SET_N8(t);
SET_Z8(t);
SET_C8(~t);
if ((t&0xFF)!=0xFF) SETC;
m_icount -= 7;
}
@ -1420,11 +1390,13 @@ void tms7000_device::decd_a()
WRF16(0,t);
CLR_NZC;
SET_N8(t.b.h);
SET_Z8(t.b.h);
SET_C16(~(t.d));
SET_N16(t.d);
if ((t.d&0xFF00)==0) SETZ;
if ((t.d&0xFFFF)!=0xFFFF) SETC;
m_icount -= 9;
}
@ -1438,10 +1410,10 @@ void tms7000_device::decd_b()
WRF16(1,t);
CLR_NZC;
SET_N8(t.b.h);
SET_Z8(t.b.h);
SET_N16(t.d);
SET_C16(~(t.d));
if ((t.d&0xFF00)==0) SETZ;
if ((t.d&0xFFFF)!=0xFFFF) SETC;
m_icount -= 9;
}
@ -1458,10 +1430,10 @@ void tms7000_device::decd_r()
WRF16(r,t);
CLR_NZC;
SET_N8(t.b.h);
SET_Z8(t.b.h);
SET_N16(t.d);
SET_C16(~(t.d));
if ((t.d&0xFF00)==0) SETZ;
if ((t.d&0xFFFF)!=0xFFFF) SETC;
m_icount -= 11;
}
@ -1480,10 +1452,6 @@ void tms7000_device::djnz_a()
WRA( t );
CLR_NZC;
SET_N8(t);
SET_Z8(t);
if( t != 0 )
{
INT8 s;
@ -1507,10 +1475,6 @@ void tms7000_device::djnz_b()
WRB( t );
CLR_NZC;
SET_N8(t);
SET_Z8(t);
if( t != 0 )
{
INT8 s;
@ -1536,11 +1500,6 @@ void tms7000_device::djnz_r()
t = RM(r) - 1;
WM(r,t);
CLR_NZC;
SET_N8(t);
SET_Z8(t);
if( t != 0 )
{
INT8 s;
@ -2117,7 +2076,7 @@ void tms7000_device::movd_inx()
UINT8 r;
IMMWORD(t);
t.w.l += RDB;
t.w.l = (t.w.l+RDB)&0xFFFF;
IMMBYTE(r);
WRF16(r,t);
@ -3461,42 +3420,23 @@ void tms7000_device::swap_r()
void tms7000_device::swap_r_exl()
{
UINT8 a,b,r;
UINT16 t;
UINT16 t;
IMMBYTE(r);
SKIPBYTE();
if (r == 0)
{ /* opcode D7 00 (LVDP) mostly equivalent to MOVP P46,A??? (timings must
be different, possibly the microcode polls the state of the VDP RDY
line prior to doing the transfer) */
t=RM(0x012e);
WRA(t);
/* opcode D7 ?? (LVDP) mostly equivalent to
* MOVP P40,xx
* MOVP P36,A
*/
RM(0x0128);
t=RM(0x0124);
WM(0,t);
CLR_NZC;
SET_N8(t);
SET_Z8(t);
CLR_NZC;
SET_N8(t);
SET_Z8(t);
m_icount -= 9; /* ?????? */
}
else
{ /* stright swap Rn instruction */
a = b = RM(r);
a <<= 4;
b >>= 4;
t = a+b;
WM(r,t);
CLR_NZC;
pSR|=((t&0x0001)<<7);
SET_N8(t);
SET_Z8(t);
m_icount -=8;
}
m_icount -= 9; /* FIXME : check real timing */
}
void tms7000_device::tstb()
@ -3532,13 +3472,8 @@ void tms7000_device::xchb_a()
void tms7000_device::xchb_b()
{
UINT16 t;
/* UINT16 u; */
t = RDB;
/* u = RDB; */
/* WRB(t); */
/* WRB(u); */
CLR_NZC;
SET_N8(t);
@ -3557,7 +3492,7 @@ void tms7000_device::xchb_r()
t = RDB;
u = RM(r);
WRA(t);
WM(r,t);
WRB(u);
CLR_NZC;

View File

@ -20,6 +20,8 @@
#define LOG 0
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
@ -54,7 +56,7 @@ const address_space_config *tms3556_device::memory_space_config(address_spacenum
inline UINT8 tms3556_device::readbyte(offs_t address)
{
return space().read_byte(address);
return space().read_byte(address&0xFFFF);
}
@ -64,7 +66,7 @@ inline UINT8 tms3556_device::readbyte(offs_t address)
inline void tms3556_device::writebyte(offs_t address, UINT8 data)
{
space().write_byte(address, data);
space().write_byte(address&0xFFFF, data);
}
@ -80,10 +82,14 @@ tms3556_device::tms3556_device(const machine_config &mconfig, const char *tag, d
: device_t(mconfig, TMS3556, "Texas Instruments VDP TMS3556", tag, owner, clock, "tms3556", __FILE__),
device_memory_interface(mconfig, *this),
m_space_config("videoram", ENDIANNESS_LITTLE, 8, 17, 0, NULL, *ADDRESS_MAP_NAME(tms3556)),
m_write_ptr(0),
m_reg_ptr(0),
m_reg_access_phase(0),
m_magical_mystery_flag(0),
m_row_col_written(0),
m_bamp_written(0),
m_colrow(0),
m_vdp_acmpxy_mode(dma_write),
m_vdp_acmpxy(0),
m_vdp_acmp(0),
m_init_read(0),
m_scanline(0),
m_blink(0),
m_blink_count(0),
@ -92,7 +98,7 @@ tms3556_device::tms3556_device(const machine_config &mconfig, const char *tag, d
for (int i = 0; i < 8; i++)
{
m_control_regs[i] = 0;
m_address_regs[i] = 0;
m_address_regs[i] = 0xFFFF;
}
}
@ -106,10 +112,13 @@ void tms3556_device::device_start()
// register for state saving
save_item(NAME(m_control_regs));
save_item(NAME(m_address_regs));
save_item(NAME(m_write_ptr));
save_item(NAME(m_reg_ptr));
save_item(NAME(m_reg_access_phase));
save_item(NAME(m_magical_mystery_flag));
save_item(NAME(m_row_col_written));
save_item(NAME(m_bamp_written));
save_item(NAME(m_colrow));
// save_item(NAME(m_vdp_acmpxy_mode)); // FIXME : mame cannot save enum
save_item(NAME(m_vdp_acmpxy));
save_item(NAME(m_vdp_acmp));
save_item(NAME(m_scanline));
save_item(NAME(m_blink));
save_item(NAME(m_blink_count));
@ -139,15 +148,36 @@ UINT32 tms3556_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap
READ8_MEMBER( tms3556_device::vram_r )
{
if (LOG) logerror("TMS3556 VRAM Read: %06x\n", offset);
UINT8 ret;
if (m_bamp_written) {
m_bamp_written=false;
m_vdp_acmpxy_mode=dma_write;
if (m_init_read)
m_vdp_acmp=VDP_BAMP;
else
m_vdp_acmp=(VDP_BAMP-1)&0xFFFF;
}
if (m_magical_mystery_flag)
{
m_write_ptr = ((m_control_regs[2] << 8) | m_control_regs[1]) + 1;
m_magical_mystery_flag = 0;
}
if (m_row_col_written) {
m_row_col_written=0;
m_vdp_acmpxy_mode=dma_read;
if (m_init_read)
m_vdp_acmpxy=m_colrow;
else
m_vdp_acmpxy=(m_colrow-1)&0xFFFF;
}
return readbyte(m_address_regs[1]++);
m_init_read=false;
if (m_vdp_acmpxy_mode==dma_read) {
ret=readbyte(m_vdp_acmpxy);
m_vdp_acmpxy++;
if (m_vdp_acmpxy==VDP_BAMTF) m_vdp_acmpxy=VDP_BAMP;
} else {
ret=readbyte(m_vdp_acmp);
m_vdp_acmp++;
if (m_vdp_acmp==VDP_BAMTF) m_vdp_acmp=VDP_BAMP;
}
return ret;
}
//-------------------------------------------------
@ -156,15 +186,28 @@ READ8_MEMBER( tms3556_device::vram_r )
WRITE8_MEMBER( tms3556_device::vram_w )
{
if (LOG) logerror("TMS3556 VRAM Write: %06x = %02x\n", offset, data);
if (m_bamp_written) {
m_bamp_written=false;
m_vdp_acmpxy_mode=dma_read;
m_vdp_acmp=VDP_BAMP;
}
if (m_magical_mystery_flag)
{
m_write_ptr = (m_control_regs[2] << 8) | m_control_regs[1];
m_magical_mystery_flag = 0;
}
if (m_row_col_written) {
m_row_col_written=0;
m_vdp_acmpxy_mode=dma_write;
m_vdp_acmpxy=m_colrow;
}
if (m_vdp_acmpxy_mode==dma_write) {
writebyte(m_vdp_acmpxy,data);
m_vdp_acmpxy++;
if (m_vdp_acmpxy==VDP_BAMTF) m_vdp_acmpxy=VDP_BAMP;
} else {
writebyte(m_vdp_acmp,data);
m_vdp_acmp++;
if (m_vdp_acmp==VDP_BAMTF) m_vdp_acmp=VDP_BAMP;
}
writebyte(m_write_ptr++, data);
}
@ -176,18 +219,8 @@ READ8_MEMBER( tms3556_device::reg_r )
{
if (LOG) logerror("TMS3556 Reg Read: %06x\n", offset);
int reply = 0;
if (m_reg_ptr < 8)
{
reply = m_control_regs[m_reg_ptr];
m_reg_access_phase = 0;
}
else
{
// ???
}
int reply = 0; // FIXME : will send internal status (VBL, HBL...)
m_reg_access_phase=0;
return reply;
}
@ -197,54 +230,85 @@ READ8_MEMBER( tms3556_device::reg_r )
WRITE8_MEMBER( tms3556_device::reg_w )
{
static int reg2=0; // FIXME : this static makes that only one TMS3556 will be present in one system...
static int reg=0;
if (LOG) logerror("TMS3556 Reg Write: %06x = %02x\n", offset, data);
if ((m_reg_access_phase == 3) && (data))
m_reg_access_phase = 0; /* ???????????? */
switch (m_reg_access_phase) {
case 0:
reg=data&0x0F;
reg2=(data&0xF0)>>4;
if (reg!=0)
m_reg_access_phase=1;
return;
switch (m_reg_access_phase)
{
case 0:
m_reg_ptr = data & 0x0f;
m_reg_access_phase = 1;
break;
case 1:
if (reg<8) {
m_control_regs[reg]=data;
// leve un flag si le dernier registre ecrit est row ou col
if ((reg==2) || (reg==1)) {
m_colrow=(m_control_regs[2]<<8)|m_control_regs[1];
m_row_col_written=true;
}
case 1:
if (m_reg_ptr < 8)
{
m_control_regs[m_reg_ptr] = data;
m_reg_access_phase = 0;
if (m_reg_ptr == 2)
m_magical_mystery_flag = 1;
}
else if (m_reg_ptr == 9)
{ /* I don't understand what is going on, but it is the only way to
get this to work */
m_address_regs[m_reg_ptr - 8] = ((m_control_regs[2] << 8) | m_control_regs[1]) + 1;
m_reg_access_phase = 0;
m_magical_mystery_flag = 0;
}
else
{
m_address_regs[m_reg_ptr - 8] = (m_control_regs[m_reg_ptr - 8] & 0xff00) | m_control_regs[1];
m_reg_access_phase = 2;
m_magical_mystery_flag = 0;
}
break;
if (reg2==0) {
m_reg_access_phase=0;
return;
}
else {
m_reg_access_phase=1;
reg=reg2;
reg2=0;
return;
}
} else {
m_address_regs[reg-8]=(m_control_regs[2]<<8)|m_control_regs[1];
// cas speciaux de decalage pour les generateurs
if ((reg>=0xB) && (reg<=0xE)) {
m_address_regs[reg-8]+=2;
m_address_regs[reg-8]&=0xFFFF;
} else {
m_address_regs[reg-8]+=1;
m_address_regs[reg-8]&=0xFFFF;
}
if (reg==9) {
m_row_col_written=false;
m_bamp_written=true;
m_reg_access_phase=0;
return;
} else {
m_row_col_written=0;
m_bamp_written=false;
m_reg_access_phase=2;//???
return;
}
logerror("VDP16[%d] = x%x",reg,m_address_regs[reg-8]);
if (reg2==0) {
m_reg_access_phase=0;
return;
}
else {
m_reg_access_phase=1;
reg=reg2;
reg2=0;
return;
}
}
case 2:
m_reg_access_phase=0;
return;
}
}
case 2:
m_address_regs[m_reg_ptr - 8] = (m_control_regs[m_reg_ptr - 8] & 0x00ff) | (m_control_regs[2] << 8);
if ((m_reg_ptr <= 10) || (m_reg_ptr == 15))
m_address_regs[m_reg_ptr - 8]++;
else
m_address_regs[m_reg_ptr - 8] += 2;
m_reg_access_phase = 3;
break;
//--------------------------------------------------------------------------
// initptr_r - set VDP in read mode (not exacly on the VDP but on the TAL)
//--------------------------------------------------------------------------
case 3:
m_reg_access_phase = 0;
break;
}
READ8_MEMBER( tms3556_device::initptr_r )
{
m_init_read=true;
return 0xff;
}
@ -509,6 +573,7 @@ void tms3556_device::draw_line(bitmap_ind16 &bmp, int line)
{
/* draw top and bottom borders */
draw_line_empty(ln);
m_cg_flag=0; // FIXME : forme text mode for 1st line in mixed
}
else
{

View File

@ -22,13 +22,29 @@
#define TMS3556_TOTAL_HEIGHT (250 + TMS3556_TOP_BORDER + TMS3556_BOTTOM_BORDER)
/* if DOUBLE_WIDTH set, the horizontal resolution is doubled */
#define TMS3556_DOUBLE_WIDTH 1
#define TMS3556_DOUBLE_WIDTH 0
#define TMS3556_MODE_OFF 0
#define TMS3556_MODE_TEXT 1
#define TMS3556_MODE_BITMAP 2
#define TMS3556_MODE_MIXED 3
#define VDP_POINTER m_control_regs[0]
#define VDP_COL m_control_regs[1]
#define VDP_ROW m_control_regs[2]
#define VDP_STAT m_control_regs[3]
#define VDP_CM1 m_control_regs[4]
#define VDP_CM2 m_control_regs[5]
#define VDP_CM3 m_control_regs[6]
#define VDP_CM4 m_control_regs[7]
#define VDP_BAMT m_address_regs[0]
#define VDP_BAMP m_address_regs[1]
#define VDP_BAPA m_address_regs[2]
#define VDP_BAGC0 m_address_regs[3]
#define VDP_BAGC1 m_address_regs[4]
#define VDP_BAGC2 m_address_regs[5]
#define VDP_BAGC3 m_address_regs[6]
#define VDP_BAMTF m_address_regs[7]
///*************************************************************************
// INTERFACE CONFIGURATION MACROS
@ -41,6 +57,9 @@
// TYPE DEFINITIONS
///*************************************************************************
typedef enum { dma_read, dma_write } dma_mode_tt;
// ======================> tms3556_device
class tms3556_device : public device_t,
@ -54,6 +73,7 @@ public:
DECLARE_WRITE8_MEMBER( vram_w );
DECLARE_READ8_MEMBER( reg_r );
DECLARE_WRITE8_MEMBER( reg_w );
DECLARE_READ8_MEMBER( initptr_r );
void interrupt(running_machine &machine);
@ -85,12 +105,17 @@ private:
// registers
UINT8 m_control_regs[8];
UINT16 m_address_regs[8];
UINT16 m_write_ptr;
// register interface
int m_reg_ptr;
int m_reg_access_phase;
int m_magical_mystery_flag;
int m_row_col_written;
int m_bamp_written;
int m_colrow;
dma_mode_tt m_vdp_acmpxy_mode;
UINT16 m_vdp_acmpxy;
UINT16 m_vdp_acmp;
int m_init_read;
int m_scanline; // scanline counter
int m_blink, m_blink_count; // blinking

View File

@ -21,7 +21,7 @@
Specs:
* main CPU is a variant of tms7020 (exl100) or tms7040 (exeltel). AFAIK,
the only difference compared to a stock tms7020/7040 is the SWAP R0
the only difference compared to a stock tms7020/7040 is the SWAP register
instruction is replaced by a custom microcoded LVDP instruction that
reads a byte from the VDP VRAM read port; it seems that the first 6 bytes
of internal ROM (0xF000-0xF005 on an exeltel) are missing, too.
@ -37,7 +37,7 @@ Specs:
CPU
* keyboard and joystick: an I/R interface controlled by the I/O CPU enables
to use a keyboard and two joysticks
* mass storage: tape interface controlled by the I/O CPU
* mass storage: tape interface controlled by the main CPU
STATUS:
* EXL 100 cannot be emulated because the ROMs are not dumped
@ -55,7 +55,7 @@ TODO:
#include "video/tms3556.h"
#include "sound/tms5220.h"
#include "machine/spchrom.h"
//#include "imagedev/cartslot.h"
#include "imagedev/cartslot.h"
//#include "imagedev/cassette.h"
@ -105,9 +105,37 @@ public:
UINT8 m_wx319; /* data of 74sl374 labeled wx319 */
DECLARE_PALETTE_INIT(exelv);
TIMER_DEVICE_CALLBACK_MEMBER(exelv_hblank_interrupt);
DECLARE_DEVICE_IMAGE_LOAD_MEMBER( exelvision_cartridge );
};
DEVICE_IMAGE_LOAD_MEMBER( exelv_state, exelvision_cartridge )
{
UINT8* pos = memregion("user1")->base();
offs_t size;
if (image.software_entry() == NULL)
size = image.length();
else
size = image.get_software_region_length("rom");
if (image.software_entry() == NULL)
{
image.fread( pos, size );
}
else
{
memcpy(pos, image.get_software_region("rom"), size);
}
return IMAGE_INIT_PASS;
}
TIMER_DEVICE_CALLBACK_MEMBER(exelv_state::exelv_hblank_interrupt)
{
m_tms3556->interrupt(machine());
@ -184,7 +212,7 @@ static DEVICE_IMAGE_UNLOAD( exelv_cart )
>0a: synthesizer data
>0b: standard generator request
>0c: I/O CPU CRC (EXELTEL only?)
>0d: send exelvision logo (EXL 100 only?), start speech ROM sound (EXELTEL only?)
>0d: send exelvision logo (EXL 100 only), start speech ROM sound (EXELTEL only?)
>0e: data for speech on ROM (EXELTEL only?)
>0f: do not decode joystick 0 keys (EXELTEL only?)
>10: do not decode joystick 1 keys (EXELTEL only?)
@ -201,6 +229,7 @@ static DEVICE_IMAGE_UNLOAD( exelv_cart )
READ8_MEMBER(exelv_state::mailbox_wx319_r)
{
logerror("[TMS7220] reading mailbox %d", m_wx319);
return m_wx319;
}
@ -276,14 +305,23 @@ WRITE8_MEMBER(exelv_state::tms7020_portb_w)
READ8_MEMBER(exelv_state::tms7041_porta_r)
{
UINT8 data = 0x00;
static UINT8 data_last=0;
logerror("tms7041_porta_r\n");
// TMS5220 OK
data |= m_tms5220c->intq_r() ? 0x08 : 0x00; // A3
data |= m_tms5220c->readyq_r() ? 0x80 : 0x00; // A7
data |= (m_tms7020_portb & 0x01 ) ? 0x04 : 0x00;
data |= m_tms5220c->intq_r() ? 0x08 : 0x00;
data |= (m_tms7020_portb & 0x02) ? 0x10 : 0x00;
data |= m_tms5220c->readyq_r() ? 0x80 : 0x00;
// TMS7220
data |= (m_tms7020_portb & 0x01 ) ? 0x04 : 0x00; // A2
data |= (m_tms7020_portb & 0x02) ? 0x10 : 0x00; // A4
// SERIAL PORT
if (data!=data_last) {
logerror("tms7041_porta_r %x\n",data);
}
data_last=data;
return data;
}
@ -321,6 +359,7 @@ WRITE8_MEMBER(exelv_state::tms7041_portb_w)
m_tms5220c->wsq_w((data & 0x01) ? 1 : 0);
m_tms5220c->rsq_w((data & 0x02) ? 1 : 0);
logerror("TMS7020 %s int1\n",((data & 0x04) ? "clear" : "assert"));
m_maincpu->set_input_line(TMS7000_IRQ1_LINE, (data & 0x04) ? CLEAR_LINE : ASSERT_LINE);
/* Check for low->high transition on B6 */
@ -371,6 +410,7 @@ WRITE8_MEMBER(exelv_state::tms7041_portc_w)
READ8_MEMBER(exelv_state::tms7041_portd_r)
{
UINT8 data = 0xff;
data=m_tms5220c->status_r(space, 0, data);
logerror("tms7041_portd_r\n");
return data;
}
@ -380,7 +420,7 @@ WRITE8_MEMBER(exelv_state::tms7041_portd_w)
{
logerror("tms7041_portd_w: data = 0x%02x\n", data);
m_tms5220c->data_w(space, 0, BITSWAP8(data,0,1,2,3,4,5,6,7));
m_tms5220c->data_w(space, 0, data);
m_tms7041_portd = data;
}
@ -410,12 +450,13 @@ WRITE8_MEMBER(exelv_state::tms7041_portd_w)
*/
static ADDRESS_MAP_START(tms7020_mem, AS_PROGRAM, 8, exelv_state)
//AM_RANGE(0x0000, 0x007f) AM_READWRITE(tms7000_internal_r, tms7000_internal_w)/* tms7020 internal RAM */
AM_RANGE(0x0080, 0x00ff) AM_NOP
//AM_RANGE(0x0100, 0x010b) AM_READWRITE(tms70x0_pf_r, tms70x0_pf_w)/* tms7020 internal I/O ports */
//AM_RANGE(0x010c, 0x01ff) AM_READWRITE(SMH_NOP, SMH_NOP) /* external I/O ports */
AM_RANGE(0x012d, 0x0012d) AM_DEVREADWRITE("tms3556", tms3556_device, reg_r/*right???*/, reg_w)
AM_RANGE(0x012e, 0x0012e) AM_DEVREADWRITE("tms3556", tms3556_device, vram_r/*right???*/, vram_w)
AM_RANGE(0x0124, 0x00124) AM_DEVREAD("tms3556", tms3556_device, vram_r)
AM_RANGE(0x0125, 0x00125) AM_DEVREAD("tms3556", tms3556_device, reg_r)
AM_RANGE(0x0128, 0x00128) AM_DEVREAD("tms3556", tms3556_device, initptr_r)
AM_RANGE(0x012d, 0x0012d) AM_DEVWRITE("tms3556", tms3556_device, reg_w)
AM_RANGE(0x012e, 0x0012e) AM_DEVWRITE("tms3556", tms3556_device, vram_w)
AM_RANGE(0x0130, 0x00130) AM_READWRITE(mailbox_wx319_r, mailbox_wx318_w)
AM_RANGE(0x0200, 0x7fff) AM_ROMBANK("bank1") /* system ROM */
AM_RANGE(0x8000, 0xbfff) AM_NOP
@ -445,12 +486,12 @@ ADDRESS_MAP_END
static ADDRESS_MAP_START(tms7040_mem, AS_PROGRAM, 8, exelv_state)
//AM_RANGE(0x0000, 0x007f) AM_READWRITE(tms7000_internal_r, tms7000_internal_w)/* tms7040 internal RAM */
AM_RANGE(0x0080, 0x00ff) AM_NOP
//AM_RANGE(0x0100, 0x010b) AM_READWRITE(tms70x0_pf_r, tms70x0_pf_w)/* tms7020 internal I/O ports */
//AM_RANGE(0x010c, 0x01ff) AM_READWRITE(SMH_NOP, SMH_NOP) /* external I/O ports */
AM_RANGE(0x012d, 0x0012d) AM_DEVREADWRITE("tms3556", tms3556_device, reg_r/*right???*/, reg_w)
AM_RANGE(0x012e, 0x0012e) AM_DEVREADWRITE("tms3556", tms3556_device, vram_r/*right???*/, vram_w)
AM_RANGE(0x0124, 0x00124) AM_DEVREAD("tms3556", tms3556_device, vram_r)
AM_RANGE(0x0125, 0x00125) AM_DEVREAD("tms3556", tms3556_device, reg_r)
AM_RANGE(0x0128, 0x00128) AM_DEVREAD("tms3556", tms3556_device, initptr_r)
AM_RANGE(0x012d, 0x0012d) AM_DEVWRITE("tms3556", tms3556_device, reg_w)
AM_RANGE(0x012e, 0x0012e) AM_DEVWRITE("tms3556", tms3556_device, vram_w)
AM_RANGE(0x0130, 0x00130) AM_READWRITE(mailbox_wx319_r, mailbox_wx318_w)
AM_RANGE(0x0200, 0x7fff) AM_ROMBANK("bank1") /* system ROM */
AM_RANGE(0x8000, 0xbfff) AM_NOP
@ -461,8 +502,7 @@ ADDRESS_MAP_END
static ADDRESS_MAP_START(tms7042_map, AS_PROGRAM, 8, exelv_state)
AM_RANGE(0xe000, 0xefff) AM_ROM AM_REGION("tms7042",0x0000)
AM_RANGE(0xf000, 0xffff) AM_ROM AM_REGION("tms7042",0x0000) /* Duplicated until a proper dump surfaces */
AM_RANGE(0xf000, 0xffff) AM_ROM AM_REGION("tms7042",0x0000)
ADDRESS_MAP_END
@ -533,7 +573,7 @@ static MACHINE_CONFIG_START( exl100, exelv_state )
MCFG_SCREEN_VISIBLE_AREA(0, TMS3556_TOTAL_WIDTH*2-1, 0, TMS3556_TOTAL_HEIGHT*2-1)
#else
MCFG_SCREEN_SIZE(TMS3556_TOTAL_WIDTH, TMS3556_TOTAL_HEIGHT*2)
MCFG_SCREEN_VISIBLE_AREA(0, TMS3556_TOTAL_WIDTH-1, 0, TMS3556_TOTAL_HEIGHT*2-1)
MCFG_SCREEN_VISIBLE_AREA(0, TMS3556_TOTAL_WIDTH-1, 0, TMS3556_TOTAL_HEIGHT-1)
#endif
MCFG_SCREEN_REFRESH_RATE(50)
MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */
@ -542,13 +582,22 @@ static MACHINE_CONFIG_START( exl100, exelv_state )
MCFG_PALETTE_ADD("palette", 8)
MCFG_PALETTE_INIT_OWNER(exelv_state, exelv)
MCFG_DEVICE_ADD("vsm", SPEECHROM, 0)
// MCFG_DEVICE_ADD("vsm", SPEECHROM, 0)
/* sound */
MCFG_SPEAKER_STANDARD_MONO("mono")
MCFG_SOUND_ADD("tms5220c", TMS5220C, 640000)
MCFG_TMS52XX_SPEECHROM("vsm")
// MCFG_TMS52XX_SPEECHROM("vsm")
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
/* cartridge */
MCFG_CARTSLOT_ADD("cart")
MCFG_CARTSLOT_EXTENSION_LIST("bin,rom")
MCFG_CARTSLOT_NOT_MANDATORY
MCFG_CARTSLOT_LOAD(exelv_state,exelvision_cartridge)
MCFG_CARTSLOT_INTERFACE("exelvision_cart")
MCFG_SOFTWARE_LIST_ADD("cart_list","exelvision_cart")
MACHINE_CONFIG_END
@ -577,7 +626,7 @@ static MACHINE_CONFIG_START( exeltel, exelv_state )
MCFG_SCREEN_VISIBLE_AREA(0, TMS3556_TOTAL_WIDTH*2-1, 0, TMS3556_TOTAL_HEIGHT*2-1)
#else
MCFG_SCREEN_SIZE(TMS3556_TOTAL_WIDTH, TMS3556_TOTAL_HEIGHT*2)
MCFG_SCREEN_VISIBLE_AREA(0, TMS3556_TOTAL_WIDTH-1, 0, TMS3556_TOTAL_HEIGHT*2-1)
MCFG_SCREEN_VISIBLE_AREA(0, TMS3556_TOTAL_WIDTH-1, 0, TMS3556_TOTAL_HEIGHT-1)
#endif
MCFG_SCREEN_REFRESH_RATE(50)
MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */
@ -601,16 +650,13 @@ MACHINE_CONFIG_END
*/
ROM_START(exl100)
ROM_REGION(0x800, "maincpu", 0)
ROM_LOAD("exl100in.bin", 0x0000, 0x0800, CRC(049109a3) SHA1(98a07297dcdacef41c793c197b6496dac1e8e744)) /* TMS7020 ROM, verification would be welcome */
ROM_LOAD("exl100in.bin", 0x0000, 0x0800, CRC(049109a3) SHA1(98a07297dcdacef41c793c197b6496dac1e8e744)) /* TMS7020 ROM, correct */
ROM_REGION(0x1000, "tms7041", 0)
ROM_LOAD("exl100_7041.bin", 0x0000, 0x1000, CRC(a0163507) SHA1(8452849df7eac8a89cf03ee98e2306047c1c4c38)) /* TMS7041 internal ROM, verification would be welcome */
ROM_LOAD("exl100_7041.bin", 0x0000, 0x1000, CRC(38f6fc7a) SHA1(b71d545664a974d8ad39bdf600c5b9884c3efab6)) /* TMS7041 internal ROM, correct */
// ROM_REGION(0x8000, "vsm", 0)
ROM_REGION(0x10000, "user1", ROMREGION_ERASEFF) /* cartridge area */
/* is this correct for exl100? */
ROM_REGION(0x8000, "vsm", 0)
ROM_LOAD("cm62312.bin", 0x0000, 0x4000, CRC(93b817de) SHA1(03863087a071b8f22d36a52d18243f1c33e17ff7)) /* system speech ROM */
ROM_END
@ -635,3 +681,4 @@ ROM_END
/* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME */
COMP(1984, exl100, 0, 0, exl100, exelv, driver_device, 0, "Exelvision", "EXL 100", GAME_NOT_WORKING)
COMP(1986, exeltel, exl100, 0, exeltel, exelv, driver_device, 0, "Exelvision", "Exeltel", GAME_NOT_WORKING)