at last sprites "work"
[ld45_start_nothing] / src / gfx.asm
1 ; vi:filetype=nasm ts=8 sts=8 sw=8:
2 ;
3 ; list of functions
4 ; -----------------
5 ; init_gfx
6 ;    initializes the video hardware and graphics routines
7 ; clear
8 ;    clears the framebuffer (not vmem)
9 ;    clobbers: eax, ecx, edi
10 ; swap_buffers
11 ;    copies the framebuffer to video memory
12 ;    clobbers: eax, ecx, edi, esi
13 ; wait_vsync
14 ;    clobbers: al, dx
15 ; set_palette_entry(idx[al], r[ah], g[bl], b[bh])
16 ;    colors are 0-255
17         bits 32
18         section .text
19
20 %define GFX_ASM_
21 %include "gfx.inc"
22
23 REG_CRTC_STATUS equ 3dah
24 CRTC_VBLANK_BIT equ 08h
25
26 REG_DAC_ADDR    equ 3c8h
27 REG_DAC_DATA    equ 3c9h
28
29         extern sprsheet
30         extern sprsheet_cmap
31
32         global init_gfx
33 init_gfx:
34         call clear
35
36         ; setup the spritesheet palette
37         mov esi, sprsheet_cmap
38         xor cl, cl
39 .cmaploop:
40         mov al, cl
41         mov ah, [esi]
42         mov bl, [esi + 1]
43         mov bh, [esi + 2]
44         add esi, 3
45         call set_palette_entry
46         inc cl
47         jnz .cmaploop
48
49         ; force color 0 to black
50         xor ax, ax
51         xor bx, bx
52         call set_palette_entry
53
54         ret
55
56         global clear
57 clear:
58         mov edi, FRAMEBUF_ADDR
59         xor eax, eax
60         mov ecx, 16000
61         rep stosd
62         ret
63
64         global swap_buffers
65 swap_buffers:
66         mov esi, FRAMEBUF_ADDR
67         mov edi, VIDMEM_ADDR
68         mov ecx, 16000
69         rep movsd
70         ret
71
72         global wait_vsync
73 wait_vsync:
74         mov dx, REG_CRTC_STATUS
75 .wait_vblank_end:
76         in al, dx
77         and al, CRTC_VBLANK_BIT
78         jnz .wait_vblank_end
79 .wait_vblank_start:
80         in al, dx
81         and al, CRTC_VBLANK_BIT
82         jz .wait_vblank_start
83         ret
84
85 set_palette_entry:
86         push dx
87         mov dx, REG_DAC_ADDR
88         out dx, al
89         inc dx  ; dx <- REG_DAC_DATA
90         mov al, ah
91         shr al, 2
92         out dx, al
93         mov al, bl
94         shr al, 2
95         out dx, al
96         mov al, bh
97         shr al, 2
98         out dx, al
99         pop dx
100         ret
101
102         ; slow_sprite(int id, int x, int y)
103         ; assumptions: 32x32, one after the other, 0 is transparent
104         global slow_sprite
105 slow_sprite:
106         push ebp
107         mov ebp, esp
108         pusha
109
110         mov eax, [ebp + 16]     ; ax <- y
111         sub eax, 16             ; ax <- y - 16 (center sprite vertically)
112         mov ebx, eax
113         shl eax, 8
114         shl ebx, 6
115         add eax, ebx            ; ax <- (y - 16) * 320
116         mov edi, [ebp + 12]     ; di <- x
117         sub edi, 16             ; di <- x - 16 (center sprite horizontally)
118         add edi, eax            ; di <- (y - 16) * 320 + (x - 16)
119         add edi, FRAMEBUF_ADDR
120
121         mov esi, sprsheet
122         ; calculate sprite id offset (each spr is 32*32=1k)
123         mov eax, [ebp + 8]
124         shl eax, 10
125         add esi, eax
126
127         mov ecx, 32
128 .yloop:
129         xor ebx, ebx
130 .xloop:
131         mov al, [esi]
132         cmp al, 0
133         ;jz .skip_pixel
134         mov [edi + ebx], al
135 .skip_pixel:
136         inc esi
137         inc ebx
138         cmp ebx, 32
139         jnz .xloop
140
141         add edi, 320
142         dec ecx
143         jnz .yloop
144
145         popa
146         pop ebp
147         ret