mirror of
https://github.com/DavidBuchanan314/6502-emu.git
synced 2024-12-26 13:31:02 +00:00
Added command line args to set initial machine state
* changed debug print to match a validation run found on nesdev.com
This commit is contained in:
parent
b9d74c2a85
commit
c5e9cf084e
84
6502-emu.c
84
6502-emu.c
@ -1,5 +1,6 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <termios.h>
|
||||
#include <time.h>
|
||||
|
||||
@ -18,14 +19,15 @@ void step_delay()
|
||||
nanosleep(&req, &rem);
|
||||
}
|
||||
|
||||
void run_cpu()
|
||||
void run_cpu(int verbose, int mem_dump)
|
||||
{
|
||||
int cycles = 0;
|
||||
int cycles_per_step = (CPU_FREQ / (ONE_SECOND / STEP_DURATION));
|
||||
|
||||
for (;;) {
|
||||
for (cycles %= cycles_per_step; cycles < cycles_per_step;) {
|
||||
cycles += step_cpu();
|
||||
if (mem_dump) save_memory(NULL);
|
||||
cycles += step_cpu(verbose);
|
||||
step_uart();
|
||||
}
|
||||
step_delay(); // remove this for more speed
|
||||
@ -48,26 +50,82 @@ void raw_stdin()
|
||||
atexit(restore_stdin);
|
||||
}
|
||||
|
||||
int hextoint(char *str) {
|
||||
int val;
|
||||
|
||||
if (*str == '$') str++;
|
||||
val = strtol(str, NULL, 16);
|
||||
return val;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc != 2) {
|
||||
printf("Usage: %s file.rom\n", argv[0]);
|
||||
printf("The first 16k of \"file.rom\" is loaded into the last 16k of memory.\n");
|
||||
int a, x, y, sp, sr, pc;
|
||||
int verbose, interactive, mem_dump;
|
||||
int opt;
|
||||
|
||||
verbose = 0;
|
||||
interactive = 0;
|
||||
mem_dump = 0;
|
||||
a = 0;
|
||||
x = 0;
|
||||
y = 0;
|
||||
sp = 0;
|
||||
sr = 0;
|
||||
pc = -RST_VEC; // negative implies indirect
|
||||
while ((opt = getopt(argc, argv, "vima:x:y:r:p:s:g:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'v':
|
||||
verbose = 1;
|
||||
break;
|
||||
case 'i':
|
||||
interactive = 1;
|
||||
break;
|
||||
case 'm':
|
||||
mem_dump = 1;
|
||||
break;
|
||||
case 'a':
|
||||
a = hextoint(optarg);
|
||||
break;
|
||||
case 'x':
|
||||
x = hextoint(optarg);
|
||||
break;
|
||||
case 'y':
|
||||
y = hextoint(optarg);
|
||||
break;
|
||||
case 's':
|
||||
sp = hextoint(optarg);
|
||||
break;
|
||||
case 'p':
|
||||
sr = hextoint(optarg);
|
||||
break;
|
||||
case 'r':
|
||||
case 'g':
|
||||
pc = hextoint(optarg);
|
||||
break;
|
||||
default: /* '?' */
|
||||
fprintf(stderr, "Usage: %s [-v] [-i] [-a HEX] [-x HEX] [-y HEX] [-s HEX] [-p HEX] [-g|-r ADDR] file.rom\nThe first 16k of \"file.rom\" is loaded into the last 16k of memory.\n",
|
||||
argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if (optind >= argc) {
|
||||
fprintf(stderr, "Expected argument after options\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (load_rom(argv[optind]) != 0) {
|
||||
printf("Error loading \"%s\".\n", argv[optind]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (load_rom(argv[1]) != 0) {
|
||||
printf("Error loading \"%s\".\n", argv[1]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
raw_stdin(); // allow individual keystrokes to be detected
|
||||
if (interactive) raw_stdin(); // allow individual keystrokes to be detected
|
||||
|
||||
init_tables();
|
||||
init_uart();
|
||||
|
||||
reset_cpu();
|
||||
run_cpu();
|
||||
reset_cpu(a, x, y, sp, sr, pc);
|
||||
run_cpu(verbose, mem_dump);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
47
6502.c
47
6502.c
@ -833,18 +833,21 @@ void init_tables() // this is only done at runtime to improve code readability.
|
||||
instructions[0xFF] = (Instruction) {"???", inst_NOP, IMPL, 1};
|
||||
}
|
||||
|
||||
void reset_cpu()
|
||||
void reset_cpu(int _a, int _x, int _y, int _sp, int _sr, int _pc)
|
||||
{
|
||||
A = 0;
|
||||
X = 0;
|
||||
Y = 0;
|
||||
SP = 0xFF;
|
||||
A = _a;
|
||||
X = _x;
|
||||
Y = _y;
|
||||
SP = _sp;
|
||||
|
||||
SR.byte = 0;
|
||||
SR.byte = _sr;
|
||||
SR.bits.interrupt = 1;
|
||||
SR.bits.unused = 1;
|
||||
|
||||
memcpy(&PC, &memory[RST_VEC], sizeof(PC));
|
||||
if (_pc < 0)
|
||||
memcpy(&PC, &memory[-_pc], sizeof(PC));
|
||||
else
|
||||
PC = _pc;
|
||||
}
|
||||
|
||||
int load_rom(char * filename)
|
||||
@ -866,20 +869,21 @@ int load_rom(char * filename)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int step_cpu() // returns cycle count
|
||||
int step_cpu(int verbose) // returns cycle count
|
||||
{
|
||||
inst = instructions[memory[PC]];
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("PC=%04X OPCODE=%02X: %s\r\n", PC, memory[PC], inst.mnemonic);
|
||||
printf("A=%02X X=%02X Y=%02X SR=%02X SP=%02X\r\n", A, X, Y, SR.byte, SP);
|
||||
|
||||
/* dump memory for analysis (slows down emulation significantly) */
|
||||
|
||||
FILE * fp = fopen("memdump", "w");
|
||||
fwrite(&memory, sizeof(memory), 1, fp);
|
||||
fclose(fp);
|
||||
#endif
|
||||
if (verbose) {
|
||||
// almost match for NES dump for easier comparison
|
||||
printf("%04X ", PC);
|
||||
if (lengths[inst.mode] == 3)
|
||||
printf("%02X %02X %02X", memory[PC], memory[PC+1], memory[PC+2]);
|
||||
else if (lengths[inst.mode] == 2)
|
||||
printf("%02X %02X ", memory[PC], memory[PC+1]);
|
||||
else
|
||||
printf("%02X ", memory[PC]);
|
||||
printf(" %-10s A:%02X X:%02X Y:%02X P:%02X SP:%02X CYC:%03d\n", inst.mnemonic, A, X, Y, SR.byte, SP, 0);
|
||||
}
|
||||
|
||||
jumping = 0;
|
||||
inst.function();
|
||||
@ -887,3 +891,10 @@ int step_cpu() // returns cycle count
|
||||
|
||||
return inst.cycles;
|
||||
}
|
||||
|
||||
void save_memory(char * filename) { // dump memory for analysis (slows down emulation significantly)
|
||||
if (filename == NULL) filename = "memdump";
|
||||
FILE * fp = fopen(filename, "w");
|
||||
fwrite(&memory, sizeof(memory), 1, fp);
|
||||
fclose(fp);
|
||||
}
|
||||
|
6
6502.h
6
6502.h
@ -65,8 +65,10 @@ Instruction instructions[0x100];
|
||||
|
||||
void init_tables();
|
||||
|
||||
void reset_cpu();
|
||||
void reset_cpu(int _a, int _x, int _y, int _sp, int _sr, int _pc);
|
||||
|
||||
int load_rom(char * filename);
|
||||
|
||||
int step_cpu();
|
||||
int step_cpu(int verbose);
|
||||
|
||||
void save_memory(char * filename);
|
||||
|
Loading…
Reference in New Issue
Block a user