build script! no more manually rebuilding cozette!
This commit is contained in:
parent
6e55faa2c0
commit
7d0b66f418
15
Cargo.toml
15
Cargo.toml
|
@ -2,27 +2,28 @@
|
||||||
name = "georgeemu"
|
name = "georgeemu"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
build = "build.rs"
|
||||||
|
|
||||||
[[bin]]
|
[[target.'cfg(not(target_arch = "wasm32"))'.bin]]
|
||||||
path = "src/bin/main.rs"
|
path = "src/bin/main.rs"
|
||||||
name = "georgeemu"
|
name = "george"
|
||||||
|
|
||||||
[target.'cfg(target_arch = "wasm32")'.lib]
|
[target.'cfg(target_arch = "wasm32")'.lib]
|
||||||
crate-type = ["cdylib", "rlib"]
|
crate-type = ["cdylib", "rlib"]
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
bdf-parser = "0.1.0"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.81"
|
anyhow = "1.0.81"
|
||||||
minifb = { git = "https://github.com/augustkline/rust_minifb" }
|
minifb = { git = "https://github.com/emoon/rust_minifb" }
|
||||||
serde = { version = "1.0.197", features = ["serde_derive", "derive"] }
|
serde = { version = "1.0.197", features = ["serde_derive", "derive"] }
|
||||||
web-sys = "0.3.70"
|
|
||||||
|
|
||||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||||
console_error_panic_hook = "0.1.7"
|
console_error_panic_hook = "0.1.7"
|
||||||
minifb = { git = "https://github.com/augustkline/rust_minifb", features = [
|
web-sys = "0.3.70"
|
||||||
"web",
|
|
||||||
] }
|
|
||||||
|
|
||||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||||
termion = "4.0.2"
|
termion = "4.0.2"
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
use std::{
|
||||||
|
env,
|
||||||
|
fs::File,
|
||||||
|
io::{stdin, stdout, IsTerminal, Read, Write},
|
||||||
|
ops::Neg,
|
||||||
|
os::unix::process::CommandExt,
|
||||||
|
path::Path,
|
||||||
|
process::{exit, Command},
|
||||||
|
};
|
||||||
|
|
||||||
|
// takes all charaters in bdf and returns a vec of each character row byte in order, normalized to
|
||||||
|
// width & height of the font (only works with 8 or fewer pixel wide fonts, should work for any height)
|
||||||
|
fn bdf_to_bitmap(mut bdf: File) -> [u8; 0x8000] {
|
||||||
|
let mut bdf_font_bytes = Vec::new();
|
||||||
|
bdf.read_to_end(&mut bdf_font_bytes).unwrap();
|
||||||
|
|
||||||
|
let bdf_font = bdf_parser::BdfFont::parse(&bdf_font_bytes).unwrap();
|
||||||
|
let mut bdf_vec = vec![];
|
||||||
|
for glyph in bdf_font.glyphs.iter() {
|
||||||
|
let glyph_offset_x = glyph.bounding_box.offset.x;
|
||||||
|
let glyph_offset_y = glyph.bounding_box.offset.y;
|
||||||
|
let glyph_height = glyph.bounding_box.size.y;
|
||||||
|
let font_height = bdf_font.metadata.bounding_box.size.y;
|
||||||
|
let font_offset_y = bdf_font.metadata.bounding_box.offset.y;
|
||||||
|
|
||||||
|
let top_space = font_height + font_offset_y - glyph_height - glyph_offset_y;
|
||||||
|
for _ in 0..top_space {
|
||||||
|
bdf_vec.push(0x00);
|
||||||
|
}
|
||||||
|
for bitmap in glyph.bitmap.iter() {
|
||||||
|
bdf_vec.push(bitmap >> glyph_offset_x);
|
||||||
|
}
|
||||||
|
|
||||||
|
let bottom_space = font_offset_y.neg() + glyph_offset_y;
|
||||||
|
for _ in 0..bottom_space {
|
||||||
|
bdf_vec.push(0x00);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let height = bdf_font.metadata.bounding_box.size.y as usize;
|
||||||
|
reorder_bitmap(&bdf_vec, height)
|
||||||
|
}
|
||||||
|
|
||||||
|
// takes an vec of ordered characters and translates them for use with the character rom
|
||||||
|
// TODO: make this work for any arbitrary char rom pin format using some kinda interface
|
||||||
|
fn reorder_bitmap(bitmap: &[u8], font_height: usize) -> [u8; 0x8000] {
|
||||||
|
let mut rom = [0; 0x8000]; // create vec the size of character rom
|
||||||
|
|
||||||
|
for row in 0..font_height {
|
||||||
|
for ascii_address in 0..u8::MAX {
|
||||||
|
// first 8 bits of address pick character
|
||||||
|
// next 5 bits pick row
|
||||||
|
// TODO: final 2 pick character set
|
||||||
|
let byte = bitmap[ascii_address as usize * font_height + row];
|
||||||
|
let rom_index: u16 = ((row as u16) << 8) + ascii_address as u16;
|
||||||
|
rom[rom_index as usize] = byte;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rom
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rom_from_file<P>(path: P) -> [u8; 0x8000]
|
||||||
|
where
|
||||||
|
P: AsRef<Path>,
|
||||||
|
{
|
||||||
|
let file = File::open(path).unwrap();
|
||||||
|
bdf_to_bitmap(file)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut regen_font = Command::new("regen-font.sh");
|
||||||
|
let mut cleanup = Command::new("cleanup.sh");
|
||||||
|
|
||||||
|
regen_font.exec();
|
||||||
|
|
||||||
|
let out_dir = env::var_os("OUT_DIR").unwrap();
|
||||||
|
let dest_path = Path::new(&out_dir).join("cozette.rom");
|
||||||
|
|
||||||
|
let cozette_rom_bytes = rom_from_file("build/cozette.bdf");
|
||||||
|
let mut cozette_rom = File::create(dest_path).unwrap();
|
||||||
|
cozette_rom.write_all(&cozette_rom_bytes).unwrap();
|
||||||
|
|
||||||
|
cleanup.exec();
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,3 @@
|
||||||
|
#! /bin/sh
|
||||||
|
|
||||||
|
rm *.bdf*
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,4 +1,4 @@
|
||||||
# this is august's version of extended ascii for george <3
|
# this is georgescii, august's version of extended ascii for george <3
|
||||||
# we're limited to 255 characters
|
# we're limited to 255 characters
|
||||||
# format: ascii byte, unicode hex, # unicode name
|
# format: ascii byte, unicode hex, # unicode name
|
||||||
#
|
#
|
|
@ -0,0 +1,5 @@
|
||||||
|
#! /bin/sh
|
||||||
|
|
||||||
|
fontforge -lang=ff -c 'Open($1); LoadEncodingFile($2, "george"); Reencode("george"); Generate($3)' Cozette.sfd georgeencoding.txt cozette.bdf
|
||||||
|
sed -i'' -e 's/FONTBOUNDINGBOX 11 13 0 -3/FONTBOUNDINGBOX 8 13 0 -3/' *.bdf
|
||||||
|
mv cozette-13.bdf cozette.bdf
|
|
@ -0,0 +1,11 @@
|
||||||
|
.org $00
|
||||||
|
|
||||||
|
.byte $80
|
||||||
|
|
||||||
|
.org $8000
|
||||||
|
|
||||||
|
reset:
|
||||||
|
bbr7 $00, reset
|
||||||
|
|
||||||
|
.org $fffc
|
||||||
|
.word reset
|
Binary file not shown.
Binary file not shown.
|
@ -37,7 +37,8 @@ newline: ; sets cursor to start of next line
|
||||||
rts
|
rts
|
||||||
|
|
||||||
text:
|
text:
|
||||||
.asciiz "george loves u <3"
|
.byte 1,2,3,2,4
|
||||||
|
.asciiz "- george loves u <3"
|
||||||
|
|
||||||
random_y:
|
random_y:
|
||||||
.byte 25,12,0,20,4,25,5,13
|
.byte 25,12,0,20,4,25,5,13
|
Binary file not shown.
|
@ -0,0 +1,189 @@
|
||||||
|
; .setcpu "65C02"
|
||||||
|
.include "./macro.inc"
|
||||||
|
|
||||||
|
; okay so rn i wanna set up a very basic system init, and write a few subroutines to draw characters at x,y coordinates
|
||||||
|
n = $01 ; temporary storage for data stack operations
|
||||||
|
|
||||||
|
key_row = $200 ; used for character lookup when key pressed
|
||||||
|
key_col = $201
|
||||||
|
cursor = $202
|
||||||
|
|
||||||
|
char_buffer = $300 ; 256 byte character buffer
|
||||||
|
|
||||||
|
kb_row = $4400 ; keyboard hardware register
|
||||||
|
kb_row_cache = $203 ; cache
|
||||||
|
|
||||||
|
.org $8000
|
||||||
|
|
||||||
|
reset:
|
||||||
|
sei
|
||||||
|
ldx #0; initialize data stack pointer
|
||||||
|
|
||||||
|
initdisplay:
|
||||||
|
lda #0
|
||||||
|
ldy #0
|
||||||
|
|
||||||
|
cleardisplay:
|
||||||
|
sta $6000,y
|
||||||
|
sta $6100,y
|
||||||
|
sta $6200,y
|
||||||
|
sta $6300,y
|
||||||
|
sta $6400,y
|
||||||
|
sta $6500,y
|
||||||
|
sta $6600,y
|
||||||
|
sta $6700,y ; this goes slightly over but it's fine
|
||||||
|
iny
|
||||||
|
bne cleardisplay
|
||||||
|
cli
|
||||||
|
|
||||||
|
print_test:
|
||||||
|
lda #0
|
||||||
|
sta key_row
|
||||||
|
lda #5
|
||||||
|
sta key_col
|
||||||
|
push_coords #5, #5
|
||||||
|
|
||||||
|
main:
|
||||||
|
; jsr printtext
|
||||||
|
; key_zero:
|
||||||
|
; stz keyboard_cache, x
|
||||||
|
; dex
|
||||||
|
; bpl key_zero
|
||||||
|
; fim:
|
||||||
|
; cli
|
||||||
|
; bra fim
|
||||||
|
jsr print
|
||||||
|
; jsr print
|
||||||
|
stp
|
||||||
|
jmp main
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; keyboard: ; reads keyboard registers and stores the column and row of the first key found
|
||||||
|
; ; TODO: make this routine store up to 8 indices (for 8 key rollover)
|
||||||
|
; ldy #0
|
||||||
|
; .check_row: ; loop through each row
|
||||||
|
; lda kb_row, y
|
||||||
|
; beq .skip_row ; if row has no key pressed, skip checking which key
|
||||||
|
; ; jmp key_down
|
||||||
|
; sta kb_row_cache, y ; if key pressed, cache it
|
||||||
|
; lda kb_row, y
|
||||||
|
; cmp kb_row_cache, y ; has key changed?
|
||||||
|
; beq key_down
|
||||||
|
; .skip_row:
|
||||||
|
; iny
|
||||||
|
; cpy #5
|
||||||
|
; bne .check_row
|
||||||
|
; rts
|
||||||
|
|
||||||
|
; key_down: ; a is loaded with the row byte
|
||||||
|
; phy
|
||||||
|
; sty key_row ; store character row
|
||||||
|
; ldy #0
|
||||||
|
; .find_col: ; test each row bit, store column if key pressed
|
||||||
|
; lsr ; test bit 7
|
||||||
|
; bcs store_col ; if unset, don't go store character columnb
|
||||||
|
; .skip:
|
||||||
|
; iny
|
||||||
|
; cpy #8
|
||||||
|
; bne .find_col ; loop until we've checked each bit
|
||||||
|
; rts
|
||||||
|
|
||||||
|
; store_col:
|
||||||
|
; sty key_col
|
||||||
|
; jsr print
|
||||||
|
; rts
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
print: ; x y -- prints the key indexed with key_col and key_row at position x, y
|
||||||
|
|
||||||
|
keymap_index:
|
||||||
|
push
|
||||||
|
lda key_col
|
||||||
|
stz 1, x
|
||||||
|
sta 0, x
|
||||||
|
push
|
||||||
|
lda #8
|
||||||
|
stz 1, x
|
||||||
|
sta 0, x
|
||||||
|
push
|
||||||
|
lda key_row
|
||||||
|
stz 1, x
|
||||||
|
sta 0, x
|
||||||
|
jsr mult
|
||||||
|
jsr plus
|
||||||
|
lda 0, x
|
||||||
|
tay
|
||||||
|
lda keymap, y
|
||||||
|
push
|
||||||
|
sta 0, x
|
||||||
|
stz 1, x
|
||||||
|
jsr draw_char
|
||||||
|
rts
|
||||||
|
|
||||||
|
keymap:
|
||||||
|
.byte "?outrew?"
|
||||||
|
.byte "?piygsq?"
|
||||||
|
.byte "a??khvd?"
|
||||||
|
.byte "42ljbfz?"
|
||||||
|
.byte "31?mncx?"
|
||||||
|
.byte "????? m"
|
||||||
|
|
||||||
|
draw:
|
||||||
|
; push_coords #0, #0
|
||||||
|
; push_char #$00
|
||||||
|
; jsr draw_char
|
||||||
|
rts
|
||||||
|
|
||||||
|
draw_char: ; draw a character c at (x, y) (n1: x n2: y n3: c -- )
|
||||||
|
lda 0, x ; load a with character to draw
|
||||||
|
pop ; and pop it off the stack
|
||||||
|
jsr get_char_address ; calculate where to put the character in memory
|
||||||
|
sta (0, x) ; store a at the address pointed to on the stack
|
||||||
|
rts
|
||||||
|
|
||||||
|
get_char_address: ; gets vram address for a character at (x, y),
|
||||||
|
; (n1: x n2: y -- n: $6000 + x + (64 * y))
|
||||||
|
;jsr push_lit ; push 64 onto stack, low byte first
|
||||||
|
;.byte 64
|
||||||
|
;.byte 0
|
||||||
|
pha
|
||||||
|
lda #64
|
||||||
|
push ; doing this instead until `push_lit` is fixed
|
||||||
|
sta 0, x
|
||||||
|
stz 1, x
|
||||||
|
jsr mult ; multiply 64 with y (n2)
|
||||||
|
jsr plus ; add result with x (n1)
|
||||||
|
|
||||||
|
;jsr push_lit ; push vram address onto the stack
|
||||||
|
;.byte $00
|
||||||
|
;.byte $60
|
||||||
|
lda #$60
|
||||||
|
push
|
||||||
|
sta 1, x
|
||||||
|
stz 0, x
|
||||||
|
jsr plus ; add vram start address to result
|
||||||
|
|
||||||
|
pla
|
||||||
|
rts
|
||||||
|
|
||||||
|
fill: ; fills an area from (x1, y1) to (x2, y2) will character c, (n1: c n2: x1 n3: y1 n4: x2 n5: y2 -- )
|
||||||
|
jsr get_char_address
|
||||||
|
|
||||||
|
isr: ; interrupt service routine
|
||||||
|
pha
|
||||||
|
phx
|
||||||
|
phy
|
||||||
|
; jsr keyboard
|
||||||
|
ply
|
||||||
|
plx
|
||||||
|
pla
|
||||||
|
rti
|
||||||
|
|
||||||
|
.include "math.inc"
|
||||||
|
|
||||||
|
.org $fffc
|
||||||
|
.word reset
|
||||||
|
.word isr
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,215 @@
|
||||||
|
; .setcpu "65C02"
|
||||||
|
.include "./macro.inc"
|
||||||
|
|
||||||
|
.org $8000
|
||||||
|
|
||||||
|
n = $01 ; temporary storage for data stack operations
|
||||||
|
|
||||||
|
temp = $20 ; scratchpad page
|
||||||
|
str_ptr = $30
|
||||||
|
|
||||||
|
cursor = $300
|
||||||
|
cursor_x = cursor
|
||||||
|
cursor_y = cursor + 1
|
||||||
|
|
||||||
|
char_buf = $302
|
||||||
|
char_buf_index = char_buf + 8
|
||||||
|
|
||||||
|
reset:
|
||||||
|
sei
|
||||||
|
ldx #0; initialize data stack pointer
|
||||||
|
|
||||||
|
init:
|
||||||
|
lda #$31
|
||||||
|
sta str_ptr
|
||||||
|
lda #$80
|
||||||
|
sta str_ptr + 1
|
||||||
|
|
||||||
|
jsr clear
|
||||||
|
lda #0
|
||||||
|
sta cursor_x
|
||||||
|
lda #0
|
||||||
|
sta cursor_y
|
||||||
|
cli
|
||||||
|
|
||||||
|
main:
|
||||||
|
jsr print
|
||||||
|
jmp main
|
||||||
|
|
||||||
|
newline: ; sets cursor to start of next line
|
||||||
|
stz cursor_x
|
||||||
|
lda cursor_y
|
||||||
|
cmp #28
|
||||||
|
bne .end
|
||||||
|
stz cursor_y
|
||||||
|
rts
|
||||||
|
.end:
|
||||||
|
inc cursor_y
|
||||||
|
rts
|
||||||
|
|
||||||
|
text:
|
||||||
|
.asciiz "hello <3"
|
||||||
|
|
||||||
|
; increments the cursor line by line, looping to (0, 0) after (63, 28)
|
||||||
|
|
||||||
|
inc_cursor:
|
||||||
|
lda cursor_x
|
||||||
|
cmp #63
|
||||||
|
beq .newline
|
||||||
|
inc cursor_x
|
||||||
|
rts
|
||||||
|
.newline:
|
||||||
|
lda cursor_y
|
||||||
|
cmp #28
|
||||||
|
beq .newscreen
|
||||||
|
stz cursor_x
|
||||||
|
inc cursor_y
|
||||||
|
rts
|
||||||
|
.newscreen:
|
||||||
|
stz cursor_y
|
||||||
|
stz cursor_x
|
||||||
|
rts
|
||||||
|
|
||||||
|
; zeroes out the display, resets cursor to 0,0
|
||||||
|
|
||||||
|
clear:
|
||||||
|
lda #0
|
||||||
|
ldy #0
|
||||||
|
|
||||||
|
.loop:
|
||||||
|
sta $6000,y
|
||||||
|
sta $6100,y
|
||||||
|
sta $6200,y
|
||||||
|
sta $6300,y
|
||||||
|
sta $6400,y
|
||||||
|
sta $6500,y
|
||||||
|
sta $6600,y
|
||||||
|
sta $6700,y ; this goes slightly over but it's fine
|
||||||
|
iny
|
||||||
|
bne .loop
|
||||||
|
stz cursor
|
||||||
|
stz cursor + 1
|
||||||
|
rts
|
||||||
|
|
||||||
|
|
||||||
|
; prints string from cursor position, stopping at end of string or at 256 chars, whichever comes first
|
||||||
|
; $6000 + (64*Y) + X
|
||||||
|
; THIS WILL WRITE OUT OF BOUNDS IF THE CURSOR IS OUT OF BOUNDS/STRING IS TOO LONG
|
||||||
|
|
||||||
|
; TODO: figure out a simple way of writing arbitrary length strings
|
||||||
|
; and
|
||||||
|
|
||||||
|
print:
|
||||||
|
jsr cursor_addr
|
||||||
|
ldy #0
|
||||||
|
; y_overflow = temp + 5
|
||||||
|
.loop:
|
||||||
|
lda (str_ptr), y
|
||||||
|
beq .end
|
||||||
|
sta (temp), y
|
||||||
|
iny
|
||||||
|
bra .loop
|
||||||
|
.end:
|
||||||
|
rts
|
||||||
|
|
||||||
|
|
||||||
|
; calculates real vram address from cursor (x, y)
|
||||||
|
|
||||||
|
cursor_addr:
|
||||||
|
stz temp
|
||||||
|
stz temp + 1
|
||||||
|
lda cursor_y
|
||||||
|
beq .add_x ; if y's zero just add x
|
||||||
|
.y_mult:
|
||||||
|
; multiply by 64
|
||||||
|
clc
|
||||||
|
asl
|
||||||
|
rol temp + 1
|
||||||
|
asl
|
||||||
|
rol temp + 1
|
||||||
|
asl
|
||||||
|
rol temp + 1
|
||||||
|
asl
|
||||||
|
rol temp + 1
|
||||||
|
asl
|
||||||
|
rol temp + 1
|
||||||
|
asl
|
||||||
|
rol temp + 1
|
||||||
|
sta temp
|
||||||
|
.add_x:
|
||||||
|
clc
|
||||||
|
lda cursor_x
|
||||||
|
adc temp
|
||||||
|
sta temp
|
||||||
|
lda #0
|
||||||
|
adc temp + 1
|
||||||
|
sta temp + 1
|
||||||
|
clc
|
||||||
|
|
||||||
|
lda #$60
|
||||||
|
adc temp + 1
|
||||||
|
sta temp + 1
|
||||||
|
rts
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; print_text:
|
||||||
|
; lda text,y
|
||||||
|
; beq .end
|
||||||
|
; sta $6000, y
|
||||||
|
; iny
|
||||||
|
; bra print_text
|
||||||
|
; .end:
|
||||||
|
; ldy #0
|
||||||
|
; rts
|
||||||
|
|
||||||
|
; draw_char: ; draw a character c at (x, y) (n1: x n2: y n3: c -- )
|
||||||
|
; lda 0, x ; load a with character to draw
|
||||||
|
; pop ; and pop it off the stack
|
||||||
|
; jsr get_char_address ; calculate where to put the character in memory
|
||||||
|
; sta (0, x) ; store a at the address pointed to on the stack
|
||||||
|
; rts
|
||||||
|
|
||||||
|
; get_char_address: ; gets vram address for a character at (x, y),
|
||||||
|
; ; (n1: x n2: y -- n: $6000 + x + (64 * y))
|
||||||
|
; ;jsr push_lit ; push 64 onto stack, low byte first
|
||||||
|
; ;.byte 64
|
||||||
|
; ;.byte 0
|
||||||
|
; pha
|
||||||
|
; lda #64
|
||||||
|
; push ; doing this instead until `push_lit` is fixed
|
||||||
|
; sta 0, x
|
||||||
|
; stz 1, x
|
||||||
|
; jsr mult ; multiply 64 with y (n2)
|
||||||
|
; jsr plus ; add result with x (n1)
|
||||||
|
|
||||||
|
; ;jsr push_lit ; push vram address onto the stack
|
||||||
|
; ;.byte $00
|
||||||
|
; ;.byte $60
|
||||||
|
; lda #$60
|
||||||
|
; push
|
||||||
|
; sta 1, x
|
||||||
|
; stz 0, x
|
||||||
|
; jsr plus ; add vram start address to result
|
||||||
|
|
||||||
|
; pla
|
||||||
|
; rts
|
||||||
|
|
||||||
|
; fill: ; fills an area from (x1, y1) to (x2, y2) will character c, (n1: c n2: x1 n3: y1 n4: x2 n5: y2 -- )
|
||||||
|
; jsr get_char_address
|
||||||
|
|
||||||
|
isr: ; interrupt service routine
|
||||||
|
pha
|
||||||
|
phx
|
||||||
|
phy
|
||||||
|
; jsr irq
|
||||||
|
ply
|
||||||
|
plx
|
||||||
|
pla
|
||||||
|
rti
|
||||||
|
|
||||||
|
.include "math.inc"
|
||||||
|
|
||||||
|
.org $fffc
|
||||||
|
.word reset
|
||||||
|
.word isr
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,173 @@
|
||||||
|
; .setcpu "65C02"
|
||||||
|
.include "./macro.inc"
|
||||||
|
|
||||||
|
; okay so rn i wanna set up a very basic system init, and write a few subroutines to draw characters at x,y coordinates
|
||||||
|
n = $01 ; temporary storage for data stack operations
|
||||||
|
|
||||||
|
key_row = $200 ; used for character lookup when key pressed
|
||||||
|
key_col = $201
|
||||||
|
cursor = $202
|
||||||
|
|
||||||
|
char_buffer = $300 ; 256 byte character buffer
|
||||||
|
|
||||||
|
kb_row = $4400 ; keyboard hardware register
|
||||||
|
kb_row_cache = $203 ; cache
|
||||||
|
|
||||||
|
.org $8000
|
||||||
|
|
||||||
|
reset:
|
||||||
|
sei
|
||||||
|
ldx #0; initialize data stack pointer
|
||||||
|
jmp main
|
||||||
|
|
||||||
|
initdisplay:
|
||||||
|
lda #20
|
||||||
|
ldy #0
|
||||||
|
|
||||||
|
cleardisplay:
|
||||||
|
sta $6000,y
|
||||||
|
sta $6100,y
|
||||||
|
sta $6200,y
|
||||||
|
sta $6300,y
|
||||||
|
sta $6400,y
|
||||||
|
sta $6500,y
|
||||||
|
sta $6600,y
|
||||||
|
sta $6700,y ; this goes slightly over but it's fine
|
||||||
|
iny
|
||||||
|
bne cleardisplay
|
||||||
|
cli
|
||||||
|
|
||||||
|
main:
|
||||||
|
; jsr keyboard
|
||||||
|
; key_zero:
|
||||||
|
; stz keyboard_cache, x
|
||||||
|
; dex
|
||||||
|
; bpl key_zero
|
||||||
|
; fim:
|
||||||
|
; cli
|
||||||
|
; bra fim
|
||||||
|
; jsr kitty_keys
|
||||||
|
lda #9
|
||||||
|
sta $6000
|
||||||
|
jmp main
|
||||||
|
|
||||||
|
not_keyboard:
|
||||||
|
ldy #0
|
||||||
|
.check_row: ; loop through each row
|
||||||
|
lda kb_row, y
|
||||||
|
beq .skip_row ; if row has no key pressed, skip checking which key
|
||||||
|
sta kb_row_cache, y ; if key pressed, cache it
|
||||||
|
lda kb_row, y
|
||||||
|
cmp kb_row_cache, y ; has key changed?
|
||||||
|
beq key_down
|
||||||
|
.skip_row:
|
||||||
|
iny
|
||||||
|
cpy #5
|
||||||
|
bne .check_row
|
||||||
|
rts
|
||||||
|
|
||||||
|
key_down: ; a is loaded with the row byte
|
||||||
|
phy
|
||||||
|
sty key_row ; store character row
|
||||||
|
ldy #0
|
||||||
|
.find_col: ; test each row bit, store column if key pressed
|
||||||
|
lsr ; test bit 7
|
||||||
|
bcs store_col ; if unset, don't go store character columnb
|
||||||
|
.skip:
|
||||||
|
iny
|
||||||
|
cpy #8
|
||||||
|
bne .find_col ; loop until we've checked each bit
|
||||||
|
|
||||||
|
store_col:
|
||||||
|
sty key_col
|
||||||
|
|
||||||
|
keymap_index:
|
||||||
|
push
|
||||||
|
lda key_col
|
||||||
|
stz 1, x
|
||||||
|
sta 0, x
|
||||||
|
push
|
||||||
|
lda #8
|
||||||
|
stz 1, x
|
||||||
|
sta 0, x
|
||||||
|
push
|
||||||
|
lda key_row
|
||||||
|
stz 1, x
|
||||||
|
sta 0, x
|
||||||
|
jsr mult
|
||||||
|
jsr plus
|
||||||
|
lda 0, x
|
||||||
|
tay
|
||||||
|
|
||||||
|
print: ; we've stored the character position, now let's
|
||||||
|
lda keymap, y
|
||||||
|
ldy cursor
|
||||||
|
sta $6000, y
|
||||||
|
inc cursor
|
||||||
|
ply
|
||||||
|
rts
|
||||||
|
|
||||||
|
keymap:
|
||||||
|
.byte "?outrew?"
|
||||||
|
.byte "?piygsq?"
|
||||||
|
.byte "a??khvd?"
|
||||||
|
.byte "42ljbfz?"
|
||||||
|
.byte "31?mncx?"
|
||||||
|
.byte "????? m"
|
||||||
|
|
||||||
|
; draw:
|
||||||
|
; ; push_coords #0, #0
|
||||||
|
; ; push_char #$00
|
||||||
|
; ; jsr draw_char
|
||||||
|
; rts
|
||||||
|
|
||||||
|
; draw_char: ; draw a character c at (x, y) (n1: x n2: y n3: c -- )
|
||||||
|
; lda 0, x ; load a with character to draw
|
||||||
|
; pop ; and pop it off the stack
|
||||||
|
; jsr get_char_address ; calculate where to put the character in memory
|
||||||
|
; sta (0, x) ; store a at the address pointed to on the stack
|
||||||
|
; rts
|
||||||
|
|
||||||
|
; get_char_address: ; gets vram address for a character at (x, y),
|
||||||
|
; ; (n1: x n2: y -- n: $6000 + x + (64 * y))
|
||||||
|
; ;jsr push_lit ; push 64 onto stack, low byte first
|
||||||
|
; ;.byte 64
|
||||||
|
; ;.byte 0
|
||||||
|
; pha
|
||||||
|
; lda #64
|
||||||
|
; push ; doing this instead until `push_lit` is fixed
|
||||||
|
; sta 0, x
|
||||||
|
; stz 1, x
|
||||||
|
; jsr mult ; multiply 64 with y (n2)
|
||||||
|
; jsr plus ; add result with x (n1)
|
||||||
|
|
||||||
|
; ;jsr push_lit ; push vram address onto the stack
|
||||||
|
; ;.byte $00
|
||||||
|
; ;.byte $60
|
||||||
|
; lda #$60
|
||||||
|
; push
|
||||||
|
; sta 1, x
|
||||||
|
; stz 0, x
|
||||||
|
; jsr plus ; add vram start address to result
|
||||||
|
|
||||||
|
; pla
|
||||||
|
; rts
|
||||||
|
|
||||||
|
; fill: ; fills an area from (x1, y1) to (x2, y2) will character c, (n1: c n2: x1 n3: y1 n4: x2 n5: y2 -- )
|
||||||
|
; jsr get_char_address
|
||||||
|
|
||||||
|
isr: ; interrupt service routine
|
||||||
|
pha
|
||||||
|
phx
|
||||||
|
phy
|
||||||
|
; jsr irq
|
||||||
|
ply
|
||||||
|
plx
|
||||||
|
pla
|
||||||
|
rti
|
||||||
|
|
||||||
|
.include "math.inc"
|
||||||
|
|
||||||
|
.org $fffc
|
||||||
|
.word reset
|
||||||
|
.word isr
|
Binary file not shown.
4
run.sh
4
run.sh
|
@ -7,6 +7,6 @@ fi
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
vasm6502_oldstyle ./src/roms/$1.asm -dotdir -wdc02 -ldots -Fbin -o ./src/roms/$1.rom;
|
vasm6502_oldstyle roms/$1.asm -dotdir -wdc02 -ldots -Fbin -o roms/$1.rom;
|
||||||
cargo run -- rom "./src/roms/$1.rom";
|
cargo run -- rom "roms/$1.rom";
|
||||||
# hexdump -C ./cpu_dump.bin;
|
# hexdump -C ./cpu_dump.bin;
|
||||||
|
|
|
@ -20,9 +20,9 @@ impl MemHandle {
|
||||||
memory.write(address, data);
|
memory.write(address, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dump(&self) {
|
pub fn dump(&self) -> [u8; 0x10000] {
|
||||||
let memory = self.0.lock().unwrap();
|
let memory = self.0.lock().unwrap();
|
||||||
let _ = memory.dump(PathBuf::from_str("./cpu_dump.bin").unwrap());
|
memory.dump()
|
||||||
}
|
}
|
||||||
pub fn poke(&self, address: u16) {
|
pub fn poke(&self, address: u16) {
|
||||||
let memory = self.0.lock().unwrap();
|
let memory = self.0.lock().unwrap();
|
||||||
|
@ -47,7 +47,7 @@ pub struct Mem([u8; 0x10000]);
|
||||||
|
|
||||||
impl Default for Mem {
|
impl Default for Mem {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
let bytes = include_bytes!("./roms/george.rom");
|
let bytes = include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/roms/george.rom"));
|
||||||
let padding = [0; 0x8000];
|
let padding = [0; 0x8000];
|
||||||
let mem: [u8; 0x10000] = {
|
let mem: [u8; 0x10000] = {
|
||||||
let mut rom: [u8; 0x10000] = [0; 0x10000];
|
let mut rom: [u8; 0x10000] = [0; 0x10000];
|
||||||
|
@ -65,10 +65,8 @@ impl Mem {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self([0; 0x10000])
|
Self([0; 0x10000])
|
||||||
}
|
}
|
||||||
pub fn dump(&self, path: PathBuf) -> io::Result<()> {
|
pub fn dump(&self) -> [u8; 0x10000] {
|
||||||
let mut outfile = File::create(path)?;
|
self.0
|
||||||
outfile.write_all(&self.0)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read(&self, address: u16) -> u8 {
|
pub fn read(&self, address: u16) -> u8 {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
|
use std::{env, fs::File, io::Read, path::Path};
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
use termion::{
|
use termion::{
|
||||||
|
@ -43,8 +44,7 @@ const HEIGHT: usize = 380;
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
const CHAR_ROM: &[u8; 0x8000] = include_bytes!("./roms/cozette.rom");
|
const CHAR_ROM: &[u8; 0x8000] = include_bytes!(concat!(env!("OUT_DIR"), "/cozette.rom"));
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
const ASCII_LOOKUP: [&str; 256] = [
|
const ASCII_LOOKUP: [&str; 256] = [
|
||||||
" ", "░", "▒", "▓", "♡", "♥", "⭐", "✭", "", "✦", "✨", "♀", "♂", "⚢", "⚣", "⚥", "♩", "♪",
|
" ", "░", "▒", "▓", "♡", "♥", "⭐", "✭", "", "✦", "✨", "♀", "♂", "⚢", "⚣", "⚥", "♩", "♪",
|
||||||
|
|
Loading…
Reference in New Issue