mirror of
https://github.com/holub/mame
synced 2025-07-03 17:08:39 +03:00
[MESS] DEC Rainbow updates: [Karl-Ludwig Deisenhofer]
- Hard disk R/W support and real-time clock support emulating ClikClok card. -wd2010: provides IRQ / (B)DRQ signals. Honors DRIVE_READY and WRITE FAULT (DRDY / WF) now. Set WF to GND and DRDY to VCC in your driver if signals are not serviced. -ds1315 : Handle chip enable / chip reset / phantom writes to RTC.
This commit is contained in:
parent
b702e6bd3e
commit
0026618a68
@ -1,12 +1,23 @@
|
|||||||
/*********************************************************************
|
/*****************************************************************************************
|
||||||
|
|
||||||
ds1315.c
|
ds1315.c
|
||||||
|
|
||||||
Dallas Semiconductor's Phantom Time Chip DS1315.
|
Dallas Semiconductor's Phantom Time Chip DS1315.
|
||||||
|
NOTE: writes are decoded, but the host's time will always be returned when asked.
|
||||||
|
|
||||||
by tim lindner, November 2001.
|
April 2015: chip enable / chip reset / phantom writes by Karl-Ludwig Deisenhofer
|
||||||
|
|
||||||
*********************************************************************/
|
November 2001: implementation by Tim Lindner
|
||||||
|
|
||||||
|
HOW DOES IT WORK?
|
||||||
|
|
||||||
|
READS: pattern recognition (64 bits in correct order). When RTC finally enables
|
||||||
|
64 bits of data can be read. Chance of accidential pattern recognition is minimal.
|
||||||
|
|
||||||
|
WRITES: two different locations (bits 0 and 1) are used to transfer data to the
|
||||||
|
DS1315. 64 bit with time/date info are transmitted directly after recognition
|
||||||
|
of the magic 64 bit pattern (see read above).
|
||||||
|
**************************************************************************************/
|
||||||
|
|
||||||
#include "ds1315.h"
|
#include "ds1315.h"
|
||||||
#include "coreutil.h"
|
#include "coreutil.h"
|
||||||
@ -47,12 +58,11 @@ void ds1315_device::device_start()
|
|||||||
|
|
||||||
void ds1315_device::device_reset()
|
void ds1315_device::device_reset()
|
||||||
{
|
{
|
||||||
memset(m_raw_data, 0, sizeof(m_raw_data));
|
chip_reset();
|
||||||
m_count = 0;
|
|
||||||
m_mode = DS_SEEK_MATCHING;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
LOCAL VARIABLES
|
LOCAL VARIABLES
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
@ -75,7 +85,7 @@ static const UINT8 ds1315_pattern[] =
|
|||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
/*-------------------------------------------------
|
/*-------------------------------------------------
|
||||||
read_0
|
read_0 (actual data)
|
||||||
-------------------------------------------------*/
|
-------------------------------------------------*/
|
||||||
|
|
||||||
READ8_MEMBER( ds1315_device::read_0 )
|
READ8_MEMBER( ds1315_device::read_0 )
|
||||||
@ -100,7 +110,7 @@ READ8_MEMBER( ds1315_device::read_0 )
|
|||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------
|
/*-------------------------------------------------
|
||||||
read_1
|
read_1 (actual data)
|
||||||
-------------------------------------------------*/
|
-------------------------------------------------*/
|
||||||
|
|
||||||
READ8_MEMBER( ds1315_device::read_1 )
|
READ8_MEMBER( ds1315_device::read_1 )
|
||||||
@ -143,36 +153,13 @@ READ8_MEMBER( ds1315_device::read_data )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------
|
|
||||||
write_data
|
|
||||||
-------------------------------------------------*/
|
|
||||||
|
|
||||||
WRITE8_MEMBER( ds1315_device::write_data )
|
|
||||||
{
|
|
||||||
if (m_mode == DS_CALENDAR_IO)
|
|
||||||
{
|
|
||||||
m_raw_data[m_count++] = data & 0x01;
|
|
||||||
|
|
||||||
if (m_count == 64)
|
|
||||||
{
|
|
||||||
m_mode = DS_SEEK_MATCHING;
|
|
||||||
m_count = 0;
|
|
||||||
input_raw_data();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------
|
/*-------------------------------------------------
|
||||||
fill_raw_data
|
fill_raw_data
|
||||||
-------------------------------------------------*/
|
-------------------------------------------------*/
|
||||||
|
|
||||||
void ds1315_device::fill_raw_data()
|
void ds1315_device::fill_raw_data()
|
||||||
{
|
{
|
||||||
/* This routine will (hopefully) call a standard 'C' library routine to get the current
|
/* This routine calls a standard 'C' library routine to get the current
|
||||||
date and time and then fill in the raw data struct.
|
date and time and then fill in the raw data struct.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -181,7 +168,7 @@ void ds1315_device::fill_raw_data()
|
|||||||
|
|
||||||
/* get the current date/time from the core */
|
/* get the current date/time from the core */
|
||||||
machine().current_datetime(systime);
|
machine().current_datetime(systime);
|
||||||
|
|
||||||
raw[0] = 0; /* tenths and hundreths of seconds are always zero */
|
raw[0] = 0; /* tenths and hundreths of seconds are always zero */
|
||||||
raw[1] = dec_2_bcd(systime.local_time.second);
|
raw[1] = dec_2_bcd(systime.local_time.second);
|
||||||
raw[2] = dec_2_bcd(systime.local_time.minute);
|
raw[2] = dec_2_bcd(systime.local_time.minute);
|
||||||
@ -203,16 +190,86 @@ void ds1315_device::fill_raw_data()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------
|
/*-------------------------------------------------
|
||||||
ds1315_input_raw_data
|
write_data
|
||||||
|
-------------------------------------------------*/
|
||||||
|
|
||||||
|
READ8_MEMBER(ds1315_device::write_data)
|
||||||
|
{
|
||||||
|
static int write_count;
|
||||||
|
if (write_count >= 64)
|
||||||
|
write_count = 0;
|
||||||
|
|
||||||
|
if (m_mode == DS_CALENDAR_IO)
|
||||||
|
{
|
||||||
|
m_raw_data[write_count++] = offset & 0x01;
|
||||||
|
|
||||||
|
if (write_count == 64)
|
||||||
|
{
|
||||||
|
write_count = 0;
|
||||||
|
|
||||||
|
m_mode = DS_SEEK_MATCHING;
|
||||||
|
m_count = 0;
|
||||||
|
input_raw_data();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0; // ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-------------------------------------------------
|
||||||
|
ds1315_input_raw_data
|
||||||
|
|
||||||
|
Routine is called when new date and time has
|
||||||
|
been written to the clock chip. Currently we
|
||||||
|
ignore setting the date and time in the clock
|
||||||
|
chip.
|
||||||
-------------------------------------------------*/
|
-------------------------------------------------*/
|
||||||
|
|
||||||
void ds1315_device::input_raw_data()
|
void ds1315_device::input_raw_data()
|
||||||
{
|
{
|
||||||
/* This routine is called when new date and time has been written to the
|
int raw[8], i, j=0;
|
||||||
clock chip. Currently we ignore setting the date and time in the clock
|
raw[0] = raw[1] = raw[2] = raw[3] = raw[4] = raw[5] = raw[6] = raw[7] = 0;
|
||||||
chip.
|
UINT8 flag = 1;
|
||||||
|
|
||||||
We always return the host's time when asked.
|
for (i = 0; i < 64; i++)
|
||||||
*/
|
{
|
||||||
|
j = i / 8;
|
||||||
|
if ((i % 8) == 0)
|
||||||
|
flag = 1;
|
||||||
|
|
||||||
|
if (m_raw_data[i] & 1)
|
||||||
|
raw[j] |= flag;
|
||||||
|
flag <<= 1;
|
||||||
|
}
|
||||||
|
raw[0] = bcd_2_dec(raw[0]); // hundreds of seconds
|
||||||
|
raw[1] = bcd_2_dec(raw[1]); // seconds (often set to zero)
|
||||||
|
raw[2] = bcd_2_dec(raw[2]); // minute
|
||||||
|
raw[3] = bcd_2_dec(raw[3]); // hour
|
||||||
|
|
||||||
|
raw[4] = bcd_2_dec(raw[4]); // weekday (10 for Friday ?!)
|
||||||
|
raw[5] = bcd_2_dec(raw[5]); // mday
|
||||||
|
raw[6] = bcd_2_dec(raw[6]); // month
|
||||||
|
raw[7] = bcd_2_dec(raw[7]); // year (two digits)
|
||||||
|
|
||||||
|
printf("\nDS1315 RTC INPUT (WILL BE IGNORED) mm/dd/yy hh:mm:ss - %02d/%02d/%02d %02d/%02d/%02d",
|
||||||
|
raw[6], raw[5], raw[7], raw[3], raw[2], raw[1]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-------------------------------------------------
|
||||||
|
query and reset chip status
|
||||||
|
-------------------------------------------------*/
|
||||||
|
bool ds1315_device::chip_enable()
|
||||||
|
{
|
||||||
|
return (m_mode == DS_CALENDAR_IO);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set a defined state (important for pattern detection)
|
||||||
|
void ds1315_device::chip_reset()
|
||||||
|
{
|
||||||
|
memset(m_raw_data, 0, sizeof(m_raw_data));
|
||||||
|
m_count = 0;
|
||||||
|
m_mode = DS_SEEK_MATCHING;
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,10 @@ public:
|
|||||||
DECLARE_READ8_MEMBER(read_0);
|
DECLARE_READ8_MEMBER(read_0);
|
||||||
DECLARE_READ8_MEMBER(read_1);
|
DECLARE_READ8_MEMBER(read_1);
|
||||||
DECLARE_READ8_MEMBER(read_data);
|
DECLARE_READ8_MEMBER(read_data);
|
||||||
DECLARE_WRITE8_MEMBER(write_data);
|
DECLARE_READ8_MEMBER(write_data);
|
||||||
|
|
||||||
|
bool chip_enable();
|
||||||
|
void chip_reset();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// device-level overrides
|
// device-level overrides
|
||||||
@ -45,12 +48,12 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
// internal state
|
// internal state
|
||||||
|
ds1315_mode_t m_mode;
|
||||||
|
|
||||||
void fill_raw_data();
|
void fill_raw_data();
|
||||||
void input_raw_data();
|
void input_raw_data();
|
||||||
|
|
||||||
int m_count;
|
int m_count;
|
||||||
ds1315_mode_t m_mode;
|
|
||||||
UINT8 m_raw_data[8*8];
|
UINT8 m_raw_data[8*8];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2,24 +2,63 @@
|
|||||||
// copyright-holders:Curt Coder
|
// copyright-holders:Curt Coder
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
|
|
||||||
Western Digital WD2010 Winchester Disk Controller
|
Western Digital WD2010 Winchester Disk Controller
|
||||||
|
|
||||||
Copyright MESS Team.
|
Copyright MESS Team.
|
||||||
Visit http://mamedev.org for licensing and usage restrictions.
|
Visit http://mamedev.org for licensing and usage restrictions.
|
||||||
|
|
||||||
|
Portions (2015) : Karl-Ludwig Deisenhofer
|
||||||
|
**********************************************************************
|
||||||
|
|
||||||
|
Implements WD2010 / WD1010 controller basics.
|
||||||
|
|
||||||
|
Provides IRQ / (B)DRQ signals needed for early MFM cards.
|
||||||
|
Honors DRIVE_READY and WRITE FAULT (DRDY / WF).
|
||||||
|
|
||||||
|
Single sector read / write (format) confirmed to work with
|
||||||
|
Rainbow-100 controller (WD1010, largely compatible to WD2010, see **)
|
||||||
|
|
||||||
|
LIST OF UNIMPLEMENTED FEATURES :
|
||||||
|
- MULTI SECTOR TRANSFERS (M = 1); MULTIPLE DRIVES
|
||||||
|
- AUTO_SCAN_ID / SEEK + INDEX TIMERS / ID NOT FOUND
|
||||||
|
- IMPLIED SEEKS / IMPLIED WRITES / RETRIES
|
||||||
|
- EDGE or LEVEL TRIGGERED SEEK_COMPLETE (SC)
|
||||||
|
- SET_PARAMETER / COMPUTE_CORRECTION (DWC flag!)
|
||||||
|
|
||||||
|
Pseudo code (from datasheet) left in to illustrate
|
||||||
|
the intended instruction flow. Some loops were omitted!
|
||||||
|
|
||||||
|
USAGE: tie WF (write fault) to ground if not needed:
|
||||||
|
MCFG_WD2010_IN_WF_CB(GND)
|
||||||
|
|
||||||
|
Other signals should be set to VCC if not serviced:
|
||||||
|
MCFG_WD2010_IN_DRDY_CB(VCC) // DRIVE READY = VCC
|
||||||
|
MCFG_WD2010_IN_SC_CB(VCC) // SEEK COMPLETE = VCC
|
||||||
|
**********************************************************************/
|
||||||
|
|
||||||
|
// WD 2010 CONFIGURATION (2048 cylinder limit)
|
||||||
|
#define STEP_LIMIT 2048
|
||||||
|
#define CYLINDER_HIGH_MASK 0x07
|
||||||
|
|
||||||
|
// DEC RD51 chip; different STEP / CYLINDER LIMIT (**):
|
||||||
|
|
||||||
|
// WD 1010 CONFIGURATION (1024 cylinder limit)
|
||||||
|
// #define STEP_LIMIT 1024
|
||||||
|
// #define CYLINDER_HIGH_MASK 0x03
|
||||||
|
|
||||||
|
// --------------------------------------------------------
|
||||||
|
#define MAX_MFM_SECTORS 17 // STANDARD MFM SECTORS/TRACK
|
||||||
|
// --------------------------------------------------------
|
||||||
|
|
||||||
**********************************************************************/
|
|
||||||
|
|
||||||
#include "machine/wd2010.h"
|
#include "machine/wd2010.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//**************************************************************************
|
//**************************************************************************
|
||||||
// MACROS / CONSTANTS
|
// MACROS / CONSTANTS
|
||||||
//**************************************************************************
|
//**************************************************************************
|
||||||
|
|
||||||
#define LOG 1
|
#define LOG 1
|
||||||
|
|
||||||
|
|
||||||
// task file
|
// task file
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
@ -44,7 +83,7 @@ enum
|
|||||||
(m_task_file[TASK_FILE_SECTOR_NUMBER])
|
(m_task_file[TASK_FILE_SECTOR_NUMBER])
|
||||||
|
|
||||||
#define CYLINDER \
|
#define CYLINDER \
|
||||||
(((m_task_file[TASK_FILE_CYLINDER_HIGH] & 0x07) << 8) | m_task_file[TASK_FILE_CYLINDER_LOW])
|
(((m_task_file[TASK_FILE_CYLINDER_HIGH] & CYLINDER_HIGH_MASK) << 8) | m_task_file[TASK_FILE_CYLINDER_LOW])
|
||||||
|
|
||||||
#define HEAD \
|
#define HEAD \
|
||||||
(m_task_file[TASK_FILE_SDH_REGISTER] & 0x07)
|
(m_task_file[TASK_FILE_SDH_REGISTER] & 0x07)
|
||||||
@ -57,7 +96,6 @@ static const int SECTOR_SIZES[4] = { 256, 512, 1024, 128 };
|
|||||||
#define SECTOR_SIZE \
|
#define SECTOR_SIZE \
|
||||||
SECTOR_SIZES[(m_task_file[TASK_FILE_SDH_REGISTER] >> 5) & 0x03]
|
SECTOR_SIZES[(m_task_file[TASK_FILE_SDH_REGISTER] >> 5) & 0x03]
|
||||||
|
|
||||||
|
|
||||||
// status register
|
// status register
|
||||||
#define STATUS_BSY 0x80
|
#define STATUS_BSY 0x80
|
||||||
#define STATUS_RDY 0x40
|
#define STATUS_RDY 0x40
|
||||||
@ -108,22 +146,24 @@ const device_type WD2010 = &device_creator<wd2010_device>;
|
|||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
wd2010_device::wd2010_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
wd2010_device::wd2010_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||||
: device_t(mconfig, WD2010, "Western Digital WD2010", tag, owner, clock, "wd2010", __FILE__),
|
: device_t(mconfig, WD2010, "Western Digital WD2010", tag, owner, clock, "wd2010", __FILE__),
|
||||||
m_out_intrq_cb(*this),
|
m_out_intrq_cb(*this),
|
||||||
m_out_bdrq_cb(*this),
|
m_out_bdrq_cb(*this),
|
||||||
m_out_bcr_cb(*this),
|
m_out_bcr_cb(*this),
|
||||||
m_in_bcs_cb(*this),
|
m_in_bcs_cb(*this),
|
||||||
m_out_bcs_cb(*this),
|
m_in_brdy_cb(*this),
|
||||||
m_out_dirin_cb(*this),
|
m_out_bcs_cb(*this),
|
||||||
m_out_step_cb(*this),
|
m_out_dirin_cb(*this),
|
||||||
m_out_rwc_cb(*this),
|
m_out_step_cb(*this),
|
||||||
m_in_drdy_cb(*this),
|
m_out_rwc_cb(*this),
|
||||||
m_in_index_cb(*this),
|
m_out_wg_cb(*this),
|
||||||
m_in_wf_cb(*this),
|
m_in_drdy_cb(*this),
|
||||||
m_in_tk000_cb(*this),
|
m_in_index_cb(*this),
|
||||||
m_in_sc_cb(*this),
|
m_in_wf_cb(*this),
|
||||||
m_status(0),
|
m_in_tk000_cb(*this),
|
||||||
m_error(0)
|
m_in_sc_cb(*this),
|
||||||
|
m_status(0),
|
||||||
|
m_error(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,17 +179,33 @@ void wd2010_device::device_start()
|
|||||||
m_out_bdrq_cb.resolve_safe();
|
m_out_bdrq_cb.resolve_safe();
|
||||||
m_out_bcr_cb.resolve_safe();
|
m_out_bcr_cb.resolve_safe();
|
||||||
m_in_bcs_cb.resolve_safe(0);
|
m_in_bcs_cb.resolve_safe(0);
|
||||||
|
|
||||||
|
m_in_brdy_cb.resolve_safe(0);
|
||||||
|
|
||||||
m_out_bcs_cb.resolve_safe();
|
m_out_bcs_cb.resolve_safe();
|
||||||
m_out_dirin_cb.resolve_safe();
|
m_out_dirin_cb.resolve_safe();
|
||||||
m_out_step_cb.resolve_safe();
|
m_out_step_cb.resolve_safe();
|
||||||
m_out_rwc_cb.resolve_safe();
|
m_out_rwc_cb.resolve_safe();
|
||||||
|
m_out_wg_cb.resolve_safe();
|
||||||
m_in_drdy_cb.resolve_safe(0);
|
m_in_drdy_cb.resolve_safe(0);
|
||||||
m_in_index_cb.resolve_safe(0);
|
m_in_index_cb.resolve_safe(0);
|
||||||
m_in_wf_cb.resolve_safe(0);
|
m_in_wf_cb.resolve_safe(0);
|
||||||
m_in_tk000_cb.resolve_safe(0);
|
m_in_tk000_cb.resolve_safe(0);
|
||||||
m_in_sc_cb.resolve_safe(0);
|
m_in_sc_cb.resolve_safe(0);
|
||||||
|
|
||||||
|
/* allocate a timer for commands */
|
||||||
|
cmd_timer = timer_alloc(0);
|
||||||
|
complete_write_when_buffer_ready_high = timer_alloc(1);
|
||||||
|
deassert_write_when_buffer_ready_low = timer_alloc(2);
|
||||||
|
deassert_read_when_buffer_ready_high = timer_alloc(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// timers
|
||||||
|
#define COMMAND_TIMER 0
|
||||||
|
#define COMPLETE_WRITE_SECTOR 1
|
||||||
|
#define DE_ASSERT_WRITE 2
|
||||||
|
#define DE_ASSERT_READ 3
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// device_reset - device-specific reset
|
// device_reset - device-specific reset
|
||||||
@ -157,6 +213,11 @@ void wd2010_device::device_start()
|
|||||||
|
|
||||||
void wd2010_device::device_reset()
|
void wd2010_device::device_reset()
|
||||||
{
|
{
|
||||||
|
m_out_intrq_cb(CLEAR_LINE);
|
||||||
|
|
||||||
|
buffer_ready(false);
|
||||||
|
|
||||||
|
m_present_cylinder = 0; // start somewhere
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -164,23 +225,36 @@ void wd2010_device::device_reset()
|
|||||||
// read -
|
// read -
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
READ8_MEMBER( wd2010_device::read )
|
READ8_MEMBER(wd2010_device::read)
|
||||||
{
|
{
|
||||||
UINT8 data = 0;
|
UINT8 data = 0;
|
||||||
|
|
||||||
switch (offset)
|
switch (offset)
|
||||||
{
|
{
|
||||||
case TASK_FILE_ERROR:
|
case TASK_FILE_ERROR:
|
||||||
data = m_error;
|
if (m_status & STATUS_CIP) // "if other registers are read while CIP, the status register contents are returned."
|
||||||
|
data = (m_in_drdy_cb() ? 0x40 : 0) | (m_in_wf_cb() ? 0x20 : 0) | (m_in_sc_cb() ? 0x10 : 0) | m_status;// see STATUS register
|
||||||
|
else
|
||||||
|
data = m_error;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TASK_FILE_STATUS:
|
case TASK_FILE_STATUS:
|
||||||
m_out_intrq_cb(CLEAR_LINE);
|
m_out_intrq_cb(CLEAR_LINE); // "reading the status register clears INTRQ" (-> datasheet)
|
||||||
data = m_status | STATUS_RDY | STATUS_SC;
|
data = (m_in_drdy_cb() ? 0x40 : 0) | (m_in_wf_cb() ? 0x20 : 0) | (m_in_sc_cb() ? 0x10 : 0) | m_status;// see ERROR register
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
data = m_task_file[offset];
|
data = m_task_file[offset];
|
||||||
|
|
||||||
|
if (offset == TASK_FILE_SDH_REGISTER)
|
||||||
|
{
|
||||||
|
|
||||||
|
logerror("(READ) %s WD2010 '%s' SDH: %u\n", machine().describe_context(), tag(), data);
|
||||||
|
logerror("(READ) %s WD2010 '%s' Head: %u\n", machine().describe_context(), tag(), HEAD);
|
||||||
|
logerror("(READ) %s WD2010 '%s' Drive: %u\n", machine().describe_context(), tag(), DRIVE);
|
||||||
|
logerror("(READ) %s WD2010 '%s' Sector Size: %u\n", machine().describe_context(), tag(), SECTOR_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,7 +266,7 @@ READ8_MEMBER( wd2010_device::read )
|
|||||||
// write -
|
// write -
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
WRITE8_MEMBER( wd2010_device::write )
|
WRITE8_MEMBER(wd2010_device::write)
|
||||||
{
|
{
|
||||||
m_task_file[offset] = data;
|
m_task_file[offset] = data;
|
||||||
|
|
||||||
@ -211,23 +285,28 @@ WRITE8_MEMBER( wd2010_device::write )
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case TASK_FILE_CYLINDER_LOW:
|
case TASK_FILE_CYLINDER_LOW:
|
||||||
if (LOG) logerror("%s WD2010 '%s' Cylinder Low: %u\n", machine().describe_context(), tag(), CYLINDER);
|
if (LOG) logerror("%s WD2010 '%s' Cylinder (lower bits set): %u\n", machine().describe_context(), tag(), CYLINDER);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TASK_FILE_CYLINDER_HIGH:
|
case TASK_FILE_CYLINDER_HIGH:
|
||||||
if (LOG) logerror("%s WD2010 '%s' Cylinder Low: %u\n", machine().describe_context(), tag(), CYLINDER);
|
if (LOG) logerror("%s WD2010 '%s' Cylinder (MSB bits set): %u\n", machine().describe_context(), tag(), CYLINDER);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TASK_FILE_SDH_REGISTER:
|
case TASK_FILE_SDH_REGISTER:
|
||||||
if (LOG)
|
if (LOG)
|
||||||
{
|
{
|
||||||
logerror("%s WD2010 '%s' Head: %u\n", machine().describe_context(), tag(), HEAD);
|
logerror("(WRITE) %s WD2010 '%s' SDH: %u\n", machine().describe_context(), tag(), data);
|
||||||
logerror("%s WD2010 '%s' Drive: %u\n", machine().describe_context(), tag(), DRIVE);
|
logerror("(WRITE) %s WD2010 '%s' Head: %u\n", machine().describe_context(), tag(), HEAD);
|
||||||
logerror("%s WD2010 '%s' Sector Size: %u\n", machine().describe_context(), tag(), SECTOR_SIZE);
|
logerror("(WRITE) %s WD2010 '%s' Drive: %u\n", machine().describe_context(), tag(), DRIVE);
|
||||||
|
logerror("(WRITE) %s WD2010 '%s' Sector Size: %u\n", machine().describe_context(), tag(), SECTOR_SIZE);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TASK_FILE_COMMAND:
|
case TASK_FILE_COMMAND:
|
||||||
|
m_out_intrq_cb(CLEAR_LINE); // "either reading the status register or writing a new command clears INTRQ"
|
||||||
|
m_status &= ~(STATUS_ERR | STATUS_BSY | STATUS_CIP); // "Reset ERR bit in STATUS upon new cmd" (see datasheet)
|
||||||
|
m_error = 0;
|
||||||
|
|
||||||
if (data == COMMAND_COMPUTE_CORRECTION)
|
if (data == COMMAND_COMPUTE_CORRECTION)
|
||||||
{
|
{
|
||||||
if (LOG) logerror("%s WD2010 '%s' COMPUTE CORRECTION\n", machine().describe_context(), tag());
|
if (LOG) logerror("%s WD2010 '%s' COMPUTE CORRECTION\n", machine().describe_context(), tag());
|
||||||
@ -253,12 +332,12 @@ WRITE8_MEMBER( wd2010_device::write )
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case COMMAND_READ_SECTOR:
|
case COMMAND_READ_SECTOR:
|
||||||
if (LOG) logerror("%s WD2010 '%s' READ SECTOR\n", machine().describe_context(), tag());
|
if (LOG) logerror("%s WD2010 '%s' READ SECTOR (I = %u) (M = %u)\n", machine().describe_context(), tag(), ((data & 8)>0), ((data & 4)>0));
|
||||||
read_sector(data);
|
read_sector(data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case COMMAND_WRITE_SECTOR:
|
case COMMAND_WRITE_SECTOR:
|
||||||
if (LOG) logerror("%s WD2010 '%s' WRITE SECTOR\n", machine().describe_context(), tag());
|
if (LOG) logerror("%s WD2010 '%s' WRITE SECTOR (M = %u)\n", machine().describe_context(), tag(), ((data & 4) > 0));
|
||||||
write_sector(data);
|
write_sector(data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -272,136 +351,644 @@ WRITE8_MEMBER( wd2010_device::write )
|
|||||||
format(data);
|
format(data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
} // switch
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// compute_correction -
|
// compute_correction -
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
void wd2010_device::compute_correction(UINT8 data)
|
void wd2010_device::compute_correction(UINT8 data)
|
||||||
{
|
{
|
||||||
|
UINT8 newstatus = STATUS_RDY | STATUS_SC;
|
||||||
|
complete_cmd(newstatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// set_parameter -
|
// set_parameter -
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
void wd2010_device::set_parameter(UINT8 data)
|
void wd2010_device::set_parameter(UINT8 data)
|
||||||
{
|
{
|
||||||
|
UINT8 newstatus = STATUS_RDY | STATUS_SC;
|
||||||
|
complete_cmd(newstatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// restore -
|
// restore -
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
void wd2010_device::restore(UINT8 data)
|
void wd2010_device::restore(UINT8 data)
|
||||||
{
|
{
|
||||||
// reset INTRQ, errors, set BUSY, CIP
|
UINT8 newstatus = STATUS_RDY | STATUS_SC;
|
||||||
m_out_intrq_cb(CLEAR_LINE);
|
|
||||||
|
m_out_intrq_cb(CLEAR_LINE); // reset INTRQ, errors, set BUSY, CIP
|
||||||
m_error = 0;
|
m_error = 0;
|
||||||
m_status = STATUS_BSY | STATUS_CIP;
|
m_status = STATUS_BSY | STATUS_CIP;
|
||||||
|
|
||||||
// reset RWC, set direction=OUT, store step rate
|
m_out_rwc_cb(0); // reset RWC, set direction = OUT
|
||||||
m_out_rwc_cb(0);
|
|
||||||
m_out_dirin_cb(0);
|
// datasheet: DIRIN HIGH = in ; LOW = out
|
||||||
|
m_out_dirin_cb(0); // 0 = heads move away from the spindle, towards track O.
|
||||||
|
|
||||||
|
// TODO: store step rate
|
||||||
|
|
||||||
|
m_present_cylinder = 0; // (sse WD2010-05 datasheet)
|
||||||
|
m_task_file[TASK_FILE_CYLINDER_HIGH] = 0;
|
||||||
|
m_task_file[TASK_FILE_CYLINDER_LOW] = 0;
|
||||||
|
|
||||||
int step_pulses = 0;
|
int step_pulses = 0;
|
||||||
|
while (step_pulses < STEP_LIMIT)
|
||||||
while (step_pulses < 2048)
|
|
||||||
{
|
{
|
||||||
while (!m_in_sc_cb())
|
while (!m_in_sc_cb())
|
||||||
{
|
{
|
||||||
// drive not ready or write fault?
|
if (!m_in_drdy_cb() || m_in_wf_cb()) // drive not ready or write fault?
|
||||||
if (!m_in_drdy_cb() || m_in_wf_cb())
|
|
||||||
{
|
{
|
||||||
// pulse BCR, set AC, INTRQ, reset BSY, CIP
|
m_out_bcr_cb(0); // pulse BCR
|
||||||
m_out_bcr_cb(0);
|
|
||||||
m_out_bcr_cb(1);
|
m_out_bcr_cb(1);
|
||||||
m_error = ERROR_AC;
|
|
||||||
m_status = (m_in_drdy_cb() << 6) | (m_in_wf_cb() << 5) | STATUS_ERR;
|
m_error = ERROR_AC; // ERROR : ABORTED COMMAND
|
||||||
m_out_intrq_cb(ASSERT_LINE);
|
complete_cmd(newstatus | STATUS_ERR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_in_tk000_cb())
|
//if (m_in_tk000_cb())
|
||||||
|
if (step_pulses == STEP_LIMIT - 2) // Simulate TRACK 00 signal (normally from DRIVE)
|
||||||
{
|
{
|
||||||
// pulse BCR, set INTRQ, reset BSY, CIP
|
m_out_bcr_cb(0); // pulse BCR
|
||||||
m_out_bcr_cb(0);
|
|
||||||
m_out_bcr_cb(1);
|
m_out_bcr_cb(1);
|
||||||
m_status &= ~(STATUS_BSY | STATUS_CIP);
|
newstatus &= ~(STATUS_BSY | STATUS_CIP); // prepare new status; (INTRQ later) reset BSY, CIP
|
||||||
m_out_intrq_cb(ASSERT_LINE);
|
complete_cmd(newstatus);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (step_pulses == 2047)
|
if (step_pulses == STEP_LIMIT - 1) // NOTE: STEP_LIMIT - differs - between WD2010 and WD1010
|
||||||
{
|
{
|
||||||
// set TK000 error
|
m_error = ERROR_TK; // ERROR: track 0 not reached within limit
|
||||||
m_error = ERROR_TK;
|
newstatus = newstatus | STATUS_ERR;
|
||||||
m_status |= STATUS_ERR;
|
|
||||||
|
|
||||||
// pulse BCR, set INTRQ, reset BSY, CIP
|
m_out_bcr_cb(0); // pulse BCR
|
||||||
m_out_bcr_cb(0);
|
|
||||||
m_out_bcr_cb(1);
|
m_out_bcr_cb(1);
|
||||||
m_status &= ~(STATUS_BSY | STATUS_CIP);
|
newstatus &= ~(STATUS_BSY | STATUS_CIP); // prepare new status; (INTRQ later) reset BSY, CIP
|
||||||
m_out_intrq_cb(ASSERT_LINE);
|
complete_cmd(newstatus);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// issue a step pulse
|
m_out_step_cb(1); // issue a step pulse
|
||||||
m_out_step_cb(1);
|
|
||||||
m_out_step_cb(0);
|
m_out_step_cb(0);
|
||||||
step_pulses++;
|
step_pulses++;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
assert(1);
|
||||||
|
}
|
||||||
|
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// seek -
|
// seek -
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
void wd2010_device::seek(UINT8 data)
|
// FIXME : step rate, drive change (!)
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// NOT IMPLEMENTED: IMPLIED SEEK ("wait until rising edge of SC signal")
|
||||||
|
void wd2010_device::seek(UINT8 data)
|
||||||
|
{
|
||||||
|
UINT8 newstatus = STATUS_RDY | STATUS_SC;
|
||||||
|
|
||||||
|
m_out_intrq_cb(CLEAR_LINE); // reset INTRQ, errors, set BUSY, CIP
|
||||||
|
m_error = 0;
|
||||||
|
m_status = STATUS_BSY | STATUS_CIP;
|
||||||
|
|
||||||
|
// TODO : store STEP RATE.
|
||||||
|
|
||||||
|
auto_scan_id(data); // has drive number changed?
|
||||||
|
|
||||||
|
int direction = 0; // 0 = towards 0
|
||||||
|
int step_pulses = 0;
|
||||||
|
|
||||||
|
// Calculate number of steps by comparing the cylinder registers
|
||||||
|
// HI/LO with the internally stored position.
|
||||||
|
UINT32 cylinder_registers = CYLINDER;
|
||||||
|
if (m_present_cylinder > cylinder_registers)
|
||||||
|
{
|
||||||
|
step_pulses = m_present_cylinder - cylinder_registers;
|
||||||
|
direction = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
step_pulses = cylinder_registers - m_present_cylinder;
|
||||||
|
direction = 1;
|
||||||
|
}
|
||||||
|
logerror("SEEK - direction = %u, step_pulses = %u\n", direction, step_pulses);
|
||||||
|
m_out_dirin_cb(direction);
|
||||||
|
|
||||||
|
if (!m_in_drdy_cb() || m_in_wf_cb()) // DRDY de-asserted or WF asserted?
|
||||||
|
{
|
||||||
|
m_error = ERROR_AC;
|
||||||
|
complete_cmd(newstatus | STATUS_ERR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (step_pulses > 0) // issue STEP PULSES
|
||||||
|
{
|
||||||
|
if (direction == 0)
|
||||||
|
{
|
||||||
|
m_out_step_cb(1); // issue a step pulse
|
||||||
|
m_out_step_cb(0);
|
||||||
|
|
||||||
|
if (m_present_cylinder > 0)
|
||||||
|
m_present_cylinder--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_out_step_cb(0);
|
||||||
|
m_out_step_cb(1);
|
||||||
|
|
||||||
|
m_present_cylinder++;
|
||||||
|
}
|
||||||
|
step_pulses--;
|
||||||
|
|
||||||
|
// TODO: delay according to rate field
|
||||||
|
}
|
||||||
|
|
||||||
|
// ALL STEPS ISSUED NOW
|
||||||
|
|
||||||
|
if (!m_in_drdy_cb()) // DRDY not asserted = > ABORTED COMMAND
|
||||||
|
{
|
||||||
|
m_error = ERROR_AC;
|
||||||
|
complete_cmd(newstatus | STATUS_ERR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AFTER ALL STEPS ARE ISSUED ...
|
||||||
|
// UPDATE INTERNAL CYLINDER POSITION REGISTER (from WD1010 spec -> "SEEK COMMAND")
|
||||||
|
m_present_cylinder = cylinder_registers;
|
||||||
|
|
||||||
|
logerror("SEEK (END) - m_present_cylinder = %u\n", m_present_cylinder);
|
||||||
|
|
||||||
|
cmd_timer->adjust(attotime::from_msec(35), newstatus); // 35 msecs makes "SEEK_TIMING" test happy.
|
||||||
|
}
|
||||||
|
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// read_sector -
|
// read_sector -
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
// FIXME: multiple sector transfers, ID / CYL / HEAD / SIZE match
|
||||||
|
// + ERROR HANDLING (...)
|
||||||
void wd2010_device::read_sector(UINT8 data)
|
void wd2010_device::read_sector(UINT8 data)
|
||||||
{
|
{
|
||||||
|
UINT8 newstatus = STATUS_RDY | STATUS_SC;
|
||||||
|
int intrq_at_end = 0; // (default) : (I = 1 INTRQ occurs when the command
|
||||||
|
|
||||||
|
m_out_intrq_cb(CLEAR_LINE); // reset INTRQ, errors, set BUSY, CIP
|
||||||
|
m_error = 0;
|
||||||
|
m_status = STATUS_BSY | STATUS_CIP;
|
||||||
|
|
||||||
|
// Assume: drive NO # has not changed... (else: SCAN_ID; GET CYL#)
|
||||||
|
auto_scan_id(data); // has drive number changed?
|
||||||
|
|
||||||
|
// CYL REGISTERS and INTERNAL CYL. SAME ?
|
||||||
|
// TODO: < NOT SAME? THEN _SEEK_ >
|
||||||
|
|
||||||
|
// DRIVE NOT READY? OR WF?
|
||||||
|
if ( (!m_in_drdy_cb()) || m_in_wf_cb() )
|
||||||
|
{
|
||||||
|
m_error = ERROR_AC; // ABORTED_COMMAND
|
||||||
|
complete_cmd(newstatus | STATUS_ERR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_out_bcs_cb(1); // activate BCS (!)
|
||||||
|
|
||||||
|
m_out_bcr_cb(0); // strobe BCR
|
||||||
|
m_out_bcr_cb(1);
|
||||||
|
|
||||||
|
if (!m_in_drdy_cb()) // DRIVE NOT READY?
|
||||||
|
{
|
||||||
|
m_error = ERROR_AC; // ABORTED_COMMAND
|
||||||
|
complete_cmd(newstatus | STATUS_ERR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// < SEARCH FOR ID FIELD >
|
||||||
|
// < CYL / HEAD / SEC.SIZE MATCH ? >
|
||||||
|
|
||||||
|
// < ID NOT FOUND >
|
||||||
|
if (SECTOR_NUMBER > MAX_MFM_SECTORS)
|
||||||
|
{
|
||||||
|
// prepare new status; (later IRQ +) reset BSY, CIP
|
||||||
|
m_error = ERROR_ID;
|
||||||
|
complete_cmd(newstatus | STATUS_ERR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// LOOP OVER 10 INDEXES : SCAN_ID / GET CYL.# (not implemented: ID NOT FOUND)
|
||||||
|
|
||||||
|
// CYL / HEAD / SEC.SIZE MATCH ? => (ID FOUND)
|
||||||
|
//
|
||||||
|
// NO "BAD BLOCK DETECT" (** NOT IMPLEMENTED **)
|
||||||
|
// NO "CRC ERROR" (** NOT IMPLEMENTED **)
|
||||||
|
// AND "DAM FOUND" (** NOT IMPLEMENTED **)
|
||||||
|
|
||||||
|
// ====> THEN "TRANSFER SECTOR TO BUFFER" <====
|
||||||
|
|
||||||
|
m_out_bcr_cb(0); // strobe BCR
|
||||||
|
m_out_bcr_cb(1);
|
||||||
|
|
||||||
|
// NO "CRC ERROR"
|
||||||
|
|
||||||
|
// FLAG "M" SET? (MULTIPLE SECTOR TRANSFERS)
|
||||||
|
if (data & 4)
|
||||||
|
logerror("WD2010 (READ): MULTIPLE SECTOR READ (M = 1).\n");
|
||||||
|
|
||||||
|
// Assume: NO "M" (MULTIPLE SECTOR TRANSFERS)
|
||||||
|
|
||||||
|
m_out_bcs_cb(0); // deactivate BCS (!)
|
||||||
|
|
||||||
|
m_out_bcr_cb(0); // strobe BCR
|
||||||
|
m_out_bcr_cb(1);
|
||||||
|
|
||||||
|
// set BDRQ (NOTE: DRQ status bit 3 reflects state of BDRQ)
|
||||||
|
m_status |= STATUS_DRQ;
|
||||||
|
m_out_bdrq_cb(1);
|
||||||
|
|
||||||
|
// reset BUSY (* after * TRANSFER OF SECTOR in READ)
|
||||||
|
m_status &= ~(STATUS_BSY);
|
||||||
|
|
||||||
|
// FLAG "I" SET?
|
||||||
|
if (!(data & 8)) // (I = 0 INTRQ occurs with BDRQ/DRQ indicating the Sector Buffer is full...)
|
||||||
|
{
|
||||||
|
m_out_intrq_cb(ASSERT_LINE);
|
||||||
|
if (!(data & 4)) // (...valid only when M = 0)
|
||||||
|
intrq_at_end = STATUS_DWC; // 'reuse' unused DWC bit!
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
intrq_at_end = 0; // (default): (I = 1 INTRQ occurs when the command is completed and the Host has read the Sector Buffer)
|
||||||
|
}
|
||||||
|
|
||||||
|
// (WAIT FOR): BRDY LOW TO HIGH? (see -> TIMER)
|
||||||
|
|
||||||
|
} // DRIVE_READY ? (inner)
|
||||||
|
|
||||||
|
} // DRIVE_READY ? (outer)
|
||||||
|
|
||||||
|
// NOTE : (intrq_at_end = 0) - INTRQ occurs when the command is completed
|
||||||
|
newstatus |= (m_status & ~(STATUS_CIP | STATUS_DRQ)) | intrq_at_end; // de-assert CIP + DRQ (BSY already reset)
|
||||||
|
|
||||||
|
deassert_read_when_buffer_ready_high->adjust(attotime::from_usec(1), newstatus); // complete command ON *RISING EDGE * OF BUFFER_READY
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// write_sector -
|
// write_sector (stage I)
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
// FIXME: SEEK, SEEK_COMPLETE, Drive # change (!)
|
||||||
|
// as well as CYL.register + internal CYL.register comparisons
|
||||||
void wd2010_device::write_sector(UINT8 data)
|
void wd2010_device::write_sector(UINT8 data)
|
||||||
{
|
{
|
||||||
|
m_error = 0; // De-assert ERROR + DRQ
|
||||||
|
m_status &= ~(STATUS_DRQ);
|
||||||
|
|
||||||
|
m_status = STATUS_BSY | STATUS_CIP; // Assert BUSY + CIP
|
||||||
|
|
||||||
|
m_status |= STATUS_DRQ; // Assert BDRQ + DRQ (= status bit 3)
|
||||||
|
m_out_bdrq_cb(1);
|
||||||
|
|
||||||
|
// WAIT UNTIL BRDY ASSERTED (-> timer):
|
||||||
|
complete_write_when_buffer_ready_high->adjust(attotime::from_usec(1), data); // 1 usec
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// write_sector (stage II)
|
||||||
|
//-------------------------------------------------
|
||||||
|
void wd2010_device::complete_write_sector(UINT8 data)
|
||||||
|
{
|
||||||
|
UINT8 newstatus = STATUS_RDY | STATUS_SC;
|
||||||
|
|
||||||
|
m_out_bdrq_cb(0); // DE-Assert BDRQ (...and DRQ !)
|
||||||
|
m_status &= ~(STATUS_DRQ);
|
||||||
|
|
||||||
|
// (When drive changed) : SCAN_ID / GET CYL#
|
||||||
|
auto_scan_id(data); // has drive number changed? (*** UNIMPLEMENTED ***)
|
||||||
|
|
||||||
|
// Assume YES : CYL.register + internal CYL.register SAME? (if NO => SEEK!)
|
||||||
|
// Assume : SEEK_COMPLETE = YES
|
||||||
|
|
||||||
|
if (!m_in_drdy_cb() || m_in_wf_cb()) // DRIVE IS READY / NO WF?
|
||||||
|
{
|
||||||
|
m_error = ERROR_AC; // ABORTED_COMMAND
|
||||||
|
complete_cmd(newstatus | STATUS_ERR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // --------------------------------------------------------
|
||||||
|
// (*** UNIMPLEMENTED ***) Search for ID field...
|
||||||
|
|
||||||
|
// < Correct ID found >
|
||||||
|
|
||||||
|
// (*** UNIMPLEMENTED ***) : 'ID NOT FOUND' - set bit 4 error register
|
||||||
|
// ........................: => SCAN_ID => RE-SEEK (2-10 INDEX PULSES) / Set ERR bit 0 status register ..
|
||||||
|
|
||||||
|
m_status &= ~(STATUS_SC); // "WRITE_GATE valid when SEEK_COMPLETE = 0" (see Rainbow 100 Addendum!)
|
||||||
|
|
||||||
|
m_out_bcs_cb(1);
|
||||||
|
m_out_wg_cb(1); // (!)
|
||||||
|
|
||||||
|
m_out_bcr_cb(0); // strobe BCR
|
||||||
|
m_out_bcr_cb(1);
|
||||||
|
|
||||||
|
// Assume: DRIVE IS READY / NO WF
|
||||||
|
|
||||||
|
if (!m_in_drdy_cb() || m_in_wf_cb()) // DRDY de-asserted or WF asserted?
|
||||||
|
{
|
||||||
|
m_error = ERROR_AC; // ABORTED_COMMAND
|
||||||
|
complete_cmd(newstatus | STATUS_ERR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// ====> WRITE DATA TO SECTOR <====
|
||||||
|
|
||||||
|
m_out_wg_cb(0); // (!)
|
||||||
|
|
||||||
|
// Assume: (single sector transfer; M = 0)
|
||||||
|
|
||||||
|
} // (INNER IF): No WF and DRIVE IS READY.
|
||||||
|
} // --------------------------------------------------------
|
||||||
|
|
||||||
|
// 'complete_cmd' ON THE FALLING EDGE OF _BUFFER_READY_ ( set by WRITE_SECTOR ) !
|
||||||
|
deassert_write_when_buffer_ready_low->adjust(attotime::from_usec(1), newstatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ******************************************************
|
||||||
|
// AUTO SCAN-ID (whenever DRIVE # changes):
|
||||||
|
|
||||||
|
// * does nothing right now *
|
||||||
|
// ******************************************************
|
||||||
|
void wd2010_device::auto_scan_id(UINT8 data)
|
||||||
|
{
|
||||||
|
static int last_drive;
|
||||||
|
|
||||||
|
if (DRIVE != last_drive)
|
||||||
|
{
|
||||||
|
printf("\n(WD2010) : UNSUPPORTED DRIVE CHANGE !\n");
|
||||||
|
logerror("\n(WD2010) : UNSUPPORTED DRIVE CHANGE !\n");
|
||||||
|
|
||||||
|
//update_sdh(new_sector_size, new_head, new_cylinder, new_sectornr);
|
||||||
|
}
|
||||||
|
last_drive = DRIVE;
|
||||||
|
|
||||||
|
return; // AUTO-SCAN CURRENTLY DISABLED (see NOTES)
|
||||||
|
}
|
||||||
|
// ******************************************************
|
||||||
|
|
||||||
|
// What to do here (just update present_cylinder with CYLINDER)...?
|
||||||
|
void wd2010_device::update_sdh(UINT8 new_sector_size, UINT8 new_head, UINT16 new_cylinder, UINT8 new_sectornr)
|
||||||
|
{
|
||||||
|
// "Update SDH"
|
||||||
|
/*
|
||||||
|
// Update SECTOR_SIZE, HEAD in SDH with the ID found -
|
||||||
|
m_task_file[TASK_FILE_SDH_REGISTER] = ???
|
||||||
|
|
||||||
|
// ...update CYLINDER registers with cylinder found -
|
||||||
|
m_task_file[TASK_FILE_CYLINDER_LOW] = (new_cylinder >> 4) & 0x0f;
|
||||||
|
m_task_file[TASK_FILE_CYLINDER_HIGH] = (new_cylinder - ((new_cylinder >> 4) << 4)) & 0x0f;
|
||||||
|
|
||||||
|
// ...update SECTOR_NUMBER with sector nr. found -
|
||||||
|
m_task_file[TASK_FILE_SECTOR_NUMBER] = new_sectornr;
|
||||||
|
*/
|
||||||
|
|
||||||
|
m_present_cylinder = CYLINDER;
|
||||||
|
logerror("UPDATE_SDH - m_present_cylinder = %u\n", m_present_cylinder);
|
||||||
|
}
|
||||||
|
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// scan_id -
|
// scan_id -
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
// Reads the cylinder number from the track on which the heads are PRESENTLY located,
|
||||||
|
// and writes this into the Present Cylinder Position Register.
|
||||||
|
|
||||||
|
// FIXME: NO ID HANDLING (ID FOUND / NOT FOUND), NO BAD BLOCK; NO CRC
|
||||||
void wd2010_device::scan_id(UINT8 data)
|
void wd2010_device::scan_id(UINT8 data)
|
||||||
{
|
{
|
||||||
|
UINT8 newstatus = STATUS_RDY;
|
||||||
|
|
||||||
|
m_out_intrq_cb(CLEAR_LINE);
|
||||||
|
m_error = 0;
|
||||||
|
m_status = STATUS_BSY | STATUS_CIP;
|
||||||
|
|
||||||
|
// Assume DRIVE READY.
|
||||||
|
// < TODO: Search for ANY ID FIELD. >
|
||||||
|
|
||||||
|
// Assume ID FOUND :
|
||||||
|
update_sdh( 32, 0, 0, 1 ); // (NEW:) SECTOR_SIZE, HEAD, CYLINDER, SECTOR_NR
|
||||||
|
|
||||||
|
// NO BAD BLOCK.
|
||||||
|
// NO CRC ERROR.
|
||||||
|
|
||||||
|
complete_cmd(newstatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------
|
||||||
|
// FORMAT ENTIRE TRACK using the task file + sector buffer
|
||||||
|
|
||||||
//-------------------------------------------------
|
// On real hardware, data fields are filled with FF.
|
||||||
// format -
|
// Sector buffer is used for track layout (see datasheet).
|
||||||
//-------------------------------------------------
|
|
||||||
|
|
||||||
|
// Routine simulates one single write on each track
|
||||||
|
// - just enough to keep formatter programs happy -
|
||||||
|
|
||||||
|
// < UNIMPLEMENTED: (IMPLIED) SEEKs, INDEX, CRC and GAPs >
|
||||||
|
//--------------------------------------------------------
|
||||||
|
// SECTOR_COUNT REG.= 'total # of sectors to be formatted'
|
||||||
|
// (raw number; no multiplication) = 16 decimal on RD51
|
||||||
|
|
||||||
|
// SECTOR NUMBER REG.= number of bytes - 3 (for GAP 1 + 3)
|
||||||
|
// = 40 decimal on DEC RD51 with WUTIL 3.2
|
||||||
|
//--------------------------------------------------------
|
||||||
void wd2010_device::format(UINT8 data)
|
void wd2010_device::format(UINT8 data)
|
||||||
{
|
{
|
||||||
|
UINT8 newstatus = STATUS_RDY;
|
||||||
|
|
||||||
|
m_out_intrq_cb(CLEAR_LINE);
|
||||||
|
m_error = 0;
|
||||||
|
m_status = STATUS_BSY | STATUS_CIP;
|
||||||
|
|
||||||
|
m_status |= STATUS_DRQ;
|
||||||
|
m_out_bdrq_cb(1);
|
||||||
|
|
||||||
|
// < WAIT UNTIL BRDY ASSERTED >
|
||||||
|
|
||||||
|
// Datasheet says [DRQ] must go LOW...
|
||||||
|
// ...delayed here _until BRDY goes high_ (=> TIMER EVENT <=):
|
||||||
|
|
||||||
|
// m_out_bdrq_cb(0);
|
||||||
|
// m_status &= ~(STATUS_DRQ);
|
||||||
|
|
||||||
|
auto_scan_id(data); // has drive number changed?
|
||||||
|
|
||||||
|
// TODO: Seek to desired cylinder
|
||||||
|
// Assume : SEEK COMPLETE.
|
||||||
|
|
||||||
|
m_out_bcr_cb(0); // strobe BCR
|
||||||
|
m_out_bcr_cb(1);
|
||||||
|
|
||||||
|
m_out_bcs_cb(1); // activate BCS (!)
|
||||||
|
|
||||||
|
if (!m_in_drdy_cb() || m_in_wf_cb())
|
||||||
|
{
|
||||||
|
m_error = ERROR_AC; // ABORTED_COMMAND
|
||||||
|
complete_cmd(newstatus | STATUS_ERR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// WAIT FOR INDEX
|
||||||
|
|
||||||
|
m_out_wg_cb(1); // Have Index, activate WRITE GATE
|
||||||
|
|
||||||
|
// Check for WRITE FAULT (WF)
|
||||||
|
if (m_in_wf_cb())
|
||||||
|
{
|
||||||
|
m_error = ERROR_AC; // ABORTED_COMMAND
|
||||||
|
complete_cmd(newstatus | STATUS_ERR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// UINT8 format_sector_count = m_task_file[TASK_FILE_SECTOR_COUNT];
|
||||||
|
// do
|
||||||
|
// {
|
||||||
|
// < WRITE GAP 1 or GAP 3 >
|
||||||
|
|
||||||
|
// < Wait for SEEK_COMPLETE=1 (extend GAP if SEEK_COMPLETE = 0) >
|
||||||
|
// < Assume SEEK COMPLETE >
|
||||||
|
|
||||||
|
// format_sector_count--;
|
||||||
|
// if (format_sector_count != 0)
|
||||||
|
{
|
||||||
|
// The Rainbow 100 driver does ignore multiple sector
|
||||||
|
// transfers so WRITE FORMAT does not actually write -
|
||||||
|
|
||||||
|
m_out_wg_cb(0); // (transition from WG 1 -> 0)
|
||||||
|
|
||||||
|
// NOTE: decrementing TASK_FILE_SECTOR_COUNT does * NOT WORK *
|
||||||
|
}
|
||||||
|
// else
|
||||||
|
// { // < Write 4Es until INDEX (*** UNIMPLEMENTED ****) >
|
||||||
|
// }
|
||||||
|
// } while (format_sector_count > 0);
|
||||||
|
|
||||||
|
// ** DELAY INTRQ UNTIL WRITE IS COMPLETE :
|
||||||
|
complete_write_when_buffer_ready_high->adjust(attotime::from_usec(1), newstatus | STATUS_DRQ); // 1 USECs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// *************************************
|
||||||
|
// INTERNAL
|
||||||
|
// *************************************
|
||||||
|
void wd2010_device::buffer_ready(bool state)
|
||||||
|
{
|
||||||
|
is_buffer_ready = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void wd2010_device::device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr)
|
||||||
|
{
|
||||||
|
switch (tid)
|
||||||
|
{
|
||||||
|
case COMMAND_TIMER:
|
||||||
|
cmd_timer->adjust(attotime::never);
|
||||||
|
complete_immediate(param);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case COMPLETE_WRITE_SECTOR: // when BUFFER_READY -> HIGH
|
||||||
|
if (is_buffer_ready)
|
||||||
|
{
|
||||||
|
complete_write_when_buffer_ready_high->adjust(attotime::never);
|
||||||
|
complete_write_sector(param);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
complete_write_when_buffer_ready_high->reset();
|
||||||
|
complete_write_when_buffer_ready_high->adjust(attotime::from_usec(1), param); // DELAY ANOTHER 1 USEC (!)
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DE_ASSERT_WRITE: // waiting for BUFFER_READY -> LOW
|
||||||
|
if (!(is_buffer_ready))
|
||||||
|
{
|
||||||
|
deassert_write_when_buffer_ready_low->adjust(attotime::never);
|
||||||
|
complete_immediate(param);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
deassert_write_when_buffer_ready_low->reset();
|
||||||
|
deassert_write_when_buffer_ready_low->adjust(attotime::from_usec(1), param); // DELAY ANOTHER 1 USEC (!)
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DE_ASSERT_READ: // when BUFFER_READY -> HIGH
|
||||||
|
if (is_buffer_ready)
|
||||||
|
{
|
||||||
|
deassert_read_when_buffer_ready_high->adjust(attotime::never);
|
||||||
|
|
||||||
|
m_error &= ~ERROR_ID;
|
||||||
|
param &= ~STATUS_ERR;
|
||||||
|
|
||||||
|
m_out_bdrq_cb(0);
|
||||||
|
complete_immediate(param);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
deassert_read_when_buffer_ready_high->reset();
|
||||||
|
deassert_read_when_buffer_ready_high->adjust(attotime::from_usec(1), param); // DELAY ANOTHER 1 USEC (!)
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called by 'device_timer' -
|
||||||
|
void wd2010_device::complete_immediate(UINT8 status)
|
||||||
|
{
|
||||||
|
// re-evaluate external signals at end of command
|
||||||
|
status &= ~(STATUS_RDY | STATUS_WF | STATUS_SC); // RDY 0x40 / WF 0x20 / SC 0x10
|
||||||
|
status |= (m_in_drdy_cb() ? 0x40 : 0) | (m_in_wf_cb() ? 0x20 : 0) | (m_in_sc_cb() ? 0x10 : 0);
|
||||||
|
|
||||||
|
if (status & STATUS_DRQ) // if DRQ was set, reset
|
||||||
|
{
|
||||||
|
status &= ~(STATUS_DRQ);
|
||||||
|
m_out_bdrq_cb(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set current status (M_STATUS)
|
||||||
|
m_status = status & (255 - STATUS_DWC); // minus "unused" bit 2 (DWC)
|
||||||
|
|
||||||
|
m_status &= ~(STATUS_BSY | STATUS_CIP); // de-assert BUSY + CIP
|
||||||
|
|
||||||
|
// "IRQ AT END OF COMMAND" when BIT 2 set (DWC 'data was corrected' - unused in this context!)
|
||||||
|
if (!(status & STATUS_DWC)) // interrupt at END OF COMMAND ?
|
||||||
|
m_out_intrq_cb(ASSERT_LINE); // Assert INTRQ (callback).
|
||||||
|
|
||||||
|
m_out_bcs_cb(0); // de-assert BCS (needed)
|
||||||
|
m_out_wg_cb(0); // deactivate WG (required by write / format)
|
||||||
|
|
||||||
|
m_out_bcr_cb(0); // strobe BCR
|
||||||
|
m_out_bcr_cb(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wd2010_device::complete_cmd(UINT8 status)
|
||||||
|
{
|
||||||
|
cmd_timer->adjust(attotime::from_msec(1), status);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -32,6 +32,9 @@
|
|||||||
#define MCFG_WD2010_OUT_BCR_CB(_devcb) \
|
#define MCFG_WD2010_OUT_BCR_CB(_devcb) \
|
||||||
devcb = &wd2010_device::set_out_bcr_callback(*device, DEVCB_##_devcb);
|
devcb = &wd2010_device::set_out_bcr_callback(*device, DEVCB_##_devcb);
|
||||||
|
|
||||||
|
#define MCFG_WD2010_IN_BRDY_CB(_devcb) \
|
||||||
|
devcb = &wd2010_device::set_in_brdy_callback(*device, DEVCB_##_devcb);
|
||||||
|
|
||||||
#define MCFG_WD2010_IN_BCS_CB(_devcb) \
|
#define MCFG_WD2010_IN_BCS_CB(_devcb) \
|
||||||
devcb = &wd2010_device::set_in_bcs_callback(*device, DEVCB_##_devcb);
|
devcb = &wd2010_device::set_in_bcs_callback(*device, DEVCB_##_devcb);
|
||||||
|
|
||||||
@ -47,6 +50,9 @@
|
|||||||
#define MCFG_WD2010_OUT_RWC_CB(_devcb) \
|
#define MCFG_WD2010_OUT_RWC_CB(_devcb) \
|
||||||
devcb = &wd2010_device::set_out_rwc_callback(*device, DEVCB_##_devcb);
|
devcb = &wd2010_device::set_out_rwc_callback(*device, DEVCB_##_devcb);
|
||||||
|
|
||||||
|
#define MCFG_WD2010_OUT_WG_CB(_devcb) \
|
||||||
|
devcb = &wd2010_device::set_out_wg_callback(*device, DEVCB_##_devcb);
|
||||||
|
|
||||||
#define MCFG_WD2010_IN_DRDY_CB(_devcb) \
|
#define MCFG_WD2010_IN_DRDY_CB(_devcb) \
|
||||||
devcb = &wd2010_device::set_in_drdy_callback(*device, DEVCB_##_devcb);
|
devcb = &wd2010_device::set_in_drdy_callback(*device, DEVCB_##_devcb);
|
||||||
|
|
||||||
@ -77,11 +83,13 @@ public:
|
|||||||
template<class _Object> static devcb_base &set_out_intrq_callback(device_t &device, _Object object) { return downcast<wd2010_device &>(device).m_out_intrq_cb.set_callback(object); }
|
template<class _Object> static devcb_base &set_out_intrq_callback(device_t &device, _Object object) { return downcast<wd2010_device &>(device).m_out_intrq_cb.set_callback(object); }
|
||||||
template<class _Object> static devcb_base &set_out_bdrq_callback(device_t &device, _Object object) { return downcast<wd2010_device &>(device).m_out_bdrq_cb.set_callback(object); }
|
template<class _Object> static devcb_base &set_out_bdrq_callback(device_t &device, _Object object) { return downcast<wd2010_device &>(device).m_out_bdrq_cb.set_callback(object); }
|
||||||
template<class _Object> static devcb_base &set_out_bcr_callback(device_t &device, _Object object) { return downcast<wd2010_device &>(device).m_out_bcr_cb.set_callback(object); }
|
template<class _Object> static devcb_base &set_out_bcr_callback(device_t &device, _Object object) { return downcast<wd2010_device &>(device).m_out_bcr_cb.set_callback(object); }
|
||||||
|
template<class _Object> static devcb_base &set_in_brdy_callback(device_t &device, _Object object) { return downcast<wd2010_device &>(device).m_in_brdy_cb.set_callback(object); }
|
||||||
template<class _Object> static devcb_base &set_in_bcs_callback(device_t &device, _Object object) { return downcast<wd2010_device &>(device).m_in_bcs_cb.set_callback(object); }
|
template<class _Object> static devcb_base &set_in_bcs_callback(device_t &device, _Object object) { return downcast<wd2010_device &>(device).m_in_bcs_cb.set_callback(object); }
|
||||||
template<class _Object> static devcb_base &set_out_bcs_callback(device_t &device, _Object object) { return downcast<wd2010_device &>(device).m_out_bcs_cb.set_callback(object); }
|
template<class _Object> static devcb_base &set_out_bcs_callback(device_t &device, _Object object) { return downcast<wd2010_device &>(device).m_out_bcs_cb.set_callback(object); }
|
||||||
template<class _Object> static devcb_base &set_out_dirin_callback(device_t &device, _Object object) { return downcast<wd2010_device &>(device).m_out_dirin_cb.set_callback(object); }
|
template<class _Object> static devcb_base &set_out_dirin_callback(device_t &device, _Object object) { return downcast<wd2010_device &>(device).m_out_dirin_cb.set_callback(object); }
|
||||||
template<class _Object> static devcb_base &set_out_step_callback(device_t &device, _Object object) { return downcast<wd2010_device &>(device).m_out_step_cb.set_callback(object); }
|
template<class _Object> static devcb_base &set_out_step_callback(device_t &device, _Object object) { return downcast<wd2010_device &>(device).m_out_step_cb.set_callback(object); }
|
||||||
template<class _Object> static devcb_base &set_out_rwc_callback(device_t &device, _Object object) { return downcast<wd2010_device &>(device).m_out_rwc_cb.set_callback(object); }
|
template<class _Object> static devcb_base &set_out_rwc_callback(device_t &device, _Object object) { return downcast<wd2010_device &>(device).m_out_rwc_cb.set_callback(object); }
|
||||||
|
template<class _Object> static devcb_base &set_out_wg_callback(device_t &device, _Object object) { return downcast<wd2010_device &>(device).m_out_wg_cb.set_callback(object); }
|
||||||
template<class _Object> static devcb_base &set_in_drdy_callback(device_t &device, _Object object) { return downcast<wd2010_device &>(device).m_in_drdy_cb.set_callback(object); }
|
template<class _Object> static devcb_base &set_in_drdy_callback(device_t &device, _Object object) { return downcast<wd2010_device &>(device).m_in_drdy_cb.set_callback(object); }
|
||||||
template<class _Object> static devcb_base &set_in_index_callback(device_t &device, _Object object) { return downcast<wd2010_device &>(device).m_in_index_cb.set_callback(object); }
|
template<class _Object> static devcb_base &set_in_index_callback(device_t &device, _Object object) { return downcast<wd2010_device &>(device).m_in_index_cb.set_callback(object); }
|
||||||
template<class _Object> static devcb_base &set_in_wf_callback(device_t &device, _Object object) { return downcast<wd2010_device &>(device).m_in_wf_cb.set_callback(object); }
|
template<class _Object> static devcb_base &set_in_wf_callback(device_t &device, _Object object) { return downcast<wd2010_device &>(device).m_in_wf_cb.set_callback(object); }
|
||||||
@ -91,11 +99,15 @@ public:
|
|||||||
DECLARE_READ8_MEMBER( read );
|
DECLARE_READ8_MEMBER( read );
|
||||||
DECLARE_WRITE8_MEMBER( write );
|
DECLARE_WRITE8_MEMBER( write );
|
||||||
|
|
||||||
|
void buffer_ready(bool state);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// device-level overrides
|
// device-level overrides
|
||||||
virtual void device_start();
|
virtual void device_start();
|
||||||
virtual void device_reset();
|
virtual void device_reset();
|
||||||
|
|
||||||
|
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void compute_correction(UINT8 data);
|
void compute_correction(UINT8 data);
|
||||||
void set_parameter(UINT8 data);
|
void set_parameter(UINT8 data);
|
||||||
@ -104,16 +116,20 @@ private:
|
|||||||
void read_sector(UINT8 data);
|
void read_sector(UINT8 data);
|
||||||
void write_sector(UINT8 data);
|
void write_sector(UINT8 data);
|
||||||
void scan_id(UINT8 data);
|
void scan_id(UINT8 data);
|
||||||
|
void update_sdh(UINT8 new_sector_size, UINT8 new_head, UINT16 new_cylinder, UINT8 new_sectornr);
|
||||||
|
void auto_scan_id(UINT8 data);
|
||||||
void format(UINT8 data);
|
void format(UINT8 data);
|
||||||
|
|
||||||
devcb_write_line m_out_intrq_cb;
|
devcb_write_line m_out_intrq_cb;
|
||||||
devcb_write_line m_out_bdrq_cb;
|
devcb_write_line m_out_bdrq_cb;
|
||||||
devcb_write_line m_out_bcr_cb;
|
devcb_write_line m_out_bcr_cb;
|
||||||
devcb_read8 m_in_bcs_cb;
|
devcb_read8 m_in_bcs_cb;
|
||||||
|
devcb_read_line m_in_brdy_cb;
|
||||||
devcb_write8 m_out_bcs_cb;
|
devcb_write8 m_out_bcs_cb;
|
||||||
devcb_write_line m_out_dirin_cb;
|
devcb_write_line m_out_dirin_cb;
|
||||||
devcb_write_line m_out_step_cb;
|
devcb_write_line m_out_step_cb;
|
||||||
devcb_write_line m_out_rwc_cb;
|
devcb_write_line m_out_rwc_cb;
|
||||||
|
devcb_write_line m_out_wg_cb;
|
||||||
devcb_read_line m_in_drdy_cb;
|
devcb_read_line m_in_drdy_cb;
|
||||||
devcb_read_line m_in_index_cb;
|
devcb_read_line m_in_index_cb;
|
||||||
devcb_read_line m_in_wf_cb;
|
devcb_read_line m_in_wf_cb;
|
||||||
@ -123,8 +139,20 @@ private:
|
|||||||
UINT8 m_status;
|
UINT8 m_status;
|
||||||
UINT8 m_error;
|
UINT8 m_error;
|
||||||
UINT8 m_task_file[8];
|
UINT8 m_task_file[8];
|
||||||
};
|
|
||||||
|
|
||||||
|
emu_timer *cmd_timer;
|
||||||
|
emu_timer *complete_write_when_buffer_ready_high;
|
||||||
|
emu_timer *deassert_write_when_buffer_ready_low;
|
||||||
|
emu_timer *deassert_read_when_buffer_ready_high;
|
||||||
|
|
||||||
|
void complete_write_sector(UINT8 status);
|
||||||
|
void complete_cmd(UINT8 status);
|
||||||
|
void complete_immediate(UINT8 status);
|
||||||
|
|
||||||
|
bool is_buffer_ready;
|
||||||
|
|
||||||
|
UINT32 m_present_cylinder; // Present Cylinder Position Register
|
||||||
|
};
|
||||||
|
|
||||||
// device type definition
|
// device type definition
|
||||||
extern const device_type WD2010;
|
extern const device_type WD2010;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -106,7 +106,12 @@
|
|||||||
</text>
|
</text>
|
||||||
</element>
|
</element>
|
||||||
|
|
||||||
|
<element name="digit" defstate="0">
|
||||||
|
<led7seg>
|
||||||
|
<color red="0.75" green="0.0" blue="0.0" />
|
||||||
|
</led7seg>
|
||||||
|
</element>
|
||||||
|
|
||||||
<view name="Default Layout">
|
<view name="Default Layout">
|
||||||
<screen index="0">
|
<screen index="0">
|
||||||
<bounds x="30" y="0" width="640" height="480" />
|
<bounds x="30" y="0" width="640" height="480" />
|
||||||
@ -206,6 +211,13 @@
|
|||||||
<bezel name="label11" element="l11_wait">
|
<bezel name="label11" element="l11_wait">
|
||||||
<bounds x="0" y="282" width="15" height="16" />
|
<bounds x="0" y="282" width="15" height="16" />
|
||||||
</bezel>
|
</bezel>
|
||||||
|
|
||||||
|
<bezel name="digit0" element="digit">
|
||||||
|
<bounds x="0" y="320" width="14" height="20" />
|
||||||
|
</bezel>
|
||||||
|
<bezel name="digit1" element="digit">
|
||||||
|
<bounds x="15" y="320" width="14" height="20" />
|
||||||
|
</bezel>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view name="Screen Only">
|
<view name="Screen Only">
|
||||||
|
@ -230,14 +230,14 @@ const rom_entry *lk201_device::device_rom_region() const
|
|||||||
|
|
||||||
DEC omitted terms like 'Interrupt', 'Break' and 'Data / Talk' on some keyboards,
|
DEC omitted terms like 'Interrupt', 'Break' and 'Data / Talk' on some keyboards,
|
||||||
so Fn numbers are definitely important for end users.
|
so Fn numbers are definitely important for end users.
|
||||||
|
|
||||||
=== CURRENT SPECIAL KEYS ===
|
=== CURRENT SPECIAL KEYS ===
|
||||||
[PC-AT] ......=> [DEC]
|
[PC-AT] ......=> [DEC]
|
||||||
LEFT CONTROL..=> Control
|
LEFT CONTROL..=> Control
|
||||||
LEFT ALT .....=> Compose
|
LEFT ALT .....=> Compose
|
||||||
|
|
||||||
RIGHT ALT ....=> Help
|
RIGHT ALT ....=> Help
|
||||||
RIGHT CONTROL => Do
|
RIGHT CONTROL => Do
|
||||||
==============================================================================================
|
==============================================================================================
|
||||||
=== (PC - AT ) keys above cursor block ===
|
=== (PC - AT ) keys above cursor block ===
|
||||||
* KEYCODE_INSERT * KEYCODE_HOME * KEYCODE_PGUP
|
* KEYCODE_INSERT * KEYCODE_HOME * KEYCODE_PGUP
|
||||||
@ -249,9 +249,9 @@ const rom_entry *lk201_device::device_rom_region() const
|
|||||||
==============================================================================================
|
==============================================================================================
|
||||||
=== CURRENT NUM PAD ASSIGNMENTS ===
|
=== CURRENT NUM PAD ASSIGNMENTS ===
|
||||||
[PF1] to [PF4] are mapped to NUM LOCK, SLASH etc. (=> 4 keys on top on num pad).
|
[PF1] to [PF4] are mapped to NUM LOCK, SLASH etc. (=> 4 keys on top on num pad).
|
||||||
Num pad '+' gives ',' on the DEC.
|
Num pad '+' gives ',' on the DEC.
|
||||||
',' translates to '.' (=> more or less the layout of model 'LK-201-AG')
|
',' translates to '.' (=> more or less the layout of model 'LK-201-AG')
|
||||||
|
|
||||||
Switch between 'full' and 'partial keyboard emulation' with Scroll Lock.
|
Switch between 'full' and 'partial keyboard emulation' with Scroll Lock.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -276,7 +276,7 @@ INPUT_PORTS_START( lk201 )
|
|||||||
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_UNUSED )
|
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_UNUSED )
|
||||||
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Compose") PORT_CODE(KEYCODE_LALT)
|
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Compose") PORT_CODE(KEYCODE_LALT)
|
||||||
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Caps Lock") PORT_CODE(KEYCODE_CAPSLOCK)
|
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Caps Lock") PORT_CODE(KEYCODE_CAPSLOCK)
|
||||||
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Ctrl") PORT_CODE(KEYCODE_LCONTROL)
|
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Ctrl") PORT_CODE(KEYCODE_LCONTROL)
|
||||||
|
|
||||||
PORT_START("KBD2")
|
PORT_START("KBD2")
|
||||||
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Z") PORT_CODE(KEYCODE_Z)
|
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Z") PORT_CODE(KEYCODE_Z)
|
||||||
@ -303,7 +303,7 @@ INPUT_PORTS_START( lk201 )
|
|||||||
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("D") PORT_CODE(KEYCODE_D)
|
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("D") PORT_CODE(KEYCODE_D)
|
||||||
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("E") PORT_CODE(KEYCODE_E)
|
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("E") PORT_CODE(KEYCODE_E)
|
||||||
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("3") PORT_CODE(KEYCODE_3)
|
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("3") PORT_CODE(KEYCODE_3)
|
||||||
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Setup (F3)") PORT_CODE(KEYCODE_F3)
|
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Setup (F3)") PORT_CODE(KEYCODE_PAUSE) // SET UP = Pause on PC
|
||||||
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNUSED )
|
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNUSED )
|
||||||
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Print Screen (F2)") PORT_CODE(KEYCODE_F2)
|
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Print Screen (F2)") PORT_CODE(KEYCODE_F2)
|
||||||
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNUSED )
|
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNUSED )
|
||||||
@ -363,20 +363,20 @@ INPUT_PORTS_START( lk201 )
|
|||||||
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("L") PORT_CODE(KEYCODE_L)
|
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("L") PORT_CODE(KEYCODE_L)
|
||||||
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("O") PORT_CODE(KEYCODE_O)
|
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("O") PORT_CODE(KEYCODE_O)
|
||||||
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("9") PORT_CODE(KEYCODE_9)
|
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("9") PORT_CODE(KEYCODE_9)
|
||||||
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("LF (F13)") PORT_CODE(KEYCODE_PRTSCR)
|
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("LF (F13)") PORT_CODE(KEYCODE_F13)
|
||||||
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNUSED )
|
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNUSED )
|
||||||
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("BS (F12)") PORT_CODE(KEYCODE_F12)
|
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("BS (F12)") PORT_CODE(KEYCODE_F12)
|
||||||
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNUSED )
|
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNUSED )
|
||||||
|
|
||||||
PORT_START("KBD11")
|
PORT_START("KBD11")
|
||||||
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("/") PORT_CODE(KEYCODE_SLASH)
|
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("/") PORT_CODE(KEYCODE_SLASH)
|
||||||
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME(";") PORT_CODE(KEYCODE_COLON)
|
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME(";") PORT_CODE(KEYCODE_COLON)
|
||||||
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED ) // FIXME - duplicate "Return"
|
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED ) // FIXME - duplicate "Return"
|
||||||
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("P") PORT_CODE(KEYCODE_P)
|
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("P") PORT_CODE(KEYCODE_P)
|
||||||
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("0") PORT_CODE(KEYCODE_0)
|
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("0") PORT_CODE(KEYCODE_0)
|
||||||
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNUSED )
|
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNUSED )
|
||||||
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Delete <X") PORT_CODE(KEYCODE_BACKSPACE)
|
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Delete <X") PORT_CODE(KEYCODE_BACKSPACE)
|
||||||
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Additional Options (F14) [Zusaetze]") PORT_CODE(KEYCODE_PAUSE)
|
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Additional Options (F14) [Zusaetze]") PORT_CODE(KEYCODE_PRTSCR)
|
||||||
|
|
||||||
PORT_START("KBD12")
|
PORT_START("KBD12")
|
||||||
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("\\") PORT_CODE(KEYCODE_BACKSLASH)
|
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("\\") PORT_CODE(KEYCODE_BACKSLASH)
|
||||||
@ -394,7 +394,7 @@ INPUT_PORTS_START( lk201 )
|
|||||||
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("'") PORT_CODE(KEYCODE_QUOTE)
|
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("'") PORT_CODE(KEYCODE_QUOTE)
|
||||||
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("[") PORT_CODE(KEYCODE_OPENBRACE)
|
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("[") PORT_CODE(KEYCODE_OPENBRACE)
|
||||||
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Previous [^]") PORT_CODE(KEYCODE_END)
|
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Previous [^]") PORT_CODE(KEYCODE_END)
|
||||||
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Do (F16) [Ausfuehren]") PORT_CODE(KEYCODE_RCONTROL)
|
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Do (F16) [Ausfuehren]") PORT_CODE(KEYCODE_RCONTROL)
|
||||||
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("-") PORT_CODE(KEYCODE_MINUS)
|
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("-") PORT_CODE(KEYCODE_MINUS)
|
||||||
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Insert Here") PORT_CODE(KEYCODE_HOME)
|
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Insert Here") PORT_CODE(KEYCODE_HOME)
|
||||||
|
|
||||||
@ -433,7 +433,7 @@ INPUT_PORTS_START( lk201 )
|
|||||||
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Num ,") PORT_CODE(KEYCODE_PLUS_PAD)
|
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Num ,") PORT_CODE(KEYCODE_PLUS_PAD)
|
||||||
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) // PORT_NAME("Num -") = duplicate...see KBD13
|
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) // PORT_NAME("Num -") = duplicate...see KBD13
|
||||||
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("PF4") PORT_CODE(KEYCODE_MINUS_PAD)
|
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("PF4") PORT_CODE(KEYCODE_MINUS_PAD)
|
||||||
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("F20")
|
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("F20")
|
||||||
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNUSED )
|
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNUSED )
|
||||||
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("F19")
|
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("F19")
|
||||||
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNUSED )
|
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNUSED )
|
||||||
@ -623,7 +623,6 @@ void lk201_device::send_port(address_space &space, UINT8 offset, UINT8 data)
|
|||||||
if (ports[1] & 0x80) kbd_data = m_kbd15->read();
|
if (ports[1] & 0x80) kbd_data = m_kbd15->read();
|
||||||
if (ports[2] & 0x1) kbd_data = m_kbd16->read();
|
if (ports[2] & 0x1) kbd_data = m_kbd16->read();
|
||||||
if (ports[2] & 0x2) kbd_data = m_kbd17->read();
|
if (ports[2] & 0x2) kbd_data = m_kbd17->read();
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
// Check for LED update strobe
|
// Check for LED update strobe
|
||||||
if (((data & 0x80) == 0) && (ports[offset] & 0x80))
|
if (((data & 0x80) == 0) && (ports[offset] & 0x80))
|
||||||
@ -634,6 +633,8 @@ void lk201_device::send_port(address_space &space, UINT8 offset, UINT8 data)
|
|||||||
output_set_value("led_hold" , (led_data & 0x4) == 0);
|
output_set_value("led_hold" , (led_data & 0x4) == 0);
|
||||||
output_set_value("led_lock" , (led_data & 0x8) == 0);
|
output_set_value("led_lock" , (led_data & 0x8) == 0);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -755,3 +756,4 @@ WRITE8_MEMBER( lk201_device::spi_w )
|
|||||||
|
|
||||||
// printf("SPI %02x to %x (PC=%x)\n", data, offset, m_maincpu->pc());
|
// printf("SPI %02x to %x (PC=%x)\n", data, offset, m_maincpu->pc());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ Copyright MESS Team.
|
|||||||
Visit http://mamedev.org for licensing and usage restrictions.
|
Visit http://mamedev.org for licensing and usage restrictions.
|
||||||
|
|
||||||
01/05/2009 Initial implementation [Miodrag Milanovic]
|
01/05/2009 Initial implementation [Miodrag Milanovic]
|
||||||
Portions (2013, 2014) by Karl-Ludwig Deisenhofer.
|
Enhancements (2013 - 2015) by Karl-Ludwig Deisenhofer.
|
||||||
|
|
||||||
DEC VIDEO : STATE AS OF JULY 2014
|
DEC VIDEO : STATE AS OF JULY 2014
|
||||||
---------------------------------
|
---------------------------------
|
||||||
@ -21,27 +21,27 @@ FIXME: work out the differences and identify common code between VT and Rainbow.
|
|||||||
- REQUIRED TODOS / TESTS :
|
- REQUIRED TODOS / TESTS :
|
||||||
* do line and character attributes (plus combinations) match real hardware?
|
* do line and character attributes (plus combinations) match real hardware?
|
||||||
* how does the AVO fit in?
|
* how does the AVO fit in?
|
||||||
|
|
||||||
- SCROLLING REGIONS / SPLIT SCREEN SCROLLING UNTESTED (if you open > 1 file with the VAX editor EDT)
|
- SCROLLING REGIONS / SPLIT SCREEN SCROLLING UNTESTED (if you open > 1 file with the VAX editor EDT)
|
||||||
See VT100 Technical Manual: 4.7.4 Address Shuffling to 4.7.9 Split Screen Smooth Scrolling.
|
See VT100 Technical Manual: 4.7.4 Address Shuffling to 4.7.9 Split Screen Smooth Scrolling.
|
||||||
More on scrolling regions: Rainbow 100 B technical documentation (QV069-GZ) April 1985 page 22
|
More on scrolling regions: Rainbow 100 B technical documentation (QV069-GZ) April 1985 page 22
|
||||||
|
|
||||||
- NEW - INTERLACED MODE (Rainbow only):
|
- NEW - INTERLACED MODE (Rainbow only):
|
||||||
Vertical resolution increases from 240 to 480, while the refresh rate halves (flickers on CRTs).
|
Vertical resolution increases from 240 to 480, while the refresh rate halves (flickers on CRTs).
|
||||||
To accomplish this, the display controller repeats even lines in odd scans.
|
To accomplish this, the display controller repeats even lines in odd scans.
|
||||||
VTVIDEO activates line doubling in 24 line, interlaced mode only.
|
VTVIDEO activates line doubling in 24 line, interlaced mode only.
|
||||||
|
|
||||||
Although the DC12 has the ability to display 48 lines, most units are low on screen RAM and
|
Although the DC12 has the ability to display 48 lines, most units are low on screen RAM and
|
||||||
won't even show 80 x 48. -> REASON: (83 x 48 = 3984 Byte) > (screen RAM) minus 'scratch area'
|
won't even show 80 x 48. -> REASON: (83 x 48 = 3984 Byte) > (screen RAM) minus 'scratch area'
|
||||||
On a VT-180, BIOS scratch requires up to 700 bytes used for SETUP, flags, SILO, keyboard.
|
On a VT-180, BIOS scratch requires up to 700 bytes used for SETUP, flags, SILO, keyboard.
|
||||||
|
|
||||||
- POSSIBLE IMPROVEMENTS:
|
- POSSIBLE IMPROVEMENTS:
|
||||||
|
|
||||||
* exact colors for different VR201 monitors ('paper white', green and amber)
|
* exact colors for different VR201 monitors (for white, green and amber)
|
||||||
|
|
||||||
* ACCURATE VIDEO DELAYS:
|
* ACCURATE VIDEO DELAYS:
|
||||||
Position of the first visible scanline (relative to the vertical reset) depends on
|
Position of the first visible scanline (relative to the vertical reset) depends on
|
||||||
content of fill bytes at the beginning of screen RAM.
|
content of fill bytes at the beginning of screen RAM.
|
||||||
|
|
||||||
Six invisible, linked lines are initially provided (at location $EE000+ on a Rainbow).
|
Six invisible, linked lines are initially provided (at location $EE000+ on a Rainbow).
|
||||||
Real-world DC hardware parses the (circular) chain until interrupted by blanking.
|
Real-world DC hardware parses the (circular) chain until interrupted by blanking.
|
||||||
@ -65,7 +65,7 @@ FIXME: work out the differences and identify common code between VT and Rainbow.
|
|||||||
PARAMETERS
|
PARAMETERS
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#define VERBOSE 0
|
#define VERBOSE 1
|
||||||
|
|
||||||
#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
|
#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
|
||||||
|
|
||||||
@ -185,10 +185,10 @@ void rainbow_video_device::device_reset()
|
|||||||
m_basic_attribute = 0;
|
m_basic_attribute = 0;
|
||||||
|
|
||||||
m_columns = 80;
|
m_columns = 80;
|
||||||
|
|
||||||
|
m_frequency = 60;
|
||||||
|
|
||||||
m_frequency = 60;
|
m_interlaced = 1;
|
||||||
|
|
||||||
m_interlaced = 1;
|
|
||||||
m_fill_lines = 2; // for 60Hz (not in use any longer -> detected)
|
m_fill_lines = 2; // for 60Hz (not in use any longer -> detected)
|
||||||
recompute_parameters();
|
recompute_parameters();
|
||||||
}
|
}
|
||||||
@ -210,8 +210,8 @@ void vt100_video_device::recompute_parameters()
|
|||||||
|
|
||||||
int vert_pix_total = ((m_linedoubler == false) ? m_height : m_height_MAX) * 10;
|
int vert_pix_total = ((m_linedoubler == false) ? m_height : m_height_MAX) * 10;
|
||||||
|
|
||||||
if (m_columns == 132)
|
if (m_columns == 132)
|
||||||
horiz_pix_total = m_columns * 9; // display 1 less filler pixel in 132 char. mode
|
horiz_pix_total = m_columns * 9; // display 1 less filler pixel in 132 char. mode
|
||||||
else
|
else
|
||||||
horiz_pix_total = m_columns * 10; // normal 80 character mode.
|
horiz_pix_total = m_columns * 10; // normal 80 character mode.
|
||||||
|
|
||||||
@ -239,30 +239,57 @@ READ8_MEMBER(vt100_video_device::lba7_r)
|
|||||||
// Also used by Rainbow-100 ************
|
// Also used by Rainbow-100 ************
|
||||||
WRITE8_MEMBER(vt100_video_device::dc012_w)
|
WRITE8_MEMBER(vt100_video_device::dc012_w)
|
||||||
{
|
{
|
||||||
// TODO: writes to 10C/0C should be treated differently (emulation disables the watchdog too often).
|
// Writes to [10C] and [0C] are treated differently
|
||||||
// - see 3.1.3.9.5 DC012 Programming Information (PC-100 spec)
|
// - see 3.1.3.9.5 DC012 Programming Information (PC-100 spec)
|
||||||
if (data == 0) // MHFU is disabled by writing 00 to port 010C.
|
|
||||||
{
|
|
||||||
MHFU_FLAG = false;
|
|
||||||
MHFU_counter = 0;
|
|
||||||
|
|
||||||
if (VERBOSE)
|
// MHFU is disabled by writing 00 to port 010C.
|
||||||
{
|
|
||||||
if (MHFU_FLAG == true)
|
// Code recognition is abysmal - sorry for that.
|
||||||
printf("MHFU *** DISABLED *** %ul \n", offset);
|
if (data == 0)
|
||||||
}
|
{
|
||||||
}
|
UINT8 *rom = machine().root_device().memregion("maincpu")->base();
|
||||||
|
if (rom != NULL)
|
||||||
|
{
|
||||||
|
UINT32 PC = space.device().safe_pc();
|
||||||
|
if ((rom[ PC - 1] == 0xe6) &&
|
||||||
|
(rom[ PC ] == 0x0c)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// OUT 0C,al < DO NOTHING >
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//UINT8 magic1= rom[PC - 1];
|
||||||
|
//printf("\n PC %05x - MHFU MAGIC -1 %02x\n", PC, magic1);
|
||||||
|
//UINT8 magic2 = rom[PC - 2];
|
||||||
|
//printf("\n PC %05x - MHFU MAGIC -2 %02x\n", PC, magic2);
|
||||||
|
//if (VERBOSE)
|
||||||
|
|
||||||
|
//if(1 )
|
||||||
|
if ((rom[PC - 2] == 0x0C) &&
|
||||||
|
(rom[PC - 1] == 0x01)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (MHFU_FLAG == true)
|
||||||
|
printf("MHFU *** DISABLED *** %05x \n", PC);
|
||||||
|
|
||||||
|
MHFU_FLAG = false;
|
||||||
|
MHFU_counter = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // DATA == 0 ONLY ....
|
||||||
|
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// RESET
|
//if (VERBOSE)
|
||||||
MHFU_FLAG = true;
|
if (MHFU_FLAG == false)
|
||||||
MHFU_counter = 0;
|
printf("MHFU ___ENABLED___ %05x \n", space.device().safe_pc());
|
||||||
|
|
||||||
if (VERBOSE)
|
// RESET
|
||||||
{
|
MHFU_FLAG = true;
|
||||||
if (MHFU_FLAG == false)
|
MHFU_counter = 0;
|
||||||
printf("MHFU ___ENABLED___ %ul \n", offset);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(data & 0x08))
|
if (!(data & 0x08))
|
||||||
@ -284,57 +311,57 @@ WRITE8_MEMBER(vt100_video_device::dc012_w)
|
|||||||
{
|
{
|
||||||
switch (data & 0x0f)
|
switch (data & 0x0f)
|
||||||
{
|
{
|
||||||
case 0x08:
|
case 0x08:
|
||||||
// toggle blink flip flop
|
// toggle blink flip flop
|
||||||
m_blink_flip_flop = !(m_blink_flip_flop) ? 1 : 0;
|
m_blink_flip_flop = !(m_blink_flip_flop) ? 1 : 0;
|
||||||
break;
|
break;
|
||||||
case 0x09:
|
case 0x09:
|
||||||
// clear vertical frequency interrupt;
|
// clear vertical frequency interrupt;
|
||||||
m_write_clear_video_interrupt(0);
|
m_write_clear_video_interrupt(0);
|
||||||
break;
|
break;
|
||||||
case 0x0a:
|
case 0x0a:
|
||||||
// set reverse field on
|
// set reverse field on
|
||||||
m_reverse_field = 1;
|
m_reverse_field = 1;
|
||||||
break;
|
break;
|
||||||
case 0x0b:
|
case 0x0b:
|
||||||
// set reverse field off
|
// set reverse field off
|
||||||
m_reverse_field = 0;
|
m_reverse_field = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Writing a 11XX bit combination clears the blink-flip flop (valid for 0x0C - 0x0F):
|
// Writing a 11XX bit combination clears the blink-flip flop (valid for 0x0C - 0x0F):
|
||||||
case 0x0c:
|
case 0x0c:
|
||||||
// set basic attribute to underline / blink flip-flop off
|
// set basic attribute to underline / blink flip-flop off
|
||||||
m_blink_flip_flop = 0;
|
m_blink_flip_flop = 0;
|
||||||
m_basic_attribute = 0; // (VT-100 without AVO): reverse video is interpreted as underline (basic_attribute 0)
|
m_basic_attribute = 0; // (VT-100 without AVO): reverse video is interpreted as underline (basic_attribute 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x0d:
|
case 0x0d:
|
||||||
// (DEC Rainbow 100 DEFAULT) : reverse video with 24 lines / blink flip-flop off
|
// (DEC Rainbow 100 DEFAULT) : reverse video with 24 lines / blink flip-flop off
|
||||||
m_blink_flip_flop = 0;
|
m_blink_flip_flop = 0;
|
||||||
m_basic_attribute = 1; // (VT-100 without AVO): reverse video is interpreted as reverse (basic_attribute 1)
|
m_basic_attribute = 1; // (VT-100 without AVO): reverse video is interpreted as reverse (basic_attribute 1)
|
||||||
|
|
||||||
if (m_height_MAX == 25) break; // Abort on VT-100 for now.
|
if (m_height_MAX == 25) break; // Abort on VT-100 for now.
|
||||||
|
|
||||||
m_height = 24; // (DEC Rainbow 100) : 24 line display
|
m_height = 24; // (DEC Rainbow 100) : 24 line display
|
||||||
recompute_parameters();
|
recompute_parameters();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x0e:
|
case 0x0e:
|
||||||
m_blink_flip_flop = 0; // 'unsupported' DC012 command. Turns blink flip-flop off (11XX).
|
m_blink_flip_flop = 0; // 'unsupported' DC012 command. Turns blink flip-flop off (11XX).
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x0f:
|
case 0x0f:
|
||||||
// (DEC Rainbow 100): reverse video with 48 lines / blink flip-flop off
|
// (DEC Rainbow 100): reverse video with 48 lines / blink flip-flop off
|
||||||
m_blink_flip_flop = 0;
|
m_blink_flip_flop = 0;
|
||||||
m_basic_attribute = 1;
|
m_basic_attribute = 1;
|
||||||
|
|
||||||
// 0x0f = 'reserved' on VT 100
|
// 0x0f = 'reserved' on VT 100
|
||||||
// Abort on VT-100 for now.
|
// Abort on VT-100 for now.
|
||||||
if (m_height_MAX == 25) break;
|
if (m_height_MAX == 25) break;
|
||||||
|
|
||||||
m_height = 48; // (DEC Rainbow 100) : 48 line display
|
m_height = 48; // (DEC Rainbow 100) : 48 line display
|
||||||
recompute_parameters();
|
recompute_parameters();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -342,15 +369,15 @@ WRITE8_MEMBER(vt100_video_device::dc012_w)
|
|||||||
// Writing to DC011 resets internal counters (& disturbs display) on real hardware.
|
// Writing to DC011 resets internal counters (& disturbs display) on real hardware.
|
||||||
WRITE8_MEMBER(vt100_video_device::dc011_w)
|
WRITE8_MEMBER(vt100_video_device::dc011_w)
|
||||||
{
|
{
|
||||||
if (!BIT(data, 5))
|
if (!BIT(data, 5))
|
||||||
{
|
{
|
||||||
m_interlaced = 1;
|
m_interlaced = 1;
|
||||||
|
|
||||||
if (!BIT(data, 4))
|
if (!BIT(data, 4))
|
||||||
m_columns = 80;
|
m_columns = 80;
|
||||||
else
|
else
|
||||||
m_columns = 132;
|
m_columns = 132;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_interlaced = 0;
|
m_interlaced = 0;
|
||||||
@ -358,16 +385,16 @@ WRITE8_MEMBER(vt100_video_device::dc011_w)
|
|||||||
if (!BIT(data, 4))
|
if (!BIT(data, 4))
|
||||||
{
|
{
|
||||||
m_frequency = 60;
|
m_frequency = 60;
|
||||||
m_fill_lines = 2;
|
m_fill_lines = 2;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_frequency = 50;
|
m_frequency = 50;
|
||||||
m_fill_lines = 5;
|
m_fill_lines = 5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
recompute_parameters();
|
recompute_parameters();
|
||||||
}
|
}
|
||||||
|
|
||||||
WRITE8_MEMBER(vt100_video_device::brightness_w)
|
WRITE8_MEMBER(vt100_video_device::brightness_w)
|
||||||
@ -388,12 +415,12 @@ void vt100_video_device::display_char(bitmap_ind16 &bitmap, UINT8 code, int x, i
|
|||||||
switch (display_type)
|
switch (display_type)
|
||||||
{
|
{
|
||||||
case 0: // bottom half, double height
|
case 0: // bottom half, double height
|
||||||
j = (i >> 1) + 5; break;
|
j = (i >> 1) + 5; break;
|
||||||
case 1: // top half, double height
|
case 1: // top half, double height
|
||||||
j = (i >> 1); break;
|
j = (i >> 1); break;
|
||||||
case 2: // double width
|
case 2: // double width
|
||||||
case 3: // normal
|
case 3: // normal
|
||||||
j = i; break;
|
j = i; break;
|
||||||
default: j = 0; break;
|
default: j = 0; break;
|
||||||
}
|
}
|
||||||
// modify line since that is how it is stored in rom
|
// modify line since that is how it is stored in rom
|
||||||
@ -415,27 +442,27 @@ void vt100_video_device::display_char(bitmap_ind16 &bitmap, UINT8 code, int x, i
|
|||||||
bit = BIT((line << b), 7);
|
bit = BIT((line << b), 7);
|
||||||
if (double_width)
|
if (double_width)
|
||||||
{
|
{
|
||||||
bitmap.pix16(y * 10 + i, x * 20 + b * 2) = (bit | prevbit) ^ invert;
|
bitmap.pix16(y * 10 + i, x * 20 + b * 2) = (bit | prevbit) ^ invert;
|
||||||
bitmap.pix16(y * 10 + i, x * 20 + b * 2 + 1) = bit ^ invert;
|
bitmap.pix16(y * 10 + i, x * 20 + b * 2 + 1) = bit ^ invert;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bitmap.pix16(y * 10 + i, x * 10 + b) = (bit | prevbit) ^ invert;
|
bitmap.pix16(y * 10 + i, x * 10 + b) = (bit | prevbit) ^ invert;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
prevbit = bit;
|
prevbit = bit;
|
||||||
// char interleave is filled with last bit
|
// char interleave is filled with last bit
|
||||||
if (double_width)
|
if (double_width)
|
||||||
{
|
{
|
||||||
bitmap.pix16(y * 10 + i, x * 20 + 16) = (bit | prevbit) ^ invert;
|
bitmap.pix16(y * 10 + i, x * 20 + 16) = (bit | prevbit) ^ invert;
|
||||||
bitmap.pix16(y * 10 + i, x * 20 + 17) = bit ^ invert;
|
bitmap.pix16(y * 10 + i, x * 20 + 17) = bit ^ invert;
|
||||||
bitmap.pix16(y * 10 + i, x * 20 + 18) = bit ^ invert;
|
bitmap.pix16(y * 10 + i, x * 20 + 18) = bit ^ invert;
|
||||||
bitmap.pix16(y * 10 + i, x * 20 + 19) = bit ^ invert;
|
bitmap.pix16(y * 10 + i, x * 20 + 19) = bit ^ invert;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bitmap.pix16(y * 10 + i, x * 10 + 8) = (bit | prevbit) ^ invert;
|
bitmap.pix16(y * 10 + i, x * 10 + 8) = (bit | prevbit) ^ invert;
|
||||||
bitmap.pix16(y * 10 + i, x * 10 + 9) = bit ^ invert;
|
bitmap.pix16(y * 10 + i, x * 10 + 9) = bit ^ invert;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -474,7 +501,7 @@ void vt100_video_device::video_update(bitmap_ind16 &bitmap, const rectangle &cli
|
|||||||
// if A12 is 1 then it is 0x2000 block, if 0 then 0x4000 (AVO)
|
// if A12 is 1 then it is 0x2000 block, if 0 then 0x4000 (AVO)
|
||||||
if (addr & 0x1000) addr &= 0xfff; else addr |= 0x2000;
|
if (addr & 0x1000) addr &= 0xfff; else addr |= 0x2000;
|
||||||
scroll_region = (temp >> 15) & 1;
|
scroll_region = (temp >> 15) & 1;
|
||||||
display_type = (temp >> 13) & 3;
|
display_type = (temp >> 13) & 3;
|
||||||
if (line >= m_fill_lines)
|
if (line >= m_fill_lines)
|
||||||
{
|
{
|
||||||
ypos++;
|
ypos++;
|
||||||
@ -533,7 +560,7 @@ void rainbow_video_device::display_char(bitmap_ind16 &bitmap, UINT8 code, int x,
|
|||||||
|
|
||||||
UINT16 y_preset;
|
UINT16 y_preset;
|
||||||
|
|
||||||
UINT16 CHARPOS_y_preset = y << 3; // CHARPOS_y_preset = y * 10;
|
UINT16 CHARPOS_y_preset = y << 3; // CHARPOS_y_preset = y * 10;
|
||||||
CHARPOS_y_preset += y;
|
CHARPOS_y_preset += y;
|
||||||
CHARPOS_y_preset += y;
|
CHARPOS_y_preset += y;
|
||||||
|
|
||||||
@ -545,10 +572,10 @@ void rainbow_video_device::display_char(bitmap_ind16 &bitmap, UINT8 code, int x,
|
|||||||
int back_intensity, back_default_intensity;
|
int back_intensity, back_default_intensity;
|
||||||
|
|
||||||
int invert = (display_type & 8) ? 1 : 0; // REVERSE
|
int invert = (display_type & 8) ? 1 : 0; // REVERSE
|
||||||
int bold = (display_type & 16) ? 0 : 1; // BIT 4
|
int bold = (display_type & 16) ? 0 : 1; // BIT 4
|
||||||
int blink = (display_type & 32) ? 0 : 1; // BIT 5
|
int blink = (display_type & 32) ? 0 : 1; // BIT 5
|
||||||
int underline = (display_type & 64) ? 0 : 1; // BIT 6
|
int underline = (display_type & 64) ? 0 : 1; // BIT 6
|
||||||
bool blank = (display_type & 128) ? true : false; // BIT 7
|
bool blank = (display_type & 128) ? true : false; // BIT 7
|
||||||
|
|
||||||
display_type = display_type & 3;
|
display_type = display_type & 3;
|
||||||
|
|
||||||
@ -580,8 +607,8 @@ void rainbow_video_device::display_char(bitmap_ind16 &bitmap, UINT8 code, int x,
|
|||||||
// BG: DEFAULT for entire character (underline overrides this for 1 line) -
|
// BG: DEFAULT for entire character (underline overrides this for 1 line) -
|
||||||
back_default_intensity = back_intensity;
|
back_default_intensity = back_intensity;
|
||||||
|
|
||||||
bool double_width = (display_type != 3) ? true : false; // all except normal: double width
|
bool double_width = (display_type != 3) ? true : false; // all except normal: double width
|
||||||
bool double_height = (display_type & 1) ? false : true; // 0,2 = double height
|
bool double_height = (display_type & 1) ? false : true; // 0,2 = double height
|
||||||
|
|
||||||
int smooth_offset = 0;
|
int smooth_offset = 0;
|
||||||
if (scroll_region != 0)
|
if (scroll_region != 0)
|
||||||
@ -610,24 +637,24 @@ void rainbow_video_device::display_char(bitmap_ind16 &bitmap, UINT8 code, int x,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
y_preset = (m_linedoubler ? 480 : 240) - extra_scan_line;
|
y_preset = (m_linedoubler ? 480 : 240) - extra_scan_line;
|
||||||
i = 0; // (should be always empty)
|
i = 0; // blank line. Might not work with TCS or other charsets (FIXME)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (display_type)
|
switch (display_type)
|
||||||
{
|
{
|
||||||
case 0: // bottom half of 'double height, double width' char.
|
case 0: // bottom half of 'double height, double width' char.
|
||||||
j = (i >> 1) + 5;
|
j = (i >> 1) + 5;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2: // top half of 'double height, double width' char.
|
case 2: // top half of 'double height, double width' char.
|
||||||
j = (i >> 1);
|
j = (i >> 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: // 1: double width
|
default: // 1: double width
|
||||||
// 3: normal
|
// 3: normal
|
||||||
j = i;
|
j = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// modify line since that is how it is stored in rom
|
// modify line since that is how it is stored in rom
|
||||||
@ -641,13 +668,13 @@ void rainbow_video_device::display_char(bitmap_ind16 &bitmap, UINT8 code, int x,
|
|||||||
{
|
{
|
||||||
if (i == 8)
|
if (i == 8)
|
||||||
{
|
{
|
||||||
if (invert == 0)
|
if (invert == 0)
|
||||||
line = 0xff; // CASE 5 A)
|
line = 0xff; // CASE 5 A)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
line = 0x00; // CASE 5 B)
|
line = 0x00; // CASE 5 B)
|
||||||
back_intensity = 0; // OVERRIDE: BLACK BACKGROUND
|
back_intensity = 0; // OVERRIDE: BLACK BACKGROUND
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -659,12 +686,12 @@ void rainbow_video_device::display_char(bitmap_ind16 &bitmap, UINT8 code, int x,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bit = BIT((line << b), 7);
|
bit = BIT((line << b), 7);
|
||||||
|
|
||||||
if (bit > 0)
|
if (bit > 0)
|
||||||
bit = fg_intensity;
|
bit = fg_intensity;
|
||||||
else
|
else
|
||||||
bit = back_intensity;
|
bit = back_intensity;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Double, 'double_height + double_width', then normal.
|
// Double, 'double_height + double_width', then normal.
|
||||||
@ -729,7 +756,7 @@ void rainbow_video_device::video_update(bitmap_ind16 &bitmap, const rectangle &c
|
|||||||
// Skip fill (0xFF) lines and put result in ADDR.
|
// Skip fill (0xFF) lines and put result in ADDR.
|
||||||
for (int xp = 1; xp <= 6; xp += 1) // beware of circular references
|
for (int xp = 1; xp <= 6; xp += 1) // beware of circular references
|
||||||
{
|
{
|
||||||
// Fetch LINE ATTRIBUTE before it is gone
|
// Fetch LINE ATTRIBUTE before it is gone
|
||||||
attr_addr = 0x1000 | ((addr + 1) & 0x0fff);
|
attr_addr = 0x1000 | ((addr + 1) & 0x0fff);
|
||||||
|
|
||||||
temp = m_read_ram(addr + 2) * 256 + m_read_ram(addr + 1);
|
temp = m_read_ram(addr + 2) * 256 + m_read_ram(addr + 1);
|
||||||
@ -749,9 +776,9 @@ void rainbow_video_device::video_update(bitmap_ind16 &bitmap, const rectangle &c
|
|||||||
code = m_read_ram(addr + xpos);
|
code = m_read_ram(addr + xpos);
|
||||||
|
|
||||||
if (code == 0x00) // TODO: investigate side effect on regular zero character!
|
if (code == 0x00) // TODO: investigate side effect on regular zero character!
|
||||||
display_type |= 0x80; // DEFAULT: filler chars (till end of line) and empty lines (00) will be blanked
|
display_type |= 0x80; // DEFAULT: filler chars (till end of line) and empty lines (00) will be blanked
|
||||||
else
|
else
|
||||||
display_type &= 0x7f; // else activate display.
|
display_type &= 0x7f; // else activate display.
|
||||||
|
|
||||||
if (code == 0xff) // end of line, fill empty till end of line
|
if (code == 0xff) // end of line, fill empty till end of line
|
||||||
{
|
{
|
||||||
@ -759,7 +786,7 @@ void rainbow_video_device::video_update(bitmap_ind16 &bitmap, const rectangle &c
|
|||||||
for (x = xpos; x < ((display_type != 3) ? (m_columns / 2) : m_columns); x++)
|
for (x = xpos; x < ((display_type != 3) ? (m_columns / 2) : m_columns); x++)
|
||||||
{
|
{
|
||||||
display_char(bitmap, code, x, ypos, scroll_region, display_type | 0x80);
|
display_char(bitmap, code, x, ypos, scroll_region, display_type | 0x80);
|
||||||
}
|
}
|
||||||
|
|
||||||
// LINE ATTRIBUTE - valid for all chars on next line ** DO NOT SHUFFLE **
|
// LINE ATTRIBUTE - valid for all chars on next line ** DO NOT SHUFFLE **
|
||||||
attr_addr = 0x1000 | ((addr + xpos + 1) & 0x0fff);
|
attr_addr = 0x1000 | ((addr + xpos + 1) & 0x0fff);
|
||||||
@ -770,7 +797,7 @@ void rainbow_video_device::video_update(bitmap_ind16 &bitmap, const rectangle &c
|
|||||||
|
|
||||||
temp = m_read_ram(attr_addr);
|
temp = m_read_ram(attr_addr);
|
||||||
scroll_region = (temp)& 1;
|
scroll_region = (temp)& 1;
|
||||||
display_type = (temp >> 1) & 3;
|
display_type = (temp >> 1) & 3;
|
||||||
|
|
||||||
ypos++; // Y + 1 in non-interlaced mode
|
ypos++; // Y + 1 in non-interlaced mode
|
||||||
if (m_linedoubler)
|
if (m_linedoubler)
|
||||||
@ -821,24 +848,24 @@ void rainbow_video_device::palette_select(int choice)
|
|||||||
{
|
{
|
||||||
switch (choice)
|
switch (choice)
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
case 0x01:
|
case 0x01:
|
||||||
m_palette->set_pen_color(1, 0xff - 100, 0xff - 100, 0xff - 100); // WHITE (dim)
|
m_palette->set_pen_color(1, 0xff - 100, 0xff - 100, 0xff - 100); // WHITE (dim)
|
||||||
m_palette->set_pen_color(2, 0xff - 50, 0xff - 50, 0xff - 50); // WHITE NORMAL
|
m_palette->set_pen_color(2, 0xff - 50, 0xff - 50, 0xff - 50); // WHITE NORMAL
|
||||||
m_palette->set_pen_color(3, 0xff, 0xff, 0xff); // WHITE (brighter)
|
m_palette->set_pen_color(3, 0xff, 0xff, 0xff); // WHITE (brighter)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x02:
|
case 0x02:
|
||||||
m_palette->set_pen_color(1, 35, 200 - 55, 75); // GREEN (dim)
|
m_palette->set_pen_color(1, 35, 200 - 55, 75); // GREEN (dim)
|
||||||
m_palette->set_pen_color(2, 35 + 55, 200, 75 + 55); // GREEN (NORMAL)
|
m_palette->set_pen_color(2, 35 + 55, 200, 75 + 55); // GREEN (NORMAL)
|
||||||
m_palette->set_pen_color(3, 35 + 110, 200 + 55, 75 + 110); // GREEN (brighter)
|
m_palette->set_pen_color(3, 35 + 110, 200 + 55, 75 + 110); // GREEN (brighter)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x03:
|
case 0x03:
|
||||||
m_palette->set_pen_color(1, 213 - 47, 146 - 47, 82 - 47); // AMBER (dim)
|
m_palette->set_pen_color(1, 213 - 47, 146 - 47, 82 - 47); // AMBER (dim)
|
||||||
m_palette->set_pen_color(2, 213, 146, 82); // AMBER (NORMAL)
|
m_palette->set_pen_color(2, 213, 146, 82); // AMBER (NORMAL)
|
||||||
m_palette->set_pen_color(3, 255, 193, 129); // AMBER (brighter)
|
m_palette->set_pen_color(3, 255, 193, 129); // AMBER (brighter)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -856,31 +883,43 @@ int rainbow_video_device::MHFU(int ASK)
|
|||||||
{
|
{
|
||||||
switch (ASK)
|
switch (ASK)
|
||||||
{
|
{
|
||||||
case 1: // "true": RETURN BOOLEAN (MHFU disabled or enabled?)
|
case 1: // "true": RETURN BOOLEAN (MHFU disabled or enabled?)
|
||||||
return MHFU_FLAG;
|
return MHFU_FLAG;
|
||||||
|
|
||||||
case -1: // -1: increment, return counter value (=> Rainbow.c)
|
case -1: // -1: increment IF ENABLED, return counter value (=> Rainbow.c)
|
||||||
if (MHFU_FLAG == true)
|
if (MHFU_FLAG == true)
|
||||||
MHFU_counter++;
|
MHFU_counter++;
|
||||||
return MHFU_counter;
|
return MHFU_counter;
|
||||||
|
|
||||||
case -100: // -100 : RESET and ENABLE MHFU counter
|
case -100: // -100 : RESET and ENABLE MHFU counter
|
||||||
if (VERBOSE)
|
MHFU_counter = 0;
|
||||||
|
if(1) //if (VERBOSE)
|
||||||
printf("-100 MHFU * reset and ENABLE * \n");
|
printf("-100 MHFU * reset and ENABLE * \n");
|
||||||
MHFU_counter = 0;
|
|
||||||
|
|
||||||
if (VERBOSE)
|
if(1) // if (VERBOSE)
|
||||||
{
|
{
|
||||||
if (MHFU_FLAG == false)
|
if (MHFU_FLAG == false)
|
||||||
printf("-100 MHFU ___ENABLED___\n");
|
printf("-100 MHFU ___ENABLED___\n");
|
||||||
}
|
}
|
||||||
MHFU_FLAG = true;
|
MHFU_FLAG = true;
|
||||||
|
|
||||||
return -100;
|
return -100;
|
||||||
|
|
||||||
|
case -200: // -200 : RESET and DISABLE MHFU
|
||||||
|
MHFU_counter = 0;
|
||||||
|
|
||||||
default:
|
if(1) //if (VERBOSE)
|
||||||
assert(1);
|
{
|
||||||
return -255;
|
if (MHFU_FLAG == true)
|
||||||
|
printf("MHFU *** DISABLED *** \n");
|
||||||
|
}
|
||||||
|
MHFU_FLAG = false;
|
||||||
|
|
||||||
|
return -200;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert(1);
|
||||||
|
return -255;
|
||||||
} // switch
|
} // switch
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
|
|
||||||
DEC VT Terminal video emulation
|
DEC VT Terminal video emulation
|
||||||
[ DC012 and DC011 emulation ]
|
[ DC012 and DC011 emulation ]
|
||||||
|
|
||||||
01/05/2009 Initial implementation [Miodrag Milanovic]
|
01/05/2009 Initial implementation [Miodrag Milanovic]
|
||||||
|
|
||||||
Copyright MESS Team.
|
Copyright MESS Team.
|
||||||
Visit http://mamedev.org for licensing and usage restrictions.
|
Visit http://mamedev.org for licensing and usage restrictions.
|
||||||
|
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
|
|
||||||
@ -16,7 +16,7 @@
|
|||||||
#include "emu.h"
|
#include "emu.h"
|
||||||
|
|
||||||
class vt100_video_device : public device_t,
|
class vt100_video_device : public device_t,
|
||||||
public device_video_interface
|
public device_video_interface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
vt100_video_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);
|
vt100_video_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);
|
||||||
|
Loading…
Reference in New Issue
Block a user