{$M 4096,0,0} {$a+,b-,d+,e-,f-,g+,i+,l+,n-,o-,p-,q-,r-,s+,t-,v+,x+} { if you have a 386 or better 'uncomment' the next line } {define cpu386} { if you want circles 'incomment' the next line } {$define CIRCLES } Program WrmhDance; { Demo by Wil Barath Oct 1994, Public Domain } { Based on Vortex demo by ??? } Var Map:word; {used as a pointer to the bitmap} stab,ctab:array[0..255] of integer; virseg:word; lstep:byte; const vidseg:word=$a000; pfx=1; {try '1' for weird palette fx} SlowMode:Boolean=False; Circles:Boolean=False; Procedure AllocateMem; {returns a segment pointer for a 64K bitmap} label noerror; begin asm mov ah,$48 mov bx,$1000 { request 64K } int $21 jnc noerror mov ax,0000 noerror: mov Map,ax { The segment pointer goes in Map } end; If Map=0 then begin Writeln('Could not allocate enough memory'); Writeln('Program ending...'); Halt;end; end; Procedure GiveBackMem; {returns the memory used for the map to the system} begin asm mov ah,$49 mov dx,Map mov es,dx int $21 end; end; procedure setpal(col,r,g,b : byte); assembler; asm mov dx,03c8h mov al,col out dx,al inc dx mov al,r out dx,al mov al,g out dx,al mov al,b out dx,al end; procedure cls(lvseg:word); assembler; asm mov es,[lvseg] xor di,di xor ax,ax {$ifdef cpu386} mov cx,256*256/4 rep db $66; stosw {$else} mov cx,256*256/2 rep stosw {$endif} end; procedure retrace; assembler; asm mov dx,03dah @vert1: in al,dx test al,8 jnz @vert1 @vert2: in al,dx test al,8 jz @vert2 end; Var cotable:Array[0..256] of Integer; Const costabptr:Pointer=(@CoTable); {----------------------------------------------------------------------} Procedure VideoMode(mode:word);assembler; Asm Mov ax,mode;Int 10h;end; Function MouseExists:Boolean;Assembler; asm Xor ax,ax;Int 33h;end; Function MouseAt(Var X:Word;Var y:Word):Word;assembler; asm Mov ax,03h;Int 33h;Les di,x;Mov ES:[DI],cx;Les di,y;Mov ES:[DI],dx Mov ax,bx;end; Function Readkey:Char;Assembler; asm Xor ax,ax;Int 16h;end; Function Keypressed:Boolean;Assembler; asm Mov ax,0100h;int 16h;Jnz @1;Xor ax,ax;@1: end; Function MouseStatus:LongInt;Assembler; asm Xor ax,ax;Int 33h;end; Procedure Pset(x,y,c:byte);Assembler; asm mov es,virseg;mov bh,y;Mov bl,x;Mov al,c;Mov es:[bx],al;end; Var ra,rb,rc:Word; Function rand:Word; Near ;Assembler; asm Mov ax,ra; Add ax,ax; Adc ax,904; Xor ax,$aaaa;Mov ra,ax;Xor ax,rb;Mov rb,ax; Xor ax,rc; Mov rc,ax; end; Function random(n:Word):Word; Near ;Assembler; asm Call Rand; Mul n;Mov ax,dx;end; Procedure mktabl;assembler; {generates Sine approx. table} Const x:Integer=127*256+221;y:integer=0;{much smaller than using BP's} label cosloop; {FP math to make it! } asm {Oct 10/94 by Wil Barath } Mov si,804 {sine portion of O } Mov bx,32758 {cosine portion of O } Mov cx,256 {number of degrees in our circle} Les di,costabptr{destination for our table} Push bp cosloop: Mov ax,x stosw Imul bx adc dx,dx Mov bp,dx {bp:= x*cos(O)} Mov ax,si Imul y adc dx,dx Sub bp,dx {bp:= x*cos(O)-y*sin(O)} Mov ax,bp Mov al,ah Mov ax,si Imul x adc dx,dx Mov x,bp {x:=bp} Mov bp,dx {bp:= x*sin(O)} Mov ax,bx Imul y adc dx,dx add bp,dx {bp:= x*sin(O)+y*cos(O)} Mov y,bp {y:=bp} Loop cosloop Pop bp end; {----------------------------------------------------------------------} Procedure DrawScreen(x,y,scale:Word;rot:word);assembler; label start,hloop,vloop; Procedure I;assembler;asm db 0;end; {fool the compiler into giving us} Procedure j;assembler;asm db 0;end; {2 WORD variables in CODE segment} asm push ds { gotta save these or all hell breaks loose :-( } Push bp Mov bx,rot {compute scanning vectors} Add bx,bx Mov ax,word(cotable[bx]) Imul scale {result in dx = scale*(ah/256)+scale*(al/65536)} Mov si,dx {thusly si:=costable[rot]*scale/256} Add bx,128 AND bx,511 Mov ax,word(cotable[bx]) Imul scale Mov cx,dx {cx:=costable[(rot+64)Mod 256]*scale/256} {this gives us the same as sin(...)} Mov bx,x {compute screen center for rotation} Mov ax,160 Mul si Sub bx,ax Mov ax,100 Mul cx add bx,ax Mov Word(i),bx {i:=x-si*160+cx*100} Mov bx,y Mov ax,160 Mul cx Sub bx,ax Mov ax,100 Mul si Sub bx,ax Mov Word(j),bx {j:=y-cx*160-si*100} Mov bp,cx { put movement vector component here...} { from here on we can't reference STACK variables...} mov ax,[Map] { get segment of bitmap (in the DATA segment)} mov ds,ax mov ax,$a000 { set es: to video memory} mov es,ax sub di,di { start at 0,0 on the screen} mov cx,200 { Number of rows on Screen} {-----This section has been hyper-optimised for 286+-------------------} vloop: push cx mov bx,Word(j) { start scanning the source bitmap} mov dx,Word(i) { at i,j which were calculated above.} mov cx,160 { Number of columns on screen/2} hloop: add bx,bp { add the 'right' vector } add dx,si { add the 'down' vector } xchg bl,dh { set up 8.8 fixed w/ Right MOD 256 and Down MOD 256} mov al,[bx] { load a pixel from source } xchg bl,dh { restore the counting registers} add bx,bp { add the 'right' vector } add dx,si { add the 'down' vector } xchg bl,dh { set up 8.8 fixed w/ Right MOD 256 and Down MOD 256} mov ah,[bx] { load a pixel from source } Stosw { write and advance 2 pixels (could do 4 w/386!)} xchg bl,dh { restore the counting registers} Loop hloop { End of horizontal loop} dec si;dec bp { Unquote one or both of these to cause mag. f/x} sub Word(i),bp { i,j is the starting coords for a line } add Word(j),si { so this moves down one line } Pop cx loop vloop { End of verticle loop } {-----That's all there is to the actual screen-writing section!--------} Pop bp pop ds { Restore the ds } end; {----------------------------------------------------------------------} var ax,ay,mx,my,x,y,h,i,j:word; c:byte; rot,dist,mouse:Word; dr,dx,dy,dd:Integer; procedure Circle(cx,cy,r,c:Integer); var rr,xx,yy:longint;x320,y320,p:Word;x,y:Integer; label Draw; begin rr:=r;y:=0;x:=r;rr:=r*r;xx:=rr-x;yy:=0; x320:=x*256;y320:=y;p:=cx+cy*256; asm Jmp @Skip @Curse: Add di,dx {dx is the x offset from center} Mov es:[di+bx],al {draw 4 cursor positions} Neg bx Mov es:[di+bx],al Sub di,dx Sub di,dx Mov es:[di+bx],al Neg bx Mov es:[di+bx],al Add di,dx Ret Draw: Mov es,VirSeg Mov di,p {di is the center of the circle} Mov bx,y320 {bx is the Y offset from center} Mov dx,x Mov ax,c Call @Curse {draw the 4 cursors in their quadrants} Mov bx,x320 Mov dx,y Call @Curse {draw the 4 cursors at 90 degrees} ret @Skip: end; Repeat if xx>(rr-yy) then Begin { asm call draw;end;{} Inc(xx,1-x-x);dec(x);dec(x320,256); end; asm call draw;end; Inc(yy,y+y+1);inc(y);inc(y320,256); Until x500) THEN DD:=-5; If ((dist+dd)<10) then dd:=10; dist:=dist+dd; until keypressed; while keypressed do readkey; GiveBackMem; VideoMode($03); end.