DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator
src/hardware/vga_pc98_cg.cpp
00001 
00002 #include "dosbox.h"
00003 #include "setup.h"
00004 #include "video.h"
00005 #include "pic.h"
00006 #include "vga.h"
00007 #include "inout.h"
00008 #include "programs.h"
00009 #include "support.h"
00010 #include "setup.h"
00011 #include "timer.h"
00012 #include "mem.h"
00013 #include "util_units.h"
00014 #include "control.h"
00015 #include "pc98_cg.h"
00016 #include "pc98_dac.h"
00017 #include "pc98_gdc.h"
00018 #include "pc98_gdc_const.h"
00019 #include "mixer.h"
00020 
00021 #include <string.h>
00022 #include <stdlib.h>
00023 #include <string>
00024 #include <stdio.h>
00025 
00026 /* Character Generator (CG) font access state */
00027 uint16_t                    a1_font_load_addr = 0;
00028 uint8_t                     a1_font_char_offset = 0;
00029 
00030 /* Character Generator ports.
00031  * This is in fact officially documented by NEC in
00032  * a 1986 book published about NEC BIOS and BASIC ROM. */
00033 Bitu pc98_a1_read(Bitu port,Bitu iolen) {
00034     (void)iolen;//UNUSED
00035     switch (port) {
00036         case 0xA9: // an 8-bit I/O port to access font RAM by...
00037             // NOTES: On a PC-9821 Lt2 laptop, the character ROM doesn't seem to latch valid data beyond
00038             //        0xxx5D. Often this reads back as zero, but depending on whatever random data is floating
00039             //        on the bus can read back nonzero. This doesn't apply to 0x0000-0x00FF of course (single wide
00040             //        characters), but only to the double-wide character set where (c & 0x007F) >= 0x5D.
00041             //        This behavior should be emulated. */
00042             return pc98_font_char_read(a1_font_load_addr,a1_font_char_offset & 0xF,(a1_font_char_offset & 0x20) ? 0 : 1);
00043         default:
00044             break;
00045     };
00046 
00047     return ~0ul;
00048 }
00049 
00050 /* Character Generator ports.
00051  * This is in fact officially documented by NEC in
00052  * a 1986 book published about NEC BIOS and BASIC ROM. */
00053 void pc98_a1_write(Bitu port,Bitu val,Bitu iolen) {
00054     (void)iolen;//UNUSED
00055     switch (port) {
00056         /* A3,A1 (out only) two JIS bytes that make up the char code */
00057         case 0xA1:
00058             a1_font_load_addr &= 0x00FF;
00059             a1_font_load_addr |= (val & 0xFF) << 8;
00060             break;
00061         case 0xA3:
00062             a1_font_load_addr &= 0xFF00;
00063             a1_font_load_addr |= (val & 0xFF);
00064             break;
00065         case 0xA5:
00066             /* From documentation:
00067              *
00068              *    bit [7:6] = Dont care
00069              *    bit [5]   = L/R
00070              *    bit [4]   = 0
00071              *    bit [3:0] = C3-C0
00072              *
00073              * This so far is consistent with real hardware behavior */
00074             a1_font_char_offset = val;
00075             break;
00076         case 0xA7:
00077             /* TODO: Various controls for the text layer */
00078             break;
00079         case 0xA9: // an 8-bit I/O port to access font RAM by...
00080                    // this is what Touhou Project uses to load fonts.
00081                    // never mind decompiling INT 18h on real hardware shows instead
00082                    // a similar sequence with REP MOVSW to A400:0000...
00083                    //
00084                    // there's a restriction noted with INT 18h AH=1Ah where the only
00085                    // codes you can overwrite are 0xxx76 and 0xxx77. I'm guessing that
00086                    // having 512KB of RAM out there dedicated to nothing but fonts
00087                    // is probably not economical to NEC's bottom line, and this
00088                    // restriction makes me wonder if the font is held in ROM except
00089                    // for this narrow sliver of codes, which map to about 8KB of RAM
00090                    // (128*2*16) * 2 = 8192 bytes
00091                    //
00092                    // I'm also guessing that this RAM is not involved with the single-wide
00093                    // character set, which is why writes to 0x0056/0x0057 are redirected to
00094                    // 0x8056/0x8057. Without this hack, Touhou Project 2 will overwrite
00095                    // the letter 'W' when loading it's font data (Level 1 will show "Eastern  ind"
00096                    // instead of "Eastern Wind" for the music title as a result).
00097                    //
00098                    // On real hardware it seems, attempts to write anywhere outside 0xxx56/0xxx57
00099                    // are ignored. They are not remapped. Attempts to write to 0x0056 are ignored
00100                    // by the hardware (since that conflicts with single-wide chars) but you can
00101                    // write to that cell if you write to 0x8056 instead.
00102             if ((a1_font_load_addr & 0x007E) == 0x0056 && (a1_font_load_addr & 0xFF00) != 0x0000)
00103                 pc98_font_char_write(a1_font_load_addr,a1_font_char_offset & 0xF,(a1_font_char_offset & 0x20) ? 0 : 1,val);
00104             else
00105                 LOG_MSG("A1 port attempt to write FONT ROM char 0x%x",a1_font_load_addr);
00106             break;
00107         default:
00108             LOG_MSG("A1 port %lx val %lx unexpected",port,val);
00109             break;
00110     };
00111 }
00112