Demo or Die #02
31 июля 1999 |
|
Demo-Building - an ancient effect a tricky name Moving Shit.
__________________________________________ (C) Devil of eTc / Scene '99 ..... Moving Shit ..... This article describes the effect of ancient a tricky name Moving Shit. I am sure that many of our readers have long been aware of it, but for a novice programmer it will, I hope, interesting. Along the way we look at many problems arising opimizatsii algorithms such as: - Transfer of the sprite to the screen ispolizovaniem stack - Rational use of tables for calculate the address screen, the address line sprite, etc. etc. To begin the essence of the algorithm. For example we have a table of sines and just two variables characterizing offset in this table. For definiteness, let the table with us will be longer than 256 bytes and will take values from 0 to 64. Just to speed up code, place it on a multiple address. Variable displacement will take 8-bit and let them find a match in variables A and B. Now we need to create a sprite in which or editor. In this case, sprat may have arbitrary width (within reason) but the length must be equal to twice muksimalnomu value neshey sinusoid ie 64 * 2 = 128. In the sprite can be located anything: teugolniki circles, etc. in general it all depends on your imagination (for example, I created two different sprite and you can immediately see the difference in the effect). Next, we need to organize a series of which we seem to be on display sprite screen, but not directly, but raschityvaya address each line based on the fact that NumLin: = (SIN [A + n] + SIN [B + n]); AddrLine: = AddrSpr + NumLin * len; where NumLin - number of output lines; n - is taken from schetka cycle; AddrSpr - well, everything is clear this is hell res sprite in memory; len - the width of sprite in familiarity; Once we got the address line safely conclude it to the screen and go to calculation of the next. Once we have built a sprite izment variables A and B-type formula: A: = A + Step1; B: = B + Step2; {Step1 not equal to Step2} That's it. If you're ponel then further can not read, and for the doubters cite an example of source code with detailed explanations. ORG # 7000 Y_S EQU 129; length sprite CALL INIT_P; Initialize all , Tables, and kideteli For more detail in the most ; Procedure START LD A, # 7F; check for depression IN A, (# FE); space and leave RRA RET NC EI XOR A OUT (# FE), A HALT; waiting INT'a LD A, 1 OUT (# FE), A DI LD D, SINTAB [; record in the D and H LD H, D; senior Address Table. ; Sinuses POS1 LD A, 0; INC'aem variable .1 INC A; A (see above) LD (POS1 +1), A LD E, A POS2 LD A, 0; DEC'aem variable .4 DEC A; B (see above) LD (POS2 +1), A LD L, A , In principle, INC or DEC Pick up on their ; Taste, more importantly, to priroshenie ; Variables A and B was as much as possible ; Different EXX LD H, TBLADD [; record in H ', Senior EXX; byte tables to ; Torah, we believe ; AddrLine, substituting , In L ', NumLin LD (SPBUF), SP LD SP, BUFADR; in SP, address table ; Lines in the open ; Kidatele sprite GETAD INC E, L LD A, (DE) ADD A, (HL) EXX ADD A, A; nabodim NumLin LD H, TBLADD [ LD L, A; L = NumLin POP DE; DE, address in kidatele ; Sprite LDI; puts AddrLin LDI; in the open kidatel EXX; sprite ENDGET DS (ENDGET-GETAD) * Y_S ; In this buffer, we povtruen 129 times ; Piece of code from GETAD to ENDGET, for ; Acceleration LD SP, (SPBUF) CALL PUTSP; actually throw on ; Screen sprite JP START; on top DOWN_HL INC H LD A, H AND 7 RET NZ LD A, L ADD A, 32 LD L, A RET C LD A, H SUB 8 LD H, A RET ; Procedure generates INIT_P kidatel ; Sprite with the application stack INIT_P LD HL, PUTLIN LD DE, ENDPUTL LD BC, (ENDPUTL-PUTLIN) * (Y_S-1) LDIR EX DE, HL LD (HL), # ED INC HL LD (HL), # 7B INC HL LD (HL), SPBUF] INC HL LD (HL), SPBUF [ INC HL LD (HL), # C9 , Further there is a procedure which generates ; Procedure for calculating the address table lines LD HL, GETAD LD DE, ENDGET LD BC, (ENDGET-GETAD) * (Y_S-1) LDIR LD B, Y_S LD HL, # 4010 LD IX, ADRSCR +1 LD DE, ENDPUTL-PUTLIN INIT1 LD (IX), L LD (IX +1), H ADD IX, DE CALL DOWN_HL DJNZ INIT1 LD B, Y_S LD DE, ENDPUTL-PUTLIN LD IX, BUFADR LD HL, PUTLIN +1 INIT2 LD (IX), L LD (IX +1), H INC IX INC IX ADD HL, DE DJNZ INIT2 LD B, Y_S LD HL, 0 LD DE, SPRAIT LD IX, TBLADD INIT3 LD C, L .4 ADD HL, HL ADD HL, DE LD (IX), L INC IX LD (IX), H INC IX LD H, 0 LD L, C INC L DJNZ INIT3 RET ; SPRAIT INCB "SHIT_SP1" SPRAIT INCB "SHIT_SP2" SPBUF DW 0 BUFADR DS Y_S * 2 ORG (($ -1) [+1) * 256 SINTAB INCB "STAB" ORG (($ -1) [+1) * 256 TBLADD DS Y_S * 2 PUTSP LD (SPBUF), SP; 20 PUTLIN LD SP, 0, 10 EXX; 4 POP HL; 10 POP DE; 10 POP BC; 10 POP AF; 10 EXX; 4 POP DE; 10 POP BC; 10 POP HL; 10 POP IY; 10 ADRSCR LD SP, 0, 6 PUSH IY; 11 PUSH HL; 11 PUSH BC; 11 PUSH DE; 11 EXX; 4 PUSH AF; 11 PUSH BC; 11 PUSH DE; 11 PUSH HL; 11 EXX; 4 ENDPUTL; Total: 222 cycles , Ie 13.87 cycles per byte , That is not so bad ... At Sim simpler and conclusion add that the way to optimize incalculable, and as one of the great: "There is no program that can not be make one byte shorter or one beat faster. " Questions please send email to: to: Sergey Movchan 2:4635 / 100.128 @ FidoNet __________________________________________
Other articles:
Similar articles:
В этот день... 23 November