]> 4ch.mooo.com Git - 16.git/blob - 16/xlib/xcbitmap.asm
16_ca needs huge amounts of work and I should remember what needs to be done soon...
[16.git] / 16 / xlib / xcbitmap.asm
1 ;-----------------------------------------------------------------------\r
2 ; MODULE XCBITMAP\r
3 ; This module was written by Matthew MacKenzie\r
4 ; matm@eng.umd.edu\r
5 ;\r
6 ; Compiled bitmap  functions all MODE X 256 Color resolutions\r
7 ;\r
8 ; Compile with Tasm.\r
9 ; C callable.\r
10 ;\r
11 ; ****** XLIB - Mode X graphics library                ****************\r
12 ; ******                                               ****************\r
13 ; ****** Written By Themie Gouthas                     ****************\r
14 ; ****** Aeronautical Research Laboratory              ****************\r
15 ; ****** Defence Science and Technology Organisation   ****************\r
16 ; ****** Australia                                     ****************\r
17 ;\r
18 ; egg@dstos3.dsto.gov.au\r
19 ; teg@bart.dsto.gov.au\r
20 ;-----------------------------------------------------------------------\r
21 \r
22 include xlib.inc\r
23 include xcbitmap.inc\r
24 \r
25 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\r
26 ; _x_compile_bitmap\r
27 ;\r
28 ; Compile a linear bitmap to generate machine code to plot it\r
29 ; at any required screen coordinates FAST. Faster than blits\r
30 ; using planar bitmaps as in module XPBIITMAP\r
31 ;\r
32 ; C near-callable as:\r
33 ; int x_compile_bitmap  (WORD logical_screen_width,\r
34 ;                        char far * bitmap, char far * output);\r
35 ;\r
36 ; The logical width is in bytes rather than pixels.\r
37 ;\r
38 ; All four main registers are totaled.\r
39 ;\r
40 ;  The source linear bitmaps have the following structure:\r
41 ;\r
42 ;  BYTE 0                 The bitmap width in pixels  range 1..255\r
43 ;  BYTE 1                 The bitmap height in rows   range 1..255\r
44 ;  BYTE 2..n              The width*height bytes of the bitmap in\r
45 ;                         cloumn row order\r
46 ;\r
47 ; The returned value is the size of the compiled bitmap, in bytes.\r
48 \r
49 \r
50 ; accessory macros to save typing (what else?)\r
51 Emitb macro arg\r
52         mov byte ptr es:[di],&arg&\r
53         inc di\r
54         endm\r
55 \r
56 Emitw macro arg\r
57         mov word ptr es:[di],&arg&\r
58         add di,2\r
59         endm\r
60 \r
61 ; opcodes emitted by _x_compile_sprite\r
62 ROL_AL          equ 0c0d0h              ; rol al\r
63 SHORT_STORE_8   equ 044c6h              ; mov [si]+disp8,  imm8\r
64 STORE_8         equ 084c6h              ; mov [si]+disp16, imm8\r
65 SHORT_STORE_16  equ 044c7h              ; mov [si]+disp8,  imm16\r
66 STORE_16        equ 084c7h              ; mov [si]+disp16, imm16\r
67 ADC_SI_IMMED    equ 0d683h              ; adc si,imm8\r
68 OUT_AL          equ 0eeh                ; out dx,al\r
69 RETURN          equ 0cbh                ; ret\r
70 \r
71 \r
72 .data\r
73 \r
74 align 2\r
75 ColumnMask      db      011h,022h,044h,088h\r
76 \r
77 \r
78 .code\r
79 \r
80         align   2\r
81 _x_compile_bitmap proc\r
82 ARG   logical_width:word,bitmap:dword,output:dword\r
83 LOCAL bwidth,scanx,scany,outputx,outputy,column,set_column,input_size:word=LocalStk\r
84         push bp\r
85         mov  bp, sp         ; caller's stack frame\r
86         sub  sp,LocalStk    ; local space\r
87         push si\r
88         push di\r
89         push ds\r
90 \r
91         mov word ptr [scanx],0\r
92         mov word ptr [scany],0\r
93         mov word ptr [outputx],0\r
94         mov word ptr [outputy],0\r
95         mov word ptr [column],0\r
96         mov word ptr [set_column],0\r
97 \r
98         lds si,[bitmap]     ; 32-bit pointer to source bitmap\r
99 \r
100         les di,[output]     ; 32-bit pointer to destination stream\r
101 \r
102         lodsb               ; load width byte\r
103         xor ah, ah          ; convert to word\r
104         mov [bwidth], ax    ; save for future reference\r
105         mov bl, al          ; copy width byte to bl\r
106         lodsb               ; load height byte -- already a word since ah=0\r
107         mul bl              ; mult height word by width byte\r
108         mov [input_size], ax;  to get pixel total \r
109 \r
110 @@MainLoop:\r
111         mov bx, [scanx]     ; position in original bitmap\r
112         add bx, [scany]\r
113 \r
114         mov al, [si+bx]     ; get pixel\r
115         or  al, al          ; skip empty pixels\r
116         jnz @@NoAdvance\r
117         jmp @@Advance\r
118 @@NoAdvance:\r
119 \r
120         mov dx, [set_column]\r
121         cmp dx, [column]\r
122         je @@SameColumn\r
123 @@ColumnLoop:\r
124         Emitw ROL_AL        ; emit code to move to new column\r
125         Emitw ADC_SI_IMMED\r
126         Emitb 0\r
127 \r
128         inc dx\r
129         cmp dx, [column]\r
130         jl @@ColumnLoop\r
131 \r
132         Emitb OUT_AL        ; emit code to set VGA mask for new column\r
133         mov [set_column], dx\r
134 @@SameColumn:\r
135         mov dx, [outputy]   ; calculate output position\r
136         add dx, [outputx]\r
137         sub dx, 128\r
138 \r
139         add word ptr [scanx], 4\r
140         mov cx, [scanx]     ; within four pixels of right edge?\r
141         cmp cx, [bwidth]\r
142         jge @@OnePixel\r
143 \r
144         inc word ptr [outputx]\r
145         mov ah, [si+bx+4]   ; get second pixel\r
146         or ah, ah\r
147         jnz @@TwoPixels\r
148 @@OnePixel:\r
149         cmp dx, 127         ; can we use shorter form?\r
150         jg @@OnePixLarge\r
151         cmp dx, -128\r
152         jl @@OnePixLarge\r
153         Emitw SHORT_STORE_8\r
154         Emitb dl            ; 8-bit position in output\r
155         jmp @@EmitOnePixel\r
156 @@OnePixLarge:\r
157         Emitw STORE_8\r
158         Emitw dx            ; position in output\r
159 @@EmitOnePixel:\r
160         Emitb al\r
161         jmp short @@Advance\r
162 @@TwoPixels:\r
163         cmp dx, 127\r
164         jg @@TwoPixLarge\r
165         cmp dx, -128\r
166         jl @@TwoPixLarge\r
167         Emitw SHORT_STORE_16\r
168         Emitb dl            ; 8-bit position in output\r
169         jmp @@EmitTwoPixels\r
170 @@TwoPixLarge:\r
171         Emitw STORE_16\r
172         Emitw dx            ; position in output\r
173 @@EmitTwoPixels:\r
174         Emitw ax\r
175 \r
176 @@Advance:\r
177         inc word ptr [outputx]\r
178         mov ax, [scanx]\r
179         add ax, 4\r
180         cmp ax, [bwidth]\r
181         jl @@AdvanceDone\r
182         mov dx, [outputy]\r
183         add dx, [logical_width]\r
184         mov cx, [scany]\r
185         add cx, [bwidth]\r
186         cmp cx, [input_size]\r
187         jl @@NoNewColumn\r
188         inc word ptr [column]\r
189         mov cx, [column]\r
190         cmp cx, 4\r
191         je @@Exit           ; Column 4: there is no column 4.\r
192         xor cx, cx          ; scany and outputy are 0 again for\r
193         mov dx, cx          ; the new column\r
194 @@NoNewColumn:\r
195         mov [outputy], dx\r
196         mov [scany], cx\r
197         mov word ptr [outputx], 0\r
198         mov ax,[column]\r
199 @@AdvanceDone:\r
200         mov [scanx], ax\r
201         jmp @@MainLoop\r
202 \r
203 @@Exit:\r
204         Emitb RETURN\r
205         mov ax,di\r
206         sub ax,word ptr [output] ; size of generated code\r
207 \r
208         pop ds\r
209         pop di\r
210         pop si\r
211         mov sp, bp\r
212         pop bp\r
213 \r
214         ret\r
215 _x_compile_bitmap endp\r
216 \r
217 \r
218 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\r
219 ; _x_sizeof_cbitmap\r
220 ;\r
221 ; This function follows the same algorithm as the one above,\r
222 ; but does not generate a new object.  Its sole purpose is to\r
223 ; determine how much space the compiled bitmap will require.\r
224 ;\r
225 ; C near-callable as:\r
226 ; int x_sizeof_cbitmap  (WORD logical_screen_width,\r
227 ;                                char far * bitmap);\r
228 ;\r
229 ; The logical width is in bytes rather than pixels.\r
230 ;\r
231 ; All four main registers are totaled.\r
232 ;\r
233 ;  The source linear bitmaps have the following structure:\r
234 ;\r
235 ;  BYTE 0                 The bitmap width in pixels  range 1..255\r
236 ;  BYTE 1                 The bitmap height in rows   range 1..255\r
237 ;  BYTE 2..n              The width*height bytes of the bitmap in\r
238 ;                         cloumn row order\r
239 ;\r
240 ; The returned value is the size of the compiled bitmap, in bytes.\r
241 \r
242 \r
243         align   2\r
244 _x_sizeof_cbitmap proc\r
245 ARG   logical_width:word,bitmap:dword\r
246 LOCAL bwidth,scanx,scany,outputx,outputy,column,set_column,input_size:word=LocalStk\r
247         push bp\r
248         mov  bp, sp         ; caller's stack frame\r
249         sub  sp,LocalStk    ; local space\r
250         push si\r
251         push di\r
252         push ds\r
253 \r
254         mov word ptr [scanx], 0\r
255         mov word ptr [scany], 0\r
256         mov word ptr [outputx], 0\r
257         mov word ptr [outputy], 0\r
258         mov word ptr [column], 0\r
259         mov word ptr [set_column], 0\r
260 \r
261         lds si,[bitmap]     ; 32-bit pointer to source bitmap\r
262 \r
263         mov di, 1           ; initial size is just the size of the far RET\r
264 \r
265         lodsb               ; load width byte\r
266         xor ah, ah          ; convert to word\r
267         mov [bwidth], ax    ; save for future reference\r
268         mov bl, al          ; copy width byte to bl\r
269         lodsb               ; load height byte -- already a word since ah=0\r
270         mul bl              ; mult height word by width byte\r
271         mov [input_size], ax;  to get pixel total\r
272 \r
273 @@MainLoop:\r
274         mov bx, [scanx]     ; position in original bitmap\r
275         add bx, [scany]\r
276 \r
277         mov al, [si+bx]     ; get pixel\r
278         or  al, al          ; skip empty pixels\r
279         jnz @@NoAdvance\r
280         jmp @@Advance\r
281 @@NoAdvance:\r
282 \r
283         mov dx, [set_column]\r
284         cmp dx, [column]\r
285         je @@SameColumn\r
286 @@ColumnLoop:\r
287         add di, 5           ; size of code to move to new column\r
288         inc dx\r
289         cmp dx,[column]\r
290         jl @@ColumnLoop\r
291 \r
292         inc di              ; size of code to set VGA mask\r
293         mov [set_column], dx\r
294 @@SameColumn:\r
295         mov dx, [outputy]   ; calculate output position\r
296         add dx, [outputx]\r
297         sub dx, 128\r
298 \r
299         add word ptr [scanx], 4\r
300         mov cx, [scanx]     ; within four pixels of right edge?\r
301         cmp cx, [bwidth]\r
302         jge @@OnePixel\r
303 \r
304         inc word ptr [outputx]\r
305         mov ah,[si+bx+4]    ; get second pixel\r
306         or ah, ah\r
307         jnz @@TwoPixels\r
308 @@OnePixel:\r
309         cmp dx, 127         ; can we use shorter form?\r
310         jg @@OnePixLarge\r
311         cmp dx, -128\r
312         jl @@OnePixLarge\r
313         add di, 4           ; size of 8-bit position in output plus one pixel\r
314         jmp @@EmitOnePixel\r
315 @@OnePixLarge:\r
316         add di, 5           ; size of position in output plus one pixels\r
317 @@EmitOnePixel:\r
318         jmp short @@Advance\r
319 @@TwoPixels:\r
320         cmp dx, 127\r
321         jg @@TwoPixLarge\r
322         cmp dx, -128\r
323         jl @@TwoPixLarge\r
324         add di, 5           ; size of 8-bit position in output plus two pixels\r
325         jmp @@EmitTwoPixels\r
326 @@TwoPixLarge:\r
327         add di, 6           ; size of 16-bit position in output plus two pixels\r
328 @@EmitTwoPixels:\r
329 \r
330 @@Advance:\r
331         inc word ptr [outputx]\r
332         mov ax, [scanx]\r
333         add ax,4\r
334         cmp ax, [bwidth]\r
335         jl @@AdvanceDone\r
336         mov dx, [outputy]\r
337         add dx, [logical_width]\r
338         mov cx, [scany]\r
339         add cx, [bwidth]\r
340         cmp cx, [input_size]\r
341         jl @@NoNewColumn\r
342         inc word ptr [column]\r
343         mov cx, [column]\r
344         cmp cx, 4\r
345         je @@Exit           ; Column 4: there is no column 4.\r
346         xor cx,cx           ; scany and outputy are 0 again for\r
347         mov dx,cx           ; the new column\r
348 @@NoNewColumn:\r
349         mov [outputy], dx\r
350         mov [scany], cx\r
351         mov word ptr [outputx], 0\r
352         mov ax,[column]\r
353 @@AdvanceDone:\r
354         mov [scanx], ax\r
355         jmp @@MainLoop\r
356 \r
357 @@Exit:\r
358         mov ax, di          ; size of generated code\r
359 \r
360         pop ds\r
361         pop di\r
362         pop si\r
363         mov sp,bp\r
364         pop bp\r
365 \r
366         ret\r
367 _x_sizeof_cbitmap endp\r
368 \r
369 \r
370 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\r
371 ; _x_put_cbitmap\r
372 ;\r
373 ; Displays a compiled bitmap generated by x_compile_bitmap at given\r
374 ; coordinates, on a given screen page.\r
375 ;\r
376 ; C near-callable as:\r
377 ; void x_put_cbitmap (int XPos, int YPos,\r
378 ;                     unsigned int PageOffset, char far * Sprite);\r
379 ; ax, bx, cx, and dx are squashed like insignificant insects.\r
380 \r
381         align   2\r
382 _x_put_cbitmap proc\r
383 ARG XPos:word,YPos:word,PageOffset:word,Sprite:dword\r
384 \r
385         push bp\r
386         mov bp, sp\r
387         push si\r
388         push ds\r
389 \r
390         mov ax, [_ScrnLogicalByteWidth] ; global Xlib variable\r
391         mul word ptr [YPos] ; height in bytes\r
392         mov si, [XPos]\r
393         mov bx, si\r
394         sar si, 2           ; width in bytes\r
395         add si, ax\r
396         add si, [PageOffset]; (YPos * screen width) +\r
397         add si, 128         ;   (Xpos / 4) + page base + 128 ==> starting pos\r
398 \r
399         and bx, 3\r
400         mov ah, ColumnMask[bx]\r
401 \r
402         mov dx, SC_INDEX\r
403         mov al, MAP_MASK\r
404         out dx, ax\r
405         inc dx              ; ready to send out other masks as bytes\r
406         mov al, ah\r
407 \r
408         mov bx, SCREEN_SEG\r
409         mov ds, bx          ; We do this so the compiled shape won't need\r
410                                                 ;  segment overrides.\r
411 \r
412         call dword ptr [Sprite] ; the business end of the routine\r
413 \r
414         pop ds\r
415         pop si\r
416         pop bp\r
417 \r
418         ret\r
419 _x_put_cbitmap endp\r
420 \r
421 end\r
422 \r