blob: 7619fe2698d6c74c9fda5f2e43c0a309b995a147 [file] [log] [blame]
#include "common.h"
#include "cpu.h"
#include "dbg.h"
#include "gui.h"
#include "screen.h"
#include <bits/getopt_core.h>
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <mqueue.h>
#include <sys/stat.h>
void cleanup_screen_thread(pthread_t thread)
{
puts("Cleaning up screen...");
pthread_cancel(thread);
}
void cleanup_debug_prompt_thread(pthread_t thread)
{
puts("Cleaning up debug prompt...");
pthread_cancel(thread);
}
int main(int argc, char **argv)
{
bool disflag = false,
runflag = false,
helpflag = false,
debugflag = false,
should_read = false,
guiflag = false,
scrflag = false,
nohaltflag = false;
int disasm_len = 0;
FILE *input = stdin;
char c;
while ((c = getopt(argc, argv, "HDsdrhgi:n:")) != -1)
{
switch (c)
{
case 'H':
nohaltflag = true;
break;
case 'd':
disflag = true;
should_read = true;
break;
case 'r':
runflag = true;
should_read = true;
break;
case 'D':
debugflag = true;
should_read = true;
break;
case 'g':
guiflag = true;
should_read = true;
break;
case 'i':
input = fopen(optarg, "r");
break;
case 'n':
disasm_len = atoi(optarg);
break;
case 's':
scrflag = true;
break;
case 'h':
case '?':
helpflag = 1;
break;
}
}
if (helpflag)
{
printf("6502 emulator, disassembler and debugger\n"
"Usage:\n"
" -g use GUI\n"
" -s use SDL screen (faster than GUI debugger)\n"
" -H keep running after CPU halts (useful on windows and to look at screen)\n"
" -d disassemble input\n"
" -r run input\n"
" -D open CLI debug prompt (like gdb)\n"
" -i <input> set input file, defaults to standard input\n"
" -n <number> number of instructions to disassemble, 0 for all\n"
" -h, -? show this help page\n");
return 0;
}
cpu_t cpu;
mqd_t mq_to_cpu;
struct mq_attr attrs;
attrs.mq_maxmsg = 10;
attrs.mq_msgsize = MQ_BUF_LEN;
if (should_read)
{
cpu = new_cpu();
fread(cpu.mem + 0x600, 0xFFFF - 0x600, 1, input);
int unlink = mq_unlink(MQ_NAME);
if (unlink < 0 && errno != ENOENT)
{
printf("Warning: mq_unlink() error: %d %s\n", errno, strerror(errno));
}
mq_to_cpu = mq_open(MQ_NAME, O_RDWR | O_CREAT | O_NONBLOCK, S_IWUSR|S_IRUSR, &attrs);
printf("error after mq_open (%ld) = %d %s\n", attrs.mq_msgsize, errno, strerror(errno));
ASSERT("Open message queue for emulator", mq_to_cpu > 0)
mq_send(mq_to_cpu, "init", 5, 2);
}
else
{
puts("6502 toolchain by swissChili <swisschili.sh>");
printf("%s -h for help\n", argv[0]);
}
if (scrflag)
{
CATCH(&cleanup_screen_thread, start_screen_thread(cpu.mem + CPU_FB_ADDR));
}
if (guiflag && scrflag)
{
THROW("-g and -s cannot be used together");
}
if (guiflag)
{
start_gui(mq_to_cpu, &cpu);
run_mq(&cpu, mq_to_cpu);
}
else if (disflag)
{
disas_num(&cpu, 64);
}
else if (runflag)
{
run(&cpu);
if (nohaltflag)
{
puts("Press any key to exit");
getchar();
}
}
else if (debugflag)
{
CATCH(&cleanup_debug_prompt_thread, start_debug_prompt(mq_to_cpu, &cpu));
run_mq(&cpu, mq_to_cpu);
}
unwind();
if (should_read)
{
free_cpu(&cpu);
mq_close(mq_to_cpu);
}
}