|
|
1.1 root 1: /*
1.1.1.5 root 2: Hatari - vdi.c
3:
1.1.1.16 root 4: This file is distributed under the GNU General Public License, version 2
5: or at your option any later version. Read the file gpl.txt for details.
1.1 root 6:
7: VDI (Virtual Device Interface) (Trap #2)
8:
1.1.1.5 root 9: To get higher resolutions on the Desktop, we intercept the VDI/Line-A calls
10: and set elements in their structures to the higher width/height/cel/planes.
11: We need to intercept the initial Line-A call (which we force into the TOS on
12: boot-up) and also the init calls to the VDI.
1.1 root 13: */
1.1.1.12 root 14: const char VDI_fileid[] = "Hatari vdi.c : " __DATE__ " " __TIME__;
1.1 root 15:
16: #include "main.h"
1.1.1.18 root 17: #include "configuration.h"
1.1 root 18: #include "file.h"
19: #include "gemdos.h"
1.1.1.19! root 20: #include "inffile.h"
1.1 root 21: #include "m68000.h"
1.1.1.17 root 22: #include "options.h"
1.1 root 23: #include "screen.h"
24: #include "stMemory.h"
25: #include "vdi.h"
26: #include "video.h"
27:
28:
1.1.1.7 root 29: Uint32 VDI_OldPC; /* When call Trap#2, store off PC */
1.1.1.2 root 30:
1.1.1.14 root 31: bool bVdiAesIntercept = false; /* Set to true to trace VDI & AES calls */
1.1.1.12 root 32: bool bUseVDIRes = false; /* Set to true (if want VDI), or false (ie for games) */
1.1.1.9 root 33: /* defaults */
34: int VDIRes = 0; /* 0,1 or 2 (low, medium, high) */
35: int VDIWidth = 640; /* 640x480, 800x600 or 1024x768 */
36: int VDIHeight = 480;
37: int VDIPlanes = 4;
38:
39: static Uint32 LineABase; /* Line-A structure */
40: static Uint32 FontBase; /* Font base, used for 16-pixel high font */
1.1 root 41:
1.1.1.14 root 42: /* Last VDI opcode & vectors */
43: static Uint16 VDIOpCode;
44: static Uint32 VDIControl;
45: static Uint32 VDIIntin;
46: static Uint32 VDIPtsin;
47: static Uint32 VDIIntout;
48: static Uint32 VDIPtsout;
49: #if ENABLE_TRACING
50: /* Last AES opcode & vectors */
51: static Uint32 AESControl;
52: static Uint32 AESGlobal;
53: static Uint32 AESIntin;
54: static Uint32 AESIntout;
55: static Uint32 AESAddrin;
56: static Uint32 AESAddrout;
57: static Uint16 AESOpCode;
58: #endif
1.1 root 59:
1.1.1.2 root 60:
61: /*-----------------------------------------------------------------------*/
1.1.1.9 root 62: /**
1.1.1.15 root 63: * Called to reset VDI variables on reset.
64: */
65: void VDI_Reset(void)
66: {
67: /* no VDI calls in progress */
68: VDI_OldPC = 0;
69: }
70:
71: /*-----------------------------------------------------------------------*/
72: /**
1.1.1.16 root 73: * Limit width and height to VDI screen size in bytes, retaining their ratio.
74: * Return true if limiting was done.
75: */
76: static bool VDI_ByteLimit(int *width, int *height, int planes)
77: {
78: double ratio;
79: int size;
80:
81: size = (*width)*(*height)*planes/8;
82: if (size <= MAX_VDI_BYTES)
83: return false;
84:
85: ratio = sqrt(MAX_VDI_BYTES) / sqrt(size);
86: *width = (*width) * ratio;
87: *height = (*height) * ratio;
88: if (*width < MIN_VDI_WIDTH || *height < MIN_VDI_HEIGHT)
89: {
90: *width = MIN_VDI_WIDTH;
91: *height = MIN_VDI_HEIGHT;
92: fputs("Bad VDI screen ratio / too small size -> use smallest valid size.\n", stderr);
93: }
94: return true;
95: }
1.1.1.2 root 96:
97: /*-----------------------------------------------------------------------*/
1.1.1.9 root 98: /**
1.1.1.16 root 99: * Set Width/Height/BitDepth according to passed GEMCOLOR_2/4/16.
100: * Align size when necessary.
1.1.1.9 root 101: */
102: void VDI_SetResolution(int GEMColor, int WidthRequest, int HeightRequest)
103: {
1.1.1.16 root 104: int w = WidthRequest;
105: int h = HeightRequest;
106:
1.1.1.9 root 107: /* Color depth */
108: switch (GEMColor)
109: {
110: case GEMCOLOR_2:
111: VDIRes = 2;
112: VDIPlanes = 1;
113: break;
114: case GEMCOLOR_4:
115: VDIRes = 1;
116: VDIPlanes = 2;
117: break;
118: case GEMCOLOR_16:
119: VDIRes = 0;
120: VDIPlanes = 4;
121: break;
122: }
1.1.1.16 root 123: /* screen size in bytes needs to be below limit */
124: VDI_ByteLimit(&w, &h, VDIPlanes);
1.1.1.9 root 125:
126: /* width needs to be aligned to 16 bytes */
1.1.1.17 root 127: VDIWidth = Opt_ValueAlignMinMax(w, 128/VDIPlanes, MIN_VDI_WIDTH, MAX_VDI_WIDTH);
1.1.1.16 root 128: /* height needs to be multiple of cell height (either 8 or 16) */
1.1.1.17 root 129: VDIHeight = Opt_ValueAlignMinMax(h, 16, MIN_VDI_HEIGHT, MAX_VDI_HEIGHT);
1.1.1.16 root 130:
131: printf("VDI screen: request = %dx%d@%d, result = %dx%d@%d\n",
1.1.1.9 root 132: WidthRequest, HeightRequest, VDIPlanes, VDIWidth, VDIHeight, VDIPlanes);
133:
1.1.1.19! root 134: /* INF file overriding so that (re-)boot uses correct bit-depth */
! 135: INF_SetVdiMode(VDIRes);
1.1.1.9 root 136: }
137:
1.1 root 138:
1.1.1.14 root 139: #if ENABLE_TRACING
140:
1.1.1.9 root 141: /*-----------------------------------------------------------------------*/
1.1.1.14 root 142:
1.1.1.16 root 143: /* AES opcodes which have string args */
144: static const struct {
145: int code; /* AES opcode */
146: int count; /* number of char * args _first_ in addrin[] */
147: } AESStrings[] = {
148: { 0x0D, 1 }, /* appl_find() */
149: { 0x12, 1 }, /* appl_search() */
150: { 0x23, 1 }, /* menu_register() */
151: { 0x34, 1 }, /* form_alert() */
152: { 0x51, 1 }, /* scrp_write() */
153: { 0x5A, 2 }, /* fsel_input() */
154: { 0x5B, 3 }, /* fsel_exinput() */
155: { 0x6E, 1 }, /* rsrc_load() */
156: { 0x7C, 1 } /* shell_find() */
157: };
158:
159: /* AES opcode -> function name mapping */
160: static const char* AESName_10[] = {
161: "appl_init", /* (0x0A) */
162: "appl_read", /* (0x0B) */
163: "appl_write", /* (0x0C) */
164: "appl_find", /* (0x0D) */
165: "appl_tplay", /* (0x0E) */
166: "appl_trecord", /* (0x0F) */
167: NULL, /* (0x10) */
168: NULL, /* (0x11) */
169: "appl_search", /* (0x12) */
170: "appl_exit", /* (0x13) */
171: "evnt_keybd", /* (0x14) */
172: "evnt_button", /* (0x15) */
173: "evnt_mesag", /* (0x16) */
174: "evnt_mesag", /* (0x17) */
175: "evnt_timer", /* (0x18) */
176: "evnt_multi", /* (0x19) */
177: "evnt_dclick", /* (0x1A) */
178: NULL, /* (0x1b) */
179: NULL, /* (0x1c) */
180: NULL, /* (0x1d) */
181: "menu_bar", /* (0x1E) */
182: "menu_icheck", /* (0x1F) */
183: "menu_ienable", /* (0x20) */
184: "menu_tnormal", /* (0x21) */
185: "menu_text", /* (0x22) */
186: "menu_register", /* (0x23) */
187: "menu_popup", /* (0x24) */
188: "menu_attach", /* (0x25) */
189: "menu_istart", /* (0x26) */
190: "menu_settings", /* (0x27) */
191: "objc_add", /* (0x28) */
192: "objc_delete", /* (0x29) */
193: "objc_draw", /* (0x2A) */
194: "objc_find", /* (0x2B) */
195: "objc_offset", /* (0x2C) */
196: "objc_order", /* (0x2D) */
197: "objc_edit", /* (0x2E) */
198: "objc_change", /* (0x2F) */
199: "objc_sysvar", /* (0x30) */
200: NULL, /* (0x31) */
201: "form_do", /* (0x32) */
202: "form_dial", /* (0x33) */
203: "form_alert", /* (0x34) */
204: "form_error", /* (0x35) */
205: "form_center", /* (0x36) */
206: "form_keybd", /* (0x37) */
207: "form_button", /* (0x38) */
208: NULL, /* (0x39) */
209: NULL, /* (0x3a) */
210: NULL, /* (0x3b) */
211: NULL, /* (0x3c) */
212: NULL, /* (0x3d) */
213: NULL, /* (0x3e) */
214: NULL, /* (0x3f) */
215: NULL, /* (0x40) */
216: NULL, /* (0x41) */
217: NULL, /* (0x42) */
218: NULL, /* (0x43) */
219: NULL, /* (0x44) */
220: NULL, /* (0x45) */
221: "graf_rubberbox", /* (0x46) */
222: "graf_dragbox", /* (0x47) */
223: "graf_movebox", /* (0x48) */
224: "graf_growbox", /* (0x49) */
225: "graf_shrinkbox", /* (0x4A) */
226: "graf_watchbox", /* (0x4B) */
227: "graf_slidebox", /* (0x4C) */
228: "graf_handle", /* (0x4D) */
229: "graf_mouse", /* (0x4E) */
230: "graf_mkstate", /* (0x4F) */
231: "scrp_read", /* (0x50) */
232: "scrp_write", /* (0x51) */
233: NULL, /* (0x52) */
234: NULL, /* (0x53) */
235: NULL, /* (0x54) */
236: NULL, /* (0x55) */
237: NULL, /* (0x56) */
238: NULL, /* (0x57) */
239: NULL, /* (0x58) */
240: NULL, /* (0x59) */
241: "fsel_input", /* (0x5A) */
242: "fsel_exinput", /* (0x5B) */
243: NULL, /* (0x5c) */
244: NULL, /* (0x5d) */
245: NULL, /* (0x5e) */
246: NULL, /* (0x5f) */
247: NULL, /* (0x60) */
248: NULL, /* (0x61) */
249: NULL, /* (0x62) */
250: NULL, /* (0x63) */
251: "wind_create", /* (0x64) */
252: "wind_open", /* (0x65) */
253: "wind_close", /* (0x66) */
254: "wind_delete", /* (0x67) */
255: "wind_get", /* (0x68) */
256: "wind_set", /* (0x69) */
257: "wind_find", /* (0x6A) */
258: "wind_update", /* (0x6B) */
259: "wind_calc", /* (0x6C) */
260: "wind_new", /* (0x6D) */
261: "rsrc_load", /* (0x6E) */
262: "rsrc_free", /* (0x6F) */
263: "rsrc_gaddr", /* (0x70) */
264: "rsrc_saddr", /* (0x71) */
265: "rsrc_obfix", /* (0x72) */
266: "rsrc_rcfix", /* (0x73) */
267: NULL, /* (0x74) */
268: NULL, /* (0x75) */
269: NULL, /* (0x76) */
270: NULL, /* (0x77) */
271: "shel_read", /* (0x78) */
272: "shel_write", /* (0x79) */
273: "shel_get", /* (0x7A) */
274: "shel_put", /* (0x7B) */
275: "shel_find", /* (0x7C) */
276: "shel_envrn", /* (0x7D) */
277: NULL, /* (0x7e) */
278: NULL, /* (0x7f) */
279: NULL, /* (0x80) */
280: NULL, /* (0x81) */
281: "appl_getinfo" /* (0x82) */
282: };
283:
1.1.1.9 root 284: /**
1.1.1.14 root 285: * Map AES call opcode to an AES function name
1.1.1.9 root 286: */
1.1.1.14 root 287: static const char* AES_Opcode2Name(Uint16 opcode)
1.1 root 288: {
1.1.1.16 root 289: int code = opcode - 10;
1.1.1.18 root 290: if (code >= 0 && code < ARRAY_SIZE(AESName_10) && AESName_10[code])
1.1.1.16 root 291: return AESName_10[code];
1.1.1.14 root 292: else
293: return "???";
1.1 root 294: }
295:
1.1.1.9 root 296: /**
1.1.1.16 root 297: * Output AES call info, including some of args
298: */
299: static void AES_OpcodeInfo(FILE *fp, Uint16 opcode)
300: {
301: int code = opcode - 10;
302: fprintf(fp, "AES call %3hd ", opcode);
1.1.1.18 root 303: if (code >= 0 && code < ARRAY_SIZE(AESName_10) && AESName_10[code])
1.1.1.16 root 304: {
305: bool first = true;
306: int i, items;
307:
308: fprintf(fp, "%s(", AESName_10[code]);
309:
310: items = 0;
311: /* there are so few of these that linear search is fine */
1.1.1.18 root 312: for (i = 0; i < ARRAY_SIZE(AESStrings); i++)
1.1.1.16 root 313: {
314: /* something that can be shown? */
315: if (AESStrings[i].code == opcode)
316: {
317: items = AESStrings[i].count;
318: break;
319: }
320: }
321: /* addrin array size in longs enough for items? */
322: if (items > 0 && items <= STMemory_ReadWord(AESControl+SIZE_WORD*3))
323: {
324: const char *str;
325: fputs("addrin: ", fp);
326: for (i = 0; i < items; i++)
327: {
328: if (first)
329: first = false;
330: else
331: fputs(", ", fp);
1.1.1.17 root 332: str = (const char *)STMemory_STAddrToPointer(STMemory_ReadLong(AESAddrin+SIZE_LONG*i));
1.1.1.16 root 333: fprintf(fp, "\"%s\"", str);
334: }
335: }
336: /* intin array size in words */
337: items = STMemory_ReadWord(AESControl+SIZE_WORD*1);
338: if (items > 0)
339: {
340: if (!first)
341: {
342: fputs(", ", fp);
343: first = true;
344: }
345: fputs("intin: ", fp);
346: for (i = 0; i < items; i++)
347: {
348: if (first)
349: first = false;
350: else
351: fputs(",", fp);
352: fprintf(fp, "0x%x", STMemory_ReadWord(AESIntin+SIZE_WORD*i));
353: }
354: }
355: fputs(")\n", fp);
356: }
357: else
358: fputs("???\n", fp);
359: fflush(fp);
360: }
361:
362: /**
1.1.1.14 root 363: * If opcodes argument is set, show AES opcode/function name table,
364: * otherwise AES vectors information.
1.1.1.9 root 365: */
1.1.1.17 root 366: void AES_Info(FILE *fp, Uint32 bShowOpcodes)
1.1 root 367: {
1.1.1.14 root 368: Uint16 opcode;
369:
370: if (bShowOpcodes)
1.1.1.9 root 371: {
1.1.1.14 root 372: for (opcode = 10; opcode < 0x86; opcode++)
373: {
1.1.1.17 root 374: fprintf(fp, "%02x %-16s", opcode, AES_Opcode2Name(opcode));
375: if ((opcode-9) % 4 == 0) fputs("\n", fp);
1.1.1.14 root 376: }
377: return;
1.1.1.9 root 378: }
1.1.1.14 root 379: if (!bVdiAesIntercept)
380: {
1.1.1.17 root 381: fputs("VDI/AES interception isn't enabled!\n", fp);
1.1.1.14 root 382: return;
383: }
384: if (!AESControl)
385: {
1.1.1.17 root 386: fputs("No traced AES calls!\n", fp);
1.1.1.14 root 387: return;
388: }
389: opcode = STMemory_ReadWord(AESControl);
390: if (opcode != AESOpCode)
391: {
1.1.1.17 root 392: fputs("AES parameter block contents changed since last call!\n", fp);
1.1.1.14 root 393: return;
394: }
395:
1.1.1.17 root 396: fputs("Latest AES Parameter block:\n", fp);
397: fprintf(fp, "- Opcode: %3hd (%s)\n",
1.1.1.14 root 398: opcode, AES_Opcode2Name(opcode));
399:
1.1.1.17 root 400: fprintf(fp, "- Control: %#8x\n", AESControl);
401: fprintf(fp, "- Global: %#8x, %d bytes\n",
1.1.1.14 root 402: AESGlobal, 2+2+2+4+4+4+4+4+4);
1.1.1.17 root 403: fprintf(fp, "- Intin: %#8x, %d words\n",
1.1.1.14 root 404: AESIntin, STMemory_ReadWord(AESControl+2*1));
1.1.1.17 root 405: fprintf(fp, "- Intout: %#8x, %d words\n",
1.1.1.14 root 406: AESIntout, STMemory_ReadWord(AESControl+2*2));
1.1.1.17 root 407: fprintf(fp, "- Addrin: %#8x, %d longs\n",
1.1.1.14 root 408: AESAddrin, STMemory_ReadWord(AESControl+2*3));
1.1.1.17 root 409: fprintf(fp, "- Addrout: %#8x, %d longs\n",
1.1.1.14 root 410: AESAddrout, STMemory_ReadWord(AESControl+2*4));
1.1 root 411: }
412:
1.1.1.2 root 413:
1.1.1.13 root 414: /*-----------------------------------------------------------------------*/
1.1.1.14 root 415:
1.1.1.13 root 416: /**
417: * Map VDI call opcode/sub-opcode to a VDI function name
418: */
419: static const char* VDI_Opcode2Name(Uint16 opcode, Uint16 subcode)
420: {
421: static const char* names_0[] = {
422: "???",
423: "v_opnwk",
424: "v_clswk",
425: "v_clrwk",
426: "v_updwk",
427: "", /* 5: lots of sub opcodes */
428: "v_pline",
429: "v_pmarker",
430: "v_gtext",
431: "v_fillarea", /* sub-opcode 13: v_bez_fill with GDOS */
432: "v_cellarray",
433: "", /* 11: lots of sub opcodes */
434: "vst_height",
435: "vst_rotation",
436: "vs_color",
437: "vsl_type",
438: "vsl_width",
439: "vsl_color",
440: "vsm_type",
441: "vsm_height",
442: "vsm_color",
443: "vst_font",
444: "vst_color",
445: "vsf_interior",
446: "vsf_style",
447: "vsf_color",
448: "vq_color",
449: "vq_cellarray",
450: "vrq/sm_locator",
451: "vrq/sm_valuator",
452: "vrq/sm_choice",
453: "vrq/sm_string",
454: "vswr_mode",
455: "vsin_mode",
456: "???", /* 34 */
457: "vql_attributes",
458: "vqm_attributes",
459: "vqf_attributes",
460: "vqt_attributes",
461: "vst_alignment"
462: };
463: static const char* names_100[] = {
464: "v_opnvwk",
465: "v_clsvwk",
466: "vq_extnd",
467: "v_contourfill",
468: "vsf_perimeter",
469: "v_get_pixel",
470: "vst_effects",
471: "vst_point",
472: "vsl_ends",
473: "vro_cpyfm",
474: "vr_trnfm",
475: "vsc_form",
476: "vsf_udpat",
477: "vsl_udsty",
478: "vr_recfl",
479: "vqin_mode",
480: "vqt_extent",
481: "vqt_width",
482: "vex_timv",
483: "vst_load_fonts",
484: "vst_unload_fonts",
485: "vrt_cpyfm",
486: "v_show_c",
487: "v_hide_c",
488: "vq_mouse",
489: "vex_butv",
490: "vex_motv",
491: "vex_curv",
492: "vq_key_s",
493: "vs_clip",
494: "vqt_name",
495: "vqt_fontinfo"
496: /* 131-233: no known opcodes
497: * 234-255: (Speedo) GDOS opcodes
498: */
499: };
500: static const char* names_opcode5[] = {
1.1.1.14 root 501: "<no subcode>",
1.1.1.13 root 502: "vq_chcells",
503: "v_exit_cur",
504: "v_enter_cur",
505: "v_curup",
506: "v_curdown",
507: "v_curright",
508: "v_curleft",
509: "v_curhome",
510: "v_eeos",
511: "v_eeol",
512: "vs_curaddress",
513: "v_curtext",
514: "v_rvon",
515: "v_rvoff",
516: "vq_curaddress",
517: "vq_tabstatus",
518: "v_hardcopy",
519: "v_dspcur",
520: "v_rmcur",
521: "v_form_adv",
522: "v_output_window",
523: "v_clear_disp_list",
524: "v_bit_image",
525: "vq_scan",
526: "v_alpha_text"
527: };
528: static const char* names_opcode5_98[] = {
529: "v_meta_extents",
530: "v_write_meta",
531: "vm_filename",
532: "???",
533: "v_fontinit"
534: };
535: static const char* names_opcode11[] = {
1.1.1.14 root 536: "<no subcode>",
1.1.1.13 root 537: "v_bar",
538: "v_arc",
539: "v_pieslice",
540: "v_circle",
541: "v_ellipse",
542: "v_ellarc",
543: "v_ellpie",
544: "v_rbox",
545: "v_rfbox",
546: "v_justified"
547: };
548:
549: if (opcode == 5)
550: {
1.1.1.18 root 551: if (subcode < ARRAY_SIZE(names_opcode5)) {
1.1.1.13 root 552: return names_opcode5[subcode];
553: }
554: if (subcode >= 98) {
555: subcode -= 98;
1.1.1.18 root 556: if (subcode < ARRAY_SIZE(names_opcode5_98)) {
1.1.1.13 root 557: return names_opcode5_98[subcode];
558: }
559: }
560: }
561: else if (opcode == 11)
562: {
1.1.1.18 root 563: if (subcode < ARRAY_SIZE(names_opcode11)) {
1.1.1.13 root 564: return names_opcode11[subcode];
565: }
566: }
1.1.1.18 root 567: else if (opcode < ARRAY_SIZE(names_0))
1.1.1.13 root 568: {
569: return names_0[opcode];
570: }
571: else if (opcode >= 100)
572: {
573: opcode -= 100;
1.1.1.18 root 574: if (opcode < ARRAY_SIZE(names_100))
1.1.1.13 root 575: {
576: return names_100[opcode];
577: }
578: }
1.1.1.14 root 579: return "GDOS?";
1.1.1.13 root 580: }
581:
1.1.1.9 root 582: /**
1.1.1.14 root 583: * If opcodes argument is set, show VDI opcode/function name table,
584: * otherwise VDI vectors information.
1.1.1.9 root 585: */
1.1.1.17 root 586: void VDI_Info(FILE *fp, Uint32 bShowOpcodes)
1.1 root 587: {
1.1.1.14 root 588: Uint16 opcode, subcode;
1.1 root 589:
1.1.1.14 root 590: if (bShowOpcodes)
1.1.1.9 root 591: {
1.1.1.14 root 592: Uint16 opcode;
593: for (opcode = 0; opcode < 0x84; )
594: {
595: if (opcode == 0x28)
596: {
1.1.1.17 root 597: fputs("--- GDOS calls? ---\n", fp);
1.1.1.14 root 598: opcode = 0x64;
599: }
1.1.1.17 root 600: fprintf(fp, "%02x %-16s",
1.1.1.14 root 601: opcode, VDI_Opcode2Name(opcode, 0));
1.1.1.17 root 602: if (++opcode % 4 == 0) fputs("\n", fp);
1.1.1.14 root 603: }
604: return;
605: }
606: if (!bVdiAesIntercept)
607: {
1.1.1.17 root 608: fputs("VDI/AES interception isn't enabled!\n", fp);
1.1.1.14 root 609: return;
610: }
611: if (!VDIControl)
612: {
1.1.1.17 root 613: fputs("No traced VDI calls!\n", fp);
1.1.1.14 root 614: return;
615: }
616: opcode = STMemory_ReadWord(VDIControl);
617: if (opcode != VDIOpCode)
618: {
1.1.1.17 root 619: fputs("VDI parameter block contents changed since last call!\n", fp);
1.1.1.14 root 620: return;
621: }
1.1 root 622:
1.1.1.17 root 623: fputs("Latest VDI Parameter block:\n", fp);
1.1.1.14 root 624: subcode = STMemory_ReadWord(VDIControl+2*5);
1.1.1.17 root 625: fprintf(fp, "- Opcode/Subcode: %hd/%hd (%s)\n",
1.1.1.14 root 626: opcode, subcode, VDI_Opcode2Name(opcode, subcode));
1.1.1.17 root 627: fprintf(fp, "- Device handle: %d\n",
1.1.1.14 root 628: STMemory_ReadWord(VDIControl+2*6));
1.1.1.17 root 629: fprintf(fp, "- Control: %#8x\n", VDIControl);
630: fprintf(fp, "- Ptsin: %#8x, %d co-ordinate word pairs\n",
1.1.1.14 root 631: VDIPtsin, STMemory_ReadWord(VDIControl+2*1));
1.1.1.17 root 632: fprintf(fp, "- Ptsout: %#8x, %d co-ordinate word pairs\n",
1.1.1.14 root 633: VDIPtsout, STMemory_ReadWord(VDIControl+2*2));
1.1.1.17 root 634: fprintf(fp, "- Intin: %#8x, %d words\n",
1.1.1.14 root 635: VDIIntin, STMemory_ReadWord(VDIControl+2*3));
1.1.1.17 root 636: fprintf(fp, "- Intout: %#8x, %d words\n",
1.1.1.14 root 637: VDIIntout, STMemory_ReadWord(VDIControl+2*4));
638: }
1.1 root 639:
1.1.1.14 root 640: #else /* !ENABLE_TRACING */
1.1.1.17 root 641: void AES_Info(FILE *fp, Uint32 bShowOpcodes)
1.1.1.14 root 642: {
1.1.1.17 root 643: fputs("Hatari isn't configured with ENABLE_TRACING\n", fp);
1.1.1.14 root 644: }
1.1.1.17 root 645: void VDI_Info(FILE *fp, Uint32 bShowOpcodes)
1.1.1.14 root 646: {
1.1.1.17 root 647: fputs("Hatari isn't configured with ENABLE_TRACING\n", fp);
1.1.1.14 root 648: }
649: #endif /* !ENABLE_TRACING */
650:
651:
652: /*-----------------------------------------------------------------------*/
653: /**
654: * Return true for only VDI opcodes that need to be handled at Trap exit.
655: */
656: static inline bool VDI_isWorkstationOpen(Uint16 opcode)
657: {
658: if (opcode == 1 || opcode == 100)
659: return true;
660: else
661: return false;
662: }
663:
664: /**
665: * Check whether this is VDI/AES call and see if we need to re-direct
666: * it to our own routines. Return true if VDI_Complete() function
667: * needs to be called on OS call exit, otherwise return false.
668: *
669: * We enter here with Trap #2, so D0 tells which OS call it is (VDI/AES)
670: * and D1 is pointer to VDI/AES vectors, i.e. Control, Intin, Ptsin etc...
671: */
672: bool VDI_AES_Entry(void)
673: {
674: Uint16 call = Regs[REG_D0];
675: Uint32 TablePtr = Regs[REG_D1];
1.1.1.12 root 676:
1.1.1.13 root 677: #if ENABLE_TRACING
1.1.1.14 root 678: /* AES call? */
679: if (call == 0xC8)
1.1.1.13 root 680: {
1.1.1.17 root 681: if ( !STMemory_CheckAreaType ( TablePtr, 24, ABFLAG_RAM ) )
1.1.1.14 root 682: {
683: Log_Printf(LOG_WARN, "AES call failed due to invalid parameter block address 0x%x+%i\n", TablePtr, 24);
684: return false;
685: }
686: /* store values for debugger "info aes" command */
687: AESControl = STMemory_ReadLong(TablePtr);
688: AESGlobal = STMemory_ReadLong(TablePtr+4);
689: AESIntin = STMemory_ReadLong(TablePtr+8);
690: AESIntout = STMemory_ReadLong(TablePtr+12);
691: AESAddrin = STMemory_ReadLong(TablePtr+16);
692: AESAddrout = STMemory_ReadLong(TablePtr+20);
693: AESOpCode = STMemory_ReadWord(AESControl);
1.1.1.16 root 694: if (LOG_TRACE_LEVEL(TRACE_OS_AES))
695: {
696: AES_OpcodeInfo(TraceFile, AESOpCode);
697: }
1.1.1.14 root 698: /* using same special opcode trick doesn't work for
699: * both VDI & AES as AES functions can be called
700: * recursively and VDI calls happen inside AES calls.
701: */
702: return false;
1.1.1.13 root 703: }
704: #endif
1.1.1.14 root 705:
706: /* VDI call? */
707: if (call == 0x73)
708: {
1.1.1.17 root 709: if ( !STMemory_CheckAreaType ( TablePtr, 20, ABFLAG_RAM ) )
1.1.1.14 root 710: {
711: Log_Printf(LOG_WARN, "VDI call failed due to invalid parameter block address 0x%x+%i\n", TablePtr, 20);
712: return false;
713: }
714: /* store values for extended VDI resolution handling
715: * and debugger "info vdi" command
716: */
717: VDIControl = STMemory_ReadLong(TablePtr);
718: VDIIntin = STMemory_ReadLong(TablePtr+4);
719: VDIPtsin = STMemory_ReadLong(TablePtr+8);
720: VDIIntout = STMemory_ReadLong(TablePtr+12);
721: VDIPtsout = STMemory_ReadLong(TablePtr+16);
722: VDIOpCode = STMemory_ReadWord(VDIControl);
723: #if ENABLE_TRACING
724: {
725: Uint16 subcode = STMemory_ReadWord(VDIControl+2*5);
726: LOG_TRACE(TRACE_OS_VDI, "VDI call %3hd/%3hd (%s)\n",
727: VDIOpCode, subcode,
728: VDI_Opcode2Name(VDIOpCode, subcode));
729: }
730: #endif
731: /* Only workstation open needs to be handled at trap return */
732: return bUseVDIRes && VDI_isWorkstationOpen(VDIOpCode);
733: }
734:
735: LOG_TRACE((TRACE_OS_VDI|TRACE_OS_AES), "Trap #2 with D0 = 0x%hX\n", call);
736: return false;
737: }
738:
739:
740: /*-----------------------------------------------------------------------*/
741: /**
742: * Modify Line-A structure for our VDI resolutions
743: */
744: void VDI_LineA(Uint32 linea, Uint32 fontbase)
745: {
1.1.1.19! root 746: Uint32 fontadr, font1, font2;
! 747:
1.1.1.17 root 748: LineABase = linea;
749: FontBase = fontbase;
750:
1.1.1.14 root 751: if (bUseVDIRes)
752: {
1.1.1.19! root 753: int cel_ht, cel_wd;
! 754:
! 755: fontadr = STMemory_ReadLong(linea-0x1cc); /* def_font */
! 756: if (fontadr == 0)
! 757: {
! 758: /* get 8x8 font header */
! 759: font1 = STMemory_ReadLong(fontbase + 4);
! 760: /* get 8x16 font header */
! 761: font2 = STMemory_ReadLong(fontbase + 8);
! 762: /* remove DEFAULT flag from 8x8 font */
! 763: STMemory_WriteWord(font1 + 66, STMemory_ReadWord(font1 + 66) & ~0x01);
! 764: /* remove DEFAULT flag from 8x16 font */
! 765: STMemory_WriteWord(font2 + 66, STMemory_ReadWord(font2 + 66) & ~0x01);
! 766: /* choose new font */
! 767: if (VDIHeight >= 400)
! 768: {
! 769: fontadr = font2;
! 770: } else
! 771: {
! 772: fontadr = font1;
! 773: }
! 774: /* make this new default font */
! 775: STMemory_WriteLong(linea-0x1cc, fontadr);
! 776: /* set DEFAULT flag for chosen font */
! 777: STMemory_WriteWord(fontadr + 66, STMemory_ReadWord(fontadr + 66) | 0x01);
! 778: }
! 779: cel_wd = STMemory_ReadWord(fontadr + 52);
! 780: cel_ht = STMemory_ReadWord(fontadr + 82);
! 781: if (cel_wd <= 0)
! 782: {
! 783: Log_Printf(LOG_WARN, "VDI Line-A init failed due to bad cell width!\n");
! 784: return;
! 785: }
1.1.1.17 root 786: if (cel_ht <= 0)
787: {
788: Log_Printf(LOG_WARN, "VDI Line-A init failed due to bad cell height!\n");
789: return;
790: }
1.1.1.19! root 791:
! 792: STMemory_WriteWord(linea-46, cel_ht); /* v_cel_ht */
! 793: STMemory_WriteWord(linea-44, (VDIWidth/cel_wd)-1); /* v_cel_mx (cols-1) */
1.1.1.16 root 794: STMemory_WriteWord(linea-42, (VDIHeight/cel_ht)-1); /* v_cel_my (rows-1) */
795: STMemory_WriteWord(linea-40, cel_ht*((VDIWidth*VDIPlanes)/8)); /* v_cel_wr */
1.1.1.14 root 796:
1.1.1.19! root 797: STMemory_WriteLong(linea-22, STMemory_ReadLong(fontadr + 76)); /* v_fnt_ad */
! 798: STMemory_WriteWord(linea-18, STMemory_ReadWord(fontadr + 38)); /* v_fnt_nd */
! 799: STMemory_WriteWord(linea-16, STMemory_ReadWord(fontadr + 36)); /* v_fnt_st */
! 800: STMemory_WriteWord(linea-14, STMemory_ReadWord(fontadr + 80)); /* v_fnt_wd */
1.1.1.14 root 801: STMemory_WriteWord(linea-12, VDIWidth); /* v_rez_hz */
1.1.1.19! root 802: STMemory_WriteLong(linea-10, STMemory_ReadLong(fontadr + 72)); /* v_off_ad */
1.1.1.14 root 803: STMemory_WriteWord(linea-4, VDIHeight); /* v_rez_vt */
804: STMemory_WriteWord(linea-2, (VDIWidth*VDIPlanes)/8); /* bytes_lin */
805: STMemory_WriteWord(linea+0, VDIPlanes); /* planes */
806: STMemory_WriteWord(linea+2, (VDIWidth*VDIPlanes)/8); /* width */
807: }
808: }
809:
810:
811: /*-----------------------------------------------------------------------*/
812: /**
813: * This is called on completion of a VDI Trap workstation open,
814: * to modify the return structure for extended resolutions.
815: */
816: void VDI_Complete(void)
817: {
818: /* right opcode? */
819: assert(VDI_isWorkstationOpen(VDIOpCode));
820: /* not changed between entry and completion? */
821: assert(VDIOpCode == STMemory_ReadWord(VDIControl));
822:
823: STMemory_WriteWord(VDIIntout, VDIWidth-1); /* IntOut[0] Width-1 */
824: STMemory_WriteWord(VDIIntout+1*2, VDIHeight-1); /* IntOut[1] Height-1 */
1.1.1.16 root 825: STMemory_WriteWord(VDIIntout+13*2, 1 << VDIPlanes); /* IntOut[13] #colors */
1.1.1.14 root 826: STMemory_WriteWord(VDIIntout+39*2, 512); /* IntOut[39] #available colors */
827:
828: STMemory_WriteWord(LineABase-0x15a*2, VDIWidth-1); /* WKXRez */
829: STMemory_WriteWord(LineABase-0x159*2, VDIHeight-1); /* WKYRez */
830:
831: VDI_LineA(LineABase, FontBase); /* And modify Line-A structure accordingly */
1.1 root 832: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.