; ʕ·ᴥ·ʔ- fuzzy v0 rev 0: parse program text and spit out binary representation @ $4000 .include "./macro.inc" n = $05 ; temporary storage for data stack operations base = $00 result_binary_base = base ; pointer to where the next byte of binary data should be stored0 binary_base_index = result_binary_base + 2 ; offset for that pointer binary_subroutine_address = binary_base_index + 1 ; pointer to a subroutine to be written to the binary .org $8000 .include "./subroutines.inc" program_text: .include "./program.inc" reset: sei lda #0 ldx #0 ldy #0 main: stz binary_base_index lda #$40 sta result_binary_base + 1 ; set where to store resulting binary stz binary_subroutine_address lda #$80 sta binary_subroutine_address + 1 ; available subroutines start at $8000 jsr compile_values stp ; parser loop, eventually this will be able to handle longer program strings, but indexing by y is fine for now compile_values: ldy #0 parser_loop: lda program_text, y ; get character at index cmp #0 ; is eof? beq .end ; yes, exit loop cmp #20 ; is space? beq parser_loop ; yes, skip this char cmp #12 ; is newline? beq .newline ; yes, handle newline jsr compile_values_op jsr compile_values_nat .newline: ; we reached a newline, y is program string index iny ; WARN: don't accidentally iny in this loop w/out handling a character lda program_text, y ; load next char cmp #12 ; is newline? bne parser_loop ; no, keep parsing tokens rts ; yes, no more tokens in body (see syntax.md for info) .end: rts ; a holds character value, y program text index, only iny if you find a matching character & consume it compile_values_op: cmp #"+" ; i personally think this syntax is really silly but whatever, one of these days i'm gonna write my own assembler and document everything cause vasm documentation is kinda terrible bne .next .is_plus: lda #1 jsr store_subroutine rts .next: rts ; cmp #"!" ; commenting these out for now to handle a single simple case ; cmp #"&" ; cmp #"|" ; cmp #"-" ; cmp #"*" ; cmp #"/" ; cmp #"=" ; cmp #">" ; cmp #"<" ; cmp #"#" ; a holds character value, y program text index, only iny if you find a matching character & consume it ; TODO: ; 1-3 digit decimal values ; 1-2 digit hex values compile_values_nat: ; TODO: ; cmp #"$" ; is hex? ; bne .decimal ; no, try decimal ; cmp ; rts cmp #47 ; less than (before) start of 0-9 georgescii range? bcc .not_nat cmp #57 ; greater than end of 0-9 georgescii range? bcs .not_nat pha lda #$a9 ; $a9: lda imm jsr store_binary pla jsr georgescii_decimal_to_value jsr store_binary lda #2 ; push jsr store_subroutine iny rts .not_nat: rts ; georgescii decimal value in a register, return equivalent plain value in a register georgescii_decimal_to_value: clc sbc #$30 ; decimal digits start at georgescii $30 rts ; we have binary in the a register we want to store store_binary: phy ldy binary_base_index sta (result_binary_base), y inc binary_base_index bne .not_overflow ; did we roll over? inc result_binary_base + 1 ; yes, roll over base address .not_overflow: ; no, carry on as normal ply rts ; binary_subroutine_address is a pointer to a subroutine that we want to store ; the first byte at the subroutine's address is its length store_contiguous_binary: pha ; just to be safe lda (binary_subroutine_address) ; get the subroutine length tax ; loop counter ldy #1 ; index into subroutine, offset by one to skip subroutine length .loop: lda (binary_subroutine_address), y jsr store_binary iny dex bne .loop .end: pla rts ; this wouldn't be necessary if we could get the ; address of a label in vasm, but that's for another time ; (when i feel like writing an assembler lol) ; for now, pass the index of the subroutine (in subroutines.asm) ; to a and it will get written to binary_subroutine_address get_subroutine_address: pha tax ; set up counter bne .loop ; first subrotine? stz binary_subroutine_address ; yes, store its address lda #$80 sta binary_subroutine_address + 1 rts .loop: ; loop through lda (binary_subroutine_address) ; no, load length of subroutine inc ; distance from next subroutine clc adc binary_subroutine_address ; add it to the current address sta binary_subroutine_address bcs .no_carry lda binary_subroutine_address + 1 ; add the carry to the high byte of address adc #0 sta binary_subroutine_address + 1 .no_carry: dex ; is this our address? bne .loop ; yes, we're done pla rts ; pass subroutine index to a and it will get written into the binary ; TODO: stabilize subroutine location & just write a `jsr $subroutine` to the binary store_subroutine: pha phy phx jsr get_subroutine_address jsr store_contiguous_binary ; reset subroutine address stz binary_subroutine_address lda #$80 sta binary_subroutine_address + 1 plx ply pla rts ; write error message and stop execution error: ldy #0 .loop: lda .message, y sta $4000, y beq .end iny bra .loop .end: stp .message: .asciiz "ruh roh! fuzzy couldn't compile" isr: ; interrupt service routine pha phx phy ply plx pla rti .org $fffc .word reset .word isr