summaryrefslogtreecommitdiff
path: root/src/ap/ap.z80
blob: 5dc7fe2acc5894fdec46af873a8706c1142d2fb1 (plain)
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
154
155
156
157
; C convention
.globl _ap_uncompress

; register call
;
; hl = source
; de = dest
.globl ap_uncompress

; The original Z80 decompressors for ApLib were written by Dan Weiss (Dwedit).
;
; aPPack decompressor
; original source by dwedit
; very slightly adapted by utopian
; optimized by Metalbrain

; this is to enable undocumented Z80 opcodes in SDCC assembler
.ez80

_ap_uncompress::
        ld hl, #2
        add hl, sp
        ld e, (hl)
        inc hl
        ld d, (hl)
        inc hl
        ld a, (hl)
        inc hl
        ld h, (hl)
        ld l, a

ap_depack::
        ld ixl, #128

apbranch1:
        ldi
aploop0:
        ld ixh, #1		;LWM = 0
aploop:
        call ap_getbit
        jr nc, apbranch1
        call ap_getbit
        jr nc, apbranch2
        ld b, #0
        call ap_getbit
        jr nc, apbranch3
        ld c, #16		;get an offset
apget4bits:
        call ap_getbit
        rl c
        jr nc, apget4bits
        jr nz, apbranch4
        ld a, b
apwritebyte:
        ld (de), a			;write a 0
        inc de
        jr aploop0
apbranch4:
        and a
        ex de, hl 		;write a previous byte (1-15 away from dest)
        sbc hl, bc
        ld a, (hl)
        add hl, bc
        ex de, hl
        jr apwritebyte
apbranch3:
        ld c, (hl)		;use 7 bit offset, length = 2 or 3
        inc  hl
        rr c
        ret z			;if a zero is encountered here, it is EOF
        ld a, #2
        adc a,b
        push hl
        ld iyh, b
        ld iyl, c
        ld h, d
        ld l, e
        sbc hl, bc
        ld c, a
        jr ap_finishup2
apbranch2:
        call ap_getgamma	;use a gamma code * 256 for offset, another gamma code for length
        dec c
        ld a, c
        sub ixh
        jr z, ap_r0_gamma		;if gamma code is 2, use old r0 offset,
        dec a
        ;do I even need this code?
        ;bc=bc*256+(hl), lazy 16bit way
        ld b, a
        ld c, (hl)
        inc hl
        ld iyh, b
        ld iyl, c

        push bc

        call ap_getgamma

        ex (sp), hl		;bc = len, hl=offs
        push de
        ex de, hl

        ld a, #4
        cp d
        jr nc, apskip2
        inc bc
        or a
apskip2:
        ld hl, #127
        sbc hl, de
        jr c, apskip3
        inc bc
        inc bc
apskip3:
        pop hl		;bc = len, de = offs, hl=junk
        push hl
        or a
ap_finishup:
        sbc hl, de
        pop de		;hl=dest-offs, bc=len, de = dest
ap_finishup2:
        ldir
        pop hl
        ld ixh, b
        jr aploop

ap_r0_gamma:
        call ap_getgamma		;and a new gamma code for length
        push hl
        push de
        ex de, hl
        ld d, iyh
        ld e, iyl
        jr ap_finishup

ap_getbit:
        ld a, ixl
        add a, a
        ld ixl, a
        ret nz
        ld a, (hl)
        inc hl
        rla
        ld ixl, a
        ret

ap_getgamma:
        ld bc, #1
ap_getgammaloop:
        call ap_getbit
        rl c
        rl b
        call ap_getbit
        jr c, ap_getgammaloop
        ret