Annotation of hatari/src/vdi.c, revision 1.1.1.19

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.