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