bits 16 cpu 486 %define base 0x7C00 %define num_mat_elem 20 %define run_secs 60 %define introdelay 0 %define scr_width 640 %define scr_height 480 %define scr_size (scr_width * scr_height) %define vga_font_seg 0xF7A0 %define vga_font_off 0x806E %define vga_font_len 96 %define vga_font_size (vga_font_len * 64) %define custom_base vga_font_len %define custom_font_buf (vga_font + vga_font_size) %define custom_font_len ((customfontlen * 8) / 36) %define custom_font_size (custom_font_len * 64) %define temp_font_loc (customfontlen * -8) %define seg(x) ((x - $$ + base) >> 4) %define addr(x) ((x - $$) - ((dstart - $$) & ~15)) %define glyphseg 0x2000 %define backbuffer_seg 0x4000 section .text org base init: push seg(dstart) pop ss ; ss = seg(dstart) xor sp, sp ; sp = 0000 mov ax, 0x4F02 ; ax = 4F02 mov bx, 0x0100 ; bx = 0100 int 0x10 ; Enter 640x400x256 mov ax, 0x4F01 ; ax = 4F01 mov cx, bx ; cx = 0100 push ss pop es ; es = seg(dstart) mov di, addr(vesamodeblk) ; es:di = vesamodeblk int 0x10 ; Get mode info cli ; IF = 0 cld ; DF = 0 mov cx, 11 ; cx = 000B .zero_regs: push 0 ; *--sp = 0 loop .zero_regs ; cx = 0000 popa ; Current state: ; ax = 0000 ; bx = 8000 ; cx = 0000 ; dx = 0000 ; si = 0000 ; di = 0000 ; bp = 0000 ; sp = FFFA ; cs = ???? ; ds = ???? ; es = 7000 ; ss = data_seg ; CF = 0 ; OF = 1 ; ZF = 0 ; SF = 1 ; Zero out backbuffer mov bh, backbuffer_seg >> 8 ; bx = backbuffer_seg .backbuffer_zero: mov es, bx ; es = backbuffer mov ch, 0x80 ; cx = 8000 rep stosw ; cx = 0000 add bh, 0x10 ; es += 0x1000 jns .backbuffer_zero ; bx = 8000 bsf dx, [bp+addr(vesamodeblk)+4] ; dx = log2(blk_kb) neg dx ; dx = -log2(blk_kb) add [cs:bx+.page_adj+2-0x8000], dx ; Adjust shift count ; Current state: ; ax = 0000 ; bx = 8000 ; cx = 0000 ; dx = ???? ; si = 0000 ; di = 0000 ; bp = 0000 ; sp = FFFA ; cs = ???? ; ds = ???? ; es = 7000 ; ss = seg(dstart) ; CF = 0 ; OF = 1 ; ZF = 0 ; SF = 1 ; First 16 entries = solid white block mov al, 0xFF ; ax = ??7F mov ch, 4 ; cx = 0400 push glyphseg pop es ; es = glyphseg rep stosb ; cx = 0000 ; di = 0400 ; Current state: ; ax = 007F ; bx = 8000 ; cx = 0000 ; dx = ???? ; si = 0000 ; di = 0400 ; bp = 0000 ; sp = FFFA ; cs = ???? ; ds = ???? ; es = 7000 ; ss = seg(dstart) ; CF = 0 ; OF = 1 ; ZF = 0 ; SF = 1 ; Unpack custom font mov ch, custom_font_size/256 ; cx = custom_font_size .unpack_custom_font: mov al, 0x3F ; ax = 63 and ax, di ; ax = di & 63 bt [bp+addr(borderdata)], ax ; CF = load next char? jnc .skip_load bt [bp+addr(customfont)], si ; CF = next bit inc si ; si++ .skip_load: salc stosb loop .unpack_custom_font ; cx = 0000 ; Current state: ; ax = 0000 ; bx = 8000 ; cx = 0000 ; dx = ???? ; si = custom_font_len*36 ; di = 0800 ; bp = 0000 ; sp = FFFA ; cs = ???? ; ds = ???? ; es = 7000 ; ss = seg(dstart) ; CF = 0 ; OF = ? ; ZF = ? ; SF = ? ; Copy lower 128 VGA font chars -> 8x8 table mov ch, ((vga_font_size + 255) / 256) ; cx = vga_font_size + slop push vga_font_seg pop ds ; ds = vga_font_seg .vga_font_loop: mov ax, di ; ax = di xor al, 7 ; ax = di ^ 7 bt [bx+vga_font_off-0x8000], ax ; CF = next bit salc ; al = next pixel (0 or 255) stosb ; *di++ = al loop .vga_font_loop ; cx = 0000 ; Current state: ; ax = 1F?? ; bx = 8000 ; cx = 0000 ; dx = ???? ; si = custom_font_len*36 ; di = 2000 ; bp = 0000 ; sp = FFFA ; cs = ???? ; ds = vga_font_seg ; es = 7000 ; ss = seg(dstart) ; CF = ? ; OF = ? ; ZF = ? ; SF = ? ; Set up palette mov dx, 0x03C8 ; dx = 03C8 pop ax ; ax = 0000 out dx, al ; index = 0 inc dx ; dx = 03C9 .palette_loop: ; ax = red/blue ; cx = green out dx, al xchg ax, cx ; ax = green ; cx = red/blue out dx, al xchg ax, cx ; ax = red/blue ; cx = green out dx, al out dx, al xchg ax, cx ; ax = green ; cx = red/blue out dx, al xchg ax, cx ; ax = red/blue ; cx = green out dx, al .ctr: inc cx ; ax = 003F add bl, 2 jz .done_palette jno .palette_loop dec byte [cs:bp+.ctr] dec cx ; cx = 003F jmp .palette_loop .done_palette: ; Current state: ; ax = 003F ; bx = 8000 ; cx = 003F ; dx = 03C9 ; si = custom_font_len*36 ; di = 2000 ; bp = 0000 ; sp = FFFC ; cs = ???? ; ds = vga_font_seg ; es = 7000 ; ss = seg(dstart) ; CF = 1 ; OF = 0 ; ZF = 1 ; SF = 0 mov fs, dx ; rand_seed = 03C9 mov bx, render_intro ; bx = render_intro pop cx ; cx = 0000 ; Current state: ; ax = 003F ; bx = render_intro ; cx = 0000 ; dx = 03C9 ; si = custom_font_len*36 ; di = 2000 ; bp = 0000 ; sp = FFFE ; cs = ???? ; ds = vga_font_seg ; es = 7000 ; ss = seg(dstart) ; CF = 1 ; OF = 0 ; ZF = 1 ; SF = 0 .renderloop: ; Current state: ; ax = 003F ; bx = render_intro ; cx = 003F ; dx = 03C9 ; si = custom_font_len*36 ; di = 2000 ; bp = 0000 ; sp = FFFE ; cs = ???? ; ds = vga_font_seg ; es = 7000 ; ss = seg(dstart) ; CF = ? ; OF = ? ; ZF = ? ; SF = ? ; Wait for vsync mov dx, 0x03DA ; dx = 03DA .wait1: in al, dx test al, 8 jz .wait1 .wait2: in al, dx test al, 8 jnz .wait2 mov ax, backbuffer_seg ; ax = backbuffer_seg push 0xA000 pop es ; es = A000 xor dx, dx ; dx = 0000 xor si, si ; si = 0000 xor di, di ; di = 0000 ; Current state: ; ax = backbuffer_seg ; bx = render_func ; cx = 0000 ; dx = 0000 ; si = 0000 ; di = 0000 ; bp = 0000 ; sp = FFFE ; cs = ???? ; ds = ???? ; es = A000 ; ss = seg(dstart) ; CF = 0 ; OF = 0 ; ZF = 1 ; SF = 0 .backbuffer_copy: pusha mov ax, 0x4F05 ; ax = 4F05 xor bx, bx .page_adj: shl dx, 6 int 0x10 popa mov ds, ax ; ds = backbuffer_seg + window mov ch, 0x80 ; cx = 8000 rep movsw ; cx = 0000 inc dx add ah, 0x10 jns .backbuffer_copy ; ax = 8000 ; Current state: ; ax = 8000 ; bx = render_func ; cx = 0000 ; dx = 0004 ; si = 0000 ; di = 0000 ; bp = 0000 ; sp = FFFE ; cs = ???? ; ds = 7000 ; es = A000 ; ss = seg(dstart) ; CF = ? ; OF = ? ; ZF = ? ; SF = ? pop ax add dx, ax jz .exit push dx call bx in al, 0x64 shr al, 1 ; CF = data ready jnc .renderloop .exit: jmp 0xFFFF:0x0000 ; Input: ; ss:si = pointer to end of elem ; bp = 0000 ; ; Output: ; ax = ???? ; fl = ???? gen_matdata_elem: call rand and ax, 0x3FFF mov [bp+si-4], ax call rand and ax, 0x0101 mov [bp+si-2], ax ret ; Input: ; None ; ; Output: ; ax = random number ; fs = rand_seed ; fl = ???? rand: mov ax, fs imul ax, 13 xchg ah, al inc ax mov fs, ax ret ; Input: ; ax = tick ; cx = 0000 ; si = 0000 ; di = 0000 ; bp = 0000 ; ss = seg(dstart) ; ; Output: ; ax = ???? ; dx = 8000 ; si = ???? ; di = ???? ; fl = ???? render_main: ; Fade current screen mov dx, backbuffer_seg .fade: mov es, dx .inner_fade: es lodsb sub al, 4 sbb ah, ah not ah and al, ah stosb loop .inner_fade add dh, 0x10 jns .fade ; Mat data elem: ; [00] = (Y*320)+X ; [02] = ticks left on cur char ; [03] = initial mov cl, num_mat_elem .matloop: ; Load the destination pointer ss lodsw xchg ax, di ; Check to see if it's our time to fall dec byte [bp+si] ss lodsw jns .do_nothing mov [bp+si-2], ah add byte [bp+si-3], scr_width*8/256/4 jnc .ok call gen_matdata_elem .ok: call rand mov ah, 3 and al, 0x0F or al, 0x10 call blit .do_nothing: loop .matloop ; cx = 0000 ret ; Input: ; cx = 0000 ; si = 0000 ; bp = 0000 ; ss = seg(dstart) ; ; Output: ; ax = 0000 ; bx = render_main ; si = num_mat_elem*4 ; fl = ???? switch_render: mov cl, num_mat_elem .random_loop: add si, 4 call gen_matdata_elem loop .random_loop ; cx = 0000 ; Switch to blend mode mov word [bp+addr(blit.accumulate)], 0x050A ; Launch next stage mov bx, render_main ; bx = render_main ret ; Input: ; ax = tick ; cx = 0000 ; si = 0000 ; di = 0000 ; bp = 0000 ; ss = seg(dstart) ; ; Output: ; ax = 0000 ; si = ???? ; di = ???? ; fl = ???? render_intro: shr ax, 4 cmp al, introtextlen + introdelay jae switch_render cmp al, introtextlen jae .skip_frame imul di, ax, 2 add di, ((scr_width-(introtextlen*8))/2)/4 xchg ax, si mov al, [bp+si+addr(introtext)] call blit add di, 2 ; di += 0002 salc ; al = 00 call blit .skip_frame: ret dstart EQU $ customfont: db 0xAA db 0x0A db 0x82 db 0xB0 db 0x37 db 0x0C db 0xFF db 0x3F db 0x0C db 0x10 db 0x46 db 0x79 db 0x90 db 0x47 db 0xF8 db 0x06 db 0xC3 db 0x68 db 0x88 db 0x8F db 0x70 db 0x08 db 0x41 db 0xFD db 0x92 db 0xC0 db 0x60 db 0x1C db 0x45 db 0x91 db 0x22 db 0xF0 db 0xE0 db 0x88 db 0x87 db 0xFC db 0x30 db 0x62 db 0x32 db 0x30 db 0xC0 db 0x21 db 0xBE db 0x08 db 0x73 db 0x06 db 0x60 db 0x80 db 0xA0 db 0x07 db 0xFC db 0x80 db 0x07 db 0xFC db 0x3E db 0x08 db 0x82 db 0xA0 db 0x2F db 0xFC db 0x92 db 0x23 db 0x7C db 0x3E db 0xE2 db 0x91 db 0x04 db 0xE6 db 0x01 db 0x1E db 0x04 db 0x39 introtext: db "What is #asm?" introtextlen equ $-introtext customfontlen equ $-customfont borderdata: db 0x00 db 0x7E db 0x7E db 0x7E db 0x7E db 0x7E db 0x7E db 0x00 ; Input: ; al = src_char ; di = ((x * 640) + y) / 4 ; ; Output: ; ds = ???? ; es = ???? ; fl = ???? blit: pusha push glyphseg pop ds ; ds = glyphseg cbw ; ax = al imul si, ax, 64 ; si = src_ptr push di shr di, 2 add di, backbuffer_seg mov es, di pop di and di, 3 shl di, 2 mov cl, 8 ; cl = width .scanline: mov ch, 8 ; ch = height .addloop: lodsb es .accumulate: nop nop stosb ; dest[y][x] |= src[y][x] dec ch ; ch = ch - 1 jnz .addloop ; ch = 0 add di, scr_width - 8 ; di = dest + dest_stride loop .scanline popa ret vesamodeblk: times 510-($-$$) db 0 dw 0xAA55