1 /*
2 * UAE - The Un*x Amiga Emulator
3 *
4 * A2410
5 *
6 */
7 #include "sysconfig.h"
8 #include "sysdeps.h"
9 
10 #include "debug.h"
11 #include "mameglue.h"
12 #include "tm34010/tms34010.h"
13 
14 #include "options.h"
15 #include "memory.h"
16 #include "custom.h"
17 #include "picasso96.h"
18 #include "statusline.h"
19 #include "newcpu.h"
20 #include "gfxboard.h"
21 
22 static int tms_vp, tms_hp;
23 rectangle tms_rectangle;
24 static mscreen tms_screen;
25 static tms340x0_device tms_device;
26 static address_space tms_space;
27 mscreen *m_screen;
28 
29 #define OVERLAY_WIDTH 1024
30 
31 static int fullrefresh;
32 static int request_fullrefresh;
33 static uae_u8 *program_ram;
34 static int a2410_palette_index;
35 static uae_u8 a2410_palette[4 * (256 + 4)];
36 static uae_u32 a2410_palette_32[256 + 4];
37 static uae_u8 a2410_palette_temp[4];
38 static uae_u8 a2410_palette_control[4];
39 static uae_u16 a2410_control;
40 static bool a2410_modified[1024];
41 static int a2410_displaywidth;
42 static int a2410_displayend;
43 static int a2410_vertical_start;
44 static bool a2410_enabled;
45 static uae_u8 a2410_overlay_mask[2];
46 static int a2410_overlay_blink_rate_on;
47 static int a2410_overlay_blink_rate_off;
48 static int a2410_overlay_blink_cnt;
49 static int tms_configured;
50 static uae_u8 tms_config[128];
51 extern addrbank tms_bank;
52 
hpos()53 int mscreen::hpos()
54 {
55 	if (a2410_displayend) {
56 		tms_hp++;
57 		tms_hp %= a2410_displayend;
58 	} else {
59 		tms_hp = 0;
60 	}
61 	return tms_hp;
62 }
vpos()63 int mscreen::vpos()
64 {
65 	return tms_vp;
66 }
67 
tms_execute_single(void)68 static void tms_execute_single(void)
69 {
70 	tms_device.m_icount = 2;
71 	tms_device.execute_run();
72 }
73 
74 #define A2410_BANK_FRAMEBUFFER 1
75 #define A2410_BANK_PROGRAM 2
76 #define A2410_BANK_RAMDAC 3
77 #define A2410_BANK_CONTROL 4
78 #define A2410_BANK_TMSIO 5
79 #define A2410_BANK_DMA 6
80 
makeaddr(UINT32 a,int * bank)81 static uaecptr makeaddr(UINT32 a, int *bank)
82 {
83 	uaecptr addr = 0;
84 	UINT32 aa = a << 3;
85 	if ((aa & 0xf0000000) == 0xc0000000) {
86 		*bank = A2410_BANK_TMSIO;
87 		addr = (a & 0xff) >> 1;
88 	} else if ((aa & 0x01900000) == 0x00800000) {
89 		*bank = A2410_BANK_RAMDAC;
90 		addr = (a >> 1) & 3;
91 	} else if ((aa & 0x01900000) == 0x00900000) {
92 		*bank = A2410_BANK_CONTROL;
93 	} else if ((aa & 0x30000000) == 0x10000000) {
94 		addr = a & 0xffffff;
95 		*bank = A2410_BANK_DMA;
96 	} else if ((aa & 0x01800000) == 0x01800000) {
97 		addr = a & 0xfffff;
98 		*bank = A2410_BANK_PROGRAM;
99 	} else if ((aa & 0x01800000) == 0x00000000) {
100 		addr = a & 0xfffff;
101 		*bank = A2410_BANK_FRAMEBUFFER;
102 	} else {
103 		*bank = 0;
104 		write_log(_T("Unknown BANK %08x PC=%08x\n"), aa, M68K_GETPC);
105 	}
106 	return addr;
107 }
108 
109 /* CONTROL
110  *
111  * bit 0 - OSC_SEL - oscillator select
112  * bit 1 - _SOG_EN - sync on green
113  * bit 2 - SWAP - byte swap enable for DMA
114  * bit 3 - SBR - bus request from TMS34010 (Sets bit 7 when bus granted)
115  * bit 4 - D_BLANK (read only) - seems to be related to BLANK output of TMS and VSYNC
116  * bit 5 - AGBG (read only) - comes straight from Zorro II BCLR signal ?
117  * bit 6 - AID = Z3Sense pin when read, HS_INV when write (Horizontal Sync Invert)
118  * bit 7 - LGBACK when read, VS_INV when write (Vertical Sync Invert) - LGBACK: A2410 owns the Zorro bus now.
119  */
120 
get_a2410_control(void)121 static uae_u8 get_a2410_control(void)
122 {
123 	uae_u8 v = a2410_control;
124 	v &= ~(0x10 | 0x40 | 0x80);
125 	v |= 0x20;
126 	if (v & 0x08) // SBR
127 		v |= 0x80; // LGBACK
128 	if (currprefs.cs_compatible == CP_A3000 || currprefs.cs_compatible == CP_A3000T ||
129 		currprefs.cs_compatible == CP_A4000 || currprefs.cs_compatible == CP_A4000T ||
130 		currprefs.cs_z3autoconfig)
131 		v |= 0x40; // AID
132 	return v;
133 }
134 
total_cycles(void)135 UINT32 total_cycles(void)
136 {
137 	return get_cycles() / CYCLE_UNIT;
138 }
139 
m_to_shiftreg_cb(address_space space,offs_t offset,UINT16 * shiftreg)140 void m_to_shiftreg_cb(address_space space, offs_t offset, UINT16 *shiftreg)
141 {
142 	memcpy(shiftreg, &gfxmem_bank.baseaddr[TOWORD(offset)], 256 * sizeof(UINT16));
143 }
m_from_shiftreg_cb(address_space space,offs_t offset,UINT16 * shiftreg)144 void m_from_shiftreg_cb(address_space space, offs_t offset, UINT16* shiftreg)
145 {
146 	memcpy(&gfxmem_bank.baseaddr[TOWORD(offset)], shiftreg, 256 * sizeof(UINT16));
147 }
148 
read_decrypted_word(UINT32 pc)149 UINT16 direct_read_data::read_decrypted_word(UINT32 pc)
150 {
151 	uae_u16 v = 0;
152 	int bank;
153 	uaecptr addr = makeaddr(pc, &bank);
154 	v = program_ram[addr] << 8;
155 	v |= program_ram[addr + 1];
156 	//write_log(_T("TMS instruction word read RAM %08x (%08x) =%04x\n"), pc, addr, v);
157 	return v;
158 }
read_raw_word(UINT32 pc)159 UINT16 direct_read_data::read_raw_word(UINT32 pc)
160 {
161 	uae_u16 v = 0;
162 	int bank;
163 	uaecptr addr = makeaddr(pc, &bank);
164 	v = program_ram[addr] << 8;
165 	v |= program_ram[addr + 1];
166 	//write_log(_T("TMS instruction word read RAM %08x (%08x) =%04x\n"), pc, addr, v);
167 	return v;
168 }
169 
mark_overlay(int addr)170 static void mark_overlay(int addr)
171 {
172 	if (!a2410_enabled)
173 		return;
174 	addr &= 0x1ffff;
175 	addr /= OVERLAY_WIDTH / 8;
176 	a2410_modified[addr] = true;
177 }
178 
a2410_create_palette32(int offset)179 static void a2410_create_palette32(int offset)
180 {
181 	int idx = a2410_palette_index / 4 + offset;
182 	if (a2410_palette[idx * 4 + 0] != a2410_palette_temp[0] ||
183 		a2410_palette[idx * 4 + 1] != a2410_palette_temp[1] ||
184 		a2410_palette[idx * 4 + 2] != a2410_palette_temp[2]) {
185 		request_fullrefresh = 1;
186 	}
187 	a2410_palette[idx * 4 + 0] = a2410_palette_temp[0];
188 	a2410_palette[idx * 4 + 1] = a2410_palette_temp[1];
189 	a2410_palette[idx * 4 + 2] = a2410_palette_temp[2];
190 	a2410_palette_32[idx] =
191 		(a2410_palette_temp[0] << 16) |
192 		(a2410_palette_temp[1] <<  8) |
193 		(a2410_palette_temp[2] <<  0);
194 #if 0
195 	write_log(_T("PAL %d: %02x %02x %02x = %08x\n"),
196 		idx,
197 		a2410_palette_temp[0],
198 		a2410_palette_temp[1],
199 		a2410_palette_temp[2],
200 		a2410_palette_32[idx]);
201 #endif
202 }
203 
write_ramdac(int addr,uae_u8 v)204 static void write_ramdac(int addr, uae_u8 v)
205 {
206 	int coloridx = a2410_palette_index & 3;
207 	switch (addr)
208 	{
209 		case 0:
210 		a2410_palette_index = v * 4;
211 		break;
212 		case 1:
213 		a2410_palette_temp[coloridx] = v;
214 		a2410_palette_index++;
215 		if ((a2410_palette_index & 3) == 3) {
216 			a2410_create_palette32(0);
217 			a2410_palette_index++;
218 		}
219 		if (a2410_palette_index >= 256 * 4)
220 			a2410_palette_index = 0;
221 		break;
222 		case 2:
223 		if (a2410_palette_index >= 4 * 4 && a2410_palette_index < 8 * 4) {
224 			a2410_palette_control[a2410_palette_index / 4 - 4] = v;
225 		}
226 		a2410_overlay_mask[0] = 0xff;
227 		a2410_overlay_mask[1] = 0xff;
228 		if (!(a2410_palette_control[6 - 4] & 1))
229 			a2410_overlay_mask[0] = 0;
230 		if (!(a2410_palette_control[6 - 4] & 2))
231 			a2410_overlay_mask[1] = 0;
232 		switch((a2410_palette_control[6 - 4] >> 4) & 3)
233 		{
234 			case 0:
235 			a2410_overlay_blink_rate_on = 16;
236 			a2410_overlay_blink_rate_off = 48;
237 			break;
238 			case 1:
239 			a2410_overlay_blink_rate_on = 16;
240 			a2410_overlay_blink_rate_off = 16;
241 			break;
242 			case 2:
243 			a2410_overlay_blink_rate_on = 32;
244 			a2410_overlay_blink_rate_off = 32;
245 			break;
246 			case 3:
247 			a2410_overlay_blink_rate_on = 64;
248 			a2410_overlay_blink_rate_off = 64;
249 			break;
250 		}
251 		break;
252 		case 3:
253 		if (a2410_palette_index < 4 * 4) {
254 			a2410_palette_temp[coloridx] = v;
255 			a2410_palette_index++;
256 			if ((a2410_palette_index & 3) == 3) {
257 				a2410_create_palette32(256);
258 				a2410_palette_index++;
259 			}
260 			if (a2410_palette_index >= 4 * 4)
261 				a2410_palette_index = 0;
262 		}
263 		break;
264 		default:
265 		write_log(_T("Unknown write RAMDAC address %08x PC=%08x\n"), addr, M68K_GETPC);
266 		break;
267 	}
268 }
read_ramdac(int addr)269 static uae_u8 read_ramdac(int addr)
270 {
271 	uae_u8 v = 0;
272 	switch (addr)
273 	{
274 		case 0:
275 		v = a2410_palette_index / 4;
276 		break;
277 		case 1:
278 		v = a2410_palette[a2410_palette_index];
279 		a2410_palette_index++;
280 		if ((a2410_palette_index & 3) == 3)
281 			a2410_palette_index++;
282 		if (a2410_palette_index >= 256 * 4)
283 			a2410_palette_index = 0;
284 		break;
285 		case 2:
286 		if (a2410_palette_index >= 4 * 4 && a2410_palette_index < 8 * 4) {
287 			v = a2410_palette_control[a2410_palette_index / 4 - 4];
288 		}
289 		break;
290 		case 3:
291 		if (a2410_palette_index < 4 * 4) {
292 			v = a2410_palette[a2410_palette_index + 256 * 4];
293 			a2410_palette_index++;
294 			if ((a2410_palette_index & 3) == 3)
295 				a2410_palette_index = 0;
296 			if (a2410_palette_index >= 4 * 4)
297 				a2410_palette_index = 0;
298 		}
299 		break;
300 		default:
301 		write_log(_T("Unknown read RAMDAC address %08x PC=%08x\n"), addr, M68K_GETPC);
302 		break;
303 	}
304 	return v;
305 }
306 
valid_dma(uaecptr addr)307 static bool valid_dma(uaecptr addr)
308 {
309 	// prevent recursive DMA
310 	return addr < (tms_configured << 16) || addr >= ((tms_configured + 1) << 16);
311 }
312 
read_byte(UINT32 a)313 UINT8 address_space::read_byte(UINT32 a)
314 {
315 	int bank;
316 	uae_u8 v = 0;
317 	UINT32 aa = a << 3;
318 	uaecptr addr = makeaddr(a, &bank);
319 
320 	addr ^= 1;
321 	switch (bank)
322 	{
323 		case A2410_BANK_PROGRAM:
324 		v = program_ram[addr];
325 		//write_log(_T("TMS byte read RAM %08x (%08x) =%02x PC=%08x\n"), aa, addr, v, M68K_GETPC);
326 		break;
327 		case A2410_BANK_FRAMEBUFFER:
328 		v = gfxmem_bank.baseaddr[addr];
329 		//write_log(_T("TMS byte read framebuffer %08x (%08x) = %02x PC=%08x\n"), aa, addr, v, M68K_GETPC);
330 		break;
331 		case A2410_BANK_RAMDAC:
332 		v = read_ramdac(addr);
333 		//write_log(_T("RAMDAC READ %08x = %02x PC=%08x\n"), aa, v, M68K_GETPC);
334 		break;
335 		case A2410_BANK_CONTROL:
336 		v = get_a2410_control();
337 		write_log(_T("CONTROL READ %08x = %02x PC=%08x\n"), aa, v, M68K_GETPC);
338 		break;
339 		case A2410_BANK_DMA:
340 		if (valid_dma(addr)) {
341 			if (a2410_control & 4)
342 				addr ^= 1;
343 			v = get_byte(addr);
344 		}
345 		break;
346 		default:
347 		write_log(_T("UNKNOWN READ %08x = %02x PC=%08x\n"), aa, v, M68K_GETPC);
348 		break;
349 
350 	}
351 	return v;
352 }
read_word(UINT32 a)353 UINT16 address_space::read_word(UINT32 a)
354 {
355 	int bank;
356 	uae_u16 v = 0;
357 	UINT32 aa = a << 3;
358 	uaecptr addr = makeaddr(a, &bank);
359 
360 	switch (bank)
361 	{
362 		case A2410_BANK_TMSIO:
363 		v = tms_device.io_register_r(*this, addr);
364 		//write_log(_T("TMS IO word read %08x (%08x) = %04x PC=%08x PC=%08x\n"), aa, addr, v, M68K_GETPC);
365 		break;
366 		case A2410_BANK_PROGRAM:
367 		v = program_ram[addr] << 8;
368 		v |= program_ram[addr + 1];
369 		//write_log(_T("TMS program word read RAM %08x (%08x) = %04x PC=%08x\n"), aa, addr, v, M68K_GETPC);
370 		break;
371 		case A2410_BANK_FRAMEBUFFER:
372 		v = gfxmem_bank.baseaddr[addr] << 8;
373 		v |= gfxmem_bank.baseaddr[addr + 1];
374 		//write_log(_T("TMS gfx word read %08x (%08x) = %04x PC=%08x\n"), aa, addr, v, M68K_GETPC);
375 		break;
376 		case A2410_BANK_RAMDAC:
377 		v = read_ramdac(addr);
378 		//write_log(_T("RAMDAC READ %08x = %02x PC=%08x\n"), aa, v, M68K_GETPC);
379 		break;
380 		case A2410_BANK_CONTROL:
381 		v = get_a2410_control();
382 		write_log(_T("CONTROL READ %08x = %02x PC=%08x\n"), aa, v, M68K_GETPC);
383 		break;
384 		case A2410_BANK_DMA:
385 		if (valid_dma(addr)) {
386 			v = get_word(addr);
387 			if (a2410_control & 4)
388 				v = (v >> 8) | (v << 8);
389 		}
390 		break;
391 		default:
392 		write_log(_T("UNKNOWN READ %08x = %04x PC=%08x\n"), aa, v, M68K_GETPC);
393 		break;
394 	}
395 	return v;
396 }
397 
write_byte(UINT32 a,UINT8 b)398 void address_space::write_byte(UINT32 a, UINT8 b)
399 {
400 	int bank;
401 	UINT32 aa = a << 3;
402 	uaecptr addr = makeaddr(a, &bank);
403 	addr ^= 1;
404 	switch (bank)
405 	{
406 		case A2410_BANK_PROGRAM:
407 		program_ram[addr] = b;
408 		if (addr < 0x40000)
409 			mark_overlay(addr);
410 		//write_log(_T("TMS program byte write %08x (%08x) = %02x PC=%08x\n"), aa, addr, b, M68K_GETPC);
411 		break;
412 		case A2410_BANK_FRAMEBUFFER:
413 		gfxmem_bank.baseaddr[addr] = b;
414 		//write_log(_T("TMS gfx byte write %08x (%08x) = %02x PC=%08x\n"), aa, addr, b, M68K_GETPC);
415 		break;
416 		case A2410_BANK_RAMDAC:
417 		//write_log(_T("RAMDAC WRITE %08x = %02x PC=%08x\n"), aa, b, M68K_GETPC);
418 		write_ramdac(addr, b);
419 		break;
420 		case A2410_BANK_CONTROL:
421 		write_log(_T("CONTROL WRITE %08x = %02x PC=%08x\n"), aa, b, M68K_GETPC);
422 		a2410_control = b;
423 		break;
424 		case A2410_BANK_DMA:
425 		if (valid_dma(addr)) {
426 			if (a2410_control & 4)
427 				addr ^= 1;
428 			put_byte(addr, b);
429 		}
430 		break;
431 		default:
432 		write_log(_T("UNKNOWN WRITE %08x = %02x PC=%08x\n"), aa, b, M68K_GETPC);
433 		break;
434 	}
435 }
436 
write_word(UINT32 a,UINT16 b)437 void address_space::write_word(UINT32 a, UINT16 b)
438 {
439 	int bank;
440 	UINT32 aa = a << 3;
441 	uaecptr addr = makeaddr(a, &bank);
442 	switch (bank)
443 	{
444 		case A2410_BANK_TMSIO:
445 		tms_device.io_register_w(*this, addr, b);
446 		//write_log(_T("TMS IO word write %08x (%08x) = %04x PC=%08x\n"), aa, addr, b, M68K_GETPC);
447 		break;
448 		case A2410_BANK_PROGRAM:
449 		program_ram[addr] = b >> 8;
450 		program_ram[addr + 1] = b & 0xff;
451 		if (addr < 0x40000)
452 			mark_overlay(addr);
453 		//write_log(_T("TMS program word write RAM %08x (%08x) = %04x PC=%08x\n"), aa, addr, b, M68K_GETPC);
454 		break;
455 		case A2410_BANK_FRAMEBUFFER:
456 		gfxmem_bank.baseaddr[addr] = b >> 8;
457 		gfxmem_bank.baseaddr[addr + 1] = b & 0xff;
458 		//write_log(_T("TMS gfx word write %08x (%08x) = %04x PC=%08x\n"), aa, addr, b, M68K_GETPC);
459 		break;
460 		case A2410_BANK_RAMDAC:
461 		//write_log(_T("RAMDAC WRITE %08x = %04x IDX=%d/%d PC=%08x\n"), aa, b, a2410_palette_index / 4, a2410_palette_index & 3, M68K_GETPC);
462 		write_ramdac(addr, b);
463 		break;
464 		case A2410_BANK_CONTROL:
465 		write_log(_T("CONTROL WRITE %08x = %04x PC=%08x\n"), aa, b, M68K_GETPC);
466 		a2410_control = b;
467 		break;
468 		case A2410_BANK_DMA:
469 		if (valid_dma(addr)) {
470 			if (a2410_control & 4)
471 				b = (b >> 8) | (b << 8);
472 			put_word(addr, b);
473 		}
474 		break;
475 		default:
476 		write_log(_T("UNKNOWN WRITE %08x = %04x PC=%08x\n"), aa, b, M68K_GETPC);
477 		break;
478 	}
479 }
480 
tms_bget(uaecptr addr)481 static uae_u32 REGPARAM2 tms_bget(uaecptr addr)
482 {
483 	uae_u32 v = 0xff;
484 	addr &= 65535;
485 	if (!tms_configured) {
486 		v = tms_config[addr];
487 	} else {
488 		uae_u16 vv = tms_device.host_r(tms_space, addr >> 1);
489 		if (!(addr & 1))
490 			vv >>= 8;
491 		v = (uae_u8)vv;
492 		//write_log(_T("TMS read %08x = %02x PC=%08x\n"), addr, v & 0xff, M68K_GETPC);
493 		tms_execute_single();
494 	}
495 	return v;
496 }
tms_wget(uaecptr addr)497 static uae_u32 REGPARAM2 tms_wget(uaecptr addr)
498 {
499 	uae_u16 v;
500 	addr &= 65535;
501 	if (tms_configured) {
502 		v = tms_device.host_r(tms_space, addr >> 1);
503 		//write_log(_T("TMS read %08x = %04x PC=%08x\n"), addr, v & 0xffff, M68K_GETPC);
504 		tms_execute_single();
505 	} else {
506 		v = tms_bget(addr) << 8;
507 		v |= tms_bget(addr + 1);
508 	}
509 	return v;
510 }
tms_lget(uaecptr addr)511 static uae_u32 REGPARAM2 tms_lget(uaecptr addr)
512 {
513 	uae_u32 v;
514 	addr &= 65535;
515 	v = tms_wget(addr) << 16;
516 	v |= tms_wget(addr + 2);
517 	return v;
518 }
519 
520 
tms_wput(uaecptr addr,uae_u32 w)521 static void REGPARAM2 tms_wput(uaecptr addr, uae_u32 w)
522 {
523 	addr &= 65535;
524 	if (tms_configured) {
525 		//write_log(_T("TMS write %08x = %04x PC=%08x\n"), addr, w & 0xffff, M68K_GETPC);
526 		tms_device.host_w(tms_space, addr  >> 1, w);
527 		tms_execute_single();
528 	}
529 }
530 
tms_lput(uaecptr addr,uae_u32 l)531 static void REGPARAM2 tms_lput(uaecptr addr, uae_u32 l)
532 {
533 	addr &= 65535;
534 	tms_wput(addr, l >> 16);
535 	tms_wput(addr + 2, l);
536 }
537 
tms_bput(uaecptr addr,uae_u32 b)538 static void REGPARAM2 tms_bput(uaecptr addr, uae_u32 b)
539 {
540 	b &= 0xff;
541 	addr &= 65535;
542 	if (!tms_configured) {
543 		if (addr == 0x48 && !tms_configured) {
544 			map_banks_z2(&tms_bank, b, 0x10000 >> 16);
545 			tms_configured = b;
546 			expamem_next(&tms_bank, NULL);
547 			return;
548 		}
549 		if (addr == 0x4c && !tms_configured) {
550 			tms_configured = 0xff;
551 			expamem_shutup(&tms_bank);
552 			return;
553 		}
554 		return;
555 	}
556 	//write_log(_T("tms_bput %08x=%02x PC=%08x\n"), addr, b, M68K_GETPC);
557 	tms_device.host_w(tms_space, addr >> 1, (b << 8) | b);
558 	tms_execute_single();
559 }
560 
561 addrbank tms_bank = {
562 	tms_lget, tms_wget, tms_bget,
563 	tms_lput, tms_wput, tms_bput,
564 	default_xlate, default_check, NULL, NULL, _T("A2410"),
565 	tms_lget, tms_wget,
566 	ABFLAG_IO, S_READ, S_WRITE
567 };
568 
569 static bool a2410_modechanged;
570 static int a2410_gotmode;
571 static int a2410_width, a2410_height;
572 static int a2410_vram_start_offset;
573 static uae_u8 *a2410_surface;
574 static int a2410_interlace;
575 static int a2410_interrupt;
576 static int a2410_hsync_max;
577 
tms_reset(void)578 void tms_reset(void)
579 {
580 	if (a2410_surface)
581 		gfx_unlock_picasso(true);
582 	a2410_surface = NULL;
583 
584 	a2410_modechanged = false;
585 	a2410_gotmode = 0;
586 	a2410_interlace = 0;
587 	a2410_interrupt = 0;
588 	a2410_hsync_max = 2;
589 
590 	if (program_ram)
591 		tms_device.device_reset();
592 	tms_configured = 0;
593 }
594 
ew(int addr,uae_u32 value)595 static void ew(int addr, uae_u32 value)
596 {
597 	addr &= 0xffff;
598 	if (addr == 00 || addr == 02 || addr == 0x40 || addr == 0x42) {
599 		tms_config[addr] = (value & 0xf0);
600 		tms_config[addr + 2] = (value & 0x0f) << 4;
601 	} else {
602 		tms_config[addr] = ~(value & 0xf0);
603 		tms_config[addr + 2] = ~((value & 0x0f) << 4);
604 	}
605 }
606 
tms_free(void)607 void tms_free(void)
608 {
609 	if (a2410_surface)
610 		gfx_unlock_picasso(true);
611 	a2410_surface = NULL;
612 	mapped_free(&gfxmem_bank);
613 	xfree(program_ram);
614 	program_ram = NULL;
615 }
616 
tms_init(int devnum)617 addrbank *tms_init(int devnum)
618 {
619 	memset(tms_config, 0xff, sizeof tms_config);
620 	ew(0x00, 0xc0 | 0x01);
621 	// product id
622 	ew(0x04, 0x00);
623 	// manufacturer id
624 	ew(0x10, 1030 >> 8);
625 	ew(0x14, 1030 & 0xff);
626 
627 	mapped_free(&gfxmem_bank);
628 	xfree(program_ram);
629 
630 	gfxmem_bank.label = _T("ram_a8");
631 	gfxmem_bank.allocated = 1 * 1024 * 1024;
632 	mapped_malloc(&gfxmem_bank);
633 	picasso_allocatewritewatch(gfxmem_bank.allocated);
634 	gfxmem_bank.start = 0xa80000;
635 
636 	program_ram = xcalloc(uae_u8, 1 * 1024 * 1024);
637 
638 	m_screen = &tms_screen;
639 	tms_device.device_start();
640 	tms_reset();
641 
642 	return &tms_bank;
643 }
644 
configure(int width,int height,rectangle vis)645 void mscreen::configure(int width, int height, rectangle vis)
646 {
647 	int ow = a2410_width, oh = a2410_height;
648 	a2410_width = vis.max_x - vis.min_x + 1;
649 	a2410_height = vis.max_y - vis.min_y + 1;
650 	a2410_interlace = vis.interlace ? 1 : 0;
651 	if (a2410_interlace)
652 		a2410_height *= 2;
653 	a2410_modechanged = true;
654 	a2410_gotmode = true;
655 	m_screen->height_v = height;
656 	m_screen->width_v = width;
657 	tms_rectangle = vis;
658 	write_log(_T("A2410 %d*%d -> %d*%d\n"), ow, oh, a2410_width, a2410_height);
659 	a2410_hsync_max = a2410_height / 300;
660 }
661 
get_a2410_surface(void)662 static void get_a2410_surface(void)
663 {
664 	bool gotsurf = false;
665 	if (picasso_on) {
666 		if (a2410_surface == NULL) {
667 			a2410_surface = gfx_lock_picasso(false, false);
668 			gotsurf = true;
669 		}
670 		if (a2410_surface && gotsurf) {
671 			if (!(currprefs.leds_on_screen & STATUSLINE_TARGET))
672 				picasso_statusline(a2410_surface);
673 		}
674 	}
675 }
676 
tms_toggle(int mode)677 bool tms_toggle(int mode)
678 {
679 	if (!tms_configured)
680 		return false;
681 
682 	if (a2410_enabled) {
683 		a2410_enabled = false;
684 		a2410_modechanged = false;
685 		picasso_requested_on = 0;
686 		a2410_gotmode = -1;
687 		return true;
688 	} else {
689 		if (!a2410_gotmode)
690 			return false;
691 		a2410_gotmode = 1;
692 		a2410_modechanged = true;
693 		return true;
694 	}
695 	return false;
696 }
697 
tms_vsync_handler2(bool internalsync)698 static void tms_vsync_handler2(bool internalsync)
699 {
700 	if (!tms_configured)
701 		return;
702 
703 	tms34010_display_params parms;
704 	tms_device.get_display_params(&parms);
705 	bool enabled = parms.enabled != 0 && a2410_gotmode > 0;
706 
707 	if (enabled != a2410_enabled || a2410_modechanged) {
708 		if (a2410_surface)
709 			gfx_unlock_picasso(false);
710 		a2410_surface = NULL;
711 
712 		if (!enabled) {
713 			picasso_requested_on = 0;
714 		} else {
715 			if (a2410_modechanged) {
716 				picasso96_state.Width = a2410_width;
717 				picasso96_state.Height = a2410_height;
718 				picasso96_state.BytesPerPixel = 1;
719 				picasso96_state.RGBFormat = RGBFB_CLUT;
720 				write_log(_T("A2410 %d*%d\n"), a2410_width, a2410_height);
721 				gfx_set_picasso_modeinfo(a2410_width, a2410_height, 1, RGBFB_NONE);
722 				init_hz_p96();
723 			}
724 			picasso_requested_on = 1;
725 			a2410_modechanged = false;
726 			fullrefresh = 2;
727 		}
728 		a2410_enabled = enabled;
729 		write_log(_T("A2410 ACTIVE=%d\n"), a2410_enabled);
730 	}
731 
732 	if (picasso_on) {
733 		if (currprefs.leds_on_screen & STATUSLINE_RTG) {
734 			get_a2410_surface();
735 		}
736 		if (internalsync) {
737 			if (fullrefresh > 0)
738 				fullrefresh--;
739 			if (request_fullrefresh) {
740 				fullrefresh = 1;
741 				request_fullrefresh = 0;
742 			}
743 		}
744 	}
745 
746 	if (a2410_surface)
747 		gfx_unlock_picasso(true);
748 	a2410_surface = NULL;
749 
750 	a2410_interlace = -a2410_interlace;
751 
752 	a2410_overlay_blink_cnt++;
753 	if (a2410_overlay_blink_cnt == 0 || a2410_overlay_blink_cnt == a2410_overlay_blink_rate_on) {
754 		// any blink mode enabled?
755 		if (a2410_palette_control[5 - 4] != 0 || (a2410_palette_control[6 - 4] & (4 | 8)))
756 			fullrefresh++;
757 	}
758 	if (a2410_overlay_blink_cnt > a2410_overlay_blink_rate_off + a2410_overlay_blink_rate_on) {
759 		a2410_overlay_blink_cnt = 0;
760 	}
761 }
762 
763 
a2410_rethink(void)764 static void a2410_rethink(void)
765 {
766 	if (a2410_interrupt)
767 		INTREQ_0(0x8000 | 0x0008);
768 }
769 
tms_vsync_handler(void)770 bool tms_vsync_handler(void)
771 {
772 	bool flushed = false;
773 	if (!a2410_enabled)
774 		tms_vsync_handler2(false);
775 
776 	if (a2410_surface) {
777 		gfx_unlock_picasso(false);
778 		flushed = true;
779 	}
780 	a2410_surface = NULL;
781 	return flushed;
782 }
783 
tms_hsync_handler2(void)784 static void tms_hsync_handler2(void)
785 {
786 	if (!tms_configured)
787 		return;
788 
789 	tms_device.m_icount = 100;
790 	tms_device.execute_run();
791 	int a2410_vpos = tms_vp;
792 	tms_vp = tms_device.scanline_callback(NULL, tms_vp, a2410_interlace < 0);
793 
794 	a2410_rethink();
795 
796 	if (!a2410_enabled)
797 		return;
798 
799 	if (a2410_vpos == 0) {
800 		tms_vsync_handler2(true);
801 		picasso_getwritewatch(a2410_vram_start_offset);
802 	}
803 
804 	if (a2410_modechanged)
805 		return;
806 
807 	tms34010_display_params parms;
808 	tms_device.get_display_params(&parms);
809 
810 	a2410_displaywidth = parms.hsblnk - parms.heblnk;
811 	a2410_displayend = parms.heblnk;
812 	a2410_vertical_start = parms.veblnk;
813 
814 	int overlay_yoffset = a2410_vpos - a2410_vertical_start;
815 
816 	int coladdr = parms.coladdr;
817 	int vramoffset = ((parms.rowaddr << 8) & 0x7ffff);
818 	uae_u16 *vram = (uae_u16*)gfxmem_bank.baseaddr + vramoffset;
819 
820 	int overlayoffset = a2410_vpos - parms.veblnk;
821 
822 	if (overlay_yoffset < 0)
823 		return;
824 
825 	if (a2410_interlace) {
826 		overlay_yoffset *= 2;
827 		if (a2410_interlace < 0)
828 			overlay_yoffset++;
829 	}
830 
831 	if (overlay_yoffset >= a2410_height || overlay_yoffset >= picasso_vidinfo.height)
832 		return;
833 
834 
835 	if (!fullrefresh && !a2410_modified[overlay_yoffset]) {
836 		if (!picasso_is_vram_dirty(gfxmem_bank.start + (vramoffset << 1), a2410_displaywidth)) {
837 			if (!picasso_is_vram_dirty(gfxmem_bank.start + ((vramoffset + 0x200) << 1), a2410_displaywidth)) {
838 				return;
839 			}
840 		}
841 	}
842 
843 	a2410_modified[overlay_yoffset] = false;
844 
845 	get_a2410_surface();
846 	uae_u8 *dst = a2410_surface;
847 	if (!dst)
848 		return;
849 	dst += overlay_yoffset * picasso_vidinfo.rowbytes;
850 	uae_u32 *dst32 = (uae_u32*)dst;
851 
852 	uae_u8 *overlay0 = program_ram + overlayoffset * OVERLAY_WIDTH / 8;
853 	uae_u8 *overlay1 = overlay0 + 0x20000;
854 
855 	bool overlay0color = !(a2410_palette_control[6 - 4] & 0x40);
856 	uae_u16 bitmap_mask = a2410_palette_control[4 - 4];
857 
858 	uae_u8 overlay_mask[2] = { a2410_overlay_mask[0], a2410_overlay_mask[1] };
859 	if (a2410_overlay_blink_cnt >= a2410_overlay_blink_rate_on) {
860 		if (a2410_palette_control[6 - 4] & 4)
861 			overlay_mask[0] = 0;
862 		if (a2410_palette_control[6 - 4] & 8)
863 			overlay_mask[1] = 0;
864 		bitmap_mask &= ~a2410_palette_control[5 - 4];
865 	}
866 
867 	int xx = 0;
868 	int overlay_offset = 0;
869 	int overlay_bitcount = 0;
870 	uae_u8 opix0 = 0, opix1 = 0;
871 
872 	for (int x = parms.heblnk; x < parms.hsblnk && xx < picasso_vidinfo.width; x += 2, xx += 2) {
873 
874 		if (a2410_vpos >= parms.veblnk && a2410_vpos < parms.vsblnk) {
875 
876 			if (!overlay_bitcount && overlayoffset >= 0) {
877 				opix0 = overlay0[overlay_offset ^ 1] & a2410_overlay_mask[0];
878 				opix1 = overlay1[overlay_offset ^ 1] & a2410_overlay_mask[1];
879 				overlay_offset++;
880 			}
881 
882 			uae_u16 pix = vram[coladdr & 0x1ff];
883 			coladdr++;
884 
885 			if (overlay0color || opix0 || opix1) {
886 
887 				int pal;
888 				uae_u8 ov;
889 
890 				pal = (pix >> 8) & bitmap_mask;
891 				ov = opix0 & 1;
892 				ov |= (opix1 & 1) << 1;
893 				if (ov || overlay0color)
894 					pal = 256 + ov;
895 				*dst32++ = a2410_palette_32[pal];
896 				opix0 >>= 1;
897 				opix1 >>= 1;
898 
899 				pal = pix & bitmap_mask;
900 				ov = opix0 & 1;
901 				ov |= (opix1 & 1) << 1;
902 				if (ov || overlay0color)
903 					pal = 256 + ov;
904 				*dst32++ = a2410_palette_32[pal];
905 				opix0 >>= 1;
906 				opix1 >>= 1;
907 
908 
909 			} else {
910 
911 				*dst32++ = a2410_palette_32[pix >> 8];
912 				*dst32++ = a2410_palette_32[pix & 0xff];
913 
914 				opix0 >>= 2;
915 				opix1 >>= 2;
916 
917 			}
918 
919 			overlay_bitcount += 2;
920 			overlay_bitcount &= 7;
921 		}
922 	}
923 
924 	while (xx < picasso_vidinfo.width) {
925 		*dst32++ = 0;
926 		xx++;
927 	}
928 
929 }
930 
tms_hsync_handler(void)931 void tms_hsync_handler(void)
932 {
933 	for (int i = 0; i < a2410_hsync_max; i++)
934 		tms_hsync_handler2();
935 }
936 
standard_irq_callback(int level)937 void standard_irq_callback(int level)
938 {
939 	a2410_interrupt = level;
940 	a2410_rethink();
941 }
942