Annotation of hatari/src/bios.c, revision 1.1.1.12

1.1       root        1: /*
1.1.1.2   root        2:   Hatari - bios.c
                      3: 
                      4:   This file is distributed under the GNU Public License, version 2 or at
                      5:   your option any later version. Read the file gpl.txt for details.
1.1       root        6: 
                      7:   Bios Handler (Trap #13)
                      8: 
1.1.1.7   root        9:   We intercept some Bios calls for debugging
1.1       root       10: */
1.1.1.8   root       11: const char Bios__fileid[] = "Hatari bios.c : " __DATE__ " " __TIME__;
1.1       root       12: 
                     13: #include "main.h"
1.1.1.2   root       14: #include "configuration.h"
1.1       root       15: #include "floppy.h"
1.1.1.3   root       16: #include "log.h"
1.1       root       17: #include "m68000.h"
                     18: #include "printer.h"
                     19: #include "rs232.h"
                     20: #include "stMemory.h"
1.1.1.2   root       21: #include "bios.h"
1.1       root       22: 
                     23: 
                     24: /*-----------------------------------------------------------------------*/
1.1.1.6   root       25: /**
1.1.1.11  root       26:  * Convert given BIOS CON: device character output to ASCII.
                     27:  * Accepts one character at the time, parses VT52 escape codes
                     28:  * and maps Atari characters to their closest ASCII equivalents.
                     29:  * 
                     30:  * On host, TOS cursor forwards movement is done with spaces,
                     31:  * backwards movement is delayed until next non-white character
                     32:  * at which point output switches to next line.  Other VT52
                     33:  * escape sequences than cursor movement are ignored.
                     34:  */
                     35: static void Bios_VT52(Uint8 value)
                     36: {
                     37:        
                     38:        static const Uint8 map_0_31[32] = {
                     39:                '.', '.', '.', '.', '.', '.', '.', '.', /* 0x00 */
                     40:                /* white space */
                     41:                '\b','\t','\n','.','.','\r', '.', '.',  /* 0x08 */
                     42:                /* LED numbers */
                     43:                '0', '1', '2', '3', '4', '5', '6', '7', /* 0x10 */
                     44:                '8', '9', '.', '.', '.', '.', '.', '.'  /* 0x18 */
                     45:        };
                     46:        static const Uint8 map_128_255[128] = {
                     47:                /* accented characters */
                     48:                'C', 'U', 'e', 'a', 'a', 'a', 'a', 'c', /* 0x80 */
                     49:                'e', 'e', 'e', 'i', 'i', 'i', 'A', 'A', /* 0x88 */
                     50:                'E', 'a', 'A', 'o', 'o', 'o', 'u', 'u', /* 0x90 */
                     51:                'y', 'o', 'u', 'c', '.', 'Y', 'B', 'f', /* 0x98 */
                     52:                'a', 'i', 'o', 'u', 'n', 'N', 'a', 'o', /* 0xA0 */
                     53:                '?', '.', '.', '.', '.', 'i', '<', '>', /* 0xA8 */
                     54:                'a', 'o', 'O', 'o', 'o', 'O', 'A', 'A', /* 0xB0 */
                     55:                'O', '"','\'', '.', '.', 'C', 'R', '.', /* 0xB8 */
                     56:                'j', 'J', '.', '.', '.', '.', '.', '.', /* 0xC0 */
                     57:                '.', '.', '.', '.', '.', '.', '.', '.', /* 0xC8 */
                     58:                '.', '.', '.', '.', '.', '.', '.', '.', /* 0xD0 */
                     59:                '.', '.', '.', '.', '.', '.', '^', '.', /* 0xD8 */
                     60:                '.', '.', '.', '.', '.', '.', '.', '.', /* 0xE0 */
                     61:                '.', '.', '.', '.', '.', '.', '.', '.', /* 0xE8 */
                     62:                '.', '.', '.', '.', '.', '.', '.', '.', /* 0xF0 */
                     63:                '.', '.', '.', '.', '.', '.', '.', '.'  /* 0xF8 */
                     64:        };
                     65: 
                     66:        /* state machine to handle/ignore VT52 escape sequence */
                     67:        static int escape_index;
                     68:        static int escape_target;
                     69:        static int hpos_host, hpos_tos;
                     70:        static bool need_nl;
                     71:        static enum {
                     72:                ESCAPE_NONE, ESCAPE_POSITION
                     73:        } escape_type;
                     74: 
                     75:        if (escape_target) {
                     76:                if (++escape_index == 1) {
1.1.1.12! root       77:                        /* VT52 escape sequences */
1.1.1.11  root       78:                        switch(value) {
1.1.1.12! root       79:                        case 'E':       /* clear screen+home -> newline */
        !            80:                                fputs("\n", stderr);
        !            81:                                hpos_host = 0;
        !            82:                                break;
        !            83:                        /* sequences with arguments */
1.1.1.11  root       84:                        case 'b':       /* foreground color */
                     85:                        case 'c':       /* background color */
                     86:                                escape_target = 2;
                     87:                                return;
                     88:                        case 'Y':       /* cursor position */
                     89:                                escape_type = ESCAPE_POSITION;
                     90:                                escape_target = 3;
                     91:                                return;
                     92:                        }
                     93:                } else if (escape_index < escape_target) {
                     94:                        return;
                     95:                }
                     96:                if (escape_type == ESCAPE_POSITION) {
                     97:                        /* last item gives horizontal position */
                     98:                        hpos_tos = value - ' ';
                     99:                        if (hpos_tos > 79) {
                    100:                                hpos_tos = 79;
                    101:                        } else if (hpos_tos < 0) {
                    102:                                hpos_tos = 0;
                    103:                        }
                    104:                        if (hpos_tos > hpos_host) {
                    105:                                fprintf(stderr, "%*s", hpos_tos - hpos_host, "");
                    106:                                hpos_host = hpos_tos;
                    107:                        } else if (hpos_tos < hpos_host) {
                    108:                                need_nl = true;
                    109:                        }
                    110:                }
                    111:                /* escape sequence end */
                    112:                escape_target = 0;
                    113:                return;
                    114:        }
                    115:        if (value == 27) {
                    116:                /* escape sequence start */
                    117:                escape_type = ESCAPE_NONE;
                    118:                escape_target = 1;
                    119:                escape_index = 0;
                    120:                return;
                    121:        }
                    122: 
                    123:        /* do newline & indent for backwards movement only when necessary */
                    124:        if (need_nl) {
                    125:                /* TOS cursor horizontal movement until host output */
                    126:                switch (value) {
                    127:                case ' ':
                    128:                        hpos_tos++;
                    129:                        return;
                    130:                case '\b':
                    131:                        hpos_tos--;
                    132:                        return;
                    133:                case '\t':
                    134:                        hpos_tos = (hpos_tos + 8) & 0xfff0;
                    135:                        return;
                    136:                case '\r':
                    137:                case '\n':
                    138:                        hpos_tos = 0;
                    139:                        break;
                    140:                }
                    141:                fputs("\n", stderr);
                    142:                if (hpos_tos > 0 && hpos_tos < 80) {
                    143:                        fprintf(stderr, "%*s", hpos_tos, "");
                    144:                        hpos_host = hpos_tos;
                    145:                } else {
                    146:                        hpos_host = 0;
                    147:                }
                    148:                need_nl = false;
                    149:        }
                    150: 
                    151:        /* host cursor horizontal movement */
                    152:        switch (value) {
                    153:        case '\b':
                    154:                hpos_host--;
                    155:                break;
                    156:        case '\t':
                    157:                hpos_host = (hpos_host + 8) & 0xfff0;
                    158:                break;
                    159:        case '\r':
                    160:        case '\n':
                    161:                hpos_host = 0;
                    162:                break;
                    163:        default:
                    164:                hpos_host++;
                    165:                break;
                    166:        }
                    167: 
                    168:        /* map normal characters to host console */
                    169:        if (value < 32) {
                    170:                fputc(map_0_31[value], stderr);
                    171:        } else if (value > 127) {
                    172:                fputc(map_128_255[value-128], stderr);
                    173:        } else {
                    174:                fputc(value, stderr);
                    175:        }
                    176: }
                    177: 
                    178: 
                    179: /*-----------------------------------------------------------------------*/
                    180: /**
1.1.1.6   root      181:  * BIOS Write character to device
                    182:  * Call 3
                    183:  */
1.1.1.12! root      184: static void Bios_Bconout(Uint32 Params)
1.1       root      185: {
1.1.1.3   root      186:        Uint16 Dev;
1.1.1.11  root      187:        Uint8 Char;
1.1       root      188: 
1.1.1.12! root      189:        Dev = STMemory_ReadWord(Params);
        !           190:        Char = STMemory_ReadWord(Params+SIZE_WORD);
1.1.1.2   root      191: 
1.1.1.12! root      192:        LOG_TRACE(TRACE_OS_BIOS, "BIOS 0x03 Bconout(%i, 0x%02hhX)\n", Dev, Char);
1.1       root      193: 
1.1.1.11  root      194:        if (Dev == 2) {
                    195:                Bios_VT52(Char);
                    196:        }
1.1       root      197: }
                    198: 
1.1.1.2   root      199: 
1.1       root      200: /*-----------------------------------------------------------------------*/
1.1.1.6   root      201: /**
                    202:  * BIOS Read/Write disk sector
                    203:  * Call 4
                    204:  */
1.1.1.12! root      205: static void Bios_RWabs(Uint32 Params)
1.1       root      206: {
1.1.1.3   root      207:        Uint32 pBuffer;
                    208:        Uint16 RWFlag, Number, RecNo, Dev;
                    209: 
                    210:        /* Read details from stack */
1.1.1.12! root      211:        RWFlag = STMemory_ReadWord(Params);
        !           212:        pBuffer = STMemory_ReadLong(Params+SIZE_WORD);
        !           213:        Number = STMemory_ReadWord(Params+SIZE_WORD+SIZE_LONG);
        !           214:        RecNo = STMemory_ReadWord(Params+SIZE_WORD+SIZE_LONG+SIZE_WORD);
        !           215:        Dev = STMemory_ReadWord(Params+SIZE_WORD+SIZE_LONG+SIZE_WORD+SIZE_WORD);
1.1       root      216: 
1.1.1.12! root      217:        LOG_TRACE(TRACE_OS_BIOS, "BIOS 0x04 Rwabs(%d,0x%lX,%d,%d,%i)\n",
        !           218:                  RWFlag, STRAM_ADDR(pBuffer), Number, RecNo, Dev);
1.1       root      219: }
                    220: 
1.1.1.2   root      221: 
1.1       root      222: /*-----------------------------------------------------------------------*/
1.1.1.2   root      223: 
1.1.1.12! root      224: #if ENABLE_TRACING
1.1.1.6   root      225: /**
1.1.1.12! root      226:  * Map BIOS call opcode to BIOS function name
1.1.1.10  root      227:  */
1.1.1.12! root      228: static const char* Bios_Call2Name(Uint16 opcode)
1.1.1.10  root      229: {
                    230:        /* GCC uses substrings from above trace statements
                    231:         * where they match, so having them again here
                    232:         * wastes only a pointer & simplifies things
                    233:         */
                    234:        static const char* names[] = {
                    235:                "Getmpb", "Bconstat","Bconin", "Bconout",
                    236:                "Rwabs",  "Setexc",  "Tickcal","Getbpb",
                    237:                "Bcostat","Mediach", "Drvmap", "Kbshift"
                    238:        };
1.1.1.12! root      239:        if (opcode < ARRAYSIZE(names) && names[opcode]) {
        !           240:                return names[opcode];
1.1.1.10  root      241:        }
1.1.1.12! root      242:        return "???";
1.1.1.10  root      243: }
                    244: 
1.1.1.12! root      245: void Bios_Info(Uint32 dummy)
        !           246: {
        !           247:        Uint16 opcode;
        !           248:        for (opcode = 0; opcode <= 0xB; ) {
        !           249:                fprintf(stderr, "%02x %-9s", opcode,
        !           250:                        Bios_Call2Name(opcode));
        !           251:                if (++opcode % 6 == 0) {
        !           252:                        fputs("\n", stderr);
        !           253:                }
        !           254:        }
        !           255: }
        !           256: #else /* !ENABLE_TRACING */
        !           257: void Bios_Info(Uint32 bShowOpcodes)
        !           258: {
        !           259:                fputs("Hatari isn't configured with ENABLE_TRACING\n", stderr);
        !           260: }
        !           261: #endif /* !ENABLE_TRACING */
        !           262: 
1.1.1.10  root      263: 
                    264: /*-----------------------------------------------------------------------*/
                    265: /**
                    266:  * Check Bios call and see if we need to re-direct to our own routines.
                    267:  * Return true if we've handled the exception, else return false to let
                    268:  * TOS attempt it
1.1.1.6   root      269:  */
1.1.1.7   root      270: bool Bios(void)
1.1       root      271: {
1.1.1.3   root      272:        Uint32 Params;
                    273:        Uint16 BiosCall;
1.1       root      274: 
1.1.1.3   root      275:        /* Get call */
                    276:        Params = Regs[REG_A7];
                    277:        BiosCall = STMemory_ReadWord(Params);
1.1.1.12! root      278:        Params += SIZE_WORD;
1.1.1.3   root      279: 
                    280:        /* Intercept? */
                    281:        switch(BiosCall)
                    282:        {
1.1.1.12! root      283:        case 0x3:
        !           284:                Bios_Bconout(Params);
        !           285:                break;
        !           286:        case 0x4:
        !           287:                Bios_RWabs(Params);
        !           288:                break;
        !           289: 
        !           290:        case 0x0:
        !           291:                LOG_TRACE(TRACE_OS_BIOS, "BIOS 0x00 Getmpb(0x%X)\n",
        !           292:                          STMemory_ReadLong(Params));
        !           293:                break;
        !           294: 
        !           295:        case 0x5:
        !           296:                LOG_TRACE(TRACE_OS_BIOS, "BIOS 0x05 Setexc(0x%hX, 0x%X)\n",
        !           297:                          STMemory_ReadWord(Params),
        !           298:                          STMemory_ReadLong(Params)+SIZE_WORD);
        !           299:                break;
        !           300: 
        !           301:        case 0x1:
        !           302:        case 0x2:
        !           303:        case 0x7:
        !           304:        case 0x8:
        !           305:        case 0x9:
        !           306:        case 0xB:
        !           307:                /* commands taking a single word */
        !           308:                LOG_TRACE(TRACE_OS_BIOS, "BIOS 0x%02hX %s(0x%hX)\n",
        !           309:                          BiosCall, Bios_Call2Name(BiosCall),
        !           310:                          STMemory_ReadWord(Params));
        !           311:                break;
        !           312: 
        !           313:        case 0x6:
        !           314:        case 0xA:
        !           315:                /* commands taking no args */
        !           316:                LOG_TRACE(TRACE_OS_BIOS, "BIOS 0x%02hX %s()\n",
        !           317:                          BiosCall, Bios_Call2Name(BiosCall));
        !           318:                break;
        !           319: 
        !           320:        default:
        !           321:                Log_Printf(LOG_WARN, "Unknown BIOS call 0x%x!\n", BiosCall);
        !           322:                break;
1.1.1.3   root      323:        }
1.1.1.12! root      324:        return false;
1.1       root      325: }

unix.superglobalmegacorp.com

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