(MESS) Apple II: Support for the Videx UltraTerm card. [R. Belmont]

This commit is contained in:
R. Belmont 2014-01-26 02:49:09 +00:00
parent 6f73e2d850
commit cc75eccd81
5 changed files with 494 additions and 0 deletions

2
.gitattributes vendored
View File

@ -416,6 +416,8 @@ src/emu/bus/a2bus/a2themill.c svneol=native#text/plain
src/emu/bus/a2bus/a2themill.h svneol=native#text/plain
src/emu/bus/a2bus/a2thunderclock.c svneol=native#text/plain
src/emu/bus/a2bus/a2thunderclock.h svneol=native#text/plain
src/emu/bus/a2bus/a2ultraterm.c svneol=native#text/plain
src/emu/bus/a2bus/a2ultraterm.h svneol=native#text/plain
src/emu/bus/a2bus/a2videoterm.c svneol=native#text/plain
src/emu/bus/a2bus/a2videoterm.h svneol=native#text/plain
src/emu/bus/a2bus/a2vulcan.c svneol=native#text/plain

View File

@ -0,0 +1,412 @@
/*********************************************************************
a2ultraterm.c
Implementation of the Videx UltraTerm 80/132/160-column card
Notes:
C0nX: C0n0 is 6845 register address,
C0n1 is 6845 register data.
C0n2 is control 1: b7 = 0 to read RAM at cc00, 1 for ROM (writes always to RAM)
b6 = 0 for Apple II video, 1 for 6845
b5 = 0 for 17.430 MHz 6845 clock, 1 for 28.7595 MHz 6845 clock
b4 = 0 for 512 byte RAM block addressing (VideoTerm emulation), 1 for 256-byte RAM page addressing
b3-b0 = page select
C0n3 is control 2: b7 = 0 for attributes software controllable, 1 for DIP switches control attributes
b5 = 0 for normal video if bit 7 set, 1 for inverse if bit 7 set
b4 = 0 for lowlight if bit 7 set, 1 for highlight if bit 7 set
b2 = 0 for high-density character set, 1 for low-density character set
b1 = same as b5
b0 = same as b4
C800-CBFF: ROM page 1
CC00-CFEF: VRAM window or ROM page 2
*********************************************************************/
#include "a2ultraterm.h"
#include "includes/apple2.h"
/***************************************************************************
PARAMETERS
***************************************************************************/
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
const device_type A2BUS_ULTRATERM = &device_creator<a2bus_ultraterm_device>;
const device_type A2BUS_ULTRATERMENH = &device_creator<a2bus_ultratermenh_device>;
#define ULTRATERM_ROM_REGION "uterm_rom"
#define ULTRATERM_GFX_REGION "uterm_gfx"
#define ULTRATERM_SCREEN_NAME "uterm_screen"
#define ULTRATERM_MC6845_NAME "mc6845_uterm"
#define CLOCK_LOW 17430000
#define CLOCK_HIGH 28759500
#define CT1_MEMSEL (0x80) // 0 for read RAM at cc00, 1 for read ROM
#define CT1_VIDSEL (0x40) // 0 for Apple video passthrough, 1 for 6845 video
#define CT1_CLKSEL (0x20) // 0 for Videoterm clock, 1 for faster clock
#define CT1_VTEMU (0x10) // Videoterm emulation mode if 0
#define CT1_PAGEMASK (0x0f)
#define CT2_USEDIPS (0x80) // 0 to use the rest of ctrl2's bits, 1 to use DIPs
#define CT2_INVBIT7H (0x20)
#define CT2_HLBIT7H (0x10)
#define CT2_HIDENSITY (0x04)
#define CT2_INVBIT7L (0x02)
#define CT2_HLBIT7L (0x01)
static MC6845_UPDATE_ROW( ultraterm_update_row );
static MC6845_INTERFACE( mc6845_mda_intf )
{
false, /* show border area */
0,0,0,0, /* visarea adjustment */
8, /* number of pixels per video memory address */
NULL, /* begin_update */
ultraterm_update_row, /* update_row */
NULL, /* end_update */
DEVCB_NULL, /* on_de_changed */
DEVCB_NULL, /* on_cur_changed */
DEVCB_NULL, /* on hsync changed */
DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER, a2bus_videx160_device, vsync_changed), /* on_vsync_changed */
NULL
};
static const rgb_t ultraterm_palette[4] =
{
MAKE_RGB(0x00,0x00,0x00),
MAKE_RGB(0x55,0x55,0x55),
MAKE_RGB(0xaa,0xaa,0xaa),
MAKE_RGB(0xff,0xff,0xff)
};
MACHINE_CONFIG_FRAGMENT( a2ultraterm )
MCFG_SCREEN_ADD( ULTRATERM_SCREEN_NAME, RASTER)
MCFG_SCREEN_RAW_PARAMS(CLOCK_LOW, 882, 0, 720, 370, 0, 350 )
MCFG_SCREEN_UPDATE_DEVICE( ULTRATERM_MC6845_NAME, mc6845_device, screen_update )
MCFG_MC6845_ADD( ULTRATERM_MC6845_NAME, MC6845, ULTRATERM_SCREEN_NAME, CLOCK_LOW/9, mc6845_mda_intf)
MACHINE_CONFIG_END
ROM_START( a2ultraterm )
ROM_REGION(0x1000, ULTRATERM_ROM_REGION, 0)
ROM_LOAD( "frm_b537.bin", 0x000000, 0x001000, CRC(1e85a93e) SHA1(b4acd1775c08ae43996ab4edf6d8e28f4736346b) )
ROM_REGION(0x1000, ULTRATERM_GFX_REGION, 0)
ROM_LOAD( "chs_7859.bin", 0x000000, 0x001000, CRC(ebe8f333) SHA1(3517fa9e7a39573f1cb159b3161d6939dec199ba) )
ROM_REGION(0x400, "pal", 0)
ROM_LOAD( "ult_2a313.jed", 0x000000, 0x000305, CRC(dcd51dea) SHA1(0ad0c5e802e48495da27f7bd26ee3ab1c92d74dd) )
ROM_END
ROM_START( a2ultratermenh )
ROM_REGION(0x1000, ULTRATERM_ROM_REGION, 0)
ROM_LOAD( "frm_b5c9.bin", 0x000000, 0x001000, CRC(b71e05e0) SHA1(092e3eda4644d4f465809864a7f023ac7d1d1542) )
ROM_REGION(0x1000, ULTRATERM_GFX_REGION, 0)
ROM_LOAD( "chs_5604.bin", 0x000000, 0x001000, CRC(3fb4e90a) SHA1(94ff75199232a9b613585c22f88470f73fb7dd09) )
ROM_REGION(0x400, "pal", 0)
ROM_LOAD( "ult_251c.jed", 0x000000, 0x000305, CRC(12fabb0d) SHA1(d4a36837cb98bb65f7ddef7455eb5a7f8e648a82) )
ROM_END
/***************************************************************************
FUNCTION PROTOTYPES
***************************************************************************/
//-------------------------------------------------
// machine_config_additions - device-specific
// machine configurations
//-------------------------------------------------
machine_config_constructor a2bus_videx160_device::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME( a2ultraterm );
}
//-------------------------------------------------
// rom_region - device-specific ROM region
//-------------------------------------------------
const rom_entry *a2bus_ultraterm_device::device_rom_region() const
{
return ROM_NAME( a2ultraterm );
}
const rom_entry *a2bus_ultratermenh_device::device_rom_region() const
{
return ROM_NAME( a2ultratermenh );
}
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
a2bus_videx160_device::a2bus_videx160_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) :
device_t(mconfig, type, name, tag, owner, clock, shortname, source),
device_a2bus_card_interface(mconfig, *this),
m_crtc(*this, ULTRATERM_MC6845_NAME)
{
}
a2bus_ultraterm_device::a2bus_ultraterm_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
a2bus_videx160_device(mconfig, A2BUS_ULTRATERM, "Videx UltraTerm (original)", tag, owner, clock, "a2ulttrm", __FILE__)
{
}
a2bus_ultratermenh_device::a2bus_ultratermenh_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
a2bus_videx160_device(mconfig, A2BUS_ULTRATERMENH, "Videx UltraTerm (enhanced //e)", tag, owner, clock, "a2ultrme", __FILE__)
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void a2bus_videx160_device::device_start()
{
// set_a2bus_device makes m_slot valid
set_a2bus_device();
astring tempstring;
m_rom = device().machine().root_device().memregion(this->subtag(tempstring, ULTRATERM_ROM_REGION))->base();
astring tempstring2;
m_chrrom = device().machine().root_device().memregion(this->subtag(tempstring2, ULTRATERM_GFX_REGION))->base();
memset(m_ram, 0, 256*16);
save_item(NAME(m_ram));
save_item(NAME(m_framecnt));
save_item(NAME(m_rambank));
save_item(NAME(m_ctrl1));
save_item(NAME(m_ctrl2));
}
void a2bus_videx160_device::device_reset()
{
m_rambank = 0;
m_framecnt = 0;
}
/*-------------------------------------------------
read_c0nx - called for reads from this card's c0nx space
-------------------------------------------------*/
UINT8 a2bus_videx160_device::read_c0nx(address_space &space, UINT8 offset)
{
// printf("Read c0n%x (PC=%x)\n", offset, space.device().safe_pc());
if (!(m_ctrl1 & CT1_VTEMU))
{
m_rambank = ((offset>>2) & 3) * 512;
}
switch (offset)
{
case 1:
return m_crtc->register_r(space, offset); // status_r?
case 2:
return m_ctrl1;
case 3:
return m_ctrl2;
}
return 0xff;
}
/*-------------------------------------------------
write_c0nx - called for writes to this card's c0nx space
-------------------------------------------------*/
void a2bus_videx160_device::write_c0nx(address_space &space, UINT8 offset, UINT8 data)
{
// printf("Write %02x to c0n%x (PC=%x)\n", data, offset, space.device().safe_pc());
switch (offset)
{
case 0:
m_crtc->address_w(space, offset, data);
break;
case 1:
m_crtc->register_w(space, offset, data);
break;
case 2:
m_ctrl1 = data;
// printf("%02x to ctrl1\n", data);
// if disabling Videoterm emulation, change RAM banking
if (data & CT1_VTEMU)
{
m_rambank = (data & CT1_PAGEMASK) * 256;
}
break;
case 3:
m_ctrl2 = data;
// printf("%02x to ctrl2\n", data);
break;
}
if (!(m_ctrl1 & CT1_VTEMU))
{
m_rambank = ((offset >> 2) & 3) * 512;
}
}
/*-------------------------------------------------
read_cnxx - called for reads from this card's cnxx space
-------------------------------------------------*/
UINT8 a2bus_videx160_device::read_cnxx(address_space &space, UINT8 offset)
{
return m_rom[offset+(m_slot * 0x100)];
}
/*-------------------------------------------------
write_cnxx - called for writes to this card's cnxx space
the firmware writes here to switch in our $C800 a lot
-------------------------------------------------*/
void a2bus_videx160_device::write_cnxx(address_space &space, UINT8 offset, UINT8 data)
{
}
/*-------------------------------------------------
read_c800 - called for reads from this card's c800 space
-------------------------------------------------*/
UINT8 a2bus_videx160_device::read_c800(address_space &space, UINT16 offset)
{
// ROM at c800-cbff
// bankswitched RAM at cc00-cdff
if (offset < 0x400)
{
// printf("Read VRAM at %x = %02x\n", offset+m_rambank, m_ram[offset + m_rambank]);
return m_rom[offset + 0x800];
}
else
{
if (m_ctrl1 & CT1_MEMSEL) // read ROM?
{
return m_rom[offset + 0x800];
}
return m_ram[(offset - 0x400) + m_rambank];
}
}
/*-------------------------------------------------
write_c800 - called for writes to this card's c800 space
-------------------------------------------------*/
void a2bus_videx160_device::write_c800(address_space &space, UINT16 offset, UINT8 data)
{
if (offset >= 0x400)
{
// printf("%02x to VRAM at %x\n", data, offset-0x400+m_rambank);
m_ram[(offset-0x400) + m_rambank] = data;
}
}
static MC6845_UPDATE_ROW( ultraterm_update_row )
{
a2bus_videx160_device *uterm = downcast<a2bus_videx160_device *>(device->owner());
UINT32 *p = &bitmap.pix32(y);
UINT16 chr_base = ra;
int i;
for ( i = 0; i < x_count; i++ )
{
UINT16 offset = ( ma + i );
UINT8 chr = uterm->m_ram[ offset ];
UINT8 data = uterm->m_chrrom[ chr_base + (chr * 16) ];
UINT8 fg = 2;
UINT8 bg = 0;
UINT8 tmp;
// apply attributes
if (!(uterm->m_ctrl2 & CT2_USEDIPS))
{
// this set and bit 7 in char, highlight
if ((uterm->m_ctrl2 & CT2_HLBIT7H) && (chr & 0x80))
{
fg = 3;
bg = 0;
}
// this set and NOT bit 7 in char, highlight
if ((uterm->m_ctrl2 & CT2_HLBIT7L) && (!(chr & 0x80)))
{
fg = 3;
bg = 0;
}
// this clear and bit 7 in char, lowlight
if (!(uterm->m_ctrl2 & CT2_HLBIT7H) && (chr & 0x80))
{
fg = 1;
bg = 0;
}
// this clear and NOT bit 7 in char, lowlight
if (!(uterm->m_ctrl2 & CT2_HLBIT7L) && (!(chr & 0x80)))
{
fg = 1;
bg = 0;
}
// invert last so invert + hilight/invert + lowlight are possible
// invert if char bit 7 is set
if ((uterm->m_ctrl2 & CT2_INVBIT7H) && (chr & 0x80))
{
tmp = fg;
fg = bg;
bg = tmp;
}
// invert if char bit 7 is clear
if ((uterm->m_ctrl2 & CT2_INVBIT7L) && (!(chr & 0x80)))
{
tmp = fg;
fg = bg;
bg = tmp;
}
}
if ( i == cursor_x )
{
if ( uterm->m_framecnt & 0x08 )
{
data = 0xFF;
}
}
*p = ultraterm_palette[( data & 0x80 ) ? fg : bg]; p++;
*p = ultraterm_palette[( data & 0x40 ) ? fg : bg]; p++;
*p = ultraterm_palette[( data & 0x20 ) ? fg : bg]; p++;
*p = ultraterm_palette[( data & 0x10 ) ? fg : bg]; p++;
*p = ultraterm_palette[( data & 0x08 ) ? fg : bg]; p++;
*p = ultraterm_palette[( data & 0x04 ) ? fg : bg]; p++;
*p = ultraterm_palette[( data & 0x02 ) ? fg : bg]; p++;
*p = ultraterm_palette[( data & 0x01 ) ? fg : bg]; p++;
}
}
WRITE_LINE_MEMBER( a2bus_videx160_device::vsync_changed )
{
if ( state )
{
m_framecnt++;
}
}

View File

@ -0,0 +1,76 @@
/*********************************************************************
a2ultraterm.h
Implementation of the Videx UltraTerm 80/132/160-column video card
*********************************************************************/
#ifndef __A2BUS_ULTRATERM__
#define __A2BUS_ULTRATERM__
#include "emu.h"
#include "a2bus.h"
#include "video/mc6845.h"
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
class a2bus_videx160_device:
public device_t,
public device_a2bus_card_interface
{
public:
// construction/destruction
a2bus_videx160_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
// optional information overrides
virtual machine_config_constructor device_mconfig_additions() const;
DECLARE_WRITE_LINE_MEMBER(vsync_changed);
UINT8 *m_rom, *m_chrrom;
UINT8 m_ram[256*16];
int m_framecnt;
UINT8 m_ctrl1, m_ctrl2;
protected:
virtual void device_start();
virtual void device_reset();
// overrides of standard a2bus slot functions
virtual UINT8 read_c0nx(address_space &space, UINT8 offset);
virtual void write_c0nx(address_space &space, UINT8 offset, UINT8 data);
virtual UINT8 read_cnxx(address_space &space, UINT8 offset);
virtual void write_cnxx(address_space &space, UINT8 offset, UINT8 data);
virtual UINT8 read_c800(address_space &space, UINT16 offset);
virtual void write_c800(address_space &space, UINT16 offset, UINT8 data);
required_device<mc6845_device> m_crtc;
private:
int m_rambank;
};
class a2bus_ultraterm_device : public a2bus_videx160_device
{
public:
a2bus_ultraterm_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
virtual const rom_entry *device_rom_region() const;
};
class a2bus_ultratermenh_device : public a2bus_videx160_device
{
public:
a2bus_ultratermenh_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
virtual const rom_entry *device_rom_region() const;
};
// device type definition
extern const device_type A2BUS_ULTRATERM;
extern const device_type A2BUS_ULTRATERMENH;
#endif /* __A2BUS_ULTRATERM__ */

View File

@ -534,6 +534,7 @@ BUSOBJS += $(BUSOBJ)/a2bus/a2vulcan.o
BUSOBJS += $(BUSOBJ)/a2bus/a2zipdrive.o
BUSOBJS += $(BUSOBJ)/a2bus/a2applicard.o
BUSOBJS += $(BUSOBJ)/a2bus/a2hsscsi.o
BUSOBJS += $(BUSOBJ)/a2bus/a2ultraterm.o
BUSOBJS += $(BUSOBJ)/a2bus/a2estd80col.o
BUSOBJS += $(BUSOBJ)/a2bus/a2eext80col.o
BUSOBJS += $(BUSOBJ)/a2bus/a2eramworks3.o

View File

@ -214,6 +214,7 @@ Apple 3.5 and Apple 5.25 drives - up to three devices
#include "bus/a2bus/a2midi.h"
#include "bus/a2bus/a2zipdrive.h"
#include "bus/a2bus/a2applicard.h"
#include "bus/a2bus/a2ultraterm.h"
#include "bus/a2bus/a2estd80col.h"
#include "bus/a2bus/a2eext80col.h"
#include "bus/a2bus/a2eramworks3.h"
@ -641,6 +642,8 @@ static SLOT_INTERFACE_START(apple2_cards)
SLOT_INTERFACE("scsi", A2BUS_SCSI) /* Apple II SCSI Card */
SLOT_INTERFACE("applicard", A2BUS_APPLICARD) /* PCPI Applicard */
SLOT_INTERFACE("aesms", A2BUS_AESMS) /* Applied Engineering Super Music Synthesizer */
SLOT_INTERFACE("ultraterm", A2BUS_ULTRATERM) /* Videx UltraTerm (original) */
SLOT_INTERFACE("ultratermenh", A2BUS_ULTRATERMENH) /* Videx UltraTerm (enhanced //e) */
SLOT_INTERFACE_END
static SLOT_INTERFACE_START(apple2eaux_cards)