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

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

unix.superglobalmegacorp.com

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