Annotation of hatari/src/tos.c, revision 1.1.1.6

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.