mirror of
https://github.com/DavidBuchanan314/6502-emu.git
synced 2024-12-27 19:29:38 +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 <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
@ -18,14 +19,15 @@ void step_delay()
|
|||||||
nanosleep(&req, &rem);
|
nanosleep(&req, &rem);
|
||||||
}
|
}
|
||||||
|
|
||||||
void run_cpu()
|
void run_cpu(int verbose, int mem_dump)
|
||||||
{
|
{
|
||||||
int cycles = 0;
|
int cycles = 0;
|
||||||
int cycles_per_step = (CPU_FREQ / (ONE_SECOND / STEP_DURATION));
|
int cycles_per_step = (CPU_FREQ / (ONE_SECOND / STEP_DURATION));
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
for (cycles %= cycles_per_step; cycles < cycles_per_step;) {
|
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_uart();
|
||||||
}
|
}
|
||||||
step_delay(); // remove this for more speed
|
step_delay(); // remove this for more speed
|
||||||
@ -48,26 +50,82 @@ void raw_stdin()
|
|||||||
atexit(restore_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[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
if (argc != 2) {
|
int a, x, y, sp, sr, pc;
|
||||||
printf("Usage: %s file.rom\n", argv[0]);
|
int verbose, interactive, mem_dump;
|
||||||
printf("The first 16k of \"file.rom\" is loaded into the last 16k of memory.\n");
|
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;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (load_rom(argv[1]) != 0) {
|
if (interactive) raw_stdin(); // allow individual keystrokes to be detected
|
||||||
printf("Error loading \"%s\".\n", argv[1]);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
raw_stdin(); // allow individual keystrokes to be detected
|
|
||||||
|
|
||||||
init_tables();
|
init_tables();
|
||||||
init_uart();
|
init_uart();
|
||||||
|
|
||||||
reset_cpu();
|
reset_cpu(a, x, y, sp, sr, pc);
|
||||||
run_cpu();
|
run_cpu(verbose, mem_dump);
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
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};
|
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;
|
A = _a;
|
||||||
X = 0;
|
X = _x;
|
||||||
Y = 0;
|
Y = _y;
|
||||||
SP = 0xFF;
|
SP = _sp;
|
||||||
|
|
||||||
SR.byte = 0;
|
SR.byte = _sr;
|
||||||
SR.bits.interrupt = 1;
|
SR.bits.interrupt = 1;
|
||||||
SR.bits.unused = 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)
|
int load_rom(char * filename)
|
||||||
@ -866,20 +869,21 @@ int load_rom(char * filename)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int step_cpu() // returns cycle count
|
int step_cpu(int verbose) // returns cycle count
|
||||||
{
|
{
|
||||||
inst = instructions[memory[PC]];
|
inst = instructions[memory[PC]];
|
||||||
|
|
||||||
#ifdef DEBUG
|
if (verbose) {
|
||||||
printf("PC=%04X OPCODE=%02X: %s\r\n", PC, memory[PC], inst.mnemonic);
|
// almost match for NES dump for easier comparison
|
||||||
printf("A=%02X X=%02X Y=%02X SR=%02X SP=%02X\r\n", A, X, Y, SR.byte, SP);
|
printf("%04X ", PC);
|
||||||
|
if (lengths[inst.mode] == 3)
|
||||||
/* dump memory for analysis (slows down emulation significantly) */
|
printf("%02X %02X %02X", memory[PC], memory[PC+1], memory[PC+2]);
|
||||||
|
else if (lengths[inst.mode] == 2)
|
||||||
FILE * fp = fopen("memdump", "w");
|
printf("%02X %02X ", memory[PC], memory[PC+1]);
|
||||||
fwrite(&memory, sizeof(memory), 1, fp);
|
else
|
||||||
fclose(fp);
|
printf("%02X ", memory[PC]);
|
||||||
#endif
|
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;
|
jumping = 0;
|
||||||
inst.function();
|
inst.function();
|
||||||
@ -887,3 +891,10 @@ int step_cpu() // returns cycle count
|
|||||||
|
|
||||||
return inst.cycles;
|
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 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 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