diff --git a/.gitignore b/.gitignore index e089905..17ca9e0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ **/build *.xcuserstate +*.xcbkptlist diff --git a/Makefile b/Makefile index e45a8f5..af0c3b8 100644 --- a/Makefile +++ b/Makefile @@ -33,7 +33,7 @@ install: -cd ./build && cmake -P cmake_install.cmake reformat: - qasm -r src/main.s + qasm -x REFORMAT src/main.s asm: diff --git a/asm.cpp b/asm.cpp index 22118e9..9df2c41 100644 --- a/asm.cpp +++ b/asm.cpp @@ -163,6 +163,7 @@ void CLASS::clear() outbytes.clear(); addressmode = 0; expr_value = 0; + eval_result = 0; flags = 0; outbytes.clear(); } @@ -451,7 +452,7 @@ int CLASS::processfile(std::string &p) } else { - printf("file %s does not exist\n", p.c_str()); + fprintf(stderr,"File <%s> does not exist.\n\n", p.c_str()); } //printf("\n\nfile read result: %d\n", res); @@ -499,7 +500,6 @@ void CLASS::init(void) int CLASS::doline(int lineno, std::string line) { - MerlinLine l(line); lines.push_back(l); return 0; @@ -513,7 +513,7 @@ void CLASS::process(void) for (uint32_t lineno = 0; lineno < ct; lineno++) { - MerlinLine &line = lines[lineno]; + MerlinLine &line = lines.at(lineno); pos = 0; len = 0; @@ -734,6 +734,8 @@ void CLASS::showSymbolTable(bool alpha) std::map alphamap; std::map nummap; + int columns = 4; + int column = columns; for (auto itr = symbols.begin(); itr != symbols.end(); itr++) { @@ -746,19 +748,29 @@ void CLASS::showSymbolTable(bool alpha) if (alpha) { - printf("\nSymbol table sorted alphabetically:\n"); + printf("\n\nSymbol table sorted alphabetically:\n\n"); for (auto itr = alphamap.begin(); itr != alphamap.end(); ++itr) { - printf("%-16s 0x%08X\n", itr->first.c_str(), itr->second); + printf("%16s 0x%08X", itr->first.c_str(), itr->second); + if( !--column ) + { + printf("\n"); + column = columns; + } } } else { - printf("\nSymbol table sorted numerically:\n"); + printf("\n\nSymbol table sorted numerically:\n\n"); for (auto itr = nummap.begin(); itr != nummap.end(); ++itr) { - printf("0x%08X %-16s\n", itr->first, itr->second.c_str()); + printf("0x%08X %-16s", itr->first, itr->second.c_str()); + if( !--column ) + { + printf("\n"); + column = columns; + } } } } @@ -825,12 +837,11 @@ const TaddrMode addrRegEx[] = { { "^(?'expr'.+)\\,[s,S]{1}$", syn_s, "e,s"}, // expr,s {"^[(]{1}(?'expr'.+)[,]{1}[(S|s)]{1}[)]{1}[,]{1}[(Y|y)]{1}$", syn_sy, "(e,s),y"}, // (expr,s),y - {"^#{1}(?'shift'[<,>,^,|]?)(.+)$", syn_imm, "immediate"}, //#expr,#^expr,#|expr,#expr + {"^#{1}(.+)$", syn_imm, "immediate"}, //#expr,#^expr,#|expr,#expr {"^[(]{1}(?'expr'.+)[,]{1}[x,X]{1}\\)$", syn_diix, "(e,x)"}, // (expr,x) {"^[(]{1}(?'expr'.+)[\\)]{1}[\\,][(Y|y]{1}$", syn_diiy, "(e),y"}, //(expr),y {"^[(]{1}(?'expr'.+)[\\)]{1}$", syn_di, "(e)"}, // (expr) {"^\\[{1}(?'expr'.+)\\]{1}[,]{1}[(Y|y)]{1}$", syn_iyl, "[e],y"}, // [expr],y - //{"^\\[{1}(?'expr'.+)\\]{1}[,]{1}[(X|x)]{1}$", syn_iyl, "[e],x"}, // [expr],x {"^\\[(?'expr'.+)\\]$", syn_dil, "[e]"}, // [expr] {"^(?'expr'.+)[,]{1}[(X|x)]{1}$", syn_absx, "e,x"}, // expr,x {"^(?'expr'.+)[,]{1}[(Y|y)]{1}$", syn_absy, "e,y"}, // expr,y @@ -839,7 +850,11 @@ const TaddrMode addrRegEx[] = {"", 0, ""} }; -const std::string valExpression = "^([$%\\+\\-:-~][^\\],()]*)$"; +// keep this next line for awhile +// {"^#{1}(?'shift'[<,>,^,|]?)(.+)$", syn_imm, "immediate"}, //#expr,#^expr,#|expr,#expr + +// one or more of any character except ][,(); +const std::string valExpression = "^([^\\]\\[,();]+)$"; // opcode check. emitted opcodes are compared against this // table, and if the XC status doesn't meet the requirements @@ -895,6 +910,8 @@ void CLASS::initpass(void) PC.origin = 0x8000; PC.currentpc = PC.origin; + PC.totalbytes=0; + PC.orgsave=PC.origin; s = getConfig("asm.cpu", "M65816"); s = Poco::trim(Poco::toUpper(s)); @@ -923,10 +940,12 @@ void CLASS::initpass(void) } relocatable = false; currentsym = NULL; - PC.totalbytes = 0; lineno = 0; errorct = 0; passcomplete = false; + dumstartaddr=0; + dumstart=0; + variables.clear(); // clear the variables for each pass while (!PCstack.empty()) @@ -944,19 +963,18 @@ void CLASS::complete(void) { if (errorct == 0) { - MerlinLine *line; std::ofstream f(savepath); uint32_t lineno = 0; uint32_t l = lines.size(); while (lineno < l) { - line = &lines[lineno++]; - if (line->outbytect > 0) + MerlinLine &line=lines.at(lineno++); + if (line.outbytect > 0) { - for (uint32_t i = 0; i < line->outbytect; i++) + for (uint32_t i = 0; i < line.outbytect; i++) { - f.put(line->outbytes[i]); + f.put(line.outbytes[i]); } } } @@ -986,7 +1004,7 @@ int CLASS::evaluate(std::string expr, int64_t &value) TEvaluator eval(*this); - res = eval.evaluate(expr, result); + res = eval.evaluate(expr, result, mx); if (res != 0) { if (isDebug() > 2) @@ -1006,6 +1024,10 @@ int CLASS::evaluate(std::string expr, int64_t &value) value = 0; res = 0; } + if (isDebug()>=3) + { + printf("Eval Result: %08lX (status=%d)\n",value,res); + } return (res); } @@ -1127,13 +1149,13 @@ int CLASS::parseOperand(MerlinLine & line) void CLASS::process(void) { uint32_t l; - int x, evalresult; + int x;; char c; std::string op, operand; //uint32_t operand_eval; //uint16_t addrmode; - MerlinLine *line; + //MerlinLine *line; pass = 0; while (pass < 2) { @@ -1142,100 +1164,115 @@ void CLASS::process(void) l = lines.size(); while ((lineno < l) && (!passcomplete)) { - evalresult = 0; - line = &lines[lineno]; + MerlinLine &line=lines[lineno]; - line->lineno = lineno + 1; - //printf("lineno: %d %d |%s|\n",lineno,l,line->operand.c_str()); + line.eval_result=0; + line.lineno = lineno + 1; + //printf("lineno: %d %d |%s|\n",lineno,l,line.operand.c_str()); - op = Poco::toLower(line->opcode); - operand = Poco::toLower(line->operand); - line->startpc = PC.currentpc; - line->linemx = mx; - line->bytect = 0; - line->showmx = showmx; + op = Poco::toLower(line.opcode); + operand = Poco::toLower(line.operand); + line.startpc = PC.currentpc; + line.linemx = mx; + line.bytect = 0; + line.showmx = showmx; - if ((line->lable != "") && (pass == 0)) + if ((line.lable != "") && (pass == 0)) { - std::string lable = Poco::trim(line->lable); + std::string lable = Poco::trim(line.lable); TSymbol *sym = NULL; bool dupsym = false; - c = line->lable[0]; + c = line.lable[0]; switch (c) { case ']': - sym = addVariable(line->lable, "", true); + sym = addVariable(line.lable, "", true); if (sym == NULL) { dupsym = true; } break; case ':': break; default: - sym = addSymbol(line->lable, PC.currentpc, false); + sym = addSymbol(line.lable, PC.currentpc, false); if (sym == NULL) { dupsym = true; } break; } if (dupsym) { - line->setError(errDupSymbol); + line.setError(errDupSymbol); } } - x = parseOperand(*line); + x = parseOperand(line); if (x >= 0) { - line->addressmode = x; + line.addressmode = x; } int64_t value = -1; - x = evaluate(line->operand_expr, value); - evalresult = x; + x = evaluate(line.operand_expr, value); + line.eval_result=x; if (x == 0) { value &= 0xFFFFFFFF; - line->expr_value = value; + line.expr_value = value; } else { - line->expr_value = 0; + line.expr_value = 0; } x = 0; if (op.length() > 0) { - x = callOpCode(op, *line); + x = callOpCode(op, line); } if (x > 0) { - if ((evalresult != 0) && (pass > 0)) + if ((line.eval_result != 0) && (pass > 0)) { - line->setError(errBadOperand); - line->errorText = line->operand_expr; + line.setError(errBadOperand); + line.errorText = line.operand_expr; } - line->bytect = x; + line.bytect = x; PC.currentpc += x; PC.totalbytes += x; } if (pass == 0) { - line->pass0bytect = line->bytect; + line.pass0bytect = line.bytect; } + if (dumstart>0) // starting a dummy section + { + PCstack.push(PC); + PC.origin=dumstartaddr; + PC.currentpc=PC.origin; + dumstart=0; + dumstartaddr=0; + } + if (dumstart<0) + { + PC=PCstack.top(); + PCstack.pop(); + dumstart=0; + dumstartaddr=0; + } if (pass == 1) { - if ((line->pass0bytect != line->bytect) && (line->errorcode == 0)) + if ((line.pass0bytect != line.bytect) && (line.errorcode == 0)) { - line->setError(errBadByteCount); + line.setError(errBadByteCount); } - if (line->errorcode != 0) + if (line.errorcode != 0) { errorct++; } - if (((!skiplist) && (listing) && (pass == 1)) || (line->errorcode != 0)) + if (((!skiplist) && (listing) && (pass == 1)) || (line.errorcode != 0)) { - line->print(lineno); + line.print(lineno); } skiplist = false; } diff --git a/asm.h b/asm.h index 7d00f35..5a09299 100644 --- a/asm.h +++ b/asm.h @@ -38,10 +38,14 @@ enum asmErrors errBadByteCount, errBadBranch, errUnimplemented, - errForwardReference, + errForwardRef, errNoRedefinition, errBadOperand, errDupSymbol, + errBadDUMop, + errOverflow, + errRecursiveOp, + errOpcodeNotStarted, errMAX }; @@ -62,7 +66,10 @@ const std::string errStrings[errMAX + 1] = "Unable to redefine symbol", "Unable to evaluate", "Duplicate Symbol", - + "Invalid use of DUM/DEND", + "Overflow detected", + "Recursive Operand", + "Opcode without start", "" }; #else @@ -96,10 +103,42 @@ enum class TOriginSection { +// SGQ - if you do something unusual here, be aware of copy constructor +// may be needed public: uint32_t origin; uint32_t currentpc; uint32_t totalbytes; + uint32_t orgsave; +#if 0 + TOriginSection(const TOriginSection &old) + { + origin = old.origin; + currentpc = old.currentpc; + orgsave=old.orgsave; + totalbytes = old.totalbytes; + }; + + TOriginSection& operator=(const TOriginSection &other) + { + origin = other.origin; + currentpc = other.currentpc; + totalbytes = other.totalbytes; + orgsave=other.orgsave; + return (*this); + }; + + TOriginSection() + { + origin = 0; + currentpc = 0; + totalbytes = 0; + orgsave=0; + }; + ~TOriginSection() + { + } +#endif }; class MerlinLine @@ -124,6 +163,7 @@ public: int32_t startpc; uint32_t addressmode; int32_t expr_value; + int32_t eval_result; // this is the error code from the evaluate routing (0 or neg) uint32_t errorcode; std::string errorText; @@ -223,10 +263,10 @@ public: bool passcomplete; bool relocatable; + int dumstart; // must be signed + uint32_t dumstartaddr; bool skiplist; // used if lst is on, but LST opcode turns it off uint32_t lineno; - //uint32_t origin; - //uint32_t currentpc; std::string savepath; TSymbol *currentsym; diff --git a/eval.cpp b/eval.cpp index c9e1044..44352e5 100644 --- a/eval.cpp +++ b/eval.cpp @@ -118,11 +118,19 @@ std::deque CLASS::exprToTokens(const std::string& expr) numexpect = false; } + else if ((numexpect) && ( (c == '^') || (c == '<') || (c == '>') || (c == '|'))) + { + ident = c; + tokens.push_back(Token{Token::Type::Shift, ident, 1, true}); + ident = ""; + } else if ((c == '*') && (numexpect)) { numexpect = false; - state = 20; + state = 0; ident += c; + tokens.push_back(Token{Token::Type::Symbol, ident, 1, false}); + ident = ""; } else if ((c == '%') && (numexpect)) { @@ -155,14 +163,7 @@ std::deque CLASS::exprToTokens(const std::string& expr) numexpect = false; } - else if ((c >= 'a') && (c <= 'z')) - { - state = 20; - ident += c; - numexpect = false; - - } - else if ((c >= 'A') && (c <= 'Z')) + else if (c >= ':') { state = 20; ident += c; @@ -229,7 +230,6 @@ std::deque CLASS::shuntingYard(const std::deque& tokens) if (sym != NULL) { sym->used = true; - //printf("symbol found\n"); sprintf(buff, "%d", sym->value); token.str = buff; } @@ -247,6 +247,9 @@ std::deque CLASS::shuntingYard(const std::deque& tokens) queue.push_back(token); break; + case Token::Type::Shift: + stack.push_back(token); + break; case Token::Type::Operator: { // If the token is operator, o1, then: @@ -317,7 +320,7 @@ std::deque CLASS::shuntingYard(const std::deque& tokens) { // If the stack runs out without finding a left parenthesis, // then there are mismatched parentheses. - printf("RightParen error (%s)\n", token.str.c_str()); + //printf("RightParen error (%s)\n", token.str.c_str()); setError(Token::operatorErr); return queue; } @@ -327,7 +330,7 @@ std::deque CLASS::shuntingYard(const std::deque& tokens) default: setError(Token::syntaxErr); - printf("error (%s)\n", token.str.c_str()); + //printf("error (%s)\n", token.str.c_str()); return queue; break; } @@ -518,11 +521,12 @@ void CLASS::setError(int ecode) } } -int CLASS::evaluate(std::string & e, int64_t &res) +int CLASS::evaluate(std::string & e, int64_t &res, uint8_t &_shiftmode) { // const std::string expr = "3+4*2/(1-5)^2^3"; // Wikipedia's example // const std::string expr = "20-30/3+4*2^3"; + _shiftmode=shiftmode=0; res = DEF_VAL; setError(Token::noError); @@ -531,8 +535,10 @@ int CLASS::evaluate(std::string & e, int64_t &res) std::string expr = Poco::trim(e); expr += " "; // add a space at end to make parsing easier - //printf("expression: |%s|\n",expr.c_str()); - + if (isDebug() >= 4) + { + printf("eval: expression: |%s|\n", expr.c_str()); + } const auto tokens = exprToTokens(expr); auto queue = shuntingYard(tokens); std::vector stack; @@ -565,6 +571,41 @@ int CLASS::evaluate(std::string & e, int64_t &res) //op = "Push " + token.str; break; + case Token::Type::Shift: + { + auto rhs = DEF_VAL; + + if (stack.size() > 0) + { + rhs = stack.back(); + stack.pop_back(); + shiftmode=token.str[0]; + + if (token.str=="^") + { + //rhs = (rhs >> 16) &0xFFFF ; + } + else if (token.str=="|") + { + //rhs = (rhs >> 16) & 0xFFFF; + } + else if (token.str=="<") + { + //rhs = (rhs << 8 ) & 0xFFFF; + } + else if (token.str==">") + { + //rhs=(rhs>>8) & 0xFFFF; + } + + stack.push_back(rhs); + } + else + { + //printf("nothing on stack\n"); + } + } + break; case Token::Type::Operator: { @@ -656,6 +697,7 @@ out: { setError(Token::syntaxErr); } + _shiftmode=shiftmode; res = v; return (evalerror); } diff --git a/eval.h b/eval.h index aaa2bef..e9cf182 100644 --- a/eval.h +++ b/eval.h @@ -41,6 +41,7 @@ public: Unknown = 0, Number, Symbol, + Shift, Operator, LeftParen, RightParen, @@ -62,6 +63,7 @@ protected: T65816Asm &assembler; int evalerror; void setError(int ecode); + uint8_t shiftmode; public: CLASS(T65816Asm &_asm); ~CLASS(); @@ -69,7 +71,7 @@ public: std::deque shuntingYard(const std::deque& tokens); std::deque exprToTokens(const std::string& expr); int parseNumber(std::string n, int64_t &val); - int evaluate(std::string &expr, int64_t &res); + int evaluate(std::string &expr, int64_t &res, uint8_t &_shiftmode); }; diff --git a/opcodes.cpp b/opcodes.cpp index 725b26d..a6582fe 100644 --- a/opcodes.cpp +++ b/opcodes.cpp @@ -687,7 +687,7 @@ void CLASS::insertOpcodes(void) pushopcode("ORG", P_ORG, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("DSK", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("SAV", P_SAV, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); - pushopcode("DS", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); + pushopcode("DS", P_DS, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("REL", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("OBJ", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); pushopcode("PUT", 0x00, OP_PSUEDO, OPHANDLER(&CLASS::doPSEUDO)); diff --git a/psuedo.cpp b/psuedo.cpp index e000d59..51a30a8 100644 --- a/psuedo.cpp +++ b/psuedo.cpp @@ -12,11 +12,47 @@ CLASS::~CLASS() } + +int CLASS::doDS(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) +{ + int res = 0; + int32_t v = line.expr_value; + if (line.eval_result!=0) + { + line.setError(errForwardRef); + } + else if ((v < 0) || ((a.PC.currentpc + v) >= 0x10000)) // no neg, or crossing bank bound + { + line.setError(errOverflow); + } + else + { + res = v; + } + return (res); +} + int CLASS::doDUM(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) { - int res=-1; - //bool isdend=((opinfo.opcode==P_DEND)?true:false); - return(res); + int res = 0; + bool isdend = ((opinfo.opcode == P_DEND) ? true : false); + + if (!isdend) + { + a.dumstart = 1; + a.dumstartaddr = line.expr_value; + } + else + { + a.dumstart = -1; + if (a.PCstack.size() == 0) + { + line.setError(errBadDUMop); + a.dumstart = 0; + } + } + + return (res); } int CLASS::doLST(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) @@ -51,11 +87,25 @@ int CLASS::ProcessOpcode(T65816Asm &a, MerlinLine &line, TSymbol &opinfo) res = -1; // undefined p-op line.setError(errUnimplemented); break; + case P_DS: + res = doDS(a, line, opinfo); + break; case P_DUM: case P_DEND: - res=doDUM(a,line,opinfo); + res = doDUM(a, line, opinfo); + break; case P_ORG: - a.PC.currentpc = line.expr_value; + if (line.operand.length()>0) + { + a.PC.orgsave=a.PC.currentpc; + a.PC.currentpc = line.expr_value; + line.startpc=line.expr_value; + } + else + { + a.PC.currentpc = a.PC.orgsave; + line.startpc=a.PC.orgsave; + } break; case P_SAV: a.savepath = line.operand; diff --git a/psuedo.h b/psuedo.h index 7599eba..508b8c6 100644 --- a/psuedo.h +++ b/psuedo.h @@ -10,6 +10,7 @@ enum P_SAV, P_DUM, P_DEND, + P_DS, P_MAX }; @@ -22,6 +23,7 @@ public: int ProcessOpcode(T65816Asm &a, MerlinLine &line, TSymbol &opinfo); int doLST(T65816Asm &a, MerlinLine &line, TSymbol &opinfo); int doDUM(T65816Asm &a, MerlinLine &line, TSymbol &opinfo); + int doDS(T65816Asm &a, MerlinLine &line, TSymbol &opinfo); diff --git a/qasm.cpp b/qasm.cpp index c3679c1..018405e 100644 --- a/qasm.cpp +++ b/qasm.cpp @@ -13,9 +13,8 @@ PAL_BASEAPP *PAL::appFactory(void) programOption PAL::appOptions[] = { { "debug", "d", "enable debug info (repeat for more verbosity)", "", false, true}, - { "config-file", "f", "load configuration data from a ", "file", false, false}, - { "tomerlin", "m", "convert file to merlin format ", "", false, false}, - { "reformat", "r", "convert to readable ascii", "", false, false}, + { "config", "f", "load configuration data from a ", "", false, false}, + { "exec", "x", "execute a command", "", false, false}, { "", "", "", "", false, false} }; @@ -49,6 +48,12 @@ int CLASS::runCommandLineApp(void) int res = -1; //LOG_DEBUG << "command line mode" << endl; + if (commandargs.size()==0) + { + fprintf(stderr,"No files given (--help for help)\n\n"); + return(res); + } + for (ArgVec::const_iterator it = commandargs.begin(); it != commandargs.end(); ++it) { Poco::File fn(*it); @@ -59,53 +64,60 @@ int CLASS::runCommandLineApp(void) std::string e = toUpper(path.getExtension()); - int x = getInt("option.reformat", 0); + std::string cmd = Poco::toUpper(getConfig("option.exec", "asm")); - if (x != 0) + if (cmd.length() > 0) { - res=0; - t = new TMerlinConverter(); - if (t != NULL) + if (cmd == "REFORMAT") { + res = 0; + t = new TMerlinConverter(); + if (t != NULL) + { - t->init(); - std::string f = path.toString(); - t->processfile(f); - t->process(); - t->complete(); - res = (t->errorct > 0) ? -1 : 0; - - delete t; - t = NULL; - } - } - else - { - if (e == "S") - { - //logger().information("ASM: " + path.toString()); + t->init(); + std::string f = path.toString(); + t->processfile(f); + t->process(); + t->complete(); + res = (t->errorct > 0) ? -1 : 0; - t = new T65816Asm(); + delete t; + t = NULL; + } } - if (e == "LNK") + else if (cmd == "ASM") { - //logger().information("LNK: " + path.toString()); - t = new T65816Link(); - } - if (t != NULL) - { - t->init(); - std::string f = path.toString(); - t->processfile(f); - t->process(); - t->complete(); - res = (t->errorct > 0) ? -1 : 0; - delete t; - t = NULL; + if (e == "S") + { + //logger().information("ASM: " + path.toString()); + + t = new T65816Asm(); + } + if (e == "LNK") + { + //logger().information("LNK: " + path.toString()); + t = new T65816Link(); + } + if (t != NULL) + { + t->init(); + std::string f = path.toString(); + t->processfile(f); + t->process(); + t->complete(); + res = (t->errorct > 0) ? -1 : 0; + delete t; + t = NULL; + } + else + { + printf("not supported type\n"); + } } else { - printf("not supported type\n"); + fprintf(stderr,"Invalid command: <%s>\n\n", cmd.c_str()); } } } diff --git a/src/main.s b/src/main.s index ce3a75e..3c54784 100644 --- a/src/main.s +++ b/src/main.s @@ -1,4 +1,4 @@ - ;lst on + lst off * * main.s * Merlin32 Test @@ -83,6 +83,7 @@ START ;adc (ZP,x) adc (0,x) + adc ($80,x) adc (_tmp,x) adc (_tmp+0,x) @@ -162,7 +163,7 @@ myQuit org ;return to ongoing address - + lst ;Issue #16 (fadden) - Byte reference modifiers are ignored (no way to force DP) lda <$fff0 ;zp lda >$fff0 ;ABS (lo word) @@ -182,6 +183,8 @@ myQuit lda #>$fff0 ;page lda #^$fff0 ;bank + lst off + lda $0008 ;ZP lda $08 ;ZP lda $ffff-$fff7 ;ZP @@ -201,3 +204,5 @@ L00BC bit L00BC stx L00BC,y //]XCODEEND ; Keep this at the end and put your code above this + lst off +