compression_test: finally got exomizer working

This commit is contained in:
Vince Weaver 2022-06-17 01:24:21 -04:00
parent 94bc946a4c
commit bff16e6de7
10 changed files with 1300 additions and 325 deletions

View File

@ -1,5 +1,14 @@
; this one is from passport
; This source code is altered and is not the original version found on
; the Exomizer homepage.
; It contains modifications made by qkumba to depack a packed file
; optionally crunched forward, and additional modifications by 4am
; for an optional progress UI.
;
; Copyright (c) 2002 - 2020 Magnus Lind.
; Original copyright statement follows:
;
; Copyright (c) 2002 - 2018 Magnus Lind.
;
; 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
@ -23,64 +32,6 @@
; used to endorse or promote products derived from this software without
; specific prior written permission.
;
; -------------------------------------------------------------------
; Known quirks:
; Can't handle a sequence reference that ends at $ffff. It is left in
; since it is a corner case and fixing it impacts negatively on
; performance or backwards compatibility.
; A simple way to work around this is to not decrunch to address $ffff.
; -------------------------------------------------------------------
; Controls if the shared get_bits routines should be inlined or not.
;INLINE_GET_BITS=1
.IFNDEF INLINE_GET_BITS
INLINE_GET_BITS = 0
.ENDIF
; -------------------------------------------------------------------
; if literal sequences is not used (the data was crunched with the -c
; flag) then the following line can be uncommented for shorter and.
; slightly faster code.
;LITERAL_SEQUENCES_NOT_USED = 1
.IFNDEF LITERAL_SEQUENCES_NOT_USED
LITERAL_SEQUENCES_NOT_USED = 0
.ENDIF
; -------------------------------------------------------------------
; if the sequence length is limited to 256 (the data was crunched with
; the -M256 flag) then the following line can be uncommented for
; shorter and slightly faster code.
;MAX_SEQUENCE_LENGTH_256 = 1
.IFNDEF MAX_SEQUENCE_LENGTH_256
MAX_SEQUENCE_LENGTH_256 = 0
.ENDIF
; -------------------------------------------------------------------
; if the sequence length 3 has its own offset table (the data was
; crunched with the -P+16 flag) then the following
; line must be uncommented.
;EXTRA_TABLE_ENTRY_FOR_LENGTH_THREE = 1
.IFNDEF EXTRA_TABLE_ENTRY_FOR_LENGTH_THREE
EXTRA_TABLE_ENTRY_FOR_LENGTH_THREE = 0
.ENDIF
; -------------------------------------------------------------------
; if sequence offsets are not reused (the data was crunched with the
; -P-32 flag) then the following line must be uncommented. Uncommenting the
; line will also result in shorter and slightly faster code.
;DONT_REUSE_OFFSET = 1
.IFNDEF DONT_REUSE_OFFSET
DONT_REUSE_OFFSET = 0
.ENDIF
; -------------------------------------------------------------------
; if decrunching forwards then the following line must be uncommented.
;DECRUNCH_FORWARDS = 1
.IFNDEF DECRUNCH_FORWARDS
DECRUNCH_FORWARDS = 0
.ENDIF
; -------------------------------------------------------------------
; if split encoding is used (the data is crunched with the -E flag)
; then the following line must be uncommented.
;ENABLE_SPLIT_ENCODING = 1
.IFNDEF ENABLE_SPLIT_ENCODING
ENABLE_SPLIT_ENCODING = 0
.ENDIF
; -------------------------------------------------------------------
; The decruncher jsr:s to the get_crunched_byte address when it wants to
; read a crunched byte into A. This subroutine has to preserve X and Y
@ -88,65 +39,73 @@ ENABLE_SPLIT_ENCODING = 0
; -------------------------------------------------------------------
;.import get_crunched_byte
; -------------------------------------------------------------------
; This function is the heart of the decruncher. (for non split crunched files)
; this function is the heart of the decruncher.
; It initializes the decruncher zeropage locations and precalculates the
; decrunch tables and decrunches the data
; This function will not change the interrupt status bit and it will not
; modify the memory configuration.
; -------------------------------------------------------------------
.export decrunch
.IF ENABLE_SPLIT_ENCODING <> 0
;.export decrunch
; -------------------------------------------------------------------
; To decrunch files crunched with the split feature (-E) you can't use the
; decrunch function. Instead you call the split_decrunch function. But you
; can only do this if the decrunch table contains the encoding used by the
; file you are decrunching. To generate the correct content for the decrunch
; table call set the get_crunched_byte function to point to the encoding data
; and then call the split_gentable function.
; Controls if the shared get_bits routines should be inlined or not.
;INLINE_GET_BITS=1
; -------------------------------------------------------------------
.export split_gentable
.export split_decrunch
.ENDIF
; if literal sequences is not used (the data was crunched with the -c
; flag) then the following line can be uncommented for shorter and.
; slightly faster code.
;LITERAL_SEQUENCES_NOT_USED = 1
; -------------------------------------------------------------------
; if the sequence length is limited to 256 (the data was crunched with
; the -M256 flag) then the following line can be uncommented for
; shorter and slightly faster code.
;MAX_SEQUENCE_LENGTH_256 = 1
; -------------------------------------------------------------------
; if the sequence length 3 has its own offset table then the following
; line can be uncommented for in some situations slightly better
; compression at the cost of a larger decrunch table.
EXTRA_TABLE_ENTRY_FOR_LENGTH_THREE = 1
; -------------------------------------------------------------------
; optional progress UI
.ifndef SHOW_PROGRESS_DURING_DECRUNCH
SHOW_PROGRESS_DURING_DECRUNCH = 0
.endif
; -------------------------------------------------------------------
; zero page addresses used
; -------------------------------------------------------------------
zp_len_lo = $9e
zp_len_hi = $9f
zp_len_lo = $a7
zp_len_hi = $a8
zp_src_lo = $ae
zp_src_hi = zp_src_lo + 1
zp_bits_hi = $a7
.IF DONT_REUSE_OFFSET = 0
zp_ro_state = $a8
.ENDIF
zp_bits_hi = $fc
zp_bitbuf = $fd
zp_dest_lo = zp_bitbuf + 1 ; dest addr lo
zp_dest_hi = zp_bitbuf + 2 ; dest addr hi
.IF EXTRA_TABLE_ENTRY_FOR_LENGTH_THREE <> 0
.ifdef EXTRA_TABLE_ENTRY_FOR_LENGTH_THREE
encoded_entries = 68
.ELSE
.else
encoded_entries = 52
.ENDIF
.endif
tabl_bi = decrunch_table
tabl_lo = decrunch_table + encoded_entries
tabl_hi = decrunch_table + encoded_entries * 2
;; refill bits is always inlined
.MACRO mac_refill_bits
.macro mac_refill_bits
pha
jsr get_crunched_byte
rol
sta zp_bitbuf
pla
.ENDMACRO
.endmacro
.MACRO mac_get_bits
.IF INLINE_GET_BITS <> 0
.SCOPE
.ifdef INLINE_GET_BITS
.macro mac_get_bits
adc #$80 ; needs c=0, affects v
asl
bpl gb_skip
@ -164,26 +123,11 @@ gb_get_hi:
sta zp_bits_hi
jsr get_crunched_byte
skip:
.ENDSCOPE
.ELSE
.endmacro
.else
.macro mac_get_bits
jsr get_bits
.ENDIF
.ENDMACRO
.MACRO mac_init_zp
.SCOPE
; -------------------------------------------------------------------
; init zeropage and x reg. (8 bytes)
;
init_zp:
jsr get_crunched_byte
sta zp_bitbuf - 1,x
dex
bne init_zp
.ENDSCOPE
.ENDMACRO
.IF INLINE_GET_BITS = 0
.endmacro
get_bits:
adc #$80 ; needs c=0, affects v
asl
@ -202,7 +146,7 @@ gb_get_hi:
sec
sta zp_bits_hi
jmp get_crunched_byte
.ENDIF
.endif
; -------------------------------------------------------------------
; no code below this comment has to be modified in order to generate
; a working decruncher of this source file.
@ -214,25 +158,42 @@ gb_get_hi:
; jsr this label to decrunch, it will in turn init the tables and
; call the decruncher
; no constraints on register content, however the
; decimal flag has to be cleared (it almost always is, otherwise do a cld)
; decimal flag has to be #0 (it almost always is, otherwise do a cld)
decrunch:
.IF ENABLE_SPLIT_ENCODING <> 0
ldx #3
jsr internal_gentable
jmp normal_decrunch
split_gentable:
ldx #1
internal_gentable:
jsr split_init_zp
.ELSE
ldx #3
mac_init_zp
.ENDIF
.if SHOW_PROGRESS_DURING_DECRUNCH = 1
lda $FBB3
cmp #$EA
bne +
lda #$A1 ; use ! instead of | for initial spinner animation
sta progress_char+1
sta progress_char+5
+
; -------------------------------------------------------------------
; calculate tables (64 bytes) + get_bits macro
; x must be #0 when entering
; show initial on-screen progress UI
;
ldy #7
init_progress_loop:
lda progress_char,y
jsr show_one_progress_char
dey
bpl init_progress_loop
done_init_progress_loop:
.endif
; -------------------------------------------------------------------
; init zeropage, x and y regs. (12 bytes)
;
ldy #0
ldx #3
init_zp:
jsr get_crunched_byte
sta zp_bitbuf - 1,x
dex
bne init_zp
; -------------------------------------------------------------------
; calculate tables (62 bytes) + get_bits macro
; x and y must be #0 when entering
;
clc
table_gen:
tax
@ -271,7 +232,7 @@ rolled:
bmi no_fixup_lohi
lda zp_len_hi
stx zp_len_hi
.BYTE $24
.byte $24
no_fixup_lohi:
txa
; -------------------------------------------------------------------
@ -279,57 +240,60 @@ no_fixup_lohi:
cpy #encoded_entries
bne table_gen
; -------------------------------------------------------------------
.IF ENABLE_SPLIT_ENCODING <> 0
rts
split_decrunch:
ldx #3
jsr split_init_zp
; X reg must be 0 here
sec
normal_decrunch:
.ENDIF
; -------------------------------------------------------------------
; prepare for main decruncher
.IF DONT_REUSE_OFFSET = 0
ror zp_ro_state
sec
.ENDIF
ldy zp_dest_lo
stx zp_dest_lo
stx zp_bits_hi
; -------------------------------------------------------------------
; copy one literal byte to destination (11 bytes)
; copy one literal byte to destination (11(10) bytes)
;
.ifndef FORWARD_DECRUNCHING
FORWARD_DECRUNCHING = 1
.endif
.if FORWARD_DECRUNCHING = 0
literal_start1:
.IF DECRUNCH_FORWARDS = 0
tya
bne no_hi_decr
dec zp_dest_hi
.IF DONT_REUSE_OFFSET = 0
dec zp_src_hi
.ENDIF
no_hi_decr:
dey
.ENDIF
jsr get_crunched_byte
sta (zp_dest_lo),y
.IF DECRUNCH_FORWARDS <> 0
.if SHOW_PROGRESS_DURING_DECRUNCH = 1
; periodically update on-screen progress UI
dec progress_counter
bne dont_update_progress_ui
tya
pha
ldy progress_index
lda progress_char,y
jsr show_one_progress_char
inc progress_index
lda progress_index
and #$07
sta progress_index
tay
lda #$20
jsr show_one_progress_char
pla
tay
dont_update_progress_ui:
.endif
.else
literal_start1:
jsr get_crunched_byte
sta (zp_dest_lo),y
iny
bne skip_hi_incr
bne no_hi_incr
inc zp_dest_hi
.IF DONT_REUSE_OFFSET = 0
inc zp_src_hi
.ENDIF
skip_hi_incr:
.ENDIF
no_hi_incr:
.endif
; -------------------------------------------------------------------
; fetch sequence length index (15 bytes)
; x must be #0 when entering and contains the length index + 1
; when exiting or 0 for literal byte
next_round:
.IF DONT_REUSE_OFFSET = 0
ror zp_ro_state
.ENDIF
dex
lda zp_bitbuf
no_literal1:
@ -349,13 +313,13 @@ nofetch8:
; check for decrunch done and literal sequences (4 bytes)
;
cpx #$11
.IF INLINE_GET_BITS <> 0
.ifdef INLINE_GET_BITS
bcc skip_jmp
jmp exit_or_lit_seq
skip_jmp:
.ELSE
.else
bcs exit_or_lit_seq
.ENDIF
.endif
; -------------------------------------------------------------------
; calulate length of sequence (zp_len) (18(11) bytes) + get_bits macro
;
@ -363,7 +327,7 @@ skip_jmp:
mac_get_bits
adc tabl_lo - 1,x ; we have now calculated zp_len_lo
sta zp_len_lo
.IF MAX_SEQUENCE_LENGTH_256 = 0
.ifndef MAX_SEQUENCE_LENGTH_256
lda zp_bits_hi
adc tabl_hi - 1,x ; c = 0 after this.
sta zp_len_hi
@ -372,32 +336,15 @@ skip_jmp:
; z-flag reflects zp_len_hi here
;
ldx zp_len_lo
.ELSE
.else
tax
.ENDIF
.IF MAX_SEQUENCE_LENGTH_256 = 0
lda #0
.ENDIF
.IF DONT_REUSE_OFFSET = 0
; -------------------------------------------------------------------
; here we decide to reuse latest offset or not (13(15) bytes)
;
bit <zp_ro_state
bmi test_reuse
no_reuse:
.ENDIF
; -------------------------------------------------------------------
; here we decide what offset table to use (17(15) bytes)
;
.IF MAX_SEQUENCE_LENGTH_256 = 0
sta <zp_bits_hi
.ENDIF
.endif
lda #$e1
.IF EXTRA_TABLE_ENTRY_FOR_LENGTH_THREE <> 0
.ifdef EXTRA_TABLE_ENTRY_FOR_LENGTH_THREE
cpx #$04
.ELSE
.else
cpx #$03
.ENDIF
.endif
bcs gbnc2_next
lda tabl_bit - 1,x
gbnc2_next:
@ -413,139 +360,144 @@ gbnc2_ok:
bcs gbnc2_next
tax
; -------------------------------------------------------------------
; calulate absolute offset (zp_src) (17 bytes) + get_bits macro
; calulate absolute offset (zp_src) (21(23) bytes) + get_bits macro
;
.ifndef MAX_SEQUENCE_LENGTH_256
lda #0
sta zp_bits_hi
.endif
lda tabl_bi,x
mac_get_bits
.IF DECRUNCH_FORWARDS = 0
.if FORWARD_DECRUNCHING = 0
adc tabl_lo,x
sta zp_src_lo
lda zp_bits_hi
adc tabl_hi,x
adc zp_dest_hi
sta zp_src_hi
.ELSE
.else
clc
adc tabl_lo,x
eor #$ff
sta zp_src_lo
lda zp_bits_hi
adc tabl_hi,x
eor #$ff
adc zp_dest_hi
sta zp_src_hi
lda zp_dest_hi
bcc skip_dest_hi
sbc #1
clc
.ENDIF
skip_dest_hi:
sbc zp_bits_hi
sbc tabl_hi,x
clc
.endif
sta zp_src_hi
; -------------------------------------------------------------------
; prepare for copy loop (2 bytes)
;
pre_copy:
ldx zp_len_lo
; -------------------------------------------------------------------
; main copy loop (30 bytes)
;
copy_next:
.IF DECRUNCH_FORWARDS = 0
.if FORWARD_DECRUNCHING = 0
tya
bne copy_skip_hi
dec zp_dest_hi
dec zp_src_hi
copy_skip_hi:
dey
.ENDIF
.IF LITERAL_SEQUENCES_NOT_USED = 0
.endif
.ifndef LITERAL_SEQUENCES_NOT_USED
bcs get_literal_byte
.ENDIF
.endif
lda (zp_src_lo),y
literal_byte_gotten:
sta (zp_dest_lo),y
.IF DECRUNCH_FORWARDS <> 0
.if (FORWARD_DECRUNCHING = 1)
iny
bne copy_skip_hi
inc zp_dest_hi
inc zp_src_hi
copy_skip_hi:
.ENDIF
.endif
dex
bne copy_next
.IF MAX_SEQUENCE_LENGTH_256 = 0
.ifndef MAX_SEQUENCE_LENGTH_256
lda zp_len_hi
.IF INLINE_GET_BITS <> 0
.ifdef INLINE_GET_BITS
bne copy_next_hi
.ENDIF
.ENDIF
.endif
.endif
begin_stx:
stx zp_bits_hi
.IF INLINE_GET_BITS = 0
.ifndef INLINE_GET_BITS
beq next_round
.ELSE
.else
jmp next_round
.ENDIF
.IF MAX_SEQUENCE_LENGTH_256 = 0
.endif
.ifndef MAX_SEQUENCE_LENGTH_256
copy_next_hi:
dec zp_len_hi
jmp copy_next
.ENDIF
.IF DONT_REUSE_OFFSET = 0
; -------------------------------------------------------------------
; test for offset reuse (11 bytes)
;
test_reuse:
bvs no_reuse
.IF MAX_SEQUENCE_LENGTH_256 <> 0
lda #$00 ; fetch one bit
.ENDIF
asl zp_bitbuf
bne gbnc1_ok
pha
.endif
.ifndef LITERAL_SEQUENCES_NOT_USED
get_literal_byte:
jsr get_crunched_byte
rol
sta zp_bitbuf
pla
gbnc1_ok:
rol
beq no_reuse ; bit == 0 => C=0, no reuse
bne copy_next ; bit != 0 => C=0, reuse previous offset
.ENDIF
bcs literal_byte_gotten
.endif
; -------------------------------------------------------------------
; exit or literal sequence handling (16(12) bytes)
;
exit_or_lit_seq:
.IF LITERAL_SEQUENCES_NOT_USED = 0
.ifndef LITERAL_SEQUENCES_NOT_USED
beq decr_exit
jsr get_crunched_byte
.IF MAX_SEQUENCE_LENGTH_256 = 0
.ifndef MAX_SEQUENCE_LENGTH_256
sta zp_len_hi
.ENDIF
.endif
jsr get_crunched_byte
tax
bcs copy_next
decr_exit:
.ENDIF
.endif
rts
.IF LITERAL_SEQUENCES_NOT_USED = 0
get_literal_byte:
jsr get_crunched_byte
bcs literal_byte_gotten
.ENDIF
.IF EXTRA_TABLE_ENTRY_FOR_LENGTH_THREE <> 0
.ifdef EXTRA_TABLE_ENTRY_FOR_LENGTH_THREE
; -------------------------------------------------------------------
; the static stable used for bits+offset for lengths 1, 2 and 3 (3 bytes)
; bits 2, 4, 4 and offsets 64, 48, 32 corresponding to
; %10010000, %11100011, %11100010
tabl_bit:
.BYTE $90, $e3, $e2
.ELSE
.byte $90, $e3, $e2
.else
; -------------------------------------------------------------------
; the static stable used for bits+offset for lengths 1 and 2 (2 bytes)
; bits 2, 4 and offsets 48, 32 corresponding to %10001100, %11100010
tabl_bit:
.BYTE $8c, $e2
.ENDIF
.IF ENABLE_SPLIT_ENCODING <> 0
split_init_zp:
mac_init_zp
.byte $8c, $e2
.endif
.if SHOW_PROGRESS_DURING_DECRUNCH = 1
progress_index:
.byte $00
progress_counter:
.byte $00
progress_char:
.byte $DC, $FC, $AF, $AD, $DC, $FC, $AF, $AD
progress_address_lo:
.byte $BB, $BC, $BD, $3D, $BD, $BC, $BB, $3B
progress_address_hi:
.byte $05, $05, $05, $06, $06, $06, $06, $06
show_one_progress_char:
; in: A=ASCII char to show
; y=0..7 index into progress_address_lo/hi array
pha
lda progress_address_lo,y
sta progress_STA+1
lda progress_address_hi,y
sta progress_STA+2
pla
progress_STA:
sta $FFFF
rts
.ENDIF
.endif
; -------------------------------------------------------------------
; end of decruncher
; -------------------------------------------------------------------
@ -554,22 +506,22 @@ split_init_zp:
; this 156 (204) byte table area may be relocated. It may also be
; clobbered by other data between decrunches.
; -------------------------------------------------------------------
decrunch_table:
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.IF EXTRA_TABLE_ENTRY_FOR_LENGTH_THREE <> 0
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.ENDIF
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byte 0,0,0,0,0,0,0,0,0,0,0,0
decrunch_table=$200;;:
;; .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
;; .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
;; .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
;;.IFDEF EXTRA_TABLE_ENTRY_FOR_LENGTH_THREE
;; .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
;; .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
;; .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
;;.ENDIF
;; .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
;; .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
;; .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
;; .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
;; .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
;; .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
;; .byte 0,0,0,0,0,0,0,0,0,0,0,0
; -------------------------------------------------------------------
; end of decruncher
; -------------------------------------------------------------------

View File

@ -0,0 +1,575 @@
;
; Copyright (c) 2002 - 2020 Magnus Lind.
;
; 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 distribution.
;
; 4. The names of this software and/or it's copyright holders may not be
; used to endorse or promote products derived from this software without
; specific prior written permission.
;
; -------------------------------------------------------------------
; Known quirks:
; Can't handle a sequence reference that ends at $ffff. It is left in
; since it is a corner case and fixing it impacts negatively on
; performance or backwards compatibility.
; A simple way to work around this is to not decrunch to address $ffff.
; -------------------------------------------------------------------
; Controls if the shared get_bits routines should be inlined or not.
;INLINE_GET_BITS=1
.IFNDEF INLINE_GET_BITS
INLINE_GET_BITS = 0
.ENDIF
; -------------------------------------------------------------------
; if literal sequences is not used (the data was crunched with the -c
; flag) then the following line can be uncommented for shorter and.
; slightly faster code.
;LITERAL_SEQUENCES_NOT_USED = 1
.IFNDEF LITERAL_SEQUENCES_NOT_USED
LITERAL_SEQUENCES_NOT_USED = 0
.ENDIF
; -------------------------------------------------------------------
; if the sequence length is limited to 256 (the data was crunched with
; the -M256 flag) then the following line can be uncommented for
; shorter and slightly faster code.
;MAX_SEQUENCE_LENGTH_256 = 1
.IFNDEF MAX_SEQUENCE_LENGTH_256
MAX_SEQUENCE_LENGTH_256 = 0
.ENDIF
; -------------------------------------------------------------------
; if the sequence length 3 has its own offset table (the data was
; crunched with the -P+16 flag) then the following
; line must be uncommented.
;EXTRA_TABLE_ENTRY_FOR_LENGTH_THREE = 1
.IFNDEF EXTRA_TABLE_ENTRY_FOR_LENGTH_THREE
EXTRA_TABLE_ENTRY_FOR_LENGTH_THREE = 0
.ENDIF
; -------------------------------------------------------------------
; if sequence offsets are not reused (the data was crunched with the
; -P-32 flag) then the following line must be uncommented. Uncommenting the
; line will also result in shorter and slightly faster code.
;DONT_REUSE_OFFSET = 1
.IFNDEF DONT_REUSE_OFFSET
DONT_REUSE_OFFSET = 0
.ENDIF
; -------------------------------------------------------------------
; if decrunching forwards then the following line must be uncommented.
;DECRUNCH_FORWARDS = 1
.IFNDEF DECRUNCH_FORWARDS
DECRUNCH_FORWARDS = 0
.ENDIF
; -------------------------------------------------------------------
; if split encoding is used (the data is crunched with the -E flag)
; then the following line must be uncommented.
;ENABLE_SPLIT_ENCODING = 1
.IFNDEF ENABLE_SPLIT_ENCODING
ENABLE_SPLIT_ENCODING = 0
.ENDIF
; -------------------------------------------------------------------
; The decruncher jsr:s to the get_crunched_byte address when it wants to
; read a crunched byte into A. This subroutine has to preserve X and Y
; register and must not modify the state of the carry nor the overflow flag.
; -------------------------------------------------------------------
;.import get_crunched_byte
; -------------------------------------------------------------------
; This function is the heart of the decruncher. (for non split crunched files)
; It initializes the decruncher zeropage locations and precalculates the
; decrunch tables and decrunches the data
; This function will not change the interrupt status bit and it will not
; modify the memory configuration.
; -------------------------------------------------------------------
.export decrunch
.IF ENABLE_SPLIT_ENCODING <> 0
; -------------------------------------------------------------------
; To decrunch files crunched with the split feature (-E) you can't use the
; decrunch function. Instead you call the split_decrunch function. But you
; can only do this if the decrunch table contains the encoding used by the
; file you are decrunching. To generate the correct content for the decrunch
; table call set the get_crunched_byte function to point to the encoding data
; and then call the split_gentable function.
; -------------------------------------------------------------------
.export split_gentable
.export split_decrunch
.ENDIF
; -------------------------------------------------------------------
; zero page addresses used
; -------------------------------------------------------------------
zp_len_lo = $9e
zp_len_hi = $9f
zp_src_lo = $ae
zp_src_hi = zp_src_lo + 1
zp_bits_hi = $a7
.IF DONT_REUSE_OFFSET = 0
zp_ro_state = $a8
.ENDIF
zp_bitbuf = $fd
zp_dest_lo = zp_bitbuf + 1 ; dest addr lo
zp_dest_hi = zp_bitbuf + 2 ; dest addr hi
.IF EXTRA_TABLE_ENTRY_FOR_LENGTH_THREE <> 0
encoded_entries = 68
.ELSE
encoded_entries = 52
.ENDIF
tabl_bi = decrunch_table
tabl_lo = decrunch_table + encoded_entries
tabl_hi = decrunch_table + encoded_entries * 2
;; refill bits is always inlined
.MACRO mac_refill_bits
pha
jsr get_crunched_byte
rol
sta zp_bitbuf
pla
.ENDMACRO
.MACRO mac_get_bits
.IF INLINE_GET_BITS <> 0
.SCOPE
adc #$80 ; needs c=0, affects v
asl
bpl gb_skip
gb_next:
asl zp_bitbuf
bne gb_ok
mac_refill_bits
gb_ok:
rol
bmi gb_next
gb_skip:
bvc skip
gb_get_hi:
sec
sta zp_bits_hi
jsr get_crunched_byte
skip:
.ENDSCOPE
.ELSE
jsr get_bits
.ENDIF
.ENDMACRO
.MACRO mac_init_zp
.SCOPE
; -------------------------------------------------------------------
; init zeropage and x reg. (8 bytes)
;
init_zp:
jsr get_crunched_byte
sta zp_bitbuf - 1,x
dex
bne init_zp
.ENDSCOPE
.ENDMACRO
.IF INLINE_GET_BITS = 0
get_bits:
adc #$80 ; needs c=0, affects v
asl
bpl gb_skip
gb_next:
asl zp_bitbuf
bne gb_ok
mac_refill_bits
gb_ok:
rol
bmi gb_next
gb_skip:
bvs gb_get_hi
rts
gb_get_hi:
sec
sta zp_bits_hi
jmp get_crunched_byte
.ENDIF
; -------------------------------------------------------------------
; no code below this comment has to be modified in order to generate
; a working decruncher of this source file.
; However, you may want to relocate the tables last in the file to a
; more suitable address.
; -------------------------------------------------------------------
; -------------------------------------------------------------------
; jsr this label to decrunch, it will in turn init the tables and
; call the decruncher
; no constraints on register content, however the
; decimal flag has to be cleared (it almost always is, otherwise do a cld)
decrunch:
.IF ENABLE_SPLIT_ENCODING <> 0
ldx #3
jsr internal_gentable
jmp normal_decrunch
split_gentable:
ldx #1
internal_gentable:
jsr split_init_zp
.ELSE
ldx #3
mac_init_zp
.ENDIF
; -------------------------------------------------------------------
; calculate tables (64 bytes) + get_bits macro
; x must be #0 when entering
;
ldy #0
clc
table_gen:
tax
tya
and #$0f
sta tabl_lo,y
beq shortcut ; start a new sequence
; -------------------------------------------------------------------
txa
adc tabl_lo - 1,y
sta tabl_lo,y
lda zp_len_hi
adc tabl_hi - 1,y
shortcut:
sta tabl_hi,y
; -------------------------------------------------------------------
lda #$01
sta <zp_len_hi
lda #$78 ; %01111000
mac_get_bits
; -------------------------------------------------------------------
lsr
tax
beq rolled
php
rolle:
asl zp_len_hi
sec
ror
dex
bne rolle
plp
rolled:
ror
sta tabl_bi,y
bmi no_fixup_lohi
lda zp_len_hi
stx zp_len_hi
.BYTE $24
no_fixup_lohi:
txa
; -------------------------------------------------------------------
iny
cpy #encoded_entries
bne table_gen
; -------------------------------------------------------------------
.IF ENABLE_SPLIT_ENCODING <> 0
rts
split_decrunch:
ldx #3
jsr split_init_zp
; X reg must be 0 here
sec
normal_decrunch:
.ENDIF
; -------------------------------------------------------------------
; prepare for main decruncher
.IF DONT_REUSE_OFFSET = 0
ror zp_ro_state
sec
.ENDIF
ldy zp_dest_lo
stx zp_dest_lo
stx zp_bits_hi
; -------------------------------------------------------------------
; copy one literal byte to destination (11 bytes)
;
literal_start1:
.IF DECRUNCH_FORWARDS = 0
tya
bne no_hi_decr
dec zp_dest_hi
.IF DONT_REUSE_OFFSET = 0
dec zp_src_hi
.ENDIF
no_hi_decr:
dey
.ENDIF
jsr get_crunched_byte
sta (zp_dest_lo),y
.IF DECRUNCH_FORWARDS <> 0
iny
bne skip_hi_incr
inc zp_dest_hi
.IF DONT_REUSE_OFFSET = 0
inc zp_src_hi
.ENDIF
skip_hi_incr:
.ENDIF
; -------------------------------------------------------------------
; fetch sequence length index (15 bytes)
; x must be #0 when entering and contains the length index + 1
; when exiting or 0 for literal byte
next_round:
.IF DONT_REUSE_OFFSET = 0
ror zp_ro_state
.ENDIF
dex
lda zp_bitbuf
no_literal1:
asl
bne nofetch8
jsr get_crunched_byte
rol
nofetch8:
inx
bcc no_literal1
sta zp_bitbuf
; -------------------------------------------------------------------
; check for literal byte (2 bytes)
;
beq literal_start1
; -------------------------------------------------------------------
; check for decrunch done and literal sequences (4 bytes)
;
cpx #$11
.IF INLINE_GET_BITS <> 0
bcc skip_jmp
jmp exit_or_lit_seq
skip_jmp:
.ELSE
bcs exit_or_lit_seq
.ENDIF
; -------------------------------------------------------------------
; calulate length of sequence (zp_len) (18(11) bytes) + get_bits macro
;
lda tabl_bi - 1,x
mac_get_bits
adc tabl_lo - 1,x ; we have now calculated zp_len_lo
sta zp_len_lo
.IF MAX_SEQUENCE_LENGTH_256 = 0
lda zp_bits_hi
adc tabl_hi - 1,x ; c = 0 after this.
sta zp_len_hi
; -------------------------------------------------------------------
; here we decide what offset table to use (27(26) bytes) + get_bits_nc macro
; z-flag reflects zp_len_hi here
;
ldx zp_len_lo
.ELSE
tax
.ENDIF
.IF MAX_SEQUENCE_LENGTH_256 = 0
lda #0
.ENDIF
.IF DONT_REUSE_OFFSET = 0
; -------------------------------------------------------------------
; here we decide to reuse latest offset or not (13(15) bytes)
;
bit <zp_ro_state
bmi test_reuse
no_reuse:
.ENDIF
; -------------------------------------------------------------------
; here we decide what offset table to use (17(15) bytes)
;
.IF MAX_SEQUENCE_LENGTH_256 = 0
sta <zp_bits_hi
.ENDIF
lda #$e1
.IF EXTRA_TABLE_ENTRY_FOR_LENGTH_THREE <> 0
cpx #$04
.ELSE
cpx #$03
.ENDIF
bcs gbnc2_next
lda tabl_bit - 1,x
gbnc2_next:
asl zp_bitbuf
bne gbnc2_ok
tax
jsr get_crunched_byte
rol
sta zp_bitbuf
txa
gbnc2_ok:
rol
bcs gbnc2_next
tax
; -------------------------------------------------------------------
; calulate absolute offset (zp_src) (17 bytes) + get_bits macro
;
lda tabl_bi,x
mac_get_bits
.IF DECRUNCH_FORWARDS = 0
adc tabl_lo,x
sta zp_src_lo
lda zp_bits_hi
adc tabl_hi,x
adc zp_dest_hi
sta zp_src_hi
.ELSE
clc
adc tabl_lo,x
eor #$ff
sta zp_src_lo
lda zp_bits_hi
adc tabl_hi,x
eor #$ff
adc zp_dest_hi
sta zp_src_hi
clc
.ENDIF
; -------------------------------------------------------------------
; prepare for copy loop (2 bytes)
;
ldx zp_len_lo
; -------------------------------------------------------------------
; main copy loop (30 bytes)
;
copy_next:
.IF DECRUNCH_FORWARDS = 0
tya
bne copy_skip_hi
dec zp_dest_hi
dec zp_src_hi
copy_skip_hi:
dey
.ENDIF
.IF LITERAL_SEQUENCES_NOT_USED = 0
bcs get_literal_byte
.ENDIF
lda (zp_src_lo),y
literal_byte_gotten:
sta (zp_dest_lo),y
.IF DECRUNCH_FORWARDS <> 0
iny
bne copy_skip_hi
inc zp_dest_hi
inc zp_src_hi
copy_skip_hi:
.ENDIF
dex
bne copy_next
.IF MAX_SEQUENCE_LENGTH_256 = 0
lda zp_len_hi
.IF INLINE_GET_BITS <> 0
bne copy_next_hi
.ENDIF
.ENDIF
stx zp_bits_hi
.IF INLINE_GET_BITS = 0
beq next_round
.ELSE
jmp next_round
.ENDIF
.IF MAX_SEQUENCE_LENGTH_256 = 0
copy_next_hi:
dec zp_len_hi
jmp copy_next
.ENDIF
.IF DONT_REUSE_OFFSET = 0
; -------------------------------------------------------------------
; test for offset reuse (11 bytes)
;
test_reuse:
bvs no_reuse
.IF MAX_SEQUENCE_LENGTH_256 <> 0
lda #$00 ; fetch one bit
.ENDIF
asl zp_bitbuf
bne gbnc1_ok
pha
jsr get_crunched_byte
rol
sta zp_bitbuf
pla
gbnc1_ok:
rol
beq no_reuse ; bit == 0 => C=0, no reuse
bne copy_next ; bit != 0 => C=0, reuse previous offset
.ENDIF
; -------------------------------------------------------------------
; exit or literal sequence handling (16(12) bytes)
;
exit_or_lit_seq:
.IF LITERAL_SEQUENCES_NOT_USED = 0
beq decr_exit
jsr get_crunched_byte
.IF MAX_SEQUENCE_LENGTH_256 = 0
sta zp_len_hi
.ENDIF
jsr get_crunched_byte
tax
bcs copy_next
decr_exit:
.ENDIF
rts
.IF LITERAL_SEQUENCES_NOT_USED = 0
get_literal_byte:
jsr get_crunched_byte
bcs literal_byte_gotten
.ENDIF
.IF EXTRA_TABLE_ENTRY_FOR_LENGTH_THREE <> 0
; -------------------------------------------------------------------
; the static stable used for bits+offset for lengths 1, 2 and 3 (3 bytes)
; bits 2, 4, 4 and offsets 64, 48, 32 corresponding to
; %10010000, %11100011, %11100010
tabl_bit:
.BYTE $90, $e3, $e2
.ELSE
; -------------------------------------------------------------------
; the static stable used for bits+offset for lengths 1 and 2 (2 bytes)
; bits 2, 4 and offsets 48, 32 corresponding to %10001100, %11100010
tabl_bit:
.BYTE $8c, $e2
.ENDIF
.IF ENABLE_SPLIT_ENCODING <> 0
split_init_zp:
mac_init_zp
rts
.ENDIF
; -------------------------------------------------------------------
; end of decruncher
; -------------------------------------------------------------------
; -------------------------------------------------------------------
; this 156 (204) byte table area may be relocated. It may also be
; clobbered by other data between decrunches.
; -------------------------------------------------------------------
decrunch_table:
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.IF EXTRA_TABLE_ENTRY_FOR_LENGTH_THREE <> 0
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.ENDIF
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byte 0,0,0,0,0,0,0,0,0,0,0,0
; -------------------------------------------------------------------
; end of decruncher
; -------------------------------------------------------------------

View File

@ -1,79 +1,98 @@
; -------------------------------------------------------------------
; this file is intended to be assembled and linked with the cc65 toolchain.
; It has not been tested with any other assemblers or linkers.
; -------------------------------------------------------------------
; -------------------------------------------------------------------
; example usage of the standard decruncher
; this program decrunches data to memory
; -------------------------------------------------------------------
; if decrunching forwards then the following line must be uncommented.
;DECRUNCH_FORWARDS = 1
.IFNDEF DECRUNCH_FORWARDS
DECRUNCH_FORWARDS = 0
.ENDIF
; -------------------------------------------------------------------
;.import decrunch
;.export get_crunched_byte
;.import end_of_data
.include "zp.inc"
.include "hardware.inc"
; .byte $01,$08,$0b,$08,<2003,>2003,$9e,'2','0','6','1',0,0,0
; -------------------------------------------------------------------
; we begin here
; -------------------------------------------------------------------
exomizer_test:
lda #$20
sta zp_dest_hi
lda #$00
sta zp_dest_lo
bit SET_GR
bit PAGE1
bit HIRES
bit FULLGR
.IF DECRUNCH_FORWARDS = 0
lda $04
sta _byte_lo
lda $05
sta _byte_hi
.ELSE
lda #<end_of_data
lda #<data_begin
sta _byte_lo
lda #>end_of_data
lda #>data_begin
sta _byte_hi
; lda $02
; sta _byte_lo
; lda $03
; sta _byte_hi
.ENDIF
jsr decrunch
jsr decrunch
.if 0
; lda #<data_begin
; sta zp_src_lo
; lda #>data_begin
; sta zp_src_hi
lda #$1F
pha
lda #>(data_end) ; sizehi2
pha
lda #<(data_end) ; sizelo2
pha
lda #>(start_d-1) ; #>(@loaddecrunch - 1)
pha
lda #<(start_d-1) ; #<(@loaddecrunch - 1)
pha
jmp decrunch_table
;decrunch_table:
;!warn "entry=",*
; pla ; <loaddecrunch
; tay
; pla ; >loaddecrunch
; tax
; clc
; pla ; sizelo2
; adc #$F8
; sta _byte_lo
; pla ;sizehi2
; sta zp_bitbuf
; pla ;#$1F
; adc zp_bitbuf
; sta _byte_hi
; txa
; pha
; tya
; pha
; jmp decrunch
; jsr decrunch
.endif
end:
jmp end
; -------------------------------------------------------------------
get_crunched_byte:
.IF DECRUNCH_FORWARDS = 0
lda _byte_lo
bne _byte_skip_hi
dec _byte_hi
_byte_skip_hi:
dec _byte_lo
.ENDIF
_byte_lo = * + 1
_byte_hi = * + 2
lda $ffff ; needs to be set correctly before
.IF DECRUNCH_FORWARDS <> 0
inc _byte_lo
bne _byte_skip_hi
inc _byte_hi
lda $1234 ; needs to be set correctly before
; decrunch_file is called.
inc _byte_lo
bne _byte_skip_hi
inc _byte_hi
_byte_skip_hi:
.ENDIF
rts ; decrunch_file is called.
; end_of_data needs to point to the address just after the address
; of the last byte of crunched data.
; -------------------------------------------------------------------
rts
start_d:
.include "exodecrunch.s"
.incbin "level5.exo"
end_of_data:
data_begin:
.byte $20,$00
.incbin "level5.exo"
data_end:

View File

@ -4,7 +4,7 @@
lzsa_test:
bit SET_GR
bit PAGE0
bit PAGE1
bit HIRES
bit FULLGR

View File

@ -4,7 +4,7 @@
lzsa_test:
bit SET_GR
bit PAGE0
bit PAGE1
bit HIRES
bit FULLGR

View File

@ -4,7 +4,7 @@
lzsa_test:
bit SET_GR
bit PAGE0
bit PAGE1
bit HIRES
bit FULLGR

View File

@ -4,7 +4,7 @@
lzsa_test:
bit SET_GR
bit PAGE0
bit PAGE1
bit HIRES
bit FULLGR

View File

@ -1,5 +1,31 @@
all:
include ../../Makefile.inc
clean:
rm -f *~
DOS33 = ../../utils/dos33fs-utils/dos33
TOKENIZE = ../../utils/asoft_basic-utils/tokenize_asoft
LINKERSCRIPTS = ../../linker_scripts
EMPTYDISK = ../../empty_disk/empty.dsk
all: cd.dsk
cd.dsk: HELLO HORIZ
cp $(EMPTYDISK) cd.dsk
$(DOS33) -y cd.dsk SAVE A HELLO
$(DOS33) -y cd.dsk BSAVE -a 0xC00 HORIZ
###
HELLO: hello.bas
$(TOKENIZE) < hello.bas > HELLO
###
HORIZ: horiz.o
ld65 -o HORIZ horiz.o -C $(LINKERSCRIPTS)/apple2_c00.inc
horiz.o: horiz.s
ca65 -o horiz.o horiz.s -l horiz.lst
####
clean:
rm -f *~ *.o *.lst HORIZ

204
music/cd/horiz.s Normal file
View File

@ -0,0 +1,204 @@
; horizontal star wipe
; initial code = 164 bytes
GBASL = $26
GBASH = $27
BASL = $28
BASH = $29
OFFSET_POINTER = $FE
LINE = $FF
SET_GR = $C050
SET_TEXT = $C051
FULLGR = $C052
TEXTGR = $C053
PAGE0 = $C054
PAGE1 = $C055
LORES = $C056 ; Enable LORES graphics
HIRES = $C057 ; Enable HIRES graphics
PLOT = $F800 ;; PLOT AT Y,A
PLOT1 = $F80E ;; PLOT at (GBASL),Y (need MASK to be $0f or $f0)
HLINE = $F819 ;; HLINE Y,$2C at A
VLINE = $F828 ;; VLINE A,$2D at Y
CLRSCR = $F832 ;; Clear low-res screen
CLRTOP = $F836 ;; clear only top of low-res screen
GBASCALC= $F847 ;; take Y-coord/2 in A, put address in GBASL/H ( a trashed, C clear)
SETCOL = $F864 ;; COLOR=A
SETTXT = $FB36
SETGR = $FB40
BASCALC = $FBC1 ; Y-Coord in A, address in BASL/H, X,Y preserved
WAIT = $FCA8 ;; delay 1/2(26+27A+5A^2) us
;================================
; Clear screen and setup graphics
;================================
horiz:
jsr SETGR ; set lo-res 40x40 mode
bit SET_GR
bit FULLGR ; make it 40x48
lda #3
sta LINE
lda #0
sta OFFSET_POINTER
forever_loop:
lda #$0
sta OFFSET_POINTER
ldx #0
big_loop:
txa
pha
jsr BASCALC
ldy #39
ldx OFFSET_POINTER
hlin:
tya
; if signed (y>offset) && (y<endoffset) draw
; if signed (y<=offset) || (y>endoffset) don't draw
clc
sbc offsets,X
bvs gurg
eor #$80
gurg:
bpl skip_pixel ; neg if A<=offset
tya
clc
sbc endoffsets,X
bvs gurg2
eor #$80
gurg2:
bmi skip_pixel ; neg if A<=endoffset
color_smc:
lda #$3b
jmp blah ; TODO: USE BIT TRICK
skip_pixel:
lda #$0 ;
blah:
sta (BASL),Y
dey
bpl hlin
lda #$bb
sta color_smc+1
;==========================================
; draw star at beginning of line
lda offsets,X
bmi skip_star
clc
lda BASL
adc offsets,X
sta BASL
ldx LINE
ldy #7 ; 8-bits wide
lda star_bitmap-1,X ; get low bit of bitmap into carry
draw_line_loop:
lsr
pha
bcc its_transparent
lda #$ff ; white
sta (BASL),Y ; draw on screen
its_transparent:
pla
dey
bpl draw_line_loop
skip_star:
; see if new line
ldx OFFSET_POINTER
dec LINE
bne not3
lda #$b3
sta color_smc+1
dec offsets,X
dec endoffsets,X
inc OFFSET_POINTER
lda #3
sta LINE
not3:
;==========================
pla
tax
inx
cpx #24
bne big_loop
; set/flip pages
; we want to flip pages and then draw to the offscreen one
;flip_pages:
; ldx #0 ; x already 0
; lda draw_page_smc+1 ; DRAW_PAGE
;; beq done_page
; inx
;done_page:
; ldy PAGE0,X ; set display page to PAGE1 or PAGE2
; eor #$4 ; flip draw page between $400/$800
; sta draw_page_smc+1 ; DRAW_PAGE
lda #80
jsr WAIT
jmp forever_loop
offsets:
.byte 5,4,3,2,1,2,3,4,5
endoffsets:
.byte 30,20,10,20,30,40,50,12
; 76543210
; @
; @@@@@
; @ @
star_bitmap:
.byte $50
.byte $f8
.byte $20
; for bot
jmp horiz

199
music/cd/horiz_bot.s Normal file
View File

@ -0,0 +1,199 @@
; horizontal star wipe
; initial code = 164 bytes
; 163 bytes = jmp to bra
; 158 bytes = cleanup initialization
; 156 bytes = BIT trick
; 154 bytes = set offsets properly
; 151 bytes = redo init
GBASL = $26
GBASH = $27
BASL = $28
BASH = $29
OFFSET_POINTER = $FE
LINE = $FF
SET_GR = $C050
SET_TEXT = $C051
FULLGR = $C052
TEXTGR = $C053
PAGE1 = $C054
PAGE2 = $C055
LORES = $C056 ; Enable LORES graphics
HIRES = $C057 ; Enable HIRES graphics
HGR2 = $F3D8
SETTXT = $FB36
SETGR = $FB40
BASCALC = $FBC1 ; Y-Coord in A, address in BASL/H, X,Y preserved
WAIT = $FCA8 ;; delay 1/2(26+27A+5A^2) us
;================================
; Clear screen and setup graphics
;================================
horiz:
jsr SETGR ; set lo-res 40x40 mode, PAGE1
bit FULLGR ; show full screen
lda #3 ; count down from 3 to 0 each subline
sta LINE
forever_loop:
lda #$0 ; offset into the length pointers
sta OFFSET_POINTER
; A = screen line, 0..24
big_loop:
pha ; save screen line on stack
jsr BASCALC ; calculate address of line in BASL/BASH
ldy #39 ; draw 40 pixels on screen
ldx OFFSET_POINTER ; get pointer to the offsets
hlin:
tya
; if signed (y>offset) && (y<endoffset) draw
; if signed (y<=offset) || (y>endoffset) don't draw
clc
sbc offsets,X
bvs gurg
eor #$80
gurg:
bpl skip_pixel ; neg if A<=offset
tya
clc
sbc endoffsets,X
bvs gurg2
eor #$80
gurg2:
bmi skip_pixel ; neg if A<=endoffset
color_smc:
lda #$3b
.byte $2c ; bit trick, skips next two bytes
skip_pixel:
lda #$0 ; color black otherwise
blah:
sta (BASL),Y ; write out pixel
dey ; decrement Xcoord
bpl hlin ; loop until done all 40 pixels
lda #$bb ; force color to all-pink
sta color_smc+1
;==========================================
; draw star at beginning of line
lda offsets,X ; only draw if on-screen
bmi skip_star
clc ; modify x-coord
lda BASL
adc offsets,X
sta BASL
ldx LINE ; which line of bitmap to use
ldy #7 ; 8-bits wide
lda star_bitmap-1,X ; get low bit of bitmap into carry
draw_line_loop:
lsr
pha
bcc its_transparent
lda #$ff ; white
sta (BASL),Y ; draw on screen
its_transparent:
pla
dey
bpl draw_line_loop
skip_star:
ldx OFFSET_POINTER
; see if new offset (meaning, we've gone three lines)
dec LINE
bne not3
;======================
; new line
;======================
lda #$b3
sta color_smc+1 ; add shadow to (top?) of line
dec offsets,X ; scroll the line length
dec endoffsets,X
inc OFFSET_POINTER ; point to next set of offsets
lda #3 ; reset line vlue
sta LINE
not3:
;==========================
pla ; restore line count
clc
adc #1
cmp #24
; tax
; inx
; cpx #24 ; see if reached bottom
bne big_loop
; ideally we'd page flip, no room though
lda #80 ; delay a bit
jsr WAIT
beq forever_loop
offsets:
.byte 30,29,31,38,31,34,32,35
endoffsets:
.byte 60,50,61,68,61,64,62,65
; 76543210
; @
; @@@@@
; @ @
star_bitmap:
.byte $50
.byte $f8
.byte $20
; for bot
jmp horiz