;*******************************************;* COMPRESS - (c) 1986 by Stefan M. Aust *;* Version 2.0 vom 04.07.1986 *;* Computertyp anpassen !! *;*******************************************;ja:equ 1nein:equ 0CPC4 64:equ ja ;hier Computertyp einstellen !CPC664:equ neinCPC128:equ nein;org #A000Main:jp Compr;Komprimierungsroutinejp Expand;Expansionsroutine;;;********************************************;* COMPRESS 1.6 *;********************************************Compr:ld de,#50C8 ;Default: D=80,E=200ld hl,#C000 ;Default: HL=C000,Bildschirmstartor a ;kein Argument?jr z,comp;ja, los geht's ->call GetPar;Koordinaten holenret c;Bei Fehler zurueck zum BASIC =>all CalWin;Window-Parameter berechnencomp:call UComp;Komprimieren und abspeicherncall #BC8F;CAS/DISK OUT CLOSEret;zum BASIC=>;;--> GetPar: Fenstergrenzen holen, entweder aus Fensternummer; oder durch Direkteing abe; In: A=Parameternummer, IX Pointer darauf; Out:HL=x1,y1, DE=x2,y2GetPar:cp 1;Fensternummer ?jr nz,GetNrld a,(ix+0) ;A=FensternummerCALL #BBB4;TXT STR SELECTld c,a ;alte Nr rettencall #BB69;TXT GET WINDOW ld a,c ;urspruengliches Fensterpush hlcall #BBB4 ;wiederherstellenpop hlor a;Kennung alles OkretGetNr:cp 4;4 Argumente ?scf;Wenn Fehler,ret nz;dann mit Carry=1 zurueck =>ld h,(ix+6) ;HL=Ecke links/obenld l,(ix+2)ld d ,(ix+4) ;DE=Ecke rechts/untenld e,(ix+0)dec h;Korrektur -1,dec l;da Firmware mitdec d;Koordinaten vondec e;0..79 arbeitetor a;Kennung alles Okret;;--> CalWin: Mode-anhaengige Fenstergroesse in unabhaendige; umrechnen. Diese Routine laeuft nur beim CPC464!; In: HL,DE=Ecke links/oben,rechts/unten; Out:HL=Bildschirmadresse,; D=Bytes/Zeile, E=RastenzeilenzahlCalWin:rst 8;Aufruf einer ROM-Routineif CPC464defw #0B95+#8000endif CPC664 defw #0B97+#8000endif CPC128defw #0B9B+#8000end;;--> UComp: Die Komprimierungsroutine, der ausgewaehlte Bereich; wird auf Datentraeger gespeichert.; In: HL=Startadresse, D=Bytes/Zeile, E=Zeilenzahl; Out:Programm auf Date ntraegerUComp:call Init;Zeilenanf und -ende merkenld a,l;Bildadr als Erstes schreibencall WriteA ;(Im INTEL-FORMAT,ld a,h; d.h. Low-Bytecall WriteA; vor High-Byte)ld a,d ;Bytes/Zeilecall WriteA ;schreibenld a,e ;Rasterzeilenzah lcall WriteA;ebenfalls schreibenld a,#FF ;Ende-Flag loeschenld (EFlag),aMLoop:ld b,0 ;Zaehler = 0Loop:ld a,(hl) ;Byte aus Bildschirm fuer Vergleichcall IncHL;HL zeigt auf naechstes Bytejr c,Nxt ; Bereichende ->cp (hl) ;Besteht Gleichheit bei 3 Bytes ?jr nz,Nxt1 ;nein ->call IncHL;HL zeigt auf naechstes Bytejr c,Nxt1 ; Bereichende ->cp (hl) ;Gleichheit ?jr nz,Nxt2 ;nein ->call DecHL;zweimal zurueckcall DecHLcall Store ;Daten schreibencall Press ;Daten komprimierenjr TstEnd ;Ist Bereichsende aufgetreten?Nxt2:call DecHL;zweimal zurueckNxt1:call DecHL ;einmal zurueckNxt:inc b ;Zaehler + 1call IncHL;naechste Adressejr c,NxtSto ; Ende, dann speichernld a,b;A=Za ehlercp 127;kleiner 127?jr c,Loop;ja->NxtSto:call StoreTstEnd:ld a,(EFlag);Ist Bereichsendeor a;aufgetreten ?jr nz,MLoop ;nein ->call WriteA ;als Ende Null schreibenret;und es ist geschafft =>;;--> Store: UP zum Schreiben von ma x. 127 Bytes normaler Daten; In: B=Zahl der Bytes, (StAdr)=Anfangsadr; Out:wenn B=0, Ende, sonst B Bytes schreibenStore:ld a,b ;A=Zaehler or a;gleich 0? ret z;ja, Ende => ld c,b;Zaehler retten stloop:call DecHL;Bildadr auf Datenanfang djnz stloop ld b,c;Zaehler restaurieren call WriteA;Zaehler schreiben Store1:ld a,(hl) ;B Bytes call WriteA ;schreiben call IncHL djnz Store1 ret ; ;--> Press: UP verkuerzt max 127 gleiche Bytes auf genau 2 Byte ; In: (StAdr)=Bildadr ; Out:HL=naechste Bildadr, Bytes schreiben Press:ld b,0 ;Zaehler neu setzen ld c,(hl) ;C = Zei chen Press1:inc b;Zaehler + 1 call IncHL ;naechste Bildadr jr c,Press2 ; Bereichende -> ld a,(hl) ;Byte gleich ? cp c jr nz,Press2 ;nein -> ld a,b ;A = Zaehlerp 12 7 ;kleiner 127 ?jr c,Press1;ja, weiter ->Press2:ld a,b ;Zaehleror #80 ; Kennung fuer Komprimierungcall WriteA ;schreibenld a,c ;und Datenbytecall WriteA ;schreibenret;;;********************************************;* EXPAND 1.1 *;********************************************Expand:ld c,a ;Parameteranzahl rettenxor a;Fehlerflag loeschenld (FFlag),acall ReadA ;Bildadrld l,a;nach HLcall ReadA ;einlesenld h,ald a,(FFlag); ist ein Fehleror a;aufgetreten ?ret nz ;ja, BASIC =>ld a,c;Parameteranzahlor a;kein Argument ?jr z,expcall GetArg ;Neue Eckkoordinate holenret c;Fehler =>call #BC1A;Koordinaten in Bildadr wandelnexp:call UExp;eigentliche Expan droutine aufrufencall #BC7A;CAS/DISK IN CLOSEret;zum BASIC =>;;--> GetArg: Koordinaten holen; In: A=Parameteranzahl, IX=Pointer auf Parameter; Out:HL=BildschirmkoordinatenGetArg:cp 1;1 Argument ?jr nz,direkt;nein ->ld a,(i x+0);a=Fensternrcall #BBB4;TXT STR SELECTld c,a;alte Fensternummer rettencall #BB69;TXT GET WINDOWld a,c ;altes Fenster anwaehlenpush hlcall #BBB4;TXT STR SELECTpop hlor a ;Kennung alles Okretdirekt:cp 2;2 Argumente ?scf ;Ar gumentfehler = Carry gesetztret nz ;zurueck bei Fehler =>ld h,(ix+2);HL=Ecke links/obenld l,(ix+0)dec h;Korrektur -1dec lor a;Kennung alles Okret;;--> UExp: Die Expansionsroutine. Das aktuelle File wird; von dem Datentraeger g elesen und auf den Bildschirm; geschrieben.; In: File auf Datentraeger, HL=Bildadr; Out:Bild auf SchirmUExp:call ReadA;D=Bytes/Zeileld d,acall ReadA;E=Rasterzeilenanzahlld e,acall Init;Bildanf und -ende speichernELoo p:call ReadA;B=Anzahlbyteor a;Ende der Datei (Null gefunden?)ret z;ja, fertig =>ld b,a;Anzahl merkenld a,(FFlag) ;Ist ein Fehler aufgetreten ?or aret nz ;ja, Abbrechen =>bit 7,b;7. Bit gesetzt ?s 7,b;auf jeden fall loes chen nz,EExp ;Expand-Modus ->orm:call ReadA ;Byte auf (hl),a;Bildschirm schreibenll IncHL;und Bildadr erhoehennz ENorm;B Bytes uebertragen ELoopxp:call ReadA;Byte lesen1:ld (hl),a;und B malll IncHL;auf Bildschirmnz ee1;schreiben ELoop****************************************** UNTERPROGRAMME *******************************************-> Init: UP:Initialisiert die Variablen fuer IncHL und DecHL In: HL=Bildadr, D=Bytes/Zeile Out:(StHL)=Adr 1.Byte, (LastHL)=Adr letztes Byteit:push hl;Register retten a,d;Bytes/Zeile fuer IncHL/DecHL merken (StD),ald (StHL),hl;Bereich Zeilenanfang merken (fuer IncHL)ld b,d;B=Bytes/Zeiledec b;-1inloop:call #BC20;SCR N EXT BYTEdjnz inloop ;Adresse des letzten Bytes der Zeileld (LastHL),hl ;berechnen und merken (fuer DecHL)pop hlret;;--> IncHL: UP:Zeiger HL wird auf naechstes Byte des; Bereichs gesetzt. Bei Bereichsende wird ein; Flag geset zt.; In: HL=Bildadr, D=Bytes/Zeile, E=Zeilenzahl; Out:wenn Ende, Carry=1, EFlag=1,; sonst Carry=0, HL=naechste BildadrIncHL:push af ;Byte rettendec d;Bytes/Zeile - 1jr z,Dist0 ;Ende der Zeile erreicht ->call #BC20 ;SCR NEXT BYTEjr Inc1;Ende mit Cy=0Dist0:dec e ;Rasterzeilenzahl - 1jr z,Eist0 ;Ende des Bereichs erreicht ->ld a,(StD);D=Bytes/Zeileld d,ald hl,(LastHL);Ende der alten Zeileall #BC26;SCR NEXT LINEld (LastHL),hl;fuer naechste Zeile merkenld hl,(StHL) ;Anfang der alten Zeilecall #BC26 ;SCR NEXT LINEld (StHL),hl ;fuer naechste Zeile merkenInc1:pop afor a ;Carry=0, HL=naechste BildadrretEist0:xor a ;EFlag setzenld (EFlag), apop afscf ;Carry=1, HL unveraendertret;;--> DecHL: UP:Zeiger HL wird auf vorheriges Byte des; Bereichs gesetzt.; In: HL=Bildadr, D=Bytes/Zeile, E=Zeilenzahl; Out:HL=vorherige BildadrDecHL:push af;Byte rettenld a,(S tD);Maximum erreicht ?cp djr z,DistD;ja, Zeilensprung ->inc d;Bytes/Zeile + 1call #BC23;SCR PREV BYTEjr Dec1;Fertig ->DistD:inc e;Rasterzeilenzahl + 1ld d,1;Byte/Zeile=1ld hl,(StHL) ;Anfang der alten Zeilecall #BC29;SCR PREV L INEld (StHL),hl;fuer naechste Zeile merkenld hl,(LastHL) ;Ende der alten Zeilecall #BC29;SCR PREV LINEld (LastHL),hl;fuer naechste Zeile merkenDec1:pop afret;;--> WriteA: UP zum Schreiben des Akkumulators auf Datentraeger; Im Fehlerfall wird das EFlag gesetzt und so ein; Abbruch des Programms erzwungen.; In: A=Datenbyte; Out:Byte auf Datentraeger, (EFlag)=StatusWriteA:call #BC95 ;CAS/DISK OUT CHAR (Akku schreiben)ret c;alles Okxor a ;EFlag setzen,ld (EFlag),a;da Fehler aufgetretenret;;--> ReadA: UP zum Lesen des Akkumulator von Datentraeger.; Im Fehlerfall wird das FFlag gesetzt und so ein; Abbruch des Programms erzwungen.; In: Datentraeger; Out:A=Datenbyte, (FFlag)=StatusReadA:call #BC80;CAS/DISK OUT CHAR (Akku lesen)ret c;alles Okcp #1A;Dateiende von Disk gemeldet und nicht wahr?scfret z;Ignorieren, alles Okld a,#FF;FFlag setzen,ld (FFlag),a;da Fehler aufgetretenret;;-- > Datenbereich: Es werden 7 Bytes Daten benoetigtStHL:defw 0 ;Speicher Bildadr Zeilenanf fuer IncHLLastHL:defw 0;Speicher Bildadr Zeilenende fuer DecHLStD:defb 0 ;Speicher Bytes/Zeile fuer IncHLEFlag:defb 0;Flag zum Anzeigen des BereichsendeFFlag:defb 0;Flag zum Anzeigen von Lesefehlern;;geschafft! |