ЇЄ ЄєЇCODING ЇєЄ ЄєЇ
(C) ALK / XTM
HOW KODIT optimally.
- Any program can be
soptimizirovat to two bytes
without losing its
functionality.
(From the oral statements
M.M.A)
- Oh, Vassily Ivanovich, do not
like
me this Sienkiewicz ...
- Do not like it - do not eat!
(From folklore)
I have no desire to speak. And was not there. And what
exactly? - How to learn to program ... Lamerstvo just some ...
Depression rules my mind ...
Do not want to look like a sort of mentor. Just do not want.
But what do have an anniversary Born Dead release, Chaos
Construction on the nose again, though, that's bursting with my
(seemingly) to share with world about the wonders of coding
(Yeah ... someone would have told you so!). In general, yes.
As it happens, this time we M.M.A presented at CC99
only 512-byte intro ABSENT. Seemed to-be, well, that can be
write in these accidents bytes? It turned out a lot. In the
process writing intra been 16 (if not more)
optimizations, and some examples of merit (in my opinion)
attention.
-------------------------------------------------- -------------
Take, for example, sine. It can be used in many
effects, such as plasma (for intro will come), flying on
Lissajous trajectories (no comments), rotation mapping (type
turns textures or sprites), and of course 3D - rendering.
Typically, the sine table is calculated in advance (in Basic),
and demah / intra This table can "eat" from 256 (8 bit) to
512 (16 bit) of bytes. And what we have in 512 bytes?
Half will take the sine and the other half - well, a maximum of
2 call-correlation effects.
No, this is not our method!
The following procedure generates a sine table.
Size: 75 bytes = 44 bytes + 31 bytes of code tables.
Size of the output table - 256 bytes. Actually, the table
stored value of the sine of 0 to 2 PI in increments of 1 / 128
PI. If interpret them as fractional parts of numbers, then they
lie in ranging from 0 to 255/256, ie, this is a classic sine
with accuracy of 1 / 256. The first 128 bytes of the table in
the calculations should be taken with a plus sign, the last 128
- with a minus sign. If visualize this sine wave, both of its
half- are positive, and the calculations need to follow the
sign. Once a reservation: the sine is not calculated, too long,
long and sad this occupation. In this example, the sine
unpacked from finished, so to speak, the archive. Table
RLESIN are DELTA RLE-data, on which construction 1 / 4
period table. Second quarter - is a "mirror" display
the first well and the second half period - a copy of the
first. It's easy!
SINTAB EQU # C000
XOR A
LD E, A
LD D, SINTAB'H; table is always located at
, "Flat" address # XX00
LD HL, RLESIN
EX AF, AF '; in A' will be formed next
, The sine, the initial value = 0
LRP1 LD A, (HL)
RRA
RRA
RRA
AND # F; bits 3 .. 6 data - the number of bytes
; Package
LD B, A
LD A, (HL)
AND 7; lower 3 bits of data - the increment of the sinus
; From the previous
LD C, A; C = +0 .. +7
EX AF, AF '
PVT LD (DE), A; put another value in an array
INC E
ADD A, C; increment value
DJNZ PVT; to the next value in a package
EX AF, AF '
INC HL; following RLE-data
BIT 6, E
JR Z, LRP1; check at the end of 1 / 4 of period -> = 64
bytes
; After DE = # C040
LD L, E
LD H, D
EX AF, AF '; A = # FF
LSI2
LD (DE), A; the construction of the second quarter
period
INC E
DEC L
LD A, (HL); copy backwards-ahead
JR NZ, LSI2
LD C, E; DE = # C080 HL = # C000 BC = # 0080
LDIR; up the first half-second
RET
RLESIN; DELTA-RLE table 1 / 4 period of sinus
DEFB # E, # F, # 26, # F, # 4E, # D
DEFB # 16, # D, # E, # 15, # E, # 2D
DEFB # C, # D, # C, # D, # 2C, # B
DEFB # C, # B, # C, # 23, # A, # B
DEFB # 2A, 9, # A, # 29,8,9, # 18
Previously, this same procedure "weighed" ~ 115 bytes. Who
are not lazy - Look at BlAME. (And as such could then leak?)
-------------------------------------------------- -------------
Of course, in 512 bytes is not razverneshsya - you can count
on attribute effects ...
That procedure for deriving attribute b / sprite: Who can
shorter?
ADRSCR EQU # 5800
LD HL, SPRITE
LD DE, ADRSCR
LG2
LD B, 8
LG1
RLC (HL)
SBC A, A; A = 0 / # FF
And if here insert AND # COLOR,
; It will be black-# color-LIMITED sprite.
And if the same add ADD A, # COLOR2,
; It will be quite 2-color sprite.
LD (DE), A
INC E
DJNZ LG1
INC HL
LD A, E
SUB ESPR-SPRITE * 8'L; = SUB # E0
JR NZ, LG2
RET
SPRITE
DEFB # 1D, # C7, # 78, # FE
DEFB # 35, # AC, # 60, # 18
DEFB # 35, # AC, # 63, # 98
DEFB # 3D, # C6, # 73, # 58
DEFB # 35, # A3, # 63, # 58
DEFB # 35, # A3, # 63, # 58
DEFB # 35, # CE, # 7B, # 58
ESPR
-------------------------------------------------- -------------
The same, but the sprite is obtained by pseudo-color:
LD HL, SPRITE
LD DE, ADRSCR
LG2
LD B, 8
LG1
RLC (HL)
SBC A, A
AND E
RRA; RRA - just to avoid FLASH
LD (DE), A
INC E
DJNZ LG1
INC HL
LD A, E
SUB ESPR-SPRITE * 8'L
JR NZ, LG2
RET
-------------------------------------------------- -------------
It is the same. Sprite smoothly "manifest."
LD HL, SPRITE
LD DE, ADRSCR
LD C, 0
EI; to not only stuck
LG3
PUSH HL
PUSH DE
HALT; can and more - a matter of taste
HALT
LG2
LD B, 8
LG1
RLC (HL)
SBC A, A
AND E
AND C
RRA
LD (DE), A
INC E
DJNZ LG1
INC HL
LD A, E
SUB ESPR-SPRITE * 8'L
JR NZ, LG2
POP DE
POP HL
SLI C; C = 0,1,3,7, # F, # 1F, # 3F, # 7F, # FF
, Say, an undocumented command .. :)
JR NC, LG3
RET
-------------------------------------------------- -------------
Another attribute to the effects of "fill" the screen "chess
field "to get a larger number of semitones:
LD C, # AA
LD HL, # 4000
LP1
LD (HL), C
INC L
JR NZ, LP1
RRC C
INC H
LD A, H
SUB # 58
JR NZ, LP1
RET
--------------------------------------------------
------------- Next I will speak theses. (M.M.A: April Theses:)
--------------------------------------------------
------------- If the procedure is performed only once - why
should it be made out as procedure?
-------------------------------------------------- -------------
In my opinion, those who use constructions like:
CALL SUBR1
RET
should be 'publicly express fi'.
--------------------------------------------------
------------- should be 4 times in a row at two locations to
perform the procedure SUBR2
Wrong: Normal: Correct:
CALL SUBR2; 3 CALL SUBR_X; 3 CALL SUBR_X; 3
CALL SUBR2; 3 .... ....
CALL SUBR2; 3 CALL SUBR_X; 3 CALL SUBR_X; 3
CALL SUBR2; 3 .... ....
.... .... ....
.... .... ....
CALL SUBR2; 3 SUBR_X LD B, 4, 2 SUBR_X CALL SUBR_Y; 3
CALL SUBR2; 3 LLX PUSH BC; a SUBR_Y CALL SUBR2; 3
CALL SUBR2; 3 CALL SUBR2; 3 SUBR2 ....
CALL SUBR2; 3 POP BC; 1 ....
.... DJNZ LLX; 2 RET
RET; 1
, 24, 16, 12
-------------------------------------------------- -------------
If the previous program fragment in the registers are
useful data, why not use them?
Wrong: Normal: Correct:
CALL SUBR_N CALL SUBR_N CALL SUBR_N
LD HL, 0, 3 XOR A; 1 LD E, D; 1
LD DE, 0, 3 LD H, A; an INC DE; 1
LD L, A; 1 LD H, E; 1
LD E, A; 1 LD L, E; 1
LD D, A; 1
, 6, 5, 4
SUBR_N
....
LD DE, # FFBF
RET
Incorrect: Correct:
LD A, E; LD A, E;
CP # 5B; SUB # 5B;
JR NZ, $ -10; JR NZ, $ -10;
XOR A; 1 OUT (C), A;
OUT (C), A;
, 1, 0
-------------------------------------------------- -------------
The same result can be achieved in different ways.
Incorrect: Correct:
LD B, D LD B, D
OUT (C), A OUT (C), A
LD B, E LD B, E
EX AF, AF '; a OUTI; 2
LD A, (HL); 1
OUT (C), A; 2
INC HL; 1
EX AF, AF '; 1
, 6, 2
Lamerstvo: Fair: Good: Fast:
LD HL, # 4000, 3 LD HL, # 5AFF; 3 LD HL, # 5B00; 3 XOR A; 1
LD BC, # 1B00; 3 LD DE, # 5AFE; 3 XOR A; 1 LD L, A; 1
LD (HL), 0, 2 LD BC, # 1B00; 3 DEC HL; 1 LD H, A; 1
INC HL; an LD (HL), C; an LD (HL), A; 1 LD E, A; 1
DEC BC; a LDDR; 2 BIT 6, H; 2 LD D, A; 1
LD A, C; 1 JR NZ, $ -4; 2 ADD HL, SP; 1
OR B; 1 EI; 1
JP NZ, $ -6; 3 HALT; 1
LD SP, # 5B00; 3
.3456 PUSH DE; 3456 * 1
LD SP, HL; 1
, 15, 12, 10, 3468
How it all: That's right:
CALL SUBRA CALL SUBRA
PUSH HL; 1 ....
.... CALL SUBRA
CALL SUBRA ....
PUSH HL; a CALL SUBRA
.... ....
CALL SUBRA ....
PUSH HL; 1 ....
.... ....
POP BC POP BC
POP DE POP DE
POP HL POP HL
.... ....
SUBRA .... SUBRA ....
LD L, H LD L, H
SBC A, A SBC A, A
LD H, A LD H, A
RET; an EX (SP), HL; 1
JP (HL); 1
4 2
-------------------------------------------------- -------------
Well, all I knew - said.