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

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

unix.superglobalmegacorp.com

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