********************************* *** CrMData V1.01 *** *** (c) 1993 Thomas Schwarz *** ********************************* incdir dh0:ass/Include/ include exec/exec_lib.i include dos/dos_lib.i include dos/dosextens.i include utility/tagitem.i incdir dh1:t/ass/Include/ include libraries/CrM.i include libraries/CrM_lib.i ************************************************* CALL MACRO jsr _LVO\1(a6) ENDM CALLEXEC MACRO move.l 4.w,a6 CALL \1 ENDM CALLCRM MACRO move.l _CrMBase(pc),a6 CALL \1 ENDM CALLDOS MACRO move.l _DOSBase(pc),a6 CALL \1 ENDM ************************************************* CrunchOnly equ 1 DecrunchOnly equ 2 ExtraMemLen equ 100 ************************************************* main: lea CommandLine(pc),a1 movem.l d0/a0,(a1) ;save CLI-Parameters ** Open dos.library: ** lea DOSName(pc),a1 CALLEXEC OldOpenLibrary lea _DOSBase(pc),a0 move.l d0,(a0) beq.s .End ** Get output handle: ** move.l d0,a6 CALL Output lea OutHandle(pc),a0 move.l d0,(a0) beq.s .CloseDOS ** Open CrM.library: ** lea CrMName(pc),a1 moveq #4,d0 CALLEXEC OpenLibrary lea _CrMBase(pc),a0 move.l d0,(a0) beq.s .CloseDOS ** Do all actions: ** bsr.s mainloop ** Close CrM.library: ** move.l _CrMBase(pc),a1 CALLEXEC CloseLibrary ** Close dos.library: ** .CloseDOS: move.l _DOSBase(pc),a1 CALLEXEC CloseLibrary ** Return to the CLI: ** .End: moveq #0,d0 rts *---------- mainloop: lea InitTxt(pc),a0 bsr.w PrintText ** Analyse Commandline: ** movem.l CommandLine(pc),d1/a1 ;get Parameters clr.b -1(a1,d1.w) ;replace <cr> by Null move.b (a1),d0 beq.w .usage ;no Parameters cmp.b #"?",d0 beq.w .usage ;question mark -> print usage lea Algorithm(pc),a2 move.w (a2),d1 ;default Algorithm cmp.b #"-",d0 bne.w .noopts ;no option specified addq.l #1,a1 ** Optionsloop: processes all options, no spaces between options are allowed! .optsloop: move.b (a1)+,d0 ;get char beq.w .usage cmp.b #" ",d0 beq.w .noopts ;no more options cmp.b #"1",d0 beq.s .norm cmp.b #"2",d0 beq.s .lzh cmp.b #"c",d0 beq.s .crunch cmp.b #"d",d0 beq.s .decrunch cmp.b #"f",d0 beq.s .flash cmp.b #"l",d0 beq.s .longer cmp.b #"s",d0 beq.s .sample cmp.b #"y",d0 beq.s .encrypt lea UnknownOpt(pc),a0 move.b d0,(a0) lea UnknownOptTxt(pc),a0 bsr.w PrintText bra.s .optsloop *----- .norm: and.w #$fff0,d1 ;kill old algorithm or.w #cm_Normal,d1 ;new algo bra.s .optsloop *----- .lzh: and.w #$fff0,d1 ;kill old algorithm or.w #cm_LZH,d1 ;new algo bra.s .optsloop *----- .crunch: lea Operation(pc),a0 move.b #CrunchOnly,(a0) bra.s .optsloop *----- .decrunch: lea Operation(pc),a0 move.b #DecrunchOnly,(a0) bra.s .optsloop *----- .flash: bset #cmB_LEDFlash,d1 bra.s .optsloop *----- .longer: lea LongerFileFlag(pc),a0 st (a0) bra.w .optsloop *----- .sample: bset #cmB_Sample,d1 bra.w .optsloop *----- .encrypt: bset #cmB_PW,d1 bra.w .optsloop *----- .noopts: move.w d1,(a2) ;algorithm lea SourceName(pc),a0 move.l a1,(a0) lea DestName(pc),a0 ;normally Source- and DestName are move.l a1,(a0) ;the same... .search: move.b (a1)+,d0 beq.s .samedest ;no second filename cmp.b #" ",d0 bne.s .search move.l a1,(a0) ;new DestName clr.b -1(a1) ;replace <Space> by Null .samedest: ** Open Sourcefile: ** move.l SourceName(pc),d1 move.l #MODE_OLDFILE,d2 CALLDOS Open move.l d0,d5 beq.w .srcnotopen ** Read DataHeader (first 14 Bytes in the file): ** move.l d5,d1 lea DataHdr(pc),a0 move.l a0,d2 moveq #14,d3 CALL Read lea DataHdr(pc),a0 CALLCRM cmCheckCrunched lea Operation(pc),a0 tst.l d0 beq.s .loadnormal ;file is not crunched with CrM cmp.b #CrunchOnly,(a0) beq.w .alreadycrunched ;can't crunch twice! move.b #DecrunchOnly,(a0) bsr.w CrunchedLoad ;load crunched file bra.s .crloadcont .loadnormal: cmp.b #DecrunchOnly,(a0) beq.w .notcrunched move.b #CrunchOnly,(a0) bsr.w NormalLoad ;load original file .crloadcont: move.l d0,-(sp) ;save return code move.l d5,d1 CALLDOS Close ;close Sourcefile move.l (sp)+,d0 beq.s .done ;loading failed! move.b Operation(pc),d0 cmp.b #DecrunchOnly,d0 bne.s .nodecr bsr.w DecrunchIt ;decrunch data beq.s .done .nodecr: move.b Operation(pc),d0 cmp.b #DecrunchOnly,d0 bne.s .nodecrsave bsr.w DecrunchedSave ;save original data .nodecrsave: move.b Operation(pc),d0 cmp.b #CrunchOnly,d0 bne.s .nocr bsr.w CrunchIt ;crunch data beq.s .done .nocr: move.b Operation(pc),d0 cmp.b #CrunchOnly,d0 bne.s .nocrsave bsr.w CrunchedSave ;save crunched data .nocrsave: .done: ** Free cmCrunchStruct: ** move.l CrStruct(pc),d0 beq.s .nocrstruct ;no cmCrunchStruct allocated move.l d0,a1 moveq #cm_FreeStruct,d0 CALLCRM cmProcessCrunchStructA .nocrstruct: ** Free Buffer: ** move.l MemBase(pc),a1 move.l MemLen(pc),d0 beq.s .End CALLEXEC FreeMem .End: rts *------- ** Sourcefile open failed! ** .srcnotopen: move.l SourceName(pc),a0 move.l a0,-(sp) lea NotOpenTxt(pc),a0 move.l sp,a1 bsr.s RawPrintText addq.l #4,sp rts *------- ** DecrunchOnly: File is not crunched ** .notcrunched: lea NotCrunchedTxt(pc),a0 .acrcont: move.l SourceName(pc),-(sp) move.l sp,a1 bsr.s RawPrintText addq.l #4,sp moveq #0,d0 bra.w .crloadcont *----- ** CrunchOnly: File is already crunched ** .alreadycrunched: lea AlreadyCrTxt(pc),a0 bra.s .acrcont *------- ** Print Usage: ** .usage: lea UsageTxt(pc),a0 ; bra.s PrintText ******************************** ** Print some text to the CLI ** PrintText: ** a0:Text movem.l d0-d3/a0-a1/a6,-(sp) move.l a0,d2 move.l OutHandle(pc),d1 moveq #-1,d3 .count: addq.l #1,d3 tst.b (a0)+ bne.s .count CALLDOS Write movem.l (sp)+,d0-d3/a0-a1/a6 rts *---------- ** Print some text to the CLI with formatting using RawDoFmt(): ** RawPrintText: ** a0:Text a1:Args movem.l d0-d2/a0-a3/a6,-(sp) lea .stuffchar(pc),a2 lea InitTxt(pc),a3 CALLEXEC RawDoFmt lea InitTxt(pc),a0 bsr.s PrintText ;print the converted text movem.l (sp)+,d0-d2/a0-a3/a6 rts *----- .stuffchar: move.b d0,(a3)+ ;put data to output string rts ***************************** ** Load a file to crunch it. A cmCrunchStruct and the Buffer for the file ** will be allocated. NormalLoad: ** Get Lock on the Sourcefile: ** move.l SourceName(pc),d1 moveq #ACCESS_READ,d2 CALLDOS Lock move.l d0,d4 beq.w .notopen ;locking failed! ** Examine Sourcefile: ** move.l d4,d1 lea InitTxt(pc),a0 ;InitTxt serves as buffer for the fib move.l a0,d2 CALL Examine move.l d0,-(sp) ;save result on the stack ** UnLock Sourcefile: ** move.l d4,d1 CALL UnLock move.l (sp)+,d0 beq.w .notopen ;examining failed! lea InitTxt(pc),a0 move.l fib_Size(a0),d7 ;Size of Sourcefile ** Allocate Buffer (Len=Sourcefilelength+ExtraMemLen): ** moveq #ExtraMemLen,d0 add.l d7,d0 lea MemLen(pc),a0 move.l d0,(a0) moveq #0,d1 CALLEXEC AllocMem lea MemBase(pc),a0 move.l d0,(a0) beq.w .nomem ;not enough memory ** Allocate a cmCrunchStruct: ** clr.l -(sp) ;TAG_DONE move.w Algorithm(pc),-(sp) clr.w -(sp) move.l #CMCS_Algo,-(sp) move.l sp,a0 moveq #cm_AllocStruct,d0 CALLCRM cmProcessCrunchStructA lea 12(sp),sp lea CrStruct(pc),a0 move.l d0,(a0) beq.s .nomem ;allocating failed move.l d7,-(sp) move.l SourceName(pc),a0 move.l a0,-(sp) lea LoadingTxt(pc),a0 move.l sp,a1 bsr.w RawPrintText addq.l #8,sp ** Copy DataHeader to Buffer ** move.l MemBase(pc),a1 add.w #ExtraMemLen,a1 lea DataHdr(pc),a0 move.l (a0)+,(a1)+ move.l (a0)+,(a1)+ move.l (a0)+,(a1)+ move.w (a0)+,(a1)+ ** Load rest of sourcefile ** move.l d5,d1 move.l a1,d2 move.l d7,d3 subq.l #8,d3 subq.l #6,d3 CALLDOS Read cmp.l d0,d3 bne.s .readerr ;readerror lea OrigLen(pc),a0 move.l d7,(a0) ;Originallen (Length of Sourcefile) lea ReturnTxt(pc),a0 bsr.w PrintText moveq #1,d0 ;return: TRUE rts *----- ** Opening failed: ** .notopen: move.l SourceName(pc),a0 move.l a0,-(sp) lea NotOpenTxt(pc),a0 move.l sp,a1 bsr.w RawPrintText addq.l #4,sp .Exit: moveq #0,d0 ;return: FALSE rts *----- ** not enough memory available: ** .nomem: lea MemLen(pc),a0 clr.l (a0) lea NoMemTxt(pc),a0 .prtx: bsr.w PrintText bra.s .Exit ** readerror: ** .readerr: lea ReadErrTxt(pc),a0 bra.s .prtx *------------ ** Crunch Data: ** CrunchIt: lea CrunchingTxt(pc),a0 bsr.w PrintText move.l CrStruct(pc),a0 move.l MemBase(pc),a1 move.l a1,cmcr_Dest(a0) moveq #ExtraMemLen,d0 add.l d0,a1 move.l a1,cmcr_Src(a0) move.l OrigLen(pc),d1 move.l d1,cmcr_SrcLen(a0) add.l d0,d1 move.l d1,cmcr_DestLen(a0) lea DataHdr(pc),a1 move.l a1,cmcr_DataHdr(a0) clr.l cmcr_DisplayHook(a0) move.w #$7ffe,cmcr_DisplayStep(a0) CALLCRM cmCrunchData lea CrLen(pc),a0 move.l d0,(a0) beq.s .error ;error while crunching ** calculate gain in percent: you have to do this complicated rotating ** because there is no longword division available on a standard 68000 ** this routine is not very cool, it will produce shit when the gain is ** negative. (Problem now fixed). move.l OrigLen(pc),d1 move.l d1,d2 move.l d1,d3 moveq #0,d4 sub.l d0,d2 ;gain bpl.s .rotloop neg.l d2 moveq #1,d4 .rotloop: tst.l d2 bmi.s .rotend tst.l d3 bmi.s .rotend add.l d2,d2 add.l d3,d3 bra.s .rotloop .rotend: lsr.l #1,d2 lsr.l #1,d3 clr.w d2 clr.w d3 swap d2 swap d3 mulu #100,d2 divu d3,d2 tst.w d4 beq.s .noneg neg.w d2 .noneg: move.w d2,-(sp) move.l d0,-(sp) move.l d1,-(sp) move.l sp,a1 lea CrunchedTxt(pc),a0 bsr.w RawPrintText lea 10(sp),sp moveq #1,d0 ;return: TRUE rts ** error while crunchung: ** .error: move.l CrStruct(pc),a0 move.b cmcr_QuitFlag(a0),d0 lea AbortTxt(pc),a0 cmp.b #"a",d0 beq.s .errend ;crunching was aborted (not possible yet) lea NotCrTxt(pc),a0 cmp.b #"n",d0 beq.s .errend ;data is not crunchable (or already ;crunched with another packer) lea UnknownErrTxt(pc),a0 .errend: bsr.w PrintText moveq #0,d0 ;return: FALSE rts *---------- ** Save crunched data: ** CrunchedSave: ** Open Destination file: ** move.l OrigLen(pc),d0 sub.l CrLen(pc),d0 subq.l #8,d0 subq.l #6,d0 bgt.s .cont move.b LongerFileFlag(pc),d0 bne.s .cont ;keep longer files lea TooLongFileTxt(pc),a0 bra.w RawPrintText *----- .cont: move.l DestName(pc),d1 move.l #MODE_NEWFILE,d2 CALLDOS Open move.l d0,d5 beq.s .notopen ;open failed moveq #14,d0 add.l CrLen(pc),d0 move.l d0,-(sp) move.l DestName(pc),-(sp) move.l sp,a1 lea SavingTxt(pc),a0 bsr.w RawPrintText addq.l #8,sp ** Write DataHeader: ** move.l d5,d1 lea DataHdr(pc),a0 move.l a0,d2 moveq #14,d3 CALL Write ;DataHeader tst.l d0 bmi.s .error ;writeerror ** Write crunched Data: ** move.l d5,d1 move.l MemBase(pc),d2 move.l CrLen(pc),d3 CALL Write ;Data tst.l d0 bmi.s .error ;writeerror ** Close Destination file: ** move.l d5,d1 CALL Close ** Generate Comment: ** lea Comment(pc),a0 move.l OrigLen(pc),-(sp) move.l sp,a1 lea .stuffchar(pc),a2 lea InitTxt(pc),a3 ;again InitTxt serves as a temporary ;buffer CALLEXEC RawDoFmt addq.l #4,sp ** Set Comment (for RTDD): ** move.l DestName(pc),d1 lea InitTxt(pc),a0 move.l a0,d2 CALLDOS SetComment lea ReturnTxt(pc),a0 bra.w PrintText ;print texte and return (no returncode) *----- ** Destfile open failed: ** .notopen: move.l DestName(pc),-(sp) move.l sp,a1 lea NotOpenTxt(pc),a0 bsr.w RawPrintText addq.l #4,sp rts *----- ** writeerror: ** .error: lea ErrorWriteTxt(pc),a0 bsr.w PrintText ** close destfile: ** move.l d5,d1 CALL Close ** delete destfile: ** move.l DestName(pc),d1 CALL DeleteFile rts *----- .stuffchar: move.b d0,(a3)+ ;put data to output string rts ***************************** ** Load data to decrunch (Buffer will be allocated): ** CrunchedLoad: ** Copy contents of DataHeader to internal Variables: ** lea DataHdr(pc),a0 lea OrigLen(pc),a1 move.l dh_OriginalLen(a0),(a1) lea CrLen(pc),a1 move.l dh_CrunchedLen(a0),(a1) ** Allocate Buffer (len=OrigLen+MinSecDist): ** moveq #0,d0 move.w dh_MinSecDist(a0),d0 add.l dh_OriginalLen(a0),d0 lea MemLen(pc),a0 move.l d0,(a0) moveq #0,d1 CALLEXEC AllocMem lea MemBase(pc),a0 move.l d0,(a0) beq.w .nomem ;not enough memory moveq #14,d0 add.l CrLen(pc),d0 move.l d0,-(sp) move.l SourceName(pc),-(sp) move.l sp,a1 lea LoadingTxt(pc),a0 bsr.w RawPrintText addq.l #8,sp ** Read crunched Data: ** move.l d5,d1 move.l MemBase(pc),d2 move.l CrLen(pc),d3 CALLDOS Read cmp.l d0,d3 bne.s .readerr ;readerror moveq #1,d0 ;return: TRUE lea ReturnTxt(pc),a0 bra.s .prtx *----- .readerr: moveq #0,d0 ;return: FALSE lea ReadErrTxt(pc),a0 bra.s .prtx *----- .nomem: lea MemLen(pc),a0 clr.l (a0) moveq #0,d0 ;return: FALSE lea NoMemTxt(pc),a0 .prtx: bra.w PrintText *------------ ** Decrunch Data: ** DecrunchIt: move.l OrigLen(pc),-(sp) move.l CrLen(pc),-(sp) move.l sp,a1 lea DecrunchingTxt(pc),a0 bsr.w RawPrintText addq.l #8,sp lea DataHdr(pc),a2 move.l MemBase(pc),a0 move.w dh_MinSecDist(a2),d0 lea 0(a0,d0.w),a1 CALLCRM cmDecrunch tst.l d0 beq.s .error lea ReturnTxt(pc),a0 bsr.w PrintText moveq #1,d0 ;return: TRUE rts *----- ** error while decrunching: ** .error: lea DecrErrorTxt(pc),a0 bsr.w PrintText moveq #0,d0 ;return: FALSE rts *---------- ** Save original (decrunched) file: ** DecrunchedSave: ** Open Destination file: ** move.l DestName(pc),d1 move.l #MODE_NEWFILE,d2 CALLDOS Open move.l d0,d5 beq.s .notopen ;openfail move.l OrigLen(pc),-(sp) move.l DestName(pc),-(sp) move.l sp,a1 lea SavingTxt(pc),a0 bsr.w RawPrintText addq.l #8,sp ** Write Data: ** move.l d5,d1 lea DataHdr(pc),a0 moveq #0,d2 move.w dh_MinSecDist(a0),d2 add.l MemBase(pc),d2 move.l OrigLen(pc),d3 CALL Write ;Data tst.l d0 bmi.s .error ;writeerror ** Close File: ** move.l d5,d1 CALL Close lea ReturnTxt(pc),a0 bra.w PrintText ;print text and return (no returncode) *----- ** destfile could not be opened: ** .notopen: move.l DestName(pc),-(sp) move.l sp,a1 lea NotOpenTxt(pc),a0 bsr.w RawPrintText addq.l #4,sp rts *----- ** writeerror: ** .error: lea ErrorWriteTxt(pc),a0 bsr.w PrintText ** Close destfile: ** move.l d5,d1 CALL Close ** Delete destfile: ** move.l DestName(pc),d1 CALL DeleteFile rts ************************************************* _DOSBase: dc.l 0 _CrMBase: dc.l 0 OutHandle: dc.l 0 ;Handle to print text in the CLI MemBase: dc.l 0 ;Start of Buffer MemLen: dc.l 0 ;Length of Buffer OrigLen: dc.l 0 ;Original Length of Data CrLen: dc.l 0 ;Crunched Length if Data CrStruct: dc.l 0 ;struct cmCrunchStruct * CommandLine: dc.l 0,0 ;CLI-Parameters (text *, len) SourceName: dc.l 0 ;Sourcefilename * DestName: dc.l 0 ;Destinationfilename * DataHdr: ds.b 14 ;struct DataHeader Algorithm: dc.w cm_LZH!cmF_Overlay ;Algorithm for cmcs_Algo Tag Operation: dc.b 0 ;type of Operation (CrunchOnly, ;DecrunchOnly or NULL for auto) LongerFileFlag: dc.b 0 ;keep longer files? DOSName: dc.b "dos.library",0 CrMName: CRMNAME cnop 0,4 InitTxt: dc.b 27,"[33;1mCrMData ",27,"[0;33mV1.01 ",27,"[0m--- " dc.b 27,"[32m(c) 1993 Thomas Schwarz",27,"[0m",10,10,0 dc.b "$VER: CrMData 1.01",0 UsageTxt: dc.b "Usage: CrMData [-12cdfsy] <sourcefile> [<destfile>]",10 dc.b "-1 : use CrM-Normal algorithm",10 dc.b "-2 : use LZ-Huffman algorithm",10 dc.b "-c : crunch only",10 dc.b "-d : decrunch only",10 dc.b "-f : enable Power-LED flashing",10 dc.b "-l : save file, even if it becomes longer",10 dc.b "-s : use Sample-Mode",10 dc.b "-y : enable password encryption",10,0 UnknownOptTxt: dc.b "Unknown option: -" UnknownOpt: dc.b " !" ReturnTxt: dc.b 10,0 NotOpenTxt: dc.b "Could not open `%s'!",10,0 LoadingTxt: dc.b "Loading `%s' (%ld bytes)...",0 NoMemTxt: dc.b "Not enough memory available!",10,0 ReadErrTxt: dc.b "Read Error!",10,0 NotCrunchedTxt: dc.b "Can't decrunch `%s': File is not crunched!",10,0 AlreadyCrTxt: dc.b "Can't crunch `%s': File is already crunched!",10,0 CrunchingTxt: dc.b "Crunching...",0 CrunchedTxt: dc.b " %ld -> %ld (%d%% gain)",10,0 AbortTxt: dc.b "Crunching aborted!",10,0 NotCrTxt: dc.b "File not crunchable!",10,0 UnknownErrTxt: dc.b "Strange error occurred while crunching!",10,0 SavingTxt: dc.b "Saving `%s' (%ld bytes)...",0 ErrorWriteTxt: dc.b " Error while writing!",10,0 Comment: dc.b "CrM!%08lx",0 DecrunchingTxt: dc.b "Decrunching (%ld -> %ld)...",0 DecrErrorTxt: dc.b " Error while decrunching!",10,0 TooLongFileTxt: dc.b "File not saved: crunched file is longer than original",10,0