Pygments highlights CBM BASIC & ca65 assembler sources¶
Since version 1.6 the syntax highlighter Pygments has support for CBM BASIC
V2 and assembler sources in ca65
format. ca65
is the macro assembler of
the cc65 C cross compiler package.
The language list does not have entries for them, but the lexer list in the documentation knows about Ca65Lexer in the lexers for assembly languages section and CbmBasicV2Lexer in the lexers for other languages section.
Examples¶
Let’s see the highlighter in action. Both examples solve assignment 3 of the HP Codewars 2012. It is about interpreting a sequence of given Reversi moves and printing the resulting board state.
Example of BASIC…
10 cp$="w":op$="b":dimb$(7,7):fori=0to7:forj=0to7:b$(i,j)=".":next:next
20 b$(3,3)="w":b$(4,3)="b":b$(3,4)="b":b$(4,4)="w":dimtx(7),ty(7):goto140
30 inputl$:ifl$="end"then end
40 y=asc(left$(l$,1))-asc("a"):x=val(right$(l$,1))-1:b$(y,x)=cp$
50 forxd=-1to1:foryd=-1to1:if(xd or yd)=0then130
60 xt=x:yt=y:tc=0
70 xt=xt+xd:yt=yt+yd
80 ifxt<0orxt>7oryt<0oryt>7thentc=0:goto120
90 t$=b$(yt,xt):ift$<>op$then110
100 tx(tc)=xt:ty(tc)=yt:tc=tc+1:goto70
110 ift$<>cp$thentc=0
120 iftc>0then fori=0totc-1:b$(ty(i),tx(i))=cp$:next
130 next:next:t$=cp$:cp$=op$:op$=t$
140 fori=0to7:forj=0to7:printb$(j,i);:next:print:next:print:goto30
…and Assembler (yes I know, it is loooong)…
chrout := $ffd2
getchr := $ffe4
.enum
WHITE = 'w'
BLACK = 'b'
EMPTY = '.'
.endenum
.zeropage
zp0 := $02
current_player := $b0
other_player := $b1
zp1 := $b2
zp2 := $b3
zp3 := $b4
zp4 := $b5
.bss
board: .res 64
.proc start
.code
jsr init_game
jmp print
loop:
jsr get_coordinate
bcs exit
jsr move
print:
jsr print_board
jmp loop
exit:
rts
.endproc
;--------------------------------------
; Init the board with empty fields and the four pieces in the middle.
; Set `current_player` & `other_player` to `WHITE` & `BLACK`.
;
; Changes: `board`, `current_player`, `other_player`
.proc init_game
ldy #63
lda #EMPTY
loop: sta board,y
dey
bpl loop
lda #WHITE
sta current_player
sta board + 3*8+3
sta board + 4*8+4
lda #BLACK
sta other_player
sta board + 3*8+4
sta board + 4*8+3
rts
.endproc
;--------------------------------------
; Print the board.
.proc print_board
ldy #0
loop: tya ; index divisible by 8 ?
and #%00000111
bne skip
lda #13 ; print newline.
jsr chrout
skip: lda board,y
jsr chrout
iny
cpy #64
bne loop
lda #13
jmp chrout
.endproc
;--------------------------------------
; Gets the coordinate from the user.
;
; User input is not validated!
;
; In: -
; Out:
; X/A: x and y coordinate if Carry=0
; Carry: if 1 then user entered "end" or pressed RUN/STOP.
.proc get_coordinate
.rodata
end_txt:
.byte "end", 13
end_txt_length := * - end_txt
.bss
buffer_length:
.res 1
buffer: .res 16
.code
lda #0 ; Read line into buffer.
sta buffer_length
@L1: jsr getchr
beq @L1
ldy buffer_length
sta buffer,y
inc buffer_length
cmp #3 ; RUN/STOP
beq exit
jsr chrout
cmp #13 ; RETURN
bne @L1
ldy #end_txt_length - 1 ; buffer == "end\n" ?
@L2: lda buffer,y
cmp end_txt,y
bne continue
dey
bpl @L2
exit:
sec
rts
continue:
lda buffer ; convert coordinate
sec
sbc #'a'
tax
lda buffer+1
clc
sbc #'0'
clc
rts
.endproc
;--------------------------------------
; Checks a line of tiles which should be turned.
;
; In:
; `check_line::x_`, `check_line::y_`: start coordinates
; X/Y: delta x and y between -1 and 1 for the direction
; in which the check is done.
; Out:
; `check_line::turn_coordinates`: the indices into `board`
; of the tiles to turn.
; A: count of indices in `check_line::turn_coordinates`.
; Changes: `zp0`, `zp1`, `zp2`
.proc check_line
x_ := zp1
y_ := zp2
turn_length := zp0
.bss
turn_coordinates:
.res 7
.code
stx xd
sty yd
lda #0
sta turn_length
loop:
clc ; x += xd
lda x_
xd := * + 1
adc #0
sta x_
clc ; y += yd
lda y_
yd := * + 1
adc #0
sta y_
;lda y_ ; check if x and y between 0 and 7
ora x_
and #%11111000
bne no_turns
lda y_ ; Y = y*8+x
asl
asl
asl
ora x_
tay
lda board,y ; board(x,t) == other_player ?
cmp other_player
bne line_end
tya ; store index into board in turn_coordinates.
ldy turn_length
sta turn_coordinates,y
inc turn_length
bne loop
line_end:
cmp current_player ; board(x,y) == current_player ?
bne no_turns
lda turn_length
rts
no_turns:
lda #0
rts
.endproc
;--------------------------------------
; Make a move and then switch players.
;
; In:
; X/A: coordinates of the move.
; Changes: `board`, `current_player`, `other_player`,
; `zp0`, `zp1`, `zp2`, `zp3`, `zp4`
.proc move
xd := zp3
yd := zp4
.code
stx x_
sta y_
asl ; Set new player tile.
asl
asl
ora x_
tay
lda current_player
sta board,y
;
; Two nested loops to check all 8 directions.
;
lda #< -1 ; for xd = -1 to...
sta xd
outer_loop:
lda #< -1 ; for yd = -1 to...
sta yd
inner_loop:
;lda yd ; if (xd | yd) = 0 then continue.
ora xd
beq inner_loop_continue
x_ := * + 1
lda #0
sta check_line::x_
y_ := * + 1
lda #0
sta check_line::y_
ldx xd
ldy yd
jsr check_line
cmp #0 ; turns ?
beq skip_turn_loop
tay ; do turns.
lda current_player
turn_loop:
ldx check_line::turn_coordinates-1,y
sta board,x
dey
bne turn_loop
skip_turn_loop:
inner_loop_continue:
inc yd ; next yd
lda yd
cmp #2
bne inner_loop
inc xd ; next xd
lda xd
cmp #2
bne outer_loop
lda current_player ; swap players.
ldx other_player
sta other_player
stx current_player
rts
.endproc
Previous:
Python – Das umfassende Handbuch
Next:
Table of contents in Tinkerer blogposts