Skip to content

Commit

Permalink
feat: Keyboard MCU emulation
Browse files Browse the repository at this point in the history
  • Loading branch information
midwan committed Jan 5, 2025
1 parent 685ff8c commit e494c66
Show file tree
Hide file tree
Showing 32 changed files with 6,606 additions and 180 deletions.
7 changes: 7 additions & 0 deletions cmake/SourceFiles.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ set(SOURCE_FILES
src/luascript.cpp
src/main.cpp
src/memory.cpp
src/mos6502.cpp
src/midiemu.cpp
src/native2amiga.cpp
src/ncr9x_scsi.cpp
Expand Down Expand Up @@ -194,6 +195,12 @@ set(SOURCE_FILES
src/caps/caps_amiberry.cpp
src/dsp3210/dsp_glue.cpp
src/dsp3210/DSP3210_emulation.cpp
src/kbmcu/8048/co8048.cpp
src/kbmcu/keyboard_mcu_6500_1.cpp
src/kbmcu/keyboard_mcu_6805.cpp
src/kbmcu/keyboard_mcu_d8039hlc.cpp
src/kbmcu/m6805/m68_ops.cpp
src/kbmcu/m6805/m68emu.cpp
src/machdep/support.cpp
src/mame/a2410.cpp
src/mame/tm34010/tms34010.cpp
Expand Down
33 changes: 28 additions & 5 deletions src/cfgfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,18 @@ static const TCHAR *eclocksync[] = { _T("default"), _T("68000"), _T("Gayle"), _T
static const TCHAR *agnusmodel[] = { _T("default"), _T("velvet"), _T("a1000"), _T("ocs"), _T("ecs"), _T("aga"), nullptr };
static const TCHAR *agnussize[] = { _T("default"), _T("512k"), _T("1m"), _T("2m"), nullptr };
static const TCHAR *denisemodel[] = { _T("default"), _T("velvet"), _T("a1000_noehb"), _T("a1000"), _T("ocs"), _T("ecs"), _T("aga"), nullptr };
static const TCHAR *kbtype[] = {
_T("disconnected"),
_T("UAE"),
_T("a500_6570-036"),
_T("a600_6570-036"),
_T("a1000_6500-1"),
_T("a1000_6570-036"),
_T("a1200_6805"),
_T("a2000_8039"),
_T("ax000_6570-036"),
nullptr
};

struct hdcontrollerconfig
{
Expand Down Expand Up @@ -2980,7 +2992,9 @@ void cfgfile_save_options (struct zfile *f, struct uae_prefs *p, int type)
cfgfile_write_bool(f, _T("fm801_pci"), p->obs_sound_fm801);
#endif

cfgfile_dwrite_bool(f, _T("keyboard_connected"), p->keyboard_connected);
cfgfile_dwrite_bool(f, _T("keyboard_connected"), p->keyboard_mode >= 0);
cfgfile_dwrite_bool(f, _T("keyboard_nkro"), p->keyboard_nkro);
cfgfile_dwrite_strarr(f, _T("keyboard_type"), kbtype, p->keyboard_mode + 1);
cfgfile_write_str (f, _T("kbd_lang"), (p->keyboard_lang == KBD_LANG_DE ? _T("de")
: p->keyboard_lang == KBD_LANG_DK ? _T("dk")
: p->keyboard_lang == KBD_LANG_ES ? _T("es")
Expand Down Expand Up @@ -5906,6 +5920,14 @@ static int cfgfile_parse_hardware (struct uae_prefs *p, const TCHAR *option, TCH
}
return 1;
}
if (cfgfile_yesno(option, value, _T("keyboard_connected"), &dummybool)) {
p->keyboard_mode = dummybool ? 0 : -1;
return 1;
}
if (cfgfile_strval(option, value, _T("keyboard_type"), &p->keyboard_mode, kbtype, 0)) {
p->keyboard_mode--;
return 1;
}

if (cfgfile_yesno(option, value, _T("immediate_blits"), &p->immediate_blits)
#ifdef AMIBERRY
Expand Down Expand Up @@ -5939,7 +5961,6 @@ static int cfgfile_parse_hardware (struct uae_prefs *p, const TCHAR *option, TCH
|| cfgfile_yesno(option, value, _T("gfxcard_dacswitch"), &p->rtg_dacswitch)
|| cfgfile_yesno(option, value, _T("gfxcard_multithread"), &p->rtg_multithread)
|| cfgfile_yesno(option, value, _T("synchronize_clock"), &p->tod_hack)
|| cfgfile_yesno(option, value, _T("keyboard_connected"), &p->keyboard_connected)
|| cfgfile_coords(option, value, _T("lightpen_offset"), &p->lightpen_offset[0], &p->lightpen_offset[1])
|| cfgfile_yesno(option, value, _T("lightpen_crosshair"), &p->lightpen_crosshair)

Expand Down Expand Up @@ -5977,6 +5998,7 @@ static int cfgfile_parse_hardware (struct uae_prefs *p, const TCHAR *option, TCH
|| cfgfile_yesno(option, value, _T("harddrive_write_protect"), &p->harddrive_read_only)
|| cfgfile_yesno(option, value, _T("uae_hide_autoconfig"), &p->uae_hide_autoconfig)
|| cfgfile_yesno(option, value, _T("board_custom_order"), &p->autoconfig_custom_sort)
|| cfgfile_yesno(option, value, _T("keyboard_nkro"), &p->keyboard_nkro)
|| cfgfile_yesno(option, value, _T("uaeserial"), &p->uaeserial))
return 1;

Expand Down Expand Up @@ -8481,7 +8503,8 @@ void default_prefs (struct uae_prefs *p, bool reset, int type)
inputdevice_joyport_config_store(p, _T("joy0"), 1, -1, -1, 0);
}
p->keyboard_lang = KBD_LANG_US;
p->keyboard_connected = true;
p->keyboard_mode = 0;
p->keyboard_nkro = true;

p->produce_sound = 3;
p->sound_stereo = SND_STEREO;
Expand Down Expand Up @@ -9670,7 +9693,7 @@ static int bip_casablanca(struct uae_prefs *p, int config, int compa, int romche
p->immediate_blits = false;
p->produce_sound = 2;
p->nr_floppies = 0;
p->keyboard_connected = false;
p->keyboard_mode = -1;
p->floppyslots[0].dfxtype = DRV_NONE;
p->floppyslots[1].dfxtype = DRV_NONE;
p->floppyslots[2].dfxtype = DRV_PC_35_ONLY_80;
Expand All @@ -9695,7 +9718,7 @@ static int bip_draco(struct uae_prefs *p, int config, int compa, int romcheck)
p->immediate_blits = false;
p->produce_sound = 2;
p->nr_floppies = 0;
p->keyboard_connected = false;
p->keyboard_mode = -1;
p->cpuboard_settings |= 0x10;
p->floppyslots[0].dfxtype = DRV_NONE;
p->floppyslots[1].dfxtype = DRV_NONE;
Expand Down
155 changes: 111 additions & 44 deletions src/cia.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
#include "scsi.h"
#include "rtc.h"
#include "devices.h"
#include "keyboard_mcu.h"

#define CIAA_DEBUG_R 0
#define CIAA_DEBUG_W 0
Expand Down Expand Up @@ -981,7 +982,7 @@ static void sendrw(void)

int resetwarning_do(int canreset)
{
if (!currprefs.keyboard_connected)
if (currprefs.keyboard_mode < 0)
return 0;
if (resetwarning_phase || regs.halted > 0) {
/* just force reset if second reset happens during resetwarning */
Expand Down Expand Up @@ -1037,13 +1038,15 @@ void CIA_hsync_prehandler (void)
{
}

static void keyreq (void)
void cia_keyreq(uae_u8 code)
{
#if KB_DEBUG
write_log(_T("code=%02x (%02x)\n"), kbcode, (uae_u8)(~((kbcode >> 1) | (kbcode << 7))));
#endif
cia[0].sdr = kbcode;
kblostsynccnt = 8 * maxvpos * 8; // 8 frames * 8 bits.
cia[0].sdr = code;
if (currprefs.keyboard_mode == 0) {
kblostsynccnt = 8 * maxvpos * 8; // 8 frames * 8 bits.
}
CIA_sync_interrupt(0, ICR_SP);
}

Expand Down Expand Up @@ -1163,6 +1166,9 @@ void keyboard_connected(bool connect)
{
if (connect) {
write_log(_T("Keyboard connected\n"));
if (currprefs.keyboard_mode > 0) {
keymcu_reset();
}
} else {
write_log(_T("Keyboard disconnected\n"));
}
Expand All @@ -1171,9 +1177,53 @@ void keyboard_connected(bool connect)
resetwarning_phase = 0;
}

static bool keymcu_execute(void)
{
bool handshake = (cia[0].t[0].cr & 0x40) != 0 && (cia[0].sdr_buf & 0x80) == 0;

#if 1
extern int blop;
if (blop & 1) {
handshake = true;
}
#endif

bool cyclemode = false;
if (currprefs.keyboard_mode == KB_A500_6570 ||
currprefs.keyboard_mode == KB_A600_6570 ||
currprefs.keyboard_mode == KB_A1000_6570 ||
currprefs.keyboard_mode == KB_Ax000_6570)
{
cyclemode = keymcu_run(handshake);
}
if (currprefs.keyboard_mode == KB_A1200_6805) {
cyclemode = keymcu2_run(handshake);
}
if (currprefs.keyboard_mode == KB_A2000_8039) {
cyclemode = keymcu3_run(handshake);
}
return cyclemode;
}

static void keymcu_event(uae_u32 v)
{
bool cyclemode = keymcu_execute();
if (cyclemode) {
// execute few times / scanline, does not need to be accurate
// because keyboard MCU has separate not that accurate clock crystal.
event2_newevent_x_remove(keymcu_event);
event2_newevent_xx(-1, 27 * CYCLE_UNIT, 0, keymcu_event);
}
}

static void keymcu_do(void)
{
keymcu_event(0);
}

static void check_keyboard(void)
{
if (currprefs.keyboard_connected) {
if (currprefs.keyboard_mode >= 0) {
if ((keys_available() || kbstate < 3) && !kblostsynccnt ) {
switch (kbstate)
{
Expand All @@ -1193,7 +1243,7 @@ static void check_keyboard(void)
kbcode = ~get_next_key();
break;
}
keyreq();
cia_keyreq(kbcode);
}
} else {
while (keys_available()) {
Expand Down Expand Up @@ -1225,29 +1275,34 @@ void CIA_hsync_posthandler(bool ciahsync, bool dotod)
if (currprefs.tod_hack && cia[0].todon) {
do_tod_hack(dotod);
}
} else if (currprefs.keyboard_connected) {
// custom hsync
if (resetwarning_phase) {
resetwarning_check();
while (keys_available()) {
get_next_key();
}
} else {
if (currprefs.keyboard_mode > 0) {
keymcu_do();
} else {
if ((hsync_counter & 15) == 0) {
check_keyboard();
if (currprefs.keyboard_mode == 0) {
// custom hsync
if (resetwarning_phase) {
resetwarning_check();
while (keys_available()) {
get_next_key();
}
} else {
if ((hsync_counter & 15) == 0) {
check_keyboard();
}
}
} else {
while (keys_available()) {
get_next_key();
}
}
}
} else {
while (keys_available()) {
get_next_key();
}
}

if (!ciahsync) {
// Increase CIA-A TOD if delayed from previous line
cia_delayed_tod(0);
}

}

static void calc_led(int old_led)
Expand Down Expand Up @@ -1322,7 +1377,7 @@ void CIA_vsync_prehandler(void)
if (kblostsynccnt <= 0) {
kblostsynccnt = 0;
kbcode = 0;
keyreq();
cia_keyreq(kbcode);
#if KB_DEBUG
write_log(_T("lostsync\n"));
#endif
Expand Down Expand Up @@ -2019,42 +2074,54 @@ static void WriteCIAA(uae_u16 addr, uae_u8 val, uae_u32 *flags)
case 13:
case 15:
CIA_update();
if (currprefs.keyboard_mode > 0 && reg == 12) {
keymcu_do();
}
WriteCIAReg(0, reg, val);
CIA_calctimers();
break;
case 14:
{
CIA_update();
// keyboard handshake handling
if (currprefs.cpuboard_type != 0 && (val & 0x40) != (c->t[0].cr & 0x40)) {
/* bleh, Phase5 CPU timed early boot key check fix.. */
if (m68k_getpc() >= 0xf00000 && m68k_getpc() < 0xf80000)
check_keyboard();
}
if ((val & CR_INMODE1) != 0 && (c->t[0].cr & CR_INMODE1) == 0) {
// handshake start
if (kblostsynccnt > 0 && currprefs.cs_kbhandshake) {
kbhandshakestart = get_cycles();
bool handshake = (val & CR_INMODE1) != (c->t[0].cr & CR_INMODE1);
if (currprefs.keyboard_mode == 0) {
// keyboard handshake handling
if (currprefs.cpuboard_type != 0 && handshake) {
/* bleh, Phase5 CPU timed early boot key check fix.. */
if (m68k_getpc() >= 0xf00000 && m68k_getpc() < 0xf80000)
check_keyboard();
}
#if KB_DEBUG
write_log(_T("KB_ACK_START %02x->%02x %08x\n"), c->t[0].cr, val, M68K_GETPC);
#endif
} else if ((val & CR_INMODE1) == 0 && (c->t[0].cr & CR_INMODE1) != 0) {
// handshake end
/* todo: check if low to high or high to low only */
if (kblostsynccnt > 0 && currprefs.cs_kbhandshake) {
evt_t len = get_cycles() - kbhandshakestart;
if (len < currprefs.cs_kbhandshake * CYCLE_UNIT) {
write_log(_T("Keyboard handshake pulse length %d < %d (CCKs)\n"), len / CYCLE_UNIT, currprefs.cs_kbhandshake);
if ((val & CR_INMODE1) != 0 && (c->t[0].cr & CR_INMODE1) == 0) {
// handshake start
if (kblostsynccnt > 0 && currprefs.cs_kbhandshake) {
kbhandshakestart = get_cycles();
}
#if KB_DEBUG
write_log(_T("KB_ACK_START %02x->%02x %08x\n"), c->t[0].cr, val, M68K_GETPC);
#endif
}
kblostsynccnt = 0;
else if ((val & CR_INMODE1) == 0 && (c->t[0].cr & CR_INMODE1) != 0) {
// handshake end
/* todo: check if low to high or high to low only */
if (kblostsynccnt > 0 && currprefs.cs_kbhandshake) {
evt_t len = get_cycles() - kbhandshakestart;
if (len < currprefs.cs_kbhandshake * CYCLE_UNIT) {
write_log(_T("Keyboard handshake pulse length %d < %d (CCKs)\n"), len / CYCLE_UNIT, currprefs.cs_kbhandshake);
}
}
kblostsynccnt = 0;
#if KB_DEBUG
write_log(_T("KB_ACK_END %02x->%02x %08x\n"), c->t[0].cr, val, M68K_GETPC);
write_log(_T("KB_ACK_END %02x->%02x %08x\n"), c->t[0].cr, val, M68K_GETPC);
#endif
}
}
WriteCIAReg(0, reg, val);
CIA_calctimers();
break;
if (currprefs.keyboard_mode > 0 && handshake) {
keymcu_do();
}
}
break;
}
}

Expand Down
Loading

0 comments on commit e494c66

Please sign in to comment.