· 5 years ago · Aug 27, 2020, 04:58 PM
1--[[
2 6502 By Lewisk3 (Redxone) - Special thanks to SquidDev for compiler help!
3Methods of emulation:
4 1. Memory segments
5 : Use a table of bytes 64KB
6 2. Onboard registers
7 : Use a seperate table for registers
8 3. Flags
9 : Use a String of true or falses
10 4. Data Stack
11 : 256B - Stored on another memory area
12--]]
13
14-- TODO: 0200 to 0D5B = Screen memory
15
16-- Setup _6502 Enviorment
17local _NIBBLE = 4
18local _BYTE = 8
19local _KBYTE = 1024
20local _BUSWIDTH = 16
21local _CCENV = true
22-- Non CC lua compatibility
23if(write == nil)then write = io.write end
24if(read == nil)then read = io.read end
25if(sleep == nil)then sleep = function() end end
26if(term == nil)then
27 term = {}
28 term.current = function() return { setVisible = function(tf) return false end } end
29 term.isColor = function() return false end
30 term.setCursorPos = function(x,y) end
31 term.clear = function() end
32 term.setBackgroundColor = function(col) end
33 term.setTextColor = function(col) end
34 colors = {}
35 colors.white = 0
36 os = {}
37 os.pullEvent = function(ev) return nil end
38 shell = {}
39 shell.resolve = function(txt) return txt end
40 shell.getRunningProgram = function() return "6502" end
41 _CCENV = false
42elseif(term.current == nil)then
43 term.current().setVisible = function(tf) return false end
44end
45-- Monochrome support
46if(not term.isColor())then
47 colors.orange = colors.white
48 colors.magenta = colors.white
49 colors.lightBlue = colors.white
50 colors.yellow = colors.white
51 colors.lime = colors.white
52 colors.pink = colors.white
53 colors.gray = colors.white
54 colors.lightGray = colors.white
55 colors.cyan = colors.white
56 colors.purple = colors.white
57 colors.blue = colors.white
58 colors.brown = colors.white
59 colors.green = colors.white
60 colors.red = colors.white
61 colors.black = colors.white
62end
63--]] "BIOS" Functionality (All functions defined for Input and Output)
64
65-- Useful bit logic functions
66
67 typeCheck = function(val)
68 if(not tonumber(val,16))then
69 return "dec"
70 else
71 return "hex"
72 end
73 end
74
75 toHex = function(dec)
76 local hex = ""
77 local hexkey = "0123456789ABCDEF"
78 local rim
79 if(dec == 0)then hex = "0" end
80 while dec > 0 do
81 rim = math.floor(dec%16)
82 hex = hexkey:sub(rim+1,rim+1) .. hex
83 dec = math.floor(dec/16)
84 end
85 if(#hex == 1)then
86 hex = "0" .. hex
87 end
88 if(dec < 0)then
89 local num = 256 + dec
90 return toHex(num)
91 end
92 return hex
93 end
94
95 toBin = function(dec)
96 -- Convert to base 10 soooo easy
97 local bin = ""
98 local binkey = "01"
99 local rim
100 if(type(dec) == "string")then error("toBin -> Invalid type: " .. dec) end
101 while dec > 0 do
102 rim = math.floor(dec%2)
103 bin = binkey:sub(rim+1,rim+1) .. bin
104 dec = math.floor(dec/2)
105 end
106 if(#bin < 8)then
107 bin = string.rep("0",8-#bin) .. bin
108 end
109 return bin
110 end
111
112 signedHextoDec = function(hex)
113 local dechex = tonumber(hex,16)
114 -- Check sign
115 local checksign = toBin(dechex):sub(1,1)
116 --print(toBin(dechex))
117 if(checksign == "1")then
118 return (dechex - 255)-1
119 else
120 return dechex
121 end
122 end
123
124-- 1Byte Registers
125function writeReg(reg,byte)
126 if(not _G.ASM.reg[reg])then
127 error("Invalid register -> " .. reg)
128 end
129 _G.ASM.reg[reg] = string.char(tonumber(byte,16))
130end
131
132function writeRegDec(reg,byte)
133 if(not _G.ASM.reg[reg])then
134 error("Invalid register -> " .. reg)
135 end
136 _G.ASM.reg[reg] = string.char(byte)
137end
138
139function writeRegChar(reg,ch)
140 if(not _G.ASM.reg[reg])then
141 error("Invalid register -> " .. reg)
142 end
143 _G.ASM.reg[reg] = ch
144end
145
146function moveRegs(from,to,flags)
147 if(flags == nil)then flags = false end
148 local from = readRegHex(from)
149 writeReg(to,from)
150 if(flags)then updateResultFlags(readRegDec(to)) end
151end
152
153function loadRegIndirect(reg,ind,itype)
154 local plusx = 0
155 local plusy = 0
156 -- Optional indexing types
157 if(itype == nil)then itype = "" end
158 if(itype == "X")then
159 plusx = decodeByte(readReg("X"))
160 elseif(itype == "Y")then
161 plusy = decodeByte(readReg("Y"))
162 end
163
164 -- Get ind data from 1, and 2 (ind + 1) and concatenate location, lsb..msb
165
166 local ind = toHex(tonumber(ind,16) + plusx)
167 local ind2 = toHex(tonumber(ind,16) + 1)
168 local byte1 = readByteHex(ind)
169 local byte2 = readByteHex(ind2)
170 local addr = toHex(tonumber(byte2 .. byte1,16) + plusy)
171 if(#addr < 4)then
172 addr = string.rep("0",4-#addr) .. addr
173 end
174 writeReg(reg,readByteHex(addr))
175end
176--storeRegIndirect("A","15","X")
177function storeRegIndirect(reg,ind,itype)
178 local plusx = 0
179 local plusy = 0
180 -- Optional indexing types
181 if(itype == nil)then itype = "" end
182 if(itype == "X")then
183 plusx = decodeByte(readReg("X"))
184 end
185 if(itype == "Y")then
186 plusy = decodeByte(readReg("Y"))
187 end
188 local ind = toHex(tonumber(ind,16) + plusx)
189 local ind2 = toHex(tonumber(ind,16) + 1)
190 local byte1 = readByteHex(ind)
191 local byte2 = readByteHex(ind2)
192 local addr = toHex(tonumber(byte2 .. byte1,16) + plusy)
193 if(#addr < 4)then
194 addr = string.rep("0",4-#addr) .. addr
195 end
196 writeByte(addr,readRegHex(reg))
197end
198
199function readReg(reg)
200 if(not _G.ASM.reg[reg])then
201 error("Invalid register -> " .. reg)
202 end
203 return tostring(_G.ASM.reg[reg])
204end
205function readRegHex(reg)
206 return toHex(decodeByte(readReg(reg)))
207end
208function readRegDec(reg)
209 if(not _G.ASM.reg[reg])then
210 error("Invalid register -> " .. reg)
211 end
212 return string.byte(_G.ASM.reg[reg])
213end
214
215function decodeByte(byte)
216 return string.byte(byte)
217end
218
219-- Program Counter
220function readPC()
221 local MSB = toHex(string.byte(_G.ASM.reg['PC']:sub(1,1)))
222 local LSB = toHex(string.byte(_G.ASM.reg['PC']:sub(2,2)))
223 return MSB .. LSB
224end
225
226setPC = function(bytes)
227 if(#bytes > 4)then print("Program counter must be 4Bytes!") end
228 if(#bytes < 4)then
229 bytes = string.rep("0",4-#bytes) .. bytes
230 end
231 local MSB = string.char(tonumber(bytes:sub(1,2),16))
232 local LSB = string.char(tonumber(bytes:sub(3,4),16))
233 --print(MSB .. LSB)
234 _G.ASM.reg['PC'] = MSB .. LSB
235end
236
237getProgramByte = function(byte)
238 -- Program byte will be a hex value
239 local hexPC = toHex(string.byte(readReg('PC')))
240 -- PROGM is in ASCII format
241 -- Convert to HEX then return
242 return readByteHex(hexPC)
243end
244
245movePC = function(bytes)
246 local absval = toHex(tonumber(readPC(),16) + bytes)
247 if(#absval < 4)then absval = "0" .. absval end
248 setPC(absval)
249end
250
251-- Stacks
252
253function pushStack(val)
254 local sp = toHex(string.byte(readReg('SP')))
255 local pointer = toHex(string.byte(readReg("SP")))
256 local val = tonumber(val,16)
257 local offs = math.floor(tonumber(pointer,16)%_BUSWIDTH)
258 local pointer = math.floor(tonumber(pointer,16)/_BUSWIDTH)+1
259 local byte = _G.ASM.stack[pointer]
260 byte = byte:sub(1,offs-1) .. string.char(val) .. byte:sub(offs+1,#byte)
261 _G.ASM.stack[pointer] = byte
262 -- Move pointer to next item in stack
263 pointer = tonumber(sp,16) - 1
264 -- If the pointer reached the end of the stack, reset it
265 if(pointer < 1)then
266 pointer = "FF"
267 -- Write pointer back into Stack Pointer
268 writeReg("SP",pointer)
269 else
270 -- Write pointer back into Stack Pointer
271 writeRegDec("SP",pointer)
272 end
273end
274
275
276function pullStack()
277 -- Pull value off stack, and increment the stack pointer
278 local sp = toHex(string.byte(readReg("SP")))
279 local pointer = toHex(string.byte(readReg("SP"))+1)
280 local offs = math.floor(tonumber(pointer,16)%_BUSWIDTH)
281 local pointer = math.floor(tonumber(pointer,16)/_BUSWIDTH)+1
282 local byte = _G.ASM.stack[pointer]
283 -- Move pointer to next item in stack
284 pointer = tonumber(sp,16) + 1
285 -- If the pointer reached the end of the stack, reset it
286 if(pointer > 255)then
287 pointer = "00"
288 -- Write pointer back into Stack Pointer
289 writeReg("SP",pointer)
290 else
291 -- Write pointer back into Stack Pointer
292 writeRegDec("SP",pointer)
293 end
294 if(byte == nil)then
295 return string.char("0")
296 end
297 return byte:sub(offs,offs)
298end
299
300-- Flags
301
302function setFlag(flagbit,onoff)
303 if(_G.ASM.flagtypes[flagbit])then flagbit = _G.ASM.flagtypes[flagbit] end
304 flagbit = tostring(flagbit)
305 local flags = toBin(decodeByte(_G.ASM.flags))
306 if(onoff ~= 1 and onoff ~= 0)then error("Invaild flag state!") end
307 if(#flags < 0 or #flags > 8)then error("Invalid flag index!") end
308 flags = flags:sub(1,flagbit-1) .. tostring(onoff) .. flags:sub(flagbit+1,#flags)
309 _G.ASM.flags = string.char(tonumber(flags,2))
310end
311function getFlag(flagbit)
312 if(_G.ASM.flagtypes[flagbit])then flagbit = _G.ASM.flagtypes[flagbit] end
313 return toBin(decodeByte(_G.ASM.flags)):sub(flagbit,flagbit)
314end
315function getFlagsByte()
316 return _G.ASM.flags
317end
318function setAllFlags(flaghex)
319 _G.ASM.flags = string.char(decodeByte(flaghex))
320end
321
322function updateResultFlags(val)
323 -- Val is in Hex
324 if(type(val) == "string")then
325 val = tonumber(val,16)
326 end
327 local binval = toBin(val)
328 local flags = toBin(decodeByte(_G.ASM.flags))
329 if(val == 0)then
330 setFlag("ZRO",1)
331 else
332 setFlag("ZRO",0)
333 end
334 if(binval:sub(1,1) == "1")then
335 setFlag("NEG",1)
336 else
337 setFlag("NEG",0)
338 end
339 return
340end
341
342function checkCarry(mode,val)
343 if(type(val) == "string")then error("Value must be decimal for CARRY check!") end
344 if(string.lower(mode) == "add")then
345 if(val > 255)then
346 setFlag("CRY",1)
347 return true
348 elseif(val < 0)then
349 setFlag("CRY",1)
350 return true
351 else
352 setFlag("CRY",0)
353 return false
354 end
355 elseif(string.lower(mode) == "sub")then
356 if(val < 0)then
357 setFlag("CRY",0)
358 return true
359 else
360 setFlag("CRY",1)
361 return false
362 end
363 else
364 error("Invalid CARRY check mode: " .. mode)
365 end
366end
367
368function addHex(n1,n2)
369 local num = tonumber(n1,16) + tonumber(n2,16)
370 if(num > 255)then
371 num = num - 256
372 end
373 return toHex(num)
374end
375function subHex(n1,n2)
376 local num = (tonumber(n1,16) - tonumber(n2,16))
377 if(num < 0)then
378 num = 256 + num
379 end
380 return toHex(num)
381end
382
383function addSignedDec(n1,n2)
384 local num = tonumber(n1,16) + tonumber(n2,16)
385 if(num > 255)then
386 num = num - 256
387 end
388 return num
389end
390
391function subSignedDec(n1,n2)
392 local num = (tonumber(n1,16) - tonumber(n2,16))
393 if(num < 0)then
394 num = 256 + num
395 end
396 return num
397end
398
399
400
401
402
403function checkOverflow(mode,val,val2)
404 if(val2 == nil)then val2 = "00" end
405 if(string.lower(mode) == "bit")then
406 val = toBin(tonumber(val,16))
407 -- Check bit 6 (0 indexed) of value for a 1 if so, set V flag
408 if(val:sub(2,2) == "1")then
409 setFlag("OVR",1)
410 return true
411 else
412 setFlag("OVR",0)
413 return false
414 end
415 elseif(string.lower(mode) == "math")then
416 val = signedHextoDec(val) + signedHextoDec(tonumber(val2,16))
417 -- Check if value is negative (2s signed)
418 -- Convert value into Decimal
419 -- Convert decimal into 8bit signed decimal
420 -- Check if val is outside the bounds of an 8bit
421 -- 2's complement signed number, if so, set overflow.
422 if(val < -127)then
423 setFlag("OVR",1)
424 return true
425 elseif(val > 127)then
426 setFlag("OVR",1)
427 return true
428 else
429 setFlag("OVR",0)
430 return false
431 end
432 end
433end
434
435function getSign(val)
436 -- Returns true if negative
437 return toBin(tonumber(val,16)):sub(1,1) == "1"
438end
439
440function signedAdd(val,val2)
441 if(getFlag("DEC") == "1")then
442 return signedAddDec(val, val2)
443 end
444 local snum = toHex(signedHextoDec(val) + signedHextoDec(val2))
445 local num = tonumber(val,16) + tonumber(val2,16)
446 checkOverflow("math",snum)
447 checkCarry("add",num)
448 if(getFlag("CRY") == "1")then
449 -- Push off MSB from NUM, to fit in 1Byte space
450 num = toHex(num)
451 num = num:sub(#num-1,#num)
452 num = tonumber(num,16)
453 end
454 return toHex(num)
455end
456
457function signedAddDec(val, val2)
458 -- Determine string HEX or Dec, based on DEC flag "reasonableness" (Basically, the DEC flag math can still do hex, but only to an extent. )
459 if(tonumber(val) == nil)then val = tonumber(val,16) else val = tonumber(val) end
460 if(tonumber(val2) == nil)then val2 = tonumber(val2,16) else val2 = tonumber(val2) end
461 local num = val + val2
462 if(num > 99)then
463 setFlag("CRY",1)
464 num = ( (num-1) - 99 )
465 elseif(num < 0)then
466 setFlag("CRY",1)
467 else
468 setFlag("CRY",0)
469 end
470 num = tostring(num)
471 if(#num == 1)then num = "0" .. num end
472 return num
473end
474
475--signedSub("FF","01")
476function signedSub(val,val2)
477 if(getFlag("DEC") == "1")then
478 return signedSubDec(val, val2)
479 end
480 local snum = toHex(signedHextoDec(val) - (signedHextoDec(val2)) )
481 local num = tonumber(val,16) - (tonumber(val2,16))
482 checkOverflow("math",snum)
483 checkCarry("sub",num)
484 return toHex(num)
485end
486
487function signedSubDec(val, val2)
488 -- Determine string HEX or Dec, based on DEC flag "reasonableness" (Basically, the DEC flag math can still do hex, but only to an extent. )
489 if(tonumber(val) == nil)then val = tonumber(val,16) else val = tonumber(val) end
490 if(tonumber(val2) == nil)then val2 = tonumber(val2,16) else val2 = tonumber(val2) end
491 local num = val - val2
492 if(num < 0)then
493 setFlag("CRY",1)
494 num = ( 99 + num )
495 else
496 setFlag("CRY",0)
497 end
498 num = tostring(num)
499 if(#num == 1)then num = "0" .. num end
500 return num
501end
502
503-- RAM
504function readIndirectByte(ind,itype)
505 local plusx = 0
506 local plusy = 0
507 if(itype == "X")then
508 plusx = decodeByte(readReg("X"))
509 end
510 if(itype == "Y")then
511 plusy = decodeByte(readReg("Y"))
512 end
513 local ind = toHex(tonumber(ind,16) + plusx)
514 local ind2 = toHex(tonumber(ind,16) + 1)
515 local byte1 = readByteHex(ind)
516 local byte2 = readByteHex(ind2)
517 local addr = toHex(tonumber(byte2 .. byte1,16) + plusy)
518 return addr
519end
520
521function writeByte(loc,byte,debug)
522 if(debug == nil)then debug = false end
523 local locraw = loc
524 local offs = math.floor(tonumber(loc,16)%_BUSWIDTH)+1
525 local absoluteloc = tonumber(loc,16) - math.floor(tonumber(loc,16)%_BUSWIDTH)
526 local loc = math.floor(tonumber(loc,16)/_BUSWIDTH)+1
527 local byte = string.char(tonumber(byte,16))
528 local byteloc = _G.ASM.ram[loc]
529 if(debug)then print(absoluteloc .. ":" .. offs .. " = " .. byte) end
530 byteloc = byteloc:sub(1,offs-1) .. byte .. byteloc:sub(offs+1,#byteloc)
531 _G.ASM.ram[loc] = byteloc
532 refreshScreen(locraw)
533 if(debug)then print(absoluteloc .. " = " .. byteloc) end
534end
535function writeByteDec(loc,byte,debug)
536 if(debug == nil)then debug = false end
537 local locraw = loc
538 local offs = math.floor(tonumber(loc,16)%_BUSWIDTH)+1
539 local absoluteloc = tonumber(loc,16) - math.floor(tonumber(loc,16)%_BUSWIDTH)
540 local loc = math.floor(tonumber(loc,16)/_BUSWIDTH)+1
541 local byte = string.char(byte)
542 local byteloc = _G.ASM.ram[loc]
543 if(debug)then print(absoluteloc .. ":" .. offs .. " = " .. byte) end
544 byteloc = byteloc:sub(1,offs-1) .. byte .. byteloc:sub(offs+1,#byteloc)
545 _G.ASM.ram[loc] = byteloc
546 refreshScreen(locraw)
547 if(debug)then print(absoluteloc .. " = " .. byteloc) end
548end
549function writeDecByte(loc,byte,debug)
550 if(debug == nil)then debug = false end
551 local locraw = loc
552 local offs = math.floor(loc%_BUSWIDTH)+1
553 local absoluteloc = loc - math.floor(loc%_BUSWIDTH)
554 local loc = math.floor(loc/_BUSWIDTH)+1
555 local byte = string.char(byte)
556 local byteloc = _G.ASM.ram[loc]
557 if(debug)then print(absoluteloc .. ":" .. offs .. " = " .. byte) end
558 byteloc = byteloc:sub(1,offs-1) .. byte .. byteloc:sub(offs+1,#byteloc)
559 _G.ASM.ram[loc] = byteloc
560 refreshScreen(locraw)
561 if(debug)then print(absoluteloc .. " = " .. byteloc) end
562end
563function readByte(loc,debug)
564 if(debug == nil)then debug = false end
565 local offs = math.floor(tonumber(loc,16)%_BUSWIDTH)+1
566 local loc = math.floor(tonumber(loc,16)/_BUSWIDTH)+1
567 local byte = tostring(_G.ASM.ram[loc]:sub(offs,offs))
568 if(debug)then print(loc .. ":" .. offs .. " = " .. byte) end
569 return byte
570end
571function readAddressByte(byte,itype)
572 local reg = false
573 if(byte == "A" or byte == "X" or byte == "Y")then
574 reg = true
575 end
576 if(itype == nil)then itype = "" end
577 local plus = 0
578 if(itype == "X")then
579 plus = decodeByte(readReg("X"))
580 end
581 if(itype == "Y")then
582 plus = decodeByte(readReg("Y"))
583 end
584 local addr = 0
585 local val = 0
586 if(not reg)then addr = toHex(tonumber(byte,16) + plus) end
587 if(reg)then
588 val = toHex(decodeByte(readReg(reg)))
589 else
590 val = toHex(decodeByte(readByte(addr)))
591 end
592 return val
593end
594
595
596function readByteHex(loc,debug)
597 return toHex(string.byte(readByte(loc,debug)))
598end
599function readByteDec(loc,debug)
600 return toHex(string.byte(readByte(loc,debug)))
601end
602
603function readDecByte(decloc)
604 return string.byte(readByte(loc,debug))
605end
606
607function writeChar(loc,byte,debug)
608 if(debug == nil)then debug = false end
609 local locraw = loc
610 local offs = math.floor(tonumber(loc,16)%_BUSWIDTH)+1
611 local absoluteloc = tonumber(loc,16) - math.floor(tonumber(loc,16)%_BUSWIDTH)
612 local loc = math.floor(tonumber(loc,16)/_BUSWIDTH)+1
613 local byteloc = _G.ASM.ram[loc]
614 if(debug)then print(absoluteloc .. ":" .. offs .. " = " .. byte) end
615 byteloc = byteloc:sub(1,offs-1) .. byte .. byteloc:sub(offs+1,#byteloc)
616 _G.ASM.ram[loc] = byteloc
617 refreshScreen(locraw)
618 if(debug)then print(absoluteloc .. " = " .. byteloc) end
619end
620
621
622-- Screen memory/rendering
623 function valueCheck(val)
624 if(type(val) == "string")then val = tonumber(val,16) end
625 return val
626 end
627
628
629function refreshScreen(mem)
630 local scr_start = 512
631 local scr_end = 2448
632 if( _G.ASM.pmode == 2 )then
633 mem = (valueCheck(mem))
634 if(mem >= scr_start and mem <= scr_end)then
635 drawScreenAt(toHex(mem))
636 end
637 end
638end
639
640
641function drawScreenAt(addr,debug)
642 if( _G.ASM.pmode ~= 2)then return nil end
643 if(debug == nil)then debug = false end
644 local scr_start = tonumber("0200",16)
645 local scr_width = 51
646 local scr_end = tonumber("0990",16)
647 local addr = tonumber(addr,16)
648 local iscolor = false
649 local ischar = false
650 if(addr < scr_start or addr > scr_end)then
651 return nil
652 end
653 -- Determine screen type at memory
654 if(addr%2 == 0)then
655 iscolor = true
656 else
657 ischar = true
658 end
659 -- Decode cursor position
660 -- As Address is always larger then or equal to screen start
661 local ypos = math.floor(((addr - scr_start)/2)/scr_width)+1
662 local xpos = 0
663 if(ischar)then
664 xpos = math.ceil(((addr - scr_start)/2)-((ypos-1)*51))
665 elseif(iscolor)then
666 xpos = math.ceil((((addr+1) - scr_start)/2)-((ypos-1)*51))
667 end
668 if(debug)then
669 print("Color: " .. tostring(iscolor))
670 print("Text : " .. tostring(ischar))
671 print("X: " .. xpos)
672 print("Y: " .. ypos)
673 end
674 -- Decode colors
675 local colors = "FF"
676 local tcol = colors.black
677 local bcol = colors.black
678 if(iscolor)then
679 colors = readByteHex(toHex(addr))
680 elseif(ischar)then
681 colors = readByteHex(toHex(addr-1))
682 end
683 -- Seperatew colors get MSB, LSB
684 tcol = 2^tonumber(colors:sub(1,1),16)
685 bcol = 2^tonumber(colors:sub(2,2),16)
686 if(debug)then
687 print("Text color: " .. tcol)
688 print("Back color: " .. bcol)
689 end
690 -- Print char
691 local char = " "
692 if(ischar)then
693 char = readByte(toHex(addr))
694 elseif(iscolor)then
695 char = readByte(toHex(addr+1))
696 end
697 local ox, oy = term.getCursorPos()
698 term.setCursorPos(xpos, ypos)
699 term.setTextColor(tcol)
700 term.setBackgroundColor(bcol)
701 write(char)
702 term.setTextColor(1)
703 term.setBackgroundColor(2^15)
704 term.setCursorPos(ox, oy)
705end
706
707function drawScreen()
708 if( _G.ASM.pmode ~= 2)then return nil end
709 local size = 969
710 local scr_start = tonumber("0200",16)
711 local scr_end = tonumber("0990",16)
712 for i = 0, size*2 do
713 drawScreenAt(toHex(scr_start+(i+1)))
714 end
715end
716
717-- Instruction decoding
718function runOpperation(op,type,val,debug,noexe)
719 -- Get Hex code first
720 local diss = ""
721 if(op == nil)then return false end
722 if(debug == nil)then debug = false end -- OCD precaution :P
723 if(noexe == nil)then noexe = false end -- OCD precaution :P
724 if(_G.ASM._HEXENCODE[op] == nil)then error("Invalid instruction: " .. op) end
725 if(_G.ASM._HEXENCODE[op][type] == nil)then error("Invalid type for: " .. op .. ", " .. type) end
726 -- Seperate arguments into Bytes
727 local opEncode = _G.ASM._HEXENCODE[op][type]
728 -- Split into bytes of 2
729 local bytes = {}
730 val = tostring(val)
731 if(#val > 2)then
732 for i=1, #val, 2 do
733 bytes[#bytes+1] = val:sub(i,i+1)
734 end
735 else
736 bytes[1] = val
737 end
738 -- If bytes passed is more than isntruction requires, error
739 local optimalBytes = _G.ASM._OPCODES[opEncode].bytes
740 if(optimalBytes > 0)then
741 --if(#bytes > optimalBytes)then error("Malformed instruction: " .. op .. ", " .. val) end
742 local i, j = 1, #bytes
743 while i < j do
744 bytes[i], bytes[j] = bytes[j], bytes[i]
745 i = i + 1
746 j = j - 1
747 end
748 for k, v in pairs(bytes) do
749 -- For Accumulative instructions
750 if(#v == 1)then v = "FF FF" end
751 diss = diss .. v .. " "
752 end
753 end
754 if(debug)then print("Dissassembly: " .. opEncode .. " " .. diss) end
755 if(not noexe)then
756 return opEncode .. " " .. diss, _G.ASM._OPCODES[opEncode]:exe(unpack(bytes))
757 else
758 return opEncode .. " " .. diss
759 end
760end
761function procInstructionType(op,debug,err)
762 -- Get instruction
763 -- Syntax Tabing check
764 if(err == nil)then err = true end
765 if(#op:gsub("%s+","") == 0)then
766 return nil
767 elseif(op:sub(1,1) == " " or op:sub(1,1) == "\t")then
768 op = op:gsub("%s+","")
769 op = op:sub(1,3) .. " " .. op:sub(4,#op)
770 end
771 if(debug == nil)then debug = false end -- OCD precaution :P
772 local instruction = string.upper(op:sub(1,3))
773 local args = (op:sub(5,#op)):gsub("%s+","")
774 local optype = "undefined"
775 -- Check for implicit instructions
776 if((#args:gsub('%s+','') == 0 or args == nil or args == "") and #op:gsub("%s+","") == 3)then
777 optype = "IMP"
778 if(debug)then print(instruction .. ":" .. optype) end
779 return instruction, optype, ""
780 end
781 -- Check for Accumulator instructions
782 if(#args == 1)then
783 args = string.upper(args)
784 if(args == "A" or args == "X" or args == "Y")then
785 if(args == "A")then num = "01" end
786 if(args == "X")then num = "02" end
787 if(args == "Y")then num = "03" end
788 optype = "ACC"
789 if(debug)then print(instruction .. ":" .. optype .. " ->" .. args) end
790 return instruction, optype, num
791 else
792 if(err)then error("Syntax Error: " .. op) else return "err" end
793 end
794 end
795 -- Check if Relative
796 if(args:sub(1,1) == "*")then
797 args = args:gsub("%s+","")
798 local sign = args:sub(2,#args):sub(1,1)
799 local num = signedHextoDec(args:sub(3,#args))
800 if(num > 127)then error("Out of bounds Error: " .. op) end
801 if(num < -127)then error("Out of bounds Error: " .. op) end
802 if(num == nil)then error("Syntax Error: " .. op) end
803 if(sign == "-")then
804 num = toHex(tonumber("FF",16) - (tonumber(toHex(math.abs(num)-1),16)))
805 else
806 num = toHex(num)
807 end
808 optype = "REL"
809 if(debug)then print(instruction .. ":" .. optype .. " -> " .. num) end
810 return instruction, optype, num
811 end
812 -- Check if Alpha numeric
813 if(args:sub(1,1) == "#" and args:sub(2,2) == "'" )then
814 if(args:sub(4,4) ~= "'")then if(err)then error("Syntax Error: " .. op) else return "err" end end
815 local char = args:sub(3,3)
816 local num = toHex(string.byte(char))
817 args = args:sub(1,1) .. "$" .. num
818 end
819 -- Determine type of instruction
820 -- Check if not HEX, then convert
821 if(args:sub(1,1) == "#" and args:sub(2,2) ~= "$")then
822 local num = args:sub(2,#args)
823 -- If trying to zero page x or y a decimal, error
824 if(args:find(","))then
825 if(err)then error("Syntax Error: " .. op) else return "err" end
826 end
827 -- Convert num to hex
828 num = toHex(tonumber(num))
829 args = args:sub(1,1) .. "$" .. num
830 end
831 -- Check if value is an Immeditate address
832 if(args:sub(1,1) == "#")then
833 local num = args:sub(3,#args)
834 if(#num == 2)then -- Instruction is Immeditate
835 optype = "IMM"
836 if(debug)then print(instruction .. ":" .. optype .. " -> " .. num) end
837 return instruction, optype, num
838 else
839 if(err)then error("Syntax Error: " .. op) else return "err" end
840 end
841 end
842 -- Zero Page X, Absolute XY checking
843 if(args:sub(1,1) == "$")then
844 local num = args:sub(2,#args)
845 -- Check for , because a Zero Page X can pass as an Absolute numerically wise.
846 if(not num:find(","))then
847 if(tonumber(num,16) == nil)then error("Syntax Error: " .. op) end
848 if(#num == 2)then -- Instruction is Zero Page
849 optype = "ZP"
850 if(debug)then print(instruction .. ":" .. optype .. " -> " .. num) end
851 return instruction, optype, num
852 end
853 if(#num == 4)then -- Instruction is absolute
854 optype = "AB"
855 if(debug)then print(instruction .. ":" .. optype .. " -> " .. num) end
856 return instruction, optype, num
857 end
858 end
859 -- Check for Zero Paged X
860 if(num:find(","))then
861 local nargs = {}
862 -- Take spaces out of string, then split it into 2 variables
863 local num = num:gsub("%s+", "")
864 -- Split string by comma
865 for word in string.gmatch(num, '([^,]+)') do
866 table.insert(nargs, word)
867 end
868 num = nargs[1]
869 local reg = string.upper(nargs[2])
870 -- If we have more than 2 variables in the string, then the user has seriously screwed up,
871 -- Be sure to annoy them with a noice syntax error.
872 if(#nargs > 2)then if(err)then error("Syntax Error: " .. op) else return "err" end end
873 -- Check if num is zero paged or absolute
874 if(#num == 2)then
875 -- Looks like we got a Zero Page, check for registered versions
876 if(string.upper(reg) == "X")then
877 optype = "ZPX"
878 if(debug)then print(instruction .. ":" .. optype .. " -> " .. num) end
879 return instruction, optype, num
880 elseif(string.upper(reg) == "Y")then
881 optype = "ZPY"
882 if(debug)then print(instruction .. ":" .. optype .. " -> " .. num) end
883 return instruction, optype, num
884 end
885 end
886
887 if(#num == 4)then
888 -- Looks like we got a Absolute, check for registered versions
889 if(string.upper(reg) == "X")then
890 optype = "ABX"
891 if(debug)then print(instruction .. ":" .. optype .. " -> " .. num .. ", X") end
892 return instruction, optype, num
893 elseif(string.upper(reg) == "Y")then
894 optype = "ABY"
895 if(debug)then print(instruction .. ":" .. optype .. " -> " .. num .. ", Y") end
896 return instruction, optype, num
897 else
898 -- Invalid register
899 if(err)then error("Syntax Error: " .. op) else return "err" end
900 end
901 end
902 else
903 -- Wut, we got a more than 4 digit value with no registers attached to it?!?!?, wut u smoking boi!
904 if(err)then error("Syntax Error: " .. op) else return "err" end
905 end
906 end
907
908 -- Indirect checking
909 if(args:sub(1,1) == "(")then
910 -- Any multi-argument statement needs to be space checked!
911 local args = string.upper(args:gsub("%s+", ""))
912 local num = 0
913 -- Insert true hex number into indirect instruction
914 if(args:sub(2,2) ~= "$")then
915 num = tonumber(args:sub(3,4))
916 if(num == nil)then if(err)then error("Syntax Error: " .. op) else return "err" end end
917 num = toHex(num)
918 args = args:sub(1,1) .. "$" .. num .. args:sub(4,#args)
919 elseif(args:sub(2,2) == "#")then
920 -- If user is trying to pass a value as an address, NOPE 'em!
921 if(err)then error("Syntax Error: " .. op) else return "err" end
922 else
923 -- If hex number is passed by default set that minus its $ symbol
924 num = args:sub(3,4)
925 end
926 if(args:sub(5,7) == "),Y")then
927 -- If this is found at 5 we know, this must be a INY
928 optype = "INY"
929 if(debug)then print(instruction .. ":" .. optype .. " -> (" .. num .. "), Y") end
930 return instruction, optype, num
931 end
932 if(args:sub(5,7) == ",X)")then
933 -- If this is found at 7 we know, this must be a INX
934 optype = "INX"
935 if(debug)then print(instruction .. ":" .. optype .. " -> (" .. num .. ", X)") end
936 return instruction, optype, num
937 end
938 if(args:sub(7,7) == ")")then
939 if(args:sub(2,2) ~= "$")then if(err)then error("Syntax Error: " .. op) else return "err" end end
940 -- If this is found at 7 we know, this must be a IN
941 -- Get new number as 2Byte HEX
942 num = args:sub(3,6)
943 if(#num == 4)then
944 optype = "IN"
945 else
946 if(err)then error("Syntax Error: " .. op) else return "err" end
947 end
948
949 if(debug)then print(instruction .. ":" .. optype .. " -> (" .. num .. ")") end
950 return instruction, optype, num
951 end
952 -- Zero paged indirect
953 if(args:sub(5,5) == ")")then
954 if(args:sub(2,2) ~= "$")then if(err)then error("Syntax Error: " .. op) else return "err" end end
955 -- If this is found at 5 we know, this must be a IZP
956 -- Get new number as 2Byte HEX
957 num = args:sub(3,4)
958 if(#num == 2)then
959 optype = "IZP"
960 else
961 if(err)then error("Syntax Error: " .. op) else return "err" end
962 end
963 if(debug)then print(instruction .. ":" .. optype .. " -> (" .. num .. ")") end
964 return instruction, optype, num
965 end
966 end
967
968 if(optype == "undefined")then
969 if(err)then error("Syntax Error: " .. op) else return "err" end
970 end
971
972end
973
974
975--- Setting everything up
976
977function initalize()
978 -- Define sizes in Bytes
979 _G.ASM = {}
980 _G.ASM.MSIZE = _KBYTE*64
981 _G.ASM.SSIZE = _BYTE*32
982 local GRAM = {}
983 local GREG = {}
984 local GSTACK = {}
985 -- Initialize Virtual RAM
986 for _RINDEX = 1, _G.ASM.MSIZE/_BUSWIDTH do
987 GRAM[_RINDEX] = string.rep(string.char("0"),_BUSWIDTH)
988 end
989 -- Initialize Virtual STACK
990 for _SINDEX = 1, _G.ASM.SSIZE/_BUSWIDTH do
991 GSTACK[_SINDEX] = string.rep(string.char("0"),_BUSWIDTH)
992 end
993 -- Initialize Virtual Registers
994 GREG['A'] = string.char("0")
995 GREG['X'] = string.char("0")
996 GREG['Y'] = string.char("0")
997 GREG['SP'] = string.char(tonumber("FF",16))
998 GREG['PC'] = string.char(tonumber("06",16)) .. string.char(tonumber("00",16))
999
1000 _G.ASM.pmode = 1 -- Program execution mode, 1 = text, 2 = graphics
1001 _G.ASM.ram = GRAM
1002 _G.ASM.stack = GSTACK
1003 _G.ASM.reg = GREG
1004 _G.ASM.flags = string.char(tonumber("00100000",2))
1005 _G.ASM.flagtypes = {
1006 ["CRY"] = 8, -- Carry
1007 ["ZRO"] = 7, -- Zero Flag
1008 ["INT"] = 6, -- Interupt Disable
1009 ["DEC"] = 5, -- Decimal
1010 ["BRK"] = 4, -- Software interupt
1011 ["UNK"] = 3, -- Unknown, logical 1
1012 ["OVR"] = 2, -- Overflow
1013 ["NEG"] = 1, -- Sign
1014 }
1015 -- Instruction encoding
1016 _G.ASM._HEXENCODE = {
1017 ['LDA'] = {
1018 ['IZP'] = "B2",
1019 ['IMM'] = "A9",
1020 ['ZP'] = "A5",
1021 ['ZPX'] = "B5",
1022 ['AB'] = "AD",
1023 ['ABX'] = "BD",
1024 ['ABY'] = "B9",
1025 ['INX'] = "A1",
1026 ['INY'] = "B1",
1027 },
1028 ['STA'] = {
1029 ['IZP'] = "92",
1030 ['ZP'] = "85",
1031 ['ZPX'] = "95",
1032 ['AB'] = "8D",
1033 ['ABX'] = "9D",
1034 ['ABY'] = "99",
1035 ['INX'] = "81",
1036 ['INY'] = "91",
1037 },
1038 ['ADC'] = {
1039 ['IZP'] = "72",
1040 ['IMM'] = "69",
1041 ['ZP'] = "65",
1042 ['ZPX'] = "75",
1043 ['AB'] = "6D",
1044 ['ABX'] = "7D",
1045 ['ABY'] = "79",
1046 ['INX'] = "61",
1047 ['INY'] = "71",
1048 },
1049 ['AND'] = {
1050 ['IZP'] = "32",
1051 ['IMM'] = "29",
1052 ['ZP'] = "25",
1053 ['ZPX'] = "35",
1054 ['AB'] = "2D",
1055 ['ABX'] = "3D",
1056 ['ABY'] = "39",
1057 ['INX'] = "21",
1058 ['INY'] = "31",
1059 },
1060 ['ASL'] = {
1061 ['ACC'] = "0A",
1062 ['ZP'] = "06",
1063 ['ZPX'] = "16",
1064 ['AB'] = "0E",
1065 ['ABX'] = "1E",
1066 },
1067 ['BCC'] = {
1068 ['REL'] = "90",
1069 },
1070 ['BCS'] = {
1071 ['REL'] = "B0",
1072 },
1073 ['BEQ'] = {
1074 ['REL'] = "F0",
1075 },
1076 ['BIT'] = {
1077 ['ZP'] = "24",
1078 ['AB'] = "2C",
1079 },
1080 ['BMI'] = {
1081 ['REL'] = "30",
1082 },
1083 ['BNE'] = {
1084 ['REL'] = "D0",
1085 },
1086 ['BPL'] = {
1087 ['REL'] = "10",
1088 },
1089 ['BRK'] = {
1090 ['IMP'] = "00",
1091 },
1092 ['BVC'] = {
1093 ['REL'] = "50",
1094 },
1095 ['BVS'] = {
1096 ['REL'] = "70",
1097 },
1098 ['CLC'] = {
1099 ['IMP'] = "18",
1100 },
1101 ['CLD'] = {
1102 ['IMP'] = "D8",
1103 },
1104 ['CLI'] = {
1105 ['IMP'] = "58",
1106 },
1107 ['CLV'] = {
1108 ['IMP'] = "B8",
1109 },
1110 ['CMP'] = {
1111 ['IZP'] = "D2",
1112 ['IMM'] = "C9",
1113 ['ZP'] = "C5",
1114 ['ZPX'] = "D5",
1115 ['AB'] = "CD",
1116 ['ABX'] = "DD",
1117 ['ABY'] = "D9",
1118 ['INX'] = "C1",
1119 ['INY'] = "D1",
1120 },
1121 ['CPX'] = {
1122 ['IMM'] = "E0",
1123 ['ZP'] = "E4",
1124 ['AB'] = "EC",
1125 },
1126 ['CPY'] = {
1127 ['IMM'] = "C0",
1128 ['ZP'] = "C4",
1129 ['AB'] = "CC",
1130 },
1131 ['DEC'] = {
1132 ['ACC'] = "3A",
1133 ['ZP'] = "C6",
1134 ['ZPX'] = "D6",
1135 ['AB'] = "CE",
1136 ['ABX'] = "DE",
1137 },
1138 ['DEX'] = {
1139 ['IMP'] = "CA",
1140 },
1141 ['DEY'] = {
1142 ['IMP'] = "88",
1143 },
1144 ['EOR'] = {
1145 ['IZP'] = "52",
1146 ['IMM'] = "49",
1147 ['ZP'] = "45",
1148 ['ZPX'] = "55",
1149 ['AB'] = "4D",
1150 ['ABX'] = "5D",
1151 ['ABY'] = "59",
1152 ['INX'] = "41",
1153 ['INY'] = "51",
1154 },
1155 ['INC'] = {
1156 ['ACC'] = "1A",
1157 ['ZP'] = "E6",
1158 ['ZPX'] = "F6",
1159 ['AB'] = "EE",
1160 ['ABX'] = "FE",
1161 },
1162 ['INX'] = {
1163 ['IMP'] = "E8",
1164 },
1165 ['INY'] = {
1166 ['IMP'] = "C8",
1167 },
1168 ['JMP'] = {
1169 ['AB'] = "4C",
1170 ['IN'] = "6C",
1171 },
1172 ['JSR'] = {
1173 ['AB'] = "20",
1174 },
1175 ['LDX'] = {
1176 ['IMM'] = "A2",
1177 ['ZP'] = "A6",
1178 ['ZPY'] = "B6",
1179 ['AB'] = "AE",
1180 ['ABY'] = "BE",
1181 },
1182 ['LDY'] = {
1183 ['IMM'] = "A0",
1184 ['ZP'] = "A4",
1185 ['ZPX'] = "B4",
1186 ['AB'] = "AC",
1187 ['ABX'] = "BC",
1188 },
1189 ['LSR'] = {
1190 ['ACC'] = "4A",
1191 ['ZP'] = "46",
1192 ['ZPX'] = "56",
1193 ['AB'] = "4E",
1194 ['ABX'] = "5E",
1195 },
1196 ['NOP'] = {
1197 ['IMP'] = "EA",
1198 },
1199 ['ORA'] = {
1200 ['IZP'] = "12",
1201 ['IMM'] = "09",
1202 ['ZP'] = "05",
1203 ['ZPX'] = "15",
1204 ['AB'] = "0D",
1205 ['ABX'] = "1D",
1206 ['ABY'] = "19",
1207 ['INX'] = "01",
1208 ['INY'] = "11",
1209 },
1210 ['PHA'] = {
1211 ['IMP'] = "48",
1212 },
1213 ['PHP'] = {
1214 ['IMP'] = "08",
1215 },
1216 ['PLA'] = {
1217 ['IMP'] = "68",
1218 },
1219 ['PLP'] = {
1220 ['IMP'] = "28",
1221 },
1222 ['ROL'] = {
1223 ['ACC'] = "2A",
1224 ['ZP'] = "26",
1225 ['ZPX'] = "36",
1226 ['AB'] = "2E",
1227 ['ABX'] = "3E",
1228 },
1229 ['ROR'] = {
1230 ['ACC'] = "6A",
1231 ['ZP'] = "66",
1232 ['ZPX'] = "76",
1233 ['AB'] = "6E",
1234 ['ABX'] = "7E",
1235 },
1236 ['RTI'] = {
1237 ['IMP'] = "40",
1238 },
1239 ['RTS'] = {
1240 ['IMP'] = "60",
1241 },
1242 ['SBC'] = {
1243 ['IZP'] = "F2",
1244 ['IMM'] = "E9",
1245 ['ZP'] = "E5",
1246 ['ZPX'] = "F5",
1247 ['AB'] = "ED",
1248 ['ABX'] = "FD",
1249 ['ABY'] = "F9",
1250 ['INX'] = "E1",
1251 ['INY'] = "F1",
1252 },
1253 ['SEC'] = {
1254 ['IMP'] = "38",
1255 },
1256 ['SED'] = {
1257 ['IMP'] = "F8",
1258 },
1259 ['SEI'] = {
1260 ['IMP'] = "78",
1261 },
1262 ['STX'] = {
1263 ['ZP'] = "86",
1264 ['ZPY'] = "96",
1265 ['AB'] = "8E",
1266 },
1267 ['STY'] = {
1268 ['ZP'] = "84",
1269 ['ZPX'] = "94",
1270 ['AB'] = "8C",
1271 },
1272 ['TAX'] = {
1273 ['IMP'] = "AA",
1274 },
1275 ['TAY'] = {
1276 ['IMP'] = "A8",
1277 },
1278 ['TSX'] = {
1279 ['IMP'] = "BA",
1280 },
1281 ['TXA'] = {
1282 ['IMP'] = "8A",
1283 },
1284 ['TXS'] = {
1285 ['IMP'] = "9A",
1286 },
1287 ['TYA'] = {
1288 ['IMP'] = "98",
1289 },
1290 }
1291 _G.ASM._OPCODES = {
1292 -- Bytes = How many more bytes to read
1293 -- Assembler will convert values to hex
1294 -- TODO: REMINDER!!!
1295 -- ACCUMULATIVE INSTRUCTIONS: Use 01 = A, 02 = X, 03 = Y
1296 --]] LDA instructions
1297 ["B2"] = {bytes=1,exe=function(self,val)
1298 -- Zero paged Indirect
1299 loadRegIndirect("A",val)
1300 updateResultFlags(readRegDec("A"))
1301 end},-- LDA ($00)
1302 ['A9'] = {bytes=1,exe=function(self,val)
1303 -- Load a value into A
1304 writeReg("A",val)
1305 updateResultFlags(val)
1306 end}, -- LDA #00
1307 ['A5'] = {bytes=1,exe=function(self,mem)
1308 -- Load a value from memory into A
1309 writeReg("A",readByteHex(mem))
1310 updateResultFlags(readByteDec(mem))
1311 end}, -- LDA $00
1312 ['B5'] = {bytes=1,exe=function(self,val)
1313 local val = ( tonumber(val,16) + decodeByte(readReg("X")) )
1314 writeReg("A",readDecByte(val))
1315 updateResultFlags(val)
1316 end}, -- LDA $00, X
1317 ['AD'] = {bytes=2,exe=function(self,lsb,msb)
1318 local val = readByteHex(msb .. lsb)
1319 writeReg('A',val)
1320 updateResultFlags(val)
1321 end}, -- LDA $0000
1322 ['BD'] = {bytes=2,exe=function(self,lsb,msb)
1323 local val = readAddressByte(msb..lsb,"X")
1324 writeReg('A', val)
1325 updateResultFlags(val)
1326 end}, -- LDA $0000, X
1327 ['B9'] = {bytes=2,exe=function(self,lsb,msb)
1328 local val = readAddressByte(msb..lsb,"Y")
1329 writeReg('A',val)
1330 updateResultFlags(val)
1331 end}, -- LDA $0000, Y
1332 ['A1'] = {bytes=1,exe=function(self,val)
1333 loadRegIndirect("A",val,"X")
1334 updateResultFlags(decodeByte(readReg("A")))
1335 end}, -- LDA ($00, X)
1336 ['B1'] = {bytes=1,exe=function(self,val)
1337 loadRegIndirect("A",val,"Y")
1338 updateResultFlags(decodeByte(readReg("A")))
1339 end}, -- LDA ($00), Y
1340 --]] STA instructions
1341 ['92'] = {bytes=1,exe=function(self,val)
1342 storeRegIndirect("A",val)
1343 end}, -- STA ($00)
1344 ['85'] = {bytes=1,exe=function(self,val) writeByteDec(val,readRegDec("A")) end}, -- STA $00
1345 ['95'] = {bytes=1,exe=function(self,val)
1346 local val = (tonumber(val,16) + decodeByte(readReg("X")))
1347 writeDecByte(val,readRegDec("A"))
1348 end}, -- STA $00, X
1349 ['8D'] = {bytes=2,exe=function(self,lsb,msb) writeByteDec(msb .. lsb,readRegDec("A")) end}, -- STA $0000
1350 ['9D'] = {bytes=2,exe=function(self,lsb,msb)
1351 local val = msb .. lsb
1352 local val = (tonumber(val,16) + decodeByte(readReg("X")))
1353 writeDecByte(val,readRegDec("A"))
1354 end}, -- STA $0000, X
1355 ['99'] = {bytes=2,exe=function(self,lsb,msb)
1356 local val = msb .. lsb
1357 local val = (tonumber(val,16) + decodeByte(readReg("Y")))
1358 writeDecByte(val,readRegDec("A"))
1359 end}, -- STA $0000, Y
1360 ['81'] = {bytes=1,exe=function(self,val)
1361 storeRegIndirect("A",val,"X")
1362 end}, -- STA ($00, X)
1363 ['91'] = {bytes=1,exe=function(self,val)
1364 storeRegIndirect("A",val,"Y")
1365 end}, -- STA ($00), Y
1366 -- ADC (Add with carry) Adds to A
1367 ['72'] = {bytes=1,exe=function(self,val)
1368 local num = signedAdd(readRegHex("A"),readByteHex(readIndirectByte(val)))
1369 writeReg("A",num)
1370 updateResultFlags(decodeByte(readReg("A")))
1371 end}, -- ADC ($00)
1372 ['69'] = {bytes=1,exe=function(self,val)
1373 local num = signedAdd(readRegHex("A"), val)
1374 writeReg("A",num)
1375 updateResultFlags(decodeByte(readReg("A")))
1376 end},-- ADC #00
1377 ['65'] = {bytes=1,exe=function(self,val)
1378 local num = signedAdd(readRegHex("A"), readByteHex(val) )
1379 writeReg("A",num)
1380 updateResultFlags(decodeByte(readReg("A")))
1381 end},-- ADC $00
1382 ['75'] = {bytes=1,exe=function(self,val)
1383 local num = signedAdd(readRegHex("A"),readAddressByte(val,"X"))
1384 writeReg("A",num)
1385 updateResultFlags(decodeByte(readReg("A")))
1386 end},-- ADC $00, X
1387 ['6D'] = {bytes=2,exe=function(self,lsb,msb)
1388 local num = signedAdd(readRegHex("A"), readByteHex(msb..lsb))
1389 writeReg("A",num)
1390 updateResultFlags(decodeByte(readReg("A")))
1391 end},-- ADC $0000
1392 ['7D'] = {bytes=2,exe=function(self,lsb,msb)
1393 local num = signedAdd(readRegHex("A"),readAddressByte(msb..lsb,"X"))
1394 writeReg("A",num)
1395 updateResultFlags(decodeByte(readReg("A")))
1396 end},-- ADC $0000, X
1397 ['79'] = {bytes=2,exe=function(self,lsb,msb)
1398 local num = signedAdd(readRegHex("A"),readAddressByte(msb..lsb,"Y"))
1399 writeReg("A",num)
1400 updateResultFlags(decodeByte(readReg("A")))
1401 end},-- ADC $0000, Y
1402 ['61'] = {bytes=1,exe=function(self,val)
1403 local num = signedAdd(readRegHex("A"),readByteHex(readIndirectByte(val,"X")))
1404 writeReg("A",num)
1405 updateResultFlags(decodeByte(readReg("A")))
1406 end},-- ADC ($00, X)
1407 ['71'] = {bytes=1,exe=function(self,val)
1408 local num = signedAdd(readRegHex("A"),readByteHex(readIndirectByte(val,"Y")))
1409 writeReg("A",num)
1410 updateResultFlags(decodeByte(readReg("A")))
1411 end},-- ADC ($00), Y
1412 -- AND (Logical And)
1413 ['32'] = {bytes=1,exe=function(self,val)
1414 local num = bit.band(decodeByte(readReg("A")), tonumber( readByteHex(readIndirectByte(val)), 16) )
1415 updateResultFlags(num)
1416 writeRegDec("A",num)
1417 end}, -- AND ($00)
1418 ['29'] = {bytes=1,exe=function(self,val)
1419 local num = bit.band(decodeByte(readReg("A")), tonumber(val,16))
1420 updateResultFlags(num)
1421 writeRegDec("A",num)
1422 end},-- AND #00
1423 ['25'] = {bytes=1,exe=function(self,val)
1424 local num = bit.band(decodeByte(readReg("A")), decodeByte(readByte(val)))
1425 updateResultFlags(num)
1426 writeRegDec("A",num)
1427 end},-- AND $00
1428 ['35'] = {bytes=1,exe=function(self,val)
1429 local num = bit.band(decodeByte(readReg("A")), tonumber(readAddressByte(val,"X"),16) )
1430 updateResultFlags(num)
1431 writeRegDec("A",num)
1432 end},-- AND $00, X
1433 ['2D'] = {bytes=2,exe=function(self,lsb,msb)
1434 local num = bit.band(decodeByte(readReg("A")), decodeByte(readByte(msb..lsb)))
1435 updateResultFlags(num)
1436 writeRegDec("A",num)
1437 end},-- AND $0000
1438 ['3D'] = {bytes=2,exe=function(self,lsb,msb)
1439 local num = bit.band(decodeByte(readReg("A")), tonumber(readAddressByte(msb..lsb,"X"),16) )
1440 updateResultFlags(num)
1441 writeRegDec("A",num)
1442 end},-- AND $0000, X
1443 ['39'] = {bytes=2,exe=function(self,lsb,msb)
1444 local num = bit.band(decodeByte(readReg("A")), tonumber(readAddressByte(msb..lsb,"Y"),16) )
1445 updateResultFlags(num)
1446 writeRegDec("A",num)
1447 end},-- AND $0000, Y
1448 ['21'] = {bytes=1,exe=function(self,val)
1449 local num = bit.band(decodeByte(readReg("A")), tonumber( readByteHex(readIndirectByte(val,"X")), 16) )
1450 updateResultFlags(num)
1451 writeRegDec("A",num)
1452 end},-- AND ($00, X)
1453 ['31'] = {bytes=1,exe=function(self,val)
1454 local num = bit.band(decodeByte(readReg("A")), tonumber( readByteHex(readIndirectByte(val,"Y"))),16)
1455 updateResultFlags(num)
1456 writeRegDec("A",num)
1457 end},-- AND ($00), Y
1458 -- ASL (Arithmetic Shift Left)
1459 ['0A'] = {bytes=1,exe=function(self,val)
1460 if(val == "01")then val = "A" end
1461 if(val == "02")then val = "X" end
1462 if(val == "03")then val = "Y" end
1463 local num = bit.blshift(decodeByte(readReg(val)), 1)
1464 setFlag("CRY",tonumber(toBin(num):sub(8,8)))
1465 updateResultFlags(num)
1466 if(num > 255)then num = 255 setFlag("NEG",0) end
1467 writeRegDec(val,num)
1468 end},-- ASL A/X/Y
1469 ['06'] = {bytes=1,exe=function(self,val)
1470 local num = bit.blshift(decodeByte(readByte(val)), 1)
1471 setFlag("CRY",tonumber(toBin(num):sub(8,8)))
1472 updateResultFlags((num))
1473 if(num > 255)then num = 255 setFlag("NEG",0) end
1474 writeByteDec(val,num)
1475 end},-- ASL $00
1476 ['16'] = {bytes=1,exe=function(self,val)
1477 local num = bit.blshift(tonumber(readAddressByte(val,"X"),16), 1)
1478 setFlag("CRY",tonumber(toBin(num):sub(8,8)))
1479 updateResultFlags((num))
1480 if(num > 255)then num = 255 setFlag("NEG",0) end
1481 writeByteDec(addHex(val,readRegHex("X")),num)
1482 end},-- ADC $00, X
1483 ['0E'] = {bytes=2,exe=function(self,lsb,msb)
1484 local num = bit.blshift(decodeByte(readByte(msb..lsb)), 1)
1485 setFlag("CRY",tonumber(toBin(num):sub(8,8)))
1486 updateResultFlags((num))
1487 if(num > 255)then num = 255 setFlag("NEG",0) end
1488 writeByteDec(msb..lsb,num)
1489 end},-- ADC $0000
1490 ['1E'] = {bytes=2,exe=function(self,lsb,msb)
1491 local num = bit.blshift(tonumber(readAddressByte(msb..lsb,"X"),16), 1)
1492 setFlag("CRY",tonumber(toBin(num):sub(8,8)))
1493 updateResultFlags((num))
1494 if(num > 255)then num = 255 setFlag("NEG",0) end
1495 writeByteDec(addHex(msb..lsb,readRegHex("Y")),num)
1496 end},-- ADC $0000, X
1497 -- BCC (Branch if Carry Clear)
1498 ['90'] = {bytes=1,exe=function(self,val)
1499 local num = signedHextoDec(val)
1500 if(getFlag("CRY") == "0")then movePC(num) end
1501 end},-- BCC *+val
1502 -- BCS (Branch if Carry Set)
1503 ['B0'] = {bytes=1,exe=function(self,val)
1504 local num = signedHextoDec(val)
1505 if(getFlag("CRY") == "1")then movePC(num) end
1506 end},-- BCS *+val
1507 -- BEQ (Branch if Equal)
1508 ['F0'] = {bytes=1,exe=function(self,val)
1509 local num = signedHextoDec(val)
1510 if(getFlag("ZRO") == "1")then movePC(num) end
1511 end},-- BCS *+val
1512 -- BIT (Bit Test)
1513 ['24'] = {bytes=1,exe=function(self,val)
1514 local num = bit.band(decodeByte(readReg("A")), decodeByte(readByte(val)))
1515 if(toBin(num):sub(2,2))then setFlag("OVR",1) end
1516 updateResultFlags(num)
1517 end},-- BIT $00
1518 ['2C'] = {bytes=2,exe=function(self,val)
1519 end},-- BIT $0000
1520 -- BMI (Branch if Minus)
1521 ['30'] = {bytes=1,exe=function(self,val)
1522 local num = signedHextoDec(val)
1523 if(getFlag("NEG") == "1")then movePC(num) end
1524 end},-- BMI *+val
1525 -- BNE (Branch if Not Equal)
1526 ['D0'] = {bytes=1,exe=function(self,val)
1527 local num = signedHextoDec(val)
1528
1529 if(getFlag("ZRO") == "0")then movePC(num) end
1530 end},-- BNE *+val
1531 -- BPL (Branch if Positive)
1532 ['10'] = {bytes=1,exe=function(self,val)
1533 local num = signedHextoDec(val)
1534 if(getFlag("NEG") == "0")then movePC(num) end
1535 end},-- BPL *+val
1536 -- BRK (Force Interrupt)
1537 ['00'] = {bytes=0,exe=function(self)
1538 pushStack(toHex(decodeByte(getFlagsByte())))
1539 local pc = "0" .. tostring(tonumber(readPC(),16)+1)
1540 pushStack(tostring(readPC()):sub(1,2))
1541 pushStack(tostring(readPC()):sub(3,4))
1542 -- Push status to stack, stop program wait for re-run program executor will check for interupt flag and pull from stacks and resume program
1543 setFlag("BRK",1)
1544 end},-- BRK
1545 -- BVC (Branch if Overflow Clear)
1546 ['50'] = {bytes=1,exe=function(self,val)
1547 local num = signedHextoDec(val)
1548 if(getFlag("OVR") == "0")then movePC(num) end
1549 end},-- BVC *+val
1550 -- BVS (Branch if Overflow Set)
1551 ['70'] = {bytes=1,exe=function(self,val)
1552 local num = signedHextoDec(val)
1553 if(getFlag("OVR") == "1")then movePC(num) end
1554 end},-- BVC *+val
1555 -- CLC (Clear Carry Flag)
1556 ['18'] = {bytes=0,exe=function(self,val)
1557 setFlag("CRY",0)
1558 end},-- CLC
1559 -- CLD (Clear Decimal Mode)
1560 ['D8'] = {bytes=0,exe=function(self,val)
1561 setFlag("DEC",0)
1562 end},-- CLD
1563 -- CLI (Clear Interrupt Disable)
1564 ['58'] = {bytes=0,exe=function(self,val)
1565 setFlag("INT",0)
1566 end},-- CLI
1567 -- CLV (Clear Overflow Flag)
1568 ['B8'] = {bytes=0,exe=function(self,val)
1569 setFlag("OVR",0)
1570 end},-- CLV
1571 -- CMP (Compare)
1572 ['D2'] = {bytes=1,exe=function(self,val)
1573 local num = tonumber(readByteHex(readIndirectByte(val)),16) - decodeByte(readReg("A"))
1574 if(num >= 0)then setFlag("CRY",1) else setFlag("CRY",0) end -- If A >= M
1575 updateResultFlags(num)
1576 end}, -- CMP ($00)
1577 ['C9'] = {bytes=1,exe=function(self,val)
1578 local num = decodeByte(readReg("A")) - tonumber(val,16)
1579 if(num >= 0)then setFlag("CRY",1) else setFlag("CRY",0) end -- If A >= M
1580 updateResultFlags(num)
1581 end},-- CMP #00
1582 ['C5'] = {bytes=1,exe=function(self,val)
1583 local num = decodeByte(readByte(val)) - decodeByte(readReg("A"))
1584 if(num >= 0)then setFlag("CRY",1) else setFlag("CRY",0) end -- If A >= M
1585 updateResultFlags(num)
1586 end},-- CMP $00
1587 ['D5'] = {bytes=1,exe=function(self,val)
1588 local num = tonumber(readAddressByte(val,"X"),16) - decodeByte(readReg("A"))
1589 if(num >= 0)then setFlag("CRY",1) else setFlag("CRY",0) end -- If A >= M
1590 updateResultFlags(num)
1591 end},-- CMP $00, X
1592 ['CD'] = {bytes=2,exe=function(self,lsb,msb)
1593 local num = decodeByte(readByte(msb..lsb)) - decodeByte(readReg("A"))
1594 if(num >= 0)then setFlag("CRY",1) else setFlag("CRY",0) end -- If A >= M
1595 updateResultFlags(num)
1596 end},-- CMP $0000
1597 ['DD'] = {bytes=2,exe=function(self,lsb,msb)
1598 local num = tonumber(readAddressByte(msb..lsb,"X"),16) - decodeByte(readReg("A"))
1599 if(num >= 0)then setFlag("CRY",1) else setFlag("CRY",0) end -- If A >= M
1600 updateResultFlags(num)
1601 end},-- CMP $0000, X
1602 ['D9'] = {bytes=2,exe=function(self,lsb,msb)
1603 local num = tonumber(readAddressByte(msb..lsb,"Y"),16) - decodeByte(readReg("A"))
1604 if(num >= 0)then setFlag("CRY",1) else setFlag("CRY",0) end -- If A >= M
1605 updateResultFlags(num)
1606 end},-- CMP $0000, Y
1607 ['C1'] = {bytes=1,exe=function(self,val)
1608 local num = tonumber(readByteHex(readIndirectByte(val,"X")),16) - decodeByte(readReg("A"))
1609 if(num >= 0)then setFlag("CRY",1) else setFlag("CRY",0) end -- If A >= M
1610 updateResultFlags(num)
1611 end},-- CMP ($00, X)
1612 ['D1'] = {bytes=1,exe=function(self,val)
1613 local num = tonumber(readByteHex(readIndirectByte(val,"Y")),16) - decodeByte(readReg("A"))
1614 if(num >= 0)then setFlag("CRY",1) else setFlag("CRY",0) end -- If A >= M
1615 updateResultFlags(num)
1616 end},-- CMP ($00), Y
1617 -- CPX (Compare X Register)
1618 ['E0'] = {bytes=1,exe=function(self,val)
1619 local num = tonumber(val,16) - decodeByte(readReg("X"))
1620 if(num >= 0)then setFlag("CRY",1) else setFlag("CRY",0) end -- If A >= M
1621 updateResultFlags(num)
1622 end},-- CPX #00
1623 ['E4'] = {bytes=1,exe=function(self,val)
1624 local num = decodeByte(readByte(val)) - decodeByte(readReg("X"))
1625 if(num >= 0)then setFlag("CRY",1) else setFlag("CRY",0) end -- If A >= M
1626 updateResultFlags(num)
1627 end},-- CPX $00
1628 ['EC'] = {bytes=2,exe=function(self,lsb,msb)
1629 local num = decodeByte(readByte(msb..lsb)) - decodeByte(readReg("X"))
1630 if(num >= 0)then setFlag("CRY",1) else setFlag("CRY",0) end -- If A >= M
1631 updateResultFlags(num)
1632 end},-- CPX $0000
1633 -- CPY (Compare Y Register)
1634 ['C0'] = {bytes=1,exe=function(self,val)
1635 local num = tonumber(val,16) - decodeByte(readReg("Y"))
1636 if(num >= 0)then setFlag("CRY",1) else setFlag("CRY",0) end -- If A >= M
1637 updateResultFlags(num)
1638 end},-- CPY #00
1639 ['C4'] = {bytes=1,exe=function(self,val)
1640 local num = decodeByte(readByte(val)) - decodeByte(readReg("Y"))
1641 if(num >= 0)then setFlag("CRY",1) else setFlag("CRY",0) end -- If A >= M
1642 updateResultFlags(num)
1643 end},-- CPY $00
1644 ['CC'] = {bytes=2,exe=function(self,lsb,msb)
1645 local num = decodeByte(readByte(msb..lsb)) - decodeByte(readReg("Y"))
1646 if(num >= 0)then setFlag("CRY",1) else setFlag("CRY",0) end -- If A >= M
1647 updateResultFlags(num)
1648 end},-- CPY $0000
1649 -- DEC (Decrement Memory)
1650 ['3A'] = {bytes=1,exe=function(self,val)
1651 if(val == "01")then val = "A" end
1652 if(val == "02")then val = "X" end
1653 if(val == "03")then val = "Y" end
1654 local num = subHex(readRegHex(val),"01")
1655 writeReg(val,num)
1656 end}, -- INC A/X/Y
1657 ['C6'] = {bytes=1,exe=function(self,val)
1658 local num = subSignedDec(readByteHex(val),"01")
1659 writeByteDec(val,num)
1660 end},-- DEC $00
1661 ['D6'] = {bytes=1,exe=function(self,val)
1662 local num = subSignedDec(readAddressByte(val,"X"),"01")
1663 writeByteDec(addHex(val,readRegHex("X")),num)
1664 end},-- DEC $00, X
1665 ['CE'] = {bytes=2,exe=function(self,lsb,msb)
1666 local num = subSignedDec(readByteHex(msb..lsb),"01")
1667 writeByteDec(msb..lsb,num)
1668 end},-- DEC $0000
1669 ['DE'] = {bytes=2,exe=function(self,lsb,msb)
1670 local num = subSignedDec(readAddressByte(msb..lsb,"X"),"01")
1671 writeByteDec(addHex(msb..lsb,readRegHex("X")),num)
1672 end},-- DEC $0000, X
1673 -- DEX (Decrement X Register)
1674 ['CA'] = {bytes=0,exe=function(self,val)
1675 local num = subSignedDec(readRegHex('X'),"01")
1676 updateResultFlags(num)
1677 writeRegDec("X",num)
1678 end},-- DEX
1679 -- DEY (Decrement Y Register)
1680 ['88'] = {bytes=0,exe=function(self,val)
1681 local num = subSignedDec(readRegHex('Y'),"01")
1682 updateResultFlags(num)
1683 writeRegDec("Y",num)
1684 end},-- DEY
1685 -- EOR (Exclusive OR)
1686 ['52'] = {bytes=1,exe=function(self,val)
1687 local num = bit.bxor(tonumber(readRegHex("A"),16), tonumber(readByteHex(readIndirectByte(val)),16))
1688 updateResultFlags(num)
1689 writeRegDec("A",num)
1690 end}, -- EOR ($00)
1691 ['49'] = {bytes=1,exe=function(self,val)
1692 local num = bit.bxor(tonumber(readRegHex("A"),16), tonumber(val,16))
1693 updateResultFlags(num)
1694 writeRegDec("A",num)
1695 end},-- EOR #00
1696 ['45'] = {bytes=1,exe=function(self,val)
1697 local num = bit.bxor(tonumber(readRegHex("A"),16), tonumber(readByteHex(val),16))
1698 updateResultFlags(num)
1699 writeRegDec("A",num)
1700 end},-- EOR $00
1701 ['55'] = {bytes=1,exe=function(self,val)
1702 local num = bit.bxor(tonumber(readRegHex("A"),16), tonumber(readAddressByte(val,"X"),16))
1703 updateResultFlags(num)
1704 writeRegDec("A",num)
1705 end},-- EOR $00, X
1706 ['4D'] = {bytes=2,exe=function(self,lsb,msb)
1707 local num = bit.bxor(tonumber(readRegHex("A"),16), tonumber(readByteHex(msb..lsb),16))
1708 updateResultFlags(num)
1709 writeRegDec("A",num)
1710 end},-- EOR $0000
1711 ['5D'] = {bytes=2,exe=function(self,lsb,msb)
1712 local num = bit.bxor(tonumber(readRegHex("A"),16), tonumber(readAddressByte(msb..lsb,"X"),16))
1713 updateResultFlags(num)
1714 writeRegDec("A",num)
1715 end},-- EOR $0000, X
1716 ['59'] = {bytes=2,exe=function(self,lsb,msb)
1717 local num = bit.bxor(tonumber(readRegHex("A"),16), tonumber(readAddressByte(msb..lsb,"Y"),16))
1718 updateResultFlags(num)
1719 writeRegDec("A",num)
1720 end},-- EOR $0000, Y
1721 ['41'] = {bytes=1,exe=function(self,val)
1722 local num = bit.bxor(tonumber(readRegHex("A"),16), tonumber(readByteHex(readIndirectByte(val,"X")),16))
1723 updateResultFlags(num)
1724 writeRegDec("A",num)
1725 end},-- EOR ($00, X)
1726 ['51'] = {bytes=1,exe=function(self,val)
1727 local num = bit.bxor(tonumber(readRegHex("A"),16), tonumber(readByteHex(readIndirectByte(val,"Y")),16))
1728 updateResultFlags(num)
1729 writeRegDec("A",num)
1730 end},-- EOR ($00), Y
1731 -- INC (Increment Memory)
1732 ['1A'] = {bytes=1,exe=function(self,val)
1733 if(val == "01")then val = "A" end
1734 if(val == "02")then val = "X" end
1735 if(val == "03")then val = "Y" end
1736 local num = addHex(readRegHex(val),"01")
1737 writeReg(val,num)
1738 end}, -- INC A/X/Y
1739 ['E6'] = {bytes=1,exe=function(self,val)
1740 local num = addSignedDec(readByteHex(val),"01")
1741 writeByteDec(val,num)
1742 end},-- INC $00
1743 ['F6'] = {bytes=1,exe=function(self,val)
1744 local num = addSignedDec(readAddressByte(val,"X"),"01")
1745 writeByteDec(addHex(val,readRegHex("X")),num)
1746 end},-- INC $00, X
1747 ['EE'] = {bytes=2,exe=function(self,lsb,msb)
1748 local num = addSignedDec(readByteHex(msb..lsb),"01")
1749 writeByteDec(msb..lsb,num)
1750 end},-- INC $0000
1751 ['FE'] = {bytes=2,exe=function(self,val)
1752 local num = addSignedDec(readAddressByte(msb..lsb,"X"),"01")
1753 writeByteDec(addHex(msb..lsb,readRegHex("X")),num)
1754 end},-- INC $0000, X
1755 -- INX (Increment X Register)
1756 ['E8'] = {bytes=0,exe=function(self,val)
1757 local num = addSignedDec(readRegHex('X'),"01")
1758 updateResultFlags(num)
1759 writeRegDec("X",num)
1760 end},-- INX
1761 -- INY (Increment Y Register)
1762 ['C8'] = {bytes=0,exe=function(self,val)
1763 local num = addSignedDec(readRegHex('Y'),"01")
1764 updateResultFlags(num)
1765 writeRegDec("Y",num)
1766 end},-- INY
1767 -- JMP (Jump)
1768 ['4C'] = {bytes=2,exe=function(self,lsb,msb)
1769 setPC(msb..lsb)
1770 end},-- JMP $0000
1771 ['6C'] = {bytes=2,exe=function(self,lsb,msb)
1772 setPC(readIndirectByte(msb..lsb))
1773 end},-- JMP ($0000)
1774 -- JSR
1775 ['20'] = {bytes=2,exe=function(self,lsb,msb)
1776 pushStack(readPC():sub(1,2))
1777 pushStack(readPC():sub(3,4))
1778 setPC(msb..lsb)
1779 end},-- JSR $0000
1780 -- LDX (Load X Register)
1781 ['A2'] = {bytes=1,exe=function(self,val)
1782 writeReg("X",val)
1783 updateResultFlags(val)
1784 end},-- LDX #00
1785 ['A6'] = {bytes=1,exe=function(self,val)
1786 writeReg("X",readByteHex(val))
1787 updateResultFlags(readByteDec(val))
1788 end},-- LDX $00
1789 ['B6'] = {bytes=1,exe=function(self,val)
1790 local val = ( tonumber(val,16) + decodeByte(readReg("Y")) )
1791 writeRegDec("X",val)
1792 updateResultFlags(val)
1793 end},-- LDX $00, Y
1794 ['AE'] = {bytes=2,exe=function(self,lsb,msb)
1795 local val = readByteHex(msb .. lsb)
1796 writeRegDec('X',val)
1797 updateResultFlags(val)
1798 end},-- LDX $0000
1799 ['BE'] = {bytes=2,exe=function(self,lsb,msb)
1800 local val = readAddressByte(msb..lsb,"Y")
1801 writeReg('X', val)
1802 updateResultFlags(val)
1803 end},-- LDX $0000, Y
1804 -- LDY (Load Y Register)
1805 ['A0'] = {bytes=1,exe=function(self,val)
1806 writeReg("Y",val)
1807 updateResultFlags(val)
1808 end},-- LDY #00
1809 ['A4'] = {bytes=1,exe=function(self,val)
1810 writeReg("Y",readByteHex(val))
1811 updateResultFlags(readByteDec(val))
1812 end},-- LDY $00
1813 ['B4'] = {bytes=1,exe=function(self,val)
1814 local val = ( tonumber(val,16) + decodeByte(readReg("X")) )
1815 writeRegDec("Y",val)
1816 updateResultFlags(val)
1817 end},-- LDY $00, X
1818 ['AC'] = {bytes=2,exe=function(self,lsb,msb)
1819 local val = readByteHex(msb .. lsb)
1820 writeReg('Y',val)
1821 updateResultFlags(val)
1822 end},-- LDY $0000
1823 ['BC'] = {bytes=2,exe=function(self,lsb,msb)
1824 local val = readAddressByte(msb..lsb,"X")
1825 writeReg('Y', val)
1826 updateResultFlags(val)
1827 end},-- LDY $0000, X
1828 -- LSR (Logical Shift Right)
1829 ['4A'] = {bytes=1,exe=function(self,val)
1830 if(val == "01")then val = "A" end
1831 if(val == "02")then val = "X" end
1832 if(val == "03")then val = "Y" end
1833 local num = bit.brshift(decodeByte(readReg(val)), 1)
1834 setFlag("CRY",tonumber(toBin(num):sub(8,8)))
1835 updateResultFlags(num)
1836 writeRegDec(val,num)
1837 end},-- LSR A/X/Y
1838 ['46'] = {bytes=1,exe=function(self,val)
1839 local num = bit.brshift(decodeByte(readByte(val)), 1)
1840 setFlag("CRY",tonumber(toBin(num):sub(8,8)))
1841 updateResultFlags(num)
1842 writeByteDec(val,num)
1843 end},-- LSR $00
1844 ['56'] = {bytes=1,exe=function(self,val)
1845 local num = bit.brshift(tonumber(readAddressByte(val,"X"),16), 1)
1846 setFlag("CRY",tonumber(toBin(num):sub(8,8)))
1847 updateResultFlags(num)
1848 writeByteDec(val,num)
1849 end},-- LSR $00, X
1850 ['4E'] = {bytes=2,exe=function(self,lsb,msb)
1851 local num = bit.brshift(decodeByte(readByte(msb..lsb)), 1)
1852 setFlag("CRY",tonumber(toBin(num):sub(8,8)))
1853 updateResultFlags(num)
1854 writeByteDec(msb..lsb,num)
1855 end},-- LSR $0000
1856 ['5E'] = {bytes=2,exe=function(self,lsb,msb)
1857 local num = bit.brshift(tonumber(readAddressByte(msb..lsb,"X"),16), 1)
1858 setFlag("CRY",tonumber(toBin(num):sub(8,8)))
1859 updateResultFlags(num)
1860 writeByteDec(msb..lsb,num)
1861 end},-- LSR $0000, X
1862 -- NOP (No Operation)
1863 ['EA'] = {bytes=0,exe=function(self,val)
1864 sleep(0) -- CC is alot faster than ur average 6502
1865 end},-- NOP
1866 -- ORA (Logical Inclusive OR)
1867 ['12'] = {bytes=1,exe=function(self,val)
1868 local num = bit.bor(tonumber(readRegHex("A"),16), tonumber(readByteHex(readIndirectByte(val)),16))
1869 updateResultFlags(num)
1870 writeRegDec("A",num)
1871 end}, -- ORA ($00)
1872 ['09'] = {bytes=1,exe=function(self,val)
1873 local num = bit.bor(tonumber(readRegHex("A"),16), tonumber(val,16))
1874 updateResultFlags((num))
1875 writeRegDec("A",(num))
1876 end},-- ORA #00
1877 ['05'] = {bytes=1,exe=function(self,val)
1878 local num = bit.bor(tonumber(readRegHex("A"),16), tonumber(readByteHex(val),16))
1879 updateResultFlags((num))
1880 writeRegDec("A",(num))
1881 end},-- ORA $00
1882 ['15'] = {bytes=1,exe=function(self,val)
1883 local num = bit.bor(tonumber(readRegHex("A"),16), tonumber(readAddressByte(val,"X"),16))
1884 updateResultFlags((num))
1885 writeRegDec("A",(num))
1886 end},-- ORA $00, X
1887 ['0D'] = {bytes=2,exe=function(self,lsb,msb)
1888 local num = bit.bor(tonumber(readRegHex("A"),16), tonumber(readByteHex(msb..lsb),16))
1889 updateResultFlags((num))
1890 writeRegDec("A",(num))
1891 end},-- ORA $0000
1892 ['1D'] = {bytes=2,exe=function(self,lsb,msb)
1893 local num = bit.bor(tonumber(readRegHex("A"),16), tonumber(readAddressByte(msb..lsb,"X"),16))
1894 updateResultFlags((num))
1895 writeRegDec("A",(num))
1896 end},-- ORA $0000, X
1897 ['19'] = {bytes=2,exe=function(self,lsb,msb)
1898 local num = bit.bor(tonumber(readRegHex("A"),16), tonumber(readAddressByte(msb..lsb,"Y"),16))
1899 updateResultFlags((num))
1900 writeRegDec("A",(num))
1901 end},-- ORA $0000, Y
1902 ['01'] = {bytes=1,exe=function(self,val)
1903 local num = bit.bor(tonumber(readRegHex("A"),16), tonumber(readByteHex(readIndirectByte(val,"X")),16))
1904 updateResultFlags((num))
1905 writeRegDec("A",(num))
1906 end},-- ORA ($00, X)
1907 ['11'] = {bytes=1,exe=function(self,val)
1908 local num = bit.bor(tonumber(readRegHex("A"),16), tonumber(readByteHex(readIndirectByte(val,"Y")),16))
1909 updateResultFlags((num))
1910 writeRegDec("A",(num))
1911 end},-- ORA ($00), Y
1912 -- PHA (Push Accumulator)
1913 ['48'] = {bytes=0,exe=function(self,val)
1914 pushStack(readRegHex("A"))
1915 end},-- PHA
1916 -- PHP (Push Processor Status)
1917 ['08'] = {bytes=0,exe=function(self,val)
1918 pushStack(toHex(decodeByte(getFlagsByte())))
1919 end},-- PHP
1920 -- PLA (Pull Accumulator)
1921 ['68'] = {bytes=0,exe=function(self,val)
1922 writeRegDec("A", decodeByte(pullStack()))
1923 updateResultFlags(readRegDec("A"))
1924 end},-- PLA
1925 -- PLP (Pull Processor Status)
1926 ['28'] = {bytes=0,exe=function(self,val)
1927 setAllFlags(pullStack())
1928 end},-- PLP
1929 -- ROL (Rotate Left)
1930 ['2A'] = {bytes=1,exe=function(self,val)
1931 if(val == "01")then val = "A" end
1932 if(val == "02")then val = "X" end
1933 if(val == "03")then val = "Y" end
1934 setFlag("CRY",tonumber(toBin(decodeByte(readReg(val))):sub(8,8)))
1935 local num = bit.blshift(decodeByte(readReg(val)), 1)
1936 updateResultFlags(num)
1937 if(num > 255)then num = tonumber(toHex(num):sub(#toHex(num)-1,#toHex(num)),16) end
1938 writeRegDec(val,num)
1939 end},-- ROL A/X/Y
1940 ['26'] = {bytes=1,exe=function(self,val)
1941 local num = bit.blshift(decodeByte(readByte(val)), 1)
1942 setFlag("CRY",tonumber(toBin(decodeByte(readByte(val))):sub(8,8)))
1943 updateResultFlags((num))
1944 if(num > 255)then num = tonumber(toHex(num):sub(#toHex(num)-1,#toHex(num)),16) end
1945 writeByteDec(val,(num))
1946 end},-- ROL $00
1947 ['36'] = {bytes=1,exe=function(self,val)
1948 local num = bit.blshift(tonumber(readAddressByte(val,"X"),16), 1)
1949 setFlag("CRY",tonumber(toBin(tonumber(readAddressByte(val,"X"),16)):sub(8,8)))
1950 updateResultFlags((num))
1951 if(num > 255)then num = tonumber(toHex(num):sub(#toHex(num)-1,#toHex(num)),16) end
1952 writeByteDec(readAddressByte(val,"X"),(num))
1953 end},-- ROL $00, X
1954 ['2E'] = {bytes=2,exe=function(self,lsb,msb)
1955 local num = bit.blshift(decodeByte(readByte(msb..lsb)), 1)
1956 setFlag("CRY",tonumber(toBin(decodeByte(readByte(msb..lsb))):sub(8,8)))
1957 updateResultFlags((num))
1958 if(num > 255)then num = tonumber(toHex(num):sub(#toHex(num)-1,#toHex(num)),16) end
1959 writeByteDec(msb..lsb,(num))
1960 end},-- ROL $0000
1961 ['3E'] = {bytes=2,exe=function(self,lsb,msb)
1962 local num = bit.blshift(tonumber(readAddressByte(msb..lsb,"X"),16), 1)
1963 setFlag("CRY",tonumber(toBin(tonumber(readAddressByte(msb..lsb,"X"),16)):sub(8,8)))
1964 updateResultFlags((num))
1965 if(num > 255)then num = tonumber(toHex(num):sub(#toHex(num)-1,#toHex(num)),16) end
1966 writeByteDec(readAddressByte(msb..lsb,"X"),(num))
1967 end},-- ROL $0000, X
1968 -- ROR (Rotate Right)
1969 ['6A'] = {bytes=1,exe=function(self,val)
1970 if(val == "01")then val = "A" end
1971 if(val == "02")then val = "X" end
1972 if(val == "03")then val = "Y" end
1973 setFlag("CRY",tonumber(toBin(decodeByte(readReg(val))):sub(8,8)))
1974 local num = bit.brshift(decodeByte(readReg(val)), 1)
1975 updateResultFlags((num))
1976 if(num > 255)then num = tonumber(toHex(num):sub(#toHex(num)-1,#toHex(num)),16) end
1977 writeRegDec(val,(num))
1978 end},-- ROR A/X/Y
1979 ['66'] = {bytes=1,exe=function(self,val)
1980 local num = bit.brshift(decodeByte(readByte(val)), 1)
1981 setFlag("CRY",tonumber(toBin(decodeByte(readByte(val))):sub(8,8)))
1982 updateResultFlags((num))
1983 if(num > 255)then num = tonumber(toHex(num):sub(#toHex(num)-1,#toHex(num)),16) end
1984 writeByteDec(val,(num))
1985 end},-- ROR $00
1986 ['76'] = {bytes=1,exe=function(self,val)
1987 local num = bit.brshift(tonumber(readAddressByte(val,"X"),16), 1)
1988 setFlag("CRY",tonumber(toBin(tonumber(readAddressByte(val,"X"),16)):sub(8,8)))
1989 updateResultFlags((num))
1990 if(num > 255)then num = tonumber(toHex(num):sub(#toHex(num)-1,#toHex(num)),16) end
1991 writeByteDec(readAddressByte(val,"X"),(num))
1992 end},-- ROR $00, X
1993 ['6E'] = {bytes=2,exe=function(self,lsb,msb)
1994 local num = bit.brshift(decodeByte(readByte(msb..lsb)), 1)
1995 setFlag("CRY",tonumber(toBin(decodeByte(readByte(msb..lsb))):sub(8,8)))
1996 updateResultFlags((num))
1997 if(num > 255)then num = tonumber(toHex(num):sub(#toHex(num)-1,#toHex(num)),16) end
1998 writeByteDec(msb..lsb,(num))
1999 end},-- ROR $0000
2000 ['7E'] = {bytes=2,exe=function(self,lsb,msb)
2001 local num = bit.brshift(tonumber(readAddressByte(msb..lsb,"X"),16), 1)
2002 setFlag("CRY",tonumber(toBin(tonumber(readAddressByte(msb..lsb,"X"),16)):sub(8,8)))
2003 updateResultFlags((num))
2004 if(num > 255)then num = tonumber(toHex(num):sub(#toHex(num)-1,#toHex(num)),16) end
2005 writeByteDec(readAddressByte(msb..lsb,"X"),(num))
2006 end},-- ROR $0000, X
2007 -- RTI (Return from Interrupt)
2008 ['40'] = {bytes=0,exe=function(self,val)
2009 local lsb = toHex(decodeByte(pullStack()))
2010 local msb = toHex(decodeByte(pullStack()))
2011 local status = pullStack()
2012 setAllFlags(status)
2013 setPC(msb..lsb)
2014 end},-- RTI
2015 -- RTS (Return from Subroutine)
2016 ['60'] = {bytes=0,exe=function(self,val)
2017 local lsb = toHex(decodeByte(pullStack()))
2018 local msb = toHex(decodeByte(pullStack()))
2019 setPC(msb..lsb)
2020 end},-- RTS
2021 -- SBC (Subtract with Carry)
2022 ['F2'] = {bytes=1,exe=function(self,val)
2023 local num = bit.bor(tonumber(readRegHex("A"),16), tonumber(readByteHex(readIndirectByte(val)),16))
2024 updateResultFlags((num))
2025 writeRegDec("A",(num))
2026 end}, -- SBC ($00)
2027 ['E9'] = {bytes=1,exe=function(self,val)
2028 local num = signedSub(readRegHex("A"), val)
2029 writeReg("A",num)
2030 updateResultFlags(decodeByte(readReg("A")))
2031 end},-- SBC #00
2032 ['E5'] = {bytes=1,exe=function(self,val)
2033 local num = signedSub(readRegHex("A"), readByteHex(val) )
2034 writeReg("A",num)
2035 updateResultFlags(decodeByte(readReg("A")))
2036 end},-- SBC $00
2037 ['F5'] = {bytes=1,exe=function(self,val)
2038 local num = signedSub(readRegHex("A"),readAddressByte(val,"X"))
2039 writeReg("A",num)
2040 updateResultFlags(decodeByte(readReg("A")))
2041 end},-- SBC $00, X
2042 ['ED'] = {bytes=2,exe=function(self,lsb,msb)
2043 local num = signedSub(readRegHex("A"), readByteHex(msb..lsb))
2044 writeReg("A",num)
2045 updateResultFlags(decodeByte(readReg("A")))
2046 end},-- SBC $0000
2047 ['FD'] = {bytes=2,exe=function(self,lsb,msb)
2048 local num = signedSub(readRegHex("A"),readAddressByte(msb..lsb,"X"))
2049 writeReg("A",num)
2050 updateResultFlags(decodeByte(readReg("A")))
2051 end},-- SBC $0000, X
2052 ['F9'] = {bytes=2,exe=function(self,lsb,msb)
2053 local num = signedSub(readRegHex("A"),readAddressByte(msb..lsb,"Y"))
2054 writeReg("A",num)
2055 updateResultFlags(decodeByte(readReg("A")))
2056 end},-- SBC $0000, Y
2057 ['E1'] = {bytes=2,exe=function(self,val)
2058 local num = signedSub(readRegHex("A"),readByteHex(readIndirectByte(val,"X")))
2059 writeReg("A",num)
2060 updateResultFlags(decodeByte(readReg("A")))
2061 end},-- SBC ($00, X)
2062 ['F1'] = {bytes=2,exe=function(self,val)
2063 local num = signedSub(readRegHex("A"),readByteHex(readIndirectByte(val,"Y")))
2064 writeReg("A",num)
2065 updateResultFlags(decodeByte(readReg("A")))
2066 end},-- SBC ($00), Y
2067 -- SEC (Set Carry Flag)
2068 ['38'] = {bytes=0,exe=function(self,val)
2069 setFlag("CRY",1)
2070 end},-- SEC
2071 -- SED (Set Decimal Flag)
2072 ['F8'] = {bytes=0,exe=function(self,val)
2073 setFlag("DEC",1)
2074 end},-- SED
2075 -- SEI (Set Interrupt Disable)
2076 ['78'] = {bytes=0,exe=function(self,val)
2077 setFlag("INT",1)
2078 end},-- SEI
2079 -- STX (Store X Register)
2080 ['86'] = {bytes=1,exe=function(self,val)
2081 writeByte(val,readRegHex("X"))
2082 end},-- STX $00
2083 ['96'] = {bytes=1,exe=function(self,val)
2084 local val = toHex(tonumber(val,16) + decodeByte(readReg("Y")))
2085 writeByteDec(addHex(val,readRegHex("Y")),decodeByte(readReg("X")))
2086 end},-- STX $00, Y
2087 ['8E'] = {bytes=2,exe=function(self,lsb,msb)
2088 writeByte(msb .. lsb,readRegHex("X"))
2089 end},-- STX $0000
2090 -- STY (Store Y Register)
2091 ['84'] = {bytes=1,exe=function(self,val)
2092 writeByte(val,readRegHex("Y"))
2093 end},-- STY $00
2094 ['94'] = {bytes=1,exe=function(self,val)
2095 local val = toHex(tonumber(val,16) + decodeByte(readReg("X")))
2096 writeByteDec(addHex(val,readRegHex("X"),decodeByte(readReg("Y"))))
2097 end},-- STY $00, X
2098 ['8C'] = {bytes=2,exe=function(self,lsb,msb)
2099 writeByte(msb .. lsb,readRegHex("Y"))
2100 end},-- STY $0000
2101 -- TAX (Transfer Accumulator to X)
2102 ['AA'] = {bytes=0,exe=function(self,val)
2103 moveRegs("A","X",true)
2104 end},-- TAX
2105 -- TAY (Transfer Accumulator to Y)
2106 ['A8'] = {bytes=0,exe=function(self,val)
2107 moveRegs("A","Y",true)
2108 end},-- TAX
2109 -- TSX (Transfer Stack Pointer to X)
2110 ['BA'] = {bytes=1,exe=function(self,val)
2111 moveRegs("SP`","X",true)
2112 end},-- TSX
2113 -- TXA (Transfer X to Accumulator)
2114 ['8A'] = {bytes=0,exe=function(self,val)
2115 moveRegs("X","A",true)
2116 end},-- TXA
2117 -- TXS (Transfer X to Stack Pointer)
2118 ['9A'] = {bytes=0,exe=function(self,val)
2119 moveRegs("X","SP",true)
2120 end},-- TXS
2121 -- TYA (Transfer Y to Accumulator)
2122 ['98'] = {bytes=0,exe=function(self,val)
2123 moveRegs("Y","A",true)
2124 end},-- TYA
2125}
2126end
2127
2128function getInstuctionBytes(op,type)
2129 if(_G.ASM._HEXENCODE[op])then
2130 if(_G.ASM._OPCODES[_G.ASM._HEXENCODE[op][type]] == nil)then
2131 print(type)
2132 end
2133 return _G.ASM._OPCODES[_G.ASM._HEXENCODE[op][type]].bytes+1
2134 else
2135 return "err"
2136 end
2137end
2138
2139function str_shearWord(str,word)
2140 local str = str:gsub("%s+","")
2141 return str:sub(#word+1,#str)
2142end
2143
2144function AssembleHEX(code,ln)
2145 local op, otype, num = procInstructionType(code,false,false)
2146 if(op == "err")then error("Syntax error line " .. ln .. ": " .. code:gsub("%s+","")) end
2147 local hex = runOpperation(op,otype,num,false,true)
2148 return hex
2149end
2150
2151function DecodeOpCodeHex(hex,args)
2152 for k, v in pairs(_G.ASM._HEXENCODE) do
2153 for kk, vv in pairs(v) do
2154 if(vv == hex)then
2155 local format = k .. " "
2156 if(kk == "IMP")then
2157 elseif(kk == "IMM")then
2158 format = format .. "#$" .. args[1]
2159 elseif(kk == "AB")then
2160 format = format .. "$" .. args[2] .. args[1]
2161 elseif(kk == "ABX")then
2162 format = format .. "$" .. args[2] .. args[1] .. ", X"
2163 elseif(kk == "ABY")then
2164 format = format .. "$" .. args[2] .. args[1] .. ", Y"
2165 elseif(kk == "IN")then
2166 format = format .. "($" .. args[1] .. ")"
2167 elseif(kk == "INX")then
2168 format = format .. "($" .. args[1] .. ", X)"
2169 elseif(kk == "INY")then
2170 format = format .. "($" .. args[1] .. "), Y"
2171 elseif(kk == "ACC")then
2172 format = format .. "$" .. args[1]
2173 elseif(kk == "REL")then
2174 format = format .. "$" .. args[1]
2175 elseif(kk == "ZP")then
2176 format = format .. "$" .. args[1]
2177 end
2178 return format
2179 end
2180 end
2181 end
2182end
2183
2184function disassembleASM(input)
2185 local code = ""
2186 local hex = {}
2187 local f = fs.open(input,"rb")
2188 local progstart = ""
2189 local counter = 1
2190 local index = 1
2191 for byte in f.read do -- Iterate over every byte in the file.
2192 if(index > 2)then
2193 hex[#hex+1] = toHex(byte)
2194 else
2195 progstart = progstart .. toHex(byte)
2196 end
2197 index = index + 1
2198 end
2199 f.close()
2200
2201 print("Read " .. index .. " Bytes.")
2202 local codeindex = 1
2203 while codeindex < #hex do
2204 local args = {}
2205 local dump = hex[codeindex]
2206 local opBytes = 0
2207 local opperation = "???"
2208 if(_G.ASM._OPCODES[hex[codeindex]] ~= nil)then
2209 opBytes = _G.ASM._OPCODES[hex[codeindex]].bytes
2210 if(opBytes >= 1)then
2211 for byteIndex = 1, opBytes do
2212 args[#args+1] = hex[codeindex+byteIndex]
2213 dump = dump .. " " .. hex[codeindex+byteIndex]
2214 end
2215 end
2216 opperation = DecodeOpCodeHex(hex[codeindex],args)
2217 end
2218 -- Example:
2219 -- Address Hexdump Disassembly
2220 -- -------------------------------
2221 -- $600 A9 02 03 LDA $0302
2222 -- $601 A9 02 LDA $02
2223 -- ..............................
2224 local addr = toHex(tonumber(progstart,16) + codeindex-1)
2225
2226 code = code .. "\n" .. "$" .. string.rep("0",4-#addr) .. addr .. " " .. dump .. string.rep(" ",(8-#dump)+4) .. opperation
2227 codeindex = codeindex + 1
2228 codeindex = codeindex + opBytes
2229 end
2230 return code
2231end
2232
2233function runCompiledASM(input,mode,debug)
2234 local step = true
2235 if(mode == "-s")then step = true else step = false end
2236 if(debug == nil)then debug = true end
2237 if(not fs.exists(input))then error("File doesnt exist: " .. input) end
2238 -- Convert Bytes to hex
2239 local dump = ""
2240 local hex = {}
2241 local f = fs.open(input,"rb")
2242 local progstart = ""
2243 local index = 1
2244 for byte in f.read do -- Iterate over every byte in the file.
2245 if(index > 2)then
2246 hex[#hex+1] = toHex(byte)
2247 dump = dump .. " " .. toHex(byte)
2248 else
2249 progstart = progstart .. toHex(byte)
2250 end
2251 index = index + 1
2252 end
2253 f.close()
2254 print("Read " .. index .. " Bytes.")
2255
2256 -- Load Hex into program memory
2257 -- Make sure interupt hasnt been called, if it has dont reset the program counter.
2258 if(tonumber(getFlag("BRK")) == 0)then
2259 setPC(progstart)
2260 else
2261 print("Break detected, resuming program.")
2262 print("press any key. ")
2263 setFlag("BRK",0)
2264 os.pullEvent("key")
2265 end
2266 -- Insert HEX into Program memory
2267 for i = 1, #hex do
2268 writeByte(toHex( tonumber(progstart,16)+(i-1) ),hex[i])
2269 end
2270 -- With program loaded, start running through it base on the program counter index
2271 local line = 1
2272 local hexstart = tonumber(progstart,16)
2273 -- Run program till its hex limit is reached.
2274 term.clear()
2275 term.setCursorPos(1, 1)
2276 while tonumber(readPC(),16) <= hexstart+(#hex-1) do
2277 if(tonumber(getFlag("BRK")) == 1)then
2278 term.setTextColor(colors.white)
2279 print("\nProgram brk at PC=$" .. readPC())
2280 break
2281 end
2282 -- Get key inputs / generate random numbers
2283 os.queueEvent("ASMWait")
2284 local ev = {os.pullEvent()}
2285 if(ev[1] == "key")then writeByte("FF",toHex(tonumber(ev[2]))) end
2286 writeByte("FE",toHex(math.random(0,255)))
2287 local args = {}
2288 local opperation = readByteHex(readPC())
2289 if(_G.ASM._OPCODES[opperation] == nil)then print(opperation .. " nil?") end
2290 local opBytes = _G.ASM._OPCODES[opperation].bytes
2291 for byteIndex = 1, opBytes do
2292 args[#args+1] = readByteHex(toHex((tonumber(readPC(),16)+byteIndex)))
2293 end
2294 -- Run command
2295 if(debug and _G.ASM.pmode ~= 2)then
2296 term.current().setVisible(false)
2297 term.clear()
2298 term.setCursorPos(1, 1)
2299 print("A: " .. readRegHex("A") .. " X: ".. readRegHex("X") .. " Y: " .. readRegHex("Y") .. " SP: " .. readRegHex("SP") .. " PC: " .. readPC())
2300 print("NZ-BDIZC")
2301 print(toBin(decodeByte(getFlagsByte())))
2302 for i = 1, #hex do
2303 local found = false
2304 local ind = tonumber(readPC(),16) - tonumber(progstart,16)
2305 if( (i-1) == ind)then
2306 term.setTextColor(colors.orange)
2307 write(hex[i] .. " ")
2308 else
2309 if(opBytes > 0)then
2310 for x = 1, opBytes do
2311 if((i-1)-x == ind)then
2312 term.setTextColor(colors.green)
2313 write(hex[i] .. " ")
2314 found = true
2315 end
2316 end
2317 end
2318 if not found then
2319 term.setTextColor(colors.white)
2320 write(hex[i] .. " ")
2321 end
2322 end
2323 end
2324 end
2325 term.current().setVisible(true)
2326 movePC(1)
2327 movePC(opBytes)
2328 _G.ASM._OPCODES[opperation]:exe(unpack(args))
2329 line = line + 1
2330 if(step)then
2331 if(_G.ASM.pmode ~= 2)then term.setCursorPos(1, 1) end
2332 term.setTextColor(colors.white)
2333 print("\nPress any key. ")
2334 os.pullEvent("key")
2335 end
2336 end
2337 if(tonumber(getFlag("BRK")) == 0)then
2338 term.setTextColor(colors.white)
2339 print("\nProgram end at PC=$" .. readPC())
2340 end
2341end
2342
2343function AssembleASM(input,output,nout)
2344 if(nout == nil)then nout = false
2345 elseif(nout ~= "-y")then nout = false end
2346 if(nout == "-y")then nout = true end
2347 if(not fs.exists(input))then error("File doesnt exist: " .. input) end
2348 if(fs.exists(output))then error("File exists: " .. output) end
2349 local labels = {}
2350 local vars = {}
2351 bytearray = {}
2352 local keyword_var = "define"
2353 local keyword_label = ":"
2354 local keyword_begin = ".begin"
2355 local keyword_bytes = "dcb"
2356 local online = 1
2357 local codeline = 0
2358 local programstart = "0600"
2359 print("Reading file...")
2360 -- Safer to read file first, then compile as the fs hook is closed, and they is no risk of data loss.
2361 local source = fs.open(input,"r")
2362 local code = {}
2363 local line = source.readLine()
2364 while line do
2365 code[#code+1] = line
2366 line = source.readLine()
2367 end
2368 source.close()
2369 -- Compile Variables and labels, check for syntax errors
2370 print("Initializing...")
2371 for i = 1, #code do
2372 -- Handle variables
2373 if(code[i]:find(";"))then
2374 local nargs = {}
2375 for word in string.gmatch(code[i], '([^;]+)') do
2376 table.insert(nargs, word)
2377 end
2378 if(#nargs <= 1)then
2379 code[i] = ""
2380 else
2381 code[i] = nargs[1]
2382 end
2383 end
2384
2385 if(code[i]:find(keyword_bytes))then
2386 local val = str_shearWord(code[i],keyword_bytes)
2387 if(code[i]:find(","))then
2388 for word in string.gmatch(val, '([^,]+)') do
2389 word = word:gsub("%s","")
2390 if(word:sub(1,1) ~= "$")then error("Syntax error line " .. online .. ": " .. code[i]) end
2391 if(word:sub(2,2) == "'")then
2392 if(#word:sub(3,#word-1) ~= 1)then error("Syntax error line " .. online .. ": " .. code[i]) end
2393 word = "$" .. toHex((string.byte(word:sub(3,#word-1))))
2394 end
2395 if(#word == 5)then
2396 -- Divide and reverse order
2397 word = "$" .. word:sub(4,5) .. word:sub(2,3)
2398 end
2399
2400 bytearray[codeline] = word:sub(2,#word)
2401 codeline = codeline + 1
2402 end
2403 else
2404 if(val:sub(2,2) == "'")then
2405 if(#val:sub(3,#val-1) ~= 1)then error("Syntax error line " .. online .. ": " .. code[i]) end
2406 val = "$" .. toHex((string.byte(val:sub(3,#val-1))))
2407 end
2408 if(val:sub(1,1) ~= "$")then error("Syntax error line " .. online .. ": " .. code[i]) end
2409 bytearray[codeline] = val:sub(2,#val)
2410 codeline = codeline + 1
2411 end
2412 end
2413
2414 if(code[i]:find(keyword_begin))then
2415 local val = str_shearWord(code[i],keyword_begin)
2416 if(val:sub(1,1) ~= "$")then error("Syntax error line " .. online .. ": " .. code[i]) end
2417 if(codeline ~= 0)then error("Syntax error line " .. online .. ": " .. code[i] .. " :> Must be placed only at start of file.") end
2418 programstart = val:sub(2,#val)
2419 end
2420 if(code[i]:find(keyword_var))then
2421 local val = str_shearWord(code[i],keyword_var)
2422 local nargs = {}
2423 -- Take spaces out of string, then split it into 2 variables
2424 val = val:gsub("%s+", "")
2425 -- Split string by $
2426 for word in string.gmatch(val, '([^$]+)') do
2427 table.insert(nargs, word)
2428 end
2429 if(#nargs > 2)then error("Syntax error line " .. online .. ": " .. code[i]) end
2430 -- Convert ASCII to hex
2431 if(nargs[2]:sub(1,1) == "'")then
2432 if(nargs[2]:sub(3,3) ~= "'")then error("Syntax error line " .. online .. ": " .. code[i]) end
2433 nargs[2] = toHex(string.byte(nargs[2]:sub(2,#nargs))) -- ToHex needed upon converted chars their respective byte.
2434 -- Using SUB because the string is split up into sections from the $ char, sub is needed to remove the ''.
2435 end
2436 -- if(_G.ASM._HEXENCODE[string.upper(nargs[1])])then error("Syntax error line " .. online .. ": " .. code[i]) end
2437 vars[nargs[1]] = nargs[2]
2438 -- print(nargs[1] .. ": " .. vars[nargs[1]])
2439 end
2440 -- Handle labels
2441 if(code[i]:find(keyword_label))then
2442 local val = code[i]:gsub("%s+","")
2443 local nargs = {}
2444 for word in string.gmatch(val, '([^:]+)') do
2445 table.insert(nargs, word)
2446 end
2447 if(#nargs > 1 or nargs == nil)then
2448 error("Syntax error line " .. online .. ": " .. code[i])
2449 end
2450 labels[nargs[1]] = codeline
2451 -- print(nargs[1] .. ": " .. labels[nargs[1]])
2452 end
2453 online = online + 1
2454 if(#code[i]:gsub("%s+","") ~= 0 and not code[i]:find(keyword_label) and not code[i]:find(keyword_var) and not code[i]:find(keyword_begin) and not code[i]:find(keyword_bytes))then
2455 codeline = codeline + 1
2456 end
2457 end
2458
2459 -- Get Bytes Per line
2460 codeline = 0
2461 online = 1
2462 linebytes = {}
2463 local loadedbytes = false
2464 code_backup = code -- LUA bug where this variable acts like a pointer and still writes to code.
2465 print("Getting Bytes...")
2466 -- Process each defined byte
2467 for i = 1, #code_backup do
2468 if(code[i]:find(";"))then
2469 local nargs = {}
2470 for word in string.gmatch(code[i], '([^;]+)') do
2471 table.insert(nargs, word)
2472 end
2473 if(#nargs <= 1)then
2474 code[i] = ""
2475 else
2476 code[i] = nargs[1]
2477 end
2478 end
2479 -- Calculate defined bytes
2480 if(code_backup[i]:find(keyword_bytes))then
2481 local val = str_shearWord(code[i],keyword_bytes)
2482 if(code_backup[i]:find(","))then
2483 for word in string.gmatch(val, '([^,]+)') do
2484 word = word:gsub("%s","")
2485 if(word:sub(1,1) ~= "$")then error("Syntax error line " .. online .. ": " .. code_backup[i]) end
2486 if(word:sub(2,2) == "'")then
2487 if(#word:sub(3,#word-1) ~= 1)then error("Syntax error line " .. online .. ": " .. code_backup[i]) end
2488 end
2489 if(#word == 5)then
2490 -- Divide and reverse order
2491 linebytes[#linebytes+1] = 2
2492 else
2493 linebytes[#linebytes+1] = 1
2494 end
2495 end
2496 else
2497 if(val:sub(2,2) == "'")then
2498 if(#val:sub(3,#val-1) ~= 1)then error("Syntax error line " .. online .. ": " .. code[i]) end
2499 linebytes[#linebytes+1] = 1
2500 else
2501 linebytes[#linebytes+1] = 1
2502 end
2503 if(val:sub(1,1) ~= "$")then error("Syntax error line " .. online .. ": " .. code[i]) end
2504 codeline = codeline + 1
2505 end
2506 end
2507
2508 if(#code_backup[i]:gsub("%s+","") ~= 0 and not code_backup[i]:find(keyword_label) and not code_backup[i]:find(keyword_var) and not code_backup[i]:find(keyword_begin) and not code_backup[i]:find(keyword_bytes))then
2509 local op = string.upper(code_backup[i]:gsub("%s+",""):sub(1,3))
2510 local vtype = code_backup[i]:gsub("%s+",""):sub(4,4)
2511 local opperand = ""
2512 local prefix = ""
2513 local val = code_backup[i]:gsub("%s+",""):sub(4,#code_backup[i])
2514 if(code[i]:find(","))then
2515 local ends = {}
2516 for word in string.gmatch(code[i], '([^,]+)') do
2517 table.insert(ends, word)
2518 end
2519 val = str_shearWord(ends[1],op)
2520 opperand = ", " .. ends[2]:gsub("%s","")
2521 if(code[i]:find("%("))then
2522 if(string.lower(ends[2]:gsub("%s","")) == "y")then
2523 opperand = ")" .. opperand
2524 end
2525 prefix = "("
2526 end
2527 end
2528 if(val:sub(1,1) == "#")then val = val:sub(2,#val) end
2529 if(not _G.ASM._HEXENCODE[op])then error("Syntax error line " .. online .. ": " .. code_backup[i]) end
2530 if(vars[val] ~= nil)then
2531 if(_G.ASM._HEXENCODE[op]['REL'] ~= nil)then
2532 error("Syntax error line " .. online .. ": " .. code_backup[i])
2533 end
2534 if(vtype == "#")then
2535 code_backup[i] = op .. " #$" .. vars[val] .. opperand
2536 else
2537 if(not tonumber(vars[val],16))then error("Syntax error line " .. online .. ": " .. code_backup[i]) end
2538 code_backup[i] = op .. " $" .. vars[val] .. opperand
2539 end
2540 elseif(labels[val] ~= nil)then
2541 if(_G.ASM._HEXENCODE[op]['REL'] ~= nil)then
2542 code_backup[i] = op .. " *+" .. "00"
2543 else
2544 code_backup[i] = op .. " $" .. "0000" .. opperand
2545 end
2546 end
2547 -- Variable encoding
2548 val = val:gsub("[()]","")
2549 if(vars[val] ~= nil)then
2550 if(_G.ASM._HEXENCODE[op]['REL'] ~= nil)then
2551 -- No variable branching!
2552 error("Syntax error line " .. online .. ": " .. code_backup[i])
2553 end
2554 if(vtype == "#")then
2555 code[i] = op .. " " .. prefix .. "#$" .. vars[val] .. opperand
2556 --print(code[i])
2557 else
2558 -- Direct index
2559 if(not tonumber(vars[val],16))then error("Syntax error line " .. online .. ": " .. code[i]) end
2560 code[i] = op .. " " .. prefix .. "$" .. vars[val] .. opperand
2561 --print(code[i])
2562 end
2563 end
2564 codeline = codeline + 1
2565 local opr, otype, num = procInstructionType(code_backup[i],false,false)
2566 if(lineB == "op")then error("Syntax error line " .. online .. ": " .. code_backup[i]) end
2567 if(otype == nil)then otype = "err" end
2568 print(opr .. ": " .. otype)
2569 local lineB = getInstuctionBytes(opr,otype)
2570 if(lineB == "err")then error("Syntax error line " .. online .. ": " .. code_backup[i]) end
2571 linebytes[#linebytes+1] = lineB
2572 --print(#linebytes .. ": " .. lineB)
2573 --os.pullEvent("key")
2574 end
2575 online = online + 1
2576 end
2577 -- Compile Code substitute variables and labels, check syntax
2578 -- Branch labels and jump labels, are controlled based on additions to the base program start
2579 codeline = 0
2580 online = 1
2581 local source = fs.open(input,"r")
2582 local code = {}
2583 local line = source.readLine()
2584 while line do
2585 code[#code+1] = line
2586 line = source.readLine()
2587 end
2588 source.close()
2589 local hexdump = ""
2590 print("Compiling code...")
2591 for i = 1, #code do
2592 if(code[i]:find(";"))then
2593 local nargs = {}
2594 for word in string.gmatch(code[i], '([^;]+)') do
2595 table.insert(nargs, word)
2596 end
2597 if(#nargs <= 1)then
2598 code[i] = ""
2599 else
2600 code[i] = nargs[1]
2601 end
2602 end
2603 if(#code[i]:gsub("%s+","") ~= 0 and not code[i]:find(keyword_label) and not code[i]:find(keyword_var) and not code[i]:find(keyword_begin) and not code[i]:find(keyword_bytes))then
2604 -- Check if code references label or variable
2605 local op = string.upper(code[i]:gsub("%s+",""):sub(1,3))
2606 local vtype = code[i]:gsub("%s+",""):sub(4,4)
2607 local opperand = ""
2608 local prefix = ""
2609 local val = code[i]:gsub("%s+",""):sub(4,#code[i])
2610 if(val:sub(1,1) == "#")then val = val:sub(2,#val) end
2611 if(code[i]:find(","))then
2612 local ends = {}
2613 for word in string.gmatch(code[i], '([^,]+)') do
2614 table.insert(ends, word)
2615 end
2616 val = str_shearWord(ends[1],op)
2617 opperand = ", " .. ends[2]:gsub("%s","")
2618 if(code[i]:find("%("))then
2619 if(string.lower(ends[2]:gsub("%s","")) == "y")then
2620 opperand = ")" .. opperand
2621 end
2622 prefix = "("
2623 end
2624 end
2625 val = val:gsub("[()]","")
2626 if(not _G.ASM._HEXENCODE[op])then error("Syntax error line " .. online .. ": " .. code[i]) end
2627 if(vars[val] ~= nil)then
2628 if(_G.ASM._HEXENCODE[op]['REL'] ~= nil)then
2629 -- No variable branching!
2630 error("Syntax error line " .. online .. ": " .. code[i])
2631 end
2632 if(vtype == "#")then
2633 code[i] = op .. " " .. prefix .. "#$" .. vars[val] .. opperand
2634 --print(code[i])
2635 else
2636 -- Direct index
2637 if(not tonumber(vars[val],16))then error("Syntax error line " .. online .. ": " .. code[i]) end
2638 code[i] = op .. " " .. prefix .. "$" .. vars[val] .. opperand
2639 --print(code[i])
2640 end
2641 elseif(labels[val] ~= nil)then
2642 -- Insert for relative branching
2643 --error("Labels do not work yet (And may never work)")
2644 local bytediff = 0
2645 branches = {}
2646 for i = 1, #linebytes do
2647 if(i > 1)then
2648 branches[i] = branches[i-1] + linebytes[i]
2649 else
2650 branches[i] = linebytes[i]
2651 end
2652 end
2653 if(_G.ASM._HEXENCODE[op]['REL'] ~= nil)then
2654
2655 -- Jump difference
2656 local difference = (branches[labels[val]] - branches[codeline+1])
2657
2658 if(difference < -128 or difference > 127)then
2659 error("Out of range branch on line " .. online .. " (branches are limited to -128 to +127): " .. code[i] .. "(" .. difference .. ") ")
2660 end
2661
2662 if(difference < 0)then
2663 -- Subtract the amount of bytes taken by branch
2664 difference = 256 + difference
2665 end
2666 difference = toHex(difference)
2667 -- Insert branch difference into code
2668 code[i] = op .. " *+" .. difference
2669 --print(code[i])
2670 else
2671 -- Insert for jumping
2672 local newBase = toHex(tonumber(programstart,16) + branches[labels[val]])
2673 if(#newBase < 4)then newBase = string.rep("0",4-#newBase) .. newBase end
2674 code[i] = op .. " $" .. newBase .. opperand
2675 --print(code[i])
2676 end
2677 end
2678 local hex = AssembleHEX(code[i],online)
2679 hexdump = hexdump .. hex
2680 codeline = codeline + 1
2681 end
2682 online = online + 1
2683
2684 -- if DCB, replace with the raw bytes
2685 -- Calculate defined bytes
2686 if(code[i]:find(keyword_bytes))then
2687 local val = str_shearWord(code[i],keyword_bytes)
2688 local hex = ""
2689 local wInd = 0
2690 if(code[i]:find(","))then
2691 for word in string.gmatch(val, '([^,]+)') do
2692 word = word:gsub("%s","")
2693 if(word:sub(1,1) ~= "$")then error("Syntax error line " .. online .. ": " .. code[i]) end
2694 if(word:sub(2,2) == "'")then
2695 if(#word:sub(3,#word-1) ~= 1)then error("Syntax error line " .. online .. ": " .. code[i]) end
2696 word = "$" .. toHex(string.byte(word:sub(3,3)))
2697 end
2698 code[wInd] = word:sub(2,#word)
2699 hex = word:sub(2,#word)
2700 wInd = wInd +1
2701 if(#hex == 4)then
2702 hex = hex:sub(1,2) .. " " .. hex:sub(3,4)
2703 end
2704 hexdump = hexdump .. hex .. " "
2705 codeline = codeline+1
2706 end
2707 else
2708 if(val:sub(2,2) == "'")then
2709 if(#val:sub(3,#val-1) ~= 1)then error("Syntax error line " .. online .. ": " .. code[i]) end
2710 val = toHex(string.byte(val:sub(3,3)))
2711 code[i] = val
2712 hex = val
2713 else
2714 code[i] = val:sub(2,#val)
2715 hex = val:sub(2,#val)
2716 end
2717 if(val:sub(1,1) ~= "$")then error("Syntax error line " .. online .. ": " .. code[i]) end
2718 if(#hex == 4)then
2719 hex = hex:sub(1,2) .. " " .. hex:sub(3,4)
2720 end
2721 hexdump = hexdump .. hex .. " "
2722 codeline = codeline + 1
2723 end
2724 end
2725 end
2726
2727 -- Compile hex to bytes
2728 local hexbytes = ""
2729 local _hexdump = hexdump
2730 hexdump = hexdump:gsub("%s+","")
2731 if(hexdump == "")then
2732 print("No code to run.")
2733 return
2734 end
2735 if(#hexdump > 2)then
2736 for i=1, #hexdump, 2 do
2737 hexbytes = hexbytes .. string.char(tonumber(hexdump:sub(i,i+1),16))
2738 end
2739 else
2740 hexbytes = string.char(tonumber(hexdump,16))
2741 end
2742 print("Hex Compiled: " .. _hexdump)
2743 if(nout == false)then
2744 local f = fs.open(output,"wb")
2745 for i=1, #hexdump, 2 do
2746 if(i == 1)then
2747 -- Program counter encoding.
2748 f.write(tonumber(programstart:sub(1,2),16))
2749 f.write(tonumber(programstart:sub(3,4),16))
2750 end
2751 f.write(tonumber(hexdump:sub(i, i + 1), 16))
2752 end
2753 f.close()
2754 print("Hex outputed to: " .. output)
2755 print("Done. ")
2756 --os.pullEvent("key")
2757 end
2758end
2759
2760local function StartSyntaxInterpreter()
2761 print("Starting Syntax Interpreter (type \"exit\" to exit.)")
2762 local running = true
2763 local function getinp()
2764 local opperation = read()
2765 if(opperation == "exit")then
2766 if(_CCENV)then
2767 print("Returning to CraftOS.")
2768 else
2769 print("Returning to LUA.")
2770 end
2771 running = false
2772 end
2773 local op, type, val = procInstructionType(opperation,true)
2774 runOpperation(op,type,val,true)
2775 print("A: " .. readRegHex("A") .. " X: ".. readRegHex("X") .. " Y: " .. readRegHex("Y") .. " SP: " .. readRegHex("SP") .. " PC: " .. readPC())
2776 print(toBin(decodeByte(getFlagsByte())))
2777 end
2778 while running do
2779
2780 write("Ready :> ")
2781 local gd, err = pcall(getinp)
2782 if(not ok and err and running)then print(err) end --print(err:sub(11,#err)) end
2783 end
2784end
2785
2786if(not _G.ASM and shell)then
2787 print("6502: Not Initialized, press any key. ")
2788 os.pullEvent("key")
2789 initalize()
2790 print("Memory testing...")
2791 writeByte("1","0C")
2792 writeByte("2","0C")
2793 writeByte("3","0C")
2794 writeByte("FFFF","0C")
2795 print("Retrieving...")
2796 readByte("1",true)
2797 readByte("2",true)
2798 readByte("3",true)
2799 readByte("FFFF",true)
2800 print("Memory check successful!, re-initalizing...")
2801 writeByte("1","0")
2802 writeByte("2","0")
2803 writeByte("3","0")
2804 writeByte("FFFF","0")
2805 print("Memory: " .. _G.ASM.MSIZE .. "B free. \n")
2806 print("Ready. ")
2807 sleep(0.5)
2808 term.clear()
2809 term.setCursorPos(1,1)
2810elseif(not shell and not _G.ASM)then
2811 initalize()
2812end
2813
2814
2815-- Program Arguments Use
2816local progargs = { ... }
2817-- Arguments -i, -c, -r, interpreter, compile, run
2818-- If this program is not being loaded as an API
2819if(shell ~= nil)then
2820 if(#progargs == 0)then
2821 print("Usage: " .. shell.resolve(shell.getRunningProgram()) .. " -<mode> <args> \n")
2822 print("Modes -> -i, -c, -r, -rn, -m, -d")
2823 print("-i Starts 6502 Interpreter. ")
2824 print("-c Compiles <file>, outputs hex to <output>.")
2825 print("-r Runs compiled ASM hex <file>. ")
2826 print("-rn Runs the <file> without exporting it.")
2827 print("-m Sets run <mode>: [1 - Text] [2 - Graphics]" )
2828 print("-d Exports Disassembled ASM from <source> to <output>")
2829 end
2830 if(not _CCENV)then
2831 local mode = io.read()
2832 for word in string.gmatch(mode, '([^ ]+)') do
2833 table.insert(progargs, word)
2834 end
2835 end
2836
2837 if(progargs[1] == "-i")then
2838 StartSyntaxInterpreter()
2839 elseif(progargs[1] == "-c")then
2840 if(#progargs < 3)then error("Usage: -i <source> <output>") end
2841 AssembleASM(progargs[2],progargs[3],progargs[4])
2842 elseif(progargs[1] == "-r")then
2843 if(#progargs < 2)then error("Usage: -r <compiled asm>") end
2844 runCompiledASM(progargs[2],progargs[3],progargs[4])
2845 elseif(progargs[1] == "-rn")then
2846 if(#progargs < 2)then error("Usage: -rn <source>") end
2847 if(fs.exists("/.tempasm"))then fs.delete("/.tempasm") end
2848 AssembleASM(progargs[2],"/.tempasm",progargs[3])
2849 if(fs.exists("/.tempasm"))then
2850 runCompiledASM("/.tempasm",progargs[3],progargs[4])
2851 end
2852 fs.delete("/.tempasm")
2853 elseif(progargs[1] == "-m")then
2854 if(#progargs < 2)then error("Usage: -m <mode>") end
2855 local mode = tonumber(progargs[2])
2856 if(progargs[2] == "2")then
2857 print("Programs set to run in Graphics mode.")
2858 elseif(progargs[2] == "1")then
2859 print("Programs set to run in Text mode.")
2860 else
2861 print("Unknown mode: " .. progargs[2])
2862 mode = 1
2863 end
2864 _G.ASM.pmode = mode
2865 elseif(progargs[1] == "-d")then
2866 if(#progargs < 3)then error("Usage: -d <compiled asm> <output>") end
2867 if(not fs.exists(progargs[2]))then error("No such file: " .. progargs[2]) end
2868 local asmc = disassembleASM(progargs[2])
2869 local f = fs.open(progargs[3],"w")
2870 f.writeLine("Address Hexdump Dissassembly")
2871 f.writeLine("-------------------------------")
2872 f.write(asmc)
2873 f.close()
2874 print("Disassembly outputed to: " .. progargs[3])
2875 end
2876end