|
|
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: /* Did we load a TOS image correctly? */
156: if (!bTOSImageLoaded) {
157: fprintf(stderr, "Error: No tos.img loaded!\n");
158: exit(-1);
159: }
160:
161: /* Fix TOS image, modify code for emulation */
162: TOS_FixRom();
163:
164: /* Set connected devices, memory configuration */
165: TOS_SetDefaultMemoryConfig();
166:
167: /* and free loaded image */
168: Memory_Free(pTOSFile);
169: }
170:
171: //-----------------------------------------------------------------------
172: /*
173: Modify TOS Rom image to set default memory configuration, connected floppies and memory size
174: and skip some TOS setup code which we don't support/need.
175: As TOS Roms need to be modified we can only run images which are entered here.
176:
177: So, how do we find these addresses when we have no commented source code?
178: Easy,
179: Hdv_init: Scan start of TOS for table of move.l <addr>,$46A(a5), around 0x224 bytes in
180: and look at the first entry - that's the hdv_init address.
181: Hdv_boot: Scan start of TOS for table of move.l <addr>,$47A(a5), and look for 5th entry
182: - that's the hdv_boot address. The function starts with link,movem,jsr.
183: Boot from DMA bus: again scan at start of rom for tst.w $482, boot call will be just above it.
184: Set connected drives: search for 'clr.w' and '$4c2' to find, may use (a5) in which case op-code
185: is only 4 bytes and also note this is only do on TOS's after 1.00
186: */
187: void TOS_FixRom(void)
188: {
189: switch(TOSVersion) {
190: /*
191: TOS 1.00 settings
192: */
193: case 0x0100:
194: /* hdv_init, initialize drives */
195: STMemory_WriteWord(0xFC0D60,RTS_OPCODE); //RTS
196:
197: /* FC1384 JSR $FC0AF8 hdv_boot, load boot sector */
198: STMemory_WriteWord(0xFC1384,NOP_OPCODE); //NOP
199: STMemory_WriteWord(0xFC1384+2,NOP_OPCODE); //NOP
200: STMemory_WriteWord(0xFC1384+4,NOP_OPCODE); //NOP
201:
202: /* FC03d6 JSR $FC04A8 Boot from DMA bus */
203: if (bUseVDIRes) {
204: STMemory_WriteWord(0xFC03D6,0xa000); //Init Line-A
205: STMemory_WriteWord(0xFC03D6+2,0xa0ff); //Trap Line-A(to get structure)
206: }
207: else {
208: STMemory_WriteWord(0xFC03D6,NOP_OPCODE); //NOP
209: STMemory_WriteWord(0xFC03D6+2,NOP_OPCODE); //NOP
210: }
211:
212: /* Timer D(MFP init 0xFC21B4), set value before call Set Timer routine */
213: STMemory_WriteWord(0xFC21F6,TIMERD_OPCODE);
214:
215: /* Modify assembler loaded into cartridge area */
216: Cart_WriteHdvAddress(0x167A);
217: break;
218:
219: /*
220: TOS 1.02 settings
221: */
222: case 0x0102:
223: /* hdv_init, initialize drives */
224: STMemory_WriteWord(0xFC0F44,RTS_OPCODE); //RTS
225:
226: /* FC1568 JSR $FC0C2E hdv_boot, load boot sector */
227: STMemory_WriteWord(0xFC1568,NOP_OPCODE); //NOP
228: STMemory_WriteWord(0xFC1568+2,NOP_OPCODE); //NOP
229: STMemory_WriteWord(0xFC1568+4,NOP_OPCODE); //NOP
230:
231: /* FC0472 BSR.W $FC0558 Boot from DMA bus */
232: if (bUseVDIRes) {
233: STMemory_WriteWord(0xFC0472,0xa000); //Init Line-A
234: STMemory_WriteWord(0xFC0472+2,0xa0ff); //Trap Line-A(to get structure)
235: }
236: else {
237: STMemory_WriteWord(0xFC0472,NOP_OPCODE); //NOP
238: STMemory_WriteWord(0xFC0472+2,NOP_OPCODE); //NOP
239: }
240:
241: /* FC0302 CLR.L $4C2 Set connected drives */
242: STMemory_WriteWord(0xFC0302,CONDRV_OPCODE);
243: STMemory_WriteWord(0xFC0302+2,NOP_OPCODE); //NOP
244: STMemory_WriteWord(0xFC0302+4,NOP_OPCODE); //NOP
245:
246: // Timer D(MFP init 0xFC2408)
247: STMemory_WriteWord(0xFC2450,TIMERD_OPCODE);
248:
249: // Modify assembler loaded into cartridge area
250: Cart_WriteHdvAddress(0x16DA);
251: break;
252:
253: /*
254: TOS 1.04 settings
255: */
256: case 0x0104:
257: /* hdv_init, initialize drives */
258: STMemory_WriteWord(0xFC16BA,RTS_OPCODE); //RTS
259:
260: /* FC1CCE JSR $FC0BD8 hdv_boot, load boot sector */
261: STMemory_WriteWord(0xFC1CCE,NOP_OPCODE); //NOP
262: STMemory_WriteWord(0xFC1CCE + 2,NOP_OPCODE); //NOP
263: STMemory_WriteWord(0xFC1CCE + 4,NOP_OPCODE); //NOP
264:
265: /* FC0466 BSR.W $FC054C Boot from DMA bus */
266: if (bUseVDIRes) {
267: STMemory_WriteWord(0xFC0466,0xa000); //Init Line-A
268: STMemory_WriteWord(0xFC0466+2,0xa0ff); //Trap Line-A(to get structure)
269: }
270: else {
271: STMemory_WriteWord(0xFC0466,NOP_OPCODE); //NOP
272: STMemory_WriteWord(0xFC0466+2,NOP_OPCODE); //NOP
273: }
274:
275: /* FC02E6 CLR.L $4C2(A5) Set connected drives */
276: STMemory_WriteWord(0xFC02E6,CONDRV_OPCODE);
277: STMemory_WriteWord(0xFC02E6+2,NOP_OPCODE); //NOP
278:
279: /* Timer D(MFP init 0xFC34FC) */
280: STMemory_WriteWord(0xFC3544,TIMERD_OPCODE);
281:
282: /* Modify assembler loaded into cartridge area */
283: Cart_WriteHdvAddress(0x181C);
284: break;
285:
286: /*
287: TOS 1.06 settings
288: */
289: // case 0x0106:
290: // // hdv_init, initialize drives
291: // STMemory_WriteWord(0xE01892,RTS_OPCODE); //RTS
292: //
293: // // E01EA6 JSR $E00D74 hdv_boot, load boot sector
294: // STMemory_WriteWord(0xE01EA6,NOP_OPCODE); //NOP
295: // STMemory_WriteWord(0xE01EA6+2,NOP_OPCODE); //NOP
296: // STMemory_WriteWord(0xE01EA6+4,NOP_OPCODE); //NOP
297: //
298: // // E00576 BSR.W $E0065C Boot from DMA bus
299: // if (bUseVDIRes) {
300: // STMemory_WriteWord(0xE00576,0xa000); //Init Line-A
301: // STMemory_WriteWord(0xE00576+2,0xa0ff); //Trap Line-A(to get structure)
302: // }
303: // else {
304: // STMemory_WriteWord(0xE00576,NOP_OPCODE); //NOP
305: // STMemory_WriteWord(0xE00576+2,NOP_OPCODE); //NOP
306: // }
307: //
308: // // E002DC CLR.L $4C2(A5) Set connected drives
309: // STMemory_WriteWord(0xE002DC,CONDRV_OPCODE);
310: // STMemory_WriteWord(0xE002DC+2,NOP_OPCODE); //NOP
311: //
312: // // Timer D(MFP init 0xE036BC)
313: // STMemory_WriteWord(0xE03704,TIMERD_OPCODE);
314: //
315: // // Modify assembler loaded into cartridge area
316: // Cart_WriteHdvAddress(0x185C);
317: // break;
318:
319: /*
320: TOS 1.62 settings
321: */
322: // case 0x0162:
323: // // hdv_init, initialize drives
324: // STMemory_WriteWord(0xE01892,RTS_OPCODE); //RTS
325: //
326: // // E01EA6 JSR $E00D74 hdv_boot, load boot sector
327: // STMemory_WriteWord(0xE01EA6,NOP_OPCODE); //NOP
328: // STMemory_WriteWord(0xE01EA6+2,NOP_OPCODE); //NOP
329: // STMemory_WriteWord(0xE01EA6+4,NOP_OPCODE); //NOP
330: //
331: // // E00576 BSR.W $E0065C Boot from DMA bus
332: // if (bUseVDIRes) {
333: // STMemory_WriteWord(0xE00576,0xa000); //Init Line-A
334: // STMemory_WriteWord(0xE00576+2,0xa0ff); //Trap Line-A(to get structure)
335: // }
336: // else {
337: // STMemory_WriteWord(0xE00576,NOP_OPCODE); //NOP
338: // STMemory_WriteWord(0xE00576+2,NOP_OPCODE); //NOP
339: // }
340: //
341: // // E002DC CLR.L $4C2(A5) Set connected drives
342: // STMemory_WriteWord(0xE002DC,CONDRV_OPCODE);
343: // STMemory_WriteWord(0xE002DC+2,NOP_OPCODE); //NOP
344: //
345: // // Timer D(MFP init 0xE036BC)
346: // STMemory_WriteWord(0xE03704,TIMERD_OPCODE);
347: //
348: // // Modify assembler loaded into cartridge area
349: // Cart_WriteHdvAddress(0x185C);
350: // break;
351:
352: /*
353: TOS 2.05 settings
354: */
355: case 0x0205:
356: // hdv_init, initialize drives
357: STMemory_WriteWord(0xE0468C,RTS_OPCODE); //RTS
358:
359: // E04CA0 JSR $E00E8E hdv_boot, load boot sector
360: STMemory_WriteWord(0xE04CA0,NOP_OPCODE); //NOP
361: STMemory_WriteWord(0xE04CA0+2,NOP_OPCODE); //NOP
362: STMemory_WriteWord(0xE04CA0+4,NOP_OPCODE); //NOP
363:
364: // E006AE BSR.W $E00794 Boot from DMA bus
365: if (bUseVDIRes) {
366: STMemory_WriteWord(0xE006AE,0xa000); //Init Line-A
367: STMemory_WriteWord(0xE006AE + 2,0xa0ff); //Trap Line-A(to get structure)
368: }
369: else {
370: STMemory_WriteWord(0xE006AE,NOP_OPCODE); //NOP
371: STMemory_WriteWord(0xE006AE + 2,NOP_OPCODE); //NOP
372: }
373:
374: // E002FC CLR.L $4C2 Set connected drives
375: STMemory_WriteWord(0xE002FC,CONDRV_OPCODE);
376: STMemory_WriteWord(0xE002FC+2,NOP_OPCODE); //NOP
377:
378: // Timer D(MFP init 0xE01928)
379: STMemory_WriteWord(0xE01972,TIMERD_OPCODE);
380:
381: // Modify assembler loaded into cartridge area
382: Cart_WriteHdvAddress(0x1410);
383: break;
384:
385: /*
386: TOS 2.06 settings
387: */
388: case 0x0206:
389: /* hdv_init, initialize drives */
390: STMemory_WriteWord(0xE0518E,RTS_OPCODE); //RTS
391:
392: /* E05944 JSR $E011DC hdv_boot, load boot sector */
393: STMemory_WriteWord(0xE05944,NOP_OPCODE); //NOP
394: STMemory_WriteWord(0xE05944+2,NOP_OPCODE); //NOP
395: STMemory_WriteWord(0xE05944+4,NOP_OPCODE); //NOP
396:
397: /* E00898 BSR.W $E0097A Boot from DMA bus */
398: if (bUseVDIRes) {
399: STMemory_WriteWord(0xE00898,0xa000); //Init Line-A
400: STMemory_WriteWord(0xE00898+2,0xa0ff); //Trap Line-A(to get structure)
401: }
402: else {
403: STMemory_WriteWord(0xE00898,NOP_OPCODE); //NOP
404: STMemory_WriteWord(0xE00898+2,NOP_OPCODE); //NOP
405: }
406:
407: /* E00362 CLR.L $4C2 Set connected drives */
408: STMemory_WriteWord(0xE00362,CONDRV_OPCODE);
409: STMemory_WriteWord(0xE00362+2,NOP_OPCODE); //NOP
410:
411: /* E007FA MOVE.L #$1FFFE,D7 Run checksums on 2xROMs(skip) */
412: /* Checksum is total of TOS rom image, but get incorrect results as we've */
413: /* changed bytes in the ROM! So, just skip anyway! */
414: STMemory_WriteWord(0xE007FA,BRAW_OPCODE); //BRA.W $E00894
415: STMemory_WriteWord(0xE007FA+2,0x98);
416:
417: /* Timer D(MFP init 0xE02206) */
418: STMemory_WriteWord(0xE02250,TIMERD_OPCODE);
419:
420: /* Modify assembler loaded into cartridge area */
421: Cart_WriteHdvAddress(0x1644);
422: break;
423: }
424: }
425:
426: //-----------------------------------------------------------------------
427: /*
428: Set default memory configuration, connected floppies and memory size
429: */
430: void TOS_SetDefaultMemoryConfig(void)
431: {
432: // As TOS checks hardware for memory size + connected devices on boot-up
433: // we set these values ourselves and fill in the magic numbers so TOS
434: // skips these tests which would crash the emulator as the reference the MMU
435:
436: // Fill in magic numbers, so TOS does not try to reference MMU
437: STMemory_WriteLong(0x420,0x752019f3); // memvalid - configuration is valid
438: STMemory_WriteLong(0x43a,0x237698aa); // another magic #
439: STMemory_WriteLong(0x51a,0x5555aaaa); // and another
440:
441: // Set memory size, adjust for extra VDI screens if needed
442: if (bUseVDIRes) {
443: // This is enough for 1024x768x16colour(0x60000)
444: STMemory_WriteLong(0x436,MemoryInfo[/*ConfigureParams.Memory.*/nMemorySize].PhysTop-0x60000); // mem top - upper end of user memory(before 32k screen)
445: STMemory_WriteLong(0x42e,MemoryInfo[/*ConfigureParams.Memory.*/nMemorySize].PhysTop-0x58000); // phys top
446: }
447: else {
448: STMemory_WriteLong(0x436,MemoryInfo[/*ConfigureParams.Memory.*/nMemorySize].PhysTop-0x8000); // mem top - upper end of user memory(before 32k screen)
449: STMemory_WriteLong(0x42e,MemoryInfo[/*ConfigureParams.Memory.*/nMemorySize].PhysTop); // phys top
450: }
451: STMemory_WriteLong(0x424,MemoryInfo[/*ConfigureParams.Memory.*/nMemorySize].MemoryConfig); // 512k configure 0x00=128k 0x01=512k 0x10=2Mb 11=reserved eg 0x1010 = 4Mb
452:
453: // Set memory range, and start of BUS error
454: STRamEnd = MemoryInfo[/*ConfigureParams.Memory.*/nMemorySize].MemoryEnd; // Set end of RAM
455: STRamEnd_BusErr = 0x00420000; // 4Mb // Between RAM end and this is void space(0's), after is a BUS error
456:
457: // Set TOS floppies
458: STMemory_WriteWord(0x446,nBootDrive); // Boot up on A(0) or C(2)
459: STMemory_WriteWord(0x4a6,0x2); // Connected floppies A,B (0 or 2)
460: //FIXME ConnectedDriveMask = ConnectedDriveMaskList[ConfigureParams.HardDisc.nDriveList];
461: STMemory_WriteLong(0x4c2,ConnectedDriveMask); /* Drives A,B and C - NOTE some TOS images overwrite value, see 'TOS_ConnectedDrive_OpCode' */
462:
463: /* Added by Thothy: */
464: STMemory_WriteLong(0x00,STMemory_ReadLong(TOSAddress) ); /* Mirror ROM */
465: STMemory_WriteLong(0x04,STMemory_ReadLong(TOSAddress+4) );
466: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.