.export output_screen_0,clear_string,clear_vram,clear_screen_0,draw_metatile .export set_bg_palette,set_obj_palette,play_pcm,write_pattern_0 .export write_nametable,draw_metatile .export hex2dec8,hex2dec16 .importzp temp_lo,temp_hi,count_lo,count_hi,v2000,v2001 .importzp addr_lo,addr_hi,temp2_lo .importzp IN0,IN1,OUT0,OUT1,OUT2,OUT3,OUT4,DIGITS .import paltable .import attribute_table .include "macros.s" .segment "CODE" ;========================================================= ; draw meta-tile ; ; writes 4 nametable blocks and writes ; the corresponding attribute table block ; X = X coordinate (0 - 16) ; Y = Y coordinate (0 - 15) ; A = tile # start ; (example: A=$80, tiles $80,$81,$90,$91 used ; temp2_lo = attribute color (0 - 3) ; addr_lo,addr_hi,temp_lo,temp_hi = temp values draw_metatile: pha sty addr_hi stx addr_lo lda #0 sta temp_hi tya asl asl rol rol temp_hi rol rol temp_hi rol rol temp_hi rol rol temp_hi sta temp_lo txa asl clc adc temp_lo sta temp_lo lda temp_hi adc #$20 sta temp_hi lda #0 sta $2001 lda $2002 lda temp_hi sta $2006 lda temp_lo sta $2006 pla sta $2007 clc adc #1 sta $2007 pha lda temp_lo clc adc #$20 sta temp_lo lda temp_hi adc #0 sta $2006 lda temp_lo sta $2006 pla clc adc #$0F sta $2007 clc adc #1 sta $2007 lda addr_hi asl asl asl asl sta addr_hi lda addr_lo clc adc addr_hi tax lda #$23 sta $2006 lda attrib_addr,x ldy attrib_shift,x sta $2006 tax lda temp2_lo cpy #0 beq @zero cpy #2 beq @two cpy #4 beq @four cpy #6 beq @six @six: asl asl asl asl asl asl pha lda #%00111111 and attribute_table,x pla ora attribute_table,x jmp endit @four: asl asl asl asl pha lda #%11001111 and attribute_table,x pla ora attribute_table,x jmp endit @two: asl asl pha lda #%11110011 and attribute_table,x pla ora attribute_table,x jmp endit @zero: pha lda #%11111100 and attribute_table,x pla ora attribute_table,x endit: sta $2007 lda v2001 sta $2001 rts .segment "RODATA" attrib_addr: .byte $C0,$C0,$C1,$C1,$C2,$C2,$C3,$C3 .byte $C4,$C4,$C5,$C5,$C6,$C6,$C7,$C7 .byte $C0,$C0,$C1,$C1,$C2,$C2,$C3,$C3 .byte $C4,$C4,$C5,$C5,$C6,$C6,$C7,$C7 .byte $C8,$C8,$C9,$C9,$CA,$CA,$CB,$CB .byte $CC,$CC,$CD,$CD,$CE,$CE,$CF,$CF .byte $C8,$C8,$C9,$C9,$CA,$CA,$CB,$CB .byte $CC,$CC,$CD,$CD,$CE,$CE,$CF,$CF .byte $D0,$D0,$D1,$D1,$D2,$D2,$D3,$D3 .byte $D4,$D4,$D5,$D5,$D6,$D6,$D7,$D7 .byte $D0,$D0,$D1,$D1,$D2,$D2,$D3,$D3 .byte $D4,$D4,$D5,$D5,$D6,$D6,$D7,$D7 .byte $D8,$D8,$D9,$D9,$DA,$DA,$DB,$DB .byte $DC,$DC,$DD,$DD,$DE,$DE,$DF,$DF .byte $D8,$D8,$D9,$D9,$DA,$DA,$DB,$DB .byte $DC,$DC,$DD,$DD,$DE,$DE,$DF,$DF .byte $E0,$E0,$E1,$E1,$E2,$E2,$E3,$E3 .byte $E4,$E4,$E5,$E5,$E6,$E6,$E7,$E7 .byte $E0,$E0,$E1,$E1,$E2,$E2,$E3,$E3 .byte $E4,$E4,$E5,$E5,$E6,$E6,$E7,$E7 .byte $E8,$E8,$E9,$E9,$EA,$EA,$EB,$EB .byte $EC,$EC,$ED,$ED,$EE,$EE,$EF,$EF .byte $E8,$E8,$E9,$E9,$EA,$EA,$EB,$EB .byte $EC,$EC,$ED,$ED,$EE,$EE,$EF,$EF .byte $F0,$F0,$F1,$F1,$F2,$F2,$F3,$F3 .byte $F4,$F4,$F5,$F5,$F6,$F6,$F7,$F7 .byte $F0,$F0,$F1,$F1,$F2,$F2,$F3,$F3 .byte $F4,$F4,$F5,$F5,$F6,$F6,$F7,$F7 .byte $F8,$F8,$F9,$F9,$FA,$FA,$FB,$FB .byte $FC,$FC,$FD,$FD,$FE,$FE,$FF,$FF .byte $F8,$F8,$F9,$F9,$FA,$FA,$FB,$FB .byte $FC,$FC,$FD,$FD,$FE,$FE,$FF,$FF attrib_shift: .byte 0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2 .byte 4,6,4,6,4,6,4,6,4,6,4,6,4,6,4,6 .byte 0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2 .byte 4,6,4,6,4,6,4,6,4,6,4,6,4,6,4,6 .byte 0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2 .byte 4,6,4,6,4,6,4,6,4,6,4,6,4,6,4,6 .byte 0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2 .byte 4,6,4,6,4,6,4,6,4,6,4,6,4,6,4,6 .byte 0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2 .byte 4,6,4,6,4,6,4,6,4,6,4,6,4,6,4,6 .byte 0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2 .byte 4,6,4,6,4,6,4,6,4,6,4,6,4,6,4,6 .byte 0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2 .byte 4,6,4,6,4,6,4,6,4,6,4,6,4,6,4,6 .byte 0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2 .byte 4,6,4,6,4,6,4,6,4,6,4,6,4,6,4,6 .code ;--------------------------------------------------------- ;========================================================= ; Write nametable #0 ; ; addr_lo = pointer to nametable data write_nametable: lda #0 sta $2000 sta $2001 tay lda $2002 lda #$20 sta $2006 sty $2006 ldx #4 : lda (addr_lo),y sta $2007 iny bne :- inc addr_hi dex bne :- rts ;--------------------------------------------------------- ;========================================================= ; ; Print a string of text (or other data) ; ; to nametable #0 ($2000-$2FFF) ; ; ; ; addr_lo,addr_hi = address to null-terminated string ; ; X = X starting coordinate (0 - 31) ; ; Y = Y starting coordinate (0 - 29) ; ; Y coordinates 30 and 31 are "rows" of attribute memory ;--------------------------------------------------------- output_screen_0: lda v2000 and #%00000100 ; preserve H/V write setting sta $2000 lda #0 sta $2001 sta temp_hi lda $2002 tya asl ; calculate VRAM address rol temp_hi rol rol temp_hi rol rol temp_hi rol rol temp_hi rol rol temp_hi stx temp_lo clc adc temp_lo sta temp_lo lda temp_hi adc #$20 sta $2006 lda temp_lo sta $2006 ldy #0 : lda (addr_lo),y beq :+ sta $2007 iny bne :- inc addr_hi jmp :- : lda v2001 sta $2001 lda v2000 sta $2000 rts ;--------------------------------------------------------- ;========================================================= ; ; Clear string (write zeros) ; ; ; ; A = number of bytes to clear ; ; X = X starting coordinate (0 - 31) ; ; Y = Y starting coordinate (0 - 29) ; ; Y coordinates 30 and 31 are "rows" of attribute memory ; ; ; ; destroys: A, X, Y ; ; upon exit: X, Y = 0 ;--------------------------------------------------------- clear_string: pha lda v2000 and #%00000100 sta $2000 lda #0 sta $2001 sta temp_hi lda $2002 tya asl rol temp_hi rol rol temp_hi rol rol temp_hi rol rol temp_hi rol rol temp_hi stx temp_lo clc adc temp_lo sta temp_lo lda temp_hi adc #$20 sta $2006 lda temp_lo sta $2006 pla tax lda #0 : sta $2007 dex bne :- lda v2001 sta $2001 lda v2000 sta $2000 rts ;--------------------------------------------------------- ;========================================================= ; ; Clear Vram ; ; ($0000 - $3FFF) ; ; destroys: A, X, Y ; ; upon exit: X, Y = 0 ;--------------------------------------------------------- clear_vram: lda #0 sta $2000 sta $2001 lda $2002 lda #0 tay ldx #$40 sta $2006 sta $2006 : sta $2007 iny bne :- dex bne :- stx $2006 stx $2006 lda v2001 sta $2001 lda v2000 sta $2000 rts ;--------------------------------------------------------- ;========================================================= ; ; Clear Nametable 0 ; ; ($2000 - $2FFF) ; ; destroys: A, X, Y ; ; upon exit: X, Y = 0 ;--------------------------------------------------------- clear_screen_0: lda #0 sta $2000 sta $2001 lda $2002 lda #$20 sta $2006 lda #0 sta $2006 tax ldy #$0F : sta $2007 dex bne :- dey bne :- stx $2006 stx $2006 lda v2001 sta $2001 lda v2000 sta $2000 rts ;========================================================= ; ; Write backgroud palette (ROM) ; ; A = palette # (0 - $7F) ; ; paltable = palette address table ; ; destroys A, Y, addr_lo, addr_hi ;--------------------------------------------------------- set_bg_palette: ldy #0 sty $2000 sty $2001 asl tay lda paltable,y sta addr_lo lda paltable+1,y sta addr_hi lda $2002 lda #$3F ; write palette sta $2006 lda #0 sta $2006 tay : lda (addr_lo),y sta $2007 iny cpy #$10 bne :- lda v2001 sta $2001 lda v2000 sta $2000 rts ;--------------------------------------------------------- ;========================================================= ; ; Write sprite palette (ROM) ; ; A = palette # (0 - $7F) ; ; paltable = palette address table ; ; destroys A, Y, addr_lo, addr_hi ;--------------------------------------------------------- set_obj_palette: ldy #0 sty $2000 sty $2001 asl tay lda paltable,y sta addr_lo lda paltable+1,y sta addr_hi lda #$3F ; write palette sta $2006 lda #$10 sta $2006 ldy #0 : lda (addr_lo),y sta $2007 iny cpy #$10 bne :- lda v2001 sta $2001 lda v2000 sta $2000 rts ;--------------------------------------------------------- ;--------------------------------------------------------- ; Raw PCM player ; this takes control until the sample is finished playing ; format: 8-bit unsigned RAW 11050hz ; addr_lo,addr_hi = sample location ; count_lo,count_hi = sample length ;--------------------------------------------------------- play_pcm: ldy #0 rawloop: lda (addr_lo),y lsr sta $4011 inc16 addr_lo cmp16 addr_lo,count_lo,continue_raw rts continue_raw: ldy #10 : dey bne :- nop jmp rawloop ;--------------------------------------------------------- ;--------------------------------------------------------- ; Load CHR-RAM Pattern Table #0 ; ; addr_lo,addr_hi = address to pattern data ; A = tile number to start on ; X = number of tiles to write ; ; destroys: A, X, Y, temp_hi,addr_lo,addr_hi ;--------------------------------------------------------- write_pattern_0: ldy #0 sty temp_hi asl a rol temp_hi rol a rol temp_hi rol a rol temp_hi rol a rol temp_hi pha lda addr_lo sec sbc #$F0 ; compensate for "fast" tile loading trick sta addr_lo lda addr_hi sbc #0 sta addr_hi sty $2000 sty $2001 lda $2002 lda temp_hi sta $2006 pla sta $2006 ldy #$F0 : lda (addr_lo),y sta $2007 iny bne :- ldy #$F0 lda addr_lo clc adc #16 sta addr_lo lda addr_hi adc #0 sta addr_hi dex bne :- lda v2001 sta $2001 lda v2000 sta $2000 rts ;--------------------------------------------------------- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; HEX2DEC8 / HEX2DEC16 ; ; ; ; Converts hex numbers to decimal and counts digits. ; ; ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; HEX2DEC8 (converts 8-bit hex to 3-digit decimal) ; ; ; ; In: A (number to be converted) ; ; ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; HEX2DEC16 (converts 16-bit hex to 5-digit decimal) ; ; ; ; In: A (low byte of number to be converted) ; ; X (high byte ") ; ; ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; Out: OUT.0 - OUT.4 (the converted number) ; ; DIGITS (digit count; 1 = 1-digit, etc) ; ; ; ; Modifies: A, X, IN.0, IN.1, OUT.0 - OUT.4 ; ; ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; hex2dec_d4: .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3 hex2dec_d3: .byte 0,0,0,0,0,0,0,0,0,0,1,2,4,8,6,2 hex2dec_d2: .byte 0,0,0,0,0,0,0,1,2,5,0,0,0,1,3,7 hex2dec_d1: .byte 0,0,0,0,1,3,6,2,5,1,2,4,9,9,8,6 hex2dec_d0: .byte 1,2,4,8,6,2,4,8,6,2,4,8,6,2,4,8 hex2dec8: ldx #0 hex2dec16: sta IN0 stx IN1 ldx #0 stx OUT0 stx OUT1 stx OUT2 stx OUT3 stx OUT4 do_hex2dec: lsr IN1 ror IN0 bcc hex2dec_no_add lda OUT0 adc hex2dec_d0,x cmp #10 bcs no_d0_carry sec sbc #10 inc OUT1 no_d0_carry: sta OUT0 lda OUT1 adc hex2dec_d1,x cmp #10 bcs no_d1_carry sec sbc #10 inc OUT2 no_d1_carry: sta OUT1 lda OUT2 adc hex2dec_d2,x cmp #10 bcs no_d2_carry sec sbc #10 inc OUT3 no_d2_carry: sta OUT2 lda OUT3 adc hex2dec_d3,x cmp #10 bcs no_d3_carry sec sbc #10 inc OUT3 no_d3_carry: sta OUT3 lda OUT4 adc hex2dec_d4,x sta OUT4 hex2dec_no_add: inx cpx #5 bne do_hex2dec digit_count: dex cpx #$FF bne digit_count_continue ldx #1 jmp digit_count_finished digit_count_continue: lda OUT0,x beq digit_count digit_count_finished: stx DIGITS rts