|
|
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: ! 9: The Atari ST TOS needs to be patched to help with emulation. Eg, it references ! 10: the MMU chip to set memory size. This is patched to the sizes we need without ! 11: the complicated emulation of hardware which is not needed (as yet). We also ! 12: patch DMA devices and Hard Drives. ! 13: NOTE: TOS versions 1.06 and 1.62 were not designed for use on a real STfm. ! 14: These were for the STe machine ONLY. They access the DMA/Microwire addresses ! 15: on boot-up which (correctly) cause a bus-error on Hatari as they would in a ! 16: real STfm. If a user tries to select any of these images we bring up an error. 1.1 root 17: */ 1.1.1.6 ! root 18: static char rcsid[] = "Hatari $Id: tos.c,v 1.13 2003/03/09 15:37:10 thothy Exp $"; 1.1 root 19: 1.1.1.4 root 20: #include <SDL_types.h> 21: 1.1 root 22: #include "main.h" 23: #include "cart.h" 24: #include "debug.h" 25: #include "decode.h" 26: #include "dialog.h" 27: #include "errlog.h" 28: #include "file.h" 29: #include "floppy.h" 1.1.1.4 root 30: #include "gemdos.h" 31: #include "hdc.h" 1.1 root 32: #include "m68000.h" 33: #include "memAlloc.h" 34: #include "memorySnapShot.h" 35: #include "stMemory.h" 36: #include "tos.h" 37: #include "vdi.h" 38: 39: 40: /* Settings for differnt memory sizes */ 1.1.1.6 ! root 41: static MEMORY_INFO MemoryInfo[] = ! 42: { ! 43: { 0x80000, 0x01, 0x00080000 }, /* MEMORYSIZE_512 */ ! 44: { 0x100000, 0x05, 0x00100000 }, /* MEMORYSIZE_1024 */ ! 45: { 0x200000, 0x02, 0x00200000 }, /* MEMORYSIZE_2MB */ ! 46: { 0x400000, 0x0A, 0x00400000 } /* MEMORYSIZE_4MB */ 1.1 root 47: }; 48: 1.1.1.4 root 49: /* Bit masks of connected drives(we support up to C,D,E,F,G,H) */ 1.1.1.6 ! root 50: unsigned int ConnectedDriveMaskList[] = ! 51: { 1.1 root 52: 0x03, /* DRIVELIST_NONE A,B */ 53: 0x07, /* DRIVELIST_C A,B,C */ 54: 0x0F, /* DRIVELIST_CD A,B,C,D */ 55: 0x1F, /* DRIVELIST_CDE A,B,C,D,E */ 56: 0x3F, /* DRIVELIST_CDEF A,B,C,D,E,F */ 1.1.1.4 root 57: 0x7F, /* DRIVELIST_CDEFG A,B,C,D,E,F,G */ 58: 0xFF, /* DRIVELIST_CDEFGH A,B,C,D,E,F,G,H */ 1.1 root 59: }; 60: 1.1.1.6 ! root 61: unsigned short int TosVersion; /* eg, 0x0100, 0x0102 */ ! 62: unsigned long TosAddress, TosSize; /* Address in ST memory and size of TOS image */ ! 63: BOOL bTosImageLoaded = FALSE; /* Successfully loaded a TOS image? */ 1.1 root 64: unsigned int ConnectedDriveMask=0x03; /* Bit mask of connected drives, eg 0x7 is A,B,C */ 65: 66: /* Possible TOS file extensions to scan for */ 1.1.1.6 ! root 67: char *pszTosNameExts[] = ! 68: { 1.1 root 69: ".img", 70: ".rom", 71: ".tos", 72: NULL 73: }; 74: 75: unsigned long STRamEnd; /* End of ST Ram, above this address is no-mans-land and hardware vectors */ 76: unsigned long STRamEnd_BusErr; /* as above, but start of BUS error exception */ 77: 78: 1.1.1.6 ! root 79: /* Flags that define if a TOS patch should be applied */ ! 80: enum 1.1 root 81: { 1.1.1.6 ! root 82: TP_ALWAYS, /* Patch should alway be applied */ ! 83: TP_HD_ON, /* Apply patch only if HD emulation is on */ ! 84: TP_HD_OFF /* Apply patch only if HD emulation is off */ ! 85: }; 1.1.1.3 root 86: 1.1.1.6 ! root 87: /* This structure is used for patching the TOS ROMs */ ! 88: typedef struct 1.1 root 89: { 1.1.1.6 ! root 90: Uint16 Version; /* TOS version number */ ! 91: Sint16 Country; /* TOS country code: -1 if it does not matter, 0=US, 1=Germany, 2=France, etc. */ ! 92: char *pszName; /* Name of the patch */ ! 93: int Flags; /* When should the patch be applied? (see enum above) */ ! 94: Uint32 Address; /* Where the patch should be applied */ ! 95: Uint32 OldData; /* Expected first 4 old bytes */ ! 96: Uint32 Size; /* Length of the patch */ ! 97: void *pNewData; /* Pointer to the new bytes */ ! 98: } TOS_PATCH; ! 99: ! 100: static char pszHdvInit[] = "hdv_init - initialize drives"; ! 101: static char pszHdvBoot[] = "hdv_boot - load boot sector"; ! 102: static char pszDmaBoot[] = "boot from DMA bus"; ! 103: static char pszSetConDrv[] = "set connected drives mask"; ! 104: static char pszClrConDrv[] = "clear connected drives mask"; ! 105: static char pszTimerD[] = "timer-D init"; /* sets value before calling the set-timer-routine */ ! 106: static char pszMouse[] = "working mouse in big screen resolutions"; ! 107: static char pszRomCheck[] = "ROM checksum"; ! 108: static char pszNoSteHw[] = "disable STE hardware access"; ! 109: ! 110: static Uint8 pRtsOpcode[] = { 0x4E, 0x75 }; /* 0x4E75 = RTS */ ! 111: static Uint8 pNopOpcodes[] = { 0x4E, 0x71, 0x4E, 0x71, 0x4E, 0x71, 0x4E, 0x71, ! 112: 0x4E, 0x71, 0x4E, 0x71, 0x4E, 0x71, 0x4E, 0x71, 0x4E, 0x71, 0x4E, 0x71, ! 113: 0x4E, 0x71, 0x4E, 0x71, 0x4E, 0x71, 0x4E, 0x71 }; /* 0x4E71 = NOP */ ! 114: static Uint8 pConDrvOpcode[] = { 0x00, 0x0A }; /* 0x000A = Hatari's CONDRV_OPCODE */ ! 115: static Uint8 pTimerDOpcode[] = { 0x00, 0x0B }; /* 0x000B = Hatari's TIMERD_OPCODE */ ! 116: static Uint8 pMouseOpcode[] = { 0xD3, 0xC1 }; /* "ADDA.L D1,A1" (instead of "ADDA.W D1,A1") */ ! 117: static Uint8 pRomCheckOpcode[] = { 0x60, 0x00, 0x00, 0x98 }; /* BRA $e00894 */ ! 118: static Uint8 pBraOpcode[] = { 0x60 }; /* 0x60XX = BRA */ 1.1 root 119: 1.1.1.6 ! root 120: /* The patches for the TOS: */ ! 121: static TOS_PATCH TosPatches[] = ! 122: { ! 123: { 0x100, -1, pszHdvInit, TP_ALWAYS, 0xFC0D60, 0x4E56FFF0, 2, pRtsOpcode }, ! 124: { 0x100, -1, pszHdvBoot, TP_ALWAYS, 0xFC1384, 0x4EB900FC, 6, pNopOpcodes }, /* JSR $FC0AF8 */ ! 125: { 0x100, -1, pszSetConDrv, TP_HD_ON, 0xFC04d4, 0x4E754DF9, 2, pConDrvOpcode }, ! 126: { 0x100, -1, pszDmaBoot, TP_HD_OFF, 0xFC03D6, 0x610000D0, 4, pNopOpcodes }, /* BSR $FC04A8 */ ! 127: { 0x100, -1, pszTimerD, TP_ALWAYS, 0xFC21F6, 0x74026100, 2, pTimerDOpcode }, /* (MFP init 0xFC21B4) */ ! 128: ! 129: { 0x102, -1, pszHdvInit, TP_ALWAYS, 0xFC0F44, 0x4E56FFF0, 2, pRtsOpcode }, ! 130: { 0x102, -1, pszHdvBoot, TP_ALWAYS, 0xFC1568, 0x4EB900FC, 6, pNopOpcodes }, /* JSR $FC0C2E */ ! 131: { 0x102, -1, pszSetConDrv, TP_HD_ON, 0xFC0584, 0x4E754DF9, 2, pConDrvOpcode }, ! 132: { 0x102, -1, pszClrConDrv, TP_HD_OFF, 0xFC0302, 0x42B90000, 6, pNopOpcodes }, /* CLR.L $4C2 */ ! 133: { 0x102, -1, pszDmaBoot, TP_HD_OFF, 0xFC0472, 0x610000E4, 4, pNopOpcodes }, /* BSR.W $FC0558 */ ! 134: /* FIXME: Timer D patch seems to be language dependent for Swedish and Swiss TOS! */ ! 135: { 0x102, -1, pszTimerD, TP_ALWAYS, 0xFC2450, 0x74026100, 2, pTimerDOpcode }, /* (MFP init 0xFC2408) */ ! 136: { 0x102, 0, pszMouse, TP_ALWAYS, 0xFD0030, 0xD2C147F9, 2, pMouseOpcode }, ! 137: { 0x102, 1, pszMouse, TP_ALWAYS, 0xFD008A, 0xD2C147F9, 2, pMouseOpcode }, ! 138: { 0x102, 2, pszMouse, TP_ALWAYS, 0xFD00A8, 0xD2C147F9, 2, pMouseOpcode }, ! 139: { 0x102, 3, pszMouse, TP_ALWAYS, 0xFD0030, 0xD2C147F9, 2, pMouseOpcode }, ! 140: { 0x102, 6, pszMouse, TP_ALWAYS, 0xFCFEF0, 0xD2C147F9, 2, pMouseOpcode }, ! 141: { 0x102, 8, pszMouse, TP_ALWAYS, 0xFCFEFE, 0xD2C147F9, 2, pMouseOpcode }, ! 142: ! 143: { 0x104, -1, pszHdvInit, TP_ALWAYS, 0xFC16BA, 0x4E56FFF0, 2, pRtsOpcode }, ! 144: { 0x104, -1, pszHdvBoot, TP_ALWAYS, 0xFC1CCE, 0x4EB900FC, 6, pNopOpcodes }, /* JSR $FC0BD8 */ ! 145: { 0x104, -1, pszSetConDrv, TP_HD_ON, 0xFC0576, 0x4E757A01, 2, pConDrvOpcode }, ! 146: { 0x104, -1, pszClrConDrv, TP_HD_OFF, 0xFC02E6, 0x42AD04C2, 4, pNopOpcodes }, /* CLR.L $4C2(A5) */ ! 147: { 0x104, -1, pszDmaBoot, TP_HD_OFF, 0xFC0466, 0x610000E4, 4, pNopOpcodes }, /* BSR.W $FC054C */ ! 148: { 0x104, -1, pszTimerD, TP_ALWAYS, 0xFC3544, 0x74026100, 2, pTimerDOpcode }, /* (MFP init 0xFC34FC) */ ! 149: ! 150: { 0x205, -1, pszSetConDrv, TP_HD_ON, 0xE0081A, 0x4E752078, 2, pConDrvOpcode }, /* when no bootable DMA devices */ ! 151: { 0x205, -1, pszSetConDrv, TP_HD_ON, 0xE00842, 0x4E7541f9, 2, pConDrvOpcode }, /* used if we have DMA devices */ ! 152: { 0x205, -1, pszClrConDrv, TP_HD_OFF, 0xE002FC, 0x42B804C2, 4, pNopOpcodes }, /* CLR.L $4C2 */ ! 153: { 0x205, -1, pszDmaBoot, TP_HD_OFF, 0xE006AE, 0x610000E4, 4, pNopOpcodes }, /* BSR.W $E00794 */ ! 154: { 0x205, -1, pszTimerD, TP_ALWAYS, 0xE01972, 0x74026100, 2, pTimerDOpcode }, /* (MFP init 0xE01928) */ ! 155: { 0x205, 0, pszHdvInit, TP_ALWAYS, 0xE0468C, 0x4E56FFF0, 2, pRtsOpcode }, ! 156: { 0x205, 1, pszHdvInit, TP_ALWAYS, 0xE046E6, 0x4E56FFF0, 2, pRtsOpcode }, ! 157: { 0x205, 2, pszHdvInit, TP_ALWAYS, 0xE04704, 0x4E56FFF0, 2, pRtsOpcode }, ! 158: { 0x205, 4, pszHdvInit, TP_ALWAYS, 0xE04712, 0x4E56FFF0, 2, pRtsOpcode }, ! 159: { 0x205, 5, pszHdvInit, TP_ALWAYS, 0xE046F4, 0x4E56FFF0, 2, pRtsOpcode }, ! 160: { 0x205, 6, pszHdvInit, TP_ALWAYS, 0xE04704, 0x4E56FFF0, 2, pRtsOpcode }, ! 161: { 0x205, 0, pszHdvBoot, TP_ALWAYS, 0xE04CA0, 0x4EB900E0, 6, pNopOpcodes }, /* JSR $E00E8E */ ! 162: { 0x205, 1, pszHdvBoot, TP_ALWAYS, 0xE04CFA, 0x4EB900E0, 6, pNopOpcodes }, ! 163: { 0x205, 2, pszHdvBoot, TP_ALWAYS, 0xE04D18, 0x4EB900E0, 6, pNopOpcodes }, ! 164: { 0x205, 4, pszHdvBoot, TP_ALWAYS, 0xE04D26, 0x4EB900E0, 6, pNopOpcodes }, ! 165: { 0x205, 5, pszHdvBoot, TP_ALWAYS, 0xE04D08, 0x4EB900E0, 6, pNopOpcodes }, ! 166: { 0x205, 6, pszHdvBoot, TP_ALWAYS, 0xE04D18, 0x4EB900E0, 6, pNopOpcodes }, ! 167: /* An unpatched TOS 2.05 only works on STEs, so apply some anti-STE patches... */ ! 168: { 0x205, -1, pszNoSteHw, TP_ALWAYS, 0xE00096, 0x42788900, 4, pNopOpcodes }, /* CLR.W $FFFF8900 */ ! 169: { 0x205, -1, pszNoSteHw, TP_ALWAYS, 0xE0009E, 0x31D88924, 4, pNopOpcodes }, /* MOVE.W (A0)+,$FFFF8924 */ ! 170: { 0x205, -1, pszNoSteHw, TP_ALWAYS, 0xE000A6, 0x09D10AA9, 28, pNopOpcodes }, ! 171: { 0x205, -1, pszNoSteHw, TP_ALWAYS, 0xE003A0, 0x30389200, 4, pNopOpcodes }, /* MOVE.W $ffff9200,D0 */ ! 172: { 0x205, -1, pszNoSteHw, TP_ALWAYS, 0xE004EA, 0x61000CBC, 4, pNopOpcodes }, ! 173: { 0x205, -1, pszNoSteHw, TP_ALWAYS, 0xE00508, 0x61000C9E, 4, pNopOpcodes }, ! 174: { 0x205, -1, pszNoSteHw, TP_ALWAYS, 0xE007A0, 0x631E2F3C, 1, pBraOpcode }, ! 175: { 0x205, -1, pszNoSteHw, TP_ALWAYS, 0xE00928, 0x10388901, 4, pNopOpcodes }, /* MOVE.B $FFFF8901,D0 */ ! 176: { 0x205, -1, pszNoSteHw, TP_ALWAYS, 0xE00944, 0xB0388901, 4, pNopOpcodes }, /* CMP.B $FFFF8901,D0 */ ! 177: { 0x205, -1, pszNoSteHw, TP_ALWAYS, 0xE00950, 0x67024601, 1, pBraOpcode }, ! 178: { 0x205, -1, pszNoSteHw, TP_ALWAYS, 0xE00968, 0x61000722, 4, pNopOpcodes }, ! 179: { 0x205, -1, pszNoSteHw, TP_ALWAYS, 0xE00CF2, 0x1038820D, 4, pNopOpcodes }, /* MOVE.B $FFFF820D,D0 */ ! 180: { 0x205, -1, pszNoSteHw, TP_ALWAYS, 0xE00E00, 0x1038820D, 4, pNopOpcodes }, /* MOVE.B $FFFF820D,D0 */ ! 181: { 0x205, 0, pszNoSteHw, TP_ALWAYS, 0xE03038, 0x31C0860E, 4, pNopOpcodes }, ! 182: { 0x205, 0, pszNoSteHw, TP_ALWAYS, 0xE034A8, 0x31C0860E, 4, pNopOpcodes }, ! 183: { 0x205, 0, pszNoSteHw, TP_ALWAYS, 0xE034F6, 0x31E90002, 6, pNopOpcodes }, ! 184: ! 185: /* E007FA MOVE.L #$1FFFE,D7 Run checksums on 2xROMs (skip) */ ! 186: /* Checksum is total of TOS ROM image, but get incorrect results */ ! 187: /* as we've changed bytes in the ROM! So, just skip anyway! */ ! 188: { 0x206, -1, pszRomCheck, TP_ALWAYS, 0xE007FA, 0x2E3C0001, 4, pRomCheckOpcode }, ! 189: { 0x206, -1, pszSetConDrv, TP_HD_ON, 0xE00B3E, 0x4E752078, 2, pConDrvOpcode }, /* when no bootable DMA devices */ ! 190: { 0x206, -1, pszSetConDrv, TP_HD_ON, 0xE00B66, 0x4E7541f9, 2, pConDrvOpcode }, /* used if we have DMA devices */ ! 191: { 0x206, -1, pszClrConDrv, TP_HD_OFF, 0xE00362, 0x42B804C2, 4, pNopOpcodes }, /* CLR.L $4C2 */ ! 192: { 0x206, -1, pszDmaBoot, TP_HD_OFF, 0xE00898, 0x610000E0, 4, pNopOpcodes }, /* BSR.W $E0097A */ ! 193: { 0x206, -1, pszTimerD, TP_ALWAYS, 0xE02250, 0x74026100, 2, pTimerDOpcode }, /* (MFP init 0xE02206) */ ! 194: { 0x206, 0, pszHdvInit, TP_ALWAYS, 0xE0518E, 0x4E56FFF0, 2, pRtsOpcode }, ! 195: { 0x206, 1, pszHdvInit, TP_ALWAYS, 0xE051E8, 0x4E56FFF0, 2, pRtsOpcode }, ! 196: { 0x206, 2, pszHdvInit, TP_ALWAYS, 0xE05206, 0x4E56FFF0, 2, pRtsOpcode }, ! 197: { 0x206, 3, pszHdvInit, TP_ALWAYS, 0xE0518E, 0x4E56FFF0, 2, pRtsOpcode }, ! 198: { 0x206, 6, pszHdvInit, TP_ALWAYS, 0xE05206, 0x4E56FFF0, 2, pRtsOpcode }, ! 199: { 0x206, 8, pszHdvInit, TP_ALWAYS, 0xE05214, 0x4E56FFF0, 2, pRtsOpcode }, ! 200: { 0x206, 0, pszHdvBoot, TP_ALWAYS, 0xE05944, 0x4EB900E0, 6, pNopOpcodes }, /* JSR $E011DC */ ! 201: { 0x206, 1, pszHdvBoot, TP_ALWAYS, 0xE0599E, 0x4EB900E0, 6, pNopOpcodes }, ! 202: { 0x206, 2, pszHdvBoot, TP_ALWAYS, 0xE059BC, 0x4EB900E0, 6, pNopOpcodes }, ! 203: { 0x206, 3, pszHdvBoot, TP_ALWAYS, 0xE05944, 0x4EB900E0, 6, pNopOpcodes }, ! 204: { 0x206, 6, pszHdvBoot, TP_ALWAYS, 0xE059BC, 0x4EB900E0, 6, pNopOpcodes }, ! 205: { 0x206, 8, pszHdvBoot, TP_ALWAYS, 0xE059CA, 0x4EB900E0, 6, pNopOpcodes }, 1.1 root 206: 1.1.1.6 ! root 207: { 0, 0, NULL, 0, 0, 0, 0, NULL } ! 208: }; 1.1 root 209: 210: 211: 1.1.1.6 ! root 212: /*-----------------------------------------------------------------------*/ ! 213: /* ! 214: Save/Restore snapshot of local variables ('MemorySnapShot_Store' handles type) ! 215: */ ! 216: void TOS_MemorySnapShot_Capture(BOOL bSave) ! 217: { ! 218: /* Save/Restore details */ ! 219: MemorySnapShot_Store(&TosVersion, sizeof(TosVersion)); ! 220: MemorySnapShot_Store(&TosAddress, sizeof(TosAddress)); ! 221: MemorySnapShot_Store(&TosSize, sizeof(TosSize)); ! 222: MemorySnapShot_Store(&ConnectedDriveMask, sizeof(ConnectedDriveMask)); 1.1 root 223: } 224: 1.1.1.3 root 225: 226: /*-----------------------------------------------------------------------*/ 1.1 root 227: /* 1.1.1.4 root 228: Patch TOS to skip some TOS setup code which we don't support/need. 1.1 root 229: 230: So, how do we find these addresses when we have no commented source code? 1.1.1.6 ! root 231: - Hdv_init: Scan start of TOS for table of move.l <addr>,$46A(a5), around 0x224 bytes in ! 232: and look at the first entry - that's the hdv_init address. ! 233: - Hdv_boot: Scan start of TOS for table of move.l <addr>,$47A(a5), and look for 5th entry, ! 234: that's the hdv_boot address. The function starts with link,movem,jsr. ! 235: - Boot from DMA bus: again scan at start of rom for tst.w $482, boot call will be just above it. ! 236: - Clear connected drives: search for 'clr.w' and '$4c2' to find, may use (a5) in which case op-code ! 237: is only 4 bytes and also note this is only do on TOS > 1.00 ! 238: ! 239: If we use hard disk emulation, we also need to force set condrv ($4c2), ! 240: because the ACSI driver (if any) will reset it. This is done after the DMA ! 241: bus boot (when the driver loads), replacing the RTS with our own routine which ! 242: sets condrv and then RTSes. 1.1 root 243: */ 1.1.1.6 ! root 244: static void TOS_FixRom(void) 1.1 root 245: { 1.1.1.6 ! root 246: int nGoodPatches, nBadPatches; ! 247: short TosCountry; ! 248: BOOL bHdIsOn; ! 249: TOS_PATCH *pPatch; 1.1 root 250: 1.1.1.6 ! root 251: /* Check for EmuTOS first since we can not patch it */ ! 252: if(STMemory_ReadLong(TosAddress+0x2c) == 0x45544F53) /* 0x45544F53 = 'ETOS' */ ! 253: { ! 254: fprintf(stderr, "Detected EmuTOS, skipping TOS patches.\n"); ! 255: return; ! 256: } 1.1 root 257: 1.1.1.6 ! root 258: nGoodPatches = nBadPatches = 0; ! 259: TosCountry = STMemory_ReadWord(TosAddress+28)>>1; /* TOS country code */ ! 260: bHdIsOn = (ACSI_EMU_ON || GEMDOS_EMU_ON); ! 261: pPatch = TosPatches; 1.1 root 262: 1.1.1.6 ! root 263: /* Apply TOS patches: */ ! 264: while(pPatch->Version) ! 265: { ! 266: /* Only apply patches that suit to the actual TOS version: */ ! 267: if(pPatch->Version == TosVersion ! 268: && (pPatch->Country == TosCountry || pPatch->Country == -1)) ! 269: { ! 270: /* Make sure that we really patch the right place by comparing data: */ ! 271: if(STMemory_ReadLong(pPatch->Address) == pPatch->OldData) 1.1.1.5 root 272: { 1.1.1.6 ! root 273: /* Only apply the patch if it is really needed: */ ! 274: if(pPatch->Flags == TP_ALWAYS || (pPatch->Flags == TP_HD_ON && bHdIsOn) ! 275: || (pPatch->Flags == TP_HD_OFF && !bHdIsOn)) 1.1.1.5 root 276: { 1.1.1.6 ! root 277: /* Now we can really apply the patch! */ ! 278: /*fprintf(stderr, "Applying TOS patch '%s'.\n", pPatch->pszName);*/ ! 279: memcpy(&STRam[pPatch->Address], pPatch->pNewData, pPatch->Size); 1.1.1.5 root 280: } 1.1.1.6 ! root 281: else 1.1.1.5 root 282: { 1.1.1.6 ! root 283: /*fprintf(stderr, "Skipped patch '%s'.\n", pPatch->pszName);*/ 1.1.1.5 root 284: } 1.1.1.6 ! root 285: nGoodPatches += 1; 1.1.1.5 root 286: } 287: else 288: { 1.1.1.6 ! root 289: fprintf(stderr, "Failed to apply TOS patch '%s'.\n", pPatch->pszName); ! 290: nBadPatches += 1; 1.1.1.5 root 291: } 1.1.1.6 ! root 292: } ! 293: pPatch += 1; ! 294: } 1.1 root 295: 1.1.1.6 ! root 296: fprintf(stderr, "Applied %i TOS patches, %i patches failed.\n", ! 297: nGoodPatches, nBadPatches); 1.1 root 298: 1.1.1.6 ! root 299: /* Modify assembler loaded into cartridge area */ ! 300: switch(TosVersion) ! 301: { ! 302: case 0x0100: Cart_WriteHdvAddress(0x167A); break; ! 303: case 0x0102: Cart_WriteHdvAddress(0x16DA); break; ! 304: case 0x0104: Cart_WriteHdvAddress(0x181C); break; ! 305: case 0x0205: Cart_WriteHdvAddress(0x1410); break; ! 306: case 0x0206: Cart_WriteHdvAddress(0x1644); break; 1.1 root 307: } 1.1.1.6 ! root 308: 1.1 root 309: } 310: 1.1.1.3 root 311: 312: /*-----------------------------------------------------------------------*/ 1.1 root 313: /* 314: Set default memory configuration, connected floppies and memory size 315: */ 1.1.1.6 ! root 316: static void TOS_SetDefaultMemoryConfig(void) 1.1 root 317: { 1.1.1.3 root 318: /* As TOS checks hardware for memory size + connected devices on boot-up */ 319: /* we set these values ourselves and fill in the magic numbers so TOS */ 320: /* skips these tests which would crash the emulator as the reference the MMU */ 321: 322: /* Fill in magic numbers, so TOS does not try to reference MMU */ 1.1.1.6 ! root 323: STMemory_WriteLong(0x420, 0x752019f3); /* memvalid - configuration is valid */ ! 324: STMemory_WriteLong(0x43a, 0x237698aa); /* another magic # */ ! 325: STMemory_WriteLong(0x51a, 0x5555aaaa); /* and another */ 1.1 root 326: 1.1.1.3 root 327: /* Set memory size, adjust for extra VDI screens if needed */ 1.1.1.5 root 328: if (bUseVDIRes) 329: { 1.1.1.3 root 330: /* This is enough for 1024x768x16colour (0x60000) */ 1.1.1.6 ! root 331: STMemory_WriteLong(0x436, MemoryInfo[ConfigureParams.Memory.nMemorySize].PhysTop-0x60000); /* mem top - upper end of user memory (before 32k screen) */ ! 332: STMemory_WriteLong(0x42e, MemoryInfo[ConfigureParams.Memory.nMemorySize].PhysTop-0x58000); /* phys top */ 1.1 root 333: } 1.1.1.5 root 334: else 335: { 1.1.1.6 ! root 336: STMemory_WriteLong(0x436, MemoryInfo[ConfigureParams.Memory.nMemorySize].PhysTop-0x8000); /* mem top - upper end of user memory(before 32k screen) */ ! 337: STMemory_WriteLong(0x42e, MemoryInfo[ConfigureParams.Memory.nMemorySize].PhysTop); /* phys top */ 1.1 root 338: } 1.1.1.6 ! root 339: STMemory_WriteByte(0x424, MemoryInfo[ConfigureParams.Memory.nMemorySize].MemoryConfig); ! 340: STMemory_WriteByte(0xff8001, MemoryInfo[ConfigureParams.Memory.nMemorySize].MemoryConfig); 1.1 root 341: 1.1.1.3 root 342: /* Set memory range, and start of BUS error */ 343: STRamEnd = MemoryInfo[ConfigureParams.Memory.nMemorySize].MemoryEnd; /* Set end of RAM */ 344: STRamEnd_BusErr = 0x00420000; /* 4Mb */ /* Between RAM end and this is void space (0's), after is a BUS error */ 345: 346: /* Set TOS floppies */ 1.1.1.6 ! root 347: STMemory_WriteWord(0x446, nBootDrive); /* Boot up on A(0) or C(2) */ ! 348: STMemory_WriteWord(0x4a6, 0x2); /* Connected floppies A,B (0 or 2) */ 1.1.1.4 root 349: 1.1.1.3 root 350: ConnectedDriveMask = ConnectedDriveMaskList[ConfigureParams.HardDisc.nDriveList]; 1.1.1.4 root 351: 1.1.1.6 ! root 352: STMemory_WriteLong(0x4c2, ConnectedDriveMask); /* Drives A,B and C - NOTE some TOS images overwrite value, see 'TOS_ConnectedDrive_OpCode' */ 1.1 root 353: 1.1.1.3 root 354: /* Mirror ROM boot vectors */ 1.1.1.6 ! root 355: STMemory_WriteLong(0x00, STMemory_ReadLong(TosAddress)); ! 356: STMemory_WriteLong(0x04, STMemory_ReadLong(TosAddress+4)); ! 357: } ! 358: ! 359: ! 360: /*-----------------------------------------------------------------------*/ ! 361: /* ! 362: Load TOS Rom image file into ST memory space and fix image so can emulate correctly ! 363: Pre TOS 1.06 are loaded at 0xFC0000 with later ones at 0xE00000 ! 364: If we cannot find the TOS image, or we detect an error we default to the built-in ! 365: TOS 1.00 image. This works great for new users who do not understand the idea of a TOS ! 366: Rom and are confused when presented with a 'select TOS image' dialog. ! 367: */ ! 368: int TOS_LoadImage(void) ! 369: { ! 370: void *pTosFile = NULL; ! 371: ! 372: bTosImageLoaded = FALSE; ! 373: ! 374: /* Load TOS image into memory so we can check it's vesion */ ! 375: TosVersion = 0; ! 376: pTosFile = File_Read(ConfigureParams.TOSGEM.szTOSImageFileName, NULL, NULL, pszTosNameExts); ! 377: TosSize = File_Length(ConfigureParams.TOSGEM.szTOSImageFileName); ! 378: ! 379: if(pTosFile && TosSize>0) ! 380: { ! 381: /* Now, look at start of image to find Version number and address */ ! 382: TosVersion = STMemory_Swap68000Int(*(Uint16 *)((Uint32)pTosFile+2)); ! 383: TosAddress = STMemory_Swap68000Long(*(Uint32 *)((Uint32)pTosFile+8)); ! 384: ! 385: /* Check for reasonable TOS version: */ ! 386: if(TosVersion<0x100 || TosVersion>0x500 || TosSize>1024*1024L ! 387: || (TosAddress!=0xe00000 && TosAddress!=0xfc0000)) ! 388: { ! 389: Main_Message("Your TOS seems not to be a valid TOS ROM file!\n", PROG_NAME); ! 390: return -2; ! 391: } ! 392: ! 393: /* TOSes 1.06 and 1.62 are for the STe ONLY and so don't run on a real STfm. */ ! 394: /* They access illegal memory addresses which don't exist on a real machine and cause the OS */ ! 395: /* to lock up. So, if user selects one of these, show an error */ ! 396: if(TosVersion==0x0106 || TosVersion==0x0162) ! 397: { ! 398: Main_Message("TOS versions 1.06 and 1.62 are NOT valid STfm images.\n\n" ! 399: "These were only designed for use on the STe range of machines.\n", PROG_NAME /*,MB_OK|MB_ICONINFORMATION*/); ! 400: return -3; ! 401: } ! 402: ! 403: /* Copy loaded image into ST memory */ ! 404: memcpy((void *)((unsigned long)STRam+TosAddress), pTosFile, TosSize); ! 405: } ! 406: else ! 407: { ! 408: char err_txt[256]; ! 409: strcpy(err_txt, "Can not load TOS file:\n "); ! 410: strncat(err_txt, ConfigureParams.TOSGEM.szTOSImageFileName, 256-32); ! 411: strcat(err_txt, "\n"); ! 412: Main_Message(err_txt, PROG_NAME); ! 413: return -1; ! 414: } ! 415: ! 416: fprintf(stderr, "Loaded TOS version %i.%c%c, starting at $%lx, " ! 417: "country code = %i, %s\n", TosVersion>>8, '0'+((TosVersion>>4)&0x0f), ! 418: '0'+(TosVersion&0x0f), TosAddress, STMemory_ReadWord(TosAddress+28)>>1, ! 419: (STMemory_ReadWord(TosAddress+28)&1)?"PAL":"NTSC"); ! 420: ! 421: /* Are we allowed VDI under this TOS? */ ! 422: if(TosVersion == 0x0100 && bUseVDIRes) ! 423: { ! 424: /* Warn user (exit if need to) */ ! 425: Main_Message("To use GEM extended resolutions, you must select a TOS >= 1.02.", ! 426: PROG_NAME /*,MB_OK|MB_ICONINFORMATION*/); ! 427: /* And select non VDI */ ! 428: bUseVDIRes = ConfigureParams.TOSGEM.bUseExtGEMResolutions = FALSE; ! 429: } ! 430: ! 431: /* Fix TOS image, modify code for emulation */ ! 432: TOS_FixRom(); ! 433: ! 434: /* Set connected devices, memory configuration */ ! 435: TOS_SetDefaultMemoryConfig(); ! 436: ! 437: /* and free loaded image */ ! 438: Memory_Free(pTosFile); ! 439: ! 440: bTosImageLoaded = TRUE; ! 441: return 0; 1.1 root 442: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.