mem.cpp
1 /* 2 * Castaway 3 * (C) 1994 - 2002 Martin Doering, Joachim Hoenig 4 * 5 * $File$ - memory read/write 6 * 7 * This file is distributed under the GPL, version 2 or at your 8 * option any later version. See doc/license.txt for details. 9 * 10 * revision history 11 * 23.05.2002 JH FAST1.0.1 code import: KR -> ANSI, restructuring 12 * 30.05.2002 JH Discontinued using mmap and mprotect, now using 13 * Martin's memory access jump table. 14 * 12.06.2002 JH Correct bus error/address error exception stack frame 15 * 14.06.2002 JH LowRamSetX() functions improved. 16 * 09.07.2002 JH Now loads any 192k ROM file 17 * 10.07.2002 MAD Now loads any ROM file 18 * 16.09.2002 JH Bugfix: Word access on unmapped I/O address stacked 19 * two bus error stack frames. Fault address corrected. 20 * 08.10.2002 JH Fixed integer types. 21 * 27.10.2002 AG Trashed everything for more speed! mwuhahaha! 22 */ 23 24 #include <stdio.h> 25 #include <stdlib.h> 26 #include <malloc.h> 27 #ifndef DREAMCAST 28 #else 29 #include <string.h> 30 #endif 31 32 #include "dcastaway.h" 33 #include "st.h" 34 #include "mem.h" 35 #include "m68k_intrf.h" 36 37 #include <Arduino.h> 38 39 static unsigned rombase_pos=0; 40 41 char rom[80]; // = ROM; 42 #ifdef DREAMCAST 43 void reinit_sdcard(void); 44 char rom_sd[24] = ROM_SD; 45 #endif 46 static int samvol[16]={0,0,0,1,1,1,2,3,5,7,11,17,25,38,57,85}; 47 extern uint32 psg[26]; 48 #define lastpsg psg[25] 49 #define sampos psg[24] 50 51 52 53 PROGMEM char GetMemB(unsigned long address) 54 { 55 address &= MEMADDRMASK; 56 if (address<MEMSIZE) 57 return ReadB(address + membase); 58 else 59 if (address<ROMBASE2) 60 return -1; 61 else 62 if (address<IOBASE) 63 return ReadB(address + rombase); 64 else 65 if (address<IOBASE+IOSIZE) 66 return DoIORB(address); 67 return -1; 68 } 69 70 /* Fetch word, address may not be word-aligned */ 71 PROGMEM short GetMemW(unsigned long address) 72 { 73 #ifdef CHKADDRESSERR 74 address &= MEMADDRMASK; 75 if (address & 0x1){ 76 ExceptionGroup0(ADDRESSERR, address, 1); 77 return -1; 78 } 79 #else 80 address &= MEMADDRMASKS; 81 #endif 82 if (address<MEMSIZE) 83 return ReadW(address + membase); 84 else 85 if (address<ROMBASE2) 86 return -1; 87 else 88 if (address<IOBASE) 89 return ReadW(address + rombase); 90 else 91 if (address<IOBASE+IOSIZE) 92 return DoIORW(address); 93 return -1; 94 } 95 96 /* Fetch dword, address may not be dword-aligned */ 97 PROGMEM long GetMemL(unsigned long address) 98 { 99 #ifdef CHKADDRESSERR 100 address &= MEMADDRMASK; 101 if (address & 0x1){ 102 ExceptionGroup0(ADDRESSERR, address, 1); 103 return -1; 104 } 105 #else 106 address &= MEMADDRMASKS; 107 #endif 108 if (address<MEMSIZE) 109 return ReadL(address + membase); 110 else 111 if (address<ROMBASE2) 112 return -1; 113 if (address<IOBASE) 114 return ReadL(address + rombase); 115 if (address<IOBASE+IOSIZE) 116 return DoIORL(address); 117 return -1; 118 } 119 120 121 /* Write byte to address */ 122 PROGMEM void SetMemB (unsigned long address, unsigned char value) 123 { 124 address &= MEMADDRMASK; 125 ON_WRITE(address, value); 126 if (address<MEMSIZE) { 127 //RAM 128 if (address<SVADDR && !GetFC2()){ 129 ExceptionGroup0(BUSERR, address, 0); 130 return; 131 } 132 WriteB(address + membase, value); 133 return; 134 } 135 if (address>=IOBASE && address<IOBASE+IOSIZE) { 136 //IO 137 DoIOWB(address, value); 138 return; 139 } 140 //Unmapped 141 ON_UNMAPPED(address, value); 142 } 143 144 /* Write word, address may not be word-aligned */ 145 PROGMEM void SetMemW(unsigned long address, unsigned short value) 146 { 147 #ifdef CHKADDRESSERR 148 address &= MEMADDRMASK; 149 if (address & 0x1){ 150 ExceptionGroup0(ADDRESSERR, address, 1); 151 return; 152 } 153 #else 154 address &= MEMADDRMASKS; 155 #endif 156 ON_WRITE(address, value); 157 if (address<MEMSIZE) { 158 //RAM 159 if (address<SVADDR ){ 160 if (!GetFC2()||address<8){ 161 ExceptionGroup0(BUSERR, address, 0); 162 return; 163 } 164 } 165 WriteW(address + membase, value); 166 return; 167 } 168 if (address>=IOBASE && address<IOBASE+IOSIZE) { 169 //IO 170 DoIOWW(address, value); 171 return; 172 } 173 //Unmapped 174 ON_UNMAPPED(address, value); 175 } 176 177 /* Write dword, address may not be dword-aligned */ 178 PROGMEM void SetMemL(unsigned long address, unsigned long value) 179 { 180 #ifdef CHKADDRESSERR 181 address &= MEMADDRMASK; 182 if (address & 0x1){ 183 ExceptionGroup0(ADDRESSERR, address, 1); 184 return; 185 } 186 #else 187 address &= MEMADDRMASKS; 188 #endif 189 190 ON_WRITE(address, value); 191 if (address<MEMSIZE) { 192 //RAM 193 if (address<SVADDR){ 194 if (!GetFC2()||address<8){ 195 ExceptionGroup0(BUSERR, address, 0); 196 return; 197 } 198 } 199 #ifdef OPTIMIZE_VMEM 200 if ( (address >= vid_mem) && (address < (vid_mem+32768) ) ) { 201 printf("vwlmem\n"); 202 WriteL(&videobuf[address-vid_mem], value); 203 } 204 else 205 #endif 206 WriteL(address + membase, value); 207 return; 208 } 209 if (address>=IOBASE && address<IOBASE+IOSIZE) { 210 //IO 211 DoIOWL(address, value); 212 return; 213 } 214 //Unmapped 215 ON_UNMAPPED(address, value); 216 } 217 218 219 220 221 #ifdef UNUSED 222 223 224 //Simplifed versions of memory access commands used for instructions fetch 225 //Instruction fetch is likely only to be from ram or rom, otherwise the 226 //program will surely have crashed anyway! 227 228 char GetMemBpc(unsigned long address) 229 { 230 address &= MEMADDRMASK; 231 if (address<MEMSIZE) return ReadB(address + membase); 232 else return ReadB(address + rombase); 233 } 234 235 short GetMemWpc(unsigned long address) 236 { 237 address &= MEMADDRMASK; 238 if (address<MEMSIZE) return ReadW(address + membase); 239 else return ReadW(address + rombase); 240 } 241 242 /* Fetch dword, address may not be dword-aligned */ 243 long GetMemLpc(unsigned long address) 244 { 245 address &= MEMADDRMASK; 246 if (address<MEMSIZE) return ReadL(address + membase); 247 else return ReadL(address + rombase); 248 } 249 250 //Movep support 251 //------------- 252 253 void SetMemPW(unsigned long address, unsigned long value) 254 { 255 // int8 psgctrl1,value1; 256 257 if (address&0xffff03==0xff8800) { 258 uint32 psgctrl1=(value>>8)&15; 259 uint32 value1=value&255; 260 psg[psgctrl1]=value1; 261 if (psgctrl1==lastpsg) sample[sampos++]=samvol[psg[8]]+samvol[psg[9]]+samvol[value1]; 262 else if (psgctrl1==13 || psgctrl1==12) psg_epos=0; 263 return; 264 } 265 address &= MEMADDRMASK; 266 if (address>=IOBASE && address<IOBASE+IOSIZE) { 267 //IO 268 DoIOWB(address, (int8)(value>>8)); 269 DoIOWB(address+2, (int8)value); 270 return; 271 } 272 if (address<MEMSIZE) { 273 //RAM 274 if (address<SVADDR && !GetFC2()) ExceptionGroup0(BUSERR, address, 0); 275 address+=(uint32)membase; 276 WriteB(address, (int8)(value>>8)); 277 WriteB(address+2, (int8)value); 278 return; 279 } 280 } 281 282 void SetMemPL(unsigned long address, unsigned long value) 283 {// int8 psgctrl1,psgctrl2,value1,value2; 284 285 if (address&0xffff03==0xff8800) { 286 uint32 psgctrl1=(value>>24)&15; 287 uint32 value1=(value>>16)&255; 288 psg[psgctrl1]=value1; 289 if (psgctrl1==lastpsg) sample[sampos++]=samvol[psg[8]]+samvol[psg[9]]+samvol[value1]; 290 else if (psgctrl1==13 || psgctrl1==12) psg_epos=0; 291 psgctrl1=(value>>8)&15; 292 value1=value&255; 293 if (psgctrl1==lastpsg) sample[sampos++]=samvol[psg[8]]+samvol[psg[9]]+samvol[value1]; 294 else if (psgctrl1==13 || psgctrl1==12) psg_epos=0; 295 return; 296 } 297 address &= MEMADDRMASK; 298 if (address>=IOBASE && address<IOBASE+IOSIZE) { 299 //IO 300 DoIOWB(address, (int8)(value>>24)); 301 DoIOWB(address+2, (int8)(value>>16)); 302 DoIOWB(address+4, (int8)(value>>8)); 303 DoIOWB(address+6, (int8)value); 304 return; 305 } 306 if (address<MEMSIZE) { 307 //RAM 308 if (address<SVADDR && !GetFC2()) ExceptionGroup0(BUSERR, address, 0); 309 address+=(uint32)membase; 310 WriteB(address, (int8)(value>>24)); 311 WriteB(address+2, (int8)(value>>16)); 312 WriteB(address+4, (int8)(value>>8)); 313 WriteB(address+6, (int8)value); 314 return; 315 } 316 } 317 318 319 320 static void *__rombase=NULL, *__membase=NULL; 321 322 void MemQuit(void) 323 { 324 if (__membase) 325 free(__membase); 326 __membase=NULL; 327 if (__rombase) 328 free(__rombase); 329 __rombase=NULL; 330 } 331 332 static void _set_dword(void *buf,unsigned dat) 333 { 334 unsigned short *b=(unsigned short *)buf; 335 *b++=dat&0xffff; 336 *b=dat>>16; 337 } 338 339 void MemClean(void) 340 { 341 membase=(int8*)__membase; 342 memset(membase,0,MEMSIZE); 343 //savestate_init(); 344 memcpy (membase, ((int8*)__rombase)+rombase_pos, 8); 345 346 _set_dword(membase+0x420,0x752019f3); 347 _set_dword(membase+0x43a,0x237698aa); 348 _set_dword(membase+0x51a,0x5555aaaa); 349 #if MEMSIZE==0x00080000 350 _set_dword(membase+0x436,0x80000-0x8000); 351 _set_dword(membase+0x42e,0x80000); 352 WriteB(membase+0x425,1); 353 WriteB(rombase+0xff8000,1); 354 memconf=1; 355 #else 356 #if MEMSIZE==0x00100000 357 _set_dword(membase+0x436,0x100000-0x8000); 358 _set_dword(membase+0x42e,0x100000); 359 WriteB(membase+0x425,5); 360 WriteB(rombase+0xff8000,5); 361 memconf=5; 362 #else 363 #if MEMSIZE==0x00200000 364 _set_dword(membase+0x436,0x200000-0x8000); 365 _set_dword(membase+0x42e,0x200000); 366 WriteB(membase+0x425,2); 367 WriteB(rombase+0xff8000,2); 368 memconf=2; 369 #else 370 #if MEMSIZE==0x00400000 371 _set_dword(membase+0x436,0x400000-0x8000); 372 _set_dword(membase+0x42e,0x400000); 373 WriteB(membase+0x425,0xA); 374 WriteB(rombase+0xff8000,0xA); 375 memconf=0xA; 376 #else 377 #error DCaSTaway ERROR: MEMSIZE incorrect. 378 #endif 379 #endif 380 #endif 381 #endif 382 _set_dword(membase+0x4c2,3); 383 WriteW(membase+0x4a6,2); 384 385 //if (TosCountry) 386 // vid_syncmode=2; 387 //else 388 // vid_syncmode=0; 389 } 390 391 392 static unsigned actual_rom_crc=0; 393 394 static unsigned rom_checksum(void) 395 { 396 int n; 397 unsigned crc=0; 398 for(n=ROMBASE2;n<MEMADDRSIZE;n++) 399 crc+=(n+1)*rombase[n]; 400 return crc; 401 } 402 403 void MemReInit(void) 404 { 405 unsigned crc=rom_checksum(); 406 if (crc!=actual_rom_crc) 407 MemInit(); 408 else 409 MemClean(); 410 } 411 412 PROGMEM int MemInit(void) 413 { 414 int n; 415 uint8 val1,val2; 416 unsigned long len; 417 FILE *roms; 418 419 //Load ROM 420 if (NULL == (roms = fopen (rom, "rb"))) { 421 #ifdef DREAMCAST 422 reinit_sdcard(); 423 if (NULL == (roms = fopen (rom_sd, "rb"))) 424 #endif 425 { 426 if (__membase) 427 memset(__membase,0,MEMSIZE); 428 return 1; 429 } 430 } 431 MemQuit(); 432 fseek(roms,0,SEEK_END); 433 len=(unsigned long)ftell(roms); 434 fseek(roms,0,SEEK_SET); 435 if (len>(MEMADDRSIZE-ROMBASE2)) 436 len=(MEMADDRSIZE-ROMBASE2); 437 if (len<=(192*1024)) 438 rombase_pos=ROMBASE-ROMBASE2; 439 else 440 rombase_pos=0; 441 442 if (!__rombase) 443 __rombase = calloc(1,MEMADDRSIZE-ROMBASE2); 444 rombase=(int8*)__rombase; 445 for(n=0;n<(MEMADDRSIZE-ROMBASE2);n+=2) 446 { 447 rombase[n]=0x4e; 448 rombase[n+1]=0x71; 449 } 450 if (len != fread(rombase+rombase_pos,1,len,roms)) 451 { 452 fclose(roms); 453 return 2; 454 } 455 fclose (roms); 456 #ifdef BYTES_SWAP 457 for (n=0; n<(MEMADDRSIZE-ROMBASE2); n+=2) { 458 val1 = rombase[n]; 459 val2 = rombase[n+1]; 460 rombase[n] = val2; 461 rombase[n+1] =val1; 462 } 463 #endif 464 /* precalculate rombase - now just address-adding happens later */ 465 if (rombase_pos) 466 { 467 rombase -= ROMBASE2+rombase_pos-(ROMBASE-ROMBASE2); 468 memcpy(rombase+ROMBASE2,rombase+ROMBASE,(MEMADDRSIZE-ROMBASE)); 469 } 470 else 471 { 472 rombase -= ROMBASE2; 473 memcpy(rombase+ROMBASE,rombase+ROMBASE2,(MEMADDRSIZE-ROMBASE)); 474 } 475 476 TOS_FixRom((uint8 *)(((int8*)__rombase)+rombase_pos)); 477 478 //Allocate and clear RAM 479 if (!__membase) 480 __membase = (int8*)calloc(1,MEMSIZE+0x10); 481 MemClean(); 482 actual_rom_crc=rom_checksum(); 483 initialize_memmap(); 484 return 0; 485 } 486 #endif