|
|
1.1 root 1: /* 1.1.1.6 root 2: Hatari - tos.c 1.1 root 3: 1.1.1.22! 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: 1.1.1.6 root 7: Load TOS image file into ST memory, fix/setup for emulator. 8: 1.1.1.18 root 9: The Atari ST TOS needs to be patched to help with emulation. Eg, it 10: references the MMU chip to set memory size. This is patched to the 11: sizes we need without the complicated emulation of hardware which 12: is not needed (as yet). We also patch DMA devices and Hard Drives. 13: 14: NOTE: TOS versions 1.06 and 1.62 were not designed for use on a 15: real STfm. These were for the STe machine ONLY. They access the 16: DMA/Microwire addresses on boot-up which (correctly) cause a 17: bus-error on Hatari as they would in a real STfm. If a user tries 18: to select any of these images we bring up an error. */ 1.1.1.16 root 19: const char TOS_fileid[] = "Hatari tos.c : " __DATE__ " " __TIME__; 1.1 root 20: 1.1.1.8 root 21: #include <SDL_endian.h> 1.1.1.4 root 22: 1.1 root 23: #include "main.h" 1.1.1.9 root 24: #include "configuration.h" 1.1 root 25: #include "file.h" 1.1.1.4 root 26: #include "gemdos.h" 27: #include "hdc.h" 1.1.1.10 root 28: #include "ioMem.h" 29: #include "log.h" 1.1 root 30: #include "m68000.h" 31: #include "memorySnapShot.h" 32: #include "stMemory.h" 1.1.1.18 root 33: #include "str.h" 1.1 root 34: #include "tos.h" 35: #include "vdi.h" 1.1.1.18 root 36: #include "falcon/dsp.h" 37: #include "clocks_timings.h" 1.1 root 38: 1.1.1.14 root 39: bool bIsEmuTOS; 40: Uint16 TosVersion; /* eg. 0x0100, 0x0102 */ 1.1.1.10 root 41: Uint32 TosAddress, TosSize; /* Address in ST memory and size of TOS image */ 1.1.1.16 root 42: bool bTosImageLoaded = false; /* Successfully loaded a TOS image? */ 43: bool bRamTosImage; /* true if we loaded a RAM TOS image */ 1.1.1.10 root 44: unsigned int ConnectedDriveMask = 0x03; /* Bit mask of connected drives, eg 0x7 is A,B,C */ 1.1.1.16 root 45: int nNumDrives = 2; /* Number of drives, default is 2 for A: and B: - Strictly, this is the highest mapped drive letter, in-between drives may not be allocated */ 1.1.1.10 root 46: 1.1 root 47: /* Possible TOS file extensions to scan for */ 1.1.1.12 root 48: static const char * const pszTosNameExts[] = 1.1.1.6 root 49: { 1.1.1.12 root 50: ".img", 51: ".rom", 52: ".tos", 53: NULL 1.1 root 54: }; 55: 1.1.1.18 root 56: static struct { 57: FILE *file; /* file pointer to contents of INF file */ 58: char prgname[16]; /* TOS name of the program to auto start */ 59: const char *infname; /* name of the INF file TOS will try to match */ 60: int match_count; /* how many times INF was matched after boot */ 61: int match_max; /* how many times TOS needs it to be matched */ 62: } TosAutoStart; 63: 64: /* autostarted program name will be added after first '\' character */ 65: static const char emudesk_inf[] = 66: "#E 9A 07\r\n" 67: "#Z 01 C:\\@\r\n" 68: "#W 00 00 02 06 26 0C 08 C:\\*.*@\r\n" 69: "#W 00 00 02 08 26 0C 00 @\r\n" 70: "#W 00 00 02 0A 26 0C 00 @\r\n" 71: "#W 00 00 02 0D 26 0C 00 @\r\n" 72: "#M 00 00 01 FF A DISK A@ @\r\n" 73: "#M 01 00 01 FF B DISK B@ @\r\n" 74: "#M 02 00 01 FF C DISK C@ @\r\n" 75: "#F FF 28 @ *.*@\r\n" 76: "#D FF 02 @ *.*@\r\n" 77: "#G 08 FF *.APP@ @\r\n" 78: "#G 08 FF *.PRG@ @\r\n" 79: "#P 08 FF *.TTP@ @\r\n" 80: "#F 08 FF *.TOS@ @\r\n" 81: "#T 00 03 03 FF TRASH@ @\r\n"; 82: 83: static const char desktop_inf[] = 84: "#a000000\r\n" 85: "#b001000\r\n" 86: "#c7770007000600070055200505552220770557075055507703111302\r\n" 87: "#d\r\n" 88: "#Z 01 C:\\@\r\n" 89: "#E D8 11\r\n" 90: "#W 00 00 10 01 17 17 13 C:\\*.*@\r\n" 91: "#W 00 00 08 0B 1D 0D 00 @\r\n" 92: "#W 00 00 0A 0F 1A 09 00 @\r\n" 93: "#W 00 00 0E 01 1A 09 00 @\r\n" 94: "#M 00 00 05 FF A DISK A@ @\r\n" 95: "#M 00 01 05 FF B DISK B@ @\r\n" 96: "#M 00 02 05 FF C DISK C@ @\r\n" 97: "#T 00 03 02 FF TRASH@ @\r\n" 98: "#F FF 04 @ *.*@\r\n" 99: "#D FF 01 @ *.*@\r\n" 100: "#P 03 04 @ *.*@\r\n" 101: "#G 03 FF *.APP@ @\r\n" 102: "#G 03 FF *.PRG@ @\r\n" 103: "#P 03 FF *.TTP@ @\r\n" 104: "#F 03 04 *.TOS@ @\r\n"; 1.1 root 105: 1.1.1.6 root 106: /* Flags that define if a TOS patch should be applied */ 107: enum 1.1 root 108: { 1.1.1.12 root 109: TP_ALWAYS, /* Patch should alway be applied */ 1.1.1.13 root 110: TP_HDIMAGE_OFF, /* Apply patch only if HD emulation is off */ 1.1.1.22! root 111: TP_ANTI_STE, /* Apply patch only if running on plain ST */ ! 112: TP_ANTI_PMMU /* Apply patch only if no PMMU is available */ 1.1.1.6 root 113: }; 1.1.1.3 root 114: 1.1.1.6 root 115: /* This structure is used for patching the TOS ROMs */ 1.1.1.7 root 116: typedef struct 1.1 root 117: { 1.1.1.12 root 118: Uint16 Version; /* TOS version number */ 119: Sint16 Country; /* TOS country code: -1 if it does not matter, 0=US, 1=Germany, 2=France, etc. */ 120: const char *pszName; /* Name of the patch */ 121: int Flags; /* When should the patch be applied? (see enum above) */ 122: Uint32 Address; /* Where the patch should be applied */ 123: Uint32 OldData; /* Expected first 4 old bytes */ 124: Uint32 Size; /* Length of the patch */ 125: const void *pNewData; /* Pointer to the new bytes */ 1.1.1.6 root 126: } TOS_PATCH; 127: 1.1.1.10 root 128: static const char pszDmaBoot[] = "boot from DMA bus"; 1.1.1.13 root 129: static const char pszMouse[] = "big resolutions mouse driver"; 1.1.1.10 root 130: static const char pszRomCheck[] = "ROM checksum"; 131: static const char pszNoSteHw[] = "disable STE hardware access"; 1.1.1.12 root 132: static const char pszNoPmmu[] = "disable PMMU access"; 1.1.1.13 root 133: static const char pszHwDisable[] = "disable hardware access"; 1.1.1.6 root 134: 1.1.1.9 root 135: //static Uint8 pRtsOpcode[] = { 0x4E, 0x75 }; /* 0x4E75 = RTS */ 1.1.1.10 root 136: static const Uint8 pNopOpcodes[] = { 0x4E, 0x71, 0x4E, 0x71, 0x4E, 0x71, 0x4E, 0x71, 1.1.1.6 root 137: 0x4E, 0x71, 0x4E, 0x71, 0x4E, 0x71, 0x4E, 0x71, 0x4E, 0x71, 0x4E, 0x71, 1.1.1.12 root 138: 0x4E, 0x71, 0x4E, 0x71, 0x4E, 0x71, 0x4E, 0x71, 0x4E, 0x71, 0x4E, 0x71 }; /* 0x4E71 = NOP */ 1.1.1.10 root 139: static const Uint8 pMouseOpcode[] = { 0xD3, 0xC1 }; /* "ADDA.L D1,A1" (instead of "ADDA.W D1,A1") */ 1.1.1.13 root 140: static const Uint8 pRomCheckOpcode206[] = { 0x60, 0x00, 0x00, 0x98 }; /* BRA $e00894 */ 141: static const Uint8 pRomCheckOpcode306[] = { 0x60, 0x00, 0x00, 0xB0 }; /* BRA $e00886 */ 142: static const Uint8 pRomCheckOpcode404[] = { 0x60, 0x00, 0x00, 0x94 }; /* BRA $e00746 */ 1.1.1.10 root 143: static const Uint8 pBraOpcode[] = { 0x60 }; /* 0x60XX = BRA */ 1.1 root 144: 1.1.1.6 root 145: /* The patches for the TOS: */ 1.1.1.10 root 146: static const TOS_PATCH TosPatches[] = 1.1.1.6 root 147: { 1.1.1.13 root 148: { 0x100, -1, pszDmaBoot, TP_HDIMAGE_OFF, 0xFC03D6, 0x610000D0, 4, pNopOpcodes }, /* BSR $FC04A8 */ 1.1.1.6 root 149: 1.1.1.13 root 150: { 0x102, -1, pszDmaBoot, TP_HDIMAGE_OFF, 0xFC0472, 0x610000E4, 4, pNopOpcodes }, /* BSR.W $FC0558 */ 1.1.1.6 root 151: { 0x102, 0, pszMouse, TP_ALWAYS, 0xFD0030, 0xD2C147F9, 2, pMouseOpcode }, 152: { 0x102, 1, pszMouse, TP_ALWAYS, 0xFD008A, 0xD2C147F9, 2, pMouseOpcode }, 153: { 0x102, 2, pszMouse, TP_ALWAYS, 0xFD00A8, 0xD2C147F9, 2, pMouseOpcode }, 154: { 0x102, 3, pszMouse, TP_ALWAYS, 0xFD0030, 0xD2C147F9, 2, pMouseOpcode }, 155: { 0x102, 6, pszMouse, TP_ALWAYS, 0xFCFEF0, 0xD2C147F9, 2, pMouseOpcode }, 156: { 0x102, 8, pszMouse, TP_ALWAYS, 0xFCFEFE, 0xD2C147F9, 2, pMouseOpcode }, 157: 1.1.1.13 root 158: { 0x104, -1, pszDmaBoot, TP_HDIMAGE_OFF, 0xFC0466, 0x610000E4, 4, pNopOpcodes }, /* BSR.W $FC054C */ 1.1.1.6 root 159: 1.1.1.13 root 160: { 0x106, -1, pszDmaBoot, TP_HDIMAGE_OFF, 0xE00576, 0x610000E4, 4, pNopOpcodes }, /* BSR.W $E0065C */ 1.1.1.10 root 161: 1.1.1.13 root 162: { 0x162, -1, pszDmaBoot, TP_HDIMAGE_OFF, 0xE00576, 0x610000E4, 4, pNopOpcodes }, /* BSR.W $E0065C */ 1.1.1.10 root 163: 1.1.1.13 root 164: { 0x205, -1, pszDmaBoot, TP_HDIMAGE_OFF, 0xE006AE, 0x610000E4, 4, pNopOpcodes }, /* BSR.W $E00794 */ 1.1.1.6 root 165: /* An unpatched TOS 2.05 only works on STEs, so apply some anti-STE patches... */ 1.1.1.11 root 166: { 0x205, -1, pszNoSteHw, TP_ANTI_STE, 0xE00096, 0x42788900, 4, pNopOpcodes }, /* CLR.W $FFFF8900 */ 167: { 0x205, -1, pszNoSteHw, TP_ANTI_STE, 0xE0009E, 0x31D88924, 4, pNopOpcodes }, /* MOVE.W (A0)+,$FFFF8924 */ 168: { 0x205, -1, pszNoSteHw, TP_ANTI_STE, 0xE000A6, 0x09D10AA9, 28, pNopOpcodes }, 169: { 0x205, -1, pszNoSteHw, TP_ANTI_STE, 0xE003A0, 0x30389200, 4, pNopOpcodes }, /* MOVE.W $ffff9200,D0 */ 170: { 0x205, -1, pszNoSteHw, TP_ANTI_STE, 0xE004EA, 0x61000CBC, 4, pNopOpcodes }, 171: { 0x205, -1, pszNoSteHw, TP_ANTI_STE, 0xE00508, 0x61000C9E, 4, pNopOpcodes }, 172: { 0x205, -1, pszNoSteHw, TP_ANTI_STE, 0xE007A0, 0x631E2F3C, 1, pBraOpcode }, 173: { 0x205, -1, pszNoSteHw, TP_ANTI_STE, 0xE00928, 0x10388901, 4, pNopOpcodes }, /* MOVE.B $FFFF8901,D0 */ 174: { 0x205, -1, pszNoSteHw, TP_ANTI_STE, 0xE00944, 0xB0388901, 4, pNopOpcodes }, /* CMP.B $FFFF8901,D0 */ 175: { 0x205, -1, pszNoSteHw, TP_ANTI_STE, 0xE00950, 0x67024601, 1, pBraOpcode }, 176: { 0x205, -1, pszNoSteHw, TP_ANTI_STE, 0xE00968, 0x61000722, 4, pNopOpcodes }, 177: { 0x205, -1, pszNoSteHw, TP_ANTI_STE, 0xE00CF2, 0x1038820D, 4, pNopOpcodes }, /* MOVE.B $FFFF820D,D0 */ 178: { 0x205, -1, pszNoSteHw, TP_ANTI_STE, 0xE00E00, 0x1038820D, 4, pNopOpcodes }, /* MOVE.B $FFFF820D,D0 */ 179: { 0x205, 0, pszNoSteHw, TP_ANTI_STE, 0xE03038, 0x31C0860E, 4, pNopOpcodes }, 180: { 0x205, 0, pszNoSteHw, TP_ANTI_STE, 0xE034A8, 0x31C0860E, 4, pNopOpcodes }, 181: { 0x205, 0, pszNoSteHw, TP_ANTI_STE, 0xE034F6, 0x31E90002, 6, pNopOpcodes }, 1.1.1.6 root 182: 183: /* E007FA MOVE.L #$1FFFE,D7 Run checksums on 2xROMs (skip) */ 184: /* Checksum is total of TOS ROM image, but get incorrect results */ 185: /* as we've changed bytes in the ROM! So, just skip anyway! */ 1.1.1.13 root 186: { 0x206, -1, pszRomCheck, TP_ALWAYS, 0xE007FA, 0x2E3C0001, 4, pRomCheckOpcode206 }, 187: { 0x206, -1, pszDmaBoot, TP_HDIMAGE_OFF, 0xE00898, 0x610000E0, 4, pNopOpcodes }, /* BSR.W $E0097A */ 1.1 root 188: 1.1.1.13 root 189: { 0x306, -1, pszRomCheck, TP_ALWAYS, 0xE007D4, 0x2E3C0001, 4, pRomCheckOpcode306 }, 1.1.1.22! root 190: { 0x306, -1, pszNoPmmu, TP_ANTI_PMMU, 0xE00068, 0xF0394000, 24, pNopOpcodes }, ! 191: { 0x306, -1, pszNoPmmu, TP_ANTI_PMMU, 0xE01702, 0xF0394C00, 32, pNopOpcodes }, 1.1.1.12 root 192: 1.1.1.22! root 193: { 0x400, -1, pszNoPmmu, TP_ANTI_PMMU, 0xE00064, 0xF0394000, 24, pNopOpcodes }, ! 194: { 0x400, -1, pszNoPmmu, TP_ANTI_PMMU, 0xE0148A, 0xF0394C00, 32, pNopOpcodes }, ! 195: { 0x400, -1, pszNoPmmu, TP_ANTI_PMMU, 0xE03948, 0xF0394000, 24, pNopOpcodes }, 1.1.1.13 root 196: { 0x400, -1, pszRomCheck, TP_ALWAYS, 0xE00686, 0x2E3C0007, 4, pRomCheckOpcode404 }, 197: 1.1.1.22! root 198: { 0x401, -1, pszNoPmmu, TP_ANTI_PMMU, 0xE0006A, 0xF0394000, 24, pNopOpcodes }, ! 199: { 0x401, -1, pszNoPmmu, TP_ANTI_PMMU, 0xE014A8, 0xF0394C00, 32, pNopOpcodes }, ! 200: { 0x401, -1, pszNoPmmu, TP_ANTI_PMMU, 0xE03946, 0xF0394000, 24, pNopOpcodes }, 1.1.1.13 root 201: { 0x401, -1, pszRomCheck, TP_ALWAYS, 0xE006A6, 0x2E3C0007, 4, pRomCheckOpcode404 }, 202: 1.1.1.22! root 203: { 0x402, -1, pszNoPmmu, TP_ANTI_PMMU, 0xE0006A, 0xF0394000, 24, pNopOpcodes }, ! 204: { 0x402, -1, pszNoPmmu, TP_ANTI_PMMU, 0xE014A8, 0xF0394C00, 32, pNopOpcodes }, ! 205: { 0x402, -1, pszNoPmmu, TP_ANTI_PMMU, 0xE03946, 0xF0394000, 24, pNopOpcodes }, 1.1.1.13 root 206: { 0x402, -1, pszRomCheck, TP_ALWAYS, 0xE006A6, 0x2E3C0007, 4, pRomCheckOpcode404 }, 207: 1.1.1.22! root 208: { 0x404, -1, pszNoPmmu, TP_ANTI_PMMU, 0xE0006A, 0xF0394000, 24, pNopOpcodes }, ! 209: { 0x404, -1, pszNoPmmu, TP_ANTI_PMMU, 0xE014E6, 0xF0394C00, 32, pNopOpcodes }, ! 210: { 0x404, -1, pszNoPmmu, TP_ANTI_PMMU, 0xE039A0, 0xF0394000, 24, pNopOpcodes }, 1.1.1.13 root 211: { 0x404, -1, pszRomCheck, TP_ALWAYS, 0xE006B0, 0x2E3C0007, 4, pRomCheckOpcode404 }, 212: 1.1.1.22! root 213: { 0x492, -1, pszNoPmmu, TP_ANTI_PMMU, 0x00F946, 0xF0394000, 24, pNopOpcodes }, ! 214: { 0x492, -1, pszNoPmmu, TP_ANTI_PMMU, 0x01097A, 0xF0394C00, 32, pNopOpcodes }, ! 215: { 0x492, -1, pszNoPmmu, TP_ANTI_PMMU, 0x012E04, 0xF0394000, 24, pNopOpcodes }, 1.1.1.13 root 216: 1.1.1.6 root 217: { 0, 0, NULL, 0, 0, 0, 0, NULL } 218: }; 1.1 root 219: 220: 221: 1.1.1.6 root 222: /*-----------------------------------------------------------------------*/ 1.1.1.13 root 223: /** 224: * Save/Restore snapshot of local variables ('MemorySnapShot_Store' handles type) 225: */ 1.1.1.14 root 226: void TOS_MemorySnapShot_Capture(bool bSave) 1.1.1.6 root 227: { 1.1.1.12 root 228: /* Save/Restore details */ 229: MemorySnapShot_Store(&TosVersion, sizeof(TosVersion)); 230: MemorySnapShot_Store(&TosAddress, sizeof(TosAddress)); 231: MemorySnapShot_Store(&TosSize, sizeof(TosSize)); 232: MemorySnapShot_Store(&ConnectedDriveMask, sizeof(ConnectedDriveMask)); 233: MemorySnapShot_Store(&nNumDrives, sizeof(nNumDrives)); 1.1 root 234: } 235: 1.1.1.3 root 236: 237: /*-----------------------------------------------------------------------*/ 1.1.1.13 root 238: /** 239: * Patch TOS to skip some TOS setup code which we don't support/need. 240: * 241: * So, how do we find these addresses when we have no commented source code? 242: * - For the "Boot from DMA bus" patch: 243: * Scan at start of rom for tst.w $482, boot call will be just above it. 244: */ 1.1.1.6 root 245: static void TOS_FixRom(void) 1.1 root 246: { 1.1.1.12 root 247: int nGoodPatches, nBadPatches; 248: short TosCountry; 249: const TOS_PATCH *pPatch; 250: 1.1.1.13 root 251: /* We can't patch RAM TOS images (yet) */ 252: if (bRamTosImage && TosVersion != 0x0492) 1.1.1.12 root 253: { 254: Log_Printf(LOG_DEBUG, "Detected RAM TOS image, skipping TOS patches.\n"); 255: return; 256: } 257: 258: nGoodPatches = nBadPatches = 0; 259: TosCountry = STMemory_ReadWord(TosAddress+28)>>1; /* TOS country code */ 260: pPatch = TosPatches; 261: 262: /* Apply TOS patches: */ 263: while (pPatch->Version) 264: { 265: /* Only apply patches that suit to the actual TOS version: */ 266: if (pPatch->Version == TosVersion 267: && (pPatch->Country == TosCountry || pPatch->Country == -1)) 268: { 1.1.1.22! root 269: #if ENABLE_WINUAE_CPU ! 270: bool use_mmu = ConfigureParams.System.bMMU; ! 271: #else ! 272: bool use_mmu = false; ! 273: #endif 1.1.1.12 root 274: /* Make sure that we really patch the right place by comparing data: */ 275: if(STMemory_ReadLong(pPatch->Address) == pPatch->OldData) 276: { 277: /* Only apply the patch if it is really needed: */ 1.1.1.13 root 278: if (pPatch->Flags == TP_ALWAYS 1.1.1.19 root 279: || (pPatch->Flags == TP_HDIMAGE_OFF && !ACSI_EMU_ON 280: && !ConfigureParams.HardDisk.bUseIdeMasterHardDiskImage 281: && ConfigureParams.System.bFastBoot) 282: || (pPatch->Flags == TP_ANTI_STE 1.1.1.22! root 283: && ConfigureParams.System.nMachineType == MACHINE_ST) ! 284: || (pPatch->Flags == TP_ANTI_PMMU && !use_mmu) ! 285: ) 1.1.1.12 root 286: { 287: /* Now we can really apply the patch! */ 1.1.1.13 root 288: Log_Printf(LOG_DEBUG, "Applying TOS patch '%s'.\n", pPatch->pszName); 289: memcpy(&RomMem[pPatch->Address], pPatch->pNewData, pPatch->Size); 1.1.1.12 root 290: nGoodPatches += 1; 291: } 292: else 293: { 1.1.1.13 root 294: Log_Printf(LOG_DEBUG, "Skipped patch '%s'.\n", pPatch->pszName); 1.1.1.12 root 295: } 296: } 297: else 298: { 299: Log_Printf(LOG_DEBUG, "Failed to apply TOS patch '%s' at %x (expected %x, found %x).\n", 300: pPatch->pszName, pPatch->Address, pPatch->OldData, STMemory_ReadLong(pPatch->Address)); 301: nBadPatches += 1; 302: } 303: } 304: pPatch += 1; 305: } 1.1.1.3 root 306: 1.1.1.12 root 307: Log_Printf(LOG_DEBUG, "Applied %i TOS patches, %i patches failed.\n", 308: nGoodPatches, nBadPatches); 1.1.1.6 root 309: } 310: 311: 312: /*-----------------------------------------------------------------------*/ 1.1.1.13 root 313: /** 1.1.1.18 root 314: * Set name of program that will be auto started after TOS boots. 315: * Supported only from TOS 1.04 forward. 316: */ 317: void TOS_AutoStart(const char *prgname) 318: { 319: Str_Filename2TOSname(prgname, TosAutoStart.prgname); 320: } 321: 322: /*-----------------------------------------------------------------------*/ 323: /** 324: * Create a temporary desktop.inf file which will start autostart program. 325: * This needs to be re-created on each boot in case user changed TOS version. 326: */ 327: static void TOS_CreateAutoInf(void) 328: { 329: const char *contents, *infname, *prgname; 330: int offset, size, max; 331: FILE *fp; 332: 333: /* in case TOS didn't for some reason close it on previous boot */ 334: TOS_AutoStartClose(TosAutoStart.file); 335: 336: prgname = TosAutoStart.prgname; 337: /* autostart not enabled? */ 338: if (!*prgname) 339: return; 340: 341: /* autostart not supported? */ 342: if (TosVersion < 0x0104) 343: { 344: Log_Printf(LOG_WARN, "Only TOS versions >= 1.04 support autostarting!\n"); 345: return; 346: } 347: 348: if (bIsEmuTOS) 349: { 350: infname = "C:\\EMUDESK.INF"; 351: size = sizeof(emudesk_inf); 352: contents = emudesk_inf; 353: max = 1; 354: } else { 355: /* need to match file TOS searches first */ 356: if (TosVersion >= 0x0200) 357: infname = "NEWDESK.INF"; 358: else 359: infname = "DESKTOP.INF"; 360: size = sizeof(desktop_inf); 361: contents = desktop_inf; 362: max = 1; 363: } 364: /* infname needs to be exactly the same string that given 365: * TOS version gives for GEMDOS to find. 366: */ 367: TosAutoStart.infname = infname; 368: TosAutoStart.match_max = max; 369: TosAutoStart.match_count = 0; 370: 371: /* find where to insert the program name */ 372: for (offset = 0; offset < size; ) 373: { 374: if (contents[offset++] == '\\') 375: break; 376: } 377: assert(offset < size); 378: 379: /* create the autostart file */ 380: fp = tmpfile(); 381: if (!(fp 382: && fwrite(contents, offset, 1, fp) == 1 383: && fwrite(prgname, strlen(prgname), 1, fp) == 1 384: && fwrite(contents+offset, size-offset-1, 1, fp) == 1 385: && fseek(fp, 0, SEEK_SET) == 0)) 386: { 387: if (fp) 388: fclose(fp); 389: Log_Printf(LOG_ERROR, "Failed to create autostart file for '%s'!\n", TosAutoStart.prgname); 390: return; 391: } 392: TosAutoStart.file = fp; 393: Log_Printf(LOG_WARN, "Virtual autostart file '%s' created for '%s'.\n", infname, prgname); 394: } 395: 396: /*-----------------------------------------------------------------------*/ 397: /** 398: * If given name matches autostart file, return its handle, NULL otherwise 399: */ 400: FILE *TOS_AutoStartOpen(const char *filename) 401: { 402: if (TosAutoStart.file && strcmp(filename, TosAutoStart.infname) == 0) 403: { 404: Log_Printf(LOG_WARN, "Autostart file '%s' for '%s' matched.\n", filename, TosAutoStart.prgname); 405: return TosAutoStart.file; 406: } 407: return NULL; 408: } 409: 410: /*-----------------------------------------------------------------------*/ 411: /** 412: * If given handle matches autostart file, close it and return true, 413: * false otherwise. 414: */ 415: bool TOS_AutoStartClose(FILE *fp) 416: { 417: if (fp && fp == TosAutoStart.file) 418: { 419: if (++TosAutoStart.match_count >= TosAutoStart.match_max) 420: { 421: /* Remove autostart INF file after TOS has 422: * read it enough times to do autostarting. 423: * Otherwise user may try change desktop settings 424: * and save them, but they would be lost. 425: */ 426: fclose(TosAutoStart.file); 427: TosAutoStart.file = NULL; 428: Log_Printf(LOG_WARN, "Autostart file removed.\n"); 429: } 430: return true; 431: } 432: return false; 433: } 434: 435: 436: /*-----------------------------------------------------------------------*/ 437: /** 1.1.1.13 root 438: * Assert that TOS version matches the machine type and change the system 439: * configuration if necessary. 440: * For example TOSes 1.06 and 1.62 are for the STE ONLY and so don't run 441: * on a real ST, TOS 3.0x is TT only and TOS 4.x is Falcon only. 442: * These TOS version access illegal memory addresses on machine they were 443: * not designed for and so cause the OS to lock up. So, if user selects one 444: * of these, switch to the appropriate machine type. 445: */ 446: static void TOS_CheckSysConfig(void) 447: { 1.1.1.22! root 448: int oldCpuLevel = ConfigureParams.System.nCpuLevel; 1.1.1.21 root 449: MACHINETYPE oldMachineType = ConfigureParams.System.nMachineType; 1.1.1.22! root 450: if (((TosVersion == 0x0106 || TosVersion == 0x0162) && ConfigureParams.System.nMachineType != MACHINE_STE) ! 451: || (TosVersion == 0x0162 && ConfigureParams.System.nCpuLevel != 0)) 1.1.1.13 root 452: { 1.1.1.14 root 453: Log_AlertDlg(LOG_ERROR, "TOS versions 1.06 and 1.62 are for Atari STE only.\n" 1.1.1.13 root 454: " ==> Switching to STE mode now.\n"); 455: IoMem_UnInit(); 456: ConfigureParams.System.nMachineType = MACHINE_STE; 1.1.1.18 root 457: ClocksTimings_InitMachine ( ConfigureParams.System.nMachineType ); 1.1.1.13 root 458: IoMem_Init(); 1.1.1.18 root 459: ConfigureParams.System.nCpuFreq = 8; 1.1.1.17 root 460: ConfigureParams.System.nCpuLevel = 0; 1.1.1.13 root 461: } 462: else if ((TosVersion & 0x0f00) == 0x0300 && ConfigureParams.System.nMachineType != MACHINE_TT) 463: { 1.1.1.14 root 464: Log_AlertDlg(LOG_ERROR, "TOS versions 3.0x are for Atari TT only.\n" 1.1.1.13 root 465: " ==> Switching to TT mode now.\n"); 466: IoMem_UnInit(); 467: ConfigureParams.System.nMachineType = MACHINE_TT; 1.1.1.18 root 468: ClocksTimings_InitMachine ( ConfigureParams.System.nMachineType ); 1.1.1.13 root 469: IoMem_Init(); 1.1.1.18 root 470: ConfigureParams.System.nCpuFreq = 32; 1.1.1.13 root 471: ConfigureParams.System.nCpuLevel = 3; 472: } 473: else if ((TosVersion & 0x0f00) == 0x0400 && ConfigureParams.System.nMachineType != MACHINE_FALCON) 474: { 1.1.1.14 root 475: Log_AlertDlg(LOG_ERROR, "TOS versions 4.x are for Atari Falcon only.\n" 1.1.1.13 root 476: " ==> Switching to Falcon mode now.\n"); 477: IoMem_UnInit(); 478: ConfigureParams.System.nMachineType = MACHINE_FALCON; 1.1.1.18 root 479: ClocksTimings_InitMachine ( ConfigureParams.System.nMachineType ); 480: #if ENABLE_DSP_EMU 481: ConfigureParams.System.nDSPType = DSP_TYPE_EMU; 482: DSP_Init(); 483: #endif 1.1.1.13 root 484: IoMem_Init(); 1.1.1.18 root 485: ConfigureParams.System.nCpuFreq = 16; 1.1.1.13 root 486: ConfigureParams.System.nCpuLevel = 3; 487: } 1.1.1.19 root 488: else if (TosVersion <= 0x0104 && 489: (ConfigureParams.System.nCpuLevel > 0 || ConfigureParams.System.nMachineType != MACHINE_ST)) 1.1.1.17 root 490: { 1.1.1.19 root 491: Log_AlertDlg(LOG_ERROR, "TOS versions <= 1.4 work only in\n" 492: "ST mode and with a 68000 CPU.\n" 1.1.1.22! root 493: " ==> Switching to ST mode with 68000 now.\n"); 1.1.1.17 root 494: IoMem_UnInit(); 495: ConfigureParams.System.nMachineType = MACHINE_ST; 1.1.1.18 root 496: ClocksTimings_InitMachine ( ConfigureParams.System.nMachineType ); 1.1.1.17 root 497: IoMem_Init(); 1.1.1.18 root 498: ConfigureParams.System.nCpuFreq = 8; 1.1.1.17 root 499: ConfigureParams.System.nCpuLevel = 0; 500: } 1.1.1.13 root 501: else if ((TosVersion < 0x0300 && ConfigureParams.System.nMachineType == MACHINE_FALCON) 502: || (TosVersion < 0x0200 && ConfigureParams.System.nMachineType == MACHINE_TT)) 503: { 1.1.1.19 root 504: Log_AlertDlg(LOG_ERROR, "This TOS version does not work in TT/Falcon mode.\n" 1.1.1.13 root 505: " ==> Switching to STE mode now.\n"); 506: IoMem_UnInit(); 507: ConfigureParams.System.nMachineType = MACHINE_STE; 1.1.1.18 root 508: ClocksTimings_InitMachine ( ConfigureParams.System.nMachineType ); 1.1.1.13 root 509: IoMem_Init(); 1.1.1.18 root 510: ConfigureParams.System.nCpuFreq = 8; 1.1.1.17 root 511: ConfigureParams.System.nCpuLevel = 0; 1.1.1.13 root 512: } 1.1.1.22! root 513: else if ((TosVersion & 0x0f00) == 0x0400 && ConfigureParams.System.nCpuLevel < 2) 1.1.1.14 root 514: { 1.1.1.22! root 515: Log_AlertDlg(LOG_ERROR, "TOS versions 4.x require a CPU >= 68020.\n" 1.1.1.14 root 516: " ==> Switching to 68020 mode now.\n"); 517: ConfigureParams.System.nCpuLevel = 2; 1.1.1.21 root 518: } 1.1.1.22! root 519: else if ((TosVersion & 0x0f00) == 0x0300 && ConfigureParams.System.nCpuLevel < 3) ! 520: { ! 521: Log_AlertDlg(LOG_ERROR, "TOS versions 3.0x require a CPU >= 68030.\n" ! 522: " ==> Switching to 68030 mode now.\n"); ! 523: ConfigureParams.System.nCpuLevel = 3; ! 524: } 1.1.1.21 root 525: /* TOS version triggered changes? */ 526: if (ConfigureParams.System.nMachineType != oldMachineType) 527: { 528: #if ENABLE_WINUAE_CPU 529: if (ConfigureParams.System.nMachineType == MACHINE_TT) 530: { 531: ConfigureParams.System.bCompatibleFPU = true; 532: ConfigureParams.System.n_FPUType = FPU_68882; 533: } else { 534: ConfigureParams.System.n_FPUType = FPU_NONE; /* TODO: or leave it as-is? */ 535: } 1.1.1.22! root 536: if (TosVersion < 0x200) ! 537: { ! 538: ConfigureParams.System.bAddressSpace24 = true; ! 539: ConfigureParams.System.bMMU = false; ! 540: } 1.1.1.21 root 541: #endif 1.1.1.18 root 542: M68000_CheckCpuSettings(); 1.1.1.14 root 543: } 1.1.1.22! root 544: else if (ConfigureParams.System.nCpuLevel != oldCpuLevel) ! 545: { ! 546: M68000_CheckCpuSettings(); ! 547: } 1.1.1.19 root 548: if (TosVersion < 0x0104 && ConfigureParams.HardDisk.bUseHardDiskDirectories) 549: { 550: Log_AlertDlg(LOG_ERROR, "Please use at least TOS v1.04 for the HD directory emulation " 551: "(all required GEMDOS functionality isn't completely emulated for this TOS version)."); 552: } 1.1.1.13 root 553: } 554: 555: 556: /*-----------------------------------------------------------------------*/ 557: /** 1.1.1.20 root 558: * Load TOS Rom image file into ST memory space and fix image so it can be 559: * emulated correctly. Pre TOS 1.06 are loaded at 0xFC0000 and later ones 560: * at 0xE00000. 1.1.1.13 root 561: */ 1.1.1.6 root 562: int TOS_LoadImage(void) 563: { 1.1.1.12 root 564: Uint8 *pTosFile = NULL; 565: long nFileSize; 1.1.1.6 root 566: 1.1.1.16 root 567: bTosImageLoaded = false; 1.1.1.6 root 568: 1.1.1.20 root 569: /* Load TOS image into memory so that we can check its version */ 1.1.1.12 root 570: TosVersion = 0; 1.1.1.13 root 571: pTosFile = File_Read(ConfigureParams.Rom.szTosImageFileName, &nFileSize, pszTosNameExts); 1.1.1.12 root 572: 573: if (!pTosFile || nFileSize <= 0) 574: { 575: Log_AlertDlg(LOG_FATAL, "Can not load TOS file:\n'%s'", ConfigureParams.Rom.szTosImageFileName); 576: return -1; 577: } 578: 579: TosSize = nFileSize; 580: 581: /* Check for RAM TOS images first: */ 582: if (SDL_SwapBE32(*(Uint32 *)pTosFile) == 0x46FC2700) 583: { 1.1.1.13 root 584: int nRamTosLoaderSize; 1.1.1.12 root 585: Log_Printf(LOG_WARN, "Detected a RAM TOS - this will probably not work very well!\n"); 586: /* RAM TOS images have a 256 bytes loader function before the real image 1.1.1.13 root 587: * starts (34 bytes for TOS 4.92). Since we directly copy the image to the right 588: * location later, we simply skip this additional header here: */ 589: if (SDL_SwapBE32(*(Uint32 *)(pTosFile+34)) == 0x602E0492) 590: nRamTosLoaderSize = 0x22; 591: else 592: nRamTosLoaderSize = 0x100; 593: TosSize -= nRamTosLoaderSize; 594: memmove(pTosFile, pTosFile + nRamTosLoaderSize, TosSize); 1.1.1.16 root 595: bRamTosImage = true; 1.1.1.12 root 596: } 597: else 598: { 1.1.1.16 root 599: bRamTosImage = false; 1.1.1.12 root 600: } 601: 1.1.1.13 root 602: /* Check for EmuTOS ... (0x45544F53 = 'ETOS') */ 603: bIsEmuTOS = (SDL_SwapBE32(*(Uint32 *)&pTosFile[0x2c]) == 0x45544F53); 604: 1.1.1.12 root 605: /* Now, look at start of image to find Version number and address */ 606: TosVersion = SDL_SwapBE16(*(Uint16 *)&pTosFile[2]); 607: TosAddress = SDL_SwapBE32(*(Uint32 *)&pTosFile[8]); 608: 609: /* Check for reasonable TOS version: */ 1.1.1.18 root 610: if (TosVersion == 0x000 && TosSize == 16384) 611: { 612: /* TOS 0.00 was a very early boot loader ROM which could only 613: * execute a boot sector from floppy disk, which was used in 614: * the very early STs before a full TOS was available in ROM. 615: * It's not very useful nowadays, but we support it here, too, 616: * just for fun. */ 617: TosAddress = 0xfc0000; 618: } 619: else if (TosVersion<0x100 || TosVersion>=0x500 || TosSize>1024*1024L 1.1.1.12 root 620: || (!bRamTosImage && TosAddress!=0xe00000 && TosAddress!=0xfc0000)) 621: { 622: Log_AlertDlg(LOG_FATAL, "Your TOS image seems not to be a valid TOS ROM file!\n" 623: "(TOS version %x, address $%x)", TosVersion, TosAddress); 624: return -2; 625: } 626: 1.1.1.13 root 627: /* Assert that machine type matches the TOS version. Note that EmuTOS can 628: * handle all machine types, so we don't do the system check there: */ 629: if (!bIsEmuTOS) 630: TOS_CheckSysConfig(); 631: 632: /* Calculate end of RAM */ 633: if (ConfigureParams.Memory.nMemorySize > 0 634: && ConfigureParams.Memory.nMemorySize <= 14) 635: STRamEnd = ConfigureParams.Memory.nMemorySize * 0x100000; 636: else 637: STRamEnd = 0x80000; /* 512 KiB */ 638: 639: /* (Re-)Initialize the memory banks: */ 640: memory_uninit(); 641: memory_init(STRamEnd, 0, TosAddress); 642: 643: /* Clear Upper memory (ROM and IO memory) */ 644: memset(&RomMem[0xe00000], 0, 0x200000); 1.1.1.12 root 645: 646: /* Copy loaded image into ST memory */ 1.1.1.13 root 647: memcpy(&RomMem[TosAddress], pTosFile, TosSize); 1.1.1.12 root 648: 649: Log_Printf(LOG_DEBUG, "Loaded TOS version %i.%c%c, starting at $%x, " 650: "country code = %i, %s\n", TosVersion>>8, '0'+((TosVersion>>4)&0x0f), 651: '0'+(TosVersion&0x0f), TosAddress, STMemory_ReadWord(TosAddress+28)>>1, 652: (STMemory_ReadWord(TosAddress+28)&1)?"PAL":"NTSC"); 653: 654: /* Are we allowed VDI under this TOS? */ 655: if (TosVersion == 0x0100 && bUseVDIRes) 656: { 657: /* Warn user */ 1.1.1.18 root 658: Log_AlertDlg(LOG_ERROR, "To use extended VDI resolutions, you must select a TOS >= 1.02."); 1.1.1.12 root 659: /* And select non VDI */ 1.1.1.16 root 660: bUseVDIRes = ConfigureParams.Screen.bUseExtVdiResolutions = false; 1.1.1.12 root 661: } 662: 663: /* Fix TOS image, modify code for emulation */ 1.1.1.19 root 664: if (ConfigureParams.Rom.bPatchTos && !bIsEmuTOS) 665: { 1.1.1.13 root 666: TOS_FixRom(); 1.1.1.19 root 667: } 668: else 669: { 670: Log_Printf(LOG_DEBUG, "Skipped TOS patches.\n"); 671: } 1.1.1.12 root 672: 673: /* Set connected devices, memory configuration, etc. */ 674: STMemory_SetDefaultConfig(); 1.1.1.6 root 675: 1.1.1.12 root 676: /* and free loaded image */ 677: free(pTosFile); 1.1.1.6 root 678: 1.1.1.16 root 679: bTosImageLoaded = true; 1.1.1.18 root 680: TOS_CreateAutoInf(); 1.1.1.6 root 681: 1.1.1.12 root 682: return 0; 1.1 root 683: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.