mirror of
https://github.com/holub/mame
synced 2025-04-23 08:49:55 +03:00
wd_fdc: Wait for sector read/write to complete on interrupt d0-7, fixes rmnimbus floppy access errors
This commit is contained in:
parent
5c64a1771a
commit
9ef70e0322
@ -22,8 +22,10 @@
|
||||
#define LOG_STATE (1U << 12) // Show state machine
|
||||
#define LOG_LIVE (1U << 13) // Live states
|
||||
#define LOG_FUNC (1U << 14) // Function calls
|
||||
#define LOG_CRC (1U << 15) // CRC errors
|
||||
|
||||
#define VERBOSE (LOG_DESC)
|
||||
//#define VERBOSE (LOG_DESC | LOG_COMMAND | LOG_MATCH | LOG_WRITE | LOG_STATE | LOG_LINES | LOG_COMP | LOG_CRC )
|
||||
//#define LOG_OUTPUT_STREAM std::cout
|
||||
|
||||
#include "logmacro.h"
|
||||
@ -42,6 +44,7 @@
|
||||
#define LOGSTATE(...) LOGMASKED(LOG_STATE, __VA_ARGS__)
|
||||
#define LOGLIVE(...) LOGMASKED(LOG_LIVE, __VA_ARGS__)
|
||||
#define LOGFUNC(...) LOGMASKED(LOG_FUNC, __VA_ARGS__)
|
||||
#define LOGCRC(...) LOGMASKED(LOG_CRC, __VA_ARGS__)
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define FUNCNAME __func__
|
||||
@ -79,6 +82,58 @@ DEFINE_DEVICE_TYPE(WD1770, wd1770_device, "wd1770", "Western Digital
|
||||
DEFINE_DEVICE_TYPE(WD1772, wd1772_device, "wd1772", "Western Digital WD1772 FDC")
|
||||
DEFINE_DEVICE_TYPE(WD1773, wd1773_device, "wd1773", "Western Digital WD1773 FDC")
|
||||
|
||||
static const char *const states[] =
|
||||
{
|
||||
"IDLE",
|
||||
"RESTORE",
|
||||
"SEEK",
|
||||
"STEP",
|
||||
"READ_SECTOR",
|
||||
"READ_TRACK",
|
||||
"READ_ID",
|
||||
"WRITE_TRACK",
|
||||
"WRITE_SECTOR",
|
||||
"SPINUP",
|
||||
"SPINUP_WAIT",
|
||||
"SPINUP_DONE",
|
||||
"SETTLE_WAIT",
|
||||
"SETTLE_DONE",
|
||||
"DATA_LOAD_WAIT",
|
||||
"DATA_LOAD_WAIT_DONE",
|
||||
"SEEK_MOVE",
|
||||
"SEEK_WAIT_STEP_TIME",
|
||||
"SEEK_WAIT_STEP_TIME_DONE",
|
||||
"SEEK_WAIT_STABILIZATION_TIME",
|
||||
"SEEK_WAIT_STABILIZATION_TIME_DONE",
|
||||
"SEEK_DONE",
|
||||
"WAIT_INDEX",
|
||||
"WAIT_INDEX_DONE",
|
||||
"SCAN_ID",
|
||||
"SCAN_ID_FAILED",
|
||||
"SECTOR_READ",
|
||||
"SECTOR_WRITE",
|
||||
"TRACK_DONE",
|
||||
"INITIAL_RESTORE",
|
||||
"DUMMY",
|
||||
"SEARCH_ADDRESS_MARK_HEADER",
|
||||
"READ_HEADER_BLOCK_HEADER",
|
||||
"READ_DATA_BLOCK_HEADER",
|
||||
"READ_ID_BLOCK_TO_LOCAL",
|
||||
"READ_ID_BLOCK_TO_DMA",
|
||||
"READ_ID_BLOCK_TO_DMA_BYTE",
|
||||
"SEARCH_ADDRESS_MARK_DATA",
|
||||
"SEARCH_ADDRESS_MARK_DATA_FAILED",
|
||||
"READ_SECTOR_DATA",
|
||||
"READ_SECTOR_DATA_BYTE",
|
||||
"READ_TRACK_DATA",
|
||||
"READ_TRACK_DATA_BYTE",
|
||||
"WRITE_TRACK_DATA",
|
||||
"WRITE_BYTE",
|
||||
"WRITE_BYTE_DONE",
|
||||
"WRITE_SECTOR_PRE",
|
||||
"WRITE_SECTOR_PRE_BYTE"
|
||||
};
|
||||
|
||||
wd_fdc_device_base::wd_fdc_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
|
||||
device_t(mconfig, type, tag, owner, clock),
|
||||
intrq_cb(*this),
|
||||
@ -131,6 +186,8 @@ void wd_fdc_device_base::device_start()
|
||||
data = 0x00;
|
||||
track = 0x00;
|
||||
mr = true;
|
||||
|
||||
delay_int = false;
|
||||
|
||||
save_item(NAME(status));
|
||||
save_item(NAME(command));
|
||||
@ -435,6 +492,7 @@ void wd_fdc_device_base::seek_continue()
|
||||
if(cur_live.crc) {
|
||||
status |= S_CRC;
|
||||
live_start(SEARCH_ADDRESS_MARK_HEADER);
|
||||
LOGCRC("CRC error in seek\n");
|
||||
return;
|
||||
}
|
||||
command_end();
|
||||
@ -540,6 +598,7 @@ void wd_fdc_device_base::read_sector_continue()
|
||||
if(cur_live.crc) {
|
||||
status |= S_CRC;
|
||||
live_start(SEARCH_ADDRESS_MARK_HEADER);
|
||||
LOGCRC("CRC error in readsector\n");
|
||||
return;
|
||||
}
|
||||
sector_size = calc_sector_size(cur_live.idbuf[3], command);
|
||||
@ -556,7 +615,10 @@ void wd_fdc_device_base::read_sector_continue()
|
||||
case SECTOR_READ:
|
||||
LOGSTATE("SECTOR_READ\n");
|
||||
if(cur_live.crc)
|
||||
{
|
||||
status |= S_CRC;
|
||||
LOGCRC("CRC error in readsector %04X\n",cur_live.crc);
|
||||
}
|
||||
|
||||
if(command & 0x10 && !(status & S_RNF)) {
|
||||
sector++;
|
||||
@ -920,6 +982,7 @@ void wd_fdc_device_base::write_sector_continue()
|
||||
if(cur_live.crc) {
|
||||
status |= S_CRC;
|
||||
live_start(SEARCH_ADDRESS_MARK_HEADER);
|
||||
LOGCRC("CRC error in writesector\n");
|
||||
return;
|
||||
}
|
||||
sector_size = calc_sector_size(cur_live.idbuf[3], command);
|
||||
@ -957,6 +1020,23 @@ void wd_fdc_device_base::interrupt_start()
|
||||
|
||||
LOGCOMMAND("cmd: forced interrupt (c=%02x)\n", command);
|
||||
|
||||
// If writing a byte to a sector, then wait until it's written before terminating
|
||||
// This behavior is required by the RM nimbus driver, otherwise the forced interrupt
|
||||
// at the end of a multiple sector write occasionally prevents the CRC byte being
|
||||
// written, causing the disk to be corrupted.
|
||||
if (/*((main_state == READ_SECTOR) && (cur_live.state == READ_SECTOR_DATA)) ||*/
|
||||
((main_state == WRITE_SECTOR) && (cur_live.state == WRITE_BYTE)))
|
||||
{
|
||||
delay_int = true;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
delay_int = false;
|
||||
}
|
||||
|
||||
//logerror("main_state=%s, cur_live.state=%s\n",states[main_state],states[cur_live.state]);
|
||||
|
||||
if(status & S_BUSY) {
|
||||
main_state = sub_state = cur_live.state = IDLE;
|
||||
cur_live.tm = attotime::never;
|
||||
@ -1229,6 +1309,8 @@ uint8_t wd_fdc_device_base::status_r()
|
||||
uint8_t val = status;
|
||||
if (inverted_bus) val ^= 0xff;
|
||||
|
||||
LOGCOMP("Status value: %02X\n",val);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
@ -1778,6 +1860,7 @@ void wd_fdc_device_base::live_run(attotime limit)
|
||||
if(cur_live.bit_counter == 16*6) {
|
||||
if(cur_live.crc) {
|
||||
status |= S_CRC;
|
||||
LOGCRC("CRC error in live_run\n");
|
||||
}
|
||||
|
||||
// Already synchronous
|
||||
@ -1901,8 +1984,15 @@ void wd_fdc_device_base::live_run(attotime limit)
|
||||
|
||||
} else if(slot < sector_size+2) {
|
||||
// CRC
|
||||
if(slot == sector_size+1) {
|
||||
live_delay(IDLE);
|
||||
if(slot == sector_size+1)
|
||||
{
|
||||
// act on delayed interrupt if active
|
||||
/* if (delay_int)
|
||||
{
|
||||
interrupt_start();
|
||||
return;
|
||||
}
|
||||
*/ live_delay(IDLE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -2117,6 +2207,13 @@ void wd_fdc_device_base::live_run(attotime limit)
|
||||
else {
|
||||
pll_stop_writing(floppy, cur_live.tm);
|
||||
cur_live.state = IDLE;
|
||||
|
||||
// Act on delayed interrupt if set.
|
||||
if (delay_int)
|
||||
{
|
||||
interrupt_start();
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2146,9 +2243,17 @@ void wd_fdc_device_base::live_run(attotime limit)
|
||||
live_write_mfm(cur_live.crc >> 8);
|
||||
else if(cur_live.byte_counter < sector_size + 16+3)
|
||||
live_write_mfm(0xff);
|
||||
// live_write_mfm(0x4e);
|
||||
else {
|
||||
pll_stop_writing(floppy, cur_live.tm);
|
||||
cur_live.state = IDLE;
|
||||
|
||||
// Act on delayed interrupt if set.
|
||||
if (delay_int)
|
||||
{
|
||||
interrupt_start();
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -2905,6 +3010,7 @@ wd2791_device::wd2791_device(const machine_config &mconfig, const char *tag, dev
|
||||
wd2793_device::wd2793_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : wd_fdc_analog_device_base(mconfig, WD2793, tag, owner, clock)
|
||||
{
|
||||
step_times = fd179x_step_times;
|
||||
|
||||
delay_register_commit = 16;
|
||||
delay_command_commit = 12;
|
||||
disable_mfm = false;
|
||||
|
@ -91,8 +91,7 @@ public:
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER(mr_w);
|
||||
|
||||
void index_callback(floppy_image_device *floppy, int state);
|
||||
|
||||
void index_callback(floppy_image_device *floppy, int state);
|
||||
protected:
|
||||
wd_fdc_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
@ -177,11 +176,11 @@ private:
|
||||
|
||||
enum {
|
||||
// General "doing nothing" state
|
||||
IDLE,
|
||||
IDLE,
|
||||
|
||||
// Main states - the commands
|
||||
RESTORE,
|
||||
SEEK,
|
||||
RESTORE,
|
||||
SEEK,
|
||||
STEP,
|
||||
READ_SECTOR,
|
||||
READ_TRACK,
|
||||
@ -242,6 +241,8 @@ private:
|
||||
WRITE_SECTOR_PRE_BYTE
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct live_info {
|
||||
enum { PT_NONE, PT_CRC_1, PT_CRC_2 };
|
||||
|
||||
@ -304,6 +305,8 @@ private:
|
||||
int format_last_byte_count;
|
||||
std::string format_description_string;
|
||||
|
||||
bool delay_int;
|
||||
|
||||
void delay_cycles(emu_timer *tm, int cycles);
|
||||
|
||||
// Device timer subfunctions
|
||||
|
@ -133,10 +133,11 @@ void rmnimbus_state::nimbus(machine_config &config)
|
||||
PALETTE(config, m_palette).set_entries(16);
|
||||
|
||||
/* Backing storage */
|
||||
WD2793(config, m_fdc, 1000000);
|
||||
WD2793(config, m_fdc, 2000000);
|
||||
m_fdc->set_force_ready(true);
|
||||
m_fdc->intrq_wr_callback().set(FUNC(rmnimbus_state::nimbus_fdc_intrq_w));
|
||||
m_fdc->drq_wr_callback().set(FUNC(rmnimbus_state::nimbus_fdc_drq_w));
|
||||
m_fdc->enmf_rd_callback().set(FUNC(rmnimbus_state::nimbus_fdc_enmf_r));
|
||||
FLOPPY_CONNECTOR(config, FDC_TAG":0", rmnimbus_floppies, "35dd", isa8_fdc_device::floppy_formats);
|
||||
FLOPPY_CONNECTOR(config, FDC_TAG":1", rmnimbus_floppies, "35dd", isa8_fdc_device::floppy_formats);
|
||||
|
||||
@ -210,6 +211,8 @@ void rmnimbus_state::nimbus(machine_config &config)
|
||||
msm5205.add_route(ALL_OUTPUTS, MONO_TAG, 0.75);
|
||||
|
||||
SOFTWARE_LIST(config, "disk_list").set_original("nimbus");
|
||||
|
||||
m_maincpu->set_dasm_override(FUNC(rmnimbus_state::dasm_override));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -88,10 +88,12 @@ public:
|
||||
void nimbus(machine_config &config);
|
||||
|
||||
uint32_t m_debug_machine;
|
||||
uint32_t m_debug_trap;
|
||||
|
||||
void decode_subbios(device_t *device, offs_t pc, uint8_t raw_flag);
|
||||
void decode_subbios(device_t *device, offs_t pc);
|
||||
void decode_subbios_return(device_t *device, offs_t pc);
|
||||
void decode_dos21(device_t *device, offs_t pc);
|
||||
|
||||
|
||||
private:
|
||||
required_device<i80186_cpu_device> m_maincpu;
|
||||
required_device<i8031_device> m_iocpu;
|
||||
@ -120,6 +122,7 @@ private:
|
||||
uint8_t m_iou_reg092;
|
||||
uint8_t m_last_playmode;
|
||||
uint8_t m_ay8910_a;
|
||||
uint8_t m_ay8910_b;
|
||||
uint16_t m_x, m_y, m_yline;
|
||||
uint8_t m_colours, m_mode, m_upmode;
|
||||
uint32_t m_debug_video;
|
||||
@ -131,7 +134,10 @@ private:
|
||||
void nimbus_mcu_w(uint8_t data);
|
||||
uint8_t scsi_r(offs_t offset);
|
||||
void scsi_w(offs_t offset, uint8_t data);
|
||||
uint8_t fdc_reg_r(offs_t offset);
|
||||
void fdc_reg_w(offs_t offset, uint8_t data);
|
||||
void fdc_ctl_w(uint8_t data);
|
||||
void nimbus_voice_w(offs_t offset, uint8_t data);
|
||||
uint8_t nimbus_pc8031_r(offs_t offset);
|
||||
void nimbus_pc8031_w(offs_t offset, uint8_t data);
|
||||
uint8_t nimbus_pc8031_iou_r(offs_t offset);
|
||||
@ -142,6 +148,9 @@ private:
|
||||
void nimbus_pc8031_port3_w(uint8_t data);
|
||||
uint8_t nimbus_iou_r(offs_t offset);
|
||||
void nimbus_iou_w(offs_t offset, uint8_t data);
|
||||
|
||||
uint8_t nimbus_rompack_r(offs_t offset);
|
||||
void nimbus_rompack_w(offs_t offset, uint8_t data);
|
||||
void nimbus_sound_ay8910_porta_w(uint8_t data);
|
||||
void nimbus_sound_ay8910_portb_w(uint8_t data);
|
||||
uint8_t nimbus_mouse_js_r();
|
||||
@ -156,6 +165,8 @@ private:
|
||||
DECLARE_WRITE_LINE_MEMBER(sio_interrupt);
|
||||
DECLARE_WRITE_LINE_MEMBER(nimbus_fdc_intrq_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(nimbus_fdc_drq_w);
|
||||
DECLARE_READ_LINE_MEMBER(nimbus_fdc_enmf_r);
|
||||
|
||||
void nimbus_via_write_portb(uint8_t data);
|
||||
DECLARE_WRITE_LINE_MEMBER(write_scsi_bsy);
|
||||
DECLARE_WRITE_LINE_MEMBER(write_scsi_cd);
|
||||
@ -189,8 +200,8 @@ private:
|
||||
void rmni_sound_reset();
|
||||
void mouse_js_reset();
|
||||
void check_scsi_irq();
|
||||
void set_scsi_drqlat(bool clock, bool clear);
|
||||
|
||||
void set_scsi_drqlat(bool clock, bool clear);
|
||||
|
||||
int m_scsi_iena;
|
||||
int m_scsi_msg;
|
||||
int m_scsi_bsy;
|
||||
@ -224,35 +235,40 @@ private:
|
||||
/* Mouse/Joystick */
|
||||
struct
|
||||
{
|
||||
int8_t m_mouse_x;
|
||||
int8_t m_mouse_y;
|
||||
int8_t m_mouse_x;
|
||||
int8_t m_mouse_y;
|
||||
|
||||
uint8_t m_mouse_pcx;
|
||||
uint8_t m_mouse_pcy;
|
||||
uint8_t m_mouse_pcx;
|
||||
uint8_t m_mouse_pcy;
|
||||
|
||||
uint8_t m_intstate_x;
|
||||
uint8_t m_intstate_y;
|
||||
uint8_t m_intstate_x;
|
||||
uint8_t m_intstate_y;
|
||||
|
||||
uint8_t m_reg0a4;
|
||||
uint8_t m_reg0a4;
|
||||
|
||||
emu_timer *m_mouse_timer;
|
||||
} m_nimbus_mouse;
|
||||
|
||||
bool m_voice_enabled;
|
||||
|
||||
void nimbus_io(address_map &map);
|
||||
void nimbus_iocpu_io(address_map &map);
|
||||
void nimbus_iocpu_mem(address_map &map);
|
||||
void nimbus_mem(address_map &map);
|
||||
|
||||
void decode_dssi_none(uint16_t ds, uint16_t si, uint8_t raw_flag);
|
||||
void decode_dssi_generic(uint16_t ds, uint16_t si, uint8_t raw_flag);
|
||||
void decode_dssi_f_fill_area(uint16_t ds, uint16_t si, uint8_t raw_flag);
|
||||
void decode_dssi_f_plot_character_string(uint16_t ds, uint16_t si, uint8_t raw_flag);
|
||||
void decode_dssi_f_set_new_clt(uint16_t ds, uint16_t si, uint8_t raw_flag);
|
||||
void decode_dssi_f_plonk_char(uint16_t ds, uint16_t si, uint8_t raw_flag);
|
||||
void decode_dssi_f_rw_sectors(uint16_t ds, uint16_t si, uint8_t raw_flag);
|
||||
|
||||
void decode_dssi_none(uint16_t ds, uint16_t si);
|
||||
void decode_dssi_generic(uint16_t ds, uint16_t si);
|
||||
void decode_dssi_f_fill_area(uint16_t ds, uint16_t si);
|
||||
void decode_dssi_f_plot_character_string(uint16_t ds, uint16_t si);
|
||||
void decode_dssi_f_set_new_clt(uint16_t ds, uint16_t si);
|
||||
void decode_dssi_f_plonk_char(uint16_t ds, uint16_t si);
|
||||
void decode_dssi_f_rw_sectors(uint16_t ds, uint16_t si);
|
||||
|
||||
void debug_command(const std::vector<std::string> ¶ms);
|
||||
void video_debug(const std::vector<std::string> ¶ms);
|
||||
offs_t dasm_override(std::ostream &stream, offs_t pc, const util::disasm_interface::data_buffer &opcodes, const util::disasm_interface::data_buffer ¶ms);
|
||||
|
||||
void do_mouse();
|
||||
};
|
||||
|
||||
#endif // MAME_INCLUDES_RMNIMBUS_H
|
||||
|
@ -109,16 +109,16 @@ chdman createhd -o ST125N.chd -chs 41921,1,1 -ss 512
|
||||
#define MOUSE_INT_ENABLE 0x08
|
||||
#define PC8031_INT_ENABLE 0x10
|
||||
|
||||
#define MOUSE_NONE 0x00
|
||||
#define MOUSE_LEFT 0x01
|
||||
#define MOUSE_RIGHT 0x02
|
||||
#define MOUSE_DOWN 0x04
|
||||
#define MOUSE_UP 0x08
|
||||
#define MOUSE_LBUTTON 0x10
|
||||
#define MOUSE_RBUTTON 0x20
|
||||
#define MOUSE_NONE 0x00
|
||||
#define MOUSE_LEFT 0x01
|
||||
#define MOUSE_RIGHT 0x02
|
||||
#define MOUSE_DOWN 0x04
|
||||
#define MOUSE_UP 0x08
|
||||
#define MOUSE_LBUTTON 0x10
|
||||
#define MOUSE_RBUTTON 0x20
|
||||
|
||||
// Frequency in Hz to poll for mouse movement.
|
||||
#define MOUSE_POLL_FREQUENCY 5000
|
||||
#define MOUSE_POLL_FREQUENCY 500
|
||||
|
||||
#define MOUSE_INT_ENABLED(state) (((state)->m_iou_reg092 & MOUSE_INT_ENABLE) ? 1 : 0)
|
||||
|
||||
@ -137,8 +137,8 @@ chdman createhd -o ST125N.chd -chs 41921,1,1 -ss 512
|
||||
|
||||
/* Debugging */
|
||||
|
||||
#define DEBUG_SET(flags) ((m_debug_machine & (flags))==(flags))
|
||||
#define DEBUG_SET_STATE(flags) ((state->m_debug_machine & (flags))==(flags))
|
||||
#define DEBUG_SET(flags) ((m_debug_machine & (flags))==(flags))
|
||||
#define DEBUG_SET_STATE(flags) ((state->m_debug_machine & (flags))==(flags))
|
||||
|
||||
#define DEBUG_NONE 0x0000000
|
||||
#define DECODE_BIOS 0x0000002
|
||||
@ -216,7 +216,7 @@ void rmnimbus_state::machine_reset()
|
||||
void rmnimbus_state::machine_start()
|
||||
{
|
||||
m_nimbus_mouse.m_mouse_timer=timer_alloc(TIMER_MOUSE);
|
||||
|
||||
|
||||
/* setup debug commands */
|
||||
if (machine().debug_flags & DEBUG_FLAG_ENABLED)
|
||||
{
|
||||
@ -228,7 +228,10 @@ void rmnimbus_state::machine_start()
|
||||
}
|
||||
|
||||
m_debug_machine=DEBUG_NONE;
|
||||
m_debug_trap=0;
|
||||
m_voice_enabled=false;
|
||||
m_fdc->dden_w(0);
|
||||
//m_fdc->overide_delays(64,m_fdc->get_cmd_delay());
|
||||
}
|
||||
|
||||
void rmnimbus_state::debug_command(const std::vector<std::string> ¶ms)
|
||||
@ -254,38 +257,59 @@ static int instruction_hook(device_t &device, offs_t curpc)
|
||||
{
|
||||
rmnimbus_state *state = device.machine().driver_data<rmnimbus_state>();
|
||||
address_space &space = device.memory().space(AS_PROGRAM);
|
||||
uint8_t *addr_ptr;
|
||||
|
||||
uint8_t *addr_ptr;
|
||||
uint8_t first;
|
||||
|
||||
addr_ptr = (uint8_t*)space.get_read_ptr(curpc);
|
||||
|
||||
if ((addr_ptr !=nullptr) && (addr_ptr[0]==0xCD))
|
||||
{
|
||||
if(DEBUG_SET_STATE(DECODE_BIOS) && (addr_ptr[1]==0xF0))
|
||||
{
|
||||
if(DEBUG_SET_STATE(DECODE_BIOS_RAW))
|
||||
state->decode_subbios(&device,curpc,1);
|
||||
else
|
||||
state->decode_subbios(&device,curpc,0);
|
||||
}
|
||||
first = (curpc & 0x01) ? 1 : 0;
|
||||
|
||||
if(DEBUG_SET_STATE(DECODE_DOS21) && (addr_ptr[1]==0x21))
|
||||
if(DEBUG_SET_STATE(DECODE_BIOS) && (curpc == state->m_debug_trap) && (0 != state->m_debug_trap))
|
||||
{
|
||||
state->decode_subbios_return(&device,curpc);
|
||||
}
|
||||
|
||||
if ((addr_ptr !=nullptr) && (addr_ptr[first]==0xCD))
|
||||
{
|
||||
if(DEBUG_SET_STATE(DECODE_BIOS) && (addr_ptr[first+1]==0xF0))
|
||||
state->decode_subbios(&device,curpc);
|
||||
|
||||
if(DEBUG_SET_STATE(DECODE_DOS21) && (addr_ptr[first+1]==0x21))
|
||||
state->decode_dos21(&device,curpc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rmnimbus_state::decode_subbios_return(device_t *device, offs_t pc)
|
||||
{
|
||||
uint16_t ax = m_maincpu->state_int(I8086_AX);
|
||||
uint16_t ds = m_maincpu->state_int(I8086_DS);
|
||||
uint16_t si = m_maincpu->state_int(I8086_SI);
|
||||
|
||||
if(!DEBUG_SET(DECODE_BIOS_RAW))
|
||||
{
|
||||
logerror("at %05X sub-bios return code : %04X\n",pc,ax);
|
||||
decode_dssi_generic(ds,si);
|
||||
logerror("=======================================================================\n");
|
||||
}
|
||||
else
|
||||
logerror("%05X :: %04X\n",pc,ax);
|
||||
|
||||
m_debug_trap=0;
|
||||
}
|
||||
|
||||
#define set_type(type_name) sprintf(type_str,type_name)
|
||||
#define set_drv(drv_name) sprintf(drv_str,drv_name)
|
||||
#define set_func(func_name) sprintf(func_str,func_name)
|
||||
|
||||
void rmnimbus_state::decode_subbios(device_t *device,offs_t pc, uint8_t raw_flag)
|
||||
void rmnimbus_state::decode_subbios(device_t *device,offs_t pc)
|
||||
{
|
||||
char type_str[80];
|
||||
char drv_str[80];
|
||||
char func_str[80];
|
||||
|
||||
void (rmnimbus_state::*dump_dssi)(uint16_t, uint16_t, uint8_t) = &rmnimbus_state::decode_dssi_none;
|
||||
void (rmnimbus_state::*dump_dssi)(uint16_t, uint16_t) = &rmnimbus_state::decode_dssi_none;
|
||||
|
||||
uint16_t ax = m_maincpu->state_int(I8086_AX);
|
||||
uint16_t bx = m_maincpu->state_int(I8086_BX);
|
||||
@ -293,12 +317,15 @@ void rmnimbus_state::decode_subbios(device_t *device,offs_t pc, uint8_t raw_flag
|
||||
uint16_t ds = m_maincpu->state_int(I8086_DS);
|
||||
uint16_t si = m_maincpu->state_int(I8086_SI);
|
||||
|
||||
// Set the address to trap after the sub-bios call.
|
||||
m_debug_trap=pc+2;
|
||||
|
||||
// *** TEMP Don't show f_enquire_display_line calls !
|
||||
if((cx==6) && (ax==43))
|
||||
return;
|
||||
// *** END TEMP
|
||||
|
||||
if(!raw_flag)
|
||||
if(!DEBUG_SET(DECODE_BIOS_RAW))
|
||||
{
|
||||
logerror("=======================================================================\n");
|
||||
logerror("Sub-bios call at %08X, AX=%04X, BX=%04X, CX=%04X, DS:SI=%04X:%04X\n",pc,ax,bx,cx,ds,si);
|
||||
@ -360,6 +387,8 @@ void rmnimbus_state::decode_subbios(device_t *device,offs_t pc, uint8_t raw_flag
|
||||
case 4 : set_drv("d_eeprom"); break;
|
||||
}
|
||||
|
||||
dump_dssi = &rmnimbus_state::decode_dssi_generic;
|
||||
|
||||
switch(ax)
|
||||
{
|
||||
case 0 : set_func("f_get_version_number"); break;
|
||||
@ -368,12 +397,11 @@ void rmnimbus_state::decode_subbios(device_t *device,offs_t pc, uint8_t raw_flag
|
||||
case 3 : set_func("f_get_device_status"); break;
|
||||
case 4 : set_func("f_read_n_sectors"); dump_dssi = &rmnimbus_state::decode_dssi_f_rw_sectors; break;
|
||||
case 5 : set_func("f_write_n_sectors"); dump_dssi = &rmnimbus_state::decode_dssi_f_rw_sectors; break;
|
||||
case 6 : set_func("f_verify_n_sectors"); break;
|
||||
case 6 : set_func("f_verify_n_sectors"); dump_dssi = &rmnimbus_state::decode_dssi_f_rw_sectors; break;
|
||||
case 7 : set_func("f_media_check"); break;
|
||||
case 8 : set_func("f_recalibrate"); break;
|
||||
case 9 : set_func("f_motors_off"); break;
|
||||
}
|
||||
dump_dssi = &rmnimbus_state::decode_dssi_f_rw_sectors;
|
||||
|
||||
}; break;
|
||||
|
||||
@ -602,43 +630,42 @@ void rmnimbus_state::decode_subbios(device_t *device,offs_t pc, uint8_t raw_flag
|
||||
}; break;
|
||||
}
|
||||
|
||||
if(raw_flag)
|
||||
if(DEBUG_SET(DECODE_BIOS_RAW))
|
||||
{
|
||||
(this->*dump_dssi)(ds, si, raw_flag);
|
||||
(this->*dump_dssi)(ds, si);
|
||||
}
|
||||
else
|
||||
{
|
||||
logerror("Type=%s, Driver=%s, Function=%s\n",type_str,drv_str,func_str);
|
||||
|
||||
(this->*dump_dssi)(ds, si, raw_flag);
|
||||
(this->*dump_dssi)(ds, si);
|
||||
logerror("=======================================================================\n");
|
||||
}
|
||||
}
|
||||
|
||||
static inline void *get_dssi_ptr(address_space &space, uint16_t ds, uint16_t si)
|
||||
static inline void *get_regpair_ptr(address_space &space, uint16_t segment, uint16_t offset)
|
||||
{
|
||||
int addr;
|
||||
|
||||
addr=((ds<<4)+si);
|
||||
// OUTPUT_SEGOFS("DS:SI",ds,si);
|
||||
addr=((segment<<4)+offset);
|
||||
|
||||
return space.get_read_ptr(addr);
|
||||
}
|
||||
|
||||
void rmnimbus_state::decode_dssi_none(uint16_t ds, uint16_t si, uint8_t raw_flag)
|
||||
void rmnimbus_state::decode_dssi_none(uint16_t ds, uint16_t si)
|
||||
{
|
||||
}
|
||||
|
||||
void rmnimbus_state::decode_dssi_generic(uint16_t ds, uint16_t si, uint8_t raw_flag)
|
||||
void rmnimbus_state::decode_dssi_generic(uint16_t ds, uint16_t si)
|
||||
{
|
||||
address_space &space = m_maincpu->space(AS_PROGRAM);
|
||||
uint16_t *params;
|
||||
int count;
|
||||
|
||||
if(raw_flag)
|
||||
if(DEBUG_SET(DECODE_BIOS_RAW))
|
||||
return;
|
||||
|
||||
params=(uint16_t *)get_dssi_ptr(space,ds,si);
|
||||
params=(uint16_t *)get_regpair_ptr(space,ds,si);
|
||||
|
||||
for(count=0; count<10; count++)
|
||||
logerror("%04X ",params[count]);
|
||||
@ -647,7 +674,7 @@ void rmnimbus_state::decode_dssi_generic(uint16_t ds, uint16_t si, uint8_t raw_f
|
||||
}
|
||||
|
||||
|
||||
void rmnimbus_state::decode_dssi_f_fill_area(uint16_t ds, uint16_t si, uint8_t raw_flag)
|
||||
void rmnimbus_state::decode_dssi_f_fill_area(uint16_t ds, uint16_t si)
|
||||
{
|
||||
address_space &space = m_maincpu->space(AS_PROGRAM);
|
||||
|
||||
@ -656,14 +683,14 @@ void rmnimbus_state::decode_dssi_f_fill_area(uint16_t ds, uint16_t si, uint8_t r
|
||||
t_nimbus_brush *brush;
|
||||
int cocount;
|
||||
|
||||
area_params = (t_area_params *)get_dssi_ptr(space,ds,si);
|
||||
area_params = (t_area_params *)get_regpair_ptr(space,ds,si);
|
||||
|
||||
if (!raw_flag)
|
||||
if (!DEBUG_SET(DECODE_BIOS_RAW))
|
||||
OUTPUT_SEGOFS("SegBrush:OfsBrush",area_params->seg_brush,area_params->ofs_brush);
|
||||
|
||||
brush=(t_nimbus_brush *)space.get_read_ptr(LINEAR_ADDR(area_params->seg_brush,area_params->ofs_brush));
|
||||
|
||||
if(raw_flag)
|
||||
if(DEBUG_SET(DECODE_BIOS_RAW))
|
||||
{
|
||||
logerror("\tdw\t%04X, %04X, %04X, %04X, %04X, %04X, %04X, %04X, %04X, ",
|
||||
brush->style,brush->style_index,brush->colour1,brush->colour2,
|
||||
@ -685,7 +712,7 @@ void rmnimbus_state::decode_dssi_f_fill_area(uint16_t ds, uint16_t si, uint8_t r
|
||||
addr_ptr = (uint16_t *)space.get_read_ptr(LINEAR_ADDR(area_params->seg_data,area_params->ofs_data));
|
||||
for(cocount=0; cocount < area_params->count; cocount++)
|
||||
{
|
||||
if(raw_flag)
|
||||
if(DEBUG_SET(DECODE_BIOS_RAW))
|
||||
{
|
||||
if(cocount!=(area_params->count-1))
|
||||
logerror("%04X, %04X, ",addr_ptr[cocount*2],addr_ptr[(cocount*2)+1]);
|
||||
@ -696,11 +723,11 @@ void rmnimbus_state::decode_dssi_f_fill_area(uint16_t ds, uint16_t si, uint8_t r
|
||||
logerror("x=%d y=%d\n",addr_ptr[cocount*2],addr_ptr[(cocount*2)+1]);
|
||||
}
|
||||
|
||||
if(raw_flag)
|
||||
if(DEBUG_SET(DECODE_BIOS_RAW))
|
||||
logerror("\n");
|
||||
}
|
||||
|
||||
void rmnimbus_state::decode_dssi_f_plot_character_string(uint16_t ds, uint16_t si, uint8_t raw_flag)
|
||||
void rmnimbus_state::decode_dssi_f_plot_character_string(uint16_t ds, uint16_t si)
|
||||
{
|
||||
address_space &space = m_maincpu->space(AS_PROGRAM);
|
||||
|
||||
@ -708,10 +735,10 @@ void rmnimbus_state::decode_dssi_f_plot_character_string(uint16_t ds, uint16_t s
|
||||
t_plot_string_params *plot_string_params;
|
||||
int charno;
|
||||
|
||||
if(raw_flag)
|
||||
if(DEBUG_SET(DECODE_BIOS_RAW))
|
||||
return;
|
||||
|
||||
plot_string_params=(t_plot_string_params *)get_dssi_ptr(space,ds,si);
|
||||
plot_string_params=(t_plot_string_params *)get_regpair_ptr(space,ds,si);
|
||||
|
||||
OUTPUT_SEGOFS("SegFont:OfsFont",plot_string_params->seg_font,plot_string_params->ofs_font);
|
||||
OUTPUT_SEGOFS("SegData:OfsData",plot_string_params->seg_data,plot_string_params->ofs_data);
|
||||
@ -729,14 +756,14 @@ void rmnimbus_state::decode_dssi_f_plot_character_string(uint16_t ds, uint16_t s
|
||||
logerror("\n");
|
||||
}
|
||||
|
||||
void rmnimbus_state::decode_dssi_f_set_new_clt(uint16_t ds, uint16_t si, uint8_t raw_flag)
|
||||
void rmnimbus_state::decode_dssi_f_set_new_clt(uint16_t ds, uint16_t si)
|
||||
{
|
||||
address_space &space = m_maincpu->space(AS_PROGRAM);
|
||||
uint16_t *new_colours;
|
||||
int colour;
|
||||
new_colours=(uint16_t *)get_dssi_ptr(space,ds,si);
|
||||
new_colours=(uint16_t *)get_regpair_ptr(space,ds,si);
|
||||
|
||||
if(raw_flag)
|
||||
if(DEBUG_SET(DECODE_BIOS_RAW))
|
||||
return;
|
||||
|
||||
OUTPUT_SEGOFS("SegColours:OfsColours",ds,si);
|
||||
@ -746,13 +773,13 @@ void rmnimbus_state::decode_dssi_f_set_new_clt(uint16_t ds, uint16_t si, uint8_t
|
||||
|
||||
}
|
||||
|
||||
void rmnimbus_state::decode_dssi_f_plonk_char(uint16_t ds, uint16_t si, uint8_t raw_flag)
|
||||
void rmnimbus_state::decode_dssi_f_plonk_char(uint16_t ds, uint16_t si)
|
||||
{
|
||||
address_space &space = m_maincpu->space(AS_PROGRAM);
|
||||
uint16_t *params;
|
||||
params=(uint16_t *)get_dssi_ptr(space,ds,si);
|
||||
params=(uint16_t *)get_regpair_ptr(space,ds,si);
|
||||
|
||||
if(raw_flag)
|
||||
if(DEBUG_SET(DECODE_BIOS_RAW))
|
||||
return;
|
||||
|
||||
OUTPUT_SEGOFS("SegParams:OfsParams",ds,si);
|
||||
@ -760,17 +787,25 @@ void rmnimbus_state::decode_dssi_f_plonk_char(uint16_t ds, uint16_t si, uint8_t
|
||||
logerror("plonked_char=%c\n",params[0]);
|
||||
}
|
||||
|
||||
void rmnimbus_state::decode_dssi_f_rw_sectors(uint16_t ds, uint16_t si, uint8_t raw_flag)
|
||||
void rmnimbus_state::decode_dssi_f_rw_sectors(uint16_t ds, uint16_t si)
|
||||
{
|
||||
address_space &space = m_maincpu->space(AS_PROGRAM);
|
||||
uint16_t *params;
|
||||
int param_no;
|
||||
|
||||
if(raw_flag)
|
||||
if(DEBUG_SET(DECODE_BIOS_RAW))
|
||||
return;
|
||||
|
||||
params=(uint16_t *)get_dssi_ptr(space,ds,si);
|
||||
params=(uint16_t *)get_regpair_ptr(space,ds,si);
|
||||
|
||||
logerror("unitno=%04X, count=%02X, first_sector=%08X buffer=%04X:%04X (%05X)\n",
|
||||
params[0],
|
||||
params[1],
|
||||
((params[3] * 65536)+params[2]),
|
||||
params[5],params[4],
|
||||
((params[5]*16)+params[4])
|
||||
);
|
||||
|
||||
for(param_no=0;param_no<16;param_no++)
|
||||
logerror("%04X ",params[param_no]);
|
||||
|
||||
@ -779,6 +814,10 @@ void rmnimbus_state::decode_dssi_f_rw_sectors(uint16_t ds, uint16_t si, uint8_t
|
||||
|
||||
void rmnimbus_state::decode_dos21(device_t *device,offs_t pc)
|
||||
{
|
||||
address_space &space = m_maincpu->space(AS_PROGRAM);
|
||||
//uint16_t *params;
|
||||
char *path;
|
||||
|
||||
uint16_t ax = m_maincpu->state_int(I8086_AX);
|
||||
uint16_t bx = m_maincpu->state_int(I8086_BX);
|
||||
uint16_t cx = m_maincpu->state_int(I8086_CX);
|
||||
@ -791,6 +830,8 @@ void rmnimbus_state::decode_dos21(device_t *device,offs_t pc)
|
||||
uint16_t si = m_maincpu->state_int(I8086_SI);
|
||||
uint16_t di = m_maincpu->state_int(I8086_DI);
|
||||
uint16_t bp = m_maincpu->state_int(I8086_BP);
|
||||
|
||||
uint8_t dosfn = ax >> 8; // Dos function is AH, upper half of AX.
|
||||
|
||||
logerror("=======================================================================\n");
|
||||
logerror("DOS Int 0x21 call at %05X\n",pc);
|
||||
@ -798,8 +839,71 @@ void rmnimbus_state::decode_dos21(device_t *device,offs_t pc)
|
||||
logerror("CS=%04X, DS=%04X, ES=%04X, SS=%04X\n",cs,ds,es,ss);
|
||||
logerror("SI=%04X, DI=%04X, BP=%04X\n",si,di,bp);
|
||||
logerror("=======================================================================\n");
|
||||
|
||||
if (((dosfn >= 0x39) && (dosfn <= 0x3d))
|
||||
|| (0x43 == dosfn)
|
||||
|| (0x4e == dosfn)
|
||||
|| (0x56 == dosfn)
|
||||
|| ((dosfn >= 0x5a) && (dosfn <= 0x5b)) )
|
||||
{
|
||||
path=(char *)get_regpair_ptr(space,ds,dx);
|
||||
logerror("Path at DS:DX=%s\n",path);
|
||||
|
||||
if (0x56 == dosfn)
|
||||
{
|
||||
path=(char *)get_regpair_ptr(space,es,di);
|
||||
logerror("Path at ES:DI=%s\n",path);
|
||||
}
|
||||
logerror("=======================================================================\n");
|
||||
}
|
||||
}
|
||||
|
||||
#define CBUFLEN 32
|
||||
|
||||
offs_t rmnimbus_state::dasm_override(std::ostream &stream, offs_t pc, const util::disasm_interface::data_buffer &opcodes, const util::disasm_interface::data_buffer ¶ms)
|
||||
{
|
||||
unsigned call;
|
||||
char callname[CBUFLEN];
|
||||
offs_t result = 0;
|
||||
|
||||
// decode and document (some) INT XX calls
|
||||
if (opcodes.r8(pc) == 0xCD)
|
||||
{
|
||||
call = opcodes.r8(pc+1);
|
||||
switch (call)
|
||||
{
|
||||
case 0x20 :
|
||||
strcpy(callname, "(dos terminate)");
|
||||
break;
|
||||
|
||||
case 0x21 :
|
||||
strcpy(callname, "(dos function)");
|
||||
break;
|
||||
|
||||
case 0xf0 :
|
||||
strcpy(callname, "(sub_bios)");
|
||||
break;
|
||||
|
||||
case 0xf3 :
|
||||
strcpy(callname, "(dispatch handler)");
|
||||
break;
|
||||
|
||||
case 0xf5 :
|
||||
strcpy(callname, "(event handler)");
|
||||
break;
|
||||
|
||||
case 0xf6 :
|
||||
strcpy(callname, "(resource message)");
|
||||
break;
|
||||
|
||||
default :
|
||||
strcpy(callname, "");
|
||||
}
|
||||
util::stream_format(stream, "int %02xh %s",call,callname);
|
||||
result = 2;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
The Nimbus has 3 banks of memory each of which can be either 16x4164 or 16x41256 giving
|
||||
@ -1021,6 +1125,11 @@ WRITE_LINE_MEMBER(rmnimbus_state::nimbus_fdc_drq_w)
|
||||
m_maincpu->drq1_w(state && FDC_DRQ_ENABLED());
|
||||
}
|
||||
|
||||
READ_LINE_MEMBER(rmnimbus_state::nimbus_fdc_enmf_r)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t rmnimbus_state::fdc_driveno(uint8_t drivesel)
|
||||
{
|
||||
switch (drivesel)
|
||||
@ -1073,7 +1182,7 @@ uint8_t rmnimbus_state::scsi_r(offs_t offset)
|
||||
{
|
||||
result |= FDC_MOTOR() << 2;
|
||||
result |= (!floppy->idx_r()) << 1;
|
||||
result |= floppy->ready_r() << 0;
|
||||
result |= (floppy->dskchg_r()) << 0;
|
||||
}
|
||||
break;
|
||||
case 0x08 :
|
||||
@ -1107,7 +1216,7 @@ void rmnimbus_state::fdc_ctl_w(uint8_t data)
|
||||
uint8_t old_drq = m_nimbus_drives.reg400 & HDC_DRQ_MASK;
|
||||
char drive[5];
|
||||
floppy_image_device *floppy;
|
||||
|
||||
|
||||
m_nimbus_drives.reg400 = data;
|
||||
|
||||
sprintf(drive, "%d", FDC_DRIVE());
|
||||
@ -1163,14 +1272,14 @@ void rmnimbus_state::hdc_reset()
|
||||
m_scsi_req = 0;
|
||||
|
||||
// Latched req, IC11b
|
||||
m_scsi_reqlat = 0;
|
||||
m_scsi_reqlat = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
The SCSI code outputs a 1 to indicate an active line, even though it is active low
|
||||
The inputs on the RM schematic are fed through inverters, but because of the above
|
||||
we don't need to invert them, unless the schematic uses the signal directly
|
||||
For consistency we will invert msg before latching.
|
||||
/*
|
||||
The SCSI code outputs a 1 to indicate an active line, even though it is active low
|
||||
The inputs on the RM schematic are fed through inverters, but because of the above
|
||||
we don't need to invert them, unless the schematic uses the signal directly
|
||||
For consistency we will invert msg before latching.
|
||||
*/
|
||||
|
||||
void rmnimbus_state::check_scsi_irq()
|
||||
@ -1185,13 +1294,13 @@ WRITE_LINE_MEMBER(rmnimbus_state::write_scsi_iena)
|
||||
}
|
||||
|
||||
// This emulates the 74LS74 latched version of req
|
||||
void rmnimbus_state::set_scsi_drqlat(bool clock, bool clear)
|
||||
{
|
||||
void rmnimbus_state::set_scsi_drqlat(bool clock, bool clear)
|
||||
{
|
||||
if (clear)
|
||||
m_scsi_reqlat = 0;
|
||||
else if (clock)
|
||||
m_scsi_reqlat = 1;
|
||||
|
||||
|
||||
if(m_scsi_reqlat)
|
||||
hdc_drq(true);
|
||||
else
|
||||
@ -1202,9 +1311,9 @@ void rmnimbus_state::hdc_post_rw()
|
||||
{
|
||||
if(m_scsi_req)
|
||||
m_scsibus->write_ack(1);
|
||||
|
||||
|
||||
// IC17A, IC17B, latched req cleared by SCSI data read or write, or C/D= command
|
||||
set_scsi_drqlat(false, true);
|
||||
set_scsi_drqlat(false, true);
|
||||
}
|
||||
|
||||
void rmnimbus_state::hdc_drq(bool state)
|
||||
@ -1220,10 +1329,10 @@ WRITE_LINE_MEMBER( rmnimbus_state::write_scsi_bsy )
|
||||
WRITE_LINE_MEMBER( rmnimbus_state::write_scsi_cd )
|
||||
{
|
||||
m_scsi_cd = state;
|
||||
|
||||
|
||||
// IC17A, IC17B, latched req cleared by SCSI data read or write, or C/D= command
|
||||
set_scsi_drqlat(false, !m_scsi_cd);
|
||||
|
||||
|
||||
check_scsi_irq();
|
||||
}
|
||||
|
||||
@ -1247,19 +1356,27 @@ WRITE_LINE_MEMBER( rmnimbus_state::write_scsi_req )
|
||||
{
|
||||
// Detect rising edge on req, IC11b, clock
|
||||
int rising = ((m_scsi_req == 0) && (state == 1));
|
||||
|
||||
|
||||
// This is the state of the actual line from the SCSI
|
||||
m_scsi_req = state;
|
||||
|
||||
|
||||
// Latched req, is forced low by C/D being set to command
|
||||
set_scsi_drqlat(rising, m_scsi_cd);
|
||||
|
||||
|
||||
if (!m_scsi_reqlat)
|
||||
m_scsibus->write_ack(0);
|
||||
|
||||
|
||||
check_scsi_irq();
|
||||
}
|
||||
|
||||
void rmnimbus_state::nimbus_voice_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
if (offset == 0xB0)
|
||||
m_voice_enabled = true;
|
||||
else if (offset == 0xB2)
|
||||
m_voice_enabled = false;
|
||||
}
|
||||
|
||||
/* 8031/8051 Peripheral controller 80186 side */
|
||||
|
||||
void rmnimbus_state::pc8031_reset()
|
||||
@ -1485,6 +1602,20 @@ void rmnimbus_state::iou_reset()
|
||||
m_eeprom_state = 0;
|
||||
}
|
||||
|
||||
/* Rompacks, not completely implemented */
|
||||
|
||||
uint8_t rmnimbus_state::nimbus_rompack_r(offs_t offset)
|
||||
{
|
||||
logerror("Rompack read offset %02X, rompack address=%04X\n",offset,(m_ay8910_b*256)+m_ay8910_a);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rmnimbus_state::nimbus_rompack_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
logerror("Rompack write offset %02X, data=%02X, rompack address=%04X\n",offset,data,(m_ay8910_b*256)+m_ay8910_a);
|
||||
}
|
||||
|
||||
/*
|
||||
Sound hardware : AY8910
|
||||
|
||||
@ -1507,6 +1638,7 @@ void rmnimbus_state::rmni_sound_reset()
|
||||
m_msm->playmode_w(m_last_playmode);
|
||||
|
||||
m_ay8910_a=0;
|
||||
m_ay8910_b=0;
|
||||
}
|
||||
|
||||
void rmnimbus_state::nimbus_sound_ay8910_porta_w(uint8_t data)
|
||||
@ -1514,16 +1646,21 @@ void rmnimbus_state::nimbus_sound_ay8910_porta_w(uint8_t data)
|
||||
m_msm->data_w(data);
|
||||
|
||||
// Mouse code needs a copy of this.
|
||||
// ROMpack lower address lines
|
||||
m_ay8910_a=data;
|
||||
}
|
||||
|
||||
void rmnimbus_state::nimbus_sound_ay8910_portb_w(uint8_t data)
|
||||
{
|
||||
if ((data & 0x07) != m_last_playmode)
|
||||
// Only update msm5205 if voice is enabled.....
|
||||
if (m_voice_enabled && ((data & 0x07) != m_last_playmode))
|
||||
{
|
||||
m_last_playmode = (data & 0x07);
|
||||
m_msm->playmode_w(m_last_playmode);
|
||||
}
|
||||
|
||||
// ROMpack upper address lines
|
||||
m_ay8910_b=data;
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(rmnimbus_state::nimbus_msm5205_vck)
|
||||
@ -1532,60 +1669,54 @@ WRITE_LINE_MEMBER(rmnimbus_state::nimbus_msm5205_vck)
|
||||
external_int(EXTERNAL_INT_MSM5205,state);
|
||||
}
|
||||
|
||||
void rmnimbus_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
|
||||
{
|
||||
switch(id)
|
||||
{
|
||||
case TIMER_MOUSE : do_mouse(); break;
|
||||
}
|
||||
}
|
||||
|
||||
static const int MOUSE_XYA[4] = { 1, 1, 0, 0 };
|
||||
static const int MOUSE_XYB[4] = { 0, 1, 1, 0 };
|
||||
|
||||
void rmnimbus_state::mouse_js_reset()
|
||||
void rmnimbus_state::do_mouse()
|
||||
{
|
||||
m_nimbus_mouse.m_mouse_x=128;
|
||||
m_nimbus_mouse.m_mouse_y=128;
|
||||
m_nimbus_mouse.m_mouse_pcx=0;
|
||||
m_nimbus_mouse.m_mouse_pcy=0;
|
||||
m_nimbus_mouse.m_intstate_x=0;
|
||||
m_nimbus_mouse.m_intstate_y=0;
|
||||
m_nimbus_mouse.m_reg0a4=0xC0;
|
||||
|
||||
// Setup timer to poll the mouse
|
||||
m_nimbus_mouse.m_mouse_timer->adjust(attotime::zero, 0, attotime::from_hz(MOUSE_POLL_FREQUENCY));
|
||||
}
|
||||
|
||||
void rmnimbus_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
|
||||
{
|
||||
int mouse_x = 0; // Current mouse X and Y
|
||||
int mouse_y = 0;
|
||||
int xdiff = 0; // Difference from previous X and Y
|
||||
int ydiff = 0;
|
||||
|
||||
uint8_t intstate_x; // Used to calculate if we should trigger interrupt
|
||||
uint8_t intstate_y;
|
||||
int xint; // X and Y interrupts to trigger
|
||||
int mouse_x = 0; // Current mouse X and Y
|
||||
int mouse_y = 0;
|
||||
int xdiff = 0; // Difference from previous X and Y
|
||||
int ydiff = 0;
|
||||
|
||||
uint8_t intstate_x; // Used to calculate if we should trigger interrupt
|
||||
uint8_t intstate_y;
|
||||
int xint; // X and Y interrupts to trigger
|
||||
int yint;
|
||||
|
||||
uint8_t mxa; // Values of quadrature encoders for X and Y
|
||||
uint8_t mxa; // Values of quadrature encoders for X and Y
|
||||
uint8_t mxb;
|
||||
uint8_t mya;
|
||||
uint8_t myb;
|
||||
|
||||
// Read mouse buttons
|
||||
m_nimbus_mouse.m_reg0a4 = m_io_mouse_button->read();
|
||||
|
||||
|
||||
// Read mose positions and calculate difference from previous value
|
||||
mouse_x = m_io_mousex->read();
|
||||
mouse_y = m_io_mousey->read();
|
||||
|
||||
xdiff = m_nimbus_mouse.m_mouse_x - mouse_x;
|
||||
ydiff = m_nimbus_mouse.m_mouse_y - mouse_y;
|
||||
|
||||
|
||||
// check and compensate for wrap.....
|
||||
if (xdiff > 0x80)
|
||||
if (xdiff > 0x80)
|
||||
xdiff -= 0x100;
|
||||
else if (xdiff < -0x80)
|
||||
xdiff += 0x100;
|
||||
|
||||
if (ydiff > 0x80)
|
||||
if (ydiff > 0x80)
|
||||
ydiff -= 0x100;
|
||||
else if (ydiff < -0x80)
|
||||
ydiff += 0x100;
|
||||
ydiff += 0x100;
|
||||
|
||||
// convert movement into emulated movement of quadrature encoder in mouse.
|
||||
if (xdiff < 0)
|
||||
@ -1597,7 +1728,7 @@ void rmnimbus_state::device_timer(emu_timer &timer, device_timer_id id, int para
|
||||
m_nimbus_mouse.m_mouse_pcy++;
|
||||
else if (ydiff > 0)
|
||||
m_nimbus_mouse.m_mouse_pcy--;
|
||||
|
||||
|
||||
// Compensate for quadrature wrap.
|
||||
m_nimbus_mouse.m_mouse_pcx &= 0x03;
|
||||
m_nimbus_mouse.m_mouse_pcy &= 0x03;
|
||||
@ -1648,6 +1779,20 @@ void rmnimbus_state::device_timer(emu_timer &timer, device_timer_id id, int para
|
||||
m_nimbus_mouse.m_intstate_y=intstate_y;
|
||||
}
|
||||
|
||||
void rmnimbus_state::mouse_js_reset()
|
||||
{
|
||||
m_nimbus_mouse.m_mouse_x=128;
|
||||
m_nimbus_mouse.m_mouse_y=128;
|
||||
m_nimbus_mouse.m_mouse_pcx=0;
|
||||
m_nimbus_mouse.m_mouse_pcy=0;
|
||||
m_nimbus_mouse.m_intstate_x=0;
|
||||
m_nimbus_mouse.m_intstate_y=0;
|
||||
m_nimbus_mouse.m_reg0a4=0xC0;
|
||||
|
||||
// Setup timer to poll the mouse
|
||||
m_nimbus_mouse.m_mouse_timer->adjust(attotime::zero, 0, attotime::from_hz(MOUSE_POLL_FREQUENCY));
|
||||
}
|
||||
|
||||
uint8_t rmnimbus_state::nimbus_mouse_js_r()
|
||||
{
|
||||
/*
|
||||
|
@ -22,10 +22,10 @@
|
||||
operation by disassembling the Nimbus bios and by writing experemental
|
||||
code on the real machine.
|
||||
|
||||
2021-09-29, P.Harvey-Smith.
|
||||
|
||||
I now have access to the service manual for the Nimbus, this documents to facilities provided
|
||||
by the video chip, which will hopefully allow a much more accurate implementation.
|
||||
2021-09-29, P.Harvey-Smith.
|
||||
|
||||
I now have access to the service manual for the Nimbus, this documents to facilities provided
|
||||
by the video chip, which will hopefully allow a much more accurate implementation.
|
||||
*/
|
||||
|
||||
#include "emu.h"
|
||||
@ -36,92 +36,92 @@
|
||||
|
||||
#include <functional>
|
||||
|
||||
/*
|
||||
Acording to the service manual the Nimbus should be capable of the following modes :
|
||||
|
||||
320 x 200 4bpp
|
||||
640 x 200 2bpp
|
||||
400 x 200 4bpp
|
||||
800 x 200 2bpp
|
||||
320 x 250 4bpp
|
||||
640 x 250 2bpp
|
||||
400 x 250 4bpp
|
||||
800 x 250 2bpp
|
||||
*/
|
||||
|
||||
/*
|
||||
From the service manual the registers are defined as follows :
|
||||
/*
|
||||
Acording to the service manual the Nimbus should be capable of the following modes :
|
||||
|
||||
320 x 200 4bpp
|
||||
640 x 200 2bpp
|
||||
400 x 200 4bpp
|
||||
800 x 200 2bpp
|
||||
320 x 250 4bpp
|
||||
640 x 250 2bpp
|
||||
400 x 250 4bpp
|
||||
800 x 250 2bpp
|
||||
*/
|
||||
|
||||
/*
|
||||
From the service manual the registers are defined as follows :
|
||||
|
||||
Ports 0x00-0x1E are the registers used to update the display RAM thus :
|
||||
|
||||
Addr m_x m_y Update memory on write?
|
||||
0x00 nop nop no
|
||||
0x02 load nop no
|
||||
0x04 nop inc no
|
||||
0x06 load inc no
|
||||
0x08 nop nop no
|
||||
0x0A inc nop no
|
||||
0x0C nop load no
|
||||
0x0E inc load no
|
||||
0x10 nop nop yes
|
||||
0x12 load nop yes
|
||||
0x14 nop inc yes
|
||||
0x16 load inc yes
|
||||
0x18 nop nop yes
|
||||
0x1A inc nop yes
|
||||
0x1C nop load yes
|
||||
0x1E inc load yes
|
||||
Addr m_x m_y Update memory on write?
|
||||
0x00 nop nop no
|
||||
0x02 load nop no
|
||||
0x04 nop inc no
|
||||
0x06 load inc no
|
||||
0x08 nop nop no
|
||||
0x0A inc nop no
|
||||
0x0C nop load no
|
||||
0x0E inc load no
|
||||
0x10 nop nop yes
|
||||
0x12 load nop yes
|
||||
0x14 nop inc yes
|
||||
0x16 load inc yes
|
||||
0x18 nop nop yes
|
||||
0x1A inc nop yes
|
||||
0x1C nop load yes
|
||||
0x1E inc load yes
|
||||
|
||||
0x20 scroll port, contains 8 bit scroll address
|
||||
0x20 scroll port, contains 8 bit scroll address
|
||||
|
||||
0x22 Update mode control port (up_mode), controls how data is written to display ram.
|
||||
see UPMODE_ constants below
|
||||
|
||||
0x24h Intensity port, provides current logical intensities for update operations
|
||||
bits 0..3 Foreground
|
||||
bits 4..7 Background
|
||||
|
||||
0x26 Display mode (m_mode) current display mode and border colour.
|
||||
see MODE_ constants below
|
||||
0x22 Update mode control port (up_mode), controls how data is written to display ram.
|
||||
see UPMODE_ constants below
|
||||
|
||||
0x24h Intensity port, provides current logical intensities for update operations
|
||||
bits 0..3 Foreground
|
||||
bits 4..7 Background
|
||||
|
||||
0x26 Display mode (m_mode) current display mode and border colour.
|
||||
see MODE_ constants below
|
||||
|
||||
For READ.
|
||||
Ports 0x28, 0x2A, 0x2C and 0x2E have different read and write functions :
|
||||
|
||||
0x28 Timing / status, all bits active high
|
||||
bit 0 line blank
|
||||
bit 1 line display
|
||||
bit 2 frame blank
|
||||
bit 3 frame display
|
||||
0x28 Timing / status, all bits active high
|
||||
bit 0 line blank
|
||||
bit 1 line display
|
||||
bit 2 frame blank
|
||||
bit 3 frame display
|
||||
|
||||
0x2A X address status, returns current value of X counter (m_x)
|
||||
|
||||
0x2A X address status, returns current value of X counter (m_x)
|
||||
|
||||
0x2C Y address status, returns current value of Y counter (m_y)
|
||||
0x2C Y address status, returns current value of Y counter (m_y)
|
||||
|
||||
For Write
|
||||
|
||||
0x28, 0x2A, 0x2C, 0x2E Colour look up table :
|
||||
|
||||
Logic colour
|
||||
Port Bits Low res High Res
|
||||
0x28 0..3 0 0
|
||||
0x28 4..7 1 0
|
||||
0x28 8..11 2 0
|
||||
0x28 12..15 3 0
|
||||
Logic colour
|
||||
Port Bits Low res High Res
|
||||
0x28 0..3 0 0
|
||||
0x28 4..7 1 0
|
||||
0x28 8..11 2 0
|
||||
0x28 12..15 3 0
|
||||
|
||||
0x2A 0..3 3 1
|
||||
0x2A 4..7 5 1
|
||||
0x2A 8..11 6 1
|
||||
0x2A 12..15 7 1
|
||||
0x2A 0..3 3 1
|
||||
0x2A 4..7 5 1
|
||||
0x2A 8..11 6 1
|
||||
0x2A 12..15 7 1
|
||||
|
||||
0x2C 0..3 8 2
|
||||
0x2C 4..7 9 2
|
||||
0x2C 8..11 10 2
|
||||
0x2C 12..15 11 2
|
||||
0x2C 0..3 8 2
|
||||
0x2C 4..7 9 2
|
||||
0x2C 8..11 10 2
|
||||
0x2C 12..15 11 2
|
||||
|
||||
0x2E 0..3 12 3
|
||||
0x2E 4..7 13 3
|
||||
0x2E 8..11 14 3
|
||||
0x2E 12..15 15 3
|
||||
0x2E 0..3 12 3
|
||||
0x2E 4..7 13 3
|
||||
0x2E 8..11 14 3
|
||||
0x2E 12..15 15 3
|
||||
|
||||
|
||||
*/
|
||||
@ -129,47 +129,47 @@ Port Bits Low res High Res
|
||||
// In following definitions ports are the WORD offset, the RM manual
|
||||
// lists them by the byte offset so they are 2* the value
|
||||
|
||||
#define P_SCROLL 0x10
|
||||
#define P_UPDATE_MODE 0x11
|
||||
#define P_INTENSITY 0x12
|
||||
#define P_MODE 0x13
|
||||
#define P_STATUS 0x14
|
||||
#define P_X_COUNT 0x15
|
||||
#define P_Y_COUNT 0x16
|
||||
#define P_SCROLL 0x10
|
||||
#define P_UPDATE_MODE 0x11
|
||||
#define P_INTENSITY 0x12
|
||||
#define P_MODE 0x13
|
||||
#define P_STATUS 0x14
|
||||
#define P_X_COUNT 0x15
|
||||
#define P_Y_COUNT 0x16
|
||||
|
||||
#define P_COLOUR03 0x14
|
||||
#define P_COLOUR47 0x15
|
||||
#define P_COLOUR8B 0x16
|
||||
#define P_COLOURCF 0x17
|
||||
#define P_COLOUR03 0x14
|
||||
#define P_COLOUR47 0x15
|
||||
#define P_COLOUR8B 0x16
|
||||
#define P_COLOURCF 0x17
|
||||
|
||||
// From the service manual, Reg022 update mode constants :
|
||||
// The first 8 are NON XOR writes
|
||||
#define UPMODE_40_TEXT 0x00 // 40 character text
|
||||
#define UPMODE_80_TEXT 0x01 // 80 character text
|
||||
#define UPMODE_LO_PIXEL 0x02 // Low res pixel
|
||||
#define UPMODE_HI_PIXEL 0x03 // Hi res pixel
|
||||
#define UPMODE_ANIMATION 0x04 // Animation (mask + data)
|
||||
#define UPMODE_SCROLL 0x05 // Scroll mode
|
||||
#define UPMODE_DIRECT 0x06 // Direct write to video ram
|
||||
#define UPMODE_ILLEGAL7 0x07
|
||||
#define UPMODE_40_TEXT 0x00 // 40 character text
|
||||
#define UPMODE_80_TEXT 0x01 // 80 character text
|
||||
#define UPMODE_LO_PIXEL 0x02 // Low res pixel
|
||||
#define UPMODE_HI_PIXEL 0x03 // Hi res pixel
|
||||
#define UPMODE_ANIMATION 0x04 // Animation (mask + data)
|
||||
#define UPMODE_SCROLL 0x05 // Scroll mode
|
||||
#define UPMODE_DIRECT 0x06 // Direct write to video ram
|
||||
#define UPMODE_ILLEGAL7 0x07
|
||||
|
||||
// The second 8 are XOR writes
|
||||
#define UPMODE_40_TEXT_X 0x08
|
||||
#define UPMODE_80_TEXT_X 0x09
|
||||
#define UPMODE_LO_PIXEL_X 0x0A
|
||||
#define UPMODE_HI_PIXEL_X 0x0B
|
||||
#define UPMODE_ANIMATION_X 0x0C
|
||||
#define UPMODE_SCROLL_X 0x0D
|
||||
#define UPMODE_DIRECT_X 0x0E
|
||||
#define UPMODE_ILLEGALF 0x0F
|
||||
#define UPMODE_40_TEXT_X 0x08
|
||||
#define UPMODE_80_TEXT_X 0x09
|
||||
#define UPMODE_LO_PIXEL_X 0x0A
|
||||
#define UPMODE_HI_PIXEL_X 0x0B
|
||||
#define UPMODE_ANIMATION_X 0x0C
|
||||
#define UPMODE_SCROLL_X 0x0D
|
||||
#define UPMODE_DIRECT_X 0x0E
|
||||
#define UPMODE_ILLEGALF 0x0F
|
||||
|
||||
#define UP_XOR_MASK 0x08
|
||||
#define UP_XOR_MASK 0x08
|
||||
|
||||
// port 026, display mode (m_mode)
|
||||
#define MODE_BORDER 0x0F // bits 0..3, Border colour number
|
||||
#define MODE_RESOLUTION 0x10 // bit 4, 0=low res (40 col), high = high res (80 col)
|
||||
#define MODE_WIDTH 0x20 // bit 5, 0=narrow, 1=wide
|
||||
#define MODE_HEIGHT 0x40 // bit 6, 0=625 lines, 1=562
|
||||
#define MODE_BORDER 0x0F // bits 0..3, Border colour number
|
||||
#define MODE_RESOLUTION 0x10 // bit 4, 0=low res (40 col), high = high res (80 col)
|
||||
#define MODE_WIDTH 0x20 // bit 5, 0=narrow, 1=wide
|
||||
#define MODE_HEIGHT 0x40 // bit 6, 0=625 lines, 1=562
|
||||
|
||||
#define WIDTH_MASK 0x07
|
||||
|
||||
@ -424,6 +424,10 @@ void rmnimbus_state::nimbus_video_io_w(offs_t offset, uint16_t data, uint16_t me
|
||||
change_palette(offset - P_COLOUR03, data);
|
||||
return;
|
||||
|
||||
// This register doesn't appear to be documented, but is written regually in setpc ibm mode
|
||||
case 0x18 :
|
||||
break;
|
||||
|
||||
default:
|
||||
logerror("nimbus: unknown video reg write %02x %04x\n", offset, data);
|
||||
return;
|
||||
@ -604,7 +608,7 @@ void rmnimbus_state::write_pixel_data(uint16_t x, uint16_t y, uint16_t data)
|
||||
// Colours are encoded as follows :
|
||||
// Each nibble contains a colour encoded as igrb
|
||||
// so we shift through the specified colours and extract the bits, to set the palette.
|
||||
//
|
||||
//
|
||||
void rmnimbus_state::change_palette(uint8_t bank, uint16_t colours)
|
||||
{
|
||||
// loop over changing colours
|
||||
|
Loading…
Reference in New Issue
Block a user