diff --git a/src/cpu/callback.cpp b/src/cpu/callback.cpp index e5294bf03..18de12b6f 100644 --- a/src/cpu/callback.cpp +++ b/src/cpu/callback.cpp @@ -403,32 +403,24 @@ Bitu CALLBACK_SetupExtra(Bitu callback, Bitu type, PhysPt physAddress, bool use_ phys_writeb(physAddress+0x0e,(uint8_t)0xcf); //An IRET Instruction return (use_cb?0x13:0x0f); case CB_IRQ1: // keyboard int9 - phys_writeb(physAddress+0x00,(uint8_t)0x50); // push ax if (machine == MCH_PCJR) { /* IBM PCjr reads the infrared input on NMI interrupt, which then calls INT 48h to * translate to IBM PC/XT scan codes before passing AL directly to IRQ1 (INT 9). * PCjr keyboard handlers, including games made for the PCjr, assume the scan code - * is in AL and do not read the I/O port. - * - * PCjr has an XT style keyboard interface where it is necessary to set, then clear, - * bit 7 of port 61h to re-enable the keyboard. - * - * Because we're talking to our own emulation, it is sufficient to just clear bit 7.*/ - phys_writew(physAddress+0x01,(uint16_t)0x60E4); // in al, 0x60 - + * is in AL and do not read the I/O port. */ if (use_cb) { - phys_writeb(physAddress+0x03,(uint8_t)0xFE); //GRP 4 - phys_writeb(physAddress+0x04,(uint8_t)0x38); //Extra Callback instruction - phys_writew(physAddress+0x05,(uint16_t)callback); //The immediate word + phys_writeb(physAddress+0x00,(uint8_t)0xFE); //GRP 4 + phys_writeb(physAddress+0x01,(uint8_t)0x38); //Extra Callback instruction + phys_writew(physAddress+0x02,(uint16_t)callback); //The immediate word physAddress+=4; } /* It wasn't an interrupt, so there's no need to ack */ - phys_writeb(physAddress+0x03,(uint8_t)0x58); // pop ax - phys_writeb(physAddress+0x04,(uint8_t)0xcf); //An IRET Instruction - return (use_cb?0x09:0x05); + phys_writeb(physAddress+0x00,(uint8_t)0xcf); //An IRET Instruction + return (use_cb?0x05:0x01); } else { + phys_writeb(physAddress+0x00,(uint8_t)0x50); // push ax if (IS_PC98_ARCH) { /* NTS: NEC PC-98 does not have keyboard input on port 60h, it's a 8251 UART elsewhere. */ phys_writew(physAddress+0x01,(uint16_t)0x9090); // nop, nop diff --git a/src/ints/bios_keyboard.cpp b/src/ints/bios_keyboard.cpp index d959acf88..6853c96d8 100644 --- a/src/ints/bios_keyboard.cpp +++ b/src/ints/bios_keyboard.cpp @@ -1180,19 +1180,45 @@ static Bitu PCjr_NMI_Keyboard_Handler(void) { * Fn + 1 into the scan code for F1. */ static Bitu PCjr_INT48_Keyboard_Handler(void) { uint8_t pcjr_f = mem_readb(BIOS_KEYBOARD_PCJR_FLAG2); + uint8_t flags1 = mem_readb(BIOS_KEYBOARD_FLAGS1); - switch (reg_al&0x7F) { - case 0x54: /* Fn key */ - if (reg_al&0x80/*release*/) pcjr_f &= ~BIOS_KEYBOARD_PCJR_FLAG2_FN_FLAG; - else pcjr_f |= BIOS_KEYBOARD_PCJR_FLAG2_FN_FLAG; - goto skip_int9; - default: /* AL without translation */ - break; + if ((reg_al&0x7F) == 0x54) { + if (reg_al&0x80/*release*/) pcjr_f &= ~BIOS_KEYBOARD_PCJR_FLAG2_FN_FLAG; + else pcjr_f |= BIOS_KEYBOARD_PCJR_FLAG2_FN_FLAG; + goto skip_int9; } +#define UPDATESHIFT(x) if (x) { flags1 &= ~0x3; /*break*/ } else { flags1 |= 0x3; /*make*/ } +#define CLEARSHIFT() UPDATESHIFT(1/*break*/) + + if (pcjr_f & (BIOS_KEYBOARD_PCJR_FLAG2_FN_FLAG|BIOS_KEYBOARD_PCJR_FLAG2_FN_LOCK)) { + const uint8_t bc = reg_al & 0x80; + switch (reg_al&0x7F) { + case 0x02: reg_al=0x3B|bc; break;/*Fn+1 = F1*/ + case 0x03: reg_al=0x3C|bc; break;/*Fn+2 = F2*/ + case 0x04: reg_al=0x3D|bc; break;/*Fn+3 = F3*/ + case 0x05: reg_al=0x3E|bc; break;/*Fn+4 = F4*/ + case 0x06: reg_al=0x3F|bc; break;/*Fn+5 = F5*/ + case 0x07: reg_al=0x40|bc; break;/*Fn+6 = F6*/ + case 0x08: reg_al=0x41|bc; break;/*Fn+7 = F7*/ + case 0x09: reg_al=0x42|bc; break;/*Fn+8 = F8*/ + case 0x0A: reg_al=0x43|bc; break;/*Fn+9 = F9*/ + case 0x0B: reg_al=0x44|bc; break;/*Fn+10 = F10*/ + case 0x1A: reg_al=0x2B|bc; UPDATESHIFT(bc); break;/*Fn+[ = | which is SHIFT+\ */ + case 0x1B: reg_al=0x29|bc; UPDATESHIFT(bc); break;/*Fn+] = ~ which is SHIFT+` */ + case 0x28: reg_al=0x29|bc; CLEARSHIFT(); break;/*Fn+' = ` which is unshifted ` */ + case 0x35: reg_al=0x2B|bc; CLEARSHIFT(); break;/*Fn+/ = \\ which is unshifted \\ */ + default: break; + } + } + +#undef UPDATESHIFT +#undef CLEARSHIFT + reg_eip++; /* skip over IRET */ skip_int9: /* if we do not skip IRET, then INT 48h returns without calling INT 9h */ + mem_writeb(BIOS_KEYBOARD_FLAGS1,flags1); mem_writeb(BIOS_KEYBOARD_PCJR_FLAG2,pcjr_f); return CBRET_NONE; }