mirror of
https://github.com/cc65/cc65.git
synced 2025-01-03 01:31:55 +00:00
Working
git-svn-id: svn://svn.cc65.org/cc65/trunk@2092 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
251547f028
commit
8bff858b09
119
src/sim65/chip.c
119
src/sim65/chip.c
@ -41,6 +41,7 @@
|
||||
#include "xmalloc.h"
|
||||
|
||||
/* sim65 */
|
||||
#include "cfgdata.h"
|
||||
#include "chipdata.h"
|
||||
#include "chiplib.h"
|
||||
#include "error.h"
|
||||
@ -88,50 +89,6 @@ static int CmpChips (void* Data attribute ((unused)),
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
Chip* NewChip (ChipLibrary* Library, const ChipData* Data)
|
||||
/* Allocate a new chip structure, initialize and return it */
|
||||
{
|
||||
/* Allocate memory */
|
||||
Chip* C = xmalloc (sizeof (Chip));
|
||||
|
||||
/* Initialize the fields */
|
||||
C->Library = Library;
|
||||
C->Data = Data;
|
||||
C->Instances = EmptyCollection;
|
||||
|
||||
/* Insert the new chip into the collection of all chips */
|
||||
CollAppend (&Chips, C);
|
||||
|
||||
/* Return the structure */
|
||||
return C;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ChipInstance* NewChipInstance (unsigned long Addr, unsigned Size)
|
||||
/* Allocate a new chip instance for the chip. */
|
||||
{
|
||||
/* Allocate a new ChipInstance structure */
|
||||
ChipInstance* Instance = xmalloc (sizeof (*Instance));
|
||||
|
||||
/* Initialize the fields */
|
||||
Instance->C = 0;
|
||||
Instance->Addr = Addr;
|
||||
Instance->Size = Size;
|
||||
Instance->InstanceData = 0;
|
||||
|
||||
/* Return the new struct */
|
||||
return Instance;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static Chip* FindChip (const char* Name)
|
||||
/* Find a chip by name. Returns the Chip data structure or NULL if the chip
|
||||
* could not be found.
|
||||
@ -158,24 +115,80 @@ static Chip* FindChip (const char* Name)
|
||||
|
||||
|
||||
|
||||
void InitChipInstance (ChipInstance* CI, const char* ChipName,
|
||||
const struct CfgData** Data, unsigned Count)
|
||||
/* Initialize the given chip instance. Assign it to the chip named ChipName,
|
||||
* and call the init function of the chip passing the given config data.
|
||||
*/
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
Chip* NewChip (ChipLibrary* Library, const ChipData* Data)
|
||||
/* Allocate a new chip structure, initialize and return it */
|
||||
{
|
||||
/* Allocate memory */
|
||||
Chip* C = xmalloc (sizeof (Chip));
|
||||
|
||||
/* Initialize the fields */
|
||||
C->Library = Library;
|
||||
C->Data = Data;
|
||||
C->Instances = EmptyCollection;
|
||||
|
||||
/* Insert the new chip into the collection of all chips */
|
||||
CollAppend (&Chips, C);
|
||||
|
||||
/* Return the structure */
|
||||
return C;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ChipInstance* NewChipInstance (const char* ChipName, unsigned Addr,
|
||||
unsigned Size, const Collection* Attributes)
|
||||
{
|
||||
ChipInstance* CI;
|
||||
|
||||
/* Find the chip with the given name */
|
||||
Chip* C = FindChip (ChipName);
|
||||
if (C == 0) {
|
||||
Error ("No chip `%s' found for address $%6lX", ChipName, CI->Addr);
|
||||
Error ("No chip `%s' found for address $%06X", ChipName, Addr);
|
||||
}
|
||||
|
||||
/* Call the initialization function */
|
||||
CI->InstanceData = C->Data->InitInstance (CI->Addr, CI->Size, Data, Count);
|
||||
/* Allocate a new ChipInstance structure */
|
||||
CI = xmalloc (sizeof (*CI));
|
||||
|
||||
/* Initialize the fields */
|
||||
CI->C = C;
|
||||
CI->Addr = Addr;
|
||||
CI->Size = Size;
|
||||
CI->Data = C->Data->InitInstance (Addr, Size,
|
||||
(const CfgData**) Attributes->Items,
|
||||
CollCount (Attributes));
|
||||
|
||||
/* Assign the chip instance to the chip */
|
||||
CI->C = C;
|
||||
CollAppend (&C->Instances, CI);
|
||||
|
||||
/* Return the new instance struct */
|
||||
return CI;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ChipInstance* MirrorChipInstance (const ChipInstance* Orig, unsigned Addr)
|
||||
/* Generate a chip instance mirror and return it. */
|
||||
{
|
||||
/* Allocate a new ChipInstance structure */
|
||||
ChipInstance* CI = xmalloc (sizeof (*CI));
|
||||
|
||||
/* Initialize the fields */
|
||||
CI->C = Orig->C;
|
||||
CI->Addr = Addr;
|
||||
CI->Size = Orig->Size;
|
||||
CI->Data = Orig->Data;
|
||||
|
||||
/* Assign the chip instance to the chip */
|
||||
CollAppend (&CI->C->Instances, CI);
|
||||
|
||||
/* Return the new instance struct */
|
||||
return CI;
|
||||
}
|
||||
|
||||
|
||||
|
@ -61,10 +61,10 @@ typedef struct ChipInstance ChipInstance;
|
||||
|
||||
/* One instance of a chip */
|
||||
struct ChipInstance {
|
||||
Chip* C; /* Pointer to corresponding chip */
|
||||
unsigned long Addr; /* Start address of range */
|
||||
unsigned Size; /* Size of range */
|
||||
void* InstanceData; /* Chip instance data */
|
||||
Chip* C; /* Pointer to corresponding chip */
|
||||
unsigned Addr; /* Start address of range */
|
||||
unsigned Size; /* Size of range */
|
||||
void* Data; /* Chip instance data */
|
||||
};
|
||||
|
||||
/* Chip structure */
|
||||
@ -85,14 +85,12 @@ struct Chip {
|
||||
Chip* NewChip (struct ChipLibrary* Library, const ChipData* Data);
|
||||
/* Allocate a new chip structure, initialize and return it */
|
||||
|
||||
ChipInstance* NewChipInstance (unsigned long Addr, unsigned Size);
|
||||
ChipInstance* NewChipInstance (const char* ChipName, unsigned Addr,
|
||||
unsigned Size, const Collection* Attributes);
|
||||
/* Allocate a new chip instance for the chip. */
|
||||
|
||||
void InitChipInstance (ChipInstance* CI, const char* ChipName,
|
||||
const struct CfgData** Data, unsigned Count);
|
||||
/* Initialize the given chip instance. Assign it to the chip named ChipName,
|
||||
* and call the init function of the chip passing the given config data.
|
||||
*/
|
||||
ChipInstance* MirrorChipInstance (const ChipInstance* Orig, unsigned Addr);
|
||||
/* Generate a chip instance mirror and return it. */
|
||||
|
||||
void SortChips (void);
|
||||
/* Sort all chips by name. Called after loading */
|
||||
|
@ -50,6 +50,7 @@
|
||||
#include "chip.h"
|
||||
#include "error.h"
|
||||
#include "global.h"
|
||||
#include "memory.h"
|
||||
#include "scanner.h"
|
||||
#include "config.h"
|
||||
|
||||
@ -67,11 +68,11 @@ static Collection Locations;
|
||||
/* One memory location */
|
||||
typedef struct Location Location;
|
||||
struct Location {
|
||||
unsigned long Start; /* Start of memory location */
|
||||
unsigned long End; /* End memory location */
|
||||
Collection Attributes; /* Attributes given */
|
||||
unsigned Line; /* Line in config file */
|
||||
unsigned Col; /* Column in config file */
|
||||
unsigned Start; /* Start of memory location */
|
||||
unsigned End; /* End memory location */
|
||||
Collection Attributes; /* Attributes given */
|
||||
unsigned Line; /* Line in config file */
|
||||
unsigned Col; /* Column in config file */
|
||||
};
|
||||
|
||||
|
||||
@ -94,7 +95,7 @@ static CfgData* NewCfgData (void)
|
||||
CfgData* D = xmalloc (sizeof (CfgData) + AttrLen);
|
||||
|
||||
/* Initialize the fields */
|
||||
D->Type = CfgDataInvalid;
|
||||
D->Type = CfgDataInvalid;
|
||||
D->Line = CfgErrorLine;
|
||||
D->Col = CfgErrorCol;
|
||||
memcpy (D->Attr, CfgSVal, AttrLen+1);
|
||||
@ -105,6 +106,30 @@ static CfgData* NewCfgData (void)
|
||||
|
||||
|
||||
|
||||
static void FreeCfgData (CfgData* D)
|
||||
/* Free a config data structure */
|
||||
{
|
||||
if (D->Type == CfgDataString) {
|
||||
/* Free the string value */
|
||||
xfree (D->V.SVal);
|
||||
}
|
||||
/* Free the structure */
|
||||
xfree (D);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void CfgDataCheckType (const CfgData* D, unsigned Type)
|
||||
/* Check the config data type */
|
||||
{
|
||||
if (D->Type != Type) {
|
||||
Error ("%s(%u): Attribute `%s' has invalid type",
|
||||
CfgGetName (), D->Line, D->Attr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* struct Location */
|
||||
/*****************************************************************************/
|
||||
@ -150,9 +175,9 @@ static int CmpLocations (void* Data attribute ((unused)),
|
||||
|
||||
|
||||
|
||||
static const CfgData* LocationFindAttr (const Location* L, const char* AttrName)
|
||||
/* Find the attribute with the given name and return it. Return NULL if the
|
||||
* attribute was not found.
|
||||
static int LocationFindAttr (const Location* L, const char* AttrName)
|
||||
/* Find the attribute with the given name and return its index. Return -1 if
|
||||
* the attribute was not found.
|
||||
*/
|
||||
{
|
||||
unsigned I;
|
||||
@ -166,12 +191,26 @@ static const CfgData* LocationFindAttr (const Location* L, const char* AttrName)
|
||||
/* Compare the name */
|
||||
if (StrCaseCmp (D->Attr, AttrName) == 0) {
|
||||
/* Found */
|
||||
return D;
|
||||
return I;
|
||||
}
|
||||
}
|
||||
|
||||
/* Not found */
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int LocationGetAttr (const Location* L, const char* AttrName)
|
||||
/* Find the attribute with the given name and return it. Call Error() if the
|
||||
* attribute was not found.
|
||||
*/
|
||||
{
|
||||
int I = LocationFindAttr (L, AttrName);
|
||||
if (I < 0) {
|
||||
Error ("%s(%u): Attribute `%s' missing", CfgGetName(), L->Line, AttrName);
|
||||
}
|
||||
return I;
|
||||
}
|
||||
|
||||
|
||||
@ -180,40 +219,17 @@ static int LocationIsMirror (const Location* L)
|
||||
/* Return true if the given location is a mirror of another one. */
|
||||
{
|
||||
/* Find the "mirror" attribute */
|
||||
return (LocationFindAttr (L, "mirror") != 0);
|
||||
return (LocationFindAttr (L, "mirror") >= 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
static void FlagAttr (unsigned* Flags, unsigned Mask, const char* Name)
|
||||
/* Check if the item is already defined. Print an error if so. If not, set
|
||||
* the marker that we have a definition now.
|
||||
*/
|
||||
{
|
||||
if (*Flags & Mask) {
|
||||
CfgError ("%s is already defined", Name);
|
||||
}
|
||||
*Flags |= Mask;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void AttrCheck (unsigned Attr, unsigned Mask, const char* Name)
|
||||
/* Check that a mandatory attribute was given */
|
||||
{
|
||||
if ((Attr & Mask) == 0) {
|
||||
CfgError ("%s attribute is missing", Name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void ParseMemory (void)
|
||||
/* Parse a MEMORY section */
|
||||
{
|
||||
@ -312,19 +328,106 @@ static void ParseMemory (void)
|
||||
if (LocationIsMirror (L)) {
|
||||
const CfgData* D;
|
||||
if (CollCount (&L->Attributes) > 1) {
|
||||
Error ("%s(%u): Location at address $%06lX is a mirror "
|
||||
Error ("%s(%u): Location at address $%06X is a mirror "
|
||||
"but has attributes", CfgGetName(), L->Line, L->Start);
|
||||
}
|
||||
D = CollConstAt (&L->Attributes, 0);
|
||||
if (D->Type != CfgDataNumber) {
|
||||
Error ("%s(%u): Mirror attribute is not an integer",
|
||||
CfgGetName (), L->Line);
|
||||
}
|
||||
CfgDataCheckType (D, CfgDataNumber);
|
||||
}
|
||||
|
||||
/* Remember this entry */
|
||||
Last = L;
|
||||
}
|
||||
|
||||
/* Now create the chip instances. Since we can only mirror existing chips,
|
||||
* we will first create all real chips and the mirrors in a second run.
|
||||
*/
|
||||
for (I = 0; I < CollCount (&Locations); ++I) {
|
||||
|
||||
int Index;
|
||||
CfgData* D;
|
||||
unsigned Range; /* Address range for this chip */
|
||||
ChipInstance* CI;
|
||||
|
||||
/* Get this location */
|
||||
Location* L = CollAtUnchecked (&Locations, I);
|
||||
|
||||
/* Skip mirrors */
|
||||
if (LocationIsMirror (L)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* The chip must have an attribute "name" of type string */
|
||||
Index = LocationGetAttr (L, "name");
|
||||
D = CollAt (&L->Attributes, Index);
|
||||
CfgDataCheckType (D, CfgDataString);
|
||||
|
||||
/* Remove the "name" attribute from the attribute list */
|
||||
CollDelete (&L->Attributes, Index);
|
||||
|
||||
/* Create the chip instance for the address range */
|
||||
Range = L->End - L->Start;
|
||||
CI = NewChipInstance (D->V.SVal, L->Start, Range, &L->Attributes);
|
||||
|
||||
/* Delete the "name" attribute */
|
||||
FreeCfgData (D);
|
||||
|
||||
/* Assign the chip instance to memory */
|
||||
MemAssignChip (CI, L->Start, Range);
|
||||
}
|
||||
|
||||
/* Create the mirrors */
|
||||
for (I = 0; I < CollCount (&Locations); ++I) {
|
||||
|
||||
const CfgData* D;
|
||||
unsigned MirrorAddr; /* Mirror address */
|
||||
unsigned Range; /* Address range for this chip */
|
||||
unsigned Offs; /* Offset of the mirror */
|
||||
const ChipInstance* CI; /* Original chip instance */
|
||||
ChipInstance* MCI; /* Mirrored chip instance */
|
||||
|
||||
/* Get this location */
|
||||
const Location* L = CollAtUnchecked (&Locations, I);
|
||||
|
||||
/* Skip non mirrors */
|
||||
if (!LocationIsMirror (L)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Calculate the address range */
|
||||
Range = L->End - L->Start;
|
||||
|
||||
/* Get the mirror address */
|
||||
D = CollConstAt (&L->Attributes, 0);
|
||||
MirrorAddr = (unsigned) D->V.IVal;
|
||||
|
||||
/* For simplicity, get the chip instance we're mirroring from the
|
||||
* memory, instead of searching for the range in the list.
|
||||
*/
|
||||
CI = MemGetChip (MirrorAddr);
|
||||
if (CI == 0) {
|
||||
/* We are mirroring an unassigned address */
|
||||
Error ("%s(%u): Mirroring an unassigned address",
|
||||
CfgGetName (), L->Line);
|
||||
}
|
||||
|
||||
/* Make sure we're mirroring the correct chip */
|
||||
CHECK (MirrorAddr >= CI->Addr && MirrorAddr < CI->Addr + CI->Size);
|
||||
|
||||
/* Calculate the offset of the mirror */
|
||||
Offs = MirrorAddr - CI->Addr;
|
||||
|
||||
/* Check if the mirror range is ok */
|
||||
if (Offs + Range > CI->Size) {
|
||||
Error ("%s(%u): Mirror range is too large", CfgGetName (), L->Line);
|
||||
}
|
||||
|
||||
/* Clone the chip instance for the new location */
|
||||
MCI = MirrorChipInstance (CI, L->Start - Offs);
|
||||
|
||||
/* Assign the chip instance to memory */
|
||||
MemAssignChip (MCI, L->Start, Range);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -292,10 +292,13 @@ int main (int argc, char* argv[])
|
||||
Error ("Simulator configuration missing");
|
||||
}
|
||||
|
||||
/* Initialize the simulated CPU memory */
|
||||
MemInit ();
|
||||
|
||||
/* Read the config file */
|
||||
CfgRead ();
|
||||
|
||||
MemInit ();
|
||||
/* Initialize the CPU */
|
||||
CPUInit ();
|
||||
#if 0
|
||||
CPURun ();
|
||||
|
@ -39,84 +39,25 @@
|
||||
|
||||
/* common */
|
||||
#include "coll.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
/* sim65 */
|
||||
#include "chip.h"
|
||||
#include "cputype.h"
|
||||
#include "error.h"
|
||||
#include "memory.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Forwards */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
static void MemWrite (unsigned Addr, unsigned char Val);
|
||||
/* Write one byte to the memory cell */
|
||||
|
||||
static unsigned char MemRead (unsigned Attr);
|
||||
/* Read one memory cell */
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* RAM attributes */
|
||||
#define RA_READFUNC_MASK 0x000F /* Up to 16 read functions */
|
||||
#define RA_WRITEFUNC_MASK 0x00F0 /* Up to 16 write functions */
|
||||
#define RA_INITIALIZED 0x0100 /* Memory cell is initialized */
|
||||
#define RA_WPROT 0x0200 /* Memory cell is write protected */
|
||||
|
||||
/* Defines reader and writer functions */
|
||||
#define RA_READFUNC_SHIFT 0
|
||||
#define RA_WRITEFUNC_SHIFT 4
|
||||
#define RA_READFUNC_MAX 16
|
||||
#define RA_WRITEFUNC_MAX 16
|
||||
|
||||
/* Read/write function declarations */
|
||||
typedef unsigned char (*ReadFunc) (unsigned Addr);
|
||||
typedef void (*WriteFunc) (unsigned Addr, unsigned char Val);
|
||||
static Collection ReadFuncs = STATIC_COLLECTION_INITIALIZER;
|
||||
static Collection WriteFuncs = STATIC_COLLECTION_INITIALIZER;
|
||||
|
||||
/* Memory attributes and the memory */
|
||||
static unsigned short MemAttr[0x10000];
|
||||
static unsigned char Mem[0x10000];
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Internal functions */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
static void MemWrite (unsigned Addr, unsigned char Val)
|
||||
/* Write one byte to the memory cell */
|
||||
{
|
||||
if (MemAttr[Addr] & RA_WPROT) {
|
||||
Warning ("Writing to write protected memory at $%04X", Addr);
|
||||
}
|
||||
Mem[Addr] = Val;
|
||||
MemAttr[Addr] |= RA_INITIALIZED;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static unsigned char MemRead (unsigned Addr)
|
||||
/* Read one memory cell */
|
||||
{
|
||||
if ((MemAttr[Addr] & RA_INITIALIZED) == 0) {
|
||||
/* We're reading a memory cell that was never written */
|
||||
Warning ("Reading from uninitialized memory at $%04X", Addr);
|
||||
}
|
||||
return Mem[Addr];
|
||||
}
|
||||
/* Pointer to our memory */
|
||||
static const ChipInstance** MemData = 0;
|
||||
unsigned MemSize = 0;
|
||||
|
||||
|
||||
|
||||
@ -129,12 +70,15 @@ static unsigned char MemRead (unsigned Addr)
|
||||
void MemWriteByte (unsigned Addr, unsigned char Val)
|
||||
/* Write a byte to a memory location */
|
||||
{
|
||||
/* Get the writer function */
|
||||
unsigned WI = (MemAttr[Addr] & RA_WRITEFUNC_MASK) >> RA_WRITEFUNC_SHIFT;
|
||||
WriteFunc WF = CollAt (&WriteFuncs, WI);
|
||||
/* Get the instance of the chip at this address */
|
||||
const ChipInstance* CI = MemData[Addr];
|
||||
|
||||
/* Call the writer function */
|
||||
WF (Addr, Val);
|
||||
/* Check if the memory is mapped */
|
||||
if (CI == 0) {
|
||||
Warning ("Writing to unassigned memory at $%06X", Addr);
|
||||
} else {
|
||||
CI->C->Data->Write (CI->Data, Addr - CI->Addr, Val);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -142,12 +86,16 @@ void MemWriteByte (unsigned Addr, unsigned char Val)
|
||||
unsigned char MemReadByte (unsigned Addr)
|
||||
/* Read a byte from a memory location */
|
||||
{
|
||||
/* Get the reader function */
|
||||
unsigned RI = (MemAttr[Addr] & RA_READFUNC_MASK) >> RA_READFUNC_SHIFT;
|
||||
ReadFunc RF = CollAt (&ReadFuncs, RI);
|
||||
/* Get the instance of the chip at this address */
|
||||
const ChipInstance* CI = MemData[Addr];
|
||||
|
||||
/* Call the reader function */
|
||||
return RF (Addr);
|
||||
/* Check if the memory is mapped */
|
||||
if (CI == 0) {
|
||||
Warning ("Reading from unassigned memory at $%06X", Addr);
|
||||
return 0xFF;
|
||||
} else {
|
||||
return CI->C->Data->Read (CI->Data, Addr - CI->Addr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -163,9 +111,9 @@ unsigned MemReadWord (unsigned Addr)
|
||||
|
||||
unsigned MemReadZPWord (unsigned char Addr)
|
||||
/* Read a word from the zero page. This function differs from ReadMemW in that
|
||||
* the read will always be in the zero page, even in case of an address
|
||||
* overflow.
|
||||
*/
|
||||
* the read will always be in the zero page, even in case of an address
|
||||
* overflow.
|
||||
*/
|
||||
{
|
||||
unsigned W = MemReadByte (Addr++);
|
||||
return (W | (MemReadByte (Addr) << 8));
|
||||
@ -173,46 +121,29 @@ unsigned MemReadZPWord (unsigned char Addr)
|
||||
|
||||
|
||||
|
||||
void MemLoad (const char* Filename, unsigned Addr, unsigned Size)
|
||||
/* Load the contents of the given file into the RAM at the given address.
|
||||
* If Size is not zero, we will read exactly Size bytes from the file and
|
||||
* consider it an error if this is not possible. The memory attributes
|
||||
* for the range is set to initialized.
|
||||
*/
|
||||
void MemAssignChip (const ChipInstance* CI, unsigned Addr, unsigned Range)
|
||||
/* Assign a chip instance to memory locations */
|
||||
{
|
||||
unsigned BytesToRead;
|
||||
unsigned BytesRead;
|
||||
unsigned I;
|
||||
/* Make sure, the addresses are in a valid range */
|
||||
PRECONDITION (Addr + Range <= MemSize);
|
||||
|
||||
/* Open the file */
|
||||
FILE* F = fopen (Filename, "rb");
|
||||
if (F == 0) {
|
||||
Error ("Cannot open `%s': %s", Filename, strerror (errno));
|
||||
/* Assign the chip instance */
|
||||
while (Range--) {
|
||||
CHECK (MemData[Addr] == 0);
|
||||
MemData[Addr++] = CI;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the number of bytes to read */
|
||||
BytesToRead = 0x10000 - Addr;
|
||||
if (Size > 0) {
|
||||
CHECK (Size <= BytesToRead); /* Must not exceed RAM */
|
||||
BytesToRead = Size;
|
||||
}
|
||||
|
||||
/* Read data from the file */
|
||||
BytesRead = fread (Mem + Addr, 1, BytesToRead, F);
|
||||
if (ferror (F)) {
|
||||
Error ("Error reading from `%s': %s", Filename, strerror (errno));
|
||||
}
|
||||
if (Size > 0 && BytesRead != Size) {
|
||||
Error ("Cannot read %u bytes from `%s'", Size, Filename);
|
||||
}
|
||||
|
||||
/* Close the file. Ignore errors, we were just reading. */
|
||||
fclose (F);
|
||||
const struct ChipInstance* MemGetChip (unsigned Addr)
|
||||
/* Get the chip that is located at the given address (may return NULL). */
|
||||
{
|
||||
/* Make sure, the address is valid */
|
||||
PRECONDITION (Addr < MemSize);
|
||||
|
||||
/* Set the memory attribute for the range to initialized */
|
||||
for (I = 0; I < BytesRead; ++I) {
|
||||
MemAttr[Addr+I] |= RA_INITIALIZED;
|
||||
}
|
||||
/* Return the chip instance */
|
||||
return MemData[Addr];
|
||||
}
|
||||
|
||||
|
||||
@ -222,23 +153,21 @@ void MemInit (void)
|
||||
{
|
||||
unsigned I;
|
||||
|
||||
/* Clear the memory and it's attributes. Writing zeroes to the
|
||||
* attribute array will cause any special flags to be reset and
|
||||
* the default read and write functions to be used.
|
||||
*/
|
||||
for (I = 0; I < sizeof (Mem) / sizeof (Mem[0]); ++I) {
|
||||
Mem[I] = 0;
|
||||
/* Allocate memory depending on the CPU type */
|
||||
switch (CPU) {
|
||||
case CPU_6502:
|
||||
case CPU_65C02:
|
||||
MemSize = 0x10000;
|
||||
break;
|
||||
default:
|
||||
Internal ("Unexpected CPU type: %d", CPU);
|
||||
}
|
||||
for (I = 0; I < sizeof (MemAttr) / sizeof (MemAttr[0]); ++I) {
|
||||
MemAttr[I] = 0;
|
||||
MemData = xmalloc (MemSize);
|
||||
|
||||
/* Clear the memory */
|
||||
for (I = 0; I < MemSize; ++I) {
|
||||
MemData[I] = 0;
|
||||
}
|
||||
|
||||
/* Add the default reader and writer functions to the collection */
|
||||
CollAppend (&ReadFuncs, MemRead);
|
||||
CollAppend (&WriteFuncs, MemWrite);
|
||||
|
||||
MemWriteByte (0xFFFC, 0x00);
|
||||
MemWriteByte (0xFFFD, 0x02);
|
||||
}
|
||||
|
||||
|
||||
|
@ -39,13 +39,21 @@
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* Forwards */
|
||||
struct ChipInstance;
|
||||
|
||||
/* Memory size of the CPU */
|
||||
extern unsigned MemSize;
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
@ -65,12 +73,11 @@ unsigned MemReadZPWord (unsigned char Addr);
|
||||
* overflow.
|
||||
*/
|
||||
|
||||
void MemLoad (const char* Filename, unsigned Addr, unsigned Size);
|
||||
/* Load the contents of the given file into the RAM at the given address.
|
||||
* If Size is not zero, we will read exactly Size bytes from the file and
|
||||
* consider it an error if this is not possible. The memory attributes
|
||||
* for the range is set to initialized.
|
||||
*/
|
||||
void MemAssignChip (const struct ChipInstance* CI, unsigned Addr, unsigned Range);
|
||||
/* Assign a chip instance to memory locations */
|
||||
|
||||
const struct ChipInstance* MemGetChip (unsigned Addr);
|
||||
/* Get the chip that is located at the given address (may return NULL). */
|
||||
|
||||
void MemInit (void);
|
||||
/* Initialize the memory subsystem */
|
||||
@ -83,3 +90,4 @@ void MemInit (void);
|
||||
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user