From e5d7c9489c03a3c4aeb2d320af5d308adad83ae9 Mon Sep 17 00:00:00 2001 From: nmlgc Date: Mon, 20 Feb 2023 21:33:15 +0100 Subject: [PATCH] [Platform] [PC-98] Gaiji upload MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Will come in handy for various research programs… 👀 Part of P0232, funded by [Anonymous]. --- platform/x86real/pc98/font.cpp | 46 ++++++++++++++++++++++++++++++++++ platform/x86real/pc98/font.hpp | 16 ++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 platform/x86real/pc98/font.cpp diff --git a/platform/x86real/pc98/font.cpp b/platform/x86real/pc98/font.cpp new file mode 100644 index 00000000..22c58a91 --- /dev/null +++ b/platform/x86real/pc98/font.cpp @@ -0,0 +1,46 @@ +#include "platform.h" +#include "x86real.h" +#include "pc98.h" +#include "planar.h" +#include "shiftjis.hpp" +#include "platform/x86real/pc98/font.hpp" + +// The PC-98 character generator can be accessed in two ways: +// +// 1) I/O ports (0xA1, 0xA3, 0xA5, 0xA9) +// 2) BIOS function INT 18h AH=14h (reading) / AH=18h (writing gaiji) +// +// The BIOS variant is both simpler to use *and* faster, as the BIOS implements +// it in the optimal way for the specific hardware we run on: +// +// • At worst, it's an optimized ASM version of the I/O port code we would +// write ourselves (as seen in the PC-9801VX / PC-9801RA BIOS). +// • At best, it directly reads from and writes to memory after mapping the JIS +// code point to an address, which is always preferable to port I/O (as seen +// in the PC-98HA BIOS). +// • Emulators directly implement it in native code. + +void font_gaiji_write( + const dot_rect_t(GLYPH_FULL_W, GLYPH_H)* gaiji, + uint16_t count, + uint8_t id +) +{ + // Yeah, that copy is kind of silly, but we don't want to force that + // awkward 16×17 format onto the caller. + font_glyph_kanji_t tmp; + + jis_t jis = (0x7680 + id); + for(uint16_t i = 0; i < count; i++) { + tmp.dots = *gaiji; + _BX = FP_SEG(&tmp); + _CX = FP_OFF(&tmp); + _DX = jis; + _DX &= 0xFF7F; + _AH = 0x1A; + geninterrupt(0x18); + + gaiji++; + jis++; + } +} diff --git a/platform/x86real/pc98/font.hpp b/platform/x86real/pc98/font.hpp index 537074a6..4159beda 100644 --- a/platform/x86real/pc98/font.hpp +++ b/platform/x86real/pc98/font.hpp @@ -16,3 +16,19 @@ struct font_glyph_ank_8x16_t : public font_glyph_header_t { struct font_glyph_kanji_t : public font_glyph_header_t { dot_rect_t(GLYPH_FULL_W, GLYPH_H) dots; }; + +// Writes user-defined glyphs to the given offset inside the PC-98 gaiji RAM. +// The 256 possible gaiji IDs are mapped onto JIS X 0208 codepoints as follows: +// +// ((0x7680 + id) & 0xFF7F) +// +// Note that not all PC-98 models support all 256 gaiji codepoints. IDs 0x00 +// and 0x80 are particularly unlikely to be supported, as they collide with +// ASCII 0x56 (V) and 0x57 (W) when written into TRAM. The safest IDs range +// from 0x21 to 0x5F inclusive, which correspond to the gaiji range from the +// first PC-9801 models that supported the feature (PC-9801E/F/M). +void font_gaiji_write( + const dot_rect_t(GLYPH_FULL_W, GLYPH_H)* gaiji, + uint16_t count, + uint8_t first_id +);