versionable header for sim65
load and run address now configured from header fix error codes not to conflict with test fix test/misc/endless.c which is supposed to fail if an endless loop does not occur
This commit is contained in:
committed by
Oliver Schmidt
parent
07ca772932
commit
fb7d4acd5c
@@ -69,7 +69,21 @@ void Error (const char* Format, ...)
|
||||
vfprintf (stderr, Format, ap);
|
||||
putc ('\n', stderr);
|
||||
va_end (ap);
|
||||
exit (EXIT_FAILURE);
|
||||
exit (SIM65_ERROR);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ErrorCode (int Code, const char* Format, ...)
|
||||
/* Print an error message and die with the given exit code */
|
||||
{
|
||||
va_list ap;
|
||||
va_start (ap, Format);
|
||||
fprintf (stderr, "Error: ");
|
||||
vfprintf (stderr, Format, ap);
|
||||
putc ('\n', stderr);
|
||||
va_end (ap);
|
||||
exit (Code);
|
||||
}
|
||||
|
||||
|
||||
@@ -83,5 +97,5 @@ void Internal (const char* Format, ...)
|
||||
vfprintf (stderr, Format, ap);
|
||||
putc ('\n', stderr);
|
||||
va_end (ap);
|
||||
exit (EXIT_FAILURE);
|
||||
exit (SIM65_ERROR);
|
||||
}
|
||||
|
||||
@@ -43,6 +43,20 @@
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#define SIM65_ERROR 256
|
||||
/* Does not use EXIT_FAILURE because it may overlap with test results. */
|
||||
|
||||
#define SIM65_ERROR_TIMEOUT 257
|
||||
/* An error result for max CPU instructions exceeded. */
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
@@ -55,6 +69,9 @@ void Warning (const char* Format, ...) attribute((format(printf,1,2)));
|
||||
void Error (const char* Format, ...) attribute((noreturn, format(printf,1,2)));
|
||||
/* Print an error message and die */
|
||||
|
||||
void ErrorCode (int Code, const char* Format, ...) attribute((noreturn, format(printf,2,3)));
|
||||
/* Print an error message and die with the given exit code */
|
||||
|
||||
void Internal (const char* Format, ...) attribute((noreturn, format(printf,1,2)));
|
||||
/* Print an internal error message and die */
|
||||
|
||||
|
||||
@@ -63,6 +63,16 @@ const char* ProgramFile;
|
||||
/* exit simulator after MaxCycles Cycles */
|
||||
unsigned long MaxCycles;
|
||||
|
||||
/* Header signature 'sim65' */
|
||||
static const unsigned char HeaderSignature[] = {
|
||||
0x73, 0x69, 0x6D, 0x36, 0x35
|
||||
};
|
||||
#define HEADER_SIGNATURE_LENGTH (sizeof(HeaderSignature)/sizeof(HeaderSignature[0]))
|
||||
|
||||
static const unsigned char HeaderVersion = 2;
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
@@ -135,8 +145,11 @@ static void OptQuitXIns (const char* Opt attribute ((unused)),
|
||||
static unsigned char ReadProgramFile (void)
|
||||
/* Load program into memory */
|
||||
{
|
||||
int Val;
|
||||
unsigned Addr = 0x0200;
|
||||
unsigned I;
|
||||
int Val, Val2;
|
||||
int Version;
|
||||
unsigned Addr;
|
||||
unsigned Load, Reset;
|
||||
unsigned char SPAddr = 0x00;
|
||||
|
||||
/* Open the file */
|
||||
@@ -145,6 +158,18 @@ static unsigned char ReadProgramFile (void)
|
||||
Error ("Cannot open '%s': %s", ProgramFile, strerror (errno));
|
||||
}
|
||||
|
||||
/* Verify the header signature */
|
||||
for (I=0; I<HEADER_SIGNATURE_LENGTH; ++I) {
|
||||
if ((Val = fgetc(F)) != HeaderSignature[I]) {
|
||||
Error ("'%s': Invalid header signature.", ProgramFile);
|
||||
}
|
||||
}
|
||||
|
||||
/* Get header version */
|
||||
if ((Version = fgetc(F)) != HeaderVersion) {
|
||||
Error ("'%s': Invalid header version.", ProgramFile);
|
||||
}
|
||||
|
||||
/* Get the CPU type from the file header */
|
||||
if ((Val = fgetc(F)) != EOF) {
|
||||
if (Val != CPU_6502 && Val != CPU_65C02) {
|
||||
@@ -158,10 +183,25 @@ static unsigned char ReadProgramFile (void)
|
||||
SPAddr = Val;
|
||||
}
|
||||
|
||||
/* Get load address */
|
||||
if (((Val = fgetc(F)) == EOF) ||
|
||||
((Val2 = fgetc(F)) == EOF)) {
|
||||
Error ("'%s': Header missing load address", ProgramFile);
|
||||
}
|
||||
Load = Val | (Val2 << 8);
|
||||
|
||||
/* Get reset address */
|
||||
if (((Val = fgetc(F)) == EOF) ||
|
||||
((Val2 = fgetc(F)) == EOF)) {
|
||||
Error ("'%s': Header missing reset address", ProgramFile);
|
||||
}
|
||||
Reset = Val | (Val2 << 8);
|
||||
|
||||
/* Read the file body into memory */
|
||||
Addr = Load;
|
||||
while ((Val = fgetc(F)) != EOF) {
|
||||
if (Addr == 0xFF00) {
|
||||
Error ("'%s': To large to fit into $0200-$FFF0", ProgramFile);
|
||||
Error ("'%s': To large to fit into $%04X-$FFF0", ProgramFile, Addr);
|
||||
}
|
||||
MemWriteByte (Addr++, (unsigned char) Val);
|
||||
}
|
||||
@@ -174,8 +214,11 @@ static unsigned char ReadProgramFile (void)
|
||||
/* Close the file */
|
||||
fclose (F);
|
||||
|
||||
Print (stderr, 1, "Loaded '%s' at $0200-$%04X\n", ProgramFile, Addr - 1);
|
||||
Print (stderr, 1, "Loaded '%s' at $%04X-$%04X\n", ProgramFile, Load, Addr - 1);
|
||||
Print (stderr, 1, "File version: %d\n", Version);
|
||||
Print (stderr, 1, "Reset: $%04X\n", Reset);
|
||||
|
||||
MemWriteWord(0xFFFC, Reset);
|
||||
return SPAddr;
|
||||
}
|
||||
|
||||
@@ -263,9 +306,7 @@ int main (int argc, char* argv[])
|
||||
while (1) {
|
||||
ExecuteInsn ();
|
||||
if (MaxCycles && (GetCycles () >= MaxCycles)) {
|
||||
Error ("Maximum number of cycles reached.");
|
||||
exit (-99); /* do not use EXIT_FAILURE to avoid conflicts with the
|
||||
same value being used in a test program */
|
||||
ErrorCode (SIM65_ERROR_TIMEOUT, "Maximum number of cycles reached.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -64,6 +64,15 @@ void MemWriteByte (unsigned Addr, unsigned char Val)
|
||||
|
||||
|
||||
|
||||
void MemWriteWord (unsigned Addr, unsigned Val)
|
||||
/* Write a word to a memory location */
|
||||
{
|
||||
MemWriteByte (Addr, Val & 0xFF);
|
||||
MemWriteByte (Addr + 1, Val >> 8);
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned char MemReadByte (unsigned Addr)
|
||||
/* Read a byte from a memory location */
|
||||
{
|
||||
@@ -82,7 +91,7 @@ unsigned MemReadWord (unsigned Addr)
|
||||
|
||||
|
||||
unsigned MemReadZPWord (unsigned char Addr)
|
||||
/* Read a word from the zero page. This function differs from ReadMemW in that
|
||||
/* Read a word from the zero page. This function differs from MemReadWord in that
|
||||
** the read will always be in the zero page, even in case of an address
|
||||
** overflow.
|
||||
*/
|
||||
@@ -96,10 +105,6 @@ unsigned MemReadZPWord (unsigned char Addr)
|
||||
void MemInit (void)
|
||||
/* Initialize the memory subsystem */
|
||||
{
|
||||
/* Fill momory with illegal opcode */
|
||||
/* Fill memory with illegal opcode */
|
||||
memset (Mem, 0xFF, sizeof (Mem));
|
||||
|
||||
/* Set RESET vector to 0x0200 */
|
||||
Mem[0xFFFC] = 0x00;
|
||||
Mem[0xFFFD] = 0x02;
|
||||
}
|
||||
|
||||
@@ -47,6 +47,9 @@
|
||||
void MemWriteByte (unsigned Addr, unsigned char Val);
|
||||
/* Write a byte to a memory location */
|
||||
|
||||
void MemWriteWord (unsigned Addr, unsigned Val);
|
||||
/* Write a word to a memory location */
|
||||
|
||||
unsigned char MemReadByte (unsigned Addr);
|
||||
/* Read a byte from a memory location */
|
||||
|
||||
@@ -54,7 +57,7 @@ unsigned MemReadWord (unsigned Addr);
|
||||
/* Read a word from a memory location */
|
||||
|
||||
unsigned MemReadZPWord (unsigned char Addr);
|
||||
/* Read a word from the zero page. This function differs from ReadMemW in that
|
||||
/* Read a word from the zero page. This function differs from MemReadWord in that
|
||||
** the read will always be in the zero page, even in case of an address
|
||||
** overflow.
|
||||
*/
|
||||
|
||||
@@ -103,15 +103,6 @@ static void SetAX (CPURegs* Regs, unsigned Val)
|
||||
|
||||
|
||||
|
||||
static void MemWriteWord (unsigned Addr, unsigned Val)
|
||||
{
|
||||
MemWriteByte (Addr, Val);
|
||||
Val >>= 8;
|
||||
MemWriteByte (Addr + 1, Val);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static unsigned char Pop (CPURegs* Regs)
|
||||
{
|
||||
return MemReadByte (0x0100 + ++Regs->SP);
|
||||
|
||||
Reference in New Issue
Block a user