Essence by Hellmood
As you might have guessed, real path tracing and lighting is (yet) impossible in 64 bytes of assembler ;) but still, it's at least possible to generate the impression of both.
; "Essence" - by HellMood/DESiRE - 5th October 2019 ; 64 bytes msdos intro, showing animated raycasted objects ; with fake pathtracing and fake lighting while playing ; ambient MIDI sound, which is coded for DosBox 0.74. ; On a real MsDos or FreeDos, the demo will work ; but no sound will be played unless a MIDI capable ; soundcard is present. On Dosbox, a custom configuration ; is needed, to provide sufficient emulation power and ; enable the MIDI UART mode, which saves a few bytes. ; -------------------------------------------------------------- ; released at https://deadline.untergrund.net/2019/ ; published at https://www.pouet.net/prod.php?which=83204 ; see also : http://www.sizecoding.org/wiki/Main_Page ; assemble with "nasm.exe" <this> -fbin -o <this>.com ; -------------------------------------------------------------- ; Set ES to the screen, to perform the "Rrrola Trick", see ; http://www.sizecoding.org/wiki/General_Coding_Tricks push 0x9FF6 pop es ; Set mode to 0x13, +0x80 means not deleting the screen content ; that is 320x200 pixels in 256 colors mov al,93h int 10h ; Setting port to MIDI data port, assuming it is in UART mode ; 0x3F has to be sent to 0x331 first, if UART mode is not on. mov dx,0x330 ; Effectively outputting all the code to the MIDI data port. ; CX=255 at start, DS=CS, SI=0x100, see MIDI section below. rep outsb ; Setting DS to zero, top stack normally contains the return ; adress. DS is needed to be 0 to access a timer later on. pop ds ; CL is the iteration count for a ray, CH is 0 all the time. ; The value is chosen to generate a blue background texture. ; Chosing 64 instead would lead to a totally black background X: mov cl,63 ; BL is the current depth of a ray, we start with minus(!) 64. ; We cast rays in negative direction to calculate the point ; in 3D and the texture color at the same time. if a ray hits ; an object from this side, the object function has a reasonable ; texture value, from the other side it would be always black. ; CL, BL are decoupled because decrementing -128 leads to 127 ; and since we are using signed multiplication for keeping things ; centered, that would result in very buggy and ugly behaviour. ; They are also decoupled because of visual beauty: because of ; the usage of signed 8 bit coordinates, objects close to the ; projection center are way too coarse and move way too fast. mov bl,-64 ; At this point, AL contains the color of the previous pixel. ; By design of the object formula, the last 4 bits contain the ; texture value while the 5th bit is always set, which maps it ; to the 16 color gray scale subtable of the VGA default ; colors. Other bits may be set, too, so they are masked. ; https://www.fountainware.com/EXPL/vga_color_palettes.htm ; Simultaneously, the object function, in combination with the ; palette subset, creates the impression of lighting from the ; front top left. The right, bottom and back side appears to ; be black. Changing the object formula will result in ; changing the texture, visibility and lighting as well. and al,31 ; Outputting the pixel on the screen and increment pointer stosb ; Instead of going pixel by pixel, the following jumps ; Pseudorandomly across the screen, this smoothes the ; animation a lot and looks a bit like pathtracing. imul di,byte 117 ; The inner loop for each ray, decrementing BX means ; advancing the ray in negative direction by 1 L: dec bx ; Assign the Rrrola constant to register AX mov ax,0xcccd ; Place the signed coordinates X and Y into DL and DH mul di ; Centering for X is implicitly done by offsetting the segment ; Centering Y has to be done "manually". any value can be used ; as long as it doesn't show the signed overflow on screen. mov al,dh sbb al,73 ; Multiply AL=Y by the current distance, to get a projection(1) imul bl ; Get X into AL, while saving the result in DX (DH) xchg ax,dx ; Multiply AL=X by the current distance, to get a projection(2) imul bl ; Considering an implicit division by 256, the projected ; coordinates now reside in DH and AH, while the depth is in BL. ; the following sequence calculates whether the current 3D ; position belongs to an object. Objects are normal cubes ; defined by f(X,Y,Z) = (X & Y & Z & 16 != 0) mov al,dh ; offset X by timer, effectively producing 18.2 FPS ; http://vitaly_filatov.tripod.com/ng/asm/asm_002.29.html add ah,[0x46c] and al,ah and al,bl test al,16 ; the inner loop is done when either the iteration count has ; reached zero or the function f(X,Y,Z) is true (object hit) loopz L ; the outer loop repeats endlessly jmp short X ; MIDI Data Section, actually code above and memory below is ; sent to the MIDI data port as well, but it does not matter db 0xc0 ; set instrument on channel 0 to the next value db 89 ; instrument 89 = Pad2 of general MIDI db 0x90 ; play notes on channel 0, minor chord over 4 octaves db 28 ; note 1, very deep db 127 ; volume 1, maximum value to let the subwoofers shake db 59 ; note 2 fitting to note 1 db 80 ; volume 2, a bit reduced to not overshadow the bass db 67 ; note 3 fitting to notes 1 & 2 db 65 ; volume 3, even more reduced to fit the other notes ; # ´ # ; # greetings # ; # sensenstahl,homecoded,rrrola,frag,T$ # ; # Optimus,Trixter,igor,gentleman,VileR # ; # Whizart,g0blinish,Rudi,ryg,TomCat . # ; # orbitaldecay,wysiwtf,Kuemmel,p01,Lara # ; # Oscar Toledo,Drift,maugli,Harekiet,etc #