home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AmigActive 6
/
AACD06.ISO
/
AACD
/
Emulation
/
Atari800
/
mem.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-02-17
|
15KB
|
846 lines
/*******************************************************
** mem.h **
** Memory-Handler **
** Speicherzugriffe, RAM,ROM,Hardware **
*******************************************************/
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include "mem.h"
#include "atari.h"
#ifndef O_BINARY
#define O_MODE O_RDONLY
#else
#define O_MODE (O_RDONLY | O_BINARY)
#endif
#ifdef VMS
#include <unixio.h>
#include <file.h>
#else
#include <fcntl.h>
#endif
mtype memory[65536];
mtype *XE_Banks[5]; /* #5 is a temporary buffer */
MemGet mget[65536];
MemPut mput[65536];
static struct Cart *current=NULL; /* currently inserted LEFT cartridge */
static struct Cart *basic=NULL; /* XL,XE basic */
static struct Cart *os=NULL; /* main OS, 0xe000,0xffff */
static struct Cart *mpack=NULL; /* math pack, 0xd800,0xdfff */
static struct Cart *os_x=NULL; /* XL OS extension 0xc000,0xcfff */
static struct Cart *selftest=NULL; /* XL selftest 0xd000,0xd7ff */
static int basic_on=FALSE;
static char *rcsid = "$Id: mem.c,v 1.00 1998/02/17 thor";
static struct Cart *ReadCart(char *filename, int fd,int addr, int nbytes);
mtype NoGet(void)
{
return ~0;
}
int NoPut(mtype byte)
{
return 0;
}
void SetRAM(int lower,int upper)
{
int i;
for(i=lower;i<=upper;i++) {
mput[i] = NULL;
mget[i] = NULL;
}
}
void SetROM(int lower,int upper)
{
int i;
for(i=lower;i<=upper;i++) {
mput[i] = &NoPut;
mget[i] = NULL;
}
}
void SetHW(int addr,int mask,MemGet read,MemPut write)
{
int i;
int lo,hi;
lo = addr & 0xff00;
hi = lo + 0x100;
for(i=lo;i<hi;i++) {
if ((i & mask)==addr) {
if (read) mget[i] = read;
else mget[i] = &NoGet;
if (write) mput[i] = write;
else mput[i] = &NoPut;
}
}
}
void SetBlank(int lower,int upper)
{
int i;
for(i=lower;i<=upper;i++) {
mget[i] = &NoGet;
mput[i] = &NoPut;
}
}
void EnablePILL (void)
{
SetROM (0x8000, 0xbfff);
}
void CopyFromMem(ATPtr from,UBYTE *to,int size)
{
memcpy(to,from+memory,size);
}
void CopyToMem(UBYTE *from,ATPtr to,int size)
{
int i;
for(i=0;i<size;i++) {
Poke(to,*from);
from++,to++;
}
}
struct Cart *AllocCart(int size)
{
struct Cart *ct;
int i;
if ((ct=malloc(sizeof(struct Cart)))!=0) {
if ((ct->image=malloc(size*sizeof(mtype)))!=0) {
if ((ct->saveback=malloc(size*sizeof(mtype)))!=0) {
ct->type = 0;
ct->active = FALSE;
ct->num_secs = 1; /* Defaults to one section */
for (i=0;i<0x4;i++) {
ct->secs[i].lo = ct->secs[i].hi = 0;
ct->secs[i].offset = 0;
ct->secs[i].active = FALSE;
}
ct->secs[0].active = TRUE; /* section zero is active by default */
return ct;
}
free(ct->image);
}
free(ct);
}
return NULL;
}
void FreeCart(struct Cart *ct)
{
if (ct) {
if (ct->image)
free(ct->image);
if (ct->saveback)
free(ct->saveback);
free(ct);
}
}
static int ReadImage(int fd,mtype *to,int nbytes)
{
UBYTE *buffer,*ptr;
int i;
int status=0;
if ((buffer=malloc(nbytes*sizeof(UBYTE)))!=0) {
if (read(fd,buffer,nbytes)==nbytes) {
for(i=0,ptr=buffer;i<nbytes;i++,ptr++,to++)
*to=*ptr;
status = 1;
}
free(buffer);
}
return status;
}
int Read5200Rom(char *filename,int fd)
{
int fdo = -1;
int status = 0;
if ((os=AllocCart(0xffff-0xf800+1))!=0) {
if (filename) {
fd = fdo = open(filename, O_MODE, 0777);
}
if (fd >= 0) {
if (ReadImage(fd,os->image,0xffff-0xf800+1)) {
status = 1;
}
}
}
if (fdo >= 0)
close(fdo);
if (status) {
os->secs[0].lo=0xf800;
os->secs[0].hi=0xffff;
return TRUE;
}
if (verbose)
perror(filename);
FreeCart(os);
os=NULL;
return FALSE;
}
int ReadOSABRom(char *filename,int fd)
{
int fdo = -1;
int status = 0;
if ((os=AllocCart(0xffff-0xe000+1))!=0) {
if ((mpack=AllocCart(0xdfff-0xd800+1))!=0) {
if (filename) {
fd = fdo = open(filename, O_MODE, 0777);
}
if (fd >= 0) {
if (ReadImage(fd,mpack->image,0xdfff-0xd800+1)) {
if (ReadImage(fd,os->image,0xffff-0xe000+1)) {
status = 1;
}
}
}
}
}
if (fdo >= 0)
close(fdo);
if (status) {
os->secs[0].lo=0xe000;
os->secs[0].hi=0xffff;
mpack->secs[0].lo=0xd800;
mpack->secs[0].hi=0xdfff;
return TRUE;
}
if (verbose)
perror(filename);
FreeCart(os);
FreeCart(mpack);
os=mpack=NULL;
return FALSE;
}
int ReadXLRom(char *filename,int fd)
{
int fdo = -1;
int status = 0;
if ((os=AllocCart(0xffff-0xe000+1))!=0) {
if ((mpack=AllocCart(0xdfff-0xd800+1))!=0) {
if ((os_x=AllocCart(0xcfff-0xc000+1))!=0) {
if ((selftest=AllocCart(0xd7ff-0xd000+1))!=0) {
if (filename) {
fd = fdo = open(filename, O_MODE, 0777);
}
if (fd>=0) {
if (ReadImage(fd,os_x->image,0xcfff-0xc000+1)) {
if (ReadImage(fd,selftest->image,0xd7ff-0xd000+1)) {
if (ReadImage(fd,mpack->image,0xdfff-0xd800+1)) {
if (ReadImage(fd,os->image,0xffff-0xe000+1)) {
status = 1;
}
}
}
}
}
}
}
}
}
if (fdo>=0)
close(fdo);
if (status) {
os->secs[0].lo=0xe000;
os->secs[0].hi=0xffff;
mpack->secs[0].lo=0xd800;
mpack->secs[0].hi=0xdfff;
selftest->secs[0].lo=0x5000;
selftest->secs[0].hi=0x57ff;
os_x->secs[0].lo=0xc000;
os_x->secs[0].hi=0xcfff;
return TRUE;
}
if (verbose)
perror(filename);
FreeCart(os);
FreeCart(mpack);
FreeCart(os_x);
FreeCart(selftest);
os=mpack=os_x=selftest=NULL;
return FALSE;
}
int ReadBasic(char *filename,int fd)
{
struct Cart *ct;
if ((ct=ReadCart(filename,fd,0xa000,0xbfff-0xa000+1))!=0) {
basic=ct;
return TRUE;
}
return FALSE;
}
/*
* Load a standard 8K ROM from the specified file
*/
int Insert_8K_ROM (char *filename,int fd)
{
struct Cart *ct;
if ((ct=ReadCart(filename,fd,0xa000,0xbfff-0xa000+1))!=0) {
ct->type = NORMAL8_CART;
RemoveCurrent();
InsertCart(ct);
return TRUE;
}
return FALSE;
}
/*
* Load a standard 16K ROM from the specified file
*/
int Insert_16K_ROM (char *filename,int fd)
{
struct Cart *ct;
if ((ct=ReadCart(filename,fd,0x8000,0xbfff-0x8000+1))!=0) {
ct->type = NORMAL16_CART;
RemoveCurrent();
InsertCart(ct);
return TRUE;
}
return FALSE;
}
/*
* Load an OSS Supercartridge from the specified file
* The OSS cartridge is a 16K bank switched cartridge
* that occupies 8K of address space between $a000
* and $bfff
*/
int Insert_OSS_ROM (char *filename,int fd)
{
struct Cart *ct;
if ((ct=ReadCart(filename,fd,0x8000,0xbfff-0x8000+1))!=0) {
ct->type = OSS_SUPERCART;
ct->secs[0].lo = 0xa000;
ct->secs[0].hi = 0xafff;
ct->secs[1].lo = 0xa000;
ct->secs[1].hi = 0xafff;
ct->secs[1].offset = 0x1000;
ct->secs[2].lo = 0xa000;
ct->secs[2].hi = 0xafff;
ct->secs[2].offset = 0x2000;
ct->secs[3].lo = 0xb000;
ct->secs[3].hi = 0xbfff;
ct->secs[3].offset = 0x3000;
ct->secs[3].active = TRUE;
RemoveCurrent();
InsertCart(ct);
return TRUE;
}
return FALSE;
}
/*
* Load a DB Supercartridge from the specified file
* The DB cartridge is a 32K bank switched cartridge
* that occupies 16K of address space between $8000
* and $bfff
*/
int Insert_DB_ROM (char *filename,int fd)
{
struct Cart *ct;
if ((ct=ReadCart(filename,fd,0x2000,0xbfff-0x2000+1))!=0) {
ct->type = DB_SUPERCART;
ct->secs[0].lo = 0x8000;
ct->secs[0].hi = 0x9fff;
ct->secs[1].lo = 0x8000;
ct->secs[1].hi = 0x9fff;
ct->secs[1].offset = 0x2000;
ct->secs[2].lo = 0x8000;
ct->secs[2].hi = 0x9fff;
ct->secs[2].offset = 0x4000;
ct->secs[3].lo = 0xa000;
ct->secs[3].hi = 0xbfff;
ct->secs[3].offset = 0x6000;
ct->secs[3].active = TRUE;
RemoveCurrent();
InsertCart(ct);
return TRUE;
}
return FALSE;
}
/*
* Load a 32K 5200 ROM from the specified file
*
* still to be checked
*/
int Insert_32K_5200ROM (char *filename,int fd)
{
struct Cart *ct;
if ((ct=ReadCart(filename,fd,0x4000,0xbfff-0x4000+1))!=0) {
ct->type = AGS32_CART;
RemoveCurrent();
InsertCart(ct);
return TRUE;
}
return FALSE;
}
int Insert_16K_5200ROM (char *filename,int fd)
{
struct Cart *ct;
if ((ct=ReadCart(filename,fd,0x4000,0x7fff-0x4000+1))!=0) {
ct->type = AGS16_CART;
/* setup the magic mirroring. Invalidates RAM saveback, but who cares...
the 5200 doesn't have RAM there anyways */
ct->secs[0].lo = 0x4000;
ct->secs[0].hi = 0x5fff;
ct->secs[0].offset = 0x0000;
ct->secs[0].active = TRUE;
ct->secs[1].lo = 0x8000;
ct->secs[1].hi = 0x9fff;
ct->secs[1].offset = 0x2000;
ct->secs[1].active = TRUE;
ct->secs[2].lo = 0xa000;
ct->secs[2].hi = 0xbfff;
ct->secs[2].offset = 0x2000;
ct->secs[2].active = TRUE;
ct->secs[3].lo = 0x6000;
ct->secs[3].hi = 0x7fff;
ct->secs[3].offset = 0x0000;
ct->secs[3].active = TRUE;
RemoveCurrent();
InsertCart(ct);
return TRUE;
}
return FALSE;
}
static struct Cart *ReadCart(char *filename, int fd,int addr, int nbytes)
{
struct Cart *ct;
int fdo = -1;
int status=0;
if ((ct=AllocCart(nbytes))!=0) {
if (filename) {
fd = fdo = open(filename, O_MODE,0777);
}
if (fd>=0) {
status = ReadImage(fd,ct->image,nbytes);
}
}
if (fdo>=0)
close(fdo);
if (status) {
ct->secs[0].lo = addr;
ct->secs[0].hi = addr+nbytes-1;
return ct;
}
if (verbose)
perror(filename);
FreeCart(ct);
return NULL;
}
int lof(char *filename)
{
struct stat buf;
if (stat(filename,&buf)==0) {
return buf.st_size;
}
if (verbose)
perror(filename);
return -1;
}
static void DisableCart(struct Cart *ct)
{
int i;
if (ct) {
if (ct->active) {
for(i=0;i<4;i++) {
if (ct->secs[i].active) {
memcpy(memory+ct->secs[i].lo,ct->saveback+ct->secs[i].offset,(ct->secs[i].hi-ct->secs[i].lo+1)*sizeof(mtype));
SetRAM(ct->secs[i].lo,ct->secs[i].hi);
#ifdef DEBUG
printf("Disabling a cart between %x and %x\n",ct->secs[i].lo,ct->secs[i].hi);
#endif
}
}
ct->active = FALSE;
}
}
}
static void EnableCart(struct Cart *ct)
{
int i;
int len;
if (ct) {
if (!(ct->active)) {
for(i=0;i<4;i++) {
if (ct->secs[i].active) {
len = (ct->secs[i].hi-ct->secs[i].lo+1)*sizeof(mtype);
memcpy(ct->saveback+ct->secs[i].offset,memory+ct->secs[i].lo,len);
memcpy(memory+ct->secs[i].lo,ct->image+ct->secs[i].offset,len);
SetROM(ct->secs[i].lo,ct->secs[i].hi);
#ifdef DEBUG
printf("Enabling a cart between %x and %x\n",ct->secs[i].lo,ct->secs[i].hi);
#endif
}
}
ct->active=TRUE;
}
}
}
void ChangeMapping(int map0,int map1,int map2, int map3)
{
struct Cart *ct=current;
if (ct) {
/* first, remove all images */
if (!(ct->active)) {
if (basic_on) {
DisableCart(basic); /* if it wasn't active before, we've to turn the
basic off */
}
} else DisableCart(ct);
ct->active = TRUE; /* enables cartridge as well */
ct->secs[0].active = map0;
ct->secs[1].active = map1;
ct->secs[2].active = map2;
ct->secs[3].active = map3;
EnableCart(ct);
}
}
void RemoveCart(void)
{
DisableCart(current);
current = NULL;
if (basic_on)
EnableCart(basic);
}
void RemoveCurrent(void)
{
struct Cart *old=current;
if (old) {
RemoveCart();
FreeCart(old);
}
}
void TurnOffCart(void)
{
struct Cart *ct=current;
if (ct) {
if (ct->active) {
DisableCart(ct);
}
if (basic_on) {
EnableCart(basic);
}
}
}
void TurnOnCart(void)
{
struct Cart *ct=current;
if (ct) {
if (!(ct->active)) {
if (basic_on) {
DisableCart(basic);
}
EnableCart(ct);
}
}
}
void InsertCart(struct Cart *ct)
{
if (ct) {
DisableCart(basic);
if (current!=ct) {
DisableCart(current);
EnableCart(ct);
current=ct;
}
}
}
int CartInserted(void)
{
if (current && current->active)
return TRUE;
return FALSE;
}
int CartType(void)
{
if (current)
return current->type;
else return -1;
}
void EnableBasic(void)
{
basic_on=TRUE;
if (!(CartInserted()))
EnableCart(basic);
}
void DisableBasic(void)
{
basic_on=FALSE;
if (!(CartInserted()))
DisableCart(basic);
}
void EnableOs(void)
{
EnableCart(os);
EnableCart(mpack);
EnableCart(os_x);
}
void DisableOs(void)
{
DisableCart(os);
DisableCart(mpack);
DisableCart(os_x);
}
void EnableSelftest(void)
{
EnableCart(selftest);
}
void DisableSelftest(void)
{
DisableCart(selftest);
}
void FreeCarts(void)
{
FreeCart(basic);
FreeCart(os);
FreeCart(os_x);
FreeCart(selftest);
FreeCart(mpack);
FreeCart(current);
basic=os=os_x=selftest=mpack=current=NULL;
}
void SelectXEBank(int byte)
{
int cpu_flag = (byte & 0x10);
#ifdef DEBUG
int antic_flag = (byte & 0x20);
#endif
int bank = (byte & 0x0c) >> 2;
static int xe_bank = -1;
#ifdef DEBUG
printf ("CPU = %d, ANTIC = %d, XE BANK = %d\n",
cpu_flag, antic_flag, bank);
#endif
/*
* Possible Bank Transitions
*
* Main -> Main
* Main -> Bank1,2,3,4
* Bank1,2,3,4 -> Main
* Bank1,2,3,4 -> Bank1,2,3,4
*/
if (cpu_flag) { /* turn off bank */
if (xe_bank != -1) {
memcpy (XE_Banks[xe_bank],memory + 0x4000,0x4000);
memcpy (memory + 0x4000,XE_Banks[5],0x4000);
xe_bank = -1;
}
} else if (bank != xe_bank) { /* turn on bank */
if (xe_bank == -1) {
memcpy (XE_Banks[5],memory + 0x4000,0x4000); /* saveback mem */
} else {
memcpy (XE_Banks[xe_bank],memory + 0x4000,0x4000); /* saveback bank */
}
memcpy (memory+0x4000,XE_Banks[bank],0x4000); /* swap in bank */
xe_bank = bank;
}
}
int Free_XE_Banks(void)
{
int i;
for(i=0;i<4;i++) {
if (XE_Banks[i])
free(XE_Banks[i]);
}
return TRUE;
}
int Build_XE_Banks(void)
{
int i;
for(i=0;i<4;i++) {
if (!(XE_Banks[i] = malloc(0x4000*sizeof(mtype))))
return FALSE;
}
return TRUE;
}
static int InCart(struct Cart *ct,ATPtr ad,mtype **where)
{
int i;
if (ct) {
for (i=0;i<4;i++) {
if (ct->secs[i].active) {
if (ad>=ct->secs[i].lo && ad<=ct->secs[i].hi) {
*where=ct->image+ct->secs[i].offset+(ad-ct->secs[i].lo);
return TRUE;
}
}
}
}
return FALSE;
}
static mtype *LocationOf(ATPtr ad)
{
mtype *in;
if (InCart(os_x,ad,&in))
return in;
if (InCart(selftest,ad,&in))
return in;
if (InCart(mpack,ad,&in))
return in;
if (InCart(os,ad,&in))
return in;
printf("Invalid ROM address %x while patching.\n",ad);
Atari800_Exit (FALSE,20);
return 0;
}
int RomGet(ATPtr ad)
{
return *LocationOf(ad);
}
int RomDGet(ATPtr ad)
{
return RomGet(ad)|(RomGet(ad+1)<<8);
}
void RomSet(ATPtr ad,int v)
{
*LocationOf(ad)=v;
}