{c64asm}
is a c64 6502 assembler written in R.
The syntax for the assembly code closely follows that of TASS.
{c64asm}
includes syntax extensions which allow for easier integration of pre-computed values and data segments directly from R.
The Commodore 64 (c64) is an 8-bit home computer running on a Motorola 6510 (a variant of the 6502).
The c64 supports 16 colours, 8 hardware sprites and a maximum resolution of 320x200 pixels.
It includes co-processors for sound (SID chip) and video (VIC-II) chip.
6502 machine code:
{c64asm}
Features
General features
* = $0801
border = $d020
lda #<routine
will store the low byte of the address of symbol routine
in the A
registerFor integration with R
.rtext
directive to include an R
string as text data.rbyte
directive to include an R
integer vector as bytes{...}
to delimit code to be evaluated at run time to manipulate labels and variables e.g. lda {border + 1}
jmp
to a location more than 128 bytes away from the current program counter.indirect indexed
and indexed indirect
modes using symbolic addresses seems to work, but need more tests.BUFPNT = $A6
is the pointer to the tape i/o bufferlda <BUFPNT
should be used to force zero page addressing mode, otherwise lda BUFPNT
would assume absolute addressing mode.
devtools::install_github('coolbutuseless/c64asm')
The documentation for the package is available online at coolbutuseless.github.io (thanks to pkgdown)
helloworld
- write text to the screenhelloborder
- colour cycling in the border as fast as possiblehelloworld_details
- a look at the intermediate assembly outputs during compilationascii
- Using R-specific .rbyte
directive to put characters from an R variable into the assembly codecustom_character_set
- Building a custom character set in R and passing it into the assemblly code with the .rbyte
directive.symbol-arithmetic
- How to do arithmetic on the program counter and address labelsThe code for the vignettes is also available in the prg/
directory of this repository.
The following c64/6502 ASM code will clear the screen and then write Hello #rstats!
at the top
asm <- '
*=$0801
.byte $0c, $08, $0a, $00, $9e, $20 ; 10 SYS 2080
.byte $32, $30, $38, $30, $00, $00
.byte $00
*=$0820
lda #$93 ; Clear the screen
jsr $ffd2
ldx #$0 ; initialise the offset pointer into our message
loop lda message,x ; load a character and write it to screen
and #$3f ; Manually place chars on screen
sta $0400,x
inx
cpx #$0e
bne loop
rts
message
.text "Hello #rstats!"
'
prg <- c64asm::compile(asm)
prg
The compiler makes a few passes through the data to resolve symbol values.
The c64asm::compile()
function is just a wrapper which calls the following 4 functions
line_tokens <- c64asm::create_line_tokens(asm)
prg_df <- c64asm::create_prg_df(line_tokens)
line_tokens
prg_df <- c64asm::process_symbols(prg_df)
prg_df <- c64asm::process_zero_padding(prg_df)
prg <- c6asm::extract_prg_bytes(prg_df)
The actual contents of the c64 prg
executable file is the sequence of values in the hexbytes
column.