First commit. C64, C16/+4 and PET 4016/4032 working.
This commit is contained in:
commit
178662a911
|
@ -0,0 +1,6 @@
|
|||
*[%~]
|
||||
*.py[co]
|
||||
*.prg
|
||||
*.lst
|
||||
*.ll
|
||||
*.d64
|
|
@ -0,0 +1,26 @@
|
|||
.PHONY: all clean d64
|
||||
|
||||
ASM=64tass --case-sensitive --ascii -Wall --vice-labels --long-branch
|
||||
|
||||
PRG=chipty5-64.prg chipty5-plus4.prg chipty5-pet40.prg
|
||||
DIAGS=$(patsubst %.ch8asm,%.ch8,$(wildcard diags/*.ch8asm))
|
||||
|
||||
all: $(PRG)
|
||||
d64: chipty5.d64
|
||||
clean:
|
||||
$(RM) *~ *% *.lst *.l *.prg *.d64 diags/*.ch8
|
||||
|
||||
%.prg : %.asm
|
||||
$(ASM) -l $(basename $<).l -L $(basename $<).lst -o $@ $^
|
||||
|
||||
%.ch8 : %.ch8asm
|
||||
./ch8asm.py $<
|
||||
|
||||
chipty5-64.prg: c64.asm chipty5-64.asm c8loader-cbmdos.asm macros.asm layout.asm display-pet40.asm chip-8.asm
|
||||
chipty5-plus4.prg: plus4.asm chipty5-plus4.asm c8loader-cbmdos.asm macros.asm layout.asm display-pet40.asm chip-8.asm
|
||||
chipty5-pet40.prg: pet.asm chipty5-pet40.asm c8loader-cbmdos.asm macros.asm layout.asm display-pet40.asm chip-8.asm
|
||||
|
||||
chipty5.d64: $(PRG) $(DIAGS) samples/*.ch8
|
||||
c1541 -format "$(basename $@),2a" d64 $@ \
|
||||
$(foreach prg,$(filter %.prg,$^),-write "$(prg)" "$(notdir $(basename $(prg)))") \
|
||||
$(foreach seq,$(filter-out %.prg,$^),-write "$(seq)" "$(notdir $(seq)),s")
|
|
@ -0,0 +1,483 @@
|
|||
;
|
||||
; Commodore 64 specific constants and memory addresses
|
||||
;
|
||||
.proff
|
||||
|
||||
.cpu "6502"
|
||||
|
||||
io .namespace
|
||||
|
||||
.include "vic2.asm"
|
||||
.include "sid.asm"
|
||||
|
||||
.virtual $d000
|
||||
vic2 .dstruct _vic2
|
||||
.endvirtual
|
||||
|
||||
.virtual $d400
|
||||
sid .dstruct _sid
|
||||
.endvirtual
|
||||
|
||||
.endnamespace
|
||||
|
||||
BASIC_START = $0801
|
||||
BTOK_SYS = $9e
|
||||
SCREEN_RAM = $0400
|
||||
|
||||
; Kernal routines
|
||||
|
||||
ACPTR = $ffa5 ; Input byte from serial port
|
||||
CHKIN = $ffc6 ; Open channel for input
|
||||
CHKOUT = $ffc9 ; Open a channel for output
|
||||
CHRIN = $ffcf ; Get a character from the input channel
|
||||
CHROUT = $ffd2 ; Output a character
|
||||
CIOUT = $ffa8 ; Transmit a byte over the serial bus
|
||||
CINT = $ff81 ; Initialize the screen editor and VIC-II Chip
|
||||
CLALL = $ffe7 ; Close all open files
|
||||
CLOSE = $ffc3 ; Close a logical file
|
||||
CLRCHN = $ffcc ; Clear all I/O channels
|
||||
GETIN = $ffe4 ; Get a character
|
||||
IOBASE = $fff3 ; Define I/O memory page
|
||||
IOINIT = $ff84 ; Initialize I/O devices
|
||||
LISTEN = $ffb1 ; Command a device on the serial bus to listen
|
||||
LOAD = $ffd5 ; Load RAM from device
|
||||
MEMBOT = $ff9c ; Set bottom of memory
|
||||
MEMTOP = $ff99 ; Set the top of RAM
|
||||
OPEN = $ffc0 ; Open a logical file
|
||||
PLOT = $fff0 ; Set or retrieve cursor location
|
||||
RAMTAS = $ff87 ; Perform RAM test
|
||||
RDTIM = $ffde ; Read system clock
|
||||
READST = $ffb7 ; Read status word
|
||||
RESTOR = $ff8a ; Set the top of RAM
|
||||
SAVE = $ffd8 ; Save memory to a device
|
||||
SCNKEY = $ff9f ; Scan the keyboard
|
||||
SCREEN = $ffed ; Return screen format
|
||||
SECOND = $ff93 ; Send secondary address for LISTEN
|
||||
SETLFS = $ffba ; Set up a logical file
|
||||
SETMSG = $ff90 ; Set system message output
|
||||
SETNAM = $ffbd ; Set up file name
|
||||
SETTIM = $ffdb ; Set the system clock
|
||||
SETTMO = $ffa2 ; Set IEEE bus card timeout flag
|
||||
STOP = $ffe1 ; Check if STOP key is pressed
|
||||
TALK = $ffb4 ; Command a device on the serial bus to talk
|
||||
TKSA = $ff96 ; Send a secondary address to a device commanded to talk
|
||||
UDTIM = $ffea ; Update the system clock
|
||||
UNLSN = $ffae ; Send an UNLISTEN command
|
||||
UNTLK = $ffab ; Send an UNTALK command
|
||||
VECTOR = $ff8d ; Manage RAM vectors
|
||||
|
||||
|
||||
; BASIC routines
|
||||
|
||||
STMDSP = $a00c ; BASIC Command Vectors WORD
|
||||
FUNDSP = $a052 ; BASIC Function Vectors WORD
|
||||
OPTAB = $a080 ; BASIC Operator Vectors WORD
|
||||
RESLST = $a09e ; BASIC Command Keyword Table DATA
|
||||
MSCLST = $a129 ; BASIC Misc. Keyword Table DATA
|
||||
OPLIST = $a140 ; BASIC Operator Keyword Table DATA
|
||||
FUNLST = $a14d ; BASIC Function Keyword Table DATA
|
||||
ERRTAB = $a19e ; Error Message Table DATA
|
||||
ERRPTR = $a328 ; Error Message Pointers WORD
|
||||
OKK = $a364 ; Misc. Messages TEXT
|
||||
FNDFOR = $a38a ; Find FOR/GOSUB Entry on Stack
|
||||
BLTU = $a3b8 ; Open Space in Memory
|
||||
GETSTK = $a3fb ; Check Stack Depth
|
||||
REASON = $a408 ; Check Memory Overlap
|
||||
OMERR = $a435 ; Output ?OUT OF MEMORY Error
|
||||
ERROR = $a437 ; Error Routine
|
||||
ERRFIN = $a469 ; Break Entry
|
||||
READY = $a474 ; Restart BASIC
|
||||
MAIN = $a480 ; Input & Identify BASIC Line
|
||||
MAIN1 = $a49c ; Get Line Number & Tokenise Text
|
||||
INSLIN = $a4a2 ; Insert BASIC Text
|
||||
LINKPRG = $a533 ; Rechain Lines
|
||||
INLIN = $a560 ; Input Line Into Buffer
|
||||
CRUNCH = $a579 ; Tokenise Input Buffer
|
||||
FNDLIN = $a613 ; Search for Line Number
|
||||
SCRTCH = $a642 ; Perform [new]
|
||||
CLEAR = $a65e ; Perform [clr]
|
||||
STXPT = $a68e ; Reset TXTPTR
|
||||
LIST = $a69c ; Perform [list]
|
||||
QPLOP = $a717 ; Handle LIST Character
|
||||
FOR = $a742 ; Perform [for]
|
||||
NEWSTT = $a7ae ; BASIC Warm Start
|
||||
CKEOL = $a7c4 ; Check End of Program
|
||||
GONE = $a7e1 ; Prepare to execute statement
|
||||
GONE3 = $a7ed ; Perform BASIC Keyword
|
||||
B_RESTOR = $a81d ; Perform [restore]
|
||||
B_STOP = $a82c ; Perform [stop], [end], break
|
||||
CONT = $a857 ; Perform [cont]
|
||||
RUN = $a871 ; Perform [run]
|
||||
GOSUB = $a883 ; Perform [gosub]
|
||||
GOTO = $a8a0 ; Perform [goto]
|
||||
RETURN = $a8d2 ; Perform [return]
|
||||
DATA = $a8f8 ; Perform [data]
|
||||
DATAN = $a906 ; Search for Next Statement / Line
|
||||
IF = $a928 ; Perform [if]
|
||||
REM = $a93b ; Perform [rem]
|
||||
ONGOTO = $a94b ; Perform [on]
|
||||
LINGET = $a96b ; Fetch linnum From BASIC
|
||||
LET = $a9a5 ; Perform [let]
|
||||
PUTINT = $a9c4 ; Assign Integer
|
||||
PTFLPT = $a9d6 ; Assign Floating Point
|
||||
PUTSTR = $a9d9 ; Assign String
|
||||
PUTTIM = $a9e3 ; Assign TI$
|
||||
GETSPT = $aa2c ; Add Digit to FAC#1
|
||||
PRINTN = $aa80 ; Perform [print]#
|
||||
CMD = $aa86 ; Perform [cmd]
|
||||
STRDON = $aa9a ; Print String From Memory
|
||||
PRINT = $aaa0 ; Perform [print]
|
||||
VAROP = $aab8 ; Output Variable
|
||||
CRDO = $aad7 ; Output CR/LF
|
||||
COMPRT = $aae8 ; Handle comma, TAB(, SPC(
|
||||
STROUT = $ab1e ; Output String
|
||||
OUTSPC = $ab3b ; Output Format Character
|
||||
DOAGIN = $ab4d ; Handle Bad Data
|
||||
GET = $ab7b ; Perform [get]
|
||||
INPUTN = $aba5 ; Perform [input#]
|
||||
INPUT = $abbf ; Perform [input]
|
||||
BUFFUL = $abea ; Read Input Buffer
|
||||
QINLIN = $abf9 ; Do Input Prompt
|
||||
READ = $ac06 ; Perform [read]
|
||||
RDGET = $ac35 ; General Purpose Read Routine
|
||||
EXINT = $acfc ; Input Error Messages TEXT
|
||||
NEXT = $ad1e ; Perform [next]
|
||||
DONEXT = $ad61 ; Check Valid Loop
|
||||
FRMNUM = $ad8a ; Confirm Result
|
||||
FRMEVL = $ad9e ; Evaluate Expression in Text
|
||||
EVAL = $ae83 ; Evaluate Single Term
|
||||
PIVAL = $aea8 ; Constant - pi DATA
|
||||
QDOT = $aead ; Continue Expression
|
||||
PARCHK = $aef1 ; Expression in Brackets
|
||||
CHKCLS = $aef7 ; Confirm Character
|
||||
;- = $aef7 ; -test ')'-
|
||||
;- = $aefa ; -test '('-
|
||||
;- = $aefd ; -test comma-
|
||||
SYNERR = $af08 ; Output ?SYNTAX Error
|
||||
DOMIN = $af0d ; Set up NOT Function
|
||||
RSVVAR = $af14 ; Identify Reserved Variable
|
||||
ISVAR = $af28 ; Search for Variable
|
||||
TISASC = $af48 ; Convert TI to ASCII String
|
||||
ISFUN = $afa7 ; Identify Function Type
|
||||
STRFUN = $afb1 ; Evaluate String Function
|
||||
NUMFUN = $afd1 ; Evaluate Numeric Function
|
||||
OROP = $afe6 ; Perform [or], [and]
|
||||
DOREL = $b016 ; Perform <, =, >
|
||||
NUMREL = $b01b ; Numeric Comparison
|
||||
STRREL = $b02e ; String Comparison
|
||||
DIM = $b07e ; Perform [dim]
|
||||
PTRGET = $b08b ; Identify Variable
|
||||
ORDVAR = $b0e7 ; Locate Ordinary Variable
|
||||
NOTFNS = $b11d ; Create New Variable
|
||||
NOTEVL = $b128 ; Create Variable
|
||||
ARYGET = $b194 ; Allocate Array Pointer Space
|
||||
N32768 = $b1a5 ; Constant 32768 in Flpt DATA
|
||||
FACINX = $b1aa ; FAC#1 to Integer in (AC/YR)
|
||||
INTIDX = $b1b2 ; Evaluate Text for Integer
|
||||
AYINT = $b1bf ; FAC#1 to Positive Integer
|
||||
ISARY = $b1d1 ; Get Array Parameters
|
||||
FNDARY = $b218 ; Find Array
|
||||
BSERR = $b245 ; ?BAD SUBSCRIPT/?ILLEGAL QUANTITY
|
||||
NOTFDD = $b261 ; Create Array
|
||||
INLPN2 = $b30e ; Locate Element in Array
|
||||
UMULT = $b34c ; Number of Bytes in Subscript
|
||||
FRE = $b37d ; Perform [fre]
|
||||
GIVAYF = $b391 ; Convert Integer in (AC/YR) to Flpt
|
||||
POS = $b39e ; Perform [pos]
|
||||
ERRDIR = $b3a6 ; Confirm Program Mode
|
||||
GETFNM = $b3e1 ; Check Syntax of FN
|
||||
FNDOER = $b3f4 ; Perform [fn]
|
||||
STRD = $b465 ; Perform [str$]
|
||||
STRLIT = $b487 ; Set Up String
|
||||
PUTNW1 = $b4d5 ; Save String Descriptor
|
||||
GETSPA = $b4f4 ; Allocate Space for String
|
||||
GARBAG = $b526 ; Garbage Collection
|
||||
DVARS = $b5bd ; Search for Next String
|
||||
GRBPAS = $b606 ; Collect a String
|
||||
CAT = $b63d ; Concatenate Two Strings
|
||||
MOVINS = $b67a ; Store String in High RAM
|
||||
FRESTR = $b6a3 ; Perform String Housekeeping
|
||||
FREFAC = $b6db ; Clean Descriptor Stack
|
||||
CHRD = $b6ec ; Perform [chr$]
|
||||
LEFTD = $b700 ; Perform [left$]
|
||||
RIGHTD = $b72c ; Perform [right$]
|
||||
MIDD = $b737 ; Perform [mid$]
|
||||
PREAM = $b761 ; Pull sTring Parameters
|
||||
LEN = $b77c ; Perform [len]
|
||||
LEN1 = $b782 ; Exit String Mode
|
||||
ASC = $b78b ; Perform [asc]
|
||||
GTBYTC = $b79b ; Evaluate Text to 1 Byte in XR
|
||||
VAL = $b7ad ; Perform [val]
|
||||
STRVAL = $b7b5 ; Convert ASCII String to Flpt
|
||||
GETNUM = $b7eb ; Get parameters for POKE/WAIT
|
||||
GETADR = $b7f7 ; Convert FAC#1 to Integer in LINNUM
|
||||
PEEK = $b80d ; Perform [peek]
|
||||
POKE = $b824 ; Perform [poke]
|
||||
WAIT = $b82d ; Perform [wait]
|
||||
FADDH = $b849 ; Add 0.5 to FAC#1
|
||||
FSUB = $b850 ; Perform Subtraction
|
||||
FADD5 = $b862 ; Normalise Addition
|
||||
FADD = $b867 ; Perform Addition
|
||||
NEGFAC = $b947 ; 2's Complement FAC#1
|
||||
OVERR = $b97e ; Output ?OVERFLOW Error
|
||||
MULSHF = $b983 ; Multiply by Zero Byte
|
||||
FONE = $b9bc ; Table of Flpt Constants DATA
|
||||
LOG = $b9ea ; Perform [log]
|
||||
FMULT = $ba28 ; Perform Multiply
|
||||
MULPLY = $ba59 ; Multiply by a Byte
|
||||
CONUPK = $ba8c ; Load FAC#2 From Memory
|
||||
MULDIV = $bab7 ; Test Both Accumulators
|
||||
MLDVEX = $bad4 ; Overflow / Underflow
|
||||
MUL10 = $bae2 ; Multiply FAC#1 by 10
|
||||
TENC = $baf9 ; Constant 10 in Flpt DATA
|
||||
DIV10 = $bafe ; Divide FAC#1 by 10
|
||||
FDIV = $bb07 ; Divide FAC#2 by Flpt at (AC/YR)
|
||||
FDIVT = $bb0f ; Divide FAC#2 by FAC#1
|
||||
MOVFM = $bba2 ; Load FAC#1 From Memory
|
||||
MOV2F = $bbc7 ; Store FAC#1 in Memory
|
||||
MOVFA = $bbfc ; Copy FAC#2 into FAC#1
|
||||
MOVAF = $bc0c ; Copy FAC#1 into FAC#2
|
||||
ROUND = $bc1b ; Round FAC#1
|
||||
SIGN = $bc2b ; Check Sign of FAC#1
|
||||
SGN = $bc39 ; Perform [sgn]
|
||||
ABS = $bc58 ; Perform [abs]
|
||||
FCOMP = $bc5b ; Compare FAC#1 With Memory
|
||||
QINT = $bc9b ; Convert FAC#1 to Integer
|
||||
INT = $bccc ; Perform [int]
|
||||
FIN = $bcf3 ; Convert ASCII String to a Number in FAC#1
|
||||
N0999 = $bdb3 ; String Conversion Constants DATA
|
||||
INPRT = $bdc2 ; Output 'IN' and Line Number
|
||||
FOUT = $bddd ; Convert FAC#1 to ASCII String
|
||||
FOUTIM = $be68 ; Convert TI to String
|
||||
FHALF = $bf11 ; Table of Constants DATA
|
||||
SQR = $bf71 ; Perform [sqr]
|
||||
FPWRT = $bf7b ; Perform power ($)
|
||||
NEGOP = $bfb4 ; Negate FAC#1
|
||||
LOGEB2 = $bfbf ; Table of Constants DATA
|
||||
EXP = $bfed ; Perform [exp]
|
||||
|
||||
; Miscellaneous
|
||||
|
||||
D6510 = $0000 ; 6510 On-chip Data Direction Register.
|
||||
R6510 = $0001 ; 6510 On-chip 8-bit Input/Output Register.
|
||||
TEMP0002 = $0002 ; Unused. Free for user programs.
|
||||
ADRAY1 = $0003 ; Jump Vector: Convert FAC to Integer in (A/Y) ($B1AA).
|
||||
ADRAY2 = $0005 ; Jump Vector: Convert Integer in (A/Y) to Floating point in (FAC); ($B391).
|
||||
CHARAC = $0007 ; Search Character/Temporary Integer during INT.
|
||||
ENDCHR = $0008 ; Flag: Scan for Quote at end of String.
|
||||
INTEGR = $0007 ; Temporary Integer during OR/AND.
|
||||
TRMPOS = $0009 ; Screen Column for last TAB.
|
||||
VERCK = $000a ; Flag: 0 = Load, 1 = Verify.
|
||||
COUNT = $000b ; Input Buffer Pointer/Number of Subscripts.
|
||||
DIMFLG = $000c ; Flag: Default Array dimension.
|
||||
VALTYP = $000d ; Data type Flag: $00 = Numeric, $FF = String.
|
||||
INTFLG = $000e ; Data type Flag: $00 = Floating point, $80 = Integer.
|
||||
GARBFL = $000f ; Flag: DATA scan/List Quote/Garbage collection.
|
||||
SUBFLG = $0010 ; Flag: Subscript reference/User Function call.
|
||||
INPFLG = $0011 ; Input Flag: $00 = INPUT, $40 = GET, $98 = READ.
|
||||
TANSGN = $0012 ; Flag: TAN sign/Comparative result.
|
||||
CHANNL = $0013 ; File number of current Input Device.
|
||||
LINNUM = $0014 ; Temporary: Integer value.
|
||||
TEMPPT = $0016 ; Pointer: Temporary String Stack.
|
||||
LASTPT = $0017 ; Last temporary String Address.
|
||||
TEMPST = $0019 ; Stack for temporary Strings.
|
||||
INDEX = $0022 ; Utility Pointer Area.
|
||||
INDEX1 = $0022 ; First Utility Pointer.
|
||||
INDEX2 = $0024 ; Second Utility Pointer.
|
||||
RESHO = $0026 ; Floating point product of Multiply and Divide.
|
||||
TXTTAB = $002b ; Pointer: Start of BASIC Text Area ($0801).
|
||||
VARTAB = $002d ; Pointer: Start of BASIC Variables.
|
||||
ARYTAB = $002f ; Pointer: Start of BASIC Arrays.
|
||||
STREND = $0031 ; Pointer: End of BASIC Arrays + 1.
|
||||
FRETOP = $0033 ; Pointer: Bottom of String space.
|
||||
FRESPC = $0035 ; Utility String Pointer.
|
||||
ZMEMSIZ = $0037 ; Pointer: Highest Address available to BASIC ($A000).
|
||||
CURLIN = $0039 ; Current BASIC Line number.
|
||||
OLDLIN = $003b ; Previous BASIC Line number.
|
||||
OLDTXT = $003d ; Pointer: BASIC Statement for CONT.
|
||||
DATLIN = $003f ; Current DATA Line number.
|
||||
DATPTR = $0041 ; Pointer: Used by READ - current DATA Item Address.
|
||||
INPPTR = $0043 ; Pointer: Temporary storage of Pointer during INPUT Routine.
|
||||
VARNAM = $0045 ; Name of Variable being sought in Variable Table.
|
||||
VARPNT = $0047 ; Pointer: to value of (VARNAM) if Integer, to descriptor if String.
|
||||
FORPNT = $0049 ; Pointer: Index Variable for FOR/NEXT loop.
|
||||
VARTXT = $004b ; Temporary storage for TXTPTR during READ, INPUT and GET.
|
||||
OPMASK = $004d ; Mask used during FRMEVL.
|
||||
TEMPF3 = $004e ; Temporary storage for FLPT value.
|
||||
FOUR6 = $0053 ; Length of String Variable during garbage collection.
|
||||
JMPER = $0054 ; Jump Vector used in Function Evaluation - JMP followed by Address ($4C,$LB,$MB).
|
||||
TEMPF1 = $0057 ; Temporary storage for FLPT value.
|
||||
TEMPF2 = $005c ; Temporary storage for FLPT value.
|
||||
FAC = $0061 ; Main Floating point Accumulator.
|
||||
FACEXP = $0061 ; FAC Exponent.
|
||||
FACHO = $0062 ; FAC Mantissa.
|
||||
FACSGN = $0066 ; FAC Sign.
|
||||
SGNFLG = $0067 ; Pointer: Series Evaluation Constant.
|
||||
BITS = $0068 ; Bit Overflow Area during normalisation Routine.
|
||||
AFAC = $0069 ; Auxiliary Floating point Accumulator.
|
||||
ARGEXP = $0069 ; AFAC Exponent.
|
||||
ARGHO = $006a ; AFAC Mantissa.
|
||||
ARGSGN = $006e ; AFAC Sign.
|
||||
ARISGN = $006f ; Sign of result of Arithmetic Evaluation.
|
||||
FACOV = $0070 ; FAC low-order rounding.
|
||||
FBUFPT = $0071 ; Pointer: Used during CRUNCH/ASCII conversion.
|
||||
CHRGET = $0073 ; Subroutine: Get next Byte of BASIC Text.
|
||||
CHRGOT = $0079 ; Entry to Get same Byte again.
|
||||
TXTPTR = $007a ; Pointer: Current Byte of BASIC Text.
|
||||
RNDX = $008b ; Floating RND Function Seed Value.
|
||||
STATUS = $0090 ; Kernal I/O Status Word ST.
|
||||
STKEY = $0091 ; Flag: $7F = STOP key.
|
||||
SVXT = $0092 ; Timing Constant for Tape.
|
||||
VERCKK = $0093 ; Flag: 0 = Load, 1 = Verify.
|
||||
C3PO = $0094 ; Flag: Serial Bus - Output Character buffered.
|
||||
BSOUR = $0095 ; Buffered Character for Serial Bus.
|
||||
SYNO = $0096 ; Cassette Sync. number.
|
||||
TEMPX = $0097 ; Temporary storage of X Register during CHRIN.
|
||||
TEMPY = $0097 ; Temporary storage of Y Register during RS232 fetch.
|
||||
LDTND = $0098 ; Number of Open Files/Index to File Table.
|
||||
DFLTN = $0099 ; Default Input Device (0).
|
||||
DFLTO = $009a ; Default Output Device (3).
|
||||
PRTY = $009b ; Parity of Byte Output to Tape.
|
||||
DPSW = $009c ; Flag: Byte received from Tape.
|
||||
MSGFLG = $009d ; Flag: $00 = Program mode: Suppress Error Messages, $40 = Kernal Error Messages only, $80 = Direct mode: Full Error Messages.
|
||||
FNMIDX = $009e ; Index to Cassette File name/Header ID for Tape write.
|
||||
PTR1 = $009e ; Tape Error log pass 1.
|
||||
PTR2 = $009f ; Tape Error log pass 2.
|
||||
TIME = $00a0 ; Real-time jiffy Clock (Updated by IRQ Interrupt approx. every 1/60 of Second); Update Routine: UDTIMK ($F69B).
|
||||
TSFCNT = $00a3 ; Bit Counter Tape Read or Write/Serial Bus EOI (End Of Input) Flag.
|
||||
TBTCNT = $00a4 ; Pulse Counter Tape Read or Write/Serial Bus shift Counter.
|
||||
CNTDN = $00a5 ; Tape Synchronising count down.
|
||||
BUFPNT = $00a6 ; Pointer: Tape I/O buffer.
|
||||
INBIT = $00a7 ; RS232 temporary for received Bit/Tape temporary.
|
||||
BITC1 = $00a8 ; RS232 Input Bit count/Tape temporary.
|
||||
RINONE = $00a9 ; RS232 Flag: Start Bit check/Tape temporary.
|
||||
RIDATA = $00aa ; RS232 Input Byte Buffer/Tape temporary.
|
||||
RIPRTY = $00ab ; RS232 Input parity/Tape temporary.
|
||||
SAL = $00ac ; Pointer: Tape Buffer/Screen scrolling.
|
||||
EAL = $00ae ; Tape End Address/End of Program.
|
||||
CMPO = $00b0 ; Tape timing Constants.
|
||||
TAPE1 = $00b2 ; Pointer: Start Address of Tape Buffer ($033C).
|
||||
BITTS = $00b4 ; RS232 Write bit count/Tape Read timing Flag.
|
||||
NXTBIT = $00b5 ; RS232 Next Bit to send/Tape Read - End of Tape.
|
||||
RODATA = $00b6 ; RS232 Output Byte Buffer/Tape Read Error Flag.
|
||||
FNLEN = $00b7 ; Number of Characters in Filename.
|
||||
LA = $00b8 ; Current File - Logical File number.
|
||||
SA = $00b9 ; Current File - Secondary Address.
|
||||
FA = $00ba ; Current File - First Address (Device number). OPEN LA,FA,SA; OPEN 1,8,15,"I0":CLOSE 1
|
||||
FNADR = $00bb ; Pointer: Current File name Address.
|
||||
ROPRTY = $00bd ; RS232 Output Parity/Tape Byte to be Input or Output.
|
||||
FSBLK = $00be ; Tape Input/Output Block count.
|
||||
MYCH = $00bf ; Serial Word Buffer.
|
||||
CAS1 = $00c0 ; Tape Motor Switch.
|
||||
STAL = $00c1 ; Start Address for LOAD and Cassette Write.
|
||||
MEMUSS = $00c3 ; Pointer: Type 3 Tape LOAD and general use.
|
||||
LSTX = $00c5 ; Matrix value of last Key pressed; No Key = $40.
|
||||
NDX = $00c6 ; Number of Characters in Keyboard Buffer queue.
|
||||
RVS = $00c7 ; Flag: Reverse On/Off; On = $01, Off = $00.
|
||||
INDX = $00c8 ; Pointer: End of Line for Input (Used to suppress trailing spaces).
|
||||
LXSP = $00c9 ; Cursor X/Y (Line/Column) position at start of Input.
|
||||
SFDX = $00cb ; Flag: Print shifted Characters.
|
||||
BLNSW = $00cc ; Flag: Cursor blink; $00 = Enabled, $01 = Disabled.
|
||||
BLNCT = $00cd ; Timer: Count down for Cursor blink toggle.
|
||||
GDBLN = $00ce ; Character under Cursor while Cursor Inverted.
|
||||
BLNON = $00cf ; Flag: Cursor Status; $00 = Off, $01 = On.
|
||||
CRSW = $00d0 ; Flag: Input from Screen = $03, or Keyboard = $00.
|
||||
PNT = $00d1 ; Pointer: Current Screen Line Address.
|
||||
PNTR = $00d3 ; Cursor Column on current Line, including Wrap-round Line, if any.
|
||||
QTSW = $00d4 ; Flag: Editor in Quote Mode; $00 = Not.
|
||||
LNMX = $00d5 ; Current logical Line length: 39 or 79.
|
||||
TBLX = $00d6 ; Current Screen Line number of Cursor.
|
||||
SCHAR = $00d7 ; Screen value of current Input Character/Last Character Output.
|
||||
INSRT = $00d8 ; Count of number of inserts outstanding.
|
||||
LDTB1 = $00d9 ; Screen Line link Table/Editor temporaries. High Byte of Line Screen Memory Location.
|
||||
USER = $00f3 ; Pointer: Current Colour RAM Location.
|
||||
KEYTAB = $00f5 ; Vector: Current Keyboard decoding Table. ($EB81)
|
||||
RIBUF = $00f7 ; RS232 Input Buffer Pointer.
|
||||
ROBUF = $00f9 ; RS232 Output Buffer Pointer.
|
||||
FREKZP = $00fb ; Free Zero Page space for User Programs.
|
||||
BASZPT = $00ff ; BASIC temporary Data Area.
|
||||
ASCWRK = $00ff ; Assembly Area for Floating point to ASCII conversion.
|
||||
BAD = $0100 ; Tape Input Error log.
|
||||
STACK = $0100 ; 6510 Hardware Stack Area.
|
||||
BSTACK = $013f ; BASIC Stack Area.
|
||||
BUF = $0200 ; BASIC Input Buffer (Input Line from Screen).
|
||||
LAT = $0259 ; Kernal Table: Active logical File numbers.
|
||||
FAT = $0263 ; Kernal Table: Active File First Addresses (Device numbers).
|
||||
SAT = $026d ; Kernal Table: Active File Secondary Addresses.
|
||||
KEYD = $0277 ; Keyboard Buffer Queue (FIFO).
|
||||
MEMSTR = $0281 ; Pointer: Bottom of Memory for Operating System ($0800).
|
||||
MEMSIZ = $0283 ; Pointer: Top of Memory for Operating System ($A000).
|
||||
TIMOUT = $0285 ; Serial IEEE Bus timeout defeat Flag.
|
||||
COLOR = $0286 ; Current Character Colour code.
|
||||
GDCOL = $0287 ; Background Colour under Cursor.
|
||||
HIBASE = $0288 ; High Byte of Screen Memory Address ($04).
|
||||
XMAX = $0289 ; Maximum number of Bytes in Keyboard Buffer ($0A).
|
||||
RPTFLG = $028a ; Flag: Repeat keys; $00 = Cursors, INST/DEL & Space repeat, $40 no Keys repeat, $80 all Keys repeat ($00).
|
||||
KOUNT = $028b ; Repeat Key: Speed Counter ($04).
|
||||
DELAY = $028c ; Repeat Key: First repeat delay Counter ($10).
|
||||
SHFLAG = $028d ; Flag: Shift Keys: Bit 1 = Shift, Bit 2 = CBM, Bit 3 = CTRL; ($00 = None, $01 = Shift, etc.).
|
||||
LSTSHF = $028e ; Last Shift Key used for debouncing.
|
||||
KEYLOG = $028f ; Vector: Routine to determine Keyboard table to use based on Shift Key Pattern ($EB48).
|
||||
MODE = $0291 ; Flag: Upper/Lower Case change: $00 = Disabled, $80 = Enabled ($00).
|
||||
AUTODN = $0292 ; Flag: Auto scroll down: $00 = Disabled ($00).
|
||||
M51CTR = $0293 ; RS232 Pseudo 6551 control Register Image.
|
||||
M51CDR = $0294 ; RS232 Pseudo 6551 command Register Image.
|
||||
M51AJB = $0295 ; RS232 Non-standard Bits/Second.
|
||||
RSSTAT = $0297 ; RS232 Pseudo 6551 Status Register Image.
|
||||
BITNUM = $0298 ; RS232 Number of Bits left to send.
|
||||
BAUDOF = $0299 ; RS232 Baud Rate; Full Bit time microseconds.
|
||||
RIDBE = $029b ; RS232 Index to End of Input Buffer.
|
||||
RIDBS = $029c ; RS232 Pointer: High Byte of Address of Input Buffer.
|
||||
RODBS = $029d ; RS232 Pointer: High Byte of Address of Output Buffer.
|
||||
RODBE = $029e ; RS232 Index to End of Output Buffer.
|
||||
IRQTMP = $029f ; Temporary store for IRQ Vector during Tape operations.
|
||||
ENABL = $02a1 ; RS232 Enables.
|
||||
TODSNS = $02a2 ; TOD sense during Tape I/O.
|
||||
TRDTMP = $02a3 ; Temporary storage during Tape READ.
|
||||
TD1IRQ = $02a4 ; Temporary D1IRQ Indicator during Tape READ.
|
||||
TLNIDX = $02a5 ; Temporary for Line Index.
|
||||
TVSFLG = $02a6 ; Flag: TV Standard: $00 = NTSC, $01 = PAL.
|
||||
TEMP02a7 = $02a7 ; Unused.
|
||||
SPR11 = $02c0 ; Sprite #11 Data Area. (SCREEN + $03F8 + SPR number) POKE 1024+1016+0,11 to use Sprite#0 DATA from ($02C0-$02FE).
|
||||
IERROR = $0300 ; Vector: Indirect entry to BASIC Error Message, (X) points to Message ($E38B).
|
||||
IMAIN = $0302 ; Vector: Indirect entry to BASIC Input Line and Decode ($A483).
|
||||
ICRNCH = $0304 ; Vector: Indirect entry to BASIC Tokenise Routine ($A57C).
|
||||
IQPLOP = $0306 ; Vector: Indirect entry to BASIC LIST Routine ($A71A).
|
||||
IGONE = $0308 ; Vector: Indirect entry to BASIC Character dispatch Routine ($A7E4).
|
||||
IEVAL = $030a ; Vector: Indirect entry to BASIC Token evaluation ($AE86).
|
||||
SAREG = $030c ; Storage for 6510 Accumulator during SYS.
|
||||
SXREG = $030d ; Storage for 6510 X-Register during SYS.
|
||||
SYREG = $030e ; Storage for 6510 Y-Register during SYS.
|
||||
SPREG = $030f ; Storage for 6510 Status Register during SYS.
|
||||
USRPOK = $0310 ; USR Function JMP Instruction ($4C).
|
||||
USRADD = $0311 ; USR Address ($LB,$MB).
|
||||
TEMP0313 = $0313 ; Unused.
|
||||
CINV = $0314 ; Vector: Hardware IRQ Interrupt Address ($EA31).
|
||||
CNBINV = $0316 ; Vector: BRK Instruction Interrupt Address ($FE66).
|
||||
NMINV = $0318 ; Vector: Hardware NMI Interrupt Address ($FE47).
|
||||
IOPEN = $031a ; Vector: Indirect entry to Kernal OPEN Routine ($F34A).
|
||||
ICLOSE = $031c ; Vector: Indirect entry to Kernal CLOSE Routine ($F291).
|
||||
ICHKIN = $031e ; Vector: Indirect entry to Kernal CHKIN Routine ($F20E).
|
||||
ICKOUT = $0320 ; Vector: Indirect entry to Kernal CHKOUT Routine ($F250).
|
||||
ICLRCH = $0322 ; Vector: Indirect entry to Kernal CLRCHN Routine ($F333).
|
||||
IBASIN = $0324 ; Vector: Indirect entry to Kernal CHRIN Routine ($F157).
|
||||
IBSOUT = $0326 ; Vector: Indirect entry to Kernal CHROUT Routine ($F1CA).
|
||||
ISTOP = $0328 ; Vector: Indirect entry to Kernal STOP Routine ($F6ED).
|
||||
IGETIN = $032a ; Vector: Indirect entry to Kernal GETIN Routine ($F13E).
|
||||
ICLALL = $032c ; Vector: Indirect entry to Kernal CLALL Routine ($F32F).
|
||||
USRCMD = $032e ; User Defined Vector ($FE66).
|
||||
ILOAD = $0330 ; Vector: Indirect entry to Kernal LOAD Routine ($F4A5).
|
||||
ISAVE = $0332 ; Vector: Indirect entry to Kernal SAVE Routine ($F5ED).
|
||||
TEMP0334 = $0334 ; Unused.
|
||||
TBUFFR = $033c ; Tape I/O Buffer.
|
||||
SPR13 = $0340 ; Sprite #13.
|
||||
SPR14 = $0380 ; Sprite #14.
|
||||
SPR15 = $03c0 ; Sprite #15.
|
||||
TEMP03fc = $03fc ; Unused.
|
||||
VICSCN = $0400 ; Default Screen Video Matrix.
|
||||
TEMP07e8 = $07e8 ; Unused.
|
||||
SPNTRS = $07f8 ; Default Sprite Data Pointers.
|
||||
|
||||
.pron
|
||||
|
||||
; vim: syntax=64tass
|
|
@ -0,0 +1,103 @@
|
|||
.weak
|
||||
IS_PET = false
|
||||
.endweak
|
||||
|
||||
.if IS_PET
|
||||
cbmopen .macro filedes, device, secaddr, filenameptr, filenamelen
|
||||
lda #\filedes
|
||||
sta LA
|
||||
lda #\device
|
||||
sta FA
|
||||
lda #\secaddr
|
||||
sta SA
|
||||
lda \filenamelen
|
||||
sta FNLEN
|
||||
lda #<\filenameptr
|
||||
sta FNADR
|
||||
lda #>\filenameptr
|
||||
sta FNADR+1
|
||||
|
||||
jsr OPEN
|
||||
lda STATUS
|
||||
beq +
|
||||
sec
|
||||
bcs ++
|
||||
+ clc
|
||||
+
|
||||
.endmacro
|
||||
|
||||
cbmstatus .macro
|
||||
lda STATUS
|
||||
.endmacro
|
||||
.else
|
||||
cbmopen .macro filedes, device, secaddr, filenameptr, filenamelen
|
||||
lda \filenamelen
|
||||
ldx #<\filenameptr
|
||||
ldy #>\filenameptr
|
||||
jsr SETNAM
|
||||
|
||||
lda #\filedes
|
||||
ldx FA
|
||||
bne +
|
||||
ldx #\device
|
||||
+ ldy #\secaddr
|
||||
jsr SETLFS
|
||||
|
||||
jsr OPEN
|
||||
.endmacro
|
||||
|
||||
cbmstatus .macro
|
||||
jsr READST
|
||||
.endmacro
|
||||
.endif
|
||||
|
||||
.section code
|
||||
LoadCH8 .proc
|
||||
|
||||
.cbmopen 2, 8, 2, ch8filename, ch8filenamelen
|
||||
bcs error
|
||||
|
||||
ldx #2
|
||||
jsr CHKIN
|
||||
|
||||
lda #<C8ENTRY
|
||||
sta EAL
|
||||
lda #>C8ENTRY
|
||||
sta EAL+1
|
||||
|
||||
ldy #0
|
||||
- .cbmstatus
|
||||
bne eof
|
||||
jsr CHRIN
|
||||
sta (EAL), y
|
||||
inc EAL
|
||||
bne +
|
||||
inc EAL+1
|
||||
+ jmp -
|
||||
|
||||
eof and #$40
|
||||
beq readerror
|
||||
|
||||
close lda #2
|
||||
jsr CLOSE
|
||||
|
||||
jsr CLRCHN
|
||||
rts
|
||||
|
||||
error ; TODO
|
||||
lda #4
|
||||
sta $d020
|
||||
jmp close
|
||||
|
||||
readerror ; TODO
|
||||
lda #1
|
||||
sta $d020
|
||||
jmp close
|
||||
.endproc
|
||||
.endsection code
|
||||
|
||||
.section data
|
||||
ch8filenamelen .byte ?
|
||||
ch8filename .text "tetris.ch8"
|
||||
.fill 16
|
||||
.endsection data
|
|
@ -0,0 +1,293 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
from typing import NamedTuple
|
||||
import re, struct
|
||||
|
||||
|
||||
class Token(NamedTuple):
|
||||
type: str
|
||||
value: str
|
||||
filename: str
|
||||
line: int
|
||||
column: int
|
||||
|
||||
|
||||
TOKENS = [
|
||||
(
|
||||
"MNEMONIC",
|
||||
"|".join(
|
||||
[
|
||||
"CLS",
|
||||
"RET",
|
||||
"SYS",
|
||||
"JP",
|
||||
"CALL",
|
||||
"SE",
|
||||
"LD",
|
||||
"ADD",
|
||||
"AND",
|
||||
"OR",
|
||||
"XOR",
|
||||
"SUBN",
|
||||
"SUB",
|
||||
"SHR",
|
||||
"SHL",
|
||||
"SNE",
|
||||
"RND",
|
||||
"DRW",
|
||||
"SKP",
|
||||
"SKNP",
|
||||
"DATA",
|
||||
"EXIT",
|
||||
]
|
||||
),
|
||||
),
|
||||
("VREG", r"V[0-9a-fA-F]"),
|
||||
("PREG", r"ST|DT|F|B|\[I\]|I|K"),
|
||||
("NUMBER", r"[0-9a-fA-F]{1,4}"),
|
||||
("SYMBOL", r"[a-zA-Z_.]+[a-zA-Z_.0-9]*"),
|
||||
("COMMA", r","),
|
||||
("COLON", r":"),
|
||||
("STAR", r"\*"),
|
||||
("EQUAL", r"="),
|
||||
("SPACE", r"[ \t]+"),
|
||||
("MISMATCH", r"."),
|
||||
]
|
||||
|
||||
TOK_RE = re.compile("|".join([f"(?P<{tn}>{tp})" for tn, tp in TOKENS]))
|
||||
|
||||
|
||||
def tokenize_line(line, filename="", lineno=-1):
|
||||
line = line.split(";", 1)[0]
|
||||
if len(line) < 1:
|
||||
return []
|
||||
r = []
|
||||
for match in TOK_RE.finditer(line):
|
||||
t = Token(
|
||||
type=match.lastgroup,
|
||||
value=match.group(),
|
||||
filename=filename,
|
||||
line=lineno,
|
||||
column=match.start(),
|
||||
)
|
||||
if t.type == "SPACE":
|
||||
continue
|
||||
r.append(t)
|
||||
return r
|
||||
|
||||
|
||||
def tokenize_file(filename):
|
||||
with open(filename, "r") as f:
|
||||
lineno = 1
|
||||
for line in f:
|
||||
yield tokenize_line(line, filename, lineno)
|
||||
lineno += 1
|
||||
|
||||
|
||||
class ParseError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def ensure_size(val, bits):
|
||||
if val.type not in ("NUMBER", "SYMBOL"):
|
||||
raise ParseError(f"Literal value expected, found {val} instead")
|
||||
if type(val.value) == str:
|
||||
v = int(val.value, 16)
|
||||
else:
|
||||
v = val.value
|
||||
if v >= (1 << bits):
|
||||
raise ParseError(f"Value to large for {bits} bits: {val}")
|
||||
return v
|
||||
|
||||
|
||||
def vreg_index(tok):
|
||||
if tok.type != "VREG":
|
||||
raise ParseError(f"V register expected, found {tok} instead")
|
||||
return int(tok.value[-1], 16)
|
||||
|
||||
|
||||
def assemble_instruction(tl, symbols):
|
||||
if type(tl) == int:
|
||||
return tl
|
||||
if tl[0].type != "MNEMONIC":
|
||||
raise ParseError("Mnemonic was expected but found " + repr(tl[0]))
|
||||
mnemonic = tl[0].value
|
||||
ntok = len(tl)
|
||||
for i in range(len(tl)):
|
||||
if tl[i].type in ("SYMBOL", "STAR"):
|
||||
if tl[i].value in symbols:
|
||||
nt = Token(
|
||||
type="NUMBER",
|
||||
value=symbols[tl[i].value],
|
||||
filename=tl[i].filename,
|
||||
line=tl[i].line,
|
||||
column=tl[i].column,
|
||||
)
|
||||
tl[i] = nt
|
||||
else:
|
||||
return tl
|
||||
if ntok == 1:
|
||||
if mnemonic == "CLS":
|
||||
return 0x00E0
|
||||
elif mnemonic == "RET":
|
||||
return 0x00EE
|
||||
elif mnemonic == "EXIT":
|
||||
return 0x00fd
|
||||
else:
|
||||
raise ParseError("Invalid number of operands for " + tl[0].value)
|
||||
elif ntok == 2:
|
||||
op1 = tl[1]
|
||||
if mnemonic == "SYS":
|
||||
return 0x0000 | ensure_size(op1, 12)
|
||||
if mnemonic == "JP":
|
||||
return 0x1000 | ensure_size(op1, 12)
|
||||
if mnemonic == "CALL":
|
||||
return 0x2000 | ensure_size(op1, 12)
|
||||
if mnemonic == "DATA":
|
||||
return ensure_size(op1, 16)
|
||||
if mnemonic == "SKP":
|
||||
return 0xE09E | (vreg_index(op1) << 8)
|
||||
if mnemonic == "SKNP":
|
||||
return 0xE0A1 | (vreg_index(op1) << 8)
|
||||
if mnemonic == "SHR":
|
||||
return 0x8006 | vreg_index(op1) << 8 | vreg_index(op1) << 4
|
||||
if mnemonic == "SHL":
|
||||
return 0x800E | vreg_index(op1) << 8 | vreg_index(op1) << 4
|
||||
else:
|
||||
raise ParseError("Invalid number of operands for " + tl[0].value)
|
||||
elif ntok == 3:
|
||||
op1 = tl[1]
|
||||
op2 = tl[2]
|
||||
if mnemonic == "SE":
|
||||
if op2.type == "VREG":
|
||||
return 0x5000 | vreg_index(op1) << 8 | vreg_index(op2) << 4
|
||||
else:
|
||||
return 0x3000 | vreg_index(op1) << 8 | ensure_size(op2, 8)
|
||||
if mnemonic == "SNE":
|
||||
if op2.type == "VREG":
|
||||
return 0x9000 | vreg_index(op1) << 8 | vreg_index(op2) << 4
|
||||
else:
|
||||
return 0x4000 | vreg_index(op1) << 8 | ensure_size(op2, 8)
|
||||
if mnemonic == "LD":
|
||||
if op1.type == "VREG":
|
||||
if op2.type == "VREG":
|
||||
return 0x8000 | vreg_index(op1) << 8 | vreg_index(op2) << 4
|
||||
elif op2.type == "PREG":
|
||||
if op2.value == "DT":
|
||||
return 0xF007 | (vreg_index(op1) << 8)
|
||||
elif op2.value == "K":
|
||||
return 0xF00A | (vreg_index(op1) << 8)
|
||||
elif op2.value == "[I]":
|
||||
return 0xF065 | (vreg_index(op1) << 8)
|
||||
elif op2.value == "R":
|
||||
return 0xF085 | (vreg_index(op1) << 8)
|
||||
else:
|
||||
raise ParseError()
|
||||
elif op2.type == "NUMBER":
|
||||
return 0x6000 | vreg_index(op1) << 8 | ensure_size(op2, 8)
|
||||
elif op1.type == "PREG":
|
||||
if op1.value == "I":
|
||||
return 0xA000 | ensure_size(op2, 12)
|
||||
elif op1.value == "DT":
|
||||
return 0xF015 | (vreg_index(op2) << 8)
|
||||
elif op1.value == "ST":
|
||||
return 0xF018 | (vreg_index(op2) << 8)
|
||||
elif op1.value == "F":
|
||||
return 0xF029 | (vreg_index(op2) << 8)
|
||||
elif op1.value == "B":
|
||||
return 0xF033 | (vreg_index(op2) << 8)
|
||||
elif op1.value == "[I]":
|
||||
return 0xF055 | (vreg_index(op2) << 8)
|
||||
else:
|
||||
raise ParseError()
|
||||
else:
|
||||
raise ParseError()
|
||||
if mnemonic == "ADD":
|
||||
if op1.type == "VREG":
|
||||
if op2.type == "VREG":
|
||||
return 0x8004 | vreg_index(op1) << 8 | vreg_index(op2) << 4
|
||||
elif op2.type == "NUMBER":
|
||||
return 0x7000 | vreg_index(op1) << 8 | ensure_size(op2, 8)
|
||||
elif op1.value == "I":
|
||||
return 0xF01E | vreg_index(op2) << 8
|
||||
else:
|
||||
raise ParseError()
|
||||
if mnemonic == "OR":
|
||||
return 0x8001 | vreg_index(op1) << 8 | vreg_index(op2) << 4
|
||||
if mnemonic == "AND":
|
||||
return 0x8002 | vreg_index(op1) << 8 | vreg_index(op2) << 4
|
||||
if mnemonic == "XOR":
|
||||
return 0x8003 | vreg_index(op1) << 8 | vreg_index(op2) << 4
|
||||
if mnemonic == "SUB":
|
||||
return 0x8005 | vreg_index(op1) << 8 | vreg_index(op2) << 4
|
||||
if mnemonic == "SUBN":
|
||||
return 0x8007 | vreg_index(op1) << 8 | vreg_index(op2) << 4
|
||||
if mnemonic == "SHR":
|
||||
return 0x8006 | vreg_index(op1) << 8 | vreg_index(op2) << 4
|
||||
if mnemonic == "SHL":
|
||||
return 0x800E | vreg_index(op1) << 8 | vreg_index(op2) << 4
|
||||
if mnemonic == "JP":
|
||||
if op1.type != "VREG" or op1.value != "V0":
|
||||
raise ParseError(f"Register V0 expected. {op1} found instead")
|
||||
return 0xB000 | ensure_size(op1, 12)
|
||||
if mnemonic == "RND":
|
||||
return 0xC000 | vreg_index(op1) << 8 | ensure_size(op2, 8)
|
||||
elif ntok == 4:
|
||||
if mnemonic == "DRW":
|
||||
op1 = tl[1]
|
||||
op2 = tl[2]
|
||||
op3 = tl[3]
|
||||
return (
|
||||
0xD000
|
||||
| vreg_index(op1) << 8
|
||||
| vreg_index(op2) << 4
|
||||
| ensure_size(op3, 4)
|
||||
)
|
||||
else:
|
||||
raise ParseError()
|
||||
else:
|
||||
raise ParseError("Invalid number of operands for " + tl[0].value)
|
||||
return tl
|
||||
|
||||
|
||||
def assemble(filename):
|
||||
addr = 0x200
|
||||
symbols = {}
|
||||
opcodes = []
|
||||
for tokline in tokenize_file(filename):
|
||||
if len(tokline) < 1:
|
||||
continue
|
||||
symbols["*"] = addr + len(opcodes) * 2
|
||||
if tokline[0].type == "SYMBOL":
|
||||
sym = tokline[0].value
|
||||
tokline = tokline[1:]
|
||||
if tokline[0].type == "COLON":
|
||||
tokline = tokline[1:]
|
||||
if tokline[0].type == "EQUAL":
|
||||
symbols[sym] = ensure_size(tokline[1], 32)
|
||||
continue
|
||||
symbols[sym] = symbols["*"]
|
||||
tokline = [t for t in tokline if t.type != "COMMA"]
|
||||
if len(tokline) < 1:
|
||||
continue
|
||||
opcodes.append(assemble_instruction(tokline, symbols))
|
||||
addr = 0x200
|
||||
for o in opcodes:
|
||||
symbols["*"] = addr
|
||||
yield assemble_instruction(o, symbols)
|
||||
addr += 2
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
|
||||
for fn in sys.argv[1:]:
|
||||
if "." in fn:
|
||||
ofn = fn[: fn.rindex(".")] + ".ch8"
|
||||
else:
|
||||
ofn = fn + ".ch8"
|
||||
with open(ofn, "wb") as of:
|
||||
for word in assemble(fn):
|
||||
if type(word) != int:
|
||||
print(word)
|
||||
of.write(struct.pack(">H", word))
|
|
@ -0,0 +1,143 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import struct
|
||||
|
||||
|
||||
OP = [
|
||||
# Mnemonic, mask, value, xmask, ymask, kmask, klabel
|
||||
('CLS', '',
|
||||
0xffff, 0x00e0, 0x0000, 0x0000, 0x0000, False),
|
||||
('RET', '',
|
||||
0xffff, 0x00ee, 0x0000, 0x0000, 0x0000, False),
|
||||
('SYS', '{k}',
|
||||
0xf000, 0x0000, 0x0000, 0x0000, 0x0fff, True),
|
||||
('JP', '{k}',
|
||||
0xf000, 0x1000, 0x0000, 0x0000, 0x0fff, True),
|
||||
('CALL', '{k}',
|
||||
0xf000, 0x2000, 0x0000, 0x0000, 0x0fff, True),
|
||||
('SE', 'V{x:01x}, {k:02x}',
|
||||
0xf000, 0x3000, 0x0f00, 0x0000, 0x00ff, False),
|
||||
('SNE', 'V{x:01x}, {k:02x}',
|
||||
0xf000, 0x4000, 0x0f00, 0x0000, 0x00ff, False),
|
||||
('SE', 'V{x:01x}, V{y:01x}',
|
||||
0xf00f, 0x5000, 0x0f00, 0x00f0, 0x0000, False),
|
||||
('LD', 'V{x:01x}, {k:02x}',
|
||||
0xf000, 0x6000, 0x0f00, 0x0000, 0x00ff, False),
|
||||
('ADD', 'V{x:01x}, {k:02x}',
|
||||
0xf000, 0x7000, 0x0f00, 0x0000, 0x00ff, False),
|
||||
('LD', 'V{x:01x}, V{y:01x}',
|
||||
0xf00f, 0x8000, 0x0f00, 0x00f0, 0x0000, False),
|
||||
('OR', 'V{x:01x}, V{y:01x}',
|
||||
0xf00f, 0x8001, 0x0f00, 0x00f0, 0x0000, False),
|
||||
('AND', 'V{x:01x}, V{y:01x}',
|
||||
0xf00f, 0x8002, 0x0f00, 0x00f0, 0x0000, False),
|
||||
('XOR', 'V{x:01x}, V{y:01x}',
|
||||
0xf00f, 0x8003, 0x0f00, 0x00f0, 0x0000, False),
|
||||
('ADD', 'V{x:01x}, V{y:01x}',
|
||||
0xf00f, 0x8004, 0x0f00, 0x00f0, 0x0000, False),
|
||||
('SUB', 'V{x:01x}, V{y:01x}',
|
||||
0xf00f, 0x8005, 0x0f00, 0x00f0, 0x0000, False),
|
||||
('SHR', 'V{x:01x}, V{y:01x}',
|
||||
0xf00f, 0x8006, 0x0f00, 0x00f0, 0x0000, False),
|
||||
('SHL', 'V{x:01x}, V{y:01x}',
|
||||
0xf00f, 0x800e, 0x0f00, 0x00f0, 0x0000, False),
|
||||
('SNE', 'V{x:01x}, V{y:01x}',
|
||||
0xf00f, 0x9000, 0x0f00, 0x00f0, 0x0000, False),
|
||||
('LD', 'I, {k}',
|
||||
0xf000, 0xa000, 0x0000, 0x0000, 0x0fff, True),
|
||||
('JP', 'V0, {k}',
|
||||
0xf000, 0xb000, 0x0000, 0x0000, 0x0fff, True),
|
||||
('RND', 'V{x:01x}, {k:02x}',
|
||||
0xf000, 0xc000, 0x0f00, 0x0000, 0x00ff, False),
|
||||
('DRW', 'V{x:01x}, V{y:01x}, {k:02x}',
|
||||
0xf000, 0xd000, 0x0f00, 0x00f0, 0x000f, False),
|
||||
('SKP', 'V{x:01x}',
|
||||
0xf0ff, 0xe09e, 0x0f00, 0x0000, 0x0000, False),
|
||||
('SKNP', 'V{x:01x}',
|
||||
0xf0ff, 0xe0a1, 0x0f00, 0x0000, 0x0000, False),
|
||||
('LD', 'V{x:01x}, DT',
|
||||
0xf0ff, 0xf007, 0x0f00, 0x0000, 0x0000, False),
|
||||
('LD', 'V{x:01x}, K',
|
||||
0xf0ff, 0xf00a, 0x0f00, 0x0000, 0x0000, False),
|
||||
('LD', 'DT, V{x:01x}',
|
||||
0xf0ff, 0xf015, 0x0f00, 0x0000, 0x0000, False),
|
||||
('LD', 'ST, V{x:01x}',
|
||||
0xf0ff, 0xf018, 0x0f00, 0x0000, 0x0000, False),
|
||||
('ADD', 'I, V{x:01x}',
|
||||
0xf0ff, 0xf01e, 0x0f00, 0x0000, 0x0000, False),
|
||||
('LD', 'F, V{x:01x}',
|
||||
0xf0ff, 0xf029, 0x0f00, 0x0000, 0x0000, False),
|
||||
('LD', 'B, V{x:01x}',
|
||||
0xf0ff, 0xf033, 0x0f00, 0x0000, 0x0000, False),
|
||||
('LD', '[I], V{x:01x}',
|
||||
0xf0ff, 0xf055, 0x0f00, 0x0000, 0x0000, False),
|
||||
('LD', 'V{x:01x}, [I]',
|
||||
0xf0ff, 0xf065, 0x0f00, 0x0000, 0x0000, False),
|
||||
|
||||
|
||||
('DATA', '{k:04x}',
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0xffff, False)
|
||||
]
|
||||
|
||||
|
||||
def c8decode(ins):
|
||||
|
||||
def _unmask(v, m):
|
||||
if m == 0:
|
||||
return None
|
||||
r = v & m
|
||||
while (m & 1) == 0:
|
||||
m >>= 1
|
||||
r >>= 1
|
||||
return r
|
||||
|
||||
for mn, fmt, mask, value, xmask, ymask, kmask, klabel in OP:
|
||||
if (ins & mask) == value:
|
||||
xo = _unmask(ins, xmask)
|
||||
yo = _unmask(ins, ymask)
|
||||
ko = _unmask(ins, kmask)
|
||||
return (mn, fmt, xo, yo, ko, klabel)
|
||||
|
||||
|
||||
def disasm(filename, org=0x200):
|
||||
pc = org
|
||||
targets = set()
|
||||
listing = []
|
||||
with open(filename, 'rb') as f:
|
||||
while True:
|
||||
w = f.read(2)
|
||||
if len(w) != 2:
|
||||
break
|
||||
instr = struct.unpack('>H', w)[0]
|
||||
mn, fmt, xo, yo, ko, klabel = c8decode(instr)
|
||||
if klabel:
|
||||
targets.add(ko)
|
||||
listing.append((pc, instr, mn, fmt, xo, yo, ko, klabel))
|
||||
pc += 2
|
||||
end = pc
|
||||
|
||||
print(f""";
|
||||
; {filename}
|
||||
; start={org:03x} end={end:03x} size={end-org}(dec)
|
||||
;
|
||||
""")
|
||||
for pc, instr, mn, fmt, xo, yo, ko, klabel in listing:
|
||||
if pc in targets:
|
||||
label = "l%03x" % (pc,)
|
||||
else:
|
||||
label = ""
|
||||
if klabel:
|
||||
if org <= ko <= end:
|
||||
ko = f"l{ko:03x}"
|
||||
else:
|
||||
ko = f"{ko:03x}"
|
||||
o = fmt.format(x=xo, y=yo, k=ko)
|
||||
print(f"{label:8s} {mn:5s} {o:12s} ; {pc:03x}: {instr:04x}")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
|
||||
for fn in sys.argv[1:]:
|
||||
disasm(fn)
|
||||
|
|
@ -0,0 +1,816 @@
|
|||
;
|
||||
; CHIP-8 emulation core
|
||||
;
|
||||
|
||||
EMBEDSAMPLE = true
|
||||
|
||||
EF_SHIFTX = %0000_0001
|
||||
EF_REGS = %0001_0000
|
||||
EF_LOAD = %0010_0000
|
||||
EF_PAUSE = %0100_0000
|
||||
EF_RESET = %1000_0000
|
||||
|
||||
C8START = $0200
|
||||
|
||||
.section zp
|
||||
zptr1 .word ?
|
||||
zptr2 .word ?
|
||||
pc .word ?
|
||||
.endsection zp
|
||||
|
||||
.section bss
|
||||
reg .block
|
||||
v .fill 16
|
||||
i .word ?
|
||||
sp .byte ?
|
||||
dt .byte ?
|
||||
st .byte ?
|
||||
pc .word ?
|
||||
.endblock
|
||||
ins .block
|
||||
opcode .word ?
|
||||
c .byte ?
|
||||
x .byte ?
|
||||
y .byte ?
|
||||
w .word ?
|
||||
ptr .word ?
|
||||
.endblock
|
||||
c8stack .fill 48
|
||||
rngst .fill 4
|
||||
rng_t1 .byte ?
|
||||
c8screen .fill (64*32)/8
|
||||
c8screenend = *-1
|
||||
scrdirty .byte ?
|
||||
.endsection bss
|
||||
|
||||
.section code
|
||||
|
||||
; This is called 60 times per second from the machine specific interrupt
|
||||
; handler
|
||||
Tick .proc
|
||||
lda reg.dt
|
||||
beq +
|
||||
dec reg.dt
|
||||
+ lda reg.st
|
||||
beq +
|
||||
dec reg.st
|
||||
bne +
|
||||
jsr SoundOff
|
||||
+ rts
|
||||
.endproc
|
||||
|
||||
C8Reset .proc
|
||||
.CopyMem sprites, C8RAM, size(sprites)
|
||||
;.FillMem C8RAM+size(sprites), 0, C8RAMSIZE-size(sprites)
|
||||
.if EMBEDSAMPLE
|
||||
.CopyMem samplecode, C8RAM+C8START, size(samplecode)
|
||||
.endif
|
||||
warm .FillMem reg, 0, size(reg)
|
||||
jsr c8cls
|
||||
jsr SoundOff
|
||||
.if (C8START & $ff) != 0
|
||||
lda #<C8START
|
||||
sta reg.pc
|
||||
.endif
|
||||
.if (C8START >> 8) != 0
|
||||
lda #>C8START
|
||||
sta reg.pc+1
|
||||
.endif
|
||||
lda eflags
|
||||
and #~EF_RESET
|
||||
sta eflags
|
||||
rts
|
||||
.endproc
|
||||
|
||||
C8Run .proc
|
||||
jsr C8Reset
|
||||
|
||||
fetch
|
||||
jsr HeartBeat
|
||||
lda eflags
|
||||
tax
|
||||
and #EF_REGS
|
||||
beq +
|
||||
jsr ShowRegisters
|
||||
+ txa
|
||||
and #EF_RESET
|
||||
beq +
|
||||
lda eflags
|
||||
and #~EF_RESET
|
||||
sta eflags
|
||||
jsr C8Reset.warm
|
||||
jmp fetch
|
||||
+ txa
|
||||
and #EF_PAUSE
|
||||
beq +
|
||||
jsr VideoDraw
|
||||
- lda eflags
|
||||
and #EF_PAUSE
|
||||
bne -
|
||||
+ txa
|
||||
and #EF_LOAD
|
||||
beq +
|
||||
lda eflags
|
||||
and #~EF_LOAD
|
||||
sta eflags
|
||||
jsr InputFileName
|
||||
lda ch8filenamelen
|
||||
beq +
|
||||
jsr LoadCH8
|
||||
jsr C8Reset.warm
|
||||
jmp fetch
|
||||
+ lda scrdirty
|
||||
beq +
|
||||
jsr GetVBlank
|
||||
bcs +
|
||||
jsr VideoDraw
|
||||
|
||||
+ clc
|
||||
lda #<C8RAM
|
||||
adc reg.pc
|
||||
sta pc
|
||||
lda #>C8RAM
|
||||
adc reg.pc+1
|
||||
sta pc+1
|
||||
; advance reg.pc
|
||||
clc
|
||||
lda #2
|
||||
adc reg.pc
|
||||
sta reg.pc
|
||||
lda #0
|
||||
adc reg.pc+1
|
||||
sta reg.pc+1
|
||||
|
||||
decode
|
||||
ldy #0
|
||||
lda (pc), y
|
||||
sta ins.opcode+1
|
||||
and #$0f
|
||||
sta ins.w+1
|
||||
sta ins.x
|
||||
lda (pc), y
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
sta ins.c
|
||||
iny
|
||||
lda (pc), y
|
||||
sta ins.opcode
|
||||
sta ins.w
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
sta ins.y
|
||||
lda ins.c
|
||||
cmp #8
|
||||
bne +
|
||||
; decode 8xxx instructions
|
||||
lda ins.w
|
||||
and #$0f
|
||||
asl a
|
||||
tay
|
||||
lda jumptable.op8, y
|
||||
sta ins.ptr
|
||||
lda jumptable.op8+1, y
|
||||
sta ins.ptr+1
|
||||
bne execute
|
||||
beq oINV
|
||||
+ asl a
|
||||
tay
|
||||
lda jumptable.main, y
|
||||
sta ins.ptr
|
||||
lda jumptable.main+1, y
|
||||
sta ins.ptr+1
|
||||
bne execute
|
||||
ldy #0
|
||||
- lda jumptable.sparse+3, y
|
||||
beq oINV
|
||||
lda ins.opcode
|
||||
cmp jumptable.sparse, y
|
||||
bne +
|
||||
lda ins.opcode+1
|
||||
and #$f0
|
||||
cmp jumptable.sparse+1, y
|
||||
bne +
|
||||
lda jumptable.sparse+2, y
|
||||
sta ins.ptr
|
||||
lda jumptable.sparse+3, y
|
||||
sta ins.ptr+1
|
||||
bne execute
|
||||
beq oINV
|
||||
+ iny
|
||||
iny
|
||||
iny
|
||||
iny
|
||||
bne -
|
||||
execute
|
||||
ldx ins.x
|
||||
ldy ins.y
|
||||
jmp (ins.ptr)
|
||||
.endproc
|
||||
|
||||
FetchNext .macro
|
||||
jmp C8Run.fetch
|
||||
.endmacro
|
||||
|
||||
oINV .proc
|
||||
inc $d020 ; FIXME
|
||||
jmp *
|
||||
.endproc
|
||||
|
||||
oNOP .proc
|
||||
.FetchNext
|
||||
.endproc
|
||||
|
||||
; 00E0 - CLS
|
||||
oCLS .proc
|
||||
jsr c8cls
|
||||
.FetchNext
|
||||
.endproc
|
||||
|
||||
; 00EE - RET
|
||||
oRET .proc
|
||||
lda reg.sp
|
||||
asl a
|
||||
tax
|
||||
lda c8stack, x
|
||||
sta reg.pc
|
||||
lda c8stack+1, x
|
||||
sta reg.pc+1
|
||||
dec reg.sp
|
||||
; FIXME: check stack boundaries
|
||||
.FetchNext
|
||||
.endproc
|
||||
|
||||
; 2nnn - CALL addr
|
||||
oCALL .proc
|
||||
inc reg.sp
|
||||
; FIXME: check stack boundaries
|
||||
lda reg.sp
|
||||
asl a
|
||||
tax
|
||||
lda reg.pc
|
||||
sta c8stack, x
|
||||
lda reg.pc+1
|
||||
sta c8stack+1, x
|
||||
; could fallthrough to oJP instead
|
||||
lda ins.w
|
||||
sta reg.pc
|
||||
lda ins.w+1
|
||||
and #$0f
|
||||
sta reg.pc+1
|
||||
.FetchNext
|
||||
.endproc
|
||||
|
||||
; 1nnn - JP addr
|
||||
oJP .proc
|
||||
lda ins.w
|
||||
sta reg.pc
|
||||
stx reg.pc+1
|
||||
.FetchNext
|
||||
.endproc
|
||||
|
||||
skip .proc
|
||||
clc
|
||||
lda #2
|
||||
adc reg.pc
|
||||
sta reg.pc
|
||||
lda #0
|
||||
adc reg.pc+1
|
||||
sta reg.pc+1
|
||||
.FetchNext
|
||||
.endproc
|
||||
|
||||
; 3xkk - SE Vx, byte
|
||||
oSEK .proc
|
||||
lda reg.v, x
|
||||
cmp ins.w
|
||||
beq skip
|
||||
.FetchNext
|
||||
.endproc
|
||||
|
||||
; 4xkk - SNE Vx, byte
|
||||
oSNEK .proc
|
||||
lda reg.v, x
|
||||
cmp ins.w
|
||||
bne skip
|
||||
.FetchNext
|
||||
.endproc
|
||||
|
||||
; 5xy0 - SE Vx, Vy
|
||||
oSE .proc
|
||||
lda reg.v, x
|
||||
cmp reg.v, y
|
||||
beq skip
|
||||
.FetchNext
|
||||
.endproc
|
||||
|
||||
; 6xkk - LD Vx, byte
|
||||
oLDn .proc
|
||||
lda ins.w
|
||||
sta reg.v, x
|
||||
.FetchNext
|
||||
.endproc
|
||||
|
||||
; 7xkk - ADD Vx, byte
|
||||
oADDn .proc
|
||||
lda ins.w
|
||||
clc
|
||||
adc reg.v, x
|
||||
sta reg.v, x
|
||||
.FetchNext
|
||||
.endproc
|
||||
|
||||
; 8xy0 - LD Vx, Vy
|
||||
oLD .proc
|
||||
lda reg.v, y
|
||||
sta reg.v, x
|
||||
.FetchNext
|
||||
.endproc
|
||||
|
||||
; 8xy1 - OR Vx, Vy
|
||||
oOR .proc
|
||||
lda reg.v, y
|
||||
ora reg.v, x
|
||||
sta reg.v, x
|
||||
.FetchNext
|
||||
.endproc
|
||||
|
||||
; 8xy2 - AND Vx, Vy
|
||||
oAND .proc
|
||||
lda reg.v, y
|
||||
and reg.v, x
|
||||
sta reg.v, x
|
||||
.FetchNext
|
||||
.endproc
|
||||
|
||||
; 8xy3 - XOR Vx, Vy
|
||||
oXOR .proc
|
||||
lda reg.v, y
|
||||
eor reg.v, x
|
||||
sta reg.v, x
|
||||
.FetchNext
|
||||
.endproc
|
||||
|
||||
; 8xy4 - ADD Vx, Vy
|
||||
oADD .proc
|
||||
lda reg.v, y
|
||||
clc
|
||||
adc reg.v, x
|
||||
sta reg.v, x
|
||||
lda #0
|
||||
rol a
|
||||
sta reg.v+$f
|
||||
.FetchNext
|
||||
.endproc
|
||||
|
||||
; 8xy5 - SUB Vx, Vy
|
||||
oSUB .proc
|
||||
lda reg.v, x
|
||||
sec
|
||||
sbc reg.v, y
|
||||
sta reg.v, x
|
||||
lda #0
|
||||
rol a
|
||||
sta reg.v+$f
|
||||
.FetchNext
|
||||
.endproc
|
||||
|
||||
; 8xy6 - SHR Vx {, Vy}
|
||||
oSHR .proc
|
||||
lda #EF_SHIFTX
|
||||
and eflags
|
||||
beq _shifty
|
||||
lda reg.v, x
|
||||
lsr a
|
||||
bpl +
|
||||
_shifty
|
||||
lda reg.v, y
|
||||
lsr a
|
||||
sta reg.v, y
|
||||
+ sta reg.v, x
|
||||
lda #0
|
||||
rol a
|
||||
sta reg.v+$f
|
||||
.FetchNext
|
||||
.endproc
|
||||
|
||||
; 8xy7 - SUBN Vx, Vy
|
||||
oSUBN .proc
|
||||
lda reg.v, y
|
||||
sec
|
||||
sbc reg.v, x
|
||||
sta reg.v, x
|
||||
lda #0
|
||||
rol a
|
||||
sta reg.v+$f
|
||||
.FetchNext
|
||||
.endproc
|
||||
|
||||
; 8xyE - SHL Vx {, Vy}
|
||||
oSHL .proc
|
||||
lda #EF_SHIFTX
|
||||
and eflags
|
||||
clc
|
||||
beq _shifty
|
||||
|
||||
lda reg.v, x
|
||||
rol a
|
||||
jmp +
|
||||
_shifty
|
||||
lda reg.v, y
|
||||
rol a
|
||||
sta reg.v, y
|
||||
+ sta reg.v, x
|
||||
lda #0
|
||||
rol a
|
||||
sta reg.v+$f
|
||||
.FetchNext
|
||||
.endproc
|
||||
|
||||
; 9xy0 - SNE Vx, Vy
|
||||
oSNE .proc
|
||||
lda reg.v, x
|
||||
cmp reg.v, y
|
||||
bne skip
|
||||
.FetchNext
|
||||
.endproc
|
||||
|
||||
; Annn - LD I, addr
|
||||
oLDI .proc
|
||||
lda ins.w
|
||||
sta reg.i
|
||||
stx reg.i+1
|
||||
.FetchNext
|
||||
.endproc
|
||||
|
||||
; Bnnn - JP V0, addr
|
||||
oJPI .proc
|
||||
lda reg.v
|
||||
clc
|
||||
adc ins.w
|
||||
sta reg.pc
|
||||
txa
|
||||
adc #0
|
||||
sta reg.pc+1
|
||||
.FetchNext
|
||||
.endproc
|
||||
|
||||
; Cxkk - RND Vx, byte
|
||||
oRND .proc
|
||||
jsr rand
|
||||
and ins.w
|
||||
sta reg.v, x
|
||||
.FetchNext
|
||||
.endproc
|
||||
|
||||
; Dxyn - DRW Vx, Vy, nibble
|
||||
oDRW .proc
|
||||
lda reg.v, y
|
||||
and #%0001_1111
|
||||
asl a
|
||||
asl a
|
||||
asl a
|
||||
sta startpos
|
||||
lda reg.v, x
|
||||
and #%0011_1111
|
||||
tax
|
||||
and #%0000_0111
|
||||
sta bitshift
|
||||
txa
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
ora startpos
|
||||
sta startpos
|
||||
lda #0
|
||||
sta reg.v+$f
|
||||
lda ins.w
|
||||
and #%0000_1111
|
||||
beq done
|
||||
sta ins.w
|
||||
lda #1
|
||||
sta scrdirty
|
||||
jsr regItozptr1
|
||||
ldy #0
|
||||
nextline
|
||||
lda (zptr1), y
|
||||
sta bitsl
|
||||
lda #0
|
||||
sta bitsr
|
||||
ldx bitshift
|
||||
beq +
|
||||
- lsr bitsl
|
||||
ror bitsr
|
||||
dex
|
||||
bne -
|
||||
+ ldx startpos
|
||||
lda bitsl
|
||||
and c8screen, x
|
||||
beq +
|
||||
lda #1
|
||||
sta reg.v+$f
|
||||
+ lda bitsl
|
||||
eor c8screen, x
|
||||
sta c8screen, x
|
||||
inx
|
||||
beq done
|
||||
txa
|
||||
and #$7
|
||||
beq skipr
|
||||
lda bitsr
|
||||
and c8screen, x
|
||||
beq +
|
||||
lda #1
|
||||
sta reg.v+$f
|
||||
+ lda bitsr
|
||||
eor c8screen, x
|
||||
sta c8screen, x
|
||||
skipr lda #8
|
||||
clc
|
||||
adc startpos
|
||||
bcs done
|
||||
sta startpos
|
||||
iny
|
||||
cpy ins.w
|
||||
bmi nextline
|
||||
done .FetchNext
|
||||
|
||||
.section bss
|
||||
startpos .byte ?
|
||||
bitshift .byte ?
|
||||
bitsl .byte ?
|
||||
bitsr .byte ?
|
||||
.endsection
|
||||
|
||||
.endproc
|
||||
|
||||
; Ex9E - SKP Vx
|
||||
oSKP .proc
|
||||
jsr ReadKeyboard
|
||||
bmi +
|
||||
cmp reg.v, x
|
||||
beq skip
|
||||
+ .FetchNext
|
||||
.endproc
|
||||
|
||||
; ExA1 - SKNP Vx
|
||||
oSKNP .proc
|
||||
jsr ReadKeyboard
|
||||
bmi skip
|
||||
cmp reg.v, x
|
||||
bne skip
|
||||
.FetchNext
|
||||
.endproc
|
||||
|
||||
; Fx07 - LD Vx, DT
|
||||
oLDxDT .proc
|
||||
lda reg.dt
|
||||
sta reg.v, x
|
||||
.FetchNext
|
||||
.endproc
|
||||
|
||||
; Fx0A - LD Vx, K
|
||||
oLDK .proc
|
||||
jsr ReadKeyboard
|
||||
bpl +
|
||||
sec
|
||||
lda reg.pc
|
||||
sbc #2
|
||||
sta reg.pc
|
||||
lda reg.pc+1
|
||||
sbc #0
|
||||
sta reg.pc+1
|
||||
.FetchNext
|
||||
+ sta reg.v, x
|
||||
.FetchNext
|
||||
.endproc
|
||||
|
||||
; Fx15 - LD DT, Vx
|
||||
oLDDTx .proc
|
||||
lda reg.v, x
|
||||
sta reg.dt
|
||||
.FetchNext
|
||||
.endproc
|
||||
|
||||
; Fx18 - LD ST, Vxsnd_
|
||||
oLDSTx .proc
|
||||
lda reg.v, x
|
||||
sta reg.st
|
||||
beq +
|
||||
jsr SoundOn
|
||||
.FetchNext
|
||||
+ jsr SoundOff
|
||||
.FetchNext
|
||||
.endproc
|
||||
|
||||
; Fx1E - ADD I, Vx
|
||||
oADDI .proc
|
||||
lda reg.v, x
|
||||
clc
|
||||
adc reg.i
|
||||
sta reg.i
|
||||
lda #0
|
||||
adc reg.i+1
|
||||
sta reg.i+1
|
||||
.FetchNext
|
||||
.endproc
|
||||
|
||||
; Fx29 - LD F, Vx
|
||||
oLDF .proc
|
||||
lda reg.v, x
|
||||
asl a
|
||||
asl a
|
||||
clc
|
||||
adc reg.v, x
|
||||
sta reg.i
|
||||
lda #0
|
||||
sta reg.i+1
|
||||
.FetchNext
|
||||
.endproc
|
||||
|
||||
; Fx33 - LD B, Vx
|
||||
oLDB .proc
|
||||
jsr regItozptr1
|
||||
lda #0
|
||||
tay
|
||||
sta (zptr1), y
|
||||
iny
|
||||
sta (zptr1), y
|
||||
lda reg.v, x
|
||||
sta zptr2
|
||||
ldx #8
|
||||
sed
|
||||
ldy #1
|
||||
- asl zptr2
|
||||
lda (zptr1), y
|
||||
adc (zptr1), y
|
||||
sta (zptr1), y
|
||||
dey
|
||||
lda (zptr1), y
|
||||
adc (zptr1), y
|
||||
sta (zptr1), y
|
||||
iny
|
||||
dex
|
||||
bne -
|
||||
cld
|
||||
; y == 1
|
||||
; now I -> 0A BC xx
|
||||
; we need I -> 0A 0B 0C
|
||||
lda (zptr1), y
|
||||
tax
|
||||
and #$0f
|
||||
iny
|
||||
sta (zptr1), y
|
||||
dey
|
||||
txa
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
sta (zptr1), y
|
||||
.FetchNext
|
||||
.endproc
|
||||
|
||||
; Fx55 - LD [I], Vx
|
||||
oLDIx .proc
|
||||
jsr regItozptr1
|
||||
txa
|
||||
tay
|
||||
- lda reg.v, y
|
||||
sta (zptr1), y
|
||||
dey
|
||||
bpl -
|
||||
.FetchNext
|
||||
.endproc
|
||||
|
||||
; Fx65 - LD Vx, [I]
|
||||
oLDxI .proc
|
||||
jsr regItozptr1
|
||||
txa
|
||||
tay
|
||||
- lda (zptr1), y
|
||||
sta reg.v, y
|
||||
dey
|
||||
bpl -
|
||||
.FetchNext
|
||||
.endproc
|
||||
|
||||
regItozptr1 .proc
|
||||
ADDRMASK = C8RAMSIZE - 1
|
||||
clc
|
||||
lda reg.i
|
||||
.if (ADDRMASK & $00ff) != $00ff
|
||||
and #<ADDRMASK
|
||||
.endif
|
||||
.if (C8RAM & $00ff) != 0
|
||||
adc #<C8RAM
|
||||
.endif
|
||||
sta zptr1
|
||||
lda reg.i+1
|
||||
and #>ADDRMASK
|
||||
adc #>C8RAM
|
||||
sta zptr1+1
|
||||
rts
|
||||
.endproc
|
||||
|
||||
c8cls .proc
|
||||
.FillMem c8screen, 0, size(c8screen)
|
||||
lda #1
|
||||
sta scrdirty
|
||||
rts
|
||||
.endproc
|
||||
|
||||
rand .proc
|
||||
; stir rng state and return next value in A
|
||||
; https://github.com/edrosten/8bit_rng/blob/master/rng-4261412736.c
|
||||
; unsigned char t = x ^ (x << 4);
|
||||
; x=y;
|
||||
; y=z;
|
||||
; z=a;
|
||||
; a = z ^ t ^ ( z >> 1) ^ (t << 1);
|
||||
|
||||
lda rngst
|
||||
asl a
|
||||
asl a
|
||||
asl a
|
||||
asl a
|
||||
eor rngst
|
||||
sta rng_t1
|
||||
asl a
|
||||
eor rng_t1
|
||||
sta rng_t1 ; t1 = (t << 1) ^ t
|
||||
lda rngst+1
|
||||
sta rngst
|
||||
lda rngst+2
|
||||
sta rngst+1
|
||||
lda rngst+3
|
||||
sta rngst+2
|
||||
lsr a
|
||||
eor rngst+2 ; ra = ( z >> 1 ) ^ z
|
||||
eor rng_t1
|
||||
sta rngst+3
|
||||
rts
|
||||
.endproc
|
||||
|
||||
.endsection code
|
||||
|
||||
.section data
|
||||
sprites .block
|
||||
.byte $F0, $90, $90, $90, $F0 ; 0
|
||||
.byte $20, $60, $20, $20, $70 ; 1
|
||||
.byte $F0, $10, $F0, $80, $F0 ; 2
|
||||
.byte $F0, $10, $F0, $10, $F0 ; 3
|
||||
.byte $90, $90, $F0, $10, $10 ; 4
|
||||
.byte $F0, $80, $F0, $10, $F0 ; 5
|
||||
.byte $F0, $80, $F0, $90, $F0 ; 6
|
||||
.byte $F0, $10, $20, $40, $40 ; 7
|
||||
.byte $F0, $90, $F0, $90, $F0 ; 8
|
||||
.byte $F0, $90, $F0, $10, $F0 ; 9
|
||||
.byte $F0, $90, $F0, $90, $90 ; a
|
||||
.byte $E0, $90, $E0, $90, $E0 ; b
|
||||
.byte $F0, $80, $80, $80, $F0 ; c
|
||||
.byte $E0, $90, $90, $90, $E0 ; d
|
||||
.byte $F0, $80, $F0, $80, $F0 ; e
|
||||
.byte $F0, $80, $F0, $80, $80 ; f
|
||||
.bend
|
||||
|
||||
eflags .byte 0
|
||||
|
||||
jumptable .block
|
||||
ops = [0, oJP, oCALL, oSEK, oSNEK, oSE, oLDn, oADDn, oINV, oSNE, oLDI, oJPI, oRND, oDRW, 0, 0]
|
||||
ops8 = [oLD, oOR, oAND, oXOR, oADD, oSUB, oSHR, oSUBN, oINV, oINV, oINV, oINV, oINV, oINV, oSHL, oINV]
|
||||
main .addr ops
|
||||
op8 .addr ops8
|
||||
sparse .word $00e0, oCLS
|
||||
.word $00ee, oRET
|
||||
.word $e09e, oSKP
|
||||
.word $e0a1, oSKNP
|
||||
.word $f007, oLDxDT
|
||||
.word $f00a, oLDK
|
||||
.word $f015, oLDDTx
|
||||
.word $f018, oLDSTx
|
||||
.word $f01e, oADDI
|
||||
.word $f029, oLDF
|
||||
.word $f033, oLDB
|
||||
.word $f055, oLDIx
|
||||
.word $f065, oLDxI
|
||||
.word 0, 0
|
||||
.endblock
|
||||
|
||||
.if EMBEDSAMPLE
|
||||
samplecode .block
|
||||
; .binary "samples/ibmlogo.ch8"
|
||||
; .binary "samples/tetris.ch8"
|
||||
; .binary "samples/lunarlander.ch8"
|
||||
; .binary "diags/keypad.ch8"
|
||||
.binary "samples/opcodes.ch8"
|
||||
; .binary "diags/sound.ch8"
|
||||
.endblock
|
||||
.endif
|
||||
|
||||
.endsection data
|
||||
|
||||
; vim: syntax=64tass
|
|
@ -0,0 +1,230 @@
|
|||
C8RAMSIZE = 4096
|
||||
.virtual $c000
|
||||
C8RAM .fill C8START
|
||||
C8ENTRY .fill C8RAMSIZE - C8START
|
||||
c8ramend = *-1
|
||||
.endvirtual
|
||||
|
||||
ZP_START = $61
|
||||
|
||||
.BasicStub MainEntry, 2021
|
||||
|
||||
.section code
|
||||
|
||||
MainEntry .proc
|
||||
;lda #EF_REGS
|
||||
lda #0
|
||||
sta eflags
|
||||
|
||||
jsr InitRandom
|
||||
jsr VideoInit
|
||||
jsr SoundInit
|
||||
jsr ClearScreen
|
||||
jsr ShowTitle
|
||||
jsr C8Reset
|
||||
jsr SetupIRQ
|
||||
jsr C8Run
|
||||
rts
|
||||
.endproc
|
||||
|
||||
SetupIRQ .proc
|
||||
lda #64
|
||||
sta prevkey
|
||||
sei
|
||||
lda CINV
|
||||
sta sysirq
|
||||
lda CINV+1
|
||||
sta sysirq+1
|
||||
lda #<handler
|
||||
sta CINV
|
||||
lda #>handler
|
||||
sta CINV+1
|
||||
cli
|
||||
rts
|
||||
handler
|
||||
lda SFDX
|
||||
tax
|
||||
cmp prevkey
|
||||
beq dotick
|
||||
cmp #3 ; F7: reset
|
||||
bne +
|
||||
lda #EF_RESET
|
||||
ora eflags
|
||||
sta eflags
|
||||
jmp done
|
||||
+ txa
|
||||
cmp #6 ; F5: Pause
|
||||
bne +
|
||||
lda #EF_PAUSE
|
||||
eor eflags
|
||||
sta eflags
|
||||
jmp done
|
||||
+ txa
|
||||
cmp #53 ; =: Registers
|
||||
bne +
|
||||
lda #EF_REGS
|
||||
eor eflags
|
||||
sta eflags
|
||||
jmp done
|
||||
+ txa
|
||||
cmp #43 ; -: Shift behaviour
|
||||
bne +
|
||||
lda #EF_SHIFTX
|
||||
eor eflags
|
||||
sta eflags
|
||||
jmp done
|
||||
+ txa
|
||||
cmp #55 ; /: Load
|
||||
bne +
|
||||
lda #EF_LOAD
|
||||
ora eflags
|
||||
sta eflags
|
||||
; jmp done
|
||||
+
|
||||
done stx prevkey
|
||||
dotick jsr Tick
|
||||
jmp (sysirq)
|
||||
|
||||
.section bss
|
||||
sysirq .word ?
|
||||
prevkey .byte ?
|
||||
.endsection bss
|
||||
|
||||
.endproc
|
||||
|
||||
RestoreIRQ .proc
|
||||
sei
|
||||
lda SetupIRQ.sysirq
|
||||
sta CINV
|
||||
lda SetupIRQ.sysirq+1
|
||||
sta CINV+1
|
||||
cli
|
||||
rts
|
||||
.endproc
|
||||
|
||||
InitRandom .proc
|
||||
ldx #0
|
||||
- lda TIME, x
|
||||
sta rngst, x
|
||||
inx
|
||||
cpx #3
|
||||
bne -
|
||||
lda io.vic2.raster
|
||||
sta rngst+3
|
||||
rts
|
||||
.endproc
|
||||
|
||||
ClearScreen .proc
|
||||
lda #0
|
||||
sta io.vic2.ec
|
||||
sta io.vic2.b0c
|
||||
lda #'{green}'
|
||||
jsr CHROUT
|
||||
lda #'{clear}'
|
||||
jsr CHROUT
|
||||
rts
|
||||
.endproc
|
||||
|
||||
ReadKeyboard .proc
|
||||
lda SFDX
|
||||
cmp #64
|
||||
bne +
|
||||
nokey
|
||||
lda #$ff
|
||||
rts
|
||||
|
||||
+ ldy #0
|
||||
- cmp kbdcodes, y
|
||||
beq +
|
||||
cpy #size(kbdcodes)
|
||||
beq nokey
|
||||
iny
|
||||
bne -
|
||||
+ tya
|
||||
rts
|
||||
.endproc
|
||||
|
||||
GetVBlank .proc
|
||||
sec
|
||||
; Clear carry flag if retracing
|
||||
lda #200
|
||||
cmp io.vic2.raster
|
||||
rts
|
||||
.endproc
|
||||
|
||||
SoundInit .proc
|
||||
FREQ = io.sid_freq(880)
|
||||
DUTY = io.sid_duty(0.5)
|
||||
lda #0
|
||||
sta io.sid.voice1.ctrl
|
||||
sta io.sid.voice2.ctrl
|
||||
sta io.sid.voice3.ctrl
|
||||
sta io.sid.voice1.ad
|
||||
lda #$f0
|
||||
sta io.sid.voice1.sr
|
||||
lda #$0f
|
||||
sta io.sid.volume
|
||||
lda #<DUTY
|
||||
sta io.sid.voice1.duty
|
||||
lda #>DUTY
|
||||
sta io.sid.voice1.duty+1
|
||||
lda #<FREQ
|
||||
sta io.sid.voice1.freq
|
||||
lda #>FREQ
|
||||
sta io.sid.voice1.freq+1
|
||||
lda #io.SID_CTRL_PULSE
|
||||
sta io.sid.voice1.ctrl
|
||||
rts
|
||||
.endproc
|
||||
|
||||
SoundOn .proc
|
||||
lda #io.SID_CTRL_PULSE|io.SID_CTRL_GATE
|
||||
sta io.sid.voice1.ctrl
|
||||
rts
|
||||
.endproc
|
||||
|
||||
SoundOff .proc
|
||||
lda #io.SID_CTRL_PULSE
|
||||
sta io.sid.voice1.ctrl
|
||||
rts
|
||||
.endproc
|
||||
|
||||
InputFileName .proc
|
||||
jsr RestoreIRQ
|
||||
ldx #ROW_FILENAME
|
||||
ldy #0
|
||||
sty ch8filenamelen
|
||||
sty NDX
|
||||
clc
|
||||
jsr PLOT
|
||||
lda #<prompt
|
||||
ldy #>prompt
|
||||
jsr STROUT
|
||||
ldy #0
|
||||
- lda #0
|
||||
sta ch8filename, y
|
||||
jsr CHRIN
|
||||
cmp #13
|
||||
beq +
|
||||
sta ch8filename, y
|
||||
iny
|
||||
jmp -
|
||||
+ sty ch8filenamelen
|
||||
ldx #ROW_FILENAME
|
||||
jsr ClearLine
|
||||
jsr SetupIRQ
|
||||
rts
|
||||
|
||||
.section data
|
||||
prompt .null "file name: "
|
||||
.endsection data
|
||||
.endproc
|
||||
|
||||
|
||||
.endsection code
|
||||
|
||||
.section data
|
||||
kbdcodes .byte 56, 59, 8, 11, 62, 9, 14, 17, 10, 13, 18, 21, 12, 23, 20, 31
|
||||
.endsection data
|
||||
|
||||
; vim: syntax=64tass
|
|
@ -0,0 +1,237 @@
|
|||
C8RAMSIZE = 4096
|
||||
.virtual $2000
|
||||
C8RAM .fill C8START
|
||||
C8ENTRY .fill C8RAMSIZE - C8START
|
||||
c8ramend = *-1
|
||||
.endvirtual
|
||||
|
||||
IS_PET = true
|
||||
|
||||
ZP_START = $54
|
||||
|
||||
.BasicStub MainEntry, 2021
|
||||
|
||||
.section code
|
||||
|
||||
MainEntry .proc
|
||||
;lda #EF_REGS
|
||||
lda #0
|
||||
sta eflags
|
||||
|
||||
jsr InitRandom
|
||||
jsr ClearScreen
|
||||
jsr ShowTitle
|
||||
jsr C8Reset
|
||||
jsr SoundInit
|
||||
jsr SetupIRQ
|
||||
jsr C8Run
|
||||
rts
|
||||
.endproc
|
||||
|
||||
NOKEY = 255
|
||||
|
||||
SetupIRQ .proc
|
||||
lda #NOKEY
|
||||
sta prevkey
|
||||
sei
|
||||
lda CINV
|
||||
sta sysirq
|
||||
lda CINV+1
|
||||
sta sysirq+1
|
||||
lda #<handler
|
||||
sta CINV
|
||||
lda #>handler
|
||||
sta CINV+1
|
||||
cli
|
||||
rts
|
||||
handler
|
||||
lda LSTX
|
||||
tax
|
||||
cmp prevkey
|
||||
beq dotick
|
||||
cmp #20 ; backspace: reset
|
||||
bne +
|
||||
lda #EF_RESET
|
||||
ora eflags
|
||||
sta eflags
|
||||
jmp done
|
||||
+ txa
|
||||
cmp #'.' ; '.'': Pause
|
||||
bne +
|
||||
lda #EF_PAUSE
|
||||
eor eflags
|
||||
sta eflags
|
||||
jmp done
|
||||
+ txa
|
||||
cmp #'=' ; =: Registers
|
||||
bne +
|
||||
lda #EF_REGS
|
||||
eor eflags
|
||||
sta eflags
|
||||
jmp done
|
||||
+ txa
|
||||
cmp #"-" ; -: Shift behaviour
|
||||
bne +
|
||||
lda #EF_SHIFTX
|
||||
eor eflags
|
||||
sta eflags
|
||||
jmp done
|
||||
+ txa
|
||||
cmp #'/' ; '/': Load
|
||||
bne +
|
||||
lda #EF_LOAD
|
||||
ora eflags
|
||||
sta eflags
|
||||
jmp done
|
||||
+
|
||||
done stx prevkey
|
||||
dotick jsr Tick
|
||||
jmp (sysirq)
|
||||
|
||||
.section bss
|
||||
sysirq .word ?
|
||||
prevkey .byte ?
|
||||
.endsection bss
|
||||
|
||||
.endproc
|
||||
|
||||
RestoreIRQ .proc
|
||||
sei
|
||||
lda SetupIRQ.sysirq
|
||||
sta CINV
|
||||
lda SetupIRQ.sysirq+1
|
||||
sta CINV+1
|
||||
cli
|
||||
rts
|
||||
.endproc
|
||||
|
||||
InitRandom .proc
|
||||
ldx #0
|
||||
- lda TIME, x
|
||||
sta rngst, x
|
||||
inx
|
||||
cpx #3
|
||||
bne -
|
||||
;lda io.vic2.raster
|
||||
;sta rngst+3
|
||||
rts
|
||||
.endproc
|
||||
|
||||
ClearScreen .proc
|
||||
lda #'{clear}'
|
||||
jsr CHROUT
|
||||
rts
|
||||
.endproc
|
||||
|
||||
ReadKeyboard .proc
|
||||
lda LSTX
|
||||
cmp #NOKEY
|
||||
bne +
|
||||
nokey
|
||||
lda #$ff
|
||||
rts
|
||||
|
||||
+ ldy #0
|
||||
- cmp kbdcodes, y
|
||||
beq +
|
||||
cpy #size(kbdcodes)
|
||||
beq nokey
|
||||
iny
|
||||
bne -
|
||||
+ tya
|
||||
rts
|
||||
.endproc
|
||||
|
||||
GetVBlank .proc
|
||||
; Clear carry flag if retracing
|
||||
; FIXME
|
||||
clc
|
||||
rts
|
||||
|
||||
lda #io.CRTC_VBLANK
|
||||
bit io.crtc.ctrl
|
||||
bne +
|
||||
sec
|
||||
rts
|
||||
+ clc
|
||||
rts
|
||||
.endproc
|
||||
|
||||
SoundInit .proc
|
||||
lda #io.VIA_SR_OUT_T2_FR
|
||||
sta io.via.acr
|
||||
lda #0
|
||||
sta io.via.t2c
|
||||
lda #22
|
||||
sta io.via.sr
|
||||
rts
|
||||
.endproc
|
||||
|
||||
SoundOn .proc
|
||||
lda #211
|
||||
sta io.via.t2c
|
||||
rts
|
||||
.endproc
|
||||
|
||||
SoundOff .proc
|
||||
lda #0
|
||||
sta io.via.t2c
|
||||
rts
|
||||
.endproc
|
||||
|
||||
|
||||
InputFileName .proc
|
||||
jsr RestoreIRQ
|
||||
ldy #0
|
||||
sty ch8filenamelen
|
||||
sty NDX
|
||||
lda #'{home}'
|
||||
jsr CHROUT
|
||||
ldx #ROW_FILENAME
|
||||
lda #'{down}'
|
||||
- jsr CHROUT
|
||||
dex
|
||||
bne -
|
||||
ldx #ROW_FILENAME
|
||||
ldy #0
|
||||
jsr myPLOT
|
||||
lda #<prompt
|
||||
ldy #>prompt
|
||||
jsr mySTROUT
|
||||
lda #ROW_FILENAME
|
||||
sta TBLX
|
||||
lda #size(prompt)
|
||||
sta PNTR
|
||||
jsr $e07f
|
||||
ldy #0
|
||||
- lda #0
|
||||
sta ch8filename, y
|
||||
jsr CHRIN
|
||||
cmp #13
|
||||
beq +
|
||||
sta ch8filename, y
|
||||
iny
|
||||
jmp -
|
||||
+ sty ch8filenamelen
|
||||
ldx #ROW_FILENAME
|
||||
jsr ClearLine
|
||||
jsr SetupIRQ
|
||||
rts
|
||||
|
||||
.section data
|
||||
.enc "screen"
|
||||
prompt .null "file name: "
|
||||
.enc "none"
|
||||
.endsection data
|
||||
.endproc
|
||||
|
||||
|
||||
|
||||
.endsection code
|
||||
|
||||
.section data
|
||||
; kbdcodes .byte 56, 59, 8, 11, 62, 9, 14, 17, 10, 13, 18, 21, 12, 23, 20, 31
|
||||
kbdcodes .text "1234qwerasdfzxcv"
|
||||
.endsection data
|
||||
|
||||
; vim: syntax=64tass
|
|
@ -0,0 +1,230 @@
|
|||
C8RAMSIZE = 4096
|
||||
.virtual $3000
|
||||
C8RAM .fill C8START
|
||||
C8ENTRY .fill C8RAMSIZE - C8START
|
||||
c8ramend = *-1
|
||||
.endvirtual
|
||||
|
||||
ZP_START = $d0
|
||||
|
||||
.BasicStub MainEntry, 2021
|
||||
|
||||
.section code
|
||||
|
||||
MainEntry .proc
|
||||
;lda #EF_REGS
|
||||
lda #0
|
||||
sta eflags
|
||||
|
||||
jsr InitRandom
|
||||
jsr VideoInit
|
||||
jsr SoundInit
|
||||
jsr ClearScreen
|
||||
jsr ShowTitle
|
||||
jsr C8Reset
|
||||
jsr SetupIRQ
|
||||
jsr C8Run
|
||||
rts
|
||||
.endproc
|
||||
|
||||
SetupIRQ .proc
|
||||
lda #64
|
||||
sta prevkey
|
||||
sei
|
||||
lda CINV
|
||||
sta sysirq
|
||||
lda CINV+1
|
||||
sta sysirq+1
|
||||
lda #<handler
|
||||
sta CINV
|
||||
lda #>handler
|
||||
sta CINV+1
|
||||
cli
|
||||
rts
|
||||
handler
|
||||
lda SFDX
|
||||
tax
|
||||
cmp prevkey
|
||||
beq dotick
|
||||
cmp #3 ; F7: reset
|
||||
bne +
|
||||
lda #EF_RESET
|
||||
ora eflags
|
||||
sta eflags
|
||||
jmp done
|
||||
+ txa
|
||||
cmp #6 ; F5: Pause
|
||||
bne +
|
||||
lda #EF_PAUSE
|
||||
eor eflags
|
||||
sta eflags
|
||||
jmp done
|
||||
+ txa
|
||||
cmp #53 ; =: Registers
|
||||
bne +
|
||||
lda #EF_REGS
|
||||
eor eflags
|
||||
sta eflags
|
||||
jmp done
|
||||
+ txa
|
||||
cmp #46 ; -: Shift behaviour
|
||||
bne +
|
||||
lda #EF_SHIFTX
|
||||
eor eflags
|
||||
sta eflags
|
||||
jmp done
|
||||
+ txa
|
||||
cmp #55 ; /: Load
|
||||
bne +
|
||||
lda #EF_LOAD
|
||||
ora eflags
|
||||
sta eflags
|
||||
; jmp done
|
||||
+
|
||||
done stx prevkey
|
||||
dotick jsr Tick
|
||||
jmp (sysirq)
|
||||
|
||||
.section bss
|
||||
sysirq .word ?
|
||||
prevkey .byte ?
|
||||
.endsection bss
|
||||
|
||||
.endproc
|
||||
|
||||
RestoreIRQ .proc
|
||||
sei
|
||||
lda SetupIRQ.sysirq
|
||||
sta CINV
|
||||
lda SetupIRQ.sysirq+1
|
||||
sta CINV+1
|
||||
cli
|
||||
rts
|
||||
.endproc
|
||||
|
||||
InitRandom .proc
|
||||
ldx #0
|
||||
- lda TIME, x
|
||||
sta rngst, x
|
||||
inx
|
||||
cpx #3
|
||||
bne -
|
||||
lda io.ted.rasterline_lo
|
||||
sta rngst+3
|
||||
lda io.ted.rastercolumn
|
||||
eor rngst+1
|
||||
sta rngst+1
|
||||
rts
|
||||
.endproc
|
||||
|
||||
ClearScreen .proc
|
||||
lda #0
|
||||
sta io.ted.bgcolor
|
||||
sta io.ted.bordercolor
|
||||
lda #'{green}'
|
||||
jsr CHROUT
|
||||
lda #'{clear}'
|
||||
jsr CHROUT
|
||||
rts
|
||||
.endproc
|
||||
|
||||
ReadKeyboard .proc
|
||||
lda SFDX
|
||||
cmp #64
|
||||
bne +
|
||||
nokey
|
||||
lda #$ff
|
||||
rts
|
||||
|
||||
+ ldy #0
|
||||
- cmp kbdcodes, y
|
||||
beq +
|
||||
cpy #size(kbdcodes)
|
||||
beq nokey
|
||||
iny
|
||||
bne -
|
||||
+ tya
|
||||
rts
|
||||
.endproc
|
||||
|
||||
GetVBlank .proc
|
||||
sec
|
||||
lda #200
|
||||
cmp io.ted.rasterline_lo
|
||||
rts
|
||||
.endproc
|
||||
|
||||
SoundInit .proc
|
||||
FREQ = io.ted_freq(880)
|
||||
lda #$0f
|
||||
sta io.ted.snd_ctrl
|
||||
lda #<FREQ
|
||||
sta io.ted.freq1
|
||||
; lda #>FREQ
|
||||
; ora io.ted.misc
|
||||
; sta io.ted.misc
|
||||
lda io.ted.misc
|
||||
and #%1111_1100
|
||||
ora #>FREQ
|
||||
sta io.ted.misc
|
||||
rts
|
||||
.endproc
|
||||
|
||||
SoundOn .proc
|
||||
lda #$10
|
||||
ora io.ted.snd_ctrl
|
||||
sta io.ted.snd_ctrl
|
||||
rts
|
||||
.endproc
|
||||
|
||||
SoundOff .proc
|
||||
lda #~$10
|
||||
and io.ted.snd_ctrl
|
||||
sta io.ted.snd_ctrl
|
||||
rts
|
||||
.endproc
|
||||
|
||||
InputFileName .proc
|
||||
jsr RestoreIRQ
|
||||
ldx #ROW_FILENAME
|
||||
ldy #0
|
||||
sty ch8filenamelen
|
||||
sty NDX
|
||||
clc
|
||||
jsr myPLOT
|
||||
lda #<prompt
|
||||
ldy #>prompt
|
||||
jsr mySTROUT
|
||||
ldx #ROW_FILENAME
|
||||
ldy #size(prompt)
|
||||
clc
|
||||
jsr PLOT
|
||||
ldy #0
|
||||
- lda #0
|
||||
sta ch8filename, y
|
||||
jsr CHRIN
|
||||
cmp #13
|
||||
beq +
|
||||
sta ch8filename, y
|
||||
iny
|
||||
jmp -
|
||||
+ sty ch8filenamelen
|
||||
ldx #ROW_FILENAME
|
||||
jsr ClearLine
|
||||
jsr SetupIRQ
|
||||
rts
|
||||
|
||||
.section data
|
||||
.enc "screen"
|
||||
prompt .null "file name: "
|
||||
.enc "none"
|
||||
.endsection data
|
||||
.endproc
|
||||
|
||||
.endsection code
|
||||
|
||||
.section data
|
||||
kbdcodes .byte 56, 59, 8, 11, 62, 9, 14, 17, 10, 13, 18, 21, 12, 23, 20, 31
|
||||
.endsection data
|
||||
|
||||
; vim: syntax=64tass
|
|
@ -0,0 +1,15 @@
|
|||
;
|
||||
; 6545/6845 (CRTC) registers
|
||||
;
|
||||
|
||||
.virtual
|
||||
_crtc .struct
|
||||
ctrl .byte ?
|
||||
data .byte ?
|
||||
.endstruct
|
||||
.endvirtual
|
||||
|
||||
CRTC_LPEN = %0100_0000
|
||||
CRTC_VBLANK = %0010_0000
|
||||
|
||||
; vim: syntax=64tass
|
|
@ -0,0 +1,16 @@
|
|||
LD I, .corner
|
||||
LD V1, 0
|
||||
.yloop LD V0, 0
|
||||
.xloop DRW V0, V1, 8
|
||||
ADD V0, 08
|
||||
SE V0, 40
|
||||
JP .xloop
|
||||
ADD V1, 08
|
||||
SE V1, 20
|
||||
JP .yloop
|
||||
.halt JP .halt
|
||||
|
||||
.corner DATA ff80
|
||||
DATA 8080
|
||||
DATA 8080
|
||||
DATA 8080
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
LD V1, 00
|
||||
.loop LD V0, K
|
||||
LD F, V0
|
||||
DRW V1, V1, 5
|
||||
.down SKNP V0
|
||||
JP .down
|
||||
DRW V1, V1, 5
|
||||
JP .loop
|
|
@ -0,0 +1,4 @@
|
|||
LD V0, 78
|
||||
LD ST, V0
|
||||
.loop JP .loop
|
||||
|
|
@ -0,0 +1,349 @@
|
|||
;
|
||||
; This is the video output driver for 40 column PETSCII machines
|
||||
; Each 2x2 pixel block is mapped to a single PETSCII character
|
||||
;
|
||||
|
||||
SCREEN_COLS = 40
|
||||
SCREEN_ROWS = 25
|
||||
|
||||
ROW_TILE = 0
|
||||
ROW_REGS = 1
|
||||
ROW_FLAGS = 2
|
||||
ROW_FILENAME = 3
|
||||
|
||||
|
||||
VIDEO_TOP = (SCREEN_ROWS-16)
|
||||
VIDEO_LEFT = (SCREEN_COLS - (64/2)) / 2
|
||||
|
||||
VIDEO_START = SCREEN_RAM + SCREEN_COLS * VIDEO_TOP + VIDEO_LEFT
|
||||
|
||||
; 00 00 00 00 01 01 01 01 10 10 10 10 11 11 11 11
|
||||
; 00 01 10 11 00 01 10 11 00 01 10 11 00 01 10 11
|
||||
petpixels = [ $20, $6c, $7b, $62, $7c, $e1, $ff, $fe, $7e, $7f, $61, $fc, $e2, $fb, $ec, $a0 ]
|
||||
|
||||
.section data
|
||||
qpix .byte petpixels
|
||||
.endsection data
|
||||
|
||||
.section code
|
||||
|
||||
VideoInit .proc
|
||||
rts
|
||||
.endproc
|
||||
|
||||
VideoDraw .proc
|
||||
ldx #0
|
||||
stx scrdirty
|
||||
lda #<VIDEO_START
|
||||
sta zptr1
|
||||
lda #>VIDEO_START
|
||||
sta zptr1+1
|
||||
- lda c8screen, x
|
||||
and #%11_00_11_00
|
||||
sta zptr2
|
||||
lda c8screen+8, x
|
||||
and #%11_00_11_00
|
||||
lsr a
|
||||
lsr a
|
||||
ora zptr2
|
||||
sta zptr2
|
||||
lda c8screen, x
|
||||
and #%00_11_00_11
|
||||
asl a
|
||||
asl a
|
||||
sta zptr2+1
|
||||
lda c8screen+8, x
|
||||
and #%00_11_00_11
|
||||
ora zptr2+1
|
||||
sta zptr2+1
|
||||
and #$0f
|
||||
tay
|
||||
lda qpix, y
|
||||
ldy #3
|
||||
sta (zptr1), y
|
||||
lda zptr2+1
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
tay
|
||||
lda qpix, y
|
||||
ldy #1
|
||||
sta (zptr1), y
|
||||
lda zptr2
|
||||
and #$0f
|
||||
tay
|
||||
lda qpix, y
|
||||
ldy #2
|
||||
sta (zptr1), y
|
||||
lda zptr2
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
tay
|
||||
lda qpix, y
|
||||
ldy #0
|
||||
sta (zptr1), y
|
||||
lda #4
|
||||
clc
|
||||
adc zptr1
|
||||
sta zptr1
|
||||
tya
|
||||
adc zptr1+1
|
||||
sta zptr1+1
|
||||
inx
|
||||
txa
|
||||
and #7
|
||||
bne -
|
||||
lda #(SCREEN_COLS-32)
|
||||
clc
|
||||
adc zptr1
|
||||
sta zptr1
|
||||
tya
|
||||
adc zptr1+1
|
||||
sta zptr1+1
|
||||
txa
|
||||
clc
|
||||
adc #8 ; skip every other row since we are processing two rows at a time
|
||||
tax
|
||||
beq +
|
||||
jmp -
|
||||
+ rts
|
||||
.endproc
|
||||
|
||||
ShowFlags .proc
|
||||
ldx #0
|
||||
lda eflags
|
||||
sta tmpflags
|
||||
- rol tmpflags
|
||||
bcc +
|
||||
lda flags, x
|
||||
bne next
|
||||
+ lda #' '
|
||||
next sta SCREEN_RAM+SCREEN_COLS*(ROW_FLAGS+1)-8, x
|
||||
inx
|
||||
cpx #8
|
||||
bne -
|
||||
rts
|
||||
.section data
|
||||
.enc "screen"
|
||||
flags .text "pltr321s"
|
||||
.enc "none"
|
||||
.endsection data
|
||||
.section bss
|
||||
tmpflags .byte ?
|
||||
.endsection bss
|
||||
.endproc
|
||||
|
||||
ClearLine .proc
|
||||
ldy #0
|
||||
clc
|
||||
jsr myPLOT
|
||||
lda #' '
|
||||
ldx #SCREEN_COLS
|
||||
- jsr myCHROUT
|
||||
dex
|
||||
bne -
|
||||
rts
|
||||
.endproc
|
||||
|
||||
ShowRegisters .proc
|
||||
lda #0
|
||||
ldx #ROW_REGS
|
||||
tay
|
||||
clc
|
||||
jsr myPLOT
|
||||
ldx #0
|
||||
- txa
|
||||
pha
|
||||
lda reg.v, x
|
||||
jsr HexByteOut
|
||||
pla
|
||||
tax
|
||||
inx
|
||||
cmp #$0f
|
||||
bmi -
|
||||
lda reg.i+1
|
||||
jsr HexByteOut
|
||||
lda reg.i
|
||||
jsr HexByteOut
|
||||
lda reg.pc+1
|
||||
jsr HexByteOut
|
||||
lda reg.pc
|
||||
jsr HexByteOut
|
||||
rts
|
||||
.endproc
|
||||
|
||||
ShowTimers .proc
|
||||
.enc "screen"
|
||||
lda #'d'
|
||||
ldx reg.dt
|
||||
bne +
|
||||
clc
|
||||
adc #' '-'d'
|
||||
+ sta SCREEN_RAM+SCREEN_COLS*ROW_FLAGS
|
||||
lda #'s'
|
||||
ldx reg.st
|
||||
bne +
|
||||
clc
|
||||
adc #' '-'s'
|
||||
+ sta SCREEN_RAM+SCREEN_COLS*ROW_FLAGS+1
|
||||
rts
|
||||
.enc "none"
|
||||
.endproc
|
||||
|
||||
HexByteOut .proc
|
||||
tay
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
tax
|
||||
lda hexdigits, x
|
||||
jsr myCHROUT
|
||||
tya
|
||||
and #$0f
|
||||
tax
|
||||
lda hexdigits, x
|
||||
jsr myCHROUT
|
||||
rts
|
||||
.section data
|
||||
.enc "screen"
|
||||
hexdigits .text "0123456789abcdef"
|
||||
.enc "none"
|
||||
.endsection data
|
||||
|
||||
.endproc
|
||||
|
||||
myPLOT .proc
|
||||
pha
|
||||
txa
|
||||
ldx #0
|
||||
stx cursorpos+1
|
||||
asl a
|
||||
asl a
|
||||
asl a
|
||||
sta cursorpos
|
||||
asl a
|
||||
rol cursorpos+1
|
||||
asl a
|
||||
rol cursorpos+1
|
||||
clc
|
||||
adc cursorpos
|
||||
sta cursorpos
|
||||
clc
|
||||
tya
|
||||
adc cursorpos
|
||||
sta cursorpos
|
||||
lda #>SCREEN_RAM
|
||||
adc cursorpos+1
|
||||
sta cursorpos+1
|
||||
pla
|
||||
rts
|
||||
.endproc
|
||||
|
||||
myCHROUT .proc
|
||||
pha
|
||||
sta chr
|
||||
tya
|
||||
pha
|
||||
ldy #0
|
||||
lda chr
|
||||
sta (cursorpos), y
|
||||
inc cursorpos
|
||||
bne +
|
||||
inc cursorpos+1
|
||||
+ pla
|
||||
tay
|
||||
pla
|
||||
rts
|
||||
chr .byte ?
|
||||
.endproc
|
||||
|
||||
mySTROUT .proc
|
||||
sta zptr1
|
||||
sty zptr1+1
|
||||
ldy #0
|
||||
- lda (zptr1), y
|
||||
beq +
|
||||
sta (cursorpos), y
|
||||
iny
|
||||
bne -
|
||||
inc cursorpos+1
|
||||
rts
|
||||
+ tya
|
||||
clc
|
||||
adc cursorpos
|
||||
sta cursorpos
|
||||
lda #0
|
||||
adc cursorpos+1
|
||||
sta cursorpos+1
|
||||
rts
|
||||
.endproc
|
||||
|
||||
HeartBeat .proc
|
||||
lda step
|
||||
clc
|
||||
adc #1
|
||||
and #size(glyphs)-1
|
||||
sta step
|
||||
tax
|
||||
lda glyphs, x
|
||||
sta SCREEN_RAM+SCREEN_COLS-1
|
||||
jsr ShowTimers
|
||||
|
||||
lda eflags
|
||||
and #EF_REGS
|
||||
beq +
|
||||
jsr ShowRegisters
|
||||
+ lda eflags
|
||||
and #EF_LOAD
|
||||
beq +
|
||||
nop
|
||||
+ lda eflags
|
||||
eor preveflags
|
||||
beq +
|
||||
jsr ShowFlags
|
||||
lda eflags
|
||||
eor preveflags
|
||||
and #EF_REGS
|
||||
beq +
|
||||
ldx #ROW_REGS
|
||||
jsr ClearLine
|
||||
+ lda eflags
|
||||
sta preveflags
|
||||
rts
|
||||
|
||||
.section data
|
||||
glyphs .byte $7b, $7e, $7c, $6c
|
||||
.endsection data
|
||||
.section bss
|
||||
step .byte ?
|
||||
preveflags .byte ?
|
||||
.endsection
|
||||
.endproc
|
||||
|
||||
ShowTitle .proc
|
||||
lda #0
|
||||
tax
|
||||
tay
|
||||
jsr myPLOT
|
||||
ldy #>title
|
||||
lda #<title
|
||||
jsr mySTROUT
|
||||
rts
|
||||
.endproc
|
||||
.endsection code
|
||||
|
||||
.section zp
|
||||
cursorpos .word ?
|
||||
.endsection zp
|
||||
|
||||
.section data
|
||||
.enc "screen"
|
||||
title .null " chipty5 chip-8 emulator for the 6502 "
|
||||
.enc "none"
|
||||
.endsection data
|
||||
|
||||
; vim: syntax=64tass
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
* = ZP_START
|
||||
.dsection zp
|
||||
|
||||
* = BASIC_START
|
||||
.dsection stub
|
||||
.dsection code
|
||||
.dsection data
|
||||
.dsection bss
|
||||
|
||||
; vim: syntax=64tass
|
|
@ -0,0 +1,60 @@
|
|||
;
|
||||
; Macros for common tasks
|
||||
;
|
||||
|
||||
BasicStub .macro entrypoint, lineno=10, align=16
|
||||
.section stub
|
||||
.word (+), \lineno
|
||||
.null BTOK_SYS, format("%d", \entrypoint)
|
||||
+ .word 0
|
||||
.if \align > 0
|
||||
.align \align
|
||||
.endif
|
||||
.endsection
|
||||
.endmacro
|
||||
|
||||
FillMem .macro ptr, value, sz
|
||||
.for blocksz := 256, ((\sz) % blocksz) > 0, blocksz -= 1
|
||||
.endfor
|
||||
blocks = (\sz) / blocksz
|
||||
|
||||
lda #\value
|
||||
.if (\value) != 0
|
||||
ldx #0
|
||||
.else
|
||||
tax
|
||||
.endif
|
||||
- .for b := 0, b < blocks, b += 1
|
||||
sta (\ptr) + (b * blocksz), x
|
||||
.endfor
|
||||
inx
|
||||
.if blocksz != 256
|
||||
cpx #blocksz
|
||||
.endif
|
||||
bne -
|
||||
+
|
||||
.endmacro
|
||||
|
||||
CopyMem .macro src, dst, sz
|
||||
.for blocksz := 256, ((\sz) % blocksz) > 0, blocksz -= 1
|
||||
.endfor
|
||||
blocks = (\sz) / blocksz
|
||||
|
||||
ldx #0
|
||||
- .for b := 0, b < blocks, b += 1
|
||||
lda (\src) + (b * blocksz), x
|
||||
sta (\dst) + (b * blocksz), x
|
||||
.endfor
|
||||
inx
|
||||
.if blocksz != 256
|
||||
cpx #blocksz
|
||||
.endif
|
||||
bne -
|
||||
+ .endmacro
|
||||
|
||||
; *=$c000
|
||||
;
|
||||
; .FillMem 1024, 0, 10000
|
||||
; rts
|
||||
|
||||
; vim: syntax=64tass
|
|
@ -0,0 +1,195 @@
|
|||
;
|
||||
; Commodore PET specific constants and memory addresses
|
||||
;
|
||||
|
||||
.proff
|
||||
|
||||
.cpu "6502"
|
||||
|
||||
|
||||
io .namespace
|
||||
|
||||
.include "via.asm"
|
||||
.include "crtc.asm"
|
||||
|
||||
.virtual $e840
|
||||
via .dstruct _via
|
||||
.endvirtual
|
||||
|
||||
.virtual $e880
|
||||
crtc .dstruct _crtc
|
||||
.endvirtual
|
||||
|
||||
.endnamespace
|
||||
|
||||
BASIC_START = $0401
|
||||
BTOK_SYS = $9e
|
||||
SCREEN_RAM = $8000
|
||||
|
||||
|
||||
|
||||
USRPOK = $0000 ; USR Function Jump Instr (4C)
|
||||
USRADD = $0001 ; USR Address Low Byte / High Byte
|
||||
CHARAC = $0003 ; Search Character
|
||||
ENDCHR = $0004 ; Flag: Scan for Quote at End of String
|
||||
COUNT = $0005 ; Input Buffer Pointer / No. of Subscripts
|
||||
DIMFLG = $0006 ; Flag: Default Array DiMension / array name
|
||||
VAUYP = $0007 ; Data Type: $FF = String, $00 = Numeric
|
||||
INTFLG = $0008 ; Data Type: $80 = Integer, $00 = Floating
|
||||
GARBFL = $0009 ; Flag: DATA scan/LlST quote/Garbage Coll
|
||||
SUBFLG = $000a ; Flag: Subscript Ref / User Function Call
|
||||
INPFLG = $000b ; Flag: $00 = INPUT, $40 = GET, $98 = READ
|
||||
TANSGN = $000c ; Flag TAN sign / Comparison Result
|
||||
LINNUM = $0011 ; Temp: Integer Value
|
||||
TEMPPT = $0013 ; Pointer Temporary String
|
||||
LASTPT = $0014 ; Last Temp String Address
|
||||
TEMPST = $0016 ; Stack for Temporary Strings
|
||||
INDEX = $001f ; Utility Pointer Area
|
||||
RESHO = $0023 ; Floating-Point Product of Multiply
|
||||
TXTTAB = $0028 ; Pointer: Start of BASIC Text
|
||||
VARTAB = $002a ; Pointer: Start of BASIC Variables
|
||||
ARYTAB = $002c ; Pointer: Start of BASIC Arrays
|
||||
STREND = $002e ; Pointer End of BASIC Arrays (+1)
|
||||
FRETOP = $0030 ; Pointer: Bottom of String Storage
|
||||
FRESPC = $0032 ; Utility String Pointer
|
||||
MEMSIZ = $0034 ; Pointer: Highest Address Used by BASIC
|
||||
CURLIN = $0036 ; Current BASIC Line Number
|
||||
OLDLIN = $0038 ; Previous BASIC Line Number
|
||||
OLDTXT = $003a ; Pointer: BASIC Statement for CONT
|
||||
DATLIN = $003c ; Current DATA Line Number
|
||||
DATPTR = $003e ; Pointer: Current DATA Item Address
|
||||
INPPTR = $0040 ; Vector: INPUT Routine
|
||||
VARNAM = $0042 ; Current BASIC Variable Name
|
||||
VARPNT = $0044 ; Pointer: Current BASIC Variable Data
|
||||
FORPNT = $0046 ; Pointer: Index Variable for FOR/NEXT
|
||||
TEMPF1 = $0054 ; Temporary storage for FLPT value.
|
||||
TEMPF2 = $0059 ; Temporary storage for FLPT value.
|
||||
FACEXP = $005e ; Floating-Point Accumulator #1: Exponent
|
||||
FACHO = $005f ; Floating Accum. #1: Mantissa
|
||||
FACSGN = $0063 ; Floating Accum. #1: Sign
|
||||
SGNFLG = $0064 ; Pointer: Series Evaluation Constant Pointer
|
||||
BITS = $0065 ; Floating -accum. #1: Overflow Digit
|
||||
ARGEXP = $0066 ; Floating-Point Accumulator #2: Exponent
|
||||
ARGHO = $0067 ; Floating Accum. #2: Mantissa
|
||||
ARGSGN = $006b ; Floating Accum. #2: Sign
|
||||
ARISGN = $006c ; Sign Comparison Result: Accum. # 1 vs #2
|
||||
FACOV = $006d ; Floating Accum. #1. Low-Order (Rounding)
|
||||
FBUFPT = $006e ; Pointer: Cassette Buffer
|
||||
CHRGET = $0070 ; Subroutine: Get Next Byte of BASIC Text
|
||||
CHRGOT = $0076 ; Entry to Get Same Byte of Text Again
|
||||
TXTPTR = $0077 ; Pointer: Current Byte of BASIC Text
|
||||
RNDX = $0088 ; Floating RND Function Seed Value
|
||||
TIME = $008d ; Real-Time Jiffy Clock (approx) 1/60 Sec
|
||||
CINV = $0090 ; Vector: Hardware Interrupt
|
||||
CBINV = $0092 ; Vector: BRK Instr. Interrupt
|
||||
NMINV = $0094 ; Vector: Non-Maskable Interrupt
|
||||
STATUS = $0096 ; Kernal I/O Status Word: ST
|
||||
LSTX = $0097 ; Current Key Pressed: 255 = No Key
|
||||
SFDX = $0098 ; Flag: Print Shifted Chars.
|
||||
STKEY = $009b ; Flag: STOP key / RVS key
|
||||
SVXT = $009c ; Timing Constant for Tape
|
||||
VERCK = $009d ; Flag: 0 = Load, 1 = Verify (Kernel)
|
||||
NDX = $009e ; No. of Chars. in Keyboard Buffer (Queue)
|
||||
RVS = $009f ; Flag: Print Reverse Chars. -1=Yes, 0=No Used
|
||||
C3PO = $00a0 ; Flag: Serial Bus-Output Char. Buffered
|
||||
INDX = $00a1 ; Pointer: End of Logical Line for INPUT
|
||||
LXSP = $00a3 ; Cursor Y-X Pos. at Start of INPUT
|
||||
BSOUR = $00a5 ; Buffered Character for IEEE Bus
|
||||
BLNSW = $00a7 ; Cursor Blink enable: 0 = Flash Cursor
|
||||
BLNCT = $00a8 ; Timer: Countdown to Toggle Cursor
|
||||
GDBLN = $00a9 ; Character Under Cursor
|
||||
BLNON = $00aa ; Flag: Last Cursor Blink On/Off
|
||||
CRSW = $00ac ; Flag: INPUT or GET from Keyboard
|
||||
LDTND = $00ae ; No. of Open Files / Index to File Table
|
||||
DFLTN = $00af ; Default Input Device (0)
|
||||
DFLTO = $00b0 ; Default Output (CMD) Device (3)
|
||||
PRTY = $00b1 ; Tape Character Parity
|
||||
DPSW = $00b2 ; Flag: Tape Byte-Received
|
||||
BUFPNT = $00bb ; Pointer: Tape I/O Buffer #1
|
||||
INBIT = $00bd ; Cassette Temp (64#00A7)
|
||||
BITCI = $00be ; Cassette Temp (64#00A8)
|
||||
RINONE = $00bf ; RS-232 Flag: Check for Start Bit (64#00A9)
|
||||
FNMIDX = $00c0 ; Index to Cassette File name/Header ID for Tape write.
|
||||
PTR1 = $00c0 ; Tape Pass 1 Error Log
|
||||
PTR2 = $00c1 ; Tape Pass 2 Error Log
|
||||
RIDATA = $00c2 ; Cassette Temp (64#00AA) read flags: 0=scan, 1-15=count, $40=load, $80=end of tape marker
|
||||
RIPRTY = $00c3 ; Cassette Short Cnt (64#00AB): counter of seconds before tape write / checksum
|
||||
PNT = $00c4 ; Pointer: Current Screen Line Address
|
||||
PNTR = $00c6 ; Cursor Column on Current Line
|
||||
SAL = $00c7 ; Pointer: Tape Buffer/ Screen Scrolling
|
||||
EAL = $00c9 ; Tape End Addresses/End of Program
|
||||
CMP0 = $00cb ; Tape Timing Constants
|
||||
QTSW = $00cd ; Flag: Editor in Quote Mode, $00 = NO
|
||||
BITTS = $00ce ; Cassette Temp (64#00B4): Tape read timer flag
|
||||
FNLEN = $00d1 ; Length of Current File Name
|
||||
LA = $00d2 ; Current Logical File Number
|
||||
SA = $00d3 ; Current Secondary Address
|
||||
FA = $00d4 ; Current Device Number
|
||||
LNMX = $00d5 ; Physical Screen Line Length
|
||||
TAPE1 = $00d6 ; Pointer: Start of Tape Buffer
|
||||
TBLX = $00d8 ; Current Cursor Physical Line Number
|
||||
DATAX = $00d9 ; Current Character to Print
|
||||
FNADR = $00da ; Pointer: Current File Name
|
||||
INSRT = $00dc ; Flag: Insert Mode, >0 = # INSTs
|
||||
ROPRTY = $00dd ; Cassette Temp
|
||||
FSBLK = $00de ; Cassette Read / Write Block Count
|
||||
MYCH = $00df ; Serial Word Buffer
|
||||
LDTB1 = $00e0 ; 3+4.40: Screen Line Link Table / Editor Temps
|
||||
SCTOP = $00e0 ; 4.80: first line of window
|
||||
SCBOT = $00e1 ; 4.80: last line of window
|
||||
SCLF = $00e2 ; 4.80: first column of window
|
||||
XMAX = $00e3 ; 4.80: Size of Keyboard Buffer
|
||||
;XMAX = $03eb ; 4.40
|
||||
RPTFLG = $00e4 ; 4.80: Flag: REPEAT Key Used, $80 = Repeat $40 = disable
|
||||
;RPTFLG = $03ee ; 4.40
|
||||
KOUNT = $00e5 ; 4.80: Repeat Speed Counter
|
||||
;KOUNT = $03ea ; 4.40
|
||||
DELAY = $00e6 ; 230 4.80: Repeat Delay Counter
|
||||
;DELAY = $03e9 ; 4.40
|
||||
CAS1 = $00f9 ; Tape Motor Interlock #1
|
||||
CAS2 = $00fa ; Tape Motor Interlock #2
|
||||
STAL = $00fb ; I/O Start Address
|
||||
MEMUSS = $00fd ; Tape Load Temps
|
||||
BAD = $0100 ; Tape Input Error Log
|
||||
BUF = $0200 ; System INPUT Buffer
|
||||
LAT = $0251 ; KERNAL Table: Active Logical File No's.
|
||||
FAT = $025b ; KERNAL Table: Device No. for Each File
|
||||
SAT = $0265 ; KERNAL Table: Second Address Each File
|
||||
KEYD = $0270 ; Keyboard Buffer Queue (FIFO)
|
||||
TBUFFR = $027a ; Tape I/O Buffer #1
|
||||
;TBUFFR = $033a ; Tape I/O Buffer #2
|
||||
;DELAY = $03e9 ; 4.40
|
||||
;KOUNT = $03ea ; 4.40
|
||||
;XMAX = $03eb ; 4.40
|
||||
;RPTFLG = $03ee ; 4.40
|
||||
TIMOUT = $03fc ; 4: Flag: Kernal Variable for IEEE Timeout
|
||||
|
||||
; Kernel
|
||||
|
||||
; CHKIN = $ffc6
|
||||
; CHKOUT = $ffc9
|
||||
; CHRIN = $ffcf
|
||||
; CHROUT = $ffd2
|
||||
; CLALL = $ffe7
|
||||
; CLOSE = $ffc3
|
||||
; CLRCHN = $ffcc
|
||||
; CSYS = $ffde
|
||||
; CVERF = $ffdb
|
||||
; GETIN = $ffe4
|
||||
; LOAD = $ffd5
|
||||
; OPEN = $ffc0
|
||||
; SAVE = $ffd0
|
||||
; STOP = $ffe1
|
||||
; UDTIM = $ffea
|
||||
|
||||
;CONSTANTS FROM PET BASIC 4.0
|
||||
CLRCHN =$FFCC ;CLOSE I/O CHANNELS
|
||||
CHKIN =$FFC6 ;OPEN INPUT CHANNEL
|
||||
CHRIN =$FFCF ;INPUT SOURCE BYTE
|
||||
CHROUT =$FFD2 ;OUTPUT CHARACTER TO CHAN
|
||||
CLOSE =$F2E2 ;CLOSE FILE .A
|
||||
OPEN =$F563 ;OPEN FILE LA,FA,SA
|
||||
|
||||
.pron
|
||||
|
||||
; vim: syntax=64tass
|
|
@ -0,0 +1,585 @@
|
|||
;
|
||||
; Commodore Plus 4 specific constants and memory addresses
|
||||
;
|
||||
.proff
|
||||
|
||||
.cpu "6502"
|
||||
|
||||
io .namespace
|
||||
|
||||
.include "ted.asm"
|
||||
|
||||
.virtual $ff00
|
||||
ted .dstruct _ted
|
||||
.endvirtual
|
||||
|
||||
.endnamespace
|
||||
|
||||
BASIC_START = $1001
|
||||
BTOK_SYS = $9e
|
||||
SCREEN_RAM = $0c00
|
||||
|
||||
; ===========================================================================
|
||||
|
||||
PDIR = $0000 ; 7501 on-chip data-direction register
|
||||
PORT = $0001 ; 7501 on-chip 8-bit Input/Output register
|
||||
SRCHTK = $0002 ; Token 'search' looks for (run-time stack)
|
||||
ZPVEC1 = $0003 ; Temp (renumber)
|
||||
ZPVEC2 = $0005 ; Temp (renumber)
|
||||
CHARAC = $0007 ; Search character
|
||||
ENDCHR = $0008 ; Flag: scan for quote at end of string
|
||||
TRMPOS = $0009 ; Screen column from last TAB
|
||||
VERCK = $000A ; Flag: 0 = load 1 - verify
|
||||
COUNT = $000B ; Input buffer pointer / No. of subsctipts
|
||||
DIMFLG = $000C ; Flag: Default Array DIMension
|
||||
VALTYP = $000D ; Data type: $FF = string $00 = numeric
|
||||
INTFLG = $000E ; Data type: $80 = integer, $00 = floating
|
||||
DORES = $000F ; Flag: DATA scan/LIST quote/garbage coll
|
||||
SUBFLG = $0010 ; Flag: subscript ref / user function coll
|
||||
INPFLG = $0011 ; Flag: $00 = INPUT, $43 = GET, $98 = READ
|
||||
TANSGN = $0012 ; Flag TAN siqn / comparison result
|
||||
CHANNL = $0013 ; Flag: INPUT prompt
|
||||
LINNUM = $0014 ; Temp: integer value
|
||||
TEMPPT = $0016 ; Pointer: temporary string stack
|
||||
LASTPT = $0317 ; Last temp string address
|
||||
TEMPST = $0019 ; Stack for temporary strings
|
||||
INDEX1 = $0022 ; Utility pointer area
|
||||
INDEX2 = $0024 ; Utility pointer area
|
||||
RESHO = $0026 ;
|
||||
RESMOH = $0027 ;
|
||||
RESMO = $0028 ;
|
||||
RESLO = $0029 ;
|
||||
TXTTAB = $002B ; Pointer: start of BASIC text
|
||||
VARTAB = $002D ; Pointer: start of BASIC variables
|
||||
ARYTAB = $002E ; Pointer: start of BASIC arrays
|
||||
STREND = $0031 ; Pointer: end of BASIC arrays (+1)
|
||||
FRFTOP = $0033 ; Pointer: bottom of string storage
|
||||
FRESPC = $0035 ; Utility string pointer
|
||||
MEMSIZ = $0037 ; Pointer: highest address used by BASIC
|
||||
CURLIN = $0039 ; Current BASIC line number
|
||||
TXTPTR = $003B ;
|
||||
FNDPNT = $003D ;
|
||||
DATLIN = $003F ; Current DATA line number
|
||||
DATPTR = $0041 ; Pointer: Current DATA item address
|
||||
INPPTR = $0043 ; Vector: INPUT routine
|
||||
VARNAM = $0045 ; Current BASIC variable name
|
||||
VARPNT = $0047 ; Pointer: Current BASIC variable data
|
||||
FORPNT = $0049 ; Pointer: Index variable for FOR/NEXT
|
||||
OPPTR = $0048 ;
|
||||
OPMASK = $004D ;
|
||||
DEFPNT = $004E ;
|
||||
DSCPNT = $0050 ;
|
||||
HELPER = $0053 ;
|
||||
JMPER = $0054 ;
|
||||
SIZE = $0055 ;
|
||||
OLDOV = $0056 ;
|
||||
TEMPF1 = $0057 ;
|
||||
HIGHDS = $0058 ;
|
||||
HIGHTR = $005A ;
|
||||
LOWDS = $005D ;
|
||||
LoWTR = $005F ;
|
||||
EXPSGN = $0060 ;
|
||||
FACEXP = $0061 ; Floating-point accumulator #1: exponent
|
||||
FACHO = $0062 ; Floating accum. #1: mantissa
|
||||
FACMOH = $0063 ;
|
||||
FACMO = $0064 ;
|
||||
FACLo = $0065 ;
|
||||
FACSGN = $0066 ; Floating accum. #1: sign
|
||||
SGNFLG = $0067 ; Pointer: series evaluation constant
|
||||
BITS = $0068 ; Floating accum. #1: overflow digit
|
||||
ARGEXP = $0069 ; Floating-point accumulator #2: exponent
|
||||
ARGHO = $006A ; Floating accum. #2: mantissa
|
||||
ARGMOH = $006B ;
|
||||
ARGMO = $006C ;
|
||||
ARGLO = $006D ;
|
||||
ARGSGN = $006E ; Floating accum. #2: sign
|
||||
ARISGN = $006F ; Sign comparison result: accum. #1 vs #2
|
||||
FACOV = $0070 ; Floating accum. #1. low-order (rounding)
|
||||
FBUFPT = $0071 ; Pointer: cassette buffer
|
||||
AUTINC = $0073 ; Increment value for auto (0 = off)
|
||||
MVDFLG = $0075 ; Flag if 10K hires allocated
|
||||
KEYNUM = $0076 ;
|
||||
KEYSIZ = $0077 ;
|
||||
SYNTMP = $0078 ; Used as temp Eor indirect loads
|
||||
DSDESC = $0079 ; Descriptor for DSS
|
||||
TOS = $007C ; Top of run time stack
|
||||
TMPTON = $007E ; Temps used by music (tone & volume)
|
||||
VOICNO = $0080 ;
|
||||
RUNMOD = $0081 ;
|
||||
POINT = $0082 ;
|
||||
GRAPHM = $0083 ; Current graphic mode
|
||||
COLSEL = $0084 ; Current color selected
|
||||
MC1 = $0085 ; Multicolor 1
|
||||
FG = $0086 ; Foreground color
|
||||
SCXMAX = $0087 ; Maximum # of columns
|
||||
SCYMAX = $0088 ; Maximum # of rows
|
||||
LTFLAG = $0089 ; Paint-left flag
|
||||
RTFLAG = $008A ; Paint-Right flag
|
||||
STOPNH = $008B ; Stop paint if not BG (Not same Color)
|
||||
GRAPNT = $008C ;
|
||||
VTEMP1 = $008E ;
|
||||
VTEMP2 = $008F ;
|
||||
STATUS = $0090 ; Kernal I/O status word: ST
|
||||
STREY = $0091 ; Flag: STOP key / RVS key
|
||||
SPVERR = $0092 ; Temp
|
||||
VERFCK = $0093 ; Flag: 0 = load, 1 = verify
|
||||
C3PO = $0094 ; Plag: serial bus - output char buffered
|
||||
BSOUR = $0095 ; Buffered character for serial bus
|
||||
XSAV = $0096 ; Temp for basin
|
||||
LDTND = $0097 ; # of open files / index to file table
|
||||
DFLTN = $0098 ; Default input device (0)
|
||||
DFLTO = $0099 ; Default output (CMD) device (3)
|
||||
MSGFLG = $009A ; Flag: $80 = direct mode $00 = program
|
||||
SAL = $009B ; Tape pass 1 error log
|
||||
SAH = $009C ; Tape pass 2 error log
|
||||
EAL = $009D ;
|
||||
EAH = $009E ;
|
||||
T1 = $009F ; Temp data area
|
||||
T2 = $00A1 ; Temp data area
|
||||
TIME = $00A3 ; Real-time jiffy clock (approx) 1/60 sec
|
||||
R2D2 = $00A6 ; Serial bus usage (EOI on output)
|
||||
TPBYTE = $00A7 ; Byte to be written/read on/off tape
|
||||
BSOUR1 = $00A8 ; Temp used by serial routine
|
||||
FPVERR = $00A9 ;
|
||||
DCOUNT = $00AA ;
|
||||
FNLEN = $00A8 ; Length of current file name
|
||||
LA = $00AC ; Current logical fiie number
|
||||
SA = $00AD ; Current seconda.y address
|
||||
FA = $00AE ; Current device number
|
||||
FNADR = $00AF ; Pointer: current file name
|
||||
ERRSUM = $00B1 ;
|
||||
STAL = $00B2 ; I/O start address
|
||||
STAH = $00B3 ;
|
||||
MEMUSS = $00B4 ; Load ram base
|
||||
TAPEBS = $00B6 ; Base pointer to cassette base
|
||||
TMP2 = $00B8 ;
|
||||
WRBASE = $00BA ; Pointer to data for tape writes
|
||||
IMPARM = $00BC ; Pointer to immediate string for primms
|
||||
FETPTR = $00BE ; Pointer to byte to be fetched in bank fetc
|
||||
SEDSAL = $00C0 ; Temp for scrolling
|
||||
RVS = $00C2 ; RVS field flag on
|
||||
INDX = $00C3 ;
|
||||
LSXP = $00C4 ; X position at start
|
||||
LSTP = $00C5 ;
|
||||
SFDX = $00C6 ; Flag: shift mode for print
|
||||
CRSW = $00C7 ; Flag: INPUT or GET from keyboard
|
||||
PNT = $00C8 ; Pointer: current screen line address
|
||||
PNTR = $00CA ; Cursor column on current line
|
||||
QTSW = $00CB ; Flag: editor in quote mode, $00 = no
|
||||
SEDT1 = $00CC ; Editor temp use
|
||||
TBLX = $00CD ; Current cursor physical line number
|
||||
DATAX = $00CE ; Temp data area
|
||||
INSRT = $00CF ; Flag: insert mode, >0 = # INSTs
|
||||
CIRSEG = $00E9 ; Screen line link table / editor temps
|
||||
USER = $00EA ; Screen editor color IP
|
||||
KEYTAB = $00EC ; Key scan table indirect
|
||||
TMPKEY = $00EE ;
|
||||
NDX = $00EF ; Index to keyboard queue
|
||||
STPFLG = $00F0 ; Pause flag
|
||||
TO = $00F1 ; Monitor ZP storage
|
||||
CHRPTR = $00F3 ;
|
||||
BUFEND = $00F4 ;
|
||||
CHKSUM = $00F5 ; Temp for checksum calculation
|
||||
LENGTH = $00F6 ;
|
||||
PASS = $00F7 ; Which pass we are doing str
|
||||
TYPE = $00F8 ; Type of block
|
||||
USE4DY = $00F9 ; (B.7 = 1)=> for wr, (B.6 = 1)=> for rd
|
||||
XSTOP = $00FA ; Save xreg for quick stopkey test
|
||||
CURBNK = $00FB ; Current bank configuration
|
||||
XoN = $00FC ; Char to send for a x-on (RS232)
|
||||
XoFF = $00FD ; Char to send for a x-off (RS232)
|
||||
SEDT2 = $00FE ; Editor temporary use
|
||||
LOFBUF = $00FF ;
|
||||
|
||||
|
||||
FBUFFR = $0100 ;
|
||||
SAVEA = $0110 ; Temp Locations for
|
||||
SAVEY = $0111 ; ... for Save and
|
||||
SAVEX = $0112 ; ... Restore
|
||||
COLKEY = $0113 ; Color/luminance table in RAM
|
||||
SYSSTK = $0124 ; System stack
|
||||
BUF = $0200 ; Basic/monitor input buffer
|
||||
OLDLIN = $0259 ; Basic storage
|
||||
OLDTXT = $025B ; Basic storage
|
||||
XCNT = $025D ; DOS loop counter
|
||||
PNBUFR = $025E ; Area for filename
|
||||
DOSF1L = $026E ; DOS filename 1 length
|
||||
DOSDS1 = $026F ; DOS disk drive 1
|
||||
DOSF1A = $0270 ; DOS filename 1 addr
|
||||
DOSF2L = $0272 ; DOS filename 2 length
|
||||
DOSDS2 = $0273 ; DOS disk drive 2
|
||||
DOSF2A = $0274 ; DOS filename 2 addr
|
||||
DOSLA = $0276 ; DOS logical address
|
||||
DOSEA = $0277 ; DOS phys addr
|
||||
DOSSA = $0278 ; DOS secordary address
|
||||
DOSDID = $0279 ; DOS disk identifier
|
||||
DIDCHK = $0278 ; DOS DID flag
|
||||
DOSSTR = $027C ; DOS output string buffer
|
||||
DOSSPC = $027D ; Area used to build DOS string
|
||||
|
||||
XPOS = $02AD ; Current x position
|
||||
YPOS = $02AE ; Current y position
|
||||
XDEST = $02B1 ; X coordinate destination
|
||||
YDEST = $02B3 ; Y coordinate destination
|
||||
XABS = $02B5 ;
|
||||
YABS = $02B7 ;
|
||||
XSGN = $02B9 ;
|
||||
YSGN = $02BB ;
|
||||
FCT1 = $02BD ;
|
||||
FCT2 = $02BF ;
|
||||
ERRVAL = $02C1 ;
|
||||
LESSER = $02C3 ;
|
||||
GREATR = $02C4 ;
|
||||
ANGSGN = $02C5 ; Sign of angle
|
||||
SINVAL = $02C6 ; Sine of value of angle
|
||||
COSVAL = $02C8 ; Cosine of value of angle
|
||||
ANGCNT = $02CA ; Temps for angle distance routines
|
||||
|
||||
BNR = $02CD ; Pointer to begin no.
|
||||
ENR = $02CE ; Pointer to end no.
|
||||
DOLR = $02CF ; Dollar flag
|
||||
FLAG = $02D0 ; Comma flag
|
||||
SWE = $02D1 ; Counter
|
||||
USGN = $02D2 ; Sign exponent
|
||||
UEXP = $02D3 ; Pointer to exponent
|
||||
VN = $02D4 ; # of digits before decimal point
|
||||
CHSN = $02D5 ; Justify flag
|
||||
VF = $02D6 ; # of pos before decimal point (field)
|
||||
NF = $02D7 ; # of pos after decimal point (field)
|
||||
POSP = $02D8 ; +/- flag (field)
|
||||
FESP = $02D9 ; Exponent flag (field)
|
||||
ETOF = $02DA ; Switch
|
||||
CFORM = $02D8 ; Char counter (field)
|
||||
SNO = $02DC ; Sign no.
|
||||
BLFD = $02DD ; Blank/star flag
|
||||
BEGFD = $02DE ; Pointer to beginning of field
|
||||
LFOR = $02DF ; Length of format
|
||||
ENDFD = $02E0 ; Pointer to end of field
|
||||
|
||||
XCENTR = $02CC
|
||||
YCENTR = $02CE
|
||||
XDIST1 = $02D0
|
||||
YDIST1 = $02D2
|
||||
XDIST2 = $02D4
|
||||
YDIST2 = $02D6
|
||||
|
||||
COLCNT = $02DA ; Characters column counter
|
||||
ROWCNT = $02DB ; Characters row counter
|
||||
STRCNT = $02DC
|
||||
|
||||
|
||||
XCORD1 = $02CC
|
||||
YCORD1 = $02CE
|
||||
BOXANG = $02D0 ; Rotation angle
|
||||
XCOUNT = $02D2
|
||||
YCOUNT = $02D4
|
||||
BXLENG = $02D6 ; Length of a side
|
||||
XCORD2 = $02D8
|
||||
YCORD2 = $02DA
|
||||
|
||||
XCIRCL = $02CC ; Circle center, x coordinate
|
||||
YCIRCL = $02CE ; Circle center, y coordinate
|
||||
XRADUS = $02D0 ; X radius
|
||||
YRADUS = $02D2 ; Y radius
|
||||
ROTANG = $02D4 ; Rotation angle
|
||||
ANGBEG = $02D8 ; Arc angle start
|
||||
ANGEND = $02DA ; Arc angle end
|
||||
XRCOS = $02DC ; X radius * cos (rotation angle)
|
||||
YRSIN = $02DE ; Y radius * sin (rotation angle)
|
||||
XRSIN = $02E0 ; X radius * sin (rotation angle)
|
||||
YRCOS = $02E2 ; Y radius * cos (rotation angle)
|
||||
|
||||
|
||||
KEYLEN = $02CD
|
||||
KEYNXT = $02CE
|
||||
STRS2 = $02CE ; String length
|
||||
GETTYP = $02D0 ; Replace string mode
|
||||
STRPTR = $02D1 ; String position counter
|
||||
OLDBYT = $02D2 ; Old bit map byte
|
||||
NEWBYT = $02D3 ; New string or bit map byte
|
||||
XSIZE = $02D5 ; Shape column length
|
||||
YSIZE = $02D7 ; Shape row length
|
||||
XSAVE = $02D9 ; Temp for column length
|
||||
STRADR = $02D8 ; Save shape string descriptor
|
||||
BITIDX = $02DD ; Bit index into byte
|
||||
SAYSIZ = $02DE ; Temporary work locations
|
||||
|
||||
CHRPAG = $02E4 ; High byte addr of char ROM for char cmd
|
||||
LITCNT = $02E5 ; Temp for gshape
|
||||
SCALEM = $02E6 ; Scale mode flag
|
||||
WIDTH = $02E7 ; Double width flag
|
||||
FILFLG = $02E8 ; Box fill flag
|
||||
BITMSK = $02E9 ; Temp for bit mask
|
||||
NUMCNT = $02EA
|
||||
TRCFLG = $02EB ; Flags trace mode
|
||||
|
||||
T3 = $02EC
|
||||
T4 = $02ED
|
||||
VTEMP3 = $02EF ; Graphic temp storage
|
||||
VTEMP4 = $02F0
|
||||
VTEMP5 = $02F1
|
||||
|
||||
ADRAY1 = $02E2 ; Ptr to routine: convert float to integer
|
||||
ADRAY2 = $02F4 ; Ptr to routine: convert integer to float
|
||||
|
||||
BNKVEC = $02FE ; Vector for function cartridge users
|
||||
IERROR = $0300 ; Indirect Error (Output Error in .X)
|
||||
IMAIN = $0302 ; Indirect Main (System Direct Loop)
|
||||
ICRNCH = $0304 ; Indirect Crunch (Tokenization Routine)
|
||||
IOPLOP = $0306 ; Indirect List (Char List)
|
||||
IGONE = $0308 ; Indirect Gone (Character Dispatch)
|
||||
IEVAL = $030A ; Indirect Eval (Symbol Evaluation)
|
||||
IESCLK = $030C ; Escape token crunch
|
||||
IESCPR = $030E ;
|
||||
IESCEX = $0310 ;
|
||||
ITIME = $0312 ;
|
||||
CINV = $0314 ; IRQ Ram Vector
|
||||
CBINV = $0316 ; BRK Instr RAM Vector
|
||||
IOPEN = $0318 ; Indirects for Code
|
||||
ICLOSE = $031A ;
|
||||
ICHKIN = $031C ;
|
||||
ICKOUT = $031E ;
|
||||
ICLRCH = $0320 ;
|
||||
IBASIN = $0322 ;
|
||||
IBSOUT = $0324 ;
|
||||
ISTOP = $0326 ;
|
||||
IGETIN = $0328 ;
|
||||
ICLALL = $032A ;
|
||||
USRCMD = $032C ;
|
||||
ILOAD = $032E ;
|
||||
ISAVE = $0330 ; Savesp
|
||||
|
||||
TAPBUF = $0333 ; Cassette tape buffer
|
||||
WRLEN = $03F3 ; Length of data to be written to tape
|
||||
RDCNT = $03F5 ; Length of data to be read from tape
|
||||
INPQUE = $03F7 ; RS-232 input queue
|
||||
ESTARL = $0437
|
||||
ESTAKH = $0455
|
||||
|
||||
CHRGET = $0473
|
||||
CHRGOT = $0479
|
||||
QNUM = $0485
|
||||
|
||||
INDSUB = $0494 ; Shared ROM fetch sub
|
||||
ZERO = $04A2 ; Numeric constant for Basic
|
||||
|
||||
INDTXT = $04A5 ; Txtptr
|
||||
INDIN1 = $04B0 ; Index & Index1
|
||||
INDIN2 = $04BB ; Index2
|
||||
INDST1 = $04C6 ; Strng1
|
||||
INDLOW = $04D1 ; Lowtr
|
||||
INDFMO = $04DC ; Facmo
|
||||
|
||||
PUFILL = $04E7 ; Print using fill symbol [space]
|
||||
PUCOMA = $04E8 ; Print using comma symbol [;]
|
||||
PUDOT = $04E9 ; Print using D.P. symbol [.]
|
||||
PUMONY = $04EA ; Print using monetary symbol [$]
|
||||
|
||||
TMPDES = $04EB ; Temp for instr
|
||||
ERRNUM = $04EF ; Last error number
|
||||
ERRLIN = $04F0 ; Line # of last error
|
||||
TRAPNO = $04F2 ; Line to go on error
|
||||
TMPTRP = $04F4 ; Hold trap no. temporarily
|
||||
ERRTXT = $04F5
|
||||
OLDSTR = $04F7
|
||||
|
||||
TMPTXT = $04F8
|
||||
TMPLIN = $04FA
|
||||
|
||||
MTIMLO = $04FC ; Table of pending jiffies (2's comp)
|
||||
MTIMHI = $04FE
|
||||
USRPOK = $0500
|
||||
KERNDX = $0503
|
||||
DEJAVU = $0508 ; 'cold' or 'warm' start status
|
||||
|
||||
LAT = $0509 ; Logical file numbers
|
||||
FAT = $0513 ; Primary device numbers
|
||||
SAT = $051D ; Secondary addresses
|
||||
|
||||
KEYD = $0527 ; IRQ keyboard buffer
|
||||
MEMSTR = $0531 ; Start of memory [1000]
|
||||
|
||||
MSIZ = $0533 ; Top of memory [FD00]
|
||||
TIMOUT = $0535 ; IEEE timeout flag
|
||||
|
||||
FILEND = $0536 ; File end reached = 1, 0 otherwise
|
||||
CTALLY = $0537 ; # of chars left in buffer (for R & W)
|
||||
CBUFVA = $0538 ; # of total valid chars in buffer (R)
|
||||
TPTR = $0539 ; Ptr to next char in buffer (for R & W)
|
||||
FLTYPE = $053A ; Contains type of current cass file
|
||||
|
||||
COLOR = $053B ; Active attribute byte
|
||||
FLASH = $053C ; Character flash flag
|
||||
HIBASE = $053E ; OC Base location of screen (top) [0C]
|
||||
XMAX = $053F ;
|
||||
RPTFLG = $0540 ; Key repeat flag
|
||||
KOUUT = $0541 ;
|
||||
DELAY = $0542 ;
|
||||
SHFLAG = $0543 ; Shift flag byte
|
||||
LSTSHF = $0544 ; Last shift pattern
|
||||
KEYLOG = $0545 ; Indirect for keyboard table setup
|
||||
MODE = $0547 ; shift, C=
|
||||
AUTODN = $0548 ; Auto scroll down flag (0=on,0off)
|
||||
LINTMP = $0549
|
||||
ROLFLG = $054A
|
||||
|
||||
FORMAT = $054B ; Monitor non-zpage storage
|
||||
MSAL = $054C
|
||||
WRAP = $054F
|
||||
TMPC = $0550
|
||||
DIFF = $0551
|
||||
PCH = $0552
|
||||
PCL = $0553
|
||||
FLGS = $0554
|
||||
ACC = $0555
|
||||
XR = $0556
|
||||
YR = $0557
|
||||
SP = $0558
|
||||
INYL = $0559
|
||||
INVH = $055A
|
||||
CMPFLG = $055B ; Used by various monitor routines
|
||||
BAD = $055C
|
||||
|
||||
KYNDX = $055D ; Used for programmable keys
|
||||
KEYIDX = $055E ;
|
||||
KEYBUF = $055F ; Table of P.F. lengths
|
||||
PKY9UF = $0567 ; P.F. Key storage area
|
||||
|
||||
KDATA = $05E7 ; Temp for data write to kennedy
|
||||
RDYCMD = $05E8 ; Select for kennedy read or write
|
||||
KDYNUM = $05E9 ; Kennedy's dev #
|
||||
RDYPRS = $05EA ; Rennedy present = $ff, else = $00
|
||||
KDYTYP = $05EB ; Temp for type of open for kennedy
|
||||
|
||||
|
||||
SAVRAM = $05EC ; 1 page used by banking routines
|
||||
PAT = $05EC ; Physical Address Table
|
||||
LNGJMP = $05F0 ; Long jump address
|
||||
FETARG = $05F2 ; Long jump accumulator
|
||||
FETXRG = $05F3 ; Long jump x register
|
||||
FETSRG = $05F4 ; Long jump status register
|
||||
|
||||
AREAS = $05F5 ; RAM areas for banking
|
||||
|
||||
ASPECH = $065E ; RAM area for speech
|
||||
|
||||
STKTOP = $06EC ; BASIC run-time stack
|
||||
|
||||
WROUT = $07B0 ; Byte to be written on tape
|
||||
PARITY = $07B1 ; Temp for parity calc
|
||||
|
||||
TT1 = $07B2 ; Temp for write-header
|
||||
TT2 = $07B3 ; Temp for write-header
|
||||
RDBITS = $07B5 ; Local index for READBYTE routine
|
||||
ERRSP = $07B6 ; Pointer into the error stack
|
||||
FPERRS = $07B7 ; Number of first pass errors
|
||||
|
||||
DSAMP1 = $07B8 ; Time constant
|
||||
DSAMP2 = $07BA ; Time constant
|
||||
ZCELL = $07BC ; Time constant
|
||||
|
||||
SRECOV = $07BE ; Stack marker for stopkey recover
|
||||
DRECOV = $07BF ; Stack marker for dropkey recover
|
||||
TRSAVE = $07C0 ; params passed to RDBLOK
|
||||
RDETMP = $07C4 ; Temp stat save for RDBLOK
|
||||
LDRSCN = $07C5 ; # consec shorts to find in leader
|
||||
CDERRM = $07C6 ; # Errors fatal in RD countdown
|
||||
VSAVE = $07C7 ; Temp for Verify command
|
||||
T1PIPE = $07C8 ; Pipe temp for T1
|
||||
ENEXT = $07CC ; Read error propagate
|
||||
|
||||
|
||||
UOUTQ = $07CD ; User chracter to send
|
||||
UOUTFG = $07CE ; 0 = empty ; 1 = full
|
||||
SOUT9 = $07CF ; System character to send
|
||||
SOUNFG = $07D0 ; 0 = empty ; 1 = full
|
||||
INOFPT = $07D1 ; Pntr to front of input queue
|
||||
INQRPT = $07D2 ; Pntr to rear of input queue
|
||||
INQCNT = $07D3 ; # of chars in input queue
|
||||
ASTAT = $07D4 ; Temp status for ACIA
|
||||
AINTMP = $07D5 ; Temp for input routine
|
||||
ALSTOP = $07D6 ; FLG for local pause
|
||||
ARSTOP = $07D7 ; FLG for remote pause
|
||||
APRES = $07D8 ; FLG to indicate presence of ACIA
|
||||
|
||||
RLUDES = $07D9 ; Indirect routine downloaded
|
||||
SCBOT = $07E5 ; Screen bottom (0...24)
|
||||
SCTOP = $07E6 ; Screen top
|
||||
SCLF = $07E7 ; Screen left (0...39)
|
||||
SCRT = $07E8 ; Screen right
|
||||
SCRDIS = $07E9 ; Negative = scroll out
|
||||
INSFLG = $07EA ; Insert mode: FF = on, 00 = off
|
||||
LSTCHR = $07EB
|
||||
LOGSCR = $07EC
|
||||
TCOLOR = $07ED
|
||||
BITABL = $07EE
|
||||
|
||||
SAREG = $07F2 ; Registers for SYS command
|
||||
SXREG = $07F3
|
||||
SYREG = $07F4
|
||||
SPREG = $07F5
|
||||
|
||||
LSTX = $07F6 ; Key scan index
|
||||
STPDSB = $07F7 ; Flag to disable CTRL-S pause
|
||||
RAMROM = $07F8 ; MSB for monitor fetches from ROM=0;RAM=1
|
||||
|
||||
COLSW = $07F9 ; MSB for color/lim table in RAM=0;ROM=1
|
||||
FFRMSK = $07FA ; ROM mask for split screen
|
||||
VMBMSK = $07FB ; VM base mask for split screen
|
||||
LSEM = $07FC ; Motor lock semaphore for cassette
|
||||
PALCNT = $07FD ; PAL tod
|
||||
|
||||
|
||||
TEDATR = $0800 ; TED attribute bytes
|
||||
TEDSCN = $0C00 ; TED character pointers
|
||||
BASBGN = $1000 ; Start of BASIC text area
|
||||
BMLUM = $1800 ; Luminance for bit map screen
|
||||
BMCOLR = $1C00 ; Color for bit map
|
||||
|
||||
; KERNAL JUMP TABLE
|
||||
|
||||
CINT = $ff81 ; Initialize screen editor
|
||||
IOINIT = $ff84 ; Initialize I/O devices
|
||||
RAMTAS = $ff87 ; Ram test
|
||||
RESTOR = $ff8a ; Restore vectors to initial values
|
||||
VECTOR = $ff8d ; Change vectors for user
|
||||
SETMSG = $ff90 ; Control O.S. messages
|
||||
SECND = $ff93 ; Send SA after LISTEN
|
||||
TKSA = $ff96 ; Send SA after TALK
|
||||
MEMTOP = $ff99 ; Set/Read top of memory
|
||||
MEMBOT = $ff9c ; Set/Read bottom of memory
|
||||
SCNKEY = $ff9f ; Scan keyboard
|
||||
SETTMO = $ffa2 ; Set timeout in DMA disk
|
||||
ACPTR = $ffa5 ; Handshake serial bus or DMA disk byte in
|
||||
CIoUT = $ffa8 ; Handshake serial bus or DMA disk byte out
|
||||
UNTLR = $ffab ; Send UNTALK out serial bus or DMA disk
|
||||
UNLSN = $ffae ; Send UNLISTEN out serial bus or DMA disk
|
||||
LISTN = $ffb1 ; Send LISTEN out serial bus or DMA disk
|
||||
TALK = $ffb4 ; Send TALK out serial bus or DMA disk
|
||||
READST = $ffb7 ; Return I/O STATUS byte
|
||||
SETLFS = $ffba ; Set LA, FA, SA
|
||||
SETNAM = $ffbd ; Set length and FN address
|
||||
OPEN = $ffc0 ; Open logical file
|
||||
CLOSE = $ffc3 ; Close logical file
|
||||
CHKIN = $ffc6 ; Open channel in
|
||||
CHOUT = $ffc9 ; open channel out
|
||||
CLRCHN = $ffcc ; Close I/O channels
|
||||
BASIN = $ffcf ; Input from channel
|
||||
CHRIN = BASIN
|
||||
BSOUT = $ffd2 ; output to channel
|
||||
CHROUT = BSOUT
|
||||
LOADSP = $ffd5 ; Load from file
|
||||
SAYESP = $ffd8 ; Save to file
|
||||
SETTIM = $ffdb ; Set internal clock
|
||||
RDTIM = $ffde ; Read internal clock
|
||||
STOP = $ffe1 ; Scan STOP key
|
||||
GETIN = $ffe4 ; Get character from queue
|
||||
CLALL = $ffe7 ; Close all files
|
||||
UDTIM = $ffea ; Increment clock
|
||||
SCRORG = $ffed ; Screen org.
|
||||
PLOT = $fff0 ; Read/Set X,Y coord of cursor
|
||||
IOBASE = $fff3 ; Return location of start of I/O
|
||||
|
||||
.pron
|
||||
|
||||
; vim: syntax=64tass
|
|
@ -0,0 +1,52 @@
|
|||
#!/bin/bash
|
||||
|
||||
X64="x64 -minimized +sound -warp -silent +saveres"
|
||||
PRG="chipty5-64.prg"
|
||||
|
||||
LBL=$(basename "$PRG" .prg).l
|
||||
|
||||
MONSCRIPT="load \"${PRG}\" 0\n
|
||||
load_labels \"${LBL}\"\n
|
||||
bload \"/tmp/c8test.ch8\" 0 .C8ENTRY\n
|
||||
break exec .oINV\n
|
||||
goto .MainEntry\n
|
||||
bsave \"/tmp/c8registers.bin\" 0 .reg:v .reg:st\n
|
||||
bsave \"/tmp/c8display.bin\" 0 .c8screen .c8screenend\n
|
||||
bsave \"/tmp/c8ram.bin\" 0 .C8RAM .c8ramend\n
|
||||
quit"
|
||||
|
||||
success () {
|
||||
echo "$(tput setaf 2)Ok$(tput sgr0)"
|
||||
}
|
||||
|
||||
failure () {
|
||||
echo "$(tput setaf 1)Failed $1$(tput sgr0)"
|
||||
exit 1
|
||||
}
|
||||
|
||||
if [ $# -gt 0 ] ; then
|
||||
TESTS="$@"
|
||||
else
|
||||
TESTS=$(find tests -mindepth 1 -maxdepth 1 -type f \
|
||||
-name "*.ch8asm" -printf "%f\\n" | sed 's/\.ch8asm$//g')
|
||||
fi
|
||||
|
||||
make $PRG
|
||||
|
||||
for testcase in $TESTS ; do
|
||||
echo -n "Running test case $testcase ... "
|
||||
cp tests/$testcase.ch8asm /tmp/c8test.ch8asm
|
||||
./ch8asm.py /tmp/c8test.ch8asm
|
||||
$X64 -initbreak ready -moncommand <(echo -e $MONSCRIPT) >/tmp/c8test.vice.log 2>&1
|
||||
if [ -f tests/$testcase.display.pbm ] ; then
|
||||
convert -size 64x32 -depth 1 gray:/tmp/c8display.bin -compress none -negate /tmp/c8display.pbm
|
||||
cmp -s /tmp/c8display.pbm tests/$testcase.display.pbm || failure "(display)"
|
||||
fi
|
||||
if [ -f tests/$testcase.registers.regex ] ; then
|
||||
grep -f tests/$testcase.registers.regex <(xxd -ps /tmp/c8registers.bin) >/dev/null || failure "(registers)"
|
||||
fi
|
||||
if [ -f tests/$testcase.ram.regex ] ; then
|
||||
grep -f tests/$testcase.ram.regex <(xxd -g1 /tmp/c8ram.bin) >/dev/null || failure "(ram)"
|
||||
fi
|
||||
success
|
||||
done
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,52 @@
|
|||
;
|
||||
; SID registers
|
||||
;
|
||||
|
||||
.virtual
|
||||
_sid .struct
|
||||
_sid_voice .struct
|
||||
freq .word ?
|
||||
duty .word ?
|
||||
ctrl .byte ?
|
||||
ad .byte ?
|
||||
sr .byte ?
|
||||
.endstruct
|
||||
voice1 .dstruct _sid_voice
|
||||
voice2 .dstruct _sid_voice
|
||||
voice3 .dstruct _sid_voice
|
||||
ffreq .word ?
|
||||
fres .byte ?
|
||||
volume .byte ?
|
||||
potx .byte ?
|
||||
poty .byte ?
|
||||
osc3 .byte ?
|
||||
env3 .byte ?
|
||||
.endstruct
|
||||
.endvirtual
|
||||
|
||||
PAL_CLOCK = 985248
|
||||
NTSC_CLOCK = 1022727
|
||||
|
||||
sid_freq .sfunction freq, clock=PAL_CLOCK, int(freq*16777216/clock)
|
||||
sid_duty .sfunction duty, int(duty*(1<<12))
|
||||
|
||||
SID_CTRL_NOISE = %1000_0000
|
||||
SID_CTRL_PULSE = %0100_0000
|
||||
SID_CTRL_SAWTOOTH = %0010_0000
|
||||
SID_CTRL_TRIANGLE = %0001_0000
|
||||
SID_CTRL_TEST = %0000_1000
|
||||
SID_CTRL_RING = %0000_0100
|
||||
SID_CTRL_SYNC = %0000_0010
|
||||
SID_CTRL_GATE = %0000_0001
|
||||
|
||||
SID_RES_EXT = %0000_1000
|
||||
SID_RES_V3 = %0000_0100
|
||||
SID_RES_V2 = %0000_0010
|
||||
SID_RES_V1 = %0000_0001
|
||||
|
||||
SID_FILTER_MUTE3 = %1000_0000
|
||||
SID_FILTER_HIGHPASS = %0100_0000
|
||||
SID_FILTER_BANDPASS = %0010_0000
|
||||
SID_FILTER_LOWPASS = %0001_0000
|
||||
|
||||
; vim: syntax=64tass
|
|
@ -0,0 +1,43 @@
|
|||
;
|
||||
; TED registers
|
||||
;
|
||||
|
||||
.virtual
|
||||
_ted .struct
|
||||
timer1 .word ?
|
||||
timer2 .word ?
|
||||
timer3 .word ?
|
||||
vscroll .byte ?
|
||||
hscroll .byte ?
|
||||
kbdlatch .byte ?
|
||||
irr .byte ?
|
||||
imr .byte ?
|
||||
irq_rasterline .byte ?
|
||||
cursor_hi .byte ?
|
||||
cursor_lo .byte ?
|
||||
freq1 .byte ?
|
||||
freq2 .word ?
|
||||
snd_ctrl .byte ?
|
||||
misc .byte ?
|
||||
char_addr .byte ?
|
||||
video_addr .byte ?
|
||||
bgcolor .byte ?
|
||||
color1 .byte ?
|
||||
color2 .byte ?
|
||||
color3 .byte ?
|
||||
bordercolor .byte ?
|
||||
bmap_reload_hi .byte ?
|
||||
bmap_reload_lo .byte ?
|
||||
rasterline_hi .byte ?
|
||||
rasterline_lo .byte ?
|
||||
rastercolumn .byte ?
|
||||
cursor_blink .byte ?
|
||||
unused .fill 30
|
||||
enable_rom .byte ?
|
||||
enable_ram .byte ?
|
||||
.endstruct
|
||||
.endvirtual
|
||||
|
||||
ted_freq .sfunction freq, int(1024-111860.781/freq)
|
||||
|
||||
; vim: syntax=64tass
|
|
@ -0,0 +1,13 @@
|
|||
;
|
||||
; Description
|
||||
;
|
||||
|
||||
.section code
|
||||
|
||||
Hello .proc
|
||||
rts
|
||||
.endproc
|
||||
|
||||
.endsection code
|
||||
|
||||
; vim: syntax=64tass
|
|
@ -0,0 +1,36 @@
|
|||
;
|
||||
; Exercise ADD opcodes
|
||||
;
|
||||
|
||||
; preload some values
|
||||
LD Va, 12
|
||||
LD Vb, 34
|
||||
LD Vc, 12
|
||||
LD Vd, 89
|
||||
LD Ve, ff
|
||||
|
||||
LD V0, 01
|
||||
LD Vf, aa
|
||||
ADD V0, 11 ; ADD Vx, nn - no carry
|
||||
LD V1, Vf
|
||||
|
||||
LD V2, b6
|
||||
LD Vf, aa
|
||||
ADD V2, 7e ; ADD Vx, nn - carry
|
||||
LD V3, Vf
|
||||
|
||||
LD V4, 22
|
||||
LD Vf, aa
|
||||
ADD V4, Vb ; ADD Vx, Vy - no carry
|
||||
LD V5, Vf
|
||||
|
||||
LD V6, ef
|
||||
LD Vf, aa
|
||||
ADD V6, Vd ; ADD Vx, Vy - carry
|
||||
LD V7, Vf
|
||||
|
||||
LD I, 0f01
|
||||
ADD I, Ve
|
||||
|
||||
EXIT
|
||||
|
|
@ -0,0 +1 @@
|
|||
12aa34aa56007801....12341289ff010010......
|
|
@ -0,0 +1,12 @@
|
|||
;
|
||||
; BCD conversion test
|
||||
;
|
||||
|
||||
LD V0, 7b ; 123 (dec)
|
||||
LD V4, 0
|
||||
LD I, 400
|
||||
LD B, V0
|
||||
LD V2, [I]
|
||||
|
||||
EXIT
|
||||
|
|
@ -0,0 +1 @@
|
|||
00000400: 01 02 03
|
|
@ -0,0 +1 @@
|
|||
010203..........................0004......
|
|
@ -0,0 +1,37 @@
|
|||
;
|
||||
; Exercise bitwise opcodes
|
||||
;
|
||||
|
||||
; preload some values
|
||||
LD Va, 12
|
||||
LD Vb, 34
|
||||
LD Vc, 55
|
||||
LD Vd, aa
|
||||
LD Ve, f0
|
||||
|
||||
LD V0, 08
|
||||
OR V0, Va
|
||||
|
||||
LD V1, 51
|
||||
AND V1, Ve
|
||||
|
||||
LD V2, 65
|
||||
XOR V2, Vd
|
||||
|
||||
LD V3, 30
|
||||
SHL V3, Vc
|
||||
LD V4, Vf
|
||||
|
||||
LD V5, 50
|
||||
SHR V5, Vd
|
||||
LD V6, Vf
|
||||
|
||||
LD V7, 70
|
||||
SHL V7, Ve
|
||||
LD V8, Vf
|
||||
|
||||
LD V9, 90
|
||||
SHR V9, Vd
|
||||
|
||||
EXIT
|
||||
|
|
@ -0,0 +1 @@
|
|||
1a50cfaa005500e0012a1234aa2ae001..........
|
|
@ -0,0 +1,21 @@
|
|||
;
|
||||
; Exercise JP/CALL/RET
|
||||
;
|
||||
|
||||
LD V0, 9
|
||||
CALL sub1
|
||||
LD V2, 9
|
||||
CALL sub2
|
||||
LD V4, 9
|
||||
JP skip
|
||||
LD V4, 0
|
||||
skip LD V5, 9
|
||||
|
||||
EXIT
|
||||
|
||||
sub1 LD V1, 1
|
||||
RET
|
||||
|
||||
sub2 LD V3, 2
|
||||
RET
|
||||
|
|
@ -0,0 +1 @@
|
|||
090109020909..............................
|
|
@ -0,0 +1,21 @@
|
|||
;
|
||||
; Show built-in hex font
|
||||
;
|
||||
|
||||
SPRH = 5 ; Built-in fonts are 4x5
|
||||
|
||||
CLS
|
||||
LD V0, 00
|
||||
LD V1, V0
|
||||
LD V2, V0
|
||||
next LD F, V0
|
||||
DRW V1, V2, SPRH
|
||||
ADD V0, 01
|
||||
ADD V1, 08
|
||||
SE V1, 20
|
||||
JP next
|
||||
LD V1, 00
|
||||
ADD V2, 08
|
||||
SE V2, 20
|
||||
JP next
|
||||
EXIT
|
|
@ -0,0 +1,34 @@
|
|||
P1
|
||||
64 32
|
||||
1 1 1 1 0 0 0 0 0 0 1 0 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
1 0 0 1 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
1 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
1 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
1 1 1 1 0 0 0 0 0 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
1 0 0 1 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
1 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 1 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
1 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 1 0 0 1 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
1 1 1 1 0 0 0 0 1 1 1 0 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
1 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
1 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
1 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
1 1 1 1 0 0 0 0 1 1 1 0 0 0 0 0 1 1 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
|
@ -0,0 +1,17 @@
|
|||
;
|
||||
; Exercise LD opcodes
|
||||
;
|
||||
|
||||
LD V0, 55
|
||||
LD V1, V0
|
||||
LD V2, aa
|
||||
LD V3, V2
|
||||
LD I, 400
|
||||
LD [I], V3
|
||||
LD I, 404
|
||||
LD [I], V3
|
||||
LD I, 403
|
||||
LD V1, [I]
|
||||
|
||||
EXIT
|
||||
|
|
@ -0,0 +1 @@
|
|||
00000400: 55 55 aa aa 55 55 aa aa
|
|
@ -0,0 +1 @@
|
|||
aa55aaaa........................0304......
|
|
@ -0,0 +1 @@
|
|||
V0V1V2V3V4V5V6V7V8V9VaVbVcVdVeVf< I>spdtst
|
|
@ -0,0 +1,37 @@
|
|||
;
|
||||
; Exercise LD opcodes
|
||||
;
|
||||
|
||||
LD V0, 01
|
||||
SE V0, 01 ; SE Vx, nn - skip
|
||||
LD V0, 00
|
||||
LD V1, 00
|
||||
SE V1, 01 ; SE Vx, nn - no skip
|
||||
LD V1, 01
|
||||
LD V2, 01
|
||||
SNE V2, 00 ; SNE Vx, nn - skip
|
||||
LD V2, 00
|
||||
LD V3, 00
|
||||
SNE V3, 00 ; SNE Vx, nn - no skip
|
||||
LD V3, 01
|
||||
|
||||
; prepare for register based skips
|
||||
LD Va, 12
|
||||
LD Vb, 34
|
||||
LD Vc, 12
|
||||
|
||||
LD V4, 01
|
||||
SE Va, Vc ; SE Vx, Vy - skip
|
||||
LD V4, 00
|
||||
LD V5, 00
|
||||
SE Va, Vb ; SE Vx, Vy - no skip
|
||||
LD V5, 01
|
||||
LD V6, 01
|
||||
SNE Va, Vb ; SNE Vx, Vy - skip
|
||||
LD V6, 00
|
||||
LD V7, 00
|
||||
SNE Va, Vc ; SNE Vx, Vy - no skip
|
||||
LD V7, 01
|
||||
|
||||
EXIT
|
||||
|
|
@ -0,0 +1 @@
|
|||
0101010101010101..........................
|
|
@ -0,0 +1,86 @@
|
|||
;
|
||||
; Exercise sprite drawing and test collision behaviour
|
||||
;
|
||||
|
||||
SPRH = 8
|
||||
|
||||
CLS
|
||||
|
||||
LD V0, 00
|
||||
LD V1, 00
|
||||
LD I, .block
|
||||
DRW V0, V1, SPRH
|
||||
LD V2, Vf
|
||||
|
||||
LD V0, 3c
|
||||
LD V1, 00
|
||||
LD I, .square
|
||||
DRW V0, V1, SPRH
|
||||
LD V3, Vf
|
||||
|
||||
LD V0, 0a
|
||||
LD V1, 1c
|
||||
DRW V0, V1, SPRH
|
||||
LD V4, Vf
|
||||
|
||||
LD V0, 3c
|
||||
LD V1, 1c
|
||||
DRW V0, V1, SPRH
|
||||
LD V5, Vf
|
||||
|
||||
LD V0, 14
|
||||
LD V1, 2a
|
||||
LD I, .checker
|
||||
DRW V0, V1, SPRH
|
||||
LD V6, Vf
|
||||
|
||||
LD V0, 1e
|
||||
LD V1, 0a
|
||||
LD I, .block
|
||||
DRW V0, V1, SPRH
|
||||
LD V7, Vf
|
||||
|
||||
LD V0, 28
|
||||
LD V1, 0a
|
||||
LD I, .corners
|
||||
DRW V0, V1, SPRH
|
||||
LD V8, Vf
|
||||
|
||||
LD V0, 1e
|
||||
LD V1, 0a
|
||||
LD I, .center
|
||||
DRW V0, V1, SPRH
|
||||
LD V9, Vf
|
||||
|
||||
LD V0, 28
|
||||
LD V1, 0a
|
||||
DRW V0, V1, SPRH
|
||||
LD Va, Vf
|
||||
|
||||
EXIT
|
||||
|
||||
.block DATA ffff
|
||||
DATA ffff
|
||||
DATA ffff
|
||||
DATA ffff
|
||||
|
||||
.square DATA ff81
|
||||
DATA 8181
|
||||
DATA 8181
|
||||
DATA 81ff
|
||||
|
||||
.corners DATA 8100
|
||||
DATA 0000
|
||||
DATA 0000
|
||||
DATA 0081
|
||||
|
||||
.center DATA 0000
|
||||
DATA 0018
|
||||
DATA 1800
|
||||
DATA 0000
|
||||
|
||||
.checker DATA aa55
|
||||
DATA aa55
|
||||
DATA aa55
|
||||
DATA aa55
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
P1
|
||||
64 32
|
||||
1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1
|
||||
1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
|
||||
1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
|
||||
1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
|
||||
1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
|
||||
1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
|
||||
1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
|
||||
1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1 0 1 0 0 0 1 1 1 1 1 1 1 1 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1 0 1 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1 0 1 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1 0 1 0 0 1 1 1 0 0 1 1 1 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1 0 1 0 0 0 1 1 1 0 0 1 1 1 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1 0 1 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1 0 1 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1 0 1 0 0 1 1 1 1 1 1 1 1 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1
|
||||
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
|
|
@ -0,0 +1 @@
|
|||
....000000000000000100........00..........
|
|
@ -0,0 +1,31 @@
|
|||
;
|
||||
; Exercise SUB/SUBN opcodes
|
||||
;
|
||||
|
||||
; preload some values
|
||||
LD Va, 12
|
||||
LD Vb, 34
|
||||
LD Vc, 56
|
||||
LD Vd, 89
|
||||
LD Ve, ff
|
||||
|
||||
LD V0, 24
|
||||
SUB V0, Va ; SUB Vx, Vy - no borrow
|
||||
LD V1, Vf
|
||||
|
||||
LD V2, 45
|
||||
SUB V2, Vd ; SUB Vx, nn - borrow
|
||||
LD V3, Vf
|
||||
|
||||
LD V4, 22
|
||||
SUBN V4, Vc ; SUBN Vx, Vy - no borrow
|
||||
LD V5, Vf
|
||||
|
||||
LD V6, 56
|
||||
SUBN V6, Vb ; SUBN Vx, Vy - borrow
|
||||
LD V7, Vf
|
||||
|
||||
; TODO: Check corner case where one of the operands is Vf
|
||||
|
||||
EXIT
|
||||
|
|
@ -0,0 +1 @@
|
|||
1201bc003401de00....12345689ff00..........
|
|
@ -0,0 +1,32 @@
|
|||
;
|
||||
; 6522 (VIA) registers
|
||||
;
|
||||
|
||||
.virtual
|
||||
_via .struct
|
||||
iorb .byte ?
|
||||
iora .byte ?
|
||||
ddrb .byte ?
|
||||
ddra .byte ?
|
||||
t1c .word ?
|
||||
t1l .word ?
|
||||
t2c .word ?
|
||||
sr .byte ?
|
||||
acr .byte ?
|
||||
pcr .byte ?
|
||||
ifr .byte ?
|
||||
ier .byte ?
|
||||
ioran .byte ?
|
||||
.endstruct
|
||||
.endvirtual
|
||||
|
||||
VIA_SR_OFF = 0 << 2
|
||||
VIA_SR_IN_T2 = 1 << 2
|
||||
VIA_SR_IN_CLOCK = 2 << 2
|
||||
VIA_SR_IN_EXT = 3 << 2
|
||||
VIA_SR_OUT_T2_FR = 4 << 2
|
||||
VIA_SR_OUT_T2_CB1 = 5 << 2
|
||||
VIA_SR_OUT_CLOCK = 6 << 2
|
||||
VIA_SR_OUT_EXT = 7 << 2
|
||||
|
||||
; vim: syntax=64tass
|
|
@ -0,0 +1,76 @@
|
|||
;
|
||||
; VIC-II registers
|
||||
;
|
||||
|
||||
.virtual
|
||||
_vic2 .struct
|
||||
m0x .byte ?
|
||||
m0y .byte ?
|
||||
m1x .byte ?
|
||||
m1y .byte ?
|
||||
m2x .byte ?
|
||||
m2y .byte ?
|
||||
m3x .byte ?
|
||||
m3y .byte ?
|
||||
m4x .byte ?
|
||||
m4y .byte ?
|
||||
m5x .byte ?
|
||||
m5y .byte ?
|
||||
m6x .byte ?
|
||||
m6y .byte ?
|
||||
m7x .byte ?
|
||||
m7y .byte ?
|
||||
mxx8 .byte ?
|
||||
cr1 .byte ?
|
||||
raster .byte ?
|
||||
lpx .byte ?
|
||||
lpy .byte ?
|
||||
mxe .byte ?
|
||||
cr2 .byte ?
|
||||
mxye .byte ?
|
||||
ptrs .byte ?
|
||||
ir .byte ?
|
||||
ie .byte ?
|
||||
mxdp .byte ?
|
||||
mxmc .byte ?
|
||||
mxxe .byte ?
|
||||
mxm .byte ?
|
||||
mxd .byte ?
|
||||
ec .byte ?
|
||||
b0c .byte ?
|
||||
b1c .byte ?
|
||||
b2c .byte ?
|
||||
b3c .byte ?
|
||||
mm0 .byte ?
|
||||
mm1 .byte ?
|
||||
m0c .byte ?
|
||||
m1c .byte ?
|
||||
m2c .byte ?
|
||||
m3c .byte ?
|
||||
m4c .byte ?
|
||||
m5c .byte ?
|
||||
m6c .byte ?
|
||||
m7c .byte ?
|
||||
.align 64
|
||||
.endstruct
|
||||
.endvirtual
|
||||
|
||||
VIC2_BLACK = 0
|
||||
VIC2_WHITE = 1
|
||||
VIC2_RED = 2
|
||||
VIC2_CYAN = 3
|
||||
VIC2_VIOLET = 4
|
||||
VIC2_PURPLE = 4
|
||||
VIC2_GREEN = 5
|
||||
VIC2_BLUE = 6
|
||||
VIC2_YELLOW = 7
|
||||
VIC2_ORANGE = 8
|
||||
VIC2_BROWN = 9
|
||||
VIC2_LIGHTRED = 10
|
||||
VIC2_DARKGREY = 11
|
||||
VIC2_GREY = 12
|
||||
VIC2_LIGHTGREEN = 13
|
||||
VIC2_LIGHTBLUE = 14
|
||||
VIC2_LIGHTGREY = 15
|
||||
|
||||
; vim: syntax=64tass
|
Loading…
Reference in New Issue