a3f2d39ea2efc34d2c2d8f328bad797a814bb3d9
[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: ax, cx, di
10 ; swap_buffers
11 ;    copies the framebuffer to video memory
12 ;    clobbers: ax, cx, di, si
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
18 VIDMEM_SEG      equ 0a000h
19 FRAMEBUF_SEG    equ 09000h
20
21 REG_CRTC_STATUS equ 3dah
22 CRTC_VBLANK_BIT equ 08h
23
24 REG_DAC_ADDR    equ 3c8h
25 REG_DAC_DATA    equ 3c9h
26
27 init_gfx:
28         ; video mode 13h (320x200 8bpp)
29         mov ax, 13h
30         int 10h
31         call clear
32
33         ; setup the spritesheet palette
34         mov si, sprsheet_cmap
35         xor cl, cl
36 .cmaploop:
37         mov al, cl
38         mov ah, [si]
39         mov bl, [si + 1]
40         mov bh, [si + 2]
41         add si, 3
42         call set_palette_entry
43         dec cl
44         jnz .cmaploop
45         
46         ret
47
48 clear:
49         push es
50         mov ax, FRAMEBUF_SEG
51         mov es, ax
52         xor di, di
53         xor ax, ax
54         mov cx, 16000
55         rep stosd
56         pop es
57         ret
58
59 swap_buffers:
60         push ds
61         push es
62         mov ax, FRAMEBUF_SEG
63         mov ds, ax
64         xor si, si
65         mov ax, VIDMEM_SEG
66         mov es, ax
67         xor di, di
68         mov cx, 16000
69         rep movsd
70         pop es
71         pop ds
72         ret
73
74 wait_vsync:
75         mov dx, REG_CRTC_STATUS
76 .wait_vblank_end:
77         in al, dx
78         and al, CRTC_VBLANK_BIT
79         jnz .wait_vblank_end
80 .wait_vblank_start:
81         in al, dx
82         and al, CRTC_VBLANK_BIT
83         jz .wait_vblank_start
84         ret
85
86 set_palette_entry:
87         push dx
88         mov dx, REG_DAC_ADDR
89         out dx, al
90         inc dx  ; dx <- REG_DAC_DATA
91         mov al, ah
92         shr al, 2
93         out dx, al
94         mov al, bl
95         shr al, 2
96         out dx, al
97         mov al, bh
98         shr al, 2
99         out dx, al
100         pop dx
101         ret
102
103         ; slow_sprite(short id, short x, short y)
104         ; assumptions: 32x32, one after the other, 0 is transparent
105         ; XXX sprsheet needs to go to its own segment
106 slow_sprite:
107         push bp
108         mov bp, sp
109         pusha
110
111         mov ax, FRAMEBUF_SEG
112         mov es, ax
113         mov ax, [bp + 8]        ; ax <- y
114         sub ax, 16              ; ax <- y - 16 (center sprite vertically)
115         mov bx, ax
116         shl ax, 8
117         shl bx, 6
118         add ax, bx              ; ax <- (y - 16) * 320
119         mov di, [bp + 6]        ; di <- x
120         sub di, 16              ; di <- x - 16 (center sprite horizontally)
121         add di, ax              ; di <- (y - 16) * 320 + (x - 16)
122
123         mov si, sprsheet_tiles
124         ; calculate sprite id offset (each spr is 32*32=1k)
125         mov ax, [bp + 4]
126         shl ax, 10
127         add si, ax
128
129         mov cx, 32
130 .yloop:
131         xor bx, bx
132 .xloop:
133         mov al, [si]
134         cmp al, 0
135         ;jz .skip_pixel
136         mov [es:di + bx], al
137 .skip_pixel:
138         inc si
139         inc bx
140         cmp bx, 32
141         jnz .xloop
142
143         add di, 320
144         dec cx
145         jnz .yloop
146
147         popa
148         pop bp
149         ret