pouët.net

Grey Tunnel With No Music by Loonies [web]

; "Grey Tunnel With No Music" by Blueberry / Loonies
; For the Revision 2019 256 bytes intro compo
; My first ever DOS prod! :)

; Run on a fast (3GHz or more) CPU. Bare metal.
; Or watch this 60fps video capture:
; http://crinkler.net/GreyTunnelWithNoMusic.avi

%define SPEED 7
%define BLUETIPS 0
%define INVERSE 0
%define ITERATIONS 32

%define VSYNC 0
%define RESTORE 0
%define COPY 0
%define FRAMEDUMP 0


org 100h
section .text
start:
	; Texture
	push word 0x8000 
C_8000 equ $-2
	pop es

	; Mode 13h
	mov al, 0x13
	int 0x10

	; Init FPU
	fninit
	fild word [si] ; 104
	fldpi
	fidiv word [byte si-0x100+C_8000] ; 2pi / 0x10000
	fild word [byte si-0x100+C_001F]

	; Make texture
texture:
	fld st0 ; 31
	mov cx, si
sines:
	; See heightmap_optimize.rs for the story of this seed.
	imul ax, cx, 0x1e2f
	mov [si], ax
	and ax, 0x1f07
	add ax, 0xf000
	imul di
	add [si], ax
	fild word [si]
	fmul st3 ; 2pi / 0x10000
	fsin
	fsubp
	loop sines

	fistp word [si]
	movsb
	dec si

	cmp di, sp
	jne texture

	; Orange and teal
	; assumes cx == 0 or > 255
palette:
	push cx

	mov al, cl
	mov dx, 0x3c8
	out dx, al
	inc dx
	and al, 0xf
	shr cl, 4
C_04 equ $-1
	sub cl, al
	mul byte [byte si-0x100+C_04] ; Clears ah
channel:
	add al, cl
	out dx, al
	add ah, dl
	js channel

	pop cx
	loop palette

	; Read from texture, write to screen
	push es
	pop ds
%if COPY
	push word 0x7000-160/16
%else
	push word 0xa000-160/16
%endif
	pop es

	mov bp, sp

mainloop:
%if VSYNC
	mov dx, 0x3da ; 0x3da = VGA Input Status #1
vblank:
	in al, dx
	test al, 8
	je vblank
%endif

pixelloop:
	mov ax, 0xcccd
	mul di
	mov bx, ax
	sub dh, 100
	and ax, strict word 31 ; Ray origin offset dither
C_001F equ $-2
	pusha
	fild word [bp-7] ; dl:bh = x
	fild word [bp-6] ; dx = y
	fld st1
	fmul st2, st0
	fld st1
	fmul st0
	faddp st3, st0
	fpatan
	fdiv st3 ; 2pi / 0x10000
	fistp word [bp-8] ; bx
	fdiv st3 ; zoom factor = sqrt(104)
	fsqrt
	fild word [bp-2] ; ax
	fdiv st2 ; Ought to be 32, but 31 works well enough
	fmul st1 ; Dithered ray origin
	fisubr word [bp+2 + C_radius]
	popa
	mov bl, 0

	add ax, ITERATIONS<<5
	xchg cx, ax
rayloop:
	fadd st0, st1

	add si, cx

	call Fetch
	push ax
	call Fetch
	push ax
	pop ax

	sub si, cx

	; Height = difference between texture lookups
	fild word [bp-4]
	fisub word [bp-2]
	fcomip st0, st1
	jc hit

	pop ax
	sub cx, 32
	jg rayloop

	xchg ax, bx ; bl is still 0
	jmp pixeldone

hit:
	; Shade color by depth
	mul cx
	xchg cx, dx
	pop ax
	mul dx

	; Dither and combine color components
	imul ax, di, 0xC777
C_radius equ $-2
	and ax, 0x0f0f
%if BLUETIPS
	mov dh, cl
	add ax, dx
%else
	mov ch, dl
	add ax, cx
%endif
	shr al, 4
	rol ax, 4

pixeldone:
	fstp st0
	fstp st0

%if INVERSE
	not al
%endif
	stosb
	cmp di, sp
	jne pixelloop

%if COPY
	pusha
	push ds
	push es
	pop ds
	push word 0xa000-160/16
	pop es

	mov si, 160
	mov di, 160
	mov cx, 320*200/4
	rep movsd

	push ds
	pop es
	pop ds
	popa
%endif

%if FRAMEDUMP
	call FrameDump
%endif

	sub si, SPEED

	; ESC check
	in al, 0x60
	dec al
	jnz mainloop
%if RESTORE
	mov ax, 0x3
	int 0x10
%endif
;	ret

Fetch:
	; Use return address as texture stride
	pop ax
	push ax
	shl ax, 4
	imul si
	; Integer part of coordinate in dx, fractional part in ax.
	; Fetch from texture and do linear interpolation.
	shr ax, 1 ; Treat fraction as unsigned
	add bx, dx
	mov al, [bx+1]
	sub al, [bx]
	imul ah
	shl ax, 1 ; Shift back
	add ah, [bx]
	sub bx, dx
	ret


%if FRAMEDUMP
FrameDump:
	pusha
	push ds
	push es
	pushf
	cld

	push cs
	pop ds

	; Update filename
	mov bx, .extension
	mov cx, 4
.incloop:
	dec bx
	inc byte [bx]
	cmp byte [bx], '9'
	jle .incdone
	mov byte [bx], '0'
	loop .incloop
	; Exit after 9999 frames
	mov ax, 0x3
	int 0x10
	int 0x20
.incdone:

	; Get palette
	push cs
	pop es
	mov di, .palette

	mov dx, 0x3c8
	in al, dx
	push ax

	mov dx, 0x3c7
	mov al, 0
	out dx, al

	mov dx, 0x3c9
	mov cx, 256
.getpalette:
	xor eax, eax
	in al, dx
	shl eax, 8
	in al, dx
	shl eax, 8
	in al, dx
	shl eax, 2
	stosd
	loop .getpalette

	mov dx, 0x3c8
	pop ax
	out dx, al

	; Create File
	mov cx, 0
	mov dx, .filename
	mov ah, 0x3c
	int 0x21
	jc .done
	xchg bx, ax

	; Write header and palette
	mov dx, .header
	mov cx, 14+40+256*4
	mov ah, 0x40
	int 0x21

	; Write pixels
	push 0xa000
	pop ds
	xor dx, dx
	mov cx, 320*200
	mov ah, 0x40
	int 0x21

	; Close file
	mov ah, 0x3e
	int 0x21

.done:
	popf
	pop es
	pop ds
	popa
	ret

.filename:
	db "dump0000"
.extension:
	db ".bmp",0

.header:
	; File header
	db "BM"
	dd 14+40+256*4+320*200
	dw 0,0
	dd 14+40+256*4

	; Info header
	dd 40, 320, -200 ; Header size, width, height
	dw 1, 8 ; Planes, depth
	dd 0,0,0,0,0,0
.palette:
%endif