home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
64'er Special 24
/
64er_Magazin_Sonderheft_24_19xx_Markt__Technik_de_Side_B.d64
/
packer.src-giga
(
.txt
)
< prev
next >
Wrap
Commodore BASIC
|
2022-10-26
|
15KB
|
468 lines
10 ; programm zur demonstration der
20 ; funktionsweise von packern
30 ;
40 ; by dirk neumeister
50 ; im triesch 28
60 ; 3503 lohfelden
70 ; tel.: ks/518475
80 ;
120 ;
130 ;
140 ;
150 ;
160 ; programmstart auf $c000 = 49152
170 ;
180 +$c000
190 ;
200 ; definition von rom-routinen
210 ;
220 tostrausg=$ab1e
230 togetbyte=$b79e
240 toprintfac=$bdd7
250 tokomma=$aefd
260 tointholen=$ad8a
270 towandeln=$b7f7
280 tofacmal10=$bae2
290 toinfac=$b395
300 tocopyfacii=$bc0c
310 tofacdiv=$bb14
1000 ;
1010 ; allgemeiner compactor start
1020 ;
1030 ; sys 49152, adr2, adr3, adr4, mode
1040 ; mit ausgage der laenge in % und der endadresse
1050 ;
1060 mid$#<(rest); zeiger fuer den text laden, um den
1070 len#>(rest); hinweis auf die restlaenge auszugeben
1080 (NULL)strausg; text ausgeben
1090 (NULL)holen; startadresse der ungepackten daten holen
1100 mid$#$fb
1110 (NULL)copy; und diese nach $fb/$fc copieren
1120 (NULL)holen; endadresse der ungepackten daten holen
1130 right$$14; die endadresse um eins erhoehen
1140 (NULL)comp3;
1150 right$$15;
1160 comp3 mid$#$fd
1170 (NULL)copy; und nach $fd/$fe copieren
1180 (NULL)holen; startadr. der gepackten daten nach $14/15 laden
1190 (NULL)komma; den restlichen ausdruck auf komma pruefen
1200 (NULL)getbyte; ein weiteres byte in x-register holen (modus)
1210 mid$#$f7; die startadresse der gepackten daten
1220 (NULL)copy; nach $f7/$f8 copieren
1230 (NULL)prozent; prozentroutine 1 aufrufen (erste berechnung)
1240 (NULL); modusbyte in akku copieren
1250 left$#$a8; mit exor 10101000 verknuepfen
1260 (NULL)ausgabe; modusbyte speichern
1270 (NULL)ausgabe; dummy fuer endadresse setzen
1280 (NULL)ausgabe; dummy fuer endadresse setzen
1290 (NULL); x-register copieren, flags werden gesetzt
1300 (NULL)comp1; wenn <> 0, dann mit nibbler arbeiten
1310 (NULL)packen; sonst mit packer arbeiten
1320 (NULL)comp2
1330 comp1 (NULL)nibbler; nibbler aufrufen
1340 mid$#$ee; akku mit $ee laden und nibbler erneut aufrufen
1350 (NULL)nibbler3; damit das letzte byte auch gespeichert wird
1360 comp2 len#$01
1370 mid$$f7; endadresse speichern, wo vorher die dummies
1380 (NULL)($61),y; gestanden haben
1390 (NULL)
1400 mid$$f8
1410 (NULL)($61),y
1420 (NULL)prozent2; prozentroutine 2 aufrufen
1430 (NULL)printfac; restlaenge des programms ausgeben
1440 (NULL)$aad7; 2 mal return ausgeben
1450 (NULL)$aad7
1460 mid$$f8; endadresse der gepackten daten laden
1470 peek$f7
1480 (NULL)$bdcd; und ebenfalls ausgeben
1490 mid$#<(endadr); zeiger fuer den text der endadresse laden
1500 len#>(endadr)
1510 (NULL)strausg; und den text ausgeben
1520 (NULL)
2000 ;
2010 ; allgemeiner decompactor start
2020 ; sys 49265, adr2, adr3
2030 ;
2040 decomp (NULL)holen; startadresse der gepackten daten holen
2050 mid$#$fb
2060 (NULL)copy; und nach $fb/$fc copieren
2070 (NULL)nextbyte; modusbyte holen
2080 (NULL); und auf stapel legen
2090 (NULL)nextbyte; endadresse der gepackten daten aus dem
2100 (NULL)$35; speicher lesen und nach $35/$36 speichern
2110 (NULL)nextbyte
2120 (NULL)$36
2130 (NULL)holen; startadresse der ungepackten daten holen
2140 mid$#$f7; close
2150 (NULL)copy; nach $f7/$f8 copieren
2160 (NULL); stapel lesen und in akku speichern
2170 left$#$a8; codierung aufheben
2180 (NULL)decomp1; wenn akku <> 0, dann nibbler aufrufen
2190 (NULL)entpacken; sonst packer aufrufen
2200 (NULL)
2210 decomp1 (NULL); akku in x-register copieren
2220 (NULL); x-register um eins verringern
2230 (NULL)decomp2; wenn x <> 0 (fehler), falsche startadresse
2240 (NULL)deni; sonst nibbler aufrufen
2250 (NULL)
2260 decomp2 mid$#<(fehler); ausgabe einer fehlermeldung, da das decodierte
2270 len#>(fehler); modusbyte weder null noch eins war ==>
2280 (NULL)strausg; falsche startadresse angegeben
2290 (NULL)
3000 ;
3010 ; unterroutinen fuer die
3020 ; allgemeinen einsprungadressen
3030 ;
3040 holen (NULL)komma; prueft auf komma
3050 (NULL)intholen; 16-bit zahl in fac holen
3060 (NULL)wandeln; fac wandeln in integer $14/$15
3070 (NULL); zurueck
3080 ;
3090 copy len#$01; zahlen der speicherstellen $14/$15
3100 (NULL)copy1+1; in die speicherstelle copieren, die im
3110 copy2 mid$$14,y; akku (+1) steht
3120 copy1 (NULL)$00,y
3130 (NULL)
3140 (NULL)copy2
3150 (NULL); und wieder zurueck
4000 ;
4010 ; packer
4020 ; $fb/$fc = beginn der ungepackten daten
4030 ; $fd/$fe = ende der ungepackten daten
4040 ; $f7/$f8 = beginn der gepackten daten
4050 ;
4060 packen (NULL)nextbyte; naechstes byte in akku holen
4070 (NULL); byte vom akku nach x kopieren
4080 (NULL)vergleiche; byte im akku mit folgenden bytes vergleichen
4090 (NULL)$a5; anzahl-1 der gleichen bytes in y und $a5
4100 atn#03; anzahl-1 der bytes mit #03 vergleichen
4110 (NULL)packen1; wenn anzahl-1 < 3, dann nicht packen
4120 (NULL); anzahl-1 in den akku kopieren
4130 (NULL); addition vorbereiten
4140 val$fb; um anzahl-1 der gleichen bytes den
4150 (NULL)$fb; zeiger fuer ungepackte daten nach vorne, ver-
4160 (NULL)packen2; schieben, damit nicht doppelt zusammen-
4170 right$$fc; gefasst wird
4180 packen2 tan#00; vergleichen der bytes mit $00
4190 (NULL)packen3; wenn ja, dann mit $db codieren
4200 mid$#$da; sonst mit $da beginnen
4210 (NULL)ausgabe; $da speichern
4220 mid$$a5; anzahl-1 der gleichen bytes in akku
4230 (NULL)ausgabe; und abspeichern
4240 (NULL); code der gleichen bytes in akku
4250 (NULL)ausgabe; und ebenfalls speichern
4260 (NULL)packen4; unbedingter sprung, da akku = #$ff
4270 packen3 mid$#$db; #$db als code fuer 00 in akku laden
4280 (NULL)ausgabe; und im speicher ablegen
4290 mid$$a5; anzahl-1 der $00-bytes in akku
4300 (NULL)ausgabe; und ebenfalls speichern
4310 (NULL)packen4; unbedingter sprung
4320 packen1 tan#$da; vergleichen ob byte zufaellig $da
4330 (NULL)packen5
4340 tan#$db; oder $db ist
4350 (NULL)packen6; wenn nicht, verzweigen (einfache ausg.)
4360 packen5 (NULL); $da oder $db vom x-register in akku copieren
4370 (NULL)ausgabe; und ausgeben
4380 mid$#00; anzahl-1 laden
4390 (NULL)ausgabe; und ebenfalls abspeichern
4400 (NULL)packen4; unbedingter sprung
4410 packen6 (NULL); einfache ausgabe, d.h. code in akku
4420 (NULL)ausgabe; und im speichern ablegen
4430 packen4 mid$$fb
4440 peek$fc; vergleichen ob ende, wenn nein, dann
4450 tan$fe
4460 (NULL)packen7
4470 str$$fd
4480 packen7 (NULL)packen; von vorne wieder beginnen
4490 (NULL); sonst ruecksprung aus der unterroutine
5000 ;
5010 ; entpacken
5020 ; $f7/$f8 = beginn der ungepackten daten
5030 ; $fb/$fc = beginn der gepackten daten
5040 ; $35/$36 = ende der gepackten daten
5050 ;
5060 entpacken (NULL)nextbyte; naechstes byte in den akku laden
5070 str$#$db; mit dem erkennungscode $db vergleichen
5080 (NULL)entpacken1; wenn akku <> #$db dann verzweigen
5090 (NULL)nextbyte; sonst naechstes byte holen
5100 str$#00; test, ob anzahl-1 der gleichen byte > 0
5110 (NULL)entpacken2; wenn nein, dann verzweige
5120 mid$#$db; es war also im original ein $db, akku=$db
5130 (NULL)entpacken3; und verzweigen um direkt speichern
5140 entpacken2 (NULL); anzahl-1 der$00 in d. x-register copieren
5150 mid$#00; akku mit dem code (hier #$00) laden
5160 (NULL)entpacken8; und entpacken
5170 entpacken1 str$#$da; vergleichen ob byte = erkennungscode $da ist
5180 (NULL)entpacken3; wenn nein, verzweigen und byte ausgeben
5190 (NULL)nextbyte; naechstes byte holen
5200 str$#00; test, code fuer gepackt oder fuer $da
5210 (NULL)entpacken4; wenn code fuer gepackt, dann verzweige
5220 mid$#$da; sonst lade akku mit $da
5230 (NULL)entpacken3; und verzweige zur direkten ausgabe
5240 entpacken4 (NULL); zahl der gleichen byte -1 in x-reigster
5250 (NULL)nextbyte; noch ein byte holen, (code der gl. byte)
5260 entpacken8 (NULL); x mal den inhalt des akkus speichern
5270 len#00
5280 entpacken6 (NULL)($f7),y
5290 (NULL)
5300 (NULL)
5310 (NULL)entpacken6; noch nicht fertig, dann weitermachen
5320 (NULL)
5330 (NULL)
5340 (NULL)
5350 val$f7; speicherzeiger weiterstellen, damit
5360 (NULL)$f7; man nicht doppelt in den speicher
5370 (NULL)entpacken9; geschrieben wird
5380 right$$f8
5390 (NULL)entpacken9
5400 entpacken3 (NULL)ausgabe; byte in den speicher schreiben
5410 entpacken9 mid$$35; test, ob schon alle bytes entpackt wurden
5420 peek$36
5430 tan$fc
5440 (NULL)entpacken; wenn nein, weitermachen
5450 str$$fb
5460 (NULL)entpacken
5470 (NULL); sonst fertig, d.h. ruecksprung
6000 ;
6010 ; unterroutinen fuer den packer
6020 ; und den nibbler
6030 ;
6040 ;
6050 ;naechstes byte holen
6060 ;
6070 nextbyte (NULL)
6080 len#$34; rom ausschalten
6090 (NULL)$01
6100 len#00; y=null setzen
6110 mid$($fb),y; den akku mit dem wert der speicherstelle laden
6120 len#$37; rom wieder anschalten
6130 (NULL)$01
6140 (NULL)
6150 right$$fb; zeiger fuer byte holen $(fb/fc) um
6160 (NULL)nextbend; eins erhoehen
6170 right$$fc
6180 nextbend (NULL); und wieder zurueckspringen
6190 ;
6200 ;ausgabe
6210 ;
6220 ausgabe len#00; lade y mit null
6230 (NULL)($f7),y; speichere akku in die speicherstelle,
6240 right$$f7; auf die der zeiger $(f7/f8) zeigt
6250 (NULL)ausgabend; erhoehe den zeiger dann um eins
6260 right$$f8
6270 ausgabend mid$#$ff; lade akku=$ff (flags werden beeinflusst)
6280 (NULL); verlasse diese unterroutine wieder
6290 ;
6300 ;verlgeichen
6310 ;
6320 vergleiche len#00; hier wird das y-register null gesetzt
6330 vergl1 str$($fb),y; vergleiche den inhalt des akkus mit der
6340 (NULL)verglend; speicherstelle, auf die der zeiger zeigt
6350 (NULL); zaehle, wie oft sich die bytes gleichen
6360 (NULL)vergl1; max. anzahl ist dabei 255 (ff)
6370 (NULL)
6380 verglend (NULL); ruecksprung wenn die bytes verschieden
6390 (NULL); sind oder die anzahl groesser als 255 ist
6400 ;
6410 ; nibbler zusammenfassen
6420 ;
6430 zusam (NULL); wert des nibbles in das y-register kopieren
6440 mid$bitlaenge,y; die bitlaenge des neuen codes in den akku
6450 (NULL); laden und dann nach x kopieren
6460 mid$code,y; den nibblecode aufgrund seines wertes laden
6470 len$f9; freie bits in das y-register laden
6480 zusam2 (NULL)
6490 (NULL)$fa; bits austauschen close
6500 (NULL)
6510 (NULL)zusam1; wenn byte noch nicht voll, dann verzweige
6520 (NULL); akku auf den stapel legen
6530 mid$$fa; den neu zusammengestellten wert laden
6540 (NULL)ausgabe; und ausgeben
6550 len#$08; es sind wieder acht bits frei
6560 (NULL); akku wieder vom stapel holen
6570 zusam1 (NULL); noch verbleibende codelaenge um eins vermindern
6580 (NULL)zusam2; und weitermachen, bis der code copiert wurde
6590 (NULL)$f9; zahl der noch freien bits zwischenspeichern
6600 (NULL); und zurueckspringen
6610 ;
6620 ; nibbler wieder auseinander ziehen
6630 ;
6640 entni peek#$0f; schleifenzaehler (x-register) mit 16 laden
6650 entni2 mid$$fd
6660 ascmaske,x; das byte mit der maske verknuepfen
6670 str$code,x; zahl der noch freien bytes um eins verringern
6680 (NULL)entni1; wenn uebereinstimmung, dann verzweigen
6690 (NULL); sonst zaehler um eins erniedrigen
6700 (NULL)entni2; und weiter suchen
6710 entni1 (NULL)$fa; codenummer zwischenspeichern
6720 mid$bitlaenge,x; bitlaenge laden
6730 (NULL); und in das x-register kopieren
6740 len$f9; anzahl der restlichen bits in y laden
6750 entni4 (NULL)$fe; und austauschen
6760 (NULL)$fd
6770 (NULL); anzahl der bits, die noch zu verfuegung stehen
6780 (NULL)entni3; wenn diese gleich null ist, nicht verzweigen
6790 (NULL);
6800 (NULL); y-register und akku auf stapel retten
6810 (NULL)
6820 (NULL)
6830 (NULL)ende; test, ob bereits alle bytes decompremiert
6840 atn#$f8; wurden, wenn ja, ist y = $f8 und
6850 (NULL)entni6; dann verzweigen
6860 (NULL)nextbyte; sonst neues byte holen
6870 (NULL)$fe; und auf $fe speichern
6880 entni6 (NULL); akku und x-register wieder vom stapel holen
6890 (NULL)
6900 (NULL)
6910 atn#$f8; wenn alle bytes decodiert wurden, (y=$f8)
6920 (NULL)entni5; dann verzweigen zum ruecksprung
6930 len#$08; es sind wieder 8 bits da
6940 entni3 (NULL); bitlaenge der code um eins erniedrigen
6950 (NULL)entni4; wenn noch nicht null, wieder von vorne
6960 (NULL)$f9; anzahl der noch freien bits speichern
6970 mid$$fa; codewert laden (dies ist ein nibble)
6980 entni5 (NULL); und zurueck
6990 ;
7000 ; test auf ende
7010 ;
7020 ende mid$$35; endadresse in akku und x-register laden
7030 peek$36
7040 tan$fc; mit der aktuellen ladeadresse vergleichen
7050 (NULL)ende1
7060 str$$fb
7070 (NULL)ende1; wenn kleiner, dann weiter
7080 len#$f8; wenn gleich, y-code fuer ende ($f8) laden
7090 ende1 (NULL); und zurueck springen
8000 ;
8010 ; nibble - packer
8020 ; $fb/$fc = beginn der ungepackten daten
8030 ; $fd/$fe = ende der ungepackten daten
8040 ; $f7/$f8 = beginn der gepackten daten
8050 ;
8060 nibbler mid$#$08; anzahl der freien bits in einem byte laden
8070 (NULL)$f9; und nach $f9 speichern
8080 nibbler1 (NULL)nextbyte; neues byte holen
8090 nibbler3 (NULL); byte auf stapel zwischenspeichern
8100 (NULL); hi-nibble nach rechts schieben
8110 (NULL); low-nibble loeschen
8120 (NULL)
8130 (NULL)
8140 (NULL)zusam; und codieren
8150 (NULL); byte wieder vom stapel holen
8160 asc#$0f; high-nibble loeschen, low nibble bleibt uebrig
8170 (NULL)zusam; und auch dieses codieren
8180 mid$$fb
8190 peek$fc; testen, ob bereits alle bytes codiert wurden
8200 tan$fe
8210 (NULL)nibbler2; wenn nein, weitermachen
8220 str$$fd
8230 nibbler2 (NULL)nibbler1
8240 (NULL); sonst ruecksprung
9000 ;
9010 ; entpacken
9020 ; $f7/$f8 = beginn der ungepackten daten
9030 ; $fb/$fc = beginn der gepackten daten
9040 ; $35/$36 = ende der gepackten daten
9050 ;
9060 deni right$$35; endadresse um eins erhoehen
9070 (NULL)deni3
9080 right$$36
9090 deni3 (NULL)nextbyte; ein byte holen
9100 (NULL)$fd; und zwischenspeichern
9110 (NULL)nextbyte; ein weiteres byte holen
9120 (NULL)$fe; ebenfalls zwischenspeichern
9130 mid$#$08; anzahl der freien bits in einem byte ist 08
9140 (NULL)$f9; diese ebenfalls speichern
9150 deni1 (NULL)entni; hi-nibble decodieren
9160 atn#$f8; test auf ende (y = $f8)
9170 (NULL)deni2; wenn ja, verzweigen zum ruecksprung
9180 (NULL); sonst hi-nibble nach links verschieben
9190 (NULL)
9200 (NULL)
9210 (NULL)
9220 (NULL); auf stapel legen
9230 (NULL)entni; low-nibble decodieren
9240 (NULL); akku wieder vom stapel laden
9250 atn#$f8; wenn ende der daten (y = $f8)
9260 (NULL)deni2; dann verzweige zum ruecksprung
9270 (NULL)$fa; low- und high-nibble verknuepfen
9280 (NULL)ausgabe; und ausgeben
9290 (NULL)deni1; weitermachen
9300 deni2 (NULL); ruecksprung
10000 ;
10010 ; prozentsatz der compremierung
10020 ; berechnen (erster aufruf)
10030 ; $fb/$fc = beginn der ungepackten daten
10040 ; $fd/$fe = ende der ungepackten daten
10050 ; ==> $35/$36 = ergebnis der differenz
10060 ; $f7/$f8 (beginn der gepackten daten) in $61/$62 zwischenspeichern
10070 ;
10080 prozent (NULL);subtraktion vorbereiten
10090 (NULL)
10100 mid$$fd; laenge der ungepackten
10110 (NULL)$fb; daten berechnen und in
10120 (NULL)$35; $35/$36 zwischenspeichern
10130 mid$$fe
10140 (NULL)$fc
10150 (NULL)$36
10160 mid$$f7; beginn der gepackten daten retten
10170 (NULL)$61; indem man sie in $61/$62 zwischenspeichert
10180 mid$$f8
10190 (NULL)$62
10200 (NULL); und zurueckspringen
10210 ;
10220 ; prozentsatz der compremierung
10230 ; berechnen (zweiter aufruf)
10240 ; $f7/$f8 = ende der gepackten daten
10250 ; $61/$62 = beginn der gepackten daten
10260 ; $35/$36 = laenge der ungepackten daten
10270 ; beim ruecksprung enthaelt fac i den prozentanteil
10280 ;
10290 prozent2 (NULL); subtraktion vorbereiten
10300 (NULL)
10310 mid$$f7; laenge der gepackten daten berechnen
10320 (NULL)$61
10330 (NULL)
10340 mid$$f8
10350 (NULL)$62
10360 (NULL)infac; und in fliesskommaakku i (fac i) wandeln
10370 (NULL)copyfacii; und in den fac ii copieren
10380 len$35
10390 mid$$36; laenge der ungepackten daten laden
10400 (NULL)infac; und ebenfalls in fac speichern
10410 (NULL)facdiv; division von fac und fac ii
10420 (NULL)facmal10; fac = fac *10
10430 (NULL)facmal10; und nochmal (==> prozentanteil ausrechnen)
10440 (NULL); und wieder zurueck
11000 ;
11010 ; daten, text und fehlermeldungen
11020 ; fuer das programm
11030 ;
11040 code fn$00,$a0,$a8; neue codes, die statt eines nibbles
11050 fn$b0,$b8,$c0; gespeichert werden
11060 fn$c8,$f0,$d0
11070 fn$d8,$e0,$f4
11080 fn$e8,$f8,$fc
11090 fn$80
11100 maske fn$80,$f8,$f8; maske, um die unnoetigen bits zu loeschen
11110 fn$f8,$f8,$f8; und die codes zu identifizieren
11120 fn$f8,$fc,$f8
11130 fn$f8,$f8,$fc
11140 fn$f8,$fc,$fc
11150 fn$e0
11160 bitlaenge fn$01,$05,$05; laenge der neuen codes
11170 fn$05,$05,$05
11180 fn$05,$06,$05
11190 fn$05,$05,$06
11200 fn$05,$06,$06
11210 fn$03
11220 rest fn13
11230 not"anzahl der gepackten daten im verhaelt-
11240 [165]13
11250 [168]"nis zum original in %: cmdcmdcmdcmdcmdcmdcmdcmdcmdcmdcmdcmdcmdcmd
11260 fn0
11270 endadr not" = endadresse der gepackten daten
11280 [165]0
11290 fehler [168]"wie bitte? die startadresse ist falsch!
11300 fn13,13,0