From fd511a54203c311434a04a58d377545566728833 Mon Sep 17 00:00:00 2001 From: "Christian A. Weber" Date: Mon, 18 May 1992 02:16:29 +0000 Subject: Total neu geschrieben. I/O ist jetzt gebuffert, und benutzt die neuen PushChunk/WriteChunkBytes/PopChunk-Routinen. Braucht jetzt nur noch etwa 100 Bytes Stack statt 650. Farben der CMAP werden jetzt richtig berechnet (*17 statt geshiftet). --- Source/SaveClip.S | 681 ++++++++++++++++++++++-------------------------------- 1 file changed, 271 insertions(+), 410 deletions(-) diff --git a/Source/SaveClip.S b/Source/SaveClip.S index ecc4925..f8e81ad 100644 --- a/Source/SaveClip.S +++ b/Source/SaveClip.S @@ -1,11 +1,11 @@ ** -** $Id: SaveClip.S,v 1.1 92/05/12 22:26:45 chris Exp $ -** $Revision: 1.1 $ +** $Id: SaveClip.S,v 21.1 92/05/15 03:22:11 chris Exp $ +** $Revision: 21.1 $ ** ** $Filename: SaveClip.S $ ** $Author: chris $ ** $Release: 19.1 $ -** $Date: 92/05/12 22:26:45 $ +** $Date: 92/05/15 03:22:11 $ ** ** iff.library/IFFL_SaveClip ** @@ -54,14 +54,14 @@ * height - height in lines of the rectangle * * RESULTS -* Non-zero if successful, 0 if error, Call IFFL_IFFError() to -* know more about the reason of the failure +* Non-zero if successful, 0 if an error occurred. You can then call +* IFFL_IFFError() to know more about the reason of the failure. * * NOTE -* This routine needs 650 bytes of stack space +* Up to V19 this routine needs at least 650 bytes of stack space * * BUGS -* The width of the rectangle will be rounded to WORD boundaries, +* The width of the rectangle will be truncated to WORD boundaries, * because DPAINT wants it! * * SEE ALSO @@ -69,423 +69,284 @@ * ***************************************************************************** -MAXPLANES: EQU 24 ; Höchstens 24 Bitplanes +MAXPLANES EQU 32 ; Höchstens 32 Bitplanes +BUFFERSIZE EQU 10240 ; Write-Buffer +BUFFERFULL EQU BUFFERSIZE-2048 ; naja... -iffhd: equ 0 ; FORM -iffsize: equ 4 ; .... ILBM + STRUCTURE Stack,0 + STRUCT stk_BMHD,bmh_SIZEOF ; Muss am Anfang sein + ULONG stk_CAMG + STRUCT stk_Planes,4*MAXPLANES + LABEL stk_SIZEOF -bmhdchunk: equ iffsize+8 ; BMHD -bmhdsize: equ bmhdchunk+4 ; .... -bmhd: equ bmhdsize+4 ; bmhd-Struktur - -camgchunk: equ bmhd+bmh_SIZEOF ; CAMG -camgsize: equ camgchunk+4 ; .... -camg: equ camgsize+4 ; 0000ViewModes - -cmapchunk: equ camg+4 ; CMAP -cmapsize: equ cmapchunk+4 ; .... -cmap: equ cmapsize+4 ; Farbwerte - -bodychunk: equ cmap+(3*512) ; BODY -bodysize: equ bodychunk+4 ; .... +SaveClipFunc: movem.l d2-d7/a2-a6,-(SP) + suba.w #stk_SIZEOF,SP ; Platz schaffen + move.l d0,d6 ; D6 : Flags + move.l a2,d5 ; D5 : Farbtabelle oder NULL + move.l a0,a2 ; A2 : Filename + movea.l a6,a5 ; A5 : IFFBase + movea.l a1,a4 ; A4 : BitMap -xoffset: equ bodysize+4 -yoffset: equ xoffset+2 -width: equ yoffset+2 -height: equ width+2 + *** BMHD erstellen auf dem Stack und Parameter eintragen -sb_datasize: equ height+2 ; Gesamt-Datengrösse + andi.w #15,d0 ; A rough guess :-) + move.b d0,bmh_Compression(SP) + lsl.w #3,d1 ; Aus Bytes mach Pixel + movem.w d1/d2,bmh_XPos(SP) ; X und Y-Position -SaveClipFunc: movem.l d2-d7/a2-a6,-(SP) - suba.w #sb_datasize,SP ; Speicher reservieren - movea.l a6,a5 ; IFFBase - move.l a0,d6 ; D6 : Filename - movea.l a1,a3 ; A3 : BitMap - movea.l SP,a4 ; A4 : wird BitMapHeader - - move.w d1,xoffset(SP) - move.w d2,yoffset(SP) bclr #0,d3 ; Breite WORD align für DPaint - move.w d3,width(SP) - move.w d4,height(SP) - - *** FORM....ILBM-Header & BMHD-Chunk initialisieren (im Speicher) - - move.l #'FORM',(a4)+ ; Ein IFF-Formular - moveq.l #cmap,d7 ; 'ILBM'+BMHD+CAMG+CMAP+BODY - move.l d7,(a4)+ ; eintragen - move.l #'ILBM',(a4)+ ; File-Typ - - move.l #'BMHD',(a4)+ ; Chunk-Name eintragen - moveq.l #bmh_SIZEOF,d7 - move.l d7,(a4)+ ; Chunk-Size eintragen - move.b d0,bmh_Compression(a4) ; Cruncher-Typ merken - - clr.b bmh_Masking(a4) - clr.b bmh_Pad1(a4) - clr.w bmh_TranspCol(a4) - move.w xoffset(SP),d0 - lsl.w #3,d0 ; Pixel - move.w d0,bmh_XPos(a4) ; X-Position - move.w yoffset(SP),bmh_YPos(a4) ; X-Position - move.w #$0A0B,bmh_XAspect(a4) ; X- und Y-Aspect zusammen! - move.b bm_Depth(a3),bmh_nPlanes(a4) - - lsl.w #3,d3 ; Breite mal 8 - move.w d3,bmh_Width(a4) ; gibt Breite in Pixel - move.w d3,bmh_PageWidth(a4) - - move.w d4,bmh_Height(a4) ; Bildhöhe eintragen - move.w d4,bmh_PageHeight(a4) - - *** CAMG-Chunk generieren (immer) - - move.l #'CAMG',camgchunk(SP) ; Chunk-Name - moveq #4,d7 - move.l d7,camgsize(SP) ; Chunk-Size - movea.l a4,a0 ; struct BitMapHeader - bsr CalcViewModes ; ViewModes nach d0 - bclr.b #7,bmh_Compression(a4) ; HAM gewünscht ? - beq.s 1$ ; nein ---> - bset #11,d0 ; HAM-Bit setzen -1$: move.l d0,camg(SP) ; ViewModes eintragen - - *** CMAP-Chunk generieren, falls notwendig (im Speicher) - - move.l #-8,cmapsize(SP) ; falls no CMAP: -'CMAP....' - - move.l a2,d0 ; tst.l a2 - beq.s nocmap - - lea cmapchunk(SP),a1 ; Hierhin will ich den Chunk - move.l #'CMAP',(a1)+ ; Chunkname - moveq #1,d0 - moveq #0,d1 - move.b bm_Depth(a3),d1 - cmpi.b #24,d1 ; Ist's ein 24-Bitplane-Bild ? - bne.s .No24 ; nein ---> - moveq #8,d1 ; Sonst immer 256 Farben + lsl.w #3,d3 ; Aus Bytes mach Pixel + movem.w d3/d4,bmh_Width(SP) ; Breite und Höhe + movem.w d3/d4,bmh_XAspect(SP) ; Aspect ratio + + move.w bm_BytesPerRow(a4),d0 + lsl.w #3,d0 + move.w d0,bmh_PageWidth(SP) + move.w bm_Rows(a4),bmh_PageHeight(SP) + + move.w bm_Depth(a4),bmh_nPlanes(SP) + + clr.b bmh_Masking(SP) + clr.b bmh_Pad1(SP) + clr.w bmh_TranspCol(SP) + + *** Puffer für Body-Daten (und CMAP) allozieren + + moveq.l #IFFL_ERROR_NOMEM,d4 ; D4 : Default-Error-Code + move.l #BUFFERSIZE,d0 + moveq.l #MEMF_PUBLIC,d1 ; No VMem! :-) + movea.l iffb_SysBase(a5),a6 + JSRLIB AllocMem + tst.l d0 + beq .NoMemory + movea.l d0,a3 ; A3 : Buffer + + *** IFF-File zum Schreiben öffnen + + moveq.l #IFFL_ERROR_WRITE,d4 ; D4 : Default-Error-Code + movea.l a2,a0 ; Filename + moveq.l #IFFL_MODE_WRITE,d0 + movea.l a5,a6 ; IFFBase + JSRLIB IFFL_OpenIFF + tst.l d0 + beq .OpenError + movea.l d0,a2 ; A2 : IFF-Handle + + *** BMHD-Chunk schreiben + + move.l #ID_ILBM,d0 + move.l #ID_BMHD,d1 + moveq.l #bmh_SIZEOF,d2 + movea.l SP,a1 ; BMHD-Struktur + bsr WriteChunk + beq .WriteError + + *** CAMG-Chunk generieren + + movea.l SP,a0 ; BMHD-Struktur + bsr CalcViewModes ; ViewModes nach D0 + + btst.l #7,d6 ; HAM gewünscht ? + beq.b .NoHAM ; nein ---> + bset.l #11,d0 ; HAM-Bit setzen +.NoHAM: move.l d0,stk_CAMG(SP) ; ViewModes auf Stack + + *** CAMG-Chunk schreiben + + ;; move.l #ID_ILBM,d0 + move.l #ID_CAMG,d1 + moveq.l #4,d2 ; 1 LONG + lea stk_CAMG(SP),a1 ; CAMG-Langwort + bsr WriteChunk + beq .WriteError + + *** CMAP-Chunk generieren und schreiben, falls notwendig + + tst.l d5 ; CMAP vorhanden ? + beq .NoCMap ; nein ---> + + moveq.l #0,d0 + move.b bm_Depth(a4),d0 ; Anzahl Planes + cmpi.b #8,d0 ; Mehr als 256 Farben (z.b. 24 bit)? + blo.b .No24 ; nein ---> + moveq #8,d0 ; Sonst maximal 256 Farben .No24: - lsl.w d1,d0 ; d0 := 2 ^ D1 = Anzahl Farben - move.w d0,d2 ; D2 : Anzahl Farben - mulu.w #3,d0 ; 3 Bytes pro Farbe - addq.l #2,d0 - andi.w #~3,d0 ; auf LONG alignen - move.l d0,(a1)+ ; Chunklänge - - subq.w #1,d2 ; für dbf -3$: move.w (a2)+,d0 - lsl.w #4,d0 - move.b d0,2(a1) ; blau - lsr.w #4,d0 - andi.b #$f0,d0 - move.b d0,1(a1) ; grün - lsr.w #4,d0 - andi.b #$f0,d0 - move.b d0,(a1) ; rot - addq.w #3,a1 - dbf d2,3$ - - *** File öffnen, IFF-Header auf Disk schreiben (vorläufig!) - -nocmap: move.l d6,d1 ; FileName - move.l #MODE_NEWFILE,d2 - movea.l iffb_DOSBase(a5),a6 - JSRLIB Open - move.l d0,d7 ; D7 : FileHandle - beq writeerror - - move.l cmapsize(SP),d0 ; CMAP-Grösse - add.l d0,iffsize(SP) ; zu Header-Grösse dazu - - move.l d7,d1 ; File - move.l SP,d2 ; Adr : IFF-Header - moveq #cmap+8,d3 ; Länge des Headers + 8 - add.l cmapsize(SP),d3 ; Plus Länge des CMAP-Chunks - JSRLIB Write ; schreiben - tst.l d0 ; Fehler ? - bmi.s writeerror ; ja! - - *** BODY-Daten schreiben, evtl. komprimiert - - tst.b bmh_Compression(a4) ; compacten ? - bne.s 1$ ; ja! - bsr VanillaSave - bra.s 2$ -1$: bsr CrunchSave -2$: tst.l d0 ; Fehler ? - bmi.s writeerror ; ja! - - move.l d0,d3 ; Body-Länge - addq.l #3,d3 ; auf nächstes LONG aufrunden - and.b #%11111100,d3 ; und LONG-alignen - move.l d3,bodysize(SP) ; aligned BODY-Grösse - add.l d3,iffsize(SP) ; zu Header-Grösse dazu - sub.l d0,d3 ; D3 := Wieviele Bytes zuviel - - tst.l d3 ; Align-Grösse = 0 ? - beq.s 3$ ; ja -> nichts schreiben - move.l d7,d1 ; File - clr.l -(SP) ; Nullen machen - move.l SP,d2 ; adr - JSRLIB Write ; schreiben - addq.l #4,SP ; Stack cleanen - tst.l d0 ; Fehler ? - bmi.s writeerror ; ja! - - *** IFF-Header nochmals schreiben & BODY-Header, diesmal korrekt - -3$: move.l d7,d1 ; File - moveq.l #0,d2 ; Position - moveq.l #OFFSET_BEGINNING,d3 ; Modus - JSRLIB Seek - - move.l d7,d1 ; File - move.l SP,d2 ; Adr : IFF-Header - moveq.l #cmap,d3 ; Länge des Headers - add.l cmapsize(SP),d3 ; Plus Länge des CMAP-Chunks - JSRLIB Write ; schreiben - tst.l d0 ; Fehler ? - bmi.s writeerror ; ja! - - lea bodychunk(SP),a0 - move.l #'BODY',(a0) ; Chunk-Namen eintragen - move.l d7,d1 ; File - move.l a0,d2 ; Adr - moveq #8,d3 ; Len - JSRLIB Write ; Body-Header schreiben - tst.l d0 ; Fehler ? - bmi.s writeerror ; ja! - - move.l d7,d1 ; File - JSRLIB Close - ;; moveq.l #0,d7 ; File ungültig - - bsr ClearError ; Error löschen, D0 := 1 - bra.s SaveClip_End - -writeerror: move.l d7,d1 ; File - beq.s 1$ ; schon / nochzu! - JSRLIB Close -1$: moveq #IFFL_ERROR_WRITE,d0 + moveq.l #1,d1 ; Bit-Maske zum Shiften + lsl.w d0,d1 ; D1 := 2^D0 = Anzahl Farben + move.l d1,d2 ; D2 : Anzahl Farben + + movea.l d5,a0 ; Amiga-Farbpalette + movea.l a3,a1 ; Destination-Buffer + bra.b .CMapDBF ; ---> für DBF +.CMapLoop: move.w (a0),d0 + lsr.w #8,d0 ; Rot-Anteil + mulu.w #17,d0 ; aus 0n mach nn + move.b d0,(a1)+ + + move.w (a0),d0 + lsr.w #4,d0 ; Grün-Anteil + andi.w #15,d0 + mulu.w #17,d0 ; aus 0n mach nn + move.b d0,(a1)+ + + move.w (a0)+,d0 + ;; lsr.w #0,d0 ; Blau-Anteil + andi.w #15,d0 + mulu.w #17,d0 ; aus 0n mach nn + move.b d0,(a1)+ + +.CMapDBF: dbf d1,.CMapLoop + + ;; move.l #ID_ILBM,d0 + move.l #ID_CMAP,d1 + mulu.w #3,d2 ; 3 Bytes pro Farbe gibt Size + movea.l a3,a1 ; CMAP-Daten + ;; movea.l a5,a6 ; IFFBase + bsr WriteChunk + tst.l d0 + beq .WriteError +.NoCMap: + + *** BODY-Chunk eröffnen + + movea.l a2,a0 ; IFF-Handle + ;; move.l #ID_ILBM,d0 + move.l #ID_BODY,d1 + movea.l a5,a6 ; IFFBase + JSRLIB IFFL_PushChunk + tst.l d0 + beq .WriteError + + *** PlanePtrs auf den Stack kopieren & X,Y-Offsets dazuaddieren + + moveq.l #0,d0 ; D1 nicht nötig wegen mulu + movem.w bmh_XPos(SP),d0/d1 ; X- und Y-Offset + lsr.w #3,d0 ; X: aus Pixel mach Bytes + mulu.w bm_BytesPerRow(a4),d1 ; Y mal Bildbreite + add.l d0,d1 ; D1 : Total-Offset + + lea bm_Planes(a4),a0 ; Source + lea stk_Planes(SP),a1 ; Destination + moveq.l #MAXPLANES-1,d2 ; Alle PlanePtrs (naja...) +.CopyPlanes: move.l (a0)+,d0 ; PlanePtr + add.l d1,d0 ; Offset dazu + move.l d0,(a1)+ ; speichern + dbf d2,.CopyPlanes + + *** Tada! BODY-Daten schreiben + + movem.w bmh_Width(SP),d3/d4 ; Breite & Höhe + lsr.w #3,d3 ; D3 : Bytes per row to write + moveq.l #0,d5 + move.b bm_Depth(a4),d5 + subq.w #1,d5 ; D5 : Depth-1 (für dbf) + move.w bm_BytesPerRow(a4),d6 ; D6 : BytesPerRow der BitMap + moveq.l #0,d7 ; D7 : Buffer-Füllstand + bra.b .RowDBF + +.RowLoop: lea stk_Planes(SP),a4 ; A4 : Plane-Array + move.l d5,d2 ; Depth-1 + +.PlaneLoop: cmpi.w #BUFFERFULL,d7 ; Zeit den Puffer zu leeren ? + blo.b .NoDump ; noch nicht ---> + movea.l a2,a0 ; IFF-Handle + movea.l a3,a1 ; Buffer + move.l d7,d0 ; Len + ;; movea.l a5,a6 ; IFFBase + JSRLIB IFFL_WriteChunkBytes + tst.l d0 + beq.b .WriteError + moveq.l #0,d7 ; Buffer ist wieder leer +.NoDump: + movea.l (a4),a0 ; Source: Nächste Linie/Plane + lea 0(a3,d7.l),a1 ; Destination: Buffer + move.l d3,d0 ; Len + moveq.l #0,d1 + move.b bmh_Compression(SP),d1 + ;; movea.l a5,a6 ; IFFBase + JSRLIB IFFL_CompressBlock + tst.l d0 + beq.b .WriteError + add.l d0,d7 ; Buffersize += komprimierte Länge + add.l d6,(a4)+ ; auf nächste Linie + + dbf d2,.PlaneLoop ; ---> Loop +.RowDBF: dbf d4,.RowLoop ; ---> Loop + + *** Buffer ein letztes Mal leeren + + movea.l a2,a0 ; IFF-Handle + movea.l a3,a1 ; Buffer + move.l d7,d0 ; Len + ;; movea.l a5,a6 ; IFFBase + JSRLIB IFFL_WriteChunkBytes + tst.l d0 + beq.b .WriteError + + *** BODY-Chunk abschliessen + + movea.l a2,a0 ; IFF-Handle + ;; movea.l a5,a6 ; IFFBase + JSRLIB IFFL_PopChunk + tst.l d0 + beq.b .WriteError + + moveq.l #0,d4 ; D4 : Error-Code: OK!! + + *** IFF-File schliessen + +.WriteError: movea.l a2,a1 ; IFF-Handle + ;; movea.l a5,a6 ; IFFBase + JSRLIB IFFL_CloseIFF + + *** Buffer freigeben + +.OpenError: move.l #BUFFERSIZE,d0 + movea.l a3,a1 + movea.l iffb_SysBase(a5),a6 + JSRLIB FreeMem + + *** Fehlerkode setzen falls nötig + +.NoMemory: move.l d4,d0 ; Error ? + beq.b .Okay ; noe ---> bsr SetError ; Error setzen, D0 := 0 + bra.b .End +.Okay: bsr ClearError -SaveClip_End: adda.w #sb_datasize,SP ; Speicher wirder freigeben - movem.l (SP)+,d2-d7/a2-a6 - rts - + *** Routine beenden -*************************************************************************** -************** V A N I L L A S A V E ************************************ -*************************************************************************** - -vs_planes: equ 0 ; ARRAY[0..MAXPLANES-1] OF PlanePtr -vs_chunksize: equ vs_planes+4*MAXPLANES -vs_linksize: equ vs_chunksize+4 - -VanillaSave: movem.l d2-d6/a2-a4,-(SP) ; 8 Register retten - lea 8*4+4(SP),a4 ; A4 : Global data Ptr - suba.w #vs_linksize,SP ; lokalen Datenraum schaffen - - *** Chunk-Grösse berechnen und merken - - move.w width(a4),d0 ; Breite in Bytes - moveq #0,d1 - move.b bm_Depth(a3),d1 - mulu d1,d0 ; mal Anzahl Planes - move.w height(a4),d1 - mulu d1,d0 ; mal Anzahl Linien - move.l d0,vs_chunksize(SP) ; merken - - *** PlanePtrs kopieren & X,Y-Offsets dazuaddieren - - move.w yoffset(a4),d1 ; Y-Offset im Bild - mulu bm_BytesPerRow(a3),d1 ; mal Bildbreite - moveq #0,d0 - move.w xoffset(a4),d0 - add.l d0,d1 ; plus X-Offset - - lea bm_Planes(a3),a0 ; Source - move.l SP,a1 ; Destination - moveq #MAXPLANES-1,d0 ; Alle PlanePtrs -1$: move.l (a0)+,d2 ; PlanePtr - add.l d1,d2 ; Offset dazu - move.l d2,(a1)+ ; speichern - dbf d0,1$ - - moveq #0,d3 - moveq #0,d4 - moveq #0,d5 - move.w bm_BytesPerRow(a3),d5 ; D5 : BytesPerRow (linesize) - move.b bm_Depth(a3),d3 ; move.b ea,Ax geht ja nicht - move.w d3,a3 ; A3 : Depth (lieber D8 als A3) - move.w width(a4),d3 ; D3 : BytesPerRow (to write) - move.w height(a4),d4 ; D4 : Rows (to write) - - subq.w #1,d4 ; für dbf - subq.w #1,a3 ; für dbf -vs_loop1: movea.l SP,a2 ; Zeiger auf Planes - move.l a3,d6 ; d6 : Depth für dbf - -vs_loop2: move.l d7,d1 ; File - move.l (a2),d2 ; Adr : Nächste Linie/Plane - JSRLIB Write ; (len ist schon in D3) - tst.l d0 ; Fehler ? - bmi.s vs_error ; ja! - add.l d5,(a2)+ ; auf nächste Linie - dbf d6,vs_loop2 ; next plane - dbf d4,vs_loop1 ; next row - - move.l vs_chunksize(SP),d0 ; Return-Wert: Chunk-Länge -vs_error: adda.w #vs_linksize,SP ; Datenraum freigeben - movem.l (SP)+,d2-d6/a2-a4 - rts - - -*************************************************************************** -************** C R U N C H S A V E ************************************** -*************************************************************************** - -cs_planes: equ 0 ; ARRAY[0..MAXPLANES-1] OF PlanePtr -cs_buffer: equ cs_planes+4*MAXPLANES ; ARRAY[0..511] OF BYTE -cs_bodysize: equ cs_buffer+512 ; LONG bodysize -cs_linksize: equ cs_bodysize+4 - -CrunchSave: movem.l d2-d6/a2-a4,-(SP) ; 8 Register retten - lea 8*4+4(SP),a4 ; A4 : Global data Ptr - suba.w #cs_linksize,SP ; lokalen Datenraum schaffen - - clr.l cs_bodysize(SP) - - *** PlanePtrs kopieren & X,Y-Offsets dazuaddieren - - move.w yoffset(a4),d1 ; Y-Offset im Bild - mulu bm_BytesPerRow(a3),d1 ; mal Bildbreite - moveq #0,d0 - move.w xoffset(a4),d0 - add.l d0,d1 ; plus X-Offset - - lea bm_Planes(a3),a0 ; Source - movea.l SP,a1 ; Destination (unsauber!) - moveq #MAXPLANES-1,d0 ; Alle Planeptrs -1$: move.l (a0)+,d2 ; PlanePtr - add.l d1,d2 ; Offset dazu - move.l d2,(a1)+ ; speichern - dbf d0,1$ - - moveq #0,d3 - moveq #0,d4 - moveq #0,d5 - move.w bm_BytesPerRow(a3),d5 ; D5 : BytesPerRow (linesize) - move.b bm_Depth(a3),d3 ; move.b ea,Ax geht ja nicht - move.l d3,a3 ; A3 : Depth (lieber D8 als A3) - move.w width(a4),d3 ; D3 : BytesPerRow (to write) - move.w height(a4),d4 ; D4 : Rows (to write) - - subq.w #1,d4 ; für dbf - subq.l #1,a3 ; für dbf - -cs_loop1: move.l SP,a2 ; PlanePtr - move.l a3,d6 ; d6 : Depth für dbf - -cs_loop2: move.w d3,d0 ; Len für CrunchRow() - move.l (a2),a0 ; Source für CrunchRow() - lea cs_buffer(SP),a1 ; Destination für CrunchRow() - bsr.s CrunchRow - add.l d0,cs_bodysize(SP) ; für calcbodysize() - - move.l d7,d1 ; File - lea cs_buffer(SP),a1 ; Daten-Puffer - move.l a1,d2 ; Adr : cs_buffer(SP) - move.l d3,-(SP) - move.l d0,d3 ; Länge, von CrunchRow() - JSRLIB Write - move.l (SP)+,d3 - tst.l d0 ; Fehler ? - bmi.s cs_error ; ja! - - add.l d5,(a2)+ ; auf nächste Linie - dbf d6,cs_loop2 ; next plane - dbf d4,cs_loop1 ; next row - - move.l cs_bodysize(SP),d0 ; return-value -cs_error: adda.w #cs_linksize,SP ; Speicher freigeben - movem.l (SP)+,d2-d6/a2-a4 +.End: adda.w #stk_SIZEOF,SP ; Stack aufräumen + movem.l (SP)+,d2-d7/a2-a6 rts -********************************************************************* -** ** -** C R U N C H R O W - eine Zeile CmpByteRun1 crunchen ** -** ** -** Parameter : A0.L : Zeiger auf Source-Adresse in Plane ** -** A1.L : Zeiger auf Destination-Buffer ** -** D0.W : Anzahl Bytes einer Source-Linie ** -** Resultat : D0.L : Anzahl gecrunchte Bytes ** -** ** -********************************************************************* - -CrunchRow: movem.l d2-d3/a2-a3,-(SP) - lea (a0,d0.w),a2 ; A2 : Source-Endadresse der Linie - moveq #0,d3 ; Byte-Zähler - -crunchloop: bsr.s CountEq ; wieviele gleiche Bytes folgen ? - cmp.w #3,d0 ; genug gleiche Bytes zum runnen ? - blt.s countdump ; nee, lohnt sich nicht -> Dumpen - - addq.l #2,d3 ; Markierbyte & Anzahl - move.b (a0),d1 ; Wert - adda.w d0,a0 ; Source anpassen - subq.w #1,d0 ; muss .w sein und nicht .b !!!!!!! - neg.b d0 ; negieren (= "Run"-Code) - move.b d0,(a1)+ ; und eintragen - move.b d1,(a1)+ ; Wert eintragen - bra.s crunchcont ; weitermachen - -countdump: movea.l a0,a3 ; Source-Pointer retten - moveq #0,d2 ; D2 : Länge des Dump-Blocks -1$: addq.b #1,d2 - bmi.s 2$ ; höchstens 127 Bytes pro Block - addq.l #1,a0 - cmpa.l a2,a0 ; Ende der Linie erreicht ? - bge.s 3$ ; ja -> abbrechen - bsr.s CountEq - cmp.w #3,d0 ; Ende des Dump-Blocks ? - blt.s 1$ ; noch nicht - bra.s 3$ ; Ende -2$: moveq #127,d2 -3$: movea.l a3,a0 ; Source-Pointer restaurieren - - add.l d2,d3 ; zur Gesamtanzahl dazuzählen - addq.l #1,d3 ; Markierbyte nicht vergessen - subq.w #1,d2 ; aus 1..128 mach 0..127 - move.b d2,(a1)+ ; Markierbyte eintragen -4$: move.b (a0)+,(a1)+ ; Datenbytes eintragen - dbf d2,4$ - - -crunchcont: cmpa.l a2,a0 ; Ende der Linie erreicht ? - blt.s crunchloop ; noch nicht! - - move.l d3,d0 ; Return: Anzahl Destination-Bytes - movem.l (SP)+,d2-d3/a2-a3 - rts - - *** Anzahl gleicher Zeichen ab (a0) zählen und nach D0 - -CountEq: move.l a0,-(SP) - moveq #1,d0 ; D0 : Anzahl gleiche Bytes -1$: move.b (a0)+,d1 ; erstes Byte -2$: cmp.b (a0)+,d1 ; Byte gleich wie letztes Byte ? - bne.s 3$ ; nein -> abbrechen - cmp.w #128,d0 - bge.s 3$ ; höchstens 128 gleiche - addq.w #1,d0 ; Anzahl erhöhen - cmpa.l a2,a0 ; Ende der Linie erreicht ? - blt.s 2$ ; noch nicht -> weiterzählen -3$: move.l (SP)+,a0 - rts +***************************************************************************** +** Chunk in File schreiben: +** A1=Adresse, A2=Handle, D0=TYPE, D1=ID, D2=Size, A6=IFFBase +** Zerstört D0/D1/A0/A1. +** Resultat: D0>0 und Z=0 falls OK, D0=0 und Z=1 falls Error + +WriteChunk: move.l a1,-(SP) ; Adresse retten + movea.l a2,a0 ; IFF-Handle + JSRLIB IFFL_PushChunk + movea.l (SP)+,a1 + tst.l d0 + beq.b .Error + + movea.l a2,a0 ; IFF-Handle + move.l d2,d0 ; Grösse + JSRLIB IFFL_WriteChunkBytes + tst.l d0 + beq.b .Error + + movea.l a2,a0 ; IFF-Handle + JSRLIB IFFL_PopChunk + tst.l d0 + ;; beq.b .Error + +.Error: rts END -- cgit v1.2.3