;*******************************************;*  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!