Skip to content

Commit

Permalink
PC-98: Write the PC-98 mapping table for all 10 possible states, thou…
Browse files Browse the repository at this point in the history
…gh incomplete for anything other than normal, shift, and control. This is enough to keep Nut Berry happy and possibly any other PC-98 game that needs the keyboard translation tables to run. Update code to reflect that the lookup tables are 0x60, not 0x80 bytes long, because they skip a range of unused scan codes
  • Loading branch information
joncampbell123 committed Feb 19, 2024
1 parent 4f1d714 commit 3d2f114
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 15 deletions.
4 changes: 2 additions & 2 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ Next:
keyboard translation table pointer in the BIOS data area for "Nut Berry".
This Nut Berry game also assumes lookup and translation tables exist at
specific locations in the ROM BIOS, so put those tables there. The shift
state table in BIOS has also been added, though at the moment, they all
reflect the normal unshifted state which shouldn't be a problem. (joncampbell123).
state table in BIOS has also been added, though at the moment, the tables
are incomplete. (joncampbell123).
- MegaZeux from the MS-DOS days had a 256-color tweakmode that worked on some
popular SVGA chipsets of it's time though on others it does nothing but halve
the display resolution of text mode. The basic idea is that it makes the VGA
Expand Down
16 changes: 8 additions & 8 deletions src/ints/bios.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10033,6 +10033,13 @@ class BIOS:public Module_base{
}
}

if (IS_PC98_ARCH) {
/* Keyboard translation tables, must exist at segment 0xFD80:0x0E00 because PC-98 MS-DOS assumes it (it writes 0x522 itself on boot) */
/* The table must be placed back far enough so that (0x60 * 10) bytes do not overlap the lookup table at 0xE28 */
BIOS_PC98_KEYBOARD_TRANSLATION_LOCATION = PhysToReal416(ROMBIOS_GetMemory(0x60 * 10,"Keyboard translation tables",/*align*/1,0xFD800+0xA13));
if (ROMBIOS_GetMemory(0x2 * 10,"Keyboard translation shift tables",/*align*/1,0xFD800+0xE28) == (~0u)) E_Exit("Failed to allocate shift tables");//reserve it
BIOSKEY_PC98_Write_Tables();
}

/* pick locations */
/* IBM PC mode: See [https://github.com/skiselev/8088_bios/blob/master/bios.asm]. Some values also provided by Allofich.
Expand All @@ -10051,12 +10058,6 @@ class BIOS:public Module_base{
BIOS_DEFAULT_IRQ07_DEF_LOCATION = PhysToReal416(ROMBIOS_GetMemory(7/*see callback.cpp for EOI_PIC1*/,"BIOS default IRQ2-7 location",/*align*/1,IS_PC98_ARCH ? 0 : 0xFFF55));
BIOS_DEFAULT_IRQ815_DEF_LOCATION = PhysToReal416(ROMBIOS_GetMemory(9/*see callback.cpp for EOI_PIC1*/,"BIOS default IRQ8-15 location",/*align*/1,IS_PC98_ARCH ? 0 : 0xFE880));

if (IS_PC98_ARCH) {
/* Keyboard translation tables, must exist at segment 0xFD80:0x0E00 because PC-98 MS-DOS assumes it (it writes 0x522 itself on boot) */
BIOS_PC98_KEYBOARD_TRANSLATION_LOCATION = PhysToReal416(ROMBIOS_GetMemory(0x80/*TODO: multiple tables eventually*/,"Keyboard translation tables",/*align*/1,0xFD800+0xB31));
BIOSKEY_PC98_Write_Tables();
}

write_FFFF_signature();

/* Setup all the interrupt handlers the bios controls */
Expand Down Expand Up @@ -10419,11 +10420,10 @@ class BIOS:public Module_base{
* (0xE31 instead of 0xE28). The table mentioned here is used to update the 0x522 offset WORD in the
* BIOS data area to reflect the translation table in effect based on the shift key status, so if you
* misread the table you end up pointing it at junk and then keyboard input doesn't work anymore. */
// FIXME: This implementation does not yet implement all tables!
// NTS: On a real PC-9821 laptop, the table is apparently 10 entries long. If BDA byte 0x53A is less than
// 8 then it's just a simple lookup. If BDA byte 0x53A has bit 4 set, then use the 8th entry, and
// if bit 4 and 3 are set, use the 9th entry.
for (unsigned int i=0;i < 10;i++) phys_writew(0xFD800+0xE28+(i*2),(unsigned int)(Real2Phys(BIOS_PC98_KEYBOARD_TRANSLATION_LOCATION) - 0xFD800));
for (unsigned int i=0;i < 10;i++) phys_writew(0xFD800+0xE28+(i*2),(unsigned int)(Real2Phys(BIOS_PC98_KEYBOARD_TRANSLATION_LOCATION) - 0xFD800) + (i * 0x60));
}
else {
if (ibm_rom_basic_size == 0) {
Expand Down
61 changes: 56 additions & 5 deletions src/ints/bios_keyboard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -300,11 +300,62 @@ static scancode_tbl scan_to_scanascii_pc98[0x80] = {

void BIOSKEY_PC98_Write_Tables(void) {
unsigned int i;
Bitu o;

/* Assume this function will not be called unless BIOS_PC98_KEYBOARD_TRANSLATION_LOCATION points to ROM BIOS */
o = Real2Phys(BIOS_PC98_KEYBOARD_TRANSLATION_LOCATION);
for (i=0;i < 0x80;i++) phys_writeb(o+i,scan_to_scanascii_pc98[i].normal);
Bitu o = Real2Phys(BIOS_PC98_KEYBOARD_TRANSLATION_LOCATION);

/* Assume this function will not be called unless BIOS_PC98_KEYBOARD_TRANSLATION_LOCATION points to ROM BIOS.
* It's actually not exactly a 1:1 mapping, the empty range between 0x56-0x61 is skipped according to the
* tables on real hardare. On real hardware the tables are noticeably 0x60 (not 0x80) bytes apart from each other.
* Special processing is done for the shift state keys that do not involve the table. */

/* [0] Normal */
for (i=0x00;i < 0x56;i++) phys_writeb(o+i,scan_to_scanascii_pc98[i].normal);
for (i=0x62;i < 0x6C;i++) phys_writeb(o+i,scan_to_scanascii_pc98[i-0xC].normal); /* NTS: 0x62-0x0C = 0x56, 10 codes fill 0x56-0x5F. 0x60-0x56 = 0x0A (10). 0x60 bytes total */
o += 0x60;

/* [1] Shift */
for (i=0x00;i < 0x56;i++) phys_writeb(o+i,scan_to_scanascii_pc98[i].shift);
for (i=0x62;i < 0x6C;i++) phys_writeb(o+i,scan_to_scanascii_pc98[i-0xC].shift); /* NTS: 0x62-0x0C = 0x56, 10 codes fill 0x56-0x5F. 0x60-0x56 = 0x0A (10). 0x60 bytes total */
o += 0x60;

/* [2] Caps */ //FIXME
for (i=0x00;i < 0x56;i++) phys_writeb(o+i,scan_to_scanascii_pc98[i].shift);
for (i=0x62;i < 0x6C;i++) phys_writeb(o+i,scan_to_scanascii_pc98[i-0xC].shift); /* NTS: 0x62-0x0C = 0x56, 10 codes fill 0x56-0x5F. 0x60-0x56 = 0x0A (10). 0x60 bytes total */
o += 0x60;

/* [3] Shift+Caps */ //FIXME
for (i=0x00;i < 0x56;i++) phys_writeb(o+i,scan_to_scanascii_pc98[i].normal);
for (i=0x62;i < 0x6C;i++) phys_writeb(o+i,scan_to_scanascii_pc98[i-0xC].normal); /* NTS: 0x62-0x0C = 0x56, 10 codes fill 0x56-0x5F. 0x60-0x56 = 0x0A (10). 0x60 bytes total */
o += 0x60;

/* [4] Kana */ //FIXME
for (i=0x00;i < 0x56;i++) phys_writeb(o+i,scan_to_scanascii_pc98[i].normal);
for (i=0x62;i < 0x6C;i++) phys_writeb(o+i,scan_to_scanascii_pc98[i-0xC].normal); /* NTS: 0x62-0x0C = 0x56, 10 codes fill 0x56-0x5F. 0x60-0x56 = 0x0A (10). 0x60 bytes total */
o += 0x60;

/* [5] Kana+Shift */ //FIXME
for (i=0x00;i < 0x56;i++) phys_writeb(o+i,scan_to_scanascii_pc98[i].shift);
for (i=0x62;i < 0x6C;i++) phys_writeb(o+i,scan_to_scanascii_pc98[i-0xC].shift); /* NTS: 0x62-0x0C = 0x56, 10 codes fill 0x56-0x5F. 0x60-0x56 = 0x0A (10). 0x60 bytes total */
o += 0x60;

/* [6] Kana+Caps */ //FIXME
for (i=0x00;i < 0x56;i++) phys_writeb(o+i,scan_to_scanascii_pc98[i].shift);
for (i=0x62;i < 0x6C;i++) phys_writeb(o+i,scan_to_scanascii_pc98[i-0xC].shift); /* NTS: 0x62-0x0C = 0x56, 10 codes fill 0x56-0x5F. 0x60-0x56 = 0x0A (10). 0x60 bytes total */
o += 0x60;

/* [7] Kana+Shift+Caps */ //FIXME
for (i=0x00;i < 0x56;i++) phys_writeb(o+i,scan_to_scanascii_pc98[i].normal);
for (i=0x62;i < 0x6C;i++) phys_writeb(o+i,scan_to_scanascii_pc98[i-0xC].normal); /* NTS: 0x62-0x0C = 0x56, 10 codes fill 0x56-0x5F. 0x60-0x56 = 0x0A (10). 0x60 bytes total */
o += 0x60;

/* [8] Kana */ //FIXME
for (i=0x00;i < 0x56;i++) phys_writeb(o+i,scan_to_scanascii_pc98[i].normal);
for (i=0x62;i < 0x6C;i++) phys_writeb(o+i,scan_to_scanascii_pc98[i-0xC].normal); /* NTS: 0x62-0x0C = 0x56, 10 codes fill 0x56-0x5F. 0x60-0x56 = 0x0A (10). 0x60 bytes total */
o += 0x60;

/* [9] Kana+Shift */ //FIXME
for (i=0x00;i < 0x56;i++) phys_writeb(o+i,scan_to_scanascii_pc98[i].shift);
for (i=0x62;i < 0x6C;i++) phys_writeb(o+i,scan_to_scanascii_pc98[i-0xC].shift); /* NTS: 0x62-0x0C = 0x56, 10 codes fill 0x56-0x5F. 0x60-0x56 = 0x0A (10). 0x60 bytes total */
o += 0x60;
}

std::queue <uint16_t>over_key_buffer;
Expand Down

0 comments on commit 3d2f114

Please sign in to comment.