mirror of
https://github.com/InkboxSoftware/excelCPU.git
synced 2026-02-06 02:51:39 +08:00
Main Excel files, compiler, and sample programs
This commit is contained in:
64
Excel-ASM16.xml
Normal file
64
Excel-ASM16.xml
Normal file
@@ -0,0 +1,64 @@
|
||||
<NotepadPlus>
|
||||
<UserLang name="EXCEL-ASM16" ext="" udlVersion="2.1">
|
||||
<Settings>
|
||||
<Global caseIgnored="yes" allowFoldOfComments="yes" foldCompact="no" forcePureLC="0" decimalSeparator="0" />
|
||||
<Prefix Keywords1="no" Keywords2="yes" Keywords3="yes" Keywords4="no" Keywords5="no" Keywords6="no" Keywords7="no" Keywords8="no" />
|
||||
</Settings>
|
||||
<KeywordLists>
|
||||
<Keywords name="Comments">00; 01 02 03 04</Keywords>
|
||||
<Keywords name="Numbers, prefix1"></Keywords>
|
||||
<Keywords name="Numbers, prefix2"></Keywords>
|
||||
<Keywords name="Numbers, extras1"></Keywords>
|
||||
<Keywords name="Numbers, extras2"></Keywords>
|
||||
<Keywords name="Numbers, suffix1"></Keywords>
|
||||
<Keywords name="Numbers, suffix2"></Keywords>
|
||||
<Keywords name="Numbers, range"></Keywords>
|
||||
<Keywords name="Operators1"></Keywords>
|
||||
<Keywords name="Operators2"></Keywords>
|
||||
<Keywords name="Folders in code1, open"></Keywords>
|
||||
<Keywords name="Folders in code1, middle"></Keywords>
|
||||
<Keywords name="Folders in code1, close"></Keywords>
|
||||
<Keywords name="Folders in code2, open"></Keywords>
|
||||
<Keywords name="Folders in code2, middle"></Keywords>
|
||||
<Keywords name="Folders in code2, close"></Keywords>
|
||||
<Keywords name="Folders in comment, open"></Keywords>
|
||||
<Keywords name="Folders in comment, middle"></Keywords>
|
||||
<Keywords name="Folders in comment, close"></Keywords>
|
||||
<Keywords name="Keywords1">JMP
JEQ
JLT
JGE
LOAD
STORE
TRAN
ADD
SUB
MULT
DIV
INC
DEC
AND
OR
XOR
NOT
NOT
ROL
ROR
CMP
CLC
STC
NOP
ORG</Keywords>
|
||||
<Keywords name="Keywords2">R</Keywords>
|
||||
<Keywords name="Keywords3">$
#
@</Keywords>
|
||||
<Keywords name="Keywords4">.DATA
.CODE
.INC</Keywords>
|
||||
<Keywords name="Keywords5"></Keywords>
|
||||
<Keywords name="Keywords6"></Keywords>
|
||||
<Keywords name="Keywords7"></Keywords>
|
||||
<Keywords name="Keywords8"></Keywords>
|
||||
<Keywords name="Delimiters"></Keywords>
|
||||
</KeywordLists>
|
||||
<Styles>
|
||||
<WordsStyle name="DEFAULT" fgColor="0080FF" bgColor="FFFFFF" fontStyle="1" nesting="0" />
|
||||
<WordsStyle name="COMMENTS" fgColor="000000" bgColor="FFFFFF" fontStyle="0" nesting="0" />
|
||||
<WordsStyle name="LINE COMMENTS" fgColor="008040" bgColor="FFFFFF" fontStyle="0" nesting="0" />
|
||||
<WordsStyle name="NUMBERS" fgColor="0080FF" bgColor="FFFFFF" fontStyle="1" nesting="0" />
|
||||
<WordsStyle name="KEYWORDS1" fgColor="0000FF" bgColor="FFFFFF" fontStyle="1" nesting="0" />
|
||||
<WordsStyle name="KEYWORDS2" fgColor="0080FF" bgColor="FFFFFF" fontStyle="1" nesting="0" />
|
||||
<WordsStyle name="KEYWORDS3" fgColor="0000A0" bgColor="FFFFFF" fontStyle="1" nesting="0" />
|
||||
<WordsStyle name="KEYWORDS4" fgColor="FF0000" bgColor="FFFFFF" fontStyle="1" nesting="0" />
|
||||
<WordsStyle name="KEYWORDS5" fgColor="000000" bgColor="FFFFFF" fontStyle="0" nesting="0" />
|
||||
<WordsStyle name="KEYWORDS6" fgColor="000000" bgColor="FFFFFF" fontStyle="0" nesting="0" />
|
||||
<WordsStyle name="KEYWORDS7" fgColor="000000" bgColor="FFFFFF" fontStyle="0" nesting="0" />
|
||||
<WordsStyle name="KEYWORDS8" fgColor="000000" bgColor="FFFFFF" fontStyle="0" nesting="0" />
|
||||
<WordsStyle name="OPERATORS" fgColor="000000" bgColor="FFFFFF" fontStyle="0" nesting="0" />
|
||||
<WordsStyle name="FOLDER IN CODE1" fgColor="000000" bgColor="FFFFFF" fontStyle="0" nesting="0" />
|
||||
<WordsStyle name="FOLDER IN CODE2" fgColor="000000" bgColor="FFFFFF" fontStyle="0" nesting="0" />
|
||||
<WordsStyle name="FOLDER IN COMMENT" fgColor="000000" bgColor="FFFFFF" fontStyle="0" nesting="0" />
|
||||
<WordsStyle name="DELIMITERS1" fgColor="000000" bgColor="FFFFFF" fontStyle="0" nesting="0" />
|
||||
<WordsStyle name="DELIMITERS2" fgColor="000000" bgColor="FFFFFF" fontStyle="0" nesting="0" />
|
||||
<WordsStyle name="DELIMITERS3" fgColor="000000" bgColor="FFFFFF" fontStyle="0" nesting="0" />
|
||||
<WordsStyle name="DELIMITERS4" fgColor="000000" bgColor="FFFFFF" fontStyle="0" nesting="0" />
|
||||
<WordsStyle name="DELIMITERS5" fgColor="000000" bgColor="FFFFFF" fontStyle="0" nesting="0" />
|
||||
<WordsStyle name="DELIMITERS6" fgColor="000000" bgColor="FFFFFF" fontStyle="0" nesting="0" />
|
||||
<WordsStyle name="DELIMITERS7" fgColor="000000" bgColor="FFFFFF" fontStyle="0" nesting="0" />
|
||||
<WordsStyle name="DELIMITERS8" fgColor="000000" bgColor="FFFFFF" fontStyle="0" nesting="0" />
|
||||
</Styles>
|
||||
</UserLang>
|
||||
</NotepadPlus>
|
||||
483
compileExcelASM16.py
Normal file
483
compileExcelASM16.py
Normal file
@@ -0,0 +1,483 @@
|
||||
#COMPILER FOR EXCEL-ASM16
|
||||
#USE: py compileExcelASM16.py [program.s] ROM.xlsx
|
||||
|
||||
import sys
|
||||
import os
|
||||
import time
|
||||
import math
|
||||
from openpyxl import load_workbook
|
||||
|
||||
compiled = False;
|
||||
filePath = ""
|
||||
spreadsheet = ""
|
||||
startTime = 0
|
||||
data = []
|
||||
program = []
|
||||
output = []
|
||||
|
||||
labelOpen = False
|
||||
labelToUse = ""
|
||||
RED = '\033[91m';
|
||||
ENDCOLOR = '\033[0m';
|
||||
|
||||
def integerError(lineNumber):
|
||||
print(RED + "\tInteger outside of expected range, line: " + str(lineNumber)+ ENDCOLOR)
|
||||
compileResults()
|
||||
|
||||
def syntaxError(lineNumber):
|
||||
print(RED + "\tSyntax Error, line: " + str(lineNumber)+ ENDCOLOR)
|
||||
compileResults()
|
||||
|
||||
def labelError(lineNumber):
|
||||
print(RED + "\tDouble label detected, line " + str(lineNumber) + ENDCOLOR)
|
||||
compileResults()
|
||||
|
||||
def referenceNotFoundError(labelName):
|
||||
print(RED + "\tReference to variable or label not found, " + str(labelName) + ENDCOLOR)
|
||||
compileResults()
|
||||
|
||||
def unrecognizedError(lineNumber):
|
||||
print(RED + "\tUnrecognized Instruction, line " + str(lineNumber) + ENDCOLOR)
|
||||
compileResults()
|
||||
|
||||
def varSequenceError(lineNumber):
|
||||
print(RED + "\tVariables must be defined before program code, line " + str(lineNumber) + ENDCOLOR)
|
||||
compileResults()
|
||||
|
||||
def varUseError(varName):
|
||||
print(RED + "\tVariable cannot be used like label, var: " + str(lineNumber) + ENDCOLOR)
|
||||
compileResults()
|
||||
|
||||
def orgError(lineNumber):
|
||||
print(RED + "\tProgram Count exceeds target address, line " + str(lineNumber) + ENDCOLOR)
|
||||
compileResults()
|
||||
|
||||
def incResourceError(resourceName, lineNumber):
|
||||
print(RED + "\tResource " + resourceName + " could not be found, line " + str(lineNumber) + ENDCOLOR)
|
||||
compileResults()
|
||||
|
||||
def lengthError(exceededWords):
|
||||
print(RED + "\tProgram length exceeds available RAM by " + str(exceededWords) + " words" + ENDCOLOR)
|
||||
compileResults()
|
||||
|
||||
def ROMbookError():
|
||||
print(RED + "\tCould not save to specified workbook, make sure the file is closed and try again" + ENDCOLOR)
|
||||
exit()
|
||||
|
||||
def createLine(label, operations):
|
||||
return [label, operations]
|
||||
|
||||
def getCurrentAddress():
|
||||
address = len(data)
|
||||
for operations in program:
|
||||
address = address + len(operations[1])
|
||||
return address
|
||||
|
||||
def getLocationOfLabel(labelName):
|
||||
location = 0
|
||||
for var in data:
|
||||
if (labelName == var[0]):
|
||||
varUseError(labelName)
|
||||
location = location + 1
|
||||
for operations in program:
|
||||
if (labelName == operations[0]):
|
||||
return location
|
||||
location = location + len(operations[1])
|
||||
return -1
|
||||
|
||||
def getVarIndex(varName):
|
||||
i = 0
|
||||
for var in data:
|
||||
if (varName == var[0]):
|
||||
return i
|
||||
i = i + 1
|
||||
return -1
|
||||
|
||||
def includeBIN(fileName):
|
||||
with open(fileName, "rb") as incFile:
|
||||
cycle = False
|
||||
lastValue = 0
|
||||
while (word := incFile.read(1)):
|
||||
value = int.from_bytes(word, "big")
|
||||
if (cycle):
|
||||
value = (lastValue * 256) + value
|
||||
if (value >= pow(2, 16)):
|
||||
input()
|
||||
program.append(createLine("", [value]))
|
||||
cycle = False
|
||||
else:
|
||||
lastValue = value
|
||||
cycle = True
|
||||
if (cycle): #catching last single byte value
|
||||
program.append(createLine("", [(lastValue * 256)]))
|
||||
|
||||
return
|
||||
|
||||
def parseNumber(numberString, lineNumber):
|
||||
prefix = numberString[0]
|
||||
numberString = numberString[1:]
|
||||
result = 0
|
||||
if (prefix == "$" or prefix == "@"):
|
||||
result = int(numberString, 16)
|
||||
if (result > 65535):
|
||||
integerError(lineNumber)
|
||||
elif (prefix == "#"):
|
||||
result = int(numberString)
|
||||
if (result > 65535):
|
||||
integerError(lineNumber)
|
||||
elif (prefix == "R" and numberString.isdigit() and int(numberString) <= 15):
|
||||
result = int(numberString)
|
||||
if (result > 15):
|
||||
integerError(lineNumber)
|
||||
else: #is a label
|
||||
result = getLocationOfLabel(prefix + numberString)
|
||||
if (result == -1 and lineNumber == -1): #second time around
|
||||
referenceNotFoundError(prefix + numberString)
|
||||
elif (result == -1):
|
||||
return "LABEL-" + (prefix + numberString)
|
||||
if (result > 65535):
|
||||
integerError(lineNumber)
|
||||
if (result < 0):
|
||||
integerError(lineNumber)
|
||||
return result
|
||||
|
||||
def encode(line, lineNumber):
|
||||
#convert to list of integers
|
||||
opcode = line[0]
|
||||
operand0 = 0
|
||||
operand1 = 0
|
||||
twoWord = False
|
||||
#check instruction format:
|
||||
if (opcode == "JMP"):
|
||||
if (not(len(line) == 2)):
|
||||
syntaxError(lineNumber)
|
||||
twoWord = True
|
||||
operand0 = int("0000", 16)
|
||||
operand1 = parseNumber(line[1], lineNumber)
|
||||
elif (opcode == "JEQ"):
|
||||
if (not(len(line) == 2)):
|
||||
syntaxError(lineNumber)
|
||||
twoWord = True
|
||||
operand0 = int("0100", 16)
|
||||
operand1 = parseNumber(line[1], lineNumber)
|
||||
elif (opcode == "JLT"):
|
||||
if (not(len(line) == 2)):
|
||||
syntaxError(lineNumber)
|
||||
twoWord = True
|
||||
operand0 = int("0200", 16)
|
||||
operand1 = parseNumber(line[1], lineNumber)
|
||||
elif (opcode == "JGE"):
|
||||
if (not(len(line) == 2)):
|
||||
syntaxError(lineNumber)
|
||||
twoWord = True
|
||||
operand0 = int("0300", 16)
|
||||
operand1 = parseNumber(line[1], lineNumber)
|
||||
elif (opcode == "LOAD"):
|
||||
if (not(len(line) == 3)):
|
||||
syntaxError(lineNumber)
|
||||
varVal = getVarIndex(line[2]) #check if references variable
|
||||
if (line[1][0] == "R" and not(str(varVal)[0] == "-")):
|
||||
twoWord = True
|
||||
operand0 = int("0400", 16) + (parseNumber(line[1], lineNumber) * 16)
|
||||
operand1 = varVal
|
||||
elif (line[1][0] == line[2][0] and line[1][0] == "R"):
|
||||
operand0 = int("1900", 16) + (parseNumber(line[1], lineNumber) * 16) + parseNumber(line[2], lineNumber)
|
||||
elif (line[1][0] == "R" and line[2][0] == "@"):
|
||||
twoWord = True
|
||||
operand0 = int("0400", 16) + (parseNumber(line[1], lineNumber) * 16)
|
||||
operand1 = parseNumber(line[2], lineNumber)
|
||||
elif (line[1][0] == "R" and (line[2][0] == "$" or line[2][0] == "#")):
|
||||
twoWord = True
|
||||
operand0 = int("0500", 16) + (parseNumber(line[1], lineNumber) * 16)
|
||||
operand1 = parseNumber(line[2], lineNumber)
|
||||
else:
|
||||
syntaxError(lineNumber)
|
||||
elif (opcode == "STORE"):
|
||||
if (not(len(line) == 3)):
|
||||
syntaxError(lineNumber)
|
||||
if (line[1][0] == line[2][0] and line[1][0] == "R"):
|
||||
operand0 = int("0700", 16) + (parseNumber(line[1], lineNumber) * 16) + parseNumber(line[2], lineNumber)
|
||||
elif (line[1][0] == "R" and line[2][0] == "@"):
|
||||
twoWord = True
|
||||
operand0 = int("0600", 16) + (parseNumber(line[1], lineNumber) * 16)
|
||||
operand1 = parseNumber(line[2], lineNumber)
|
||||
else:
|
||||
syntaxError(lineNumber)
|
||||
elif (opcode == "TRAN"):
|
||||
if (not(len(line) == 3)):
|
||||
syntaxError(lineNumber)
|
||||
if (line[1][0] == line[2][0] and line[1][0] == "R"):
|
||||
operand0 = int("0800", 16) + (parseNumber(line[1], lineNumber) * 16) + parseNumber(line[2], lineNumber)
|
||||
else:
|
||||
syntaxError(lineNumber)
|
||||
elif (opcode == "ADD"):
|
||||
if (not(len(line) == 3)):
|
||||
syntaxError(lineNumber)
|
||||
if (line[1][0] == line[2][0] and line[1][0] == "R"):
|
||||
operand0 = int("0900", 16) + (parseNumber(line[1], lineNumber) * 16) + parseNumber(line[2], lineNumber)
|
||||
else:
|
||||
syntaxError(lineNumber)
|
||||
elif (opcode == "SUB"):
|
||||
if (not(len(line) == 3)):
|
||||
syntaxError(lineNumber)
|
||||
if (line[1][0] == line[2][0] and line[1][0] == "R"):
|
||||
operand0 = int("0A00", 16) + (parseNumber(line[1], lineNumber) * 16) + parseNumber(line[2], lineNumber)
|
||||
else:
|
||||
syntaxError(lineNumber)
|
||||
elif (opcode == "MULT"):
|
||||
if (not(len(line) == 3)):
|
||||
syntaxError(lineNumber)
|
||||
if (line[1][0] == line[2][0] and line[1][0] == "R"):
|
||||
operand0 = int("0B00", 16) + (parseNumber(line[1], lineNumber) * 16) + parseNumber(line[2], lineNumber)
|
||||
else:
|
||||
syntaxError(lineNumber)
|
||||
elif (opcode == "DIV"):
|
||||
if (not(len(line) == 3)):
|
||||
syntaxError(lineNumber)
|
||||
if (line[1][0] == line[2][0] and line[1][0] == "R"):
|
||||
operand0 = int("0C00", 16) + (parseNumber(line[1], lineNumber) * 16) + parseNumber(line[2], lineNumber)
|
||||
else:
|
||||
syntaxError(lineNumber)
|
||||
elif (opcode == "INC"):
|
||||
if (not(len(line) == 2)):
|
||||
syntaxError(lineNumber)
|
||||
if (line[1][0] == "R"):
|
||||
operand0 = int("0D00", 16) + (parseNumber(line[1], lineNumber) * 16)
|
||||
else:
|
||||
syntaxError(lineNumber)
|
||||
elif (opcode == "DEC"):
|
||||
if (not(len(line) == 2)):
|
||||
syntaxError(lineNumber)
|
||||
if (line[1][0] == "R"):
|
||||
operand0 = int("0E00", 16) + (parseNumber(line[1], lineNumber) * 16)
|
||||
else:
|
||||
syntaxError(lineNumber)
|
||||
elif (opcode == "AND"):
|
||||
if (not(len(line) == 3)):
|
||||
syntaxError(lineNumber)
|
||||
if (line[1][0] == line[2][0] and line[1][0] == "R"):
|
||||
operand0 = int("0F00", 16) + (parseNumber(line[1], lineNumber) * 16) + parseNumber(line[2], lineNumber)
|
||||
else:
|
||||
syntaxError(lineNumber)
|
||||
elif (opcode == "OR"):
|
||||
if (not(len(line) == 3)):
|
||||
syntaxError(lineNumber)
|
||||
if (line[1][0] == line[2][0] and line[1][0] == "R"):
|
||||
operand0 = int("1000", 16) + (parseNumber(line[1], lineNumber) * 16) + parseNumber(line[2], lineNumber)
|
||||
else:
|
||||
syntaxError(lineNumber)
|
||||
elif (opcode == "XOR"):
|
||||
if (not(len(line) == 3)):
|
||||
syntaxError(lineNumber)
|
||||
if (line[1][0] == line[2][0] and line[1][0] == "R"):
|
||||
operand0 = int("1100", 16) + (parseNumber(line[1], lineNumber) * 16) + parseNumber(line[2], lineNumber)
|
||||
else:
|
||||
syntaxError(lineNumber)
|
||||
elif (opcode == "NOT"):
|
||||
if (not(len(line) == 2)):
|
||||
syntaxError(lineNumber)
|
||||
if (line[1][0] == "R"):
|
||||
operand0 = int("1200", 16) + (parseNumber(line[1], lineNumber) * 16)
|
||||
else:
|
||||
syntaxError(lineNumber)
|
||||
elif (opcode == "ROL"):
|
||||
if (not(len(line) == 3)):
|
||||
syntaxError(lineNumber)
|
||||
if (not(line[1][0]) == line[2][0] and line[1][0] == "R"):
|
||||
operand0 = int("1300", 16) + (parseNumber(line[1], lineNumber) * 16) + parseNumber(line[2], lineNumber)
|
||||
else:
|
||||
syntaxError(lineNumber)
|
||||
elif (opcode == "ROR"):
|
||||
if (not(len(line) == 3)):
|
||||
syntaxError(lineNumber)
|
||||
if (not(line[1][0] == line[2][0]) and line[1][0] == "R"):
|
||||
operand0 = int("1400", 16) + (parseNumber(line[1], lineNumber) * 16) + parseNumber(line[2], lineNumber)
|
||||
else:
|
||||
syntaxError(lineNumber)
|
||||
elif (opcode == "CMP"):
|
||||
if (not(len(line) == 3)):
|
||||
syntaxError(lineNumber)
|
||||
if (line[1][0] == line[2][0] and line[1][0] == "R"):
|
||||
operand0 = int("1500", 16) + (parseNumber(line[1], lineNumber) * 16) + parseNumber(line[2], lineNumber)
|
||||
else:
|
||||
syntaxError(lineNumber)
|
||||
elif (opcode == "CLC"):
|
||||
if (not(len(line) == 1)):
|
||||
syntaxError(lineNumber)
|
||||
operand0 = int("1600", 16)
|
||||
elif (opcode == "STC"):
|
||||
if (not(len(line) == 1)):
|
||||
syntaxError(lineNumber)
|
||||
operand0 = int("1700", 16)
|
||||
elif (opcode == "NOP"):
|
||||
if (not(len(line) == 1)):
|
||||
syntaxError(lineNumber)
|
||||
operand0 = int("1800", 16)
|
||||
elif (len(line) == 3 and line[1] == "="): #variables
|
||||
if (len(program) > 0):
|
||||
varSequenceError(lineNumber)
|
||||
data.append(createLine(line[0], line[2]))
|
||||
return None
|
||||
elif (len(line) == 1 and line[0] == ".DATA"):
|
||||
return None
|
||||
elif (len(line) == 1 and line[0] == ".CODE"):
|
||||
#ADD JUMP TO START OF PROGRAM
|
||||
data.insert(0, createLine("", len(data) + 2)) #number of words in data section
|
||||
data.insert(0, createLine("", int("0000", 16))) #JMP
|
||||
return None
|
||||
elif (opcode == "ORG"):
|
||||
if (not(len(line) == 2)):
|
||||
syntaxError(lineNumber)
|
||||
targetAddress = parseNumber(line[1], lineNumber)
|
||||
currentAddress = getCurrentAddress()
|
||||
if (currentAddress > targetAddress):
|
||||
orgError(lineNumber)
|
||||
while(currentAddress < targetAddress):
|
||||
program.append(createLine("", [0]))
|
||||
currentAddress = currentAddress + 1
|
||||
return None
|
||||
elif (opcode == ".INC"):
|
||||
if (not(len(line) == 2)):
|
||||
syntaxError(lineNumber)
|
||||
line[1] = line[1].replace("\"", "")
|
||||
line[1] = line[1].replace("\'", "")
|
||||
if (not(os.path.isfile(line[1]))):
|
||||
incResourceError(line[1], lineNumber)
|
||||
includeBIN(line[1])
|
||||
return None
|
||||
else:
|
||||
unrecognizedError(lineNumber)
|
||||
|
||||
if (not twoWord):
|
||||
#print(str(hex(operand0)).upper())
|
||||
return [operand0]
|
||||
else:
|
||||
#print(str(hex(operand0)).upper() + ", " + str(hex(operand1)).upper())
|
||||
return [operand0, operand1]
|
||||
|
||||
def parseProgram():
|
||||
global output
|
||||
global compiled
|
||||
global data
|
||||
for value in data:
|
||||
if (len(value[0]) > 0):
|
||||
value[1] = parseNumber(value[1], 0)
|
||||
output.append(value[1])
|
||||
for operations in program:
|
||||
for value in operations[1]:
|
||||
output.append(value)
|
||||
if (len(output) > 65536):
|
||||
lengthError(len(output) - 65536)
|
||||
compiled = True
|
||||
return
|
||||
|
||||
def parseUnmarkedLabels():
|
||||
pLine = 0
|
||||
for operations in program:
|
||||
valLine = 0
|
||||
for val in operations[1]:
|
||||
if ("LABEL" in str(val)):
|
||||
program[pLine][1][valLine] = parseNumber(val[6:], -1)
|
||||
valLine = valLine + 1
|
||||
pLine = pLine + 1
|
||||
return
|
||||
|
||||
def compileASM(filepath):
|
||||
file = open(filepath, "r")
|
||||
lineNumber = 1 #file line number for specifying errors
|
||||
for line in file:
|
||||
#print(line)
|
||||
line = line.upper()
|
||||
line = line.split(";") #getting rid of comments
|
||||
line[0] = line[0].replace("\n", "") #removing return line
|
||||
line[0] = line[0].replace("\r", "")
|
||||
line[0] = line[0].strip()
|
||||
#print(line)
|
||||
if (len(line[0]) > 0):
|
||||
parseLine(line[0], lineNumber)
|
||||
lineNumber = lineNumber + 1
|
||||
parseUnmarkedLabels()
|
||||
parseProgram()
|
||||
compileResults()
|
||||
|
||||
def parseLine(line, lineNumber):
|
||||
global labelOpen
|
||||
global labelToUse
|
||||
labelLine = line.split(":");
|
||||
label = labelLine[0]
|
||||
if (":" in line and len(labelLine[1]) <= 1):
|
||||
if (labelOpen):
|
||||
labelError(lineNumber)
|
||||
labelToUse = label #add a label with no operations to program
|
||||
labelOpen = True
|
||||
return
|
||||
elif (":" not in line):
|
||||
if (labelOpen):
|
||||
label = labelToUse
|
||||
labelOpen = False
|
||||
else:
|
||||
label = ""
|
||||
else:
|
||||
if (labelOpen):
|
||||
labelError(lineNumber)
|
||||
line = labelLine[1].strip()
|
||||
line = line.split(" ")
|
||||
#print(str(lineNumber) + "\t" + str(label) + "\t" + str(line))
|
||||
operations = encode(line, lineNumber)
|
||||
if (not(operations == None)):
|
||||
program.append(createLine(label, operations))
|
||||
return
|
||||
|
||||
def sendToSpreadsheet():
|
||||
#load excel file
|
||||
workbook = load_workbook(filename = spreadsheet)
|
||||
#open workbook
|
||||
sheet = workbook.active
|
||||
try:
|
||||
i = 0
|
||||
while (i < pow(2, 16)):
|
||||
if (i < len(output)):
|
||||
sheet.cell(row = math.floor(i / 256) + 1, column = (i % 256) + 1, value = output[i])
|
||||
else:
|
||||
sheet.cell(row = math.floor(i / 256) + 1, column = (i % 256) + 1, value = 0)
|
||||
i = i + 1
|
||||
#save the file
|
||||
workbook.save(filename = spreadsheet)
|
||||
except:
|
||||
ROMbookError()
|
||||
return
|
||||
|
||||
def compileResults():
|
||||
if (not(compiled)):
|
||||
print(RED + "\tProgram could not be compiled" + ENDCOLOR)
|
||||
else:
|
||||
print("\tProgram compiled Successfully")
|
||||
#print(output)
|
||||
print("\tProgram length in words: " + str(getCurrentAddress()))
|
||||
print("\tWriting to spreadsheet ROM...")
|
||||
sendToSpreadsheet()
|
||||
print("\tFinished in " + str(time.time()-startTime)[:6] + "s")
|
||||
exit()
|
||||
|
||||
if __name__ == "__main__":
|
||||
startTime = time.time()
|
||||
os.system('color')
|
||||
print("\tStarting operation...")
|
||||
|
||||
if (len(sys.argv) == 3):
|
||||
filePath = sys.argv[1]
|
||||
spreadsheet = sys.argv[2]
|
||||
elif (len(sys.argv) == 1):
|
||||
print(RED + "\tInsufficent arguments, no ASM file specified" + ENDCOLOR)
|
||||
compileResults()
|
||||
elif (len(sys.argv) == 2):
|
||||
print(RED + "\tInsufficent arguments, no target spreadsheet specified" + ENDCOLOR)
|
||||
compileResults()
|
||||
else:
|
||||
print(RED + "\tArguments too many" + ENDCOLOR)
|
||||
compileResults()
|
||||
|
||||
if (not(os.path.isfile(filePath))):
|
||||
print(RED + "\tFile " + filePath + " not found" + ENDCOLOR)
|
||||
compileResults()
|
||||
compileASM(filePath)
|
||||
BIN
instructionSet.xlsx
Normal file
BIN
instructionSet.xlsx
Normal file
Binary file not shown.
BIN
sample programs/PAGODA.BIN
Normal file
BIN
sample programs/PAGODA.BIN
Normal file
Binary file not shown.
122
sample programs/bouncingBall.s
Normal file
122
sample programs/bouncingBall.s
Normal file
@@ -0,0 +1,122 @@
|
||||
;4x4 pixel ball bounces around the screen
|
||||
|
||||
.DATA
|
||||
SCREEN = $F000
|
||||
DIRX = $0000
|
||||
DIRY = $0000
|
||||
COLOR = $1111
|
||||
LOCATION = $FC81
|
||||
.CODE
|
||||
LOAD R0 #0
|
||||
LOAD R15 SCREEN
|
||||
LOAD R1 #124
|
||||
LOAD R2 COLOR
|
||||
LOAD R3 DIRX
|
||||
LOAD R4 DIRY
|
||||
LOAD R5 LOCATION
|
||||
;TMP VARS
|
||||
LOAD R13 $20
|
||||
|
||||
BOUNCE:
|
||||
;DIR 0 IS --
|
||||
;DIR 1 IS ++
|
||||
JMP DRAWBALL
|
||||
FROMDRAWBALL:
|
||||
;JMP ERASEBALL
|
||||
;FROMERASEBALL:
|
||||
JMP MOVEBALL
|
||||
|
||||
DRAWBALL:
|
||||
TRAN R5 R14
|
||||
STORE R2 R14
|
||||
CLC
|
||||
ADD R14 R13
|
||||
STORE R2 R14
|
||||
ADD R14 R13
|
||||
STORE R2 R14
|
||||
ADD R14 R13
|
||||
STORE R2 R14
|
||||
JMP FROMDRAWBALL
|
||||
|
||||
ERASEBALL:
|
||||
TRAN R5 R14
|
||||
STORE R0 R14
|
||||
CLC
|
||||
ADD R14 R13
|
||||
STORE R0 R14
|
||||
ADD R14 R13
|
||||
STORE R0 R14
|
||||
ADD R14 R13
|
||||
STORE R0 R14
|
||||
;JMP FROMERASEBALL
|
||||
|
||||
MOVEBALL:
|
||||
;CHECK Y
|
||||
TRAN R5 R14
|
||||
LOAD R12 $0FFF
|
||||
AND R14 R12
|
||||
LOAD R12 $0080
|
||||
DIV R14 R12
|
||||
TRAN R12 R11 ;KEEP X LOCATION IN R11
|
||||
JMP YMOVE
|
||||
AFTERYMOVE:
|
||||
CMP R14 R0
|
||||
JEQ SWITCHDIRY
|
||||
LOAD R12 $001F
|
||||
CMP R14 R12
|
||||
JEQ SWITCHDIRY
|
||||
|
||||
RESETLOCY:
|
||||
LOAD R12 $0080
|
||||
MULT R14 R12
|
||||
LOAD R12 $F000
|
||||
OR R14 R12
|
||||
TRAN R14 R5
|
||||
|
||||
JMP XMOVE
|
||||
AFTERXMOVE:
|
||||
CMP R11 R0
|
||||
JEQ SWITCHDIRX
|
||||
LOAD R12 $001F
|
||||
CMP R11 R12
|
||||
JEQ SWITCHDIRX
|
||||
|
||||
RESETLOCX:
|
||||
CLC
|
||||
ADD R5 R11
|
||||
|
||||
ADJUSTCOLOR:
|
||||
LOAD R12 $1111
|
||||
CLC
|
||||
ADD R2 R12
|
||||
|
||||
JMP BOUNCE
|
||||
|
||||
|
||||
YMOVE:
|
||||
CMP R4 R0
|
||||
JEQ YUP; IF DIRY = 0
|
||||
INC R14
|
||||
JMP AFTERYMOVE
|
||||
YUP:
|
||||
DEC R14
|
||||
JMP AFTERYMOVE
|
||||
|
||||
XMOVE:
|
||||
CMP R3 R0
|
||||
JEQ XLEFT; IF DIRX = 0
|
||||
INC R11
|
||||
JMP AFTERXMOVE
|
||||
XLEFT:
|
||||
DEC R11
|
||||
JMP AFTERXMOVE
|
||||
|
||||
SWITCHDIRY:
|
||||
LOAD R12 $0001
|
||||
XOR R4 R12
|
||||
JMP RESETLOCY
|
||||
|
||||
SWITCHDIRX:
|
||||
LOAD R12 $0001
|
||||
XOR R3 R12
|
||||
JMP RESETLOCX
|
||||
23
sample programs/cycle.s
Normal file
23
sample programs/cycle.s
Normal file
@@ -0,0 +1,23 @@
|
||||
.DATA
|
||||
SCREEN = $F000
|
||||
.CODE
|
||||
LOAD R0 SCREEN
|
||||
LOAD R1 $0123
|
||||
LOAD R2 $4567
|
||||
LOAD R3 $89AB
|
||||
LOAD R4 $CDEF
|
||||
|
||||
LOOP:
|
||||
STORE R1 R0
|
||||
INC R0
|
||||
STORE R2 R0
|
||||
INC R0
|
||||
STORE R3 R0
|
||||
INC R0
|
||||
STORE R4 R0
|
||||
INC R0
|
||||
JMP LOOP
|
||||
|
||||
|
||||
;ORG $F000
|
||||
.INC "PAGODA.BIN"
|
||||
Reference in New Issue
Block a user