2 // New raster effects engine
3 // I'd like to thank the Mac folks for giving me a good template to work from.
4 // This is just a cheap rehash of their code, except friendlier to other bit
5 // depths. :) I also put in a few little optimizations, like blank checking
6 // and especially the sprites.
12 // This is marked each time the palette is updated. Handy for the 8bpp
13 // implementation, so we don't waste time changing the palette unnecessarily.
16 // Macros, to route draw_tile and draw_tile_solid to the right handler
17 #define draw_tile(which, line, where) \
21 draw_tile1((which),(line),(where)); break;\
23 draw_tile2((which),(line),(where)); break;\
25 draw_tile3((which),(line),(where)); break;\
27 draw_tile4((which),(line),(where)); break;\
30 #define draw_tile_solid(which, line, where) \
34 draw_tile1_solid((which),(line),(where)); break;\
36 draw_tile2_solid((which),(line),(where)); break;\
38 draw_tile3_solid((which),(line),(where)); break;\
40 draw_tile4_solid((which),(line),(where)); break;\
43 // Silly utility function, get a big-endian word
44 #ifdef WORDS_BIGENDIAN
45 static inline int get_word(unsigned char *where
)
46 { return (int)(*(unsigned short*)where
); }
48 static inline int get_word(unsigned char *where
)
49 { return (where
[0] << 8) | where
[1]; }
53 #ifdef WORDS_BIGENDIAN
54 # define PIXEL0 (0xf0000000)
55 # define PIXEL1 (0x0f000000)
56 # define PIXEL2 (0x00f00000)
57 # define PIXEL3 (0x000f0000)
58 # define PIXEL4 (0x0000f000)
59 # define PIXEL5 (0x00000f00)
60 # define PIXEL6 (0x000000f0)
61 # define PIXEL7 (0x0000000f)
70 #else // WORDS_BIGENDIAN
71 # define PIXEL0 (0x000000f0)
72 # define PIXEL1 (0x0000000f)
73 # define PIXEL2 (0x0000f000)
74 # define PIXEL3 (0x00000f00)
75 # define PIXEL4 (0x00f00000)
76 # define PIXEL5 (0x000f0000)
77 # define PIXEL6 (0xf0000000)
78 # define PIXEL7 (0x0f000000)
87 #endif // WORDS_BIGENDIAN
91 void _asm_tiles_init(unsigned char *vram
,
95 void _drawtile1(int which
, int line
, unsigned char *where
);
96 void _drawtile1_solid(int which
, int line
, unsigned char *where
);
97 void _drawtile2(int which
, int line
, unsigned char *where
);
98 void _drawtile2_solid(int which
, int line
, unsigned char *where
);
99 void _drawtile3(int which
, int line
, unsigned char *where
);
100 void _drawtile3_solid(int which
, int line
, unsigned char *where
);
101 void _drawtile4(int which
, int line
, unsigned char *where
);
102 void _drawtile4_solid(int which
, int line
, unsigned char *where
);
105 // Pass off these calls to assembler counterparts
106 inline void md_vdp::draw_tile1_solid(int which
, int line
, unsigned char *where
)
107 { _drawtile1_solid(which
, line
, where
); }
109 inline void md_vdp::draw_tile1(int which
, int line
, unsigned char *where
)
110 { _drawtile1(which
, line
, where
); }
112 inline void md_vdp::draw_tile2_solid(int which
, int line
, unsigned char *where
)
113 { _drawtile2_solid(which
, line
, where
); }
115 inline void md_vdp::draw_tile2(int which
, int line
, unsigned char *where
)
116 { _drawtile2(which
, line
, where
); }
118 inline void md_vdp::draw_tile3_solid(int which
, int line
, unsigned char *where
)
119 { _drawtile3_solid(which
, line
, where
); }
121 inline void md_vdp::draw_tile3(int which
, int line
, unsigned char *where
)
122 { _drawtile3(which
, line
, where
); }
124 inline void md_vdp::draw_tile4_solid(int which
, int line
, unsigned char *where
)
125 { _drawtile4_solid(which
, line
, where
); }
127 inline void md_vdp::draw_tile4(int which
, int line
, unsigned char *where
)
128 { _drawtile4(which
, line
, where
); }
132 // Blit tile solidly, for 1 byte-per-pixel
133 inline void md_vdp::draw_tile1_solid(int which
, int line
, unsigned char *where
)
137 pal
= (which
>> 9 & 0x30); // Determine which 16-color palette
139 if(which
& 0x1000) // y flipped
140 line
^= 7; // take from the bottom, instead of the top
142 if(reg
[12] & 2) // interlace
143 tile
= *(unsigned*)(vram
+ ((which
&0x7ff) << 6) + (line
<< 3));
145 tile
= *(unsigned*)(vram
+ ((which
&0x7ff) << 5) + (line
<< 2));
148 if(which
& 0x800) // x flipped
150 *(where
) = ((tile
& PIXEL7
)>>SHIFT7
) | pal
;
151 *(where
+1) = ((tile
& PIXEL6
)>>SHIFT6
) | pal
;
152 *(where
+2) = ((tile
& PIXEL5
)>>SHIFT5
) | pal
;
153 *(where
+3) = ((tile
& PIXEL4
)>>SHIFT4
) | pal
;
154 *(where
+4) = ((tile
& PIXEL3
)>>SHIFT3
) | pal
;
155 *(where
+5) = ((tile
& PIXEL2
)>>SHIFT2
) | pal
;
156 *(where
+6) = ((tile
& PIXEL1
)>>SHIFT1
) | pal
;
157 *(where
+7) = ((tile
& PIXEL0
)>>SHIFT0
) | pal
;
159 *(where
) = ((tile
& PIXEL0
)>>SHIFT0
) | pal
;
160 *(where
+1) = ((tile
& PIXEL1
)>>SHIFT1
) | pal
;
161 *(where
+2) = ((tile
& PIXEL2
)>>SHIFT2
) | pal
;
162 *(where
+3) = ((tile
& PIXEL3
)>>SHIFT3
) | pal
;
163 *(where
+4) = ((tile
& PIXEL4
)>>SHIFT4
) | pal
;
164 *(where
+5) = ((tile
& PIXEL5
)>>SHIFT5
) | pal
;
165 *(where
+6) = ((tile
& PIXEL6
)>>SHIFT6
) | pal
;
166 *(where
+7) = ((tile
& PIXEL7
)>>SHIFT7
) | pal
;
170 // Blit tile, leaving color zero transparent, for 1 byte per pixel
171 inline void md_vdp::draw_tile1(int which
, int line
, unsigned char *where
)
175 pal
= (which
>> 9 & 0x30); // Determine which 16-color palette
177 if(which
& 0x1000) // y flipped
178 line
^= 7; // take from the bottom, instead of the top
180 if(reg
[12] & 2) // interlace
181 tile
= *(unsigned*)(vram
+ ((which
&0x7ff) << 6) + (line
<< 3));
183 tile
= *(unsigned*)(vram
+ ((which
&0x7ff) << 5) + (line
<< 2));
184 // If the tile is all 0's, why waste the time?
188 if(which
& 0x800) // x flipped
190 if(tile
& PIXEL7
) *(where
) = ((tile
& PIXEL7
)>>SHIFT7
) | pal
;
191 if(tile
& PIXEL6
) *(where
+1) = ((tile
& PIXEL6
)>>SHIFT6
) | pal
;
192 if(tile
& PIXEL5
) *(where
+2) = ((tile
& PIXEL5
)>>SHIFT5
) | pal
;
193 if(tile
& PIXEL4
) *(where
+3) = ((tile
& PIXEL4
)>>SHIFT4
) | pal
;
194 if(tile
& PIXEL3
) *(where
+4) = ((tile
& PIXEL3
)>>SHIFT3
) | pal
;
195 if(tile
& PIXEL2
) *(where
+5) = ((tile
& PIXEL2
)>>SHIFT2
) | pal
;
196 if(tile
& PIXEL1
) *(where
+6) = ((tile
& PIXEL1
)>>SHIFT1
) | pal
;
197 if(tile
& PIXEL0
) *(where
+7) = ((tile
& PIXEL0
)>>SHIFT0
) | pal
;
199 if(tile
& PIXEL0
) *(where
) = ((tile
& PIXEL0
)>>SHIFT0
) | pal
;
200 if(tile
& PIXEL1
) *(where
+1) = ((tile
& PIXEL1
)>>SHIFT1
) | pal
;
201 if(tile
& PIXEL2
) *(where
+2) = ((tile
& PIXEL2
)>>SHIFT2
) | pal
;
202 if(tile
& PIXEL3
) *(where
+3) = ((tile
& PIXEL3
)>>SHIFT3
) | pal
;
203 if(tile
& PIXEL4
) *(where
+4) = ((tile
& PIXEL4
)>>SHIFT4
) | pal
;
204 if(tile
& PIXEL5
) *(where
+5) = ((tile
& PIXEL5
)>>SHIFT5
) | pal
;
205 if(tile
& PIXEL6
) *(where
+6) = ((tile
& PIXEL6
)>>SHIFT6
) | pal
;
206 if(tile
& PIXEL7
) *(where
+7) = ((tile
& PIXEL7
)>>SHIFT7
) | pal
;
210 // Blit tile solidly, for 2 byte-per-pixel
211 inline void md_vdp::draw_tile2_solid(int which
, int line
, unsigned char *where
)
213 unsigned tile
, temp
, *pal
;
214 unsigned short *wwhere
= (unsigned short*)where
;
216 pal
= highpal
+ (which
>> 9 & 0x30); // Determine which 16-color palette
217 temp
= *pal
; *pal
= highpal
[reg
[7]&0x3f]; // Get background color
219 if(which
& 0x1000) // y flipped
220 line
^= 7; // take from the bottom, instead of the top
222 if(reg
[12] & 2) // interlace
223 tile
= *(unsigned*)(vram
+ ((which
&0x7ff) << 6) + (line
<< 3));
225 tile
= *(unsigned*)(vram
+ ((which
&0x7ff) << 5) + (line
<< 2));
228 if(which
& 0x800) // x flipped
230 *(wwhere
) = pal
[((tile
& PIXEL7
)>>SHIFT7
)];
231 *(wwhere
+1) = pal
[((tile
& PIXEL6
)>>SHIFT6
)];
232 *(wwhere
+2) = pal
[((tile
& PIXEL5
)>>SHIFT5
)];
233 *(wwhere
+3) = pal
[((tile
& PIXEL4
)>>SHIFT4
)];
234 *(wwhere
+4) = pal
[((tile
& PIXEL3
)>>SHIFT3
)];
235 *(wwhere
+5) = pal
[((tile
& PIXEL2
)>>SHIFT2
)];
236 *(wwhere
+6) = pal
[((tile
& PIXEL1
)>>SHIFT1
)];
237 *(wwhere
+7) = pal
[((tile
& PIXEL0
)>>SHIFT0
)];
239 *(wwhere
) = pal
[((tile
& PIXEL0
)>>SHIFT0
)];
240 *(wwhere
+1) = pal
[((tile
& PIXEL1
)>>SHIFT1
)];
241 *(wwhere
+2) = pal
[((tile
& PIXEL2
)>>SHIFT2
)];
242 *(wwhere
+3) = pal
[((tile
& PIXEL3
)>>SHIFT3
)];
243 *(wwhere
+4) = pal
[((tile
& PIXEL4
)>>SHIFT4
)];
244 *(wwhere
+5) = pal
[((tile
& PIXEL5
)>>SHIFT5
)];
245 *(wwhere
+6) = pal
[((tile
& PIXEL6
)>>SHIFT6
)];
246 *(wwhere
+7) = pal
[((tile
& PIXEL7
)>>SHIFT7
)];
248 // Restore the original color
252 // Blit tile, leaving color zero transparent, for 2 byte per pixel
253 inline void md_vdp::draw_tile2(int which
, int line
, unsigned char *where
)
256 unsigned short *wwhere
= (unsigned short*)where
;
258 pal
= highpal
+ (which
>> 9 & 0x30); // Determine which 16-color palette
260 if(which
& 0x1000) // y flipped
261 line
^= 7; // take from the bottom, instead of the top
263 if(reg
[12] & 2) // interlace
264 tile
= *(unsigned*)(vram
+ ((which
&0x7ff) << 6) + (line
<< 3));
266 tile
= *(unsigned*)(vram
+ ((which
&0x7ff) << 5) + (line
<< 2));
267 // If the tile is all 0's, why waste the time?
271 if(which
& 0x800) // x flipped
273 if(tile
& PIXEL7
) *(wwhere
) = pal
[((tile
& PIXEL7
)>>SHIFT7
)];
274 if(tile
& PIXEL6
) *(wwhere
+1) = pal
[((tile
& PIXEL6
)>>SHIFT6
)];
275 if(tile
& PIXEL5
) *(wwhere
+2) = pal
[((tile
& PIXEL5
)>>SHIFT5
)];
276 if(tile
& PIXEL4
) *(wwhere
+3) = pal
[((tile
& PIXEL4
)>>SHIFT4
)];
277 if(tile
& PIXEL3
) *(wwhere
+4) = pal
[((tile
& PIXEL3
)>>SHIFT3
)];
278 if(tile
& PIXEL2
) *(wwhere
+5) = pal
[((tile
& PIXEL2
)>>SHIFT2
)];
279 if(tile
& PIXEL1
) *(wwhere
+6) = pal
[((tile
& PIXEL1
)>>SHIFT1
)];
280 if(tile
& PIXEL0
) *(wwhere
+7) = pal
[((tile
& PIXEL0
)>>SHIFT0
)];
282 if(tile
& PIXEL0
) *(wwhere
) = pal
[((tile
& PIXEL0
)>>SHIFT0
)];
283 if(tile
& PIXEL1
) *(wwhere
+1) = pal
[((tile
& PIXEL1
)>>SHIFT1
)];
284 if(tile
& PIXEL2
) *(wwhere
+2) = pal
[((tile
& PIXEL2
)>>SHIFT2
)];
285 if(tile
& PIXEL3
) *(wwhere
+3) = pal
[((tile
& PIXEL3
)>>SHIFT3
)];
286 if(tile
& PIXEL4
) *(wwhere
+4) = pal
[((tile
& PIXEL4
)>>SHIFT4
)];
287 if(tile
& PIXEL5
) *(wwhere
+5) = pal
[((tile
& PIXEL5
)>>SHIFT5
)];
288 if(tile
& PIXEL6
) *(wwhere
+6) = pal
[((tile
& PIXEL6
)>>SHIFT6
)];
289 if(tile
& PIXEL7
) *(wwhere
+7) = pal
[((tile
& PIXEL7
)>>SHIFT7
)];
293 inline void md_vdp::draw_tile3_solid(int which
, int line
, unsigned char *where
)
298 pal
= ((unsigned char*)highpal
) + (which
>> 7 & 0xc0); // Determine 16-color palette
300 if(which
& 0x1000) // y flipped
301 line
^= 7; // take from the bottom, instead of the top
303 if(reg
[12] & 2) // interlace
304 tile
= *(unsigned*)(vram
+ ((which
&0x7ff) << 6) + (line
<< 3));
306 tile
= *(unsigned*)(vram
+ ((which
&0x7ff) << 5) + (line
<< 2));
308 // Blit the tile (this is UGLY! Do you know of a better way? :P)
311 *(where
) = pal
[((tile
& 0x0f000000)>>22)+1];
312 *(where
+1 ) = pal
[((tile
& 0x0f000000)>>22)+2];
313 *(where
+2 ) = pal
[((tile
& 0x0f000000)>>22) ];
314 *(where
+3 ) = pal
[((tile
& 0xf0000000)>>26)+1];
315 *(where
+4 ) = pal
[((tile
& 0xf0000000)>>26)+2];
316 *(where
+5 ) = pal
[((tile
& 0xf0000000)>>26) ];
317 *(where
+6 ) = pal
[((tile
& 0x000f0000)>>14)+1];
318 *(where
+7 ) = pal
[((tile
& 0x000f0000)>>14)+2];
319 *(where
+8 ) = pal
[((tile
& 0x000f0000)>>14) ];
320 *(where
+9 ) = pal
[((tile
& 0x00f00000)>>18)+1];
321 *(where
+10) = pal
[((tile
& 0x00f00000)>>18)+2];
322 *(where
+11) = pal
[((tile
& 0x00f00000)>>18) ];
323 *(where
+12) = pal
[((tile
& 0x00000f00)>> 6)+1];
324 *(where
+13) = pal
[((tile
& 0x00000f00)>> 6)+2];
325 *(where
+14) = pal
[((tile
& 0x00000f00)>> 6) ];
326 *(where
+15) = pal
[((tile
& 0x0000f000)>>10)+1];
327 *(where
+16) = pal
[((tile
& 0x0000f000)>>10)+2];
328 *(where
+17) = pal
[((tile
& 0x0000f000)>>10) ];
329 *(where
+18) = pal
[((tile
& 0x0000000f)<< 2)+1];
330 *(where
+19) = pal
[((tile
& 0x0000000f)<< 2)+2];
331 *(where
+20) = pal
[((tile
& 0x0000000f)<< 2) ];
332 *(where
+21) = pal
[((tile
& 0x000000f0)>> 2)+1];
333 *(where
+22) = pal
[((tile
& 0x000000f0)>> 2)+2];
334 *(where
+23) = pal
[((tile
& 0x000000f0)>> 2) ];
336 *(where
) = pal
[((tile
& 0x000000f0)>> 2)+1];
337 *(where
+ 1) = pal
[((tile
& 0x000000f0)>> 2)+2];
338 *(where
+ 2) = pal
[((tile
& 0x000000f0)>> 2) ];
339 *(where
+ 3) = pal
[((tile
& 0x0000000f)<< 2)+1];
340 *(where
+ 4) = pal
[((tile
& 0x0000000f)<< 2)+2];
341 *(where
+ 5) = pal
[((tile
& 0x0000000f)<< 2) ];
342 *(where
+ 6) = pal
[((tile
& 0x0000f000)>>10)+1];
343 *(where
+ 7) = pal
[((tile
& 0x0000f000)>>10)+2];
344 *(where
+ 8) = pal
[((tile
& 0x0000f000)>>10) ];
345 *(where
+ 9) = pal
[((tile
& 0x00000f00)>> 6)+1];
346 *(where
+10) = pal
[((tile
& 0x00000f00)>> 6)+2];
347 *(where
+11) = pal
[((tile
& 0x00000f00)>> 6) ];
348 *(where
+12) = pal
[((tile
& 0x00f00000)>>18)+1];
349 *(where
+13) = pal
[((tile
& 0x00f00000)>>18)+2];
350 *(where
+14) = pal
[((tile
& 0x00f00000)>>18) ];
351 *(where
+15) = pal
[((tile
& 0x000f0000)>>14)+1];
352 *(where
+16) = pal
[((tile
& 0x000f0000)>>14)+2];
353 *(where
+17) = pal
[((tile
& 0x000f0000)>>14) ];
354 *(where
+18) = pal
[((tile
& 0xf0000000)>>26)+1];
355 *(where
+19) = pal
[((tile
& 0xf0000000)>>26)+2];
356 *(where
+20) = pal
[((tile
& 0xf0000000)>>26) ];
357 *(where
+21) = pal
[((tile
& 0x0f000000)>>22)+1];
358 *(where
+22) = pal
[((tile
& 0x0f000000)>>22)+2];
359 *(where
+23) = pal
[((tile
& 0x0f000000)>>22) ];
363 inline void md_vdp::draw_tile3(int which
, int line
, unsigned char *where
)
368 pal
= ((unsigned char*)highpal
) + (which
>> 7 & 0xc0); // Determine 16-color palette
370 if(which
& 0x1000) // y flipped
371 line
^= 7; // take from the bottom, instead of the top
373 if(reg
[12] & 2) // interlace
374 tile
= *(unsigned*)(vram
+ ((which
&0x7ff) << 6) + (line
<< 3));
376 tile
= *(unsigned*)(vram
+ ((which
&0x7ff) << 5) + (line
<< 2));
377 // If it's empty, why waste the time?
380 // Blit the tile (this is UGLY! Do you know of a better way? :P)
383 // The numbers are a little wierd, because of little endian. *gag*
384 // <SARCASM>Thanks Intel!</SARCASM>
385 if(tile
& 0x0f000000) { *(where
) = pal
[((tile
& 0x0f000000)>>22)+1];
386 *(where
+1 ) = pal
[((tile
& 0x0f000000)>>22)+2];
387 *(where
+2 ) = pal
[((tile
& 0x0f000000)>>22) ]; }
388 if(tile
& 0xf0000000) { *(where
+3 ) = pal
[((tile
& 0xf0000000)>>26)+1];
389 *(where
+4 ) = pal
[((tile
& 0xf0000000)>>26)+2];
390 *(where
+5 ) = pal
[((tile
& 0xf0000000)>>26) ]; }
391 if(tile
& 0x000f0000) { *(where
+6 ) = pal
[((tile
& 0x000f0000)>>14)+1];
392 *(where
+7 ) = pal
[((tile
& 0x000f0000)>>14)+2];
393 *(where
+8 ) = pal
[((tile
& 0x000f0000)>>14) ]; }
394 if(tile
& 0x00f00000) { *(where
+9 ) = pal
[((tile
& 0x00f00000)>>18)+1];
395 *(where
+10) = pal
[((tile
& 0x00f00000)>>18)+2];
396 *(where
+11) = pal
[((tile
& 0x00f00000)>>18) ]; }
397 if(tile
& 0x00000f00) { *(where
+12) = pal
[((tile
& 0x00000f00)>> 6)+1];
398 *(where
+13) = pal
[((tile
& 0x00000f00)>> 6)+2];
399 *(where
+14) = pal
[((tile
& 0x00000f00)>> 6) ]; }
400 if(tile
& 0x0000f000) { *(where
+15) = pal
[((tile
& 0x0000f000)>>10)+1];
401 *(where
+16) = pal
[((tile
& 0x0000f000)>>10)+2];
402 *(where
+17) = pal
[((tile
& 0x0000f000)>>10) ]; }
403 if(tile
& 0x0000000f) { *(where
+18) = pal
[((tile
& 0x0000000f)<< 2)+1];
404 *(where
+19) = pal
[((tile
& 0x0000000f)<< 2)+2];
405 *(where
+20) = pal
[((tile
& 0x0000000f)<< 2) ]; }
406 if(tile
& 0x000000f0) { *(where
+21) = pal
[((tile
& 0x000000f0)>> 2)+1];
407 *(where
+22) = pal
[((tile
& 0x000000f0)>> 2)+2];
408 *(where
+23) = pal
[((tile
& 0x000000f0)>> 2) ]; }
410 if(tile
& 0x000000f0) { *(where
) = pal
[((tile
& 0x000000f0)>> 2)+1];
411 *(where
+ 1) = pal
[((tile
& 0x000000f0)>> 2)+2];
412 *(where
+ 2) = pal
[((tile
& 0x000000f0)>> 2) ]; }
413 if(tile
& 0x0000000f) { *(where
+ 3) = pal
[((tile
& 0x0000000f)<< 2)+1];
414 *(where
+ 4) = pal
[((tile
& 0x0000000f)<< 2)+2];
415 *(where
+ 5) = pal
[((tile
& 0x0000000f)<< 2) ]; }
416 if(tile
& 0x0000f000) { *(where
+ 6) = pal
[((tile
& 0x0000f000)>>10)+1];
417 *(where
+ 7) = pal
[((tile
& 0x0000f000)>>10)+2];
418 *(where
+ 8) = pal
[((tile
& 0x0000f000)>>10) ]; }
419 if(tile
& 0x00000f00) { *(where
+ 9) = pal
[((tile
& 0x00000f00)>> 6)+1];
420 *(where
+10) = pal
[((tile
& 0x00000f00)>> 6)+2];
421 *(where
+11) = pal
[((tile
& 0x00000f00)>> 6) ]; }
422 if(tile
& 0x00f00000) { *(where
+12) = pal
[((tile
& 0x00f00000)>>18)+1];
423 *(where
+13) = pal
[((tile
& 0x00f00000)>>18)+2];
424 *(where
+14) = pal
[((tile
& 0x00f00000)>>18) ]; }
425 if(tile
& 0x000f0000) { *(where
+15) = pal
[((tile
& 0x000f0000)>>14)+1];
426 *(where
+16) = pal
[((tile
& 0x000f0000)>>14)+2];
427 *(where
+17) = pal
[((tile
& 0x000f0000)>>14) ]; }
428 if(tile
& 0xf0000000) { *(where
+18) = pal
[((tile
& 0xf0000000)>>26)+1];
429 *(where
+19) = pal
[((tile
& 0xf0000000)>>26)+2];
430 *(where
+20) = pal
[((tile
& 0xf0000000)>>26) ]; }
431 if(tile
& 0x0f000000) { *(where
+21) = pal
[((tile
& 0x0f000000)>>22)+1];
432 *(where
+22) = pal
[((tile
& 0x0f000000)>>22)+2];
433 *(where
+23) = pal
[((tile
& 0x0f000000)>>22) ]; }
437 // Blit tile solidly, for 4 byte-per-pixel
438 inline void md_vdp::draw_tile4_solid(int which
, int line
, unsigned char *where
)
440 unsigned tile
, temp
, *pal
;
441 unsigned *wwhere
= (unsigned*)where
;
443 pal
= highpal
+ (which
>> 9 & 0x30); // Determine which 16-color palette
444 temp
= *pal
; *pal
= highpal
[reg
[7]&0x3f]; // Get background color
446 if(which
& 0x1000) // y flipped
447 line
^= 7; // take from the bottom, instead of the top
449 if(reg
[12] & 2) // interlace
450 tile
= *(unsigned*)(vram
+ ((which
&0x7ff) << 6) + (line
<< 3));
452 tile
= *(unsigned*)(vram
+ ((which
&0x7ff) << 5) + (line
<< 2));
455 if(which
& 0x800) // x flipped
457 *(wwhere
) = pal
[((tile
& PIXEL7
)>>SHIFT7
)];
458 *(wwhere
+1) = pal
[((tile
& PIXEL6
)>>SHIFT6
)];
459 *(wwhere
+2) = pal
[((tile
& PIXEL5
)>>SHIFT5
)];
460 *(wwhere
+3) = pal
[((tile
& PIXEL4
)>>SHIFT4
)];
461 *(wwhere
+4) = pal
[((tile
& PIXEL3
)>>SHIFT3
)];
462 *(wwhere
+5) = pal
[((tile
& PIXEL2
)>>SHIFT2
)];
463 *(wwhere
+6) = pal
[((tile
& PIXEL1
)>>SHIFT1
)];
464 *(wwhere
+7) = pal
[((tile
& PIXEL0
)>>SHIFT0
)];
466 *(wwhere
) = pal
[((tile
& PIXEL0
)>>SHIFT0
)];
467 *(wwhere
+1) = pal
[((tile
& PIXEL1
)>>SHIFT1
)];
468 *(wwhere
+2) = pal
[((tile
& PIXEL2
)>>SHIFT2
)];
469 *(wwhere
+3) = pal
[((tile
& PIXEL3
)>>SHIFT3
)];
470 *(wwhere
+4) = pal
[((tile
& PIXEL4
)>>SHIFT4
)];
471 *(wwhere
+5) = pal
[((tile
& PIXEL5
)>>SHIFT5
)];
472 *(wwhere
+6) = pal
[((tile
& PIXEL6
)>>SHIFT6
)];
473 *(wwhere
+7) = pal
[((tile
& PIXEL7
)>>SHIFT7
)];
475 // Restore the original color
479 // Blit tile, leaving color zero transparent, for 4 byte per pixel
480 inline void md_vdp::draw_tile4(int which
, int line
, unsigned char *where
)
483 unsigned *wwhere
= (unsigned*)where
;
485 pal
= highpal
+ (which
>> 9 & 0x30); // Determine which 16-color palette
487 if(which
& 0x1000) // y flipped
488 line
^= 7; // take from the bottom, instead of the top
490 if(reg
[12] & 2) // interlace
491 tile
= *(unsigned*)(vram
+ ((which
&0x7ff) << 6) + (line
<< 3));
493 tile
= *(unsigned*)(vram
+ ((which
&0x7ff) << 5) + (line
<< 2));
494 // If the tile is all 0's, why waste the time?
498 if(which
& 0x800) // x flipped
500 if(tile
& PIXEL7
) *(wwhere
) = pal
[((tile
& PIXEL7
)>>SHIFT7
)];
501 if(tile
& PIXEL6
) *(wwhere
+1) = pal
[((tile
& PIXEL6
)>>SHIFT6
)];
502 if(tile
& PIXEL5
) *(wwhere
+2) = pal
[((tile
& PIXEL5
)>>SHIFT5
)];
503 if(tile
& PIXEL4
) *(wwhere
+3) = pal
[((tile
& PIXEL4
)>>SHIFT4
)];
504 if(tile
& PIXEL3
) *(wwhere
+4) = pal
[((tile
& PIXEL3
)>>SHIFT3
)];
505 if(tile
& PIXEL2
) *(wwhere
+5) = pal
[((tile
& PIXEL2
)>>SHIFT2
)];
506 if(tile
& PIXEL1
) *(wwhere
+6) = pal
[((tile
& PIXEL1
)>>SHIFT1
)];
507 if(tile
& PIXEL0
) *(wwhere
+7) = pal
[((tile
& PIXEL0
)>>SHIFT0
)];
509 if(tile
& PIXEL0
) *(wwhere
) = pal
[((tile
& PIXEL0
)>>SHIFT0
)];
510 if(tile
& PIXEL1
) *(wwhere
+1) = pal
[((tile
& PIXEL1
)>>SHIFT1
)];
511 if(tile
& PIXEL2
) *(wwhere
+2) = pal
[((tile
& PIXEL2
)>>SHIFT2
)];
512 if(tile
& PIXEL3
) *(wwhere
+3) = pal
[((tile
& PIXEL3
)>>SHIFT3
)];
513 if(tile
& PIXEL4
) *(wwhere
+4) = pal
[((tile
& PIXEL4
)>>SHIFT4
)];
514 if(tile
& PIXEL5
) *(wwhere
+5) = pal
[((tile
& PIXEL5
)>>SHIFT5
)];
515 if(tile
& PIXEL6
) *(wwhere
+6) = pal
[((tile
& PIXEL6
)>>SHIFT6
)];
516 if(tile
& PIXEL7
) *(wwhere
+7) = pal
[((tile
& PIXEL7
)>>SHIFT7
)];
521 // Draw the window (front or back)
522 void md_vdp::draw_window(int line
, int front
)
528 unsigned char *where
;
532 total_window
= (y
< (reg
[18]&0x1f)) ^ (reg
[18] >> 7);
535 size
= (reg
[12] & 1)? 64 : 32;
537 pl
= (reg
[3] << 10) + ((y
&0x3f)*size
*2);
539 // Wide(320) or narrow(256)?
549 where
= dest
+ (start
* Bpp
);
555 if(x
< ((reg
[17]&0x1f) << 1)) goto skip
;
557 if(x
>= ((reg
[17]&0x1f) << 1)) goto skip
;
559 which
= get_word(((unsigned char*)vram
) + (pl
+(add
&((size
-1)<<1))));
560 if((which
>>15) == front
)
561 draw_tile(which
, line
&7, where
);
563 add
+= 2; where
+= Bpp_times8
;
567 void md_vdp::draw_sprites(int line
, int front
)
570 int tx
, ty
, x
, y
, xend
, ysize
, yoff
, i
;
571 unsigned char *where
, *sprite
;
572 // Sprites have to be in reverse order :P
573 for(i
= sprite_count
- 1; i
>= 0; --i
)
575 sprite
= sprite_base
+ (sprite_order
[i
] << 3);
576 // Get the first tile
577 which
= get_word(sprite
+ 4);
578 // Only do it if it's on the right priority
579 if((which
>> 15) == front
)
581 // Get the sprite's location
582 y
= get_word(sprite
);
583 x
= get_word(sprite
+ 6) & 0x1ff;
587 y
= (y
& 0x3fe) >> 1;
596 if(!(reg
[12] & 1)) x
+= 32;
598 xend
= ((sprite
[2] << 1) & 0x18) + x
;
599 ysize
= sprite
[2] & 0x3;
601 // Render if this sprite's on this line
602 if(xend
> -8 && x
< 320 && yoff
>= 0 && yoff
<= (ysize
<<3)+7)
607 which
+= ysize
- (yoff
>> 3);
609 which
+= (yoff
>> 3);
614 where
= dest
+ (xend
* Bpp
);
615 for(tx
= xend
; tx
>= x
; tx
-= 8)
617 if(tx
> -8 && tx
< 320)
618 draw_tile(which
, ty
, where
);
623 where
= dest
+ (x
* Bpp
);
624 for(tx
= x
; tx
<= xend
; tx
+= 8)
626 if(tx
> -8 && tx
< 320)
627 draw_tile(which
, ty
, where
);
637 // The body for the next few functions is in an extraneous header file.
638 // Phil, I hope I left enough in this file for GLOBAL to hack it right. ;)
639 // Thanks to John Stiles for this trick :)
641 void md_vdp::draw_plane_back0(int line
)
645 #include "ras-drawplane.h"
650 void md_vdp::draw_plane_back1(int line
)
654 #include "ras-drawplane.h"
659 void md_vdp::draw_plane_front0(int line
)
663 #include "ras-drawplane.h"
668 void md_vdp::draw_plane_front1(int line
)
672 #include "ras-drawplane.h"
677 // The main interface function, to generate a scanline
678 void md_vdp::draw_scanline(struct bmap
*bits
, int line
)
681 // Set the destination in the bmap
682 dest
= bits
->data
+ (bits
->pitch
* (line
+ 8) + 16);
683 // If bytes per pixel hasn't yet been set, do it
686 if(bits
->bpp
<= 8) Bpp
= 1;
687 else if(bits
->bpp
<= 16) Bpp
= 2;
688 else if(bits
->bpp
<= 24) Bpp
= 3;
690 Bpp_times8
= Bpp
<< 3; // used for tile blitting
692 _asm_tiles_init(vram
, reg
, highpal
); // pass these values to the asm tiles
696 // If the palette's been changed, update it
700 // What color depth are we?
705 for(i
= 0; i
< 128; i
+= 2)
706 *ptr
++ = ((cram
[i
+1]&0x0e) << 20) |
707 ((cram
[i
+1]&0xe0) << 8 ) |
708 ((cram
[i
] &0x0e) << 4 );
711 for(i
= 0; i
< 128; i
+= 2)
712 *ptr
++ = ((cram
[i
+1]&0x0e) << 12) |
713 ((cram
[i
+1]&0xe0) << 3 ) |
714 ((cram
[i
] &0x0e) << 1 );
717 for(i
= 0; i
< 128; i
+= 2)
718 *ptr
++ = ((cram
[i
+1]&0x0e) << 11) |
719 ((cram
[i
+1]&0xe0) << 2 ) |
720 ((cram
[i
] &0x0e) << 1 );
724 // Let the hardware palette sort it out :P
725 for(i
= 0; i
< 64; ++i
) *ptr
++ = i
;
731 // Render the screen if it's turned on
734 // Recalculate the sprite order, if it's dirty
735 if((dirt
[0x30] & 0x20) || (dirt
[0x34] & 1))
738 // Find the sprite base in VRAM
739 sprite_base
= vram
+ (reg
[5]<<9);
741 sprite_count
= sprite_order
[0] = 0;
743 next
= sprite_base
[(next
<< 3) + 3];
744 sprite_order
[++sprite_count
] = next
;
745 // No more than 256 sprites/line, a reasonable limit ;)
746 } while (next
&& sprite_count
< 0x100);
748 dirt
[0x30] &= ~0x20; dirt
[0x34] &= ~1;
750 // Draw, from the bottom up
752 draw_plane_back1(line
);
753 draw_plane_back0(line
);
754 draw_window(line
, 0);
755 draw_sprites(line
, 0);
757 draw_plane_front1(line
);
758 draw_plane_front0(line
);
759 draw_window(line
, 1);
760 draw_sprites(line
, 1);
762 // The display is off, paint it black
763 // Do it a dword at a time
764 unsigned *destl
= (unsigned*)dest
;
765 for(i
= 0; i
< (80 * Bpp
); ++i
) destl
[i
] = 0;
768 // If we're in narrow (256) mode, cut off the messy edges
771 unsigned *destl
= (unsigned*)dest
;
772 for(i
= 0; i
< Bpp_times8
; ++i
)
773 destl
[i
] = destl
[i
+ (72 * Bpp
)] = 0;