2015-09-13 00:09:01 +00:00
//
// main.c
// apple1
//
// Created by Daniel Loffgren on 9/12/15.
// Copyright (c) 2015 Daniel Loffgren. All rights reserved.
//
2015-09-14 00:09:42 +00:00
# include <stdio.h>
2015-09-14 00:28:23 +00:00
# include <unistd.h>
2015-09-18 07:16:14 +00:00
# include <histedit.h>
2015-09-18 08:49:26 +00:00
# include <signal.h>
2015-09-18 07:16:14 +00:00
# include <stdlib.h>
2015-09-14 00:42:17 +00:00
# include <dis6502/reverse.h>
2015-09-17 04:20:15 +00:00
# include <v6502/log.h>
2015-09-18 07:16:14 +00:00
# include <v6502/debugger.h>
# include <v6502/cpu.h>
# include <v6502/mem.h>
# include <as6502/error.h>
2015-12-09 02:27:13 +00:00
# include <as6502/linectl.h>
2015-09-18 07:16:14 +00:00
# include "pia.h"
2015-09-14 00:09:42 +00:00
2015-12-22 08:08:31 +00:00
# define BASIC_LOAD_ADDRESS 0xE000
2015-09-14 01:13:54 +00:00
# define ROM_START 0xF000
# define ROM_SIZE 0x00FF
# define RESET_VECTOR 0xFF00
2015-09-19 05:36:29 +00:00
# define DEBUGGER_MESSAGE " [ Hit ` for debugger ] "
2015-09-13 00:09:01 +00:00
2015-09-18 07:16:14 +00:00
static v6502_cpu * cpu ;
static a1pia * pia ;
2015-09-19 05:36:29 +00:00
static int consoleMessageSeen ;
2015-09-25 07:58:08 +00:00
static as6502_symbol_table * table ;
2015-09-29 07:45:47 +00:00
static v6502_breakpoint_list * breakpoint_list ;
2015-12-09 02:27:13 +00:00
static int continuousMode ;
2015-09-18 07:16:14 +00:00
static void fault ( void * ctx , const char * e ) {
2015-09-13 00:17:41 +00:00
( * ( int * ) ctx ) + + ;
}
2015-09-18 07:16:14 +00:00
//static uint8_t romMirrorCallback(struct _v6502_memory *memory, uint16_t offset, int trap, void *context) {
// return memory->bytes[offset % ROM_SIZE];
//}
static void run ( v6502_cpu * cpu ) {
2015-09-18 08:29:31 +00:00
int faulted = 0 ;
cpu - > fault_callback = fault ;
cpu - > fault_context = & faulted ;
2015-09-18 07:16:14 +00:00
FILE * asmfile = fopen ( " runtime.s " , " w " ) ;
2015-12-09 02:27:13 +00:00
pia_start ( pia , continuousMode ) ;
2015-12-10 01:25:30 +00:00
// Step once (since the PIA is now up) to escape debugger traps if we happened to be resumed from a breakpoint
v6502_step ( cpu ) ;
2015-09-19 05:36:29 +00:00
// This depends on the fact that pia_start will get curses up and going
if ( ! consoleMessageSeen ) {
wmove ( pia - > screen , getmaxy ( pia - > screen ) - 1 , getmaxx ( pia - > screen ) - sizeof ( DEBUGGER_MESSAGE ) ) ;
attron ( A_REVERSE ) ;
wprintw ( pia - > screen , DEBUGGER_MESSAGE ) ;
attroff ( A_REVERSE ) ;
wmove ( pia - > screen , 0 , 0 ) ;
consoleMessageSeen + + ;
}
2015-09-18 08:29:31 +00:00
while ( ! faulted & & ! pia - > signalled ) {
2015-09-29 07:45:47 +00:00
if ( v6502_breakpointIsInList ( breakpoint_list , cpu - > pc ) ) {
pia_stop ( pia ) ;
fclose ( asmfile ) ;
printf ( " Hit breakpoint at 0x%02x. \n " , cpu - > pc ) ;
return ;
}
2016-01-17 09:29:10 +00:00
//dis6502_printAnnotatedInstruction(asmfile, cpu, cpu->pc, table);
2015-09-18 07:16:14 +00:00
v6502_step ( cpu ) ;
2016-01-17 09:29:10 +00:00
//v6502_printCpuState(asmfile, cpu);
2015-09-14 00:09:42 +00:00
}
2015-09-18 07:16:14 +00:00
pia_stop ( pia ) ;
fclose ( asmfile ) ;
2015-09-14 00:09:42 +00:00
}
2015-09-18 07:16:14 +00:00
static const char * prompt ( ) {
static char prompt [ 10 ] ;
snprintf ( prompt , 10 , " (0x%04x) " , cpu - > pc ) ;
return prompt ;
2015-09-14 00:09:42 +00:00
}
2015-09-13 00:17:41 +00:00
int main ( int argc , const char * argv [ ] )
{
2015-09-18 18:56:40 +00:00
currentFileName = " apple1 " ;
2015-09-18 07:16:14 +00:00
cpu = v6502_createCPU ( ) ;
2015-09-19 05:11:53 +00:00
printf ( " Allocating 64k of memory... \n " ) ;
2015-09-14 00:28:23 +00:00
cpu - > memory = v6502_createMemory ( v6502_memoryStartCeiling + 1 ) ;
2016-01-17 09:29:10 +00:00
cpu - > memory - > mapCacheEnabled = YES ;
2015-09-19 05:11:53 +00:00
2015-09-29 07:45:47 +00:00
breakpoint_list = v6502_createBreakpointList ( ) ;
2015-09-25 07:58:08 +00:00
table = as6502_createSymbolTable ( ) ;
2015-09-14 00:09:42 +00:00
// Load Woz Monitor
2015-09-19 05:11:53 +00:00
printf ( " Loading ROM... \n " ) ;
2015-09-23 07:29:18 +00:00
v6502_loadFileAtAddress ( cpu - > memory , " apple1.rom " , RESET_VECTOR ) ;
//v6502_map(cpu->memory, start, ROM_SIZE, romMirrorCallback, NULL, NULL);
2015-12-22 08:13:21 +00:00
// Load integer BASIC
FILE * file = fopen ( " apple1basic.bin " , " r " ) ;
2015-09-26 23:30:03 +00:00
if ( file ) {
fclose ( file ) ;
2015-12-22 08:13:21 +00:00
printf ( " Loading BASIC... \n " ) ;
v6502_loadFileAtAddress ( cpu - > memory , " apple1basic.bin " , BASIC_LOAD_ADDRESS ) ;
2015-09-26 23:30:03 +00:00
}
2015-12-22 08:13:21 +00:00
// Load debugger script
int verbose = 0 ;
file = fopen ( " apple1.dbg " , " r " ) ;
2015-12-22 08:08:31 +00:00
if ( file ) {
2015-12-22 08:13:21 +00:00
printf ( " Executing debugger script... \n " ) ;
v6502_runDebuggerScript ( cpu , file , breakpoint_list , table , run , & verbose ) ;
2015-12-22 08:08:31 +00:00
fclose ( file ) ;
}
2015-09-14 00:28:23 +00:00
// Attach PIA
2015-09-19 05:11:53 +00:00
printf ( " Initializing PIA... \n " ) ;
2015-12-19 23:29:19 +00:00
pia = pia_create ( cpu ) ;
2015-09-14 00:28:23 +00:00
2015-09-19 05:11:53 +00:00
printf ( " Resetting CPU... \n " ) ;
2015-09-13 00:17:41 +00:00
v6502_reset ( cpu ) ;
2015-09-19 05:11:53 +00:00
printf ( " Running... \n " ) ;
run ( cpu ) ;
2015-09-18 07:16:14 +00:00
int commandLen ;
HistEvent ev ;
History * hist = history_init ( ) ;
history ( hist , & ev , H_SETSIZE , 100 ) ;
2015-09-18 18:56:40 +00:00
EditLine * el = el_init ( currentFileName , stdin , stdout , stderr ) ;
2015-09-18 07:16:14 +00:00
el_set ( el , EL_PROMPT , & prompt ) ;
el_set ( el , EL_SIGNAL , SIGWINCH ) ;
el_set ( el , EL_EDITOR , " emacs " ) ;
el_set ( el , EL_HIST , history , hist ) ;
char * command = NULL ;
while ( ! feof ( stdin ) ) {
currentLineNum + + ;
const char * in = el_gets ( el , & commandLen ) ;
if ( ! in ) {
break ;
}
history ( hist , & ev , H_ENTER , in ) ;
command = realloc ( command , commandLen + 1 ) ;
memcpy ( command , in , commandLen ) ;
// Trim newline, always the last char
command [ commandLen - 1 ] = ' \0 ' ;
if ( command [ 0 ] = = ' \0 ' ) {
continue ;
}
2015-09-25 07:58:08 +00:00
if ( v6502_handleDebuggerCommand ( cpu , command , commandLen , breakpoint_list , table , run , & verbose ) ) {
2015-09-26 20:09:56 +00:00
if ( v6502_compareDebuggerCommand ( command , commandLen , " help " ) ) {
printf ( " woz Print relevant woz monitor parameters and registers. \n " ) ;
2015-12-09 02:27:13 +00:00
printf ( " nonstop Read or toggle nonstop mode. Nonstop mode is considerably less efficient, but may be required for some software that expects runtime to continue while simultaneously waiting for keyboard input. \n " ) ;
2015-12-19 23:43:16 +00:00
printf ( " freeze <filename> Dump the entire contents of memory, and the current cpu state, into a file for later loading. \n " ) ;
printf ( " restore <filename> Restore memory and cpu state from a freeze file. \n " ) ;
2015-09-26 20:09:56 +00:00
}
2015-09-18 07:16:14 +00:00
continue ;
}
2015-09-26 20:09:56 +00:00
else if ( v6502_compareDebuggerCommand ( command , commandLen , " woz " ) ) {
printf ( " KBD 0x%02x \n "
" XAML 0x%02x \n "
" XAMH 0x%02x \n "
" STL 0x%02x \n "
" STH 0x%02x \n "
" L 0x%02x \n "
" H 0x%02x \n "
" YSAV 0x%02x \n "
" MODE 0x%02x \n " ,
v6502_read ( cpu - > memory , A1PIA_KEYBOARD_INPUT_REGISTER , NO ) ,
v6502_read ( cpu - > memory , 0x24 , NO ) , // XAML
v6502_read ( cpu - > memory , 0x25 , NO ) , // XAMH
v6502_read ( cpu - > memory , 0x26 , NO ) , // STL
v6502_read ( cpu - > memory , 0x27 , NO ) , // STH
v6502_read ( cpu - > memory , 0x28 , NO ) , // L
v6502_read ( cpu - > memory , 0x29 , NO ) , // H
v6502_read ( cpu - > memory , 0x2A , NO ) , // YSAV
v6502_read ( cpu - > memory , 0x2B , NO ) ) ; // MODE
}
2015-12-09 02:27:13 +00:00
else if ( v6502_compareDebuggerCommand ( command , commandLen , " nonstop " ) ) {
// command = trimheadtospc(command, commandLen);
//
// if(command[0]) {
printf ( " Nonstop mode %d -> %d \n " , continuousMode , ! continuousMode ) ;
continuousMode = ! continuousMode ;
// }
// else {
// printf("Currently set to %d", continuousMode);
// }
}
2015-12-19 23:43:16 +00:00
else if ( v6502_compareDebuggerCommand ( command , commandLen , " freeze " ) ) {
command = trimheadtospc ( command , commandLen ) ;
if ( command [ 0 ] ) {
saveFreeze ( pia , command ) ;
}
else {
printf ( " A filename is required to save freeze. \n " ) ;
}
}
else if ( v6502_compareDebuggerCommand ( command , commandLen , " restore " ) ) {
command = trimheadtospc ( command , commandLen ) ;
if ( command [ 0 ] ) {
loadFreeze ( pia , command ) ;
}
else {
printf ( " A filename is required to load freeze. \n " ) ;
}
}
2015-09-18 07:16:14 +00:00
else if ( command [ 0 ] ! = ' ; ' ) {
2015-09-20 03:58:59 +00:00
currentLineText = command ;
2015-09-18 07:16:14 +00:00
as6502_executeAsmLineOnCPU ( cpu , command , strlen ( command ) ) ;
}
2015-09-13 00:17:41 +00:00
}
2015-09-25 07:58:08 +00:00
as6502_destroySymbolTable ( table ) ;
2015-09-18 07:16:14 +00:00
v6502_destroyBreakpointList ( breakpoint_list ) ;
history_end ( hist ) ;
el_end ( el ) ;
free ( command ) ;
2015-09-14 01:33:42 +00:00
pia_destroy ( pia ) ;
2015-09-13 00:17:41 +00:00
v6502_destroyMemory ( cpu - > memory ) ;
v6502_destroyCPU ( cpu ) ;
2015-09-18 07:16:14 +00:00
printf ( " \n " ) ;
return EXIT_SUCCESS ;
2015-09-13 00:09:01 +00:00
}