Squirmer by Tonik

; This source code is Copyright (C) 1999 by Gergely Kutenich (gk@scene.hu).
; This is the source code of the 256 bytes intro "Squirmer".
; It compiles with NASM (freeware; http://www.cryogen.com/Nasm).

SPOTNUM equ 7200

; variable pointers
%define WLEN si-12
%define IDD si-10
%define ISY si-8
%define WSZ si-6
%define WDZ si-4
%define ACTFRAME si-2
%define IDRAW si                        ; the most often used is SI
%define ITEMP si+2

bits 16
org 0x100


  mov si,var

  ; set graphics mode
  mov al,0x13
  int 0x10

  ; set palette
  mov dx,0x3C8
  out dx,al
  inc dx
    push ax
    shr al,2
    out dx,al
    xor ax,ax
    out dx,al
    out dx,al
    pop ax
    inc al
  jnz .pal


  ; draw object
  mov word[IDRAW],SPOTNUM

      ; calculate coordinates
      fldz                              ; y

      fild word[IDRAW]
      fidiv word[ISY]
      faddp st1
      fimul word[WLEN]                  ; z y

      fldz                              ; x z y

      fimul word[IDRAW]
      fidiv word[IDD]
      call rot2d                        ; rotate along y axis

      fild word[IDRAW]
      fidiv word[ISY]
      call rot2d                        ; rotate along x axis

      ; create oval shape
      fldl2e                            ; any fine constant will do
      fmulp st1

      ; rotate
      mov cx,3
        fild word[IDRAW]
        fidiv word[IDD]
        fild word[ACTFRAME]
        fidiv word[ISY]
        fmulp st1
        fild word[ACTFRAME]
        fimul word[ISY]
        fidiv word[WDZ]
        faddp st1
        call rot2d
      loop .rotate

      ; get z coordinate for color & z-buffer
      fist word[ITEMP]
      mov al,128
      sub al,[ITEMP]

      ; perform perspective transformation
      fiadd word[WDZ]
      fidivr word[WSZ]                  ; 1/z y x
      fmul st1,st0                      ; 1/z y/z x
      fmulp st2,st0                     ; y/z x/z
      fistp word[ITEMP]                 ; 1/z x
      mov di,[ITEMP]
      add di,100
      fistp word[ITEMP]
      mov bx,[ITEMP]
      add bx,buffer+160-20
      imul di,320
      add di,bx

      ; draw spot
      mov cl,SPOTSIZE
        mov ch,SPOTSIZE
          cmp al,[di]
          jbe .skippixel
          dec di
          inc di
          dec ch
        jnz .spotx
        add di,320-SPOTSIZE
      loop .spoty

    dec word[IDRAW]
  jnz near .draw

  ; copy buffer to video memory
  push word 0xA000
  pop ES
  mov di,buffer
  mov cx,320*196
    mov ax,di
    add al,ch
    and al,0x20
    shr al,5
    adc al,1
    xchg al,[di]
  loop .copy
  push DS
  pop ES

  inc word[ACTFRAME]

  ; repeat core loop until ESC is pressed
  in al,0x60
  dec ax
jnz near core

  ; set text mode and exit to the OS
  mov al,3
  int 0x10

; rot2d - rotate a 3d point around one axis with the specified angle
; input                 output  (through FPU stack)
; yAngle x z y          y z x
; xAngle z y x          x z y
; zAngle y x z          z y x
; comments are for y axis
; x= x*cos(ya) - z*sin(ya);
; z= z*cos(ya) + x*sin(ya);
                                ; angle x z y
  fsincos                       ; cos sin x z y
  fld st2                       ; x cos sin x z y
  fmul st1                      ; x*cos cos sin x z y
  fld st4                       ; z x*cos cos sin x z y
  fmul st3                      ; z*sin x*cos cos sin x z y
  fsubp st1                     ; x*cos-z*sin cos sin x z y

  fxch st4                      ; z cos sin x x*cos-z*sin y
  fmulp st1                     ; z*cos sin x x*cos-z*sin y
  fxch st2                      ; x sin z*cos x*cos-z*sin y
  fmulp st1                     ; x*sin z*cos x*cos-z*sin y
  faddp st1                     ; x*sin+z*cos x*cos-z*sin y

  fxch st2                      ; y z_r x_r

; constants and variables
wLen dw 82
idd dw SPOTNUM
isy dw 12
wsz dw 256
wdz dw 400
actframe equ (wdz+2)
idraw equ (wdz+4)
itemp equ (wdz+6)
var equ (wdz+4)

; screen buffer. 640 bytes are enough for the code
buffer equ (320*2)