|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.