[go: up one dir, main page]

Menu

[r132]: / psrp / asm / t4a.asm  Maximize  Restore  History

Download this file

154 lines (112 with data), 3.4 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
;
; Semi-adaptive Huffman decoder
; - Shining Force Gaiden: Final Conflict
;
; Written in TASM 3.0.1
;
; Start of decoder
;
; Note:
; The Z80 uses one set of registers for decoding the Huffman input data
; The other context is used to traverse the Huffman tree itself
;
; Encoded Huffman data is in page 2
;
; Huffman tree data is in page 2
; The symbols for the tree are stored in backwards linear order
#include "vars.asm"
#define TREE_BANK $02 ; bank containing Huffman trees ($8000-$BFFF)
.org $7ed0 ; $bed0-bf4f
; PUSH BC ; Save stack
; PUSH DE
PUSH HL
LD A,($FFFE) ; Save current page 1
PUSH AF
LD A,$6f000/$4000 ; Load in script bank #2
LD ($FFFE),A
LD HL,(SCRIPT) ; Set Huffman data location
LD A,(BARREL) ; Load Huffman barrel
EX AF,AF' ; Context switch to tree mode
EXX
LD A,(TREE) ; Load in tree / last symbol
; PUSH HL
; LD HL,$FFFF ; Page in Huffman tree data
; LD (HL),TREE_BANK
; POP HL
PUSH AF
LD BC,TREE_PTR ; Set physical address of tree data
LD H,$00 ; 8 -> 16
LD L,A
ADD HL,HL ; 2-byte indices
ADD HL,BC ; add offset
LD A,(HL) ; grab final offset
INC HL
LD H,(HL)
LD L,A
POP AF
LD A,$80 ; Initialise the tree barrel data
LD D,H ; Point to symbol data
LD E,L
DEC DE ; Symbol data starts one behind the tree
JR Tree_Shift1 ; Grab first bit
Tree_Mode1:
EX AF,AF' ; Context switch to tree mode
EXX
Tree_Shift1:
ADD A,A ; Shift out next tree bit to carry flag
JR NZ,Check_Tree1 ; Check for empty tree barrel
LD A,(HL) ; Shift out next tree bit to carry flag
INC HL ; Bump tree pointer
ADC A,A ; Note: We actually shift in a '1' by doing this!
; Clever trick to use all 8 bits for tree codes
Check_Tree1:
JR C,Decode_Done ; 0 -> tree node = continue looking
; 1 -> root node = symbol found
EX AF,AF' ; Switch to Huffman data processing = full context switch
EXX
ADD A,A ; Read in Huffman bit
JR NZ,Check_Huffman1 ; Check Huffman barrel status
LD A,(HL) ; Reload 8-bit Huffman barrel
INC HL ; Bump Huffman data pointer
ADC A,A ; Re-grab bit
Check_Huffman1:
JR NC,Tree_Mode1 ; 0 -> travel left, 1 -> travel right
EX AF,AF' ; Switch back to tree mode
EXX
LD C,$01 ; Start counting how many symbols to skip in the linear
; list since we are traversing the right sub-tree
Tree_Shift2:
ADD A,A ; Check if tree data needs refreshing
JR NZ,Check_Tree2
LD A,(HL) ; Refresh tree barrel again
INC HL ; Bump tree pointer
ADC A,A ; Grab new tree bit
Check_Tree2:
JR C,Bump_Symbol ; 0 -> tree, 1 -> symbol
INC C ; Need to bypass one more node
JR Tree_Shift2 ; Keep bypassing symbols
Bump_Symbol:
DEC DE ; Bump pointer in symbol list backwards
DEC C ; One less node/symbol to skip
JR NZ,Tree_Shift2 ; Check for full exhaustion of left subtree nodes
JR Tree_Shift1 ; Need status of termination
Decode_Done:
POP AF ; Restore old page 1
LD ($FFFE),A
LD A,(DE) ; Find symbol
LD (TREE),A ; Save decoded byte
; PUSH HL
; LD HL,$FFFF ; Page in old page 2
; LD (HL),OLD_BANK
; POP HL
EX AF,AF' ; Go to Huffman mode
EXX
LD (SCRIPT),HL ; Save script pointer
LD (BARREL),A ; Save Huffman barrel
EX AF,AF' ; Go to Tree mode
; EXX
POP HL ; Restore stack and exit
; POP DE
; POP BC
RET
.end ; TASM-only