by Matthew Wilhelm Tiny Parallax Starfield First: STARNOKB.COM DOES NOT CHECK FOR A KEYSTROKE TO EXIT. IT IS AN INFINITE LOOP. UNLESS YOU RUN IT UNDER A DOS SHELL (OS/2, WINDOWS 95, ETC) YOU WILL NEED TO REBOOT YOUR MACHINE. Description: These files are a modification of my winning entry to the small, randomized ~200 star 4+ speed parallax scroller speed competition. The code delivers multicolor stars at many different scroll rates, exceeding the specifications of the competition. It runs tolerably on my 486/50 with ET4000 ISA video card. It runs quite nicely on a my p133 with ET6000 PCI card. As you may notice, text mode is not restored. STAR.* include keyboard checking and is slow. STARNOKB.*, removes the keyboard check. It runs much more smoothly. Code notes: I compile this code with Borland Turbo Assembler (TASM) 4.0 using the following commands: tasm star tlink /t star to produce star.com. Starnokb.asm may be compiled the same way. The algorithm used is very small, albeit slow. An explanation follows: -Setup Code- Some registers are assumed to be 0 on program entry (per DOS specification). First, graphics mode 13h is set by calling BIOS interrupt 10h with AH=0 (video mode set routine) and AL=13h (320x200x256). This code is unavoidable and cannot be optimized. BX is 0. Setting the high byte to a0 sets BX = A000, the segment of video memory. This is stored in ES. (This code is the same size as push 0a000h / pop es). An optional 'dec ch' will wrap ch from 00 to FFh, creating a very large number of stars. -Random Star Generator- This routine not only generates stars but also draws them on the screen. AL is loaded with a value from port 40h, the timer, for randomness. The AAA instruction converts the value in AL for specific reasons: The value from port 40h can vary widely, however, the display of stars looks ugly when there are too many random colors. In addition, with a large scroll distance/frame (associated with color), a star doesn't really appear to scroll; it appears to jerk around randomly. AAA takes care of this problem by filtering the random value from port 40h. AX (or AL, since AH = 0) is subtracted from DI providing a new location on the display for each pixel. The pixel color (AL), is stored at ES:[DI] with STOSB. LOOP GENSTAR repeats the process CX times. After the random star generation is finished, execution will procede through the loop statement. -Star Scrolling- The next section of code performs animation. First, AX is cleared. XCHG AL,ES:[DI] does two things, erases the pixel on the screen (sets it equal to AL, which is 0 after the clear) and loads the pixel value in AL. CX is incremented (set to 1) so that execution will simply pass through LOOP GENSTAR. This allows the code after SCROLL: to serve double duty as part of both the randomizing and animation routines. Again, DI is decremented, moving the pixel to the left. The pixel is replotted with STOSB. LOOP decreases the value in CX, then compares it to 0. Since we set CX to 1, it will never loop to the first routine. The keyboard-checking version sets AH to 1 and calls interrupt 16H, checking for an available keystroke. (Note that this code was NOT optimized) If there is a keystroke (based on Zero flag), the byte at hidden_ret + 1 is executed. This is a RET instruction encoded by MOV ES,AX (a small optimization). The scrolling routine essentially reads a pixel, erases it, replots it at a position to the left equal to its color value. STOSB, used to plot, also increments DI. The pixel one unit to the right of the newly displaced pixel is read. Its value is 0 if blank. 0 loaded to AL, erased on the screen (set to 0 again), subtracted from DI and stored again. When a 0 is encountered, it passes through the engine as any other pixel, however, the only net result is the incrementation of DI. In this manner, the algorithm goes through video memory searching for pixels. When a pixel goes off the left side of the screen, it reappears on the right side one column above. Subtracting a value from DI, after all, will never produce a value outside the 64k area allocated to video memory. Normally, it will just move the pixel left. In this case it wraps around the side. Similarly, when a pixel scrolls off the first line, it will reappear near the end of video memory. Since 2^16 = 65536 and 320*200 = 64000, there are 1536 bytes of buffer that are not displayed at the end of the screen. The star moves along in this hidden area for a bit before becoming visible around DI=64000. To my knowledge, there are no more optimizations that can be performed without sacrificing quality. The SBB instructions are interchangeable for SUB. SBB just looks cooler :) When a star passes a slower one, an interesting effect occurs: a star will appear to leap. The animation routine traces through video memory from the point of the last star write. A fast star will be relocated behind a slower star that has already been processed in the iteration. The slower star will be processed again when the routine traces through memory to it. The slower star effectively moves twice as far as it normally would. I leave it as an exercise for the reader to explain this effect in astrophysical terms :) Stars disappear after a while. Disappearing occurs when a star jumps on top of another one. Since the only information about a star is itself (the pixel's color), overwriting this value deletes the star entirely. Modifications: One day, BigCheese of #coders (Adam Letts) came to me and said he had lopped off another byte from my program. The xchg instruction used to erase the pixel was his idea. Coupled with the support code (xor ax,ax) it was a byte smaller than my original entry (27 bytes opposed to 28). I had previously thought that there was no more optimization possible on the code. How wrong an assumption that was :) Vowing that it could be made smaller, we both shrunk the code an additional 3 bytes to its current 24 bytes (working independently of each other). It is possible to reduce it even further (see code comments) but that involves sacrifices in quality. Adam suggested the substitution of 'in al,40h' with 'inc ax.' This saves a byte but the star positioning is no longer random. He also suggested that I try to make use of the overlapping code in the generate/draw routines (sbb di,ax/stosb) which I had previously been too lazy to do :) Critical Acclaim: Chris Hargrove, Programmer at Raven Software At some point, size optimization ceases to be optimization and becomes compression. :) ThaDragon, #coders channel os\2: fuck 3d starfields can prolly be made smaller than that ;} Pascal of Cubic Team, CubicPlayer guy strange. very strange. your program is too strange.. Moopy, #coders channel could you sent it to lewpy Lewpy, #coders channel Stumpy Oleg McNoleg BigCheese, #coders channel os2man: it's crap, but hey :) os2man: Why don't you follow the standard and call it tinystar.com or something? :) About me (blab): My name is Matt Wilhelm. I am an 18 year old student about to enter freshman year at the California Institute of Technology (CIT, Caltech). My interests include computer graphics, algorithm optimizations, Intel assembly code tweaking, and structured/OOP programming in C++. My current project is a graphics engine for Microsoft DirectX (c) (TM) (whatever) that features realtime lossless image decompression, color conversion between various hi/trucolor formats, dynamic memory management (NOT as in Windows swapping), and many other useful features. I may or may not finish and release this C++/ASM library depending on how much programming time I have once school begins. I have also become interested in non-polygon 3D methods including Splines, NURBS, and fast raytracing. I may work on modeling worlds with mechanical and visual correctness. Until 9/20/96, I may be mailed at: FDWilhelm@worldnet.att.net _PLEASE_DO_NOT_ use this address after that date. I will start Caltech the following day and have a nice, fast ethernet connection. I do not know what my e-mail address will be. I am often in the IRC #coders channel on the European side of EFNet. To connect to this network from inside the US, try the server irc-2.stealth.net(:6667). My IRC nick is os\2man.