|
|
1.1 root 1: /*
1.1.1.3 root 2: Hatari - stMemory.c
1.1 root 3:
1.1.1.15 root 4: This file is distributed under the GNU General Public License, version 2
5: or at your option any later version. Read the file gpl.txt for details.
1.1.1.3 root 6:
1.1.1.4 root 7: ST Memory access functions.
1.1 root 8: */
1.1.1.10 root 9: const char STMemory_fileid[] = "Hatari stMemory.c : " __DATE__ " " __TIME__;
1.1 root 10:
1.1.1.4 root 11: #include "stMemory.h"
1.1.1.6 root 12: #include "configuration.h"
13: #include "floppy.h"
1.1.1.10 root 14: #include "gemdos.h"
1.1.1.12 root 15: #include "ioMem.h"
1.1.1.10 root 16: #include "log.h"
1.1.1.7 root 17: #include "memory.h"
1.1.1.12 root 18: #include "memorySnapShot.h"
19: #include "tos.h"
20: #include "vdi.h"
1.1.1.17! root 21: #include "m68000.h"
1.1.1.2 root 22:
1.1.1.7 root 23: /* STRam points to our ST Ram. Unless the user enabled SMALL_MEM where we have
24: * to save memory, this includes all TOS ROM and IO hardware areas for ease
25: * and emulation speed - so we create a 16 MiB array directly here.
26: * But when the user turned on ENABLE_SMALL_MEM, this only points to a malloc'ed
27: * buffer with the ST RAM; the ROM and IO memory will be handled separately. */
28: #if ENABLE_SMALL_MEM
29: Uint8 *STRam;
30: #else
31: Uint8 STRam[16*1024*1024];
32: #endif
1.1.1.4 root 33:
1.1.1.7 root 34: Uint32 STRamEnd; /* End of ST Ram, above this address is no-mans-land and ROM/IO memory */
1.1 root 35:
1.1.1.2 root 36:
1.1.1.7 root 37: /**
38: * Clear section of ST's memory space.
39: */
1.1.1.15 root 40: static void STMemory_Clear(Uint32 StartAddress, Uint32 EndAddress)
1.1 root 41: {
1.1.1.5 root 42: memset(&STRam[StartAddress], 0, EndAddress-StartAddress);
1.1 root 43: }
44:
1.1.1.13 root 45: /**
46: * Copy given memory area safely to Atari RAM.
47: * If the memory area isn't fully within RAM, only the valid parts are written.
48: * Useful for all kinds of IO operations.
49: *
50: * addr - destination Atari RAM address
51: * src - source Hatari memory address
52: * len - number of bytes to copy
53: * name - name / description if this memory copy for error messages
54: *
55: * Return true if whole copy was safe / valid.
56: */
57: bool STMemory_SafeCopy(Uint32 addr, Uint8 *src, unsigned int len, const char *name)
58: {
59: Uint32 end;
60:
1.1.1.17! root 61: if ( STMemory_CheckAreaType ( addr, len, ABFLAG_RAM ) )
1.1.1.13 root 62: {
63: memcpy(&STRam[addr], src, len);
64: return true;
65: }
66: Log_Printf(LOG_WARN, "Invalid '%s' RAM range 0x%x+%i!\n", name, addr, len);
67:
68: for (end = addr + len; addr < end; addr++, src++)
69: {
1.1.1.17! root 70: if ( STMemory_CheckAreaType ( addr, 1, ABFLAG_RAM ) )
1.1.1.13 root 71: STRam[addr] = *src;
72: }
73: return false;
74: }
1.1.1.6 root 75:
1.1.1.12 root 76: /**
77: * Save/Restore snapshot of RAM / ROM variables
78: * ('MemorySnapShot_Store' handles type)
79: */
80: void STMemory_MemorySnapShot_Capture(bool bSave)
81: {
82: MemorySnapShot_Store(&STRamEnd, sizeof(STRamEnd));
83:
84: /* Only save/restore area of memory machine is set to, eg 1Mb */
85: MemorySnapShot_Store(STRam, STRamEnd);
86:
87: /* And Cart/TOS/Hardware area */
88: MemorySnapShot_Store(&RomMem[0xE00000], 0x200000);
89: }
90:
91:
1.1.1.7 root 92: /**
93: * Set default memory configuration, connected floppies, memory size and
94: * clear the ST-RAM area.
95: * As TOS checks hardware for memory size + connected devices on boot-up
96: * we set these values ourselves and fill in the magic numbers so TOS
97: * skips these tests.
98: */
1.1.1.6 root 99: void STMemory_SetDefaultConfig(void)
100: {
101: int i;
1.1.1.17! root 102: int screensize, limit;
! 103: int memtop, phystop;
1.1.1.6 root 104: Uint8 nMemControllerByte;
1.1.1.13 root 105: Uint8 nFalcSysCntrl;
106:
1.1.1.6 root 107: static const int MemControllerTable[] =
108: {
109: 0x01, /* 512 KiB */
110: 0x05, /* 1 MiB */
111: 0x02, /* 2 MiB */
112: 0x06, /* 2.5 MiB */
113: 0x0A /* 4 MiB */
114: };
115:
1.1.1.7 root 116: if (bRamTosImage)
117: {
118: /* Clear ST-RAM, excluding the RAM TOS image */
119: STMemory_Clear(0x00000000, TosAddress);
120: STMemory_Clear(TosAddress+TosSize, STRamEnd);
121: }
1.1.1.6 root 122: else
1.1.1.7 root 123: {
124: /* Clear whole ST-RAM */
125: STMemory_Clear(0x00000000, STRamEnd);
126: }
1.1.1.6 root 127:
128: /* Mirror ROM boot vectors */
129: STMemory_WriteLong(0x00, STMemory_ReadLong(TosAddress));
130: STMemory_WriteLong(0x04, STMemory_ReadLong(TosAddress+4));
131:
1.1.1.14 root 132: /* Fill in magic numbers to bypass TOS' memory tests for faster boot or
1.1.1.17! root 133: * if VDI resolution is enabled or if more than 4 MB of ram are used
! 134: * or if TT RAM added in Falcon mode.
1.1.1.14 root 135: * (for highest compatibility, those tests should not be bypassed in
136: * the common STF/STE cases as some programs like "Yolanda" rely on
137: * the RAM content after those tests) */
1.1.1.17! root 138: if ( ConfigureParams.System.bFastBoot
! 139: || bUseVDIRes
! 140: || ( ConfigureParams.Memory.nMemorySize > 4 && !bIsEmuTOS )
! 141: || ( ( ConfigureParams.System.nMachineType == MACHINE_FALCON ) && TTmemory ) )
1.1.1.14 root 142: {
143: /* Write magic values to sysvars to signal valid config */
144: STMemory_WriteLong(0x420, 0x752019f3); /* memvalid */
145: STMemory_WriteLong(0x43a, 0x237698aa); /* memval2 */
146: STMemory_WriteLong(0x51a, 0x5555aaaa); /* memval3 */
1.1.1.17! root 147:
! 148: /* If ST RAM detection is bypassed, we must also force TT RAM config if enabled */
! 149: if ( TTmemory )
! 150: STMemory_WriteLong ( 0x5a4 , 0x01000000 + TTmem_size ); /* ramtop */
! 151: else
! 152: STMemory_WriteLong ( 0x5a4 , 0 ); /* ramtop */
! 153: STMemory_WriteLong ( 0x5a8 , 0x1357bd13 ); /* ramvalid */
! 154:
! 155: /* On Falcon, set bit6=1 at $ff8007 to simulate a warm start */
! 156: /* (else memory detection is not skipped after a cold start/reset) */
! 157: if ( ConfigureParams.System.nMachineType == MACHINE_FALCON )
! 158: STMemory_WriteByte ( 0xff8007, IoMem_ReadByte(0xff8007) | 0x40 );
! 159:
! 160: /* On TT, set bit0=1 at $ff8e09 to simulate a warm start */
! 161: /* (else memory detection is not skipped after a cold start/reset) */
! 162: if ( ConfigureParams.System.nMachineType == MACHINE_TT )
! 163: STMemory_WriteByte ( 0xff8e09, IoMem_ReadByte(0xff8e09) | 0x01 );
1.1.1.14 root 164: }
1.1.1.6 root 165:
1.1.1.17! root 166: /* Set memory size, adjust for extra VDI screens if needed. */
1.1.1.7 root 167: screensize = VDIWidth * VDIHeight / 8 * VDIPlanes;
1.1.1.14 root 168: /* Use 32 kiB in normal screen mode or when the screen size is smaller than 32 kiB */
1.1.1.7 root 169: if (!bUseVDIRes || screensize < 0x8000)
170: screensize = 0x8000;
1.1.1.17! root 171: /* mem top - upper end of user memory (right before the screen memory)
! 172: * memtop / phystop must be dividable by 512 or TOS crashes */
1.1.1.7 root 173: memtop = (STRamEnd - screensize) & 0xfffffe00;
1.1.1.17! root 174: /* phys top - 32k gap causes least issues with apps & TOS
! 175: * as that's the largest _common_ screen size. EmuTOS behavior
! 176: * depends on machine type.
! 177: *
! 178: * TODO: what to do about _native_ TT & Videl resolutions
! 179: * which size is >32k? Should memtop be adapted also for
! 180: * those?
! 181: */
! 182: switch (ConfigureParams.System.nMachineType)
! 183: {
! 184: case MACHINE_FALCON:
! 185: /* TOS v4 doesn't work with VDI mode (yet), and
! 186: * EmuTOS works with correct gap, so use that */
! 187: phystop = STRamEnd;
! 188: break;
! 189: case MACHINE_TT:
! 190: /* For correct TOS v3 memory detection, phystop should be
! 191: * at the end of memory, not at memtop + 32k.
! 192: *
! 193: * However:
! 194: * - TOS v3 crashes/hangs if phystop-memtop gap is larger
! 195: * than largest real HW screen size (150k)
! 196: * - NVDI hangs if gap is larger than 32k in any other than
! 197: * monochrome mode
! 198: */
! 199: if (VDIPlanes == 1)
! 200: limit = 1280*960/8;
! 201: else
! 202: limit = 0x8000;
! 203: if (screensize > limit)
! 204: {
! 205: phystop = memtop + limit;
! 206: fprintf(stderr, "WARNING: too large VDI mode for TOS v3 memory detection to work correctly!\n");
! 207: }
! 208: else
! 209: phystop = STRamEnd;
! 210: break;
! 211: default:
! 212: phystop = memtop + 0x8000;
! 213: }
1.1.1.7 root 214: STMemory_WriteLong(0x436, memtop);
1.1.1.17! root 215: STMemory_WriteLong(0x42e, phystop);
! 216: if (bUseVDIRes)
! 217: fprintf(stderr, "VDI mode memtop: 0x%x, phystop: 0x%x (screensize: %d kB, memtop->phystop: %d kB)\n",
! 218: memtop, phystop, (screensize+511) / 1024, (phystop-memtop+511) / 1024);
1.1.1.6 root 219:
220: /* Set memory controller byte according to different memory sizes */
221: /* Setting per bank: %00=128k %01=512k %10=2Mb %11=reserved. - e.g. %1010 means 4Mb */
222: if (ConfigureParams.Memory.nMemorySize <= 4)
223: nMemControllerByte = MemControllerTable[ConfigureParams.Memory.nMemorySize];
224: else
225: nMemControllerByte = 0x0f;
226: STMemory_WriteByte(0x424, nMemControllerByte);
227: IoMem_WriteByte(0xff8001, nMemControllerByte);
228:
1.1.1.7 root 229: if (ConfigureParams.System.nMachineType == MACHINE_FALCON)
230: {
1.1.1.13 root 231: /* Set the Falcon memory and monitor configuration register:
232:
1.1.1.15 root 233: $ffff8006.b [R] 76543210 Monitor-memory
234: ||||||||
235: |||||||+- RAM Wait Status
236: ||||||| 0 = 1 Wait (default)
237: ||||||| 1 = 0 Wait
238: ||||||+-- Video Bus size ???
239: |||||| 0 = 16 Bit
240: |||||| 1 = 32 Bit (default)
241: ||||++--- ROM Wait Status
242: |||| 00 = Reserved
243: |||| 01 = 2 Wait (default)
244: |||| 10 = 1 Wait
245: |||| 11 = 0 Wait
246: ||++----- Falcon Memory
247: || 00 = 1 MB
248: || 01 = 4 MB
249: || 10 = 14 MB
250: || 11 = no boot !
251: ++------- Monitor-Typ
252: 00 - Monochrome (SM124)
253: 01 - Color (SC1224)
254: 10 - VGA Color
255: 11 - Television
1.1.1.13 root 256:
257: Bit 1 seems not to be well documented. It's used by TOS at bootup to compute the memory size.
258: After some tests, I get the following RAM values (Bits 5, 4, 1 are involved) :
259:
260: 00 = 512 Ko 20 = 8192 Ko
261: 02 = 1024 Ko 22 = 14366 Ko
262: 10 = 2048 Ko 30 = Illegal
263: 12 = 4096 Ko 32 = Illegal
264:
265: I use these values for Hatari's emulation.
266: I also set the bit 3 and 2 at value 01 are mentioned in the register description.
267: */
268:
269: if (ConfigureParams.Memory.nMemorySize == 14) /* 14 Meg */
270: nFalcSysCntrl = 0x26;
271: else if (ConfigureParams.Memory.nMemorySize == 8) /* 8 Meg */
272: nFalcSysCntrl = 0x24;
273: else if (ConfigureParams.Memory.nMemorySize == 4) /* 4 Meg */
1.1.1.7 root 274: nFalcSysCntrl = 0x16;
1.1.1.13 root 275: else if (ConfigureParams.Memory.nMemorySize == 2) /* 2 Meg */
1.1.1.7 root 276: nFalcSysCntrl = 0x14;
1.1.1.13 root 277: else if (ConfigureParams.Memory.nMemorySize == 1) /* 1 Meg */
1.1.1.7 root 278: nFalcSysCntrl = 0x06;
279: else
1.1.1.13 root 280: nFalcSysCntrl = 0x04; /* 512 Ko */
281:
1.1.1.8 root 282: switch(ConfigureParams.Screen.nMonitorType) {
1.1.1.13 root 283: case MONITOR_TYPE_TV:
284: nFalcSysCntrl |= FALCON_MONITOR_TV;
285: break;
286: case MONITOR_TYPE_VGA:
287: nFalcSysCntrl |= FALCON_MONITOR_VGA;
288: break;
289: case MONITOR_TYPE_RGB:
290: nFalcSysCntrl |= FALCON_MONITOR_RGB;
291: break;
292: case MONITOR_TYPE_MONO:
293: nFalcSysCntrl |= FALCON_MONITOR_MONO;
294: break;
1.1.1.7 root 295: }
296: STMemory_WriteByte(0xff8006, nFalcSysCntrl);
297: }
298:
1.1.1.6 root 299: /* Set TOS floppies */
300: STMemory_WriteWord(0x446, nBootDrive); /* Boot up on A(0) or C(2) */
301:
1.1.1.16 root 302: /* Create connected drives mask (only for harddrives, don't change floppy drive detected by TOS) */
1.1.1.10 root 303: ConnectedDriveMask = STMemory_ReadLong(0x4c2); // Get initial drive mask (see what TOS thinks)
304: if (GEMDOS_EMU_ON)
1.1.1.6 root 305: {
1.1.1.10 root 306: for (i = 0; i < MAX_HARDDRIVES; i++)
307: {
308: if (emudrives[i] != NULL) // Is this GEMDOS drive enabled?
1.1.1.12 root 309: ConnectedDriveMask |= (1 << emudrives[i]->drive_number);
1.1.1.10 root 310: }
1.1.1.6 root 311: }
312: /* Set connected drives system variable.
313: * NOTE: some TOS images overwrite this value, see 'OpCode_SysInit', too */
314: STMemory_WriteLong(0x4c2, ConnectedDriveMask);
315: }
1.1.1.17! root 316:
! 317:
! 318: /**
! 319: * Check that the region of 'size' starting at 'addr' is entirely inside
! 320: * a memory bank of the same memory type
! 321: */
! 322: bool STMemory_CheckAreaType ( Uint32 addr , int size , int mem_type )
! 323: {
! 324: addrbank *pBank;
! 325:
! 326: pBank = &get_mem_bank ( addr );
! 327:
! 328: if ( ( pBank->flags & mem_type ) == 0 )
! 329: {
! 330: fprintf(stderr, "pBank flags mismatch: 0x%x & 0x%x (RAM = 0x%x)\n", pBank->flags, mem_type, ABFLAG_RAM);
! 331: return false;
! 332: }
! 333:
! 334: return pBank->check ( addr , size );
! 335: }
! 336:
! 337:
! 338: /**
! 339: * Check if an address points to a memory region that causes bus error
! 340: * This is used for blitter and other DMA chips that should not cause
! 341: * a bus error when accessing such regions (on the contrary of the CPU)
! 342: * Returns true if region gives bus error
! 343: */
! 344: bool STMemory_CheckRegionBusError ( Uint32 addr )
! 345: {
! 346: return memory_region_bus_error ( addr );
! 347: }
! 348:
! 349:
! 350: /**
! 351: * Convert an address in the ST memory space to a direct pointer
! 352: * in the host memory.
! 353: *
! 354: * NOTE : Using this function to get a direct pointer to the memory should
! 355: * only be used after doing a call to valid_address or STMemory_CheckAreaType
! 356: * to ensure we don't try to access a non existing memory region.
! 357: * Basically, this function should be used only for addr in RAM or in ROM
! 358: */
! 359: void *STMemory_STAddrToPointer ( Uint32 addr )
! 360: {
! 361: Uint8 *p;
! 362:
! 363: if ( ConfigureParams.System.bAddressSpace24 == true )
! 364: addr &= 0x00ffffff; /* Only keep the 24 lowest bits */
! 365:
! 366: p = get_real_address ( addr );
! 367: return (void *)p;
! 368: }
! 369:
! 370:
! 371:
! 372: /**
! 373: * Those functions are directly accessing the memory of the corresponding
! 374: * bank, without calling its dedicated access handlers (they won't generate
! 375: * bus errors or address errors or update IO values)
! 376: * They are only used for internal work of the emulation, such as debugger,
! 377: * log to print the content of memory, intercepting gemdos/bios calls, ...
! 378: *
! 379: * These functions are not used by the CPU emulation itself, see memory.c
! 380: * for the functions that emulate real memory accesses.
! 381: */
! 382:
! 383: /**
! 384: * Write long/word/byte into memory.
! 385: * NOTE - value will be converted to 68000 endian
! 386: */
! 387: void STMemory_Write ( Uint32 addr , Uint32 val , int size )
! 388: {
! 389: addrbank *pBank;
! 390: Uint8 *p;
! 391:
! 392: //printf ( "mem direct write %x %x %d\n" , addr , val , size );
! 393: pBank = &get_mem_bank ( addr );
! 394:
! 395: if ( pBank->baseaddr == NULL )
! 396: return; /* No real memory, do nothing */
! 397:
! 398: addr -= pBank->start & pBank->mask;
! 399: addr &= pBank->mask;
! 400: p = pBank->baseaddr + addr;
! 401:
! 402: /* We modify the memory, so we flush the instr/data caches if needed */
! 403: M68000_Flush_All_Caches ( addr , size );
! 404:
! 405: if ( size == 4 )
! 406: do_put_mem_long ( p , val );
! 407: else if ( size == 2 )
! 408: do_put_mem_word ( p , (Uint16)val );
! 409: else
! 410: *p = (Uint8)val;
! 411: }
! 412:
! 413: void STMemory_WriteLong ( Uint32 addr , Uint32 val )
! 414: {
! 415: STMemory_Write ( addr , val , 4 );
! 416: }
! 417:
! 418: void STMemory_WriteWord ( Uint32 addr , Uint16 val )
! 419: {
! 420: STMemory_Write ( addr , (Uint32)val , 2 );
! 421: }
! 422:
! 423: void STMemory_WriteByte ( Uint32 addr , Uint8 val )
! 424: {
! 425: STMemory_Write ( addr , (Uint32)val , 1 );
! 426: }
! 427:
! 428:
! 429: /**
! 430: * Read long/word/byte from memory.
! 431: * NOTE - value will be converted to 68000 endian
! 432: */
! 433: Uint32 STMemory_Read ( Uint32 addr , int size )
! 434: {
! 435: addrbank *pBank;
! 436: Uint8 *p;
! 437:
! 438: //printf ( "mem direct read %x %d\n" , addr , size );
! 439: pBank = &get_mem_bank ( addr );
! 440:
! 441: if ( pBank->baseaddr == NULL )
! 442: return 0; /* No real memory, return 0 */
! 443:
! 444: addr -= pBank->start & pBank->mask;
! 445: addr &= pBank->mask;
! 446: p = pBank->baseaddr + addr;
! 447:
! 448: if ( size == 4 )
! 449: return do_get_mem_long ( p );
! 450: else if ( size == 2 )
! 451: return (Uint32)do_get_mem_word ( p );
! 452: else
! 453: return (Uint32)*p;
! 454: }
! 455:
! 456: Uint32 STMemory_ReadLong ( Uint32 addr )
! 457: {
! 458: return (Uint32) STMemory_Read ( addr , 4 );
! 459: }
! 460:
! 461: Uint16 STMemory_ReadWord ( Uint32 addr )
! 462: {
! 463: return (Uint16)STMemory_Read ( addr , 2 );
! 464: }
! 465:
! 466: Uint8 STMemory_ReadByte ( Uint32 addr )
! 467: {
! 468: return (Uint8)STMemory_Read ( addr , 1 );
! 469: }
! 470:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.