(C) Kot / North Star group 07.1998
--------------------------------
Compressors decompressors
and they are not alone ...
All pryuvet from a group of North Star. In
this article I will address several problems of product quality
"plants softovareniya" nashego immense CIS.
Probably malomalski self-respecting
coder (a hacker) is almost always enjoys the compressor data,
whether it be a screen or code. Currently, the number
programs of this type has been steadily increasing and
have to choose. However, service performance, and sometimes and
software features often leave much to be desired.
Let's start with the program. It is known that
professionally made screen decompressors relotsiruemy, I mean
start carried out with the load address. Classical protsedurka
"self-re-addressing" looks like this:
DI;!!!
CALL ret_adr; # 0052, # 1792, # 33C5 etc
; E1>
DEC SP
; E2>
DEC SP
POP reg_p; HL, DE, BC, etc.
.......
Some wise guy (we will not show
finger: see ZF # 7Persprektivy
POS.O.T.A.p.p. Screen Compressor) advised (and, as I recall,
called lamerizmom) command to remove the first DI
the entire procedure. You see, gives displeasure to hear
inhibition Mouzon during a call to the decompressor ... So
let's clean up this stinking x DI or morfirovat it to NOP and
the program will look "elite". That is, he wants to
to say that dear Andrei
Sendetsky for general Ponte its ASC
placed first DI because he - lamer? But no, my friend. What do
we see if interrupt enable? You just
Think what will remove garbage from the stack
POP reg_p, if the CPU starts processing the interrupt at the
points e1 and e2! If someone did not understand why it happens,
let instead of e1 or e2 substitute any PUSH and the same POP
(emulation transmission interruption). Here I am here
"Zapachil" picture in a new LAZY_PACK.
Then uploaded to the STS: the beginning of the decompressor the
above "classic" ... only without the DI ... A pity. You think
for - But some clean DI and decompressor type MS_PACK'a where
data removed stack ... I still imagine
Alternatively, when in operation with a stack
SP is always a result of SP +2, but in a
same decompressor MS_PACK'a available:
.........
DEC SP
POP AF
.........
Potrassiruyte STS'om packed
MS_PACK'om unit with its original decompressor and count how
many times program addresses the above
pieces of code. And then to calculate their own theories: will
interrupt or not come to this moment and have time for a
decruncher 1 / 50 seconds ... Good luck ...
A striking example is TRANCE MD
(SBG), where, for example, along with the characters comes out
something "more uzhasnoe" ...
We now turn to the so-called technical service. That's all
write: we supposedly Progressive People, etc., but often the
whole real indication in the program - decimal (this applies to
sys-prog any purpose). Me (I'm sure not only me), this fact
"mad", roughly speaking, angry. Interestingly, whether many of
these "People", which for a couple of seconds to say that #
B700 is 46848? I I think there are not many and I'm not one of
them. Do not make the input (and display) of numerical values
and in HEX'e and DEC'e.
About themselves decruncher'ah special conversation.
Would long ago have time to forgive the banality, "to adopt a
standard" request type "And if you want to hem decruncher?"
(Decompressor ON / OFF). After all, for example,
how convenient zapachit all files (part of the MD,
levels of games or overlays systems) in the compressor and ship
them without dcrnchr'a and When unpacking, use one
decompressor only. This allows for PCD, MegaLZ and DSQ,
although it As for compressors, all kinds of data, including
on-screen. Desirable Included give two (or more) decompressor -
the choice of responsible, for example, the following
conditions: using the stack when not interrupt :-) Or without
the use of stack and IY in any status interrupts, etc. Options
can be any number, but if per se is only one, then it should
work with interrupt enable (this my personal opinion). Some
will say: Here a DSQ dekompresor also works with any status
interrupt, so it's probably the brake. The answer is: what As
DSQ, so there is data in hryanyatsya continuous form, and these
same data have raznobitnuyu value (see Figure), and
decompressor itself has a fairly compact size.
bit 76543210 | 76543210 | 76543210 |
----------------------------
l) 000 | 1101 | 0101010 | 01 | 01110110 |
f) 00011010 | 10101001 | 01110110 |
l) - logical data obtained at
compression (in a form accepted decompressor) continuous, ie
initial bits of the log. data unit does not sovapadaet with an
initial bit of nat. units. data that gives the effect of saving
bits in accordance file size (in direct proportion);
f) - a physical form, ie, so
data is located in the computer memory;
Think logically, we can conclude
that the transformation of data from the form l)
in the form of f) must be applied shifts (RR, RL and
etc.). Here's to it and leaves the lion's share
time at the decompressor DSQ, although there are
sense to optimize it.
Well, that if we are talking about DSQ, then discuss it in
detail. As you know, DSQ possible to stop the decompressor. But
this is half the battle. In prog DSQ_INFO, as often happens,
instead of descriptions - Hello, and kominsuny
any such nonsense. So, if you
decided to use castrated (without
dkmprsr'a) dataskviznuty blochok, then if you please know the
following things: it turns out that this block has a header
(len: 6 byte, but the idea should be 7 - see below), which
indicated:
N0 (byte) - the number of "cuts"
window of bits (much the way that fits
definition);
N1 (word) - the address entered in the query
DECRUNCH CODE TO: NNNN;
N2 (word) - Address, N1-1 + the real length
file, in other words - the address of the last byte of the file
(it is the latter, but not following it);
N3 (byte, and must be a word) - strongly
Do not laugh, but it is the low byte address
introduced at the request AUTOSTART: NNNN,
just a small glitch DSQ;
Total: byte + word + word + byte = 6 byte.
In fact, besides more bytes N0
a damn do not have, the more significant byte
start :-). You can, in principle, to leave
on-site N1 full length of the source file. But this - advice
for those who can be transformed DSQ in a new way
(With a cool service, etc.). Reasonable
question: what to do with N0?
.........
LD B, NN; nuf
LD H, # 2002
ADD HL, DE
CALL NNNN
ADD HL, BC
POP BC
LDDR
LD HL, XXXX; nif
SBC HL, DE
JR C, NNNN
POP HL
EXX
RET
..........
The argument of ref. B in a row and have nuf
same N0, and for full understanding
statements about the "window bits" potrassiruyte decompressor
debugger'om. N0 option depends on what was selected window size
When packing file.
And how do extract the block is not native decompressor?
First, DSQ in general is not an ordinary compressor. Let me
explain why. If you know the order of data transmission
"native" decompressor packer LPC, PCD, CC, MS_PACK, then able
to observe the following picture:
1) block LDIR (LDDR) on body file
(To perform end_block = end_file)
2) source (HL) = start_block
3) destination (DE) = start_file
LP 4) translate (HL) bits to (DE) bytes
5) inc HL, inc DE
6) go to LP if DE <(end_file +1)
In all DSQ "up side down":
1) block LDIR (LDDR) on body file
(To perform start_block = start_file)
2) source (HL) = end_block
3) destination (DE) = end_file
LP 4) translate (HL) bits to (DE) bytes
5) dec HL, dec DE
6) go to LP if DE <(start_file-1)
Profanity:
file - the original file;
block - the result of compression;
source - from where we take;
destin - where to put;
start_file - start address dkmprsiruemyh data;
end_file - the address of the last byte
dkmprsiruemyh data;
start_block - beginning of the data block'a;
end_block - the address of the last byte
block'a;
inc, dec - increase, decrease in
NNNN bytes (contrary to legend - not only
per unit);
body file - a chunk of memory,
redundant under the file;
Generally, these schemes are in the ideal. In fact for DSQ
There are some impressive amendment.
If you do enjoy the DSQ, you probably remember something (-2).
This occurs because destin'atsiya is faster
sour'sirovanie than as a result, when
remains unpacked 1-3 bytes is equal to destination source, and
the next cycle generally ahead of him. Here and there
situation when, for example, the marker
end is taken "something" whose probability to be a marker of
the end of 1 / 256 ... Therefore LDIR'it or LDDR'it must be so
to start_blok = start_file-2 (-2, -3 and more but not less than
-2), and if the block DSQ with the headline, then start_block =
start_file-2-6 (-8, -9, and more, not less than -8). All this,
of course, the glory of DSQ does not add to, and in fact could
be as a PCD or MS_PACK'e using the buffer - there
everything works according to the above scheme
as a "native" or "not family"
dkmprsrami. Note: nif in a chunk disassembler dehryunchera
posed not by accident - there must necessarily be
start_file-one!
Finish with DSQ and return to # 1B00,
ie to skrinovym packer. Put forward more
one suggestion: why, even in
compressors, the screen does not provide
the possibility of a change of address extraction? About
What are you, old man? You will probably
faced a situation when you have
decompress the image on the SCR1 (in the seventh
page), ie under the address # C0 or even
unpacked at # 40 and not # C0, and go somewhere "in general nor
there" (eg, when implementing any gasilok / Lighters
and other "manifestations"). My suggestion
is to be able to choose the least senior part destin'atsii,
a junior would be zero "by default"
For example, # 70, # 67, # BF, # 9A, # DE, etc. A
then after unpacking in any way it (the picture) show (you can
even LDIR'om :-)).
Now back to "relotsiruemomu Start programs. I will give you a
set of small procedures that provide "self-location":
1) DI; required! (See above)
CALL ROM_RET; # 52, # 7C, # 33C5, etc.
DEC SP
DEC SP
POP reg_p; HL, DE, BC, IX, etc.
........ ; Length: 7-8 bytes
2) LD HL, # E9E1; POP HL (# E1)
LD (# 4000), HL; JP (HL) (# E9)
CALL # 4000;
.......... And the result in HL
; Length: 9 bytes
3) LD HL, # 4000; <- start_1
PUSH HL; <- start_2
LD (HL), # E1
INC HL
LD (HL), # E9
DEC HL
CALL ROM_JHL; JP (HL): # 162C, # 6F
........ And the result in HL
POP reg_p; length: 14 bytes
The first option works only if
Interrupt prohibited, but the address
can be placed in any of register pairs. Used ROM-48.
The second option is for 1-2 bayta, but
works with any status prervyvany and
does not use ROM.
The third option yavyaetsya universal
but again uses ROM. There is
two points of entry and start_1 start_2. Through
start_1 by binding unpack the data to a fixed memory address,
using the same start_2 you themselves are free to choose the
address, but it is important to younger, too, was equal to zero
(Depending how the counting is "screen" addresses dkmprsrom - a
condition: (not) allowed to use a non-zero low part).
In general, options may be much
anywhere, as long as it was convenient,
cool and no bugs :-(.
A few days ago looked inlaytskie demos and
one of them (Art Vision by etc group)
learned that, say, uses the deme
decruncher ((c) LAZY) MS_PACK'a that does not use the stack for
"pumping" the data etc. Since the MSP is not provided
Off the decompressor, the "new"
dkmprsr works with building blocks
MSP, which already has a decompressor.
; MS_PACK blocks decruncher
; Written by LAZY / etc group
; Entry: IX - adr of block
; (Wiz standard decruncher)
INC HX
LD L, (IX-# 17)
LD H, (IX-# 16)
LD DE, MSPBUF +4
LD BC, # 0005
LDDR
LD L, (IX-# 15)
LD H, (IX-# 14)
LD E, (IX-# 13)
LD D, (IX-# 12)
LD C, (IX-# 11)
LD B, (IX-# 10)
LDDR
INC DE
INC DE
INC DE
EX DE, HL
LD E, (HL)
INC HL
LD D, (HL)
INC HL
EX DE, HL
LD BC, # 1010
EXX
LD E, (IX-# 0F)
LD D, (IX-# 0E)
MSP_LP CALL MSPCOD
JR C, LL631D
CALL MSPBYT
LD (DE), A
INC DE
JR MSP_LP
LL631D LD HL, # 0302
LL6320 LD B, # 02
CALL BCOD_A
CP H
JR C, LL632F
ADD A, L
LD L, A
CP # 11
JR NZ, LL6320
XOR A
LL632F ADD A, L
CP # 05
JR NC, LL6364
CP # 02
JR NZ, LL6367
LD C, A
LL6339 XOR A
LL633A LD H, A
CALL MSPBYT
LD L, A
LD A, E
SCF
SBC A, L
LD L, A
LD A, D
SBC A, H
LD H, A
LDIR
JR MSP_LP
LL634A CALL MSPBYT
INC A
JR Z, MSPEND
INC A
JR NZ, LL635D
CALL MSPBYT
LD C, A
CALL MSPBYT
LD B, A
JR LL6368
LL635D ADD A, # 0F
JR NC, LL6367
INC B
JR LL6367
LL6364 JR Z, LL634A
DEC A
LL6367 LD C, A
LL6368 CALL MSPCOD
JR C, LL6339
LD L, B
LD B, H
CALL BCOD_A
LD B, L
CP # 02
JR NC, LL637A
INC A
JR LL633A
LL637A CALL LL63B1
CP # 08
JR NC, LL6384
DEC A
JR LL633A
LL6384 CALL LL63B1
CP # 17
JR NC, LL638F
SUB # 09
JR LL633A
LL638F CALL LL63B1
AND # 1F
CP # 1F
JR C, LL633A
CALL MSPBYT
JR LL633A
MSPEND LD HL, MSPBUF
LD BC, # 0005
LDIR
LD HL, # 2758
EXX
RET
BCOD_A XOR A
CALL LL63B1
DJNZ $ -3
RET
LL63B1 CALL MSPCOD
RLA
RET
MSPCOD EXX
ADD HL, HL
DJNZ NONEXT
LD B, C
EX DE, HL
LD E, (HL)
INC HL
LD D, (HL)
INC HL
EX DE, HL
NONEXT EXX
RET
MSPBYT EXX
LD A, (DE)
INC DE
EXX
RET
MSPBUF DEFB 0,0,0,0,0
Well, probably, and all I wanted
to tell you. If anyone has any comments, let MIRACLE wrote to
the editor or me (Kot'u).
Bye'te!
Kot / NSG 07.1998
Kirovsk-apatite-Olenegorsk
---------------------------------------