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