1 // license:BSD-3-Clause
2 // copyright-holders:Angelo Salese
3 /*************************************************************************************************************************************
4 
5     PC-8801 (c) 1981 NEC
6 
7     driver by Angelo Salese, original MESS PC-88SR driver by ???
8 
9     TODO:
10     - implement proper i8214 routing, also add irq latch mechanism;
11     - Fix up Floppy Terminal Count 0 / 1 writes properly, Castle Excellent (and presumably other games) is very picky about it.
12 
13     - add differences between various models;
14     - implement proper upd3301 / i8257 support;
15     - fix "jumps" in mouse support pointer (noticeable in Balance of Power);
16     - Add limits for extend work RAM;
17     - What happens to the palette contents when the analog/digital palette mode changes?
18     - waitstates;
19     - dipswitches needs to be controlled;
20     - below notes states that plain PC-8801 doesn't have a disk CPU, but the BIOS clearly checks the floppy ports. Wrong info?
21     - clean-ups, banking and video in particular (i.e. hook-ups with memory region should go away and device models should be used instead)
22 
23     per-game specific TODO:
24     - 100yen Soft 8 Revival Special: tight loop with vblank bit, but vblank irq takes too much time to execute its code;
25     - 177: gameplay is too fast (parent pc8801 only);
26     - 1942: missing sound, enables a masked irq;
27     - Acro Jet: hangs waiting for an irq (floppy issue);
28     - Arcus: doesn't surpass Wolf Team logo;
29     - Advanced Fantasian: garbage during gameplay (floppy?)
30     - American Success: reads the light pen?
31     - Attacker: resets after a bunch of animation frames;
32     - Balance of Power: uses the SIO port for something ...
33     - Belloncho Shintai Kensa: hangs
34     - Bishoujo Baseball Gakuen: checks ym2608 after intro screen;
35     - The Black Onyx: writes a katakana msg: "sono kata ha koko ni orimasen" then doesn't show up anything. (Needs user disk?)
36     - Boukenshatachi: dies after the intro.
37     - Campaign Ban Daisenryaku 2: Hangs at title screen?
38     - Carigraph: inputs doesn't work?
39     - Can Can Bunny: bitmap artifacts on intro, caused by a fancy usage of the attribute vram;
40     - Can Can Bunny: no sound (regression);
41     - Can Can Bunny Superior: black screen during the intro
42     - Chou Bishoujo Densetsu CROQUIS: accesses ports 0xa0-0xa3 and 0xc2-0xc3
43     - Combat: mono gfx mode enabled, but I don't see any noticeable quirk?
44     - Cranston Manor (actually N88-Basic demo): no sound
45     - Datenshi Kyouko: gfx garbage on the right edge?
46     - Final Crisis: sound stuck with OPNA?
47     - Fire Hawk: tries to r/w the opn ports (probably crashed due to floppy?)
48     - Game Music Library: "Disk I/O error on 3040", starting from Sorcerian item
49     - Gaudi - Barcelona no Kaze: fails PCM loading
50     - GeGeGe no Kitarou: title screen text/bitmap contrast is pretty ugly (BTANB?);
51     - Grobda: palette is ugly (parent pc8801 only);
52     - Makaimura: after losing a life the game doesn't work properly anymore, copy protection?
53     - Music Collection Vol. 2 - Final Fantasy Tokushuu: sound irq dies pretty soon
54     - N-BASIC: cursor doesn't show up;
55     - The Return of Ishtar: z80 exception after entering the name.
56     - Star Cruiser: bad kanji data?
57     - Star Cruiser: reads at i/o 0x8e?
58     - Wanderers from Ys: user data disk looks screwed? It loads with everything as maximum as per now ...
59     - WerDragon: no BGMs
60     - Xevious: game is too fast (parent pc8801 only)
61 
62     list of games/apps that crashes due of floppy issues (* -> denotes games fixed with current floppy code, # -> regressed with current floppy code):
63     * Agni no Ishi
64     * Amazoness no Hihou (takes invalid data from floppy)
65     - American Truck / American Truck SR (polls read deleted data command)
66     * Ankokujou
67     * Ao No Sekizou (fdc CPU irq doesn't fire anymore)
68     * Arcus
69     * Attacker
70     - Autumn Park (BASIC error)
71     * Battle Gorilla
72     * Belloncho Shintai Kensa
73     - Bishoujo Noriko Part I (writes to FDC CPU ROM then expects some strict values, taken from floppy image)
74     * Blassty (attempts to read at 0x801b)
75     - Bokosuka Wars (polls read ID command)
76     * Boukenshatachi
77     * Can Can Bunny Superior
78     - Carmine
79     - Castle Excellent (sets sector 0xf4? Jumps to 0xa100 and it shouldn't) (REGRESSED with current floppy code)
80     - Card Game Pro 8.8k Plus Unit 1 (prints Disk i/o error 135 in vram, not visible for whatever reason)
81     - Championship Lode Runner (fdc CPU irq doesn't fire anymore)
82     - Change Vol. 1 (stops at PCM loading)
83     - Chikyuu Boueigun (disk i/o error during "ESDF SYSTEM LOADING") (REGRESSED with current floppy code)
84     * Chikyuu Senshi Rayieza (fdc CPU crashes)
85     - Choplifter
86     - Columns (code at 0x28c8, copy protection)
87     - Corridor ("THIS SYSTEM NOT KOEI SYSTEM" printed on screen) (REGRESSED with current floppy code)
88     # Craze (returns to basic after logo pops up, tries to self-modify program data via the window offset?)
89     * Crimson
90     * Crimson 3
91     * Cuby Panic (copy protection routine at 0x911A)
92     - Daidasso (prints "BOOT dekimasen" on screen -> can't boot)
93     - Daikoukai Jidai (YSHELL.COM error)
94     - Databox (app)
95     - Day Dream ("Bad drive number at 570")
96     - Demons Ring
97     * Dennou Tsuushin
98     - Door Door MK-2 (sets up TC in the middle of execution phase read then wants status bit 6 to be low PC=0x7050 of fdc cpu)
99     * Dragon Slayer - The Legend of Heroes 2
100     - Dungeon Buster
101     * El Dorado Denki
102     * Elevator Action
103     - Emerald Densetsu (dies after few seconds of intro)
104     - Emerald Dragon (it seems to miss a timer)
105     - Emmy
106     - Explosion (fails to load ADPCM data?)
107     * F15 Strike Eagle
108     - F2 Grand Prix ("Boot dekimasen")
109     # Fangs - The Saga of Wolf Blood (Crashes at the first random battle)
110     - Fantasian
111     * Final Zone
112     # Final Zone (demo) (REGRESSION: asserts at MESS boot)
113     - Fruit Panic
114     - FSD Sample Ongaku Shuu Vol. 1-7
115     - Gaia no Kiba (Disk I/O error at 150)
116     - Gaiflame
117     - Gambler Jiko Chuushin ha
118     - Gambler Jiko Chuushin ha 2
119     - Gambler Jiko Chuushin ha 3
120     - Gambler Jiko Chuushin ha 3 (demo)
121     - Gambler Jiko Chuushin ha Mahjong Puzzle Collection
122     - Gambler Jiko Chuushin ha Mahjong Puzzle Collection (demo)
123     * Game Music Library
124     * Gaudi - Barcelona no Kaze (bad Wolfteam logo then black screen)
125     - GC-clusterz Music Disk Vol. 1-7
126     * Genji
127     * Gokuraku Tengoku
128     - Grodius 3 (might not be floppy)
129     - Gun Ship (at gameplay)
130     (Hacker)
131 
132     - Harakiri
133     - Kaseijin (app) (code snippet is empty at some point)
134     - Lamia: fails to create an user disk (after character creation) -> disk write error
135     * MakaiMura (attempts to r/w the sio ports, but it's clearly crashed)
136     * Mugen Senshi Valis (at Telenet logo, it also appears to have a nasty copy protection when taking a specific item (untested))
137     - Mr. Pro Yakyuu
138     - Panorama Toh
139     - PC-8034 (app)
140     - PC-8037SR (app)
141     - P1 (app)
142     - Pattern Editor 88 (app)
143     - Super Shunbo II (app) (Load error)
144     - Super TII (app)
145     * The Return of Ishtar
146     - Tobira wo Akete (random crashes in parent pc8801 only)
147 
148     list of games that doesn't like i8214_irq_level == 5 in sound irq
149     - 100yen Disk 2 / Jumper 2: Sound BGM dies pretty soon;
150     - Alpha (demo): stuck note in title screen, doesn't seem to go further;
151     - Ayumi: black screen after new game / load game screen;
152     - Brunette: No sound, eventually hangs at gameplay;
153     - Digital Devil Story Megami Tensei: hangs at gameplay (sound irq issue)
154     - Double Face: hangs at logo (sound irq issue)
155 
156     games that needs to NOT have write-protect floppies (BTANBs):
157     - Balance of Power
158     - Blue Moon Story: moans with a kanji msg;
159     - Mahjong Clinic Zoukangou
160     - Tobira wo Akete (hangs at title screen)
161 
162     games that needs to HAVE write-protect floppies (BTANBs):
163     - 100 Yen Disk 7: (doesn't boot in V2 mode)
164 
165     other BTANBs
166     - Attack Hirokochan: returns to BASIC after an initial animation, needs BASIC V1:
167     - Jark (needs PC-8801MC)
168     - Kuronekosou Souzoku Satsujin Jiken: "Illegal function call in 105", needs BASIC V1;
169 
170     Notes:
171     - BIOS disk ROM defines what kind of floppies you could load:
172       * with 0x0800 ROM size you can load 2d floppies only;
173       * with 0x2000 ROM size you can load 2d and 2hd floppies;
174     - Later models have palette bugs with some games (Alphos, Tokyo Nampa Street).
175       This is because you have to set up the V1 / V2 DIP-SW to V1 for those games (it's the BIOS that sets up to analog and never changes back otherwise).
176     - Password for "AY-1: Fortress Solomon" is "123" then press enter, any other key pressed makes it to fail the check (you must soft reset the machine)
177     - Pressing Home in Dennou Gakuen during gameplay makes it to show a fake DASM screen. That's supposed to be a panic button and it's also in the
178       sequels (with different screens);
179 
180     Bankswitch Notes:
181     - 0x31 - graphic banking
182     - 0x32 - misc banking
183     - 0x5c / 0x5f - VRAM banking
184     - 0x70 - window offset (banking)
185     - 0x71 - extra ROM banking
186     - 0x78 - window offset (banking) increment (+ 0x100)
187     - 0xe2 / 0xe3 - extra RAM banking
188     - 0xf0 / 0xf1 = kanji banking
189 
190 ======================================================================================================================================
191 
192     PC-88xx Models (and similar machines like PC-80xx and PC-98DO)
193 
194     Model            | release |      CPU     |                      BIOS components                        |       |
195                      |         |     clock    | N-BASIC | N88-BASIC | N88-BASIC Enh |  Sound  |  CD |  Dict |  Disk | Notes
196     ==================================================================================================================================
197     PC-8001          | 1979-03 |   z80A @ 4   |    X    |     -     |       -       |    -    |  -  |   -   |   -   |
198     PC-8001A         |   ??    |   z80A @ 4   |    X    |     -     |       -       |    -    |  -  |   -   |   -   | (U)
199     PC-8801          | 1981-11 |   z80A @ 4   |    X    |     X     |       -       |    -    |  -  |   -   |   -   | (KO)
200     PC-8801A         |   ??    |   z80A @ 4   |    X    |     X     |       -       |    -    |  -  |   -   |   -   | (U)
201     PC-8001 mkII     | 1983-03 |   z80A @ 4   |    X    |     -     |       -       |    -    |  -  |   -   |   -   | (GE),(KO)
202     PC-8001 mkIIA    |   ??    |   z80A @ 4   |    X    |     -     |       -       |    -    |  -  |   -   |   -   | (U),(GE)
203     PC-8801 mkII     | 1983-11 |   z80A @ 4   |    X    |     X     |       -       |    -    |  -  |   -   | (FDM) | (K1)
204     PC-8001 mkII SR  | 1985-01 |   z80A @ 4   |    X    |     -     |       -       |    -    |  -  |   -   |   -   | (GE),(NE),(KO)
205     PC-8801 mkII SR  | 1985-03 |   z80A @ 4   |    X    |     X     |       X       |    X    |  -  |   -   | (FDM) | (K1)
206     PC-8801 mkII TR  | 1985-10 |   z80A @ 4   |    X    |     X     |       X       |    X    |  -  |   -   | (FD2) | (K1)
207     PC-8801 mkII FR  | 1985-11 |   z80A @ 4   |    X    |     X     |       X       |    X    |  -  |   -   | (FDM) | (K1)
208     PC-8801 mkII MR  | 1985-11 |   z80A @ 4   |    X    |     X     |       X       |    X    |  -  |   -   | (FDH) | (K2)
209     PC-8801 FH       | 1986-11 |  z80H @ 4/8  |    X    |     X     |       X       |    X    |  -  |   -   | (FDM) | (K2)
210     PC-8801 MH       | 1986-11 |  z80H @ 4/8  |    X    |     X     |       X       |    X    |  -  |   -   | (FDH) | (K2)
211     PC-88 VA         | 1987-03 | z80H+v30 @ 8 |    -    |     X     |       X       |    X    |  -  |   X   | (FDH) | (K2)
212     PC-8801 FA       | 1987-11 |  z80H @ 4/8  |    X    |     X     |       X       |    X    |  -  |   -   | (FD2) | (K2)
213     PC-8801 MA       | 1987-11 |  z80H @ 4/8  |    X    |     X     |       X       |    X    |  -  |   X   | (FDH) | (K2)
214     PC-88 VA2        | 1988-03 | z80H+v30 @ 8 |    -    |     X     |       X       |    X    |  -  |   X   | (FDH) | (K2)
215     PC-88 VA3        | 1988-03 | z80H+v30 @ 8 |    -    |     X     |       X       |    X    |  -  |   X   | (FD3) | (K2)
216     PC-8801 FE       | 1988-10 |  z80H @ 4/8  |    X    |     X     |       X       |    X    |  -  |   -   | (FD2) | (K2)
217     PC-8801 MA2      | 1988-10 |  z80H @ 4/8  |    X    |     X     |       X       |    X    |  -  |   X   | (FDH) | (K2)
218     PC-98 DO         | 1989-06 |   z80H @ 8   |    X    |     X     |       X       |    X    |  -  |   -   | (FDH) | (KE)
219     PC-8801 FE2      | 1989-10 |  z80H @ 4/8  |    X    |     X     |       X       |    X    |  -  |   -   | (FD2) | (K2)
220     PC-8801 MC       | 1989-11 |  z80H @ 4/8  |    X    |     X     |       X       |    X    |  X  |   X   | (FDH) | (K2)
221     PC-98 DO+        | 1990-10 |   z80H @ 8   |    X    |     X     |       X       |    X    |  -  |   -   | (FDH) | (KE)
222 
223     info for PC-98 DO & DO+ refers to their 88-mode
224 
225     Disk Drive options:
226     (FDM): there exist three model of this computer: Model 10 (base model, only optional floppy drive), Model 20
227         (1 floppy drive for 5.25" 2D disks) and Model 30 (2 floppy drive for 5.25" 2D disks)
228     (FD2): 2 floppy drive for 5.25" 2D disks
229     (FDH): 2 floppy drive for both 5.25" 2D disks and 5.25" HD disks
230     (FD3): 2 floppy drive for both 5.25" 2D disks and 5.25" HD disks + 1 floppy drive for 3.5" 2TD disks
231 
232     Notes:
233     (U): US version
234     (GE): Graphic Expansion for PC-8001
235     (NE): N-BASIC Expansion for PC-8001 (similar to N88-BASIC Expansion for PC-88xx)
236     (KO): Optional Kanji ROM
237     (K1): Kanji 1st Level ROM
238     (K2): Kanji 2nd Level ROM
239     (KE): Kanji Enhanced ROM
240 
241     Memory mounting locations:
242      * N-BASIC 0x0000 - 0x5fff, N-BASIC Expansion & Graph Enhhancement 0x6000 - 0x7fff
243      * N-BASIC 0x0000 - 0x5fff, N-BASIC Expansion & Graph Enhhancement 0x6000 - 0x7fff
244      * N88-BASIC 0x0000 - 0x7fff, N88-BASIC Expansion & Graph Enhhancement 0x6000 - 0x7fff
245      * Sound BIOS: 0x6000 - 0x7fff
246      * CD-ROM BIOS: 0x0000 - 0x7fff
247      * Dictionary: 0xc000 - 0xffff (32 Banks)
248 
249     info from http://www.geocities.jp/retro_zzz/machines/nec/cmn_roms.html
250     also, refer to http://www.geocities.jp/retro_zzz/machines/nec/cmn_vers.html for
251         info about BASIC revisions in the various models (BASIC V2 is the BASIC
252         Expansion, if I unerstood correctly)
253 
254 *************************************************************************************************************************************/
255 
256 
257 #include "emu.h"
258 #include "includes/pc8801.h"
259 
260 
261 
262 #define IRQ_DEBUG       (0)
263 #define IRQ_LOG(x) do { if (IRQ_DEBUG) printf x; } while (0)
264 
265 #define MASTER_CLOCK XTAL(4'000'000)
266 // TODO: exact clocks
267 #define PIXEL_CLOCK_15KHz XTAL(14'318'181)
268 #define PIXEL_CLOCK_24KHz XTAL(21'477'272)
269 
270 
271 /*
272 CRTC command params:
273 0. CRTC reset
274 
275 [0] *--- ---- <unknown>
276 [0] -xxx xxxx screen columns (+2)
277 
278 [1] xx-- ---- blink speed (in frame unit) (+1, << 3)
279 [1] --xx xxxx screen lines (+1)
280 
281 [2] x--- ---- "skip line"
282 [2] -x-- ---- cursor style (reverse on / underscore off)
283 [2] --x- ---- cursor blink on/off
284 [2] ---x xxxx lines per character (+1)
285 
286 [3] xxx- ---- Vertical Retrace (+1)
287 [3] ---x xxxx Horizontal Retrace (+2)
288 
289 [4] x--- ---- attribute not separate flag
290 [4] -x-- ---- attribute color flag
291 [4] --x- ---- attribute not special flag (invalidates next register)
292 [4] ---x xxxx attribute size (+1)
293 */
294 
295 #define screen_width ((m_crtc.param[0][0] & 0x7f) + 2) * 8
296 
297 #define blink_speed ((((m_crtc.param[0][1] & 0xc0) >> 6) + 1) << 3)
298 #define screen_height ((m_crtc.param[0][1] & 0x3f) + 1)
299 
300 #define lines_per_char ((m_crtc.param[0][2] & 0x1f) + 1)
301 
302 #define vretrace (((m_crtc.param[0][3] & 0xe0) >> 5) + 1)
303 #define hretrace ((m_crtc.param[0][3] & 0x1f) + 2) * 8
304 
305 #define text_color_flag ((m_crtc.param[0][4] & 0xe0) == 0x40)
306 //#define monitor_24KHz ((m_gfx_ctrl & 0x19) == 0x08) /* TODO: this is most likely to be WRONG */
307 
video_start()308 void pc8801_state::video_start()
309 {
310 }
311 
draw_bitmap_3bpp(bitmap_ind16 & bitmap,const rectangle & cliprect)312 void pc8801_state::draw_bitmap_3bpp(bitmap_ind16 &bitmap,const rectangle &cliprect)
313 {
314 	uint32_t count = 0;
315 
316 	uint16_t y_double = (pc8801_pixel_clock());
317 	uint16_t y_size = (y_double+1) * 200;
318 
319 	for(int y=0;y<y_size;y+=(y_double+1))
320 	{
321 		for(int x=0;x<640;x+=8)
322 		{
323 			for(int xi=0;xi<8;xi++)
324 			{
325 				int pen = 0;
326 
327 				/* note: layer masking doesn't occur in 3bpp mode, Bug Attack relies on this */
328 				pen |= ((m_gvram[count+0x0000] >> (7-xi)) & 1) << 0;
329 				pen |= ((m_gvram[count+0x4000] >> (7-xi)) & 1) << 1;
330 				pen |= ((m_gvram[count+0x8000] >> (7-xi)) & 1) << 2;
331 
332 				if(y_double)
333 				{
334 					if(cliprect.contains(x+xi, y+0))
335 						bitmap.pix(y+0, x+xi) = m_palette->pen(pen & 7);
336 
337 					if(cliprect.contains(x+xi, y+1))
338 						bitmap.pix(y+1, x+xi) = m_palette->pen(pen & 7);
339 				}
340 				else
341 				{
342 					if(cliprect.contains(x+xi, y+0))
343 						bitmap.pix(y, x+xi) = m_palette->pen(pen & 7);
344 				}
345 			}
346 
347 			count++;
348 		}
349 	}
350 }
351 
draw_bitmap_1bpp(bitmap_ind16 & bitmap,const rectangle & cliprect)352 void pc8801_state::draw_bitmap_1bpp(bitmap_ind16 &bitmap,const rectangle &cliprect)
353 {
354 	uint32_t count = 0;
355 	uint8_t color = (m_gfx_ctrl & 1) ? 7 & ((m_layer_mask ^ 0xe) >> 1) : 7;
356 	uint8_t is_cursor = 0;
357 
358 	for(int y=0;y<200;y++)
359 	{
360 		for(int x=0;x<640;x+=8)
361 		{
362 			if(!(m_gfx_ctrl & 1))
363 				is_cursor = calc_cursor_pos(x/8,y/lines_per_char,y & (lines_per_char-1));
364 
365 			for(int xi=0;xi<8;xi++)
366 			{
367 				int pen = ((m_gvram[count+0x0000] >> (7-xi)) & 1);
368 				if(is_cursor)
369 					pen^=1;
370 
371 				if((m_gfx_ctrl & 1))
372 				{
373 					if(cliprect.contains(x+xi, y*2+0))
374 						bitmap.pix(y*2+0, x+xi) = m_palette->pen(pen ? color : 0);
375 
376 					if(cliprect.contains(x+xi, y*2+1))
377 						bitmap.pix(y*2+1, x+xi) = m_palette->pen(pen ? color : 0);
378 				}
379 				else
380 				{
381 					if(cliprect.contains(x+xi, y))
382 						bitmap.pix(y, x+xi) = m_palette->pen(pen ? color : 0);
383 				}
384 			}
385 
386 			count++;
387 		}
388 	}
389 
390 	if(!(m_gfx_ctrl & 1)) // 400 lines
391 	{
392 		count = 0;
393 
394 		for(int y=200;y<400;y++)
395 		{
396 			for(int x=0;x<640;x+=8)
397 			{
398 				if(!(m_gfx_ctrl & 1))
399 					is_cursor = calc_cursor_pos(x/8,y/lines_per_char,y & (lines_per_char-1));
400 
401 				for(int xi=0;xi<8;xi++)
402 				{
403 					int pen = ((m_gvram[count+0x4000] >> (7-xi)) & 1);
404 					if(is_cursor)
405 						pen^=1;
406 
407 					if(cliprect.contains(x+xi, y))
408 						bitmap.pix(y, x+xi) = m_palette->pen(pen ? 7 : 0);
409 				}
410 
411 				count++;
412 			}
413 		}
414 	}
415 }
416 
calc_cursor_pos(int x,int y,int yi)417 uint8_t pc8801_state::calc_cursor_pos(int x,int y,int yi)
418 {
419 	if(!(m_crtc.cursor_on)) // don't bother if cursor is off
420 		return 0;
421 
422 	if(x == m_crtc.param[4][0] && y == m_crtc.param[4][1]) /* check if position matches */
423 	{
424 		/* don't pass through if we are using underscore */
425 		if((!(m_crtc.param[0][2] & 0x40)) && yi != 7)
426 			return 0;
427 
428 		/* finally check if blinking is currently active high */
429 		if(!(m_crtc.param[0][2] & 0x20))
430 			return 1;
431 
432 		if(((m_screen->frame_number() / blink_speed) & 1) == 0)
433 			return 1;
434 
435 		return 0;
436 	}
437 
438 	return 0;
439 }
440 
441 
442 
extract_text_attribute(uint32_t address,int x,uint8_t width,uint8_t & non_special)443 uint8_t pc8801_state::extract_text_attribute(uint32_t address,int x, uint8_t width, uint8_t &non_special)
444 {
445 	uint8_t *vram = m_work_ram.get();
446 	int i;
447 	int fifo_size;
448 	int offset;
449 
450 	non_special = 0;
451 	if(m_crtc.param[0][4] & 0x80)
452 	{
453 		popmessage("Using non-separate mode for text tilemap, contact MESSdev");
454 		return 0;
455 	}
456 
457 	fifo_size = (m_crtc.param[0][4] & 0x20) ? 0 : ((m_crtc.param[0][4] & 0x1f) + 1);
458 
459 	if(fifo_size == 0)
460 	{
461 		non_special = 1;
462 		return (text_color_flag) ? 0xe8 : 0;
463 	}
464 
465 	/* TODO: correct or hack-ish? Certainly having 0 as a attribute X is weird in any case. */
466 	offset = (vram[address] == 0) ? 2 : 0;
467 
468 	for(i=0;i<fifo_size;i++)
469 	{
470 		if(x < vram[address+offset])
471 		{
472 			return vram[address+1];
473 		}
474 		else
475 			address+=2;
476 	}
477 
478 	return vram[address-3+offset];
479 }
480 
pc8801_draw_char(bitmap_ind16 & bitmap,int x,int y,int pal,uint8_t gfx_mode,uint8_t reverse,uint8_t secret,uint8_t blink,uint8_t upper,uint8_t lower,int y_size,int width,uint8_t non_special)481 void pc8801_state::pc8801_draw_char(bitmap_ind16 &bitmap,int x,int y,int pal,uint8_t gfx_mode,uint8_t reverse,uint8_t secret,uint8_t blink,uint8_t upper,uint8_t lower,int y_size,int width, uint8_t non_special)
482 {
483 	uint8_t *vram = m_work_ram.get();
484 
485 	uint8_t y_height = lines_per_char;
486 	uint8_t y_double = (pc8801_pixel_clock());
487 	uint8_t y_step = (non_special) ? 80 : 120; // trusted by Elthlead
488 	uint8_t is_cursor = 0;
489 
490 	for(int yi=0;yi<y_height;yi++)
491 	{
492 		if(m_gfx_ctrl & 1)
493 			is_cursor = calc_cursor_pos(x,y,yi);
494 
495 		for(int xi=0;xi<8;xi++)
496 		{
497 			int tile = vram[x+(y*y_step)+m_dma_address[2]];
498 
499 			int res_x = x*8+xi*(width+1);
500 			int res_y = y*y_height+yi;
501 
502 			if(!m_screen->visible_area().contains(res_x, res_y))
503 				continue;
504 
505 			int color;
506 			if(gfx_mode)
507 			{
508 				uint8_t mask;
509 
510 				mask = (xi & 4) ? 0x10 : 0x01;
511 				mask <<= ((yi & (0x6 << y_double)) >> (1+y_double));
512 				color = (tile & mask) ? pal : -1;
513 			}
514 			else
515 			{
516 				uint8_t blink_mask = 0;
517 				if(blink && ((m_screen->frame_number() / blink_speed) & 3) == 1)
518 					blink_mask = 1;
519 
520 				uint8_t char_data;
521 				if(yi >= (1 << (y_double+3)) || secret || blink_mask)
522 					char_data = 0;
523 				else
524 					char_data = (m_cg_rom[tile*8+(yi >> y_double)] >> (7-xi)) & 1;
525 
526 				if(yi == 0 && upper)
527 					char_data = 1;
528 
529 				if(yi == y_height && lower)
530 					char_data = 1;
531 
532 				if(is_cursor)
533 					char_data^=1;
534 
535 				if(reverse)
536 					char_data^=1;
537 
538 				color = char_data ? pal : -1;
539 			}
540 
541 			if(color != -1)
542 			{
543 				bitmap.pix(res_y, res_x) = m_palette->pen(color);
544 				if(width)
545 				{
546 					if(!m_screen->visible_area().contains(res_x+1, res_y))
547 						continue;
548 
549 					bitmap.pix(res_y, res_x+1) = m_palette->pen(color);
550 				}
551 			}
552 		}
553 	}
554 }
555 
draw_text(bitmap_ind16 & bitmap,int y_size,uint8_t width)556 void pc8801_state::draw_text(bitmap_ind16 &bitmap,int y_size, uint8_t width)
557 {
558 	int x,y;
559 	uint8_t attr;
560 	uint8_t reverse;
561 	uint8_t gfx_mode;
562 	uint8_t secret;
563 	uint8_t upper;
564 	uint8_t lower;
565 	uint8_t blink;
566 	int pal;
567 	uint8_t non_special;
568 
569 	for(y=0;y<y_size;y++)
570 	{
571 		for(x=0;x<80;x++)
572 		{
573 			if(x & 1 && !width)
574 				continue;
575 
576 			attr = extract_text_attribute((((y*120)+80+m_dma_address[2]) & 0xffff),(x),width,non_special);
577 
578 			if(text_color_flag && (attr & 8)) // color mode
579 			{
580 				pal =  ((attr & 0xe0) >> 5);
581 				gfx_mode = (attr & 0x10) >> 4;
582 				reverse = 0;
583 				secret = 0;
584 				upper = 0;
585 				lower = 0;
586 				blink = 0;
587 				pal|=8; //text pal bank
588 			}
589 			else // monochrome
590 			{
591 				pal = 7; /* TODO: Bishoujo Baseball Gakuen Pasoket logo wants this to be black somehow ... */
592 				gfx_mode = (attr & 0x80) >> 7;
593 				reverse = (attr & 4) >> 2;
594 				secret = (attr & 1);
595 				upper = (attr & 0x10) >> 4;
596 				lower = (attr & 0x20) >> 5;
597 				blink = (attr & 2) >> 1;
598 				pal|=8; //text pal bank
599 				reverse ^= m_crtc.inverse;
600 
601 				if(attr & 0x80)
602 					popmessage("Warning: mono gfx mode enabled, contact MESSdev");
603 
604 			}
605 
606 			pc8801_draw_char(bitmap,x,y,pal,gfx_mode,reverse,secret,blink,upper,lower,y_size,!width,non_special);
607 		}
608 	}
609 }
610 
screen_update(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)611 uint32_t pc8801_state::screen_update( screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
612 {
613 	bitmap.fill(m_palette->pen(0), cliprect);
614 
615 //  popmessage("%04x %04x %02x",m_dma_address[2],m_dma_counter[2],m_dmac_mode);
616 
617 	if(m_gfx_ctrl & 8)
618 	{
619 		if(m_gfx_ctrl & 0x10)
620 			draw_bitmap_3bpp(bitmap,cliprect);
621 		else
622 			draw_bitmap_1bpp(bitmap,cliprect);
623 	}
624 
625 	//popmessage("%02x %02x %02x %02x %02x",state->m_layer_mask,state->m_dmac_mode,state->m_crtc.status,state->m_crtc.irq_mask,state->m_gfx_ctrl);
626 
627 	if(!(m_layer_mask & 1) && m_dmac_mode & 4 && m_crtc.status & 0x10 && m_crtc.irq_mask == 3)
628 	{
629 		//popmessage("%02x %02x",m_crtc.param[0][0],m_crtc.param[0][4]);
630 
631 		draw_text(bitmap,screen_height,m_txt_width);
632 	}
633 
634 	return 0;
635 }
636 
pc8801_alu_r(offs_t offset)637 uint8_t pc8801_state::pc8801_alu_r(offs_t offset)
638 {
639 	int i;
640 	uint8_t b,r,g;
641 
642 	/* store data to ALU regs */
643 	for(i=0;i<3;i++)
644 		m_alu_reg[i] = m_gvram[i*0x4000 + offset];
645 
646 	b = m_gvram[offset + 0x0000];
647 	r = m_gvram[offset + 0x4000];
648 	g = m_gvram[offset + 0x8000];
649 	if(!(m_alu_ctrl2 & 1)) { b^=0xff; }
650 	if(!(m_alu_ctrl2 & 2)) { r^=0xff; }
651 	if(!(m_alu_ctrl2 & 4)) { g^=0xff; }
652 
653 	return b & r & g;
654 }
655 
pc8801_alu_w(offs_t offset,uint8_t data)656 void pc8801_state::pc8801_alu_w(offs_t offset, uint8_t data)
657 {
658 	int i;
659 
660 	switch(m_alu_ctrl2 & 0x30) // alu write mode
661 	{
662 		case 0x00: //logic operation
663 		{
664 			uint8_t logic_op;
665 
666 			for(i=0;i<3;i++)
667 			{
668 				logic_op = (m_alu_ctrl1 & (0x11 << i)) >> i;
669 
670 				switch(logic_op)
671 				{
672 					case 0x00: { m_gvram[i*0x4000 + offset] &= ~data; } break;
673 					case 0x01: { m_gvram[i*0x4000 + offset] |= data; } break;
674 					case 0x10: { m_gvram[i*0x4000 + offset] ^= data; } break;
675 					case 0x11: break; // NOP
676 				}
677 			}
678 		}
679 		break;
680 
681 		case 0x10: // restore data from ALU regs
682 		{
683 			for(i=0;i<3;i++)
684 				m_gvram[i*0x4000 + offset] = m_alu_reg[i];
685 		}
686 		break;
687 
688 		case 0x20: // swap ALU reg 1 into R GVRAM
689 			m_gvram[0x0000 + offset] = m_alu_reg[1];
690 			break;
691 
692 		case 0x30: // swap ALU reg 0 into B GVRAM
693 			m_gvram[0x4000 + offset] = m_alu_reg[0];
694 			break;
695 	}
696 }
697 
698 
pc8801_wram_r(offs_t offset)699 uint8_t pc8801_state::pc8801_wram_r(offs_t offset)
700 {
701 	return m_work_ram[offset];
702 }
703 
pc8801_wram_w(offs_t offset,uint8_t data)704 void pc8801_state::pc8801_wram_w(offs_t offset, uint8_t data)
705 {
706 	m_work_ram[offset] = data;
707 }
708 
pc8801_ext_wram_r(offs_t offset)709 uint8_t pc8801_state::pc8801_ext_wram_r(offs_t offset)
710 {
711 	if(offset < m_extram_size)
712 		return m_ext_work_ram[offset];
713 
714 	return 0xff;
715 }
716 
pc8801_ext_wram_w(offs_t offset,uint8_t data)717 void pc8801_state::pc8801_ext_wram_w(offs_t offset, uint8_t data)
718 {
719 	if(offset < m_extram_size)
720 		m_ext_work_ram[offset] = data;
721 }
722 
pc8801_nbasic_rom_r(offs_t offset)723 uint8_t pc8801_state::pc8801_nbasic_rom_r(offs_t offset)
724 {
725 	return m_n80rom[offset];
726 }
727 
pc8801_n88basic_rom_r(offs_t offset)728 uint8_t pc8801_state::pc8801_n88basic_rom_r(offs_t offset)
729 {
730 	return m_n88rom[offset];
731 }
732 
pc8801_gvram_r(offs_t offset)733 uint8_t pc8801_state::pc8801_gvram_r(offs_t offset)
734 {
735 	return m_gvram[offset];
736 }
737 
pc8801_gvram_w(offs_t offset,uint8_t data)738 void pc8801_state::pc8801_gvram_w(offs_t offset, uint8_t data)
739 {
740 	m_gvram[offset] = data;
741 }
742 
pc8801_high_wram_r(offs_t offset)743 uint8_t pc8801_state::pc8801_high_wram_r(offs_t offset)
744 {
745 	return m_hi_work_ram[offset];
746 }
747 
pc8801_high_wram_w(offs_t offset,uint8_t data)748 void pc8801_state::pc8801_high_wram_w(offs_t offset, uint8_t data)
749 {
750 	m_hi_work_ram[offset] = data;
751 }
752 
pc8801ma_dic_r(offs_t offset)753 uint8_t pc8801_state::pc8801ma_dic_r(offs_t offset)
754 {
755 	uint8_t *dic_rom = memregion("dictionary")->base();
756 
757 	return dic_rom[offset];
758 }
759 
pc8801_cdbios_rom_r(offs_t offset)760 uint8_t pc8801_state::pc8801_cdbios_rom_r(offs_t offset)
761 {
762 	uint8_t *cdrom_bios = memregion("cdrom")->base();
763 
764 	return cdrom_bios[offset];
765 }
766 
pc8801_mem_r(offs_t offset)767 uint8_t pc8801_state::pc8801_mem_r(offs_t offset)
768 {
769 	if(offset <= 0x7fff)
770 	{
771 		if(m_extram_mode & 1)
772 			return pc8801_ext_wram_r(offset | (m_extram_bank * 0x8000));
773 
774 		if(m_gfx_ctrl & 2)
775 			return pc8801_wram_r(offset);
776 
777 		if(m_has_cdrom && m_cdrom_reg[9] & 0x10)
778 			return pc8801_cdbios_rom_r((offset & 0x7fff) | ((m_gfx_ctrl & 4) ? 0x8000 : 0x0000));
779 
780 		if(m_gfx_ctrl & 4)
781 			return pc8801_nbasic_rom_r(offset);
782 
783 		if(offset >= 0x6000 && offset <= 0x7fff && ((m_ext_rom_bank & 1) == 0))
784 			return pc8801_n88basic_rom_r(0x8000 + (offset & 0x1fff) + (0x2000 * (m_misc_ctrl & 3)));
785 
786 		return pc8801_n88basic_rom_r(offset);
787 	}
788 	else if(offset >= 0x8000 && offset <= 0x83ff) // work RAM window
789 	{
790 		uint32_t window_offset;
791 
792 		if(m_gfx_ctrl & 6) //wram read select or n basic select banks this as normal wram
793 			return pc8801_wram_r(offset);
794 
795 		window_offset = (offset & 0x3ff) + (m_window_offset_bank << 8);
796 
797 		if(((window_offset & 0xf000) == 0xf000) && (m_misc_ctrl & 0x10))
798 			printf("Read from 0xf000 - 0xffff window offset\n"); //accessed by Castle Excellent, no noticeable quirk
799 
800 		if(((window_offset & 0xf000) == 0xf000) && (m_misc_ctrl & 0x10))
801 			return pc8801_high_wram_r(window_offset & 0xfff);
802 
803 		return pc8801_wram_r(window_offset);
804 	}
805 	else if(offset >= 0x8400 && offset <= 0xbfff)
806 	{
807 		return pc8801_wram_r(offset);
808 	}
809 	else if(offset >= 0xc000 && offset <= 0xffff)
810 	{
811 		if(m_has_dictionary && m_dic_ctrl)
812 			return pc8801ma_dic_r((offset & 0x3fff) + ((m_dic_bank & 0x1f) * 0x4000));
813 
814 		if(m_misc_ctrl & 0x40)
815 		{
816 			if(!machine().side_effects_disabled())
817 				m_vram_sel = 3;
818 
819 			if(m_alu_ctrl2 & 0x80)
820 				return pc8801_alu_r(offset & 0x3fff);
821 		}
822 
823 		if(m_vram_sel == 3)
824 		{
825 			if(offset >= 0xf000 && offset <= 0xffff && (m_misc_ctrl & 0x10))
826 				return pc8801_high_wram_r(offset & 0xfff);
827 
828 			return pc8801_wram_r(offset);
829 		}
830 
831 		return pc8801_gvram_r((offset & 0x3fff) + (0x4000 * m_vram_sel));
832 	}
833 
834 	return 0xff;
835 }
836 
pc8801_mem_w(offs_t offset,uint8_t data)837 void pc8801_state::pc8801_mem_w(offs_t offset, uint8_t data)
838 {
839 	if(offset <= 0x7fff)
840 	{
841 		if(m_extram_mode & 0x10)
842 			pc8801_ext_wram_w(offset | (m_extram_bank * 0x8000),data);
843 		else
844 			pc8801_wram_w(offset,data);
845 
846 		return;
847 	}
848 	else if(offset >= 0x8000 && offset <= 0x83ff)
849 	{
850 		if(m_gfx_ctrl & 6) //wram read select or n basic select banks this as normal wram
851 			pc8801_wram_w(offset,data);
852 		else
853 		{
854 			uint32_t window_offset;
855 
856 			window_offset = (offset & 0x3ff) + (m_window_offset_bank << 8);
857 
858 			if(((window_offset & 0xf000) == 0xf000) && (m_misc_ctrl & 0x10))
859 				printf("Write to 0xf000 - 0xffff window offset\n"); //accessed by Castle Excellent, no noticeable quirk
860 
861 			if(((window_offset & 0xf000) == 0xf000) && (m_misc_ctrl & 0x10))
862 				pc8801_high_wram_w(window_offset & 0xfff,data);
863 			else
864 				pc8801_wram_w(window_offset,data);
865 		}
866 
867 		return;
868 	}
869 	else if(offset >= 0x8400 && offset <= 0xbfff)
870 	{
871 		pc8801_wram_w(offset,data);
872 		return;
873 	}
874 	else if(offset >= 0xc000 && offset <= 0xffff)
875 	{
876 		if(m_misc_ctrl & 0x40)
877 		{
878 			if(!machine().side_effects_disabled())
879 				m_vram_sel = 3;
880 
881 			if(m_alu_ctrl2 & 0x80)
882 			{
883 				pc8801_alu_w(offset & 0x3fff,data);
884 				return;
885 			}
886 		}
887 
888 		if(m_vram_sel == 3)
889 		{
890 			if(offset >= 0xf000 && offset <= 0xffff && (m_misc_ctrl & 0x10))
891 			{
892 				pc8801_high_wram_w(offset & 0xfff,data);
893 				return;
894 			}
895 
896 			pc8801_wram_w(offset,data);
897 			return;
898 		}
899 
900 		pc8801_gvram_w((offset & 0x3fff) + (0x4000 * m_vram_sel),data);
901 		return;
902 	}
903 }
904 
pc8801_mem(address_map & map)905 void pc8801_state::pc8801_mem(address_map &map)
906 {
907 	map(0x0000, 0xffff).rw(FUNC(pc8801_state::pc8801_mem_r), FUNC(pc8801_state::pc8801_mem_w));
908 }
909 
pc8801_ctrl_r()910 uint8_t pc8801_state::pc8801_ctrl_r()
911 {
912 	/*
913 	11-- ----
914 	--x- ---- vrtc
915 	---x ---- calendar CDO
916 	---- x--- fdc auto-boot DIP-SW
917 	---- -x-- (RS-232C related)
918 	---- --x- monitor refresh rate DIP-SW
919 	---- ---x (pbsy?)
920 	*/
921 	return ioport("CTRL")->read();
922 }
923 
pc8801_ctrl_w(uint8_t data)924 void pc8801_state::pc8801_ctrl_w(uint8_t data)
925 {
926 	/*
927 	x--- ---- SING (buzzer mask?)
928 	-x-- ---- mouse latch (JOP1, routes on OPN sound port A)
929 	--x- ---- beeper
930 	---x ---- ghs mode
931 	---- x--- crtc i/f sync mode
932 	---- -x-- upd1990a clock bit
933 	---- --x- upd1990a strobe bit
934 	---- ---x printer strobe
935 	*/
936 
937 	m_rtc->stb_w((data & 2) >> 1);
938 	m_rtc->clk_w((data & 4) >> 2);
939 
940 	if(((m_device_ctrl_data & 0x20) == 0x00) && ((data & 0x20) == 0x20))
941 		m_beeper->set_state(1);
942 
943 	if(((m_device_ctrl_data & 0x20) == 0x20) && ((data & 0x20) == 0x00))
944 		m_beeper->set_state(0);
945 
946 	if((m_device_ctrl_data & 0x40) != (data & 0x40))
947 	{
948 		attotime new_time = machine().time();
949 
950 		if(m_mouse.phase == 0)
951 		{
952 			m_mouse.x = ioport("MOUSEX")->read();
953 			m_mouse.y = ioport("MOUSEY")->read();
954 		}
955 
956 		if(data & 0x40 && (new_time - m_mouse.time) > attotime::from_hz(900))
957 		{
958 			m_mouse.phase = 0;
959 		}
960 		else
961 		{
962 			m_mouse.phase++;
963 			m_mouse.phase &= 3;
964 		}
965 
966 		m_mouse.time = machine().time();
967 	}
968 
969 	/* TODO: is SING a buzzer mask? Bastard Special relies on this ... */
970 	if(m_device_ctrl_data & 0x80)
971 		m_beeper->set_state(0);
972 
973 	m_device_ctrl_data = data;
974 }
975 
pc8801_ext_rom_bank_r()976 uint8_t pc8801_state::pc8801_ext_rom_bank_r()
977 {
978 	return m_ext_rom_bank;
979 }
980 
pc8801_ext_rom_bank_w(uint8_t data)981 void pc8801_state::pc8801_ext_rom_bank_w(uint8_t data)
982 {
983 	m_ext_rom_bank = data;
984 }
985 
pc8801_pixel_clock(void)986 uint8_t pc8801_state::pc8801_pixel_clock(void)
987 {
988 	int ysize = m_screen->height(); /* TODO: correct condition*/
989 
990 	return (ysize >= 400);
991 }
992 
pc8801_dynamic_res_change(void)993 void pc8801_state::pc8801_dynamic_res_change(void)
994 {
995 	rectangle visarea;
996 	int xsize,ysize,xvis,yvis;
997 	attoseconds_t refresh;;
998 
999 	/* bail out if screen params aren't valid */
1000 	if(!m_crtc.param[0][0] || !m_crtc.param[0][1] || !m_crtc.param[0][2] || !m_crtc.param[0][3])
1001 		return;
1002 
1003 	xvis = screen_width;
1004 	yvis = screen_height * lines_per_char;
1005 	xsize = screen_width + hretrace;
1006 	ysize = screen_height * lines_per_char + vretrace * lines_per_char;
1007 
1008 //  popmessage("H %d V %d (%d x %d) HR %d VR %d (%d %d)\n",xvis,yvis,screen_height,lines_per_char,hretrace,vretrace, xsize,ysize);
1009 
1010 	visarea.set(0, xvis - 1, 0, yvis - 1);
1011 	if(pc8801_pixel_clock())
1012 		refresh = HZ_TO_ATTOSECONDS(PIXEL_CLOCK_24KHz) * (xsize) * ysize;
1013 	else
1014 		refresh = HZ_TO_ATTOSECONDS(PIXEL_CLOCK_15KHz) * (xsize) * ysize;
1015 
1016 	m_screen->configure(xsize, ysize, visarea, refresh);
1017 }
1018 
pc8801_gfx_ctrl_w(uint8_t data)1019 void pc8801_state::pc8801_gfx_ctrl_w(uint8_t data)
1020 {
1021 	/*
1022 	--x- ---- ???
1023 	---x ---- graphic color yes (1) / no (0)
1024 	---- x--- graphic display yes (1) / no (0)
1025 	---- -x-- Basic N (1) / N88 (0)
1026 	---- --x- RAM select yes (1) / no (0)
1027 	---- ---x VRAM 200 lines (1) / 400 lines (0) in 1bpp mode
1028 	*/
1029 
1030 	m_gfx_ctrl = data;
1031 
1032 	pc8801_dynamic_res_change();
1033 }
1034 
pc8801_vram_select_r()1035 uint8_t pc8801_state::pc8801_vram_select_r()
1036 {
1037 	return 0xf8 | ((m_vram_sel == 3) ? 0 : (1 << m_vram_sel));
1038 }
1039 
pc8801_vram_select_w(offs_t offset,uint8_t data)1040 void pc8801_state::pc8801_vram_select_w(offs_t offset, uint8_t data)
1041 {
1042 	m_vram_sel = offset & 3;
1043 }
1044 
1045 #if USE_PROPER_I8214
1046 
i8214_irq_level_w(uint8_t data)1047 void pc8801_state::i8214_irq_level_w(uint8_t data)
1048 {
1049 	if(data & 8)
1050 		m_pic->b_w(7);
1051 	else
1052 		m_pic->b_w(data & 0x07);
1053 }
1054 
i8214_irq_mask_w(uint8_t data)1055 void pc8801_state::i8214_irq_mask_w(uint8_t data)
1056 {
1057 	m_timer_irq_mask = data & 1;
1058 	m_vblank_irq_mask = data & 2;
1059 }
1060 
1061 
1062 #else
pc8801_irq_level_w(uint8_t data)1063 void pc8801_state::pc8801_irq_level_w(uint8_t data)
1064 {
1065 	if(data & 8)
1066 		m_i8214_irq_level = 7;
1067 	else
1068 		m_i8214_irq_level = data & 7;
1069 
1070 //  IRQ_LOG(("%02x LV\n",m_i8214_irq_level));
1071 }
1072 
1073 
pc8801_irq_mask_w(uint8_t data)1074 void pc8801_state::pc8801_irq_mask_w(uint8_t data)
1075 {
1076 	m_timer_irq_mask = data & 1;
1077 	m_vrtc_irq_mask = data & 2;
1078 
1079 	if(m_timer_irq_mask == 0)
1080 		m_timer_irq_latch = 0;
1081 
1082 	if(m_vrtc_irq_mask == 0)
1083 		m_vrtc_irq_latch = 0;
1084 
1085 	if(m_timer_irq_latch == 0 && m_vrtc_irq_latch == 0 && m_sound_irq_latch == 0)
1086 		m_maincpu->set_input_line(0,CLEAR_LINE);
1087 
1088 //  IRQ_LOG(("%02x MASK (%02x %02x)\n",data,m_timer_irq_latch,m_vrtc_irq_latch));
1089 
1090 	//if(data & 4)
1091 	//  printf("IRQ mask %02x\n",data);
1092 }
1093 #endif
1094 
pc8801_window_bank_r()1095 uint8_t pc8801_state::pc8801_window_bank_r()
1096 {
1097 	return m_window_offset_bank;
1098 }
1099 
pc8801_window_bank_w(uint8_t data)1100 void pc8801_state::pc8801_window_bank_w(uint8_t data)
1101 {
1102 	m_window_offset_bank = data;
1103 }
1104 
pc8801_window_bank_inc_w(uint8_t data)1105 void pc8801_state::pc8801_window_bank_inc_w(uint8_t data)
1106 {
1107 	m_window_offset_bank++;
1108 	m_window_offset_bank&=0xff;
1109 }
1110 
pc8801_misc_ctrl_r()1111 uint8_t pc8801_state::pc8801_misc_ctrl_r()
1112 {
1113 	return m_misc_ctrl;
1114 }
1115 
pc8801_misc_ctrl_w(uint8_t data)1116 void pc8801_state::pc8801_misc_ctrl_w(uint8_t data)
1117 {
1118 	/*
1119 	x--- ---- sound irq mask, active low
1120 	--x- ---- analog (1) / digital (0) palette select
1121 	*/
1122 
1123 	m_misc_ctrl = data;
1124 
1125 	#if USE_PROPER_I8214
1126 	m_sound_irq_mask = ((data & 0x80) == 0);
1127 	#else
1128 	m_sound_irq_mask = ((data & 0x80) == 0);
1129 
1130 	if(m_sound_irq_mask == 0)
1131 		m_sound_irq_latch = 0;
1132 
1133 	if(m_timer_irq_latch == 0 && m_vrtc_irq_latch == 0 && m_sound_irq_latch == 0)
1134 		m_maincpu->set_input_line(0,CLEAR_LINE);
1135 
1136 	if(m_sound_irq_mask && m_sound_irq_pending)
1137 	{
1138 		m_maincpu->set_input_line(0,HOLD_LINE);
1139 		m_sound_irq_latch = 1;
1140 		m_sound_irq_pending = 0;
1141 	}
1142 
1143 	#endif
1144 }
1145 
pc8801_bgpal_w(uint8_t data)1146 void pc8801_state::pc8801_bgpal_w(uint8_t data)
1147 {
1148 	if(data)
1149 		printf("BG Pal %02x\n",data);
1150 }
1151 
pc8801_palram_w(offs_t offset,uint8_t data)1152 void pc8801_state::pc8801_palram_w(offs_t offset, uint8_t data)
1153 {
1154 	if(m_misc_ctrl & 0x20) //analog palette
1155 	{
1156 		if((data & 0x40) == 0)
1157 		{
1158 			m_palram[offset].b = data & 0x7;
1159 			m_palram[offset].r = (data & 0x38) >> 3;
1160 		}
1161 		else
1162 		{
1163 			m_palram[offset].g = data & 0x7;
1164 		}
1165 	}
1166 	else //digital palette
1167 	{
1168 		m_palram[offset].b = data & 1 ? 7 : 0;
1169 		m_palram[offset].r = data & 2 ? 7 : 0;
1170 		m_palram[offset].g = data & 4 ? 7 : 0;
1171 	}
1172 
1173 	m_palette->set_pen_color(offset, pal3bit(m_palram[offset].r), pal3bit(m_palram[offset].g), pal3bit(m_palram[offset].b));
1174 }
1175 
pc8801_layer_masking_w(uint8_t data)1176 void pc8801_state::pc8801_layer_masking_w(uint8_t data)
1177 {
1178 	/*
1179 	---- x--- green gvram masked flag
1180 	---- -x-- red gvram masked flag
1181 	---- --x- blue gvram masked flag
1182 	---- ---x text vram masked
1183 	*/
1184 
1185 	m_layer_mask = data;
1186 }
1187 
pc8801_crtc_param_r()1188 uint8_t pc8801_state::pc8801_crtc_param_r()
1189 {
1190 	printf("CRTC param reading\n");
1191 	return 0xff;
1192 }
1193 
pc88_crtc_param_w(uint8_t data)1194 void pc8801_state::pc88_crtc_param_w(uint8_t data)
1195 {
1196 	if(m_crtc.param_count < 5)
1197 	{
1198 		m_crtc.param[m_crtc.cmd][m_crtc.param_count] = data;
1199 		if(m_crtc.cmd == 0)
1200 			pc8801_dynamic_res_change();
1201 
1202 		m_crtc.param_count++;
1203 	}
1204 }
1205 
pc8801_crtc_status_r()1206 uint8_t pc8801_state::pc8801_crtc_status_r()
1207 {
1208 	/*
1209 	---x ---- video enable
1210 	---- x--- DMA is running
1211 	---- -x-- special control character IRQ
1212 	---- --x- indication end IRQ
1213 	---- ---x light pen input
1214 	*/
1215 
1216 	return m_crtc.status;
1217 }
1218 
1219 #if 0
1220 static const char *const crtc_command[] =
1221 {
1222 	"Reset / Stop Display",             // 0
1223 	"Start Display",                    // 1
1224 	"Set IRQ MASK",                     // 2
1225 	"Read Light Pen",                   // 3
1226 	"Load Cursor Position",             // 4
1227 	"Reset IRQ",                        // 5
1228 	"Reset Counters",                   // 6
1229 	"Read Status"                       // 7
1230 };
1231 #endif
1232 
pc88_crtc_cmd_w(uint8_t data)1233 void pc8801_state::pc88_crtc_cmd_w(uint8_t data)
1234 {
1235 	m_crtc.cmd = (data & 0xe0) >> 5;
1236 	m_crtc.param_count = 0;
1237 
1238 	switch(m_crtc.cmd)
1239 	{
1240 		case 0:  // reset CRTC
1241 			m_crtc.status &= (~0x16);
1242 			break;
1243 		case 1:  // start display
1244 			m_crtc.status |= 0x10;
1245 			m_crtc.status &= (~0x08);
1246 			m_crtc.inverse = data & 1;
1247 
1248 			if(data & 1) /* Ink Pot uses it, but I want another test case before removing this log */
1249 				printf("CRTC inverse mode ON\n");
1250 			break;
1251 		case 2:  // set irq mask
1252 			m_crtc.irq_mask = data & 3;
1253 			break;
1254 		case 3:  // read light pen
1255 			m_crtc.status &= (~0x01);
1256 			break;
1257 		case 4:  // load cursor position ON/OFF
1258 			m_crtc.cursor_on = data & 1;
1259 			break;
1260 		case 5:  // reset IRQ
1261 		case 6:  // reset counters
1262 			m_crtc.status &= (~0x06);
1263 			break;
1264 	}
1265 
1266 	//if((data >> 5) != 4)
1267 	//  printf("CRTC cmd %s polled %02x\n",crtc_command[data >> 5],data & 0x1f);
1268 }
1269 
pc8801_dmac_r(offs_t offset)1270 uint8_t pc8801_state::pc8801_dmac_r(offs_t offset)
1271 {
1272 	printf("DMAC R %08x\n",offset);
1273 	return 0xff;
1274 }
1275 
pc8801_dmac_w(offs_t offset,uint8_t data)1276 void pc8801_state::pc8801_dmac_w(offs_t offset, uint8_t data)
1277 {
1278 	if(offset & 1)
1279 		m_dma_counter[offset >> 1] = (m_dmac_ff) ? (m_dma_counter[offset >> 1]&0xff)|(data<<8) : (m_dma_counter[offset >> 1]&0xff00)|(data&0xff);
1280 	else
1281 		m_dma_address[offset >> 1] = (m_dmac_ff) ? (m_dma_address[offset >> 1]&0xff)|(data<<8) : (m_dma_address[offset >> 1]&0xff00)|(data&0xff);
1282 
1283 	m_dmac_ff ^= 1;
1284 }
1285 
pc8801_dmac_status_r()1286 uint8_t pc8801_state::pc8801_dmac_status_r()
1287 {
1288 	printf("DMAC R STATUS\n");
1289 	return 0xff;
1290 }
1291 
pc8801_dmac_mode_w(uint8_t data)1292 void pc8801_state::pc8801_dmac_mode_w(uint8_t data)
1293 {
1294 	m_dmac_mode = data;
1295 	m_dmac_ff = 0;
1296 
1297 	if(data != 0xe4 && data != 0xa0 && data != 0xc4 && data != 0x80 && data != 0x00)
1298 		printf("%02x DMAC mode\n",data);
1299 }
1300 
pc8801_extram_mode_r()1301 uint8_t pc8801_state::pc8801_extram_mode_r()
1302 {
1303 	return (m_extram_mode ^ 0x11) | 0xee;
1304 }
1305 
pc8801_extram_mode_w(uint8_t data)1306 void pc8801_state::pc8801_extram_mode_w(uint8_t data)
1307 {
1308 	/*
1309 	---x ---- Write EXT RAM access at 0x0000 - 0x7fff
1310 	---- ---x Read EXT RAM access at 0x0000 - 0x7fff
1311 	*/
1312 
1313 	m_extram_mode = data & 0x11;
1314 }
1315 
pc8801_extram_bank_r()1316 uint8_t pc8801_state::pc8801_extram_bank_r()
1317 {
1318 	return m_extram_bank;
1319 }
1320 
pc8801_extram_bank_w(uint8_t data)1321 void pc8801_state::pc8801_extram_bank_w(uint8_t data)
1322 {
1323 	m_extram_bank = data;
1324 }
1325 
pc8801_alu_ctrl1_w(uint8_t data)1326 void pc8801_state::pc8801_alu_ctrl1_w(uint8_t data)
1327 {
1328 	m_alu_ctrl1 = data;
1329 }
1330 
pc8801_alu_ctrl2_w(uint8_t data)1331 void pc8801_state::pc8801_alu_ctrl2_w(uint8_t data)
1332 {
1333 	m_alu_ctrl2 = data;
1334 }
1335 
pc8801_pcg8100_w(offs_t offset,uint8_t data)1336 void pc8801_state::pc8801_pcg8100_w(offs_t offset, uint8_t data)
1337 {
1338 	if(data)
1339 		printf("Write to PCG-8100 %02x %02x\n",offset,data);
1340 }
1341 
pc8801_txt_cmt_ctrl_w(uint8_t data)1342 void pc8801_state::pc8801_txt_cmt_ctrl_w(uint8_t data)
1343 {
1344 	/* bits 2 to 5 are cmt related */
1345 
1346 	m_txt_width = data & 1;
1347 	m_txt_color = data & 2;
1348 
1349 	m_cassette->change_state(BIT(data,3) ? CASSETTE_MOTOR_ENABLED : CASSETTE_MOTOR_DISABLED, CASSETTE_MASK_MOTOR);
1350 }
1351 
1352 
pc8801_kanji_r(offs_t offset)1353 uint8_t pc8801_state::pc8801_kanji_r(offs_t offset)
1354 {
1355 	if((offset & 2) == 0)
1356 		return m_kanji_rom[m_knj_addr[0]*2+((offset & 1) ^ 1)];
1357 
1358 	return 0xff;
1359 }
1360 
pc8801_kanji_w(offs_t offset,uint8_t data)1361 void pc8801_state::pc8801_kanji_w(offs_t offset, uint8_t data)
1362 {
1363 	if((offset & 2) == 0)
1364 		m_knj_addr[0] = ((offset & 1) == 0) ? ((m_knj_addr[0]&0xff00)|(data&0xff)) : ((m_knj_addr[0]&0x00ff)|(data<<8));
1365 }
1366 
pc8801_kanji_lv2_r(offs_t offset)1367 uint8_t pc8801_state::pc8801_kanji_lv2_r(offs_t offset)
1368 {
1369 	if((offset & 2) == 0)
1370 		return m_kanji_rom[m_knj_addr[1]*2+((offset & 1) ^ 1)];
1371 
1372 	return 0xff;
1373 }
1374 
pc8801_kanji_lv2_w(offs_t offset,uint8_t data)1375 void pc8801_state::pc8801_kanji_lv2_w(offs_t offset, uint8_t data)
1376 {
1377 	if((offset & 2) == 0)
1378 		m_knj_addr[1] = ((offset & 1) == 0) ? ((m_knj_addr[1]&0xff00)|(data&0xff)) : ((m_knj_addr[1]&0x00ff)|(data<<8));
1379 }
1380 
pc8801_dic_bank_w(uint8_t data)1381 void pc8801_state::pc8801_dic_bank_w(uint8_t data)
1382 {
1383 	printf("JISHO BANK = %02x\n",data);
1384 	if(m_has_dictionary)
1385 		m_dic_bank = data  & 0x1f;
1386 }
1387 
pc8801_dic_ctrl_w(uint8_t data)1388 void pc8801_state::pc8801_dic_ctrl_w(uint8_t data)
1389 {
1390 	printf("JISHO CTRL = %02x\n",data);
1391 	if(m_has_dictionary)
1392 		m_dic_ctrl = (data ^ 1) & 1;
1393 }
1394 
pc8801_cdrom_r()1395 uint8_t pc8801_state::pc8801_cdrom_r()
1396 {
1397 	//printf("CD-ROM read [%02x]\n",offset);
1398 
1399 	//if(m_has_cdrom)
1400 	//  return m_cdrom_reg[offset];
1401 
1402 	return 0xff;
1403 }
1404 
pc8801_cdrom_w(offs_t offset,uint8_t data)1405 void pc8801_state::pc8801_cdrom_w(offs_t offset, uint8_t data)
1406 {
1407 	/*
1408 	[9] ---x ---- CD-ROM BIOS bank
1409 	    ---- ---x CD-ROM E-ROM bank (?)
1410 	*/
1411 	//printf("CD-ROM write %02x -> [%02x]\n",data,offset);
1412 
1413 	if(m_has_cdrom)
1414 		m_cdrom_reg[offset] = data;
1415 }
1416 
pc8801_cpuclock_r()1417 uint8_t pc8801_state::pc8801_cpuclock_r()
1418 {
1419 	if(m_has_clock_speed)
1420 		return 0x10 | m_clock_setting;
1421 
1422 	return 0xff;
1423 }
1424 
pc8801_baudrate_r()1425 uint8_t pc8801_state::pc8801_baudrate_r()
1426 {
1427 	if(m_has_clock_speed)
1428 		return 0xf0 | m_baudrate_val;
1429 
1430 	return 0xff;
1431 }
1432 
pc8801_baudrate_w(uint8_t data)1433 void pc8801_state::pc8801_baudrate_w(uint8_t data)
1434 {
1435 	if(m_has_clock_speed)
1436 		m_baudrate_val = data & 0xf;
1437 }
1438 
pc8801_rtc_w(uint8_t data)1439 void pc8801_state::pc8801_rtc_w(uint8_t data)
1440 {
1441 	m_rtc->c0_w((data & 1) >> 0);
1442 	m_rtc->c1_w((data & 2) >> 1);
1443 	m_rtc->c2_w((data & 4) >> 2);
1444 	m_rtc->data_in_w((data & 8) >> 3);
1445 
1446 	/* TODO: remaining bits */
1447 }
1448 
pc8801_sound_board_r(offs_t offset)1449 uint8_t pc8801_state::pc8801_sound_board_r(offs_t offset)
1450 {
1451 	if(m_has_opna)
1452 		return m_opna->read(offset);
1453 
1454 	return (offset & 2) ? 0xff : m_opn->read(offset);
1455 }
1456 
pc8801_sound_board_w(offs_t offset,uint8_t data)1457 void pc8801_state::pc8801_sound_board_w(offs_t offset, uint8_t data)
1458 {
1459 	if(m_has_opna)
1460 		m_opna->write(offset,data);
1461 	else if((offset & 2) == 0)
1462 		m_opn->write(offset, data);
1463 }
1464 
pc8801_opna_r(offs_t offset)1465 uint8_t pc8801_state::pc8801_opna_r(offs_t offset)
1466 {
1467 	if(m_has_opna && (offset & 2) == 0)
1468 		return m_opna->read((offset & 1) | ((offset & 4) >> 1));
1469 
1470 	return 0xff;
1471 }
1472 
pc8801_opna_w(offs_t offset,uint8_t data)1473 void pc8801_state::pc8801_opna_w(offs_t offset, uint8_t data)
1474 {
1475 	if(m_has_opna && (offset & 2) == 0)
1476 		m_opna->write((offset & 1) | ((offset & 4) >> 1),data);
1477 	else if(m_has_opna && offset == 2)
1478 	{
1479 		m_sound_irq_mask = ((data & 0x80) == 0);
1480 
1481 		if(m_sound_irq_mask == 0)
1482 			m_sound_irq_latch = 0;
1483 
1484 		if(m_timer_irq_latch == 0 && m_vrtc_irq_latch == 0 && m_sound_irq_latch == 0)
1485 			m_maincpu->set_input_line(0,CLEAR_LINE);
1486 
1487 		if(m_sound_irq_mask && m_sound_irq_pending)
1488 		{
1489 			m_maincpu->set_input_line(0,HOLD_LINE);
1490 			m_sound_irq_latch = 1;
1491 			m_sound_irq_pending = 0;
1492 		}
1493 	}
1494 }
1495 
pc8801_unk_r()1496 uint8_t pc8801_state::pc8801_unk_r()
1497 {
1498 	printf("Read port 0x33\n");
1499 	return 0xff;
1500 }
1501 
pc8801_unk_w(uint8_t data)1502 void pc8801_state::pc8801_unk_w(uint8_t data)
1503 {
1504 	printf("Write port 0x33\n");
1505 }
1506 
pc8801_io(address_map & map)1507 void pc8801_state::pc8801_io(address_map &map)
1508 {
1509 	map.global_mask(0xff);
1510 	map.unmap_value_high();
1511 	map(0x00, 0x00).portr("KEY0");
1512 	map(0x01, 0x01).portr("KEY1");
1513 	map(0x02, 0x02).portr("KEY2");
1514 	map(0x03, 0x03).portr("KEY3");
1515 	map(0x04, 0x04).portr("KEY4");
1516 	map(0x05, 0x05).portr("KEY5");
1517 	map(0x06, 0x06).portr("KEY6");
1518 	map(0x07, 0x07).portr("KEY7");
1519 	map(0x08, 0x08).portr("KEY8");
1520 	map(0x09, 0x09).portr("KEY9");
1521 	map(0x0a, 0x0a).portr("KEY10");
1522 	map(0x0b, 0x0b).portr("KEY11");
1523 	map(0x0c, 0x0c).portr("KEY12");
1524 	map(0x0d, 0x0d).portr("KEY13");
1525 	map(0x0e, 0x0e).portr("KEY14");
1526 	map(0x0f, 0x0f).portr("KEY15");
1527 	map(0x00, 0x02).w(FUNC(pc8801_state::pc8801_pcg8100_w));
1528 	map(0x10, 0x10).w(FUNC(pc8801_state::pc8801_rtc_w));
1529 	map(0x20, 0x21).mirror(0x0e).rw(I8251_TAG, FUNC(i8251_device::read), FUNC(i8251_device::write)); /* RS-232C and CMT */
1530 	map(0x30, 0x30).portr("DSW1").w(FUNC(pc8801_state::pc8801_txt_cmt_ctrl_w));
1531 	map(0x31, 0x31).portr("DSW2").w(FUNC(pc8801_state::pc8801_gfx_ctrl_w));
1532 	map(0x32, 0x32).rw(FUNC(pc8801_state::pc8801_misc_ctrl_r), FUNC(pc8801_state::pc8801_misc_ctrl_w));
1533 	map(0x33, 0x33).rw(FUNC(pc8801_state::pc8801_unk_r), FUNC(pc8801_state::pc8801_unk_w));
1534 	map(0x34, 0x34).w(FUNC(pc8801_state::pc8801_alu_ctrl1_w));
1535 	map(0x35, 0x35).w(FUNC(pc8801_state::pc8801_alu_ctrl2_w));
1536 	map(0x40, 0x40).rw(FUNC(pc8801_state::pc8801_ctrl_r), FUNC(pc8801_state::pc8801_ctrl_w));
1537 	map(0x44, 0x47).rw(FUNC(pc8801_state::pc8801_sound_board_r), FUNC(pc8801_state::pc8801_sound_board_w)); /* OPN / OPNA ports */
1538 	map(0x50, 0x50).rw(FUNC(pc8801_state::pc8801_crtc_param_r), FUNC(pc8801_state::pc88_crtc_param_w));
1539 	map(0x51, 0x51).rw(FUNC(pc8801_state::pc8801_crtc_status_r), FUNC(pc8801_state::pc88_crtc_cmd_w));
1540 	map(0x52, 0x52).w(FUNC(pc8801_state::pc8801_bgpal_w));
1541 	map(0x53, 0x53).w(FUNC(pc8801_state::pc8801_layer_masking_w));
1542 	map(0x54, 0x5b).w(FUNC(pc8801_state::pc8801_palram_w));
1543 	map(0x5c, 0x5c).r(FUNC(pc8801_state::pc8801_vram_select_r));
1544 	map(0x5c, 0x5f).w(FUNC(pc8801_state::pc8801_vram_select_w));
1545 	map(0x60, 0x67).rw(FUNC(pc8801_state::pc8801_dmac_r), FUNC(pc8801_state::pc8801_dmac_w));
1546 	map(0x68, 0x68).rw(FUNC(pc8801_state::pc8801_dmac_status_r), FUNC(pc8801_state::pc8801_dmac_mode_w));
1547 	map(0x6e, 0x6e).r(FUNC(pc8801_state::pc8801_cpuclock_r));
1548 	map(0x6f, 0x6f).rw(FUNC(pc8801_state::pc8801_baudrate_r), FUNC(pc8801_state::pc8801_baudrate_w));
1549 	map(0x70, 0x70).rw(FUNC(pc8801_state::pc8801_window_bank_r), FUNC(pc8801_state::pc8801_window_bank_w));
1550 	map(0x71, 0x71).rw(FUNC(pc8801_state::pc8801_ext_rom_bank_r), FUNC(pc8801_state::pc8801_ext_rom_bank_w));
1551 	map(0x78, 0x78).w(FUNC(pc8801_state::pc8801_window_bank_inc_w));
1552 	map(0x90, 0x9f).rw(FUNC(pc8801_state::pc8801_cdrom_r), FUNC(pc8801_state::pc8801_cdrom_w));
1553 //  map(0xa0, 0xa3).noprw();                                     /* music & network */
1554 	map(0xa8, 0xad).rw(FUNC(pc8801_state::pc8801_opna_r), FUNC(pc8801_state::pc8801_opna_w));  /* second sound board */
1555 //  map(0xb4, 0xb5).noprw();                                     /* Video art board */
1556 //  map(0xc1, 0xc1).noprw();                                     /* (unknown) */
1557 //  map(0xc2, 0xcf).noprw();                                     /* music */
1558 //  map(0xd0, 0xd7).noprw();                                     /* music & GP-IB */
1559 //  map(0xd8, 0xd8).noprw();                                     /* GP-IB */
1560 //  map(0xdc, 0xdf).noprw();                                     /* MODEM */
1561 	map(0xe2, 0xe2).rw(FUNC(pc8801_state::pc8801_extram_mode_r), FUNC(pc8801_state::pc8801_extram_mode_w));            /* expand RAM mode */
1562 	map(0xe3, 0xe3).rw(FUNC(pc8801_state::pc8801_extram_bank_r), FUNC(pc8801_state::pc8801_extram_bank_w));            /* expand RAM bank */
1563 #if USE_PROPER_I8214
1564 	map(0xe4, 0xe4).w(FUNC(pc8801_state::i8214_irq_level_w));
1565 	map(0xe6, 0xe6).w(FUNC(pc8801_state::i8214_irq_mask_w));
1566 #else
1567 	map(0xe4, 0xe4).w(FUNC(pc8801_state::pc8801_irq_level_w));
1568 	map(0xe6, 0xe6).w(FUNC(pc8801_state::pc8801_irq_mask_w));
1569 #endif
1570 //  map(0xe7, 0xe7).noprw();                                     /* Arcus writes here, almost likely to be a mirror of above */
1571 	map(0xe8, 0xeb).rw(FUNC(pc8801_state::pc8801_kanji_r), FUNC(pc8801_state::pc8801_kanji_w));
1572 	map(0xec, 0xef).rw(FUNC(pc8801_state::pc8801_kanji_lv2_r), FUNC(pc8801_state::pc8801_kanji_lv2_w));
1573 	map(0xf0, 0xf0).w(FUNC(pc8801_state::pc8801_dic_bank_w));
1574 	map(0xf1, 0xf1).w(FUNC(pc8801_state::pc8801_dic_ctrl_w));
1575 //  map(0xf3, 0xf3).noprw();                                     /* DMA floppy (unknown) */
1576 //  map(0xf4, 0xf7).noprw();                                     /* DMA 5'floppy (may be not released) */
1577 //  map(0xf8, 0xfb).noprw();                                     /* DMA 8'floppy (unknown) */
1578 	map(0xfc, 0xff).rw("d8255_master", FUNC(i8255_device::read), FUNC(i8255_device::write));
1579 }
1580 
cpu_8255_c_r()1581 uint8_t pc8801_state::cpu_8255_c_r()
1582 {
1583 //  machine().scheduler().synchronize(); // force resync
1584 
1585 	return m_i8255_1_pc >> 4;
1586 }
1587 
cpu_8255_c_w(uint8_t data)1588 void pc8801_state::cpu_8255_c_w(uint8_t data)
1589 {
1590 //  machine().scheduler().synchronize(); // force resync
1591 
1592 	m_i8255_0_pc = data;
1593 }
1594 
1595 
fdc_8255_c_r()1596 uint8_t pc8801_state::fdc_8255_c_r()
1597 {
1598 //  machine().scheduler().synchronize(); // force resync
1599 
1600 	return m_i8255_0_pc >> 4;
1601 }
1602 
fdc_8255_c_w(uint8_t data)1603 void pc8801_state::fdc_8255_c_w(uint8_t data)
1604 {
1605 //  machine().scheduler().synchronize(); // force resync
1606 
1607 	m_i8255_1_pc = data;
1608 }
1609 
pc8801fdc_mem(address_map & map)1610 void pc8801_state::pc8801fdc_mem(address_map &map)
1611 {
1612 	map(0x0000, 0x1fff).rom();
1613 	map(0x4000, 0x7fff).ram();
1614 }
1615 
TIMER_CALLBACK_MEMBER(pc8801_state::pc8801fd_upd765_tc_to_zero)1616 TIMER_CALLBACK_MEMBER(pc8801_state::pc8801fd_upd765_tc_to_zero)
1617 {
1618 	//printf("0\n");
1619 	m_fdc->tc_w(false);
1620 }
1621 
upd765_mc_w(uint8_t data)1622 void pc8801_state::upd765_mc_w(uint8_t data)
1623 {
1624 	m_fdd[0]->get_device()->mon_w(!(data & 1));
1625 	m_fdd[1]->get_device()->mon_w(!(data & 2));
1626 }
1627 
upd765_tc_r()1628 uint8_t pc8801_state::upd765_tc_r()
1629 {
1630 	//printf("%04x 1\n",m_fdccpu->pc());
1631 
1632 	m_fdc->tc_w(true);
1633 	//TODO: I'm not convinced that this works correctly with current hook-up ... 1000 usec is needed by Aploon, a bigger value breaks Alpha.
1634 	//OTOH, 50 seems more than enough for the new upd...
1635 	machine().scheduler().timer_set(attotime::from_usec(50), timer_expired_delegate(FUNC(pc8801_state::pc8801fd_upd765_tc_to_zero),this));
1636 	return 0xff; // value is meaningless
1637 }
1638 
fdc_irq_vector_w(uint8_t data)1639 void pc8801_state::fdc_irq_vector_w(uint8_t data)
1640 {
1641 	popmessage("Write to FDC IRQ vector I/O %02x, contact MESSdev\n",data);
1642 	m_fdc_irq_opcode = data;
1643 }
1644 
fdc_drive_mode_w(uint8_t data)1645 void pc8801_state::fdc_drive_mode_w(uint8_t data)
1646 {
1647 	logerror("FDC drive mode %02x\n", data);
1648 	m_fdd[0]->get_device()->set_rpm(data & 0x01 ? 360 : 300);
1649 	m_fdd[1]->get_device()->set_rpm(data & 0x02 ? 360 : 300);
1650 
1651 	m_fdc->set_rate(data & 0x20 ? 500000 : 250000);
1652 }
1653 
pc8801fdc_io(address_map & map)1654 void pc8801_state::pc8801fdc_io(address_map &map)
1655 {
1656 	map.global_mask(0xff);
1657 	map(0xf0, 0xf0).w(FUNC(pc8801_state::fdc_irq_vector_w)); // Interrupt Opcode Port
1658 	map(0xf4, 0xf4).w(FUNC(pc8801_state::fdc_drive_mode_w)); // Drive mode, 2d, 2dd, 2hd
1659 	map(0xf7, 0xf7).nopw(); // printer port output
1660 	map(0xf8, 0xf8).rw(FUNC(pc8801_state::upd765_tc_r), FUNC(pc8801_state::upd765_mc_w)); // (R) Terminal Count Port (W) Motor Control Port
1661 	map(0xfa, 0xfb).m(m_fdc, FUNC(upd765a_device::map));
1662 	map(0xfc, 0xff).rw("d8255_slave", FUNC(i8255_device::read), FUNC(i8255_device::write));
1663 }
1664 
1665 /* Input Ports */
1666 
1667 /* 2008-05 FP:
1668 Small note about the strange default mapping of function keys:
1669 the top line of keys in PC8801 keyboard is as follows
1670 [STOP][COPY]      [F1][F2][F3][F4][F5]      [ROLL UP][ROLL DOWN]
1671 Therefore, in Full Emulation mode, "F1" goes to 'F3' and so on
1672 
1673 Also, the Keypad has 16 keys, making impossible to map it in a satisfactory
1674 way to a PC keypad. Therefore, default settings for these keys in Full
1675 Emulation are currently based on the effect of the key rather than on
1676 their real position
1677 
1678 About natural keyboards: currently,
1679 - "Stop" is mapped to 'Pause'
1680 - "Copy" is mapped to 'Print Screen'
1681 - "Kana" is mapped to 'F6'
1682 - "Grph" is mapped to 'F7'
1683 - "Roll Up" and "Roll Down" are mapped to 'Page Up' and 'Page Down'
1684 - "Help" is mapped to 'F8'
1685  */
1686 
1687 static INPUT_PORTS_START( pc8001 )
1688 	PORT_START("KEY0")
1689 	PORT_BIT (0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0_PAD)       PORT_CHAR(UCHAR_MAMEKEY(0_PAD))
1690 	PORT_BIT (0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1_PAD)       PORT_CHAR(UCHAR_MAMEKEY(1_PAD))
1691 	PORT_BIT (0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2_PAD)       PORT_CHAR(UCHAR_MAMEKEY(2_PAD))
1692 	PORT_BIT (0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3_PAD)       PORT_CHAR(UCHAR_MAMEKEY(3_PAD))
1693 	PORT_BIT (0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4_PAD)       PORT_CHAR(UCHAR_MAMEKEY(4_PAD))
1694 	PORT_BIT (0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5_PAD)       PORT_CHAR(UCHAR_MAMEKEY(5_PAD))
1695 	PORT_BIT (0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6_PAD)       PORT_CHAR(UCHAR_MAMEKEY(6_PAD))
1696 	PORT_BIT (0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7_PAD)       PORT_CHAR(UCHAR_MAMEKEY(7_PAD))
1697 
1698 	PORT_START("KEY1")
1699 	PORT_BIT (0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8_PAD)       PORT_CHAR(UCHAR_MAMEKEY(8_PAD))
1700 	PORT_BIT (0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9_PAD)       PORT_CHAR(UCHAR_MAMEKEY(9_PAD))
1701 	PORT_BIT (0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ASTERISK)    PORT_CHAR(UCHAR_MAMEKEY(ASTERISK))
1702 	PORT_BIT (0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_PLUS_PAD)    PORT_CHAR(UCHAR_MAMEKEY(PLUS_PAD))
1703 	PORT_BIT (0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_PGUP)        PORT_CHAR(UCHAR_MAMEKEY(EQUALS_PAD))
1704 	PORT_BIT (0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_PGDN)        PORT_CHAR(UCHAR_MAMEKEY(COMMA_PAD))
1705 	PORT_BIT (0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_DEL_PAD)     PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD))
1706 	PORT_BIT (0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Return") PORT_CODE(KEYCODE_ENTER) PORT_CODE(KEYCODE_ENTER_PAD) PORT_CHAR(13)
1707 
1708 	PORT_START("KEY2")
1709 	PORT_BIT (0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE)   PORT_CHAR('@')
1710 	PORT_BIT (0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_A)           PORT_CHAR('a') PORT_CHAR('A')
1711 	PORT_BIT (0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_B)           PORT_CHAR('b') PORT_CHAR('B')
1712 	PORT_BIT (0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_C)           PORT_CHAR('c') PORT_CHAR('C')
1713 	PORT_BIT (0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_D)           PORT_CHAR('d') PORT_CHAR('D')
1714 	PORT_BIT (0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_E)           PORT_CHAR('e') PORT_CHAR('E')
1715 	PORT_BIT (0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F)           PORT_CHAR('f') PORT_CHAR('F')
1716 	PORT_BIT (0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_G)           PORT_CHAR('g') PORT_CHAR('G')
1717 
1718 	PORT_START("KEY3")
1719 	PORT_BIT (0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_H)           PORT_CHAR('h') PORT_CHAR('H')
1720 	PORT_BIT (0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_I)           PORT_CHAR('i') PORT_CHAR('I')
1721 	PORT_BIT (0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_J)           PORT_CHAR('j') PORT_CHAR('J')
1722 	PORT_BIT (0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_K)           PORT_CHAR('k') PORT_CHAR('K')
1723 	PORT_BIT (0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_L)           PORT_CHAR('l') PORT_CHAR('L')
1724 	PORT_BIT (0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M)           PORT_CHAR('m') PORT_CHAR('M')
1725 	PORT_BIT (0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_N)           PORT_CHAR('n') PORT_CHAR('N')
1726 	PORT_BIT (0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_O)           PORT_CHAR('o') PORT_CHAR('O')
1727 
1728 	PORT_START("KEY4")
1729 	PORT_BIT (0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_P)           PORT_CHAR('p') PORT_CHAR('P')
1730 	PORT_BIT (0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q)           PORT_CHAR('q') PORT_CHAR('Q')
1731 	PORT_BIT (0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_R)           PORT_CHAR('r') PORT_CHAR('R')
1732 	PORT_BIT (0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_S)           PORT_CHAR('s') PORT_CHAR('S')
1733 	PORT_BIT (0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_T)           PORT_CHAR('t') PORT_CHAR('T')
1734 	PORT_BIT (0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_U)           PORT_CHAR('u') PORT_CHAR('U')
1735 	PORT_BIT (0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_V)           PORT_CHAR('v') PORT_CHAR('V')
1736 	PORT_BIT (0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_W)           PORT_CHAR('w') PORT_CHAR('W')
1737 
1738 	PORT_START("KEY5")
1739 	PORT_BIT (0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_X)           PORT_CHAR('x') PORT_CHAR('X')
1740 	PORT_BIT (0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y)           PORT_CHAR('y') PORT_CHAR('Y')
1741 	PORT_BIT (0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z)           PORT_CHAR('z') PORT_CHAR('Z')
1742 	PORT_BIT (0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE)  PORT_CHAR('[') PORT_CHAR('{')
1743 	PORT_BIT (0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH2)  PORT_CHAR(0xA5) PORT_CHAR('|')
1744 	PORT_BIT (0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH)   PORT_CHAR(']') PORT_CHAR('}')
1745 	PORT_BIT (0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS)      PORT_CHAR('^')
1746 	PORT_BIT (0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS)       PORT_CHAR('-') PORT_CHAR('=')
1747 
1748 	PORT_START("KEY6")
1749 	PORT_BIT (0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0)           PORT_CHAR('0')
1750 	PORT_BIT (0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1)           PORT_CHAR('1') PORT_CHAR('!')
1751 	PORT_BIT (0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2)           PORT_CHAR('2') PORT_CHAR('"')
1752 	PORT_BIT (0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3)           PORT_CHAR('3') PORT_CHAR('#')
1753 	PORT_BIT (0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4)           PORT_CHAR('4') PORT_CHAR('$')
1754 	PORT_BIT (0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5)           PORT_CHAR('5') PORT_CHAR('%')
1755 	PORT_BIT (0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6)           PORT_CHAR('6') PORT_CHAR('&')
1756 	PORT_BIT (0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7)           PORT_CHAR('7') PORT_CHAR('\'')
1757 
1758 	PORT_START("KEY7")
1759 	PORT_BIT (0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8)           PORT_CHAR('8') PORT_CHAR('(')
1760 	PORT_BIT (0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9)           PORT_CHAR('9') PORT_CHAR(')')
1761 	PORT_BIT (0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE)       PORT_CHAR(':') PORT_CHAR('*')
1762 	PORT_BIT (0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON)       PORT_CHAR(';') PORT_CHAR('+')
1763 	PORT_BIT (0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA)       PORT_CHAR(',') PORT_CHAR('<')
1764 	PORT_BIT (0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP)        PORT_CHAR('.') PORT_CHAR('>')
1765 	PORT_BIT (0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH)       PORT_CHAR('/') PORT_CHAR('?')
1766 	PORT_BIT (0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("  _") PORT_CODE(KEYCODE_DEL)            PORT_CHAR(0) PORT_CHAR('_')
1767 
1768 	PORT_START("KEY8")
1769 	PORT_BIT (0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Clr Home") PORT_CODE(KEYCODE_HOME)      PORT_CHAR(UCHAR_MAMEKEY(HOME))
1770 	PORT_BIT (0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(UTF8_UP) PORT_CODE(KEYCODE_UP)   PORT_CHAR(UCHAR_MAMEKEY(UP))
1771 	PORT_BIT (0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(UTF8_RIGHT) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT))
1772 	PORT_BIT (0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Del Ins") PORT_CODE(KEYCODE_BACKSPACE)  PORT_CHAR(UCHAR_MAMEKEY(DEL)) PORT_CHAR(UCHAR_MAMEKEY(INSERT))
1773 	PORT_BIT (0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Grph") PORT_CODE(KEYCODE_LALT)  PORT_CODE(KEYCODE_RALT) PORT_CHAR(UCHAR_MAMEKEY(F7))
1774 	PORT_BIT (0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Kana") PORT_CODE(KEYCODE_LCONTROL) PORT_TOGGLE PORT_CHAR(UCHAR_MAMEKEY(F6))
1775 	PORT_BIT (0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1)
1776 	PORT_BIT (0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RCONTROL)                        PORT_CHAR(UCHAR_SHIFT_2)
1777 
1778 	PORT_START("KEY9")
1779 	PORT_BIT (0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Stop") PORT_CODE(KEYCODE_F1)            PORT_CHAR(UCHAR_MAMEKEY(PAUSE))
1780 	PORT_BIT (0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F3)                              PORT_CHAR(UCHAR_MAMEKEY(F1))
1781 	PORT_BIT (0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F4)                              PORT_CHAR(UCHAR_MAMEKEY(F2))
1782 	PORT_BIT (0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F5)                              PORT_CHAR(UCHAR_MAMEKEY(F3))
1783 	PORT_BIT (0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F6)                              PORT_CHAR(UCHAR_MAMEKEY(F4))
1784 	PORT_BIT (0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F7)                              PORT_CHAR(UCHAR_MAMEKEY(F5))
1785 	PORT_BIT (0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE)                           PORT_CHAR(' ')
1786 	PORT_BIT (0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ESC)                             PORT_CHAR(UCHAR_MAMEKEY(ESC))
1787 
1788 	PORT_START("KEY10")
1789 	PORT_BIT (0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TAB)                             PORT_CHAR('\t')
1790 	PORT_BIT (0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(UTF8_DOWN) PORT_CODE(KEYCODE_DOWN)   PORT_CHAR(UCHAR_MAMEKEY(DOWN))
1791 	PORT_BIT (0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(UTF8_LEFT) PORT_CODE(KEYCODE_LEFT)   PORT_CHAR(UCHAR_MAMEKEY(LEFT))
1792 	PORT_BIT (0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Help") PORT_CODE(KEYCODE_END)           PORT_CHAR(UCHAR_MAMEKEY(F8))
1793 	PORT_BIT (0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Copy") PORT_CODE(KEYCODE_F2)            PORT_CHAR(UCHAR_MAMEKEY(PRTSCR))
1794 	PORT_BIT (0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS_PAD)                       PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD))
1795 	PORT_BIT (0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH_PAD)                       PORT_CHAR(UCHAR_MAMEKEY(SLASH_PAD))
1796 	PORT_BIT (0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Caps") PORT_CODE(KEYCODE_CAPSLOCK) PORT_TOGGLE PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK))
1797 
1798 	PORT_START("KEY11")
1799 	PORT_BIT (0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Roll Up") PORT_CODE(KEYCODE_F8)         PORT_CHAR(UCHAR_MAMEKEY(PGUP))
1800 	PORT_BIT (0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Roll Down") PORT_CODE(KEYCODE_F9)       PORT_CHAR(UCHAR_MAMEKEY(PGDN))
1801 	PORT_BIT( 0xfc, IP_ACTIVE_LOW, IPT_UNUSED )
1802 
1803 	PORT_START("KEY12")     /* port 0x0c */
1804 	PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
1805 
1806 	PORT_START("KEY13")     /* port 0x0d */
1807 	PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
1808 
1809 	PORT_START("KEY14")     /* port 0x0e */
1810 	PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
1811 
1812 	PORT_START("KEY15")     /* port 0x0f */
1813 	PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
1814 
1815 	PORT_START("DSW1")
1816 	PORT_DIPNAME( 0x01, 0x00, "BASIC" )
1817 	PORT_DIPSETTING(    0x01, "N88-BASIC" )
1818 	PORT_DIPSETTING(    0x00, "N-BASIC" )
1819 	PORT_DIPNAME( 0x02, 0x02, "Terminal mode" )
1820 	PORT_DIPSETTING(    0x02, DEF_STR( Off ) )
1821 	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
1822 	PORT_DIPNAME( 0x04, 0x00, "Text width" )
1823 	PORT_DIPSETTING(    0x04, "40 chars/line" )
1824 	PORT_DIPSETTING(    0x00, "80 chars/line" )
1825 	PORT_DIPNAME( 0x08, 0x00, "Text height" )
1826 	PORT_DIPSETTING(    0x08, "20 lines/screen" )
1827 	PORT_DIPSETTING(    0x00, "25 lines/screen" )
1828 	PORT_DIPNAME( 0x10, 0x10, "Enable S parameter" )
1829 	PORT_DIPSETTING(    0x10, DEF_STR( Off ) )
1830 	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
1831 	PORT_DIPNAME( 0x20, 0x00, "Enable DEL code" )
1832 	PORT_DIPSETTING(    0x20, DEF_STR( Off ) )
1833 	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
1834 	PORT_DIPNAME( 0x40, 0x40, "Memory wait" )
1835 	PORT_DIPSETTING(    0x40, DEF_STR( Off ) )
1836 	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
1837 	PORT_DIPNAME( 0x80, 0x80, "Disable CMD SING" )
1838 	PORT_DIPSETTING(    0x80, DEF_STR( Off ) )
1839 	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
1840 
1841 	PORT_START("DSW2")
1842 	PORT_DIPNAME( 0x01, 0x01, "Parity generate" )
1843 	PORT_DIPSETTING(    0x01, DEF_STR( Off ) )
1844 	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
1845 	PORT_DIPNAME( 0x02, 0x00, "Parity type" )
1846 	PORT_DIPSETTING(    0x00, "Even" )
1847 	PORT_DIPSETTING(    0x02, "Odd" )
1848 	PORT_DIPNAME( 0x04, 0x00, "Serial character length" )
1849 	PORT_DIPSETTING(    0x04, "7 bits/char" )
1850 	PORT_DIPSETTING(    0x00, "8 bits/char" )
1851 	PORT_DIPNAME( 0x08, 0x08, "Stop bit length" )
1852 	PORT_DIPSETTING(    0x08, "1" )
1853 	PORT_DIPSETTING(    0x00, "2" )
1854 	PORT_DIPNAME( 0x10, 0x10, "Enable X parameter" )
1855 	PORT_DIPSETTING(    0x10, DEF_STR( Off ) )
1856 	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
1857 	PORT_DIPNAME( 0x20, 0x20, "Duplex" )
1858 	PORT_DIPSETTING(    0x20, "Half" )
1859 	PORT_DIPSETTING(    0x00, "Full" )
1860 	PORT_DIPNAME( 0xc0, 0x40, "Basic mode" )
1861 	PORT_DIPSETTING(    0x80, "N88-BASIC (V1L)" )
1862 	PORT_DIPSETTING(    0xc0, "N88-BASIC (V1H)" )
1863 	PORT_DIPSETTING(    0x40, "N88-BASIC (V2)" )
1864 //  PORT_DIPSETTING(    0x00, "N88-BASIC (V2)" )
1865 
1866 	PORT_START("CTRL")
1867 	PORT_DIPNAME( 0x02, 0x02, "Monitor Type" )
1868 	PORT_DIPSETTING(    0x02, "15 KHz" )
1869 	PORT_DIPSETTING(    0x00, "24 KHz" )
1870 	PORT_DIPNAME( 0x08, 0x00, "Auto-boot floppy at start-up" )
1871 	PORT_DIPSETTING(    0x08, DEF_STR( Off ) )
1872 	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
1873 	PORT_BIT( 0x10, IP_ACTIVE_HIGH,IPT_CUSTOM ) PORT_READ_LINE_DEVICE_MEMBER("upd1990a", upd1990a_device, data_out_r)
1874 	PORT_BIT( 0x20, IP_ACTIVE_HIGH,IPT_CUSTOM ) PORT_VBLANK("screen")
1875 	PORT_BIT( 0xc0, IP_ACTIVE_LOW, IPT_UNUSED )
1876 
1877 	PORT_START("CFG")       /* EXSWITCH */
1878 	#if 0 // reference only, afaik there isn't a thing like this ...
1879 	PORT_DIPNAME( 0x0f, 0x08, "Serial speed" )
1880 	PORT_DIPSETTING(    0x01, "75bps" )
1881 	PORT_DIPSETTING(    0x02, "150bps" )
1882 	PORT_DIPSETTING(    0x03, "300bps" )
1883 	PORT_DIPSETTING(    0x04, "600bps" )
1884 	PORT_DIPSETTING(    0x05, "1200bps" )
1885 	PORT_DIPSETTING(    0x06, "2400bps" )
1886 	PORT_DIPSETTING(    0x07, "4800bps" )
1887 	PORT_DIPSETTING(    0x08, "9600bps" )
1888 	PORT_DIPSETTING(    0x09, "19200bps" )
1889 	#endif
1890 	PORT_DIPNAME( 0x40, 0x40, "Speed mode" )
1891 	PORT_DIPSETTING(    0x00, "Slow" )
1892 	PORT_DIPSETTING(    0x40, DEF_STR( High ) )
1893 	PORT_DIPNAME( 0x80, 0x80, "Main CPU clock" )
1894 	PORT_DIPSETTING(    0x80, "4MHz" )
1895 	PORT_DIPSETTING(    0x00, "8MHz" )
1896 
1897 	PORT_START("OPN_PA")
1898 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("BOARD_CONFIG", 0x02, EQUALS, 0x00)
1899 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("BOARD_CONFIG", 0x02, EQUALS, 0x00)
1900 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("BOARD_CONFIG", 0x02, EQUALS, 0x00)
1901 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("BOARD_CONFIG", 0x02, EQUALS, 0x00)
1902 	PORT_BIT( 0xf0, IP_ACTIVE_LOW, IPT_UNUSED )
1903 
1904 	PORT_START("OPN_PB")
1905 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_NAME("P1 Joystick Button 1") PORT_CONDITION("BOARD_CONFIG", 0x02, EQUALS, 0x00)
1906 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) PORT_NAME("P1 Joystick Button 2") PORT_CONDITION("BOARD_CONFIG", 0x02, EQUALS, 0x00)
1907 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_NAME("P1 Mouse Button 1") PORT_CONDITION("BOARD_CONFIG", 0x02, EQUALS, 0x02)
1908 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) PORT_NAME("P1 Mouse Button 2") PORT_CONDITION("BOARD_CONFIG", 0x02, EQUALS, 0x02)
1909 	PORT_BIT( 0xfc, IP_ACTIVE_LOW, IPT_UNUSED )
1910 
1911 	PORT_START("MOUSEX")
1912 	PORT_BIT( 0xff, 0x00, IPT_MOUSE_X ) PORT_RESET PORT_REVERSE PORT_SENSITIVITY(20) PORT_KEYDELTA(20) PORT_PLAYER(1) PORT_CONDITION("BOARD_CONFIG", 0x02, EQUALS, 0x02)
1913 
1914 	PORT_START("MOUSEY")
1915 	PORT_BIT( 0xff, 0x00, IPT_MOUSE_Y ) PORT_RESET PORT_REVERSE PORT_SENSITIVITY(20) PORT_KEYDELTA(20) PORT_PLAYER(1) PORT_CONDITION("BOARD_CONFIG", 0x02, EQUALS, 0x02)
1916 
1917 	PORT_START("MEM")
1918 	PORT_CONFNAME( 0x0f, 0x0a, "Extension memory" )
1919 	PORT_CONFSETTING(    0x00, DEF_STR( None ) )
1920 	PORT_CONFSETTING(    0x01, "32KB (PC-8012-02 x 1)" )
1921 	PORT_CONFSETTING(    0x02, "64KB (PC-8012-02 x 2)" )
1922 	PORT_CONFSETTING(    0x03, "128KB (PC-8012-02 x 4)" )
1923 	PORT_CONFSETTING(    0x04, "128KB (PC-8801-02N x 1)" )
1924 	PORT_CONFSETTING(    0x05, "256KB (PC-8801-02N x 2)" )
1925 	PORT_CONFSETTING(    0x06, "512KB (PC-8801-02N x 4)" )
1926 	PORT_CONFSETTING(    0x07, "1M (PIO-8234H-1M x 1)" )
1927 	PORT_CONFSETTING(    0x08, "2M (PIO-8234H-2M x 1)" )
1928 	PORT_CONFSETTING(    0x09, "4M (PIO-8234H-2M x 2)" )
1929 	PORT_CONFSETTING(    0x0a, "8M (PIO-8234H-2M x 4)" )
1930 	PORT_CONFSETTING(    0x0b, "1.1M (PIO-8234H-1M x 1 + PC-8801-02N x 1)" )
1931 	PORT_CONFSETTING(    0x0c, "2.1M (PIO-8234H-2M x 1 + PC-8801-02N x 1)" )
1932 	PORT_CONFSETTING(    0x0d, "4.1M (PIO-8234H-2M x 2 + PC-8801-02N x 1)" )
1933 
1934 	PORT_START("BOARD_CONFIG")
1935 	PORT_CONFNAME( 0x01, 0x01, "Sound Board" ) /* TODO: is it possible to have BOTH sound chips in there? */
1936 	PORT_CONFSETTING(    0x00, "OPN (YM2203)" )
1937 	PORT_CONFSETTING(    0x01, "OPNA (YM2608)" )
1938 	PORT_CONFNAME( 0x02, 0x00, "Port 1 Connection" )
1939 	PORT_CONFSETTING(    0x00, "Joystick" )
1940 	PORT_CONFSETTING(    0x02, "Mouse" )
1941 INPUT_PORTS_END
1942 
1943 static INPUT_PORTS_START( pc88sr )
1944 	PORT_INCLUDE( pc8001 )
1945 
1946 	PORT_MODIFY("DSW1")
1947 	PORT_DIPNAME( 0x01, 0x01, "BASIC" )
1948 	PORT_DIPSETTING(    0x01, "N88-BASIC" )
1949 	PORT_DIPSETTING(    0x00, "N-BASIC" )
1950 INPUT_PORTS_END
1951 
1952 /* Graphics Layouts */
1953 
1954 static const gfx_layout char_layout =
1955 {
1956 	8, 8,
1957 	RGN_FRAC(1,1),
1958 	1,
1959 	{ 0 },
1960 	{ STEP8(0,1) },
1961 	{ STEP8(0,8) },
1962 	8*8
1963 };
1964 
1965 static const gfx_layout kanji_layout =
1966 {
1967 	16, 16,
1968 	RGN_FRAC(1,1),
1969 	1,
1970 	{ 0 },
1971 	{ STEP16(0,1) },
1972 	{ STEP16(0,16) },
1973 	16*16
1974 };
1975 
1976 /* debugging only */
1977 static GFXDECODE_START( gfx_pc8801 )
1978 	GFXDECODE_ENTRY( "cgrom", 0, char_layout,  0, 8 )
1979 	GFXDECODE_ENTRY( "kanji", 0, kanji_layout, 0, 8 )
1980 GFXDECODE_END
1981 
1982 /* Floppy Configuration */
1983 
pc88_floppies(device_slot_interface & device)1984 static void pc88_floppies(device_slot_interface &device)
1985 {
1986 	device.option_add("525hd", FLOPPY_525_HD);
1987 }
1988 
1989 #if 0
1990 /* Cassette Configuration */
1991 
1992 static const cassette_interface pc88_cassette_interface =
1993 {
1994 	cassette_default_formats,   // we need T88 format support!
1995 	nullptr,
1996 	CASSETTE_STOPPED | CASSETTE_MOTOR_ENABLED | CASSETTE_SPEAKER_MUTED,
1997 	"pc8801_cass"
1998 };
1999 #endif
2000 
2001 #if USE_PROPER_I8214
pc8801_raise_irq(uint8_t irq,uint8_t state)2002 void pc8801_state::pc8801_raise_irq(uint8_t irq,uint8_t state)
2003 {
2004 	if(state)
2005 	{
2006 		drvm_int_state |= irq;
2007 
2008 		drvm_pic->r_w(~irq);
2009 
2010 		m_maincpu->set_input_line(0,ASSERT_LINE);
2011 	}
2012 	else
2013 	{
2014 		//drvm_int_state &= ~irq;
2015 
2016 		//m_maincpu->set_input_line(0,CLEAR_LINE);
2017 	}
2018 }
2019 
WRITE_LINE_MEMBER(pc8801_state::pic_int_w)2020 WRITE_LINE_MEMBER(pc8801_state::pic_int_w)
2021 {
2022 	device_t *device = m_maincpu;
2023 //  if (state == ASSERT_LINE)
2024 //  {
2025 //  }
2026 }
2027 
WRITE_LINE_MEMBER(pc8801_state::pic_enlg_w)2028 WRITE_LINE_MEMBER(pc8801_state::pic_enlg_w)
2029 {
2030 	device_t *device = m_maincpu;
2031 	//if (state == CLEAR_LINE)
2032 	//{
2033 	//}
2034 }
2035 
I8214_INTERFACE(pic_intf)2036 static I8214_INTERFACE( pic_intf )
2037 {
2038 	DEVCB_DRIVER_LINE_MEMBER(pc8801_state,pic_int_w),
2039 	DEVCB_DRIVER_LINE_MEMBER(pc8801_state,pic_enlg_w)
2040 };
2041 
IRQ_CALLBACK_MEMBER(pc8801_state::pc8801_irq_callback)2042 IRQ_CALLBACK_MEMBER(pc8801_state::pc8801_irq_callback)
2043 {
2044 	uint8_t vector = (7 - m_pic->a_r());
2045 
2046 	m_int_state &= ~(1<<vector);
2047 	m_maincpu->set_input_line(0,CLEAR_LINE);
2048 
2049 	return vector << 1;
2050 }
2051 
WRITE_LINE_MEMBER(pc8801_state::pc8801_sound_irq)2052 WRITE_LINE_MEMBER(pc8801_state::pc8801_sound_irq)
2053 {
2054 	if(m_sound_irq_mask && state)
2055 		pc8801_raise_irq(machine(),1<<(4),1);
2056 }
2057 
2058 /*
2059 TIMER_DEVICE_CALLBACK_MEMBER(pc8801_state::pc8801_rtc_irq)
2060 {
2061     if(m_timer_irq_mask)
2062         pc8801_raise_irq(machine(),1<<(2),1);
2063 }
2064 */
2065 
INTERRUPT_GEN_MEMBER(pc8801_state::pc8801_vrtc_irq)2066 INTERRUPT_GEN_MEMBER(pc8801_state::pc8801_vrtc_irq)
2067 {
2068 	if(m_vblank_irq_mask)
2069 		pc8801_raise_irq(machine(),1<<(1),1);
2070 }
2071 
2072 #else
2073 
2074 #include "debugger.h"
2075 
IRQ_CALLBACK_MEMBER(pc8801_state::pc8801_irq_callback)2076 IRQ_CALLBACK_MEMBER(pc8801_state::pc8801_irq_callback)
2077 {
2078 	if(m_sound_irq_latch)
2079 	{
2080 		m_sound_irq_latch = 0;
2081 		return 4*2;
2082 	}
2083 	else if(m_vrtc_irq_latch)
2084 	{
2085 		m_vrtc_irq_latch = 0;
2086 		return 1*2;
2087 	}
2088 	else if(m_timer_irq_latch)
2089 	{
2090 		m_timer_irq_latch = 0;
2091 		return 2*2;
2092 	}
2093 
2094 	printf("IRQ triggered but no vector on the bus! %02x %02x %02x %02x\n",m_i8214_irq_level,m_sound_irq_latch,m_vrtc_irq_latch,m_timer_irq_latch);
2095 	machine().debug_break();
2096 
2097 	return 4*2; //TODO: mustn't happen
2098 }
2099 
WRITE_LINE_MEMBER(pc8801_state::pc8801_sound_irq)2100 WRITE_LINE_MEMBER(pc8801_state::pc8801_sound_irq)
2101 {
2102 //  printf("%02x %02x %02x\n",m_sound_irq_mask,m_i8214_irq_level,state);
2103 	/* TODO: correct i8214 irq level? */
2104 	if(state)
2105 	{
2106 		if(m_sound_irq_mask)
2107 		{
2108 			m_sound_irq_latch = 1;
2109 			m_sound_irq_pending = 0;
2110 			//IRQ_LOG(("sound\n"));
2111 			m_maincpu->set_input_line(0,HOLD_LINE);
2112 		}
2113 		else
2114 			m_sound_irq_pending = 1;
2115 	}
2116 }
2117 
TIMER_DEVICE_CALLBACK_MEMBER(pc8801_state::pc8801_rtc_irq)2118 TIMER_DEVICE_CALLBACK_MEMBER(pc8801_state::pc8801_rtc_irq)
2119 {
2120 	if(m_timer_irq_mask && m_i8214_irq_level >= 3)
2121 	{
2122 		m_timer_irq_latch = 1;
2123 		//IRQ_LOG(("timer\n"));
2124 		m_maincpu->set_input_line(0,HOLD_LINE);
2125 	}
2126 }
2127 
INTERRUPT_GEN_MEMBER(pc8801_state::pc8801_vrtc_irq)2128 INTERRUPT_GEN_MEMBER(pc8801_state::pc8801_vrtc_irq)
2129 {
2130 	if(m_vrtc_irq_mask && m_i8214_irq_level >= 2)
2131 	{
2132 		m_vrtc_irq_latch = 1;
2133 		//IRQ_LOG(("vrtc\n"));
2134 		m_maincpu->set_input_line(0,HOLD_LINE);
2135 	}
2136 }
2137 #endif
2138 
machine_start()2139 void pc8801_state::machine_start()
2140 {
2141 	m_fdd[0]->get_device()->set_rpm(300);
2142 	m_fdd[1]->get_device()->set_rpm(300);
2143 	m_fdc->set_rate(250000);
2144 
2145 	m_rtc->cs_w(1);
2146 	m_rtc->oe_w(1);
2147 
2148 	m_work_ram = make_unique_clear<uint8_t[]>(0x10000);
2149 	m_hi_work_ram = make_unique_clear<uint8_t[]>(0x1000);
2150 	m_ext_work_ram = make_unique_clear<uint8_t[]>(0x8000*0x100);
2151 	m_gvram = make_unique_clear<uint8_t[]>(0xc000);
2152 	m_n80rom = memregion("n80rom")->base();
2153 	m_n88rom = memregion("n88rom")->base();
2154 	m_kanji_rom = memregion("kanji")->base();
2155 	m_cg_rom = memregion("cgrom")->base();
2156 
2157 	save_pointer(NAME(m_work_ram), 0x10000);
2158 	save_pointer(NAME(m_hi_work_ram), 0x1000);
2159 	save_pointer(NAME(m_ext_work_ram), 0x8000*0x100);
2160 	save_pointer(NAME(m_gvram), 0xc000);
2161 }
2162 
machine_reset()2163 void pc8801_state::machine_reset()
2164 {
2165 	#define kB 1024
2166 	#define MB 1024*1024
2167 	const uint32_t extram_type[] = { 0*kB, 32*kB,64*kB,128*kB,128*kB,256*kB,512*kB,1*MB,2*MB,4*MB,8*MB,1*MB+128*kB,2*MB+128*kB,4*MB+128*kB, 0*kB, 0*kB };
2168 	#undef kB
2169 	#undef MB
2170 
2171 	m_ext_rom_bank = 0xff;
2172 	m_gfx_ctrl = 0x31;
2173 	m_window_offset_bank = 0x80;
2174 	m_misc_ctrl = 0x80;
2175 	m_layer_mask = 0x00;
2176 	m_vram_sel = 3;
2177 
2178 //  pc8801_dynamic_res_change(machine());
2179 
2180 	m_fdc_irq_opcode = 0; //TODO: copied from PC-88VA, could be wrong here ... should be 0x7f ld a,a in the latter case
2181 	m_mouse.phase = 0;
2182 
2183 	m_fdccpu->set_input_line_vector(0, 0); // Z80
2184 
2185 	{
2186 		m_txt_color = 2;
2187 	}
2188 
2189 	{
2190 		int i;
2191 
2192 		for(i=0;i<3;i++)
2193 			m_alu_reg[i] = 0x00;
2194 	}
2195 
2196 	{
2197 		m_crtc.param_count = 0;
2198 		m_crtc.cmd = 0;
2199 		m_crtc.status = 0;
2200 	}
2201 
2202 	m_beeper->set_state(0);
2203 
2204 	#if USE_PROPER_I8214
2205 	{
2206 		/* initialize I8214 */
2207 		m_pic->etlg_w(1);
2208 		m_pic->inte_w(1);
2209 	}
2210 	#else
2211 	{
2212 		m_vrtc_irq_mask = 0;
2213 		m_vrtc_irq_latch = 0;
2214 		m_timer_irq_mask = 0;
2215 		m_timer_irq_latch = 0;
2216 		m_sound_irq_mask = 0;
2217 		m_sound_irq_latch = 0;
2218 		m_i8214_irq_level = 0;
2219 		m_sound_irq_pending = 0;
2220 	}
2221 	#endif
2222 
2223 	{
2224 		m_dma_address[2] = 0xf300;
2225 	}
2226 
2227 	{
2228 		m_extram_bank = 0;
2229 		m_extram_mode = 0;
2230 	}
2231 
2232 	{
2233 		int i;
2234 
2235 		for(i=0;i<0x10;i++) //text + bitmap
2236 			m_palette->set_pen_color(i, pal1bit(i >> 1), pal1bit(i >> 2), pal1bit(i >> 0));
2237 	}
2238 
2239 	m_has_clock_speed = 0;
2240 	m_has_dictionary = 0;
2241 	m_has_cdrom = 0;
2242 
2243 	m_extram_size = extram_type[ioport("MEM")->read() & 0x0f];
2244 	m_has_opna = ioport("BOARD_CONFIG")->read() & 1;
2245 }
2246 
MACHINE_RESET_MEMBER(pc8801_state,pc8801_clock_speed)2247 MACHINE_RESET_MEMBER(pc8801_state,pc8801_clock_speed)
2248 {
2249 	pc8801_state::machine_reset();
2250 	m_has_clock_speed = 1;
2251 	m_clock_setting = ioport("CFG")->read() & 0x80;
2252 
2253 	m_maincpu->set_unscaled_clock(m_clock_setting ?  XTAL(4'000'000) : XTAL(8'000'000));
2254 	m_fdccpu->set_unscaled_clock(m_clock_setting ?  XTAL(4'000'000) : XTAL(8'000'000)); // correct?
2255 	m_baudrate_val = 0;
2256 }
2257 
MACHINE_RESET_MEMBER(pc8801_state,pc8801_dic)2258 MACHINE_RESET_MEMBER(pc8801_state,pc8801_dic)
2259 {
2260 	MACHINE_RESET_CALL_MEMBER( pc8801_clock_speed );
2261 	m_has_dictionary = 1;
2262 	m_dic_bank = 0;
2263 	m_dic_ctrl = 0;
2264 }
2265 
MACHINE_RESET_MEMBER(pc8801_state,pc8801_cdrom)2266 MACHINE_RESET_MEMBER(pc8801_state,pc8801_cdrom)
2267 {
2268 	MACHINE_RESET_CALL_MEMBER( pc8801_dic );
2269 	m_has_cdrom = 1;
2270 
2271 	{
2272 		int i;
2273 
2274 		for(i=0;i<0x10;i++)
2275 			m_cdrom_reg[i] = 0;
2276 	}
2277 }
2278 
pc8801_palette(palette_device & palette) const2279 void pc8801_state::pc8801_palette(palette_device &palette) const
2280 {
2281 	for(int i = 0; i< 0x10; i++) //text + bitmap
2282 		palette.set_pen_color(i, pal1bit(i >> 1), pal1bit(i >> 2), pal1bit(i >> 0));
2283 }
2284 
2285 /* YM2203 Interface */
2286 
opn_porta_r()2287 uint8_t pc8801_state::opn_porta_r()
2288 {
2289 	if(ioport("BOARD_CONFIG")->read() & 2)
2290 	{
2291 		uint8_t shift,res;
2292 
2293 		shift = (m_mouse.phase & 1) ? 0 : 4;
2294 		res = (m_mouse.phase & 2) ? m_mouse.y : m_mouse.x;
2295 
2296 //      printf("%d\n",m_mouse.phase);
2297 
2298 		return ((res >> shift) & 0x0f) | 0xf0;
2299 	}
2300 
2301 	return ioport("OPN_PA")->read();
2302 }
opn_portb_r()2303 uint8_t pc8801_state::opn_portb_r(){ return ioport("OPN_PB")->read(); }
2304 
2305 /* Cassette Configuration */
WRITE_LINE_MEMBER(pc8801_state::txdata_callback)2306 WRITE_LINE_MEMBER( pc8801_state::txdata_callback )
2307 {
2308 	//m_cass->output( (state) ? 0.8 : -0.8);
2309 }
2310 
WRITE_LINE_MEMBER(pc8801_state::rxrdy_w)2311 WRITE_LINE_MEMBER( pc8801_state::rxrdy_w )
2312 {
2313 	// ...
2314 }
2315 
pc8801(machine_config & config)2316 void pc8801_state::pc8801(machine_config &config)
2317 {
2318 	/* main CPU */
2319 	Z80(config, m_maincpu, MASTER_CLOCK);        /* 4 MHz */
2320 	m_maincpu->set_addrmap(AS_PROGRAM, &pc8801_state::pc8801_mem);
2321 	m_maincpu->set_addrmap(AS_IO, &pc8801_state::pc8801_io);
2322 	m_maincpu->set_vblank_int("screen", FUNC(pc8801_state::pc8801_vrtc_irq));
2323 	m_maincpu->set_irq_acknowledge_callback(FUNC(pc8801_state::pc8801_irq_callback));
2324 
2325 	/* sub CPU(5 inch floppy drive) */
2326 	Z80(config, m_fdccpu, MASTER_CLOCK);       /* 4 MHz */
2327 	m_fdccpu->set_addrmap(AS_PROGRAM, &pc8801_state::pc8801fdc_mem);
2328 	m_fdccpu->set_addrmap(AS_IO, &pc8801_state::pc8801fdc_io);
2329 
2330 	//config.set_maximum_quantum(attotime::from_hz(300000));
2331 	config.set_perfect_quantum(m_maincpu);
2332 
2333 	i8255_device &d8255_master(I8255(config, "d8255_master"));
2334 	d8255_master.in_pa_callback().set("d8255_slave", FUNC(i8255_device::pb_r));
2335 	d8255_master.in_pb_callback().set("d8255_slave", FUNC(i8255_device::pa_r));
2336 	d8255_master.in_pc_callback().set(FUNC(pc8801_state::cpu_8255_c_r));
2337 	d8255_master.out_pc_callback().set(FUNC(pc8801_state::cpu_8255_c_w));
2338 
2339 	i8255_device &d8255_slave(I8255(config, "d8255_slave"));
2340 	d8255_slave.in_pa_callback().set("d8255_master", FUNC(i8255_device::pb_r));
2341 	d8255_slave.in_pb_callback().set("d8255_master", FUNC(i8255_device::pa_r));
2342 	d8255_slave.in_pc_callback().set(FUNC(pc8801_state::fdc_8255_c_r));
2343 	d8255_slave.out_pc_callback().set(FUNC(pc8801_state::fdc_8255_c_w));
2344 
2345 	UPD765A(config, m_fdc, 8'000'000, true, true);
2346 	m_fdc->intrq_wr_callback().set_inputline(m_fdccpu, INPUT_LINE_IRQ0);
2347 
2348 	#if USE_PROPER_I8214
2349 	I8214(config, I8214_TAG, MASTER_CLOCK);
2350 	#endif
2351 	UPD1990A(config, m_rtc);
2352 	//CENTRONICS(config, "centronics", centronics_devices, "printer");
2353 	CASSETTE(config, m_cassette);
2354 	m_cassette->set_default_state(CASSETTE_STOPPED | CASSETTE_MOTOR_ENABLED | CASSETTE_SPEAKER_ENABLED);
2355 	m_cassette->set_interface("pc8801_cass");
2356 
2357 	SOFTWARE_LIST(config, "tape_list").set_original("pc8801_cass");
2358 
2359 	i8251_device &i8251(I8251(config, I8251_TAG, 0));
2360 	i8251.txd_handler().set(FUNC(pc8801_state::txdata_callback));
2361 	i8251.rts_handler().set(FUNC(pc8801_state::rxrdy_w));
2362 
2363 	FLOPPY_CONNECTOR(config, "upd765:0", pc88_floppies, "525hd", floppy_image_device::default_floppy_formats);
2364 	FLOPPY_CONNECTOR(config, "upd765:1", pc88_floppies, "525hd", floppy_image_device::default_floppy_formats);
2365 	SOFTWARE_LIST(config, "disk_list").set_original("pc8801_flop");
2366 
2367 	/* video hardware */
2368 	SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
2369 	m_screen->set_raw(PIXEL_CLOCK_24KHz,848,0,640,448,0,400);
2370 	m_screen->set_screen_update(FUNC(pc8801_state::screen_update));
2371 	m_screen->set_palette(m_palette);
2372 
2373 	GFXDECODE(config, "gfxdecode", m_palette, gfx_pc8801);
2374 	PALETTE(config, m_palette, FUNC(pc8801_state::pc8801_palette), 0x10);
2375 
2376 //  MCFG_VIDEO_START_OVERRIDE(pc8801_state,pc8801)
2377 
2378 	/* sound hardware */
2379 	SPEAKER(config, "mono").front_center();
2380 	m_cassette->add_route(ALL_OUTPUTS, "mono", 0.05);
2381 	YM2203(config, m_opn, MASTER_CLOCK);
2382 	m_opn->irq_handler().set(FUNC(pc8801_state::pc8801_sound_irq));
2383 	m_opn->port_a_read_callback().set(FUNC(pc8801_state::opn_porta_r));
2384 	m_opn->port_b_read_callback().set(FUNC(pc8801_state::opn_portb_r));
2385 	m_opn->add_route(ALL_OUTPUTS, "mono", 1.00);
2386 
2387 	YM2608(config, m_opna, MASTER_CLOCK*2);
2388 	m_opna->irq_handler().set(FUNC(pc8801_state::pc8801_sound_irq));
2389 	m_opna->port_a_read_callback().set(FUNC(pc8801_state::opn_porta_r));
2390 	m_opna->port_b_read_callback().set(FUNC(pc8801_state::opn_portb_r));
2391 	m_opna->add_route(ALL_OUTPUTS, "mono", 1.00);
2392 
2393 	BEEP(config, m_beeper, 2400).add_route(ALL_OUTPUTS, "mono", 0.10);
2394 
2395 	TIMER(config, "rtc_timer").configure_periodic(FUNC(pc8801_state::pc8801_rtc_irq), attotime::from_hz(600));
2396 }
2397 
pc8801fh(machine_config & config)2398 void pc8801_state::pc8801fh(machine_config &config)
2399 {
2400 	pc8801(config);
2401 	MCFG_MACHINE_RESET_OVERRIDE(pc8801_state, pc8801_clock_speed )
2402 }
2403 
pc8801ma(machine_config & config)2404 void pc8801_state::pc8801ma(machine_config &config)
2405 {
2406 	pc8801(config);
2407 	MCFG_MACHINE_RESET_OVERRIDE(pc8801_state, pc8801_dic )
2408 }
2409 
pc8801mc(machine_config & config)2410 void pc8801_state::pc8801mc(machine_config &config)
2411 {
2412 	pc8801(config);
2413 	MCFG_MACHINE_RESET_OVERRIDE(pc8801_state, pc8801_cdrom )
2414 }
2415 
2416 
2417 /* TODO: clean this up */
2418 #define PC8801_MEM_LOAD \
2419 	ROM_REGION( 0x100000, "opna", ROMREGION_ERASE00 )
2420 
2421 
2422 ROM_START( pc8801 )
2423 	PC8801_MEM_LOAD
2424 
2425 	ROM_REGION( 0x8000, "n80rom", ROMREGION_ERASEFF ) // 1.2
2426 	ROM_LOAD( "n80.rom",   0x0000, 0x8000, CRC(5cb8b584) SHA1(063609dd518c124a4fc9ba35d1bae35771666a34) )
2427 
2428 	ROM_REGION( 0x10000, "n88rom", ROMREGION_ERASEFF ) // 1.0
2429 	ROM_LOAD( "n88.rom",   0x0000, 0x8000, CRC(ffd68be0) SHA1(3518193b8207bdebf22c1380c2db8c554baff329) )
2430 	ROM_LOAD( "n88_0.rom", 0x8000, 0x2000, CRC(61984bab) SHA1(d1ae642aed4f0584eeb81ff50180db694e5101d4) )
2431 
2432 	ROM_REGION( 0x10000, "fdccpu", 0)
2433 	ROM_LOAD( "disk.rom", 0x0000, 0x0800, CRC(2158d307) SHA1(bb7103a0818850a039c67ff666a31ce49a8d516f) )
2434 
2435 	ROM_REGION( 0x40000, "kanji", ROMREGION_ERASEFF)
2436 	ROM_LOAD_OPTIONAL( "kanji1.rom", 0x00000, 0x20000, CRC(6178bd43) SHA1(82e11a177af6a5091dd67f50a2f4bafda84d6556) )
2437 
2438 	ROM_REGION( 0x800, "cgrom", 0)
2439 	ROM_LOAD( "font.rom", 0x0000, 0x0800, CRC(56653188) SHA1(84b90f69671d4b72e8f219e1fe7cd667e976cf7f) )
2440 ROM_END
2441 
2442 /* The dump only included "maincpu". Other roms arbitrariely taken from PC-8801 & PC-8801 MkIISR (there should be
2443 at least 1 Kanji ROM). */
2444 ROM_START( pc8801mk2 )
2445 	PC8801_MEM_LOAD
2446 
2447 	ROM_REGION( 0x8000, "n80rom", ROMREGION_ERASEFF ) // 1.4
2448 	ROM_LOAD( "m2_n80.rom",   0x0000, 0x8000, CRC(91d84b1a) SHA1(d8a1abb0df75936b3fc9d226ccdb664a9070ffb1) )
2449 
2450 	ROM_REGION( 0x10000, "n88rom", ROMREGION_ERASEFF ) //1.3
2451 	ROM_LOAD( "m2_n88.rom",   0x0000, 0x8000, CRC(f35169eb) SHA1(ef1f067f819781d9fb2713836d195866f0f81501) )
2452 	ROM_LOAD( "m2_n88_0.rom", 0x8000, 0x2000, CRC(5eb7a8d0) SHA1(95a70af83b0637a5a0f05e31fb0452bb2cb68055) )
2453 
2454 	ROM_REGION( 0x10000, "fdccpu", 0)
2455 	ROM_LOAD( "disk.rom", 0x0000, 0x0800, CRC(2158d307) SHA1(bb7103a0818850a039c67ff666a31ce49a8d516f) )
2456 
2457 	ROM_REGION( 0x40000, "kanji", ROMREGION_ERASEFF)
2458 	ROM_LOAD_OPTIONAL( "kanji1.rom", 0x00000, 0x20000, CRC(6178bd43) SHA1(82e11a177af6a5091dd67f50a2f4bafda84d6556) )
2459 
2460 	ROM_REGION( 0x800, "cgrom", 0)
2461 	ROM_COPY( "kanji", 0x1000, 0x0000, 0x800 )
2462 ROM_END
2463 
2464 ROM_START( pc8801mk2sr )
2465 	PC8801_MEM_LOAD
2466 
2467 	ROM_REGION( 0x8000, "n80rom", ROMREGION_ERASEFF ) // 1.5
2468 	ROM_LOAD( "mk2sr_n80.rom",   0x0000, 0x8000, CRC(27e1857d) SHA1(5b922ed9de07d2a729bdf1da7b57c50ddf08809a) )
2469 
2470 	ROM_REGION( 0x10000, "n88rom", ROMREGION_ERASEFF ) // 2.0
2471 	ROM_LOAD( "mk2sr_n88.rom",   0x0000, 0x8000, CRC(a0fc0473) SHA1(3b31fc68fa7f47b21c1a1cb027b86b9e87afbfff) )
2472 	ROM_LOAD( "mk2sr_n88_0.rom", 0x8000, 0x2000, CRC(710a63ec) SHA1(d239c26ad7ac5efac6e947b0e9549b1534aa970d) )
2473 	ROM_LOAD( "n88_1.rom",       0xa000, 0x2000, CRC(c0bd2aa6) SHA1(8528eef7946edf6501a6ccb1f416b60c64efac7c) )
2474 	ROM_LOAD( "n88_2.rom",       0xc000, 0x2000, CRC(af2b6efa) SHA1(b7c8bcea219b77d9cc3ee0efafe343cc307425d1) )
2475 	ROM_LOAD( "n88_3.rom",       0xe000, 0x2000, CRC(7713c519) SHA1(efce0b51cab9f0da6cf68507757f1245a2867a72) )
2476 
2477 	ROM_REGION( 0x10000, "fdccpu", 0)
2478 	ROM_LOAD( "disk.rom", 0x0000, 0x0800, CRC(2158d307) SHA1(bb7103a0818850a039c67ff666a31ce49a8d516f) )
2479 
2480 	/* No idea of the proper size: it has never been dumped */
2481 	ROM_REGION( 0x2000, "audiocpu", 0)
2482 	ROM_LOAD( "soundbios.rom", 0x0000, 0x2000, NO_DUMP )
2483 
2484 	ROM_REGION( 0x40000, "kanji", 0)
2485 	ROM_LOAD( "kanji1.rom", 0x00000, 0x20000, CRC(6178bd43) SHA1(82e11a177af6a5091dd67f50a2f4bafda84d6556) )
2486 	ROM_LOAD( "kanji2.rom", 0x20000, 0x20000, CRC(154803cc) SHA1(7e6591cd465cbb35d6d3446c5a83b46d30fafe95) )    // it should not be here
2487 
2488 	ROM_REGION( 0x800, "cgrom", 0)
2489 	ROM_COPY( "kanji", 0x1000, 0x0000, 0x800 )
2490 ROM_END
2491 
2492 ROM_START( pc8801mk2fr )
2493 	PC8801_MEM_LOAD
2494 
2495 	ROM_REGION( 0x8000, "n80rom", ROMREGION_ERASEFF ) // 1.5
2496 	ROM_LOAD( "m2fr_n80.rom",   0x0000, 0x8000, CRC(27e1857d) SHA1(5b922ed9de07d2a729bdf1da7b57c50ddf08809a) )
2497 
2498 	ROM_REGION( 0x10000, "n88rom", ROMREGION_ERASEFF ) // 2.1
2499 	ROM_LOAD( "m2fr_n88.rom",   0x0000, 0x8000, CRC(b9daf1aa) SHA1(696a480232bcf8c827c7aeea8329db5c44420d2a) )
2500 	ROM_LOAD( "m2fr_n88_0.rom", 0x8000, 0x2000, CRC(710a63ec) SHA1(d239c26ad7ac5efac6e947b0e9549b1534aa970d) )
2501 	ROM_LOAD( "m2fr_n88_1.rom", 0xa000, 0x2000, CRC(e3e78a37) SHA1(85ecd287fe72b56e54c8b01ea7492ca4a69a7470) )
2502 	ROM_LOAD( "m2fr_n88_2.rom", 0xc000, 0x2000, CRC(98c3a7b2) SHA1(fc4980762d3caa56964d0ae583424756f511d186) )
2503 	ROM_LOAD( "m2fr_n88_3.rom", 0xe000, 0x2000, CRC(0ca08abd) SHA1(a5a42d0b7caa84c3bc6e337c9f37874d82f9c14b) )
2504 
2505 	ROM_REGION( 0x10000, "fdccpu", 0)
2506 	ROM_LOAD( "m2fr_disk.rom", 0x0000, 0x0800, CRC(2163b304) SHA1(80da2dee49d4307f00895a129a5cfeff00cf5321) )
2507 
2508 	/* No idea of the proper size: it has never been dumped */
2509 	ROM_REGION( 0x2000, "audiocpu", 0)
2510 	ROM_LOAD( "soundbios.rom", 0x0000, 0x2000, NO_DUMP )
2511 
2512 	ROM_REGION( 0x40000, "kanji", 0)
2513 	ROM_LOAD( "kanji1.rom", 0x00000, 0x20000, CRC(6178bd43) SHA1(82e11a177af6a5091dd67f50a2f4bafda84d6556) )
2514 
2515 	ROM_REGION( 0x800, "cgrom", 0)
2516 	ROM_COPY( "kanji", 0x1000, 0x0000, 0x800 )
2517 ROM_END
2518 
2519 ROM_START( pc8801mk2mr )
2520 	PC8801_MEM_LOAD
2521 
2522 	ROM_REGION( 0x8000, "n80rom", ROMREGION_ERASEFF ) // 1.8
2523 	ROM_LOAD( "m2mr_n80.rom",   0x0000, 0x8000, CRC(f074b515) SHA1(ebe9cf4cf57f1602c887f609a728267f8d953dce) )
2524 
2525 	ROM_REGION( 0x10000, "n88rom", ROMREGION_ERASEFF ) // 2.2
2526 	ROM_LOAD( "m2mr_n88.rom",   0x0000, 0x8000, CRC(69caa38e) SHA1(3c64090237152ee77c76e04d6f36bad7297bea93) )
2527 	ROM_LOAD( "m2mr_n88_0.rom", 0x8000, 0x2000, CRC(710a63ec) SHA1(d239c26ad7ac5efac6e947b0e9549b1534aa970d) )
2528 	ROM_LOAD( "m2mr_n88_1.rom", 0xa000, 0x2000, CRC(e3e78a37) SHA1(85ecd287fe72b56e54c8b01ea7492ca4a69a7470) )
2529 	ROM_LOAD( "m2mr_n88_2.rom", 0xc000, 0x2000, CRC(11176e0b) SHA1(f13f14f3d62df61498a23f7eb624e1a646caea45) )
2530 	ROM_LOAD( "m2mr_n88_3.rom", 0xe000, 0x2000, CRC(0ca08abd) SHA1(a5a42d0b7caa84c3bc6e337c9f37874d82f9c14b) )
2531 
2532 	ROM_REGION( 0x10000, "fdccpu", 0)
2533 	ROM_LOAD( "m2mr_disk.rom", 0x0000, 0x2000, CRC(2447516b) SHA1(1492116f15c426f9796dc2bb6fcccf2656c0ca75) )
2534 
2535 	/* No idea of the proper size: it has never been dumped */
2536 	ROM_REGION( 0x2000, "audiocpu", 0)
2537 	ROM_LOAD( "soundbios.rom", 0x0000, 0x2000, NO_DUMP )
2538 
2539 	ROM_REGION( 0x40000, "kanji", 0)
2540 	ROM_LOAD( "kanji1.rom",      0x00000, 0x20000, CRC(6178bd43) SHA1(82e11a177af6a5091dd67f50a2f4bafda84d6556) )
2541 	ROM_LOAD( "m2mr_kanji2.rom", 0x20000, 0x20000, CRC(376eb677) SHA1(bcf96584e2ba362218b813be51ea21573d1a2a78) )
2542 
2543 	ROM_REGION( 0x800, "cgrom", 0)
2544 	ROM_COPY( "kanji", 0x1000, 0x0000, 0x800 )
2545 ROM_END
2546 
2547 ROM_START( pc8801mh )
2548 	PC8801_MEM_LOAD
2549 
2550 	ROM_REGION( 0x8000, "n80rom", ROMREGION_ERASEFF ) // 1.8, but different BIOS code?
2551 	ROM_LOAD( "mh_n80.rom",   0x0000, 0x8000, CRC(8a2a1e17) SHA1(06dae1db384aa29d81c5b6ed587877e7128fcb35) )
2552 
2553 	ROM_REGION( 0x10000, "n88rom", ROMREGION_ERASEFF ) // 2.3
2554 	ROM_LOAD( "mh_n88.rom",   0x0000, 0x8000, CRC(64c5d162) SHA1(3e0aac76fb5d7edc99df26fa9f365fd991742a5d) )
2555 	ROM_LOAD( "mh_n88_0.rom", 0x8000, 0x2000, CRC(deb384fb) SHA1(5f38cafa8aab16338038c82267800446fd082e79) )
2556 	ROM_LOAD( "mh_n88_1.rom", 0xa000, 0x2000, CRC(7ad5d943) SHA1(4ae4d37409ff99411a623da9f6a44192170a854e) )
2557 	ROM_LOAD( "mh_n88_2.rom", 0xc000, 0x2000, CRC(6aa6b6d8) SHA1(2a077ab444a4fd1470cafb06fd3a0f45420c39cc) )
2558 	ROM_LOAD( "mh_n88_3.rom", 0xe000, 0x2000, CRC(692cbcd8) SHA1(af452aed79b072c4d17985830b7c5dca64d4b412) )
2559 
2560 	ROM_REGION( 0x10000, "fdccpu", 0)
2561 	ROM_LOAD( "mh_disk.rom", 0x0000, 0x2000, CRC(a222ecf0) SHA1(79e9c0786a14142f7a83690bf41fb4f60c5c1004) )
2562 
2563 	/* No idea of the proper size: it has never been dumped */
2564 	ROM_REGION( 0x2000, "audiocpu", 0)
2565 	ROM_LOAD( "soundbios.rom", 0x0000, 0x2000, NO_DUMP )
2566 
2567 	ROM_REGION( 0x40000, "kanji", 0)
2568 	ROM_LOAD( "kanji1.rom",    0x00000, 0x20000, CRC(6178bd43) SHA1(82e11a177af6a5091dd67f50a2f4bafda84d6556) )
2569 	ROM_LOAD( "mh_kanji2.rom", 0x20000, 0x20000, CRC(376eb677) SHA1(bcf96584e2ba362218b813be51ea21573d1a2a78) )
2570 
2571 	ROM_REGION( 0x800, "cgrom", 0)
2572 	ROM_COPY( "kanji", 0x1000, 0x0000, 0x0800 )
2573 ROM_END
2574 
2575 ROM_START( pc8801fa )
2576 	PC8801_MEM_LOAD
2577 
2578 	ROM_REGION( 0x8000, "n80rom", ROMREGION_ERASEFF ) // 1.8, but different BIOS code?
2579 	ROM_LOAD( "fa_n80.rom",   0x0000, 0x8000, CRC(8a2a1e17) SHA1(06dae1db384aa29d81c5b6ed587877e7128fcb35) )
2580 
2581 	ROM_REGION( 0x10000, "n88rom", ROMREGION_ERASEFF ) // 2.3 but different BIOS code?
2582 	ROM_LOAD( "fa_n88.rom",   0x0000, 0x8000, CRC(73573432) SHA1(9b1346d44044eeea921c4cce69b5dc49dbc0b7e9) )
2583 	ROM_LOAD( "fa_n88_0.rom", 0x8000, 0x2000, CRC(a72697d7) SHA1(5aedbc5916d67ef28767a2b942864765eea81bb8) )
2584 	ROM_LOAD( "fa_n88_1.rom", 0xa000, 0x2000, CRC(7ad5d943) SHA1(4ae4d37409ff99411a623da9f6a44192170a854e) )
2585 	ROM_LOAD( "fa_n88_2.rom", 0xc000, 0x2000, CRC(6aee9a4e) SHA1(e94278682ef9e9bbb82201f72c50382748dcea2a) )
2586 	ROM_LOAD( "fa_n88_3.rom", 0xe000, 0x2000, CRC(692cbcd8) SHA1(af452aed79b072c4d17985830b7c5dca64d4b412) )
2587 
2588 	ROM_REGION( 0x10000, "fdccpu", 0)
2589 	ROM_LOAD( "fa_disk.rom", 0x0000, 0x0800, CRC(2163b304) SHA1(80da2dee49d4307f00895a129a5cfeff00cf5321) )
2590 
2591 	/* No idea of the proper size: it has never been dumped */
2592 	ROM_REGION( 0x2000, "audiocpu", 0)
2593 	ROM_LOAD( "soundbios.rom", 0x0000, 0x2000, NO_DUMP )
2594 
2595 	ROM_REGION( 0x40000, "kanji", 0 )
2596 	ROM_LOAD( "kanji1.rom",    0x00000, 0x20000, CRC(6178bd43) SHA1(82e11a177af6a5091dd67f50a2f4bafda84d6556) )
2597 	ROM_LOAD( "fa_kanji2.rom", 0x20000, 0x20000, CRC(376eb677) SHA1(bcf96584e2ba362218b813be51ea21573d1a2a78) )
2598 
2599 	ROM_REGION( 0x800, "cgrom", 0)
2600 	ROM_COPY( "kanji", 0x1000, 0x0000, 0x0800 )
2601 ROM_END
2602 
2603 ROM_START( pc8801ma ) // newer floppy BIOS and Jisyo (dictionary) ROM
2604 	PC8801_MEM_LOAD
2605 
2606 	ROM_REGION( 0x8000, "n80rom", ROMREGION_ERASEFF ) // 1.8, but different BIOS code?
2607 	ROM_LOAD( "ma_n80.rom",   0x0000, 0x8000, CRC(8a2a1e17) SHA1(06dae1db384aa29d81c5b6ed587877e7128fcb35) )
2608 
2609 	ROM_REGION( 0x10000, "n88rom", ROMREGION_ERASEFF ) // 2.3 but different BIOS code?
2610 	ROM_LOAD( "ma_n88.rom",   0x0000, 0x8000, CRC(73573432) SHA1(9b1346d44044eeea921c4cce69b5dc49dbc0b7e9) )
2611 	ROM_LOAD( "ma_n88_0.rom", 0x8000, 0x2000, CRC(a72697d7) SHA1(5aedbc5916d67ef28767a2b942864765eea81bb8) )
2612 	ROM_LOAD( "ma_n88_1.rom", 0xa000, 0x2000, CRC(7ad5d943) SHA1(4ae4d37409ff99411a623da9f6a44192170a854e) )
2613 	ROM_LOAD( "ma_n88_2.rom", 0xc000, 0x2000, CRC(6aee9a4e) SHA1(e94278682ef9e9bbb82201f72c50382748dcea2a) )
2614 	ROM_LOAD( "ma_n88_3.rom", 0xe000, 0x2000, CRC(692cbcd8) SHA1(af452aed79b072c4d17985830b7c5dca64d4b412) )
2615 
2616 	ROM_REGION( 0x10000, "fdccpu", 0)
2617 	ROM_LOAD( "ma_disk.rom", 0x0000, 0x2000, CRC(a222ecf0) SHA1(79e9c0786a14142f7a83690bf41fb4f60c5c1004) )
2618 
2619 	/* No idea of the proper size: it has never been dumped */
2620 	ROM_REGION( 0x2000, "audiocpu", 0)
2621 	ROM_LOAD( "soundbios.rom", 0x0000, 0x2000, NO_DUMP )
2622 
2623 	ROM_REGION( 0x40000, "kanji", 0 )
2624 	ROM_LOAD( "kanji1.rom",    0x00000, 0x20000, CRC(6178bd43) SHA1(82e11a177af6a5091dd67f50a2f4bafda84d6556) )
2625 	ROM_LOAD( "ma_kanji2.rom", 0x20000, 0x20000, CRC(376eb677) SHA1(bcf96584e2ba362218b813be51ea21573d1a2a78) )
2626 
2627 	ROM_REGION( 0x800, "cgrom", 0)
2628 	ROM_COPY( "kanji", 0x1000, 0x0000, 0x0800 )
2629 
2630 	/* 32 banks, to be loaded at 0xc000 - 0xffff */
2631 	ROM_REGION( 0x80000, "dictionary", 0 )
2632 	ROM_LOAD( "ma_jisyo.rom", 0x00000, 0x80000, CRC(a6108f4d) SHA1(3665db538598abb45d9dfe636423e6728a812b12) )
2633 ROM_END
2634 
2635 ROM_START( pc8801ma2 )
2636 	PC8801_MEM_LOAD
2637 
2638 	ROM_REGION( 0x8000, "n80rom", ROMREGION_ERASEFF ) // 1.8
2639 	ROM_LOAD( "ma2_n80.rom",   0x0000, 0x8000, CRC(8a2a1e17) SHA1(06dae1db384aa29d81c5b6ed587877e7128fcb35) )
2640 
2641 	ROM_REGION( 0x10000, "n88rom", ROMREGION_ERASEFF ) // 2.3 (2.31?)
2642 	ROM_LOAD( "ma2_n88.rom",   0x0000, 0x8000, CRC(ae1a6ebc) SHA1(e53d628638f663099234e07837ffb1b0f86d480d) )
2643 	ROM_LOAD( "ma2_n88_0.rom", 0x8000, 0x2000, CRC(a72697d7) SHA1(5aedbc5916d67ef28767a2b942864765eea81bb8) )
2644 	ROM_LOAD( "ma2_n88_1.rom", 0xa000, 0x2000, CRC(7ad5d943) SHA1(4ae4d37409ff99411a623da9f6a44192170a854e) )
2645 	ROM_LOAD( "ma2_n88_2.rom", 0xc000, 0x2000, CRC(1d6277b6) SHA1(dd9c3e50169b75bb707ef648f20d352e6a8bcfe4) )
2646 	ROM_LOAD( "ma2_n88_3.rom", 0xe000, 0x2000, CRC(692cbcd8) SHA1(af452aed79b072c4d17985830b7c5dca64d4b412) )
2647 
2648 	ROM_REGION( 0x10000, "fdccpu", 0)
2649 	ROM_LOAD( "ma2_disk.rom", 0x0000, 0x2000, CRC(a222ecf0) SHA1(79e9c0786a14142f7a83690bf41fb4f60c5c1004) )
2650 
2651 	/* No idea of the proper size: it has never been dumped */
2652 	ROM_REGION( 0x2000, "audiocpu", 0)
2653 	ROM_LOAD( "soundbios.rom", 0x0000, 0x2000, NO_DUMP )
2654 
2655 	ROM_REGION( 0x40000, "kanji", 0)
2656 	ROM_LOAD( "kanji1.rom",     0x00000, 0x20000, CRC(6178bd43) SHA1(82e11a177af6a5091dd67f50a2f4bafda84d6556) )
2657 	ROM_LOAD( "ma2_kanji2.rom", 0x20000, 0x20000, CRC(376eb677) SHA1(bcf96584e2ba362218b813be51ea21573d1a2a78) )
2658 
2659 	ROM_REGION( 0x800, "cgrom", 0)
2660 	ROM_COPY( "kanji", 0x1000, 0x0000, 0x0800 )
2661 
2662 	ROM_REGION( 0x80000, "dictionary", 0 )
2663 	ROM_LOAD( "ma2_jisyo.rom", 0x00000, 0x80000, CRC(856459af) SHA1(06241085fc1d62d4b2968ad9cdbdadc1e7d7990a) )
2664 ROM_END
2665 
2666 ROM_START( pc8801mc )
2667 	PC8801_MEM_LOAD
2668 
2669 	ROM_REGION( 0x08000, "n80rom", ROMREGION_ERASEFF ) // 1.8
2670 	ROM_LOAD( "mc_n80.rom",   0x0000, 0x8000, CRC(8a2a1e17) SHA1(06dae1db384aa29d81c5b6ed587877e7128fcb35) )
2671 
2672 	ROM_REGION( 0x10000, "n88rom", ROMREGION_ERASEFF ) // 2.3 (2.33?)
2673 	ROM_LOAD( "mc_n88.rom",   0x0000, 0x8000, CRC(356d5719) SHA1(5d9ba80d593a5119f52aae1ccd61a1457b4a89a1) )
2674 	ROM_LOAD( "mc_n88_0.rom", 0x8000, 0x2000, CRC(a72697d7) SHA1(5aedbc5916d67ef28767a2b942864765eea81bb8) )
2675 	ROM_LOAD( "mc_n88_1.rom", 0xa000, 0x2000, CRC(7ad5d943) SHA1(4ae4d37409ff99411a623da9f6a44192170a854e) )
2676 	ROM_LOAD( "mc_n88_2.rom", 0xc000, 0x2000, CRC(1d6277b6) SHA1(dd9c3e50169b75bb707ef648f20d352e6a8bcfe4) )
2677 	ROM_LOAD( "mc_n88_3.rom", 0xe000, 0x2000, CRC(692cbcd8) SHA1(af452aed79b072c4d17985830b7c5dca64d4b412) )
2678 
2679 	ROM_REGION( 0x10000, "fdccpu", 0)
2680 	ROM_LOAD( "mc_disk.rom", 0x0000, 0x2000, CRC(a222ecf0) SHA1(79e9c0786a14142f7a83690bf41fb4f60c5c1004) )
2681 
2682 	ROM_REGION( 0x10000, "cdrom", 0 )
2683 	ROM_LOAD( "cdbios.rom", 0x0000, 0x10000, CRC(5c230221) SHA1(6394a8a23f44ea35fcfc3e974cf940bc8f84d62a) )
2684 
2685 	/* No idea of the proper size: it has never been dumped */
2686 	ROM_REGION( 0x2000, "audiocpu", 0)
2687 	ROM_LOAD( "soundbios.rom", 0x0000, 0x2000, NO_DUMP )
2688 
2689 	ROM_REGION( 0x40000, "kanji", 0 )
2690 	ROM_LOAD( "kanji1.rom",    0x00000, 0x20000, CRC(6178bd43) SHA1(82e11a177af6a5091dd67f50a2f4bafda84d6556) )
2691 	ROM_LOAD( "mc_kanji2.rom", 0x20000, 0x20000, CRC(376eb677) SHA1(bcf96584e2ba362218b813be51ea21573d1a2a78) )
2692 
2693 	ROM_REGION( 0x800, "cgrom", 0)
2694 	ROM_COPY( "kanji", 0x1000, 0x0000, 0x0800 )
2695 
2696 	ROM_REGION( 0x80000, "dictionary", 0 )
2697 	ROM_LOAD( "mc_jisyo.rom", 0x00000, 0x80000, CRC(bd6eb062) SHA1(deef0cc2a9734ba891a6d6c022aa70ffc66f783e) )
2698 ROM_END
2699 
2700 /* System Drivers */
2701 
2702 /*    YEAR  NAME         PARENT  COMPAT  MACHINE      INPUT   CLASS         INIT        COMPANY  FULLNAME */
2703 
2704 COMP( 1981, pc8801,      0,      0,      pc8801,      pc88sr, pc8801_state, empty_init, "NEC",   "PC-8801",       MACHINE_NOT_WORKING )
2705 COMP( 1983, pc8801mk2,   pc8801, 0,      pc8801,      pc88sr, pc8801_state, empty_init, "NEC",   "PC-8801mkII",   MACHINE_NOT_WORKING )
2706 COMP( 1985, pc8801mk2sr, pc8801, 0,      pc8801,      pc88sr, pc8801_state, empty_init, "NEC",   "PC-8801mkIISR", MACHINE_NOT_WORKING )
2707 //COMP( 1985, pc8801mk2tr, pc8801, 0,      pc8801,      pc88sr, pc8801_state, empty_init, "NEC",   "PC-8801mkIITR", MACHINE_NOT_WORKING )
2708 COMP( 1985, pc8801mk2fr, pc8801, 0,      pc8801,      pc88sr, pc8801_state, empty_init, "NEC",   "PC-8801mkIIFR", MACHINE_NOT_WORKING )
2709 COMP( 1985, pc8801mk2mr, pc8801, 0,      pc8801,      pc88sr, pc8801_state, empty_init, "NEC",   "PC-8801mkIIMR", MACHINE_NOT_WORKING )
2710 
2711 //COMP( 1986, pc8801fh,    0,      0,      pc8801,      pc88sr, pc8801_state, empty_init, "NEC",   "PC-8801FH",     MACHINE_NOT_WORKING )
2712 COMP( 1986, pc8801mh,    pc8801, 0,      pc8801fh,    pc88sr, pc8801_state, empty_init, "NEC",   "PC-8801MH",     MACHINE_NOT_WORKING )
2713 COMP( 1987, pc8801fa,    pc8801, 0,      pc8801fh,    pc88sr, pc8801_state, empty_init, "NEC",   "PC-8801FA",     MACHINE_NOT_WORKING )
2714 COMP( 1987, pc8801ma,    pc8801, 0,      pc8801ma,    pc88sr, pc8801_state, empty_init, "NEC",   "PC-8801MA",     MACHINE_NOT_WORKING )
2715 //COMP( 1988, pc8801fe,    pc8801, 0,      pc8801,      pc88sr, pc8801_state, empty_init, "NEC",   "PC-8801FE",     MACHINE_NOT_WORKING )
2716 COMP( 1988, pc8801ma2,   pc8801, 0,      pc8801ma,    pc88sr, pc8801_state, empty_init, "NEC",   "PC-8801MA2",    MACHINE_NOT_WORKING )
2717 //COMP( 1989, pc8801fe2,   pc8801, 0,      pc8801,      pc88sr, pc8801_state, empty_init, "NEC",   "PC-8801FE2",    MACHINE_NOT_WORKING )
2718 COMP( 1989, pc8801mc,    pc8801, 0,      pc8801mc,    pc88sr, pc8801_state, empty_init, "NEC",   "PC-8801MC",     MACHINE_NOT_WORKING )
2719 
2720 //COMP( 1989, pc98do,      0,      0,      pc88va,      pc88sr, pc8801_state, empty_init, "NEC",   "PC-98DO",       MACHINE_NOT_WORKING )
2721 //COMP( 1990, pc98dop,     0,      0,      pc88va,      pc88sr, pc8801_state, empty_init, "NEC",   "PC-98DO+",      MACHINE_NOT_WORKING )
2722