From 0d1f5cc0e600a0edb4011ea67a7bed7a59198f72 Mon Sep 17 00:00:00 2001 From: Vince Weaver Date: Wed, 11 Aug 2021 15:49:03 -0400 Subject: [PATCH] peasant: intro animation works, but is *really* slow --- games/peasant/Makefile | 3 +- games/peasant/decompress_overlay.s | 315 +++++++++++++++++++++++++++++ games/peasant/hardware.inc | 8 +- games/peasant/hgr_overlay.s | 300 +++++++++++++++++++++++++++ games/peasant/intro.s | 48 ++++- 5 files changed, 665 insertions(+), 9 deletions(-) create mode 100644 games/peasant/decompress_overlay.s create mode 100644 games/peasant/hgr_overlay.s diff --git a/games/peasant/Makefile b/games/peasant/Makefile index 2e506547..1d46f5db 100644 --- a/games/peasant/Makefile +++ b/games/peasant/Makefile @@ -46,7 +46,8 @@ qload.o: qload.s qboot.inc INTRO: intro.o ld65 -o INTRO intro.o -C $(LINKER_SCRIPTS)/apple2_6000.inc -intro.o: intro.s graphics_intro/intro_graphics.inc +intro.o: intro.s decompress_fast_v2.s hgr_overlay.s \ + graphics_intro/intro_graphics.inc ca65 -o intro.o intro.s -l intro.lst ### diff --git a/games/peasant/decompress_overlay.s b/games/peasant/decompress_overlay.s new file mode 100644 index 00000000..307e5a73 --- /dev/null +++ b/games/peasant/decompress_overlay.s @@ -0,0 +1,315 @@ +; NOTE! DOES NOT WORK + +; alogithm uses the result as a lookup table so if you try to modify +; before writing then everything gets corrupt + + +; note -- modified by Vince Weaver to assemble with ca65 +; in this case, A = page to decompress to +; getsrc_smc+1, getsrc_smc+2 is src location + +; ----------------------------------------------------------------------------- +; Decompress raw LZSA2 block. +; Create one with lzsa -r -f2 +; +; in: +; * LZSA_SRC_LO and LZSA_SRC_HI contain the compressed raw block address +; * LZSA_DST_LO and LZSA_DST_HI contain the destination buffer address +; +; out: +; * LZSA_DST_LO and LZSA_DST_HI contain the last decompressed byte address, +1 +; +; ----------------------------------------------------------------------------- +; Backward decompression is also supported, use lzsa -r -b -f2 +; To use it, also define BACKWARD_DECOMPRESS=1 before including this code! +; +; in: +; * LZSA_SRC_LO/LZSA_SRC_HI must contain the address of the last byte of compressed data +; * LZSA_DST_LO/LZSA_DST_HI must contain the address of the last byte of the destination buffer +; +; out: +; * LZSA_DST_LO/LZSA_DST_HI contain the last decompressed byte address, -1 +; +; ----------------------------------------------------------------------------- +; +; Copyright (C) 2019 Emmanuel Marty, Peter Ferrie +; +; This software is provided 'as-is', without any express or implied +; warranty. In no event will the authors be held liable for any damages +; arising from the use of this software. +; +; Permission is granted to anyone to use this software for any purpose, +; including commercial applications, and to alter it and redistribute it +; freely, subject to the following restrictions: +; +; 1. The origin of this software must not be misrepresented; you must not +; claim that you wrote the original software. If you use this software +; in a product, an acknowledgment in the product documentation would be +; appreciated but is not required. +; 2. Altered source versions must be plainly marked as such, and must not be +; misrepresented as being the original software. +; 3. This notice may not be removed or altered from any source distribution. +; ----------------------------------------------------------------------------- + +;NIBCOUNT = $FC ; zero-page location for temp offset + +decompress_lzsa2_overlay: + + sta LZSA_DST_HI_OVERLAY + + ldy #$00 + sty LZSA_DST_LO_OVERLAY + sty NIBCOUNT + +decode_token_overlay: + jsr getsrc_overlay ; read token byte: XYZ|LL|MMM + pha ; preserve token on stack + + and #$18 ; isolate literals count (LL) + beq no_literals_overlay ; skip if no literals to copy + cmp #$18 ; LITERALS_RUN_LEN_V2? + bcc prepare_copy_literals_overlay ; if less, count is directly embedded in token + + jsr getnibble_overlay ; get extra literals length nibble + ; add nibble to len from token + adc #$02 ; (LITERALS_RUN_LEN_V2) minus carry + cmp #$12 ; LITERALS_RUN_LEN_V2 + 15 ? + bcc prepare_copy_literals_direct_overlay ; if less, literals count is complete + + jsr getsrc_overlay ; get extra byte of variable literals count + ; the carry is always set by the CMP above + ; GETSRC doesn't change it + sbc #$EE ; overflow? + jmp prepare_copy_literals_direct_overlay + +prepare_copy_literals_large_overlay: + ; handle 16 bits literals count + ; literals count = directly these 16 bits + jsr getlargesrc_overlay ; grab low 8 bits in X, high 8 bits in A + tay ; put high 8 bits in Y + bcs prepare_copy_literals_high_overlay ; (*same as JMP PREPARE_COPY_LITERALS_HIGH but shorter) + +prepare_copy_literals_overlay: + lsr ; shift literals count into place + lsr + lsr + +prepare_copy_literals_direct_overlay: + tax + bcs prepare_copy_literals_large_overlay ; if so, literals count is large + +prepare_copy_literals_high_overlay: + txa + beq copy_literals_overlay + iny + +copy_literals_overlay: + jsr getput_overlay ; copy one byte of literals + dex + bne copy_literals_overlay + dey + bne copy_literals_overlay + +no_literals_overlay: + pla ; retrieve token from stack + pha ; preserve token again + asl + bcs repmatch_or_large_offset_overlay ; 1YZ: rep-match or 13/16 bit offset + + asl ; 0YZ: 5 or 9 bit offset + bcs offset_9_bit_overlay + + ; 00Z: 5 bit offset + + ldx #$FF ; set offset bits 15-8 to 1 + + jsr getcombinedbits_overlay ; rotate Z bit into bit 0, read nibble for bits 4-1 + ora #$E0 ; set bits 7-5 to 1 + bne got_offset_lo_overlay ; go store low byte of match offset and prepare match + +offset_9_bit_overlay: ; 01Z: 9 bit offset + ;;asl ; shift Z (offset bit 8) in place + rol + rol + and #$01 + eor #$FF ; set offset bits 15-9 to 1 + bne got_offset_hi_overlay ; go store high byte, read low byte of match offset and prepare match + ; (*same as JMP GOT_OFFSET_HI but shorter) + +repmatch_or_large_offset_overlay: + asl ; 13 bit offset? + bcs repmatch_or_16bit_overlay ; handle rep-match or 16-bit offset if not + + ; 10Z: 13 bit offset + + jsr getcombinedbits_overlay ; rotate Z bit into bit 8, read nibble for bits 12-9 + adc #$DE ; set bits 15-13 to 1 and substract 2 (to substract 512) + bne got_offset_hi_overlay ; go store high byte, read low byte of match offset and prepare match + ; (*same as JMP GOT_OFFSET_HI but shorter) + +repmatch_or_16bit_overlay: ; rep-match or 16 bit offset + ;;ASL ; XYZ=111? + bmi rep_match_overlay ; reuse previous offset if so (rep-match) + + ; 110: handle 16 bit offset + jsr getsrc_overlay ; grab high 8 bits +got_offset_hi_overlay: + tax + jsr getsrc_overlay ; grab low 8 bits +got_offset_lo_overlay: + sta OFFSLO_OVERLAY ; store low byte of match offset + stx OFFSHI_OVERLAY ; store high byte of match offset + +rep_match_overlay: + + ; Forward decompression - add match offset + + clc ; add dest + match offset + lda putdst_smc_overlay+1 ; low 8 bits +OFFSLO_OVERLAY = *+1 + adc #$AA + sta copy_match_loop_overlay+1 ; store back reference address +OFFSHI_OVERLAY = *+1 + lda #$AA ; high 8 bits + adc putdst_smc_overlay+2 + sta copy_match_loop_overlay+2 ; store high 8 bits of address + + pla ; retrieve token from stack again + and #$07 ; isolate match len (MMM) + adc #$01 ; add MIN_MATCH_SIZE_V2 and carry + cmp #$09 ; MIN_MATCH_SIZE_V2 + MATCH_RUN_LEN_V2? + bcc prepare_copy_match_overlay ; if less, length is directly embedded in token + + jsr getnibble_overlay ; get extra match length nibble + ; add nibble to len from token + adc #$08 ; (MIN_MATCH_SIZE_V2 + MATCH_RUN_LEN_V2) minus carry + cmp #$18 ; MIN_MATCH_SIZE_V2 + MATCH_RUN_LEN_V2 + 15? + bcc prepare_copy_match_overlay ; if less, match length is complete + + jsr getsrc_overlay ; get extra byte of variable match length + ; the carry is always set by the CMP above + ; GETSRC doesn't change it + sbc #$E8 ; overflow? + +prepare_copy_match_overlay: + tax + bcc prepare_copy_match_y_overlay ; if not, the match length is complete + beq decompression_done_overlay ; if EOD code, bail + + ; Handle 16 bits match length + jsr getlargesrc_overlay ; grab low 8 bits in X, high 8 bits in A + tay ; put high 8 bits in Y + +prepare_copy_match_y_overlay: + txa + beq copy_match_loop_overlay + iny + +copy_match_loop_overlay: + lda $AAAA ; get one byte of backreference + jsr putdst_overlay ; copy to destination + + ; Forward decompression -- put backreference bytes forward + + inc copy_match_loop_overlay+1 + beq getmatch_adj_hi_overlay +getmatch_done_overlay: + + dex + bne copy_match_loop_overlay + dey + bne copy_match_loop_overlay + jmp decode_token_overlay + +getmatch_adj_hi_overlay: + inc copy_match_loop_overlay+2 + jmp getmatch_done_overlay + +getcombinedbits_overlay: + eor #$80 + asl + php + + jsr getnibble_overlay ; get nibble into bits 0-3 (for offset bits 1-4) + plp ; merge Z bit as the carry bit (for offset bit 0) +combinedbitz_overlay: + rol ; nibble -> bits 1-4; carry(!Z bit) -> bit 0 ; carry cleared +decompression_done_overlay: + rts + +getnibble_overlay: +NIBBLES_OVERLAY = *+1 + lda #$AA + lsr NIBCOUNT + bcc need_nibbles_overlay + and #$0F ; isolate low 4 bits of nibble + rts + +need_nibbles_overlay: + inc NIBCOUNT + jsr getsrc_overlay ; get 2 nibbles + sta NIBBLES_OVERLAY + lsr + lsr + lsr + lsr + sec + rts + + ; Forward decompression -- get and put bytes forward + + + ; Note: must preserve A here + + +getput_overlay: + jsr getsrc_overlay + + +putdst_overlay: + + pha +output_overlay: + lda $9000 + +putdst_smc_overlay: +LZSA_DST_LO_OVERLAY = *+1 +LZSA_DST_HI_OVERLAY = *+2 + sta $AAAA + inc putdst_smc_overlay+1 +; beq putdst_adj_hi_overlay + bne adjust_input_overlay + +putdst_adj_hi_overlay: + inc putdst_smc_overlay+2 + +adjust_input_overlay: + inc output_overlay+1 + beq output_adj_hi_overlay + bne done_overlay +output_adj_hi_overlay: + inc output_overlay+2 + +done_overlay: + pla + rts + +getlargesrc_overlay: + jsr getsrc_overlay ; grab low 8 bits + tax ; move to X + ; fall through grab high 8 bits + +getsrc_overlay: +getsrc_smc_overlay: +LZSA_SRC_LO_OVERLAY = *+1 +LZSA_SRC_HI_OVERLAY = *+2 + lda $AAAA + inc getsrc_overlay+1 + beq getsrc_adj_hi_overlay + rts + +getsrc_adj_hi_overlay: + inc getsrc_overlay+2 + rts + + diff --git a/games/peasant/hardware.inc b/games/peasant/hardware.inc index ca899cdd..6f04c7b1 100644 --- a/games/peasant/hardware.inc +++ b/games/peasant/hardware.inc @@ -4,8 +4,8 @@ KEYPRESS = $C000 KEYRESET = $C010 ; SOFT SWITCHES -CLR80COL = $C000 ; PAGE0/PAGE1 normal -SET80COL = $C001 ; PAGE0/PAGE1 switches PAGE0 in Aux instead +CLR80COL = $C000 ; PAGE1/PAGE1 normal +SET80COL = $C001 ; PAGE1/PAGE2 switches PAGE1 in Aux instead EIGHTYCOLOFF = $C00C EIGHTYCOLON = $C00D TBCOLOR = $C022 ; IIgs text foreground / background colors @@ -16,8 +16,8 @@ SET_GR = $C050 SET_TEXT = $C051 FULLGR = $C052 TEXTGR = $C053 -PAGE0 = $C054 -PAGE1 = $C055 +PAGE1 = $C054 +PAGE2 = $C055 LORES = $C056 ; Enable LORES graphics HIRES = $C057 ; Enable HIRES graphics AN3 = $C05E ; Annunciator 3 diff --git a/games/peasant/hgr_overlay.s b/games/peasant/hgr_overlay.s new file mode 100644 index 00000000..f519c444 --- /dev/null +++ b/games/peasant/hgr_overlay.s @@ -0,0 +1,300 @@ + ;======================= + ; HGR Overlay + ;======================= + ; loads from DRAW_PAGE + ; OR with $9000 + ; store back to DRAW_PAGE + +hgr_overlay: + lda DRAW_PAGE + cmp #$20 + beq hgr_overlay_page1 + jmp hgr_overlay_page2 + +hgr_overlay_page1: + + ldy #0 +hgr_overlay_page1_loop: + + lda $9000,Y + ora $2000,Y + sta $2000,Y + + lda $9100,Y + ora $2100,Y + sta $2100,Y + + lda $9200,Y + ora $2200,Y + sta $2200,Y + + lda $9300,Y + ora $2300,Y + sta $2300,Y + + lda $9400,Y + ora $2400,Y + sta $2400,Y + + lda $9500,Y + ora $2500,Y + sta $2500,Y + + lda $9600,Y + ora $2600,Y + sta $2600,Y + + lda $9700,Y + ora $2700,Y + sta $2700,Y + + lda $9800,Y + ora $2800,Y + sta $2800,Y + + lda $9900,Y + ora $2900,Y + sta $2900,Y + + lda $9A00,Y + ora $2A00,Y + sta $2A00,Y + + lda $9B00,Y + ora $2B00,Y + sta $2B00,Y + + lda $9C00,Y + ora $2C00,Y + sta $2C00,Y + + lda $9D00,Y + ora $2D00,Y + sta $2D00,Y + + lda $9E00,Y + ora $2E00,Y + sta $2E00,Y + + lda $9F00,Y + ora $2F00,Y + sta $2F00,Y + + + + lda $A000,Y + ora $3000,Y + sta $3000,Y + + lda $A100,Y + ora $3100,Y + sta $3100,Y + + lda $A200,Y + ora $3200,Y + sta $3200,Y + + lda $A300,Y + ora $3300,Y + sta $3300,Y + + lda $A400,Y + ora $3400,Y + sta $3400,Y + + lda $A500,Y + ora $3500,Y + sta $3500,Y + + lda $A600,Y + ora $3600,Y + sta $3600,Y + + lda $A700,Y + ora $3700,Y + sta $3700,Y + + lda $A800,Y + ora $3800,Y + sta $3800,Y + + lda $A900,Y + ora $3900,Y + sta $3900,Y + + lda $AA00,Y + ora $3A00,Y + sta $3A00,Y + + lda $AB00,Y + ora $3B00,Y + sta $3B00,Y + + lda $AC00,Y + ora $3C00,Y + sta $3C00,Y + + lda $AD00,Y + ora $3D00,Y + sta $3D00,Y + + lda $AE00,Y + ora $3E00,Y + sta $3E00,Y + + lda $AF00,Y + ora $3F00,Y + sta $3F00,Y + + + iny + beq hgr_page1_overlay_done + jmp hgr_overlay_page1_loop + +hgr_page1_overlay_done: + rts + + +hgr_overlay_page2: + + ldy #0 +hgr_overlay_page2_loop: + + lda $9000,Y + ora $4000,Y + sta $4000,Y + + lda $9100,Y + ora $4100,Y + sta $4100,Y + + lda $9200,Y + ora $4200,Y + sta $4200,Y + + lda $9300,Y + ora $4300,Y + sta $4300,Y + + lda $9400,Y + ora $4400,Y + sta $4400,Y + + lda $9500,Y + ora $4500,Y + sta $4500,Y + + lda $9600,Y + ora $4600,Y + sta $4600,Y + + lda $9700,Y + ora $4700,Y + sta $4700,Y + + lda $9800,Y + ora $4800,Y + sta $4800,Y + + lda $9900,Y + ora $4900,Y + sta $4900,Y + + lda $9A00,Y + ora $4A00,Y + sta $4A00,Y + + lda $9B00,Y + ora $4B00,Y + sta $4B00,Y + + lda $9C00,Y + ora $4C00,Y + sta $4C00,Y + + lda $9D00,Y + ora $4D00,Y + sta $4D00,Y + + lda $9E00,Y + ora $4E00,Y + sta $4E00,Y + + lda $9F00,Y + ora $4F00,Y + sta $4F00,Y + + + + lda $A000,Y + ora $5000,Y + sta $5000,Y + + lda $A100,Y + ora $5100,Y + sta $5100,Y + + lda $A200,Y + ora $5200,Y + sta $5200,Y + + lda $A300,Y + ora $5300,Y + sta $5300,Y + + lda $A400,Y + ora $5400,Y + sta $5400,Y + + lda $A500,Y + ora $5500,Y + sta $5500,Y + + lda $A600,Y + ora $5600,Y + sta $5600,Y + + lda $A700,Y + ora $5700,Y + sta $5700,Y + + lda $A800,Y + ora $5800,Y + sta $5800,Y + + lda $A900,Y + ora $5900,Y + sta $5900,Y + + lda $AA00,Y + ora $5A00,Y + sta $5A00,Y + + lda $AB00,Y + ora $5B00,Y + sta $5B00,Y + + lda $AC00,Y + ora $5C00,Y + sta $5C00,Y + + lda $AD00,Y + ora $5D00,Y + sta $5D00,Y + + lda $AE00,Y + ora $5E00,Y + sta $5E00,Y + + lda $AF00,Y + ora $5F00,Y + sta $5F00,Y + + + iny + beq hgr_page2_overlay_done + jmp hgr_overlay_page2_loop + +hgr_page2_overlay_done: + rts + diff --git a/games/peasant/intro.s b/games/peasant/intro.s index 3b4c3551..97d1528f 100644 --- a/games/peasant/intro.s +++ b/games/peasant/intro.s @@ -14,6 +14,10 @@ GBASH = $27 CURSOR_X = $62 CURSOR_Y = $63 HGR_COLOR = $E4 +HGR_PAGE = $E6 +DISP_PAGE = $F0 +DRAW_PAGE = $F1 + P0 = $F1 P1 = $F2 P2 = $F3 @@ -31,26 +35,54 @@ OUTH = $FF hgr_display: jsr HGR2 ; Hi-res graphics, no text at bottom ; Y=0, A=0 after this called + ; HGR_PAGE=$40 + + lda #$40 + sta DISP_PAGE + lda #$20 + sta DRAW_PAGE ;************************ - ; Opening + ; Intro ;************************ + + ; Load logo offscreen at $9000 + lda #<(videlectrix_lzsa) sta getsrc_smc+1 lda #>(videlectrix_lzsa) sta getsrc_smc+2 - lda #$40 + lda #$90 jsr decompress_lzsa2_fast - jsr wait_until_keypress +; jsr wait_until_keypress ldy #0 animation_loop: + lda DRAW_PAGE + cmp #$40 + beq show_page2 + +show_page1: + bit PAGE1 + lda #$40 + bne done_page ; bra + +show_page2: + bit PAGE2 + lda #$20 + +done_page: + sta DRAW_PAGE + eor #$60 + sta DISP_PAGE + + lda delays,Y bmi done_loop @@ -62,10 +94,12 @@ animation_loop: tya pha - lda #$40 + lda DRAW_PAGE jsr decompress_lzsa2_fast + jsr hgr_overlay + pla tay @@ -74,6 +108,9 @@ animation_loop: jmp animation_loop done_loop: + + jsr wait_until_keypress + rts ;forever: @@ -191,6 +228,9 @@ delays: .include "decompress_fast_v2.s" +;.include "decompress_overlay.s" +.include "hgr_overlay.s" + .include "wait_keypress.s" .include "graphics_intro/intro_graphics.inc"