iccard.cpp
joystick.cpp
joypad.cpp
+ mouse.cpp
+
msdosrom.cpp
serialrom.cpp
dictionary.cpp
#include "./joystick.h"
#include "./joypad.h"
#include "./keyboard.h"
+#include "./mouse.h"
#include "./msdosrom.h"
#include "./scsi.h"
#include "./serialrom.h"
using FMTOWNS::JOYSTICK;
using FMTOWNS::JOYPAD;
using FMTOWNS::KEYBOARD;
+using FMTOWNS::MOUSE;
using FMTOWNS::MSDOSROM;
using FMTOWNS::SCSI;
using FMTOWNS::SERIAL_ROM;
#endif
joypad[0] = new JOYPAD(this, emu);
joypad[1] = new JOYPAD(this, emu);
+ mouse = new MOUSE(this, emu);
uint16_t machine_id = 0x0100; // FM-Towns1
uint16_t cpu_id = 0x0001; // i386DX
timer->set_context_rtc(rtc);
timer->set_context_halt_line(cpu, SIG_CPU_HALTREQ, 0xffffffff);
+ joystick->set_context_mouse(mouse, SIG_MOUSE_STROBE, 0xff);
+
joystick->set_context_enable0(joypad[0], SIG_JOYPAD_ENABLE, 0xffffffff);
joystick->set_context_enable1(joypad[1], SIG_JOYPAD_ENABLE, 0xffffffff);
joystick->set_context_mask(joypad[0], SIG_JOYPAD_SELECT_BUS, 0x10); // Mouse0 or joypad0
class TOWNS_VRAM;
class PLANEVRAM;
class JOYPAD;
- class JOYSTICK; // Mouse and Joystick.
+ class MOUSE;
}
class VM : public VM_TEMPLATE
FMTOWNS::FLOPPY* floppy;
FMTOWNS::JOYSTICK* joystick;
FMTOWNS::JOYPAD* joypad[2];
+ FMTOWNS::MOUSE* mouse;
FMTOWNS::KEYBOARD* keyboard;
FMTOWNS::TIMER* timer;
FMTOWNS::TOWNS_VRAM* vram;
*/
#include "./joystick.h"
+#include "./mouse.h"
namespace FMTOWNS {
-#define EVENT_MOUSE_TIMEOUT 1
-#define EVENT_MOUSE_SAMPLING 2
void JOYSTICK::reset()
{
- dx = dy = 0;
- lx = ly = 0;
- mouse_state = emu->get_mouse_buffer();
- mouse_mask = 0x00;
- mouse_type = -1; // Force update data.
- mouse_phase = 0;
- mouse_strobe = false;
- mouse_data = 0x00;
+ mouse_mask = 0xff;
update_config(); // Update MOUSE PORT.
-
}
void JOYSTICK::initialize()
{
rawdata = emu->get_joy_buffer();
- mouse_state = emu->get_mouse_buffer();
joydata[0] = joydata[1] = 0x00;
- dx = dy = 0;
- lx = ly = 0;
- mouse_button = 0x00;
- mouse_timeout_event = -1;
- mouse_sampling_event = -1;
- set_emulate_mouse();
- mouse_type = config.mouse_type;
+
// Force reset pads.
connected_type[0] = 0xffffffff;
connected_type[1] = 0xffffffff;
stat_com[0] = stat_com[1] = false;
// register_frame_event(this);
+ register_frame_event(this);
}
void JOYSTICK::release()
void JOYSTICK::event_pre_frame()
{
- event_callback(EVENT_MOUSE_SAMPLING, 0);
+ for(int i = 0; i < 2; i++) {
+ if(connected_type[i] == SIG_JOYPORT_TYPE_2BUTTONS) {
+ write_signals(&outputs_query, 1 << i);
+ }
+ }
}
-
+
void JOYSTICK::write_io8(uint32_t address, uint32_t data)
{
// ToDo: Mouse
if(address == 0x04d6) {
- if(emulate_mouse[0]) {
- update_strobe(((data & 0x10) != 0));
- } else if(emulate_mouse[1]) {
- update_strobe(((data & 0x20) != 0));
+ if(mouse_mask != data) {
+ mouse_mask = data;
+ write_signals(&outputs_mask, data);
}
- mouse_mask = data;
- write_signals(&outputs_mask, data);
}
}
switch(address) {
case 0x04d0:
case 0x04d2:
- if(emulate_mouse[port_num]) {
- uint8_t trig = (mouse_mask >> (port_num << 1)) & 0x03;
- uint8_t mask2 = (mouse_mask >> (port_num + 4)) & 0x01;
- uint8_t rval = 0x70;
- rval |= (update_mouse() & 0x0f);
- mouse_state = emu->get_mouse_buffer();
- if(mouse_state != NULL) {
- uint32_t stat = mouse_state[2];
- mouse_button = 0x00;
- if((stat & 0x01) == 0) mouse_button |= 0x10; // left
- if((stat & 0x02) == 0) mouse_button |= 0x20; // right
- }
- if((mask2 & 0x01) == 0) { // COM
- rval = rval & ~0x40;
- }
- if((trig & 0x02) == 0) { // TRIG2
- rval = rval & ~0x20;
- }
- if((trig & 0x01) == 0) { // TRIG1
- rval = rval & ~0x10;
- }
- if((mouse_button & 0x10) != 0) {
- rval &= ~0x10; // Button LEFT
- }
- if((mouse_button & 0x20) != 0) {
- rval &= ~0x20; // Button RIGHT
- }
- retval = rval;
- } else {
- write_signals(&outputs_query, 1 << (port_num + 0));
- uint8_t trig = (mouse_mask >> (port_num << 1)) & 0x03;
+ {
+ retval = 0xff;
uint8_t mask2 = (mouse_mask >> (port_num + 4)) & 0x01;
- retval = 0x7f;
if((mask2 & 0x01) == 0) { // COM
retval = retval & ~0x40;
}
- if((trig & 0x02) == 0) { // TRIG2
- retval = retval & ~0x20;
- }
- if((trig & 0x01) == 0) { // TRIG1
- retval = retval & ~0x10;
- }
- if(connected_type[port_num] == SIG_JOYPORT_TYPE_NULL) {
- // None Connected
- return retval;
- }
- // Trigger independents from direction keys.
- if((joydata[port_num] & LINE_JOYPORT_B) != 0) {
- retval = retval & ~0x20;
- }
- if((joydata[port_num] & LINE_JOYPORT_A) != 0) {
- retval = retval & ~0x10;
- }
- //if((mask & (0x10 << port_num)) == 0) {
- if((joydata[port_num] & LINE_JOYPORT_LEFT) != 0) { // LEFT
- retval = retval & ~0x04; // LEFT
- }
- if((joydata[port_num] & LINE_JOYPORT_RIGHT) != 0) { // RIGHT
- retval = retval & ~0x08; // RIGHT
- }
- if((joydata[port_num] & LINE_JOYPORT_UP) != 0) { // UP
- retval = retval & ~0x01; // FWD
- }
- if((joydata[port_num] & LINE_JOYPORT_DOWN) != 0) { // DOWN
- retval = retval & ~0x02; // BACK
+ if(emulate_mouse[port_num]) {
+ if(d_mouse != nullptr) {
+ retval &= d_mouse->read_signal(SIG_MOUSE_DATA);
+ }
+ } else {
+ uint8_t trig = (mouse_mask >> (port_num << 1)) & 0x03;
+ if(connected_type[port_num] == SIG_JOYPORT_TYPE_NULL) {
+ // None Connected
+ return retval;
+ }
+ // Trigger independents from direction keys.
+ if((joydata[port_num] & LINE_JOYPORT_B) != 0) {
+ if((trig & 0x02) != 0) { // TRIG2
+ retval = retval & ~0x20;
+ }
+ }
+ if((joydata[port_num] & LINE_JOYPORT_A) != 0) {
+ if((trig & 0x01) != 0) { // TRIG1
+ retval = retval & ~0x10;
+ }
+ }
+ //if((mask & (0x10 << port_num)) == 0) {
+// if((mask2 & 0x01) == 0) { // COM
+ if((joydata[port_num] & LINE_JOYPORT_LEFT) != 0) { // LEFT
+ retval = retval & ~0x04; // LEFT
+ }
+ if((joydata[port_num] & LINE_JOYPORT_RIGHT) != 0) { // RIGHT
+ retval = retval & ~0x08; // RIGHT
+ }
+ if((joydata[port_num] & LINE_JOYPORT_UP) != 0) { // UP
+ retval = retval & ~0x01; // FWD
+ }
+ if((joydata[port_num] & LINE_JOYPORT_DOWN) != 0) { // DOWN
+ retval = retval & ~0x02; // BACK
+ }
+// }
}
+ return retval;
}
- return retval;
break;
default:
break;
return 0xff;
}
-void JOYSTICK::event_callback(int event_id, int err)
-{
- switch(event_id) {
- case EVENT_MOUSE_TIMEOUT:
- mouse_phase = 0;
- mouse_timeout_event = -1;
- dx = dy = 0;
- lx = ly = 0;
- mouse_data = 0x00;
- break;
- case EVENT_MOUSE_SAMPLING:
- if((emulate_mouse[0]) || (emulate_mouse[1])) {
- mouse_state = emu->get_mouse_buffer();
- if(mouse_state != NULL) {
- dx += mouse_state[0];
- dy += mouse_state[1];
- if(dx < -127) {
- dx += 128;
- } else if(dx > 127) {
- dx -= 128;
- }
- if(dy < -127) {
- dy += 128;
- } else if(dy > 127) {
- dy -= 128;
- }
- }
- }
- break;
- }
-}
void JOYSTICK::write_signal(int id, uint32_t data, uint32_t mask)
{
if(emulate_mouse[1]) {
ntype[1] = SIG_JOYPORT_TYPE_MOUSE;
}
- if((emulate_mouse[0]) || (emulate_mouse[1])) {
- force_register_event(this, EVENT_MOUSE_SAMPLING, 8.0e3, true, mouse_sampling_event);
- } else {
- clear_event(this, mouse_sampling_event);
- }
+
+ write_signals(&outputs_mask, mouse_mask);
for(int i = 0; i < 2; i++) {
// if(connected_type[i] != ntype[i]) {
write_signals(&outputs_enable[i], 1 << ntype[i]);
break;
}
}
- mouse_type = config.mouse_type;
+
}
void JOYSTICK::set_emulate_mouse()
case 1:
emulate_mouse[0] = true;
emulate_mouse[1] = false;
+ if(d_mouse != nullptr) {
+ d_mouse->write_signal(SIG_MOUSE_ENABLE, 0xfffffffe, 0xffffffff);
+ }
break;
case 2:
emulate_mouse[0] = false;
emulate_mouse[1] = true;
+ if(d_mouse != nullptr) {
+ d_mouse->write_signal(SIG_MOUSE_ENABLE, 0xffffffff, 0xffffffff);
+ }
break;
default:
emulate_mouse[0] = false;
emulate_mouse[1] = false;
- break;
- }
-}
-
-void JOYSTICK::update_strobe(bool flag)
-{
- bool _bak = mouse_strobe;
- mouse_strobe = flag;
- if((_bak != mouse_strobe)/* && (flag)*/) {
- if((mouse_phase == 0)) {
- // Sample data from MOUSE to registers.
- lx = -dx;
- ly = -dy;
- dx = 0;
- dy = 0;
- clear_event(this, mouse_timeout_event);
- register_event(this, EVENT_MOUSE_TIMEOUT, 600.0, false, &mouse_timeout_event);
- if(mouse_strobe) {
- mouse_phase = 1; // SYNC from MAME 0.225. 20201126 K.O
- }
+ if(d_mouse != nullptr) {
+ d_mouse->write_signal(SIG_MOUSE_ENABLE, 0x00000000, 0xffffffff);
}
- mouse_phase++;
-// if(mouse_phase > 5) {
-// mouse_phase = 0;
-// mouse_strobe = false;
-// clear_event(this, mouse_timeout_event);
-// }
- }
-}
-
-uint32_t JOYSTICK::update_mouse()
-{
- switch(mouse_phase) {
-// case 1: // SYNC
-// mouse_data = 0x0f;
-// break;
- case 2: // X_HIGH
- mouse_data = (lx >> 0) & 0x0f;
- break;
- case 3: // X_LOW
- mouse_data = (lx >> 4) & 0x0f;
- break;
- case 4: // Y_HIGH
- mouse_data = (ly >> 0) & 0x0f;
- break;
- case 5: // Y_LOW
- mouse_data = (ly >> 4) & 0x0f;
- break;
- default:
- mouse_data = 0x0f;
break;
}
-// out_debug_log(_T("READ MOUSE DATA=%01X PHASE=%d STROBE=%d"), mouse_data, mouse_phase, (mouse_strobe) ? 1 : 0);
- return mouse_data;
}
-#define STATE_VERSION 5
+#define STATE_VERSION 6
bool JOYSTICK::process_state(FILEIO *state_fio, bool loading)
{
state_fio->StateArray(emulate_mouse, sizeof(emulate_mouse), 1);
state_fio->StateArray(stat_com, sizeof(stat_com), 1);
- state_fio->StateValue(dx);
- state_fio->StateValue(dy);
- state_fio->StateValue(lx);
- state_fio->StateValue(ly);
- state_fio->StateValue(mouse_button);
- state_fio->StateValue(mouse_type);
- state_fio->StateValue(mouse_strobe);
- state_fio->StateValue(mouse_phase);
- state_fio->StateValue(mouse_data);
- state_fio->StateValue(mouse_timeout_event);
- state_fio->StateValue(mouse_sampling_event);
return true;
}
class JOYSTICK : public DEVICE
{
private:
+ DEVICE* d_mouse;
+
outputs_t outputs_mask;
outputs_t outputs_query;
outputs_t outputs_enable[2];
+
bool emulate_mouse[2];
uint32_t joydata[2];
bool stat_com[2];
const uint32_t *rawdata;
- const int32_t *mouse_state;
- int dx, dy;
- int lx, ly;
- uint32_t mouse_button;
- int mouse_phase;
- bool mouse_strobe;
- uint8_t mouse_data;
-
- int mouse_timeout_event;
- int mouse_sampling_event;
- int mouse_type;
+
uint8_t mouse_mask;
uint32_t connected_type[2];
void set_emulate_mouse();
- virtual void update_strobe(bool flag);
- uint32_t update_mouse();
-
public:
JOYSTICK(VM_TEMPLATE* parent_vm, EMU_TEMPLATE* parent_emu) : DEVICE(parent_vm, parent_emu)
{
- mouse_timeout_event = -1;
- mouse_sampling_event = -1;
+ d_mouse = NULL;
initialize_output_signals(&outputs_query);
initialize_output_signals(&outputs_mask);
initialize_output_signals(&outputs_enable[0]);
initialize_output_signals(&outputs_enable[1]);
connected_type[0] = SIG_JOYPORT_CH0 | SIG_JOYPORT_TYPE_NULL;
connected_type[1] = SIG_JOYPORT_CH1 | SIG_JOYPORT_TYPE_NULL;
- set_device_name(_T("FM-Towns PAD Port and MOUSE (JIS)"));
+ set_device_name(_T("FM-Towns PAD Port"));
}
~JOYSTICK() {}
// common functions
void initialize(void);
- void event_pre_frame(void);
void release();
void reset();
+ void event_pre_frame();
void __FASTCALL write_io8(uint32_t addr, uint32_t data);
uint32_t __FASTCALL read_io8(uint32_t addr);
void __FASTCALL write_signal(int id, uint32_t data, uint32_t mask);
- void __FASTCALL event_callback(int event_id, int err);
void update_config();
bool process_state(FILEIO* state_fio, bool loading);
{
register_output_signal(&outputs_query, dev, id, mask);
}
+ void set_context_mouse(DEVICE* dev, int id, uint32_t mask)
+ {
+ if((d_mouse == nullptr) && (dev != nullptr)) {
+ d_mouse = dev;
+ register_output_signal(&outputs_mask, dev, id, mask);
+ }
+ }
};
--- /dev/null
+/*
+ FUJITSU FM Towns Emulator 'eFMTowns'
+
+ Author : Kyuma.Ohta <whatisthis.sowhat _at_ gmail.com>
+ Date : 2021.06.16 -
+ History : 2021.06.16 Initial
+ [ Towns Mouse]
+
+*/
+
+#include "./mouse.h"
+
+namespace FMTOWNS {
+
+#define EVENT_MOUSE_TIMEOUT 1
+#define EVENT_MOUSE_SAMPLING 2
+#define EVENT_MOUSE_RESET 3
+
+void MOUSE::initialize()
+{
+ phase = 0;
+ strobe = false;
+ mouse_state = NULL;
+ mouse_connected = false;
+ port_num = 0;
+
+ dx = dy = 0;
+ lx = ly = 0;
+ event_timeout = -1;
+ event_sampling = -1;
+
+ register_frame_event(this);
+}
+
+void MOUSE::release()
+{
+}
+
+void MOUSE::event_pre_frame()
+{
+ event_callback(EVENT_MOUSE_SAMPLING, 0);
+}
+
+void MOUSE::reset()
+{
+ // Values around mouse aren't initialized on reset.
+// mouse_state = emu->get_mouse_buffer();
+// update_config(); // Update MOUSE PORT.
+}
+
+void MOUSE::update_strobe()
+{
+ bool _bak = strobe;
+ uint8_t _mask = ((port_num & 1) != 0) ? 0x20 : 0x10;
+ strobe = ((mouse_mask & _mask) != 0) ? true : false;
+ if((_bak != strobe)/* && (flag)*/) {
+ if(phase == 0) {
+ if(strobe) {
+ // Sample data from MOUSE to registers.
+ lx = -dx;
+ ly = -dy;
+ dx = 0;
+ dy = 0;
+ // From FM Towns Technical book, Sec.1-7, P.241.
+ // (Ta + Tj * 3 + Ti) <= 920.0uS
+ //force_register_event(this, EVENT_MOUSE_TIMEOUT, 920.0, false, event_timeout);
+ force_register_event(this, EVENT_MOUSE_TIMEOUT, 2000.0, false, event_timeout);
+ phase = 2; // SYNC from MAME 0.225. 20201126 K.O
+ }
+ return;
+ }
+ phase++;
+ }
+}
+
+
+uint32_t MOUSE::update_mouse()
+{
+ uint32_t mouse_data = 0x0f;
+ switch(phase) {
+// case 1: // SYNC
+// mouse_data = 0x0f;
+// break;
+ case 2: // X_HIGH
+ mouse_data = (lx >> 0) & 0x0f;
+ break;
+ case 3: // X_LOW
+ mouse_data = (lx >> 4) & 0x0f;
+ break;
+ case 4: // Y_HIGH
+ mouse_data = (ly >> 0) & 0x0f;
+ break;
+ case 5: // Y_LOW
+ mouse_data = (ly >> 4) & 0x0f;
+ // From FM Towns Technical book, Sec.1-7, P.241.
+ // Ti(min)
+ force_register_event(this, EVENT_MOUSE_TIMEOUT, 150.0, false, event_timeout);
+ break;
+ }
+
+// out_debug_log(_T("READ MOUSE DATA=%01X PHASE=%d STROBE=%d"), mouse_data, mouse_phase, (mouse_strobe) ? 1 : 0);
+ return mouse_data;
+}
+
+uint32_t MOUSE::read_signal(int ch)
+{
+ switch(ch) {
+ case SIG_MOUSE_DATA:
+ if(mouse_connected) {
+ uint8_t trig = (mouse_mask >> (port_num << 1)) & 0x03;
+ uint8_t rval = 0xf0;
+
+ rval |= (update_mouse() & 0x0f);
+ mouse_state = emu->get_mouse_buffer();
+ if(mouse_state != NULL) {
+ uint32_t stat = mouse_state[2];
+ if((trig & 0x01) != 0) {
+ if((stat & 0x01) == 0) {
+ rval &= ~0x10; // Button LEFT
+ }
+ }
+ if((trig & 0x02) != 0) {
+ if((stat & 0x02) == 0) {
+ rval &= ~0x20; // Button LEFT
+ }
+ }
+ }
+ if(!(strobe)) { // COM
+ rval = rval & ~0x40;
+ }
+ return rval;
+ }
+ break;
+ case SIG_MOUSE_ENABLE:
+ return ((mouse_connected) ? 0xffffffff : 0);
+ break;
+ case SIG_MOUSE_NUM:
+ return port_num & 1;
+ break;
+ }
+ return 0xffffffff;
+}
+
+void MOUSE::write_signal(int id, uint32_t data, uint32_t mask)
+{
+ switch(id) {
+ case SIG_MOUSE_ENABLE:
+ {
+ bool _bak = mouse_connected;
+ mouse_connected = (((data & mask) & 0xfffffffe) != 0) ? true : false;
+ port_num = (data & mask) & 0x01;
+ if(_bak != mouse_connected) {
+ if(!(_bak)) { // off -> on
+ phase = 0;
+ dx = dy = 0;
+ lx = ly = 0;
+ strobe = false;
+ clear_event(this, event_timeout);
+// force_register_event(this, EVENT_MOUSE_SAMPLING,
+// 4.0e3, true, event_sampling);
+ } else { // on -> off
+ clear_event(this, event_timeout);
+// clear_event(this, event_sampling);
+ }
+ }
+ }
+ break;
+ case SIG_MOUSE_STROBE:
+ mouse_mask = data;
+ if(mouse_connected) {
+ update_strobe();
+ }
+ break;
+ }
+}
+
+void MOUSE::event_callback(int event_id, int err)
+{
+ switch(event_id) {
+ case EVENT_MOUSE_RESET:
+ event_timeout = -1;
+ phase = 0;
+ break;
+ case EVENT_MOUSE_TIMEOUT:
+ phase = 0;
+ event_timeout = -1;
+ dx = dy = 0;
+ lx = ly = 0;
+ break;
+ case EVENT_MOUSE_SAMPLING:
+ mouse_state = emu->get_mouse_buffer();
+ if(mouse_state != NULL) {
+ dx += mouse_state[0];
+ dy += mouse_state[1];
+ if(dx < -127) {
+ dx += 128;
+ } else if(dx > 127) {
+ dx -= 128;
+ }
+ if(dy < -127) {
+ dy += 128;
+ } else if(dy > 127) {
+ dy -= 128;
+ }
+ }
+ break;
+ }
+}
+
+#define STATE_VERSION 1
+
+bool MOUSE::process_state(FILEIO *state_fio, bool loading)
+{
+ if(!state_fio->StateCheckUint32(STATE_VERSION)) {
+ return false;
+ }
+ if(!state_fio->StateCheckInt32(this_device_id)) {
+ return false;
+ }
+
+ state_fio->StateValue(mouse_connected);
+ state_fio->StateValue(port_num);
+
+ state_fio->StateValue(phase);
+ state_fio->StateValue(strobe);
+ state_fio->StateValue(dx);
+ state_fio->StateValue(dy);
+ state_fio->StateValue(lx);
+ state_fio->StateValue(ly);
+
+ state_fio->StateValue(mouse_mask);
+ state_fio->StateValue(event_timeout);
+ state_fio->StateValue(event_sampling);
+
+ return true;
+}
+}
--- /dev/null
+/*
+ FUJITSU FM Towns Emulator 'eFMTowns'
+
+ Author : Kyuma.Ohta <whatisthis.sowhat _at_ gmail.com>
+ Date : 2021.06.16 -
+ History : 2020.06.16 Initial.
+ [ Towns Mouse]
+
+*/
+
+#pragma once
+
+#include "../device.h"
+
+#define SIG_MOUSE_ENABLE 1
+#define SIG_MOUSE_STROBE 2
+#define SIG_MOUSE_NUM 3
+#define SIG_MOUSE_DATA 4
+
+namespace FMTOWNS {
+
+class MOUSE : public DEVICE
+{
+private:
+ const int32_t* mouse_state;
+
+ int phase;
+ bool strobe;
+ int dx, dy;
+ int lx, ly;
+
+ bool mouse_connected;
+ int port_num;
+
+ uint8_t mouse_mask;
+
+ int event_timeout;
+ int event_sampling;
+
+ void update_strobe();
+ uint32_t update_mouse();
+
+public:
+ MOUSE(VM_TEMPLATE* parent_vm, EMU_TEMPLATE* parent_emu) : DEVICE(parent_vm, parent_emu)
+ {
+ set_device_name(_T("FM-Towns MOUSE"));
+ }
+ ~MOUSE() {}
+
+ void initialize();
+ void release();
+
+ void reset();
+ void __FASTCALL event_callback(int event_id, int err);
+ void event_pre_frame();
+
+ uint32_t __FASTCALL read_signal(int ch);
+ void __FASTCALL write_signal(int id, uint32_t data, uint32_t mask);
+
+ bool process_state(FILEIO* state_fio, bool loading);
+};
+
+}
+