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.
18 // This is marked each time the palette is updated. Handy for the 8bpp
19 // implementation, so we don't waste time changing the palette unnecessarily.
22 // Macros, to route draw_tile and draw_tile_solid to the right handler
23 #define draw_tile(which, line, where) \
27 draw_tile1((which),(line),(where)); break;\
29 draw_tile2((which),(line),(where)); break;\
31 draw_tile3((which),(line),(where)); break;\
33 draw_tile4((which),(line),(where)); break;\
36 #define draw_tile_solid(which, line, where) \
40 draw_tile1_solid((which),(line),(where)); break;\
42 draw_tile2_solid((which),(line),(where)); break;\
44 draw_tile3_solid((which),(line),(where)); break;\
46 draw_tile4_solid((which),(line),(where)); break;\
49 // Silly utility function, get a big-endian word
50 #ifdef WORDS_BIGENDIAN
51 static inline int get_word(unsigned char *where
)
52 { return (int)(*(unsigned short*)where
); }
54 static inline int get_word(unsigned char *where
)
55 { return (where
[0] << 8) | where
[1]; }
59 #ifdef WORDS_BIGENDIAN
60 # define PIXEL0 (0xf0000000)
61 # define PIXEL1 (0x0f000000)
62 # define PIXEL2 (0x00f00000)
63 # define PIXEL3 (0x000f0000)
64 # define PIXEL4 (0x0000f000)
65 # define PIXEL5 (0x00000f00)
66 # define PIXEL6 (0x000000f0)
67 # define PIXEL7 (0x0000000f)
76 #else // WORDS_BIGENDIAN
77 # define PIXEL0 (0x000000f0)
78 # define PIXEL1 (0x0000000f)
79 # define PIXEL2 (0x0000f000)
80 # define PIXEL3 (0x00000f00)
81 # define PIXEL4 (0x00f00000)
82 # define PIXEL5 (0x000f0000)
83 # define PIXEL6 (0xf0000000)
84 # define PIXEL7 (0x0f000000)
93 #endif // WORDS_BIGENDIAN
98 void asm_tiles_init(unsigned char *vram
,
102 void drawtile1(int which
, int line
, unsigned char *where
);
103 void drawtile1_solid(int which
, int line
, unsigned char *where
);
104 void drawtile2(int which
, int line
, unsigned char *where
);
105 void drawtile2_solid(int which
, int line
, unsigned char *where
);
106 void drawtile3(int which
, int line
, unsigned char *where
);
107 void drawtile3_solid(int which
, int line
, unsigned char *where
);
108 void drawtile4(int which
, int line
, unsigned char *where
);
109 void drawtile4_solid(int which
, int line
, unsigned char *where
);
112 // Pass off these calls to assembler counterparts
113 inline void md_vdp::draw_tile1_solid(int which
, int line
, unsigned char *where
)
114 { drawtile1_solid(which
, line
, where
); }
116 inline void md_vdp::draw_tile1(int which
, int line
, unsigned char *where
)
117 { drawtile1(which
, line
, where
); }
119 inline void md_vdp::draw_tile2_solid(int which
, int line
, unsigned char *where
)
120 { drawtile2_solid(which
, line
, where
); }
122 inline void md_vdp::draw_tile2(int which
, int line
, unsigned char *where
)
123 { drawtile2(which
, line
, where
); }
125 inline void md_vdp::draw_tile3_solid(int which
, int line
, unsigned char *where
)
126 { drawtile3_solid(which
, line
, where
); }
128 inline void md_vdp::draw_tile3(int which
, int line
, unsigned char *where
)
129 { drawtile3(which
, line
, where
); }
131 inline void md_vdp::draw_tile4_solid(int which
, int line
, unsigned char *where
)
132 { drawtile4_solid(which
, line
, where
); }
134 inline void md_vdp::draw_tile4(int which
, int line
, unsigned char *where
)
135 { drawtile4(which
, line
, where
); }
137 #else // WITH_X86_TILES
139 static bool has_zero_nibbles(uint32_t u32
)
141 return ((u32
- 0x11111111) & ~u32
& 0x88888888);
144 // Blit tile solidly, for 1 byte-per-pixel
145 inline void md_vdp::draw_tile1_solid(int which
, int line
, unsigned char *where
)
149 pal
= (which
>> 9 & 0x30); // Determine which 16-color palette
151 if(which
& 0x1000) // y flipped
152 line
^= 7; // take from the bottom, instead of the top
154 if(reg
[12] & 2) // interlace
155 tile
= *(unsigned*)(vram
+ ((which
&0x7ff) << 6) + (line
<< 3));
157 tile
= *(unsigned*)(vram
+ ((which
&0x7ff) << 5) + (line
<< 2));
160 if(which
& 0x800) // x flipped
162 *(where
) = ((tile
& PIXEL7
)>>SHIFT7
) | pal
;
163 *(where
+1) = ((tile
& PIXEL6
)>>SHIFT6
) | pal
;
164 *(where
+2) = ((tile
& PIXEL5
)>>SHIFT5
) | pal
;
165 *(where
+3) = ((tile
& PIXEL4
)>>SHIFT4
) | pal
;
166 *(where
+4) = ((tile
& PIXEL3
)>>SHIFT3
) | pal
;
167 *(where
+5) = ((tile
& PIXEL2
)>>SHIFT2
) | pal
;
168 *(where
+6) = ((tile
& PIXEL1
)>>SHIFT1
) | pal
;
169 *(where
+7) = ((tile
& PIXEL0
)>>SHIFT0
) | pal
;
171 *(where
) = ((tile
& PIXEL0
)>>SHIFT0
) | pal
;
172 *(where
+1) = ((tile
& PIXEL1
)>>SHIFT1
) | pal
;
173 *(where
+2) = ((tile
& PIXEL2
)>>SHIFT2
) | pal
;
174 *(where
+3) = ((tile
& PIXEL3
)>>SHIFT3
) | pal
;
175 *(where
+4) = ((tile
& PIXEL4
)>>SHIFT4
) | pal
;
176 *(where
+5) = ((tile
& PIXEL5
)>>SHIFT5
) | pal
;
177 *(where
+6) = ((tile
& PIXEL6
)>>SHIFT6
) | pal
;
178 *(where
+7) = ((tile
& PIXEL7
)>>SHIFT7
) | pal
;
182 // Blit tile, leaving color zero transparent, for 1 byte per pixel
183 inline void md_vdp::draw_tile1(int which
, int line
, unsigned char *where
)
187 pal
= (which
>> 9 & 0x30); // Determine which 16-color palette
189 if(which
& 0x1000) // y flipped
190 line
^= 7; // take from the bottom, instead of the top
192 if(reg
[12] & 2) // interlace
193 tile
= *(unsigned*)(vram
+ ((which
&0x7ff) << 6) + (line
<< 3));
195 tile
= *(unsigned*)(vram
+ ((which
&0x7ff) << 5) + (line
<< 2));
196 // If the tile is all 0's, why waste the time?
199 // If the tile doesn't have any transparent pixels, draw it solidly.
200 if (!has_zero_nibbles(tile
)) {
203 *(where
) = ((tile
& PIXEL7
)>>SHIFT7
) | pal
;
204 *(where
+1) = ((tile
& PIXEL6
)>>SHIFT6
) | pal
;
205 *(where
+2) = ((tile
& PIXEL5
)>>SHIFT5
) | pal
;
206 *(where
+3) = ((tile
& PIXEL4
)>>SHIFT4
) | pal
;
207 *(where
+4) = ((tile
& PIXEL3
)>>SHIFT3
) | pal
;
208 *(where
+5) = ((tile
& PIXEL2
)>>SHIFT2
) | pal
;
209 *(where
+6) = ((tile
& PIXEL1
)>>SHIFT1
) | pal
;
210 *(where
+7) = ((tile
& PIXEL0
)>>SHIFT0
) | pal
;
213 *(where
) = ((tile
& PIXEL0
)>>SHIFT0
) | pal
;
214 *(where
+1) = ((tile
& PIXEL1
)>>SHIFT1
) | pal
;
215 *(where
+2) = ((tile
& PIXEL2
)>>SHIFT2
) | pal
;
216 *(where
+3) = ((tile
& PIXEL3
)>>SHIFT3
) | pal
;
217 *(where
+4) = ((tile
& PIXEL4
)>>SHIFT4
) | pal
;
218 *(where
+5) = ((tile
& PIXEL5
)>>SHIFT5
) | pal
;
219 *(where
+6) = ((tile
& PIXEL6
)>>SHIFT6
) | pal
;
220 *(where
+7) = ((tile
& PIXEL7
)>>SHIFT7
) | pal
;
226 if(which
& 0x800) // x flipped
228 if(tile
& PIXEL7
) *(where
) = ((tile
& PIXEL7
)>>SHIFT7
) | pal
;
229 if(tile
& PIXEL6
) *(where
+1) = ((tile
& PIXEL6
)>>SHIFT6
) | pal
;
230 if(tile
& PIXEL5
) *(where
+2) = ((tile
& PIXEL5
)>>SHIFT5
) | pal
;
231 if(tile
& PIXEL4
) *(where
+3) = ((tile
& PIXEL4
)>>SHIFT4
) | pal
;
232 if(tile
& PIXEL3
) *(where
+4) = ((tile
& PIXEL3
)>>SHIFT3
) | pal
;
233 if(tile
& PIXEL2
) *(where
+5) = ((tile
& PIXEL2
)>>SHIFT2
) | pal
;
234 if(tile
& PIXEL1
) *(where
+6) = ((tile
& PIXEL1
)>>SHIFT1
) | pal
;
235 if(tile
& PIXEL0
) *(where
+7) = ((tile
& PIXEL0
)>>SHIFT0
) | pal
;
237 if(tile
& PIXEL0
) *(where
) = ((tile
& PIXEL0
)>>SHIFT0
) | pal
;
238 if(tile
& PIXEL1
) *(where
+1) = ((tile
& PIXEL1
)>>SHIFT1
) | pal
;
239 if(tile
& PIXEL2
) *(where
+2) = ((tile
& PIXEL2
)>>SHIFT2
) | pal
;
240 if(tile
& PIXEL3
) *(where
+3) = ((tile
& PIXEL3
)>>SHIFT3
) | pal
;
241 if(tile
& PIXEL4
) *(where
+4) = ((tile
& PIXEL4
)>>SHIFT4
) | pal
;
242 if(tile
& PIXEL5
) *(where
+5) = ((tile
& PIXEL5
)>>SHIFT5
) | pal
;
243 if(tile
& PIXEL6
) *(where
+6) = ((tile
& PIXEL6
)>>SHIFT6
) | pal
;
244 if(tile
& PIXEL7
) *(where
+7) = ((tile
& PIXEL7
)>>SHIFT7
) | pal
;
248 // Blit tile solidly, for 2 byte-per-pixel
249 inline void md_vdp::draw_tile2_solid(int which
, int line
, unsigned char *where
)
251 unsigned tile
, temp
, *pal
;
252 unsigned short *wwhere
= (unsigned short*)where
;
254 pal
= highpal
+ (which
>> 9 & 0x30); // Determine which 16-color palette
255 temp
= *pal
; *pal
= highpal
[reg
[7]&0x3f]; // Get background color
257 if(which
& 0x1000) // y flipped
258 line
^= 7; // take from the bottom, instead of the top
260 if(reg
[12] & 2) // interlace
261 tile
= *(unsigned*)(vram
+ ((which
&0x7ff) << 6) + (line
<< 3));
263 tile
= *(unsigned*)(vram
+ ((which
&0x7ff) << 5) + (line
<< 2));
266 if(which
& 0x800) // x flipped
268 *(wwhere
) = pal
[((tile
& PIXEL7
)>>SHIFT7
)];
269 *(wwhere
+1) = pal
[((tile
& PIXEL6
)>>SHIFT6
)];
270 *(wwhere
+2) = pal
[((tile
& PIXEL5
)>>SHIFT5
)];
271 *(wwhere
+3) = pal
[((tile
& PIXEL4
)>>SHIFT4
)];
272 *(wwhere
+4) = pal
[((tile
& PIXEL3
)>>SHIFT3
)];
273 *(wwhere
+5) = pal
[((tile
& PIXEL2
)>>SHIFT2
)];
274 *(wwhere
+6) = pal
[((tile
& PIXEL1
)>>SHIFT1
)];
275 *(wwhere
+7) = pal
[((tile
& PIXEL0
)>>SHIFT0
)];
277 *(wwhere
) = pal
[((tile
& PIXEL0
)>>SHIFT0
)];
278 *(wwhere
+1) = pal
[((tile
& PIXEL1
)>>SHIFT1
)];
279 *(wwhere
+2) = pal
[((tile
& PIXEL2
)>>SHIFT2
)];
280 *(wwhere
+3) = pal
[((tile
& PIXEL3
)>>SHIFT3
)];
281 *(wwhere
+4) = pal
[((tile
& PIXEL4
)>>SHIFT4
)];
282 *(wwhere
+5) = pal
[((tile
& PIXEL5
)>>SHIFT5
)];
283 *(wwhere
+6) = pal
[((tile
& PIXEL6
)>>SHIFT6
)];
284 *(wwhere
+7) = pal
[((tile
& PIXEL7
)>>SHIFT7
)];
286 // Restore the original color
290 // Blit tile, leaving color zero transparent, for 2 byte per pixel
291 inline void md_vdp::draw_tile2(int which
, int line
, unsigned char *where
)
294 unsigned short *wwhere
= (unsigned short*)where
;
296 pal
= highpal
+ (which
>> 9 & 0x30); // Determine which 16-color palette
298 if(which
& 0x1000) // y flipped
299 line
^= 7; // take from the bottom, instead of the top
301 if(reg
[12] & 2) // interlace
302 tile
= *(unsigned*)(vram
+ ((which
&0x7ff) << 6) + (line
<< 3));
304 tile
= *(unsigned*)(vram
+ ((which
&0x7ff) << 5) + (line
<< 2));
305 // If the tile is all 0's, why waste the time?
308 // If the tile doesn't have any transparent pixels, draw it solidly.
309 if (!has_zero_nibbles(tile
)) {
312 *(wwhere
) = pal
[((tile
& PIXEL7
)>>SHIFT7
)];
313 *(wwhere
+1) = pal
[((tile
& PIXEL6
)>>SHIFT6
)];
314 *(wwhere
+2) = pal
[((tile
& PIXEL5
)>>SHIFT5
)];
315 *(wwhere
+3) = pal
[((tile
& PIXEL4
)>>SHIFT4
)];
316 *(wwhere
+4) = pal
[((tile
& PIXEL3
)>>SHIFT3
)];
317 *(wwhere
+5) = pal
[((tile
& PIXEL2
)>>SHIFT2
)];
318 *(wwhere
+6) = pal
[((tile
& PIXEL1
)>>SHIFT1
)];
319 *(wwhere
+7) = pal
[((tile
& PIXEL0
)>>SHIFT0
)];
322 *(wwhere
) = pal
[((tile
& PIXEL0
)>>SHIFT0
)];
323 *(wwhere
+1) = pal
[((tile
& PIXEL1
)>>SHIFT1
)];
324 *(wwhere
+2) = pal
[((tile
& PIXEL2
)>>SHIFT2
)];
325 *(wwhere
+3) = pal
[((tile
& PIXEL3
)>>SHIFT3
)];
326 *(wwhere
+4) = pal
[((tile
& PIXEL4
)>>SHIFT4
)];
327 *(wwhere
+5) = pal
[((tile
& PIXEL5
)>>SHIFT5
)];
328 *(wwhere
+6) = pal
[((tile
& PIXEL6
)>>SHIFT6
)];
329 *(wwhere
+7) = pal
[((tile
& PIXEL7
)>>SHIFT7
)];
335 if(which
& 0x800) // x flipped
337 if(tile
& PIXEL7
) *(wwhere
) = pal
[((tile
& PIXEL7
)>>SHIFT7
)];
338 if(tile
& PIXEL6
) *(wwhere
+1) = pal
[((tile
& PIXEL6
)>>SHIFT6
)];
339 if(tile
& PIXEL5
) *(wwhere
+2) = pal
[((tile
& PIXEL5
)>>SHIFT5
)];
340 if(tile
& PIXEL4
) *(wwhere
+3) = pal
[((tile
& PIXEL4
)>>SHIFT4
)];
341 if(tile
& PIXEL3
) *(wwhere
+4) = pal
[((tile
& PIXEL3
)>>SHIFT3
)];
342 if(tile
& PIXEL2
) *(wwhere
+5) = pal
[((tile
& PIXEL2
)>>SHIFT2
)];
343 if(tile
& PIXEL1
) *(wwhere
+6) = pal
[((tile
& PIXEL1
)>>SHIFT1
)];
344 if(tile
& PIXEL0
) *(wwhere
+7) = pal
[((tile
& PIXEL0
)>>SHIFT0
)];
346 if(tile
& PIXEL0
) *(wwhere
) = pal
[((tile
& PIXEL0
)>>SHIFT0
)];
347 if(tile
& PIXEL1
) *(wwhere
+1) = pal
[((tile
& PIXEL1
)>>SHIFT1
)];
348 if(tile
& PIXEL2
) *(wwhere
+2) = pal
[((tile
& PIXEL2
)>>SHIFT2
)];
349 if(tile
& PIXEL3
) *(wwhere
+3) = pal
[((tile
& PIXEL3
)>>SHIFT3
)];
350 if(tile
& PIXEL4
) *(wwhere
+4) = pal
[((tile
& PIXEL4
)>>SHIFT4
)];
351 if(tile
& PIXEL5
) *(wwhere
+5) = pal
[((tile
& PIXEL5
)>>SHIFT5
)];
352 if(tile
& PIXEL6
) *(wwhere
+6) = pal
[((tile
& PIXEL6
)>>SHIFT6
)];
353 if(tile
& PIXEL7
) *(wwhere
+7) = pal
[((tile
& PIXEL7
)>>SHIFT7
)];
357 inline void md_vdp::draw_tile3_solid(int which
, int line
, unsigned char *where
)
359 unsigned tile
, temp
, *pal
;
360 uint24_t
*wwhere
= (uint24_t
*)where
;
362 pal
= highpal
+ (which
>> 9 & 0x30); // Determine which 16-color palette
363 temp
= *pal
; *pal
= highpal
[reg
[7]&0x3f]; // Get background color
365 if(which
& 0x1000) // y flipped
366 line
^= 7; // take from the bottom, instead of the top
368 if(reg
[12] & 2) // interlace
369 tile
= *(unsigned*)(vram
+ ((which
&0x7ff) << 6) + (line
<< 3));
371 tile
= *(unsigned*)(vram
+ ((which
&0x7ff) << 5) + (line
<< 2));
374 if(which
& 0x800) // x flipped
376 u24cpy(&wwhere
[0], (uint24_t
*)&pal
[((tile
& PIXEL7
) >> SHIFT7
)]);
377 u24cpy(&wwhere
[1], (uint24_t
*)&pal
[((tile
& PIXEL6
) >> SHIFT6
)]);
378 u24cpy(&wwhere
[2], (uint24_t
*)&pal
[((tile
& PIXEL5
) >> SHIFT5
)]);
379 u24cpy(&wwhere
[3], (uint24_t
*)&pal
[((tile
& PIXEL4
) >> SHIFT4
)]);
380 u24cpy(&wwhere
[4], (uint24_t
*)&pal
[((tile
& PIXEL3
) >> SHIFT3
)]);
381 u24cpy(&wwhere
[5], (uint24_t
*)&pal
[((tile
& PIXEL2
) >> SHIFT2
)]);
382 u24cpy(&wwhere
[6], (uint24_t
*)&pal
[((tile
& PIXEL1
) >> SHIFT1
)]);
383 u24cpy(&wwhere
[7], (uint24_t
*)&pal
[((tile
& PIXEL0
) >> SHIFT0
)]);
385 u24cpy(&wwhere
[0], (uint24_t
*)&pal
[((tile
& PIXEL0
) >> SHIFT0
)]);
386 u24cpy(&wwhere
[1], (uint24_t
*)&pal
[((tile
& PIXEL1
) >> SHIFT1
)]);
387 u24cpy(&wwhere
[2], (uint24_t
*)&pal
[((tile
& PIXEL2
) >> SHIFT2
)]);
388 u24cpy(&wwhere
[3], (uint24_t
*)&pal
[((tile
& PIXEL3
) >> SHIFT3
)]);
389 u24cpy(&wwhere
[4], (uint24_t
*)&pal
[((tile
& PIXEL4
) >> SHIFT4
)]);
390 u24cpy(&wwhere
[5], (uint24_t
*)&pal
[((tile
& PIXEL5
) >> SHIFT5
)]);
391 u24cpy(&wwhere
[6], (uint24_t
*)&pal
[((tile
& PIXEL6
) >> SHIFT6
)]);
392 u24cpy(&wwhere
[7], (uint24_t
*)&pal
[((tile
& PIXEL7
) >> SHIFT7
)]);
394 // Restore the original color
398 inline void md_vdp::draw_tile3(int which
, int line
, unsigned char *where
)
401 uint24_t
*wwhere
= (uint24_t
*)where
;
403 pal
= highpal
+ (which
>> 9 & 0x30); // Determine which 16-color palette
405 if(which
& 0x1000) // y flipped
406 line
^= 7; // take from the bottom, instead of the top
408 if(reg
[12] & 2) // interlace
409 tile
= *(unsigned*)(vram
+ ((which
&0x7ff) << 6) + (line
<< 3));
411 tile
= *(unsigned*)(vram
+ ((which
&0x7ff) << 5) + (line
<< 2));
412 // If it's empty, why waste the time?
415 // If the tile doesn't have any transparent pixels, draw it solidly.
416 if (!has_zero_nibbles(tile
)) {
419 u24cpy(&wwhere
[0], (uint24_t
*)&pal
[((tile
& PIXEL7
) >> SHIFT7
)]);
420 u24cpy(&wwhere
[1], (uint24_t
*)&pal
[((tile
& PIXEL6
) >> SHIFT6
)]);
421 u24cpy(&wwhere
[2], (uint24_t
*)&pal
[((tile
& PIXEL5
) >> SHIFT5
)]);
422 u24cpy(&wwhere
[3], (uint24_t
*)&pal
[((tile
& PIXEL4
) >> SHIFT4
)]);
423 u24cpy(&wwhere
[4], (uint24_t
*)&pal
[((tile
& PIXEL3
) >> SHIFT3
)]);
424 u24cpy(&wwhere
[5], (uint24_t
*)&pal
[((tile
& PIXEL2
) >> SHIFT2
)]);
425 u24cpy(&wwhere
[6], (uint24_t
*)&pal
[((tile
& PIXEL1
) >> SHIFT1
)]);
426 u24cpy(&wwhere
[7], (uint24_t
*)&pal
[((tile
& PIXEL0
) >> SHIFT0
)]);
429 u24cpy(&wwhere
[0], (uint24_t
*)&pal
[((tile
& PIXEL0
) >> SHIFT0
)]);
430 u24cpy(&wwhere
[1], (uint24_t
*)&pal
[((tile
& PIXEL1
) >> SHIFT1
)]);
431 u24cpy(&wwhere
[2], (uint24_t
*)&pal
[((tile
& PIXEL2
) >> SHIFT2
)]);
432 u24cpy(&wwhere
[3], (uint24_t
*)&pal
[((tile
& PIXEL3
) >> SHIFT3
)]);
433 u24cpy(&wwhere
[4], (uint24_t
*)&pal
[((tile
& PIXEL4
) >> SHIFT4
)]);
434 u24cpy(&wwhere
[5], (uint24_t
*)&pal
[((tile
& PIXEL5
) >> SHIFT5
)]);
435 u24cpy(&wwhere
[6], (uint24_t
*)&pal
[((tile
& PIXEL6
) >> SHIFT6
)]);
436 u24cpy(&wwhere
[7], (uint24_t
*)&pal
[((tile
& PIXEL7
) >> SHIFT7
)]);
442 if(which
& 0x800) // x flipped
446 (uint24_t
*)&pal
[((tile
& PIXEL7
) >> SHIFT7
)]);
449 (uint24_t
*)&pal
[((tile
& PIXEL6
) >> SHIFT6
)]);
452 (uint24_t
*)&pal
[((tile
& PIXEL5
) >> SHIFT5
)]);
455 (uint24_t
*)&pal
[((tile
& PIXEL4
) >> SHIFT4
)]);
458 (uint24_t
*)&pal
[((tile
& PIXEL3
) >> SHIFT3
)]);
461 (uint24_t
*)&pal
[((tile
& PIXEL2
) >> SHIFT2
)]);
464 (uint24_t
*)&pal
[((tile
& PIXEL1
) >> SHIFT1
)]);
467 (uint24_t
*)&pal
[((tile
& PIXEL0
) >> SHIFT0
)]);
471 (uint24_t
*)&pal
[((tile
& PIXEL0
) >> SHIFT0
)]);
474 (uint24_t
*)&pal
[((tile
& PIXEL1
) >> SHIFT1
)]);
477 (uint24_t
*)&pal
[((tile
& PIXEL2
) >> SHIFT2
)]);
480 (uint24_t
*)&pal
[((tile
& PIXEL3
) >> SHIFT3
)]);
483 (uint24_t
*)&pal
[((tile
& PIXEL4
) >> SHIFT4
)]);
486 (uint24_t
*)&pal
[((tile
& PIXEL5
) >> SHIFT5
)]);
489 (uint24_t
*)&pal
[((tile
& PIXEL6
) >> SHIFT6
)]);
492 (uint24_t
*)&pal
[((tile
& PIXEL7
) >> SHIFT7
)]);
496 // Blit tile solidly, for 4 byte-per-pixel
497 inline void md_vdp::draw_tile4_solid(int which
, int line
, unsigned char *where
)
499 unsigned tile
, temp
, *pal
;
500 unsigned *wwhere
= (unsigned*)where
;
502 pal
= highpal
+ (which
>> 9 & 0x30); // Determine which 16-color palette
503 temp
= *pal
; *pal
= highpal
[reg
[7]&0x3f]; // Get background color
505 if(which
& 0x1000) // y flipped
506 line
^= 7; // take from the bottom, instead of the top
508 if(reg
[12] & 2) // interlace
509 tile
= *(unsigned*)(vram
+ ((which
&0x7ff) << 6) + (line
<< 3));
511 tile
= *(unsigned*)(vram
+ ((which
&0x7ff) << 5) + (line
<< 2));
514 if(which
& 0x800) // x flipped
516 *(wwhere
) = pal
[((tile
& PIXEL7
)>>SHIFT7
)];
517 *(wwhere
+1) = pal
[((tile
& PIXEL6
)>>SHIFT6
)];
518 *(wwhere
+2) = pal
[((tile
& PIXEL5
)>>SHIFT5
)];
519 *(wwhere
+3) = pal
[((tile
& PIXEL4
)>>SHIFT4
)];
520 *(wwhere
+4) = pal
[((tile
& PIXEL3
)>>SHIFT3
)];
521 *(wwhere
+5) = pal
[((tile
& PIXEL2
)>>SHIFT2
)];
522 *(wwhere
+6) = pal
[((tile
& PIXEL1
)>>SHIFT1
)];
523 *(wwhere
+7) = pal
[((tile
& PIXEL0
)>>SHIFT0
)];
525 *(wwhere
) = pal
[((tile
& PIXEL0
)>>SHIFT0
)];
526 *(wwhere
+1) = pal
[((tile
& PIXEL1
)>>SHIFT1
)];
527 *(wwhere
+2) = pal
[((tile
& PIXEL2
)>>SHIFT2
)];
528 *(wwhere
+3) = pal
[((tile
& PIXEL3
)>>SHIFT3
)];
529 *(wwhere
+4) = pal
[((tile
& PIXEL4
)>>SHIFT4
)];
530 *(wwhere
+5) = pal
[((tile
& PIXEL5
)>>SHIFT5
)];
531 *(wwhere
+6) = pal
[((tile
& PIXEL6
)>>SHIFT6
)];
532 *(wwhere
+7) = pal
[((tile
& PIXEL7
)>>SHIFT7
)];
534 // Restore the original color
538 // Blit tile, leaving color zero transparent, for 4 byte per pixel
539 inline void md_vdp::draw_tile4(int which
, int line
, unsigned char *where
)
542 unsigned *wwhere
= (unsigned*)where
;
544 pal
= highpal
+ (which
>> 9 & 0x30); // Determine which 16-color palette
546 if(which
& 0x1000) // y flipped
547 line
^= 7; // take from the bottom, instead of the top
549 if(reg
[12] & 2) // interlace
550 tile
= *(unsigned*)(vram
+ ((which
&0x7ff) << 6) + (line
<< 3));
552 tile
= *(unsigned*)(vram
+ ((which
&0x7ff) << 5) + (line
<< 2));
553 // If the tile is all 0's, why waste the time?
556 // If the tile doesn't have any transparent pixels, draw it solidly.
557 if (!has_zero_nibbles(tile
)) {
560 *(wwhere
) = pal
[((tile
& PIXEL7
)>>SHIFT7
)];
561 *(wwhere
+1) = pal
[((tile
& PIXEL6
)>>SHIFT6
)];
562 *(wwhere
+2) = pal
[((tile
& PIXEL5
)>>SHIFT5
)];
563 *(wwhere
+3) = pal
[((tile
& PIXEL4
)>>SHIFT4
)];
564 *(wwhere
+4) = pal
[((tile
& PIXEL3
)>>SHIFT3
)];
565 *(wwhere
+5) = pal
[((tile
& PIXEL2
)>>SHIFT2
)];
566 *(wwhere
+6) = pal
[((tile
& PIXEL1
)>>SHIFT1
)];
567 *(wwhere
+7) = pal
[((tile
& PIXEL0
)>>SHIFT0
)];
570 *(wwhere
) = pal
[((tile
& PIXEL0
)>>SHIFT0
)];
571 *(wwhere
+1) = pal
[((tile
& PIXEL1
)>>SHIFT1
)];
572 *(wwhere
+2) = pal
[((tile
& PIXEL2
)>>SHIFT2
)];
573 *(wwhere
+3) = pal
[((tile
& PIXEL3
)>>SHIFT3
)];
574 *(wwhere
+4) = pal
[((tile
& PIXEL4
)>>SHIFT4
)];
575 *(wwhere
+5) = pal
[((tile
& PIXEL5
)>>SHIFT5
)];
576 *(wwhere
+6) = pal
[((tile
& PIXEL6
)>>SHIFT6
)];
577 *(wwhere
+7) = pal
[((tile
& PIXEL7
)>>SHIFT7
)];
583 if(which
& 0x800) // x flipped
585 if(tile
& PIXEL7
) *(wwhere
) = pal
[((tile
& PIXEL7
)>>SHIFT7
)];
586 if(tile
& PIXEL6
) *(wwhere
+1) = pal
[((tile
& PIXEL6
)>>SHIFT6
)];
587 if(tile
& PIXEL5
) *(wwhere
+2) = pal
[((tile
& PIXEL5
)>>SHIFT5
)];
588 if(tile
& PIXEL4
) *(wwhere
+3) = pal
[((tile
& PIXEL4
)>>SHIFT4
)];
589 if(tile
& PIXEL3
) *(wwhere
+4) = pal
[((tile
& PIXEL3
)>>SHIFT3
)];
590 if(tile
& PIXEL2
) *(wwhere
+5) = pal
[((tile
& PIXEL2
)>>SHIFT2
)];
591 if(tile
& PIXEL1
) *(wwhere
+6) = pal
[((tile
& PIXEL1
)>>SHIFT1
)];
592 if(tile
& PIXEL0
) *(wwhere
+7) = pal
[((tile
& PIXEL0
)>>SHIFT0
)];
594 if(tile
& PIXEL0
) *(wwhere
) = pal
[((tile
& PIXEL0
)>>SHIFT0
)];
595 if(tile
& PIXEL1
) *(wwhere
+1) = pal
[((tile
& PIXEL1
)>>SHIFT1
)];
596 if(tile
& PIXEL2
) *(wwhere
+2) = pal
[((tile
& PIXEL2
)>>SHIFT2
)];
597 if(tile
& PIXEL3
) *(wwhere
+3) = pal
[((tile
& PIXEL3
)>>SHIFT3
)];
598 if(tile
& PIXEL4
) *(wwhere
+4) = pal
[((tile
& PIXEL4
)>>SHIFT4
)];
599 if(tile
& PIXEL5
) *(wwhere
+5) = pal
[((tile
& PIXEL5
)>>SHIFT5
)];
600 if(tile
& PIXEL6
) *(wwhere
+6) = pal
[((tile
& PIXEL6
)>>SHIFT6
)];
601 if(tile
& PIXEL7
) *(wwhere
+7) = pal
[((tile
& PIXEL7
)>>SHIFT7
)];
604 #endif // WITH_X86_TILES
606 // Draw the window (front or back)
607 void md_vdp::draw_window(int line
, int front
)
613 unsigned char *where
;
617 total_window
= (y
< (reg
[18]&0x1f)) ^ (reg
[18] >> 7);
620 size
= (reg
[12] & 1)? 64 : 32;
622 pl
= (reg
[3] << 10) + ((y
&0x3f)*size
*2);
624 // Wide(320) or narrow(256)?
634 where
= dest
+ (start
* (int)Bpp
);
635 for (x
= -1; (x
< w
); ++x
) {
637 if (reg
[17] & 0x80) {
638 if (x
< ((reg
[17] & 0x1f) << 1))
642 if (x
>= ((reg
[17] & 0x1f) << 1))
646 which
= get_word(((unsigned char *)vram
) +
647 (pl
+ (add
& ((size
- 1) << 1))));
648 if ((which
>> 15) == front
)
649 draw_tile(which
, (line
& 7), where
);
656 inline void md_vdp::get_sprite_info(struct sprite_info
& info
, int index
)
660 info
.sprite
= (sprite_base
+ (index
<< 3));
662 // Get the sprite's location
663 info
.y
= get_word(info
.sprite
);
664 info
.x
= (get_word(info
.sprite
+ 6) & 0x1ff);
668 // "& 1" below is a workaround for a GCC (g++) <= 4.2.1 bug seen
670 // info.inter is a bit-field member of size 1 that normally cannot
671 // store anything other than 0 or 1, but which does in practice,
672 // causing info.tile to point to a bad address and crashing.
673 info
.inter
= ((reg
[12] >> 1) & 1);
676 prop
= get_word(info
.sprite
+ 4);
677 info
.prio
= (prop
>> 15);
678 info
.xflip
= (prop
>> 11);
679 info
.yflip
= (prop
>> 12);
680 info
.tile
= (uint32_t *)(vram
+ ((prop
& 0x07ff) << (5 + info
.inter
)));
683 info
.y
= ((info
.y
& 0x3fe) >> 1);
694 info
.tw
= (((info
.sprite
[2] >> 2) & 0x03) + 1);
695 info
.th
= ((info
.sprite
[2] & 0x03) + 1);
696 info
.w
= (info
.tw
<< 3);
697 info
.h
= (info
.th
<< 3);
700 void md_vdp::sprite_masking_overflow(int line
)
702 int masking_sprite_index
;
703 bool masking_effective
;
710 * Search for the highest priority sprite with x = 0. Call this sprite
711 * s0. Any sprite with a lower priority than s0 (therefore higher
712 * index in the array) is not drawn on the scanlines that s0 occupies
713 * on the y-axis. This is called sprite masking and is used by games
714 * like Streets of Rage and Lotus Turbo Challenge.
716 * Thanks for Charles MacDonald for explaining this to me (vext01).
718 * This loop also limits the number of sprites per line, which is 20
719 * in H40 and 16 in H32 _or_ 320 pixels wide in H40 and 256 pixels
720 * wide in H32, with a possibility for the last sprite to be only
723 masking_sprite_index
= -1;
724 // If sprites on the previous line overflowed, sprite masking becomes
725 // effective by default for the current line (it normally isn't).
726 masking_effective
= (sprite_overflow_line
== (line
- 1));
727 // Set sprites and dots limits for the current line.
738 for (i
= 0; i
< sprite_count
; i
++) {
743 // First, make sure the frame limit hasn't been reached.
744 idx
= sprite_order
[i
];
745 if (idx
>= frame_limit
) {
746 if (masking_sprite_index
== -1)
747 masking_sprite_index
= (i
- 1);
750 // Get current sprite coordinates and dimensions.
751 sprite
= (sprite_base
+ (idx
<< 3));
752 x
= get_word(sprite
+ 6) & 0x1ff;
753 y
= get_word(sprite
);
755 y
= ((y
& 0x3fe) >> 1);
758 h
= (((sprite
[2] & 0x03) << 3) + 8);
759 w
= (((sprite
[2] << 1) & 0x18) + 8);
760 // If this sprite isn't found on the current line, skip it.
761 if (!(((line
+ 0x80) >= y
) && ((line
+ 0x80) < (y
+ h
))))
763 // Substract sprite from the dots limit and decrease the
767 // If this sprite is not a masking sprite (x != 0), sprite
768 // masking becomes effective. The next sprite with (x == 0)
769 // will be a masking sprite.
771 masking_effective
= true;
772 // If a dot overflow occured, update sprite_overflow_line with
773 // the current line. This update must be done only once for a
776 sprite_overflow_line
= line
;
777 // If no masking sprite index has been set so far, do
778 // it now. Otherwise reset dots, because this sprite
779 // must not be truncated.
780 if (masking_sprite_index
== -1)
781 masking_sprite_index
= i
;
784 // Don't process any more sprites, exit from the loop.
787 // Check whether sprites limit has been reached.
788 if (line_limit
== 0) {
789 // If no masking sprite index has been set so far, do
791 if (masking_sprite_index
== -1)
792 masking_sprite_index
= i
;
793 // Trigger sprite overflow bit (d6).
794 belongs
.coo5
|= 0x40;
795 // Don't process any more sprites, exit from the loop.
798 // If sprite masking is effective and the current sprite is a
799 // masking sprite (x == 0), if we haven't already found one
800 // before, use this one, then continue to process the sprites
801 // list as we still need to know whether a dot overflow
803 if ((masking_effective
) &&
805 (masking_sprite_index
== -1))
806 masking_sprite_index
= i
;
808 // If no masking sprite index was found, display them all.
809 if (masking_sprite_index
== -1)
810 masking_sprite_index
= (sprite_count
- 1);
811 masking_sprite_index_cache
= masking_sprite_index
;
815 inline void md_vdp::sprite_mask_add(uint8_t* dest
, int pitch
,
816 struct sprite_info
& info
, int value
)
818 uint32_t *tile
= info
.tile
;
819 int len
= (info
.tw
* info
.h
);
820 int lines
= (8 << info
.inter
);
826 dest
+= (pitch
* info
.y
);
828 dest
+= (pitch
* (info
.h
- 1));
832 dest
+= (info
.w
- 1);
836 uint_fast32_t dots
= be2h32(*tile
);
839 for (tmp
= 0; (tmp
!= 8); ++tmp
) {
840 assert(dest
>= (uint8_t *)sprite_mask
);
841 assert(dest
< ((uint8_t *)sprite_mask
+
842 sizeof(sprite_mask
)));
844 * If a non-transparent sprite dot has already been
845 * drawn here, trigger the collision bit (d5).
846 * FIXME: doing this here is hackish and doesn't take
847 * sprites with the high priority bit into account.
850 belongs
.coo5
|= 0x20;
851 #ifdef WORDS_BIGENDIAN
852 if (dots
& 0x0000000f)
856 if (dots
& 0xf0000000)
868 if (wrap
== info
.th
) {
869 /* Next tiles column. */
870 dest
-= (pitch
* (info
.h
- 1));
874 /* Next tiles row. */
875 dest
+= (pitch
- (8 * unit
));
879 /* Next line of dots. */
887 void md_vdp::sprite_mask_generate()
891 memset(sprite_mask
, 0xff, sizeof(sprite_mask
));
892 for (i
= (sprite_count
- 1); (i
>= 0); --i
) {
895 get_sprite_info(info
, sprite_order
[i
]);
896 // We only care about sprites with the low priority bit unset.
899 // Don't bother with hidden sprites.
900 if ((info
.x
>= 320) || ((info
.x
+ info
.w
) < 0))
902 if ((info
.y
>= 256) || ((info
.y
+ info
.h
) < 0))
906 // Draw overlap mask for this sprite in a 512x512 virtual area.
907 sprite_mask_add((uint8_t *)sprite_mask
, sizeof(sprite_mask
[0]),
912 void md_vdp::draw_sprites(int line
, bool front
)
915 int tx
, ty
, x
, y
, xend
, ysize
, yoff
, i
, masking_sprite_index
;
917 unsigned char *where
;
918 #ifdef WITH_DEBUG_VDP
920 static unsigned long ant_last
[2];
921 unsigned long ant_cur
;
923 if ((dgen_vdp_sprites_boxing
) && (line
== 0)) {
924 ant_cur
= pd_usecs();
925 if ((ant_cur
- ant_last
[front
]) > 100000) {
926 ant_last
[front
] = ant_cur
;
931 masking_sprite_index
= masking_sprite_index_cache
;
933 // If dots_cache is less than zero, draw the first sprite partially.
936 // Sprites have to be in reverse order :P
937 for (i
= masking_sprite_index
; i
>= 0; --i
)
941 get_sprite_info(info
, sprite_order
[i
]);
942 // Only do it if it's on the right priority.
943 if (info
.prio
== front
)
945 which
= get_word(info
.sprite
+ 4);
946 // Get the sprite's location
950 xend
= ((info
.w
- 8) + x
);
951 // Partial draw if negative.
953 ysize
= ((info
.h
- 8) >> 3);
954 // Render if this sprite's on this line
955 if(xend
> -8 && x
< 320 && yoff
>= 0 && yoff
<= (ysize
<<3)+7)
960 which
+= ysize
- (yoff
>> 3);
962 which
+= (yoff
>> 3);
964 // Unconditionally draw this sprite. It's supposed to always
965 // appear on top of other sprites.
969 where
= dest
+ (xend
* (int)Bpp
);
970 for(tx
= xend
; tx
>= x
; tx
-= 8)
972 if(tx
> -8 && tx
< 320)
973 draw_tile(which
, ty
, where
);
979 where
= dest
+ (x
* (int)Bpp
);
980 for(tx
= x
; tx
<= xend
; tx
+= 8)
982 if(tx
> -8 && tx
< 320)
983 draw_tile(which
, ty
, where
);
989 // Draw sprite with the high priority bit set only where it's
990 // not covered by a higher priority sprite (lower index in the
991 // list) but with this bit unset. Those have already been drawn
992 // during the previous pass.
1002 if (which
& 0x800) {
1003 where
= dest
+ (xend
* (int)Bpp
);
1004 for (tx
= xend
; (tx
>= x
); tx
-= 8) {
1005 if ((tx
> -8) && (tx
< 320)) {
1009 memcpy(tile
.t1
, where
, Bpp_times8
);
1010 draw_tile(which
, ty
, tile
.t1
);
1011 for (xx
= tx
, xo
= 0; (xo
!= 8); ++xo
, ++xx
)
1012 if (sprite_mask
[(line
+ 0x80)][(xx
+ 0x80)] >= i
)
1013 memcpy(&dest
[(xx
* (int)Bpp
)],
1014 &tile
.t1
[(xo
* (int)Bpp
)],
1018 where
-= Bpp_times8
;
1022 where
= dest
+ (x
* (int)Bpp
);
1023 for (tx
= x
; (tx
<= xend
); tx
+= 8) {
1024 if ((tx
> -8) && (tx
< 320)) {
1028 memcpy(tile
.t1
, where
, Bpp_times8
);
1029 draw_tile(which
, ty
, tile
.t1
);
1030 for (xx
= tx
, xo
= 0; (xo
!= 8); ++xo
, ++xx
)
1031 if (sprite_mask
[(line
+ 0x80)][(xx
+ 0x80)] >= i
)
1032 memcpy(&dest
[(xx
* (int)Bpp
)],
1033 &tile
.t1
[(xo
* (int)Bpp
)],
1037 where
+= Bpp_times8
;
1041 #ifdef WITH_DEBUG_VDP
1042 if (dgen_vdp_sprites_boxing
) {
1043 uint32_t color
[2] = {
1044 (uint32_t)dgen_vdp_sprites_boxing_bg
,
1045 (uint32_t)dgen_vdp_sprites_boxing_fg
1050 if ((ph
= 0, (y
== line
)) ||
1051 (ph
= 1, ((y
+ info
.h
- 1) == line
)))
1052 for (fx
= (ant
[front
] ^ ph
); (fx
< info
.w
); fx
+= 2)
1053 draw_pixel(this->bmap
, (info
.x
+ fx
),
1054 line
, color
[info
.prio
]);
1056 draw_pixel(this->bmap
,
1057 (((line
& 1) == ant
[front
]) ?
1058 (info
.x
+ info
.w
- 1) : info
.x
),
1059 line
, color
[info
.prio
]);
1068 // The body for the next few functions is in an extraneous header file.
1069 // Phil, I hope I left enough in this file for GLOBAL to hack it right. ;)
1070 // Thanks to John Stiles for this trick :)
1072 void md_vdp::draw_plane_back0(int line
)
1076 #include "ras-drawplane.h"
1081 void md_vdp::draw_plane_back1(int line
)
1085 #include "ras-drawplane.h"
1090 void md_vdp::draw_plane_front0(int line
)
1094 #include "ras-drawplane.h"
1099 void md_vdp::draw_plane_front1(int line
)
1103 #include "ras-drawplane.h"
1108 // Allow frame components to be hidden when WITH_DEBUG_VDP is defined.
1109 #ifdef WITH_DEBUG_VDP
1110 #define vdp_hide_if(a, b) ((a) ? (void)0 : (void)(b))
1112 #define vdp_hide_if(a, b) (void)(b)
1115 // The main interface function, to generate a scanline
1116 void md_vdp::draw_scanline(struct bmap
*bits
, int line
)
1119 // Set the destination in the bmap
1121 dest
= bits
->data
+ (bits
->pitch
* (line
+ 8) + 16);
1122 // If bytes per pixel hasn't yet been set, do it
1123 if ((Bpp
== 0) || (Bpp
!= BITS_TO_BYTES(bits
->bpp
)))
1125 if(bits
->bpp
<= 8) Bpp
= 1;
1126 else if(bits
->bpp
<= 16) Bpp
= 2;
1127 else if(bits
->bpp
<= 24) Bpp
= 3;
1129 Bpp_times8
= Bpp
<< 3; // used for tile blitting
1130 #ifdef WITH_X86_TILES
1131 asm_tiles_init(vram
, reg
, highpal
); // pass these values to the asm tiles
1135 // If the palette's been changed, update it
1139 // What color depth are we?
1143 #ifdef WORDS_BIGENDIAN
1144 for (i
= 0; (i
< 128); i
+= 2)
1145 *ptr
++ = (((cram
[(i
+ 1)] & 0x0e) << 28) |
1146 ((cram
[(i
+ 1)] & 0xe0) << 16) |
1147 ((cram
[i
] & 0x0e) << 12));
1150 for (i
= 0; (i
< 128); i
+= 2)
1151 *ptr
++ = (((cram
[(i
+ 1)] & 0x0e) << 4) |
1152 ((cram
[(i
+ 1)] & 0xe0) << 16) |
1153 ((cram
[i
] & 0x0e) << 12));
1157 for(i
= 0; i
< 128; i
+= 2)
1158 *ptr
++ = ((cram
[i
+1]&0x0e) << 20) |
1159 ((cram
[i
+1]&0xe0) << 8 ) |
1160 ((cram
[i
] &0x0e) << 4 );
1163 for(i
= 0; i
< 128; i
+= 2)
1164 *ptr
++ = ((cram
[i
+1]&0x0e) << 12) |
1165 ((cram
[i
+1]&0xe0) << 3 ) |
1166 ((cram
[i
] &0x0e) << 1 );
1169 for(i
= 0; i
< 128; i
+= 2)
1170 *ptr
++ = ((cram
[i
+1]&0x0e) << 11) |
1171 ((cram
[i
+1]&0xe0) << 2 ) |
1172 ((cram
[i
] &0x0e) << 1 );
1176 // Let the hardware palette sort it out :P
1177 for(i
= 0; i
< 64; ++i
) *ptr
++ = i
;
1179 // Clean up the dirt
1183 // Render the screen if it's turned on
1186 // Recalculate the sprite order, if it's dirty
1187 if((dirt
[0x30] & 0x20) || (dirt
[0x34] & 1))
1190 // Max number of sprites per frame: 80 in H40, 64 in H32.
1191 int max
= ((reg
[12] & 1) ? 80 : 64);
1192 // Find the sprite base in VRAM
1193 sprite_base
= vram
+ (reg
[5]<<9);
1194 // Order the sprites
1195 sprite_count
= sprite_order
[0] = 0;
1197 next
= sprite_base
[(next
<< 3) + 3];
1198 sprite_order
[++sprite_count
] = next
;
1199 } while (next
&& sprite_count
< max
);
1200 // Clean up the dirt
1201 dirt
[0x30] &= ~0x20; dirt
[0x34] &= ~1;
1202 // Generate overlap mask for sprites with high priority bit
1203 sprite_mask_generate();
1205 // Calculate sprite masking and overflow.
1206 sprite_masking_overflow(line
);
1207 // Draw, from the bottom up
1209 vdp_hide_if(dgen_vdp_hide_plane_b
, draw_plane_back1(line
));
1210 vdp_hide_if(dgen_vdp_hide_plane_a
, draw_plane_back0(line
));
1211 vdp_hide_if(dgen_vdp_hide_plane_w
, draw_window(line
, 0));
1212 vdp_hide_if(dgen_vdp_hide_sprites
, draw_sprites(line
, 0));
1214 vdp_hide_if(dgen_vdp_hide_plane_b
, draw_plane_front1(line
));
1215 vdp_hide_if(dgen_vdp_hide_plane_a
, draw_plane_front0(line
));
1216 vdp_hide_if(dgen_vdp_hide_plane_w
, draw_window(line
, 1));
1217 vdp_hide_if(dgen_vdp_hide_sprites
, draw_sprites(line
, 1));
1219 // The display is off, paint it black
1220 // Do it a dword at a time
1221 unsigned *destl
= (unsigned*)dest
;
1222 for(i
= 0; i
< (80 * Bpp
); ++i
) destl
[i
] = 0;
1225 // If we're in narrow (256) mode, cut off the messy edges
1228 unsigned *destl
= (unsigned*)dest
;
1229 for(i
= 0; i
< Bpp_times8
; ++i
)
1230 destl
[i
] = destl
[i
+ (72 * Bpp
)] = 0;
1234 void md_vdp::draw_pixel(struct bmap
*bits
, int x
, int y
, uint32_t rgb
)
1238 if ((x
< 0) || (x
>= bits
->w
) || (y
< 0) || (y
>= bits
->h
))
1240 out
= ((bits
->data
+ (bits
->pitch
* (y
+ 8) + 16)) +
1241 (x
* BITS_TO_BYTES(bits
->bpp
)));
1242 switch (bits
->bpp
) {
1246 memcpy(out
, &rgb
, sizeof(rgb
));
1249 u24cpy((uint24_t
*)out
,
1250 (const uint24_t
*)((uint8_t *)&rgb
+ 1));
1253 tmp
= (((rgb
>> 5) & 0xf800) |
1254 ((rgb
>> 3) & 0x07e0) |
1256 memcpy(out
, &tmp
, sizeof(tmp
));
1259 tmp
= (((rgb
>> 6) & 0x7c00) |
1260 ((rgb
>> 3) & 0x03e0) |
1262 memcpy(out
, &tmp
, sizeof(tmp
));