.include "zp.inc" FRAME = $60 TREE1X = $61 TREE2X = $62 LETTERL = $63 LETTERH = $64 LETTERX = $65 LETTERY = $66 LETTERD = $67 LETTER = $68 BLARGH = $69 MBASE = $97 MBOFFSET = $98 ;=================== ; init screen jsr TEXT jsr HOME ;================== ; Init vars lda #28 sta TREE1X lda #37 sta TREE2X lda #0 sta MBOFFSET lda #>music sta MBASE lda #letters sta LETTERH lda #39 sta LETTERX lda #1 sta LETTERY lda #15 sta LETTERD lda #0 sta DISP_PAGE lda #0 sta DRAW_PAGE ;========================== ; setup mockingboard jsr mockingboard_detect_slot4 stx MB_DETECTED ldx MB_DETECTED beq no_init_mb jsr mockingboard_init no_init_mb: ;========================== ; setup text screen lda #0 sta CH sta CV lda #line1 sta OUTH jsr move_and_print inc CV jsr move_and_print inc CV jsr move_and_print inc CV jsr move_and_print inc CV jsr move_and_print inc CV jsr move_and_print ; draw the moon lda #0 sta CV lda #3 sta CH jsr htab_vtab ; vtab(1); htab(4) lda #32 ; inverse space ldy #0 sta (BASL),Y inc CV dec CH jsr htab_vtab lda #32 ldy #0 sta (BASL),Y inc CV jsr htab_vtab lda #32 ldy #0 sta (BASL),Y inc CV inc CH jsr htab_vtab lda #32 ldy #0 sta (BASL),Y ; test letters ;letter_loop: ; lda #80 ; jsr WAIT ; jsr move_letters ; jmp letter_loop ; Wait ; jsr wait_until_keypressed ; GR part bit LORES bit SET_GR bit FULLGR jsr draw_bottom_green ; 6 ; Wait ; jsr wait_until_keypressed bit HIRES ; Wait ; jsr wait_until_keypressed ;===================================================== ; attempt vapor lock ; by reading the "floating bus" we can see most recently ; written value of the display ; we look for $44 (which is the green grass on low-res) ;===================================================== ; See: ; Have an Apple Split by Bob Bishop ; Softalk, October 1982 ; Challenges: each scan line scans 40 bytes. ; The blanking happens at the *beginning* ; So 65 bytes are scanned, starting at adress of the line - 25 ; the scan takes 8 cycles, look for 4 repeats of the value ; to avoid false positive found if the horiz blanking is mirroring ; the line (max 3 repeats in that case) vapor_lock_loop: LDA #$A0 zxloop: LDX #$04 wiloop: CMP $C051 BNE zxloop DEX BNE wiloop LDA #$44 zloop: LDX #$04 qloop: CMP $C051 BNE zloop DEX BNE qloop ; found first line of low-res green, need to kill time ; until we can enter at top of screen ; so we want roughly 5200+4550 - 65 (for the scanline we missed) ; want 9685 ; Try X=34 Y=55 cycles=9681 lda #0 ; 2 lda #0 ; 2 ldy #55 ; 2 loopA: ldx #34 ; 2 loopB: dex ; 2 bne loopB ; 2nt/3 dey ; 2 bne loopA ; 2nt/3 jmp display_loop .align $100 ;===================================================== ;===================================================== ; Loop forever display loop ;===================================================== ;===================================================== display_loop: ; each scan line 65 cycles ; 1 cycle each byte (40cycles) + 25 for horizontal ; Total of 12480 cycles to draw screen ; Vertical blank = 4550 cycles (70 scan lines) ; Total of 17030 cycles to get back to where was ; 16666 = 17030 x=1021.8 ; 1000 x ; TODO: find beginning of scan ; Text mode for 6*8=48 scanlines (3120 cycles) ; hgr for 64 scalines (4160 cycles) ; gr for 80 scalines (5200 cycles) ; vblank = 4550 cycles ; text bit SET_TEXT ; 4 ;================ ; clear bottom green jsr draw_bottom_green ; 2209+6 ;================ ; Draw Small Tree lda #>small_tree ; 2 sta INH ; 3 lda #big_tree ; 2 sta INH ; 3 lda #bird_rider_stand_right ; 2 sta INH ; 3 lda #bird_rider_walk_right ; 2 sta INH ; 3 lda #music+5 ; 2 bne waste_7 ; ; 2 lda MBOFFSET ; 3 cmp #16 ; 2 bne waste_12 ; ; 2 lda #>music ; 2 sta MBASE ; 3 lda #0 ; 2 sta MBOFFSET ; 3 jmp not_ready_to_loop ; 3 waste_7: lda #0 ; 2 inc BLARGH ; 5 waste_12: ; 3 lda #0 ; 2 inc BLARGH ; 5 inc BLARGH ; 5 not_ready_to_loop: ; lores want 5200 ; mockingboard -492 ; wrap -24 ; softswitch -4 ;=================== ; 4680 cycles ; Try X=7 Y=114 cycles=4675 R5 inc BLARGH ; 5 ; lda #0 ; 2 ; lda #0 ; 2 ; lda #0 ; 2 ; lda #0 ; 2 ldy #114 ; 2 loop5: ldx #7 ; 2 loop6: dex ; 2 bne loop6 ; 2nt/3 dey ; 2 bne loop5 ; 2nt/3 ;======================================================================== ; vertical blank ; want 4550 cycles ; Try X=13 Y=64 cycles=4545 R2 ;========================================================================= jsr move_letters ; 6+110 ; Blanking time: 4550 ; move_letters -116 ; JMP at end -3 ;========================4431 cycles ; Try X=176 Y=5 cycles=4431 ; lda #0 ; 2 ; lda #0 ; 2 ldy #5 ; 2 loop7: ldx #176 ; 2 loop8: dex ; 2 bne loop8 ; 2nt/3 dey ; 2 bne loop7 ; 2nt/3 jmp display_loop ; 3 ;=========================================================== ;=========================================================== ;=========================================================== ;wait_until_keypressed: ; lda KEYPRESS ; check if keypressed ; bpl wait_until_keypressed ; if not, loop ; bit KEYRESET ; rts ;============================================= ; put_sprite ;============================================= ; Sprite to display in INH,INL ; Location is XPOS,YPOS ; Note, only works if YPOS is multiple of two ; time= 28 setup ; Y*outerloop ; outerloop = 34 setup ; X*innerloop ; innerloop = 30 if $00 17+13(done) ; 64 if $0X 16+7+8+20(put_sprite_mask)+13(done) ; 69 if $X0 16+8+7+5+20(put_sprite_mask)+13(done) ; 54 if if $XX 16+8+8+9(put_all)+13(done) ; -1 for last iteration ; 18 (-1 for last) ; 6 return ; so cost = 28 + Y*(34+18)+ (INNER-Y) -1 + 6 ; = 33 + Y*(52)+(INNER-Y) ; = 33 + Y*(52)+ [30A + 64B + 69C + 54D]-Y .align $100 put_sprite: ldy #0 ; byte 0 is xsize ; 2 lda (INL),Y ; 5 sta CH ; xsize is in CH ; 3 iny ; 2 lda (INL),Y ; byte 1 is ysize ; 5 sta CV ; ysize is in CV ; 3 iny ; 2 lda YPOS ; make a copy of ypos ; 3 sta TEMPY ; as we modify it ; 3 ;=========== ; 28 put_sprite_loop: sty TEMP ; save sprite pointer ; 3 ldy TEMPY ; 3 lda gr_offsets,Y ; lookup low-res memory address ; 4 clc ; 2 adc XPOS ; add in xpos ; 3 sta OUTL ; store out low byte of addy ; 3 lda gr_offsets+1,Y ; look up high byte ; 4 adc DRAW_PAGE ; ; 3 sta OUTH ; and store it out ; 3 ldy TEMP ; restore sprite pointer ; 3 ; OUTH:OUTL now points at right place ldx CH ; load xsize into x ; 3 ;=========== ; 34 put_sprite_pixel: lda (INL),Y ; get sprite colors ; 5 iny ; increment sprite pointer ; 2 sty TEMP ; save sprite pointer ; 3 ldy #$0 ; 2 ; check if completely transparent ; if so, skip cmp #$0 ; if all zero, transparent ; 2 beq put_sprite_done_draw ; don't draw it ; 2nt/3 ;============== ; 16/17 sta COLOR ; save color for later ; 3 ; check if top pixel transparent and #$f0 ; check if top nibble zero ; 2 bne put_sprite_bottom ; if not skip ahead ; 2nt/3 ;============== ; 7/8 lda #$f0 ; setup mask ; 2 sta MASK ; 3 bmi put_sprite_mask ; always? ; 3 ;============= ; 8 put_sprite_bottom: lda COLOR ; re-load color ; 3 and #$0f ; check if bottom nibble zero ; 2 bne put_sprite_all ; if not, skip ahead ; 2nt/3 ;============= ; 7/8 lda #$0f ; 2 sta MASK ; setup mask ; 3 ;=========== ; 5 put_sprite_mask: lda (OUTL),Y ; get color at output ; 5 and MASK ; mask off unneeded part ; 3 ora COLOR ; or the color in ; 3 sta (OUTL),Y ; store it back ; 6 jmp put_sprite_done_draw ; we are done ; 3 ;=========== ; 20 put_sprite_all: lda COLOR ; load color ; 3 sta (OUTL),Y ; and write it out ; 6 ;============ ; 9 put_sprite_done_draw: ldy TEMP ; restore sprite pointer ; 3 inc OUTL ; increment output pointer ; 5 dex ; decrement x counter ; 2 bne put_sprite_pixel ; if not done, keep looping ; 2nt/3 ;============== ; 12/13 inc TEMPY ; each line has two y vars ; 5 inc TEMPY ; 5 dec CV ; decemenet total y count ; 5 bne put_sprite_loop ; loop if not done ; 2nt/3 ;============== ; 17/18 rts ; return ; 6 ;==================================== ; Draw bottom green ;==================================== ; using hlin 7127, optimized a bit but still awful ; this one is much better ; 2209 cycles draw_bottom_green: lda #$44 ; 2 ldx #39 ; 2 green_loop: sta $728,X ; 28 ; 5 sta $7a8,X ; 30 ; 5 sta $450,X ; 32 ; 5 sta $4d0,X ; 34 ; 5 sta $550,X ; 36 ; 5 sta $5d0,X ; 38 ; 5 sta $650,X ; 40 ; 5 sta $6d0,X ; 42 ; 5 sta $750,X ; 44 ; 5 sta $7d0,X ; 46 ; 5 dex ; 2 bpl green_loop ; 2nt/3 rts ; 6 ; 4 + (40*55) + 6 - 1 ;=============================================== ; Move Letters ;=============================================== ; Normal =10+25+38+9 = 82 need 28 (28) ; End of line =10+25+38+37 = 110 ; Next line =10+5+12+34 = 61 need 49 (28+21) ; done entirely =10+5+9 = 24 need 86 (28+21+37) ; all forced to be 109 move_letters: ldy #0 ; 2 lda (LETTERL),Y ; 5 sta LETTER ; 3 ;========== ; 10 bmi letter_special ; 2 lda LETTERY ; 3 asl ; 2 tay ; 2 lda gr_offsets,Y ; lookup low-res memory address ; 4 sta BASL ; store out low byte of addy ; 3 lda gr_offsets+1,Y ; look up high byte ; 4 sta BASH ; 3 lda #0 ; cycle-killer ; 2 ;========== ; 25 ldy #0 ; erase old char with space ; 2 lda #' '|$80 ; 2 ldy LETTERX ; 3 sta (BASL),Y ; 6 dey ; draw new char ; 2 sty LETTERX ; 3 lda LETTER ; 3 ora #$80 ; 2 ldy LETTERX ; 3 sta (BASL),Y ; 6 lda LETTERX ; 3 cmp LETTERD ; 3 ;=========== ; 38 beq letter_next ; 2 lda #0 ; 2 lda #0 ; 2 jmp waste_28 ; 3 ;========== ; 9 letter_next: ; 3 clc ; 2 lda LETTERL ; 3 adc #1 ; 2 sta LETTERL ; 3 lda LETTERH ; 3 adc #0 ; 2 sta LETTERH ; 3 inc LETTERD ; 5 lda #39 ; 2 sta LETTERX ; 3 rts ; 6 ;=========== ; 37 letter_special: ; 3 cmp #$ff ; 2 ;========== ; 5 beq letter_done ; 2 ldy #1 ; 2 lda (LETTERL),Y ; 5 sta LETTERY ; 3 ;=========== ; 12 iny ; 2 lda (LETTERL),Y ; 5 sta LETTERD ; 3 clc ; 2 lda LETTERL ; 3 adc #3 ; 2 sta LETTERL ; 3 lda LETTERH ; 3 adc #0 ; 2 sta LETTERH ; 3 lda LETTERH ; waste ; 3 jmp waste_21 ; 3 ;=========== ; 34 letter_done: ; 3 lda LETTERH ; 3 lda LETTERH ; 3 waste_37: ldx #0 ; 2 inc BLARGH ; 5 inc BLARGH ; 5 inc BLARGH ; 5 inc BLARGH ; 5 inc BLARGH ; 5 inc BLARGH ; 5 inc BLARGH ; 5 waste_21: ldx #0 ; 2 ldx #0 ; 2 ldx #0 ; 2 inc BLARGH ; 5 inc BLARGH ; 5 inc BLARGH ; 5 waste_28: ldx #0 ; 2 inc BLARGH ; 5 inc BLARGH ; 5 inc BLARGH ; 5 inc BLARGH ; 5 rts ; 6 letters: ;.byte 1,15 .byte "T A L B O T",128 .byte 2,14,"F A N T A S Y",128 .byte 3,16,"S E V E N",128 .byte 1,15," ",128 .byte 2,14," ",128 .byte 3,16," ",128 .byte 1,19,"BY",128 .byte 3,14,"VINCE WEAVER",128 .byte 1,19," ",128 .byte 3,14," ",128 .byte 1,16,"MUSIC BY",128 .byte 3,12,"HIROKAZU TANAKA",128 .byte 1,16," ",128 .byte 3,12," ",128 .byte 2,13,"CYCLE COUNTING",128 .byte 3,16,"IS HARD!" .byte 255 line1:.asciiz " * . " line2:.asciiz " * . . " line3:.asciiz " * " line4:.asciiz " * " line5:.asciiz " . . . " line6:.asciiz " . " .include "../asm_routines/text_print.s" .include "mockingboard.s" .align $100 .include "../asm_routines/gr_offsets.s" .include "tfv_sprites.inc" .align $1000 graphics: .incbin "KATC.BIN" music: .incbin "music.tfv"