Save'n'Pack
von Christian Dombacher
----------------------------------------
Die Effekte werden immer besser, noch mehr Sprites und Farben schillern auf dem Bildschirm. Die Kehrseite der Me- daille ist der Speicheraufwand. Bisher wurde dieses Problem dadurch gelöst (oder umgangen), daß man die Note im Speicher gepackt und dann auf Disk abge- speichert hat. Da der Speicherinhalt dadurch unverwendbar geworden ist, kann danach nur noch ein Reset durchgeführt werden. Die Idee, die hinter dem >>Sa- ve'n'Pack-System<< steht, ist eigentlich ganz einfach. Mit Hilfe eines Equal- Char-Packers und einer leicht geänderten Save-Routine kann man vom Speicher di- rekt auf Disk packen. Zuerst wird mit dem Scanner ein Codebyte gesucht, das im zu packenden Speicherbereich möglichst selten vorkommt. Bevor die eigentliche Arbeit beginnt, wird der Entpacker über den Bus ausgegeben. Befinden sich nun mehr als drei gleiche Bytes im Speicher, so wird eine spezielle Bytekombination abgespeichert, die angibt, wie oft wel- ches Byte beim Entpacken dupliziert wer- den muß. Anderenfalls wird das Origi- nalbyte ausgegeben. Verwendet wird die Routine folgenderma- ßen: Zunächst müssen die Filenamenpara- meter (über $FFBD) gesetzt werden. Dann wird die Endadresse des zu packenden Speicherbereichs in >>END<< abgespei- chert, danach wird die Anfangsadresse ins X- und Y-Register geladen und die Routine aufgerufen. Es sind also nicht mehr Parameter als bei der normalen Sa- ve-Routine nötig. Dies ermöglicht ein leichtes Einbauen in vorhandene Program- me. Der Inhalt des Prozessorstatusregi- sters und der Programmeinsprung im De- packerteil müssen beim Abtippen festge- legt werden (Im Kommentar steht >>Enter Value !<<). Die Decrunchroutine liegt in der Zeropage, ihr könnt also Speicherbe- reiche von $0100-$FFFF mit dem Save'n'- Pack-System in Angriff nehmen.
;--------------------------
;- Save'n'Pack by the sir -
;- Assembler: Startool -
;--------------------------
BUF = $CE00 ;define labels
INITI5 = $FFBD
I1 = $AC
I2 = $AE
I5 = $BB
BY = $02
WORK = $03
END = $F8
;--- Cruncher & Scanner ---
CRUNCH STX ANFL+1
STY ANFH+1
LDA #$08 ;Drive
STA $BA
LDA #$61
STA $B9
JSR $F3D5 ;Open
LDA $BA
JSR $ED0C ;Send Driveaddr
LDA $B9
JSR $EDB9 ;Send Sekaddr
LDA #$01 ;Startaddress
JSR $EDDD ;Low
LDA #$08
JSR $EDDD ;High
JSR SSCAN ;Scan Memory
LDY #$00
CR5 LDA DEPACK,Y ;Depacker Out
JSR $EDDD
INY
CPY #<PACK-DEPACK
BNE CR5
JSR CR0 ;Packen
JSR STOSEQ ;Last Sequence
JMP $F63F ;Close
CR0 LDX ANFL+1
LDY ANFH+1
STX I2
STY I2+1
LDX #$01 ;X=Lencounter
JSR GETBYT ;Get First Byte
STA BY
CR2 JSR GETBYT ;Equal ?
CMP BY
BNE CR1
INX ;Count + 1
BNE CR2 ;Count < 255
DEX ;Overflow
CR1 PHA
JSR STOSEQ ;Store Sequence
LDX #$01 ;Len = 1
PLA
CMP BY ;Overflow ?
BEQ CR2
STA BY ;New Value
JSR CHKEND ;End ?
BCC CR2
RTS
STOSEQ LDA BY
CMP DC0 ;Byte=Code
BEQ CR3 ;-> Store Seq
CPX #$04 ;Len > 3 ?
BCS CR3 ;-> Store Seq
CR4 JSR $EDDD ;Byte Out
DEX ;Len times
BNE CR4
RTS
CR3 LDA DC0 ;Codebyte Out
JSR $EDDD
TXA ;Len Out
JSR $EDDD
LDA BY ;Byte Out
JMP $EDDD
SSCAN LDX ANFL+1
LDY ANFH+1
STX I2
STY I2+1
LDY #$00 ;Clear Buffer
TYA
SC6 STA BUF,Y
STA BUF+$0100,Y
INY
BNE SC6
JSR SC0 ;Count Bytes
LDY #$FF ;Search Minimum
STY I1
STY I1+1
INY
SC4 TYA ;Pos of Number
ASL
STA I5
LDA #>BUF
ADC #$00
STA I5+1
STY WORK
LDY #$00
LDA (I5),Y ;(I5) < I1 ?
PHA
CMP I1
INY
LDA (I5),Y
TAX
SBC I1+1
PLA
LDY WORK
BCS SC3 ;(I5) > I1
STA I1 ;Set New I1
STX I1+1
STY DC0 ;Set Codebyte
SC3 INY
BNE SC4
RTS
SC0 LDY #$00
SC1 JSR GETBYT ;Byte from Mem
ASL ;Pos of Number
STA I5
LDA #>BUF
ADC #$00
STA I5+1
LDA (I5),Y ;(I5) + 1
CLC
ADC #$01
STA (I5),Y
INY
LDA (I5),Y
ADC #$00
STA (I5),Y
DEY
JSR CHKEND
BCC SC1
RTS
GETBYT LDA (I2),Y ;Byte from Mem
INC I2
BNE GB1
INC I2+1
RTS
CHKEND LDA I2 ;End ?
CMP END
LDA I2+1
SBC END+1
RTS
;--- Decruncher ---
DEPACK .BYTE $0E,$08,$C8,$07,$9E
.TEXT "2062 TS"
.BYTE $00,$00,$00
ZPPOS = $5C
SEI
INC $01
LDY #$32 ;Trans Depacker
DC3 LDA DC0-1-K,Y
STA ZPPOS-1,Y
DEY
BNE DC3
STY $AC ;Trans Proggie
STY $AD
DC1 DEC $AD
DEC $AF
DC2 DEY
LDA ($AE),Y
STA ($AC),Y
TYA
BNE DC2
LDA $AF
CMP #$07
BNE DC1
LDA $AE ;Set Addrs
EOR #$FF
CLC
ADC #<PACK+1-K
STA $AC
BCC ANFL
INC $AD
ANFL LDX #$01 ;Start
ANFH LDY #$08
STX $AE
STY $AF
LDY #$00
JMP ZPPOS+1
DC0 .BYTE $99 ;Codebyte
DC7 JSR DC8-C ;Get Byte
CMP ZPPOS ;= Codebyte ?
BNE DC4
JSR DC8-C ;Get Len
TAX
JSR DC8-C ;Get Byte
.BYTE $2C ;Skip 2 Bytes
DC4 LDX #$01
DC6 STA ($AE),Y ;Store Byte/Seq
INC $AE
BNE DC5
INC $AF
DC5 DEX
BNE DC6
LDA $AD
BNE DC7
LDA #$37 ;Enter Value !
STA $01
CLI
JMP $FFFF ;Enter Value !
DC8 LDA ($AC),Y ;Get Byte
INC $AC
BNE DC9
INC $AD
DC9 RTS
PACK .BYTE $00 ;Dummy C = DC0-ZPPOS ;Correction K = DEPACK-$0801 So, das war's. Natürlich findet ihr den Sourcecode (im Startool-Format) und den ausführbaren Code auf Disk vor. In die- sem Sinne, mögen Eure Programme schrump- fen.
(cd)