aboutsummaryrefslogtreecommitdiff
path: root/lib/cpcrslib/cpc_Uncrunch.s
diff options
context:
space:
mode:
authorJuan J. Martinez <jjm@usebox.net>2021-05-03 08:21:10 +0100
committerJuan J. Martinez <jjm@usebox.net>2021-05-03 10:00:00 +0100
commitc3b0fa04a663fe233765b83d3be41a42aa08c25d (patch)
tree0befda349001ef6ce306b39378f9c70ad917363e /lib/cpcrslib/cpc_Uncrunch.s
downloadreturn-of-traxtor-cpc-c3b0fa04a663fe233765b83d3be41a42aa08c25d.tar.gz
return-of-traxtor-cpc-c3b0fa04a663fe233765b83d3be41a42aa08c25d.zip
Initial import for public releaseHEADmain
Diffstat (limited to 'lib/cpcrslib/cpc_Uncrunch.s')
-rw-r--r--lib/cpcrslib/cpc_Uncrunch.s308
1 files changed, 308 insertions, 0 deletions
diff --git a/lib/cpcrslib/cpc_Uncrunch.s b/lib/cpcrslib/cpc_Uncrunch.s
new file mode 100644
index 0000000..7eba8c3
--- /dev/null
+++ b/lib/cpcrslib/cpc_Uncrunch.s
@@ -0,0 +1,308 @@
+; ******************************************************
+; ** Librería de rutinas SDCC para Amstrad CPC **
+; ** Raúl Simarro (Artaburu) - 2009, 2012 **
+; ******************************************************
+
+
+;*************************************
+; UNCRUNCH
+;*************************************
+
+
+.globl _cpc_Uncrunch
+
+_cpc_Uncrunch::
+; datos necesarios que vienen en la pila:
+; ORIGEN HL
+; DESTINO DE
+
+ ;Ojo, para que el pucrunch funcione hay que coger y quitar el salto de las interrupciones.
+ DI
+ LD HL,(#0X0038)
+ LD (#datos_int),HL
+
+ LD HL,#0X00C9
+ LD (#0x0038),HL
+ EI
+
+;POP AF
+;POP HL
+;POP DE
+;PUSH AF
+ LD IX,#2
+ ADD IX,SP
+ LD e,2 (IX)
+ LD d,3 (IX) ;DESTINO
+ LD l,0 (IX)
+ LD h,1 (IX) ;TEXTO ORIGEN
+
+
+pucrunch:
+ PUSH DE ; destination pointer to 2nd register
+ EXX ; set
+ POP DE
+
+
+ PUSH HL
+ PUSH DE
+ PUSH BC
+ PUSH AF
+
+ EXX
+
+ ; read the header self-modifying the
+ ; parameters straight into the code
+ ; skip useless data
+
+
+ LD BC,#6
+ ADD HL,BC
+
+ LD A, (HL) ; starting escape
+ INC HL
+ LD (#esc+1), A
+
+ INC HL ; skip useless data
+ INC HL
+
+ LD A, (HL) ; number of escape bits
+ INC HL
+ LD (#escb0+1), A
+ LD (#escb1+1), A
+
+ LD B, A ; 8 - escape bits
+ LD A, #8
+ SUB B
+ LD (#noesc+1), A
+
+ LD A, (HL) ; maxGamma + 1
+ INC HL
+ LD (#mg+1), A
+
+ LD B, A ; 8 - maxGamma
+ LD A, #9
+ SUB B
+ LD (#longrle+1), A
+
+ LD A, (HL) ; (1 << maxGamma)
+ INC HL
+ LD (#mg1+1), A
+
+ ADD A, A ; (2 << maxGamma) - 1
+ DEC A
+ LD (#mg21+1), A
+
+ LD A, (HL) ; extra lz77_0 position bits
+ INC HL
+ LD (#elzpb+1), A
+
+ INC HL ; skip useless data
+ INC HL
+
+ LD E, (HL) ; RLE table length
+ LD (#rlet+1), HL ; RLE table pointer
+ INC HL
+ LD D, #0
+ ADD HL, DE
+
+ LD C, #0X80 ; start decompression
+ JP loop_u
+
+newesc:
+ ld a, (#esc+1) ; save old escape code
+ ld d, a
+
+escb0:
+ LD B, #2 ; ** parameter
+ XOR A ; get new escape code
+ CALL get_bits
+ LD (#esc+1), A
+
+ LD A, D
+
+noesc:
+ LD B, #6 ; ** parameter
+ CALL get_bits ; get more bits to complete a byte
+
+ EXX ; output the byte
+ LD (DE), A
+ INC DE
+ EXX
+
+loop_u:
+ XOR A
+escb1:
+ LD B, #2 ; ** parameter
+ CALL get_bits ; get escape code
+esc:
+ CP #0 ; ** PARAMETER
+ JP NZ, noesc
+
+ CALL get_gamma ; get length
+ EXX
+ LD B, #0
+ LD C, A
+ EXX
+
+ CP #1
+ JP NZ, lz77_0 ; lz77_0
+
+ XOR A
+ CALL get_bit
+ JP NC, lz77_0_2 ; 2-byte lz77_0
+
+ CALL get_bit
+ JP NC, newesc ; escaped literal byte
+
+ CALL get_gamma ; get length
+ EXX
+ LD B, #1
+ LD C, A
+ EXX
+
+mg1:
+ CP #64 ; ** parameter
+ JP C, chrcode ; short RLE, get bytecode
+
+longrle:
+ LD B, #2 ; ** parameter
+ CALL get_bits ; complete length LSB
+ EX AF, AF'
+
+ CALL get_gamma ; length MSB
+ EXX
+ LD B, A
+ EX AF, AF'
+ LD C, A
+ EXX
+
+chrcode:
+ CALL get_gamma ; get byte to repeat
+
+ PUSH HL
+rlet:
+ LD HL, #0X0000 ; ** parameter
+ LD D, #0
+ LD E, A
+ ADD HL, DE
+
+ CP #32
+ LD A, (HL)
+ POP HL
+ JP C, dorle
+
+ LD A, E ; get 3 more bits to complete the
+ LD B, #3 ; byte
+ CALL get_bits
+
+dorle:
+ EXX ; output the byte n times
+ INC C
+dorlei:
+ LD (DE), A
+ INC DE
+ DEC C
+ JP NZ, dorlei
+ DEC B
+ JP NZ, dorlei
+ EXX
+ JP loop_u
+
+lz77_0:
+ CALL get_gamma ; offset MSB
+mg21:
+ CP #127 ; ** parameter
+
+ ; ret z
+
+ JP Z, fin ; EOF, return
+
+ DEC A ; (1...126 -> 0...125)
+elzpb:
+ LD B, #0 ; ** parameter
+ CALL get_bits ; complete offset MSB
+
+lz77_0_2:
+ EX AF, AF'
+ LD B, #8 ; offset LSB
+ CALL get_bits
+ CPL ; xor'ed by the compressor
+
+ EXX ; combine them into offset
+ LD L, A
+ EX AF, AF'
+ LD H, A
+ INC HL
+
+ XOR A ; CF = 0
+
+ PUSH DE ; (current output position) - (offset)
+ EX DE, HL
+ SBC HL, DE
+ POP DE
+
+ INC BC
+
+ LDIR ; copy
+ EXX
+ JP loop_u
+
+;## Get a bit from the source stream.
+;## Return CF = result
+get_bit:
+ SLA C ; shift next bit into CF
+ RET NZ
+ LD C, (HL) ; get next byte
+ INC HL ; increase source stream pointer
+ RL C ; shift next bit into CF, bit0 = 1
+ RET
+
+;## Get multiple bits from the source stream.
+;## In B = number of bits to get
+;## Return A = result
+get_bits:
+ DEC B
+ RET M
+ SLA C ; shift next bit into CF
+ JP NZ, gb1
+ LD C, (HL) ; get next byte
+ INC HL ; increase source stream pointer
+ RL C ; shift next bit into CF, bit0 = 1
+gb1:
+ RLA ; rotate next bit into A
+ JP get_bits
+
+;## Get an Elias Gamma coded value from the source stream.
+;## Return A = result
+get_gamma:
+ LD B, #1
+mg:
+ LD A, #7 ; ** parameter
+gg1:
+ CALL get_bit ; get bits until 0-bit or max
+ JR NC, gg2
+ INC B
+ CP B
+ JP NZ, gg1
+gg2:
+ LD A, #1 ; GET THE ACTUAL VALUE
+ DEC B
+ JP get_bits
+
+fin:
+ ; Restauramos los registros dobles y vuelta limpia
+ EXX
+ POP AF
+ POP BC
+ POP DE
+ POP HL
+ EXX
+
+ ;RET
+ DI
+ LD HL,(#datos_int)
+ LD (#0X0038),HL ;RESTAURO LA INTERRUPCIÓN ORIGINAL
+ EI
+ RET
+datos_int:
+ .DW #0 \ No newline at end of file