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

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

unix.superglobalmegacorp.com

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