This is the 20-byte starfield coded by Niklas Beisert (pascal). The 20-byte starfield is based on a 24-byte version written by Matt Wilhelm. Niklas refers to Matt in the text. The original sources for both the 20-byte and the 24-byte versions are included in the archive below.
This text does not cover all optimizations done to achive the original 24-byte version. Such text is however included in the archive.
Setup Code:
Video mode init done as usual:
mov al,13h int 10hI also tried to skip the randomizing part by not cleaning the video memory. (
MOV AL,93h
). Matt did not like it. (You can do a 14 byte version with it. The only thing about it is that it does not look like a starfield anymore.SP
is popped, which makes it 0 (a RET
would make IP
point to CS:0
, where you find INT 20h
that terminates the program).CX
is popped effectively making it 20CDh
(opcode of INT 20h
), this also sets the number of stars to about 8000.POP DS
, and this is the critical part of it all. At the address SP
points to, you find the upper memory boundary, and this is usually 9FFFh (tested on many computers). If it does not, strange things may happen. The starfield algorithm will destroy MSDOS memory management (first 16 bytes in DS
), so a keyboard version that could be ended somehow is senseless. DS
is now the screen segment.Random Star Generator:
The randomizer was changed to POP AX
. Even if memory is clean at least the PSP and the program code will produce some "random" numbers. You'll get at least 50 stars with this. (pray that the program is not interruped when SP
points to the code, messing it up!) Pixels are set by exchanging the screen pixel (probably 0) with AL
(random). This saves 1 byte. (1-byte pop instead of 2-byte in)
Star Scrolling:
The algorithm was changed a bit. I only use one xchg to set/reset pixels. Usually AL
is 0. If so the screen pointer is incremented, and the current pixel is replaced by al. If that pixel was black, AL
is 0 again, and nothing happend on the screen. Black regions of the screen are thus skipped. If a nonzero pixel is encountered, it is replaced by the 0 in AL
and the screen pointer is incremented by the value of the pixel plus 1. In the next loop the current pixel (probably 0) is replaced by AL
. All in all a star is moved by some pixels. This saves 2 bytes. (es: prefix removed, 1-byte cbw instead of 2-byte xor)
about the making:
I was listening to strange discussion about starfields and 26 byte versions and stuff on #coders. I didn't really take it seriously. A starfield in 26 bytes or less is utopia. Some time Matt Wilhelm asked me something and we had a nice chat about demos and so and finally he gave me his starfield.
I was amazed.
Tried to work through the code for some hours and I finally got the point. When I went to bed some hours later than I originally planned to I was negative about further optimizations. Everything just stuck together and you couldn't change something without messing up the rest. Next morning I had the idea to rearrange the loop (after some stupid randomizing ideas) and cut 2 bytes off the program. Later I found a different randomizing method and I also found the screen segment in memory and in reach.
This 20 byte starfield would never have been possible without the 24 byte starfield by Matthew Wilhelm and Adam Letts. It'd rather be hundereds!
The 20-byte version, the 24-byte version, a 30-byte version which does allow you to exit, the original optimization text and compiled version with object files are included in the following archive (9422 bytes).;
; pascal's 20 byte version of
;
; Tiny Parallax Starfield
; by Matthew Wilhelm
;
.model tiny
.code
org 100h
start:
mov al,13h ; ah assumed to be 0. ok.
int 10h
pop sp ; com loader pushes 0, => sp == 0
pop cx ; 2 instr. bytes for int 20h => cx = 20CDh
; pop something else for less stars
pop ds ; we need the video segment 0A000h, here we
; find 9FFFh (upper memory segment limit)
; on most machines. this is not clean,
; but who cares...
lp1:
pop ax ; randomize, hope no irq occurs while
aaa ; popping code! afterwards al<10
lp2:
xchg [di],al ; clean & put star
; es prefix removed
add di,ax ; new pos for star / randomize pos in init
loop lp1 ; init loop, skipped in star moving loop
inc di ; a clean pixel must also move
; was stosb
cbw ; clear ah
; was xor ax,ax
inc cx ; to skip loop command
jmp lp2 ; star moving loop
end start