diff --git a/.gitignore b/.gitignore index c3c12cf..3934525 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,7 @@ *.o emu816 +/.vs +/Debug +/examples/simple/simple.obj +/emu816.VC.VC.opendb +/emu816.VC.db diff --git a/README.md b/README.md index 36e25a4..3146008 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,23 @@ -# emu816 -A C++ based 65C816 Emulator +# emu816 - A C++ based 65C816 Emulator + +The repository contains the source code for a simple 65C816 emulator for Windows, +Linux and the embedded ChipKIT platform. + +This is the first release of the code and it has only had a limited amount of +testing. Currently there is no support for decimal arithmetic but the full +instruction set is supported. + +There is no I/O at the moment or source of interrupts. Executing a WDM #$FF will +cause the emulator to exit. + +## Building + +The code is provided with a Visual Studio project for Windows and a Makefile for +Linux plaforms. + +A (very) simple example built with my DEV65 assembler is provided in the examples +folder. Use the following command to run it. + +``` +emu816 -t examples/simple/simple.s28 +``` diff --git a/emu816.cc b/emu816.cc index 45a7786..399d6d4 100644 --- a/emu816.cc +++ b/emu816.cc @@ -1,10 +1,30 @@ +//============================================================================== +// .ooooo. .o .ooo +// d88' `8. o888 .88' +// .ooooo. ooo. .oo. .oo. oooo oooo Y88.. .8' 888 d88' +// d88' `88b `888P"Y88bP"Y88b `888 `888 `88888b. 888 d888P"Ybo. +// 888ooo888 888 888 888 888 888 .8' ``88b 888 Y88[ ]88 +// 888 .o 888 888 888 888 888 `8. .88P 888 `Y88 88P +// `Y8bod8P' o888o o888o o888o `V88V"V8P' `boood8' o888o `88bod8' +// +// A Portable C++ WDC 65C816 Emulator +//------------------------------------------------------------------------------ +// Copyright (C)2016 Andrew John Jacobs +// All rights reserved. +// +// This work is made available under the terms of the Creative Commons +// Attribution-NonCommercial-ShareAlike 4.0 International license. Open the +// following URL to see the details. +// +// http://creativecommons.org/licenses/by-nc-sa/4.0/ +//------------------------------------------------------------------------------ // TODO: decimal mode #include "emu816.h" #ifdef CHIPKIT -#include "WProgram.h" +# include "WProgram.h" #else # include # include @@ -13,16 +33,18 @@ using namespace std; #endif //============================================================================== -//------------------------------------------------------------------------------ +// Construct a emu816 instance. emu816::emu816(mem816 &mem) : mem(mem) { } +// Destroy a emu816 instance. emu816::~emu816() { } -void emu816::reset() +// Reset the state of emulator +void emu816::reset(bool trace) { e = 1; pbr = 0x00 << 16; @@ -33,8 +55,11 @@ void emu816::reset() p.b = 0x34; interrupted = false; + + this -> trace = trace; } +// Execute a single instruction or invoke an interrupt void emu816::step() { // Check for NMI/IRQ @@ -322,7 +347,11 @@ void emu816::step() // Debugging Utilities //------------------------------------------------------------------------------ +// The ChipKIT versions of the debugging functions output to the serial monitor +// rather than standard output. + #ifdef CHIPKIT +// The current PC and opcode byte void emu816::show() { Serial.print (toHex(pbr, 2)); @@ -332,6 +361,7 @@ void emu816::show() Serial.print (toHex(mem.getByte(join(pbr, pc)), 2)); } +// Display the operand bytes void emu816::bytes(unsigned int count) { if (count > 0) { @@ -358,6 +388,7 @@ void emu816::bytes(unsigned int count) Serial.print(' '); } +// Display registers and top of stack void emu816::dump(const char *mnem, Addr ea) { Serial.print(mnem); @@ -444,6 +475,7 @@ void emu816::dump(const char *mnem, Addr ea) Serial.print(toHex(dbr, 2)); } #else +// The current PC and opcode byte void emu816::show() { cout << toHex(pbr, 2); @@ -451,6 +483,7 @@ void emu816::show() cout << ' ' << toHex(mem.getByte(join(pbr, pc)), 2); } +// Display the operand bytes void emu816::bytes(unsigned int count) { if (count > 0) @@ -471,6 +504,7 @@ void emu816::bytes(unsigned int count) cout << ' '; } +// Display registers and top of stack void emu816::dump(const char *mnem, Addr ea) { cout << mnem << " {" << toHex(ea, 4) << '}'; @@ -518,4 +552,4 @@ void emu816::dump(const char *mnem, Addr ea) cout << " }"; cout << " DBR=" << toHex(dbr, 2); } -#endif +#endif \ No newline at end of file diff --git a/emu816.h b/emu816.h index 0443cea..3db6962 100644 --- a/emu816.h +++ b/emu816.h @@ -1,15 +1,39 @@ -#ifndef EMU816 -#define EMU816 +//============================================================================== +// .ooooo. .o .ooo +// d88' `8. o888 .88' +// .ooooo. ooo. .oo. .oo. oooo oooo Y88.. .8' 888 d88' +// d88' `88b `888P"Y88bP"Y88b `888 `888 `88888b. 888 d888P"Ybo. +// 888ooo888 888 888 888 888 888 .8' ``88b 888 Y88[ ]88 +// 888 .o 888 888 888 888 888 `8. .88P 888 `Y88 88P +// `Y8bod8P' o888o o888o o888o `V88V"V8P' `boood8' o888o `88bod8' +// +// A Portable C++ WDC 65C816 Emulator +//------------------------------------------------------------------------------ +// Copyright (C)2016 Andrew John Jacobs +// All rights reserved. +// +// This work is made available under the terms of the Creative Commons +// Attribution-NonCommercial-ShareAlike 4.0 International license. Open the +// following URL to see the details. +// +// http://creativecommons.org/licenses/by-nc-sa/4.0/ +//------------------------------------------------------------------------------ + +#ifndef EMU816_H +#define EMU816_H + #include "mem816.h" +#include + #if 1 -# define TRACE(MNEM) { dump(MNEM, ea); } -# define BYTES(N) { bytes(N); pc += N; } -# define SHOWPC() { show(); } +# define TRACE(MNEM) { if (trace) dump(MNEM, ea); } +# define BYTES(N) { if (trace) bytes(N); pc += N; } +# define SHOWPC() { if (trace) show(); } # ifdef CHIPKIT # define ENDL() { Serial.println (); } # else -# define ENDL() { cout << endl; } +# define ENDL() { if (trace) cout << endl; } # endif #else # define TRACE(MNEM) @@ -25,7 +49,7 @@ public: emu816(mem816 &mem); ~emu816(); - void reset(); + void reset(bool trace); void step(); private: @@ -57,11 +81,13 @@ private: bool interrupted; unsigned long cycles; + bool trace; void show(); void bytes(unsigned int); void dump(const char *, Addr); + // Push a byte on the stack INLINE void pushByte(Byte value) { mem.setByte(sp.w, value); @@ -72,12 +98,14 @@ private: --sp.w; } + // Push a word on the stack INLINE void pushWord(Word value) { pushByte(hi(value)); pushByte(lo(value)); } + // Pull a byte from the stack INLINE Byte pullByte() { if (e) @@ -88,6 +116,7 @@ private: return (mem.getByte(sp.w)); } + // Pull a word from the stack INLINE Word pullWord() { register Byte l = pullByte(); @@ -292,6 +321,7 @@ private: return (ea); } + // Long Relative - d INLINE Addr am_lrel() { Word disp = mem.getWord(bank(pbr) | pc); @@ -300,6 +330,7 @@ private: return (bank(pbr) | (Word)(pc + (signed short)disp)); } + // Relative - d INLINE Addr am_rela() { Byte disp = mem.getByte(bank(pbr) | pc); @@ -337,42 +368,50 @@ private: return (bank(dbr) | (Word)(ia + y.w)); } + // Set the Negative flag INLINE void setn(unsigned int flag) { p.f_n = flag ? 1 : 0; } + // Set the Overflow flag INLINE void setv(unsigned int flag) { p.f_v = flag ? 1 : 0; } + // Set the decimal flag INLINE void setd(unsigned int flag) { p.f_d = flag ? 1 : 0; } + // Set the Interrupt Disable flag INLINE void seti(unsigned int flag) { p.f_i = flag ? 1 : 0; } + // Set the Zero flag INLINE void setz(unsigned int flag) { p.f_z = flag ? 1 : 0; } + // Set the Carry flag INLINE void setc(unsigned int flag) { p.f_c = flag ? 1 : 0; } + // Set the Negative and Zero flags from a byte value INLINE void setnz_b(Byte value) { setn(value & 0x80); setz(value == 0); } + // Set the Negative and Zero flags from a word value INLINE void setnz_w(Word value) { setn(value & 0x8000); @@ -1441,6 +1480,10 @@ private: INLINE void op_wdm(Addr ea) { TRACE("WDM"); + + switch (mem.getByte(ea)) { + case 0xff: exit(0); + } } INLINE void op_xba(Addr ea) diff --git a/emu816.sln b/emu816.sln new file mode 100644 index 0000000..6185cf8 --- /dev/null +++ b/emu816.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25123.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "emu816", "emu816.vcxproj", "{49047D22-8F3C-48BB-B93A-36CC9981114E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {49047D22-8F3C-48BB-B93A-36CC9981114E}.Debug|x64.ActiveCfg = Debug|x64 + {49047D22-8F3C-48BB-B93A-36CC9981114E}.Debug|x64.Build.0 = Debug|x64 + {49047D22-8F3C-48BB-B93A-36CC9981114E}.Debug|x86.ActiveCfg = Debug|Win32 + {49047D22-8F3C-48BB-B93A-36CC9981114E}.Debug|x86.Build.0 = Debug|Win32 + {49047D22-8F3C-48BB-B93A-36CC9981114E}.Release|x64.ActiveCfg = Release|x64 + {49047D22-8F3C-48BB-B93A-36CC9981114E}.Release|x64.Build.0 = Release|x64 + {49047D22-8F3C-48BB-B93A-36CC9981114E}.Release|x86.ActiveCfg = Release|Win32 + {49047D22-8F3C-48BB-B93A-36CC9981114E}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/emu816.vcxproj b/emu816.vcxproj new file mode 100644 index 0000000..c1f6d72 --- /dev/null +++ b/emu816.vcxproj @@ -0,0 +1,158 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {49047D22-8F3C-48BB-B93A-36CC9981114E} + Win32Proj + emu816 + 8.1 + + + + Application + true + v140 + Unicode + + + Application + false + v140 + true + Unicode + + + Application + true + v140 + Unicode + + + Application + false + v140 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + + + Level3 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/emu816.vcxproj.filters b/emu816.vcxproj.filters new file mode 100644 index 0000000..30163f9 --- /dev/null +++ b/emu816.vcxproj.filters @@ -0,0 +1,42 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/emu816.vcxproj.user b/emu816.vcxproj.user new file mode 100644 index 0000000..4ec55d7 --- /dev/null +++ b/emu816.vcxproj.user @@ -0,0 +1,7 @@ + + + + -t examples\simple\simple.s28 + WindowsLocalDebugger + + \ No newline at end of file diff --git a/examples/Dev65.jar b/examples/Dev65.jar new file mode 100644 index 0000000..4b52f76 Binary files /dev/null and b/examples/Dev65.jar differ diff --git a/examples/Makefile b/examples/Makefile new file mode 100644 index 0000000..dd2e9b3 --- /dev/null +++ b/examples/Makefile @@ -0,0 +1,48 @@ +#=============================================================================== +# DEV65 Build Rules +#------------------------------------------------------------------------------- +# Copyright (C),2015-2016 HandCoded Software Ltd. +# All rights reserved. +# +# This work is made available under the terms of the Creative Commons +# Attribution-NonCommercial 2.0 license. Open the following URL to see the +# details. +# +# http://creativecommons.org/licenses/by-nc/2.0/ +#------------------------------------------------------------------------------- +# +# Notes: +# +# +#------------------------------------------------------------------------------- + +# Update the following line to reflect where you have installed the ZIP file +# containing the JAVA classes relative to where the assembler is invoked. + +DEV65_DIR = .. + +#=============================================================================== + +DEV65_JAR = $(DEV65_DIR)/Dev65.jar + +AS65_CLASS = uk.co.demon.obelisk.w65xx.As65 + +LK65_CLASS = uk.co.demon.obelisk.w65xx.Lk65 + +LB65_CLASS = uk.co.demon.obelisk.w65xx.Lb65 + +AS65 = java -cp $(DEV65_JAR) $(AS65_CLASS) + +LK65 = java -cp $(DEV65_JAR) $(LK65_CLASS) + +LB65 = java -cp $(DEV65_JAR) $(LB65_CLASS) + +RM = erase + +#=============================================================================== +# Rules +#------------------------------------------------------------------------------- + +.asm.obj: + $(AS65) $(AS65_FLAGS) $< + diff --git a/examples/NMAKE.ERR b/examples/NMAKE.ERR new file mode 100644 index 0000000..7de37c5 --- /dev/null +++ b/examples/NMAKE.ERR @@ -0,0 +1,129 @@ +1000 "syntax error : ')' missing in macro invocation" +1001 "syntax error : illegal character '%c' in macro" +1002 "syntax error : invalid macro invocation '$'" +1003 "syntax error : '=' missing in macro" +1004 "syntax error : macro name missing" +1005 "syntax error : text must follow ':' in macro" +1006 "syntax error : missing closing double quotation mark" +1007 "double quotation mark not allowed in name" +1017 "unknown directive '!%s'" +1018 "directive and/or expression part missing" +1019 "too many nested !IF blocks" +1020 "end-of-file found before next directive" +1021 "syntax error : !ELSE unexpected" +1022 "missing terminating character for string/program invocation : '%c'" +1023 "syntax error in expression" +1024 "illegal argument to !CMDSWITCHES" +1031 "filename missing (or macro is null)" +1033 "syntax error : '%s' unexpected" +1034 "syntax error : separator missing" +1035 "syntax error : expected ':' or '=' separator" +1036 "syntax error : too many names to left of '='" +1037 "syntax error : target name missing" +1038 "internal error : lexer" +1039 "internal error : parser" +1040 "internal error : macro expansion" +1041 "internal error : target building" +1042 "internal error : expression stack overflow" +1043 "internal error : temp file limit exceeded" +1045 "spawn failed : %s" +1046 "internal error : out of search handles" +1047 "argument before ')' expands to nothing" +1048 "cannot write to file '%s'" +1049 "macro or inline file too long (maximum : 64K)" +1050 "%s" +1051 "out of memory" +1052 "file '%s' not found" +1053 "file '%s' unreadable" +1054 "cannot create inline file '%s'" +1055 "out of environment space" +1056 "cannot find command processor" +1057 "cannot delete temporary file '%s'" +1058 "terminated by user" +1059 "syntax error : '}' missing in dependent" +1060 "unable to close file : '%s'" +1061 "/F option requires a filename" +1062 "missing filename with /X option" +1063 "missing macro name before '='" +1064 "MAKEFILE not found and no target specified" +1065 "invalid option '%c'" +1069 "no match found for wildcard '%s'" +1070 "cycle in macro definition '%s'" +1071 "cycle in dependency tree for target '%s'" +1072 "cycle in include files : '%s'" +1073 "don't know how to make '%s'" +1076 "name too long" +1077 "'%s' : return code '0x%x'" +1078 "constant overflow at '%s'" +1079 "illegal expression : divide by zero" +1080 "operator and/or operand usage illegal" +1081 "'%s' : program not found" +1082 "'%s' : cannot execute command; out of memory" +1083 "target macro '%s' expands to nothing" +1084 "cannot create temporary file '%s'" +1085 "cannot mix implicit and explicit rules" +1086 "inference rule cannot have dependents" +1087 "cannot have : and :: dependents for same target" +1088 "invalid separator '::' on inference rule" +1089 "cannot have build commands for directive '%s'" +1090 "cannot have dependents for directive '%s'" +1092 "too many names in rule" +1093 "cannot mix dot directives" +1094 "syntax error : only (NO)KEEP allowed here" +1095 "expanded command line '%s' too long" +1096 "cannot open inline file '%s'" +1097 "filename-parts syntax requires dependent" +1098 "illegal filename-parts syntax in '%s'" +2001 "no more file handles (too many files open)" +4001 "command file can be invoked only from command line" +4002 "resetting value of special macro '%s'" +4004 "too many rules for target '%s'" +4005 "ignoring rule '%s' (extension not in .SUFFIXES)" +4006 "special macro undefined : '%s'" +4007 "filename '%s' too long; truncating to 8.3" +4008 "removed target '%s'" +4010 "'%s' : build failed; /K specified, continuing ..." +4011 "'%s' : not all dependents available; target not built" +1 "file %s doesn't exist" +2 "'%s' is up-to-date" +3 "** %s newer than %s" +4 "%*s%-14s %*s" +5 "\ttouch %s" +6 "%*s%-14s target does not exist" +7 "\nINFERENCE RULES:\n" +8 "\nMACROS:\n" +9 "\nTARGETS:\n" +10 "\n\tcommands:\t" +11 "\n\tflags:\t" +12 "\n\tdependents:\t" +13 "%s\n" +14 "%13s = %s\n" +15 "Building: %s" +20 "fatal error" +21 "error" +22 "warning" +23 "Stop.\n" +24 "Microsoft (R) Program Maintenance Utility Version %s" +25 "Copyright (c) Microsoft Corp %s. All rights reserved.\n" +100 "Usage: %s @commandfile" +101 "\t%s [options] [/f makefile] [/x stderrfile] [macrodefs] [targets]\n" +102 "Options:\n" +103 "/A Build all evaluated targets" +104 "/B Build if time stamps are equal" +105 "/C Suppress output messages" +106 "/D Display build information" +107 "/E Override env-var macros" +108 "/HELP Display brief usage message" +109 "/I Ignore exit codes from commands" +110 "/K Build unrelated targets on error" +111 "/M Ignore extended/expanded memory" +112 "/N Display commands but do not execute" +113 "/NOLOGO Suppress copyright message" +114 "/P Display NMAKE information" +115 "/Q Check time stamps but do not build" +116 "/R Ignore predefined rules/macros" +117 "/S Suppress executed-commands display" +118 "/T Change time stamps but do not build" +119 "/V Inherit macros during recursion" +120 "/? Display brief usage message\n" +125 "%-39s%s" diff --git a/examples/NMAKE.EXE b/examples/NMAKE.EXE new file mode 100644 index 0000000..b1497ce Binary files /dev/null and b/examples/NMAKE.EXE differ diff --git a/examples/simple/Makefile b/examples/simple/Makefile new file mode 100644 index 0000000..f170429 --- /dev/null +++ b/examples/simple/Makefile @@ -0,0 +1,48 @@ +#=============================================================================== +# Makefile for Simple Example +#------------------------------------------------------------------------------- +# Copyright (C)2016 HandCoded Software Ltd. +# All rights reserved. +# +# This work is made available under the terms of the Creative Commons +# Attribution-NonCommercial 2.0 license. Open the following URL to see the +# details. +# +# http://creativecommons.org/licenses/by-nc/2.0/ +#------------------------------------------------------------------------------- +# +# Notes: +# +# +#------------------------------------------------------------------------------- + +include ../Makefile + +#=============================================================================== +# Targets +#------------------------------------------------------------------------------- + +OBJS = \ + simple.obj + + +all: simple.s28 + +clean: + $(RM) *.obj + $(RM) *.bin + $(RM) *.hex + $(RM) *.txt + $(RM) *.lst + $(RM) *.map + $(RM) *.s28 + +simple.s28: $(OBJS) + $(LK65) -bss $$0000-$$7FFF -code $$F000-$$FFFF -s28 -output $@ $(OBJS) + +#=============================================================================== +# Dependencies +#------------------------------------------------------------------------------- + +simple.obj: \ + simple.asm ..\w65c816.inc diff --git a/examples/simple/clean.bat b/examples/simple/clean.bat new file mode 100644 index 0000000..c018af5 --- /dev/null +++ b/examples/simple/clean.bat @@ -0,0 +1,2 @@ +..\nmake clean +if errorlevel 1 pause \ No newline at end of file diff --git a/examples/simple/make.bat b/examples/simple/make.bat new file mode 100644 index 0000000..8a8b960 --- /dev/null +++ b/examples/simple/make.bat @@ -0,0 +1,2 @@ +..\nmake %* +if errorlevel 1 pause \ No newline at end of file diff --git a/examples/simple/simple.asm b/examples/simple/simple.asm new file mode 100644 index 0000000..14dfe23 --- /dev/null +++ b/examples/simple/simple.asm @@ -0,0 +1,99 @@ +;=============================================================================== +; +; A Simple W65C816 Program +;------------------------------------------------------------------------------- +; Copyright (C),2016 HandCoded Software Ltd. +; All rights reserved. +; +; This work is made available under the terms of the Creative Commons +; Attribution-NonCommercial 2.0 license. Open the following URL to see the +; details. +; +; http://creativecommons.org/licenses/by-nc/2.0/ +;------------------------------------------------------------------------------- +; +; Notes: +; +; +; +;------------------------------------------------------------------------------- + + .include "../w65c816.inc" + + .page0 + +;=============================================================================== +; Memory Areas +;------------------------------------------------------------------------------- + + .space 128 +STACK: ; Top of stack area + +;=============================================================================== +; Power On Reset Handler +;------------------------------------------------------------------------------- + + .code + .org $f000 + + .longa off + .longi off +RESET: + sei + cld + native + long_ai + + lda #STACK + tcs + + ldy #2 + repeat + ldx #123 + repeat + dex + until eq + dey + until eq + wdm #$ff + +;=============================================================================== +; Dummy Interrupt Handlers +;------------------------------------------------------------------------------- + +IRQN: +COPN: +ABORTN: +NMIN: +BRKN + bra $ + +COP: +ABORT: +NMI: +IRQBRK: + bra $ + +;=============================================================================== +; Vectors +;------------------------------------------------------------------------------- + + .org $ffe0 + + .space 4 ; Reserved + .word COPN ; $FFE4 - COP(816) + .word BRKN ; $FFE6 - BRK(816) + .word ABORTN ; $FFE8 - ABORT(816) + .word NMIN ; $FFEA - NMI(816) + .space 2 ; Reserved + .word IRQN ; $FFEE - IRQ(816) + + .space 4 + .word COP ; $FFF4 - COP(C02) + .space 2 ; $Reserved + .word ABORT ; $FFF8 - ABORT(C02) + .word NMI ; $FFFA - NMI(C02) + .word RESET ; $FFFC - RESET(C02) + .word IRQBRK ; $FFFE - IRQBRK(C02) + + .end \ No newline at end of file diff --git a/examples/simple/simple.lst b/examples/simple/simple.lst new file mode 100644 index 0000000..a29c3a1 --- /dev/null +++ b/examples/simple/simple.lst @@ -0,0 +1,255 @@ + +Portable 65xx Assembler [16.06] + + ;=============================================================================== + ; + ; A Simple W65C816 Program + ;------------------------------------------------------------------------------- + ; Copyright (C),2016 HandCoded Software Ltd. + ; All rights reserved. + ; + ; This work is made available under the terms of the Creative Commons + ; Attribution-NonCommercial 2.0 license. Open the following URL to see the + ; details. + ; + ; http://creativecommons.org/licenses/by-nc/2.0/ + ;------------------------------------------------------------------------------- + ; + ; Notes: + ; + ; + ; + ;------------------------------------------------------------------------------- + + .include "../w65c816.inc" + ;=============================================================================== + ; __ ____ ____ ____ ___ _ __ + ; \ \ / / /_| ___| / ___( _ )/ |/ /_ + ; \ \ /\ / / '_ \___ \| | / _ \| | '_ \ + ; \ V V /| (_) |__) | |__| (_) | | (_) | + ; \_/\_/ \___/____/ \____\___/|_|\___/ + ; + ; Western Design Center W65C816 device definitions + ;------------------------------------------------------------------------------- + ; Copyright (C)2015 HandCoded Software Ltd. + ; All rights reserved. + ; + ; This work is made available under the terms of the Creative Commons + ; Attribution-NonCommercial-ShareAlike 4.0 International license. Open the + ; following URL to see the details. + ; + ; http://creativecommons.org/licenses/by-nc-sa/4.0/ + ; + ;=============================================================================== + ; Notes: + ; + ; Various macros and definitions for the W65C816 microcontroller. + ; + ;=============================================================================== + ; Revision History: + ; + ; 2015-12-18 AJ Initial version + ;------------------------------------------------------------------------------- + ; $Id$ + ;------------------------------------------------------------------------------- + + .65816 + + +Portable 65xx Assembler [16.06] + + ;=============================================================================== + ; Status Register Bits + ;------------------------------------------------------------------------------- + + 00000080 = N_FLAG .equ 1<<7 + 00000040 = V_FLAG .equ 1<<6 + 00000020 = M_FLAG .equ 1<<5 + 00000010 = X_FLAG .equ 1<<4 + 00000010 = B_FLAG .equ 1<<4 + 00000008 = D_FLAG .equ 1<<3 + 00000004 = I_FLAG .equ 1<<2 + 00000002 = Z_FLAG .equ 1<<1 + 00000001 = C_FLAG .equ 1<<0 + + ;============================================================================== + ; Macros + ;------------------------------------------------------------------------------ + + ; Puts the processor in emulation mode. A, X and Y become 8-bits and the stack + ; is fixed at $0100-$01ff. + + emulate .macro + sec + xce + .endm + + ; Puts the processor in native mode. The size of the memory and index register + ; operations is not controlled by the M & X bits in the status register. + + native .macro + clc + xce + .endm + + ; Resets the M bit making the accumator and memory accesses 16-bits wide. + + long_a .macro + rep #M_FLAG + .longa on + .endm + + ; Resets the X bit making the index registers 16-bits wide + + long_i .macro + rep #X_FLAG + .longi on + .endm + + ; Resets the M and X bits making the accumator, memory accesses and index + ; registers 16-bits wide. + + long_ai .macro + rep #M_FLAG|X_FLAG + .longa on + +Portable 65xx Assembler [16.06] + + .longi on + .endm + + ; Sets the M bit making the accumator and memory accesses 16-bits wide. + + short_a .macro + sep #M_FLAG + .longa off + .endm + + short_i .macro + sep #X_FLAG + .longi off + .endm + + short_ai .macro + sep #M_FLAG|X_FLAG + .longa off + .longi off + .endm + + .page0 + + ;=============================================================================== + ; Memory Areas + ;------------------------------------------------------------------------------- + +00:0000' 0000000000000000> : .space 128 + STACK: ; Top of stack area + + ;=============================================================================== + ; Power On Reset Handler + ;------------------------------------------------------------------------------- + + .code + .org $f000 + + .longa off + .longi off + RESET: +00:F000 78 : sei +00:F001 D8 : cld + native +00:F002 18 + clc +00:F003 FB + xce + long_ai +00:F004 C230 + rep #M_FLAG|X_FLAG + + .longa on + + .longi on + +00:F006 A9???? : lda #STACK +00:F009 1B : tcs + +00:F00A A00200 : ldy #2 + +Portable 65xx Assembler [16.06] + + repeat +00:F00D A27B00 : ldx #123 + repeat +00:F010 CA : dex +00:F011 D0FD : until eq +00:F013 88 : dey +00:F014 D0F7 : until eq +00:F016 42FF : wdm #$ff + + ;=============================================================================== + ; Dummy Interrupt Handlers + ;------------------------------------------------------------------------------- + + IRQN: + COPN: + ABORTN: + NMIN: + BRKN +00:F018 80FE : bra $ + + COP: + ABORT: + NMI: + IRQBRK: +00:F01A 80FE : bra $ + + ;=============================================================================== + ; Vectors + ;------------------------------------------------------------------------------- + + .org $ffe0 + +00:FFE0 00000000 : .space 4 ; Reserved +00:FFE4 18F0 : .word COPN ; $FFE4 - COP(816) +00:FFE6 18F0 : .word BRKN ; $FFE6 - BRK(816) +00:FFE8 18F0 : .word ABORTN ; $FFE8 - ABORT(816) +00:FFEA 18F0 : .word NMIN ; $FFEA - NMI(816) +00:FFEC 0000 : .space 2 ; Reserved +00:FFEE 18F0 : .word IRQN ; $FFEE - IRQ(816) + +00:FFF0 00000000 : .space 4 +00:FFF4 1AF0 : .word COP ; $FFF4 - COP(C02) +00:FFF6 0000 : .space 2 ; $Reserved +00:FFF8 1AF0 : .word ABORT ; $FFF8 - ABORT(C02) +00:FFFA 1AF0 : .word NMI ; $FFFA - NMI(C02) +00:FFFC 00F0 : .word RESET ; $FFFC - RESET(C02) +00:FFFE 1AF0 : .word IRQBRK ; $FFFE - IRQBRK(C02) + + .end + + +Portable 65xx Assembler [16.06] + +Symbol Table + +ABORT 0000F01A | __6501__ 00000000 +ABORTN 0000F018 | __6502__ 00000000 +BRKN 0000F018 | __65832__ 00000000 +B_FLAG 00000010 | __65C02__ 00000000 +COP 0000F01A | __65SC02__ 00000000 +COPN 0000F018 | C_FLAG 00000001 +C_FLAG 00000001 | __65816__ 00000001 +D_FLAG 00000008 | Z_FLAG 00000002 +IRQBRK 0000F01A | I_FLAG 00000004 +IRQN 0000F018 | D_FLAG 00000008 +I_FLAG 00000004 | B_FLAG 00000010 +M_FLAG 00000020 | X_FLAG 00000010 +NMI 0000F01A | M_FLAG 00000020 +NMIN 0000F018 | V_FLAG 00000040 +N_FLAG 00000080 | N_FLAG 00000080 +RESET 0000F000 | STACK 00000080' +STACK 00000080' | RESET 0000F000 +V_FLAG 00000040 | ABORTN 0000F018 +X_FLAG 00000010 | BRKN 0000F018 +Z_FLAG 00000002 | COPN 0000F018 +__6501__ 00000000 | IRQN 0000F018 +__6502__ 00000000 | NMIN 0000F018 +__65816__ 00000001 | ABORT 0000F01A +__65832__ 00000000 | COP 0000F01A +__65C02__ 00000000 | IRQBRK 0000F01A +__65SC02__ 00000000 | NMI 0000F01A diff --git a/examples/simple/simple.map b/examples/simple/simple.map new file mode 100644 index 0000000..6fb2003 --- /dev/null +++ b/examples/simple/simple.map @@ -0,0 +1,9 @@ +Global Symbol Map + + + +Sections: + +.page0 : 00000000 - 0000007F in simple.obj +.code : 0000F000 - 0000F01B in simple.obj + 0000FFE0 - 0000FFFF in simple.obj diff --git a/examples/simple/simple.s28 b/examples/simple/simple.s28 new file mode 100644 index 0000000..0bcf3a5 --- /dev/null +++ b/examples/simple/simple.s28 @@ -0,0 +1,130 @@ +S22400F00078D818FBC230A980001BA00200A27B00CAD0FD88D0F742FF80FE80FE0000000070 +S22400F0200000000000000000000000000000000000000000000000000000000000000000CB +S22400F0400000000000000000000000000000000000000000000000000000000000000000AB +S22400F06000000000000000000000000000000000000000000000000000000000000000008B +S22400F08000000000000000000000000000000000000000000000000000000000000000006B +S22400F0A000000000000000000000000000000000000000000000000000000000000000004B +S22400F0C000000000000000000000000000000000000000000000000000000000000000002B +S22400F0E000000000000000000000000000000000000000000000000000000000000000000B +S22400F1000000000000000000000000000000000000000000000000000000000000000000EA +S22400F1200000000000000000000000000000000000000000000000000000000000000000CA +S22400F1400000000000000000000000000000000000000000000000000000000000000000AA +S22400F16000000000000000000000000000000000000000000000000000000000000000008A +S22400F18000000000000000000000000000000000000000000000000000000000000000006A +S22400F1A000000000000000000000000000000000000000000000000000000000000000004A +S22400F1C000000000000000000000000000000000000000000000000000000000000000002A +S22400F1E000000000000000000000000000000000000000000000000000000000000000000A +S22400F2000000000000000000000000000000000000000000000000000000000000000000E9 +S22400F2200000000000000000000000000000000000000000000000000000000000000000C9 +S22400F2400000000000000000000000000000000000000000000000000000000000000000A9 +S22400F260000000000000000000000000000000000000000000000000000000000000000089 +S22400F280000000000000000000000000000000000000000000000000000000000000000069 +S22400F2A0000000000000000000000000000000000000000000000000000000000000000049 +S22400F2C0000000000000000000000000000000000000000000000000000000000000000029 +S22400F2E0000000000000000000000000000000000000000000000000000000000000000009 +S22400F3000000000000000000000000000000000000000000000000000000000000000000E8 +S22400F3200000000000000000000000000000000000000000000000000000000000000000C8 +S22400F3400000000000000000000000000000000000000000000000000000000000000000A8 +S22400F360000000000000000000000000000000000000000000000000000000000000000088 +S22400F380000000000000000000000000000000000000000000000000000000000000000068 +S22400F3A0000000000000000000000000000000000000000000000000000000000000000048 +S22400F3C0000000000000000000000000000000000000000000000000000000000000000028 +S22400F3E0000000000000000000000000000000000000000000000000000000000000000008 +S22400F4000000000000000000000000000000000000000000000000000000000000000000E7 +S22400F4200000000000000000000000000000000000000000000000000000000000000000C7 +S22400F4400000000000000000000000000000000000000000000000000000000000000000A7 +S22400F460000000000000000000000000000000000000000000000000000000000000000087 +S22400F480000000000000000000000000000000000000000000000000000000000000000067 +S22400F4A0000000000000000000000000000000000000000000000000000000000000000047 +S22400F4C0000000000000000000000000000000000000000000000000000000000000000027 +S22400F4E0000000000000000000000000000000000000000000000000000000000000000007 +S22400F5000000000000000000000000000000000000000000000000000000000000000000E6 +S22400F5200000000000000000000000000000000000000000000000000000000000000000C6 +S22400F5400000000000000000000000000000000000000000000000000000000000000000A6 +S22400F560000000000000000000000000000000000000000000000000000000000000000086 +S22400F580000000000000000000000000000000000000000000000000000000000000000066 +S22400F5A0000000000000000000000000000000000000000000000000000000000000000046 +S22400F5C0000000000000000000000000000000000000000000000000000000000000000026 +S22400F5E0000000000000000000000000000000000000000000000000000000000000000006 +S22400F6000000000000000000000000000000000000000000000000000000000000000000E5 +S22400F6200000000000000000000000000000000000000000000000000000000000000000C5 +S22400F6400000000000000000000000000000000000000000000000000000000000000000A5 +S22400F660000000000000000000000000000000000000000000000000000000000000000085 +S22400F680000000000000000000000000000000000000000000000000000000000000000065 +S22400F6A0000000000000000000000000000000000000000000000000000000000000000045 +S22400F6C0000000000000000000000000000000000000000000000000000000000000000025 +S22400F6E0000000000000000000000000000000000000000000000000000000000000000005 +S22400F7000000000000000000000000000000000000000000000000000000000000000000E4 +S22400F7200000000000000000000000000000000000000000000000000000000000000000C4 +S22400F7400000000000000000000000000000000000000000000000000000000000000000A4 +S22400F760000000000000000000000000000000000000000000000000000000000000000084 +S22400F780000000000000000000000000000000000000000000000000000000000000000064 +S22400F7A0000000000000000000000000000000000000000000000000000000000000000044 +S22400F7C0000000000000000000000000000000000000000000000000000000000000000024 +S22400F7E0000000000000000000000000000000000000000000000000000000000000000004 +S22400F8000000000000000000000000000000000000000000000000000000000000000000E3 +S22400F8200000000000000000000000000000000000000000000000000000000000000000C3 +S22400F8400000000000000000000000000000000000000000000000000000000000000000A3 +S22400F860000000000000000000000000000000000000000000000000000000000000000083 +S22400F880000000000000000000000000000000000000000000000000000000000000000063 +S22400F8A0000000000000000000000000000000000000000000000000000000000000000043 +S22400F8C0000000000000000000000000000000000000000000000000000000000000000023 +S22400F8E0000000000000000000000000000000000000000000000000000000000000000003 +S22400F9000000000000000000000000000000000000000000000000000000000000000000E2 +S22400F9200000000000000000000000000000000000000000000000000000000000000000C2 +S22400F9400000000000000000000000000000000000000000000000000000000000000000A2 +S22400F960000000000000000000000000000000000000000000000000000000000000000082 +S22400F980000000000000000000000000000000000000000000000000000000000000000062 +S22400F9A0000000000000000000000000000000000000000000000000000000000000000042 +S22400F9C0000000000000000000000000000000000000000000000000000000000000000022 +S22400F9E0000000000000000000000000000000000000000000000000000000000000000002 +S22400FA000000000000000000000000000000000000000000000000000000000000000000E1 +S22400FA200000000000000000000000000000000000000000000000000000000000000000C1 +S22400FA400000000000000000000000000000000000000000000000000000000000000000A1 +S22400FA60000000000000000000000000000000000000000000000000000000000000000081 +S22400FA80000000000000000000000000000000000000000000000000000000000000000061 +S22400FAA0000000000000000000000000000000000000000000000000000000000000000041 +S22400FAC0000000000000000000000000000000000000000000000000000000000000000021 +S22400FAE0000000000000000000000000000000000000000000000000000000000000000001 +S22400FB000000000000000000000000000000000000000000000000000000000000000000E0 +S22400FB200000000000000000000000000000000000000000000000000000000000000000C0 +S22400FB400000000000000000000000000000000000000000000000000000000000000000A0 +S22400FB60000000000000000000000000000000000000000000000000000000000000000080 +S22400FB80000000000000000000000000000000000000000000000000000000000000000060 +S22400FBA0000000000000000000000000000000000000000000000000000000000000000040 +S22400FBC0000000000000000000000000000000000000000000000000000000000000000020 +S22400FBE0000000000000000000000000000000000000000000000000000000000000000000 +S22400FC000000000000000000000000000000000000000000000000000000000000000000DF +S22400FC200000000000000000000000000000000000000000000000000000000000000000BF +S22400FC4000000000000000000000000000000000000000000000000000000000000000009F +S22400FC6000000000000000000000000000000000000000000000000000000000000000007F +S22400FC8000000000000000000000000000000000000000000000000000000000000000005F +S22400FCA000000000000000000000000000000000000000000000000000000000000000003F +S22400FCC000000000000000000000000000000000000000000000000000000000000000001F +S22400FCE00000000000000000000000000000000000000000000000000000000000000000FF +S22400FD000000000000000000000000000000000000000000000000000000000000000000DE +S22400FD200000000000000000000000000000000000000000000000000000000000000000BE +S22400FD4000000000000000000000000000000000000000000000000000000000000000009E +S22400FD6000000000000000000000000000000000000000000000000000000000000000007E +S22400FD8000000000000000000000000000000000000000000000000000000000000000005E +S22400FDA000000000000000000000000000000000000000000000000000000000000000003E +S22400FDC000000000000000000000000000000000000000000000000000000000000000001E +S22400FDE00000000000000000000000000000000000000000000000000000000000000000FE +S22400FE000000000000000000000000000000000000000000000000000000000000000000DD +S22400FE200000000000000000000000000000000000000000000000000000000000000000BD +S22400FE4000000000000000000000000000000000000000000000000000000000000000009D +S22400FE6000000000000000000000000000000000000000000000000000000000000000007D +S22400FE8000000000000000000000000000000000000000000000000000000000000000005D +S22400FEA000000000000000000000000000000000000000000000000000000000000000003D +S22400FEC000000000000000000000000000000000000000000000000000000000000000001D +S22400FEE00000000000000000000000000000000000000000000000000000000000000000FD +S22400FF000000000000000000000000000000000000000000000000000000000000000000DC +S22400FF200000000000000000000000000000000000000000000000000000000000000000BC +S22400FF4000000000000000000000000000000000000000000000000000000000000000009C +S22400FF6000000000000000000000000000000000000000000000000000000000000000007C +S22400FF8000000000000000000000000000000000000000000000000000000000000000005C +S22400FFA000000000000000000000000000000000000000000000000000000000000000003C +S22400FFC000000000000000000000000000000000000000000000000000000000000000001C +S22400FFE00000000018F018F018F018F0000018F0000000001AF000001AF01AF000F01AF0BC +S505000000807A +S80400F0000B diff --git a/examples/w65c816.inc b/examples/w65c816.inc new file mode 100644 index 0000000..fb369b0 --- /dev/null +++ b/examples/w65c816.inc @@ -0,0 +1,107 @@ +;=============================================================================== +; __ ____ ____ ____ ___ _ __ +; \ \ / / /_| ___| / ___( _ )/ |/ /_ +; \ \ /\ / / '_ \___ \| | / _ \| | '_ \ +; \ V V /| (_) |__) | |__| (_) | | (_) | +; \_/\_/ \___/____/ \____\___/|_|\___/ +; +; Western Design Center W65C816 device definitions +;------------------------------------------------------------------------------- +; Copyright (C)2015 HandCoded Software Ltd. +; All rights reserved. +; +; This work is made available under the terms of the Creative Commons +; Attribution-NonCommercial-ShareAlike 4.0 International license. Open the +; following URL to see the details. +; +; http://creativecommons.org/licenses/by-nc-sa/4.0/ +; +;=============================================================================== +; Notes: +; +; Various macros and definitions for the W65C816 microcontroller. +; +;=============================================================================== +; Revision History: +; +; 2015-12-18 AJ Initial version +;------------------------------------------------------------------------------- +; $Id$ +;------------------------------------------------------------------------------- + + .65816 + +;=============================================================================== +; Status Register Bits +;------------------------------------------------------------------------------- + +N_FLAG .equ 1<<7 +V_FLAG .equ 1<<6 +M_FLAG .equ 1<<5 +X_FLAG .equ 1<<4 +B_FLAG .equ 1<<4 +D_FLAG .equ 1<<3 +I_FLAG .equ 1<<2 +Z_FLAG .equ 1<<1 +C_FLAG .equ 1<<0 + +;============================================================================== +; Macros +;------------------------------------------------------------------------------ + +; Puts the processor in emulation mode. A, X and Y become 8-bits and the stack +; is fixed at $0100-$01ff. + +emulate .macro + sec + xce + .endm + +; Puts the processor in native mode. The size of the memory and index register +; operations is not controlled by the M & X bits in the status register. + +native .macro + clc + xce + .endm + +; Resets the M bit making the accumator and memory accesses 16-bits wide. + +long_a .macro + rep #M_FLAG + .longa on + .endm + +; Resets the X bit making the index registers 16-bits wide + +long_i .macro + rep #X_FLAG + .longi on + .endm + +; Resets the M and X bits making the accumator, memory accesses and index +; registers 16-bits wide. + +long_ai .macro + rep #M_FLAG|X_FLAG + .longa on + .longi on + .endm + +; Sets the M bit making the accumator and memory accesses 16-bits wide. + +short_a .macro + sep #M_FLAG + .longa off + .endm + +short_i .macro + sep #X_FLAG + .longi off + .endm + +short_ai .macro + sep #M_FLAG|X_FLAG + .longa off + .longi off + .endm diff --git a/mem816.cc b/mem816.cc index 56b9bc3..1c30831 100644 --- a/mem816.cc +++ b/mem816.cc @@ -1,15 +1,42 @@ +//============================================================================== +// .ooooo. .o .ooo +// d88' `8. o888 .88' +// .ooooo. ooo. .oo. .oo. oooo oooo Y88.. .8' 888 d88' +// d88' `88b `888P"Y88bP"Y88b `888 `888 `88888b. 888 d888P"Ybo. +// 888ooo888 888 888 888 888 888 .8' ``88b 888 Y88[ ]88 +// 888 .o 888 888 888 888 888 `8. .88P 888 `Y88 88P +// `Y8bod8P' o888o o888o o888o `V88V"V8P' `boood8' o888o `88bod8' +// +// A Portable C++ WDC 65C816 Emulator +//------------------------------------------------------------------------------ +// Copyright (C)2016 Andrew John Jacobs +// All rights reserved. +// +// This work is made available under the terms of the Creative Commons +// Attribution-NonCommercial-ShareAlike 4.0 International license. Open the +// following URL to see the details. +// +// http://creativecommons.org/licenses/by-nc-sa/4.0/ +//------------------------------------------------------------------------------ #include "mem816.h" +//============================================================================== + +// Construct a memory area using dynamic allocation mem816::mem816(Addr memMask, Addr ramSize, const Byte *pROM) - : memMask(memMask), ramSize(ramSize), pROM(pROM) + : memMask(memMask), ramSize(ramSize), pROM(pROM), freeRAM(true) { pRAM = new Byte[ramSize]; } +// Construct a memory area using statically allocated arrays mem816::mem816(Addr memMask, Addr ramSize, Byte *pRAM, const Byte *pROM) - : memMask(memMask), ramSize(ramSize), pRAM (pRAM), pROM(pROM) + : memMask(memMask), ramSize(ramSize), pRAM(pRAM), pROM(pROM), freeRAM(false) { } +// Destory an instance releasing the RAM if allocated. mem816::~mem816() -{ } +{ + if (freeRAM) delete pRAM; +} \ No newline at end of file diff --git a/mem816.h b/mem816.h index 2fb4f93..99f5387 100644 --- a/mem816.h +++ b/mem816.h @@ -1,5 +1,27 @@ -#ifndef MEM816 -#define MEM816 +//============================================================================== +// .ooooo. .o .ooo +// d88' `8. o888 .88' +// .ooooo. ooo. .oo. .oo. oooo oooo Y88.. .8' 888 d88' +// d88' `88b `888P"Y88bP"Y88b `888 `888 `88888b. 888 d888P"Ybo. +// 888ooo888 888 888 888 888 888 .8' ``88b 888 Y88[ ]88 +// 888 .o 888 888 888 888 888 `8. .88P 888 `Y88 88P +// `Y8bod8P' o888o o888o o888o `V88V"V8P' `boood8' o888o `88bod8' +// +// A Portable C++ WDC 65C816 Emulator +//------------------------------------------------------------------------------ +// Copyright (C)2016 Andrew John Jacobs +// All rights reserved. +// +// This work is made available under the terms of the Creative Commons +// Attribution-NonCommercial-ShareAlike 4.0 International license. Open the +// following URL to see the details. +// +// http://creativecommons.org/licenses/by-nc-sa/4.0/ +//------------------------------------------------------------------------------ + +#ifndef MEM816_H +#define MEM816_H + #include "wdc816.h" class mem816 : @@ -46,5 +68,7 @@ private: Byte *pRAM; const Byte *pROM; + + const bool freeRAM; }; #endif diff --git a/program.cc b/program.cc index 8ef756c..f64b31e 100644 --- a/program.cc +++ b/program.cc @@ -1,3 +1,23 @@ +//============================================================================== +// .ooooo. .o .ooo +// d88' `8. o888 .88' +// .ooooo. ooo. .oo. .oo. oooo oooo Y88.. .8' 888 d88' +// d88' `88b `888P"Y88bP"Y88b `888 `888 `88888b. 888 d888P"Ybo. +// 888ooo888 888 888 888 888 888 .8' ``88b 888 Y88[ ]88 +// 888 .o 888 888 888 888 888 `8. .88P 888 `Y88 88P +// `Y8bod8P' o888o o888o o888o `V88V"V8P' `boood8' o888o `88bod8' +// +// A Portable C++ WDC 65C816 Emulator +//------------------------------------------------------------------------------ +// Copyright (C)2016 Andrew John Jacobs +// All rights reserved. +// +// This work is made available under the terms of the Creative Commons +// Attribution-NonCommercial-ShareAlike 4.0 International license. Open the +// following URL to see the details. +// +// http://creativecommons.org/licenses/by-nc-sa/4.0/ +//------------------------------------------------------------------------------ #include #include @@ -9,36 +29,34 @@ using namespace std; #include "emu816.h" //============================================================================== -// Memory Definitions and Access +// Memory Definitions //------------------------------------------------------------------------------ -#define RAM_SIZE (384 * 1024) -#define ROM_SIZE (128 * 1024L) +// On Windows/Linux create a 512Kb RAM area - No ROM. +#define RAM_SIZE (512 * 1024) #define MEM_MASK (512 * 1024L - 1) -// The ROM area 128K -const wdc816::Byte ROM[ROM_SIZE] = -{ - 0x00, 0x00, 0x00, -}; - -mem816 mem(MEM_MASK, RAM_SIZE, ROM); +mem816 mem(MEM_MASK, RAM_SIZE, NULL); emu816 emu(mem); -//============================================================================== -//------------------------------------------------------------------------------ +bool trace = false; +//============================================================================== + +// Initialise the emulator void setup() { - emu.reset(); + emu.reset(trace); } +// Execute instructions void loop() { emu.step(); } //============================================================================== +// S28 Record Loader //------------------------------------------------------------------------------ unsigned int toNybble(char ch) @@ -66,6 +84,10 @@ unsigned long toAddr(string &str, int &offset) return (h | m | l); } +//============================================================================== +// Command Handler +//------------------------------------------------------------------------------ + void load(char *filename) { ifstream file(filename); @@ -86,18 +108,46 @@ void load(char *filename) } } } + file.close(); } + else + cerr << "Failed to open file" << endl; - file.close(); } int main(int argc, char **argv) { - for (int index = 1; index < argc;) - load(argv[index++]); + int index = 1; + + while (index < argc) { + if (argv[index][0] != '-') break; + + if (!strcmp(argv[index], "-t")) { + trace = true; + ++index; + continue; + } + + if (!strcmp(argv[index], "-?")) { + cerr << "Usage: emu816 [-t] s28-file ..." << endl; + return (1); + } + + cerr << "Invalid: option '" << argv[index] << "'" << endl; + return (1); + } + + if (index < argc) + do { + load(argv[index++]); + } while (index < argc); + else { + cerr << "No S28 files specified" << endl; + return (1); + } setup(); for (;;) loop(); return(0); -} +} \ No newline at end of file diff --git a/wdc816.cc b/wdc816.cc index e306c10..3a0b388 100644 --- a/wdc816.cc +++ b/wdc816.cc @@ -1,3 +1,24 @@ +//============================================================================== +// .ooooo. .o .ooo +// d88' `8. o888 .88' +// .ooooo. ooo. .oo. .oo. oooo oooo Y88.. .8' 888 d88' +// d88' `88b `888P"Y88bP"Y88b `888 `888 `88888b. 888 d888P"Ybo. +// 888ooo888 888 888 888 888 888 .8' ``88b 888 Y88[ ]88 +// 888 .o 888 888 888 888 888 `8. .88P 888 `Y88 88P +// `Y8bod8P' o888o o888o o888o `V88V"V8P' `boood8' o888o `88bod8' +// +// A Portable C++ WDC 65C816 Emulator +//------------------------------------------------------------------------------ +// Copyright (C)2016 Andrew John Jacobs +// All rights reserved. +// +// This work is made available under the terms of the Creative Commons +// Attribution-NonCommercial-ShareAlike 4.0 International license. Open the +// following URL to see the details. +// +// http://creativecommons.org/licenses/by-nc-sa/4.0/ +//------------------------------------------------------------------------------ + #include "wdc816.h" wdc816::wdc816() @@ -6,6 +27,7 @@ wdc816::wdc816() wdc816::~wdc816() { } +// Convert a value to a hex string char *wdc816::toHex(unsigned long value, unsigned int digits) { static char buffer[16]; @@ -17,4 +39,4 @@ char *wdc816::toHex(unsigned long value, unsigned int digits) value >>= 4; } return (&(buffer[offset])); -} +} \ No newline at end of file diff --git a/wdc816.h b/wdc816.h index 8cf963a..405ec15 100644 --- a/wdc816.h +++ b/wdc816.h @@ -1,12 +1,33 @@ -#ifndef WDC816 -#define WDC816 +//============================================================================== +// .ooooo. .o .ooo +// d88' `8. o888 .88' +// .ooooo. ooo. .oo. .oo. oooo oooo Y88.. .8' 888 d88' +// d88' `88b `888P"Y88bP"Y88b `888 `888 `88888b. 888 d888P"Ybo. +// 888ooo888 888 888 888 888 888 .8' ``88b 888 Y88[ ]88 +// 888 .o 888 888 888 888 888 `8. .88P 888 `Y88 88P +// `Y8bod8P' o888o o888o o888o `V88V"V8P' `boood8' o888o `88bod8' +// +// A Portable C++ WDC 65C816 Emulator +//------------------------------------------------------------------------------ +// Copyright (C)2016 Andrew John Jacobs +// All rights reserved. +// +// This work is made available under the terms of the Creative Commons +// Attribution-NonCommercial-ShareAlike 4.0 International license. Open the +// following URL to see the details. +// +// http://creativecommons.org/licenses/by-nc-sa/4.0/ +//------------------------------------------------------------------------------ + +#ifndef WDC816_H +#define WDC816_H //#define CHIPKIT #ifdef CHIPKIT -#define INLINE inline +# define INLINE inline #else -#define INLINE inline +# define INLINE inline #endif class wdc816 @@ -60,4 +81,4 @@ public: return ((value >> 8) | (value << 8)); } }; -#endif +#endif \ No newline at end of file