Clock Test
As a method of troubleshooting, or if there was a need to export code to standard assembly langauge, the customSyntax and ca65hl macros now support a simple method of printing the assembly code that the macros generate to the console. It is possible to coax ca65 to print
to a file, but this would require a custom linker config and more macro code, and for the limited use this might see, I plan to leave it as is for now. This feature has been added to https://github.com/Movax12/ca65hl.
To understand how to use this feature, please see the following example, which is using code from the previous post.
The code enclosed by the
ca65hl_Listing on
and
ca65hl_Listing off
will be printed to the console as standard assembly code.
; --------------------------------------------------------------------------------------------
; File: mainGameLoopState
; --------------------------------------------------------------------------------------------
; this State is one level above rootState
; --------------------------------------------------------------------------------------------
; required headers:
.include "config.h"
.include "header/memory.h"
.include "header/funcCall.h"
.include "header/ca65hl.h"
; --------------------------------------------------------------------------------------------
; Define State:
identifyState "mainGameLoopState"
loadState "mainGameLoopState"
; --------------------------------------------------------------------------------------------
; Constants for State:
; --------------------------------------------------------------------------------------------
; Headers for State:
; standard library
.include "header/string.h"
.include "header/nmi.h"
.include "header/controller.h"
.include "header/condes.h"
.include "header/nes_constants.h"
.include "header/ppu.h"
.include "header/clock.h"
; --------------------------------------------------------------------------------------------
; Code segment for State:
.segment "CODE"
; --------------------------------------------------------------------------------------------
; global memory settings:
resBSS clockRunning .byte
; --------------------------------------------------------------------------------------------
; Imports:
; --------------------------------------------------------------------------------------------
; Exports:
declarefunc nmiEnd
; --------------------------------------------------------------------------------------------
; States:
declarefunc mainGameLoopState
; --------------------------------------------------------------------------------------------
; Forward Declarations:
.pushseg
.segment "RODATA"
palette:
.byte $01,$36,$05,$16,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F
cursorPos:
.byte 0, 3, 6, 9
.popseg
func mainGameLoopState
resBSS timeStr .byte 4 ; 3 byte string plus terminator
resBSS cursor .byte ; position as 0 to 3
resBSS i .byte ; loop counter
mb cursor = #0
mb clockRunning = #1
call nmi::waitForNMI ; wait for vblank to write palette
call ppu::setBackgroundPalette, { &palette }
jPrintRenderMode off
jPrintSetMaxCol 32
jPrintSetCursor 9, 6
jPrint "Clock Test!"
jPrint
jPrint
jPrint
jPrint "00:00:00:00"
jPrintSetCursor 1, 14
jPrint "Press START to Pause"
jPrint "Press UP/DOWN to change value"
jPrint "Press A to reset value"
jPrintEnd
PPU_RENDER_ON
ca65hl_Listing on, "Main Loop"
repeat
; draw the time:
; i = 0 -> hours
; i = 1 -> minutes
; i = 2 -> seconds
; i = 3 -> hundredths
for ( mb i := #3, !N, dec i ) ; i: 3 to 0
ldx i
call str::byteToDecimal, { clock::time[ x ], &timeStr }
ldx i : mb a = cursorPos[ x ] + #9
call str::print, { a , #10, &(timeStr + 1) } ; only print the last 2 digits
next
; draw cursor
jPrintRenderMode on
jPrintSetCursor 10, 11
jPrint " " ; create a blank buffer
jPrintEnd
ldy cursor
txa ; x holds vramBufferIndex
mb x = a + cursorPos[ y ]
mb ppu::vramBuffer[ x ] = #$1F ; arrow symbol
; process input:
lda controller::pressedNew : tay ; store a copy of buttons in y to quickly restore a
ldx cursor
if ( !zero && a & #BUTTON_LEFT )
dex
elseif ( tya : a & #BUTTON_RIGHT && x < #3 )
inx
elseif ( tya : a & #BUTTON_START ), !Z
inc clockRunning
elseif ( tya : a & #BUTTON_A )
mb clock::time[ x ] = #0
elseif ( tya : a & #BUTTON_UP && clock::time[ x ] <> #59 ), Z
inc clock::time[ x ]
elseif ( tya : a & #BUTTON_DOWN && clock::time[ x ] ), !Z
dec clock::time[ x ]
endif
stx cursor
call nmi::waitForNMI
forever
ca65hl_Listing off
endfunc
; --------------------------------------------------------------------------------------------
func nmiEnd
call controller::readPort, { #0 }
call controller::autoRepeatButtons, { #0, #$FF } ; allow all to auto repeat
if ( clockRunning & #1 )
call clock::clockTick
endif
rts
endfunc
; --------------------------------------------------------------------------------------------
The output captured from the console:
; Main Loop
DO_WHILE_LOOP_LABEL_0000:
lda #$03
sta i
FOR_STATEMENT_LABEL_0000:
ldx i
lda clock::time, x
ldx #<timeStr
ldy #>timeStr
jsr str::byteToDecimal
ldx i
lda cursorPos, x
clc
adc #$09
sta ___functionMacro::parameterAddress
lda #$0A
ldx #<( timeStr + $01)
ldy #>( timeStr + $01)
jsr str::print
dec i
bpl FOR_STATEMENT_LABEL_0000
lda #<( jPrintStringData_01 )
ldx #>( jPrintStringData_01 )
ldy #jusPrint::bufferByteCount
jsr ppu::vramBufferPutBlock
ldy cursor
txa
clc
adc cursorPos, y
tax
lda #$1F
sta ppu::vramBuffer, x
lda controller::pressedNew
tay
ldx cursor
beq IF_STATEMENT_0001_ENDIF_LABEL
and #BUTTON_LEFT
beq IF_STATEMENT_0001_ENDIF_LABEL
dex
jmp IF_STATEMENT_0001_ELSE_ENDIF_LABEL
IF_STATEMENT_0001_ENDIF_LABEL:
tya
and #BUTTON_RIGHT
beq IF_STATEMENT_0001_ELSEIF_LABEL_0000
cpx #$03
bcs IF_STATEMENT_0001_ELSEIF_LABEL_0000
inx
bne IF_STATEMENT_0001_ELSE_ENDIF_LABEL
IF_STATEMENT_0001_ELSEIF_LABEL_0000:
tya
and #BUTTON_START
beq IF_STATEMENT_0001_ELSEIF_LABEL_0001
inc clockRunning
jmp IF_STATEMENT_0001_ELSE_ENDIF_LABEL
IF_STATEMENT_0001_ELSEIF_LABEL_0001:
tya
and #BUTTON_A
beq IF_STATEMENT_0001_ELSEIF_LABEL_0002
lda #$00
sta clock::time, x
beq IF_STATEMENT_0001_ELSE_ENDIF_LABEL
IF_STATEMENT_0001_ELSEIF_LABEL_0002:
tya
and #BUTTON_UP
beq IF_STATEMENT_0001_ELSEIF_LABEL_0003
lda clock::time, x
cmp #$3B
beq IF_STATEMENT_0001_ELSEIF_LABEL_0003
inc clock::time, x
bne IF_STATEMENT_0001_ELSE_ENDIF_LABEL
IF_STATEMENT_0001_ELSEIF_LABEL_0003:
tya
and #BUTTON_DOWN
beq IF_STATEMENT_0001_ELSEIF_LABEL_0004
lda clock::time, x
beq IF_STATEMENT_0001_ELSEIF_LABEL_0004
dec clock::time, x
IF_STATEMENT_0001_ELSE_ENDIF_LABEL:
IF_STATEMENT_0001_ELSEIF_LABEL_0004:
stx cursor
jsr nmi::waitForNMI
jmp DO_WHILE_LOOP_LABEL_0000
The output is able to capture all labels generated by the ca65hl macros, as well as all instructions processed by the assembler. It will not capture user labels or data (such as values generated by the .byte statement).
No comments:
Post a Comment