|
|
1.1 root 1: /*
2: Hatari
3:
4: Load TOS image file into ST memory, fix/setup for emulator
5:
6: The Atari ST TOS needs to be patched to help with emulation. Eg, it references the MMU chip
7: to set memory size. This is patched to the sizes we need without the complicated emulation
8: of hardware which is not needed(as yet). We also patch DMA devices and Hard Drives.
9: NOTE: TOS versions 1.06 and 1.62 were not designed for use on a real STfm. These were for the
10: STe machine ONLY. They access the DMA/Microwire addresses on boot-up which(correctly) cause a
11: bus-error on Hatari as they would in a real STfm. If a user tries to select any of these images
12: we bring up an error and default back to the built-in TOS 1.00
13: */
14:
15: #include "main.h"
16: #include "cart.h"
17: #include "debug.h"
18: #include "decode.h"
19: #include "dialog.h"
20: #include "errlog.h"
21: #include "file.h"
22: #include "floppy.h"
23: #include "m68000.h"
24: #include "memAlloc.h"
25: #include "memorySnapShot.h"
26: #include "stMemory.h"
27: #include "tos.h"
28: #include "vdi.h"
29:
30: #define szTOSImageFileName "tos.img" /* FIXME: Make it more flexible */
31:
32:
33: /* Settings for differnt memory sizes */
34: static MEMORY_INFO MemoryInfo[] = {
35: 0x80000,0x0000,0x00080000, /* MEMORYSIZE_512 */
36: 0x100000,0x0101,0x00100000, /* MEMORYSIZE_1024 */
37: 0x200000,0x0001,0x00200000, /* MEMORYSIZE_2MB */
38: 0x400000,0x1010,0x00400000 /* MEMORYSIZE_4MB */
39: };
40:
41: int nMemorySize=1; /* 0=512k, 1=1MB, 2=2MB, 3=4MB */
42:
43: /* Bit masks of connected drives(we support upto C,D,E,F) */
44: unsigned int ConnectedDriveMaskList[] = {
45: 0x03, /* DRIVELIST_NONE A,B */
46: 0x07, /* DRIVELIST_C A,B,C */
47: 0x0F, /* DRIVELIST_CD A,B,C,D */
48: 0x1F, /* DRIVELIST_CDE A,B,C,D,E */
49: 0x3F, /* DRIVELIST_CDEF A,B,C,D,E,F */
50: };
51:
52: unsigned short int TOSVersion; /* eg, 0x0100, 0x0102 */
53: unsigned long TOSAddress,TOSSize; /* Address in ST memory and size of TOS image */
54: unsigned int ConnectedDriveMask=0x03; /* Bit mask of connected drives, eg 0x7 is A,B,C */
55: /*BOOL bOverrideTOSImage=FALSE;*/ /* Override TOS filename, used by Favourites(retains dialog TOS setting for saving) */
56: /*char szTOSImageOverrideFileName[MAX_FILENAME_LENGTH];*/
57:
58: /* Possible TOS file extensions to scan for */
59: char *pszTOSNameExts[] = {
60: ".img",
61: ".rom",
62: ".tos",
63: NULL
64: };
65:
66: /* Taken from Decode.asm - Thothy */
67: unsigned long STRamEnd; /* End of ST Ram, above this address is no-mans-land and hardware vectors */
68: unsigned long STRamEnd_BusErr; /* as above, but start of BUS error exception */
69:
70:
71:
72: //-----------------------------------------------------------------------
73: /*
74: Save/Restore snapshot of local variables('MemorySnapShot_Store' handles type)
75: */
76: void TOS_MemorySnapShot_Capture(BOOL bSave)
77: {
78: // Save/Restore details
79: MemorySnapShot_Store(&TOSVersion,sizeof(TOSVersion));
80: MemorySnapShot_Store(&TOSAddress,sizeof(TOSAddress));
81: MemorySnapShot_Store(&TOSSize,sizeof(TOSSize));
82: MemorySnapShot_Store(&ConnectedDriveMask,sizeof(ConnectedDriveMask));
83: }
84:
85: //-----------------------------------------------------------------------
86: /*
87: Load TOS Rom image file into ST memory space and fix image so can emulate correctly
88: Pre TOS 1.06 are loaded at 0xFC0000 with later ones at 0xE00000
89: If we cannot find the TOS image, or we detect an error we default to the built-in
90: TOS 1.00 image. This works great for new users who do not understand the idea of a TOS
91: Rom and are confused when presented with a 'select TOS image' dialog.
92: */
93: void TOS_LoadImage(void)
94: {
95: void *pTOSFile = NULL;
96: unsigned short int *pVersionPtr, *pTerritoryPtr;
97: BOOL bTOSImageLoaded = FALSE;
98:
99: /* Load TOS image into memory so we can check it's vesion */
100: TOSVersion = 0;
101: /* if (bOverrideTOSImage)
102: pTOSFile = File_Read(szTOSImageOverrideFileName,NULL,NULL,pszTOSNameExts);*/
103: /* If not override TOS, if it failed to load use detault */
104: if (pTOSFile==NULL)
105: pTOSFile = File_Read(/*ConfigureParams.TOSGEM.*/szTOSImageFileName,NULL,NULL,pszTOSNameExts);
106:
107: if (pTOSFile) {
108: /* Now, look at start of image to find Version number and Territory */
109: pVersionPtr = (unsigned short int *)((unsigned long)pTOSFile+0x2);
110: pTerritoryPtr = (unsigned short int *)((unsigned long)pTOSFile+0x1c);
111: TOSVersion = STMemory_Swap68000Int(*pVersionPtr);
112:
113: /* Now see where to copy image */
114: switch(TOSVersion) {
115: case 0x0100: /* TOS 1.00 */
116: case 0x0102: /* TOS 1.02 */
117: case 0x0104: /* TOS 1.04 */
118: TOSAddress = 0xFC0000;
119: TOSSize = 192*1024; /* 192k */
120: bTOSImageLoaded = TRUE;
121: break;
122:
123: /* TOSes 1.06 and 1.62 are for the STe ONLY and so don't run on a real STfm. */
124: /* They access illegal memory addresses which don't exist on a real machine and cause the OS */
125: /* to lock up. So, if user selects one of these, show error and default to original TOS */
126: case 0x0106: /* TOS 1.06 */
127: case 0x0162: /* TOS 1.62 */
128: Main_Message("TOS versions 1.06 and 1.62 are NOT valid STfm images.\n\nThese were only designed for use on the STe range of machines.\n",PROG_NAME /*,MB_OK|MB_ICONINFORMATION*/);
129: bTOSImageLoaded = FALSE;
130: break;
131:
132: case 0x0205: /* TOS 2.05 */
133: case 0x0206: /* TOS 2.06 */
134: TOSAddress = 0xE00000;
135: TOSSize = 256*1024; /* 256k */
136: bTOSImageLoaded = TRUE;
137: break;
138: }
139:
140: /* Copy loaded image into ST memory, if found valid one*/
141: if (bTOSImageLoaded)
142: memcpy((void *)((unsigned long)STRam+TOSAddress),pTOSFile,TOSSize);
143: }
144:
145: /* Are we allowed VDI under this TOS? */
146: if ( (TOSVersion<0x0104) && (bUseVDIRes) ) {
147: /* Warn user (exit if need to) */
148: Main_Message("To use GEM Extended resolutions, you must select TOS 1.04 or higher.",PROG_NAME /*,MB_OK|MB_ICONINFORMATION*/);
149: /* And select non VDI */
150: bUseVDIRes = ConfigureParams.TOSGEM.bUseExtGEMResolutions = FALSE; /*FIXME*/
151: /* Default TOS 1.00 */
152: bTOSImageLoaded = FALSE;
153: }
154:
155: /* We currently only can handle TOS 1.00-1.04, TOS 2.0x does not work, don't know why... */
156: if(TOSVersion>0x0104)
157: {
158: fprintf(stderr, "Hatari only support TOS 1.00, 1.02 and 1.04 at the moment. Sorry.\n");
159: /*bTOSImageLoaded=FALSE;*/
160: }
161:
162: /* Did we load a TOS image correctly? */
163: if (!bTOSImageLoaded) {
164: fprintf(stderr, "Error: No tos.img loaded!\n");
165: exit(-1);
166: }
167:
168: /* Fix TOS image, modify code for emulation */
169: TOS_FixRom();
170:
171: /* Set connected devices, memory configuration */
172: TOS_SetDefaultMemoryConfig();
173:
174: /* and free loaded image */
175: Memory_Free(pTOSFile);
176: }
177:
178: //-----------------------------------------------------------------------
179: /*
180: Modify TOS Rom image to set default memory configuration, connected floppies and memory size
181: and skip some TOS setup code which we don't support/need.
182: As TOS Roms need to be modified we can only run images which are entered here.
183:
184: So, how do we find these addresses when we have no commented source code?
185: Easy,
186: Hdv_init: Scan start of TOS for table of move.l <addr>,$46A(a5), around 0x224 bytes in
187: and look at the first entry - that's the hdv_init address.
188: Hdv_boot: Scan start of TOS for table of move.l <addr>,$47A(a5), and look for 5th entry
189: - that's the hdv_boot address. The function starts with link,movem,jsr.
190: Boot from DMA bus: again scan at start of rom for tst.w $482, boot call will be just above it.
191: Set connected drives: search for 'clr.w' and '$4c2' to find, may use (a5) in which case op-code
192: is only 4 bytes and also note this is only do on TOS's after 1.00
193: */
194: void TOS_FixRom(void)
195: {
196: switch(TOSVersion) {
197: /*
198: TOS 1.00 settings
199: */
200: case 0x0100:
201: /* hdv_init, initialize drives */
202: STMemory_WriteWord(0xFC0D60,RTS_OPCODE); //RTS
203:
204: /* FC1384 JSR $FC0AF8 hdv_boot, load boot sector */
205: STMemory_WriteWord(0xFC1384,NOP_OPCODE); //NOP
206: STMemory_WriteWord(0xFC1384+2,NOP_OPCODE); //NOP
207: STMemory_WriteWord(0xFC1384+4,NOP_OPCODE); //NOP
208:
209: /* FC03d6 JSR $FC04A8 Boot from DMA bus */
210: if (bUseVDIRes) {
211: STMemory_WriteWord(0xFC03D6,0xa000); //Init Line-A
212: STMemory_WriteWord(0xFC03D6+2,0xa0ff); //Trap Line-A(to get structure)
213: }
214: else {
215: STMemory_WriteWord(0xFC03D6,NOP_OPCODE); //NOP
216: STMemory_WriteWord(0xFC03D6+2,NOP_OPCODE); //NOP
217: }
218:
219: /* Timer D(MFP init 0xFC21B4), set value before call Set Timer routine */
220: STMemory_WriteWord(0xFC21F6,TIMERD_OPCODE);
221:
222: /* Modify assembler loaded into cartridge area */
223: Cart_WriteHdvAddress(0x167A);
224: break;
225:
226: /*
227: TOS 1.02 settings
228: */
229: case 0x0102:
230: /* hdv_init, initialize drives */
231: STMemory_WriteWord(0xFC0F44,RTS_OPCODE); //RTS
232:
233: /* FC1568 JSR $FC0C2E hdv_boot, load boot sector */
234: STMemory_WriteWord(0xFC1568,NOP_OPCODE); //NOP
235: STMemory_WriteWord(0xFC1568+2,NOP_OPCODE); //NOP
236: STMemory_WriteWord(0xFC1568+4,NOP_OPCODE); //NOP
237:
238: /* FC0472 BSR.W $FC0558 Boot from DMA bus */
239: if (bUseVDIRes) {
240: STMemory_WriteWord(0xFC0472,0xa000); //Init Line-A
241: STMemory_WriteWord(0xFC0472+2,0xa0ff); //Trap Line-A(to get structure)
242: }
243: else {
244: STMemory_WriteWord(0xFC0472,NOP_OPCODE); //NOP
245: STMemory_WriteWord(0xFC0472+2,NOP_OPCODE); //NOP
246: }
247:
248: /* FC0302 CLR.L $4C2 Set connected drives */
249: STMemory_WriteWord(0xFC0302,CONDRV_OPCODE);
250: STMemory_WriteWord(0xFC0302+2,NOP_OPCODE); //NOP
251: STMemory_WriteWord(0xFC0302+4,NOP_OPCODE); //NOP
252:
253: // Timer D(MFP init 0xFC2408)
254: STMemory_WriteWord(0xFC2450,TIMERD_OPCODE);
255:
256: // Modify assembler loaded into cartridge area
257: Cart_WriteHdvAddress(0x16DA);
258: break;
259:
260: /*
261: TOS 1.04 settings
262: */
263: case 0x0104:
264: /* hdv_init, initialize drives */
265: STMemory_WriteWord(0xFC16BA,RTS_OPCODE); //RTS
266:
267: /* FC1CCE JSR $FC0BD8 hdv_boot, load boot sector */
268: STMemory_WriteWord(0xFC1CCE,NOP_OPCODE); //NOP
269: STMemory_WriteWord(0xFC1CCE + 2,NOP_OPCODE); //NOP
270: STMemory_WriteWord(0xFC1CCE + 4,NOP_OPCODE); //NOP
271:
272: /* FC0466 BSR.W $FC054C Boot from DMA bus */
273: if (bUseVDIRes) {
274: STMemory_WriteWord(0xFC0466,0xa000); //Init Line-A
275: STMemory_WriteWord(0xFC0466+2,0xa0ff); //Trap Line-A(to get structure)
276: }
277: else {
278: STMemory_WriteWord(0xFC0466,NOP_OPCODE); //NOP
279: STMemory_WriteWord(0xFC0466+2,NOP_OPCODE); //NOP
280: }
281:
282: /* FC02E6 CLR.L $4C2(A5) Set connected drives */
283: STMemory_WriteWord(0xFC02E6,CONDRV_OPCODE);
284: STMemory_WriteWord(0xFC02E6+2,NOP_OPCODE); //NOP
285:
286: /* Timer D(MFP init 0xFC34FC) */
287: STMemory_WriteWord(0xFC3544,TIMERD_OPCODE);
288:
289: /* Modify assembler loaded into cartridge area */
290: Cart_WriteHdvAddress(0x181C);
291: break;
292:
293: /*
294: TOS 1.06 settings
295: */
296: // case 0x0106:
297: // // hdv_init, initialize drives
298: // STMemory_WriteWord(0xE01892,RTS_OPCODE); //RTS
299: //
300: // // E01EA6 JSR $E00D74 hdv_boot, load boot sector
301: // STMemory_WriteWord(0xE01EA6,NOP_OPCODE); //NOP
302: // STMemory_WriteWord(0xE01EA6+2,NOP_OPCODE); //NOP
303: // STMemory_WriteWord(0xE01EA6+4,NOP_OPCODE); //NOP
304: //
305: // // E00576 BSR.W $E0065C Boot from DMA bus
306: // if (bUseVDIRes) {
307: // STMemory_WriteWord(0xE00576,0xa000); //Init Line-A
308: // STMemory_WriteWord(0xE00576+2,0xa0ff); //Trap Line-A(to get structure)
309: // }
310: // else {
311: // STMemory_WriteWord(0xE00576,NOP_OPCODE); //NOP
312: // STMemory_WriteWord(0xE00576+2,NOP_OPCODE); //NOP
313: // }
314: //
315: // // E002DC CLR.L $4C2(A5) Set connected drives
316: // STMemory_WriteWord(0xE002DC,CONDRV_OPCODE);
317: // STMemory_WriteWord(0xE002DC+2,NOP_OPCODE); //NOP
318: //
319: // // Timer D(MFP init 0xE036BC)
320: // STMemory_WriteWord(0xE03704,TIMERD_OPCODE);
321: //
322: // // Modify assembler loaded into cartridge area
323: // Cart_WriteHdvAddress(0x185C);
324: // break;
325:
326: /*
327: TOS 1.62 settings
328: */
329: // case 0x0162:
330: // // hdv_init, initialize drives
331: // STMemory_WriteWord(0xE01892,RTS_OPCODE); //RTS
332: //
333: // // E01EA6 JSR $E00D74 hdv_boot, load boot sector
334: // STMemory_WriteWord(0xE01EA6,NOP_OPCODE); //NOP
335: // STMemory_WriteWord(0xE01EA6+2,NOP_OPCODE); //NOP
336: // STMemory_WriteWord(0xE01EA6+4,NOP_OPCODE); //NOP
337: //
338: // // E00576 BSR.W $E0065C Boot from DMA bus
339: // if (bUseVDIRes) {
340: // STMemory_WriteWord(0xE00576,0xa000); //Init Line-A
341: // STMemory_WriteWord(0xE00576+2,0xa0ff); //Trap Line-A(to get structure)
342: // }
343: // else {
344: // STMemory_WriteWord(0xE00576,NOP_OPCODE); //NOP
345: // STMemory_WriteWord(0xE00576+2,NOP_OPCODE); //NOP
346: // }
347: //
348: // // E002DC CLR.L $4C2(A5) Set connected drives
349: // STMemory_WriteWord(0xE002DC,CONDRV_OPCODE);
350: // STMemory_WriteWord(0xE002DC+2,NOP_OPCODE); //NOP
351: //
352: // // Timer D(MFP init 0xE036BC)
353: // STMemory_WriteWord(0xE03704,TIMERD_OPCODE);
354: //
355: // // Modify assembler loaded into cartridge area
356: // Cart_WriteHdvAddress(0x185C);
357: // break;
358:
359: /*
360: TOS 2.05 settings
361: */
362: case 0x0205:
363: // hdv_init, initialize drives
364: STMemory_WriteWord(0xE0468C,RTS_OPCODE); //RTS
365:
366: // E04CA0 JSR $E00E8E hdv_boot, load boot sector
367: STMemory_WriteWord(0xE04CA0,NOP_OPCODE); //NOP
368: STMemory_WriteWord(0xE04CA0+2,NOP_OPCODE); //NOP
369: STMemory_WriteWord(0xE04CA0+4,NOP_OPCODE); //NOP
370:
371: // E006AE BSR.W $E00794 Boot from DMA bus
372: if (bUseVDIRes) {
373: STMemory_WriteWord(0xE006AE,0xa000); //Init Line-A
374: STMemory_WriteWord(0xE006AE + 2,0xa0ff); //Trap Line-A(to get structure)
375: }
376: else {
377: STMemory_WriteWord(0xE006AE,NOP_OPCODE); //NOP
378: STMemory_WriteWord(0xE006AE + 2,NOP_OPCODE); //NOP
379: }
380:
381: // E002FC CLR.L $4C2 Set connected drives
382: STMemory_WriteWord(0xE002FC,CONDRV_OPCODE);
383: STMemory_WriteWord(0xE002FC+2,NOP_OPCODE); //NOP
384:
385: // Timer D(MFP init 0xE01928)
386: STMemory_WriteWord(0xE01972,TIMERD_OPCODE);
387:
388: // Modify assembler loaded into cartridge area
389: Cart_WriteHdvAddress(0x1410);
390: break;
391:
392: /*
393: TOS 2.06 settings
394: */
395: case 0x0206:
396: /* hdv_init, initialize drives */
397: STMemory_WriteWord(0xE0518E,RTS_OPCODE); //RTS
398:
399: /* E05944 JSR $E011DC hdv_boot, load boot sector */
400: STMemory_WriteWord(0xE05944,NOP_OPCODE); //NOP
401: STMemory_WriteWord(0xE05944+2,NOP_OPCODE); //NOP
402: STMemory_WriteWord(0xE05944+4,NOP_OPCODE); //NOP
403:
404: /* E00898 BSR.W $E0097A Boot from DMA bus */
405: if (bUseVDIRes) {
406: STMemory_WriteWord(0xE00898,0xa000); //Init Line-A
407: STMemory_WriteWord(0xE00898+2,0xa0ff); //Trap Line-A(to get structure)
408: }
409: else {
410: STMemory_WriteWord(0xE00898,NOP_OPCODE); //NOP
411: STMemory_WriteWord(0xE00898+2,NOP_OPCODE); //NOP
412: }
413:
414: /* E00362 CLR.L $4C2 Set connected drives */
415: STMemory_WriteWord(0xE00362,CONDRV_OPCODE);
416: STMemory_WriteWord(0xE00362+2,NOP_OPCODE); //NOP
417:
418: /* E007FA MOVE.L #$1FFFE,D7 Run checksums on 2xROMs(skip) */
419: /* Checksum is total of TOS rom image, but get incorrect results as we've */
420: /* changed bytes in the ROM! So, just skip anyway! */
421: STMemory_WriteWord(0xE007FA,BRAW_OPCODE); //BRA.W $E00894
422: STMemory_WriteWord(0xE007FA+2,0x98);
423:
424: /* Timer D(MFP init 0xE02206) */
425: STMemory_WriteWord(0xE02250,TIMERD_OPCODE);
426:
427: /* Modify assembler loaded into cartridge area */
428: Cart_WriteHdvAddress(0x1644);
429: break;
430: }
431: }
432:
433: //-----------------------------------------------------------------------
434: /*
435: Set default memory configuration, connected floppies and memory size
436: */
437: void TOS_SetDefaultMemoryConfig(void)
438: {
439: // As TOS checks hardware for memory size + connected devices on boot-up
440: // we set these values ourselves and fill in the magic numbers so TOS
441: // skips these tests which would crash the emulator as the reference the MMU
442:
443: // Fill in magic numbers, so TOS does not try to reference MMU
444: STMemory_WriteLong(0x420,0x752019f3); // memvalid - configuration is valid
445: STMemory_WriteLong(0x43a,0x237698aa); // another magic #
446: STMemory_WriteLong(0x51a,0x5555aaaa); // and another
447:
448: // Set memory size, adjust for extra VDI screens if needed
449: if (bUseVDIRes) {
450: // This is enough for 1024x768x16colour(0x60000)
451: STMemory_WriteLong(0x436,MemoryInfo[/*ConfigureParams.Memory.*/nMemorySize].PhysTop-0x60000); // mem top - upper end of user memory(before 32k screen)
452: STMemory_WriteLong(0x42e,MemoryInfo[/*ConfigureParams.Memory.*/nMemorySize].PhysTop-0x58000); // phys top
453: }
454: else {
455: STMemory_WriteLong(0x436,MemoryInfo[/*ConfigureParams.Memory.*/nMemorySize].PhysTop-0x8000); // mem top - upper end of user memory(before 32k screen)
456: STMemory_WriteLong(0x42e,MemoryInfo[/*ConfigureParams.Memory.*/nMemorySize].PhysTop); // phys top
457: }
458: STMemory_WriteLong(0x424,MemoryInfo[/*ConfigureParams.Memory.*/nMemorySize].MemoryConfig); // 512k configure 0x00=128k 0x01=512k 0x10=2Mb 11=reserved eg 0x1010 = 4Mb
459:
460: // Set memory range, and start of BUS error
461: STRamEnd = MemoryInfo[/*ConfigureParams.Memory.*/nMemorySize].MemoryEnd; // Set end of RAM
462: STRamEnd_BusErr = 0x00420000; // 4Mb // Between RAM end and this is void space(0's), after is a BUS error
463:
464: // Set TOS floppies
465: STMemory_WriteWord(0x446,nBootDrive); // Boot up on A(0) or C(2)
466: STMemory_WriteWord(0x4a6,0x2); // Connected floppies A,B (0 or 2)
467: //FIXME ConnectedDriveMask = ConnectedDriveMaskList[ConfigureParams.HardDisc.nDriveList];
468: STMemory_WriteLong(0x4c2,ConnectedDriveMask); /* Drives A,B and C - NOTE some TOS images overwrite value, see 'TOS_ConnectedDrive_OpCode' */
469:
470: /* Added by Thothy: */
471: STMemory_WriteLong(0x00,STMemory_ReadLong(TOSAddress) ); /* Mirror ROM */
472: STMemory_WriteLong(0x04,STMemory_ReadLong(TOSAddress+4) );
473: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.