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