summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/drivers/pc9801.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/drivers/pc9801.cpp')
-rw-r--r--src/mame/drivers/pc9801.cpp3887
1 files changed, 3887 insertions, 0 deletions
diff --git a/src/mame/drivers/pc9801.cpp b/src/mame/drivers/pc9801.cpp
new file mode 100644
index 00000000000..8dbb2815924
--- /dev/null
+++ b/src/mame/drivers/pc9801.cpp
@@ -0,0 +1,3887 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese,Carl
+/***************************************************************************************************
+
+ PC-9801 (c) 1981 NEC
+
+ driver by Angelo Salese
+
+ TODO:
+ - proper 8251 uart hook-up on keyboard
+ - SASI /SCSI support;
+ - Write a PC80S31K device (also used on PC-8801 and PC-88VA, it's the FDC + Z80 sub-system);
+ - Finish DIP-Switches support
+ - text scrolling
+ - GRCG+
+ - rewrite using slot devices
+ - some later SWs put "Invalid command byte 05" (Absolutely Mahjong on Epson logo)
+ - investigate on POR bit
+ - test 2dd more
+
+ TODO (PC-9801RS):
+ - extra features;
+ - keyboard shift doesn't seem to disable properly;
+ - clean-up duplicate code;
+
+ TODO (PC-9821):
+ - fix CPU for some clones;
+ - "cache error"
+ - undumped IDE ROM, kludged to work
+ - Compatibility is untested;
+
+ TODO: (PC-486MU)
+ - Tries to read port C of i8255_sys (-> 0x35) at boot without setting up the control
+ port. This causes a jump to invalid program area;
+ - Dies on ARTIC check;
+ - Presumably one ROM is undumped?
+
+ TODO: (PC-9821AP)
+ - No way to exit the initial loop. Code looks broken/bad dump?
+
+ floppy issues TODO (certain fail)
+ - Unsupported disk types: *.nfd, *.fdd, *.nhd
+ - 46 Okunen Monogatari - The Shinkaron
+ - AD&D Champions of Krynn
+ - AI Shougi (asserts upon loading, 3'5 image?)
+ - Aki no Tsukasa no Fushigi no Kabe (works in PC-9801RS only)
+ - Aoki Ookami no Shiroki Mejika - Gengis Khan
+ - Arcshu
+ - Arcus 2
+ - Art Jigsaw
+ - Atlantia (disk swap?)
+ - Azusa 108 Jimusho
+ - Bacta 2
+ - BattleTech (disk swap?)
+ - Bay City Elegy (disk swap?)
+ - Beast (keeps reading command sense)
+ - Beast 2
+ - Bells Avenue (disk swap?)
+ - Bible Master 2 (at new game loading)
+ - Birdy World
+
+ - Bokosuka Wars
+ - Jangou 2: floppy fails to load after the title screen;
+
+ List of per-game TODO:
+ - 38 Man Kilo no Kokuu: doesn't seem possible to skip the intro?
+ - 4D Boxing: inputs are unresponsive
+ - A Ressha de Ikou 2: missing text (PC-9801RS only);
+ - Absolutely Mahjong: Transitions are too fast.
+ - Agumix Selects!: needs GDC = 5 MHz, interlace doesn't work properly;
+ - Alice no Yakata: doesn't set bitmap interlace properly, can't do disk swaps via the File Manager;
+ - Anniversary - Memories of Summer: thinks that a button is pressed;
+ - Another Genesis: fails loading;
+ - Apple Club 1: how to pass an hand?
+ - Arctic: keyboard doesn't work?
+ - Arcus 3: moans with a JP message "not enough memory (needs 640kb to start)";
+ - Armored Flagship Atragon: needs HDD install
+ - Arquephos: needs extra sound board(s)?
+ - Asoko no Koufuku: black screen with BGM, waits at 0x225f6;
+ - Band-Kun: (how to run this without installing?)
+ - Battle Chess: wants some dip-switches to be on in DSW4, too slow during IA thinking?
+ - Bishoujo Audition: Moans with a "(program) ended. remove the floppy disk and turn off the poewr."
+ - Bishoujo Hunter ZX: Doesn't color cycle at intro (seems stuck?), doesn't clear text selection at new game screen;
+ - Bishoujo Shanshinkan: has white rectangles all over the place;
+ - Bishoujo Tsuushin: hangs with a beep while writing some intro text;
+
+ - Bomber Quest: beeps when speech is supposed to be played (0->1 to i/o port 0xfe8e?)
+ - Deflektor: no sound, moans about a DIP-sw during loading, very slow on non-pc9801rs machines;
+ - Dragon Buster: slight issue with window masking;
+ - Far Side Moon: doesn't detect sound board (tied to 0x00ec ports)
+ - Jan Borg Suzume: gets stuck at a pic8259 read;
+ - Karateka: no sound?
+ - Lovely Horror: Doesn't show kanji, tries to read it thru the 0xa9 port;
+ - Madou Monogatari 1/2/3: doesn't display bitmap gfxs during gameplay;
+ - Quarth: title screen is broken after first attract play;
+ - Princess Maker 2: mouse is buggy;
+ - Princess Maker 2: screen transitions are very ugly (btanb?)
+ - Puyo Puyo: beeps out when it's supposed to play samples, Not supposed to use ADPCM, is it a PIT issue?
+ - Puzznic: trips illegal irq 0x41 (?), prints an error on screen. (PC-9801RS only, writes an 1 to 0x69d2f for whatever reason, almost surely a btanb)
+ - Runner's High: wrong double height on the title screen;
+ - Sokoban Perfect: hangs at title screen, after loading the menu;
+ - Sorcerian, Twilight Zone 3: Fails initial booting, issue with 2dd irq?
+ - The Incredible Machine: hangs at main menu (YM mis-fires irq?)
+ - Uchiyama Aki no Chou Bangai: keyboard irq is fussy (sometimes it doesn't register a key press);
+ - Uno: has minor EGC gfx bugs;
+ - Windows 2: EGC drawing issue (byte wide writes?)
+
+ per-game TODO (PC-9821):
+ - Battle Skin Panic: gfx bugs at the Gainax logo, it crashes after it;
+ - Policenauts: EMS error at boot;
+
+ Notes:
+ - Animahjong V3 makes advantage of the possibility of installing 2 sound boards, where SFX and BGMs are played on separate chips.
+ - Apple Club 1/2 needs data disks to load properly;
+ - Beast Lord: needs a titan.fnt, in MS-DOS
+ - To deprotect BASIC modules set 0xcd7 in ram to 0
+
+========================================================================================
+
+ This series features a huge number of models released between 1982 and 1997. They
+ were not IBM PC-compatible, but they had similar hardware (and software: in the
+ 1990s, they run MS Windows as OS)
+
+ Models:
+
+ | CPU | RAM | Drives | CBus| Release |
+ PC-9801 | 8086 @ 5 | 128 KB | - | 6 | 1982/10 |
+ PC-9801F1 | 8086-2 @ 5/8 | 128 KB | 5"2DDx1 | 4 | 1983/10 |
+ PC-9801F2 | 8086-2 @ 5/8 | 128 KB | 5"2DDx2 | 4 | 1983/10 |
+ PC-9801E | 8086-2 @ 5/8 | 128 KB | - | 6 | 1983/11 |
+ PC-9801F3 | 8086-2 @ 5/8 | 256 KB | 5"2DDx1, 10M SASI HDD | 2 | 1984/10 |
+ PC-9801M2 | 8086-2 @ 5/8 | 256 KB | 5"2HDx2 | 4 | 1984/11 |
+ PC-9801M3 | 8086-2 @ 5/8 | 256 KB | 5"2HDx1, 20M SASI HDD | 3 | 1985/02 |
+ PC-9801U2 | V30 @ 8 | 128 KB | 3.5"2HDx2 | 2 | 1985/05 |
+ PC-98XA1 | 80286 @ 8 | 512 KB | - | 6 | 1985/05 |
+ PC-98XA2 | 80286 @ 8 | 512 KB | 5"2DD/2HDx2 | 6 | 1985/05 |
+ PC-98XA3 | 80286 @ 8 | 512 KB | 5"2DD/2HDx1, 20M SASI HDD | 6 | 1985/05 |
+ PC-9801VF2 | V30 @ 8 | 384 KB | 5"2DDx2 | 4 | 1985/07 |
+ PC-9801VM0 | V30 @ 8/10 | 384 KB | - | 4 | 1985/07 |
+ PC-9801VM2 | V30 @ 8/10 | 384 KB | 5"2DD/2HDx2 | 4 | 1985/07 |
+ PC-9801VM4 | V30 @ 8/10 | 384 KB | 5"2DD/2HDx2, 20M SASI HDD | 4 | 1985/10 |
+ PC-98XA11 | 80286 @ 8 | 512 KB | - | 6 | 1986/05 |
+ PC-98XA21 | 80286 @ 8 | 512 KB | 5"2DD/2HDx2 | 6 | 1986/05 |
+ PC-98XA31 | 80286 @ 8 | 512 KB | 5"2DD/2HDx1, 20M SASI HDD | 6 | 1986/05 |
+ PC-9801UV2 | V30 @ 8/10 | 384 KB | 3.5"2DD/2HDx2 | 2 | 1986/05 |
+ PC-98LT1 | V50 @ 8 | 384 KB | 3.5"2DD/2HDx1 | 0 | 1986/11 |
+ PC-98LT2 | V50 @ 8 | 384 KB | 3.5"2DD/2HDx1 | 0 | 1986/11 |
+ PC-9801VM21 | V30 @ 8/10 | 640 KB | 5"2DD/2HDx2 | 4 | 1986/11 |
+ PC-9801VX0 | 80286 @ 8 & V30 @ 8/10 | 640 KB | - | 4 | 1986/11 |
+ PC-9801VX2 | 80286 @ 8 & V30 @ 8/10 | 640 KB | 5"2DD/2HDx2 | 4 | 1986/11 |
+ PC-9801VX4 | 80286 @ 8 & V30 @ 8/10 | 640 KB | 5"2DD/2HDx2, 20M SASI HDD | 4 | 1986/11 |
+ PC-9801VX4/WN | 80286 @ 8 & V30 @ 8/10 | 640 KB | 5"2DD/2HDx2, 20M SASI HDD | 4 | 1986/11 |
+ PC-98XL1 | 80286 @ 8 & V30 @ 8/10 | 1152 KB | - | 4 | 1986/12 |
+ PC-98XL2 | 80286 @ 8 & V30 @ 8/10 | 1152 KB | 5"2DD/2HDx2 | 4 | 1986/12 |
+ PC-98XL4 | 80286 @ 8 & V30 @ 8/10 | 1152 KB | 5"2DD/2HDx1, 20M SASI HDD | 4 | 1986/12 |
+ PC-9801VX01 | 80286-10 @ 8/10 & V30 @ 8/10 | 640 KB | - | 4 | 1987/06 |
+ PC-9801VX21 | 80286-10 @ 8/10 & V30 @ 8/10 | 640 KB | 5"2DD/2HDx2 | 4 | 1987/06 |
+ PC-9801VX41 | 80286-10 @ 8/10 & V30 @ 8/10 | 640 KB | 5"2DD/2HDx2, 20M SASI HDD | 4 | 1987/06 |
+ PC-9801UV21 | V30 @ 8/10 | 640 KB | 3.5"2DD/2HDx2 | 2 | 1987/06 |
+ PC-98XL^2 | i386DX-16 @ 16 & V30 @ 8 | 1.6 MB | 5"2DD/2HDx2, 40M SASI HDD | 4 | 1987/10 |
+ PC-98LT11 | V50 @ 8 | 640 KB | 3.5"2DD/2HDx1 | 0 | 1987/10 |
+ PC-98LT21 | V50 @ 8 | 640 KB | 3.5"2DD/2HDx1 | 0 | 1987/10 |
+ PC-9801UX21 | 80286-10 @ 10 & V30 @ 8 | 640 KB | 3.5"2DD/2HDx2 | 3 | 1987/10 |
+ PC-9801UX41 | 80286-10 @ 10 & V30 @ 8 | 640 KB | 3.5"2DD/2HDx2, 20M SASI HDD | 3 | 1987/10 |
+ PC-9801LV21 | V30 @ 8/10 | 640 KB | 3.5"2DD/2HDx2 | 0 | 1988/03 |
+ PC-9801CV21 | V30 @ 8/10 | 640 KB | 3.5"2DD/2HDx2 | 2 | 1988/03 |
+ PC-9801UV11 | V30 @ 8/10 | 640 KB | 3.5"2DD/2HDx2 | 2 | 1988/03 |
+ PC-9801RA2 | i386DX-16 @ 16 & V30 @ 8 | 1.6 MB | 5"2DD/2HDx2 | 4 | 1988/07 |
+ PC-9801RA5 | i386DX-16 @ 16 & V30 @ 8 | 1.6 MB | 5"2DD/2HDx2, 40M SASI HDD | 4 | 1988/07 |
+ PC-9801RX2 | 80286-12 @ 10/12 & V30 @ 8 | 640 KB | 5"2DD/2HDx2 | 4 | 1988/07 |
+ PC-9801RX4 | 80286-12 @ 10/12 & V30 @ 8 | 640 KB | 5"2DD/2HDx2, 20M SASI HDD | 4 | 1988/07 |
+ PC-98LT22 | V50 @ 8 | 640 KB | 3.5"2DD/2HDx1 | 0 | 1988/11 |
+ PC-98LS2 | i386SX-16 @ 16 & V30 @ 8 | 1.6 MB | 5"2DD/2HDx2 | 0 | 1988/11 |
+ PC-98LS5 | i386SX-16 @ 16 & V30 @ 8 | 1.6 MB | 5"2DD/2HDx2, 40M SASI HDD | 0 | 1988/11 |
+ PC-9801VM11 | V30 @ 8/10 | 640 KB | 5"2DD/2HDx2 | 4 | 1988/11 |
+ PC-9801LV22 | V30 @ 8/10 | 640 KB | 3.5"2DD/2HDx2 | 0 | 1989/01 |
+ PC-98RL2 | i386DX-20 @ 16/20 & V30 @ 8 | 1.6 MB | 5"2DD/2HDx2 | 4 | 1989/02 |
+ PC-98RL5 | i386DX-20 @ 16/20 & V30 @ 8 | 1.6 MB | 5"2DD/2HDx2, 40M SASI HDD | 4 | 1989/02 |
+ PC-9801EX2 | 80286-12 @ 10/12 & V30 @ 8 | 640 KB | 3.5"2DD/2HDx2 | 3 | 1989/04 |
+ PC-9801EX4 | 80286-12 @ 10/12 & V30 @ 8 | 640 KB | 3.5"2DD/2HDx2, 20M SASI HDD | 3 | 1989/04 |
+ PC-9801ES2 | i386SX-16 @ 16 & V30 @ 8 | 1.6 MB | 3.5"2DD/2HDx2 | 3 | 1989/04 |
+ PC-9801ES5 | i386SX-16 @ 16 & V30 @ 8 | 1.6 MB | 3.5"2DD/2HDx2, 40M SASI HDD | 3 | 1989/04 |
+ PC-9801LX2 | 80286-12 @ 10/12 & V30 @ 8 | 640 KB | 3.5"2DD/2HDx2 | 0 | 1989/04 |
+ PC-9801LX4 | 80286-12 @ 10/12 & V30 @ 8 | 640 KB | 3.5"2DD/2HDx2, 20M SASI HDD | 0 | 1989/04 |
+ PC-9801LX5 | 80286-12 @ 10/12 & V30 @ 8 | 640 KB | 3.5"2DD/2HDx2, 40M SASI HDD | 0 | 1989/06 |
+ PC-98DO | V30 @ 8/10 | 640 KB | 5"2DD/2HDx2 | 1 | 1989/06 |
+ PC-9801LX5C | 80286-12 @ 10/12 & V30 @ 8 | 640 KB | 3.5"2DD/2HDx2, 40M SASI HDD | 0 | 1989/06 |
+ PC-9801RX21 | 80286-12 @ 10/12 & V30 @ 8 | 640 KB | 5"2DD/2HDx2 | 4 | 1989/10 |
+ PC-9801RX51 | 80286-12 @ 10/12 & V30 @ 8 | 640 KB | 5"2DD/2HDx2, 40M SASI HDD | 4 | 1989/10 |
+ PC-9801RA21 | i386DX-20 @ 16/20 & V30 @ 8 | 1.6 MB | 5"2DD/2HDx2 | 4 | 1989/11 |
+ PC-9801RA51 | i386DX-20 @ 16/20 & V30 @ 8 | 1.6 MB | 5"2DD/2HDx2, 40M SASI HDD | 4 | 1989/11 |
+ PC-9801RS21 | i386SX-16 @ 16 & V30 @ 8 | 640 KB | 5"2DD/2HDx2 | 4 | 1989/11 |
+ PC-9801RS51 | i386SX-16 @ 16 & V30 @ 8 | 640 KB | 5"2DD/2HDx2, 40M SASI HDD | 4 | 1989/11 |
+ PC-9801N | V30 @ 10 | 640 KB | 3.5"2DD/2HDx1 | 0 | 1989/11 |
+ PC-9801TW2 | i386SX-20 @ 20 & V30 @ 8 | 640 KB | 3.5"2DD/2HDx2 | 2 | 1990/02 |
+ PC-9801TW5 | i386SX-20 @ 20 & V30 @ 8 | 1.6 MB | 3.5"2DD/2HDx2, 40M SASI HDD | 2 | 1990/02 |
+ PC-9801TS5 | i386SX-20 @ 20 & V30 @ 8 | 1.6 MB | 3.5"2DD/2HDx2, 40M SASI HDD | 2 | 1990/06 |
+ PC-9801NS | i386SX-12 @ 12 | 1.6 MB | 3.5"2DD/2HDx1 | 0 | 1990/06 |
+ PC-9801TF5 | i386SX-20 @ 20 & V30 @ 8 | 1.6 MB | 3.5"2DD/2HDx2, 40M SASI HDD | 2 | 1990/07 |
+ PC-9801NS-20 | i386SX-12 @ 12 | 1.6 MB | 3.5"2DD/2HDx1, 20M SASI HDD | 0 | 1990/09 |
+ PC-98RL21 | i386DX-20 @ 20 & V30 @ 8 | 1.6 MB | 5"2DD/2HDx2 | 4 | 1990/09 |
+ PC-98RL51 | i386DX-20 @ 20 & V30 @ 8 | 1.6 MB | 5"2DD/2HDx1, 40M SASI HDD | 4 | 1990/09 |
+ PC-98DO+ | V33A @ 8/16 | 640 KB | 5"2DD/2HDx2 | 1 | 1990/10 |
+ PC-9801DX2 | 80286-12 @ 10/12 & V30 @ 8 | 640 KB | 5"2DD/2HDx2 | 4 | 1990/11 |
+ PC-9801DX/U2 | 80286-12 @ 10/12 & V30 @ 8 | 640 KB | 3.5"2DD/2HDx2 | 4 | 1990/11 |
+ PC-9801DX5 | 80286-12 @ 10/12 & V30 @ 8 | 640 KB | 5"2DD/2HDx2, 40M SASI HDD | 4 | 1990/11 |
+ PC-9801DX/U5 | 80286-12 @ 10/12 & V30 @ 8 | 640 KB | 3.5"2DD/2HDx2, 40M SASI HDD | 4 | 1990/11 |
+ PC-9801NV | V30HL @ 8/16 | 1.6 MB | 3.5"2DD/2HDx1 | 0 | 1990/11 |
+ PC-9801DS2 | i386SX-16 @ 16 & V30 @ 8 | 640 KB | 5"2DD/2HDx2 | 4 | 1991/01 |
+ PC-9801DS/U2 | i386SX-16 @ 16 & V30 @ 8 | 640 KB | 3.5"2DD/2HDx2 | 4 | 1991/01 |
+ PC-9801DS5 | i386SX-16 @ 16 & V30 @ 8 | 640 KB | 5"2DD/2HDx2, 40M SASI HDD | 4 | 1991/01 |
+ PC-9801DS/U5 | i386SX-16 @ 16 & V30 @ 8 | 640 KB | 3.5"2DD/2HDx2, 40M SASI HDD | 4 | 1991/01 |
+ PC-9801DA2 | i386DX-20 @ 16/20 & V30 @ 8 | 1.6 MB | 5"2DD/2HDx2 | 4 | 1991/01 |
+ PC-9801DA/U2 | 80286-12 @ 10/12 & V30 @ 8 | 640 KB | 3.5"2DD/2HDx2 | 4 | 1991/01 |
+ PC-9801DA5 | 80286-12 @ 10/12 & V30 @ 8 | 640 KB | 5"2DD/2HDx2, 40M SASI HDD | 4 | 1991/01 |
+ PC-9801DA/U5 | 80286-12 @ 10/12 & V30 @ 8 | 640 KB | 3.5"2DD/2HDx2, 40M SASI HDD | 4 | 1991/01 |
+ PC-9801DA7 | 80286-12 @ 10/12 & V30 @ 8 | 640 KB | 5"2DD/2HDx2, 100M SCSI HDD | 4 | 1991/02 |
+ PC-9801DA/U7 | 80286-12 @ 10/12 & V30 @ 8 | 640 KB | 3.5"2DD/2HDx2, 100M SCSI HDD | 4 | 1991/02 |
+ PC-9801UF | V30 @ 8/16 | 640 KB | 3.5"2DD/2HDx2 | 2 | 1991/02 |
+ PC-9801UR | V30 @ 8/16 | 640 KB | 3.5"2DD/2HDx1, 1.25MB RAM Disk | 2 | 1991/02 |
+ PC-9801UR/20 | V30 @ 8/16 | 640 KB | 3.5"2DD/2HDx1, 1.25MB RAM Disk, 20M SASI HDD | 2 | 1991/02 |
+ PC-9801NS/E | i386SX-16 @ 16 | 1.6 MB | 3.5"2DD/2HDx1, 1.25MB RAM Disk | 0 | 1991/06 |
+ PC-9801NS/E20 | i386SX-16 @ 16 | 1.6 MB | 3.5"2DD/2HDx1, 1.25MB RAM Disk, 20M SASI HDD | 0 | 1991/06 |
+ PC-9801NS/E40 | i386SX-16 @ 16 | 1.6 MB | 3.5"2DD/2HDx1, 1.25MB RAM Disk, 40M SASI HDD | 0 | 1991/06 |
+ PC-9801TW7 | i386SX-20 @ 20 & V30 @ 8 | 1.6 MB | 3.5"2DD/2HDx2, 100M SCSI HDD | 2 | 1991/07 |
+ PC-9801TF51 | i386SX-20 @ 20 & V30 @ 8 | 1.6 MB | 3.5"2DD/2HDx2, 40M SASI HDD | 2 | 1991/07 |
+ PC-9801TF71 | i386SX-20 @ 20 & V30 @ 8 | 1.6 MB | 3.5"2DD/2HDx2, 100M SCSI HDD | 2 | 1991/07 |
+ PC-9801NC | i386SX-20 @ 20 | 2.6 MB | 3.5"2DD/2HDx1, 1.25MB RAM Disk | 0 | 1991/10 |
+ PC-9801NC40 | i386SX-20 @ 20 | 2.6 MB | 3.5"2DD/2HDx1, 1.25MB RAM Disk, 40M SASI HDD | 0 | 1991/10 |
+ PC-9801CS2 | i386SX-16 @ 16 | 640 KB | 3.5"2DD/2HDx2 | 2 | 1991/10 |
+ PC-9801CS5 | i386SX-16 @ 16 | 640 KB | 3.5"2DD/2HDx2, 40M SASI HDD | 2 | 1991/10 |
+ PC-9801CS5/W | i386SX-16 @ 16 | 3.6 MB | 3.5"2DD/2HDx2, 40M SASI HDD | 2 | 1991/11 |
+ PC-98GS1 | i386SX-20 @ 20 & V30 @ 8 | 2.6 MB | 3.5"2DD/2HDx2, 40M SASI HDD | 3 | 1991/11 |
+ PC-98GS2 | i386SX-20 @ 20 & V30 @ 8 | 2.6 MB | 3.5"2DD/2HDx2, 40M SASI HDD, 1xCD-ROM | 3 | 1991/11 |
+ PC-9801FA2 | i486SX-16 @ 16 | 1.6 MB | 5"2DD/2HDx2 | 4 | 1992/01 |
+ PC-9801FA/U2 | i486SX-16 @ 16 | 1.6 MB | 3.5"2DD/2HDx2 | 4 | 1992/01 |
+ PC-9801FA5 | i486SX-16 @ 16 | 1.6 MB | 5"2DD/2HDx2, 40M SCSI HDD | 4 | 1992/01 |
+ PC-9801FA/U5 | i486SX-16 @ 16 | 1.6 MB | 3.5"2DD/2HDx2, 40M SCSI HDD | 4 | 1992/01 |
+ PC-9801FA7 | i486SX-16 @ 16 | 1.6 MB | 5"2DD/2HDx2, 100M SCSI HDD | 4 | 1992/01 |
+ PC-9801FA/U7 | i486SX-16 @ 16 | 1.6 MB | 3.5"2DD/2HDx2, 100M SCSI HDD | 4 | 1992/01 |
+ PC-9801FS2 | i386SX-20 @ 16/20 | 1.6 MB | 5"2DD/2HDx2 | 4 | 1992/05 |
+ PC-9801FS/U2 | i386SX-20 @ 16/20 | 1.6 MB | 3.5"2DD/2HDx2 | 4 | 1992/05 |
+ PC-9801FS5 | i386SX-20 @ 16/20 | 1.6 MB | 5"2DD/2HDx2, 40M SCSI HDD | 4 | 1992/05 |
+ PC-9801FS/U5 | i386SX-20 @ 16/20 | 1.6 MB | 3.5"2DD/2HDx2, 40M SCSI HDD | 4 | 1992/05 |
+ PC-9801FS7 | i386SX-20 @ 16/20 | 1.6 MB | 5"2DD/2HDx2, 100M SCSI HDD | 4 | 1992/01 |
+ PC-9801FS/U7 | i386SX-20 @ 16/20 | 1.6 MB | 3.5"2DD/2HDx2, 100M SCSI HDD | 4 | 1992/01 |
+ PC-9801NS/T | i386SL(98) @ 20 | 1.6 MB | 3.5"2DD/2HDx1, 1.25MB RAM Disk | 0 | 1992/01 |
+ PC-9801NS/T40 | i386SL(98) @ 20 | 1.6 MB | 3.5"2DD/2HDx1, 1.25MB RAM Disk, 40M SASI HDD | 0 | 1992/01 |
+ PC-9801NS/T80 | i386SL(98) @ 20 | 1.6 MB | 3.5"2DD/2HDx1, 1.25MB RAM Disk, 80M SASI HDD | 0 | 1992/01 |
+ PC-9801NL | V30H @ 8/16 | 640 KB | 1.25 MB RAM Disk | 0 | 1992/01 |
+ PC-9801FX2 | i386SX-12 @ 10/12 | 1.6 MB | 5"2DD/2HDx2 | 4 | 1992/05 |
+ PC-9801FX/U2 | i386SX-12 @ 10/12 | 1.6 MB | 3.5"2DD/2HDx2 | 4 | 1992/05 |
+ PC-9801FX5 | i386SX-12 @ 10/12 | 1.6 MB | 5"2DD/2HDx2, 40M SCSI HDD | 4 | 1992/05 |
+ PC-9801FX/U5 | i386SX-12 @ 10/12 | 1.6 MB | 3.5"2DD/2HDx2, 40M SCSI HDD | 4 | 1992/05 |
+ PC-9801US | i386SX-16 @ 16 | 1.6 MB | 3.5"2DD/2HDx2 | 2 | 1992/07 |
+ PC-9801US40 | i386SX-16 @ 16 | 1.6 MB | 3.5"2DD/2HDx2, 40M SASI HDD | 2 | 1992/07 |
+ PC-9801US80 | i386SX-16 @ 16 | 1.6 MB | 3.5"2DD/2HDx2, 80M SASI HDD | 2 | 1992/07 |
+ PC-9801NS/L | i386SX-20 @ 10/20 | 1.6 MB | 3.5"2DD/2HDx1, 1.25MB RAM Disk | 0 | 1992/07 |
+ PC-9801NS/L40 | i386SX-20 @ 10/20 | 1.6 MB | 3.5"2DD/2HDx1, 1.25MB RAM Disk, 40M SASI HDD | 0 | 1992/07 |
+ PC-9801NA | i486SX-20 @ 20 | 2.6 MB | 3.5"2DD/2HDx1, 1.25MB RAM Disk | 0 | 1992/11 |
+ PC-9801NA40 | i486SX-20 @ 20 | 2.6 MB | 3.5"2DD/2HDx1, 1.25MB RAM Disk, 40M SASI HDD | 0 | 1992/11 |
+ PC-9801NA120 | i486SX-20 @ 20 | 2.6 MB | 3.5"2DD/2HDx1, 1.25MB RAM Disk, 120M SASI HDD | 0 | 1992/11 |
+ PC-9801NA/C | i486SX-20 @ 20 | 2.6 MB | 3.5"2DD/2HDx1, 1.25MB RAM Disk | 0 | 1992/11 |
+ PC-9801NA40/C | i486SX-20 @ 20 | 2.6 MB | 3.5"2DD/2HDx1, 1.25MB RAM Disk, 40M SASI HDD | 0 | 1992/11 |
+ PC-9801NA120/C | i486SX-20 @ 20 | 2.6 MB | 3.5"2DD/2HDx1, 1.25MB RAM Disk, 120M SASI HDD | 0 | 1992/11 |
+ PC-9801NS/R | i486SX(J) @ 20 | 1.6 MB | 3.5"2DD/2HDx1 (3mode), 1.25MB RAM Disk | 0 | 1993/01 |
+ PC-9801NS/R40 | i486SX(J) @ 20 | 1.6 MB | 3.5"2DD/2HDx1 (3mode), 1.25MB RAM Disk, 40M SASI HDD | 0 | 1993/01 |
+ PC-9801NS/R120 | i486SX(J) @ 20 | 1.6 MB | 3.5"2DD/2HDx1 (3mode), 1.25MB RAM Disk, 120M SASI HDD | 0 | 1993/01 |
+ PC-9801BA/U2 | i486DX2-40 @ 40 | 1.6 MB | 3.5"2DD/2HDx2 | 3 | 1993/01 |
+ PC-9801BA/U6 | i486DX2-40 @ 40 | 3.6 MB | 3.5"2DD/2HDx1, 40M SASI HDD | 3 | 1993/01 |
+ PC-9801BA/M2 | i486DX2-40 @ 40 | 1.6 MB | 5"2DD/2HDx2 | 3 | 1993/01 |
+ PC-9801BX/U2 | i486SX-20 @ 20 | 1.6 MB | 3.5"2DD/2HDx2 | 3 | 1993/01 |
+ PC-9801BX/U6 | i486SX-20 @ 20 | 3.6 MB | 3.5"2DD/2HDx1, 40M SASI HDD | 3 | 1993/01 |
+ PC-9801BX/M2 | i486SX-20 @ 20 | 1.6 MB | 5"2DD/2HDx2 | 3 | 1993/01 |
+ PC-9801NX/C | i486SX(J) @ 20 | 1.6 MB | 3.5"2DD/2HDx1, 1.25MB RAM Disk | 0 | 1993/07 |
+ PC-9801NX/C120 | i486SX(J) @ 20 | 3.6 MB | 3.5"2DD/2HDx1, 1.25MB RAM Disk | 0 | 1993/07 |
+ PC-9801P40/D | i486SX(J) @ 20 | 5.6 MB | 40MB IDE HDD | 0 | 1993/07 |
+ PC-9801P80/W | i486SX(J) @ 20 | 7.6 MB | 80MB IDE HDD | 0 | 1993/07 |
+ PC-9801P80/P | i486SX(J) @ 20 | 7.6 MB | 80MB IDE HDD | 0 | 1993/07 |
+ PC-9801BA2/U2 | i486DX2-66 @ 66 | 3.6 MB | 3.5"2DD/2HDx2 | 3 | 1993/11 |
+ PC-9801BA2/U7 | i486DX2-66 @ 66 | 3.6 MB | 3.5"2DD/2HDx1, 120MB IDE HDD | 3 | 1993/11 |
+ PC-9801BA2/M2 | i486DX2-66 @ 66 | 3.6 MB | 5"2DD/2HDx2 | 3 | 1993/11 |
+ PC-9801BS2/U2 | i486SX-33 @ 33 | 3.6 MB | 3.5"2DD/2HDx2 | 3 | 1993/11 |
+ PC-9801BS2/U7 | i486SX-33 @ 33 | 3.6 MB | 3.5"2DD/2HDx1, 120MB IDE HDD | 3 | 1993/11 |
+ PC-9801BS2/M2 | i486SX-33 @ 33 | 3.6 MB | 5"2DD/2HDx2 | 3 | 1993/11 |
+ PC-9801BX2/U2 | i486SX-25 @ 25 | 1.8 MB | 3.5"2DD/2HDx2 | 3 | 1993/11 |
+ PC-9801BX2/U7 | i486SX-25 @ 25 | 3.6 MB | 3.5"2DD/2HDx1, 120MB IDE HDD | 3 | 1993/11 |
+ PC-9801BX2/M2 | i486SX-25 @ 25 | 1.8 MB | 5"2DD/2HDx2 | 3 | 1993/11 |
+ PC-9801BA3/U2 | i486DX-66 @ 66 | 3.6 MB | 3.5"2DD/2HDx2 | 3 | 1995/01 |
+ PC-9801BA3/U2/W | i486DX-66 @ 66 | 7.6 MB | 3.5"2DD/2HDx2, 210MB IDE HDD | 3 | 1995/01 |
+ PC-9801BX3/U2 | i486SX-33 @ 33 | 1.6 MB | 3.5"2DD/2HDx2 | 3 | 1995/01 |
+ PC-9801BX3/U2/W | i486SX-33 @ 33 | 5.6 MB | 3.5"2DD/2HDx2, 210MB IDE HDD | 3 | 1995/01 |
+ PC-9801BX4/U2 | AMD/i 486DX2-66 @ 66 | 2 MB | 3.5"2DD/2HDx2 | 3 | 1995/07 |
+ PC-9801BX4/U2/C | AMD/i 486DX2-66 @ 66 | 2 MB | 3.5"2DD/2HDx2, 2xCD-ROM | 3 | 1995/07 |
+ PC-9801BX4/U2-P | Pentium ODP @ 66 | 2 MB | 3.5"2DD/2HDx2 | 3 | 1995/09 |
+ PC-9801BX4/U2/C-P | Pentium ODP @ 66 | 2 MB | 3.5"2DD/2HDx2, 2xCD-ROM | 3 | 1995/09 |
+
+ For more info (e.g. optional hardware), see http://www.geocities.jp/retro_zzz/machines/nec/9801/mdl98cpu.html
+
+
+ PC-9821 Series
+
+ PC-9821 (1992) - aka 98MULTi, desktop computer, 386 based
+ PC-9821A series (1993->1994) - aka 98MATE A, desktop computers, 486 based
+ PC-9821B series (1993) - aka 98MATE B, desktop computers, 486 based
+ PC-9821C series (1993->1996) - aka 98MULTi CanBe, desktop & tower computers, various CPU
+ PC-9821Es (1994) - aka 98FINE, desktop computer with integrated LCD, successor of the PC-98T
+ PC-9821X series (1994->1995) - aka 98MATE X, desktop computers, Pentium based
+ PC-9821V series (1995) - aka 98MATE Valuestar, desktop computers, Pentium based
+ PC-9821S series (1995->2996) - aka 98Pro, tower computers, PentiumPro based
+ PC-9821R series (1996->2000) - aka 98MATE R, desktop & tower & server computers, various CPU
+ PC-9821C200 (1997) - aka CEREB, desktop computer, Pentium MMX based
+ PC-9821 Ne/Ns/Np/Nm (1993->1995) - aka 98NOTE, laptops, 486 based
+ PC-9821 Na/Nb/Nw (1995->1997) - aka 98NOTE Lavie, laptops, Pentium based
+ PC-9821 Lt/Ld (1995) - aka 98NOTE Light, laptops, 486 based
+ PC-9821 La/Ls (1995->1997) - aka 98NOTE Aile, laptops, Pentium based
+
+====
+
+Documentation notes (for unemulated stuff, courtesy of T. Kodaka and T. Kono):
+
+IDE:
+(r/w)
+0x430: IDE drive switch
+0x432: IDE drive switch
+0x435: <unknown>
+
+ (ISA correlated i/o)
+----------------------------------------------------------
+0x0640 |WORD|R/W|Data Register |01F0h
+0x0642 |BYTE| R |Error Register |01F1h
+0x0642 |BYTE| W |Write Precomp Register |01F1h
+0x0644 |BYTE|R/W|Sector Count |01F2h
+0x0646 |BYTE|R/W|Sector Number |01F3h
+0x0648 |BYTE|R/W|Cylinder Low |01F4h
+0x064A |BYTE|R/W|Cylinder High |01F5h
+0x064C |BYTE|R/W|SDH Register |01F6h
+0x064E |BYTE| R |Status Register |01F7h
+0x064E |BYTE| W |Command Register |01F7h
+0x074C |BYTE| R |Alternate Status Register |03F6h
+0x074C |BYTE| W |Digital Output Register |03F6h
+0x074E |BYTE| R |Digital Input Register |03F7h
+
+Video F/F (i/o 0x68):
+KAC mode (video ff = 5) is basically how the kanji ROM could be accessed, 1=thru the CG window ports, 0=thru the kanji
+window RAM at 0xa4***.
+My guess is that the system locks up or doesn't have any data if the wrong port is being accessed.
+
+Ext Video F/F (i/o 0x6a):
+0000 011x enables EGC
+0000 111x enables PC-98GS
+0010 000x enables multicolor (a.k.a. 256 colors mode)
+0010 001x enables 65'536 colors
+0010 010x 64k color palette related (?)
+0010 011x full screen reverse (?)
+0010 100x text and gfxs synthesis (?)
+0010 101x 256 color palette registers fast write (?)
+0010 110x 256 color overscan (?)
+0100 000x (0) CRT (1) Plasma/LCD
+0100 001x text and gfxs right shifted one dot (undocumented behaviour)
+0100 010x hi-res mode in PC-9821
+0110 000x EEGC mode
+0110 001x VRAM config (0) plain (1) packed
+0110 011x AGDC mode
+0110 100x 480 lines
+0110 110x VRAM bitmap orientation (0) MSB left-to-right LSB (1) LSB left-to-right MSB
+1000 001x CHR GDC clock (0) 2,5 MHz (1) 5 MHz
+1000 010x BMP GDC clock
+1000 111x related to GFX accelerator cards (like Vision864)
+1100 010x chart GDC operating mode (?)
+(everything else is undocumented / unknown)
+
+Keyboard TX commands:
+0xfa ACK
+0xfc NACK
+0x95
+---- --xx extension key settings (00 normal 11 Win and App Keys enabled)
+0x96 identification codes
+0x9c
+-xx- ---- key delay (11 = 1000 ms, 10 = 500 ms, 01 = 500 ms, 00 = 250 ms)
+---x xxxx repeat rate (slow 11111 -> 00001 fast)
+0x9d keyboard LED settings
+0x9f keyboard ID
+
+****************************************************************************************************/
+
+#include "emu.h"
+
+#include "cpu/i86/i86.h"
+#include "cpu/nec/nec.h"
+#include "cpu/i86/i286.h"
+#include "cpu/i386/i386.h"
+
+#include "machine/i8255.h"
+#include "machine/pit8253.h"
+#include "machine/am9517a.h"
+#include "machine/pic8259.h"
+#include "machine/upd765.h"
+#include "machine/upd1990a.h"
+#include "machine/i8251.h"
+
+#include "bus/scsi/pc9801_sasi.h"
+#include "bus/scsi/scsi.h"
+#include "bus/scsi/scsihd.h"
+#include "machine/buffer.h"
+#include "machine/latch.h"
+
+#include "sound/beep.h"
+#include "sound/speaker.h"
+#include "sound/2608intf.h"
+
+#include "video/upd7220.h"
+
+#include "machine/ram.h"
+
+#include "formats/pc98_dsk.h"
+#include "formats/pc98fdi_dsk.h"
+#include "formats/fdd_dsk.h"
+#include "formats/dcp_dsk.h"
+#include "formats/dip_dsk.h"
+#include "formats/nfd_dsk.h"
+
+#include "machine/pc9801_26.h"
+#include "machine/pc9801_86.h"
+#include "machine/pc9801_118.h"
+#include "machine/pc9801_cbus.h"
+#include "machine/pc9801_kbd.h"
+
+#include "machine/idectrl.h"
+#include "machine/idehd.h"
+
+#include "debugger.h"
+#include "softlist.h"
+
+#define UPD1990A_TAG "upd1990a"
+#define UPD8251_TAG "upd8251"
+#define SASIBUS_TAG "sasi"
+
+class pc9801_state : public driver_device
+{
+public:
+ pc9801_state(const machine_config &mconfig, device_type type, const char *tag) :
+ driver_device(mconfig, type, tag),
+ m_maincpu(*this, "maincpu"),
+ m_dmac(*this, "i8237"),
+ m_pit8253(*this, "pit8253"),
+ m_pic1(*this, "pic8259_master"),
+ m_pic2(*this, "pic8259_slave"),
+ m_fdc_2hd(*this, "upd765_2hd"),
+ m_fdc_2dd(*this, "upd765_2dd"),
+ m_rtc(*this, UPD1990A_TAG),
+ m_keyb(*this, "keyb"),
+ m_sio(*this, UPD8251_TAG),
+ m_hgdc1(*this, "upd7220_chr"),
+ m_hgdc2(*this, "upd7220_btm"),
+ m_sasibus(*this, SASIBUS_TAG),
+ m_sasi_data_out(*this, "sasi_data_out"),
+ m_sasi_data_in(*this, "sasi_data_in"),
+ m_sasi_ctrl_in(*this, "sasi_ctrl_in"),
+ m_ide(*this, "ide"),
+ m_video_ram_1(*this, "video_ram_1"),
+ m_video_ram_2(*this, "video_ram_2"),
+ m_ext_gvram(*this, "ext_gvram"),
+ m_beeper(*this, "beeper"),
+ m_ram(*this, RAM_TAG),
+ m_gfxdecode(*this, "gfxdecode"),
+ m_palette(*this, "palette"),
+ m_screen(*this, "screen")
+ {
+ }
+
+ required_device<cpu_device> m_maincpu;
+ required_device<am9517a_device> m_dmac;
+ required_device<pit8253_device> m_pit8253;
+ required_device<pic8259_device> m_pic1;
+ required_device<pic8259_device> m_pic2;
+ required_device<upd765a_device> m_fdc_2hd;
+ optional_device<upd765a_device> m_fdc_2dd;
+ required_device<upd1990a_device> m_rtc;
+ required_device<pc9801_kbd_device> m_keyb;
+ required_device<i8251_device> m_sio;
+ required_device<upd7220_device> m_hgdc1;
+ required_device<upd7220_device> m_hgdc2;
+ optional_device<SCSI_PORT_DEVICE> m_sasibus;
+ optional_device<output_latch_device> m_sasi_data_out;
+ optional_device<input_buffer_device> m_sasi_data_in;
+ optional_device<input_buffer_device> m_sasi_ctrl_in;
+ optional_device<ata_interface_device> m_ide;
+ required_shared_ptr<UINT16> m_video_ram_1;
+ required_shared_ptr<UINT16> m_video_ram_2;
+ optional_shared_ptr<UINT16> m_ext_gvram;
+ required_device<beep_device> m_beeper;
+ optional_device<ram_device> m_ram;
+ required_device<gfxdecode_device> m_gfxdecode;
+ required_device<palette_device> m_palette;
+ required_device<screen_device> m_screen;
+
+ virtual void video_start();
+ UINT32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
+
+ enum
+ {
+ TIMER_VBIRQ
+ };
+
+ emu_timer *m_vbirq;
+ UINT8 *m_ipl_rom;
+ UINT8 *m_char_rom;
+ UINT8 *m_kanji_rom;
+
+ UINT8 m_dma_offset[4];
+ int m_dack;
+
+ UINT8 m_video_ff[8],m_gfx_ff;
+ UINT8 m_txt_scroll_reg[8];
+ UINT8 m_pal_clut[4];
+
+ UINT16 *m_tvram;
+
+ UINT16 m_font_addr;
+ UINT8 m_font_line;
+ UINT16 m_font_lr;
+
+ UINT8 m_keyb_press;
+
+ UINT8 m_fdc_2dd_ctrl,m_fdc_2hd_ctrl;
+ UINT8 m_nmi_ff;
+
+ UINT8 m_vram_bank;
+ UINT8 m_vram_disp;
+
+ /* PC9801RS specific */
+ UINT8 m_gate_a20; //A20 line
+ UINT8 m_nmi_enable;
+ UINT8 m_access_ctrl; // DMA related
+ UINT8 m_rom_bank;
+ UINT8 m_fdc_ctrl;
+ UINT8 m_ex_video_ff[128];
+ struct {
+ UINT8 pal_entry;
+ UINT8 r[16],g[16],b[16];
+ }m_analog16;
+ struct {
+ UINT8 pal_entry;
+ UINT8 r[0x100],g[0x100],b[0x100];
+ }m_analog256;
+ struct {
+ UINT8 mode;
+ UINT8 tile[4], tile_index;
+ }m_grcg;
+
+ struct {
+ UINT16 regs[8];
+ UINT16 pat[4];
+ UINT16 src[4];
+ INT16 count;
+ UINT16 leftover[4];
+ bool first;
+ bool init;
+ } m_egc;
+
+ /* PC9821 specific */
+ UINT8 m_sdip[24], m_sdip_bank;
+ UINT8 m_pc9821_window_bank;
+ UINT8 m_ext2_ff;
+ UINT8 m_sys_type;
+
+ DECLARE_WRITE_LINE_MEMBER( write_uart_clock );
+ DECLARE_WRITE8_MEMBER(rtc_dmapg_w);
+ DECLARE_WRITE8_MEMBER(nmi_ctrl_w);
+ DECLARE_WRITE8_MEMBER(vrtc_clear_w);
+ DECLARE_WRITE8_MEMBER(pc9801_video_ff_w);
+ DECLARE_READ8_MEMBER(txt_scrl_r);
+ DECLARE_WRITE8_MEMBER(txt_scrl_w);
+ DECLARE_READ8_MEMBER(grcg_r);
+ DECLARE_WRITE8_MEMBER(grcg_w);
+ DECLARE_WRITE16_MEMBER(egc_w);
+ DECLARE_READ8_MEMBER(pc9801_a0_r);
+ DECLARE_WRITE8_MEMBER(pc9801_a0_w);
+ DECLARE_READ8_MEMBER(pc9801_fdc_2hd_r);
+ DECLARE_WRITE8_MEMBER(pc9801_fdc_2hd_w);
+ DECLARE_READ8_MEMBER(pc9801_fdc_2dd_r);
+ DECLARE_WRITE8_MEMBER(pc9801_fdc_2dd_w);
+ DECLARE_READ16_MEMBER(tvram_r);
+ DECLARE_WRITE16_MEMBER(tvram_w);
+ DECLARE_READ8_MEMBER(gvram_r);
+ DECLARE_WRITE8_MEMBER(gvram_w);
+ DECLARE_WRITE8_MEMBER(pc9801rs_mouse_freq_w);
+ DECLARE_CUSTOM_INPUT_MEMBER(system_type_r);
+ DECLARE_READ16_MEMBER(grcg_gvram_r);
+ DECLARE_WRITE16_MEMBER(grcg_gvram_w);
+ DECLARE_READ16_MEMBER(grcg_gvram0_r);
+ DECLARE_WRITE16_MEMBER(grcg_gvram0_w);
+ DECLARE_READ16_MEMBER(upd7220_grcg_r);
+ DECLARE_WRITE16_MEMBER(upd7220_grcg_w);
+ void egc_blit_w(UINT32 offset, UINT16 data, UINT16 mem_mask);
+ UINT16 egc_blit_r(UINT32 offset, UINT16 mem_mask);
+ UINT32 pc9801_286_a20(bool state);
+
+ DECLARE_READ8_MEMBER(ide_hack_r);
+ DECLARE_WRITE8_MEMBER(sasi_data_w);
+ DECLARE_READ8_MEMBER(sasi_data_r);
+ DECLARE_WRITE_LINE_MEMBER(write_sasi_io);
+ DECLARE_WRITE_LINE_MEMBER(write_sasi_req);
+ DECLARE_READ8_MEMBER(sasi_status_r);
+ DECLARE_WRITE8_MEMBER(sasi_ctrl_w);
+
+ UINT8 m_sasi_data;
+ int m_sasi_data_enable;
+ UINT8 m_sasi_ctrl;
+
+ DECLARE_READ8_MEMBER(pc9801rs_ipl_r);
+ DECLARE_READ8_MEMBER(pc9801rs_knjram_r);
+ DECLARE_WRITE8_MEMBER(pc9801rs_knjram_w);
+ DECLARE_WRITE8_MEMBER(pc9801rs_bank_w);
+ DECLARE_READ8_MEMBER(a20_ctrl_r);
+ DECLARE_WRITE8_MEMBER(a20_ctrl_w);
+ DECLARE_READ8_MEMBER(pc9810rs_fdc_ctrl_r);
+ DECLARE_WRITE8_MEMBER(pc9810rs_fdc_ctrl_w);
+ DECLARE_READ8_MEMBER(pc9801rs_2hd_r);
+ DECLARE_WRITE8_MEMBER(pc9801rs_2hd_w);
+// DECLARE_READ8_MEMBER(pc9801rs_2dd_r);
+// DECLARE_WRITE8_MEMBER(pc9801rs_2dd_w);
+ DECLARE_WRITE8_MEMBER(pc9801rs_video_ff_w);
+ DECLARE_WRITE8_MEMBER(pc9801rs_a0_w);
+ DECLARE_WRITE8_MEMBER(pc9821_video_ff_w);
+ DECLARE_READ8_MEMBER(pc9821_a0_r);
+ DECLARE_WRITE8_MEMBER(pc9821_a0_w);
+ DECLARE_READ8_MEMBER(pc9801rs_access_ctrl_r);
+ DECLARE_WRITE8_MEMBER(pc9801rs_access_ctrl_w);
+ DECLARE_WRITE8_MEMBER(pc9801rs_nmi_w);
+ DECLARE_READ8_MEMBER(pc9801rs_midi_r);
+// DECLARE_READ8_MEMBER(winram_r);
+// DECLARE_WRITE8_MEMBER(winram_w);
+// DECLARE_READ8_MEMBER(pc9801_ext_opna_r);
+// DECLARE_WRITE8_MEMBER(pc9801_ext_opna_w);
+ DECLARE_READ8_MEMBER(pic_r);
+ DECLARE_WRITE8_MEMBER(pic_w);
+
+ DECLARE_READ8_MEMBER(sdip_0_r);
+ DECLARE_READ8_MEMBER(sdip_1_r);
+ DECLARE_READ8_MEMBER(sdip_2_r);
+ DECLARE_READ8_MEMBER(sdip_3_r);
+ DECLARE_READ8_MEMBER(sdip_4_r);
+ DECLARE_READ8_MEMBER(sdip_5_r);
+ DECLARE_READ8_MEMBER(sdip_6_r);
+ DECLARE_READ8_MEMBER(sdip_7_r);
+ DECLARE_READ8_MEMBER(sdip_8_r);
+ DECLARE_READ8_MEMBER(sdip_9_r);
+ DECLARE_READ8_MEMBER(sdip_a_r);
+ DECLARE_READ8_MEMBER(sdip_b_r);
+
+ DECLARE_WRITE8_MEMBER(sdip_0_w);
+ DECLARE_WRITE8_MEMBER(sdip_1_w);
+ DECLARE_WRITE8_MEMBER(sdip_2_w);
+ DECLARE_WRITE8_MEMBER(sdip_3_w);
+ DECLARE_WRITE8_MEMBER(sdip_4_w);
+ DECLARE_WRITE8_MEMBER(sdip_5_w);
+ DECLARE_WRITE8_MEMBER(sdip_6_w);
+ DECLARE_WRITE8_MEMBER(sdip_7_w);
+ DECLARE_WRITE8_MEMBER(sdip_8_w);
+ DECLARE_WRITE8_MEMBER(sdip_9_w);
+ DECLARE_WRITE8_MEMBER(sdip_a_w);
+ DECLARE_WRITE8_MEMBER(sdip_b_w);
+
+ DECLARE_READ8_MEMBER(pc9821_window_bank_r);
+ DECLARE_WRITE8_MEMBER(pc9821_window_bank_w);
+ DECLARE_READ16_MEMBER(pc9821_timestamp_r);
+ DECLARE_READ8_MEMBER(pc9821_ext2_video_ff_r);
+ DECLARE_WRITE8_MEMBER(pc9821_ext2_video_ff_w);
+
+ DECLARE_FLOPPY_FORMATS( floppy_formats );
+ UPD7220_DISPLAY_PIXELS_MEMBER( hgdc_display_pixels );
+ UPD7220_DRAW_TEXT_LINE_MEMBER( hgdc_draw_text );
+
+private:
+ UINT8 m_sdip_read(UINT16 port, UINT8 sdip_offset);
+ void m_sdip_write(UINT16 port, UINT8 sdip_offset,UINT8 data);
+ UINT16 egc_do_partial_op(int plane, UINT16 src, UINT16 pat, UINT16 dst);
+ UINT16 egc_shift(int plane, UINT16 val);
+public:
+ DECLARE_MACHINE_START(pc9801_common);
+ DECLARE_MACHINE_START(pc9801f);
+ DECLARE_MACHINE_START(pc9801rs);
+ DECLARE_MACHINE_START(pc9801bx2);
+ DECLARE_MACHINE_START(pc9821);
+ DECLARE_MACHINE_START(pc9821ap2);
+ DECLARE_MACHINE_RESET(pc9801_common);
+ DECLARE_MACHINE_RESET(pc9801f);
+ DECLARE_MACHINE_RESET(pc9801rs);
+ DECLARE_MACHINE_RESET(pc9821);
+
+ DECLARE_PALETTE_INIT(pc9801);
+ INTERRUPT_GEN_MEMBER(pc9801_vrtc_irq);
+ DECLARE_READ8_MEMBER(get_slave_ack);
+ DECLARE_WRITE_LINE_MEMBER(dma_hrq_changed);
+ DECLARE_WRITE_LINE_MEMBER(tc_w);
+ DECLARE_READ8_MEMBER(dma_read_byte);
+ DECLARE_WRITE8_MEMBER(dma_write_byte);
+ DECLARE_WRITE_LINE_MEMBER(dack0_w);
+ DECLARE_WRITE_LINE_MEMBER(dack1_w);
+ DECLARE_WRITE_LINE_MEMBER(dack2_w);
+ DECLARE_WRITE_LINE_MEMBER(dack3_w);
+ DECLARE_WRITE8_MEMBER(ppi_sys_portc_w);
+
+ DECLARE_WRITE_LINE_MEMBER(fdc_2dd_irq);
+ DECLARE_WRITE_LINE_MEMBER(pc9801rs_fdc_irq);
+ DECLARE_WRITE_LINE_MEMBER(pc9801rs_fdc_drq);
+
+ DECLARE_READ8_MEMBER(ppi_mouse_porta_r);
+ DECLARE_WRITE8_MEMBER(ppi_mouse_porta_w);
+ DECLARE_WRITE8_MEMBER(ppi_mouse_portb_w);
+ DECLARE_WRITE8_MEMBER(ppi_mouse_portc_w);
+ struct{
+ UINT8 control;
+ UINT8 lx;
+ UINT8 ly;
+ UINT8 freq_reg;
+ UINT8 freq_index;
+ }m_mouse;
+ TIMER_DEVICE_CALLBACK_MEMBER( mouse_irq_cb );
+
+ DECLARE_DRIVER_INIT(pc9801_kanji);
+ inline void set_dma_channel(int channel, int state);
+ virtual void device_reset_after_children();
+};
+
+
+
+#define ATTRSEL_REG 0
+#define WIDTH40_REG 2
+#define FONTSEL_REG 3
+#define INTERLACE_REG 4
+#define MEMSW_REG 6
+#define DISPLAY_REG 7
+
+#define ANALOG_16_MODE 0
+#define ANALOG_256_MODE 0x10
+
+void pc9801_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ switch(id)
+ {
+ case TIMER_VBIRQ:
+ m_pic1->ir2_w(0);
+ }
+}
+
+void pc9801_state::video_start()
+{
+ m_tvram = auto_alloc_array(machine(), UINT16, 0x2000);
+
+ // find memory regions
+ m_char_rom = memregion("chargen")->base();
+ m_kanji_rom = memregion("kanji")->base();
+}
+
+UINT32 pc9801_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+{
+ bitmap.fill(m_palette->black_pen(), cliprect);
+
+ /* graphics */
+ m_hgdc2->screen_update(screen, bitmap, cliprect);
+ m_hgdc1->screen_update(screen, bitmap, cliprect);
+ return 0;
+}
+
+UPD7220_DISPLAY_PIXELS_MEMBER( pc9801_state::hgdc_display_pixels )
+{
+ const rgb_t *palette = m_palette->palette()->entry_list_raw();
+ int xi;
+ int res_x,res_y;
+ UINT8 pen;
+ UINT8 interlace_on;
+ UINT8 colors16_mode;
+
+ if(m_video_ff[DISPLAY_REG] == 0) //screen is off
+ return;
+
+// popmessage("%02x %d",m_video_ff[INTERLACE_REG],machine().first_screen()->visible_area().max_y + 1);
+// interlace_on = ((machine().first_screen()->visible_area().max_y + 1) >= 400) ? 1 : 0;
+ interlace_on = m_video_ff[INTERLACE_REG];
+ colors16_mode = (m_ex_video_ff[ANALOG_16_MODE]) ? 16 : 8;
+
+ if(m_ex_video_ff[ANALOG_256_MODE])
+ {
+ for(xi=0;xi<16;xi++)
+ {
+ res_x = x + xi;
+ res_y = y;
+
+ if(!m_screen->visible_area().contains(res_x, res_y*2+0))
+ return;
+
+ pen = m_ext_gvram[((address*16+xi)+(m_vram_disp*0x40000)) >> 1];
+
+ bitmap.pix32(res_y*2+0, res_x) = palette[pen + 0x20];
+ if(m_screen->visible_area().contains(res_x, res_y*2+1))
+ bitmap.pix32(res_y*2+1, res_x) = palette[pen + 0x20];
+ }
+ }
+ else
+ {
+ for(xi=0;xi<16;xi++)
+ {
+ res_x = x + xi;
+ res_y = y;
+
+ pen = ((m_video_ram_2[((address & 0x7fff) + (0x08000) + (m_vram_disp*0x20000)) >> 1] >> xi) & 1) ? 1 : 0;
+ pen|= ((m_video_ram_2[((address & 0x7fff) + (0x10000) + (m_vram_disp*0x20000)) >> 1] >> xi) & 1) ? 2 : 0;
+ pen|= ((m_video_ram_2[((address & 0x7fff) + (0x18000) + (m_vram_disp*0x20000)) >> 1] >> xi) & 1) ? 4 : 0;
+ if(m_ex_video_ff[ANALOG_16_MODE])
+ pen|= ((m_video_ram_2[((address & 0x7fff) + (0) + (m_vram_disp*0x20000)) >> 1] >> xi) & 1) ? 8 : 0;
+
+ if(interlace_on)
+ {
+ if(m_screen->visible_area().contains(res_x, res_y*2+0))
+ bitmap.pix32(res_y*2+0, res_x) = palette[pen + colors16_mode];
+ /* TODO: it looks like that PC-98xx can only display even lines ... */
+ if(m_screen->visible_area().contains(res_x, res_y*2+1))
+ bitmap.pix32(res_y*2+1, res_x) = palette[pen + colors16_mode];
+ }
+ else
+ bitmap.pix32(res_y, res_x) = palette[pen + colors16_mode];
+ }
+ }
+}
+
+UPD7220_DRAW_TEXT_LINE_MEMBER( pc9801_state::hgdc_draw_text )
+{
+ const rgb_t *palette = m_palette->palette()->entry_list_raw();
+ int xi,yi;
+ int x;
+ UINT8 char_size;
+// UINT8 interlace_on;
+ UINT16 tile;
+ UINT8 kanji_lr;
+ UINT8 kanji_sel;
+ UINT8 x_step;
+
+ if(m_video_ff[DISPLAY_REG] == 0) //screen is off
+ return;
+
+// interlace_on = m_video_ff[INTERLACE_REG];
+ char_size = m_video_ff[FONTSEL_REG] ? 16 : 8;
+ tile = 0;
+
+ for(x=0;x<pitch;x+=x_step)
+ {
+ UINT8 tile_data,secret,reverse,u_line,v_line,blink;
+ UINT8 color;
+ UINT8 attr;
+ int pen;
+ UINT32 tile_addr;
+ UINT8 knj_tile;
+ UINT8 gfx_mode;
+
+ tile_addr = addr+(x*(m_video_ff[WIDTH40_REG]+1));
+
+ kanji_sel = 0;
+ kanji_lr = 0;
+
+ tile = m_video_ram_1[tile_addr & 0xfff] & 0xff;
+ knj_tile = m_video_ram_1[tile_addr & 0xfff] >> 8;
+ if(knj_tile)
+ {
+ /* Note: bit 7 doesn't really count, if a kanji is enabled then the successive tile is always the second part of it.
+ Trusted with Alice no Yakata, Animahjong V3, Aki no Tsukasa no Fushigi no Kabe, Apros ...
+ */
+ //kanji_lr = (knj_tile & 0x80) >> 7;
+ //kanji_lr |= (tile & 0x80) >> 7; // Tokimeki Sports Gal 3
+ tile &= 0x7f;
+ tile <<= 8;
+ tile |= (knj_tile & 0x7f);
+ kanji_sel = 1;
+ if((tile & 0x7c00) == 0x0800) // 8x16 charset selector
+ x_step = 1;
+ else
+ x_step = 2;
+// kanji_lr = 0;
+ }
+ else
+ x_step = 1;
+
+
+
+ for(kanji_lr=0;kanji_lr<x_step;kanji_lr++)
+ {
+ /* Rori Rori Rolling definitely uses different colors for brake stop PCG elements,
+ assume that all attributes are recalculated on different strips */
+ attr = (m_video_ram_1[((tile_addr+kanji_lr) & 0xfff) | 0x1000] & 0xff);
+
+ secret = (attr & 1) ^ 1;
+ blink = attr & 2;
+ reverse = attr & 4;
+ u_line = attr & 8;
+ v_line = (m_video_ff[ATTRSEL_REG]) ? 0 : attr & 0x10;
+ gfx_mode = (m_video_ff[ATTRSEL_REG]) ? attr & 0x10 : 0;
+ color = (attr & 0xe0) >> 5;
+
+ for(yi=0;yi<lr;yi++)
+ {
+ for(xi=0;xi<8;xi++)
+ {
+ int res_x,res_y;
+
+ res_x = ((x+kanji_lr)*8+xi) * (m_video_ff[WIDTH40_REG]+1);
+ res_y = y+yi - (m_txt_scroll_reg[3] & 0xf);
+
+ if(!m_screen->visible_area().contains(res_x, res_y))
+ continue;
+
+ tile_data = 0;
+
+ if(!secret)
+ {
+ /* TODO: priority */
+ if(gfx_mode)
+ {
+ int gfx_bit;
+ tile_data = 0;
+
+ /*
+ gfx strip mode:
+
+ number refers to the bit number in the tile data.
+ This mode is identical to the one seen in PC-8801
+ 00004444
+ 11115555
+ 22226666
+ 33337777
+ */
+
+ gfx_bit = (xi & 4);
+ gfx_bit+= (yi & (2 << (char_size == 16 ? 0x01 : 0x00)))>>(1+(char_size == 16));
+ gfx_bit+= (yi & (4 << (char_size == 16 ? 0x01 : 0x00)))>>(1+(char_size == 16));
+
+ tile_data = ((tile >> gfx_bit) & 1) ? 0xff : 0x00;
+ }
+ else if(kanji_sel)
+ tile_data = (m_kanji_rom[tile*0x20+yi*2+kanji_lr]);
+ else
+ tile_data = (m_char_rom[tile*char_size+m_video_ff[FONTSEL_REG]*0x800+yi]);
+ }
+
+ if(reverse) { tile_data^=0xff; }
+ if(u_line && yi == 7) { tile_data = 0xff; }
+ if(v_line) { tile_data|=8; }
+
+ /* TODO: proper blink rate for these two */
+ if(cursor_on && cursor_addr == tile_addr && m_screen->frame_number() & 0x10)
+ tile_data^=0xff;
+
+ if(blink && m_screen->frame_number() & 0x10)
+ tile_data^=0xff;
+
+ if(yi >= char_size)
+ pen = -1;
+ else
+ pen = (tile_data >> (7-xi) & 1) ? color : -1;
+
+ if(pen != -1)
+ bitmap.pix32(res_y, res_x) = palette[pen];
+
+ if(m_video_ff[WIDTH40_REG])
+ {
+ if(!m_screen->visible_area().contains(res_x+1, res_y))
+ continue;
+
+ if(pen != -1)
+ bitmap.pix32(res_y, res_x+1) = palette[pen];
+ }
+ }
+ }
+ }
+ }
+}
+
+
+WRITE8_MEMBER(pc9801_state::rtc_dmapg_w)
+{
+ if((offset & 1) == 0)
+ {
+ if(offset == 0)
+ {
+ m_rtc->c0_w((data & 0x01) >> 0);
+ m_rtc->c1_w((data & 0x02) >> 1);
+ m_rtc->c2_w((data & 0x04) >> 2);
+ m_rtc->stb_w((data & 0x08) >> 3);
+ m_rtc->clk_w((data & 0x10) >> 4);
+ m_rtc->data_in_w(((data & 0x20) >> 5));
+ if(data & 0xc0)
+ logerror("RTC write to undefined bits %02x\n",data & 0xc0);
+ }
+ else
+ logerror("Write to undefined port [%02x] <- %02x\n",offset+0x20,data);
+ }
+ else // odd
+ {
+// logerror("Write to DMA bank register %d %02x\n",((offset >> 1)+1) & 3,data);
+ m_dma_offset[((offset >> 1)+1) & 3] = data & 0x0f;
+ }
+}
+
+WRITE8_MEMBER(pc9801_state::nmi_ctrl_w)
+{
+ m_nmi_ff = (offset & 2) >> 1;
+}
+
+WRITE8_MEMBER(pc9801_state::vrtc_clear_w)
+{
+ m_pic1->ir2_w(0);
+}
+
+WRITE8_MEMBER(pc9801_state::pc9801_video_ff_w)
+{
+ /*
+ TODO: this is my best bet so far. Register 4 is annoying, the pattern seems to be:
+ Write to video FF register Graphic -> 00
+ Write to video FF register 200 lines -> 0x
+ Write to video FF register 200 lines -> 00
+
+ where x is the current mode.
+ */
+ switch((data & 0x0e) >> 1)
+ {
+ case 1:
+ m_gfx_ff = 1;
+ if(data & 1)
+ logerror("Graphic f/f actually enabled!\n");
+ break;
+ case 4:
+ if(m_gfx_ff)
+ {
+ m_video_ff[(data & 0x0e) >> 1] = data &1;
+ m_gfx_ff = 0;
+ }
+ break;
+ default: m_video_ff[(data & 0x0e) >> 1] = data & 1; break;
+ }
+
+ if(0)
+ {
+ static const char *const video_ff_regnames[] =
+ {
+ "Attribute Select", // 0
+ "Graphic", // 1
+ "Column", // 2
+ "Font Select", // 3
+ "200 lines", // 4
+ "KAC?", // 5
+ "Memory Switch", // 6
+ "Display ON" // 7
+ };
+
+ logerror("Write to video FF register %s -> %02x\n",video_ff_regnames[(data & 0x0e) >> 1],data & 1);
+ }
+}
+
+
+READ8_MEMBER(pc9801_state::txt_scrl_r)
+{
+ //logerror("Read to display register [%02x]\n",offset+0x70);
+ /* TODO: ok? */
+ return m_txt_scroll_reg[offset >> 1];
+}
+
+WRITE8_MEMBER(pc9801_state::txt_scrl_w)
+{
+ //logerror("Write to display register [%02x] %02x\n",offset+0x70,data);
+ m_txt_scroll_reg[offset >> 1] = data;
+
+ //popmessage("%02x %02x %02x %02x",m_txt_scroll_reg[0],m_txt_scroll_reg[1],m_txt_scroll_reg[2],m_txt_scroll_reg[3]);
+}
+
+READ8_MEMBER(pc9801_state::pc9801_a0_r)
+{
+ if((offset & 1) == 0)
+ {
+ switch(offset & 0xe)
+ {
+ case 0x00:
+ case 0x02:
+ return m_hgdc2->read(space, (offset & 2) >> 1);
+ /* TODO: double check these two */
+ case 0x04:
+ return m_vram_disp & 1;
+ case 0x06:
+ return m_vram_bank & 1;
+ /* bitmap palette clut read */
+ case 0x08:
+ case 0x0a:
+ case 0x0c:
+ case 0x0e:
+ return m_pal_clut[(offset & 0x6) >> 1];
+ }
+
+ return 0xff; //code unreachable
+ }
+ else // odd
+ {
+ switch((offset & 0xe) + 1)
+ {
+ case 0x09://cg window font read
+ {
+ UINT32 pcg_offset;
+
+ pcg_offset = (m_font_addr & 0x7f7f) << 5;
+ pcg_offset|= m_font_line;
+ pcg_offset|= m_font_lr;
+
+ return m_kanji_rom[pcg_offset];
+ }
+ }
+
+ logerror("Read to undefined port [%02x]\n",offset+0xa0);
+ return 0xff;
+ }
+}
+
+WRITE8_MEMBER(pc9801_state::pc9801_a0_w)
+{
+ if((offset & 1) == 0)
+ {
+ switch(offset & 0xe)
+ {
+ case 0x00:
+ case 0x02:
+ m_hgdc2->write(space, (offset & 2) >> 1,data);
+ return;
+ case 0x04:
+ m_vram_disp = data & 1;
+ return;
+ case 0x06:
+ m_vram_bank = data & 1;
+ return;
+ /* bitmap palette clut write */
+ case 0x08:
+ case 0x0a:
+ case 0x0c:
+ case 0x0e:
+ {
+ UINT8 pal_entry;
+
+ m_pal_clut[(offset & 0x6) >> 1] = data;
+
+ /* can't be more twisted I presume ... :-/ */
+ pal_entry = (((offset & 4) >> 1) | ((offset & 2) << 1)) >> 1;
+ pal_entry ^= 3;
+
+ m_palette->set_pen_color((pal_entry)|4|8, pal1bit((data & 0x2) >> 1), pal1bit((data & 4) >> 2), pal1bit((data & 1) >> 0));
+ m_palette->set_pen_color((pal_entry)|8, pal1bit((data & 0x20) >> 5), pal1bit((data & 0x40) >> 6), pal1bit((data & 0x10) >> 4));
+ return;
+ }
+ default:
+ logerror("Write to undefined port [%02x] <- %02x\n",offset+0xa0,data);
+ return;
+ }
+ }
+ else // odd
+ {
+ switch((offset & 0xe) + 1)
+ {
+ case 0x01:
+ m_font_addr = (data & 0xff) | (m_font_addr & 0x7f00);
+ return;
+ case 0x03:
+ m_font_addr = ((data & 0x7f) << 8) | (m_font_addr & 0xff);
+ return;
+ case 0x05:
+ //logerror("%02x\n",data);
+ m_font_line = ((data & 0x0f) << 1);
+ m_font_lr = ((data & 0x20) >> 5) ^ 1;
+ return;
+ case 0x09: //cg window font write
+ {
+ UINT32 pcg_offset;
+
+ pcg_offset = m_font_addr << 5;
+ pcg_offset|= m_font_line;
+ pcg_offset|= m_font_lr;
+ //logerror("%04x %02x %02x %08x\n",m_font_addr,m_font_line,m_font_lr,pcg_offset);
+ if((m_font_addr & 0xff00) == 0x5600 || (m_font_addr & 0xff00) == 0x5700)
+ {
+ m_kanji_rom[pcg_offset] = data;
+ m_gfxdecode->gfx(2)->mark_dirty(pcg_offset >> 5);
+ }
+ return;
+ }
+ }
+
+ //logerror("Write to undefined port [%02x) <- %02x\n",offset+0xa0,data);
+ }
+}
+
+DECLARE_WRITE_LINE_MEMBER(pc9801_state::write_uart_clock)
+{
+ m_sio->write_txc(state);
+ m_sio->write_rxc(state);
+}
+
+READ8_MEMBER(pc9801_state::pc9801_fdc_2hd_r)
+{
+ if((offset & 1) == 0)
+ {
+ switch(offset & 6)
+ {
+ case 0: return m_fdc_2hd->msr_r(space, 0, 0xff);
+ case 2: return m_fdc_2hd->fifo_r(space, 0, 0xff);
+ case 4: return 0x5f; //unknown port meaning
+ }
+ }
+ else
+ {
+ switch((offset & 6) + 1)
+ {
+ case 1: return m_sio->data_r(space, 0);
+ case 3: return m_sio->status_r(space, 0);
+ }
+ logerror("Read to undefined port [%02x]\n",offset+0x90);
+ return 0xff;
+ }
+
+ return 0xff;
+}
+
+WRITE8_MEMBER(pc9801_state::pc9801_fdc_2hd_w)
+{
+ if((offset & 1) == 0)
+ {
+ switch(offset & 6)
+ {
+ case 0: logerror("Write to undefined port [%02x] <- %02x\n",offset+0x90,data); return;
+ case 2: m_fdc_2hd->fifo_w(space, 0, data, 0xff); return;
+ case 4:
+ //logerror("%02x ctrl\n",data);
+ if(((m_fdc_2hd_ctrl & 0x80) == 0) && (data & 0x80))
+ m_fdc_2hd->soft_reset();
+
+ m_fdc_2hd_ctrl = data;
+
+ if(data & 0x40)
+ {
+ m_fdc_2hd->set_ready_line_connected(0);
+ m_fdc_2hd->ready_w(0);
+ }
+ else
+ m_fdc_2hd->set_ready_line_connected(1);
+
+ // TODO: is the motor control bit really inverted relative to the other fdcs?
+ m_fdc_2hd->subdevice<floppy_connector>("0")->get_device()->mon_w(data & 8 ? ASSERT_LINE : CLEAR_LINE);
+ m_fdc_2hd->subdevice<floppy_connector>("1")->get_device()->mon_w(data & 8 ? ASSERT_LINE : CLEAR_LINE);
+ break;
+ }
+ }
+ else
+ {
+ switch((offset & 6) + 1)
+ {
+ case 1: m_sio->data_w(space, 0, data); return;
+ case 3: m_sio->control_w(space, 0, data); return;
+ }
+ logerror("Write to undefined port [%02x] <- %02x\n",offset+0x90,data);
+ }
+}
+
+
+READ8_MEMBER(pc9801_state::pc9801_fdc_2dd_r)
+{
+ if((offset & 1) == 0)
+ {
+ switch(offset & 6)
+ {
+ case 0: return m_fdc_2dd->msr_r(space, 0, 0xff);
+ case 2: return m_fdc_2dd->fifo_r(space, 0, 0xff);
+ case 4:
+ {
+ int ret = (!m_fdc_2dd->subdevice<floppy_connector>("0")->get_device()->ready_r()) ? 0x10 : 0;
+ ret |= (m_fdc_2dd->subdevice<floppy_connector>("1")->get_device()->ready_r()) ? 0x10 : 0;
+ return ret | 0x40; //unknown port meaning, might be 0x70
+ }
+ }
+ }
+ else
+ {
+ logerror("Read to undefined port [%02x]\n",offset+0xc8);
+ return 0xff;
+ }
+
+ return 0xff;
+}
+
+WRITE8_MEMBER(pc9801_state::pc9801_fdc_2dd_w)
+{
+ if((offset & 1) == 0)
+ {
+ switch(offset & 6)
+ {
+ case 0: logerror("Write to undefined port [%02x] <- %02x\n",offset+0xc8,data); return;
+ case 2: m_fdc_2dd->fifo_w(space, 0, data, 0xff); return;
+ case 4:
+ logerror("%02x ctrl\n",data);
+ if(((m_fdc_2dd_ctrl & 0x80) == 0) && (data & 0x80))
+ m_fdc_2dd->soft_reset();
+
+ m_fdc_2dd_ctrl = data;
+ m_fdc_2dd->subdevice<floppy_connector>("0")->get_device()->mon_w(data & 8 ? CLEAR_LINE : ASSERT_LINE);
+ m_fdc_2dd->subdevice<floppy_connector>("1")->get_device()->mon_w(data & 8 ? CLEAR_LINE : ASSERT_LINE);
+ break;
+ }
+ }
+ else
+ {
+ logerror("Write to undefined port [%02x] <- %02x\n",offset+0xc8,data);
+ }
+}
+
+
+/* TODO: banking? */
+READ16_MEMBER(pc9801_state::tvram_r)
+{
+ UINT16 res;
+
+ if((offset & 0x1000) && (mem_mask == 0xff00))
+ return 0xffff;
+
+ res = m_tvram[offset];
+
+ return res;
+}
+
+WRITE16_MEMBER(pc9801_state::tvram_w)
+{
+ if(offset < (0x3fe2>>1) || m_video_ff[MEMSW_REG])
+ COMBINE_DATA(&m_tvram[offset]);
+
+ COMBINE_DATA(&m_video_ram_1[offset]); //TODO: check me
+}
+
+/* +0x8000 is trusted (bank 0 is actually used by 16 colors mode) */
+READ8_MEMBER(pc9801_state::gvram_r)
+{
+ return BITSWAP8(m_video_ram_2[(offset>>1)+0x04000+m_vram_bank*0x10000] >> ((offset & 1) << 3),0,1,2,3,4,5,6,7);
+}
+
+WRITE8_MEMBER(pc9801_state::gvram_w)
+{
+ UINT16 ram = m_video_ram_2[(offset>>1)+0x04000+m_vram_bank*0x10000];
+ int mask = (offset & 1) << 3;
+ data = BITSWAP8(data,0,1,2,3,4,5,6,7);
+ m_video_ram_2[(offset>>1)+0x04000+m_vram_bank*0x10000] = (ram & (0xff00 >> mask)) | (data << mask);
+}
+
+UINT16 pc9801_state::egc_shift(int plane, UINT16 val)
+{
+ int src_off = m_egc.regs[6] & 0xf, dst_off = (m_egc.regs[6] >> 4) & 0xf;
+ int left = src_off - dst_off, right = dst_off - src_off;
+ UINT16 out;
+ if(m_egc.regs[6] & 0x1000)
+ {
+ if(right >= 0)
+ {
+ out = (val >> right) | m_egc.leftover[plane];
+ m_egc.leftover[plane] = val << (16 - right);
+ }
+ else
+ {
+ out = (val >> (16 - left)) | m_egc.leftover[plane];
+ m_egc.leftover[plane] = val << left;
+ }
+ }
+ else
+ {
+ if(right >= 0)
+ {
+ out = (val << right) | m_egc.leftover[plane];
+ m_egc.leftover[plane] = val >> (16 - right);
+ }
+ else
+ {
+ out = (val << (16 - left)) | m_egc.leftover[plane];
+ m_egc.leftover[plane] = val >> left;
+ }
+ }
+ return out;
+}
+
+UINT16 pc9801_state::egc_do_partial_op(int plane, UINT16 src, UINT16 pat, UINT16 dst)
+{
+ UINT16 out = 0;
+
+ for(int i = 7; i >= 0; i--)
+ {
+ if(BIT(m_egc.regs[2], i))
+ out |= src & pat & dst;
+ pat = ~pat;
+ dst = (!(i & 1)) ? ~dst : dst;
+ src = (i == 4) ? ~src : src;
+ }
+ return out;
+}
+
+void pc9801_state::egc_blit_w(UINT32 offset, UINT16 data, UINT16 mem_mask)
+{
+ UINT16 mask = m_egc.regs[4] & mem_mask, out = 0;
+ bool dir = !(m_egc.regs[6] & 0x1000);
+ int dst_off = (m_egc.regs[6] >> 4) & 0xf, src_off = m_egc.regs[6] & 0xf;
+ offset &= 0x13fff;
+
+ if(!m_egc.init && (src_off > dst_off))
+ {
+ if(BIT(m_egc.regs[2], 10))
+ {
+ m_egc.leftover[0] = 0;
+ egc_shift(0, data);
+ // leftover[0] is inited above, set others to same
+ m_egc.leftover[1] = m_egc.leftover[2] = m_egc.leftover[3] = m_egc.leftover[0];
+ }
+ m_egc.init = true;
+ return;
+ }
+
+ // mask off the bits before the start
+ if(m_egc.first)
+ {
+ mask &= dir ? ~((1 << dst_off) - 1) : ((1 << (16 - dst_off)) - 1);
+ if(BIT(m_egc.regs[2], 10) && !m_egc.init)
+ m_egc.leftover[0] = m_egc.leftover[1] = m_egc.leftover[2] = m_egc.leftover[3] = 0;
+ }
+
+ // mask off the bits past the end of the blit
+ if(m_egc.count < 16)
+ {
+ UINT16 end_mask = dir ? ((1 << m_egc.count) - 1) : ~((1 << (16 - m_egc.count)) - 1);
+ // if the blit is less than 16 bits, adjust the masks
+ if(m_egc.first)
+ {
+ if(dir)
+ end_mask <<= dst_off;
+ else
+ end_mask >>= dst_off;
+ }
+ mask &= end_mask;
+ }
+
+ for(int i = 0; i < 4; i++)
+ {
+ if(!BIT(m_egc.regs[0], i))
+ {
+ UINT16 src = m_egc.src[i] & mem_mask, pat = m_egc.pat[i];
+ if(BIT(m_egc.regs[2], 10))
+ src = egc_shift(i, data);
+
+ if((m_egc.regs[2] & 0x300) == 0x200)
+ pat = m_video_ram_2[offset + (((i + 1) & 3) * 0x4000)];
+
+ switch((m_egc.regs[2] >> 11) & 3)
+ {
+ case 0:
+ out = data;
+ break;
+ case 1:
+ if(mem_mask == 0x00ff)
+ src = src | src << 8;
+ else if(mem_mask == 0xff00)
+ src = src | src >> 8;
+
+ out = egc_do_partial_op(i, src, pat, m_video_ram_2[offset + (((i + 1) & 3) * 0x4000)]);
+ break;
+ case 2:
+ out = pat;
+ break;
+ case 3:
+ logerror("Invalid EGC blit operation\n");
+ return;
+ }
+
+ m_video_ram_2[offset + (((i + 1) & 3) * 0x4000)] &= ~mask;
+ m_video_ram_2[offset + (((i + 1) & 3) * 0x4000)] |= out & mask;
+ }
+ }
+ if(mem_mask != 0xffff)
+ {
+ if(m_egc.first)
+ m_egc.count -= 8 - (dst_off & 7);
+ else
+ m_egc.count -= 8;
+ }
+ else
+ {
+ if(m_egc.first)
+ m_egc.count -= 16 - dst_off;
+ else
+ m_egc.count -= 16;
+ }
+
+ m_egc.first = false;
+
+ if(m_egc.count <= 0)
+ {
+ m_egc.first = true;
+ m_egc.init = false;
+ m_egc.count = (m_egc.regs[7] & 0xfff) + 1;
+ }
+}
+
+UINT16 pc9801_state::egc_blit_r(UINT32 offset, UINT16 mem_mask)
+{
+ UINT32 plane_off = offset & 0x13fff;
+ if((m_egc.regs[2] & 0x300) == 0x100)
+ {
+ m_egc.pat[0] = m_video_ram_2[plane_off + 0x4000];
+ m_egc.pat[1] = m_video_ram_2[plane_off + (0x4000 * 2)];
+ m_egc.pat[2] = m_video_ram_2[plane_off + (0x4000 * 3)];
+ m_egc.pat[3] = m_video_ram_2[plane_off];
+ }
+ if(m_egc.first && !m_egc.init)
+ {
+ m_egc.leftover[0] = m_egc.leftover[1] = m_egc.leftover[2] = m_egc.leftover[3] = 0;
+ m_egc.init = true;
+ }
+ for(int i = 0; i < 4; i++)
+ m_egc.src[i] = egc_shift(i, m_video_ram_2[plane_off + (((i + 1) & 3) * 0x4000)]);
+
+ if(BIT(m_egc.regs[2], 13))
+ return m_video_ram_2[offset];
+ else
+ return m_egc.src[(m_egc.regs[1] >> 8) & 3];
+}
+
+READ16_MEMBER(pc9801_state::upd7220_grcg_r)
+{
+ UINT16 res = 0;
+
+ if(!(m_grcg.mode & 0x80) || space.debugger_access())
+ res = m_video_ram_2[offset];
+ else if(m_ex_video_ff[2])
+ res = egc_blit_r(offset, mem_mask);
+ else if(!(m_grcg.mode & 0x40))
+ {
+ int i;
+
+ offset &= 0x13fff;
+ res = 0;
+ for(i=0;i<4;i++)
+ {
+ if((m_grcg.mode & (1 << i)) == 0)
+ {
+ res |= m_video_ram_2[offset | (((i + 1) & 3) * 0x4000)] ^ (m_grcg.tile[i] | m_grcg.tile[i] << 8);
+ }
+ }
+
+ res ^= 0xffff;
+ }
+
+ return res;
+}
+
+WRITE16_MEMBER(pc9801_state::upd7220_grcg_w)
+{
+ if(!(m_grcg.mode & 0x80))
+ COMBINE_DATA(&m_video_ram_2[offset]);
+ else if(m_ex_video_ff[2])
+ egc_blit_w(offset, data, mem_mask);
+ else
+ {
+ int i;
+ UINT8 *vram = (UINT8 *)m_video_ram_2.target();
+ offset = (offset << 1) & 0x27fff;
+
+ if(m_grcg.mode & 0x40) // RMW
+ {
+ for(i=0;i<4;i++)
+ {
+ if((m_grcg.mode & (1 << i)) == 0)
+ {
+ if(mem_mask & 0xff)
+ {
+ vram[offset | (((i + 1) & 3) * 0x8000)] &= ~(data >> 0);
+ vram[offset | (((i + 1) & 3) * 0x8000)] |= m_grcg.tile[i] & (data >> 0);
+ }
+ if(mem_mask & 0xff00)
+ {
+ vram[offset | (((i + 1) & 3) * 0x8000) | 1] &= ~(data >> 8);
+ vram[offset | (((i + 1) & 3) * 0x8000) | 1] |= m_grcg.tile[i] & (data >> 8);
+ }
+ }
+ }
+ }
+ else // TDW
+ {
+ for(i=0;i<4;i++)
+ {
+ if((m_grcg.mode & (1 << i)) == 0)
+ {
+ if(mem_mask & 0xff)
+ vram[offset | (((i + 1) & 3) * 0x8000)] = m_grcg.tile[i];
+ if(mem_mask & 0xff00)
+ vram[offset | (((i + 1) & 3) * 0x8000) | 1] = m_grcg.tile[i];
+ }
+ }
+ }
+ }
+}
+
+READ8_MEMBER(pc9801_state::ide_hack_r)
+{
+ address_space &ram = m_maincpu->space(AS_PROGRAM);
+ // this makes the ide driver not do 512 to 256 byte sector translation, the 9821 looks for bit 6 of offset 0xac403 of the kanji ram to set this, the rs unknown
+ ram.write_byte(0x457, ram.read_byte(0x457) | 0xc0);
+ return 0xff;
+}
+
+READ8_MEMBER( pc9801_state::sasi_data_r )
+{
+ UINT8 data = m_sasi_data_in->read();
+
+ if(m_sasi_ctrl_in->read() & 0x80)
+ m_sasibus->write_ack(1);
+ return data;
+}
+
+WRITE8_MEMBER( pc9801_state::sasi_data_w )
+{
+ m_sasi_data = data;
+
+ if (m_sasi_data_enable)
+ {
+ m_sasi_data_out->write(m_sasi_data);
+ if(m_sasi_ctrl_in->read() & 0x80)
+ m_sasibus->write_ack(1);
+ }
+}
+
+WRITE_LINE_MEMBER( pc9801_state::write_sasi_io )
+{
+ m_sasi_ctrl_in->write_bit2(state);
+
+ m_sasi_data_enable = !state;
+
+ if (m_sasi_data_enable)
+ {
+ m_sasi_data_out->write(m_sasi_data);
+ }
+ else
+ {
+ m_sasi_data_out->write(0);
+ }
+ if((m_sasi_ctrl_in->read() & 0x9C) == 0x8C)
+ m_pic2->ir1_w(m_sasi_ctrl & 1);
+ else
+ m_pic2->ir1_w(0);
+}
+
+WRITE_LINE_MEMBER( pc9801_state::write_sasi_req )
+{
+ m_sasi_ctrl_in->write_bit7(state);
+
+ if (!state)
+ m_sasibus->write_ack(0);
+
+ if((m_sasi_ctrl_in->read() & 0x9C) == 0x8C)
+ m_pic2->ir1_w(m_sasi_ctrl & 1);
+ else
+ m_pic2->ir1_w(0);
+
+ m_dmac->dreq0_w(!(state && !(m_sasi_ctrl_in->read() & 8) && (m_sasi_ctrl & 2)));
+}
+
+
+READ8_MEMBER( pc9801_state::sasi_status_r )
+{
+ UINT8 res = 0;
+
+ if(m_sasi_ctrl & 0x40) // read status
+ {
+ /*
+ x--- ---- REQ
+ -x-- ---- ACK
+ --x- ---- BSY
+ ---x ---- MSG
+ ---- x--- CD
+ ---- -x-- IO
+ ---- ---x INT?
+ */
+ res |= m_sasi_ctrl_in->read();
+ }
+ else // read drive info
+ {
+/*
+ xx-- ---- unknown but tested
+ --xx x--- SASI-1 media type
+ ---- -xxx SASI-2 media type
+*/
+ //res |= 7 << 3; // read mediatype SASI-1
+ //res |= 7; // read mediatype SASI-2
+ }
+ return res;
+}
+
+WRITE8_MEMBER( pc9801_state::sasi_ctrl_w )
+{
+ /*
+ x--- ---- channel enable
+ -x-- ---- read switch
+ --x- ---- sel
+ ---- x--- reset line
+ ---- --x- dma enable
+ ---- ---x irq enable
+ */
+
+ m_sasibus->write_sel(BIT(data, 5));
+
+ if(m_sasi_ctrl & 8 && ((data & 8) == 0)) // 1 -> 0 transition
+ {
+ m_sasibus->write_rst(1);
+// m_timer_rst->adjust(attotime::from_nsec(100));
+ }
+ else
+ m_sasibus->write_rst(0); // TODO
+
+ m_sasi_ctrl = data;
+
+// m_sasibus->write_sel(BIT(data, 0));
+}
+
+static ADDRESS_MAP_START( pc9801_map, AS_PROGRAM, 16, pc9801_state )
+ AM_RANGE(0x00000, 0x9ffff) AM_RAM //work RAM
+ AM_RANGE(0xa0000, 0xa3fff) AM_READWRITE(tvram_r,tvram_w) //TVRAM
+ AM_RANGE(0xa8000, 0xbffff) AM_READWRITE8(gvram_r,gvram_w,0xffff) //bitmap VRAM
+ AM_RANGE(0xcc000, 0xcdfff) AM_ROM AM_REGION("sound_bios",0) //sound BIOS
+ AM_RANGE(0xd6000, 0xd6fff) AM_ROM AM_REGION("fdc_bios_2dd",0) //floppy BIOS 2dd
+ AM_RANGE(0xd7000, 0xd7fff) AM_ROM AM_REGION("fdc_bios_2hd",0) //floppy BIOS 2hd
+ AM_RANGE(0xe8000, 0xfffff) AM_ROM AM_REGION("ipl",0)
+ADDRESS_MAP_END
+
+/* first device is even offsets, second one is odd offsets */
+static ADDRESS_MAP_START( pc9801_io, AS_IO, 16, pc9801_state )
+ ADDRESS_MAP_UNMAP_HIGH
+ AM_RANGE(0x0000, 0x001f) AM_DEVREADWRITE8("i8237", am9517a_device, read, write, 0xff00)
+ AM_RANGE(0x0000, 0x000f) AM_READWRITE8(pic_r, pic_w, 0x00ff) // i8259 PIC (bit 3 ON slave / master) / i8237 DMA
+ AM_RANGE(0x0020, 0x0027) AM_WRITE8(rtc_dmapg_w,0xffff) // RTC / DMA registers (LS244)
+ AM_RANGE(0x0030, 0x0037) AM_DEVREADWRITE8("ppi8255_sys", i8255_device, read, write, 0xff00) //i8251 RS232c / i8255 system port
+ AM_RANGE(0x0040, 0x0047) AM_DEVREADWRITE8("ppi8255_prn", i8255_device, read, write, 0x00ff)
+ AM_RANGE(0x0040, 0x0043) AM_DEVREADWRITE8("keyb", pc9801_kbd_device, rx_r, tx_w, 0xff00) //i8255 printer port / i8251 keyboard
+ AM_RANGE(0x0050, 0x0057) AM_DEVREADWRITE8("ppi8255_fdd", i8255_device, read, write, 0xff00)
+ AM_RANGE(0x0050, 0x0053) AM_WRITE8(nmi_ctrl_w,0x00ff) // NMI FF / i8255 floppy port (2d?)
+ AM_RANGE(0x0060, 0x0063) AM_DEVREADWRITE8("upd7220_chr", upd7220_device, read, write, 0x00ff) //upd7220 character ports / <undefined>
+ AM_RANGE(0x0064, 0x0065) AM_WRITE8(vrtc_clear_w,0x00ff)
+ AM_RANGE(0x0068, 0x0069) AM_WRITE8(pc9801_video_ff_w,0x00ff) //mode FF / <undefined>
+// AM_RANGE(0x006c, 0x006f) border color / <undefined>
+ AM_RANGE(0x0070, 0x007f) AM_DEVREADWRITE8("pit8253", pit8253_device, read, write, 0xff00)
+ AM_RANGE(0x0070, 0x007b) AM_READWRITE8(txt_scrl_r,txt_scrl_w,0x00ff) //display registers / i8253 pit
+ AM_RANGE(0x0080, 0x0081) AM_READWRITE8(sasi_data_r, sasi_data_w, 0x00ff)
+ AM_RANGE(0x0082, 0x0083) AM_READWRITE8(sasi_status_r, sasi_ctrl_w,0x00ff)
+ AM_RANGE(0x0090, 0x0097) AM_READWRITE8(pc9801_fdc_2hd_r,pc9801_fdc_2hd_w,0xffff) //upd765a 2hd / cmt
+ AM_RANGE(0x00a0, 0x00af) AM_READWRITE8(pc9801_a0_r,pc9801_a0_w,0xffff) //upd7220 bitmap ports / display registers
+ AM_RANGE(0x00c8, 0x00cd) AM_READWRITE8(pc9801_fdc_2dd_r,pc9801_fdc_2dd_w,0xffff) //upd765a 2dd / <undefined>
+// AM_RANGE(0x0188, 0x018b) AM_READWRITE8(pc9801_opn_r,pc9801_opn_w,0xffff) //ym2203 opn / <undefined>
+ AM_RANGE(0x7fd8, 0x7fdf) AM_DEVREADWRITE8("ppi8255_mouse", i8255_device, read, write, 0xff00)
+ADDRESS_MAP_END
+
+/*************************************
+ *
+ * PC-9801RS specific handlers (IA-32)
+ *
+ ************************************/
+
+READ8_MEMBER(pc9801_state::pc9801rs_ipl_r) { return m_ipl_rom[(offset & 0x1ffff)+(m_rom_bank*0x20000)]; }
+
+/* TODO: it's possible that the offset calculation is actually linear. */
+/* TODO: having this non-linear makes the system to boot in BASIC for PC-9821. Perhaps it stores settings? How to change these? */
+READ8_MEMBER(pc9801_state::pc9801rs_knjram_r)
+{
+ UINT32 pcg_offset;
+
+ pcg_offset = m_font_addr << 5;
+ pcg_offset|= offset & 0x1e;
+ pcg_offset|= m_font_lr;
+
+ if(!(m_font_addr & 0xff))
+ {
+ int char_size = m_video_ff[FONTSEL_REG];
+ return m_char_rom[(m_font_addr >> 8) * (8 << char_size) + (char_size * 0x800) + ((offset >> 1) & 0xf)];
+ }
+
+ /* TODO: investigate on this difference */
+ if((m_font_addr & 0xff00) == 0x5600 || (m_font_addr & 0xff00) == 0x5700)
+ return m_kanji_rom[pcg_offset];
+
+ pcg_offset = m_font_addr << 5;
+ pcg_offset|= offset & 0x1f;
+// pcg_offset|= m_font_lr;
+
+ return m_kanji_rom[pcg_offset];
+}
+
+WRITE8_MEMBER(pc9801_state::pc9801rs_knjram_w)
+{
+ UINT32 pcg_offset;
+
+ pcg_offset = m_font_addr << 5;
+ pcg_offset|= offset & 0x1e;
+ pcg_offset|= m_font_lr;
+
+ if((m_font_addr & 0xff00) == 0x5600 || (m_font_addr & 0xff00) == 0x5700)
+ {
+ m_kanji_rom[pcg_offset] = data;
+ m_gfxdecode->gfx(2)->mark_dirty(pcg_offset >> 5);
+ }
+}
+
+/* FF-based */
+WRITE8_MEMBER(pc9801_state::pc9801rs_bank_w)
+{
+ if(offset == 1)
+ {
+ if((data & 0xf0) == 0x00 || (data & 0xf0) == 0x10)
+ {
+ if((data & 0xed) == 0x00)
+ {
+ m_rom_bank = (data & 2) >> 1;
+ return;
+ }
+ }
+
+ logerror("Unknown EMS ROM setting %02x\n",data);
+ }
+ if(offset == 3)
+ {
+ if((data & 0xf0) == 0x20)
+ m_vram_bank = (data & 2) >> 1;
+ else
+ {
+ logerror("Unknown EMS RAM setting %02x\n",data);
+ }
+ }
+}
+
+READ8_MEMBER(pc9801_state::a20_ctrl_r)
+{
+ if(offset == 0x01)
+ return (m_gate_a20 ^ 1) | 0xfe;
+ else if(offset == 0x03)
+ return (m_gate_a20 ^ 1) | (m_nmi_enable << 1);
+
+ return 0x00;
+}
+
+WRITE8_MEMBER(pc9801_state::a20_ctrl_w)
+{
+ if(offset == 0x00)
+ {
+ UINT8 por;
+ /* reset POR bit, TODO: is there any other way? */
+ por = machine().device<i8255_device>("ppi8255_sys")->read(space, 2) & ~0x20;
+ machine().device<i8255_device>("ppi8255_sys")->write(space, 2,por);
+ m_maincpu->set_input_line(INPUT_LINE_A20, 0);
+ m_maincpu->set_input_line(INPUT_LINE_RESET, PULSE_LINE);
+ m_gate_a20 = 0;
+ }
+
+ if(offset == 0x01)
+ m_gate_a20 = 1;
+
+ if(offset == 0x03)
+ {
+ if(data == 0x02)
+ m_gate_a20 = 1;
+ else if(data == 0x03)
+ m_gate_a20 = 0;
+ }
+ m_maincpu->set_input_line(INPUT_LINE_A20, m_gate_a20);
+}
+
+READ8_MEMBER(pc9801_state::grcg_r)
+{
+ if(offset == 6)
+ {
+ logerror("GRCG mode R\n");
+ return 0xff;
+ }
+ else if(offset == 7)
+ {
+ logerror("GRCG tile R\n");
+ return 0xff;
+ }
+ return txt_scrl_r(space,offset);
+}
+
+WRITE8_MEMBER(pc9801_state::grcg_w)
+{
+ if(offset == 6)
+ {
+// logerror("%02x GRCG MODE\n",data);
+ m_grcg.mode = data;
+ m_grcg.tile_index = 0;
+ return;
+ }
+ else if(offset == 7)
+ {
+// logerror("%02x GRCG TILE %02x\n",data,m_grcg.tile_index);
+ m_grcg.tile[m_grcg.tile_index] = BITSWAP8(data,0,1,2,3,4,5,6,7);
+ m_grcg.tile_index ++;
+ m_grcg.tile_index &= 3;
+ return;
+ }
+
+ txt_scrl_w(space,offset,data);
+}
+
+WRITE16_MEMBER(pc9801_state::egc_w)
+{
+ if(!m_ex_video_ff[2])
+ return;
+
+ if(!(m_egc.regs[1] & 0x6000) || (offset != 4)) // why?
+ COMBINE_DATA(&m_egc.regs[offset]);
+ switch(offset)
+ {
+ case 1:
+ case 3:
+ case 5:
+ {
+ UINT8 color = 0;
+ switch((m_egc.regs[1] >> 13) & 3)
+ {
+ case 1:
+ //back color
+ color = m_egc.regs[5];
+ break;
+ case 2:
+ //fore color
+ color = m_egc.regs[3];
+ break;
+ default:
+ return;
+ }
+ m_egc.pat[0] = (color & 1) ? 0xffff : 0;
+ m_egc.pat[1] = (color & 2) ? 0xffff : 0;
+ m_egc.pat[2] = (color & 4) ? 0xffff : 0;
+ m_egc.pat[3] = (color & 8) ? 0xffff : 0;
+ break;
+ }
+ case 6:
+ case 7:
+ m_egc.count = (m_egc.regs[7] & 0xfff) + 1;
+ m_egc.first = true;
+ m_egc.init = false;
+ break;
+ }
+}
+
+READ8_MEMBER(pc9801_state::pc9810rs_fdc_ctrl_r)
+{
+ return (m_fdc_ctrl & 3) | 0xf0 | 8 | 4;
+}
+
+WRITE8_MEMBER(pc9801_state::pc9810rs_fdc_ctrl_w)
+{
+ /*
+ ---- x--- ready line?
+ ---- --x- select type (1) 2hd (0) 2dd
+ ---- ---x select irq
+ */
+
+ m_fdc_2hd->subdevice<floppy_connector>("0")->get_device()->set_rpm(data & 0x02 ? 360 : 300);
+ m_fdc_2hd->subdevice<floppy_connector>("1")->get_device()->set_rpm(data & 0x02 ? 360 : 300);
+
+ m_fdc_2hd->set_rate(data & 0x02 ? 500000 : 250000);
+
+ m_fdc_ctrl = data;
+ //if(data & 0xfc)
+ // logerror("FDC ctrl called with %02x\n",data);
+}
+
+READ8_MEMBER(pc9801_state::pc9801rs_2hd_r)
+{
+ if((offset & 1) == 0)
+ {
+ switch(offset & 6)
+ {
+ case 0: return m_fdc_2hd->msr_r(space, 0, 0xff);
+ case 2: return m_fdc_2hd->fifo_r(space, 0, 0xff);
+ case 4: return 0x44; //2hd flag
+ }
+ }
+
+ logerror("Read to undefined port [%02x]\n",offset+0x90);
+
+ return 0xff;
+}
+
+WRITE8_MEMBER(pc9801_state::pc9801rs_2hd_w)
+{
+ if((offset & 1) == 0)
+ {
+ switch(offset & 6)
+ {
+ case 2: m_fdc_2hd->fifo_w(space, 0, data, 0xff); return;
+ case 4:
+ if(data & 0x80)
+ m_fdc_2hd->soft_reset();
+
+ if(data & 0x40)
+ {
+ m_fdc_2hd->set_ready_line_connected(0);
+ m_fdc_2hd->ready_w(0);
+ }
+ else
+ m_fdc_2hd->set_ready_line_connected(1);
+
+ //TODO: verify
+ if(!(m_fdc_ctrl & 4))
+ {
+ m_fdc_2hd->subdevice<floppy_connector>("0")->get_device()->mon_w(data & 8 ? CLEAR_LINE : ASSERT_LINE);
+ m_fdc_2hd->subdevice<floppy_connector>("1")->get_device()->mon_w(data & 8 ? CLEAR_LINE : ASSERT_LINE);
+ }
+ return;
+ }
+ }
+
+ logerror("Write to undefined port [%02x] %02x\n",offset+0x90,data);
+}
+
+#if 0
+READ8_MEMBER(pc9801_state::pc9801rs_2dd_r)
+{
+// if(m_fdc_ctrl & 1)
+// return 0xff;
+
+ if((offset & 1) == 0)
+ {
+ switch(offset & 6)
+ {
+ case 0: return machine().device<upd765a_device>("upd765_2hd")->msr_r(space, 0, 0xff);
+ case 2: return machine().device<upd765a_device>("upd765_2hd")->fifo_r(space, 0, 0xff);
+ case 4: return 0x44; //2dd flag
+ }
+ }
+
+ logerror("Read to undefined port [%02x]\n",offset+0x90);
+
+ return 0xff;
+}
+
+WRITE8_MEMBER(pc9801_state::pc9801rs_2dd_w)
+{
+// if(m_fdc_ctrl & 1)
+// return;
+
+ if((offset & 1) == 0)
+ {
+ switch(offset & 6)
+ {
+ case 2: machine().device<upd765a_device>("upd765_2hd")->fifo_w(space, 0, data, 0xff); return;
+ case 4: logerror("%02x 2DD FDC ctrl\n",data); return;
+ }
+ }
+
+ logerror("Write to undefined port [%02x] %02x\n",offset+0x90,data);
+}
+#endif
+
+WRITE8_MEMBER(pc9801_state::pc9801rs_video_ff_w)
+{
+ if(offset == 1)
+ {
+ if((data & 0xf0) == 0) /* disable any PC-9821 specific HW regs */
+ m_ex_video_ff[(data & 0xfe) >> 1] = data & 1;
+
+ if(0)
+ {
+ static const char *const ex_video_ff_regnames[] =
+ {
+ "16 colors mode", // 0
+ "<unknown>", // 1
+ "EGC related", // 2
+ "<unknown>" // 3
+ };
+
+ logerror("Write to extended video FF register %s -> %02x\n",ex_video_ff_regnames[(data & 0x06) >> 1],data & 1);
+ }
+ //else
+ // logerror("Write to extended video FF register %02x\n",data);
+
+ return;
+ }
+
+ pc9801_video_ff_w(space,offset,data);
+}
+
+WRITE8_MEMBER(pc9801_state::pc9801rs_a0_w)
+{
+ if((offset & 1) == 0 && offset & 8 && m_ex_video_ff[ANALOG_16_MODE])
+ {
+ switch(offset)
+ {
+ case 0x08: m_analog16.pal_entry = data & 0xf; break;
+ case 0x0a: m_analog16.g[m_analog16.pal_entry] = data & 0xf; break;
+ case 0x0c: m_analog16.r[m_analog16.pal_entry] = data & 0xf; break;
+ case 0x0e: m_analog16.b[m_analog16.pal_entry] = data & 0xf; break;
+ }
+
+ m_palette->set_pen_color((m_analog16.pal_entry)+0x10,
+ pal4bit(m_analog16.r[m_analog16.pal_entry]),
+ pal4bit(m_analog16.g[m_analog16.pal_entry]),
+ pal4bit(m_analog16.b[m_analog16.pal_entry]));
+ return;
+ }
+
+ pc9801_a0_w(space,offset,data);
+}
+
+READ8_MEMBER( pc9801_state::pc9801rs_access_ctrl_r )
+{
+ if(offset == 1)
+ return m_access_ctrl;
+
+ return 0xff;
+}
+
+WRITE8_MEMBER( pc9801_state::pc9801rs_access_ctrl_w )
+{
+ if(offset == 1)
+ m_access_ctrl = data;
+}
+
+WRITE8_MEMBER( pc9801_state::pc9801rs_mouse_freq_w )
+{
+ /* TODO: bit 3 used */
+ if(offset == 3)
+ {
+ m_mouse.freq_reg = data & 3;
+ m_mouse.freq_index = 0;
+ }
+}
+
+
+WRITE8_MEMBER( pc9801_state::pc9801rs_nmi_w )
+{
+ if(offset == 0)
+ m_nmi_enable = 0;
+
+ if(offset == 2)
+ m_nmi_enable = 1;
+}
+
+READ8_MEMBER( pc9801_state::pc9801rs_midi_r )
+{
+ /* unconnect, needed by Amaranth KH to boot */
+ return 0xff;
+}
+
+READ8_MEMBER(pc9801_state::pic_r)
+{
+ return ((offset >= 4) ? m_pic2 : m_pic1)->read(space, offset & 3);
+}
+
+WRITE8_MEMBER(pc9801_state::pic_w)
+{
+ ((offset >= 4) ? m_pic2 : m_pic1)->write(space, offset & 3, data);
+}
+
+READ16_MEMBER(pc9801_state::grcg_gvram_r)
+{
+ UINT16 ret = upd7220_grcg_r(space, (offset + 0x4000) | (m_vram_bank << 16), mem_mask);
+ return BITSWAP16(ret,8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7);
+}
+
+WRITE16_MEMBER(pc9801_state::grcg_gvram_w)
+{
+ data = BITSWAP16(data,8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7);
+ upd7220_grcg_w(space, (offset + 0x4000) | (m_vram_bank << 16), data, mem_mask);
+}
+
+READ16_MEMBER(pc9801_state::grcg_gvram0_r)
+{
+ UINT16 ret = upd7220_grcg_r(space, offset | (m_vram_bank << 16), mem_mask);
+ return BITSWAP16(ret,8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7);
+}
+
+WRITE16_MEMBER(pc9801_state::grcg_gvram0_w)
+{
+ data = BITSWAP16(data,8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7);
+ upd7220_grcg_w(space, offset | (m_vram_bank << 16), data, mem_mask);
+}
+
+static ADDRESS_MAP_START( pc9801ux_map, AS_PROGRAM, 16, pc9801_state )
+ AM_RANGE(0x000000, 0x09ffff) AM_RAMBANK("wram")
+ AM_RANGE(0x0a0000, 0x0a3fff) AM_READWRITE(tvram_r, tvram_w)
+ AM_RANGE(0x0a4000, 0x0a4fff) AM_READWRITE8(pc9801rs_knjram_r, pc9801rs_knjram_w, 0xffff)
+ AM_RANGE(0x0a8000, 0x0bffff) AM_READWRITE(grcg_gvram_r, grcg_gvram_w)
+ AM_RANGE(0x0e0000, 0x0e7fff) AM_READWRITE(grcg_gvram0_r,grcg_gvram0_w)
+ AM_RANGE(0x0e0000, 0x0fffff) AM_READ8(pc9801rs_ipl_r, 0xffff)
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( pc9801ux_io, AS_IO, 16, pc9801_state )
+ ADDRESS_MAP_UNMAP_HIGH
+ AM_RANGE(0x0050, 0x0057) AM_NOP // 2dd ppi?
+ AM_RANGE(0x005c, 0x005f) AM_READ(pc9821_timestamp_r) AM_WRITENOP // artic
+ AM_RANGE(0x0068, 0x006b) AM_WRITE8(pc9801rs_video_ff_w,0x00ff) //mode FF / <undefined>
+ AM_RANGE(0x0070, 0x007f) AM_READWRITE8(grcg_r, grcg_w, 0x00ff) //display registers "GRCG" / i8253 pit
+ AM_RANGE(0x0090, 0x0097) AM_READWRITE8(pc9801rs_2hd_r, pc9801rs_2hd_w, 0xffff)
+ AM_RANGE(0x00a0, 0x00af) AM_READWRITE8(pc9801_a0_r, pc9801rs_a0_w, 0xffff) //upd7220 bitmap ports / display registers
+ AM_RANGE(0x00bc, 0x00bf) AM_READWRITE8(pc9810rs_fdc_ctrl_r,pc9810rs_fdc_ctrl_w,0xffff)
+ AM_RANGE(0x00c8, 0x00cf) AM_READWRITE8(pc9801rs_2hd_r, pc9801rs_2hd_w, 0xffff)
+ AM_RANGE(0x00f0, 0x00ff) AM_READWRITE8(a20_ctrl_r, a20_ctrl_w, 0x00ff)
+ AM_RANGE(0x0438, 0x043b) AM_READWRITE8(pc9801rs_access_ctrl_r,pc9801rs_access_ctrl_w,0xffff)
+ AM_RANGE(0x043c, 0x043f) AM_WRITE8(pc9801rs_bank_w, 0xffff) //ROM/RAM bank
+ AM_RANGE(0x04a0, 0x04af) AM_WRITE(egc_w)
+ AM_RANGE(0x3fd8, 0x3fdf) AM_DEVREADWRITE8("pit8253", pit8253_device, read, write, 0xff00)
+// AM_RANGE(0xa460, 0xa463) AM_READWRITE8(pc9801_ext_opna_r, pc9801_ext_opna_w, 0xffff)
+ AM_IMPORT_FROM(pc9801_io)
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( pc9801rs_map, AS_PROGRAM, 16, pc9801_state )
+// AM_RANGE(0x0d8000, 0x0d9fff) AM_ROM AM_REGION("ide",0)
+ AM_RANGE(0x0da000, 0x0dbfff) AM_RAM // ide ram
+ AM_RANGE(0xee0000, 0xefffff) AM_READ8(pc9801rs_ipl_r, 0xffff)
+ AM_RANGE(0xfe0000, 0xffffff) AM_READ8(pc9801rs_ipl_r, 0xffff)
+ AM_IMPORT_FROM(pc9801ux_map)
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( pc9801rs_io, AS_IO, 16, pc9801_state )
+ ADDRESS_MAP_UNMAP_HIGH
+ AM_RANGE(0x0050, 0x0053) AM_WRITE8(pc9801rs_nmi_w, 0xffff)
+ AM_RANGE(0x0430, 0x0433) AM_READ8(ide_hack_r, 0x00ff)
+ AM_RANGE(0x0640, 0x064f) AM_DEVREADWRITE("ide", ata_interface_device, read_cs0, write_cs0)
+ AM_RANGE(0x0740, 0x074f) AM_DEVREADWRITE("ide", ata_interface_device, read_cs1, write_cs1)
+ AM_RANGE(0xbfd8, 0xbfdf) AM_WRITE8(pc9801rs_mouse_freq_w, 0xffff)
+ AM_RANGE(0xe0d0, 0xe0d3) AM_READ8(pc9801rs_midi_r, 0xffff)
+ AM_IMPORT_FROM(pc9801ux_io)
+ADDRESS_MAP_END
+
+/*************************************
+ *
+ * PC-9821 specific handlers
+ *
+ ************************************/
+
+WRITE8_MEMBER(pc9801_state::pc9821_video_ff_w)
+{
+ if(offset == 1)
+ {
+ m_ex_video_ff[(data & 0xfe) >> 1] = data & 1;
+
+ //if((data & 0xfe) == 0x20)
+ // logerror("%02x\n",data & 1);
+ }
+
+ /* Intentional fall-through */
+ pc9801rs_video_ff_w(space,offset,data);
+}
+
+READ8_MEMBER(pc9801_state::pc9821_a0_r)
+{
+ if((offset & 1) == 0 && offset & 8)
+ {
+ if(m_ex_video_ff[ANALOG_256_MODE])
+ {
+ logerror("256 color mode [%02x] R\n",offset);
+ return 0;
+ }
+ else if(m_ex_video_ff[ANALOG_16_MODE]) //16 color mode, readback possible there
+ {
+ UINT8 res = 0;
+
+ switch(offset)
+ {
+ case 0x08: res = m_analog16.pal_entry & 0xf; break;
+ case 0x0a: res = m_analog16.g[m_analog16.pal_entry] & 0xf; break;
+ case 0x0c: res = m_analog16.r[m_analog16.pal_entry] & 0xf; break;
+ case 0x0e: res = m_analog16.b[m_analog16.pal_entry] & 0xf; break;
+ }
+
+ return res;
+ }
+ }
+
+ return pc9801_a0_r(space,offset);
+}
+
+WRITE8_MEMBER(pc9801_state::pc9821_a0_w)
+{
+ if((offset & 1) == 0 && offset & 8 && m_ex_video_ff[ANALOG_256_MODE])
+ {
+ switch(offset)
+ {
+ case 0x08: m_analog256.pal_entry = data & 0xff; break;
+ case 0x0a: m_analog256.g[m_analog256.pal_entry] = data & 0xff; break;
+ case 0x0c: m_analog256.r[m_analog256.pal_entry] = data & 0xff; break;
+ case 0x0e: m_analog256.b[m_analog256.pal_entry] = data & 0xff; break;
+ }
+
+ m_palette->set_pen_color((m_analog256.pal_entry)+0x20,
+ m_analog256.r[m_analog256.pal_entry],
+ m_analog256.g[m_analog256.pal_entry],
+ m_analog256.b[m_analog256.pal_entry]);
+ return;
+ }
+
+ pc9801rs_a0_w(space,offset,data);
+}
+
+READ8_MEMBER(pc9801_state::pc9821_window_bank_r)
+{
+ if(offset == 1)
+ return m_pc9821_window_bank & 0xfe;
+
+ return 0xff;
+}
+
+WRITE8_MEMBER(pc9801_state::pc9821_window_bank_w)
+{
+ if(offset == 1)
+ m_pc9821_window_bank = data & 0xfe;
+ else
+ logerror("PC-9821 $f0000 window bank %02x\n",data);
+}
+
+UINT8 pc9801_state::m_sdip_read(UINT16 port, UINT8 sdip_offset)
+{
+ if(port == 2)
+ return m_sdip[sdip_offset];
+
+ logerror("Warning: read from unknown SDIP area %02x %04x\n",port,0x841c + port + (sdip_offset % 12)*0x100);
+ return 0xff;
+}
+
+void pc9801_state::m_sdip_write(UINT16 port, UINT8 sdip_offset,UINT8 data)
+{
+ if(port == 2)
+ {
+ m_sdip[sdip_offset] = data;
+ return;
+ }
+
+ logerror("Warning: write from unknown SDIP area %02x %04x %02x\n",port,0x841c + port + (sdip_offset % 12)*0x100,data);
+}
+
+READ8_MEMBER(pc9801_state::sdip_0_r) { return m_sdip_read(offset, 0+m_sdip_bank*12); }
+READ8_MEMBER(pc9801_state::sdip_1_r) { return m_sdip_read(offset, 1+m_sdip_bank*12); }
+READ8_MEMBER(pc9801_state::sdip_2_r) { return m_sdip_read(offset, 2+m_sdip_bank*12); }
+READ8_MEMBER(pc9801_state::sdip_3_r) { return m_sdip_read(offset, 3+m_sdip_bank*12); }
+READ8_MEMBER(pc9801_state::sdip_4_r) { return m_sdip_read(offset, 4+m_sdip_bank*12); }
+READ8_MEMBER(pc9801_state::sdip_5_r) { return m_sdip_read(offset, 5+m_sdip_bank*12); }
+READ8_MEMBER(pc9801_state::sdip_6_r) { return m_sdip_read(offset, 6+m_sdip_bank*12); }
+READ8_MEMBER(pc9801_state::sdip_7_r) { return m_sdip_read(offset, 7+m_sdip_bank*12); }
+READ8_MEMBER(pc9801_state::sdip_8_r) { return m_sdip_read(offset, 8+m_sdip_bank*12); }
+READ8_MEMBER(pc9801_state::sdip_9_r) { return m_sdip_read(offset, 9+m_sdip_bank*12); }
+READ8_MEMBER(pc9801_state::sdip_a_r) { return m_sdip_read(offset, 10+m_sdip_bank*12); }
+READ8_MEMBER(pc9801_state::sdip_b_r) { return m_sdip_read(offset, 11+m_sdip_bank*12); }
+
+WRITE8_MEMBER(pc9801_state::sdip_0_w) { m_sdip_write(offset,0+m_sdip_bank*12,data); }
+WRITE8_MEMBER(pc9801_state::sdip_1_w) { m_sdip_write(offset,1+m_sdip_bank*12,data); }
+WRITE8_MEMBER(pc9801_state::sdip_2_w) { m_sdip_write(offset,2+m_sdip_bank*12,data); }
+WRITE8_MEMBER(pc9801_state::sdip_3_w) { m_sdip_write(offset,3+m_sdip_bank*12,data); }
+WRITE8_MEMBER(pc9801_state::sdip_4_w) { m_sdip_write(offset,4+m_sdip_bank*12,data); }
+WRITE8_MEMBER(pc9801_state::sdip_5_w) { m_sdip_write(offset,5+m_sdip_bank*12,data); }
+WRITE8_MEMBER(pc9801_state::sdip_6_w) { m_sdip_write(offset,6+m_sdip_bank*12,data); }
+WRITE8_MEMBER(pc9801_state::sdip_7_w) { m_sdip_write(offset,7+m_sdip_bank*12,data); }
+WRITE8_MEMBER(pc9801_state::sdip_8_w) { m_sdip_write(offset,8+m_sdip_bank*12,data); }
+WRITE8_MEMBER(pc9801_state::sdip_9_w) { m_sdip_write(offset,9+m_sdip_bank*12,data); }
+WRITE8_MEMBER(pc9801_state::sdip_a_w) { m_sdip_write(offset,10+m_sdip_bank*12,data); }
+WRITE8_MEMBER(pc9801_state::sdip_b_w)
+{
+ if(offset == 3)
+ m_sdip_bank = (data & 0x40) >> 6;
+
+ if(offset == 2)
+ m_sdip_write(offset,11+m_sdip_bank*12,data);
+
+ if((offset & 2) == 0)
+ logerror("SDIP area B write %02x %02x\n",offset,data);
+}
+
+READ16_MEMBER(pc9801_state::pc9821_timestamp_r)
+{
+ return (m_maincpu->total_cycles() >> (16 * offset));
+}
+
+/* basically a read-back of various registers */
+READ8_MEMBER(pc9801_state::pc9821_ext2_video_ff_r)
+{
+ UINT8 res;
+
+ res = 0;
+
+ switch(m_ext2_ff)
+ {
+ case 3: res = m_video_ff[DISPLAY_REG]; break; // display reg
+ default:
+ logerror("PC-9821: read ext2 f/f with value %02x\n",m_ext2_ff);
+ }
+
+ return res;
+}
+
+WRITE8_MEMBER(pc9801_state::pc9821_ext2_video_ff_w)
+{
+ m_ext2_ff = data;
+}
+
+/*READ8_MEMBER(pc9801_state::winram_r)
+{
+ offset = (offset & 0x1ffff) | (m_pc9821_window_bank & 0xfe) * 0x10000;
+ return
+}
+
+
+WRITE8_MEMBER(pc9801_state::winram_w)
+{
+ offset = (offset & 0x1ffff) | (m_pc9821_window_bank & 0xfe) * 0x10000;
+}*/
+
+static ADDRESS_MAP_START( pc9821_map, AS_PROGRAM, 32, pc9801_state )
+ AM_RANGE(0x00000000, 0x0009ffff) AM_RAMBANK("wram")
+ //AM_RANGE(0x00080000, 0x0009ffff) AM_READWRITE8(winram_r, winram_w, 0xffffffff)
+ AM_RANGE(0x000a0000, 0x000a3fff) AM_READWRITE16(tvram_r, tvram_w, 0xffffffff)
+ AM_RANGE(0x000a4000, 0x000a4fff) AM_READWRITE8(pc9801rs_knjram_r, pc9801rs_knjram_w, 0xffffffff)
+ AM_RANGE(0x000a8000, 0x000bffff) AM_READWRITE16(grcg_gvram_r, grcg_gvram_w, 0xffffffff)
+ AM_RANGE(0x000cc000, 0x000cdfff) AM_ROM AM_REGION("sound_bios",0) //sound BIOS
+// AM_RANGE(0x000d8000, 0x000d9fff) AM_ROM AM_REGION("ide",0)
+ AM_RANGE(0x000da000, 0x000dbfff) AM_RAM // ide ram
+ AM_RANGE(0x000e0000, 0x000e7fff) AM_READWRITE16(grcg_gvram0_r,grcg_gvram0_w, 0xffffffff)
+ AM_RANGE(0x000e0000, 0x000fffff) AM_READ8(pc9801rs_ipl_r, 0xffffffff)
+ AM_RANGE(0x00f00000, 0x00f9ffff) AM_RAM AM_SHARE("ext_gvram")
+ AM_RANGE(0xffee0000, 0xffefffff) AM_READ8(pc9801rs_ipl_r, 0xffffffff)
+ AM_RANGE(0xfffe0000, 0xffffffff) AM_READ8(pc9801rs_ipl_r, 0xffffffff)
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( pc9821_io, AS_IO, 32, pc9801_state )
+// ADDRESS_MAP_UNMAP_HIGH // TODO: a read to somewhere makes this to fail at POST
+ AM_RANGE(0x0000, 0x001f) AM_DEVREADWRITE8("i8237", am9517a_device, read, write, 0xff00ff00)
+ AM_RANGE(0x0000, 0x000f) AM_READWRITE8(pic_r, pic_w, 0x00ff00ff) // i8259 PIC (bit 3 ON slave / master) / i8237 DMA
+ AM_RANGE(0x0020, 0x0027) AM_WRITE8(rtc_dmapg_w, 0xffffffff) // RTC / DMA registers (LS244)
+ AM_RANGE(0x0030, 0x0037) AM_DEVREADWRITE8("ppi8255_sys", i8255_device, read, write, 0xff00ff00) //i8251 RS232c / i8255 system port
+ AM_RANGE(0x0040, 0x0047) AM_DEVREADWRITE8("ppi8255_prn", i8255_device, read, write, 0x00ff00ff)
+ AM_RANGE(0x0040, 0x0043) AM_DEVREADWRITE8("keyb", pc9801_kbd_device, rx_r, tx_w, 0xff00ff00) //i8255 printer port / i8251 keyboard
+ AM_RANGE(0x0050, 0x0053) AM_WRITE8(pc9801rs_nmi_w, 0xffffffff)
+ AM_RANGE(0x005c, 0x005f) AM_READ16(pc9821_timestamp_r,0xffffffff) AM_WRITENOP // artic
+ AM_RANGE(0x0060, 0x0063) AM_DEVREADWRITE8("upd7220_chr", upd7220_device, read, write, 0x00ff00ff) //upd7220 character ports / <undefined>
+ AM_RANGE(0x0064, 0x0067) AM_WRITE8(vrtc_clear_w, 0x000000ff)
+ AM_RANGE(0x0068, 0x006b) AM_WRITE8(pc9821_video_ff_w, 0x00ff00ff) //mode FF / <undefined>
+ AM_RANGE(0x0070, 0x007f) AM_DEVREADWRITE8("pit8253", pit8253_device, read, write, 0xff00ff00)
+ AM_RANGE(0x0070, 0x007f) AM_READWRITE8(grcg_r, grcg_w, 0x00ff00ff) //display registers "GRCG" / i8253 pit
+ AM_RANGE(0x0090, 0x0097) AM_READWRITE8(pc9801rs_2hd_r, pc9801rs_2hd_w, 0xffffffff)
+ AM_RANGE(0x00a0, 0x00af) AM_READWRITE8(pc9821_a0_r, pc9821_a0_w, 0xffffffff) //upd7220 bitmap ports / display registers
+// AM_RANGE(0x00b0, 0x00b3) PC9861k (serial port?)
+// AM_RANGE(0x00b9, 0x00b9) PC9861k
+// AM_RANGE(0x00bb, 0x00bb) PC9861k
+ AM_RANGE(0x00bc, 0x00bf) AM_READWRITE8(pc9810rs_fdc_ctrl_r,pc9810rs_fdc_ctrl_w,0xffffffff)
+ AM_RANGE(0x00c8, 0x00cf) AM_READWRITE8(pc9801rs_2hd_r, pc9801rs_2hd_w, 0xffffffff)
+// AM_RANGE(0x00d8, 0x00df) AMD98 (sound?) board
+ AM_RANGE(0x00f0, 0x00ff) AM_READWRITE8(a20_ctrl_r, a20_ctrl_w, 0x00ff00ff)
+// AM_RANGE(0x0188, 0x018f) AM_READWRITE8(pc9801_opn_r, pc9801_opn_w, 0xffffffff) //ym2203 opn / <undefined>
+// AM_RANGE(0x018c, 0x018f) YM2203 OPN extended ports / <undefined>
+ AM_RANGE(0x0430, 0x0433) AM_READ8(ide_hack_r, 0x000000ff)
+ AM_RANGE(0x0438, 0x043b) AM_READWRITE8(pc9801rs_access_ctrl_r,pc9801rs_access_ctrl_w,0xffffffff)
+// AM_RANGE(0x043d, 0x043d) ROM/RAM bank (NEC)
+ AM_RANGE(0x043c, 0x043f) AM_WRITE8(pc9801rs_bank_w, 0xffffffff) //ROM/RAM bank (EPSON)
+ AM_RANGE(0x0460, 0x0463) AM_READWRITE8(pc9821_window_bank_r,pc9821_window_bank_w, 0xffffffff)
+ AM_RANGE(0x04a0, 0x04af) AM_WRITE16(egc_w, 0xffffffff)
+// AM_RANGE(0x04be, 0x04be) FDC "RPM" register
+ AM_RANGE(0x0640, 0x064f) AM_DEVREADWRITE16("ide", ata_interface_device, read_cs0, write_cs0, 0xffffffff)
+ AM_RANGE(0x0740, 0x074f) AM_DEVREADWRITE16("ide", ata_interface_device, read_cs1, write_cs1, 0xffffffff)
+// AM_RANGE(0x08e0, 0x08ea) <undefined> / EMM SIO registers
+ AM_RANGE(0x09a0, 0x09a3) AM_READWRITE8(pc9821_ext2_video_ff_r, pc9821_ext2_video_ff_w, 0x000000ff) // GDC extended register r/w
+// AM_RANGE(0x09a8, 0x09a8) GDC 31KHz register r/w
+// AM_RANGE(0x0c07, 0x0c07) EPSON register w
+// AM_RANGE(0x0c03, 0x0c03) EPSON register 0 r
+// AM_RANGE(0x0c13, 0x0c14) EPSON register 1 r
+// AM_RANGE(0x0c24, 0x0c24) cs4231 PCM board register control
+// AM_RANGE(0x0c2b, 0x0c2b) cs4231 PCM board low byte control
+// AM_RANGE(0x0c2d, 0x0c2d) cs4231 PCM board hi byte control
+// AM_RANGE(0x0cc0, 0x0cc7) SCSI interface / <undefined>
+// AM_RANGE(0x0cfc, 0x0cff) PCI bus
+ AM_RANGE(0x3fd8, 0x3fdf) AM_DEVREADWRITE8("pit8253", pit8253_device, read, write, 0xff00ff00) // <undefined> / pit mirror ports
+ AM_RANGE(0x7fd8, 0x7fdf) AM_DEVREADWRITE8("ppi8255_mouse", i8255_device, read, write, 0xff00ff00)
+ AM_RANGE(0x841c, 0x841f) AM_READWRITE8(sdip_0_r,sdip_0_w,0xffffffff)
+ AM_RANGE(0x851c, 0x851f) AM_READWRITE8(sdip_1_r,sdip_1_w,0xffffffff)
+ AM_RANGE(0x861c, 0x861f) AM_READWRITE8(sdip_2_r,sdip_2_w,0xffffffff)
+ AM_RANGE(0x871c, 0x871f) AM_READWRITE8(sdip_3_r,sdip_3_w,0xffffffff)
+ AM_RANGE(0x881c, 0x881f) AM_READWRITE8(sdip_4_r,sdip_4_w,0xffffffff)
+ AM_RANGE(0x891c, 0x891f) AM_READWRITE8(sdip_5_r,sdip_5_w,0xffffffff)
+ AM_RANGE(0x8a1c, 0x8a1f) AM_READWRITE8(sdip_6_r,sdip_6_w,0xffffffff)
+ AM_RANGE(0x8b1c, 0x8b1f) AM_READWRITE8(sdip_7_r,sdip_7_w,0xffffffff)
+ AM_RANGE(0x8c1c, 0x8c1f) AM_READWRITE8(sdip_8_r,sdip_8_w,0xffffffff)
+ AM_RANGE(0x8d1c, 0x8d1f) AM_READWRITE8(sdip_9_r,sdip_9_w,0xffffffff)
+ AM_RANGE(0x8e1c, 0x8e1f) AM_READWRITE8(sdip_a_r,sdip_a_w,0xffffffff)
+ AM_RANGE(0x8f1c, 0x8f1f) AM_READWRITE8(sdip_b_r,sdip_b_w,0xffffffff)
+// AM_RANGE(0xa460, 0xa463) AM_READWRITE8(pc9801_ext_opna_r, pc9801_ext_opna_w, 0xffffffff)
+// AM_RANGE(0xa460, 0xa46f) cs4231 PCM extended port / <undefined>
+// AM_RANGE(0xbfdb, 0xbfdb) mouse timing port
+// AM_RANGE(0xc0d0, 0xc0d3) MIDI port, option 0 / <undefined>
+// AM_RANGE(0xc4d0, 0xc4d3) MIDI port, option 1 / <undefined>
+// AM_RANGE(0xc8d0, 0xc8d3) MIDI port, option 2 / <undefined>
+// AM_RANGE(0xccd0, 0xccd3) MIDI port, option 3 / <undefined>
+// AM_RANGE(0xd0d0, 0xd0d3) MIDI port, option 4 / <undefined>
+// AM_RANGE(0xd4d0, 0xd4d3) MIDI port, option 5 / <undefined>
+// AM_RANGE(0xd8d0, 0xd8d3) MIDI port, option 6 / <undefined>
+// AM_RANGE(0xdcd0, 0xdcd3) MIDI port, option 7 / <undefined>
+ AM_RANGE(0xe0d0, 0xe0d3) AM_READ8(pc9801rs_midi_r, 0xffffffff) // MIDI port, option 8 / <undefined>
+// AM_RANGE(0xe4d0, 0xe4d3) MIDI port, option 9 / <undefined>
+// AM_RANGE(0xe8d0, 0xe8d3) MIDI port, option A / <undefined>
+// AM_RANGE(0xecd0, 0xecd3) MIDI port, option B / <undefined>
+// AM_RANGE(0xf0d0, 0xf0d3) MIDI port, option C / <undefined>
+// AM_RANGE(0xf4d0, 0xf4d3) MIDI port, option D / <undefined>
+// AM_RANGE(0xf8d0, 0xf8d3) MIDI port, option E / <undefined>
+// AM_RANGE(0xfcd0, 0xfcd3) MIDI port, option F / <undefined>
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( upd7220_1_map, AS_0, 16, pc9801_state )
+ AM_RANGE(0x00000, 0x3ffff) AM_RAM AM_SHARE("video_ram_1")
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( upd7220_2_map, AS_0, 16, pc9801_state )
+ AM_RANGE(0x00000, 0x3ffff) AM_RAM AM_SHARE("video_ram_2")
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( upd7220_grcg_2_map, AS_0, 16, pc9801_state )
+ AM_RANGE(0x00000, 0x3ffff) AM_READWRITE(upd7220_grcg_r, upd7220_grcg_w) AM_SHARE("video_ram_2")
+ADDRESS_MAP_END
+
+CUSTOM_INPUT_MEMBER(pc9801_state::system_type_r)
+{
+// System Type (0x00 stock PC-9801, 0xc0 PC-9801U / PC-98LT, PC-98HA, 0x80 others)
+ return m_sys_type;
+}
+
+static INPUT_PORTS_START( pc9801 )
+ PORT_START("DSW1")
+ PORT_BIT(0x0001, IP_ACTIVE_HIGH,IPT_SPECIAL) PORT_READ_LINE_DEVICE_MEMBER("upd1990a", upd1990a_device, data_out_r)
+ PORT_DIPNAME( 0x0002, 0x0000, "DSW1" ) // error beep if OFF
+ PORT_DIPSETTING( 0x0002, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
+ PORT_DIPNAME( 0x0004, 0x0000, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x0004, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
+ PORT_DIPNAME( 0x0008, 0x0008, "Display Type" ) PORT_DIPLOCATION("SW2:1")
+ PORT_DIPSETTING( 0x0000, "Normal Display" )
+ PORT_DIPSETTING( 0x0008, "Hi-Res Display" )
+ PORT_DIPNAME( 0x0010, 0x0000, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x0010, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
+ PORT_DIPNAME( 0x0020, 0x0020, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x0020, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
+ PORT_DIPNAME( 0x0040, 0x0040, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x0040, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
+ PORT_DIPNAME( 0x0080, 0x0080, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x0080, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
+
+ PORT_START("DSW5")
+ PORT_DIPNAME( 0x01, 0x00, "DSW5" ) // goes into basic with this off, PC-9801VF / PC-9801U setting
+ PORT_DIPSETTING( 0x01, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x02, 0x00, DEF_STR( Unknown ) ) // V30 / V33
+ PORT_DIPSETTING( 0x02, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x04, 0x04, DEF_STR( Unknown ) ) // printer busy
+ PORT_DIPSETTING( 0x04, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x08, 0x08, DEF_STR( Unknown ) ) // 8 / 4096
+ PORT_DIPSETTING( 0x08, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x10, 0x10, DEF_STR( Unknown ) ) // LCD display
+ PORT_DIPSETTING( 0x10, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x20, 0x00, DEF_STR( Unknown ) ) //system clock = 5 MHz (0) / 8 MHz (1)
+ PORT_DIPSETTING( 0x20, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_BIT( 0xc0, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM_MEMBER(DEVICE_SELF, pc9801_state, system_type_r, NULL)
+
+ PORT_START("DSW2")
+ PORT_DIPNAME( 0x01, 0x01, "System Specification" ) PORT_DIPLOCATION("SW1:1") //jumps to daa00 if off, presumably some card booting
+ PORT_DIPSETTING( 0x01, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x02, 0x02, "Terminal Mode" ) PORT_DIPLOCATION("SW1:2")
+ PORT_DIPSETTING( 0x02, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x04, 0x00, "Text width" ) PORT_DIPLOCATION("SW1:3")
+ PORT_DIPSETTING( 0x04, "40 chars/line" )
+ PORT_DIPSETTING( 0x00, "80 chars/line" )
+ PORT_DIPNAME( 0x08, 0x00, "Text height" ) PORT_DIPLOCATION("SW1:4")
+ PORT_DIPSETTING( 0x08, "20 lines/screen" )
+ PORT_DIPSETTING( 0x00, "25 lines/screen" )
+ PORT_DIPNAME( 0x10, 0x00, "Memory Switch Init" ) PORT_DIPLOCATION("SW1:5")
+ PORT_DIPSETTING( 0x00, DEF_STR( No ) ) //Fix memory switch condition
+ PORT_DIPSETTING( 0x10, DEF_STR( Yes ) ) //Initialize Memory Switch with the system default
+ PORT_DIPUNUSED_DIPLOC( 0x20, 0x20, "SW1:6" )
+ PORT_DIPUNUSED_DIPLOC( 0x40, 0x40, "SW1:7" )
+ PORT_DIPUNUSED_DIPLOC( 0x80, 0x80, "SW1:8" )
+
+ PORT_START("DSW3")
+ PORT_DIPNAME( 0x01, 0x01, "DSW3" )
+ PORT_DIPSETTING( 0x01, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x02, 0x02, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x02, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x04, 0x04, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x04, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x08, 0x08, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x08, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x10, 0x10, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x10, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x20, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x40, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x80, 0x80, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x80, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+
+ PORT_START("DSW4")
+ PORT_DIPNAME( 0x01, 0x01, "DSW4" )
+ PORT_DIPSETTING( 0x01, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x02, 0x02, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x02, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x04, 0x04, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x04, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x08, 0x08, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x08, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x10, 0x10, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x10, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x20, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x40, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x80, 0x80, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x80, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+
+ PORT_START("MOUSE_X")
+ PORT_BIT( 0xff, 0x00, IPT_MOUSE_X ) PORT_RESET PORT_SENSITIVITY(30) PORT_KEYDELTA(30)
+
+ PORT_START("MOUSE_Y")
+ PORT_BIT( 0xff, 0x00, IPT_MOUSE_Y ) PORT_RESET PORT_SENSITIVITY(30) PORT_KEYDELTA(30)
+
+ PORT_START("MOUSE_B")
+ PORT_BIT(0x0f, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_BUTTON3) PORT_CODE(MOUSECODE_BUTTON3) PORT_NAME("Mouse Middle Button")
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_CODE(MOUSECODE_BUTTON2) PORT_NAME("Mouse Right Button")
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_CODE(MOUSECODE_BUTTON1) PORT_NAME("Mouse Left Button")
+
+ PORT_START("ROM_LOAD")
+ PORT_CONFNAME( 0x01, 0x01, "Load floppy 2hd BIOS" )
+ PORT_CONFSETTING( 0x00, DEF_STR( Yes ) )
+ PORT_CONFSETTING( 0x01, DEF_STR( No ) )
+ PORT_CONFNAME( 0x02, 0x02, "Load floppy 2dd BIOS" )
+ PORT_CONFSETTING( 0x00, DEF_STR( Yes ) )
+ PORT_CONFSETTING( 0x02, DEF_STR( No ) )
+INPUT_PORTS_END
+
+static INPUT_PORTS_START( pc9801rs )
+ PORT_INCLUDE( pc9801 )
+
+ PORT_MODIFY("DSW2")
+ PORT_DIPNAME( 0x80, 0x80, "GDC clock" ) PORT_DIPLOCATION("SW1:8") // DSW 2-8
+ PORT_DIPSETTING( 0x80, "2.5 MHz" )
+ PORT_DIPSETTING( 0x00, "5 MHz" )
+
+ PORT_MODIFY("DSW4")
+ PORT_DIPNAME( 0x04, 0x00, "CPU Type" ) PORT_DIPLOCATION("SW4:8") // DSW 3-8
+ PORT_DIPSETTING( 0x04, "V30" )
+ PORT_DIPSETTING( 0x00, "I386" )
+
+ PORT_MODIFY("DSW5")
+ PORT_DIPNAME( 0x08, 0x00, "Graphic Function" ) // DSW 1-8
+ PORT_DIPSETTING( 0x08, "Basic (8 Colors)" )
+ PORT_DIPSETTING( 0x00, "Expanded (16/4096 Colors)" )
+
+ PORT_MODIFY("ROM_LOAD")
+ PORT_BIT( 0x03, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_CONFNAME( 0x04, 0x04, "Load IDE BIOS" )
+ PORT_CONFSETTING( 0x00, DEF_STR( Yes ) )
+ PORT_CONFSETTING( 0x04, DEF_STR( No ) )
+
+// PORT_START("SOUND_CONFIG")
+// PORT_CONFNAME( 0x01, 0x00, "Sound Type" )
+// PORT_CONFSETTING( 0x00, "YM2203 (OPN)" )
+// PORT_CONFSETTING( 0x01, "YM2608 (OPNA)" )
+INPUT_PORTS_END
+
+static INPUT_PORTS_START( pc9821 )
+ PORT_INCLUDE( pc9801rs )
+
+ PORT_MODIFY("DSW2")
+ PORT_DIPNAME( 0x01, 0x00, "S-Dip SW Init" ) PORT_DIPLOCATION("SW1:1")
+ PORT_DIPSETTING( 0x01, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+
+ PORT_MODIFY("DSW3")
+ PORT_DIPNAME( 0x40, 0x40, "Conventional RAM size" ) PORT_DIPLOCATION("SW3:7")
+ PORT_DIPSETTING( 0x40, "640 KB" )
+ PORT_DIPSETTING( 0x00, "512 KB" )
+INPUT_PORTS_END
+
+static const gfx_layout charset_8x8 =
+{
+ 8,8,
+ 256,
+ 1,
+ { 0 },
+ { 0, 1, 2, 3, 4, 5, 6, 7 },
+ { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 },
+ 8*8
+};
+
+static const gfx_layout charset_8x16 =
+{
+ 8,16,
+ 256,
+ 1,
+ { 0 },
+ { 0, 1, 2, 3, 4, 5, 6, 7 },
+ { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8,8*8, 9*8, 10*8, 11*8, 12*8, 13*8, 14*8, 15*8 },
+ 8*16
+};
+
+static const gfx_layout charset_16x16 =
+{
+ 16,16,
+ RGN_FRAC(1,1),
+ 1,
+ { 0 },
+ { STEP16(0,1) },
+ { STEP16(0,16) },
+ 16*16
+};
+
+static GFXDECODE_START( pc9801 )
+ GFXDECODE_ENTRY( "chargen", 0x00000, charset_8x8, 0x000, 0x01 )
+ GFXDECODE_ENTRY( "chargen", 0x00800, charset_8x16, 0x000, 0x01 )
+ GFXDECODE_ENTRY( "kanji", 0x00000, charset_16x16, 0x000, 0x01 )
+ GFXDECODE_ENTRY( "raw_kanji", 0x00000, charset_16x16, 0x000, 0x01 )
+ GFXDECODE_ENTRY( "new_chargen",0, charset_16x16, 0x000, 0x01 )
+GFXDECODE_END
+
+/****************************************
+*
+* I8259 PIC interface
+*
+****************************************/
+
+/*
+irq assignment (PC-9801F):
+
+8259 master:
+ir0 PIT
+ir1 keyboard
+ir2 vblank
+ir3
+ir4 rs-232c
+ir5
+ir6
+ir7 slave irq
+
+8259 slave:
+ir0 printer
+ir1 IDE?
+ir2 2dd floppy irq
+ir3 2hd floppy irq
+ir4 opn
+ir5 mouse
+ir6
+ir7
+*/
+
+
+READ8_MEMBER(pc9801_state::get_slave_ack)
+{
+ if (offset==7) { // IRQ = 7
+ return m_pic2->acknowledge();
+ }
+ return 0x00;
+}
+
+/****************************************
+*
+* I8253 PIT interface
+*
+****************************************/
+
+/* basically, PC-98xx series has two xtals.
+ My guess is that both are on the PCB, and they clocks the various system components.
+ PC-9801RS needs X1 for the pit, otherwise Uchiyama Aki no Chou Bangai has sound pitch bugs
+ PC-9821 definitely needs X2, otherwise there's a timer error at POST. Unless it needs a different clock anyway ...
+ */
+#define MAIN_CLOCK_X1 XTAL_1_9968MHz
+#define MAIN_CLOCK_X2 XTAL_2_4576MHz
+
+/****************************************
+*
+* I8237 DMA interface
+*
+****************************************/
+
+WRITE_LINE_MEMBER(pc9801_state::dma_hrq_changed)
+{
+ m_maincpu->set_input_line(INPUT_LINE_HALT, state ? ASSERT_LINE : CLEAR_LINE);
+
+ m_dmac->hack_w(state);
+
+// logerror("%02x HLDA\n",state);
+}
+
+WRITE_LINE_MEMBER(pc9801_state::tc_w )
+{
+ /* floppy terminal count */
+ m_fdc_2hd->tc_w(state);
+ if(m_fdc_2dd)
+ m_fdc_2dd->tc_w(state);
+
+// logerror("TC %02x\n",state);
+}
+
+READ8_MEMBER(pc9801_state::dma_read_byte)
+{
+ address_space &program = m_maincpu->space(AS_PROGRAM);
+ offs_t addr = (m_dma_offset[m_dack] << 16) | offset;
+
+// logerror("%08x\n",addr);
+
+ return program.read_byte(addr);
+}
+
+
+WRITE8_MEMBER(pc9801_state::dma_write_byte)
+{
+ address_space &program = m_maincpu->space(AS_PROGRAM);
+ offs_t addr = (m_dma_offset[m_dack] << 16) | offset;
+
+// logerror("%08x %02x\n",addr,data);
+
+ program.write_byte(addr, data);
+}
+
+void pc9801_state::set_dma_channel(int channel, int state)
+{
+ if (!state) m_dack = channel;
+}
+
+WRITE_LINE_MEMBER(pc9801_state::dack0_w){ /*logerror("%02x 0\n",state);*/ set_dma_channel(0, state); }
+WRITE_LINE_MEMBER(pc9801_state::dack1_w){ /*logerror("%02x 1\n",state);*/ set_dma_channel(1, state); }
+WRITE_LINE_MEMBER(pc9801_state::dack2_w){ /*logerror("%02x 2\n",state);*/ set_dma_channel(2, state); }
+WRITE_LINE_MEMBER(pc9801_state::dack3_w){ /*logerror("%02x 3\n",state);*/ set_dma_channel(3, state); }
+
+/*
+ch1 cs-4231a
+ch2 FDC
+ch3 SCSI
+*/
+
+/****************************************
+*
+* PPI interfaces
+*
+****************************************/
+
+WRITE8_MEMBER(pc9801_state::ppi_sys_portc_w)
+{
+ m_beeper->set_state(!(data & 0x08));
+}
+
+READ8_MEMBER(pc9801_state::ppi_mouse_porta_r)
+{
+ UINT8 res;
+ UINT8 isporthi;
+ const char *const mousenames[] = { "MOUSE_X", "MOUSE_Y" };
+
+ res = ioport("MOUSE_B")->read() & 0xf0;
+ isporthi = ((m_mouse.control & 0x20) >> 5)*4;
+
+ if((m_mouse.control & 0x80) == 0)
+ res |= ioport(mousenames[(m_mouse.control & 0x40) >> 6])->read() >> (isporthi) & 0xf;
+ else
+ {
+ if(m_mouse.control & 0x40)
+ res |= (m_mouse.ly >> isporthi) & 0xf;
+ else
+ res |= (m_mouse.lx >> isporthi) & 0xf;
+ }
+
+// logerror("A\n");
+ return res;
+}
+
+WRITE8_MEMBER(pc9801_state::ppi_mouse_porta_w)
+{
+// logerror("A %02x\n",data);
+}
+
+WRITE8_MEMBER(pc9801_state::ppi_mouse_portb_w)
+{
+// logerror("B %02x\n",data);
+}
+
+WRITE8_MEMBER(pc9801_state::ppi_mouse_portc_w)
+{
+ if((m_mouse.control & 0x80) == 0 && data & 0x80)
+ {
+ m_mouse.lx = ioport("MOUSE_X")->read();
+ m_mouse.ly = ioport("MOUSE_Y")->read();
+ }
+
+ m_mouse.control = data;
+}
+
+/****************************************
+*
+* UPD765 interface
+*
+****************************************/
+
+static SLOT_INTERFACE_START( pc9801_floppies )
+ SLOT_INTERFACE( "525dd", FLOPPY_525_DD )
+ SLOT_INTERFACE( "525hd", FLOPPY_525_HD )
+ SLOT_INTERFACE( "35hd", FLOPPY_35_HD )
+SLOT_INTERFACE_END
+
+static SLOT_INTERFACE_START( pc9801_cbus )
+// PC-9801-14
+ SLOT_INTERFACE( "pc9801_26", PC9801_26 )
+ SLOT_INTERFACE( "pc9801_86", PC9801_86 )
+// PC-9801-86
+// PC-9801-26 + PC-9801-86 (?)
+// PC-9801-86 + Chibi-Oto
+ SLOT_INTERFACE( "pc9801_118", PC9801_118 )
+// Speak Board
+// Spark Board
+// AMD-98 (AmuseMent boarD)
+SLOT_INTERFACE_END
+
+// Jast Sound, could be put independently
+
+WRITE_LINE_MEMBER( pc9801_state::fdc_2dd_irq )
+{
+ logerror("IRQ 2DD %d\n",state);
+
+ if(m_fdc_2dd_ctrl & 8)
+ {
+ m_pic2->ir2_w(state);
+ }
+}
+
+WRITE_LINE_MEMBER( pc9801_state::pc9801rs_fdc_irq )
+{
+ /* 0xffaf8 */
+
+ //logerror("%02x %d\n",m_fdc_ctrl,state);
+
+ if(m_fdc_ctrl & 1)
+ m_pic2->ir3_w(state);
+ else
+ m_pic2->ir2_w(state);
+}
+
+WRITE_LINE_MEMBER( pc9801_state::pc9801rs_fdc_drq )
+{
+ if(m_fdc_ctrl & 1)
+ m_dmac->dreq2_w(state ^ 1);
+ else
+ m_dmac->dreq3_w(state ^ 1);
+}
+
+UINT32 pc9801_state::pc9801_286_a20(bool state)
+{
+ return (state ? 0xffffff : 0x0fffff);
+}
+
+/****************************************
+*
+* Init emulation status
+*
+****************************************/
+
+//
+PALETTE_INIT_MEMBER(pc9801_state,pc9801)
+{
+ int i;
+
+ for(i=0;i<8;i++)
+ palette.set_pen_color(i, pal1bit(i >> 1), pal1bit(i >> 2), pal1bit(i >> 0));
+ for(i=8;i<palette.entries();i++)
+ palette.set_pen_color(i, pal1bit(0), pal1bit(0), pal1bit(0));
+}
+
+MACHINE_START_MEMBER(pc9801_state,pc9801_common)
+{
+ m_rtc->cs_w(1);
+ m_rtc->oe_w(1);
+
+ m_ipl_rom = memregion("ipl")->base();
+ m_vbirq = timer_alloc(TIMER_VBIRQ);
+
+ save_item(NAME(m_sasi_data));
+ save_item(NAME(m_sasi_data_enable));
+ save_item(NAME(m_sasi_ctrl));
+}
+
+MACHINE_START_MEMBER(pc9801_state,pc9801f)
+{
+ MACHINE_START_CALL_MEMBER(pc9801_common);
+
+ m_fdc_2hd->set_rate(500000);
+ m_fdc_2dd->set_rate(250000);
+ m_sys_type = 0x00 >> 6;
+}
+
+MACHINE_START_MEMBER(pc9801_state,pc9801rs)
+{
+ MACHINE_START_CALL_MEMBER(pc9801_common);
+
+ int ram_size = m_ram->size() - 0xa0000;
+
+ address_space& space = m_maincpu->space(AS_PROGRAM);
+ membank("wram")->set_base(m_ram->pointer());
+ if(ram_size)
+ {
+ space.install_read_bank(0x100000, 0x100000 + ram_size - 1, "ext_wram");
+ space.install_write_bank(0x100000, 0x100000 + ram_size - 1, "ext_wram");
+ membank("ext_wram")->set_base(m_ram->pointer() + 0xa0000);
+ }
+
+ m_sys_type = 0x80 >> 6;
+}
+
+MACHINE_START_MEMBER(pc9801_state,pc9801bx2)
+{
+ MACHINE_START_CALL_MEMBER(pc9801rs);
+
+ save_pointer(NAME(m_sdip), 24);
+}
+
+
+MACHINE_START_MEMBER(pc9801_state,pc9821)
+{
+ MACHINE_START_CALL_MEMBER(pc9801rs);
+
+ save_pointer(NAME(m_sdip), 24);
+}
+
+MACHINE_START_MEMBER(pc9801_state,pc9821ap2)
+{
+ MACHINE_START_CALL_MEMBER(pc9821);
+
+ // ...
+}
+
+MACHINE_RESET_MEMBER(pc9801_state,pc9801_common)
+{
+ memset(m_tvram, 0, sizeof(UINT16) * 0x2000);
+ /* this looks like to be some kind of backup ram, system will boot with green colors otherwise */
+ {
+ int i;
+ static const UINT8 default_memsw_data[0x10] =
+ {
+ 0xe1, 0x48, 0xe1, 0x05, 0xe1, 0x04, 0xe1, 0x00, 0xe1, 0x01, 0xe1, 0x00, 0xe1, 0x00, 0xe1, 0x6e
+// 0xe1, 0xff, 0xe1, 0xff, 0xe1, 0xff, 0xe1, 0xff, 0xe1, 0xff, 0xe1, 0xff, 0xe1, 0xff, 0xe1, 0xff
+ };
+
+ for(i=0;i<0x10;i++)
+ m_tvram[(0x3fe0>>1)+i] = default_memsw_data[i];
+ }
+
+ m_beeper->set_frequency(2400);
+ m_beeper->set_state(0);
+
+ m_nmi_ff = 0;
+ m_mouse.control = 0xff;
+ m_mouse.freq_reg = 0;
+ m_mouse.freq_index = 0;
+ memset(&m_egc, 0, sizeof(m_egc));
+}
+
+MACHINE_RESET_MEMBER(pc9801_state,pc9801f)
+{
+ MACHINE_RESET_CALL_MEMBER(pc9801_common);
+
+ UINT8 op_mode;
+ UINT8 *ROM;
+ UINT8 *PRG = memregion("fdc_data")->base();
+ int i;
+
+ ROM = memregion("fdc_bios_2dd")->base();
+ op_mode = (ioport("ROM_LOAD")->read() & 2) >> 1;
+
+ for(i=0;i<0x1000;i++)
+ ROM[i] = PRG[i+op_mode*0x8000];
+
+ ROM = memregion("fdc_bios_2hd")->base();
+ op_mode = ioport("ROM_LOAD")->read() & 1;
+
+ for(i=0;i<0x1000;i++)
+ ROM[i] = PRG[i+op_mode*0x8000+0x10000];
+}
+
+MACHINE_RESET_MEMBER(pc9801_state,pc9801rs)
+{
+ MACHINE_RESET_CALL_MEMBER(pc9801_common);
+
+ m_gate_a20 = 0;
+ m_rom_bank = 0;
+ m_fdc_ctrl = 3;
+ m_access_ctrl = 0;
+ m_keyb_press = 0xff; // temp kludge, for PC-9821 booting
+// m_has_opna = ioport("SOUND_CONFIG")->read() & 1;
+ m_maincpu->set_input_line(INPUT_LINE_A20, m_gate_a20);
+
+ if(!(ioport("ROM_LOAD")->read() & 4))
+ m_maincpu->space(AS_PROGRAM).install_rom(0xd8000, 0xd9fff, memregion("ide")->base());
+ else
+ m_maincpu->space(AS_PROGRAM).install_rom(0xd8000, 0xd9fff, memregion("ide")->base() + 0x2000);
+}
+
+MACHINE_RESET_MEMBER(pc9801_state,pc9821)
+{
+ MACHINE_RESET_CALL_MEMBER(pc9801rs);
+
+ m_pc9821_window_bank = 0x08;
+}
+
+void pc9801_state::device_reset_after_children()
+{
+ driver_device::device_reset_after_children();
+ ata_mass_storage_device *ide0 = machine().device<ata_mass_storage_device>("ide:0:hdd");
+ if(ide0)
+ ide0->identify_device_buffer()[47] = 0;
+}
+
+INTERRUPT_GEN_MEMBER(pc9801_state::pc9801_vrtc_irq)
+{
+ m_pic1->ir2_w(1);
+ m_vbirq->adjust(m_screen->time_until_vblank_end());
+}
+
+
+FLOPPY_FORMATS_MEMBER( pc9801_state::floppy_formats )
+ FLOPPY_PC98_FORMAT,
+ FLOPPY_PC98FDI_FORMAT,
+ FLOPPY_FDD_FORMAT,
+ FLOPPY_DCP_FORMAT,
+ FLOPPY_DIP_FORMAT,
+ FLOPPY_NFD_FORMAT
+FLOPPY_FORMATS_END
+
+TIMER_DEVICE_CALLBACK_MEMBER( pc9801_state::mouse_irq_cb )
+{
+ if((m_mouse.control & 0x10) == 0)
+ {
+ m_mouse.freq_index ++;
+
+// logerror("%02x\n",m_mouse.freq_index);
+ if(m_mouse.freq_index > m_mouse.freq_reg)
+ {
+// logerror("irq %02x\n",m_mouse.freq_reg);
+ m_mouse.freq_index = 0;
+ m_pic2->ir5_w(0);
+ m_pic2->ir5_w(1);
+ }
+ }
+}
+
+static MACHINE_CONFIG_FRAGMENT( pc9801_keyboard )
+ MCFG_DEVICE_ADD("keyb", PC9801_KBD, 53)
+ MCFG_PC9801_KBD_IRQ_CALLBACK(DEVWRITELINE("pic8259_master", pic8259_device, ir1_w))
+MACHINE_CONFIG_END
+
+static MACHINE_CONFIG_FRAGMENT( pc9801_mouse )
+ MCFG_DEVICE_ADD("ppi8255_mouse", I8255, 0)
+ MCFG_I8255_IN_PORTA_CB(READ8(pc9801_state, ppi_mouse_porta_r))
+ MCFG_I8255_OUT_PORTA_CB(WRITE8(pc9801_state, ppi_mouse_porta_w))
+ MCFG_I8255_IN_PORTB_CB(IOPORT("DSW3"))
+ MCFG_I8255_OUT_PORTB_CB(WRITE8(pc9801_state, ppi_mouse_portb_w))
+ MCFG_I8255_IN_PORTC_CB(IOPORT("DSW4"))
+ MCFG_I8255_OUT_PORTC_CB(WRITE8(pc9801_state, ppi_mouse_portc_w))
+
+ MCFG_TIMER_DRIVER_ADD_PERIODIC("mouse_timer", pc9801_state, mouse_irq_cb, attotime::from_hz(120))
+MACHINE_CONFIG_END
+
+static MACHINE_CONFIG_FRAGMENT( pc9801_cbus )
+ MCFG_PC9801CBUS_SLOT_ADD("cbus0", pc9801_cbus, "pc9801_26")
+ MCFG_PC9801CBUS_SLOT_ADD("cbus1", pc9801_cbus, NULL)
+// TODO: six max slots
+MACHINE_CONFIG_END
+
+static MACHINE_CONFIG_FRAGMENT( pc9801_sasi )
+ MCFG_DEVICE_ADD(SASIBUS_TAG, SCSI_PORT, 0)
+ MCFG_SCSI_DATA_INPUT_BUFFER("sasi_data_in")
+ MCFG_SCSI_IO_HANDLER(WRITELINE(pc9801_state, write_sasi_io)) // bit2
+ MCFG_SCSI_CD_HANDLER(DEVWRITELINE("sasi_ctrl_in", input_buffer_device, write_bit3))
+ MCFG_SCSI_MSG_HANDLER(DEVWRITELINE("sasi_ctrl_in", input_buffer_device, write_bit4))
+ MCFG_SCSI_BSY_HANDLER(DEVWRITELINE("sasi_ctrl_in", input_buffer_device, write_bit5))
+ MCFG_SCSI_ACK_HANDLER(DEVWRITELINE("sasi_ctrl_in", input_buffer_device, write_bit6))
+ MCFG_SCSI_REQ_HANDLER(WRITELINE(pc9801_state, write_sasi_req))
+
+ MCFG_SCSIDEV_ADD(SASIBUS_TAG ":" SCSI_PORT_DEVICE1, "harddisk", PC9801_SASI, SCSI_ID_0)
+
+ MCFG_SCSI_OUTPUT_LATCH_ADD("sasi_data_out", SASIBUS_TAG)
+ MCFG_DEVICE_ADD("sasi_data_in", INPUT_BUFFER, 0)
+ MCFG_DEVICE_ADD("sasi_ctrl_in", INPUT_BUFFER, 0)
+
+ MCFG_DEVICE_MODIFY("i8237")
+ MCFG_I8237_IN_IOR_0_CB(READ8(pc9801_state, sasi_data_r))
+ MCFG_I8237_OUT_IOW_0_CB(WRITE8(pc9801_state, sasi_data_w))
+MACHINE_CONFIG_END
+
+
+static MACHINE_CONFIG_FRAGMENT( pc9801_ide )
+ MCFG_ATA_INTERFACE_ADD("ide", ata_devices, "hdd", NULL, false)
+ MCFG_ATA_INTERFACE_IRQ_HANDLER(DEVWRITELINE("pic8259_slave", pic8259_device, ir1_w))
+MACHINE_CONFIG_END
+
+static MACHINE_CONFIG_FRAGMENT( pc9801_common )
+ MCFG_DEVICE_ADD("pit8253", PIT8253, 0)
+ MCFG_PIT8253_CLK0(MAIN_CLOCK_X1) /* heartbeat IRQ */
+ MCFG_PIT8253_OUT0_HANDLER(DEVWRITELINE("pic8259_master", pic8259_device, ir0_w))
+ MCFG_PIT8253_CLK1(MAIN_CLOCK_X1) /* Memory Refresh */
+ MCFG_PIT8253_CLK2(MAIN_CLOCK_X1) /* RS-232c */
+ MCFG_PIT8253_OUT2_HANDLER(WRITELINE(pc9801_state, write_uart_clock))
+
+ MCFG_DEVICE_ADD("i8237", AM9517A, 5000000) // unknown clock, TODO: check channels 0 - 1
+ MCFG_I8237_OUT_HREQ_CB(WRITELINE(pc9801_state, dma_hrq_changed))
+ MCFG_I8237_OUT_EOP_CB(WRITELINE(pc9801_state, tc_w))
+ MCFG_I8237_IN_MEMR_CB(READ8(pc9801_state, dma_read_byte))
+ MCFG_I8237_OUT_MEMW_CB(WRITE8(pc9801_state, dma_write_byte))
+ MCFG_I8237_IN_IOR_2_CB(DEVREAD8("upd765_2hd", upd765a_device, mdma_r))
+ MCFG_I8237_OUT_IOW_2_CB(DEVWRITE8("upd765_2hd", upd765a_device, mdma_w))
+ MCFG_I8237_OUT_DACK_0_CB(WRITELINE(pc9801_state, dack0_w))
+ MCFG_I8237_OUT_DACK_1_CB(WRITELINE(pc9801_state, dack1_w))
+ MCFG_I8237_OUT_DACK_2_CB(WRITELINE(pc9801_state, dack2_w))
+ MCFG_I8237_OUT_DACK_3_CB(WRITELINE(pc9801_state, dack3_w))
+ MCFG_PIC8259_ADD( "pic8259_master", INPUTLINE("maincpu", 0), VCC, READ8(pc9801_state,get_slave_ack) )
+ MCFG_PIC8259_ADD( "pic8259_slave", DEVWRITELINE("pic8259_master", pic8259_device, ir7_w), GND, NULL ) // TODO: Check ir7_w
+
+ MCFG_DEVICE_ADD("ppi8255_sys", I8255, 0)
+ MCFG_I8255_IN_PORTA_CB(IOPORT("DSW2"))
+ MCFG_I8255_IN_PORTB_CB(IOPORT("DSW1"))
+ MCFG_I8255_IN_PORTC_CB(CONSTANT(0xa0)) // 0x80 cpu triple fault reset flag?
+ MCFG_I8255_OUT_PORTC_CB(WRITE8(pc9801_state, ppi_sys_portc_w))
+
+ MCFG_DEVICE_ADD("ppi8255_prn", I8255, 0)
+ /* TODO: check this one */
+ MCFG_I8255_IN_PORTB_CB(IOPORT("DSW5"))
+
+ MCFG_FRAGMENT_ADD(pc9801_keyboard)
+ MCFG_FRAGMENT_ADD(pc9801_mouse)
+ MCFG_FRAGMENT_ADD(pc9801_cbus)
+
+ MCFG_DEVICE_ADD(UPD8251_TAG, I8251, 0)
+
+ MCFG_UPD765A_ADD("upd765_2hd", true, true)
+ MCFG_UPD765_INTRQ_CALLBACK(DEVWRITELINE("pic8259_slave", pic8259_device, ir3_w))
+ MCFG_UPD765_DRQ_CALLBACK(DEVWRITELINE("i8237", am9517a_device, dreq2_w)) MCFG_DEVCB_INVERT
+ MCFG_FLOPPY_DRIVE_ADD("upd765_2hd:0", pc9801_floppies, "525hd", pc9801_state::floppy_formats)
+ MCFG_FLOPPY_DRIVE_ADD("upd765_2hd:1", pc9801_floppies, "525hd", pc9801_state::floppy_formats)
+
+ MCFG_DEVICE_ADD("ppi8255_fdd", I8255, 0)
+ MCFG_I8255_IN_PORTA_CB(CONSTANT(0xff))
+ MCFG_I8255_IN_PORTB_CB(CONSTANT(0xff)) //upd765_status_r(machine().device("upd765_2dd"),space, 0);
+ MCFG_I8255_IN_PORTC_CB(CONSTANT(0xff)) //upd765_data_r(machine().device("upd765_2dd"),space, 0);
+ //MCFG_I8255_OUT_PORTC_CB(WRITE8(pc9801_state, ppi_fdd_portc_w)) //upd765_data_w(machine().device("upd765_2dd"),space, 0,data);
+
+ MCFG_SOFTWARE_LIST_ADD("disk_list","pc98")
+
+ /* video hardware */
+ MCFG_SCREEN_ADD("screen", RASTER)
+ MCFG_SCREEN_REFRESH_RATE(60)
+ MCFG_SCREEN_UPDATE_DRIVER(pc9801_state, screen_update)
+ MCFG_SCREEN_SIZE(640, 480)
+ MCFG_SCREEN_VISIBLE_AREA(0, 640-1, 0, 200-1)
+
+ MCFG_DEVICE_ADD("upd7220_chr", UPD7220, 5000000/2)
+ MCFG_DEVICE_ADDRESS_MAP(AS_0, upd7220_1_map)
+ MCFG_UPD7220_DRAW_TEXT_CALLBACK_OWNER(pc9801_state, hgdc_draw_text)
+ MCFG_UPD7220_VSYNC_CALLBACK(DEVWRITELINE("upd7220_btm", upd7220_device, ext_sync_w))
+
+ MCFG_DEVICE_ADD("upd7220_btm", UPD7220, 5000000/2)
+ MCFG_DEVICE_ADDRESS_MAP(AS_0, upd7220_2_map)
+ MCFG_UPD7220_DISPLAY_PIXELS_CALLBACK_OWNER(pc9801_state, hgdc_display_pixels)
+
+ MCFG_SPEAKER_STANDARD_MONO("mono")
+
+ MCFG_SOUND_ADD("beeper", BEEP, 0)
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS,"mono",0.15)
+ MCFG_GFXDECODE_ADD("gfxdecode", "palette", pc9801)
+MACHINE_CONFIG_END
+
+static MACHINE_CONFIG_START( pc9801, pc9801_state )
+ MCFG_CPU_ADD("maincpu", I8086, 5000000) //unknown clock
+ MCFG_CPU_PROGRAM_MAP(pc9801_map)
+ MCFG_CPU_IO_MAP(pc9801_io)
+ MCFG_CPU_VBLANK_INT_DRIVER("screen", pc9801_state, pc9801_vrtc_irq)
+ MCFG_CPU_IRQ_ACKNOWLEDGE_DEVICE("pic8259_master", pic8259_device, inta_cb)
+
+ MCFG_FRAGMENT_ADD(pc9801_common)
+
+ MCFG_MACHINE_START_OVERRIDE(pc9801_state,pc9801f)
+ MCFG_MACHINE_RESET_OVERRIDE(pc9801_state,pc9801f)
+#if 0
+ MCFG_RAM_ADD(RAM_TAG)
+ MCFG_RAM_DEFAULT_SIZE("128K")
+ MCFG_RAM_EXTRA_OPTIONS("256K,384K,512K,640K")
+#endif
+
+ MCFG_UPD765A_ADD("upd765_2dd", false, true)
+ MCFG_UPD765_INTRQ_CALLBACK(WRITELINE(pc9801_state, fdc_2dd_irq))
+ MCFG_UPD765_DRQ_CALLBACK(DEVWRITELINE("i8237", am9517a_device, dreq3_w)) MCFG_DEVCB_INVERT
+ MCFG_FLOPPY_DRIVE_ADD("upd765_2dd:0", pc9801_floppies, "525dd", pc9801_state::floppy_formats)
+ MCFG_FLOPPY_DRIVE_ADD("upd765_2dd:1", pc9801_floppies, "525dd", pc9801_state::floppy_formats)
+
+ MCFG_FRAGMENT_ADD(pc9801_sasi)
+ MCFG_UPD1990A_ADD(UPD1990A_TAG, XTAL_32_768kHz, NULL, NULL)
+
+ MCFG_DEVICE_MODIFY("i8237")
+ MCFG_I8237_IN_IOR_3_CB(DEVREAD8("upd765_2dd", upd765a_device, mdma_r))
+ MCFG_I8237_OUT_IOW_3_CB(DEVWRITE8("upd765_2dd", upd765a_device, mdma_w))
+
+ MCFG_PALETTE_ADD("palette", 16)
+ MCFG_PALETTE_INIT_OWNER(pc9801_state,pc9801)
+MACHINE_CONFIG_END
+
+static MACHINE_CONFIG_DERIVED( pc9801vm, pc9801 )
+ MCFG_CPU_REPLACE("maincpu",V30,10000000)
+ MCFG_CPU_PROGRAM_MAP(pc9801ux_map)
+ MCFG_CPU_IO_MAP(pc9801ux_io)
+ MCFG_CPU_VBLANK_INT_DRIVER("screen", pc9801_state, pc9801_vrtc_irq)
+
+ MCFG_MACHINE_START_OVERRIDE(pc9801_state,pc9801_common)
+ MCFG_MACHINE_RESET_OVERRIDE(pc9801_state,pc9801_common)
+MACHINE_CONFIG_END
+
+static MACHINE_CONFIG_START( pc9801rs, pc9801_state )
+ MCFG_CPU_ADD("maincpu", I386SX, MAIN_CLOCK_X1*8) // unknown clock.
+ MCFG_CPU_PROGRAM_MAP(pc9801rs_map)
+ MCFG_CPU_IO_MAP(pc9801rs_io)
+ MCFG_CPU_VBLANK_INT_DRIVER("screen", pc9801_state, pc9801_vrtc_irq)
+ MCFG_CPU_IRQ_ACKNOWLEDGE_DEVICE("pic8259_master", pic8259_device, inta_cb)
+
+ MCFG_FRAGMENT_ADD(pc9801_common)
+
+ MCFG_MACHINE_START_OVERRIDE(pc9801_state,pc9801rs)
+ MCFG_MACHINE_RESET_OVERRIDE(pc9801_state,pc9801rs)
+
+ MCFG_DEVICE_MODIFY("i8237")
+ MCFG_DEVICE_CLOCK(MAIN_CLOCK_X1*8); // unknown clock
+
+ MCFG_FRAGMENT_ADD(pc9801_ide)
+ MCFG_UPD4990A_ADD("upd1990a", XTAL_32_768kHz, NULL, NULL)
+
+ MCFG_RAM_ADD(RAM_TAG)
+ MCFG_RAM_DEFAULT_SIZE("1664K")
+ MCFG_RAM_EXTRA_OPTIONS("640K,3712K,7808K")
+
+ MCFG_DEVICE_MODIFY("upd7220_btm")
+ MCFG_DEVICE_ADDRESS_MAP(AS_0, upd7220_grcg_2_map)
+
+ MCFG_PALETTE_ADD("palette", 16+16)
+ MCFG_PALETTE_INIT_OWNER(pc9801_state,pc9801)
+MACHINE_CONFIG_END
+
+static MACHINE_CONFIG_DERIVED( pc9801ux, pc9801rs )
+ MCFG_CPU_REPLACE("maincpu",I80286,10000000)
+ MCFG_CPU_PROGRAM_MAP(pc9801ux_map)
+ MCFG_CPU_IO_MAP(pc9801ux_io)
+ MCFG_80286_A20(pc9801_state, pc9801_286_a20)
+ MCFG_CPU_VBLANK_INT_DRIVER("screen", pc9801_state, pc9801_vrtc_irq)
+ MCFG_CPU_IRQ_ACKNOWLEDGE_DEVICE("pic8259_master", pic8259_device, inta_cb)
+// MCFG_DEVICE_MODIFY("i8237", AM9157A, 10000000) // unknown clock
+MACHINE_CONFIG_END
+
+static MACHINE_CONFIG_DERIVED( pc9801bx2, pc9801rs )
+ MCFG_CPU_REPLACE("maincpu",I486,25000000)
+ MCFG_CPU_PROGRAM_MAP(pc9821_map)
+ MCFG_CPU_IO_MAP(pc9821_io)
+ MCFG_CPU_VBLANK_INT_DRIVER("screen", pc9801_state, pc9801_vrtc_irq)
+ MCFG_CPU_IRQ_ACKNOWLEDGE_DEVICE("pic8259_master", pic8259_device, inta_cb)
+
+ MCFG_MACHINE_START_OVERRIDE(pc9801_state,pc9801bx2)
+MACHINE_CONFIG_END
+
+static MACHINE_CONFIG_DERIVED( pc9821, pc9801rs )
+ MCFG_CPU_REPLACE("maincpu", I486, 16000000) // unknown clock
+ MCFG_CPU_PROGRAM_MAP(pc9821_map)
+ MCFG_CPU_IO_MAP(pc9821_io)
+ MCFG_CPU_VBLANK_INT_DRIVER("screen", pc9801_state, pc9801_vrtc_irq)
+ MCFG_CPU_IRQ_ACKNOWLEDGE_DEVICE("pic8259_master", pic8259_device, inta_cb)
+
+ MCFG_DEVICE_MODIFY("pit8253")
+ MCFG_PIT8253_CLK0(MAIN_CLOCK_X2)
+ MCFG_PIT8253_CLK1(MAIN_CLOCK_X2)
+ MCFG_PIT8253_CLK2(MAIN_CLOCK_X2)
+
+ MCFG_MACHINE_START_OVERRIDE(pc9801_state,pc9821)
+ MCFG_MACHINE_RESET_OVERRIDE(pc9801_state,pc9821)
+
+ MCFG_DEVICE_MODIFY("i8237")
+ MCFG_DEVICE_CLOCK(16000000); // unknown clock
+
+ MCFG_DEVICE_REMOVE("palette")
+ MCFG_PALETTE_ADD("palette", 16+16+256)
+ MCFG_PALETTE_INIT_OWNER(pc9801_state,pc9801)
+MACHINE_CONFIG_END
+
+static MACHINE_CONFIG_DERIVED( pc9821ap2, pc9821)
+ MCFG_CPU_REPLACE("maincpu", I486, 66666667) // unknown clock
+ MCFG_CPU_PROGRAM_MAP(pc9821_map)
+ MCFG_CPU_IO_MAP(pc9821_io)
+ MCFG_CPU_VBLANK_INT_DRIVER("screen", pc9801_state, pc9801_vrtc_irq)
+ MCFG_CPU_IRQ_ACKNOWLEDGE_DEVICE("pic8259_master", pic8259_device, inta_cb)
+
+ MCFG_MACHINE_START_OVERRIDE(pc9801_state,pc9821ap2)
+MACHINE_CONFIG_END
+
+static MACHINE_CONFIG_DERIVED( pc9821v20, pc9821 )
+ MCFG_CPU_REPLACE("maincpu",PENTIUM,32000000) /* TODO: clock */
+ MCFG_CPU_PROGRAM_MAP(pc9821_map)
+ MCFG_CPU_IO_MAP(pc9821_io)
+ MCFG_CPU_VBLANK_INT_DRIVER("screen", pc9801_state, pc9801_vrtc_irq)
+ MCFG_CPU_IRQ_ACKNOWLEDGE_DEVICE("pic8259_master", pic8259_device, inta_cb)
+MACHINE_CONFIG_END
+
+/* took from "raw" memory dump, uncomment ROM_FILL if you want to play with it */
+#define LOAD_IDE_ROM \
+ ROM_REGION( 0x4000, "ide", ROMREGION_ERASEVAL(0xcb) ) \
+ ROM_LOAD( "d8000.rom", 0x0000, 0x2000, BAD_DUMP CRC(5dda57cc) SHA1(d0dead41c5b763008a4d777aedddce651eb6dcbb) ) \
+ ROM_IGNORE( 0x2000 ) \
+ ROM_IGNORE( 0x2000 ) \
+ ROM_IGNORE( 0x2000 )
+
+// all of these are half size :/
+#define LOAD_KANJI_ROMS \
+ ROM_REGION( 0x80000, "raw_kanji", ROMREGION_ERASEFF ) \
+ ROM_LOAD16_BYTE( "24256c-x01.bin", 0x00000, 0x4000, BAD_DUMP CRC(28ec1375) SHA1(9d8e98e703ce0f483df17c79f7e841c5c5cd1692) ) \
+ ROM_CONTINUE( 0x20000, 0x4000 ) \
+ ROM_LOAD16_BYTE( "24256c-x02.bin", 0x00001, 0x4000, BAD_DUMP CRC(90985158) SHA1(78fb106131a3f4eb054e87e00fe4f41193416d65) ) \
+ ROM_CONTINUE( 0x20001, 0x4000 ) \
+ ROM_LOAD16_BYTE( "24256c-x03.bin", 0x40000, 0x4000, BAD_DUMP CRC(d4893543) SHA1(eb8c1bee0f694e1e0c145a24152222d4e444e86f) ) \
+ ROM_CONTINUE( 0x60000, 0x4000 ) \
+ ROM_LOAD16_BYTE( "24256c-x04.bin", 0x40001, 0x4000, BAD_DUMP CRC(5dec0fc2) SHA1(41000da14d0805ed0801b31eb60623552e50e41c) ) \
+ ROM_CONTINUE( 0x60001, 0x4000 ) \
+ ROM_REGION( 0x100000, "kanji", ROMREGION_ERASEFF ) \
+ ROM_REGION( 0x80000, "new_chargen", ROMREGION_ERASEFF )
+/*
+F - 8086 5
+*/
+
+ROM_START( pc9801f )
+ ROM_REGION( 0x18000, "ipl", ROMREGION_ERASEFF )
+ ROM_LOAD16_BYTE( "urm01-02.bin", 0x00000, 0x4000, CRC(cde04615) SHA1(8f6fb587c0522af7a8131b45d13f8ae8fc60e8cd) )
+ ROM_LOAD16_BYTE( "urm02-02.bin", 0x00001, 0x4000, CRC(9e39b8d1) SHA1(df1f3467050a41537cb9d071e4034f0506f07eda) )
+ ROM_LOAD16_BYTE( "urm03-02.bin", 0x08000, 0x4000, CRC(95e79064) SHA1(c27d96949fad82aeb26e316200c15a4891e1063f) )
+ ROM_LOAD16_BYTE( "urm04-02.bin", 0x08001, 0x4000, CRC(e4855a53) SHA1(223f66482c77409706cfc64c214cec7237c364e9) )
+ ROM_LOAD16_BYTE( "urm05-02.bin", 0x10000, 0x4000, CRC(ffefec65) SHA1(106e0d920e857e59da12225a489ca2756ca405c1) )
+ ROM_LOAD16_BYTE( "urm06-02.bin", 0x10001, 0x4000, CRC(1147760b) SHA1(4e0299091dfd53ac7988d40c5a6775a10389faac) )
+
+ ROM_REGION( 0x4000, "sound_bios", ROMREGION_ERASEFF ) /* FM board*/
+ ROM_LOAD( "sound.rom", 0x0000, 0x4000, CRC(80eabfde) SHA1(e09c54152c8093e1724842c711aed6417169db23) )
+
+ ROM_REGION( 0x1000, "fdc_bios_2dd", ROMREGION_ERASEFF )
+
+ ROM_REGION( 0x1000, "fdc_bios_2hd", ROMREGION_ERASEFF )
+
+ ROM_REGION( 0x20000, "fdc_data", ROMREGION_ERASEFF ) // 2dd fdc bios, presumably bad size (should be 0x800 for each rom)
+ ROM_LOAD16_BYTE( "urf01-01.bin", 0x00000, 0x4000, BAD_DUMP CRC(2f5ae147) SHA1(69eb264d520a8fc826310b4fce3c8323867520ee) )
+ ROM_LOAD16_BYTE( "urf02-01.bin", 0x00001, 0x4000, BAD_DUMP CRC(62a86928) SHA1(4160a6db096dbeff18e50cbee98f5d5c1a29e2d1) )
+ ROM_LOAD( "2hdif.rom", 0x10000, 0x1000, BAD_DUMP CRC(9652011b) SHA1(b607707d74b5a7d3ba211825de31a8f32aec8146) ) // needs dumping from a board
+
+ ROM_REGION( 0x800, "kbd_mcu", ROMREGION_ERASEFF)
+ ROM_LOAD( "mcu.bin", 0x0000, 0x0800, NO_DUMP ) //connected through a i8251 UART, needs decapping
+
+ /* note: ROM names of following two might be swapped */
+ ROM_REGION( 0x80000, "chargen", 0 )
+ ROM_LOAD( "d23128c-17.bin", 0x00000, 0x00800, BAD_DUMP CRC(eea57180) SHA1(4aa037c684b72ad4521212928137d3369174eb1e) ) //original is a bad dump, this is taken from i386 model
+ ROM_LOAD("hn613128pac8.bin",0x00800, 0x01000, BAD_DUMP CRC(b5a15b5c) SHA1(e5f071edb72a5e9a8b8b1c23cf94a74d24cb648e) ) //bad dump, 8x16 charset? (it's on the kanji board)
+
+ LOAD_KANJI_ROMS
+ROM_END
+
+/*
+UX - 80286 10 + V30 8
+*/
+
+ROM_START( pc9801ux )
+ ROM_REGION( 0x60000, "ipl", ROMREGION_ERASEFF )
+ ROM_LOAD( "itf_ux.rom", 0x18000, 0x08000, CRC(c7942563) SHA1(61bb210d64c7264be939b11df1e9cd14ffeee3c9) )
+ ROM_LOAD( "bios_ux.rom", 0x28000, 0x18000, BAD_DUMP CRC(97375ca2) SHA1(bfe458f671d90692104d0640730972ca8dc0a100) )
+
+ ROM_REGION( 0x10000, "sound_bios", 0 )
+ ROM_LOAD( "sound_ux.rom", 0x0000, 0x4000, CRC(80eabfde) SHA1(e09c54152c8093e1724842c711aed6417169db23) )
+
+ ROM_REGION( 0x80000, "chargen", 0 )
+ ROM_LOAD( "font_ux.rom", 0x000000, 0x046800, BAD_DUMP CRC(19a76eeb) SHA1(96a006e8515157a624599c2b53a581ae0dd560fd) )
+
+ LOAD_KANJI_ROMS
+// LOAD_IDE_ROM
+ROM_END
+
+/*
+RX - 80286 12 (no V30?)
+
+The bios is from a 386 model not an RX
+*/
+
+ROM_START( pc9801rx )
+ ROM_REGION( 0x60000, "ipl", ROMREGION_ERASEFF )
+ ROM_LOAD( "itf_rs.rom", 0x18000, 0x08000, BAD_DUMP CRC(c1815325) SHA1(a2fb11c000ed7c976520622cfb7940ed6ddc904e) )
+ ROM_LOAD( "bios_rx.rom", 0x28000, 0x018000, BAD_DUMP CRC(0a682b93) SHA1(76a7360502fa0296ea93b4c537174610a834d367) )
+ // fix csum
+ ROM_FILL(0x3fffe, 1, 0x0d)
+
+ ROM_REGION( 0x10000, "sound_bios", 0 )
+ ROM_LOAD( "sound_rx.rom", 0x000000, 0x004000, CRC(fe9f57f2) SHA1(d5dbc4fea3b8367024d363f5351baecd6adcd8ef) )
+
+ ROM_REGION( 0x80000, "chargen", 0 )
+ ROM_LOAD( "font_rx.rom", 0x000000, 0x046800, CRC(456d9fc7) SHA1(78ba9960f135372825ab7244b5e4e73a810002ff) )
+
+ LOAD_KANJI_ROMS
+ LOAD_IDE_ROM
+ROM_END
+
+/*
+RS - 386SX 16
+
+(note: might be a different model!)
+*/
+
+ROM_START( pc9801rs )
+ ROM_REGION( 0x60000, "ipl", ROMREGION_ERASEFF )
+ ROM_LOAD( "itf_rs.rom", 0x18000, 0x08000, CRC(c1815325) SHA1(a2fb11c000ed7c976520622cfb7940ed6ddc904e) )
+ ROM_LOAD( "bios_rs.rom", 0x28000, 0x18000, BAD_DUMP CRC(315d2703) SHA1(4f208d1dbb68373080d23bff5636bb6b71eb7565) )
+
+ /* following is an emulator memory dump, should be checked and nuked */
+ ROM_REGION( 0x100000, "memory", 0 )
+ ROM_LOAD( "00000.rom", 0x00000, 0x8000, CRC(6e299128) SHA1(d0e7d016c005cdce53ea5ecac01c6f883b752b80) )
+ ROM_LOAD( "c0000.rom", 0xc0000, 0x8000, CRC(1b43eabd) SHA1(ca711c69165e1fa5be72993b9a7870ef6d485249) ) // 0xff everywhere
+ ROM_LOAD( "c8000.rom", 0xc8000, 0x8000, CRC(f2a262b0) SHA1(fe97d2068d18bbb7425d9774e2e56982df2aa1fb) )
+ ROM_LOAD( "d0000.rom", 0xd0000, 0x8000, CRC(1b43eabd) SHA1(ca711c69165e1fa5be72993b9a7870ef6d485249) ) // 0xff everywhere
+ ROM_LOAD( "e8000.rom", 0xe8000, 0x8000, CRC(4e32081e) SHA1(e23571273b7cad01aa116cb7414c5115a1093f85) ) // contains n-88 basic (86) v2.0
+ ROM_LOAD( "f0000.rom", 0xf0000, 0x8000, CRC(4da85a6c) SHA1(18dccfaf6329387c0c64cc4c91b32c25cde8bd5a) )
+ ROM_LOAD( "f8000.rom", 0xf8000, 0x8000, CRC(2b1e45b1) SHA1(1fec35f17d96b2e2359e3c71670575ad9ff5007e) )
+
+ ROM_REGION( 0x10000, "sound_bios", 0 )
+ ROM_LOAD( "sound.rom", 0x0000, 0x4000, CRC(80eabfde) SHA1(e09c54152c8093e1724842c711aed6417169db23) )
+
+ ROM_REGION( 0x80000, "chargen", 0 )
+ ROM_LOAD( "font_rs.rom", 0x00000, 0x46800, BAD_DUMP CRC(da370e7a) SHA1(584d0c7fde8c7eac1f76dc5e242102261a878c5e) )
+
+ LOAD_KANJI_ROMS
+ LOAD_IDE_ROM
+ROM_END
+
+/*
+BX2/U2 - 486SX - (should be 33, but "dumper" note says it's 25 MHz)
+
+Yet another franken-dump done with a lame program, shrug
+
+*/
+
+ROM_START( pc9801bx2 )
+ ROM_REGION( 0x60000, "ipl", ROMREGION_ERASEFF )
+ ROM_LOAD( "pc98bank0.bin", 0x00000, 0x08000, BAD_DUMP CRC(bfd100cc) SHA1(cf8e6a5679cca7761481abef0ba4b35ead39efdb) )
+ ROM_LOAD( "pc98bank1.bin", 0x00000, 0x08000, BAD_DUMP CRC(d0562af8) SHA1(2c4fd27eb598f4b8a00f3e86941ba27007d58e47) )
+ ROM_LOAD( "pc98bank2.bin", 0x00000, 0x08000, BAD_DUMP CRC(12818a14) SHA1(9c31e8ac85d78fa779d6bbc2095557065294ec09) )
+ ROM_LOAD( "pc98bank3.bin", 0x00000, 0x08000, BAD_DUMP CRC(d0bda44e) SHA1(c1022a3b2be4d2a1e43914df9e4605254e5f99d5) )
+ ROM_LOAD( "pc98bank4.bin", 0x18000, 0x08000, BAD_DUMP CRC(be8092f4) SHA1(12c8a166b8c6ebbef85568b67e1f098562883365) )
+ ROM_LOAD( "pc98bank5.bin", 0x00000, 0x08000, BAD_DUMP CRC(4e32081e) SHA1(e23571273b7cad01aa116cb7414c5115a1093f85) )
+ ROM_LOAD( "pc98bank6.bin", 0x00000, 0x08000, BAD_DUMP CRC(f878c160) SHA1(cad47f09075ffe4f7b51bb937c9f716c709d4596) )
+ ROM_LOAD( "pc98bank7.bin", 0x00000, 0x08000, BAD_DUMP CRC(1bd6537b) SHA1(ff9ee1c976a12b87851635ce8991ac4ad607675b) )
+
+ ROM_REGION( 0x10000, "sound_bios", 0 )
+ ROM_LOAD( "sound.rom", 0x0000, 0x4000, CRC(80eabfde) SHA1(e09c54152c8093e1724842c711aed6417169db23) )
+
+ ROM_REGION( 0x80000, "chargen", 0 )
+ ROM_LOAD( "font_rs.rom", 0x00000, 0x46800, BAD_DUMP CRC(da370e7a) SHA1(584d0c7fde8c7eac1f76dc5e242102261a878c5e) )
+
+ LOAD_KANJI_ROMS
+ LOAD_IDE_ROM
+ROM_END
+
+/*
+VM - V30 8/10
+
+TODO: this ISN'T a real VM model!
+*/
+
+ROM_START( pc9801vm )
+ ROM_REGION( 0x60000, "ipl", ROMREGION_ERASEFF )
+ ROM_LOAD( "itf_ux.rom", 0x18000, 0x08000, BAD_DUMP CRC(c7942563) SHA1(61bb210d64c7264be939b11df1e9cd14ffeee3c9) )
+ ROM_LOAD( "bios_vm.rom", 0x28000, 0x018000, CRC(2e2d7cee) SHA1(159549f845dc70bf61955f9469d2281a0131b47f) )
+
+ ROM_REGION( 0x10000, "sound_bios", 0 )
+ ROM_LOAD( "sound_vm.rom", 0x000000, 0x004000, CRC(fe9f57f2) SHA1(d5dbc4fea3b8367024d363f5351baecd6adcd8ef) )
+
+ ROM_REGION( 0x80000, "chargen", 0 )
+ ROM_LOAD( "font_vm.rom", 0x000000, 0x046800, BAD_DUMP CRC(456d9fc7) SHA1(78ba9960f135372825ab7244b5e4e73a810002ff) )
+
+ LOAD_KANJI_ROMS
+// LOAD_IDE_ROM
+ROM_END
+
+/*
+98MATE A - 80486SX 25
+
+(note: might be a different model!)
+*/
+
+ROM_START( pc9821 )
+ ROM_REGION( 0x60000, "ipl", ROMREGION_ERASEFF )
+ ROM_LOAD( "itf.rom", 0x18000, 0x08000, CRC(dd4c7bb8) SHA1(cf3aa193df2722899066246bccbed03f2e79a74a) )
+ ROM_LOAD( "bios.rom", 0x28000, 0x18000, BAD_DUMP CRC(34a19a59) SHA1(2e92346727b0355bc1ec9a7ded1b444a4917f2b9) )
+
+ ROM_REGION( 0x10000, "sound_bios", 0 )
+ ROM_LOAD( "sound.rom", 0x0000, 0x4000, CRC(a21ef796) SHA1(34137c287c39c44300b04ee97c1e6459bb826b60) )
+
+ ROM_REGION( 0x80000, "chargen", 0 )
+ ROM_LOAD( "font.rom", 0x00000, 0x46800, BAD_DUMP CRC(a61c0649) SHA1(554b87377d176830d21bd03964dc71f8e98676b1) )
+
+ LOAD_KANJI_ROMS
+ LOAD_IDE_ROM
+ROM_END
+
+/*
+As - 80486DX 33
+*/
+
+ROM_START( pc9821as )
+ ROM_REGION( 0x60000, "ipl", ROMREGION_ERASEFF )
+ ROM_LOAD( "itf.rom", 0x18000, 0x08000, BAD_DUMP CRC(dd4c7bb8) SHA1(cf3aa193df2722899066246bccbed03f2e79a74a) )
+ ROM_LOAD( "bios_as.rom", 0x28000, 0x018000, BAD_DUMP CRC(0a682b93) SHA1(76a7360502fa0296ea93b4c537174610a834d367) )
+
+ ROM_REGION( 0x10000, "sound_bios", 0 )
+ ROM_LOAD( "sound_as.rom", 0x000000, 0x004000, CRC(fe9f57f2) SHA1(d5dbc4fea3b8367024d363f5351baecd6adcd8ef) )
+
+ ROM_REGION( 0x80000, "chargen", 0 )
+ ROM_LOAD( "font_as.rom", 0x000000, 0x046800, BAD_DUMP CRC(456d9fc7) SHA1(78ba9960f135372825ab7244b5e4e73a810002ff) )
+
+ LOAD_KANJI_ROMS
+ LOAD_IDE_ROM
+ROM_END
+
+/*
+PC-9821AP2/U8W
+80486DX2 66MHz
+DOS 5.0, Windows 3.1
+5.6MB RAM, up to 73.6MB
+340MB HD
+Expansion slot C-BUS4 (4)
+Graphics controller S3 86C928
+*/
+
+ROM_START( pc9821ap2 )
+ ROM_REGION( 0x80000, "biosrom", ROMREGION_ERASEFF )
+ ROM_DEFAULT_BIOS("phd0104")
+ ROM_SYSTEM_BIOS(0, "phd0104", "PHD0104")
+ ROMX_LOAD( "phd0104.rom", 0x000000, 0x80000, CRC(da73b372) SHA1(2c15b63a0869b81ef7f04972dbb0975f4e77d384), ROM_BIOS(1) )
+ ROM_SYSTEM_BIOS(1, "phd0102", "PHD0102")
+ ROMX_LOAD( "phd0102.rom", 0x000000, 0x80000, CRC(3036774c) SHA1(59856a348f156adf5eca06326f967aca54ff871c), ROM_BIOS(2) )
+
+ ROM_REGION( 0x60000, "ipl", ROMREGION_ERASEFF ) // TODO: identify ROM banks
+ ROM_COPY( "biosrom", 0x20000, 0x18000, 0x08000 )
+ ROM_COPY( "biosrom", 0x30000, 0x28000, 0x18000 )
+
+ ROM_REGION( 0x10000, "sound_bios", 0 )
+ ROM_LOAD( "sound.rom", 0x0000, 0x4000, CRC(a21ef796) SHA1(34137c287c39c44300b04ee97c1e6459bb826b60) )
+
+ ROM_REGION( 0x80000, "chargen", 0 )
+ ROM_LOAD( "font.rom", 0x00000, 0x46800, BAD_DUMP CRC(a61c0649) SHA1(554b87377d176830d21bd03964dc71f8e98676b1) )
+
+ LOAD_KANJI_ROMS
+ LOAD_IDE_ROM
+ROM_END
+
+
+/*
+98NOTE - i486SX 33
+*/
+
+ROM_START( pc9821ne )
+ ROM_REGION( 0x60000, "ipl", ROMREGION_ERASEFF )
+ ROM_LOAD( "itf.rom", 0x18000, 0x08000, CRC(dd4c7bb8) SHA1(cf3aa193df2722899066246bccbed03f2e79a74a) )
+ ROM_LOAD( "bios_ne.rom", 0x28000, 0x18000, BAD_DUMP CRC(2ae070c4) SHA1(d7963942042bfd84ed5fc9b7ba8f1c327c094172) )
+
+ ROM_REGION( 0x10000, "sound_bios", 0 )
+ ROM_LOAD( "sound_ne.rom", 0x0000, 0x4000, CRC(a21ef796) SHA1(34137c287c39c44300b04ee97c1e6459bb826b60) )
+
+ ROM_REGION( 0x80000, "chargen", 0 )
+ ROM_LOAD( "font_ne.rom", 0x00000, 0x46800, BAD_DUMP CRC(fb213757) SHA1(61525826d62fb6e99377b23812faefa291d78c2e) )
+
+ LOAD_KANJI_ROMS
+ LOAD_IDE_ROM
+ROM_END
+
+/*
+Epson PC-486MU - 486 based, unknown clock
+*/
+
+ROM_START( pc486mu )
+ ROM_REGION( 0x60000, "ipl", ROMREGION_ERASEFF )
+ ROM_LOAD( "bios_486mu.rom", 0x08000, 0x18000, BAD_DUMP CRC(57b5d701) SHA1(15029800842e93e07615b0fd91fb9f2bfe3e3c24))
+ ROM_RELOAD( 0x28000, 0x18000 ) // missing rom?
+
+ ROM_REGION( 0x10000, "sound_bios", 0 )
+ ROM_LOAD( "sound_486mu.rom", 0x0000, 0x4000, CRC(6cdfa793) SHA1(4b8250f9b9db66548b79f961d61010558d6d6e1c))
+
+ ROM_REGION( 0x80000, "chargen", 0 )
+ ROM_LOAD( "font_486mu.rom", 0x0000, 0x46800, CRC(456d9fc7) SHA1(78ba9960f135372825ab7244b5e4e73a810002ff))
+
+ LOAD_KANJI_ROMS
+ LOAD_IDE_ROM
+ROM_END
+
+/*
+98MULTi Ce2 - 80486SX 25
+*/
+
+ROM_START( pc9821ce2 )
+ ROM_REGION( 0x60000, "ipl", ROMREGION_ERASEFF )
+ ROM_LOAD( "itf_ce2.rom", 0x18000, 0x08000, CRC(273e9e88) SHA1(9bca7d5116788776ed0f297bccb4dfc485379b41) )
+ ROM_LOAD( "bios_ce2.rom", 0x28000, 0x018000, BAD_DUMP CRC(76affd90) SHA1(910fae6763c0cd59b3957b6cde479c72e21f33c1) )
+
+ ROM_REGION( 0x10000, "sound_bios", 0 )
+ ROM_LOAD( "sound_ce2.rom", 0x000000, 0x004000, CRC(a21ef796) SHA1(34137c287c39c44300b04ee97c1e6459bb826b60) )
+
+ ROM_REGION( 0x80000, "chargen", 0 )
+ ROM_LOAD( "font_ce2.rom", 0x000000, 0x046800, CRC(d1c2702a) SHA1(e7781e9d35b6511d12631641d029ad2ba3f7daef) )
+
+ LOAD_KANJI_ROMS
+ LOAD_IDE_ROM
+ROM_END
+
+/*
+98MATE X - 486/Pentium based
+*/
+
+ROM_START( pc9821xs )
+ ROM_REGION( 0x60000, "ipl", ROMREGION_ERASEFF )
+ ROM_LOAD( "itf.rom", 0x18000, 0x08000, BAD_DUMP CRC(dd4c7bb8) SHA1(cf3aa193df2722899066246bccbed03f2e79a74a) )
+ ROM_LOAD( "bios_xs.rom", 0x28000, 0x018000, BAD_DUMP CRC(0a682b93) SHA1(76a7360502fa0296ea93b4c537174610a834d367) )
+
+ ROM_REGION( 0x10000, "sound_bios", 0 )
+ ROM_LOAD( "sound_xs.rom", 0x000000, 0x004000, CRC(80eabfde) SHA1(e09c54152c8093e1724842c711aed6417169db23) )
+
+ ROM_REGION( 0x80000, "chargen", 0 )
+ ROM_LOAD( "font_xs.rom", 0x000000, 0x046800, BAD_DUMP CRC(c9a77d8f) SHA1(deb8563712eb2a634a157289838b95098ba0c7f2) )
+
+ LOAD_KANJI_ROMS
+ LOAD_IDE_ROM
+ROM_END
+
+
+/*
+98MATE VALUESTAR - Pentium based
+*/
+
+ROM_START( pc9821v13 )
+ ROM_REGION( 0x60000, "ipl", ROMREGION_ERASEFF )
+ ROM_LOAD( "itf.rom", 0x18000, 0x08000, CRC(dd4c7bb8) SHA1(cf3aa193df2722899066246bccbed03f2e79a74a) )
+ ROM_LOAD( "bios_v13.rom", 0x28000, 0x18000, BAD_DUMP CRC(0a682b93) SHA1(76a7360502fa0296ea93b4c537174610a834d367) )
+
+ ROM_REGION( 0x10000, "sound_bios", 0 )
+ ROM_LOAD( "sound_v13.rom", 0x0000, 0x4000, CRC(a21ef796) SHA1(34137c287c39c44300b04ee97c1e6459bb826b60) )
+
+ ROM_REGION( 0x80000, "chargen", 0 )
+ ROM_LOAD( "font_a.rom", 0x00000, 0x46800, BAD_DUMP CRC(c9a77d8f) SHA1(deb8563712eb2a634a157289838b95098ba0c7f2) )
+
+ LOAD_KANJI_ROMS
+ LOAD_IDE_ROM
+ROM_END
+
+/*
+98MATE VALUESTAR - Pentium based
+*/
+
+ROM_START( pc9821v20 )
+ ROM_REGION( 0x60000, "ipl", ROMREGION_ERASEFF )
+ ROM_LOAD( "itf_v20.rom", 0x38000, 0x08000, CRC(10e52302) SHA1(f95b8648e3f5a23e507a9fbda8ab2e317d8e5151) )
+ ROM_LOAD( "bios_v20.rom", 0x08000, 0x018000, BAD_DUMP CRC(d5d1f13b) SHA1(bf44b5f4e138e036f1b848d6616fbd41b5549764) )
+
+ ROM_REGION( 0x10000, "sound_bios", 0 )
+ ROM_LOAD( "sound_v20.rom", 0x000000, 0x004000, CRC(80eabfde) SHA1(e09c54152c8093e1724842c711aed6417169db23) )
+
+ ROM_REGION( 0x80000, "chargen", 0 )
+ ROM_LOAD( "font_v20.rom", 0x000000, 0x046800, BAD_DUMP CRC(6244c4c0) SHA1(9513cac321e89b4edb067b30e9ecb1adae7e7be7) )
+
+ LOAD_KANJI_ROMS
+ LOAD_IDE_ROM
+ROM_END
+
+
+
+DRIVER_INIT_MEMBER(pc9801_state,pc9801_kanji)
+{
+ #define copy_kanji_strip(_dst,_src,_fill_type) \
+ for(i=_dst,k=_src;i<_dst+0x20;i++,k++) \
+ { \
+ for(j=0;j<0x20;j++) \
+ kanji[j+(i << 5)] = _fill_type ? new_chargen[j+(k << 5)] : 0; \
+ }
+ UINT32 i,j,k;
+ UINT32 pcg_tile;
+ UINT8 *kanji = memregion("kanji")->base();
+ UINT8 *raw_kanji = memregion("raw_kanji")->base();
+ UINT8 *new_chargen = memregion("new_chargen")->base();
+ UINT8 *chargen = memregion("chargen")->base();
+
+ /* Convert the ROM bitswap here from the original structure */
+ /* TODO: kanji bitswap should be completely wrong, will check it out once that a dump is remade. */
+ for(i=0;i<0x80000/0x20;i++)
+ {
+ for(j=0;j<0x20;j++)
+ {
+ pcg_tile = BITSWAP16(i,15,14,13,12,11,7,6,5,10,9,8,4,3,2,1,0) << 5;
+ kanji[j+(i << 5)] = raw_kanji[j+pcg_tile];
+ }
+ }
+
+ /* convert charset into even/odd structure */
+ for(i=0;i<0x80000/0x20;i++)
+ {
+ for(j=0;j<0x10;j++)
+ {
+ new_chargen[j*2+(i << 5)] = chargen[j+(i<<5)];
+ new_chargen[j*2+(i << 5)+1] = chargen[j+(i<<5)+0x10];
+ }
+ }
+
+ /* now copy the data from the fake roms into our kanji struct */
+ copy_kanji_strip(0x0800, -1,0); copy_kanji_strip(0x0820, -1,0); copy_kanji_strip(0x0840, -1,0); copy_kanji_strip(0x0860, -1,0);
+ copy_kanji_strip(0x0900, -1,0); copy_kanji_strip(0x0920,0x3c0,1); copy_kanji_strip(0x0940,0x3e0,1); copy_kanji_strip(0x0960,0x400,1);
+ copy_kanji_strip(0x0a00, -1,0); copy_kanji_strip(0x0a20,0x420,1); copy_kanji_strip(0x0a40,0x440,1); copy_kanji_strip(0x0a60,0x460,1);
+ copy_kanji_strip(0x0b00, -1,0); copy_kanji_strip(0x0b20,0x480,1); copy_kanji_strip(0x0b40,0x4a0,1); copy_kanji_strip(0x0b60,0x4c0,1);
+ copy_kanji_strip(0x0c00, -1,0); copy_kanji_strip(0x0c20,0x4e0,1); copy_kanji_strip(0x0c40,0x500,1); copy_kanji_strip(0x0c60,0x520,1);
+ copy_kanji_strip(0x0d00, -1,0); copy_kanji_strip(0x0d20,0x540,1); copy_kanji_strip(0x0d40,0x560,1); copy_kanji_strip(0x0d60,0x580,1);
+ copy_kanji_strip(0x0e00, -1,0); copy_kanji_strip(0x0e20, -1,0); copy_kanji_strip(0x0e40, -1,0); copy_kanji_strip(0x0e60, -1,0);
+ copy_kanji_strip(0x0f00, -1,0); copy_kanji_strip(0x0f20, -1,0); copy_kanji_strip(0x0f40, -1,0); copy_kanji_strip(0x0f60, -1,0);
+ {
+ int src_1,dst_1;
+
+ for(src_1=0x1000,dst_1=0x660;src_1<0x8000;src_1+=0x100,dst_1+=0x60)
+ {
+ copy_kanji_strip(src_1, -1,0);
+ copy_kanji_strip(src_1+0x20,dst_1+0x00,1);
+ copy_kanji_strip(src_1+0x40,dst_1+0x20,1);
+ copy_kanji_strip(src_1+0x60,dst_1+0x40,1);
+ }
+ }
+ #undef copy_kanji_strip
+}
+
+/* Genuine dumps */
+COMP( 1983, pc9801f, 0, 0, pc9801, pc9801, pc9801_state, pc9801_kanji, "Nippon Electronic Company", "PC-9801F", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND)
+
+/* TODO: ANYTHING below there needs REDUMPING! */
+COMP( 1989, pc9801rs, 0 ,0, pc9801rs, pc9801rs, pc9801_state, pc9801_kanji, "Nippon Electronic Company", "PC-9801RS", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND) //TODO: not sure about the exact model
+COMP( 1985, pc9801vm, pc9801ux,0, pc9801vm, pc9801rs, pc9801_state, pc9801_kanji, "Nippon Electronic Company", "PC-9801VM", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND)
+COMP( 1987, pc9801ux, 0 ,0, pc9801ux, pc9801rs, pc9801_state, pc9801_kanji, "Nippon Electronic Company", "PC-9801UX", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND)
+COMP( 1988, pc9801rx, pc9801rs,0, pc9801rs, pc9801rs, pc9801_state, pc9801_kanji, "Nippon Electronic Company", "PC-9801RX", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND)
+COMP( 1993, pc9801bx2, pc9801rs,0, pc9801bx2,pc9801rs, pc9801_state, pc9801_kanji, "Nippon Electronic Company", "PC-9801BX2/U2", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND)
+COMP( 1994, pc9821, 0, 0, pc9821, pc9821, pc9801_state, pc9801_kanji, "Nippon Electronic Company", "PC-9821 (98MATE)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND) //TODO: not sure about the exact model
+COMP( 1993, pc9821as, pc9821, 0, pc9821, pc9821, pc9801_state, pc9801_kanji, "Nippon Electronic Company", "PC-9821 (98MATE A)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND)
+COMP( 1993, pc9821ap2, pc9821, 0, pc9821ap2,pc9821, pc9801_state, pc9801_kanji, "Nippon Electronic Company", "PC-9821AP2/U8W (98MATE A)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND)
+COMP( 1994, pc9821xs, pc9821, 0, pc9821, pc9821, pc9801_state, pc9801_kanji, "Nippon Electronic Company", "PC-9821 (98MATE Xs)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND)
+COMP( 1994, pc9821ce2, pc9821, 0, pc9821, pc9821, pc9801_state, pc9801_kanji, "Nippon Electronic Company", "PC-9821 (98MULTi Ce2)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND)
+COMP( 1994, pc9821ne, pc9821, 0, pc9821, pc9821, pc9801_state, pc9801_kanji, "Nippon Electronic Company", "PC-9821 (98NOTE)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND)
+COMP( 1994, pc486mu, pc9821, 0, pc9821, pc9821, pc9801_state, pc9801_kanji, "Epson", "PC-486MU", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
+COMP( 1998, pc9821v13, pc9821, 0, pc9821, pc9821, pc9801_state, pc9801_kanji, "Nippon Electronic Company", "PC-9821 (98MATE VALUESTAR 13)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND)
+COMP( 1998, pc9821v20, pc9821, 0, pc9821v20,pc9821, pc9801_state, pc9801_kanji, "Nippon Electronic Company", "PC-9821 (98MATE VALUESTAR 20)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND)