/****************************************************************************/ /* Beebem - (c) David Alan Gilbert 1994 */ /* ------------------------------------ */ /* This program may be distributed freely within the following restrictions:*/ /* */ /* 1) You may not charge for this program or for any part of it. */ /* 2) This copyright message must be distributed with all copies. */ /* 3) This program must be distributed complete with source code. Binary */ /* only distribution is not permitted. */ /* 4) The author offers no warrenties, or guarentees etc. - you use it at */ /* your own risk. If it messes something up or destroys your computer */ /* thats YOUR problem. */ /* 5) You may use small sections of code from this program in your own */ /* applications - but you must acknowledge its use. If you plan to use */ /* large sections then please ask the author. */ /* */ /* If you do not agree with any of the above then please do not use this */ /* program. */ /* Please report any problems to the author at gilbertd@cs.man.ac.uk */ /****************************************************************************/ /* Beebemulator - memory subsystem - David Alan Gilbert 16/10/94 */ ///#include #include #include #include #include "iostream.h" #include "6502core.h" #include "disc8271.h" #include "main.h" #include "sysvia.h" #include "uservia.h" #include "video.h" void error(char *t1,char *t2); static int PagedRomReg; static int RomModified=0; /* Rom changed - needs copying back */ unsigned char WholeRam[65536]; static unsigned char Roms[16][16384]; /*----------------------------------------------------------------------------*/ /* Perform hardware address wrap around */ static unsigned int WrapAddr(int in) { unsigned int offsets[]={0x4000,0x6000,0x3000,0x5800}; if (in<0x8000) return(in); in+=offsets[(IC32State & 0x30)>>4]; in&=0x7fff; return(in); }; /* WrapAddr */ /*----------------------------------------------------------------------------*/ /* This is for the use of the video routines. It returns a pointer to a continuous area of 'n' bytes containing the contents of the 'n' bytes of beeb memory starting at address 'a', with wrap around at 0x8000. Potentially this routine may return a pointer into a static buffer - so use the contents before recalling it 'n' must be less than 1K in length. See 'BeebMemPtrWithWrapMo7' for use in Mode 7 - its a special case. */ char *BeebMemPtrWithWrap(int a, int n) { static char tmpBuf[1024]; char *tmpBufPtr; int EndAddr=a+n-1; int toCopy; a=WrapAddr(a); EndAddr=WrapAddr(EndAddr); if (a<=EndAddr) { return((char *)WholeRam+a); }; toCopy=0x8000-a; if (toCopy>n) toCopy=n; if (toCopy>0) memcpy(tmpBuf,WholeRam+a,toCopy); tmpBufPtr=tmpBuf+toCopy; toCopy=n-toCopy; if (toCopy>0) memcpy(tmpBufPtr,WholeRam+EndAddr-(toCopy-1),toCopy); /* Should that -1 be there ? */ return(tmpBuf); }; /* BeebMemPtrWithWrap */ /*----------------------------------------------------------------------------*/ /* Perform hardware address wrap around - for mode 7*/ static unsigned int WrapAddrMo7(int in) { if (in<0x8000) return(in); in+=0x7c00; in&=0x7fff; return(in); }; /* WrapAddrMo7 */ /*----------------------------------------------------------------------------*/ /* Special case of BeebMemPtrWithWrap for use in mode 7 */ char *BeebMemPtrWithWrapMo7(int a, int n) { static char tmpBuf[1024]; char *tmpBufPtr; int EndAddr=a+n-1; int toCopy; a=WrapAddrMo7(a); EndAddr=WrapAddrMo7(EndAddr); if (a<=EndAddr) { return((char *)WholeRam+a); }; toCopy=0x8000-a; if (toCopy>n) return((char *)WholeRam+a); if (toCopy>0) memcpy(tmpBuf,WholeRam+a,toCopy); tmpBufPtr=tmpBuf+toCopy; toCopy=n-toCopy; if (toCopy>0) memcpy(tmpBufPtr,WholeRam+EndAddr-(toCopy-1),toCopy); /* Should that -1 be there ? */ return(tmpBuf); }; /* BeebMemPtrWithWrapMo7 */ /*----------------------------------------------------------------------------*/ int BeebReadMem(int Address) { static int extracycleprompt=0; /* We now presume that the caller has checked to see if the address is below fc00 and if so does a direct read */ /* if (Address<0xfc00) return(WholeRam[Address]); */ if (Address>=0xff00) return(WholeRam[Address]); Cycles++; extracycleprompt++; if (extracycleprompt & 8) Cycles++; /* OK - its IO space - lets check some system devices */ /* VIA's first - games seem to do really heavy reaing of these */ if ((Address & ~0xf)==0xfe40) return(SysVIARead(Address & 0xf)); if ((Address & ~0xf)==0xfe60) return(UserVIARead(Address & 0xf)); if ((Address & ~7)==0xfe00) return(CRTCRead(Address & 0x7)); if ((Address & ~0xf)==0xfe20) return(VideoULARead(Address & 0xf)); if ((Address & ~0x1f)==0xfe80) return(Disc8271_read(Address & 0x7)); if ((Address & ~0x1f)==0xfea0) return(0xfe); /* Disable econet */ if ((Address & ~0x1f)==0xfee0) return(0xfe); /* Disable tube */ return(0); } /* BeebReadMem */ /*----------------------------------------------------------------------------*/ static void DoRomChange(int NewBank) { /* Speed up hack - if we are switching to the same rom, then don't bother */ if (NewBank==PagedRomReg) return; if (RomModified) { memcpy(Roms[PagedRomReg],WholeRam+0x8000,0x4000); RomModified=0; }; PagedRomReg=NewBank; memcpy(WholeRam+0x8000,Roms[PagedRomReg],0x4000); }; /* DoRomChange */ /*----------------------------------------------------------------------------*/ void BeebWriteMem(int Address, int Value) { static int extracycleprompt=0; /* fprintf(stderr,"Write %x to 0x%x\n",Value,Address); */ /* Now we presume that the caller has validated the address as beingwithin main ram and hence the following line is not required */ /*if (Address<0x8000) { WholeRam[Address]=Value; return; } */ if (Address<0xc000) { WholeRam[Address]=Value; RomModified=1; return; } Cycles++; extracycleprompt++; if (extracycleprompt & 8) Cycles++; if ((Address>=0xfc00) && (Address<=0xfeff)) { /* Check for some hardware */ if ((Address & ~0xf)==0xfe20) { VideoULAWrite(Address & 0xf, Value); return; } if ((Address & ~0xf)==0xfe40) { SysVIAWrite((Address & 0xf),Value); return; } if ((Address & ~0xf)==0xfe60) { UserVIAWrite((Address & 0xf),Value); return; } if (Address==0xfe30) { DoRomChange(Value & 0xf); return; } /*cerr << "Write *0x" << hex << Address << "=0x" << Value << dec << "\n"; */ if ((Address & ~0x7)==0xfe00) { CRTCWrite(Address & 0x7, Value); return; } if ((Address & ~0x1f)==0xfe80) { Disc8271_write((Address & 7),Value); return; } if (Address==0xfc01) exit(0); return; } } /*----------------------------------------------------------------------------*/ static void ReadRom(char *name,int bank) { FILE *InFile; char fullname[256]; strcpy(fullname,name); if (InFile=fopen(fullname,"rb"),InFile==NULL) { error("Could not open rom file ",name); } if (fread(Roms[bank],1,16384,InFile)!=16384) { error("Could not read rom file ",name); } fclose(InFile); } /* ReadRom */ /*----------------------------------------------------------------------------*/ void BeebMemInit(void) { FILE *InFile; // HANDLE InFile; // DWORD read; ReadRom("basic",0xf); // ReadRom("test.rom",0xe); /* ReadRom("memdump_bottom",0x4); ReadRom("memdump_top",0x5); */ ReadRom("dnfs",0); /* Load OS */ if (InFile=fopen("os12","rb"),InFile==NULL) { // fprintf(stderr,"Could not open OS rom file\n"); //abort(); $NRM dunno why this fails error("Rom file os12 not found",""); } if (fread(WholeRam+0xc000,1,16384,InFile)!=16384) { // fprintf(stderr,"Could not read OS\n"); //abort(); error("Rom file os12 read fail",""); } fclose(InFile); /* Put first ROM in */ memcpy(WholeRam+0x8000,Roms[0xf],0x4000); PagedRomReg=0xf; RomModified=0; } /* BeebMemInit */ /* dump the contents of mainram into 2 16 K files */ void beebmem_dumpstate(void) { FILE *bottom,*top; bottom=fopen("memdump_bottom","wb"); top=fopen("memdump_top","wb"); if ((bottom==NULL) || (top==NULL)) { cerr << "Couldn't open memory dump files\n"; return; }; fwrite(WholeRam,1,16384,bottom); fwrite(WholeRam+16384,1,16384,top); fclose(bottom); fclose(top); }; /* beebmem_dumpstate */