Expand description
§C64 Assembler
The goal of this crate is to being able to compile C64 assembly directly from Rust.
The reasoning behind it is that in a typical C64 development workflow the programs are generated in a separate step and then being saved to a disk image. For generating disk images there are already crates out there like cmb.
However some projects require more control over the compilation stage and disk construction stage. Having a C64 assembler written in rust can build a bridge and allows custom disk formats and faster iterations during development.
§Modules and functions
An crate::Application is organized in crate::Module and crate::Function. Modules can be shared between applications. A module public API is organized in functions. Multiple variations of functions can exists. By swapping out functions in a module a module can be size-optimized or CPU cycles optimized based on the actual needs of the program.
§Usage
§Building pattern
An application can be build using builder patterns.
use c64_assembler::builder::ApplicationBuilder;
use c64_assembler::builder::ModuleBuilder;
use c64_assembler::builder::InstructionBuilder;
let application = ApplicationBuilder::default()
.name("Set black border")
.include_vic2_defines()
.module(
ModuleBuilder::default()
.name("main")
.instructions(
InstructionBuilder::default()
.add_basic_header()
.label("main_entry_point")
.lda_imm(0x00)
.comment("Load black color")
.sta_addr("VIC2_BORDER_COLOR")
.rts()
.build(),
)
.build(),
)
.build().unwrap();
§Validating
Using the crate::validator::Validator to check for consistency.
use c64_assembler::validator::Validator;
let validation_result = application.validate();
assert!(validation_result.is_ok());
§Generating dasm source
Using the crate::generator::DasmGenerator a dasm compatible assembly source can be generated.
use c64_assembler::generator::Generator;
use c64_assembler::generator::DasmGenerator;
let source = DasmGenerator::default().generate(application).unwrap();
println!("{}", source);
Would output
; --- Application: SET BLACK BORDER ---
; NOTE: This file is generated, do not modify
processor 6502
VIC2_BORDER_COLOR = $D020
org $0800
; --- Module begin: MAIN ---
byte $00, $0C, $08 ; New basic line
; 10 SYS 2062
byte $0A, $00, $9E, $20, $32, $30, $36, $32
byte $00, $00, $00 ; End basic program
main_entry_point:
lda #$00
sta VIC2_BORDER_COLOR
rts
; --- Module end: MAIN ---
§Generating .PRG byte stream
Using the crate::generator::ProgramGenerator to generate the byte stream. The byte stream includes the loading address.
use c64_assembler::generator::{Generator, ProgramGenerator, print_hexdump};
let bytes = ProgramGenerator::default().generate(application).unwrap();
print_hexdump(&bytes);
0000: 00 08 00 0C 08 0A 00 9E 20 32 30 36 32 00 00 00
0010: A9 00 8D 20 D0 60
§Using macros (work in progress)
To reduce the boilerplating macros can be used. This is still under development. Expect less stability, error messages and some instructions not supported.
use c64_assembler_macro::application;
let application = application!(
name="Set black border"
include_vic2_defines
module!(
name="main"
instructions!(
include_basic_header
main_entry_point:
"Load black color into accumulator"
lda #$00
sta VIC2_BORDER_COLOR
rts
)
)
).unwrap();
Modules§
- builder
- Builder classes for application, module, function and instructions
- generator
- Generators to export to a .PRG or source code.
- instruction
- memory
- validator
- Validate the consistency of an application.
Structs§
- Application
- Application is the root container for the assembler
- Function
- Function is a replaceble public part of a module.
- Instructions
- Stream of instructions.
- Module
- Module