level 7
; Cubist - a little plasma effect by Bonz; assemble with NASM; -------------------------------------------------------------------------; If defined, do not assume CX=0xFFh on startup, and does not set video mode; %define DEBUG; If defined, don't set the palette (-39 bytes); %define NO_PAL; If defined, squares don't rotate (-44 bytes); %define SIMPLE; If defined, squares rotate around a vertex rather than the center (+1 byte); %define HEADACHE; -------------------------------------------------------------------------%ifdef SIMPLENXequ64; Number of horizontal blocksNYequ40; Number of vertical blocksBLKequ5; Spacing between each block%elseNXequ30; Number of horizontal blocksNYequ18; Number of vertical blocksBLKequ10; Spacing between each block%endif_Iequ-192//NX; Vertical cosine 1 update per row_Jequ2; Vertical cosine 1 update per frame_Kequ320//NX; Double cosine update per column_Nequ128//NX; Vertical cosine 2 update per row_Oequ1; Vertical cosine 2 update per frame_Lequ-192//NX; Horizontal cosine update per column_Mequ3; Horizontal cosine update per frame; A few parameters for the plasma. The bigger they are, the more; periods are visible on each frame, or the faster the animation is.; Bigger NX and NY should be compensated with small values of ; _[IKNL]%ifdef HEADACHEORIGINequ0; Origin of each squareSIZEequ78h; Scaling factor for the blocks%elseORIGINequ-128; Origin of each squareSIZEequ40h; Scaling factor for the blocks%endifINCRequ700h / SIZE; Delta between two points (empiric); Initial coordinates and increment between two rowsX0equ(320-NX*BLK)/2 + BLK/2Y0equ(200-NY*BLK)/2 + BLK/2ADVequ320*BLK-NX*BLK; -------------------------------------------------------------------------; Macro to update the cosine values, exploiting a few constant values; of the registers%macro cos_set 2movbyte[si+%1-vcos1], %2%endm%macro cos_upd 2%if ((%2) & 255) = 2addbyte[si+%1-vcos1], bh%elif ((%2) & 255) = 3addbyte[si+%1-vcos1], dh%elif ((-%2) & 255) = 2subbyte[si+%1-vcos1], bh%elif ((-%2) & 255) = 3subbyte[si+%1-vcos1], dh%elseaddbyte[si+%1-vcos1], (%2) & 255%endif%endm; Macro to set the individual bytes in a word%define MAKEWORD(a, b)((a) * 256) | ((b) & 255); set video mode (4 bytes) -------------------------------------------------org100h%ifdef DEBUGmovcx, 0ffh%elsemoval, 13hint10h%endif; compute sine table (31 bytes) --------------------------------------------movdi, sine; Point DI to beginning of data areainccx; CX = 256sineloop:; Construct a 256-entries -sine tablemovax, di; AX = sign extended (-128..127) valuecbwmovsi, aximulsi, si; SI = x^2lea
bp
, [si-16341]; BP = x ^ 2 - 16341shrsi, 1; SI = 10291 + x^2/2addsi, 10291imulbp; DX:AX = x (x^2 - 16341)idivsi; divide -- negated sine in AXsaral, 1; Turn range to -31..31stosb; Store AL (CS=ES)loopsineloop; Until the sine table is full; set palette (39 bytes) --------------------------------------------------%ifndef NO_PAL movdx,3c8h; DAC address registerxoreax, eax outdx, aldecax; eax = BGRM (M=marker, R is red-1) incdx; DAC data register; Meaning of the bytes in EAX:; 00h-3fhOutput this; 7fhOutput this -- it has already reached 3fh; FFhIncrement the next byte;; At start, BBGGRRMM = 0000FFFFh; note that only AL acts as a marker; because AH -- red -- is incremented to 00h when the LSB is rotated).;; When we reach MMBBGGRR = FF00003Fh, we XOR the magic value 8000FFC0h; and turn it to RRBBGGMM = 7F00FFFFh. Again, AH -- green -- becomes; 00h so it is not a marker.;; Analogously, MMRRBBGG = FF7F003Fh is turned to GGRRBBMM = 7F7FFFFFh; (where again AH -- blue -- becomes 00h).;; Finally when we reach MMGGRRBB = FF7F7F3Fh, XORing the same value as; before gives BBGGRRMM = 7F7F80FFh which we recognize easily because; AH is not turned to FFh.setpal:roreax, 8; Advance EAX, set carry if markeradcal, 0; Increment if the marker was therejssetpal; Don't output AL if it is a markeroutdx, al cmpal, 63 jnesetpalxoreax, 08000ffc0h; See abovesahf; Stop when 7fh (red) becomes 80h jcsetpalmoval, 3fh; AX = 803fhpal3:; set 64 entries to white -> blackoutdx, al; Output 63-0outdx, aloutdx, aldecaxjspal3; Until AX = 7fffh%endifframe:xchgcx, ax; Zero the off-screen buffer (CX=0)movch, 320*200/256; about 320*200 bytesmovdi, bufferpushdirepstosb
2008年05月01日 13点05分