home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
620.lha
/
PP_v1.4
/
Source.LZH
/
Source
/
newstuff.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-12-17
|
4KB
|
158 lines
/* Modified version of Nico's ppLoadData */
#include <pragmas.h>
#include <libraries/dosextens.h>
#include <exec/memory.h>
#define SAFETY 8 /* Safety decrunch margin */
extern int pp_DecrunchBuffer(UBYTE *,UBYTE *,int *);
extern UBYTE *fragallocabs(int,int,UBYTE *);
extern void fragfree(UBYTE *,int,int);
#asm
;
; What follows is Nico's own decrunch routine (v2.0). I couldn't get the
; in-library version to work. How about fixing the .fd file, Nico?!
;
; The code has undergone some optimization and application-speciffic
; modification by myself. Nothing too radical, but should do better than
; Nico's own code in most cases. Considered doing a Forbid() around tight
; loops, but dropped the idea (too hostile towards the rest of the system).
;
_pp_DecrunchBuffer:
movem.l d2-d7/a2-a3/a5,-(sp) ; /mich: Only preserve
move.l 36+4(a7),a0 ; relevant registers
move.l 36+8(a7),a3
move.l 36+12(a7),a5
; ' /mich: dropped 'move.l 36+16(a7),a6'
bsr.s Decrunch
movem.l (sp)+,d2-d7/a2-a3/a5
rts
; a3 -> file, a0 -> longword after crunched, a5 -> ptr to eff.
; destroys a0-a6 and d0-d7 (/mich: no longer entirely true)
Decrunch: moveq #3,d6
moveq #7,d7
moveq #1,d5
move.l d5,d4 ; /mich: Constant '#1' in d4
move.l a3,a2 ; remember start of file
move.l -(a0),d1 ; get file length and empty bits
tst.b d1
beq.s NoEmptyBits
bsr.s ReadBit ; this will always get the next long (D5 = 1)
sub.b d4,d1 ; /mich: Use constant '#1'
lsr.l d1,d5 ; get rid of empty bits
NoEmptyBits: lsr.l #8,d1
add.l d1,a3 ; a3 = endfile
CheckCrunch: bsr.s ReadBit ; check if crunch or normal
bcs.s CrunchedBytes
NormalBytes: moveq #0,d2
Read2BitsRow: move.l d4,d0 ; /mich: Use constant '#1'
bsr.s ReadD1
add.w d1,d2
cmp.w d6,d1
beq.s Read2BitsRow
ReadNormalByte: moveq #7,d0
bsr.s ReadD1
move.b d1,-(a3)
dbf d2,ReadNormalByte
cmp.l a3,a2
bcs.s CrunchedBytes
rts
ReadBit: lsr.l d4,d5 ; this will also set X if d5 becomes zero
beq.s GetNextLong ; /mich: Use constant '#1' (previous line)
rts
GetNextLong: move.l -(a0),d5
roxr.l d4,d5 ; X-bit set by lsr above
rts ; /mich: Use constant '#1' (previous line)
ReadD1sub: sub.w d4,d0 ; /mich: Use constant '#1'
ReadD1: moveq #0,d1
ReadBits: lsr.l d4,d5 ; this will also set X if d5 becomes zero
beq.s GetNext ; /mich: Use constant '#1' (previous line)
RotX: roxl.l d4,d1 ; /mich: Use constant '#1'
dbf d0,ReadBits
rts
GetNext: move.l -(a0),d5
roxr.l d4,d5 ; X-bit set by lsr above
bra.s RotX ; /mich: Use constant '#1' (prev line)
CrunchedBytes: move.l d4,d0 ; /mich: Use constant '#1'
bsr.s ReadD1 ; read code
moveq #0,d0
move.b 0(a5,d1.w),d0 ; get number of bits of offset
move.w d1,d2 ; d2 = code = length-2
cmp.w d6,d2 ; if d2 = 3 check offset bit and read length
bne.s ReadOffset
bsr.s ReadBit ; read offset bit (long/short)
bcs.s LongBlkOffs
moveq #7,d0
LongBlkOffs: bsr.s ReadD1sub
move.w d1,d3 ; d3 = offset
Read3BitsRow: moveq #2,d0
bsr.s ReadD1
add.w d1,d2 ; d2 = length-1
cmp.w d7,d1 ; cmp with #7
beq.s Read3BitsRow
bra.s DecrunchBlock
ReadOffset: bsr.s ReadD1sub ; read offset
move.w d1,d3 ; d3 = offset
DecrunchBlock: add.w d4,d2 ; /mich: Use constant '#1'
1$ move.b 0(a3,d3.w),-(a3)
dbf d2,1$
EndOfLoop: ; /mich: dropped 'move.w a3,(a6)'
cmp.l a3,a2
bcs CheckCrunch
rts
#endasm
myPPLoadData(register BPTR filehandle,register UBYTE **mem,register *size)
{
int efficiency,decrunched;
register crunlen;
register UBYTE *memgot;
register returnval = 1;
Read(filehandle,(char *)&efficiency,sizeof(int));
Seek(filehandle,-sizeof(int),OFFSET_END);
Read(filehandle,(char *)&decrunched,sizeof(int));
if (memgot = AllocMem((decrunched >>= 8) + SAFETY,MEMF_PUBLIC))
{
UBYTE *filebody;
Forbid();
FreeMem(memgot,decrunched + SAFETY);
filebody = fragallocabs(decrunched,10240,memgot+SAFETY);
memgot = AllocAbs(SAFETY,memgot);
Permit();
crunlen = Seek(filehandle,8,OFFSET_BEGINNING) - 8;
if (Read(filehandle,(char *)memgot,crunlen) == crunlen)
{
pp_DecrunchBuffer(memgot+crunlen,memgot+SAFETY,&efficiency);
FreeMem(memgot,SAFETY);
*mem = filebody;
*size = decrunched;
returnval = 0;
}
else
{
FreeMem(memgot,SAFETY);
fragfree(filebody,decrunched,10240);
}
}
return(returnval);
}