|
|
1.1 ! root 1: /* ! 2: * UAE - The Un*x Amiga Emulator ! 3: * ! 4: * AutoConfig devices ! 5: * ! 6: * (c) 1995 Bernd Schmidt ! 7: * (c) 1996 Ed Hanway ! 8: */ ! 9: ! 10: #include "sysconfig.h" ! 11: #include "sysdeps.h" ! 12: ! 13: #include "config.h" ! 14: #include "options.h" ! 15: #include "memory.h" ! 16: #include "custom.h" ! 17: #include "newcpu.h" ! 18: #include "disk.h" ! 19: #include "xwin.h" ! 20: #include "autoconf.h" ! 21: ! 22: static struct { ! 23: CPTR libbase; ! 24: TrapFunction functions[300]; /* I don't think any library has more than 300 functions */ ! 25: } libpatches[20]; ! 26: static int n_libpatches = 0; ! 27: ! 28: ULONG Call68k_retaddr(CPTR address, int saveregs, CPTR retaddr) ! 29: { ! 30: ULONG retval; ! 31: CPTR oldpc = m68k_getpc(); ! 32: ! 33: struct regstruct backup_regs; ! 34: if (saveregs) ! 35: backup_regs = regs; ! 36: regs.a[7] -= 4; ! 37: put_long (regs.a[7], retaddr); ! 38: m68k_setpc(address); ! 39: m68k_go(0); ! 40: retval = regs.d[0]; ! 41: if (saveregs) ! 42: regs = backup_regs; ! 43: m68k_setpc(oldpc); ! 44: return retval; ! 45: } ! 46: ! 47: ULONG Call68k(CPTR address, int saveregs) ! 48: { ! 49: return Call68k_retaddr(address, saveregs, 0xF0FFF0); ! 50: } ! 51: ! 52: ULONG CallLib(CPTR base, WORD offset) ! 53: { ! 54: int i; ! 55: CPTR olda6 = regs.a[6]; ! 56: ULONG retval; ! 57: ! 58: for (i = 0; i < n_libpatches; i++) { ! 59: if (libpatches[i].libbase == base && libpatches[i].functions[-offset/6] != NULL) ! 60: return (*libpatches[i].functions[-offset/6])(); ! 61: } ! 62: ! 63: regs.a[6] = base; ! 64: retval = Call68k(base + offset, 1); ! 65: regs.a[6] = olda6; ! 66: return retval; ! 67: } ! 68: ! 69: /* @$%&� compiler bugs */ ! 70: static volatile int four = 4; ! 71: ! 72: CPTR libemu_InstallFunctionFlags(TrapFunction f, CPTR libbase, int offset, ! 73: int flags) ! 74: { ! 75: int i; ! 76: CPTR retval; ! 77: CPTR execbase = get_long(four); ! 78: ULONG addr = here(); ! 79: calltrap2(deftrap2(f, flags)); ! 80: dw(RTS); ! 81: ! 82: regs.a[1] = libbase; ! 83: regs.a[0] = offset; ! 84: regs.d[0] = addr; ! 85: retval = CallLib(execbase, -420); ! 86: for (i = 0; i < n_libpatches; i++) { ! 87: if (libpatches[i].libbase == libbase) ! 88: break; ! 89: } ! 90: if (i == n_libpatches) { ! 91: int j; ! 92: libpatches[i].libbase = libbase; ! 93: for (j = 0; j < 300; j++) ! 94: libpatches[i].functions[j] = NULL; ! 95: n_libpatches++; ! 96: } ! 97: libpatches[i].functions[-offset/6] = f; ! 98: return retval; ! 99: } ! 100: ! 101: CPTR libemu_InstallFunction(TrapFunction f, CPTR libbase, int offset) ! 102: { ! 103: return libemu_InstallFunctionFlags(f, libbase, offset, 0); ! 104: } ! 105: ! 106: /* Commonly used autoconfig strings */ ! 107: ! 108: CPTR EXPANSION_explibname, EXPANSION_doslibname, EXPANSION_uaeversion; ! 109: CPTR EXPANSION_uaedevname, EXPANSION_explibbase = 0, EXPANSION_haveV36; ! 110: CPTR EXPANSION_bootcode; ! 111: ! 112: static int current_deviceno = 0; ! 113: ! 114: int get_new_device(char **devname, CPTR *devname_amiga) ! 115: { ! 116: char buffer[80]; ! 117: ! 118: sprintf(buffer,"UAE%d", current_deviceno); ! 119: ! 120: *devname_amiga = ds(*devname = strdup(buffer)); ! 121: return current_deviceno++; ! 122: } ! 123: ! 124: /* ROM tag area memory access */ ! 125: ! 126: static UBYTE rtarea[65536]; ! 127: ! 128: static ULONG rtarea_lget(CPTR) REGPARAM; ! 129: static UWORD rtarea_wget(CPTR) REGPARAM; ! 130: static UBYTE rtarea_bget(CPTR) REGPARAM; ! 131: static void rtarea_lput(CPTR, ULONG) REGPARAM; ! 132: static void rtarea_wput(CPTR, UWORD) REGPARAM; ! 133: static void rtarea_bput(CPTR, UBYTE) REGPARAM; ! 134: static UBYTE *rtarea_xlate(CPTR) REGPARAM; ! 135: ! 136: addrbank rtarea_bank = { ! 137: rtarea_lget, rtarea_wget, ! 138: rtarea_lget, rtarea_wget, rtarea_bget, ! 139: rtarea_lput, rtarea_wput, rtarea_bput, ! 140: rtarea_xlate, default_check ! 141: }; ! 142: ! 143: UBYTE *rtarea_xlate(CPTR addr) ! 144: { ! 145: addr &= 0xFFFF; ! 146: return rtarea + addr; ! 147: } ! 148: ! 149: ULONG rtarea_lget(CPTR addr) ! 150: { ! 151: addr &= 0xFFFF; ! 152: return (ULONG)(rtarea_wget(addr) << 16) + rtarea_wget(addr+2); ! 153: } ! 154: ! 155: UWORD rtarea_wget(CPTR addr) ! 156: { ! 157: addr &= 0xFFFF; ! 158: return (rtarea[addr]<<8) + rtarea[addr+1]; ! 159: } ! 160: ! 161: UBYTE rtarea_bget(CPTR addr) ! 162: { ! 163: UWORD data; ! 164: addr &= 0xFFFF; ! 165: return rtarea[addr]; ! 166: } ! 167: ! 168: void rtarea_lput(CPTR addr, ULONG value) { } ! 169: void rtarea_bput(CPTR addr, UBYTE value) { } ! 170: ! 171: /* Don't start at 0 -- can get bogus writes there. */ ! 172: static ULONG trap_base_addr = 0x00F00180; ! 173: ! 174: /* We'll need a lot of these. */ ! 175: TrapFunction traps[16384]; ! 176: char trapmode[16384]; ! 177: ! 178: static int max_trap = 0; ! 179: ! 180: int lasttrap; ! 181: ! 182: void do_emultrap(int tr) ! 183: { ! 184: struct regstruct backup_regs; ! 185: ULONG retval; ! 186: ! 187: if ((trapmode[tr] & 1) == 0) ! 188: backup_regs = regs; ! 189: retval = (*traps[tr])(); ! 190: if ((trapmode[tr] & 1) == 0) ! 191: regs = backup_regs; ! 192: if ((trapmode[tr] & 2) == 0) ! 193: regs.d[0] = retval; ! 194: } ! 195: ! 196: void rtarea_wput(CPTR addr, UWORD value) ! 197: { ! 198: /* Save all registers */ ! 199: struct regstruct backup_regs; ! 200: ULONG retval = 0; ! 201: ULONG func = ((addr - trap_base_addr) & 0xFFFF) >> 1; ! 202: ! 203: if (func == 0) { ! 204: lasttrap = get_long(regs.a[7]); ! 205: regs.a[7] += 4; ! 206: regs.spcflags |= SPCFLAG_EMULTRAP; ! 207: return; ! 208: } ! 209: ! 210: backup_regs = regs; ! 211: if(func < max_trap) { ! 212: retval = (*traps[func])(); ! 213: } else { ! 214: fprintf(stderr, "illegal emulator trap\n"); ! 215: } ! 216: regs = backup_regs; ! 217: regs.d[0] = retval; ! 218: } ! 219: ! 220: /* some quick & dirty code to fill in the rt area and save me a lot of ! 221: * scratch paper ! 222: */ ! 223: ! 224: static int rt_addr = 0; ! 225: static int rt_straddr = 0xFF00 - 2; ! 226: ! 227: ULONG addr(int ptr) ! 228: { ! 229: return (ULONG)ptr + 0x00F00000; ! 230: } ! 231: ! 232: void dw(UWORD data) ! 233: { ! 234: rtarea[rt_addr++] = data >> 8; ! 235: rtarea[rt_addr++] = data; ! 236: } ! 237: ! 238: void dl(ULONG data) ! 239: { ! 240: rtarea[rt_addr++] = data >> 24; ! 241: rtarea[rt_addr++] = data >> 16; ! 242: rtarea[rt_addr++] = data >> 8; ! 243: rtarea[rt_addr++] = data; ! 244: } ! 245: ! 246: /* store strings starting at the end of the rt area and working ! 247: * backward. store pointer at current address ! 248: */ ! 249: ! 250: ULONG ds(char *str) ! 251: { ! 252: int len = strlen(str) + 1; ! 253: ! 254: rt_straddr -= len; ! 255: strcpy(rtarea + rt_straddr, str); ! 256: ! 257: return addr(rt_straddr); ! 258: } ! 259: ! 260: void calltrap2(ULONG n) ! 261: { ! 262: dw(0x4878); /* PEA.L n.w */ ! 263: dw(n); ! 264: /* Call trap #0 is reserved for this */ ! 265: dw(0x33C0); /* MOVE.W D0,abs32 */ ! 266: dl(trap_base_addr); ! 267: } ! 268: ! 269: void calltrap(ULONG n) ! 270: { ! 271: #if 1 ! 272: dw(0x33C0); /* MOVE.W D0,abs32 */ ! 273: dl(n*2 + trap_base_addr); ! 274: #else ! 275: calltrap2(n); ! 276: #endif ! 277: } ! 278: ! 279: void org(ULONG a) ! 280: { ! 281: rt_addr = a - 0x00F00000; ! 282: } ! 283: ! 284: ULONG here(void) ! 285: { ! 286: return addr(rt_addr); ! 287: } ! 288: ! 289: int deftrap(TrapFunction func) ! 290: { ! 291: int num = max_trap++; ! 292: traps[num] = func; ! 293: trapmode[num] = 0; ! 294: return num; ! 295: } ! 296: ! 297: int deftrap2(TrapFunction func, int mode) ! 298: { ! 299: int num = max_trap++; ! 300: traps[num] = func; ! 301: trapmode[num] = mode; ! 302: return num; ! 303: } ! 304: ! 305: void align(int b) ! 306: { ! 307: rt_addr = (rt_addr + (b-1)) & ~(b-1); ! 308: } ! 309: ! 310: static ULONG bootcode(void) ! 311: { ! 312: regs.a[1] = EXPANSION_doslibname; ! 313: regs.d[0] = CallLib (regs.a[6], -96); /* FindResident() */ ! 314: regs.a[0] = get_long(regs.d[0]+22); /* get dos.library rt_init */ ! 315: return regs.a[0]; ! 316: } ! 317: ! 318: void rtarea_init() ! 319: { ! 320: ULONG a; ! 321: char uaever[100]; ! 322: sprintf(uaever, "uae-%d.%d.%d", (version / 100) % 10, (version / 10) % 10, (version / 1) % 10); ! 323: ! 324: EXPANSION_uaeversion = ds(uaever); ! 325: EXPANSION_explibname = ds("expansion.library"); ! 326: EXPANSION_doslibname = ds("dos.library"); ! 327: EXPANSION_uaedevname = ds("uae.device"); ! 328: ! 329: deftrap(NULL); /* Generic emulator trap */ ! 330: lasttrap = 0; ! 331: ! 332: align(4); ! 333: EXPANSION_bootcode = here(); ! 334: calltrap2(deftrap2(bootcode, 1)); ! 335: dw(0x2040); /* move.l d0,a0 */ ! 336: dw(0x4e90); /* jsr (a0) */ ! 337: dw(RTS); ! 338: ! 339: a = here(); ! 340: ! 341: /* Idle task */ ! 342: org(0xF0FFF0 - 4); ! 343: dw(0x4E72); dw (0x2000); /* STOP 0x2000 */ ! 344: ! 345: /* Standard "return from 68k mode" trap */ ! 346: /*org(0xF0FFF0); */ ! 347: calltrap2(0); ! 348: dw(RTS); ! 349: org(a); ! 350: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.