1 // license:BSD-3-Clause
2 // copyright-holders:Angelo Salese
3 /********************************************************************************************************************************
4 
5     Sharp MZ-2500 (c) 1985 Sharp Corporation
6 
7     driver by Angelo Salese
8 
9     Computer box contains 2 floppy drives on the right, and a front-loading cassette player on the left.
10     Keyboard is separate, and the key layout is very similar to the fm7.
11 
12     TODO:
13     - Kanji text is cutted in half when font_size is 1 / interlace is disabled, different ROM used? (check Back to the Future);
14     - Implement external ROM hook-up;
15     - Add remaining missing peripherals, SIO, HDD and w1300a network;
16     - FDC loading without the IPLPRO doesn't work at all, why?
17     - reverse / blanking tvram attributes;
18     - clean-ups! ^^'
19 
20     per-game/program specific TODO:
21     - Dust Box vol. 1-3: they die with text garbage, might be bad dumps;
22     - Dust Box vol. 4: window effect transition is bugged;
23     - Dust Box vol. n: three items returns "purple" text, presumably HW failures (DFJustin: joystick "digital", mouse "not installed", HDD "not installed");
24     - LayDock: hangs at title screen due of a PIT bug (timer irq dies for whatever reason);
25     - Moon Child: needs mixed 3+3bpp tvram supported, kludged for now (not a real test case);
26     - Moon Child: window masking doesn't mask bottom part of the screen?
27     - Moon Child: appears to be a network / system link game, obviously doesn't work with current MAME / MESS framework;
28     - Marchen Veil I: doesn't load if you try to run it directly, it does if you load another game first (for example Mappy) then do a soft reset;
29     - Mugen no Shinzou II - The Prince of Darkness: dies on IPLPRO loading, presumably a wd17xx core bug;
30     - Multiplan: random hangs/crashes after you set the RTC, sometimes it loads properly;
31     - Murder Club: has lots of CG artifacts, FDC issue?
32     - Orrbit 3: floppy issue makes it to throw a game over as soon as you start a game;
33     - Penguin Kun Wars: has a bug with window effects ("Push space or trigger" msg on the bottom"), needs investigation;
34     - Sound Gal Music Editor: wants a "master disk", that apparently isn't available;
35     - Yukar K2 (normal version): moans about something, DFJustin: "please put the system disk back to normal", disk write-protected?
36 
37 ********************************************************************************************************************************/
38 
39 #include "emu.h"
40 #include "includes/mz2500.h"
41 
42 
43 /* machine stuff */
44 
45 #define WRAM_RESET 0
46 #define IPL_RESET 1
47 
48 static constexpr uint8_t bank_reset_val[2][8] =
49 {
50 	{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 },
51 	{ 0x34, 0x35, 0x36, 0x37, 0x04, 0x05, 0x06, 0x07 }
52 };
53 
54 /* video stuff*/
55 
video_start()56 void mz2500_state::video_start()
57 {
58 }
59 
60 /*
61 [0] xxxx xxxx tile
62 [1] ---- -xxx color offset
63 [1] ---- x--- PCG combine mode
64 [1] --xx ---- PCG select
65 [1] xx-- ---- reverse / blink attributes
66 [2] --xx xxxx tile bank (for kanji ROMs)
67 [2] xx-- ---- kanji select
68 */
69 
70 /* helper function, to draw stuff without getting crazy with height / width conditions :) */
mz2500_draw_pixel(bitmap_ind16 & bitmap,int x,int y,uint16_t pen,uint8_t width,uint8_t height)71 void mz2500_state::mz2500_draw_pixel(bitmap_ind16 &bitmap,int x,int y,uint16_t  pen,uint8_t width,uint8_t height)
72 {
73 	if(width && height)
74 	{
75 		bitmap.pix(y*2+0, x*2+0) = m_palette->pen(pen);
76 		bitmap.pix(y*2+0, x*2+1) = m_palette->pen(pen);
77 		bitmap.pix(y*2+1, x*2+0) = m_palette->pen(pen);
78 		bitmap.pix(y*2+1, x*2+1) = m_palette->pen(pen);
79 	}
80 	else if(width)
81 	{
82 		bitmap.pix(y, x*2+0) = m_palette->pen(pen);
83 		bitmap.pix(y, x*2+1) = m_palette->pen(pen);
84 	}
85 	else if(height)
86 	{
87 		bitmap.pix(y*2+0, x) = m_palette->pen(pen);
88 		bitmap.pix(y*2+1, x) = m_palette->pen(pen);
89 	}
90 	else
91 		bitmap.pix(y, x) = m_palette->pen(pen);
92 }
93 
draw_80x25(bitmap_ind16 & bitmap,const rectangle & cliprect,uint16_t map_addr)94 void mz2500_state::draw_80x25(bitmap_ind16 &bitmap,const rectangle &cliprect,uint16_t map_addr)
95 {
96 	uint8_t *vram = m_tvram;
97 	int x,y,count,xi,yi;
98 	uint8_t *gfx_data;
99 	uint8_t y_step;
100 	uint8_t s_y;
101 	uint8_t y_height;
102 
103 	count = (map_addr & 0x7ff);
104 
105 	y_step = (m_text_font_reg) ? 1 : 2;
106 	y_height = (m_text_reg[0] & 0x10) ? 10 : 8;
107 	s_y = m_text_reg[9] & 0xf;
108 
109 	for (y=0;y<26*y_step;y+=y_step)
110 	{
111 		for (x=0;x<80;x++)
112 		{
113 			int tile = vram[count+0x0000] & 0xff;
114 			int attr = vram[count+0x0800];
115 			int tile_bank = vram[count+0x1000] & 0x3f;
116 			int gfx_sel = (attr & 0x38) | (vram[count+0x1000] & 0xc0);
117 			int color = attr & 7;
118 			int inv_col = (attr & 0x40) >> 6;
119 
120 			if(gfx_sel & 8) // Xevious, PCG 8 colors have priority above kanji roms
121 				gfx_data = m_pcg_ram.get();
122 			else if(gfx_sel == 0x80)
123 			{
124 				gfx_data = m_kanji_rom;
125 				tile|= tile_bank << 8;
126 				if(y_step == 2)
127 					tile &= 0x3ffe;
128 			}
129 			else if(gfx_sel == 0xc0)
130 			{
131 				gfx_data = m_kanji_rom;
132 				tile|= (tile_bank << 8);
133 				if(y_step == 2)
134 					tile &= 0x3ffe;
135 				tile|=0x4000;
136 			}
137 			else
138 			{
139 				gfx_data = m_pcg_ram.get();
140 			}
141 
142 			for(yi=0;yi<8*y_step;yi++)
143 			{
144 				for(xi=0;xi<8;xi++)
145 				{
146 					uint8_t pen_bit[3],pen;
147 					int res_x,res_y;
148 
149 					res_x = x*8+xi;
150 					res_y = y*y_height+yi-s_y;
151 
152 					/* check TV window boundaries */
153 					if(res_x < m_tv_hs || res_x >= m_tv_he || res_y < m_tv_vs || res_y >= m_tv_ve)
154 						continue;
155 
156 					if(gfx_sel & 0x8)
157 					{
158 						pen_bit[0] = ((gfx_data[tile*8+yi+0x1800]>>(7-xi)) & 1) ? (4+8) : 0; //G
159 						pen_bit[1] = ((gfx_data[tile*8+yi+0x1000]>>(7-xi)) & 1) ? (2+8) : 0; //R
160 						pen_bit[2] = ((gfx_data[tile*8+yi+0x0800]>>(7-xi)) & 1) ? (1+8) : 0; //B
161 
162 						pen = (pen_bit[0]|pen_bit[1]|pen_bit[2]);
163 
164 						//if(inv_col) { pen ^= 7; } breaks Mappy
165 					}
166 					else
167 						pen = (((gfx_data[tile*8+yi+((gfx_sel & 0x30)<<7)]>>(7-xi)) & 1) ^ inv_col) ? (color+8) : 0;
168 
169 					if(pen)
170 					{
171 						if((res_y) >= 0 && (res_y) < 200*y_step)
172 							mz2500_draw_pixel(bitmap,res_x,res_y,pen+(m_pal_select ? 0x00 : 0x10),0,0);
173 					}
174 				}
175 			}
176 
177 			count++;
178 			count&=0x7ff;
179 		}
180 	}
181 }
182 
draw_40x25(bitmap_ind16 & bitmap,const rectangle & cliprect,int plane,uint16_t map_addr)183 void mz2500_state::draw_40x25(bitmap_ind16 &bitmap,const rectangle &cliprect,int plane,uint16_t map_addr)
184 {
185 	uint8_t *vram = m_tvram;
186 	int x,y,count,xi,yi;
187 	uint8_t *gfx_data;
188 	uint8_t y_step;
189 	uint8_t s_y;
190 	uint8_t y_height;
191 
192 	count = (((plane * 0x400) + map_addr) & 0x7ff);
193 
194 	y_step = (m_text_font_reg) ? 1 : 2;
195 	y_height = (m_text_reg[0] & 0x10) ? 10 : 8;
196 	s_y = m_text_reg[9] & 0xf;
197 
198 	for (y=0;y<26*y_step;y+=y_step)
199 	{
200 		for (x=0;x<40;x++)
201 		{
202 			int tile = vram[count+0x0000] & 0xff;
203 			int attr = vram[count+0x0800];
204 			int tile_bank = vram[count+0x1000] & 0x3f;
205 			int gfx_sel = (attr & 0x38) | (vram[count+0x1000] & 0xc0);
206 			//int gfx_num;
207 			int color = attr & 7;
208 			int inv_col = (attr & 0x40) >> 6;
209 
210 			if(gfx_sel & 8) // Xevious, PCG 8 colors have priority above kanji roms
211 				gfx_data = m_pcg_ram.get();
212 			else if(gfx_sel == 0x80)
213 			{
214 				gfx_data = m_kanji_rom;
215 				tile|= tile_bank << 8;
216 				if(y_step == 2)
217 					tile &= 0x3ffe;
218 			}
219 			else if(gfx_sel == 0xc0)
220 			{
221 				gfx_data = m_kanji_rom;
222 				tile|= (tile_bank << 8);
223 				if(y_step == 2)
224 					tile &= 0x3ffe;
225 				tile|=0x4000;
226 			}
227 			else
228 			{
229 				gfx_data = m_pcg_ram.get();
230 			}
231 
232 			for(yi=0;yi<8*y_step;yi++)
233 			{
234 				for(xi=0;xi<8;xi++)
235 				{
236 					uint8_t pen_bit[3],pen;
237 					int res_x,res_y;
238 
239 					res_x = x*8+xi;
240 					res_y = y*y_height+yi-s_y;
241 
242 					/* check TV window boundaries */
243 					if(res_x < m_tv_hs || res_x >= m_tv_he || res_y < m_tv_vs || res_y >= m_tv_ve)
244 						continue;
245 
246 					if(gfx_sel & 0x8)
247 					{
248 						pen_bit[0] = ((gfx_data[tile*8+yi+0x1800]>>(7-xi)) & 1) ? (4+8) : 0; //G
249 						pen_bit[1] = ((gfx_data[tile*8+yi+0x1000]>>(7-xi)) & 1) ? (2+8) : 0; //R
250 						pen_bit[2] = ((gfx_data[tile*8+yi+0x0800]>>(7-xi)) & 1) ? (1+8) : 0; //B
251 
252 						pen = (pen_bit[0]|pen_bit[1]|pen_bit[2]);
253 
254 						//if(inv_col) { pen ^= 7; } breaks Mappy
255 					}
256 					else
257 						pen = (((gfx_data[tile*8+yi+((gfx_sel & 0x30)<<7)]>>(7-xi)) & 1) ^ inv_col) ? (color+8) : 0;
258 
259 					if(pen)
260 					{
261 						if((res_y) >= 0 && (res_y) < 200*y_step)
262 							mz2500_draw_pixel(bitmap,res_x,res_y,pen+(m_pal_select ? 0x00 : 0x10),m_scr_x_size == 640,0);
263 					}
264 				}
265 			}
266 
267 			count++;
268 			count&=0x7ff;
269 		}
270 	}
271 }
272 
draw_cg4_screen(bitmap_ind16 & bitmap,const rectangle & cliprect,int pri)273 void mz2500_state::draw_cg4_screen(bitmap_ind16 &bitmap,const rectangle &cliprect,int pri)
274 {
275 	uint32_t count;
276 	uint8_t *vram = m_cgram;
277 	uint8_t pen,pen_bit[2];
278 	int x,y,xi,pen_i;
279 	int res_x,res_y;
280 
281 	count = 0x0000;
282 
283 	for(y=0;y<400;y++)
284 	{
285 		for(x=0;x<640;x+=8)
286 		{
287 			for(xi=0;xi<8;xi++)
288 			{
289 				res_x = x+xi;
290 				res_y = y;
291 
292 				/* check window boundaries */
293 				//if(res_x < m_cg_hs || res_x >= m_cg_he || res_y < m_cg_vs || res_y >= m_cg_ve)
294 				//  continue;
295 
296 				/* TODO: very preliminary, just Yukar K2 uses this so far*/
297 				pen_bit[0] = (vram[count + 0x00000]>>(xi)) & 1 ? 7 : 0; // B
298 				pen_bit[1] = (vram[count + 0x0c000]>>(xi)) & 1 ? 7 : 0; // R
299 
300 				pen = 0;
301 				for(pen_i=0;pen_i<2;pen_i++)
302 					pen |= pen_bit[pen_i];
303 
304 				{
305 					//if(pri == ((m_clut256[pen] & 0x100) >> 8))
306 					mz2500_draw_pixel(bitmap,res_x,res_y,pen,0,0);
307 				}
308 			}
309 			count++;
310 		}
311 	}
312 }
313 
draw_cg16_screen(bitmap_ind16 & bitmap,const rectangle & cliprect,int plane,int x_size,int pri)314 void mz2500_state::draw_cg16_screen(bitmap_ind16 &bitmap,const rectangle &cliprect,int plane,int x_size,int pri)
315 {
316 	uint32_t count;
317 	uint8_t *vram = m_cgram; //TODO
318 	uint8_t pen,pen_bit[4];
319 	int x,y,xi,pen_i;
320 	uint32_t wa_reg;
321 	uint8_t s_x;
322 	uint8_t base_mask;
323 	int res_x,res_y;
324 	uint8_t cg_interlace;
325 	uint8_t pen_mask;
326 
327 	base_mask = (x_size == 640) ? 0x3f : 0x1f;
328 
329 	count = (m_cg_reg[0x10]) | ((m_cg_reg[0x11] & base_mask) << 8);
330 	wa_reg = (m_cg_reg[0x12]) | ((m_cg_reg[0x13] & base_mask) << 8);
331 	/* TODO: layer 2 scrolling */
332 	s_x = (m_cg_reg[0x0f] & 0xf);
333 	cg_interlace = m_text_font_reg ? 1 : 2;
334 	pen_mask = (m_cg_reg[0x18] >> ((plane & 1) * 4)) & 0x0f;
335 
336 //  popmessage("%d %d %d %d",m_cg_hs,m_cg_he,m_cg_vs,m_cg_ve);
337 
338 	for(y=0;y<200;y++)
339 	{
340 		for(x=0;x<x_size;x+=8)
341 		{
342 			for(xi=0;xi<8;xi++)
343 			{
344 				res_x = x+xi+s_x;
345 				res_y = y;
346 
347 				/* check window boundaries */
348 				if(res_x < m_cg_hs || res_x >= m_cg_he || res_y < m_cg_vs || res_y >= m_cg_ve)
349 					continue;
350 
351 				pen_bit[0] = (vram[count+0x0000+((plane & 1) * 0x2000)+(((plane & 2)>>1) * 0x10000)]>>(xi)) & 1 ? (pen_mask & 0x01) : 0; //B
352 				pen_bit[1] = (vram[count+0x4000+((plane & 1) * 0x2000)+(((plane & 2)>>1) * 0x10000)]>>(xi)) & 1 ? (pen_mask & 0x02) : 0; //R
353 				pen_bit[2] = (vram[count+0x8000+((plane & 1) * 0x2000)+(((plane & 2)>>1) * 0x10000)]>>(xi)) & 1 ? (pen_mask & 0x04) : 0; //G
354 				pen_bit[3] = (vram[count+0xc000+((plane & 1) * 0x2000)+(((plane & 2)>>1) * 0x10000)]>>(xi)) & 1 ? (pen_mask & 0x08) : 0; //I
355 
356 				pen = 0;
357 				for(pen_i=0;pen_i<4;pen_i++)
358 					pen |= pen_bit[pen_i];
359 
360 				if(pri == ((m_clut16[pen] & 0x10) >> 4) && m_clut16[pen] != 0x00 && pen_mask) //correct?
361 					mz2500_draw_pixel(bitmap,res_x,res_y,(m_clut16[pen] & 0x0f)+0x10,(x_size == 320 && m_scr_x_size == 640),cg_interlace == 2);
362 			}
363 			count++;
364 			count&=((base_mask<<8) | 0xff);
365 			if(count > wa_reg)
366 				count = 0;
367 		}
368 	}
369 }
370 
draw_cg256_screen(bitmap_ind16 & bitmap,const rectangle & cliprect,int plane,int pri)371 void mz2500_state::draw_cg256_screen(bitmap_ind16 &bitmap,const rectangle &cliprect,int plane,int pri)
372 {
373 	uint32_t count;
374 	uint8_t *vram = m_cgram;
375 	uint8_t pen,pen_bit[8];
376 	int x,y,xi,pen_i;
377 	uint32_t wa_reg;
378 	uint8_t s_x;
379 	uint8_t base_mask;
380 	int res_x,res_y;
381 	uint8_t cg_interlace;
382 
383 	base_mask = 0x3f; //no x_size == 640
384 
385 	count = (m_cg_reg[0x10]) | ((m_cg_reg[0x11] & base_mask) << 8);
386 	wa_reg = (m_cg_reg[0x12]) | ((m_cg_reg[0x13] & base_mask) << 8);
387 	/* TODO: layer 2 scrolling */
388 	s_x = (m_cg_reg[0x0f] & 0xf);
389 	cg_interlace = m_text_font_reg ? 1 : 2;
390 
391 	for(y=0;y<200;y++)
392 	{
393 		for(x=0;x<320;x+=8)
394 		{
395 			for(xi=0;xi<8;xi++)
396 			{
397 				res_x = x+xi+s_x;
398 				res_y = y;
399 
400 				/* check window boundaries */
401 				if(res_x < m_cg_hs || res_x >= m_cg_he || res_y < m_cg_vs || res_y >= m_cg_ve)
402 					continue;
403 
404 				pen_bit[0] = (vram[count + 0x0000 + (((plane & 2)>>1) * 0x10000) + 0x2000]>>(xi)) & 1 ? (m_cg_reg[0x18] & 0x10) : 0; // B1
405 				pen_bit[1] = (vram[count + 0x0000 + (((plane & 2)>>1) * 0x10000) + 0x0000]>>(xi)) & 1 ? (m_cg_reg[0x18] & 0x01) : 0; // B0
406 				pen_bit[2] = (vram[count + 0x0000 + (((plane & 2)>>1) * 0x10000) + 0x6000]>>(xi)) & 1 ? (m_cg_reg[0x18] & 0x20) : 0; // R1
407 				pen_bit[3] = (vram[count + 0x0000 + (((plane & 2)>>1) * 0x10000) + 0x4000]>>(xi)) & 1 ? (m_cg_reg[0x18] & 0x02) : 0; // R0
408 				pen_bit[4] = (vram[count + 0x0000 + (((plane & 2)>>1) * 0x10000) + 0xa000]>>(xi)) & 1 ? (m_cg_reg[0x18] & 0x40) : 0; // G1
409 				pen_bit[5] = (vram[count + 0x0000 + (((plane & 2)>>1) * 0x10000) + 0x8000]>>(xi)) & 1 ? (m_cg_reg[0x18] & 0x04) : 0; // G0
410 				pen_bit[6] = (vram[count + 0x0000 + (((plane & 2)>>1) * 0x10000) + 0xe000]>>(xi)) & 1 ? (m_cg_reg[0x18] & 0x80) : 0; // I1
411 				pen_bit[7] = (vram[count + 0x0000 + (((plane & 2)>>1) * 0x10000) + 0xc000]>>(xi)) & 1 ? (m_cg_reg[0x18] & 0x08) : 0; // I0
412 
413 				pen = 0;
414 				for(pen_i=0;pen_i<8;pen_i++)
415 					pen |= pen_bit[pen_i];
416 
417 				if(pri == ((m_clut256[pen] & 0x100) >> 8))
418 					mz2500_draw_pixel(bitmap,res_x,res_y,(m_clut256[pen] & 0xff)+0x100,m_scr_x_size == 640,cg_interlace == 2);
419 			}
420 			count++;
421 			count&=((base_mask<<8) | 0xff);
422 			if(count > wa_reg)
423 				count = 0;
424 		}
425 	}
426 }
427 
draw_tv_screen(bitmap_ind16 & bitmap,const rectangle & cliprect)428 void mz2500_state::draw_tv_screen(bitmap_ind16 &bitmap,const rectangle &cliprect)
429 {
430 	uint16_t base_addr;
431 
432 	base_addr = m_text_reg[1] | ((m_text_reg[2] & 0x7) << 8);
433 
434 //  popmessage("%02x",m_clut16[0]);
435 //  popmessage("%d %d %d %d",m_tv_hs,(m_tv_he),m_tv_vs,(m_tv_ve));
436 
437 	if(m_text_col_size)
438 		draw_80x25(bitmap,cliprect,base_addr);
439 	else
440 	{
441 		int tv_mode;
442 
443 		tv_mode = m_text_reg[0] >> 2;
444 
445 		switch(tv_mode & 3)
446 		{
447 			case 0: //mixed 6bpp mode, TODO
448 				draw_40x25(bitmap,cliprect,0,base_addr);
449 				break;
450 			case 1:
451 				draw_40x25(bitmap,cliprect,0,base_addr);
452 				break;
453 			case 2:
454 				draw_40x25(bitmap,cliprect,1,base_addr);
455 				break;
456 			case 3:
457 				draw_40x25(bitmap,cliprect,1,base_addr);
458 				draw_40x25(bitmap,cliprect,0,base_addr);
459 				break;
460 			//default: popmessage("%02x %02x %02x",tv_mode & 3,m_text_reg[1],m_text_reg[2]); break;
461 		}
462 	}
463 }
464 
draw_cg_screen(bitmap_ind16 & bitmap,const rectangle & cliprect,int pri)465 void mz2500_state::draw_cg_screen(bitmap_ind16 &bitmap,const rectangle &cliprect,int pri)
466 {
467 	//popmessage("%02x %02x",m_cg_reg[0x0e],m_cg_reg[0x18]);
468 
469 	switch(m_cg_reg[0x0e])
470 	{
471 		case 0x00:
472 			break;
473 		case 0x03:
474 			draw_cg4_screen(bitmap,cliprect,0);
475 			break;
476 		case 0x14:
477 			draw_cg16_screen(bitmap,cliprect,0,320,pri);
478 			draw_cg16_screen(bitmap,cliprect,1,320,pri);
479 			break;
480 		case 0x15:
481 			draw_cg16_screen(bitmap,cliprect,1,320,pri);
482 			draw_cg16_screen(bitmap,cliprect,0,320,pri);
483 			break;
484 		case 0x17:
485 			draw_cg16_screen(bitmap,cliprect,0,640,pri);
486 			break;
487 		case 0x1d:
488 			draw_cg256_screen(bitmap,cliprect,0,pri);
489 			break;
490 		case 0x97:
491 			draw_cg16_screen(bitmap,cliprect,2,640,pri);
492 			break;
493 		default:
494 			popmessage("Unsupported CG mode %02x, contact MESS dev",m_cg_reg[0x0e]);
495 			break;
496 	}
497 }
498 
screen_update_mz2500(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)499 uint32_t mz2500_state::screen_update_mz2500(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
500 {
501 	bitmap.fill(m_palette->pen(0), cliprect); //TODO: correct?
502 
503 	if(m_screen_enable)
504 		return 0;
505 
506 	draw_cg_screen(bitmap,cliprect,0);
507 	draw_tv_screen(bitmap,cliprect);
508 	draw_cg_screen(bitmap,cliprect,1);
509 	//  popmessage("%02x (%02x %02x) (%02x %02x) (%02x %02x) (%02x %02x)",m_cg_reg[0x0f],m_cg_reg[0x10],m_cg_reg[0x11],m_cg_reg[0x12],m_cg_reg[0x13],m_cg_reg[0x14],m_cg_reg[0x15],m_cg_reg[0x16],m_cg_reg[0x17]);
510 	//  popmessage("%02x",m_text_reg[0x0f]);
511 
512 
513 	return 0;
514 }
515 
mz2500_reconfigure_screen()516 void mz2500_state::mz2500_reconfigure_screen()
517 {
518 	rectangle visarea;
519 
520 	if((m_cg_reg[0x0e] & 0x1f) == 0x17 || (m_cg_reg[0x0e] & 0x1f) == 0x03 || m_text_col_size)
521 		m_scr_x_size = 640;
522 	else
523 		m_scr_x_size = 320;
524 
525 	if((m_cg_reg[0x0e] & 0x1f) == 0x03)
526 		m_scr_y_size = 400;
527 	else
528 		m_scr_y_size = 200 * ((m_text_font_reg) ? 1 : 2);
529 
530 	visarea.set(0, m_scr_x_size - 1, 0, m_scr_y_size - 1);
531 
532 	//popmessage("%d %d %d %d %02x",vs,ve,hs,he,m_cg_reg[0x0e]);
533 
534 	m_screen->configure(720, 480, visarea, m_screen->frame_period().attoseconds());
535 
536 	/* calculate CG window parameters here */
537 	m_cg_vs = (m_cg_reg[0x08]) | ((m_cg_reg[0x09]<<8) & 1);
538 	m_cg_ve = (m_cg_reg[0x0a]) | ((m_cg_reg[0x0b]<<8) & 1);
539 	m_cg_hs = ((m_cg_reg[0x0c] & 0x7f)*8);
540 	m_cg_he = ((m_cg_reg[0x0d] & 0x7f)*8);
541 
542 	if(m_scr_x_size == 320)
543 	{
544 		m_cg_hs /= 2;
545 		m_cg_he /= 2;
546 	}
547 
548 	/* calculate TV window parameters here */
549 	{
550 		int x_offs,y_offs;
551 
552 		m_monitor_type = ((m_text_reg[0x0f] & 0x08) >> 3);
553 
554 		switch((m_monitor_type|m_text_col_size<<1) & 3)
555 		{
556 			default:
557 			case 0: x_offs = 64; break;
558 			case 1: x_offs = 80; break;
559 			case 2: x_offs = 72; break;
560 			case 3: x_offs = 88; break;
561 		}
562 		//printf("%d %d %d\n",x_offs,(m_text_reg[7] & 0x7f) * 8,(m_text_reg[8] & 0x7f)* 8);
563 
564 		y_offs = (m_monitor_type) ? 76 : 34;
565 
566 		m_tv_hs = ((m_text_reg[7] & 0x7f)*8) - x_offs;
567 		m_tv_he = ((m_text_reg[8] & 0x7f)*8) - x_offs;
568 		m_tv_vs = (m_text_reg[3]*2) - y_offs;
569 		m_tv_ve = (m_text_reg[5]*2) - y_offs;
570 
571 		if(m_scr_x_size == 320)
572 		{
573 			m_tv_hs /= 2;
574 			m_tv_he /= 2;
575 		}
576 
577 		if(m_scr_y_size == 200)
578 		{
579 			m_tv_vs /= 2;
580 			m_tv_ve /= 2;
581 		}
582 	}
583 }
584 
mz2500_cg_latch_compare()585 uint8_t mz2500_state::mz2500_cg_latch_compare()
586 {
587 	uint8_t compare_val = m_cg_reg[0x07] & 0xf;
588 	uint8_t pix_val;
589 	uint8_t res;
590 	uint16_t i;
591 	res = 0;
592 
593 	for(i=1;i<0x100;i<<=1)
594 	{
595 		pix_val = ((m_cg_latch[0] & i) ? 1 : 0) | ((m_cg_latch[1] & i) ? 2 : 0) | ((m_cg_latch[2] & i) ? 4 : 0) | ((m_cg_latch[3] & i) ? 8 : 0);
596 		if(pix_val == compare_val)
597 			res|=i;
598 	}
599 
600 	return res;
601 }
602 
mz2500_bank_addr_r()603 uint8_t mz2500_state::mz2500_bank_addr_r()
604 {
605 	return m_bank_addr;
606 }
607 
mz2500_bank_addr_w(uint8_t data)608 void mz2500_state::mz2500_bank_addr_w(uint8_t data)
609 {
610 //  printf("%02x\n",data);
611 	m_bank_addr = data & 7;
612 }
613 
mz2500_bank_data_r()614 uint8_t mz2500_state::mz2500_bank_data_r()
615 {
616 	uint8_t res;
617 
618 	res = m_bank_val[m_bank_addr];
619 
620 	m_bank_addr++;
621 	m_bank_addr&=7;
622 
623 	return res;
624 }
625 
mz2500_bank_data_w(uint8_t data)626 void mz2500_state::mz2500_bank_data_w(uint8_t data)
627 {
628 	m_bank_val[m_bank_addr] = data & 0x3f;
629 	m_rambank[m_bank_addr]->set_bank(m_bank_val[m_bank_addr]);
630 
631 //  if((data*2) >= 0x70)
632 //  printf("%s %02x\n",bank_name[m_bank_addr],m_bank_val[m_bank_addr]*2);
633 
634 //  membank(bank_name[m_bank_addr])->set_base(&m_main_ram[m_bank_val[m_bank_addr]*0x2000]);
635 
636 	m_bank_addr++;
637 	m_bank_addr&=7;
638 }
639 
mz2500_kanji_bank_w(uint8_t data)640 void mz2500_state::mz2500_kanji_bank_w(uint8_t data)
641 {
642 	m_kanji_bank = data;
643 }
644 
mz2500_dictionary_bank_w(uint8_t data)645 void mz2500_state::mz2500_dictionary_bank_w(uint8_t data)
646 {
647 	m_dic_bank = data;
648 }
649 
650 /* 0xf4 - 0xf7 all returns vblank / hblank states */
mz2500_crtc_hvblank_r()651 uint8_t mz2500_state::mz2500_crtc_hvblank_r()
652 {
653 	uint8_t vblank_bit, hblank_bit;
654 
655 	vblank_bit = m_screen->vblank() ? 0 : 1;
656 	hblank_bit = m_screen->hblank() ? 0 : 2;
657 
658 	return vblank_bit | hblank_bit;
659 }
660 
661 /*
662 TVRAM / CRTC registers
663 
664 [0x00] ---x ---- line height (0) 16 (1) 20
665 [0x00] ---- xx-- 40 column mode (0) 64 colors (1) screen 1 (2) screen 2 (3) screen 1 + screen 2
666 [0x00] ---- --x- (related to the transparent pen)
667 [0x01] xxxx xxxx TV map offset low address value
668 [0x02] ---- -xxx TV map offset high address value
669 [0x03] xxxx xxxx CRTC vertical start register
670 
671 [0x05] xxxx xxxx CRTC vertical end register
672 
673 [0x07] -xxx xxxx CRTC horizontal start register
674 [0x08] -xxx xxxx CRTC horizontal end register
675 [0x09] ---- xxxx vertical scrolling shift position
676 [0x0a] --GG RRBB 256 color mode
677 [0x0b] -r-- ---- Back plane red gradient
678 [0x0b] ---- -b-- Back plane blue gradient
679 [0x0b] ---- ---i Back plane i gradient
680 [0x0c] ---- ---g Back plane green gradient
681 
682 [0x0f] ---- x--- sets monitor type interlace / progressive
683 */
684 
pal_256_param(int index,int param)685 uint8_t mz2500_state::pal_256_param(int index, int param)
686 {
687 	uint8_t val = 0;
688 
689 	switch(param & 3)
690 	{
691 		case 0: val = index & 0x80 ? 1 : 0; break;
692 		case 1: val = index & 0x08 ? 1 : 0; break;
693 		case 2: val = 1; break;
694 		case 3: val = 0; break;
695 	}
696 
697 	return val;
698 }
699 
mz2500_tv_crtc_w(offs_t offset,uint8_t data)700 void mz2500_state::mz2500_tv_crtc_w(offs_t offset, uint8_t data)
701 {
702 	switch(offset)
703 	{
704 		case 0: m_text_reg_index = data; break;
705 		case 1:
706 			m_text_reg[m_text_reg_index] = data;
707 
708 			#if 0
709 			//printf("[%02x] <- %02x\n",m_text_reg_index,data);
710 			popmessage("(%02x %02x) (%02x %02x %02x %02x) (%02x %02x %02x) (%02x %02x %02x %02x)"
711 			,m_text_reg[0] & ~0x1e,m_text_reg[3]
712 			,m_text_reg[4],m_text_reg[5],m_text_reg[6],m_text_reg[7]
713 			,m_text_reg[8],m_text_reg[10],m_text_reg[11]
714 			,m_text_reg[12],m_text_reg[13],m_text_reg[14],m_text_reg[15]);
715 
716 			#endif
717 			//popmessage("%d %02x %d %02x %d %d",m_text_reg[3],m_text_reg[4],m_text_reg[5],m_text_reg[6],m_text_reg[7]*8,m_text_reg[8]*8);
718 
719 			mz2500_reconfigure_screen();
720 
721 			if(m_text_reg_index == 0x0a) // set 256 color palette
722 			{
723 				int i,r,g,b;
724 				uint8_t b_param,r_param,g_param;
725 
726 				b_param = (data & 0x03) >> 0;
727 				r_param = (data & 0x0c) >> 2;
728 				g_param = (data & 0x30) >> 4;
729 
730 				for(i = 0;i < 0x100;i++)
731 				{
732 					int bit0,bit1,bit2;
733 
734 					bit0 = pal_256_param(i,b_param) ? 1 : 0;
735 					bit1 = i & 0x01 ? 2 : 0;
736 					bit2 = i & 0x10 ? 4 : 0;
737 					b = bit0|bit1|bit2;
738 					bit0 = pal_256_param(i,r_param) ? 1 : 0;
739 					bit1 = i & 0x02 ? 2 : 0;
740 					bit2 = i & 0x20 ? 4 : 0;
741 					r = bit0|bit1|bit2;
742 					bit0 = pal_256_param(i,g_param) ? 1 : 0;
743 					bit1 = i & 0x04 ? 2 : 0;
744 					bit2 = i & 0x40 ? 4 : 0;
745 					g = bit0|bit1|bit2;
746 
747 					m_palette->set_pen_color(i+0x100,pal3bit(r),pal3bit(g),pal3bit(b));
748 				}
749 			}
750 			if(m_text_reg_index >= 0x80 && m_text_reg_index <= 0x8f) //Bitmap 16 clut registers
751 			{
752 				/*
753 				---x ---- priority
754 				---- xxxx clut number
755 				*/
756 				m_clut16[m_text_reg_index & 0xf] = data & 0x1f;
757 				//printf("%02x -> [%02x]\n",m_text_reg[m_text_reg_index],m_text_reg_index);
758 
759 				{
760 					int i;
761 
762 					for(i=0;i<0x10;i++)
763 					{
764 						m_clut256[(m_text_reg_index & 0xf) | (i << 4)] = (((data & 0x1f) << 4) | i);
765 					}
766 				}
767 			}
768 			break;
769 		case 2: /* CG Mask reg (priority mixer) */
770 			m_cg_mask = data;
771 			break;
772 		case 3:
773 			/* Font size reg */
774 			m_text_font_reg = data & 1;
775 			mz2500_reconfigure_screen();
776 			break;
777 	}
778 }
779 
mz2500_irq_sel_w(uint8_t data)780 void mz2500_state::mz2500_irq_sel_w(uint8_t data)
781 {
782 	m_irq_sel = data;
783 	//printf("%02x\n",m_irq_sel);
784 	// activeness is trusted, see Tower of Druaga
785 	m_irq_mask[0] = (data & 0x08); //CRTC
786 	m_irq_mask[1] = (data & 0x04); //i8253
787 	m_irq_mask[2] = (data & 0x02); //printer
788 	m_irq_mask[3] = (data & 0x01); //RP5c15
789 }
790 
mz2500_irq_data_w(uint8_t data)791 void mz2500_state::mz2500_irq_data_w(uint8_t data)
792 {
793 	if(m_irq_sel & 0x80)
794 		m_irq_vector[0] = data; //CRTC
795 	if(m_irq_sel & 0x40)
796 		m_irq_vector[1] = data; //i8253
797 	if(m_irq_sel & 0x20)
798 		m_irq_vector[2] = data; //printer
799 	if(m_irq_sel & 0x10)
800 		m_irq_vector[3] = data; //RP5c15
801 
802 //  popmessage("%02x %02x %02x %02x",m_irq_vector[0],m_irq_vector[1],m_irq_vector[2],m_irq_vector[3]);
803 }
804 
floppy_select_w(uint8_t data)805 void mz2500_state::floppy_select_w(uint8_t data)
806 {
807 	switch ((data & 0x03) ^ m_fdc_reverse)
808 	{
809 	case 0: m_floppy = m_floppy0->get_device(); break;
810 	case 1: m_floppy = m_floppy1->get_device(); break;
811 	case 2: m_floppy = m_floppy2->get_device(); break;
812 	case 3: m_floppy = m_floppy3->get_device(); break;
813 	}
814 
815 	m_fdc->set_floppy(m_floppy);
816 
817 	if (m_floppy)
818 		m_floppy->mon_w(!BIT(data, 7));
819 }
820 
floppy_side_w(uint8_t data)821 void mz2500_state::floppy_side_w(uint8_t data)
822 {
823 	if (m_floppy)
824 		m_floppy->ss_w(BIT(data, 0));
825 }
826 
mz2500_map(address_map & map)827 void mz2500_state::mz2500_map(address_map &map)
828 {
829 	map(0x0000, 0x1fff).m(m_rambank[0], FUNC(address_map_bank_device::amap8));
830 	map(0x2000, 0x3fff).m(m_rambank[1], FUNC(address_map_bank_device::amap8));
831 	map(0x4000, 0x5fff).m(m_rambank[2], FUNC(address_map_bank_device::amap8));
832 	map(0x6000, 0x7fff).m(m_rambank[3], FUNC(address_map_bank_device::amap8));
833 	map(0x8000, 0x9fff).m(m_rambank[4], FUNC(address_map_bank_device::amap8));
834 	map(0xa000, 0xbfff).m(m_rambank[5], FUNC(address_map_bank_device::amap8));
835 	map(0xc000, 0xdfff).m(m_rambank[6], FUNC(address_map_bank_device::amap8));
836 	map(0xe000, 0xffff).m(m_rambank[7], FUNC(address_map_bank_device::amap8));
837 }
838 
rmw_r(offs_t offset)839 uint8_t mz2500_state::rmw_r(offs_t offset)
840 {
841 	// TODO: correct?
842 	if(m_cg_reg[0x0e] == 0x3)
843 		return 0xff;
844 
845 	int plane;
846 	m_cg_latch[0] = m_cgram[offset+0x0000]; //B
847 	m_cg_latch[1] = m_cgram[offset+0x4000]; //R
848 	m_cg_latch[2] = m_cgram[offset+0x8000]; //G
849 	m_cg_latch[3] = m_cgram[offset+0xc000]; //I
850 	plane = m_cg_reg[0x07] & 3;
851 
852 	if(m_cg_reg[0x07] & 0x10)
853 		return mz2500_cg_latch_compare();
854 
855 	return m_cg_latch[plane];
856 }
857 
rmw_w(offs_t offset,uint8_t data)858 void mz2500_state::rmw_w(offs_t offset, uint8_t data)
859 {
860 	// TODO: correct?
861 	if(m_cg_reg[0x0e] == 0x3)
862 		return;
863 
864 	if((m_cg_reg[0x05] & 0xc0) == 0x00) //replace
865 	{
866 		if(m_cg_reg[5] & 1) //B
867 		{
868 			m_cgram[offset+0x0000] &= ~m_cg_reg[6];
869 			m_cgram[offset+0x0000] |= (m_cg_reg[4] & 1) ? (data & m_cg_reg[0] & m_cg_reg[6]) : 0;
870 		}
871 		if(m_cg_reg[5] & 2) //R
872 		{
873 			m_cgram[offset+0x4000] &= ~m_cg_reg[6];
874 			m_cgram[offset+0x4000] |= (m_cg_reg[4] & 2) ? (data & m_cg_reg[1] & m_cg_reg[6]) : 0;
875 		}
876 		if(m_cg_reg[5] & 4) //G
877 		{
878 			m_cgram[offset+0x8000] &= ~m_cg_reg[6];
879 			m_cgram[offset+0x8000] |= (m_cg_reg[4] & 4) ? (data & m_cg_reg[2] & m_cg_reg[6]) : 0;
880 		}
881 		if(m_cg_reg[5] & 8) //I
882 		{
883 			m_cgram[offset+0xc000] &= ~m_cg_reg[6];
884 			m_cgram[offset+0xc000] |= (m_cg_reg[4] & 8) ? (data & m_cg_reg[3] & m_cg_reg[6]) : 0;
885 		}
886 	}
887 	else if((m_cg_reg[0x05] & 0xc0) == 0x40) //pset
888 	{
889 		if(m_cg_reg[5] & 1) //B
890 		{
891 			m_cgram[offset+0x0000] &= ~data;
892 			m_cgram[offset+0x0000] |= (m_cg_reg[4] & 1) ? (data & m_cg_reg[0]) : 0;
893 		}
894 		if(m_cg_reg[5] & 2) //R
895 		{
896 			m_cgram[offset+0x4000] &= ~data;
897 			m_cgram[offset+0x4000] |= (m_cg_reg[4] & 2) ? (data & m_cg_reg[1]) : 0;
898 		}
899 		if(m_cg_reg[5] & 4) //G
900 		{
901 			m_cgram[offset+0x8000] &= ~data;
902 			m_cgram[offset+0x8000] |= (m_cg_reg[4] & 4) ? (data & m_cg_reg[2]) : 0;
903 		}
904 		if(m_cg_reg[5] & 8) //I
905 		{
906 			m_cgram[offset+0xc000] &= ~data;
907 			m_cgram[offset+0xc000] |= (m_cg_reg[4] & 8) ? (data & m_cg_reg[3]) : 0;
908 		}
909 	}
910 }
911 
kanji_pcg_r(offs_t offset)912 uint8_t mz2500_state::kanji_pcg_r(offs_t offset)
913 {
914 	if(m_kanji_bank & 0x80) //kanji ROM
915 		return m_kanji_rom[(offset & 0x7ff)+((m_kanji_bank & 0x7f)*0x800)];
916 
917 	//PCG RAM
918 	return m_pcg_ram[offset];
919 }
920 
kanji_pcg_w(offs_t offset,uint8_t data)921 void mz2500_state::kanji_pcg_w(offs_t offset, uint8_t data)
922 {
923 	if((m_kanji_bank & 0x80) == 0) ////PCG RAM
924 	{
925 		m_pcg_ram[offset] = data;
926 		if((offset & 0x1800) == 0x0000)
927 			m_gfxdecode->gfx(3)->mark_dirty((offset) >> 3);
928 		else
929 			m_gfxdecode->gfx(4)->mark_dirty((offset & 0x7ff) >> 3);
930 	}
931 	// kanji ROM is read only
932 }
933 
dict_rom_r(offs_t offset)934 uint8_t mz2500_state::dict_rom_r(offs_t offset)
935 {
936 	return m_dic_rom[(offset & 0x1fff) + ((m_dic_bank & 0x1f)*0x2000)];
937 }
938 
939 /*
940     memory map:
941     0x00000-0x3ffff Work RAM
942     0x40000-0x5ffff CG RAM
943     0x60000-0x67fff "Read modify write" area (related to the CG RAM) (0x30-0x33)
944     0x68000-0x6ffff IPL ROM (0x34-0x37)
945     0x70000-0x71fff TVRAM (0x38)
946     0x72000-0x73fff Kanji ROM / PCG RAM (banked) (0x39)
947     0x74000-0x75fff Dictionary ROM (banked) (0x3a)
948     0x76000-0x77fff NOP (0x3b)
949     0x78000-0x7ffff Phone ROM (0x3c-0x3f)
950 */
mz2500_bank_window_map(address_map & map)951 void mz2500_state::mz2500_bank_window_map(address_map &map)
952 {
953 	map(0x00000,0x3ffff).ram().share("wram");
954 	map(0x40000,0x5ffff).ram().share("cgram");
955 	map(0x60000,0x67fff).rw(FUNC(mz2500_state::rmw_r),FUNC(mz2500_state::rmw_w));
956 	map(0x68000,0x6ffff).rom().region("ipl", 0);
957 	map(0x70000,0x71fff).ram().share("tvram");
958 	map(0x72000,0x73fff).rw(FUNC(mz2500_state::kanji_pcg_r),FUNC(mz2500_state::kanji_pcg_w));
959 	map(0x74000,0x75fff).r(FUNC(mz2500_state::dict_rom_r));
960 	map(0x78000,0x7ffff).rom().region("phone", 0);
961 }
962 
mz2500_rom_r()963 uint8_t mz2500_state::mz2500_rom_r()
964 {
965 	m_lrom_index = (m_maincpu->state_int(Z80_B));
966 
967 	m_rom_index = (m_rom_index & 0xffff00) | (m_lrom_index & 0xff);
968 
969 	return m_iplpro_rom[m_rom_index];
970 }
971 
mz2500_rom_w(uint8_t data)972 void mz2500_state::mz2500_rom_w(uint8_t data)
973 {
974 	m_hrom_index = (m_maincpu->state_int(Z80_B));
975 
976 	m_rom_index = (data << 8) | (m_rom_index & 0x0000ff) | ((m_hrom_index & 0xff)<<16);
977 	//printf("%02x\n",data);
978 }
979 
980 /* sets 16 color entries out of 4096 possible combinations */
palette4096_io_w(uint8_t data)981 void mz2500_state::palette4096_io_w(uint8_t data)
982 {
983 	uint8_t pal_index;
984 	uint8_t pal_entry;
985 
986 	pal_index = m_maincpu->state_int(Z80_B);
987 	pal_entry = (pal_index & 0x1e) >> 1;
988 
989 	if(pal_index & 1)
990 		m_pal[pal_entry].g = (data & 0x0f);
991 	else
992 	{
993 		m_pal[pal_entry].r = (data & 0xf0) >> 4;
994 		m_pal[pal_entry].b = data & 0x0f;
995 	}
996 
997 	m_palette->set_pen_color(pal_entry+0x10, pal4bit(m_pal[pal_entry].r), pal4bit(m_pal[pal_entry].g), pal4bit(m_pal[pal_entry].b));
998 }
999 
fdc_r(offs_t offset)1000 uint8_t mz2500_state::fdc_r(offs_t offset)
1001 {
1002 	return m_fdc->read(offset) ^ 0xff;
1003 }
1004 
fdc_w(offs_t offset,uint8_t data)1005 void mz2500_state::fdc_w(offs_t offset, uint8_t data)
1006 {
1007 	m_fdc->write(offset, data ^ 0xff);
1008 }
1009 
mz2500_bplane_latch_r()1010 uint8_t mz2500_state::mz2500_bplane_latch_r()
1011 {
1012 	if(m_cg_reg[7] & 0x10)
1013 		return mz2500_cg_latch_compare();
1014 	else
1015 		return m_cg_latch[0];
1016 }
1017 
1018 
mz2500_rplane_latch_r()1019 uint8_t mz2500_state::mz2500_rplane_latch_r()
1020 {
1021 	if(m_cg_reg[0x07] & 0x10)
1022 	{
1023 		uint8_t vblank_bit;
1024 
1025 		vblank_bit = m_screen->vblank() ? 0 : 0x80 | m_cg_clear_flag;
1026 
1027 		return vblank_bit;
1028 	}
1029 	else
1030 		return m_cg_latch[1];
1031 }
1032 
mz2500_gplane_latch_r()1033 uint8_t mz2500_state::mz2500_gplane_latch_r()
1034 {
1035 	return m_cg_latch[2];
1036 }
1037 
mz2500_iplane_latch_r()1038 uint8_t mz2500_state::mz2500_iplane_latch_r()
1039 {
1040 	return m_cg_latch[3];
1041 }
1042 
1043 /*
1044 "GDE" CRTC registers
1045 
1046 0x00: CG B - Replace / Pset register data mask
1047 0x01: CG R - Replace / Pset register data mask
1048 0x02: CG G - Replace / Pset register data mask
1049 0x03: CG I - Replace / Pset register data mask
1050 0x04: CG Replace / Pset active pixel
1051 0x05: CG Replace / Pset mode register
1052 0x06: CG Replace data register
1053 0x07: compare CG buffer register
1054 0x08: CG window vertical start lo reg
1055 0x09: CG window vertical start hi reg (upper 1 bit)
1056 0x0a: CG window vertical end lo reg
1057 0x0b: CG window vertical end hi reg (upper 1 bit)
1058 0x0c: CG window horizontal start reg (7 bits, val x 8)
1059 0x0d: CG window horizontal end reg (7 bits, val x 8)
1060 0x0e: CG mode
1061 0x0f: vertical scroll shift (---- xxxx)
1062 0x10: CG map base lo reg
1063 0x11: CG map base hi reg
1064 0x12: CG layer 0 end address lo reg
1065 0x13: CG layer 0 end address hi reg
1066 0x14: CG layer 1 start address lo reg
1067 0x15: CG layer 1 start address hi reg
1068 0x16: CG layer 1 y pixel start lo reg
1069 0x17: CG layer 1 y pixel start hi reg
1070 0x18: CG color masking
1071 */
1072 
mz2500_cg_addr_w(uint8_t data)1073 void mz2500_state::mz2500_cg_addr_w(uint8_t data)
1074 {
1075 	m_cg_reg_index = data;
1076 }
1077 
mz2500_cg_data_w(uint8_t data)1078 void mz2500_state::mz2500_cg_data_w(uint8_t data)
1079 {
1080 	m_cg_reg[m_cg_reg_index & 0x1f] = data;
1081 
1082 	if((m_cg_reg_index & 0x1f) == 0x08) //accessing VS LO reg clears VS HI reg
1083 		m_cg_reg[0x09] = 0;
1084 
1085 	if((m_cg_reg_index & 0x1f) == 0x0a) //accessing VE LO reg clears VE HI reg
1086 		m_cg_reg[0x0b] = 0;
1087 
1088 	if((m_cg_reg_index & 0x1f) == 0x05 && (m_cg_reg[0x05] & 0xc0) == 0x80) //clear bitmap buffer
1089 	{
1090 		uint32_t i;
1091 		uint8_t *vram = m_cgram;
1092 		uint32_t layer_bank;
1093 
1094 		layer_bank = (m_cg_reg[0x0e] & 0x80) ? 0x10000 : 0x00000;
1095 
1096 		/* TODO: this isn't yet 100% accurate */
1097 		if(m_cg_reg[0x05] & 1)
1098 		{
1099 			for(i=0;i<0x4000;i++)
1100 				vram[i+0x0000+layer_bank] = 0x00; //clear B
1101 		}
1102 		if(m_cg_reg[0x05] & 2)
1103 		{
1104 			for(i=0;i<0x4000;i++)
1105 				vram[i+0x4000+layer_bank] = 0x00; //clear R
1106 		}
1107 		if(m_cg_reg[0x05] & 4)
1108 		{
1109 			for(i=0;i<0x4000;i++)
1110 				vram[i+0x8000+layer_bank] = 0x00; //clear G
1111 		}
1112 		if(m_cg_reg[0x05] & 8)
1113 		{
1114 			for(i=0;i<0x4000;i++)
1115 				vram[i+0xc000+layer_bank] = 0x00; //clear I
1116 		}
1117 		m_cg_clear_flag = 1;
1118 	}
1119 
1120 	{
1121 		mz2500_reconfigure_screen();
1122 	}
1123 
1124 	if(m_cg_reg_index & 0x80) //enable auto-inc
1125 		m_cg_reg_index = (m_cg_reg_index & 0xfc) | ((m_cg_reg_index + 1) & 0x03);
1126 }
1127 
timer_w(uint8_t data)1128 void mz2500_state::timer_w(uint8_t data)
1129 {
1130 	m_pit->write_gate0(1);
1131 	m_pit->write_gate1(1);
1132 	m_pit->write_gate0(0);
1133 	m_pit->write_gate1(0);
1134 	m_pit->write_gate0(1);
1135 	m_pit->write_gate1(1);
1136 }
1137 
1138 
mz2500_joystick_r()1139 uint8_t mz2500_state::mz2500_joystick_r()
1140 {
1141 	uint8_t res,dir_en,in_r;
1142 
1143 	res = 0xff;
1144 	in_r = ~ioport(m_joy_mode & 0x40 ? "JOY_2P" : "JOY_1P")->read();
1145 
1146 	if(m_joy_mode & 0x40)
1147 	{
1148 		if(!(m_joy_mode & 0x04)) res &= ~0x20;
1149 		if(!(m_joy_mode & 0x08)) res &= ~0x10;
1150 		dir_en = (m_joy_mode & 0x20) ? 0 : 1;
1151 	}
1152 	else
1153 	{
1154 		if(!(m_joy_mode & 0x01)) res &= ~0x20;
1155 		if(!(m_joy_mode & 0x02)) res &= ~0x10;
1156 		dir_en = (m_joy_mode & 0x10) ? 0 : 1;
1157 	}
1158 
1159 	if(dir_en)
1160 		res &= (~((in_r) & 0x0f));
1161 
1162 	res &= (~((in_r) & 0x30));
1163 
1164 	return res;
1165 }
1166 
mz2500_joystick_w(uint8_t data)1167 void mz2500_state::mz2500_joystick_w(uint8_t data)
1168 {
1169 	m_joy_mode = data;
1170 }
1171 
1172 
mz2500_kanji_r(offs_t offset)1173 uint8_t mz2500_state::mz2500_kanji_r(offs_t offset)
1174 {
1175 	printf("Read from kanji 2 ROM\n");
1176 
1177 	return m_kanji2_rom[(m_kanji_index << 1) | (offset & 1)];
1178 }
1179 
mz2500_kanji_w(offs_t offset,uint8_t data)1180 void mz2500_state::mz2500_kanji_w(offs_t offset, uint8_t data)
1181 {
1182 	(offset & 1) ? (m_kanji_index = (data << 8) | (m_kanji_index & 0xff)) : (m_kanji_index = (data & 0xff) | (m_kanji_index & 0xff00));
1183 }
1184 
rp5c15_8_r()1185 uint8_t mz2500_state::rp5c15_8_r()
1186 {
1187 	uint8_t rtc_index = (m_maincpu->state_int(Z80_B));
1188 
1189 	return m_rtc->read(rtc_index);
1190 }
1191 
rp5c15_8_w(uint8_t data)1192 void mz2500_state::rp5c15_8_w(uint8_t data)
1193 {
1194 	uint8_t rtc_index = (m_maincpu->state_int(Z80_B));
1195 
1196 	m_rtc->write(rtc_index, data);
1197 }
1198 
1199 
mz2500_emm_data_r()1200 uint8_t mz2500_state::mz2500_emm_data_r()
1201 {
1202 	uint8_t emm_lo_index;
1203 
1204 	emm_lo_index = (m_maincpu->state_int(Z80_B));
1205 
1206 	m_emm_offset = (m_emm_offset & 0xffff00) | (emm_lo_index & 0xff);
1207 
1208 	if(m_emm_offset < 0x100000) //emm max size
1209 		return m_emm_ram[m_emm_offset];
1210 
1211 	return 0xff;
1212 }
1213 
mz2500_emm_addr_w(uint8_t data)1214 void mz2500_state::mz2500_emm_addr_w(uint8_t data)
1215 {
1216 	uint8_t emm_hi_index;
1217 
1218 	emm_hi_index = (m_maincpu->state_int(Z80_B));
1219 
1220 	m_emm_offset = ((emm_hi_index & 0xff) << 16) | ((data & 0xff) << 8) | (m_emm_offset & 0xff);
1221 }
1222 
mz2500_emm_data_w(uint8_t data)1223 void mz2500_state::mz2500_emm_data_w(uint8_t data)
1224 {
1225 	uint8_t emm_lo_index;
1226 
1227 	emm_lo_index = (m_maincpu->state_int(Z80_B));
1228 
1229 	m_emm_offset = (m_emm_offset & 0xffff00) | (emm_lo_index & 0xff);
1230 
1231 	if(m_emm_offset < 0x100000) //emm max size
1232 		m_emm_ram[m_emm_offset] = data;
1233 }
1234 
mz2500_io(address_map & map)1235 void mz2500_state::mz2500_io(address_map &map)
1236 {
1237 	map.global_mask(0xff);
1238 //  map(0x60, 0x63).w(FUNC(mz2500_state::w3100a_w));
1239 //  map(0x63, 0x63).r(FUNC(mz2500_state::w3100a_r));
1240 //  map(0x98, 0x99) ADPCM, unknown type, custom?
1241 	map(0xa0, 0xa3).rw("z80sio", FUNC(z80sio_device::ba_cd_r), FUNC(z80sio_device::ba_cd_w));
1242 //  map(0xa4, 0xa5).rw(FUNC(mz2500_state::sasi_r), FUNC(mz2500_state::sasi_w));
1243 	map(0xa8, 0xa8).w(FUNC(mz2500_state::mz2500_rom_w));
1244 	map(0xa9, 0xa9).r(FUNC(mz2500_state::mz2500_rom_r));
1245 	map(0xac, 0xac).w(FUNC(mz2500_state::mz2500_emm_addr_w));
1246 	map(0xad, 0xad).r(FUNC(mz2500_state::mz2500_emm_data_r)).w(FUNC(mz2500_state::mz2500_emm_data_w));
1247 	map(0xae, 0xae).w(FUNC(mz2500_state::palette4096_io_w));
1248 //  map(0xb0, 0xb3).rw(FUNC(mz2500_state::sio_r), FUNC(mz2500_state::sio_w));
1249 	map(0xb4, 0xb4).rw(FUNC(mz2500_state::mz2500_bank_addr_r), FUNC(mz2500_state::mz2500_bank_addr_w));
1250 	map(0xb5, 0xb5).rw(FUNC(mz2500_state::mz2500_bank_data_r), FUNC(mz2500_state::mz2500_bank_data_w));
1251 	map(0xb7, 0xb7).nopw();
1252 	map(0xb8, 0xb9).rw(FUNC(mz2500_state::mz2500_kanji_r), FUNC(mz2500_state::mz2500_kanji_w));
1253 	map(0xbc, 0xbc).r(FUNC(mz2500_state::mz2500_bplane_latch_r)).w(FUNC(mz2500_state::mz2500_cg_addr_w));
1254 	map(0xbd, 0xbd).r(FUNC(mz2500_state::mz2500_rplane_latch_r)).w(FUNC(mz2500_state::mz2500_cg_data_w));
1255 	map(0xbe, 0xbe).r(FUNC(mz2500_state::mz2500_gplane_latch_r));
1256 	map(0xbf, 0xbf).r(FUNC(mz2500_state::mz2500_iplane_latch_r));
1257 	map(0xc6, 0xc6).w(FUNC(mz2500_state::mz2500_irq_sel_w));
1258 	map(0xc7, 0xc7).w(FUNC(mz2500_state::mz2500_irq_data_w));
1259 	map(0xc8, 0xc9).rw("ym", FUNC(ym2203_device::read), FUNC(ym2203_device::write));
1260 //  map(0xca, 0xca).rw(FUNC(mz2500_state::voice_r), FUNC(mz2500_state::voice_w));
1261 	map(0xcc, 0xcc).rw(FUNC(mz2500_state::rp5c15_8_r), FUNC(mz2500_state::rp5c15_8_w));
1262 	map(0xce, 0xce).w(FUNC(mz2500_state::mz2500_dictionary_bank_w));
1263 	map(0xcf, 0xcf).w(FUNC(mz2500_state::mz2500_kanji_bank_w));
1264 	map(0xd8, 0xdb).rw(FUNC(mz2500_state::fdc_r), FUNC(mz2500_state::fdc_w));
1265 	map(0xdc, 0xdc).w(FUNC(mz2500_state::floppy_select_w));
1266 	map(0xdd, 0xdd).w(FUNC(mz2500_state::floppy_side_w));
1267 	map(0xde, 0xde).nopw();
1268 	map(0xe0, 0xe3).rw("i8255_0", FUNC(i8255_device::read), FUNC(i8255_device::write));
1269 	map(0xe4, 0xe7).rw(m_pit, FUNC(pit8253_device::read), FUNC(pit8253_device::write));
1270 	map(0xe8, 0xeb).rw("z80pio_1", FUNC(z80pio_device::read_alt), FUNC(z80pio_device::write_alt));
1271 	map(0xef, 0xef).rw(FUNC(mz2500_state::mz2500_joystick_r), FUNC(mz2500_state::mz2500_joystick_w));
1272 	map(0xf0, 0xf3).w(FUNC(mz2500_state::timer_w));
1273 	map(0xf4, 0xf7).r(FUNC(mz2500_state::mz2500_crtc_hvblank_r)).w(FUNC(mz2500_state::mz2500_tv_crtc_w));
1274 //  map(0xf8, 0xf9).rw(FUNC(mz2500_state::extrom_r), FUNC(mz2500_state::extrom_w));
1275 }
1276 
1277 /* Input ports */
1278 static INPUT_PORTS_START( mz2500 )
1279 	PORT_START("KEY0")
PORT_CODE(KEYCODE_F1)1280 	PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("F1") PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1))
1281 	PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("F2") PORT_CODE(KEYCODE_F2) PORT_CHAR(UCHAR_MAMEKEY(F2))
1282 	PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("F3") PORT_CODE(KEYCODE_F3) PORT_CHAR(UCHAR_MAMEKEY(F3))
1283 	PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("F4") PORT_CODE(KEYCODE_F4) PORT_CHAR(UCHAR_MAMEKEY(F4))
1284 	PORT_BIT(0x10,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("F5") PORT_CODE(KEYCODE_F5) PORT_CHAR(UCHAR_MAMEKEY(F5))
1285 	PORT_BIT(0x20,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("F6") PORT_CODE(KEYCODE_F6) PORT_CHAR(UCHAR_MAMEKEY(F6))
1286 	PORT_BIT(0x40,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("F7") PORT_CODE(KEYCODE_F7) PORT_CHAR(UCHAR_MAMEKEY(F7))
1287 	PORT_BIT(0x80,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("F8") PORT_CODE(KEYCODE_F8) PORT_CHAR(UCHAR_MAMEKEY(F8))
1288 
1289 	PORT_START("KEY1")
1290 	PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("F9") PORT_CODE(KEYCODE_F9) PORT_CHAR(UCHAR_MAMEKEY(F9))
1291 	PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("F10") PORT_CODE(KEYCODE_F10) PORT_CHAR(UCHAR_MAMEKEY(F10))
1292 	PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("8 (PAD)") PORT_CODE(KEYCODE_8_PAD)
1293 	PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("9 (PAD)") PORT_CODE(KEYCODE_9_PAD)
1294 	PORT_BIT(0x10,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME(", (PAD)") PORT_CODE(KEYCODE_COMMA_PAD)
1295 	PORT_BIT(0x20,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME(". (PAD)") PORT_CODE(KEYCODE_DEL_PAD)
1296 	PORT_BIT(0x40,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("+ (PAD)") PORT_CODE(KEYCODE_PLUS_PAD)
1297 	PORT_BIT(0x80,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("- (PAD)") PORT_CODE(KEYCODE_MINUS_PAD)
1298 
1299 	PORT_START("KEY2")
1300 	PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("0 (PAD)") PORT_CODE(KEYCODE_0_PAD)
1301 	PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("1 (PAD)") PORT_CODE(KEYCODE_1_PAD)
1302 	PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("2 (PAD)") PORT_CODE(KEYCODE_2_PAD)
1303 	PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("3 (PAD)") PORT_CODE(KEYCODE_3_PAD)
1304 	PORT_BIT(0x10,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("4 (PAD)") PORT_CODE(KEYCODE_4_PAD)
1305 	PORT_BIT(0x20,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("5 (PAD)") PORT_CODE(KEYCODE_5_PAD)
1306 	PORT_BIT(0x40,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("6 (PAD)") PORT_CODE(KEYCODE_6_PAD)
1307 	PORT_BIT(0x80,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("7 (PAD)") PORT_CODE(KEYCODE_7_PAD)
1308 
1309 	PORT_START("KEY3")
1310 	PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("TAB") PORT_CODE(KEYCODE_TAB) PORT_CHAR(9)
1311 	PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Space") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
1312 	PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("RETURN") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13)
1313 	PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Up") PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP))
1314 	PORT_BIT(0x10,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Down") PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN))
1315 	PORT_BIT(0x20,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Left") PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT))
1316 	PORT_BIT(0x40,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Right") PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT))
1317 	PORT_BIT(0x80,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("BREAK") PORT_CHAR(3) //PORT_CODE(KEYCODE_ESC)
1318 
1319 	PORT_START("KEY4")
1320 	PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("/") PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?')
1321 	PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("A") PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A')
1322 	PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("B") PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B')
1323 	PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("C") PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C')
1324 	PORT_BIT(0x10,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("D") PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D')
1325 	PORT_BIT(0x20,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("E") PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E')
1326 	PORT_BIT(0x40,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("F") PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F')
1327 	PORT_BIT(0x80,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("G") PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G')
1328 
1329 	PORT_START("KEY5")
1330 	PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("H") PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H')
1331 	PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("I") PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I')
1332 	PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("J") PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J')
1333 	PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("K") PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K')
1334 	PORT_BIT(0x10,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("L") PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L')
1335 	PORT_BIT(0x20,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("M") PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M')
1336 	PORT_BIT(0x40,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("N") PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N')
1337 	PORT_BIT(0x80,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("O") PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O')
1338 
1339 	PORT_START("KEY6")
1340 	PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("P") PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P')
1341 	PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Q") PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q')
1342 	PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("R") PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R')
1343 	PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("S") PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S')
1344 	PORT_BIT(0x10,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("T") PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T')
1345 	PORT_BIT(0x20,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("U") PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U')
1346 	PORT_BIT(0x40,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("V") PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V')
1347 	PORT_BIT(0x80,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("W") PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W')
1348 
1349 	PORT_START("KEY7")
1350 	PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("X") PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X')
1351 	PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Y") PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y')
1352 	PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Z") PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z')
1353 	PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("^") PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('^')
1354 	PORT_BIT(0x10,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("\xEF\xBF\xA5") PORT_CHAR(165) PORT_CHAR('|') //Yen symbol
1355 	PORT_BIT(0x20,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("_") PORT_CHAR('_')
1356 	PORT_BIT(0x40,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME(".") PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>')
1357 	PORT_BIT(0x80,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME(",") PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<')
1358 
1359 	PORT_START("KEY8")
1360 	PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("0") PORT_CODE(KEYCODE_0) PORT_CHAR('0')
1361 	PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("1") PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!')
1362 	PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("2") PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"')
1363 	PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("3") PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#')
1364 	PORT_BIT(0x10,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("4") PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$')
1365 	PORT_BIT(0x20,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("5") PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%')
1366 	PORT_BIT(0x40,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("6") PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&')
1367 	PORT_BIT(0x80,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("7") PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('\'')
1368 
1369 	PORT_START("KEY9")
1370 	PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("8") PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(')
1371 	PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("9") PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')')
1372 	PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME(":") PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(':') PORT_CHAR('*')
1373 	PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME(";") PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR('+')
1374 	PORT_BIT(0x10,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("-") PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-')  PORT_CHAR('=')
1375 	PORT_BIT(0x20,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("@") PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('@') PORT_CHAR('`')
1376 	PORT_BIT(0x40,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("[") PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR('[') PORT_CHAR('{')
1377 	PORT_BIT(0x80,IP_ACTIVE_LOW,IPT_UNUSED)
1378 
1379 	PORT_START("KEYA")
1380 	PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("]") PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR(']') PORT_CHAR('}')
1381 	PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("COPY")
1382 	PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("CLR")
1383 	PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("INST")
1384 	PORT_BIT(0x10,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("BACKSPACE") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8)
1385 	PORT_BIT(0x20,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("ESC") PORT_CODE(KEYCODE_TILDE) PORT_CHAR(27)
1386 	PORT_BIT(0x40,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("* (PAD)") PORT_CODE(KEYCODE_ASTERISK)
1387 	PORT_BIT(0x80,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("/ (PAD)") PORT_CODE(KEYCODE_SLASH_PAD)
1388 
1389 	PORT_START("KEYB")
1390 	PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("GRPH")
1391 	PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("SLOCK")
1392 	PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("SHIFT") PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1)
1393 	PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("KANA")
1394 	PORT_BIT(0x10,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("CTRL") PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_SHIFT_2)
1395 	PORT_BIT(0xe0,IP_ACTIVE_LOW,IPT_UNUSED)
1396 
1397 	PORT_START("KEYC")
1398 	PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("KJ1")
1399 	PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("KJ2")
1400 	PORT_BIT(0xfc,IP_ACTIVE_LOW,IPT_UNUSED)
1401 
1402 	PORT_START("KEYD")
1403 	PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("LOGO KEY")
1404 	PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("HELP")
1405 	PORT_BIT(0xfc,IP_ACTIVE_LOW,IPT_UNUSED)
1406 
1407 	PORT_START("UNUSED")
1408 	PORT_BIT(0xff,IP_ACTIVE_LOW,IPT_UNUSED )
1409 
1410 	/* this enables HD-loader */
1411 	PORT_START("DSW1")
1412 	PORT_DIPNAME( 0x01, 0x01, "DSW1" )
1413 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
1414 	PORT_DIPSETTING(    0x01, DEF_STR( On ) )
1415 	PORT_DIPNAME( 0x02, 0x02, DEF_STR( Unknown ) )
1416 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
1417 	PORT_DIPSETTING(    0x02, DEF_STR( On ) )
1418 	PORT_DIPNAME( 0x04, 0x04, DEF_STR( Unknown ) )
1419 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
1420 	PORT_DIPSETTING(    0x04, DEF_STR( On ) )
1421 	PORT_DIPNAME( 0x08, 0x08, DEF_STR( Unknown ) )
1422 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
1423 	PORT_DIPSETTING(    0x08, DEF_STR( On ) )
1424 	PORT_DIPNAME( 0x30, 0x30, "IPLPRO" )
1425 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
1426 	PORT_DIPSETTING(    0x30, DEF_STR( On ) )
1427 	PORT_DIPNAME( 0x40, 0x40, "Monitor Interlace" ) //not all games support this
1428 	PORT_DIPSETTING(    0x40, DEF_STR( Off ) )
1429 	PORT_DIPSETTING(    0x00, DEF_STR( On ) )
1430 	PORT_DIPNAME( 0x80, 0x80, DEF_STR( Unknown ) )
1431 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
1432 	PORT_DIPSETTING(    0x80, DEF_STR( On ) )
1433 
1434 	PORT_START("JOY_1P")
1435 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1)
1436 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1)
1437 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(1)
1438 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(1)
1439 	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1)
1440 	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1)
1441 	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED )
1442 	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED )
1443 
1444 	PORT_START("JOY_2P")
1445 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2)
1446 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2)
1447 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(2)
1448 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2)
1449 	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2)
1450 	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2)
1451 	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED )
1452 	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED )
1453 INPUT_PORTS_END
1454 
1455 void mz2500_state::reset_banks(uint8_t type)
1456 {
1457 	int i;
1458 
1459 	for(i=0;i<8;i++)
1460 	{
1461 		m_bank_val[i] = bank_reset_val[type][i];
1462 		m_rambank[i]->set_bank(m_bank_val[i]);
1463 	}
1464 }
1465 
1466 static const gfx_layout mz2500_pcg_layout_1bpp =
1467 {
1468 	8, 8,
1469 	0x100,
1470 	1,
1471 	{ 0 },
1472 	{ 0, 1, 2, 3, 4, 5, 6, 7 },
1473 	{ 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 },
1474 	8 * 8
1475 };
1476 
1477 static const gfx_layout mz2500_pcg_layout_3bpp =
1478 {
1479 	8, 8,
1480 	0x100,
1481 	3,
1482 	{ 0x1800*8, 0x1000*8, 0x800*8 },
1483 	{ 0, 1, 2, 3, 4, 5, 6, 7 },
1484 	{ 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 },
1485 	8 * 8
1486 };
1487 
machine_start()1488 void mz2500_state::machine_start()
1489 {
1490 	m_pcg_ram = make_unique_clear<uint8_t[]>(0x2000);
1491 	m_ipl_rom = memregion("ipl")->base();
1492 	m_kanji_rom = memregion("kanji")->base();
1493 	m_kanji2_rom = memregion("kanji2")->base();
1494 	m_emm_ram = make_unique_clear<uint8_t[]>(0x100000);
1495 	m_dic_rom = memregion("dictionary")->base();
1496 	m_phone_rom = memregion("phone")->base();
1497 	m_iplpro_rom = memregion("iplpro")->base();
1498 
1499 	save_pointer(NAME(m_pcg_ram), 0x2000);
1500 	save_pointer(NAME(m_emm_ram), 0x100000);
1501 
1502 	/* TODO: gfx[4] crashes as per now */
1503 	m_gfxdecode->set_gfx(3, std::make_unique<gfx_element>(m_palette, mz2500_pcg_layout_1bpp, m_pcg_ram.get(), 0, 0x10, 0));
1504 	m_gfxdecode->set_gfx(4, std::make_unique<gfx_element>(m_palette, mz2500_pcg_layout_3bpp, m_pcg_ram.get(), 0, 4, 0));
1505 }
1506 
machine_reset()1507 void mz2500_state::machine_reset()
1508 {
1509 	uint32_t i;
1510 
1511 	reset_banks(IPL_RESET);
1512 
1513 	//m_irq_vector[0] = 0xef; /* RST 28h - vblank */
1514 
1515 	m_text_col_size = 0;
1516 	m_text_font_reg = 0;
1517 
1518 	/* clear CG RAM */
1519 	for(i=0;i<0x20000;i++)
1520 		m_cgram[i] = 0x00;
1521 
1522 	/* disable IRQ */
1523 	for(i=0;i<4;i++)
1524 	{
1525 		m_irq_mask[i] = 0;
1526 		m_irq_pending[i] = 0;
1527 	}
1528 	m_kanji_bank = 0;
1529 
1530 	m_cg_clear_flag = 0;
1531 
1532 	m_beeper->set_state(0);
1533 
1534 //  m_monitor_type = ioport("DSW1")->read() & 0x40 ? 1 : 0;
1535 }
1536 
1537 static const gfx_layout mz2500_cg_layout =
1538 {
1539 	8, 8,       /* 8 x 8 graphics */
1540 	RGN_FRAC(1,1),      /* 512 codes */
1541 	1,      /* 1 bit per pixel */
1542 	{ 0 },      /* no bitplanes */
1543 	{ 0, 1, 2, 3, 4, 5, 6, 7 },
1544 	{ 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 },
1545 	8 * 8       /* code takes 8 times 8 bits */
1546 };
1547 
1548 /* gfx1 is mostly 16x16, but there are some 8x8 characters */
1549 static const gfx_layout mz2500_8_layout =
1550 {
1551 	8, 8,       /* 8 x 8 graphics */
1552 	1920,       /* 1920 codes */
1553 	1,      /* 1 bit per pixel */
1554 	{ 0 },      /* no bitplanes */
1555 	{ 0, 1, 2, 3, 4, 5, 6, 7 },
1556 	{ 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 },
1557 	8 * 8       /* code takes 8 times 8 bits */
1558 };
1559 
1560 static const gfx_layout mz2500_16_layout =
1561 {
1562 	16, 16,     /* 16 x 16 graphics */
1563 	RGN_FRAC(1,1),      /* 8192 codes */
1564 	1,      /* 1 bit per pixel */
1565 	{ 0 },      /* no bitplanes */
1566 	{ 0, 1, 2, 3, 4, 5, 6, 7, 128, 129, 130, 131, 132, 133, 134, 135 },
1567 	{ 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8, 8*8, 9*8, 10*8, 11*8, 12*8, 13*8, 14*8, 15*8 },
1568 	16 * 16     /* code takes 16 times 16 bits */
1569 };
1570 
1571 /* these are just for viewer sake, actually they aren't used in drawing routines */
1572 static GFXDECODE_START( gfx_mz2500 )
1573 	GFXDECODE_ENTRY("kanji", 0, mz2500_cg_layout, 0, 256)
1574 	GFXDECODE_ENTRY("kanji", 0x4400, mz2500_8_layout, 0, 256)
1575 	GFXDECODE_ENTRY("kanji", 0, mz2500_16_layout, 0, 256)
1576 //  GFXDECODE_ENTRY("pcg", 0, mz2500_pcg_layout_1bpp, 0, 0x10)
1577 //  GFXDECODE_ENTRY("pcg", 0, mz2500_pcg_layout_3bpp, 0, 4)
1578 GFXDECODE_END
1579 
INTERRUPT_GEN_MEMBER(mz2500_state::mz2500_vbl)1580 INTERRUPT_GEN_MEMBER(mz2500_state::mz2500_vbl)
1581 {
1582 	if(m_irq_mask[0])
1583 	{
1584 		m_irq_pending[0] = 1;
1585 		m_maincpu->set_input_line(0, ASSERT_LINE);
1586 	}
1587 	m_cg_clear_flag = 0;
1588 }
1589 
IRQ_CALLBACK_MEMBER(mz2500_state::mz2500_irq_ack)1590 IRQ_CALLBACK_MEMBER(mz2500_state::mz2500_irq_ack)
1591 {
1592 	int i;
1593 	for(i=0;i<4;i++)
1594 	{
1595 		if(m_irq_mask[i] && m_irq_pending[i])
1596 		{
1597 			m_irq_pending[i] = 0;
1598 			m_maincpu->set_input_line(0, CLEAR_LINE);
1599 			return m_irq_vector[i];
1600 		}
1601 	}
1602 	return 0;
1603 }
1604 
mz2500_porta_r()1605 uint8_t mz2500_state::mz2500_porta_r()
1606 {
1607 	logerror("PPI PORTA R\n");
1608 
1609 	return 0xff;
1610 }
1611 
mz2500_portb_r()1612 uint8_t mz2500_state::mz2500_portb_r()
1613 {
1614 	uint8_t vblank_bit;
1615 
1616 	vblank_bit = m_screen->vblank() ? 0 : 1; //Guess: NOBO wants this bit to be high/low
1617 
1618 	return 0xfe | vblank_bit;
1619 }
1620 
mz2500_portc_r()1621 uint8_t mz2500_state::mz2500_portc_r()
1622 {
1623 	logerror("PPI PORTC R\n");
1624 
1625 	return 0xff;
1626 }
1627 
mz2500_porta_w(uint8_t data)1628 void mz2500_state::mz2500_porta_w(uint8_t data)
1629 {
1630 	logerror("PPI PORTA W %02x\n",data);
1631 }
1632 
mz2500_portb_w(uint8_t data)1633 void mz2500_state::mz2500_portb_w(uint8_t data)
1634 {
1635 	logerror("PPI PORTB W %02x\n",data);
1636 }
1637 
mz2500_portc_w(uint8_t data)1638 void mz2500_state::mz2500_portc_w(uint8_t data)
1639 {
1640 	/*
1641 	---- x--- 0->1 transition = IPL reset
1642 	---- -x-- beeper state
1643 	---- --x- 0->1 transition = Work RAM reset
1644 	---- ---x screen mask
1645 	*/
1646 
1647 	/* work RAM reset */
1648 	if((m_old_portc & 0x02) == 0x00 && (data & 0x02))
1649 	{
1650 		reset_banks(WRAM_RESET);
1651 		/* correct? */
1652 		m_maincpu->pulse_input_line(INPUT_LINE_RESET, attotime::zero);
1653 	}
1654 
1655 	/* bit 2 is speaker */
1656 
1657 	/* IPL reset */
1658 	if((m_old_portc & 0x08) == 0x00 && (data & 0x08))
1659 		reset_banks(IPL_RESET);
1660 
1661 	m_old_portc = data;
1662 
1663 	m_beeper->set_state(data & 0x04);
1664 
1665 	m_screen_enable = data & 1;
1666 
1667 	if(data & ~0x0f)
1668 		logerror("PPI PORTC W %02x\n",data & ~0x0f);
1669 }
1670 
mz2500_pio1_porta_w(uint8_t data)1671 void mz2500_state::mz2500_pio1_porta_w(uint8_t data)
1672 {
1673 //  printf("%02x\n",data);
1674 
1675 	if(m_prev_col_val != ((data & 0x20) >> 5))
1676 	{
1677 		m_text_col_size = ((data & 0x20) >> 5);
1678 		m_prev_col_val = m_text_col_size;
1679 		mz2500_reconfigure_screen();
1680 	}
1681 	m_key_mux = data & 0x1f;
1682 }
1683 
1684 
mz2500_pio1_porta_r()1685 uint8_t mz2500_state::mz2500_pio1_porta_r()
1686 {
1687 	static const char *const keynames[] = { "KEY0", "KEY1", "KEY2", "KEY3",
1688 											"KEY4", "KEY5", "KEY6", "KEY7",
1689 											"KEY8", "KEY9", "KEYA", "KEYB",
1690 											"KEYC", "KEYD", "UNUSED", "UNUSED" };
1691 
1692 	if(((m_key_mux & 0x10) == 0x00) || ((m_key_mux & 0x0f) == 0x0f)) //status read
1693 	{
1694 		int res,i;
1695 
1696 		res = 0xff;
1697 		for(i=0;i<0xe;i++)
1698 			res &= ioport(keynames[i])->read();
1699 
1700 		m_pio_latchb = res;
1701 
1702 		return res;
1703 	}
1704 
1705 	m_pio_latchb = ioport(keynames[m_key_mux & 0xf])->read();
1706 
1707 	return ioport(keynames[m_key_mux & 0xf])->read();
1708 }
1709 
1710 #if 0
1711 uint8_t mz2500_state::mz2500_pio1_portb_r()
1712 {
1713 	return m_pio_latchb;
1714 }
1715 #endif
1716 
opn_porta_r()1717 uint8_t mz2500_state::opn_porta_r()
1718 {
1719 	return m_ym_porta;
1720 }
1721 
opn_porta_w(uint8_t data)1722 void mz2500_state::opn_porta_w(uint8_t data)
1723 {
1724 	/*
1725 	---- x--- mouse select
1726 	---- -x-- palette bit (16/4096 colors)
1727 	---- --x- floppy reverse bit (controls wd17xx bits in command registers)
1728 	*/
1729 
1730 	m_fdc_reverse = data & 2;
1731 	m_pal_select = (data & 4) ? 1 : 0;
1732 
1733 	m_ym_porta = data;
1734 }
1735 
mz2500_palette(palette_device & palette) const1736 void mz2500_state::mz2500_palette(palette_device &palette) const
1737 {
1738 	for (int i = 0; i < 0x200; i++)
1739 		palette.set_pen_color(i,pal1bit(0),pal1bit(0),pal1bit(0));
1740 
1741 	// set up 8 colors (PCG)
1742 	for (int i = 0; i < 8; i++)
1743 		palette.set_pen_color(i+8,pal1bit((i & 2)>>1),pal1bit((i & 4)>>2),pal1bit((i & 1)>>0));
1744 
1745 	// set up 16 colors (PCG / CG)
1746 
1747 	// set up 256 colors (CG)
1748 	for (int i = 0; i < 0x100; i++)
1749 	{
1750 		int bit0, bit1, bit2;
1751 
1752 		bit0 = pal_256_param(i,0) ? 1 : 0;
1753 		bit1 = i & 0x01 ? 2 : 0;
1754 		bit2 = i & 0x10 ? 4 : 0;
1755 		int const b = bit0|bit1|bit2;
1756 		bit0 = pal_256_param(i,0) ? 1 : 0;
1757 		bit1 = i & 0x02 ? 2 : 0;
1758 		bit2 = i & 0x20 ? 4 : 0;
1759 		int const r = bit0|bit1|bit2;
1760 		bit0 = pal_256_param(i,0) ? 1 : 0;
1761 		bit1 = i & 0x04 ? 2 : 0;
1762 		bit2 = i & 0x40 ? 4 : 0;
1763 		int const g = bit0|bit1|bit2;
1764 
1765 		palette.set_pen_color(i + 0x100, pal3bit(r), pal3bit(g), pal3bit(b));
1766 	}
1767 }
1768 
1769 /* PIT8253 Interface */
1770 
WRITE_LINE_MEMBER(mz2500_state::pit8253_clk0_irq)1771 WRITE_LINE_MEMBER(mz2500_state::pit8253_clk0_irq)
1772 {
1773 	if(m_irq_mask[1] && state & 1)
1774 	{
1775 		m_irq_pending[1] = 1;
1776 		m_maincpu->set_input_line(0, ASSERT_LINE);
1777 	}
1778 }
1779 
WRITE_LINE_MEMBER(mz2500_state::mz2500_rtc_alarm_irq)1780 WRITE_LINE_MEMBER(mz2500_state::mz2500_rtc_alarm_irq)
1781 {
1782 	/* TODO: doesn't work yet */
1783 //  if(m_irq_mask[3] && state & 1)
1784 //      m_maincpu->set_input_line_and_vector(0, HOLD_LINE,drvm_irq_vector[3]); // Z80
1785 }
1786 
1787 
mz2500_floppies(device_slot_interface & device)1788 static void mz2500_floppies(device_slot_interface &device)
1789 {
1790 	device.option_add("dd", FLOPPY_35_DD);
1791 }
1792 
mz2500(machine_config & config)1793 void mz2500_state::mz2500(machine_config &config)
1794 {
1795 	/* basic machine hardware */
1796 	Z80(config, m_maincpu, 6000000);
1797 	m_maincpu->set_addrmap(AS_PROGRAM, &mz2500_state::mz2500_map);
1798 	m_maincpu->set_addrmap(AS_IO, &mz2500_state::mz2500_io);
1799 	m_maincpu->set_vblank_int("screen", FUNC(mz2500_state::mz2500_vbl));
1800 	m_maincpu->set_irq_acknowledge_callback(FUNC(mz2500_state::mz2500_irq_ack));
1801 
1802 	for (int bank = 0; bank < 8; bank++)
1803 	{
1804 		ADDRESS_MAP_BANK(config, m_rambank[bank]).set_map(&mz2500_state::mz2500_bank_window_map).set_options(ENDIANNESS_LITTLE, 8, 16+3, 0x2000);
1805 	}
1806 
1807 	i8255_device &ppi(I8255(config, "i8255_0"));
1808 	ppi.in_pa_callback().set(FUNC(mz2500_state::mz2500_porta_r));
1809 	ppi.out_pa_callback().set(FUNC(mz2500_state::mz2500_porta_w));
1810 	ppi.in_pb_callback().set(FUNC(mz2500_state::mz2500_portb_r));
1811 	ppi.out_pb_callback().set(FUNC(mz2500_state::mz2500_portb_w));
1812 	ppi.in_pc_callback().set(FUNC(mz2500_state::mz2500_portc_r));
1813 	ppi.out_pc_callback().set(FUNC(mz2500_state::mz2500_portc_w));
1814 
1815 	z80pio_device& pio(Z80PIO(config, "z80pio_1", 6000000));
1816 	pio.in_pa_callback().set(FUNC(mz2500_state::mz2500_pio1_porta_r));
1817 	pio.out_pa_callback().set(FUNC(mz2500_state::mz2500_pio1_porta_w));
1818 	pio.in_pb_callback().set(FUNC(mz2500_state::mz2500_pio1_porta_r));
1819 
1820 	Z80SIO(config, "z80sio", 6000000);
1821 
1822 	RP5C15(config, m_rtc, 32.768_kHz_XTAL);
1823 	m_rtc->alarm().set(FUNC(mz2500_state::mz2500_rtc_alarm_irq));
1824 
1825 	PIT8253(config, m_pit, 0);
1826 	m_pit->set_clk<0>(31250);
1827 	m_pit->out_handler<0>().set(FUNC(mz2500_state::pit8253_clk0_irq));
1828 	// TODO: is this really right?
1829 	m_pit->set_clk<1>(0);
1830 	m_pit->set_clk<2>(16); //CH2, used by Super MZ demo / The Black Onyx and a few others (TODO: timing of this)
1831 	m_pit->out_handler<2>().set(m_pit, FUNC(pit8253_device::write_clk1));
1832 
1833 	MB8877(config, m_fdc, 1_MHz_XTAL);
1834 
1835 	FLOPPY_CONNECTOR(config, "mb8877a:0", mz2500_floppies, "dd", floppy_image_device::default_floppy_formats);
1836 	FLOPPY_CONNECTOR(config, "mb8877a:1", mz2500_floppies, "dd", floppy_image_device::default_floppy_formats);
1837 	FLOPPY_CONNECTOR(config, "mb8877a:2", mz2500_floppies, "dd", floppy_image_device::default_floppy_formats);
1838 	FLOPPY_CONNECTOR(config, "mb8877a:3", mz2500_floppies, "dd", floppy_image_device::default_floppy_formats);
1839 
1840 	SOFTWARE_LIST(config, "flop_list").set_original("mz2500");
1841 
1842 	/* video hardware */
1843 	SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
1844 	m_screen->set_raw(21'477'272, 640+108, 0, 640, 480, 0, 200); //unknown clock / divider
1845 	m_screen->set_screen_update(FUNC(mz2500_state::screen_update_mz2500));
1846 	m_screen->set_palette(m_palette);
1847 
1848 	PALETTE(config, m_palette, FUNC(mz2500_state::mz2500_palette), 0x200);
1849 
1850 	GFXDECODE(config, m_gfxdecode, m_palette, gfx_mz2500);
1851 
1852 
1853 	SPEAKER(config, "mono").front_center();
1854 
1855 	ym2203_device &ym(YM2203(config, "ym", 2000000)); //unknown clock / divider
1856 	ym.port_a_read_callback().set(FUNC(mz2500_state::opn_porta_r));
1857 	ym.port_b_read_callback().set_ioport("DSW1");
1858 	ym.port_a_write_callback().set(FUNC(mz2500_state::opn_porta_w));
1859 	ym.add_route(0, "mono", 0.25);
1860 	ym.add_route(1, "mono", 0.25);
1861 	ym.add_route(2, "mono", 0.50);
1862 	ym.add_route(3, "mono", 0.50);
1863 
1864 	BEEP(config, m_beeper, 4096).add_route(ALL_OUTPUTS,"mono",0.50);
1865 }
1866 
1867 
1868 
1869 /* ROM definition */
1870 ROM_START( mz2500 )
1871 	ROM_REGION( 0x08000, "ipl", 0 )
1872 	ROM_LOAD( "ipl.rom", 0x00000, 0x8000, CRC(7a659f20) SHA1(ccb3cfdf461feea9db8d8d3a8815f7e345d274f7) )
1873 
1874 	/* this is probably an hand made ROM, will be removed in the end ...*/
1875 	ROM_REGION( 0x1000, "cgrom", 0 )
1876 	ROM_LOAD( "cg.rom", 0x0000, 0x0800, CRC(a082326f) SHA1(dfa1a797b2159838d078650801c7291fa746ad81) )
1877 
1878 	ROM_REGION( 0x40000, "kanji", 0 )
1879 	ROM_LOAD( "kanji.rom", 0x0000, 0x40000, CRC(dd426767) SHA1(cc8fae0cd1736bc11c110e1c84d3f620c5e35b80) )
1880 
1881 	ROM_REGION( 0x20000, "kanji2", 0 )
1882 	ROM_LOAD( "kanji2.rom", 0x0000, 0x20000, CRC(eaaf20c9) SHA1(771c4d559b5241390215edee798f3bce169d418c) )
1883 
1884 	ROM_REGION( 0x40000, "dictionary", 0 )
1885 	ROM_LOAD( "dict.rom", 0x00000, 0x40000, CRC(aa957c2b) SHA1(19a5ba85055f048a84ed4e8d471aaff70fcf0374) )
1886 
1887 	ROM_REGION( 0x8000, "iplpro", ROMREGION_ERASEFF )
1888 	ROM_LOAD( "sasi.rom", 0x00000, 0x8000, CRC(a7bf39ce) SHA1(3f4a237fc4f34bac6fe2bbda4ce4d16d42400081) )
1889 
1890 	ROM_REGION( 0x8000, "phone", ROMREGION_ERASEFF )
1891 	ROM_LOAD( "phone.rom", 0x00000, 0x4000, CRC(8e49e4dc) SHA1(2589f0c95028037a41ca32a8fd799c5f085dab51) )
1892 ROM_END
1893 
1894 ROM_START( mz2520 )
1895 	ROM_REGION( 0x08000, "ipl", 0 )
1896 	ROM_LOAD( "ipl2520.rom", 0x00000, 0x8000, CRC(0a126eb2) SHA1(faf71236b3ad82d30184adea951d43d10ced663d) )
1897 
1898 	/* this is probably an hand made ROM, will be removed in the end ...*/
1899 	ROM_REGION( 0x1000, "cgrom", 0 )
1900 	ROM_LOAD( "cg.rom", 0x0000, 0x0800, CRC(a082326f) SHA1(dfa1a797b2159838d078650801c7291fa746ad81) )
1901 
1902 	ROM_REGION( 0x40000, "kanji", 0 )
1903 	ROM_LOAD( "kanji.rom", 0x0000, 0x40000, CRC(dd426767) SHA1(cc8fae0cd1736bc11c110e1c84d3f620c5e35b80) )
1904 
1905 	ROM_REGION( 0x20000, "kanji2", 0 )
1906 	ROM_LOAD( "kanji2.rom", 0x0000, 0x20000, CRC(eaaf20c9) SHA1(771c4d559b5241390215edee798f3bce169d418c) )
1907 
1908 	ROM_REGION( 0x40000, "dictionary", 0 )
1909 	ROM_LOAD( "dict.rom", 0x00000, 0x40000, CRC(aa957c2b) SHA1(19a5ba85055f048a84ed4e8d471aaff70fcf0374) )
1910 
1911 	ROM_REGION( 0x8000, "iplpro", ROMREGION_ERASEFF )
1912 	ROM_LOAD( "sasi.rom", 0x00000, 0x8000, CRC(a7bf39ce) SHA1(3f4a237fc4f34bac6fe2bbda4ce4d16d42400081) )
1913 
1914 	ROM_REGION( 0x8000, "phone", ROMREGION_ERASEFF )
1915 	ROM_LOAD( "phone.rom", 0x00000, 0x4000, CRC(8e49e4dc) SHA1(2589f0c95028037a41ca32a8fd799c5f085dab51) )
1916 ROM_END
1917 
1918 /* Driver */
1919 
1920 COMP( 1985, mz2500, 0,      0, mz2500, mz2500, mz2500_state, empty_init, "Sharp", "MZ-2500", MACHINE_IMPERFECT_GRAPHICS )
1921 COMP( 1985, mz2520, mz2500, 0, mz2500, mz2500, mz2500_state, empty_init, "Sharp", "MZ-2520", MACHINE_IMPERFECT_GRAPHICS ) // looks a stripped down version of the regular MZ-2500, with only two floppies drives and no cassette interface
1922