Connect with us

3D animation with sound in 64 bytes of assembler

Viral News

3D animation with sound in 64 bytes of assembler

As far as I can tell, something like this is going on:This whole things assumes certain fixed values of registers upon program entry. Targetting MS-DOS, this is rather reasonable. The registers we need to concern ourselves with are:AX = 0 CX = 0xff SI = 0x100 DI = 0xfffe BP = 0x091c DS = CS…

3D animation with sound in 64 bytes of assembler

As far as I’m able to repeat, something be pleased here is going on:

This complete things assumes positive mounted values of registers upon program entry. Targetting MS-DOS, here is rather cheap. The registers we want to verbalize ourselves with are:

AX = 0
CX = 0xff
SI = 0x100
DI = 0xfffe
BP = 0x091c
DS = CS = ES

BP is a itsy-bitsy bit extra variable than the others, nonetheless now not by noteworthy.

adc al, 0x13
mov dx, 0x330
get outsb

OUTSB will output the worth of whatever is at reputation DS: [SI] to the port whose number is in DX and then increment SI. The REP prefix will enact this CX cases, decrementing CX at any time when. SI begins off pointing before all the pieces attach apart of our code, which formula that 255 bytes of stuff is readily shoved into port 0x330, beginning with the 64 byte binary itself. Port 0x330 is a MIDI port for Sound Blaster 16, nonetheless I’m roughly uncertain as to why it accepts this barrage of knowledge, or how it turns into the song/helicopter smatter. Both formula, here is the solely reputation within the code that offers with sound, so that is the “song” fragment handled.

    int 0x10
    mov ax, 0xc4f
    out 0x40, al
    loop clrscr

Having spot AL to 0x13 above, the determination to interrupt 0x10 gadgets the correct conceal mode in the beginning of the first iteration of the loop. Surroundings AX to 0x0c4f is for the next iterations, and might maybe maybe maybe make the next interrupt 0x10 utilize feature 0x0c to intention a pixel of color AL to coordinates (CX, DX). One might maybe maybe maybe additionally purchase that since DX by no formula changes, this is able to solely intention pixels on one row of the conceal. My guess is that the BIOS routine proper variety writes to address DX * hres + CX, without be pleased overflow.

You might maybe maybe per chance maybe additionally surprise how this loop will loop the least bit, what with CX being zero from the old section. The secret’s that the LOOP decrements CX and then assessments whether it’s far 0. The first decrement will thus spot off an underflow to 0xffff, making the loop stagger round 65 536 cases. This would per chance maybe additionally definite the conceal.

What’s extra, we additionally output AL (0x4f) to port 0x40. That is a port for setting the timer divisor for the Programmable Interval Timer chip. To identify that impress, you send first the low and excessive bytes of a 16-bit impress to the port. Since we are spamming that port with the identical impress, the divisor shall be spot to 0x4f4f (20 303). The timer in demand makes utilize of this impress to study how in overall this might maybe occasionally per chance fireplace an interrupt 0x8, thru the ravishing formula 1 193 182 / 20 303 ~= 58.77 Hz (in overall 18.2 Hz). Interrupt 0x8, in turn, increments a counter at address 0040: 006c, thereby retaining a tally on how many such ticks devour occured since heart of the evening (?).

This would per chance maybe additionally be crucial for the animation.

pop ds

Upon entry to a .COM file, a single zero note is pushed to stack, which formula this might maybe occasionally per chance spot DS to 0.

push note 0xa500
pop es

Video memory for mode 0x13 begins at memory address a000: 0000. Thru the magic joy of segmented memory, setting ES to a impress 0x500 (1 280) bigger formula that we are 1 280 * 16 bytes additional along into video memory. Mode 0x13 has a determination of 320×200 so that formula ES will demonstrate the first pixel on row 64. As good a reputation as any for a horizon.

    mov ax, 0xcccd
    mul di          ; DX:AX = AX * DI = 0xcccd * DI

Any 16-bit multiplication on an x86 will effect a 32-bit result, which is saved in DX:AX (excessive note in DX, low note in AX). This particular multiplication will automagically set apart the Y coordinate (relative to the horizon) in DH and the X (rescaled to a host 0..255) coordinate in DL.

mov ax, bp
sub dh, 0xf6
div dh

BP begins with 0x091c (in DOSBox now not lower than, and shut ample on many versions of DOS), which makes the above equivalent to:

AX = 2 332 / (y + 10)

AX will now grasp some fashion of scale, having lower values the additional in the direction of the backside of the conceal we are.

xchg ax, dx         ; swap (coordinates, scale)
sub al, 0x7f        ; Centers x coordinate round 0
imul dl             ; Multiply coordinates by scale

Swaps AX and DX (or scale and coordinates). Subtracting 0x7f from the X coordinate to make it centered round zero, then multiply with the scale. To be proper variety, I’m a itsy-bitsy hazy as to how the complete scaling enterprise works, nonetheless scales it does.

add dl, [0x46c]
xor dh, al
imul dh

Here is the meat of it all. First, we add the tick counter that our reprogrammed PIT produces 58.77 per second to the scale. Why? Be awake that the scale will get smaller the additional down on the conceal we are. Adding to this impress formula we are pretending to be a itsy-bitsy bit above the attach apart we indubitably are.

The XOR? Not 100% definite, nonetheless devour a feeling it helps to effect the checkerboard sample.

Taking a glimpse forward, we spy:

; AH = AL / 9 (discarded)
; AL = AL % 9
aam 0x9


sub al, 0x74
stosb           ; [DI++] = AL

The STOSB writes a pixel with a color of AL, which became once constrained to a palette of 9 colors by AAM 0x9 nonetheless which within the slay got here from our calculations above. For the reason that color of the present pixel depends on the scale, which depends on the attach apart we are on the conceal, that formula we acquire a checkerboard sample. However the scale is a itsy-bitsy bit altered by the tick counter, or to attach apart it another formula, by time passing. Adding to the scale is which capacity truth the identical as going a itsy-bitsy bit into the past. This form that if some small interval of time has handed, we are drawing the brand new pixel with a color that, adding the tick counter, comes from a itsy-bitsy bit above it within the checkerboard. This creates the form of colors flowing downwards (in the direction of us).

The percentual difference between scale and time-adjusted scale will enhance with Y, since the lower the scale, the bigger impression any preference of ticks will devour. This stretches things top-wise, producing point of view.

Ticks are noteworthy extra likely to occur right thru a conceal refresh, making that line and any subsequent one of that physique a itsy-bitsy wonky, nonetheless with a refresh rate of terminate to 60 fps, we’re now not going to ogle it.

jmp mainloop

SCASW does literally nothing nonetheless approach DI by 2. No opinion why. Some interleaving intention?

cmp [bx + di + 0x6746], bl
push cx
db 0x7f

This looks be pleased padding. Is by no formula executed. Is shovelled to the MIDI port, so per chance essential there?

There are things I’m uncertain of, comparable to the explicit nature of the sample producing, and the seemingly useless PUSHFW / POPFW pair within the important thing loop (those might maybe maybe maybe additionally be for timing purposes… maaaybe). I even devour absolute confidence additionally devour misunderstood some parts of the code, nonetheless I feel here is the basic gist of it, now not lower than.

Subscribe to the newsletter news

We hate SPAM and promise to keep your email address safe

Click to comment

Leave a Reply

Your email address will not be published. Required fields are marked *

What’s Hot

To Top