From a43f875f190b99cb5f4efab34e3323478b02a27e Mon Sep 17 00:00:00 2001 From: Vince Weaver Date: Mon, 10 Dec 2018 13:06:21 -0500 Subject: [PATCH] xmas2018: something that builds --- xmas_2018/Makefile | 3 + xmas_2018/delay_a.s | 25 +++++ xmas_2018/gr_fast_clear.s | 192 ++++++++++++++++++++++++++++++++++ xmas_2018/gr_hline.s | 44 ++++++++ xmas_2018/gr_offsets.s | 4 + xmas_2018/gr_putsprite.s | 137 ++++++++++++++++++++++++ xmas_2018/lz4_decode.s | 213 ++++++++++++++++++++++++++++++++++++++ xmas_2018/mockingboard.s | 2 +- xmas_2018/wait_keypress.s | 5 + xmas_2018/wreath.s | 148 ++++---------------------- xmas_2018/xmas2018.s | 175 +++++-------------------------- 11 files changed, 673 insertions(+), 275 deletions(-) create mode 100644 xmas_2018/delay_a.s create mode 100644 xmas_2018/gr_fast_clear.s create mode 100644 xmas_2018/gr_hline.s create mode 100644 xmas_2018/gr_offsets.s create mode 100644 xmas_2018/gr_putsprite.s create mode 100644 xmas_2018/lz4_decode.s create mode 100644 xmas_2018/wait_keypress.s diff --git a/xmas_2018/Makefile b/xmas_2018/Makefile index 293bbe3b..c59c57da 100644 --- a/xmas_2018/Makefile +++ b/xmas_2018/Makefile @@ -37,6 +37,9 @@ xmas2018.o: xmas2018.s \ #D_HGRC.BIN: d_hgr.bmp # $(B2D) d_hgr.bmp HGR -d +wreath.img.lz4: wreath.img + lz4 -f -16 wreath.img + wreath.img: WREATHC.BIN cp WREATHC.BIN wreath.img diff --git a/xmas_2018/delay_a.s b/xmas_2018/delay_a.s new file mode 100644 index 00000000..2d0802da --- /dev/null +++ b/xmas_2018/delay_a.s @@ -0,0 +1,25 @@ +; From http://6502org.wikidot.com/software-delay + +; 25+A cycles (including JSR), 19 bytes (excluding JSR) +; +; The branches must not cross page boundaries! +; + + ; Cycles Accumulator Carry flag + ; 0 1 2 3 4 5 6 (hex) 0 1 2 3 4 5 6 + +; jsr delay_a ; 6 6 6 6 6 6 6 00 01 02 03 04 05 06 + +dly0: sbc #7 +delay_a:cmp #7 ; 2 2 2 2 2 2 2 00 01 02 03 04 05 06 0 0 0 0 0 0 0 + bcs dly0 ; 2 2 2 2 2 2 2 00 01 02 03 04 05 06 0 0 0 0 0 0 0 + lsr ; 2 2 2 2 2 2 2 00 00 01 01 02 02 03 0 1 0 1 0 1 0 + bcs dly1 ; 2 3 2 3 2 3 2 00 00 01 01 02 02 03 0 1 0 1 0 1 0 +dly1: beq dly2 ; 3 3 2 2 2 2 2 00 00 01 01 02 02 03 0 1 0 1 0 1 0 + lsr ; 2 2 2 2 2 00 00 01 01 01 1 1 0 0 1 + beq dly3 ; 3 3 2 2 2 00 00 01 01 01 1 1 0 0 1 + bcc dly3 ; 3 3 2 01 01 01 0 0 1 +dly2: bne dly3 ; 2 2 3 00 00 01 0 1 0 +dly3: rts ; 6 6 6 6 6 6 6 00 00 00 00 01 01 01 0 1 1 1 0 0 1 + ; + ; Total cycles: 25 26 27 28 29 30 31 diff --git a/xmas_2018/gr_fast_clear.s b/xmas_2018/gr_fast_clear.s new file mode 100644 index 00000000..796b985a --- /dev/null +++ b/xmas_2018/gr_fast_clear.s @@ -0,0 +1,192 @@ +clear_screens: + ;=================================== + ; Clear top/bottom of page 0 + ;=================================== + + lda #$0 + sta DRAW_PAGE + jsr clear_top + jsr clear_bottom + + ;=================================== + ; Clear top/bottom of page 1 + ;=================================== + + lda #$4 + sta DRAW_PAGE + jsr clear_top + jsr clear_bottom + + rts + +clear_bottoms: + ;=================================== + ; Clear bottom of page 0 + ;=================================== + + lda #$0 + sta DRAW_PAGE + jsr clear_bottom + + ;=================================== + ; Clear bottom of page 1 + ;=================================== + + lda #$4 + sta DRAW_PAGE + jsr clear_bottom + + rts + + + + ;========================================================= + ; clear_top + ;========================================================= + ; clear DRAW_PAGE + ; original = 14,558 cycles(?) 15ms, 70Hz + ; OPTIMIZED MAX (page0,48rows): 45*120+4+6 = 5410 = 5.4ms 185Hz + ; (pageX,40rows): 50*120+4+6 = 6010 = 6.0ms 166Hz + ; 50*120+4+6+37 = 6055 = 6.0ms 166Hz +clear_top: + lda #0 ; 2 +clear_top_a: + sta COLOR ; 3 + clc ; 2 + lda DRAW_PAGE ; 3 + + adc #4 ; 2 + sta __ctf+2 ; 3 + sta __ctf+5 ; 3 + adc #1 ; 2 + sta __ctf+8 ; 3 + sta __ctf+11 ; 3 + adc #1 ; 2 + sta __ctf2+2 ; 3 + sta __ctf2+5 ; 3 + adc #1 ; 2 + sta __ctf2+8 ; 3 + sta __ctf2+11 ; 3 + + + ldy #120 ; 2 + lda COLOR ; 3 +clear_top_fast_loop: +__ctf: + sta $400,Y ; 5 + sta $480,Y ; 5 + sta $500,Y ; 5 + sta $580,Y ; 5 + + cpy #80 ; 2 + bpl no_draw_bottom ; 2nt/3 +__ctf2: + sta $600,Y ; 5 + sta $680,Y ; 5 + sta $700,Y ; 5 + sta $780,Y ; 5 +no_draw_bottom: + + dey ; 2 + bpl clear_top_fast_loop ; 2nt/3 + + rts ; 6 + + + + + ;========================================================= + ; clear_bottom + ;========================================================= + ; clear bottom of draw page + +clear_bottom: + clc ; 2 + lda DRAW_PAGE ; 3 + + adc #6 ; 2 + sta __cbf2+2 ; 3 + sta __cbf2+5 ; 3 + adc #1 ; 2 + sta __cbf2+8 ; 3 + sta __cbf2+11 ; 3 + + + ldy #120 ; 2 + lda #$a0 ; Normal Space ; 2 +clear_bottom_fast_loop: +__cbf2: + sta $600,Y ; 5 + sta $680,Y ; 5 + sta $700,Y ; 5 + sta $780,Y ; 5 + + dey ; 2 + cpy #80 ; 2 + bpl clear_bottom_fast_loop ; 2nt/3 + + rts ; 6 + + +clear_screens_notext: + ;=================================== + ; Clear top/bottom of page 0 + ;=================================== + + lda #$0 + sta DRAW_PAGE + jsr clear_all + + ;=================================== + ; Clear top/bottom of page 1 + ;=================================== + + lda #$4 + sta DRAW_PAGE + jsr clear_all + + rts + + + ;========================================================= + ; clear_all + ;========================================================= + ; clear 48 rows + +clear_all: + clc ; 2 + lda DRAW_PAGE ; 3 + + adc #4 ; 2 + sta __caf+2 ; 3 + sta __caf+5 ; 3 + adc #1 ; 2 + sta __caf+8 ; 3 + sta __caf+11 ; 3 + adc #1 ; 2 + sta __caf2+2 ; 3 + sta __caf2+5 ; 3 + adc #1 ; 2 + sta __caf2+8 ; 3 + sta __caf2+11 ; 3 + + + ldy #120 ; 2 +clear_all_color: + lda #0 ; 2 +clear_all_fast_loop: +__caf: + sta $400,Y ; 5 + sta $480,Y ; 5 + sta $500,Y ; 5 + sta $580,Y ; 5 +__caf2: + sta $600,Y ; 5 + sta $680,Y ; 5 + sta $700,Y ; 5 + sta $780,Y ; 5 + + dey ; 2 + bpl clear_all_fast_loop ; 2nt/3 + + rts ; 6 diff --git a/xmas_2018/gr_hline.s b/xmas_2018/gr_hline.s new file mode 100644 index 00000000..002d795e --- /dev/null +++ b/xmas_2018/gr_hline.s @@ -0,0 +1,44 @@ + ;================================== + ; HLINE + ;================================== + ; Color in A + ; Y has which line + ; takes 435 cycles +hline: + pha ; 3 + ldx gr_offsets,y ; 4+ + stx hline_loop+1 ; self-modify code ; 4 + lda gr_offsets+1,y ; 4+ + clc ; 2 + adc DRAW_PAGE ; 3 + sta hline_loop+2 ; self-modify code ; 4 + pla ; 4 + ldx #39 ; 2 + ;=========== + ; 30 +hline_loop: + sta $5d0,X ; 38 ; 5 + dex ; 2 + bpl hline_loop ; 2nt/3 + ;=========== + ; 40*(10)=400 + + ; -1 + rts ; 6 + + ;========================== + ; Clear gr screen + ;========================== + ; Color in A, Clears 0 to and including Y + ; clear_gr: takes 2+(48/2)*(6+435+7)+5 = 10759 + ; cpl: takes (Y/2)*(6+435+7)+5 = ? +clear_gr: + ldy #46 ; 2 +clear_page_loop: + jsr hline ; 6+435 + dey ; 2 + dey ; 2 + bpl clear_page_loop ; 2/3 + rts ; 6 + + diff --git a/xmas_2018/gr_offsets.s b/xmas_2018/gr_offsets.s new file mode 100644 index 00000000..32bbfe08 --- /dev/null +++ b/xmas_2018/gr_offsets.s @@ -0,0 +1,4 @@ +gr_offsets: + .word $400,$480,$500,$580,$600,$680,$700,$780 + .word $428,$4a8,$528,$5a8,$628,$6a8,$728,$7a8 + .word $450,$4d0,$550,$5d0,$650,$6d0,$750,$7d0 diff --git a/xmas_2018/gr_putsprite.s b/xmas_2018/gr_putsprite.s new file mode 100644 index 00000000..a81ac0c6 --- /dev/null +++ b/xmas_2018/gr_putsprite.s @@ -0,0 +1,137 @@ + + ;============================================= + ; 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 + +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 + + diff --git a/xmas_2018/lz4_decode.s b/xmas_2018/lz4_decode.s new file mode 100644 index 00000000..4355da11 --- /dev/null +++ b/xmas_2018/lz4_decode.s @@ -0,0 +1,213 @@ +; LZ4 data decompressor for Apple II + +; Code by Peter Ferrie (qkumba) (peter.ferrie@gmail.com) +; "LZ4 unpacker in 143 bytes (6502 version) (2013)" +; http://pferrie.host22.com/misc/appleii.htm +; This is that code, but with comments and labels added for clarity. +; I also found a bug when decoding with runs of multiples of 256 +; which has since been fixed upstream. + +; For LZ4 reference see +; https://github.com/lz4/lz4/wiki/lz4_Frame_format.md + +; LZ4 summary: +; +; HEADER: +; Should: check for magic number 04 22 4d 18 +; FLG: 64 in our case (01=version, block.index=1, block.checksum=0 +; size=0, checksum=1, reserved +; MAX Blocksize: 40 (64kB) +; HEADER CHECKSUM: a7 +; BLOCK HEADER: 4 bytes (le) length If highest bit set, uncompressed! +; data (see below), followed by checksum? +; BLOCKS: +; Token byte. High 4-bits literal length, low 4-bits copy length +; + If literal length==15, then following byte gets added to length +; If that byte was 255, then keep adding bytes until not 255 +; + The literal bytes follow. There may be zero of them +; + Next is block copy info. little-endian 2-byte offset to +; be subtracted from current read position indicating source +; + The low 4-bits of the token are the copy length, which needs +; 4 added to it. As with the literal length, if it is 15 then +; you read a byte and add (and if that byte is 255, keep adding) + +; At end you have 4 byte end-of-block marker (all zeros?) then +; 4 bytes of checksum (if marked in flags) +; our code does that, so be sure to set end -8 + + +;LZ4_SRC EQU $00 +;LZ4_DST EQU $02 +;LZ4_END EQU $04 +;COUNT EQU $06 +;DELTA EQU $08 + +;UNPACK_BUFFER EQU $5E00 ; offset of first unpacked byte + + + ;====================== + ; LZ4 decode + ;====================== + ; input buffer in LZ4_SRC + ; output buffer hardcoded still + ; size in ENDH:ENDL + +lz4_decode: +; lda LZ4_SRC ; packed data offset +; clc +; adc LZ4_END +; sta LZ4_END +; lda LZ4_SRC+1 +; adc LZ4_END+1 +; sta LZ4_END+1 + +; lda #>UNPACK_BUFFER ; original unpacked data offset +; sta LZ4_DST+1 +; lda #sb_background_hgr + lda #>wreath_hgr sta LZ4_SRC+1 - lda #<(sb_background_hgr_end-8) ; skip checksum at end + lda #<(wreath_hgr_end-8) ; skip checksum at end sta LZ4_END - lda #>(sb_background_hgr_end-8) ; skip checksum at end + lda #>(wreath_hgr_end-8) ; skip checksum at end sta LZ4_END+1 lda #<$2000 @@ -50,7 +50,7 @@ wreath: ; so we have 5070 + 4550 = 9620 to kill - jsr gr_copy_to_current ; 6+ 9292 +; jsr gr_copy_to_current ; 6+ 9292 ; now we have 322 left @@ -137,17 +137,17 @@ sb_hgr_loop: ; draw sprite at same time - lda #>ship_forward ; 2 - sta INH ; 3 - lda #ship_forward ; 2 +; sta INH ; 3 +; lda #ship_forward - sta INH - lda #ship_forward +; sta INH +; lda #ship_small - sta INH - lda #ship_tiny - sta INH - lda # .include "zp.inc" @@ -7,12 +7,12 @@ ; external routines -play_music=$1000 -mockingboard_init=$1100 -mockingboard_mute=$11a1 +;play_music=$1000 +;mockingboard_init=$1100 +;mockingboard_mute=$11a1 -megademo_start: ; this should end up at $4000 +xmas2018_start: ; this should end up at $4000 ;=================== ; Check for Apple II and patch @@ -22,8 +22,8 @@ megademo_start: ; this should end up at $4000 cmp #6 beq apple_iie - lda #$54 ; patch the check_email font code - sta ce_patch+1 +; lda #$54 ; patch the check_email font code +; sta ce_patch+1 apple_iie: @@ -44,146 +44,51 @@ apple_iie: ;=================== jsr HOME -; jsr space_bars - -; jsr arriving_there - -; jsr fireworks - - ; C64 Opening Sequence - - jsr c64_opener - - ; Falling Apple II - - jsr falling_apple - - ; Starring Screens - jsr starring - - jsr setup_people_fs - jsr starring_people - jsr setup_people_deater - jsr starring_people - jsr setup_people_lg - jsr starring_people - - ; E-mail arriving - jsr check_email - - ; Leaving house - jsr leaving_home - - ; Riding bird - jsr bird_mountain - - ; Waterfall - jsr waterfall - - ; Enter ship - jsr rocket_takeoff - - ; mode7 (???) - jsr mode7_flying - - ; Fly in space - jsr space_bars - - ; Arrive - jsr arriving_there - - ; Fireworks - jsr fireworks + jsr wreath ;================== ; Game over ;================== ; we never get here -;game_over_man: -; jmp game_over_man +game_over_man: + jmp game_over_man .align $100 + .include "wreath.s" .include "lz4_decode.s" - .include "c64_opener.s" - .include "falling_apple.s" - .include "gr_unrle.s" - .include "gr_copy.s" - .include "starring.s" - .include "starring_people.s" - .include "check_email.s" -.align $100 .include "gr_offsets.s" .include "gr_hline.s" + .include "gr_fast_clear.s" .include "vapor_lock.s" .include "delay_a.s" -; .include "wait_keypress.s" - .include "random16.s" -.align $100 - .include "fireworks.s" - .include "hgr.s" - .include "bird_mountain.s" - .include "move_letters.s" -.align $100 + .include "wait_keypress.s" + .include "mockingboard.s" +; .include "random16.s" +; .include "hgr.s" +; .include "move_letters.s" .include "gr_putsprite.s" - .include "mode7.s" - .include "space_bars.s" - .include "takeoff.s" - .include "leaving.s" - .include "arrival.s" - .include "waterfall.s" - .include "text_print.s" -.align $100 - .include "screen_split.s" +; .include "text_print.s" +; .include "screen_split.s" ;============================ ; Include Sprites ;============================ -.align $100 - .include "tfv_sprites.inc" - .include "mode7_sprites.inc" +;.align $100 +; .include "tfv_sprites.inc" +; .include "mode7_sprites.inc" ;================================= ; Include Text for Sliding Letters ; *DONT CROSS PAGES* ;================================= -.include "letters.s" +;.include "letters.s" ;============================ ; Include Lores Graphics ; No Alignment Needed ;============================ -; falling_apple -.include "apple_40_96.inc" - -; starring -.include "starring1.inc" -.include "starring2.inc" -.include "fs.inc" -.include "deater.inc" -.include "lg.inc" -.include "sp_names.inc" - -; e-mail -.include "email_40_96.inc" - -; leaving -.include "leaving.inc" - -; waterfall -.include "waterfall_page1.inc" -.include "waterfall_page2.inc" - -; takeoff -.include "takeoff.inc" - -; arrival -.include "arrival.inc" - -;background: -.include "fw_background.inc" - ;============================ ; Include Hires Graphics ; No Alignment Needed @@ -191,34 +96,8 @@ apple_iie: ;============================ ; starring -starring3: -.incbin "starring3.img.lz4",11 -starring3_end: -fs_hgr: -.incbin "FS_HGRC.BIN.lz4",11 -fs_hgr_end: -deater_hgr: -.incbin "DEATER_HGRC.BIN.lz4",11 -deater_hgr_end: -lg_hgr: -.incbin "LG_HGRC.BIN.lz4",11 -lg_hgr_end: - -; bird mountain -katahdin: -.incbin "KATC.BIN.lz4",11 ; skip the header -katahdin_end: - -; takeoff -takeoff_hgr: -.incbin "takeoff.img.lz4",11 -takeoff_hgr_end: - -; spacebars -sb_background_hgr: -.incbin "SB_BACKGROUNDC.BIN.lz4",11 -sb_background_hgr_end: - - +wreath_hgr: +.incbin "wreath.img.lz4",11 +wreath_hgr_end: