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