|   | 1 | /* gameplaySP | 
|   | 2 |  * | 
|   | 3 |  * Copyright (C) 2006 Exophase <exophase@gmail.com> | 
|   | 4 |  * | 
|   | 5 |  * This program is free software; you can redistribute it and/or | 
|   | 6 |  * modify it under the terms of the GNU General Public License as | 
|   | 7 |  * published by the Free Software Foundation; either version 2 of | 
|   | 8 |  * the License, or (at your option) any later version. | 
|   | 9 |  * | 
|   | 10 |  * This program is distributed in the hope that it will be useful, | 
|   | 11 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|   | 12 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|   | 13 |  * General Public License for more details. | 
|   | 14 |  * | 
|   | 15 |  * You should have received a copy of the GNU General Public License | 
|   | 16 |  * along with this program; if not, write to the Free Software | 
|   | 17 |  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | 
|   | 18 |  */ | 
|   | 19 |  | 
|   | 20 | #include "common.h" | 
|   | 21 | #define WANT_FONT_BITS | 
|   | 22 | #include "font.h" | 
|   | 23 |  | 
|   | 24 | #ifdef PSP_BUILD | 
|   | 25 |  | 
|   | 26 | #include <pspctrl.h> | 
|   | 27 |  | 
|   | 28 | #include <pspkernel.h> | 
|   | 29 | #include <pspdebug.h> | 
|   | 30 | #include <pspdisplay.h> | 
|   | 31 |  | 
|   | 32 | #include <pspgu.h> | 
|   | 33 | #include <psppower.h> | 
|   | 34 | #include <psprtc.h> | 
|   | 35 |  | 
|   | 36 | static float *screen_vertex = (float *)0x441FC100; | 
|   | 37 | static u32 *ge_cmd = (u32 *)0x441FC000; | 
|   | 38 | static u16 *psp_gu_vram_base = (u16 *)(0x44000000); | 
|   | 39 | static u32 *ge_cmd_ptr = (u32 *)0x441FC000; | 
|   | 40 | static u32 gecbid; | 
|   | 41 | static u32 video_direct = 0; | 
|   | 42 |  | 
|   | 43 | static u32 __attribute__((aligned(16))) display_list[32]; | 
|   | 44 |  | 
|   | 45 | #define GBA_SCREEN_WIDTH 240 | 
|   | 46 | #define GBA_SCREEN_HEIGHT 160 | 
|   | 47 |  | 
|   | 48 | #define PSP_SCREEN_WIDTH 480 | 
|   | 49 | #define PSP_SCREEN_HEIGHT 272 | 
|   | 50 | #define PSP_LINE_SIZE 512 | 
|   | 51 |  | 
|   | 52 | #define PSP_ALL_BUTTON_MASK 0xFFFF | 
|   | 53 |  | 
|   | 54 | #define GE_CMD_FBP    0x9C | 
|   | 55 | #define GE_CMD_FBW    0x9D | 
|   | 56 | #define GE_CMD_TBP0   0xA0 | 
|   | 57 | #define GE_CMD_TBW0   0xA8 | 
|   | 58 | #define GE_CMD_TSIZE0 0xB8 | 
|   | 59 | #define GE_CMD_TFLUSH 0xCB | 
|   | 60 | #define GE_CMD_CLEAR  0xD3 | 
|   | 61 | #define GE_CMD_VTYPE  0x12 | 
|   | 62 | #define GE_CMD_BASE   0x10 | 
|   | 63 | #define GE_CMD_VADDR  0x01 | 
|   | 64 | #define GE_CMD_IADDR  0x02 | 
|   | 65 | #define GE_CMD_PRIM   0x04 | 
|   | 66 | #define GE_CMD_FINISH 0x0F | 
|   | 67 | #define GE_CMD_SIGNAL 0x0C | 
|   | 68 | #define GE_CMD_NOP    0x00 | 
|   | 69 |  | 
|   | 70 | #define GE_CMD(cmd, operand)                                                \ | 
|   | 71 |   *ge_cmd_ptr = (((GE_CMD_##cmd) << 24) | (operand));                       \ | 
|   | 72 |   ge_cmd_ptr++                                                              \ | 
|   | 73 |  | 
|   | 74 | static u16 *screen_texture = (u16 *)(0x4000000 + (512 * 272 * 2)); | 
|   | 75 | static u16 *current_screen_texture = (u16 *)(0x4000000 + (512 * 272 * 2)); | 
|   | 76 | static u16 *screen_pixels = (u16 *)(0x4000000 + (512 * 272 * 2)); | 
|   | 77 | static u32 screen_pitch = 240; | 
|   | 78 |  | 
|   | 79 | static void Ge_Finish_Callback(int id, void *arg) | 
|   | 80 | { | 
|   | 81 | } | 
|   | 82 |  | 
|   | 83 | #define get_screen_pixels()                                                   \ | 
|   | 84 |   screen_pixels                                                               \ | 
|   | 85 |  | 
|   | 86 | #define get_screen_pitch()                                                    \ | 
|   | 87 |   screen_pitch                                                                \ | 
|   | 88 |  | 
|   | 89 | #elif defined(POLLUX_BUILD) | 
|   | 90 |  | 
|   | 91 | static u16 rot_buffer[240*4]; | 
|   | 92 | static u32 rot_lines_total = 4; | 
|   | 93 | static u32 rot_line_count = 0; | 
|   | 94 | #ifdef WIZ_BUILD | 
|   | 95 | static char rot_msg_buff[64]; | 
|   | 96 | #endif | 
|   | 97 |  | 
|   | 98 | static u32 screen_offset = 0; | 
|   | 99 | static u16 *screen_pixels = NULL; | 
|   | 100 | const u32 screen_pitch = 320; | 
|   | 101 |  | 
|   | 102 | #define get_screen_pixels()                                                   \ | 
|   | 103 |   screen_pixels                                                               \ | 
|   | 104 |  | 
|   | 105 | #define get_screen_pitch()                                                    \ | 
|   | 106 |   screen_pitch                                                                \ | 
|   | 107 |  | 
|   | 108 | #elif defined(PND_BUILD) || defined(RPI_BUILD) | 
|   | 109 |  | 
|   | 110 | static u16 *screen_pixels = NULL; | 
|   | 111 |  | 
|   | 112 | #define get_screen_pixels()                                                   \ | 
|   | 113 |   screen_pixels                                                               \ | 
|   | 114 |  | 
|   | 115 | #define get_screen_pitch()                                                    \ | 
|   | 116 |   resolution_width                                                            \ | 
|   | 117 |  | 
|   | 118 | #else | 
|   | 119 |  | 
|   | 120 | #ifdef GP2X_BUILD | 
|   | 121 | #include "SDL_gp2x.h" | 
|   | 122 | SDL_Surface *hw_screen; | 
|   | 123 | #endif | 
|   | 124 | SDL_Surface *screen; | 
|   | 125 | const u32 video_scale = 1; | 
|   | 126 |  | 
|   | 127 | #define get_screen_pixels()                                                   \ | 
|   | 128 |   ((u16 *)screen->pixels)                                                     \ | 
|   | 129 |  | 
|   | 130 | #define get_screen_pitch()                                                    \ | 
|   | 131 |   (screen->pitch / 2)                                                         \ | 
|   | 132 |  | 
|   | 133 | #endif | 
|   | 134 |  | 
|   | 135 | static void render_scanline_conditional_tile(u32 start, u32 end, u16 *scanline, | 
|   | 136 |  u32 enable_flags, u32 dispcnt, u32 bldcnt, const tile_layer_render_struct | 
|   | 137 |  *layer_renderers); | 
|   | 138 | static void render_scanline_conditional_bitmap(u32 start, u32 end, u16 *scanline, | 
|   | 139 |  u32 enable_flags, u32 dispcnt, u32 bldcnt, const bitmap_layer_render_struct | 
|   | 140 |  *layer_renderers); | 
|   | 141 |  | 
|   | 142 | #define no_op                                                                 \ | 
|   | 143 |  | 
|   | 144 | // This old version is not necessary if the palette is either being converted | 
|   | 145 | // transparently or the ABGR 1555 format is being used natively. The direct | 
|   | 146 | // version (without conversion) is much faster. | 
|   | 147 |  | 
|   | 148 | #define tile_lookup_palette_full(palette, source)                             \ | 
|   | 149 |   current_pixel = palette[source];                                            \ | 
|   | 150 |   convert_palette(current_pixel)                                              \ | 
|   | 151 |  | 
|   | 152 | #define tile_lookup_palette(palette, source)                                  \ | 
|   | 153 |   current_pixel = palette[source];                                            \ | 
|   | 154 |  | 
|   | 155 |  | 
|   | 156 | #ifdef RENDER_COLOR16_NORMAL | 
|   | 157 |  | 
|   | 158 | #define tile_expand_base_normal(index)                                        \ | 
|   | 159 |   tile_expand_base_color16(index)                                             \ | 
|   | 160 |  | 
|   | 161 | #else | 
|   | 162 |  | 
|   | 163 | #define tile_expand_base_normal(index)                                        \ | 
|   | 164 |   tile_lookup_palette(palette, current_pixel);                                \ | 
|   | 165 |   dest_ptr[index] = current_pixel                                             \ | 
|   | 166 |  | 
|   | 167 | #endif | 
|   | 168 |  | 
|   | 169 | #define tile_expand_transparent_normal(index)                                 \ | 
|   | 170 |   tile_expand_base_normal(index)                                              \ | 
|   | 171 |  | 
|   | 172 | #define tile_expand_copy(index)                                               \ | 
|   | 173 |   dest_ptr[index] = copy_ptr[index]                                           \ | 
|   | 174 |  | 
|   | 175 |  | 
|   | 176 | #define advance_dest_ptr_base(delta)                                          \ | 
|   | 177 |   dest_ptr += delta                                                           \ | 
|   | 178 |  | 
|   | 179 | #define advance_dest_ptr_transparent(delta)                                   \ | 
|   | 180 |   advance_dest_ptr_base(delta)                                                \ | 
|   | 181 |  | 
|   | 182 | #define advance_dest_ptr_copy(delta)                                          \ | 
|   | 183 |   advance_dest_ptr_base(delta);                                               \ | 
|   | 184 |   copy_ptr += delta                                                           \ | 
|   | 185 |  | 
|   | 186 |  | 
|   | 187 | #define color_combine_mask_a(layer)                                           \ | 
|   | 188 |   ((io_registers[REG_BLDCNT] >> layer) & 0x01)                                \ | 
|   | 189 |  | 
|   | 190 | // For color blending operations, will create a mask that has in bit | 
|   | 191 | // 10 if the layer is target B, and bit 9 if the layer is target A. | 
|   | 192 |  | 
|   | 193 | #define color_combine_mask(layer)                                             \ | 
|   | 194 |   (color_combine_mask_a(layer) |                                              \ | 
|   | 195 |    ((io_registers[REG_BLDCNT] >> (layer + 7)) & 0x02)) << 9                   \ | 
|   | 196 |  | 
|   | 197 | // For alpha blending renderers, draw the palette index (9bpp) and | 
|   | 198 | // layer bits rather than the raw RGB. For the base this should write to | 
|   | 199 | // the 32bit location directly. | 
|   | 200 |  | 
|   | 201 | #define tile_expand_base_alpha(index)                                         \ | 
|   | 202 |   dest_ptr[index] = current_pixel | pixel_combine                             \ | 
|   | 203 |  | 
|   | 204 | #define tile_expand_base_bg(index)                                            \ | 
|   | 205 |   dest_ptr[index] = bg_combine                                                \ | 
|   | 206 |  | 
|   | 207 |  | 
|   | 208 | // For layered (transparent) writes this should shift the "stack" and write | 
|   | 209 | // to the bottom. This will preserve the topmost pixel and the most recent | 
|   | 210 | // one. | 
|   | 211 |  | 
|   | 212 | #define tile_expand_transparent_alpha(index)                                  \ | 
|   | 213 |   dest_ptr[index] = (dest_ptr[index] << 16) | current_pixel | pixel_combine   \ | 
|   | 214 |  | 
|   | 215 |  | 
|   | 216 | // OBJ should only shift if the top isn't already OBJ | 
|   | 217 | #define tile_expand_transparent_alpha_obj(index)                              \ | 
|   | 218 |   dest = dest_ptr[index];                                                     \ | 
|   | 219 |   if(dest & 0x00000100)                                                       \ | 
|   | 220 |   {                                                                           \ | 
|   | 221 |     dest_ptr[index] = (dest & 0xFFFF0000) | current_pixel | pixel_combine;    \ | 
|   | 222 |   }                                                                           \ | 
|   | 223 |   else                                                                        \ | 
|   | 224 |   {                                                                           \ | 
|   | 225 |     dest_ptr[index] = (dest << 16) | current_pixel | pixel_combine;           \ | 
|   | 226 |   }                                                                           \ | 
|   | 227 |  | 
|   | 228 |  | 
|   | 229 | // For color effects that don't need to preserve the previous layer. | 
|   | 230 | // The color32 version should be used with 32bit wide dest_ptr so as to be | 
|   | 231 | // compatible with alpha combine on top of it. | 
|   | 232 |  | 
|   | 233 | #define tile_expand_base_color16(index)                                       \ | 
|   | 234 |   dest_ptr[index] = current_pixel | pixel_combine                             \ | 
|   | 235 |  | 
|   | 236 | #define tile_expand_transparent_color16(index)                                \ | 
|   | 237 |   tile_expand_base_color16(index)                                             \ | 
|   | 238 |  | 
|   | 239 | #define tile_expand_base_color32(index)                                       \ | 
|   | 240 |   tile_expand_base_color16(index)                                             \ | 
|   | 241 |  | 
|   | 242 | #define tile_expand_transparent_color32(index)                                \ | 
|   | 243 |   tile_expand_base_color16(index)                                             \ | 
|   | 244 |  | 
|   | 245 |  | 
|   | 246 | // Operations for isolation 8bpp pixels within 32bpp pixel blocks. | 
|   | 247 |  | 
|   | 248 | #define tile_8bpp_pixel_op_mask(op_param)                                     \ | 
|   | 249 |   current_pixel = current_pixels & 0xFF                                       \ | 
|   | 250 |  | 
|   | 251 | #define tile_8bpp_pixel_op_shift_mask(shift)                                  \ | 
|   | 252 |   current_pixel = (current_pixels >> shift) & 0xFF                            \ | 
|   | 253 |  | 
|   | 254 | #define tile_8bpp_pixel_op_shift(shift)                                       \ | 
|   | 255 |   current_pixel = current_pixels >> shift                                     \ | 
|   | 256 |  | 
|   | 257 | #define tile_8bpp_pixel_op_none(shift)                                        \ | 
|   | 258 |  | 
|   | 259 | // Base should always draw raw in 8bpp mode; color 0 will be drawn where | 
|   | 260 | // color 0 is. | 
|   | 261 |  | 
|   | 262 | #define tile_8bpp_draw_base_normal(index)                                     \ | 
|   | 263 |   tile_expand_base_normal(index)                                              \ | 
|   | 264 |  | 
|   | 265 | #define tile_8bpp_draw_base_alpha(index)                                      \ | 
|   | 266 |   if(current_pixel)                                                           \ | 
|   | 267 |   {                                                                           \ | 
|   | 268 |     tile_expand_base_alpha(index);                                            \ | 
|   | 269 |   }                                                                           \ | 
|   | 270 |   else                                                                        \ | 
|   | 271 |   {                                                                           \ | 
|   | 272 |     tile_expand_base_bg(index);                                               \ | 
|   | 273 |   }                                                                           \ | 
|   | 274 |  | 
|   | 275 |  | 
|   | 276 | #define tile_8bpp_draw_base_color16(index)                                    \ | 
|   | 277 |   tile_8bpp_draw_base_alpha(index)                                            \ | 
|   | 278 |  | 
|   | 279 | #define tile_8bpp_draw_base_color32(index)                                    \ | 
|   | 280 |   tile_8bpp_draw_base_alpha(index)                                            \ | 
|   | 281 |  | 
|   | 282 |  | 
|   | 283 | #define tile_8bpp_draw_base(index, op, op_param, alpha_op)                    \ | 
|   | 284 |   tile_8bpp_pixel_op_##op(op_param);                                          \ | 
|   | 285 |   tile_8bpp_draw_base_##alpha_op(index)                                       \ | 
|   | 286 |  | 
|   | 287 | // Transparent (layered) writes should only replace what is there if the | 
|   | 288 | // pixel is not transparent (zero) | 
|   | 289 |  | 
|   | 290 | #define tile_8bpp_draw_transparent(index, op, op_param, alpha_op)             \ | 
|   | 291 |   tile_8bpp_pixel_op_##op(op_param);                                          \ | 
|   | 292 |   if(current_pixel)                                                           \ | 
|   | 293 |   {                                                                           \ | 
|   | 294 |     tile_expand_transparent_##alpha_op(index);                                \ | 
|   | 295 |   }                                                                           \ | 
|   | 296 |  | 
|   | 297 | #define tile_8bpp_draw_copy(index, op, op_param, alpha_op)                    \ | 
|   | 298 |   tile_8bpp_pixel_op_##op(op_param);                                          \ | 
|   | 299 |   if(current_pixel)                                                           \ | 
|   | 300 |   {                                                                           \ | 
|   | 301 |     tile_expand_copy(index);                                                  \ | 
|   | 302 |   }                                                                           \ | 
|   | 303 |  | 
|   | 304 | // Get the current tile from the map in 8bpp mode | 
|   | 305 |  | 
|   | 306 | #define get_tile_8bpp()                                                       \ | 
|   | 307 |   current_tile = *map_ptr;                                                    \ | 
|   | 308 |   tile_ptr = tile_base + ((current_tile & 0x3FF) * 64)                        \ | 
|   | 309 |  | 
|   | 310 |  | 
|   | 311 | // Draw half of a tile in 8bpp mode, for base renderer | 
|   | 312 |  | 
|   | 313 | #define tile_8bpp_draw_four_noflip(index, combine_op, alpha_op)               \ | 
|   | 314 |   tile_8bpp_draw_##combine_op(index + 0, mask, 0, alpha_op);                  \ | 
|   | 315 |   tile_8bpp_draw_##combine_op(index + 1, shift_mask, 8, alpha_op);            \ | 
|   | 316 |   tile_8bpp_draw_##combine_op(index + 2, shift_mask, 16, alpha_op);           \ | 
|   | 317 |   tile_8bpp_draw_##combine_op(index + 3, shift, 24, alpha_op)                 \ | 
|   | 318 |  | 
|   | 319 |  | 
|   | 320 | // Like the above, but draws the half-tile horizontally flipped | 
|   | 321 |  | 
|   | 322 | #define tile_8bpp_draw_four_flip(index, combine_op, alpha_op)                 \ | 
|   | 323 |   tile_8bpp_draw_##combine_op(index + 3, mask, 0, alpha_op);                  \ | 
|   | 324 |   tile_8bpp_draw_##combine_op(index + 2, shift_mask, 8, alpha_op);            \ | 
|   | 325 |   tile_8bpp_draw_##combine_op(index + 1, shift_mask, 16, alpha_op);           \ | 
|   | 326 |   tile_8bpp_draw_##combine_op(index + 0, shift, 24, alpha_op)                 \ | 
|   | 327 |  | 
|   | 328 | #define tile_8bpp_draw_four_base(index, alpha_op, flip_op)                    \ | 
|   | 329 |   tile_8bpp_draw_four_##flip_op(index, base, alpha_op)                        \ | 
|   | 330 |  | 
|   | 331 |  | 
|   | 332 | // Draw half of a tile in 8bpp mode, for transparent renderer; as an | 
|   | 333 | // optimization the entire thing is checked against zero (in transparent | 
|   | 334 | // capable renders it is more likely for the pixels to be transparent than | 
|   | 335 | // opaque) | 
|   | 336 |  | 
|   | 337 | #define tile_8bpp_draw_four_transparent(index, alpha_op, flip_op)             \ | 
|   | 338 |   if(current_pixels != 0)                                                     \ | 
|   | 339 |   {                                                                           \ | 
|   | 340 |     tile_8bpp_draw_four_##flip_op(index, transparent, alpha_op);              \ | 
|   | 341 |   }                                                                           \ | 
|   | 342 |  | 
|   | 343 | #define tile_8bpp_draw_four_copy(index, alpha_op, flip_op)                    \ | 
|   | 344 |   if(current_pixels != 0)                                                     \ | 
|   | 345 |   {                                                                           \ | 
|   | 346 |     tile_8bpp_draw_four_##flip_op(index, copy, alpha_op);                     \ | 
|   | 347 |   }                                                                           \ | 
|   | 348 |  | 
|   | 349 | // Helper macro for drawing 8bpp tiles clipped against the edge of the screen | 
|   | 350 |  | 
|   | 351 | #define partial_tile_8bpp(combine_op, alpha_op)                               \ | 
|   | 352 |   for(i = 0; i < partial_tile_run; i++)                                       \ | 
|   | 353 |   {                                                                           \ | 
|   | 354 |     tile_8bpp_draw_##combine_op(0, mask, 0, alpha_op);                        \ | 
|   | 355 |     current_pixels >>= 8;                                                     \ | 
|   | 356 |     advance_dest_ptr_##combine_op(1);                                         \ | 
|   | 357 |   }                                                                           \ | 
|   | 358 |  | 
|   | 359 |  | 
|   | 360 | // Draws 8bpp tiles clipped against the left side of the screen, | 
|   | 361 | // partial_tile_offset indicates how much clipped in it is, partial_tile_run | 
|   | 362 | // indicates how much it should draw. | 
|   | 363 |  | 
|   | 364 | #define partial_tile_right_noflip_8bpp(combine_op, alpha_op)                  \ | 
|   | 365 |   if(partial_tile_offset >= 4)                                                \ | 
|   | 366 |   {                                                                           \ | 
|   | 367 |     current_pixels = *((u32 *)(tile_ptr + 4)) >>                              \ | 
|   | 368 |      ((partial_tile_offset - 4) * 8);                                         \ | 
|   | 369 |     partial_tile_8bpp(combine_op, alpha_op);                                  \ | 
|   | 370 |   }                                                                           \ | 
|   | 371 |   else                                                                        \ | 
|   | 372 |   {                                                                           \ | 
|   | 373 |     partial_tile_run -= 4;                                                    \ | 
|   | 374 |     current_pixels = *((u32 *)tile_ptr) >> (partial_tile_offset * 8);         \ | 
|   | 375 |     partial_tile_8bpp(combine_op, alpha_op);                                  \ | 
|   | 376 |     current_pixels = *((u32 *)(tile_ptr + 4));                                \ | 
|   | 377 |     tile_8bpp_draw_four_##combine_op(0, alpha_op, noflip);                    \ | 
|   | 378 |     advance_dest_ptr_##combine_op(4);                                         \ | 
|   | 379 |   }                                                                           \ | 
|   | 380 |  | 
|   | 381 |  | 
|   | 382 | // Draws 8bpp tiles clipped against both the left and right side of the | 
|   | 383 | // screen, IE, runs of less than 8 - partial_tile_offset. | 
|   | 384 |  | 
|   | 385 | #define partial_tile_mid_noflip_8bpp(combine_op, alpha_op)                    \ | 
|   | 386 |   if(partial_tile_offset >= 4)                                                \ | 
|   | 387 |   {                                                                           \ | 
|   | 388 |     current_pixels = *((u32 *)(tile_ptr + 4)) >>                              \ | 
|   | 389 |      ((partial_tile_offset - 4) * 8);                                         \ | 
|   | 390 |     partial_tile_8bpp(combine_op, alpha_op);                                  \ | 
|   | 391 |   }                                                                           \ | 
|   | 392 |   else                                                                        \ | 
|   | 393 |   {                                                                           \ | 
|   | 394 |     current_pixels = *((u32 *)tile_ptr) >> (partial_tile_offset * 8);         \ | 
|   | 395 |     if((partial_tile_offset + partial_tile_run) > 4)                          \ | 
|   | 396 |     {                                                                         \ | 
|   | 397 |       u32 old_run = partial_tile_run;                                         \ | 
|   | 398 |       partial_tile_run = 4 - partial_tile_offset;                             \ | 
|   | 399 |       partial_tile_8bpp(combine_op, alpha_op);                                \ | 
|   | 400 |       partial_tile_run = old_run - partial_tile_run;                          \ | 
|   | 401 |       current_pixels = *((u32 *)(tile_ptr + 4));                              \ | 
|   | 402 |       partial_tile_8bpp(combine_op, alpha_op);                                \ | 
|   | 403 |     }                                                                         \ | 
|   | 404 |     else                                                                      \ | 
|   | 405 |     {                                                                         \ | 
|   | 406 |       partial_tile_8bpp(combine_op, alpha_op);                                \ | 
|   | 407 |     }                                                                         \ | 
|   | 408 |   }                                                                           \ | 
|   | 409 |  | 
|   | 410 |  | 
|   | 411 | // Draws 8bpp tiles clipped against the right side of the screen, | 
|   | 412 | // partial_tile_run indicates how much there is to draw. | 
|   | 413 |  | 
|   | 414 | #define partial_tile_left_noflip_8bpp(combine_op, alpha_op)                   \ | 
|   | 415 |   if(partial_tile_run >= 4)                                                   \ | 
|   | 416 |   {                                                                           \ | 
|   | 417 |     current_pixels = *((u32 *)tile_ptr);                                      \ | 
|   | 418 |     tile_8bpp_draw_four_##combine_op(0, alpha_op, noflip);                    \ | 
|   | 419 |     advance_dest_ptr_##combine_op(4);                                         \ | 
|   | 420 |     tile_ptr += 4;                                                            \ | 
|   | 421 |     partial_tile_run -= 4;                                                    \ | 
|   | 422 |   }                                                                           \ | 
|   | 423 |                                                                               \ | 
|   | 424 |   current_pixels = *((u32 *)(tile_ptr));                                      \ | 
|   | 425 |   partial_tile_8bpp(combine_op, alpha_op)                                     \ | 
|   | 426 |  | 
|   | 427 |  | 
|   | 428 | // Draws a non-clipped (complete) 8bpp tile. | 
|   | 429 |  | 
|   | 430 | #define tile_noflip_8bpp(combine_op, alpha_op)                                \ | 
|   | 431 |   current_pixels = *((u32 *)tile_ptr);                                        \ | 
|   | 432 |   tile_8bpp_draw_four_##combine_op(0, alpha_op, noflip);                      \ | 
|   | 433 |   current_pixels = *((u32 *)(tile_ptr + 4));                                  \ | 
|   | 434 |   tile_8bpp_draw_four_##combine_op(4, alpha_op, noflip)                       \ | 
|   | 435 |  | 
|   | 436 |  | 
|   | 437 | // Like the above versions but draws flipped tiles. | 
|   | 438 |  | 
|   | 439 | #define partial_tile_flip_8bpp(combine_op, alpha_op)                          \ | 
|   | 440 |   for(i = 0; i < partial_tile_run; i++)                                       \ | 
|   | 441 |   {                                                                           \ | 
|   | 442 |     tile_8bpp_draw_##combine_op(0, shift, 24, alpha_op);                      \ | 
|   | 443 |     current_pixels <<= 8;                                                     \ | 
|   | 444 |     advance_dest_ptr_##combine_op(1);                                         \ | 
|   | 445 |   }                                                                           \ | 
|   | 446 |  | 
|   | 447 | #define partial_tile_right_flip_8bpp(combine_op, alpha_op)                    \ | 
|   | 448 |   if(partial_tile_offset >= 4)                                                \ | 
|   | 449 |   {                                                                           \ | 
|   | 450 |     current_pixels = *((u32 *)tile_ptr) << ((partial_tile_offset - 4) * 8);   \ | 
|   | 451 |     partial_tile_flip_8bpp(combine_op, alpha_op);                             \ | 
|   | 452 |   }                                                                           \ | 
|   | 453 |   else                                                                        \ | 
|   | 454 |   {                                                                           \ | 
|   | 455 |     partial_tile_run -= 4;                                                    \ | 
|   | 456 |     current_pixels = *((u32 *)(tile_ptr + 4)) <<                              \ | 
|   | 457 |      ((partial_tile_offset - 4) * 8);                                         \ | 
|   | 458 |     partial_tile_flip_8bpp(combine_op, alpha_op);                             \ | 
|   | 459 |     current_pixels = *((u32 *)tile_ptr);                                      \ | 
|   | 460 |     tile_8bpp_draw_four_##combine_op(0, alpha_op, flip);                      \ | 
|   | 461 |     advance_dest_ptr_##combine_op(4);                                         \ | 
|   | 462 |   }                                                                           \ | 
|   | 463 |  | 
|   | 464 | #define partial_tile_mid_flip_8bpp(combine_op, alpha_op)                      \ | 
|   | 465 |   if(partial_tile_offset >= 4)                                                \ | 
|   | 466 |   {                                                                           \ | 
|   | 467 |     current_pixels = *((u32 *)tile_ptr) << ((partial_tile_offset - 4) * 8);   \ | 
|   | 468 |     partial_tile_flip_8bpp(combine_op, alpha_op);                             \ | 
|   | 469 |   }                                                                           \ | 
|   | 470 |   else                                                                        \ | 
|   | 471 |   {                                                                           \ | 
|   | 472 |     current_pixels = *((u32 *)(tile_ptr + 4)) <<                              \ | 
|   | 473 |      ((partial_tile_offset - 4) * 8);                                         \ | 
|   | 474 |                                                                               \ | 
|   | 475 |     if((partial_tile_offset + partial_tile_run) > 4)                          \ | 
|   | 476 |     {                                                                         \ | 
|   | 477 |       u32 old_run = partial_tile_run;                                         \ | 
|   | 478 |       partial_tile_run = 4 - partial_tile_offset;                             \ | 
|   | 479 |       partial_tile_flip_8bpp(combine_op, alpha_op);                           \ | 
|   | 480 |       partial_tile_run = old_run - partial_tile_run;                          \ | 
|   | 481 |       current_pixels = *((u32 *)(tile_ptr));                                  \ | 
|   | 482 |       partial_tile_flip_8bpp(combine_op, alpha_op);                           \ | 
|   | 483 |     }                                                                         \ | 
|   | 484 |     else                                                                      \ | 
|   | 485 |     {                                                                         \ | 
|   | 486 |       partial_tile_flip_8bpp(combine_op, alpha_op);                           \ | 
|   | 487 |     }                                                                         \ | 
|   | 488 |   }                                                                           \ | 
|   | 489 |  | 
|   | 490 | #define partial_tile_left_flip_8bpp(combine_op, alpha_op)                     \ | 
|   | 491 |   if(partial_tile_run >= 4)                                                   \ | 
|   | 492 |   {                                                                           \ | 
|   | 493 |     current_pixels = *((u32 *)(tile_ptr + 4));                                \ | 
|   | 494 |     tile_8bpp_draw_four_##combine_op(0, alpha_op, flip);                      \ | 
|   | 495 |     advance_dest_ptr_##combine_op(4);                                         \ | 
|   | 496 |     tile_ptr -= 4;                                                            \ | 
|   | 497 |     partial_tile_run -= 4;                                                    \ | 
|   | 498 |   }                                                                           \ | 
|   | 499 |                                                                               \ | 
|   | 500 |   current_pixels = *((u32 *)(tile_ptr + 4));                                  \ | 
|   | 501 |   partial_tile_flip_8bpp(combine_op, alpha_op)                                \ | 
|   | 502 |  | 
|   | 503 | #define tile_flip_8bpp(combine_op, alpha_op)                                  \ | 
|   | 504 |   current_pixels = *((u32 *)(tile_ptr + 4));                                  \ | 
|   | 505 |   tile_8bpp_draw_four_##combine_op(0, alpha_op, flip);                        \ | 
|   | 506 |   current_pixels = *((u32 *)tile_ptr);                                        \ | 
|   | 507 |   tile_8bpp_draw_four_##combine_op(4, alpha_op, flip)                         \ | 
|   | 508 |  | 
|   | 509 |  | 
|   | 510 | // Operations for isolating 4bpp tiles in a 32bit block | 
|   | 511 |  | 
|   | 512 | #define tile_4bpp_pixel_op_mask(op_param)                                     \ | 
|   | 513 |   current_pixel = current_pixels & 0x0F                                       \ | 
|   | 514 |  | 
|   | 515 | #define tile_4bpp_pixel_op_shift_mask(shift)                                  \ | 
|   | 516 |   current_pixel = (current_pixels >> shift) & 0x0F                            \ | 
|   | 517 |  | 
|   | 518 | #define tile_4bpp_pixel_op_shift(shift)                                       \ | 
|   | 519 |   current_pixel = current_pixels >> shift                                     \ | 
|   | 520 |  | 
|   | 521 | #define tile_4bpp_pixel_op_none(op_param)                                     \ | 
|   | 522 |  | 
|   | 523 | // Draws a single 4bpp pixel as base, normal renderer; checks to see if the | 
|   | 524 | // pixel is zero because if so the current palette should not be applied. | 
|   | 525 | // These ifs can be replaced with a lookup table, may or may not be superior | 
|   | 526 | // this way, should be benchmarked. The lookup table would be from 0-255 | 
|   | 527 | // identity map except for multiples of 16, which would map to 0. | 
|   | 528 |  | 
|   | 529 | #define tile_4bpp_draw_base_normal(index)                                     \ | 
|   | 530 |   if(current_pixel)                                                           \ | 
|   | 531 |   {                                                                           \ | 
|   | 532 |     current_pixel |= current_palette;                                         \ | 
|   | 533 |     tile_expand_base_normal(index);                                           \ | 
|   | 534 |   }                                                                           \ | 
|   | 535 |   else                                                                        \ | 
|   | 536 |   {                                                                           \ | 
|   | 537 |     tile_expand_base_normal(index);                                           \ | 
|   | 538 |   }                                                                           \ | 
|   | 539 |  | 
|   | 540 |  | 
|   | 541 | #define tile_4bpp_draw_base_alpha(index)                                      \ | 
|   | 542 |   if(current_pixel)                                                           \ | 
|   | 543 |   {                                                                           \ | 
|   | 544 |     current_pixel |= current_palette;                                         \ | 
|   | 545 |     tile_expand_base_alpha(index);                                            \ | 
|   | 546 |   }                                                                           \ | 
|   | 547 |   else                                                                        \ | 
|   | 548 |   {                                                                           \ | 
|   | 549 |     tile_expand_base_bg(index);                                               \ | 
|   | 550 |   }                                                                           \ | 
|   | 551 |  | 
|   | 552 | #define tile_4bpp_draw_base_color16(index)                                    \ | 
|   | 553 |   tile_4bpp_draw_base_alpha(index)                                            \ | 
|   | 554 |  | 
|   | 555 | #define tile_4bpp_draw_base_color32(index)                                    \ | 
|   | 556 |   tile_4bpp_draw_base_alpha(index)                                            \ | 
|   | 557 |  | 
|   | 558 |  | 
|   | 559 | #define tile_4bpp_draw_base(index, op, op_param, alpha_op)                    \ | 
|   | 560 |   tile_4bpp_pixel_op_##op(op_param);                                          \ | 
|   | 561 |   tile_4bpp_draw_base_##alpha_op(index)                                       \ | 
|   | 562 |  | 
|   | 563 |  | 
|   | 564 | // Draws a single 4bpp pixel as layered, if not transparent. | 
|   | 565 |  | 
|   | 566 | #define tile_4bpp_draw_transparent(index, op, op_param, alpha_op)             \ | 
|   | 567 |   tile_4bpp_pixel_op_##op(op_param);                                          \ | 
|   | 568 |   if(current_pixel)                                                           \ | 
|   | 569 |   {                                                                           \ | 
|   | 570 |     current_pixel |= current_palette;                                         \ | 
|   | 571 |     tile_expand_transparent_##alpha_op(index);                                \ | 
|   | 572 |   }                                                                           \ | 
|   | 573 |  | 
|   | 574 | #define tile_4bpp_draw_copy(index, op, op_param, alpha_op)                    \ | 
|   | 575 |   tile_4bpp_pixel_op_##op(op_param);                                          \ | 
|   | 576 |   if(current_pixel)                                                           \ | 
|   | 577 |   {                                                                           \ | 
|   | 578 |     current_pixel |= current_palette;                                         \ | 
|   | 579 |     tile_expand_copy(index);                                                  \ | 
|   | 580 |   }                                                                           \ | 
|   | 581 |  | 
|   | 582 |  | 
|   | 583 | // Draws eight background pixels in transparent mode, for alpha or normal | 
|   | 584 | // renderers. | 
|   | 585 |  | 
|   | 586 | #define tile_4bpp_draw_eight_base_zero(value)                                 \ | 
|   | 587 |   dest_ptr[0] = value;                                                        \ | 
|   | 588 |   dest_ptr[1] = value;                                                        \ | 
|   | 589 |   dest_ptr[2] = value;                                                        \ | 
|   | 590 |   dest_ptr[3] = value;                                                        \ | 
|   | 591 |   dest_ptr[4] = value;                                                        \ | 
|   | 592 |   dest_ptr[5] = value;                                                        \ | 
|   | 593 |   dest_ptr[6] = value;                                                        \ | 
|   | 594 |   dest_ptr[7] = value                                                         \ | 
|   | 595 |  | 
|   | 596 |  | 
|   | 597 | // Draws eight background pixels for the alpha renderer, basically color zero | 
|   | 598 | // with the background flag high. | 
|   | 599 |  | 
|   | 600 | #define tile_4bpp_draw_eight_base_zero_alpha()                                \ | 
|   | 601 |   tile_4bpp_draw_eight_base_zero(bg_combine)                                  \ | 
|   | 602 |  | 
|   | 603 | #define tile_4bpp_draw_eight_base_zero_color16()                              \ | 
|   | 604 |   tile_4bpp_draw_eight_base_zero_alpha()                                      \ | 
|   | 605 |  | 
|   | 606 | #define tile_4bpp_draw_eight_base_zero_color32()                              \ | 
|   | 607 |   tile_4bpp_draw_eight_base_zero_alpha()                                      \ | 
|   | 608 |  | 
|   | 609 |  | 
|   | 610 | // Draws eight background pixels for the normal renderer, just a bunch of | 
|   | 611 | // zeros. | 
|   | 612 |  | 
|   | 613 | #ifdef RENDER_COLOR16_NORMAL | 
|   | 614 |  | 
|   | 615 | #define tile_4bpp_draw_eight_base_zero_normal()                               \ | 
|   | 616 |   current_pixel = 0;                                                          \ | 
|   | 617 |   tile_4bpp_draw_eight_base_zero(current_pixel)                               \ | 
|   | 618 |  | 
|   | 619 | #else | 
|   | 620 |  | 
|   | 621 | #define tile_4bpp_draw_eight_base_zero_normal()                               \ | 
|   | 622 |   current_pixel = palette[0];                                                 \ | 
|   | 623 |   tile_4bpp_draw_eight_base_zero(current_pixel)                               \ | 
|   | 624 |  | 
|   | 625 | #endif | 
|   | 626 |  | 
|   | 627 |  | 
|   | 628 | // Draws eight 4bpp pixels. | 
|   | 629 |  | 
|   | 630 | #define tile_4bpp_draw_eight_noflip(combine_op, alpha_op)                     \ | 
|   | 631 |   tile_4bpp_draw_##combine_op(0, mask, 0, alpha_op);                          \ | 
|   | 632 |   tile_4bpp_draw_##combine_op(1, shift_mask, 4, alpha_op);                    \ | 
|   | 633 |   tile_4bpp_draw_##combine_op(2, shift_mask, 8, alpha_op);                    \ | 
|   | 634 |   tile_4bpp_draw_##combine_op(3, shift_mask, 12, alpha_op);                   \ | 
|   | 635 |   tile_4bpp_draw_##combine_op(4, shift_mask, 16, alpha_op);                   \ | 
|   | 636 |   tile_4bpp_draw_##combine_op(5, shift_mask, 20, alpha_op);                   \ | 
|   | 637 |   tile_4bpp_draw_##combine_op(6, shift_mask, 24, alpha_op);                   \ | 
|   | 638 |   tile_4bpp_draw_##combine_op(7, shift, 28, alpha_op)                         \ | 
|   | 639 |  | 
|   | 640 |  | 
|   | 641 | // Draws eight 4bpp pixels in reverse order (for hflip). | 
|   | 642 |  | 
|   | 643 | #define tile_4bpp_draw_eight_flip(combine_op, alpha_op)                       \ | 
|   | 644 |   tile_4bpp_draw_##combine_op(7, mask, 0, alpha_op);                          \ | 
|   | 645 |   tile_4bpp_draw_##combine_op(6, shift_mask, 4, alpha_op);                    \ | 
|   | 646 |   tile_4bpp_draw_##combine_op(5, shift_mask, 8, alpha_op);                    \ | 
|   | 647 |   tile_4bpp_draw_##combine_op(4, shift_mask, 12, alpha_op);                   \ | 
|   | 648 |   tile_4bpp_draw_##combine_op(3, shift_mask, 16, alpha_op);                   \ | 
|   | 649 |   tile_4bpp_draw_##combine_op(2, shift_mask, 20, alpha_op);                   \ | 
|   | 650 |   tile_4bpp_draw_##combine_op(1, shift_mask, 24, alpha_op);                   \ | 
|   | 651 |   tile_4bpp_draw_##combine_op(0, shift, 28, alpha_op)                         \ | 
|   | 652 |  | 
|   | 653 |  | 
|   | 654 | // Draws eight 4bpp pixels in base mode, checks if all are zero, if so draws | 
|   | 655 | // the appropriate background pixels. | 
|   | 656 |  | 
|   | 657 | #define tile_4bpp_draw_eight_base(alpha_op, flip_op)                          \ | 
|   | 658 |   if(current_pixels != 0)                                                     \ | 
|   | 659 |   {                                                                           \ | 
|   | 660 |     tile_4bpp_draw_eight_##flip_op(base, alpha_op);                           \ | 
|   | 661 |   }                                                                           \ | 
|   | 662 |   else                                                                        \ | 
|   | 663 |   {                                                                           \ | 
|   | 664 |     tile_4bpp_draw_eight_base_zero_##alpha_op();                              \ | 
|   | 665 |   }                                                                           \ | 
|   | 666 |  | 
|   | 667 |  | 
|   | 668 | // Draws eight 4bpp pixels in transparent (layered) mode, checks if all are | 
|   | 669 | // zero and if so draws nothing. | 
|   | 670 |  | 
|   | 671 | #define tile_4bpp_draw_eight_transparent(alpha_op, flip_op)                   \ | 
|   | 672 |   if(current_pixels != 0)                                                     \ | 
|   | 673 |   {                                                                           \ | 
|   | 674 |     tile_4bpp_draw_eight_##flip_op(transparent, alpha_op);                    \ | 
|   | 675 |   }                                                                           \ | 
|   | 676 |  | 
|   | 677 |  | 
|   | 678 | #define tile_4bpp_draw_eight_copy(alpha_op, flip_op)                          \ | 
|   | 679 |   if(current_pixels != 0)                                                     \ | 
|   | 680 |   {                                                                           \ | 
|   | 681 |     tile_4bpp_draw_eight_##flip_op(copy, alpha_op);                           \ | 
|   | 682 |   }                                                                           \ | 
|   | 683 |  | 
|   | 684 | // Gets the current tile in 4bpp mode, also getting the current palette and | 
|   | 685 | // the pixel block. | 
|   | 686 |  | 
|   | 687 | #define get_tile_4bpp()                                                       \ | 
|   | 688 |   current_tile = *map_ptr;                                                    \ | 
|   | 689 |   current_palette = (current_tile >> 12) << 4;                                \ | 
|   | 690 |   tile_ptr = tile_base + ((current_tile & 0x3FF) * 32);                       \ | 
|   | 691 |  | 
|   | 692 |  | 
|   | 693 | // Helper macro for drawing clipped 4bpp tiles. | 
|   | 694 |  | 
|   | 695 | #define partial_tile_4bpp(combine_op, alpha_op)                               \ | 
|   | 696 |   for(i = 0; i < partial_tile_run; i++)                                       \ | 
|   | 697 |   {                                                                           \ | 
|   | 698 |     tile_4bpp_draw_##combine_op(0, mask, 0, alpha_op);                        \ | 
|   | 699 |     current_pixels >>= 4;                                                     \ | 
|   | 700 |     advance_dest_ptr_##combine_op(1);                                         \ | 
|   | 701 |   }                                                                           \ | 
|   | 702 |  | 
|   | 703 |  | 
|   | 704 | // Draws a 4bpp tile clipped against the left edge of the screen. | 
|   | 705 | // partial_tile_offset is how far in it's clipped, partial_tile_run is | 
|   | 706 | // how many to draw. | 
|   | 707 |  | 
|   | 708 | #define partial_tile_right_noflip_4bpp(combine_op, alpha_op)                  \ | 
|   | 709 |   current_pixels = *((u32 *)tile_ptr) >> (partial_tile_offset * 4);           \ | 
|   | 710 |   partial_tile_4bpp(combine_op, alpha_op)                                     \ | 
|   | 711 |  | 
|   | 712 |  | 
|   | 713 | // Draws a 4bpp tile clipped against both edges of the screen, same as right. | 
|   | 714 |  | 
|   | 715 | #define partial_tile_mid_noflip_4bpp(combine_op, alpha_op)                    \ | 
|   | 716 |   partial_tile_right_noflip_4bpp(combine_op, alpha_op)                        \ | 
|   | 717 |  | 
|   | 718 |  | 
|   | 719 | // Draws a 4bpp tile clipped against the right edge of the screen. | 
|   | 720 | // partial_tile_offset is how many to draw. | 
|   | 721 |  | 
|   | 722 | #define partial_tile_left_noflip_4bpp(combine_op, alpha_op)                   \ | 
|   | 723 |   current_pixels = *((u32 *)tile_ptr);                                        \ | 
|   | 724 |   partial_tile_4bpp(combine_op, alpha_op)                                     \ | 
|   | 725 |  | 
|   | 726 |  | 
|   | 727 | // Draws a complete 4bpp tile row (not clipped) | 
|   | 728 | #define tile_noflip_4bpp(combine_op, alpha_op)                                \ | 
|   | 729 |   current_pixels = *((u32 *)tile_ptr);                                        \ | 
|   | 730 |   tile_4bpp_draw_eight_##combine_op(alpha_op, noflip)                         \ | 
|   | 731 |  | 
|   | 732 |  | 
|   | 733 | // Like the above, but draws flipped tiles. | 
|   | 734 |  | 
|   | 735 | #define partial_tile_flip_4bpp(combine_op, alpha_op)                          \ | 
|   | 736 |   for(i = 0; i < partial_tile_run; i++)                                       \ | 
|   | 737 |   {                                                                           \ | 
|   | 738 |     tile_4bpp_draw_##combine_op(0, shift, 28, alpha_op);                      \ | 
|   | 739 |     current_pixels <<= 4;                                                     \ | 
|   | 740 |     advance_dest_ptr_##combine_op(1);                                         \ | 
|   | 741 |   }                                                                           \ | 
|   | 742 |  | 
|   | 743 | #define partial_tile_right_flip_4bpp(combine_op, alpha_op)                    \ | 
|   | 744 |   current_pixels = *((u32 *)tile_ptr) << (partial_tile_offset * 4);           \ | 
|   | 745 |   partial_tile_flip_4bpp(combine_op, alpha_op)                                \ | 
|   | 746 |  | 
|   | 747 | #define partial_tile_mid_flip_4bpp(combine_op, alpha_op)                      \ | 
|   | 748 |   partial_tile_right_flip_4bpp(combine_op, alpha_op)                          \ | 
|   | 749 |  | 
|   | 750 | #define partial_tile_left_flip_4bpp(combine_op, alpha_op)                     \ | 
|   | 751 |   current_pixels = *((u32 *)tile_ptr);                                        \ | 
|   | 752 |   partial_tile_flip_4bpp(combine_op, alpha_op)                                \ | 
|   | 753 |  | 
|   | 754 | #define tile_flip_4bpp(combine_op, alpha_op)                                  \ | 
|   | 755 |   current_pixels = *((u32 *)tile_ptr);                                        \ | 
|   | 756 |   tile_4bpp_draw_eight_##combine_op(alpha_op, flip)                           \ | 
|   | 757 |  | 
|   | 758 |  | 
|   | 759 | // Draws a single (partial or complete) tile from the tilemap, flipping | 
|   | 760 | // as necessary. | 
|   | 761 |  | 
|   | 762 | #define single_tile_map(tile_type, combine_op, color_depth, alpha_op)         \ | 
|   | 763 |   get_tile_##color_depth();                                                   \ | 
|   | 764 |   if(current_tile & 0x800)                                                    \ | 
|   | 765 |     tile_ptr += vertical_pixel_flip;                                          \ | 
|   | 766 |                                                                               \ | 
|   | 767 |   if(current_tile & 0x400)                                                    \ | 
|   | 768 |   {                                                                           \ | 
|   | 769 |     tile_type##_flip_##color_depth(combine_op, alpha_op);                     \ | 
|   | 770 |   }                                                                           \ | 
|   | 771 |   else                                                                        \ | 
|   | 772 |   {                                                                           \ | 
|   | 773 |     tile_type##_noflip_##color_depth(combine_op, alpha_op);                   \ | 
|   | 774 |   }                                                                           \ | 
|   | 775 |  | 
|   | 776 |  | 
|   | 777 | // Draws multiple sequential tiles from the tilemap, hflips and vflips as | 
|   | 778 | // necessary. | 
|   | 779 |  | 
|   | 780 | #define multiple_tile_map(combine_op, color_depth, alpha_op)                  \ | 
|   | 781 |   for(i = 0; i < tile_run; i++)                                               \ | 
|   | 782 |   {                                                                           \ | 
|   | 783 |     single_tile_map(tile, combine_op, color_depth, alpha_op);                 \ | 
|   | 784 |     advance_dest_ptr_##combine_op(8);                                         \ | 
|   | 785 |     map_ptr++;                                                                \ | 
|   | 786 |   }                                                                           \ | 
|   | 787 |  | 
|   | 788 | // Draws a partial tile from a tilemap clipped against the left edge of the | 
|   | 789 | // screen. | 
|   | 790 |  | 
|   | 791 | #define partial_tile_right_map(combine_op, color_depth, alpha_op)             \ | 
|   | 792 |   single_tile_map(partial_tile_right, combine_op, color_depth, alpha_op);     \ | 
|   | 793 |   map_ptr++                                                                   \ | 
|   | 794 |  | 
|   | 795 | // Draws a partial tile from a tilemap clipped against both edges of the | 
|   | 796 | // screen. | 
|   | 797 |  | 
|   | 798 | #define partial_tile_mid_map(combine_op, color_depth, alpha_op)               \ | 
|   | 799 |   single_tile_map(partial_tile_mid, combine_op, color_depth, alpha_op)        \ | 
|   | 800 |  | 
|   | 801 | // Draws a partial tile from a tilemap clipped against the right edge of the | 
|   | 802 | // screen. | 
|   | 803 |  | 
|   | 804 | #define partial_tile_left_map(combine_op, color_depth, alpha_op)              \ | 
|   | 805 |   single_tile_map(partial_tile_left, combine_op, color_depth, alpha_op)       \ | 
|   | 806 |  | 
|   | 807 |  | 
|   | 808 | // Advances a non-flipped 4bpp obj to the next tile. | 
|   | 809 |  | 
|   | 810 | #define obj_advance_noflip_4bpp()                                             \ | 
|   | 811 |   tile_ptr += 32                                                              \ | 
|   | 812 |  | 
|   | 813 |  | 
|   | 814 | // Advances a non-flipped 8bpp obj to the next tile. | 
|   | 815 |  | 
|   | 816 | #define obj_advance_noflip_8bpp()                                             \ | 
|   | 817 |   tile_ptr += 64                                                              \ | 
|   | 818 |  | 
|   | 819 |  | 
|   | 820 | // Advances a flipped 4bpp obj to the next tile. | 
|   | 821 |  | 
|   | 822 | #define obj_advance_flip_4bpp()                                               \ | 
|   | 823 |   tile_ptr -= 32                                                              \ | 
|   | 824 |  | 
|   | 825 |  | 
|   | 826 | // Advances a flipped 8bpp obj to the next tile. | 
|   | 827 |  | 
|   | 828 | #define obj_advance_flip_8bpp()                                               \ | 
|   | 829 |   tile_ptr -= 64                                                              \ | 
|   | 830 |  | 
|   | 831 |  | 
|   | 832 |  | 
|   | 833 | // Draws multiple sequential tiles from an obj, flip_op determines if it should | 
|   | 834 | // be flipped or not (set to flip or noflip) | 
|   | 835 |  | 
|   | 836 | #define multiple_tile_obj(combine_op, color_depth, alpha_op, flip_op)         \ | 
|   | 837 |   for(i = 0; i < tile_run; i++)                                               \ | 
|   | 838 |   {                                                                           \ | 
|   | 839 |     tile_##flip_op##_##color_depth(combine_op, alpha_op);                     \ | 
|   | 840 |     obj_advance_##flip_op##_##color_depth();                                  \ | 
|   | 841 |     advance_dest_ptr_##combine_op(8);                                         \ | 
|   | 842 |   }                                                                           \ | 
|   | 843 |  | 
|   | 844 |  | 
|   | 845 | // Draws an obj's tile clipped against the left side of the screen | 
|   | 846 |  | 
|   | 847 | #define partial_tile_right_obj(combine_op, color_depth, alpha_op, flip_op)    \ | 
|   | 848 |   partial_tile_right_##flip_op##_##color_depth(combine_op, alpha_op);         \ | 
|   | 849 |   obj_advance_##flip_op##_##color_depth()                                     \ | 
|   | 850 |  | 
|   | 851 | // Draws an obj's tile clipped against both sides of the screen | 
|   | 852 |  | 
|   | 853 | #define partial_tile_mid_obj(combine_op, color_depth, alpha_op, flip_op)      \ | 
|   | 854 |   partial_tile_mid_##flip_op##_##color_depth(combine_op, alpha_op)            \ | 
|   | 855 |  | 
|   | 856 | // Draws an obj's tile clipped against the right side of the screen | 
|   | 857 |  | 
|   | 858 | #define partial_tile_left_obj(combine_op, color_depth, alpha_op, flip_op)     \ | 
|   | 859 |   partial_tile_left_##flip_op##_##color_depth(combine_op, alpha_op)           \ | 
|   | 860 |  | 
|   | 861 |  | 
|   | 862 | // Extra variables specific for 8bpp/4bpp tile renderers. | 
|   | 863 |  | 
|   | 864 | #define tile_extra_variables_8bpp()                                           \ | 
|   | 865 |  | 
|   | 866 | #define tile_extra_variables_4bpp()                                           \ | 
|   | 867 |   u32 current_palette                                                         \ | 
|   | 868 |  | 
|   | 869 |  | 
|   | 870 | // Byte lengths of complete tiles and tile rows in 4bpp and 8bpp. | 
|   | 871 |  | 
|   | 872 | #define tile_width_4bpp 4 | 
|   | 873 | #define tile_size_4bpp 32 | 
|   | 874 | #define tile_width_8bpp 8 | 
|   | 875 | #define tile_size_8bpp 64 | 
|   | 876 |  | 
|   | 877 |  | 
|   | 878 | // Render a single scanline of text tiles | 
|   | 879 |  | 
|   | 880 | #define tile_render(color_depth, combine_op, alpha_op)                        \ | 
|   | 881 | {                                                                             \ | 
|   | 882 |   u32 vertical_pixel_offset = (vertical_offset % 8) *                         \ | 
|   | 883 |    tile_width_##color_depth;                                                  \ | 
|   | 884 |   u32 vertical_pixel_flip =                                                   \ | 
|   | 885 |    ((tile_size_##color_depth - tile_width_##color_depth) -                    \ | 
|   | 886 |    vertical_pixel_offset) - vertical_pixel_offset;                            \ | 
|   | 887 |   tile_extra_variables_##color_depth();                                       \ | 
|   | 888 |   u8 *tile_base = vram + (((bg_control >> 2) & 0x03) * (1024 * 16)) +         \ | 
|   | 889 |    vertical_pixel_offset;                                                     \ | 
|   | 890 |   u32 pixel_run = 256 - (horizontal_offset % 256);                            \ | 
|   | 891 |   u32 current_tile;                                                           \ | 
|   | 892 |                                                                               \ | 
|   | 893 |   map_base += ((vertical_offset % 256) / 8) * 32;                             \ | 
|   | 894 |   partial_tile_offset = (horizontal_offset % 8);                              \ | 
|   | 895 |                                                                               \ | 
|   | 896 |   if(pixel_run >= end)                                                        \ | 
|   | 897 |   {                                                                           \ | 
|   | 898 |     if(partial_tile_offset)                                                   \ | 
|   | 899 |     {                                                                         \ | 
|   | 900 |       partial_tile_run = 8 - partial_tile_offset;                             \ | 
|   | 901 |       if(end < partial_tile_run)                                              \ | 
|   | 902 |       {                                                                       \ | 
|   | 903 |         partial_tile_run = end;                                               \ | 
|   | 904 |         partial_tile_mid_map(combine_op, color_depth, alpha_op);              \ | 
|   | 905 |         return;                                                               \ | 
|   | 906 |       }                                                                       \ | 
|   | 907 |       else                                                                    \ | 
|   | 908 |       {                                                                       \ | 
|   | 909 |         end -= partial_tile_run;                                              \ | 
|   | 910 |         partial_tile_right_map(combine_op, color_depth, alpha_op);            \ | 
|   | 911 |       }                                                                       \ | 
|   | 912 |     }                                                                         \ | 
|   | 913 |                                                                               \ | 
|   | 914 |     tile_run = end / 8;                                                       \ | 
|   | 915 |     multiple_tile_map(combine_op, color_depth, alpha_op);                     \ | 
|   | 916 |                                                                               \ | 
|   | 917 |     partial_tile_run = end % 8;                                               \ | 
|   | 918 |                                                                               \ | 
|   | 919 |     if(partial_tile_run)                                                      \ | 
|   | 920 |     {                                                                         \ | 
|   | 921 |       partial_tile_left_map(combine_op, color_depth, alpha_op);               \ | 
|   | 922 |     }                                                                         \ | 
|   | 923 |   }                                                                           \ | 
|   | 924 |   else                                                                        \ | 
|   | 925 |   {                                                                           \ | 
|   | 926 |     if(partial_tile_offset)                                                   \ | 
|   | 927 |     {                                                                         \ | 
|   | 928 |       partial_tile_run = 8 - partial_tile_offset;                             \ | 
|   | 929 |       partial_tile_right_map(combine_op, color_depth, alpha_op);              \ | 
|   | 930 |     }                                                                         \ | 
|   | 931 |                                                                               \ | 
|   | 932 |     tile_run = (pixel_run - partial_tile_run) / 8;                            \ | 
|   | 933 |     multiple_tile_map(combine_op, color_depth, alpha_op);                     \ | 
|   | 934 |     map_ptr = second_ptr;                                                     \ | 
|   | 935 |     end -= pixel_run;                                                         \ | 
|   | 936 |     tile_run = end / 8;                                                       \ | 
|   | 937 |     multiple_tile_map(combine_op, color_depth, alpha_op);                     \ | 
|   | 938 |                                                                               \ | 
|   | 939 |     partial_tile_run = end % 8;                                               \ | 
|   | 940 |     if(partial_tile_run)                                                      \ | 
|   | 941 |     {                                                                         \ | 
|   | 942 |       partial_tile_left_map(combine_op, color_depth, alpha_op);               \ | 
|   | 943 |     }                                                                         \ | 
|   | 944 |   }                                                                           \ | 
|   | 945 | }                                                                             \ | 
|   | 946 |  | 
|   | 947 | #define render_scanline_dest_normal         u16 | 
|   | 948 | #define render_scanline_dest_alpha          u32 | 
|   | 949 | #define render_scanline_dest_alpha_obj      u32 | 
|   | 950 | #define render_scanline_dest_color16        u16 | 
|   | 951 | #define render_scanline_dest_color32        u32 | 
|   | 952 | #define render_scanline_dest_partial_alpha  u32 | 
|   | 953 | #define render_scanline_dest_copy_tile      u16 | 
|   | 954 | #define render_scanline_dest_copy_bitmap    u16 | 
|   | 955 |  | 
|   | 956 |  | 
|   | 957 | // If rendering a scanline that is not a target A then there's no point in | 
|   | 958 | // keeping what's underneath it because it can't blend with it. | 
|   | 959 |  | 
|   | 960 | #define render_scanline_skip_alpha(bg_type, combine_op)                       \ | 
|   | 961 |   if((pixel_combine & 0x00000200) == 0)                                       \ | 
|   | 962 |   {                                                                           \ | 
|   | 963 |     render_scanline_##bg_type##_##combine_op##_color32(layer,                 \ | 
|   | 964 |      start, end, scanline);                                                   \ | 
|   | 965 |     return;                                                                   \ | 
|   | 966 |   }                                                                           \ | 
|   | 967 |  | 
|   | 968 |  | 
|   | 969 | #ifdef RENDER_COLOR16_NORMAL | 
|   | 970 |  | 
|   | 971 | #define render_scanline_extra_variables_base_normal(bg_type)                  \ | 
|   | 972 |   const u32 pixel_combine = 0                                                 \ | 
|   | 973 |  | 
|   | 974 | #else | 
|   | 975 |  | 
|   | 976 | #define render_scanline_extra_variables_base_normal(bg_type)                  \ | 
|   | 977 |   u16 *palette = palette_ram_converted                                        \ | 
|   | 978 |  | 
|   | 979 | #endif | 
|   | 980 |  | 
|   | 981 |  | 
|   | 982 | #define render_scanline_extra_variables_base_alpha(bg_type)                   \ | 
|   | 983 |   u32 bg_combine = color_combine_mask(5);                                     \ | 
|   | 984 |   u32 pixel_combine = color_combine_mask(layer) | (bg_combine << 16);         \ | 
|   | 985 |   render_scanline_skip_alpha(bg_type, base)                                   \ | 
|   | 986 |  | 
|   | 987 | #define render_scanline_extra_variables_base_color()                          \ | 
|   | 988 |   u32 bg_combine = color_combine_mask(5);                                     \ | 
|   | 989 |   u32 pixel_combine = color_combine_mask(layer)                               \ | 
|   | 990 |  | 
|   | 991 | #define render_scanline_extra_variables_base_color16(bg_type)                 \ | 
|   | 992 |   render_scanline_extra_variables_base_color()                                \ | 
|   | 993 |  | 
|   | 994 | #define render_scanline_extra_variables_base_color32(bg_type)                 \ | 
|   | 995 |   render_scanline_extra_variables_base_color()                                \ | 
|   | 996 |  | 
|   | 997 |  | 
|   | 998 | #define render_scanline_extra_variables_transparent_normal(bg_type)           \ | 
|   | 999 |   render_scanline_extra_variables_base_normal(bg_type)                        \ | 
|   | 1000 |  | 
|   | 1001 | #define render_scanline_extra_variables_transparent_alpha(bg_type)            \ | 
|   | 1002 |   u32 pixel_combine = color_combine_mask(layer);                              \ | 
|   | 1003 |   render_scanline_skip_alpha(bg_type, transparent)                            \ | 
|   | 1004 |  | 
|   | 1005 | #define render_scanline_extra_variables_transparent_color()                   \ | 
|   | 1006 |   u32 pixel_combine = color_combine_mask(layer)                               \ | 
|   | 1007 |  | 
|   | 1008 | #define render_scanline_extra_variables_transparent_color16(bg_type)          \ | 
|   | 1009 |   render_scanline_extra_variables_transparent_color()                         \ | 
|   | 1010 |  | 
|   | 1011 | #define render_scanline_extra_variables_transparent_color32(bg_type)          \ | 
|   | 1012 |   render_scanline_extra_variables_transparent_color()                         \ | 
|   | 1013 |  | 
|   | 1014 |  | 
|   | 1015 |  | 
|   | 1016 |  | 
|   | 1017 | static const u32 map_widths[] = { 256, 512, 256, 512 }; | 
|   | 1018 |  | 
|   | 1019 | // Build text scanline rendering functions. | 
|   | 1020 |  | 
|   | 1021 | #define render_scanline_text_builder(combine_op, alpha_op)                    \ | 
|   | 1022 | static void render_scanline_text_##combine_op##_##alpha_op(u32 layer,         \ | 
|   | 1023 |  u32 start, u32 end, void *scanline)                                          \ | 
|   | 1024 | {                                                                             \ | 
|   | 1025 |   render_scanline_extra_variables_##combine_op##_##alpha_op(text);            \ | 
|   | 1026 |   u32 bg_control = io_registers[REG_BG0CNT + layer];                          \ | 
|   | 1027 |   u32 map_size = (bg_control >> 14) & 0x03;                                   \ | 
|   | 1028 |   u32 map_width = map_widths[map_size];                                       \ | 
|   | 1029 |   u32 horizontal_offset =                                                     \ | 
|   | 1030 |    (io_registers[REG_BG0HOFS + (layer * 2)] + start) % 512;                   \ | 
|   | 1031 |   u32 vertical_offset = (io_registers[REG_VCOUNT] +                           \ | 
|   | 1032 |    io_registers[REG_BG0VOFS + (layer * 2)]) % 512;                            \ | 
|   | 1033 |   u32 current_pixel;                                                          \ | 
|   | 1034 |   u32 current_pixels;                                                         \ | 
|   | 1035 |   u32 partial_tile_run = 0;                                                   \ | 
|   | 1036 |   u32 partial_tile_offset;                                                    \ | 
|   | 1037 |   u32 tile_run;                                                               \ | 
|   | 1038 |   u32 i;                                                                      \ | 
|   | 1039 |   render_scanline_dest_##alpha_op *dest_ptr =                                 \ | 
|   | 1040 |    ((render_scanline_dest_##alpha_op *)scanline) + start;                     \ | 
|   | 1041 |                                                                               \ | 
|   | 1042 |   u16 *map_base = (u16 *)(vram + ((bg_control >> 8) & 0x1F) * (1024 * 2));    \ | 
|   | 1043 |   u16 *map_ptr, *second_ptr;                                                  \ | 
|   | 1044 |   u8 *tile_ptr;                                                               \ | 
|   | 1045 |                                                                               \ | 
|   | 1046 |   end -= start;                                                               \ | 
|   | 1047 |                                                                               \ | 
|   | 1048 |   if((map_size & 0x02) && (vertical_offset >= 256))                           \ | 
|   | 1049 |   {                                                                           \ | 
|   | 1050 |     map_base += ((map_width / 8) * 32) +                                      \ | 
|   | 1051 |      (((vertical_offset - 256) / 8) * 32);                                    \ | 
|   | 1052 |   }                                                                           \ | 
|   | 1053 |   else                                                                        \ | 
|   | 1054 |   {                                                                           \ | 
|   | 1055 |     map_base += (((vertical_offset % 256) / 8) * 32);                         \ | 
|   | 1056 |   }                                                                           \ | 
|   | 1057 |                                                                               \ | 
|   | 1058 |   if(map_size & 0x01)                                                         \ | 
|   | 1059 |   {                                                                           \ | 
|   | 1060 |     if(horizontal_offset >= 256)                                              \ | 
|   | 1061 |     {                                                                         \ | 
|   | 1062 |       horizontal_offset -= 256;                                               \ | 
|   | 1063 |       map_ptr = map_base + (32 * 32) + (horizontal_offset / 8);               \ | 
|   | 1064 |       second_ptr = map_base;                                                  \ | 
|   | 1065 |     }                                                                         \ | 
|   | 1066 |     else                                                                      \ | 
|   | 1067 |     {                                                                         \ | 
|   | 1068 |       map_ptr = map_base + (horizontal_offset / 8);                           \ | 
|   | 1069 |       second_ptr = map_base + (32 * 32);                                      \ | 
|   | 1070 |     }                                                                         \ | 
|   | 1071 |   }                                                                           \ | 
|   | 1072 |   else                                                                        \ | 
|   | 1073 |   {                                                                           \ | 
|   | 1074 |     horizontal_offset %= 256;                                                 \ | 
|   | 1075 |     map_ptr = map_base + (horizontal_offset / 8);                             \ | 
|   | 1076 |     second_ptr = map_base;                                                    \ | 
|   | 1077 |   }                                                                           \ | 
|   | 1078 |                                                                               \ | 
|   | 1079 |   if(bg_control & 0x80)                                                       \ | 
|   | 1080 |   {                                                                           \ | 
|   | 1081 |     tile_render(8bpp, combine_op, alpha_op);                                  \ | 
|   | 1082 |   }                                                                           \ | 
|   | 1083 |   else                                                                        \ | 
|   | 1084 |   {                                                                           \ | 
|   | 1085 |     tile_render(4bpp, combine_op, alpha_op);                                  \ | 
|   | 1086 |   }                                                                           \ | 
|   | 1087 | }                                                                             \ | 
|   | 1088 |  | 
|   | 1089 | render_scanline_text_builder(base, normal); | 
|   | 1090 | render_scanline_text_builder(transparent, normal); | 
|   | 1091 | render_scanline_text_builder(base, color16); | 
|   | 1092 | render_scanline_text_builder(transparent, color16); | 
|   | 1093 | render_scanline_text_builder(base, color32); | 
|   | 1094 | render_scanline_text_builder(transparent, color32); | 
|   | 1095 | render_scanline_text_builder(base, alpha); | 
|   | 1096 | render_scanline_text_builder(transparent, alpha); | 
|   | 1097 |  | 
|   | 1098 |  | 
|   | 1099 | s32 affine_reference_x[2]; | 
|   | 1100 | s32 affine_reference_y[2]; | 
|   | 1101 |  | 
|   | 1102 | #define affine_render_bg_pixel_normal()                                       \ | 
|   | 1103 |   current_pixel = palette_ram_converted[0]                                    \ | 
|   | 1104 |  | 
|   | 1105 | #define affine_render_bg_pixel_alpha()                                        \ | 
|   | 1106 |   current_pixel = bg_combine                                                  \ | 
|   | 1107 |  | 
|   | 1108 | #define affine_render_bg_pixel_color16()                                      \ | 
|   | 1109 |   affine_render_bg_pixel_alpha()                                              \ | 
|   | 1110 |  | 
|   | 1111 | #define affine_render_bg_pixel_color32()                                      \ | 
|   | 1112 |   affine_render_bg_pixel_alpha()                                              \ | 
|   | 1113 |  | 
|   | 1114 | #define affine_render_bg_pixel_base(alpha_op)                                 \ | 
|   | 1115 |   affine_render_bg_pixel_##alpha_op()                                         \ | 
|   | 1116 |  | 
|   | 1117 | #define affine_render_bg_pixel_transparent(alpha_op)                          \ | 
|   | 1118 |  | 
|   | 1119 | #define affine_render_bg_pixel_copy(alpha_op)                                 \ | 
|   | 1120 |  | 
|   | 1121 | #define affine_render_bg_base(alpha_op)                                       \ | 
|   | 1122 |   dest_ptr[0] = current_pixel | 
|   | 1123 |  | 
|   | 1124 | #define affine_render_bg_transparent(alpha_op)                                \ | 
|   | 1125 |  | 
|   | 1126 | #define affine_render_bg_copy(alpha_op)                                       \ | 
|   | 1127 |  | 
|   | 1128 | #define affine_render_bg_remainder_base(alpha_op)                             \ | 
|   | 1129 |   affine_render_bg_pixel_##alpha_op();                                        \ | 
|   | 1130 |   for(; i < end; i++)                                                         \ | 
|   | 1131 |   {                                                                           \ | 
|   | 1132 |     affine_render_bg_base(alpha_op);                                          \ | 
|   | 1133 |     advance_dest_ptr_base(1);                                                 \ | 
|   | 1134 |   }                                                                           \ | 
|   | 1135 |  | 
|   | 1136 | #define affine_render_bg_remainder_transparent(alpha_op)                      \ | 
|   | 1137 |  | 
|   | 1138 | #define affine_render_bg_remainder_copy(alpha_op)                             \ | 
|   | 1139 |  | 
|   | 1140 | #define affine_render_next(combine_op)                                        \ | 
|   | 1141 |   source_x += dx;                                                             \ | 
|   | 1142 |   source_y += dy;                                                             \ | 
|   | 1143 |   advance_dest_ptr_##combine_op(1)                                            \ | 
|   | 1144 |  | 
|   | 1145 | #define affine_render_scale_offset()                                          \ | 
|   | 1146 |   tile_base += ((pixel_y % 8) * 8);                                           \ | 
|   | 1147 |   map_base += (pixel_y / 8) << map_pitch                                      \ | 
|   | 1148 |  | 
|   | 1149 | #define affine_render_scale_pixel(combine_op, alpha_op)                       \ | 
|   | 1150 |   map_offset = (pixel_x / 8);                                                 \ | 
|   | 1151 |   if(map_offset != last_map_offset)                                           \ | 
|   | 1152 |   {                                                                           \ | 
|   | 1153 |     tile_ptr = tile_base + (map_base[map_offset] * 64);                       \ | 
|   | 1154 |     last_map_offset = map_offset;                                             \ | 
|   | 1155 |   }                                                                           \ | 
|   | 1156 |   tile_ptr = tile_base + (map_base[(pixel_x / 8)] * 64);                      \ | 
|   | 1157 |   current_pixel = tile_ptr[(pixel_x % 8)];                                    \ | 
|   | 1158 |   tile_8bpp_draw_##combine_op(0, none, 0, alpha_op);                          \ | 
|   | 1159 |   affine_render_next(combine_op)                                              \ | 
|   | 1160 |  | 
|   | 1161 | #define affine_render_scale(combine_op, alpha_op)                             \ | 
|   | 1162 | {                                                                             \ | 
|   | 1163 |   pixel_y = source_y >> 8;                                                    \ | 
|   | 1164 |   u32 i = 0;                                                                  \ | 
|   | 1165 |   affine_render_bg_pixel_##combine_op(alpha_op);                              \ | 
|   | 1166 |   if((u32)pixel_y < (u32)width_height)                                        \ | 
|   | 1167 |   {                                                                           \ | 
|   | 1168 |     affine_render_scale_offset();                                             \ | 
|   | 1169 |     for(; i < end; i++)                                                       \ | 
|   | 1170 |     {                                                                         \ | 
|   | 1171 |       pixel_x = source_x >> 8;                                                \ | 
|   | 1172 |                                                                               \ | 
|   | 1173 |       if((u32)pixel_x < (u32)width_height)                                    \ | 
|   | 1174 |       {                                                                       \ | 
|   | 1175 |         break;                                                                \ | 
|   | 1176 |       }                                                                       \ | 
|   | 1177 |                                                                               \ | 
|   | 1178 |       affine_render_bg_##combine_op(alpha_op);                                \ | 
|   | 1179 |       affine_render_next(combine_op);                                         \ | 
|   | 1180 |     }                                                                         \ | 
|   | 1181 |                                                                               \ | 
|   | 1182 |     for(; i < end; i++)                                                       \ | 
|   | 1183 |     {                                                                         \ | 
|   | 1184 |       pixel_x = source_x >> 8;                                                \ | 
|   | 1185 |                                                                               \ | 
|   | 1186 |       if((u32)pixel_x >= (u32)width_height)                                   \ | 
|   | 1187 |         break;                                                                \ | 
|   | 1188 |                                                                               \ | 
|   | 1189 |       affine_render_scale_pixel(combine_op, alpha_op);                        \ | 
|   | 1190 |     }                                                                         \ | 
|   | 1191 |   }                                                                           \ | 
|   | 1192 |   affine_render_bg_remainder_##combine_op(alpha_op);                          \ | 
|   | 1193 | }                                                                             \ | 
|   | 1194 |  | 
|   | 1195 | #define affine_render_scale_wrap(combine_op, alpha_op)                        \ | 
|   | 1196 | {                                                                             \ | 
|   | 1197 |   u32 wrap_mask = width_height - 1;                                           \ | 
|   | 1198 |   pixel_y = (source_y >> 8) & wrap_mask;                                      \ | 
|   | 1199 |   if((u32)pixel_y < (u32)width_height)                                        \ | 
|   | 1200 |   {                                                                           \ | 
|   | 1201 |     affine_render_scale_offset();                                             \ | 
|   | 1202 |     for(i = 0; i < end; i++)                                                  \ | 
|   | 1203 |     {                                                                         \ | 
|   | 1204 |       pixel_x = (source_x >> 8) & wrap_mask;                                  \ | 
|   | 1205 |       affine_render_scale_pixel(combine_op, alpha_op);                        \ | 
|   | 1206 |     }                                                                         \ | 
|   | 1207 |   }                                                                           \ | 
|   | 1208 | }                                                                             \ | 
|   | 1209 |  | 
|   | 1210 |  | 
|   | 1211 | #define affine_render_rotate_pixel(combine_op, alpha_op)                      \ | 
|   | 1212 |   map_offset = (pixel_x / 8) + ((pixel_y / 8) << map_pitch);                  \ | 
|   | 1213 |   if(map_offset != last_map_offset)                                           \ | 
|   | 1214 |   {                                                                           \ | 
|   | 1215 |     tile_ptr = tile_base + (map_base[map_offset] * 64);                       \ | 
|   | 1216 |     last_map_offset = map_offset;                                             \ | 
|   | 1217 |   }                                                                           \ | 
|   | 1218 |                                                                               \ | 
|   | 1219 |   current_pixel = tile_ptr[(pixel_x % 8) + ((pixel_y % 8) * 8)];              \ | 
|   | 1220 |   tile_8bpp_draw_##combine_op(0, none, 0, alpha_op);                          \ | 
|   | 1221 |   affine_render_next(combine_op)                                              \ | 
|   | 1222 |  | 
|   | 1223 | #define affine_render_rotate(combine_op, alpha_op)                            \ | 
|   | 1224 | {                                                                             \ | 
|   | 1225 |   affine_render_bg_pixel_##combine_op(alpha_op);                              \ | 
|   | 1226 |   for(i = 0; i < end; i++)                                                    \ | 
|   | 1227 |   {                                                                           \ | 
|   | 1228 |     pixel_x = source_x >> 8;                                                  \ | 
|   | 1229 |     pixel_y = source_y >> 8;                                                  \ | 
|   | 1230 |                                                                               \ | 
|   | 1231 |     if(((u32)pixel_x < (u32)width_height) &&                                  \ | 
|   | 1232 |      ((u32)pixel_y < (u32)width_height))                                      \ | 
|   | 1233 |     {                                                                         \ | 
|   | 1234 |       break;                                                                  \ | 
|   | 1235 |     }                                                                         \ | 
|   | 1236 |     affine_render_bg_##combine_op(alpha_op);                                  \ | 
|   | 1237 |     affine_render_next(combine_op);                                           \ | 
|   | 1238 |   }                                                                           \ | 
|   | 1239 |                                                                               \ | 
|   | 1240 |   for(; i < end; i++)                                                         \ | 
|   | 1241 |   {                                                                           \ | 
|   | 1242 |     pixel_x = source_x >> 8;                                                  \ | 
|   | 1243 |     pixel_y = source_y >> 8;                                                  \ | 
|   | 1244 |                                                                               \ | 
|   | 1245 |     if(((u32)pixel_x >= (u32)width_height) ||                                 \ | 
|   | 1246 |      ((u32)pixel_y >= (u32)width_height))                                     \ | 
|   | 1247 |     {                                                                         \ | 
|   | 1248 |       affine_render_bg_remainder_##combine_op(alpha_op);                      \ | 
|   | 1249 |       break;                                                                  \ | 
|   | 1250 |     }                                                                         \ | 
|   | 1251 |                                                                               \ | 
|   | 1252 |     affine_render_rotate_pixel(combine_op, alpha_op);                         \ | 
|   | 1253 |   }                                                                           \ | 
|   | 1254 | }                                                                             \ | 
|   | 1255 |  | 
|   | 1256 | #define affine_render_rotate_wrap(combine_op, alpha_op)                       \ | 
|   | 1257 | {                                                                             \ | 
|   | 1258 |   u32 wrap_mask = width_height - 1;                                           \ | 
|   | 1259 |   for(i = 0; i < end; i++)                                                    \ | 
|   | 1260 |   {                                                                           \ | 
|   | 1261 |     pixel_x = (source_x >> 8) & wrap_mask;                                    \ | 
|   | 1262 |     pixel_y = (source_y >> 8) & wrap_mask;                                    \ | 
|   | 1263 |                                                                               \ | 
|   | 1264 |     affine_render_rotate_pixel(combine_op, alpha_op);                         \ | 
|   | 1265 |   }                                                                           \ | 
|   | 1266 | }                                                                             \ | 
|   | 1267 |  | 
|   | 1268 |  | 
|   | 1269 | // Build affine background renderers. | 
|   | 1270 |  | 
|   | 1271 | #define render_scanline_affine_builder(combine_op, alpha_op)                  \ | 
|   | 1272 | void render_scanline_affine_##combine_op##_##alpha_op(u32 layer,              \ | 
|   | 1273 |  u32 start, u32 end, void *scanline)                                          \ | 
|   | 1274 | {                                                                             \ | 
|   | 1275 |   render_scanline_extra_variables_##combine_op##_##alpha_op(affine);          \ | 
|   | 1276 |   u32 bg_control = io_registers[REG_BG0CNT + layer];                          \ | 
|   | 1277 |   u32 current_pixel;                                                          \ | 
|   | 1278 |   s32 source_x, source_y;                                                     \ | 
|   | 1279 |   u32 pixel_x, pixel_y;                                                       \ | 
|   | 1280 |   u32 layer_offset = (layer - 2) * 8;                                         \ | 
|   | 1281 |   s32 dx, dy;                                                                 \ | 
|   | 1282 |   u32 map_size = (bg_control >> 14) & 0x03;                                   \ | 
|   | 1283 |   u32 width_height = 1 << (7 + map_size);                                     \ | 
|   | 1284 |   u32 map_pitch = map_size + 4;                                               \ | 
|   | 1285 |   u8 *map_base = vram + (((bg_control >> 8) & 0x1F) * (1024 * 2));            \ | 
|   | 1286 |   u8 *tile_base = vram + (((bg_control >> 2) & 0x03) * (1024 * 16));          \ | 
|   | 1287 |   u8 *tile_ptr = NULL;                                                        \ | 
|   | 1288 |   u32 map_offset, last_map_offset = (u32)-1;                                  \ | 
|   | 1289 |   u32 i;                                                                      \ | 
|   | 1290 |   render_scanline_dest_##alpha_op *dest_ptr =                                 \ | 
|   | 1291 |    ((render_scanline_dest_##alpha_op *)scanline) + start;                     \ | 
|   | 1292 |                                                                               \ | 
|   | 1293 |   dx = (s16)io_registers[REG_BG2PA + layer_offset];                           \ | 
|   | 1294 |   dy = (s16)io_registers[REG_BG2PC + layer_offset];                           \ | 
|   | 1295 |   source_x = affine_reference_x[layer - 2] + (start * dx);                    \ | 
|   | 1296 |   source_y = affine_reference_y[layer - 2] + (start * dy);                    \ | 
|   | 1297 |                                                                               \ | 
|   | 1298 |   end -= start;                                                               \ | 
|   | 1299 |                                                                               \ | 
|   | 1300 |   switch(((bg_control >> 12) & 0x02) | (dy != 0))                             \ | 
|   | 1301 |   {                                                                           \ | 
|   | 1302 |     case 0x00:                                                                \ | 
|   | 1303 |       affine_render_scale(combine_op, alpha_op);                              \ | 
|   | 1304 |       break;                                                                  \ | 
|   | 1305 |                                                                               \ | 
|   | 1306 |     case 0x01:                                                                \ | 
|   | 1307 |       affine_render_rotate(combine_op, alpha_op);                             \ | 
|   | 1308 |       break;                                                                  \ | 
|   | 1309 |                                                                               \ | 
|   | 1310 |     case 0x02:                                                                \ | 
|   | 1311 |       affine_render_scale_wrap(combine_op, alpha_op);                         \ | 
|   | 1312 |       break;                                                                  \ | 
|   | 1313 |                                                                               \ | 
|   | 1314 |     case 0x03:                                                                \ | 
|   | 1315 |       affine_render_rotate_wrap(combine_op, alpha_op);                        \ | 
|   | 1316 |       break;                                                                  \ | 
|   | 1317 |   }                                                                           \ | 
|   | 1318 | }                                                                             \ | 
|   | 1319 |  | 
|   | 1320 | render_scanline_affine_builder(base, normal); | 
|   | 1321 | render_scanline_affine_builder(transparent, normal); | 
|   | 1322 | render_scanline_affine_builder(base, color16); | 
|   | 1323 | render_scanline_affine_builder(transparent, color16); | 
|   | 1324 | render_scanline_affine_builder(base, color32); | 
|   | 1325 | render_scanline_affine_builder(transparent, color32); | 
|   | 1326 | render_scanline_affine_builder(base, alpha); | 
|   | 1327 | render_scanline_affine_builder(transparent, alpha); | 
|   | 1328 |  | 
|   | 1329 |  | 
|   | 1330 | #define bitmap_render_pixel_mode3(alpha_op)                                   \ | 
|   | 1331 |   convert_palette(current_pixel);                                             \ | 
|   | 1332 |   *dest_ptr = current_pixel                                                   \ | 
|   | 1333 |  | 
|   | 1334 | #define bitmap_render_pixel_mode4(alpha_op)                                   \ | 
|   | 1335 |   tile_expand_base_##alpha_op(0)                                              \ | 
|   | 1336 |  | 
|   | 1337 | #define bitmap_render_pixel_mode5(alpha_op)                                   \ | 
|   | 1338 |   bitmap_render_pixel_mode3(alpha_op)                                         \ | 
|   | 1339 |  | 
|   | 1340 |  | 
|   | 1341 | #define bitmap_render_scale(type, alpha_op, width, height)                    \ | 
|   | 1342 |   pixel_y = (source_y >> 8);                                                  \ | 
|   | 1343 |   if((u32)pixel_y < (u32)height)                                              \ | 
|   | 1344 |   {                                                                           \ | 
|   | 1345 |     pixel_x = (source_x >> 8);                                                \ | 
|   | 1346 |     src_ptr += (pixel_y * width);                                             \ | 
|   | 1347 |     if(dx == 0x100)                                                           \ | 
|   | 1348 |     {                                                                         \ | 
|   | 1349 |       if(pixel_x < 0)                                                         \ | 
|   | 1350 |       {                                                                       \ | 
|   | 1351 |         end += pixel_x;                                                       \ | 
|   | 1352 |         dest_ptr -= pixel_x;                                                  \ | 
|   | 1353 |         pixel_x = 0;                                                          \ | 
|   | 1354 |       }                                                                       \ | 
|   | 1355 |       else                                                                    \ | 
|   | 1356 |                                                                               \ | 
|   | 1357 |       if(pixel_x > 0)                                                         \ | 
|   | 1358 |       {                                                                       \ | 
|   | 1359 |         src_ptr += pixel_x;                                                   \ | 
|   | 1360 |       }                                                                       \ | 
|   | 1361 |                                                                               \ | 
|   | 1362 |       if((pixel_x + end) >= width)                                            \ | 
|   | 1363 |         end = (width - pixel_x);                                              \ | 
|   | 1364 |                                                                               \ | 
|   | 1365 |       for(i = 0; (s32)i < (s32)end; i++)                                      \ | 
|   | 1366 |       {                                                                       \ | 
|   | 1367 |         current_pixel = *src_ptr;                                             \ | 
|   | 1368 |         bitmap_render_pixel_##type(alpha_op);                                 \ | 
|   | 1369 |         src_ptr++;                                                            \ | 
|   | 1370 |         dest_ptr++;                                                           \ | 
|   | 1371 |       }                                                                       \ | 
|   | 1372 |     }                                                                         \ | 
|   | 1373 |     else                                                                      \ | 
|   | 1374 |     {                                                                         \ | 
|   | 1375 |       if((u32)(source_y >> 8) < (u32)height)                                  \ | 
|   | 1376 |       {                                                                       \ | 
|   | 1377 |         for(i = 0; i < end; i++)                                              \ | 
|   | 1378 |         {                                                                     \ | 
|   | 1379 |           pixel_x = (source_x >> 8);                                          \ | 
|   | 1380 |                                                                               \ | 
|   | 1381 |           if((u32)pixel_x < (u32)width)                                       \ | 
|   | 1382 |             break;                                                            \ | 
|   | 1383 |                                                                               \ | 
|   | 1384 |           source_x += dx;                                                     \ | 
|   | 1385 |           dest_ptr++;                                                         \ | 
|   | 1386 |         }                                                                     \ | 
|   | 1387 |                                                                               \ | 
|   | 1388 |         for(; i < end; i++)                                                   \ | 
|   | 1389 |         {                                                                     \ | 
|   | 1390 |           pixel_x = (source_x >> 8);                                          \ | 
|   | 1391 |                                                                               \ | 
|   | 1392 |           if((u32)pixel_x >= (u32)width)                                      \ | 
|   | 1393 |             break;                                                            \ | 
|   | 1394 |                                                                               \ | 
|   | 1395 |           current_pixel = src_ptr[pixel_x];                                   \ | 
|   | 1396 |           bitmap_render_pixel_##type(alpha_op);                               \ | 
|   | 1397 |                                                                               \ | 
|   | 1398 |           source_x += dx;                                                     \ | 
|   | 1399 |           dest_ptr++;                                                         \ | 
|   | 1400 |         }                                                                     \ | 
|   | 1401 |       }                                                                       \ | 
|   | 1402 |     }                                                                         \ | 
|   | 1403 |   }                                                                           \ | 
|   | 1404 |  | 
|   | 1405 | #define bitmap_render_rotate(type, alpha_op, width, height)                   \ | 
|   | 1406 |   for(i = 0; i < end; i++)                                                    \ | 
|   | 1407 |   {                                                                           \ | 
|   | 1408 |     pixel_x = source_x >> 8;                                                  \ | 
|   | 1409 |     pixel_y = source_y >> 8;                                                  \ | 
|   | 1410 |                                                                               \ | 
|   | 1411 |     if(((u32)pixel_x < (u32)width) && ((u32)pixel_y < (u32)height))           \ | 
|   | 1412 |       break;                                                                  \ | 
|   | 1413 |                                                                               \ | 
|   | 1414 |     source_x += dx;                                                           \ | 
|   | 1415 |     source_y += dy;                                                           \ | 
|   | 1416 |     dest_ptr++;                                                               \ | 
|   | 1417 |   }                                                                           \ | 
|   | 1418 |                                                                               \ | 
|   | 1419 |   for(; i < end; i++)                                                         \ | 
|   | 1420 |   {                                                                           \ | 
|   | 1421 |     pixel_x = (source_x >> 8);                                                \ | 
|   | 1422 |     pixel_y = (source_y >> 8);                                                \ | 
|   | 1423 |                                                                               \ | 
|   | 1424 |     if(((u32)pixel_x >= (u32)width) || ((u32)pixel_y >= (u32)height))         \ | 
|   | 1425 |       break;                                                                  \ | 
|   | 1426 |                                                                               \ | 
|   | 1427 |     current_pixel = src_ptr[pixel_x + (pixel_y * width)];                     \ | 
|   | 1428 |      bitmap_render_pixel_##type(alpha_op);                                    \ | 
|   | 1429 |                                                                               \ | 
|   | 1430 |     source_x += dx;                                                           \ | 
|   | 1431 |     source_y += dy;                                                           \ | 
|   | 1432 |     dest_ptr++;                                                               \ | 
|   | 1433 |   }                                                                           \ | 
|   | 1434 |  | 
|   | 1435 |  | 
|   | 1436 | #define render_scanline_vram_setup_mode3()                                    \ | 
|   | 1437 |   u16 *src_ptr = (u16 *)vram                                                  \ | 
|   | 1438 |  | 
|   | 1439 | #define render_scanline_vram_setup_mode5()                                    \ | 
|   | 1440 |   u16 *src_ptr;                                                               \ | 
|   | 1441 |   if(io_registers[REG_DISPCNT] & 0x10)                                        \ | 
|   | 1442 |     src_ptr = (u16 *)(vram + 0xA000);                                         \ | 
|   | 1443 |   else                                                                        \ | 
|   | 1444 |     src_ptr = (u16 *)vram                                                     \ | 
|   | 1445 |  | 
|   | 1446 |  | 
|   | 1447 | #ifdef RENDER_COLOR16_NORMAL | 
|   | 1448 |  | 
|   | 1449 | #define render_scanline_vram_setup_mode4()                                    \ | 
|   | 1450 |   const u32 pixel_combine = 0;                                                \ | 
|   | 1451 |   u8 *src_ptr;                                                                \ | 
|   | 1452 |   if(io_registers[REG_DISPCNT] & 0x10)                                        \ | 
|   | 1453 |     src_ptr = vram + 0xA000;                                                  \ | 
|   | 1454 |   else                                                                        \ | 
|   | 1455 |     src_ptr = vram                                                            \ | 
|   | 1456 |  | 
|   | 1457 |  | 
|   | 1458 | #else | 
|   | 1459 |  | 
|   | 1460 | #define render_scanline_vram_setup_mode4()                                    \ | 
|   | 1461 |   u16 *palette = palette_ram_converted;                                       \ | 
|   | 1462 |   u8 *src_ptr;                                                                \ | 
|   | 1463 |   if(io_registers[REG_DISPCNT] & 0x10)                                        \ | 
|   | 1464 |     src_ptr = vram + 0xA000;                                                  \ | 
|   | 1465 |   else                                                                        \ | 
|   | 1466 |     src_ptr = vram                                                            \ | 
|   | 1467 |  | 
|   | 1468 | #endif | 
|   | 1469 |  | 
|   | 1470 |  | 
|   | 1471 |  | 
|   | 1472 | // Build bitmap scanline rendering functions. | 
|   | 1473 |  | 
|   | 1474 | #define render_scanline_bitmap_builder(type, alpha_op, width, height)         \ | 
|   | 1475 | static void render_scanline_bitmap_##type##_##alpha_op(u32 start, u32 end,    \ | 
|   | 1476 |  void *scanline)                                                              \ | 
|   | 1477 | {                                                                             \ | 
|   | 1478 |   u32 current_pixel;                                                          \ | 
|   | 1479 |   s32 source_x, source_y;                                                     \ | 
|   | 1480 |   s32 pixel_x, pixel_y;                                                       \ | 
|   | 1481 |                                                                               \ | 
|   | 1482 |   s32 dx = (s16)io_registers[REG_BG2PA];                                      \ | 
|   | 1483 |   s32 dy = (s16)io_registers[REG_BG2PC];                                      \ | 
|   | 1484 |                                                                               \ | 
|   | 1485 |   u32 i;                                                                      \ | 
|   | 1486 |                                                                               \ | 
|   | 1487 |   render_scanline_dest_##alpha_op *dest_ptr =                                 \ | 
|   | 1488 |    ((render_scanline_dest_##alpha_op *)scanline) + start;                     \ | 
|   | 1489 |   render_scanline_vram_setup_##type();                                        \ | 
|   | 1490 |                                                                               \ | 
|   | 1491 |   end -= start;                                                               \ | 
|   | 1492 |                                                                               \ | 
|   | 1493 |   source_x = affine_reference_x[0] + (start * dx);                            \ | 
|   | 1494 |   source_y = affine_reference_y[0] + (start * dy);                            \ | 
|   | 1495 |                                                                               \ | 
|   | 1496 |   if(dy == 0)                                                                 \ | 
|   | 1497 |   {                                                                           \ | 
|   | 1498 |     bitmap_render_scale(type, alpha_op, width, height);                       \ | 
|   | 1499 |   }                                                                           \ | 
|   | 1500 |   else                                                                        \ | 
|   | 1501 |   {                                                                           \ | 
|   | 1502 |     bitmap_render_rotate(type, alpha_op, width, height);                      \ | 
|   | 1503 |   }                                                                           \ | 
|   | 1504 | }                                                                             \ | 
|   | 1505 |  | 
|   | 1506 | render_scanline_bitmap_builder(mode3, normal, 240, 160); | 
|   | 1507 | render_scanline_bitmap_builder(mode4, normal, 240, 160); | 
|   | 1508 | render_scanline_bitmap_builder(mode5, normal, 160, 128); | 
|   | 1509 |  | 
|   | 1510 |  | 
|   | 1511 | // Fill in the renderers for a layer based on the mode type, | 
|   | 1512 |  | 
|   | 1513 | #define tile_layer_render_functions(type)                                     \ | 
|   | 1514 | {                                                                             \ | 
|   | 1515 |   render_scanline_##type##_base_normal,                                       \ | 
|   | 1516 |   render_scanline_##type##_transparent_normal,                                \ | 
|   | 1517 |   render_scanline_##type##_base_alpha,                                        \ | 
|   | 1518 |   render_scanline_##type##_transparent_alpha,                                 \ | 
|   | 1519 |   render_scanline_##type##_base_color16,                                      \ | 
|   | 1520 |   render_scanline_##type##_transparent_color16,                               \ | 
|   | 1521 |   render_scanline_##type##_base_color32,                                      \ | 
|   | 1522 |   render_scanline_##type##_transparent_color32                                \ | 
|   | 1523 | }                                                                             \ | 
|   | 1524 |  | 
|   | 1525 |  | 
|   | 1526 | // Use if a layer is unsupported for that mode. | 
|   | 1527 |  | 
|   | 1528 | #define tile_layer_render_null()                                              \ | 
|   | 1529 | {                                                                             \ | 
|   | 1530 |   NULL, NULL, NULL, NULL                                                      \ | 
|   | 1531 | }                                                                             \ | 
|   | 1532 |  | 
|   | 1533 | #define bitmap_layer_render_functions(type)                                   \ | 
|   | 1534 | {                                                                             \ | 
|   | 1535 |   render_scanline_bitmap_##type##_normal                                      \ | 
|   | 1536 | }                                                                             \ | 
|   | 1537 |  | 
|   | 1538 | // Structs containing functions to render the layers for each mode, for | 
|   | 1539 | // each render type. | 
|   | 1540 | static const tile_layer_render_struct tile_mode_renderers[3][4] = | 
|   | 1541 | { | 
|   | 1542 |   { | 
|   | 1543 |     tile_layer_render_functions(text), tile_layer_render_functions(text), | 
|   | 1544 |     tile_layer_render_functions(text), tile_layer_render_functions(text) | 
|   | 1545 |   }, | 
|   | 1546 |   { | 
|   | 1547 |     tile_layer_render_functions(text), tile_layer_render_functions(text), | 
|   | 1548 |     tile_layer_render_functions(affine), tile_layer_render_functions(text) | 
|   | 1549 |   }, | 
|   | 1550 |   { | 
|   | 1551 |     tile_layer_render_functions(text), tile_layer_render_functions(text), | 
|   | 1552 |     tile_layer_render_functions(affine), tile_layer_render_functions(affine) | 
|   | 1553 |   } | 
|   | 1554 | }; | 
|   | 1555 |  | 
|   | 1556 | static const bitmap_layer_render_struct bitmap_mode_renderers[3] = | 
|   | 1557 | { | 
|   | 1558 |   bitmap_layer_render_functions(mode3), | 
|   | 1559 |   bitmap_layer_render_functions(mode4), | 
|   | 1560 |   bitmap_layer_render_functions(mode5) | 
|   | 1561 | }; | 
|   | 1562 |  | 
|   | 1563 |  | 
|   | 1564 | #define render_scanline_layer_functions_tile()                                \ | 
|   | 1565 |   const tile_layer_render_struct *layer_renderers =                           \ | 
|   | 1566 |    tile_mode_renderers[dispcnt & 0x07]                                        \ | 
|   | 1567 |  | 
|   | 1568 | #define render_scanline_layer_functions_bitmap()                              \ | 
|   | 1569 |   const bitmap_layer_render_struct *layer_renderers =                         \ | 
|   | 1570 |    bitmap_mode_renderers + ((dispcnt & 0x07) - 3)                             \ | 
|   | 1571 |  | 
|   | 1572 |  | 
|   | 1573 | // Adjust a flipped obj's starting position | 
|   | 1574 |  | 
|   | 1575 | #define obj_tile_offset_noflip(color_depth)                                   \ | 
|   | 1576 |  | 
|   | 1577 | #define obj_tile_offset_flip(color_depth)                                     \ | 
|   | 1578 |   + (tile_size_##color_depth * ((obj_width - 8) / 8))                         \ | 
|   | 1579 |  | 
|   | 1580 |  | 
|   | 1581 | // Adjust the obj's starting point if it goes too far off the left edge of | 
|   | 1582 | // the screen. | 
|   | 1583 |  | 
|   | 1584 | #define obj_tile_right_offset_noflip(color_depth)                             \ | 
|   | 1585 |   tile_ptr += (partial_tile_offset / 8) * tile_size_##color_depth             \ | 
|   | 1586 |  | 
|   | 1587 | #define obj_tile_right_offset_flip(color_depth)                               \ | 
|   | 1588 |   tile_ptr -= (partial_tile_offset / 8) * tile_size_##color_depth             \ | 
|   | 1589 |  | 
|   | 1590 | // Get the current row offset into an obj in 1D map space | 
|   | 1591 |  | 
|   | 1592 | #define obj_tile_offset_1D(color_depth, flip_op)                              \ | 
|   | 1593 |   tile_ptr = tile_base + ((obj_attribute_2 & 0x3FF) * 32)                     \ | 
|   | 1594 |    + ((vertical_offset / 8) * (obj_width / 8) * tile_size_##color_depth)      \ | 
|   | 1595 |    + ((vertical_offset % 8) * tile_width_##color_depth)                       \ | 
|   | 1596 |    obj_tile_offset_##flip_op(color_depth)                                     \ | 
|   | 1597 |  | 
|   | 1598 | // Get the current row offset into an obj in 2D map space | 
|   | 1599 |  | 
|   | 1600 | #define obj_tile_offset_2D(color_depth, flip_op)                              \ | 
|   | 1601 |   tile_ptr = tile_base + ((obj_attribute_2 & 0x3FF) * 32)                     \ | 
|   | 1602 |    + ((vertical_offset / 8) * 1024)                                           \ | 
|   | 1603 |    + ((vertical_offset % 8) * tile_width_##color_depth)                       \ | 
|   | 1604 |    obj_tile_offset_##flip_op(color_depth)                                     \ | 
|   | 1605 |  | 
|   | 1606 |  | 
|   | 1607 | // Get the palette for 4bpp obj. | 
|   | 1608 |  | 
|   | 1609 | #define obj_get_palette_4bpp()                                                \ | 
|   | 1610 |   current_palette = (obj_attribute_2 >> 8) & 0xF0                             \ | 
|   | 1611 |  | 
|   | 1612 | #define obj_get_palette_8bpp()                                                \ | 
|   | 1613 |  | 
|   | 1614 |  | 
|   | 1615 | // Render the current row of an obj. | 
|   | 1616 |  | 
|   | 1617 | #define obj_render(combine_op, color_depth, alpha_op, map_space, flip_op)     \ | 
|   | 1618 | {                                                                             \ | 
|   | 1619 |   obj_get_palette_##color_depth();                                            \ | 
|   | 1620 |   obj_tile_offset_##map_space(color_depth, flip_op);                          \ | 
|   | 1621 |                                                                               \ | 
|   | 1622 |   if(obj_x < (s32)start)                                                      \ | 
|   | 1623 |   {                                                                           \ | 
|   | 1624 |     dest_ptr = scanline + start;                                              \ | 
|   | 1625 |     pixel_run = obj_width - (start - obj_x);                                  \ | 
|   | 1626 |     if((s32)pixel_run > 0)                                                    \ | 
|   | 1627 |     {                                                                         \ | 
|   | 1628 |       if((obj_x + obj_width) >= end)                                          \ | 
|   | 1629 |       {                                                                       \ | 
|   | 1630 |         pixel_run = end - start;                                              \ | 
|   | 1631 |         partial_tile_offset = start - obj_x;                                  \ | 
|   | 1632 |         obj_tile_right_offset_##flip_op(color_depth);                         \ | 
|   | 1633 |         partial_tile_offset %= 8;                                             \ | 
|   | 1634 |                                                                               \ | 
|   | 1635 |         if(partial_tile_offset)                                               \ | 
|   | 1636 |         {                                                                     \ | 
|   | 1637 |           partial_tile_run = 8 - partial_tile_offset;                         \ | 
|   | 1638 |           if((s32)pixel_run < (s32)partial_tile_run)                          \ | 
|   | 1639 |           {                                                                   \ | 
|   | 1640 |             if((s32)pixel_run > 0)                                            \ | 
|   | 1641 |             {                                                                 \ | 
|   | 1642 |               partial_tile_run = pixel_run;                                   \ | 
|   | 1643 |               partial_tile_mid_obj(combine_op, color_depth, alpha_op,         \ | 
|   | 1644 |                flip_op);                                                      \ | 
|   | 1645 |             }                                                                 \ | 
|   | 1646 |             continue;                                                         \ | 
|   | 1647 |           }                                                                   \ | 
|   | 1648 |           else                                                                \ | 
|   | 1649 |           {                                                                   \ | 
|   | 1650 |             pixel_run -= partial_tile_run;                                    \ | 
|   | 1651 |             partial_tile_right_obj(combine_op, color_depth, alpha_op,         \ | 
|   | 1652 |              flip_op);                                                        \ | 
|   | 1653 |           }                                                                   \ | 
|   | 1654 |         }                                                                     \ | 
|   | 1655 |         tile_run = pixel_run / 8;                                             \ | 
|   | 1656 |         multiple_tile_obj(combine_op, color_depth, alpha_op, flip_op);        \ | 
|   | 1657 |         partial_tile_run = pixel_run % 8;                                     \ | 
|   | 1658 |         if(partial_tile_run)                                                  \ | 
|   | 1659 |         {                                                                     \ | 
|   | 1660 |           partial_tile_left_obj(combine_op, color_depth, alpha_op,            \ | 
|   | 1661 |            flip_op);                                                          \ | 
|   | 1662 |         }                                                                     \ | 
|   | 1663 |       }                                                                       \ | 
|   | 1664 |       else                                                                    \ | 
|   | 1665 |       {                                                                       \ | 
|   | 1666 |         partial_tile_offset = start - obj_x;                                  \ | 
|   | 1667 |         obj_tile_right_offset_##flip_op(color_depth);                         \ | 
|   | 1668 |         partial_tile_offset %= 8;                                             \ | 
|   | 1669 |         if(partial_tile_offset)                                               \ | 
|   | 1670 |         {                                                                     \ | 
|   | 1671 |           partial_tile_run = 8 - partial_tile_offset;                         \ | 
|   | 1672 |           partial_tile_right_obj(combine_op, color_depth, alpha_op,           \ | 
|   | 1673 |            flip_op);                                                          \ | 
|   | 1674 |         }                                                                     \ | 
|   | 1675 |         tile_run = pixel_run / 8;                                             \ | 
|   | 1676 |         multiple_tile_obj(combine_op, color_depth, alpha_op, flip_op);        \ | 
|   | 1677 |       }                                                                       \ | 
|   | 1678 |     }                                                                         \ | 
|   | 1679 |   }                                                                           \ | 
|   | 1680 |   else                                                                        \ | 
|   | 1681 |                                                                               \ | 
|   | 1682 |   if((obj_x + obj_width) >= end)                                              \ | 
|   | 1683 |   {                                                                           \ | 
|   | 1684 |     pixel_run = end - obj_x;                                                  \ | 
|   | 1685 |     if((s32)pixel_run > 0)                                                    \ | 
|   | 1686 |     {                                                                         \ | 
|   | 1687 |       dest_ptr = scanline + obj_x;                                            \ | 
|   | 1688 |       tile_run = pixel_run / 8;                                               \ | 
|   | 1689 |       multiple_tile_obj(combine_op, color_depth, alpha_op, flip_op);          \ | 
|   | 1690 |       partial_tile_run = pixel_run % 8;                                       \ | 
|   | 1691 |       if(partial_tile_run)                                                    \ | 
|   | 1692 |       {                                                                       \ | 
|   | 1693 |         partial_tile_left_obj(combine_op, color_depth, alpha_op, flip_op);    \ | 
|   | 1694 |       }                                                                       \ | 
|   | 1695 |     }                                                                         \ | 
|   | 1696 |   }                                                                           \ | 
|   | 1697 |   else                                                                        \ | 
|   | 1698 |   {                                                                           \ | 
|   | 1699 |     dest_ptr = scanline + obj_x;                                              \ | 
|   | 1700 |     tile_run = obj_width / 8;                                                 \ | 
|   | 1701 |     multiple_tile_obj(combine_op, color_depth, alpha_op, flip_op);            \ | 
|   | 1702 |   }                                                                           \ | 
|   | 1703 | }                                                                             \ | 
|   | 1704 |  | 
|   | 1705 | #define obj_scale_offset_1D(color_depth)                                      \ | 
|   | 1706 |   tile_ptr = tile_base + ((obj_attribute_2 & 0x3FF) * 32)                     \ | 
|   | 1707 |    + ((vertical_offset / 8) * (max_x / 8) * tile_size_##color_depth)          \ | 
|   | 1708 |    + ((vertical_offset % 8) * tile_width_##color_depth)                       \ | 
|   | 1709 |  | 
|   | 1710 | // Get the current row offset into an obj in 2D map space | 
|   | 1711 |  | 
|   | 1712 | #define obj_scale_offset_2D(color_depth)                                      \ | 
|   | 1713 |   tile_ptr = tile_base + ((obj_attribute_2 & 0x3FF) * 32)                     \ | 
|   | 1714 |    + ((vertical_offset / 8) * 1024)                                           \ | 
|   | 1715 |    + ((vertical_offset % 8) * tile_width_##color_depth)                       \ | 
|   | 1716 |  | 
|   | 1717 | #define obj_render_scale_pixel_4bpp(combine_op, alpha_op)                     \ | 
|   | 1718 |   if(tile_x & 0x01)                                                           \ | 
|   | 1719 |   {                                                                           \ | 
|   | 1720 |     current_pixel = tile_ptr[tile_map_offset + ((tile_x >> 1) & 0x03)] >> 4;  \ | 
|   | 1721 |   }                                                                           \ | 
|   | 1722 |   else                                                                        \ | 
|   | 1723 |   {                                                                           \ | 
|   | 1724 |     current_pixel =                                                           \ | 
|   | 1725 |      tile_ptr[tile_map_offset + ((tile_x >> 1) & 0x03)] & 0x0F;               \ | 
|   | 1726 |   }                                                                           \ | 
|   | 1727 |                                                                               \ | 
|   | 1728 |   tile_4bpp_draw_##combine_op(0, none, 0, alpha_op)                           \ | 
|   | 1729 |  | 
|   | 1730 |  | 
|   | 1731 | #define obj_render_scale_pixel_8bpp(combine_op, alpha_op)                     \ | 
|   | 1732 |   current_pixel = tile_ptr[tile_map_offset + (tile_x & 0x07)];                \ | 
|   | 1733 |   tile_8bpp_draw_##combine_op(0, none, 0, alpha_op);                          \ | 
|   | 1734 |  | 
|   | 1735 | #define obj_render_scale(combine_op, color_depth, alpha_op, map_space)        \ | 
|   | 1736 | {                                                                             \ | 
|   | 1737 |   u32 vertical_offset;                                                        \ | 
|   | 1738 |   source_y += (y_delta * dmy);                                                \ | 
|   | 1739 |   vertical_offset = (source_y >> 8);                                          \ | 
|   | 1740 |   if((u32)vertical_offset < (u32)max_y)                                       \ | 
|   | 1741 |   {                                                                           \ | 
|   | 1742 |     obj_scale_offset_##map_space(color_depth);                                \ | 
|   | 1743 |     source_x += (y_delta * dmx) - (middle_x * dx);                            \ | 
|   | 1744 |                                                                               \ | 
|   | 1745 |     for(i = 0; i < obj_width; i++)                                            \ | 
|   | 1746 |     {                                                                         \ | 
|   | 1747 |       tile_x = (source_x >> 8);                                               \ | 
|   | 1748 |                                                                               \ | 
|   | 1749 |       if((u32)tile_x < (u32)max_x)                                            \ | 
|   | 1750 |         break;                                                                \ | 
|   | 1751 |                                                                               \ | 
|   | 1752 |       source_x += dx;                                                         \ | 
|   | 1753 |       advance_dest_ptr_##combine_op(1);                                       \ | 
|   | 1754 |     }                                                                         \ | 
|   | 1755 |                                                                               \ | 
|   | 1756 |     for(; i < obj_width; i++)                                                 \ | 
|   | 1757 |     {                                                                         \ | 
|   | 1758 |       tile_x = (source_x >> 8);                                               \ | 
|   | 1759 |                                                                               \ | 
|   | 1760 |       if((u32)tile_x >= (u32)max_x)                                           \ | 
|   | 1761 |         break;                                                                \ | 
|   | 1762 |                                                                               \ | 
|   | 1763 |       tile_map_offset = (tile_x >> 3) * tile_size_##color_depth;              \ | 
|   | 1764 |       obj_render_scale_pixel_##color_depth(combine_op, alpha_op);             \ | 
|   | 1765 |                                                                               \ | 
|   | 1766 |       source_x += dx;                                                         \ | 
|   | 1767 |       advance_dest_ptr_##combine_op(1);                                       \ | 
|   | 1768 |     }                                                                         \ | 
|   | 1769 |   }                                                                           \ | 
|   | 1770 | }                                                                             \ | 
|   | 1771 |  | 
|   | 1772 |  | 
|   | 1773 | #define obj_rotate_offset_1D(color_depth)                                     \ | 
|   | 1774 |   obj_tile_pitch = (max_x / 8) * tile_size_##color_depth                      \ | 
|   | 1775 |  | 
|   | 1776 | #define obj_rotate_offset_2D(color_depth)                                     \ | 
|   | 1777 |   obj_tile_pitch = 1024                                                       \ | 
|   | 1778 |  | 
|   | 1779 | #define obj_render_rotate_pixel_4bpp(combine_op, alpha_op)                    \ | 
|   | 1780 |   if(tile_x & 0x01)                                                           \ | 
|   | 1781 |   {                                                                           \ | 
|   | 1782 |     current_pixel = tile_ptr[tile_map_offset +                                \ | 
|   | 1783 |      ((tile_x >> 1) & 0x03) + ((tile_y & 0x07) * obj_pitch)] >> 4;            \ | 
|   | 1784 |   }                                                                           \ | 
|   | 1785 |   else                                                                        \ | 
|   | 1786 |   {                                                                           \ | 
|   | 1787 |     current_pixel = tile_ptr[tile_map_offset +                                \ | 
|   | 1788 |      ((tile_x >> 1) & 0x03) + ((tile_y & 0x07) * obj_pitch)] & 0x0F;          \ | 
|   | 1789 |   }                                                                           \ | 
|   | 1790 |                                                                               \ | 
|   | 1791 |   tile_4bpp_draw_##combine_op(0, none, 0, alpha_op)                           \ | 
|   | 1792 |  | 
|   | 1793 | #define obj_render_rotate_pixel_8bpp(combine_op, alpha_op)                    \ | 
|   | 1794 |   current_pixel = tile_ptr[tile_map_offset +                                  \ | 
|   | 1795 |    (tile_x & 0x07) + ((tile_y & 0x07) * obj_pitch)];                          \ | 
|   | 1796 |                                                                               \ | 
|   | 1797 |   tile_8bpp_draw_##combine_op(0, none, 0, alpha_op)                           \ | 
|   | 1798 |  | 
|   | 1799 | #define obj_render_rotate(combine_op, color_depth, alpha_op, map_space)       \ | 
|   | 1800 | {                                                                             \ | 
|   | 1801 |   tile_ptr = tile_base + ((obj_attribute_2 & 0x3FF) * 32);                    \ | 
|   | 1802 |   obj_rotate_offset_##map_space(color_depth);                                 \ | 
|   | 1803 |                                                                               \ | 
|   | 1804 |   source_x += (y_delta * dmx) - (middle_x * dx);                              \ | 
|   | 1805 |   source_y += (y_delta * dmy) - (middle_x * dy);                              \ | 
|   | 1806 |                                                                               \ | 
|   | 1807 |   for(i = 0; i < obj_width; i++)                                              \ | 
|   | 1808 |   {                                                                           \ | 
|   | 1809 |     tile_x = (source_x >> 8);                                                 \ | 
|   | 1810 |     tile_y = (source_y >> 8);                                                 \ | 
|   | 1811 |                                                                               \ | 
|   | 1812 |     if(((u32)tile_x < (u32)max_x) && ((u32)tile_y < (u32)max_y))              \ | 
|   | 1813 |       break;                                                                  \ | 
|   | 1814 |                                                                               \ | 
|   | 1815 |     source_x += dx;                                                           \ | 
|   | 1816 |     source_y += dy;                                                           \ | 
|   | 1817 |     advance_dest_ptr_##combine_op(1);                                         \ | 
|   | 1818 |   }                                                                           \ | 
|   | 1819 |                                                                               \ | 
|   | 1820 |   for(; i < obj_width; i++)                                                   \ | 
|   | 1821 |   {                                                                           \ | 
|   | 1822 |     tile_x = (source_x >> 8);                                                 \ | 
|   | 1823 |     tile_y = (source_y >> 8);                                                 \ | 
|   | 1824 |                                                                               \ | 
|   | 1825 |     if(((u32)tile_x >= (u32)max_x) || ((u32)tile_y >= (u32)max_y))            \ | 
|   | 1826 |       break;                                                                  \ | 
|   | 1827 |                                                                               \ | 
|   | 1828 |     tile_map_offset = ((tile_x >> 3) * tile_size_##color_depth) +             \ | 
|   | 1829 |     ((tile_y >> 3) * obj_tile_pitch);                                         \ | 
|   | 1830 |     obj_render_rotate_pixel_##color_depth(combine_op, alpha_op);              \ | 
|   | 1831 |                                                                               \ | 
|   | 1832 |     source_x += dx;                                                           \ | 
|   | 1833 |     source_y += dy;                                                           \ | 
|   | 1834 |     advance_dest_ptr_##combine_op(1);                                         \ | 
|   | 1835 |   }                                                                           \ | 
|   | 1836 | }                                                                             \ | 
|   | 1837 |  | 
|   | 1838 | // Render the current row of an affine transformed OBJ. | 
|   | 1839 |  | 
|   | 1840 | #define obj_render_affine(combine_op, color_depth, alpha_op, map_space)       \ | 
|   | 1841 | {                                                                             \ | 
|   | 1842 |   s16 *params = (s16 *)oam_ram + (((obj_attribute_1 >> 9) & 0x1F) * 16);      \ | 
|   | 1843 |   s32 dx = params[3];                                                         \ | 
|   | 1844 |   s32 dmx = params[7];                                                        \ | 
|   | 1845 |   s32 dy = params[11];                                                        \ | 
|   | 1846 |   s32 dmy = params[15];                                                       \ | 
|   | 1847 |   s32 source_x, source_y;                                                     \ | 
|   | 1848 |   s32 tile_x, tile_y;                                                         \ | 
|   | 1849 |   u32 tile_map_offset;                                                        \ | 
|   | 1850 |   s32 middle_x;                                                               \ | 
|   | 1851 |   s32 middle_y;                                                               \ | 
|   | 1852 |   s32 max_x = obj_width;                                                      \ | 
|   | 1853 |   s32 max_y = obj_height;                                                     \ | 
|   | 1854 |   s32 y_delta;                                                                \ | 
|   | 1855 |   u32 obj_pitch = tile_width_##color_depth;                                   \ | 
|   | 1856 |   u32 obj_tile_pitch;                                                         \ | 
|   | 1857 |                                                                               \ | 
|   | 1858 |   middle_x = (obj_width / 2);                                                 \ | 
|   | 1859 |   middle_y = (obj_height / 2);                                                \ | 
|   | 1860 |                                                                               \ | 
|   | 1861 |   source_x = (middle_x << 8);                                                 \ | 
|   | 1862 |   source_y = (middle_y << 8);                                                 \ | 
|   | 1863 |                                                                               \ | 
|   | 1864 |                                                                               \ | 
|   | 1865 |   if(obj_attribute_0 & 0x200)                                                 \ | 
|   | 1866 |   {                                                                           \ | 
|   | 1867 |     obj_width *= 2;                                                           \ | 
|   | 1868 |     obj_height *= 2;                                                          \ | 
|   | 1869 |     middle_x *= 2;                                                            \ | 
|   | 1870 |     middle_y *= 2;                                                            \ | 
|   | 1871 |   }                                                                           \ | 
|   | 1872 |                                                                               \ | 
|   | 1873 |   if((s32)obj_x < (s32)start)                                                 \ | 
|   | 1874 |   {                                                                           \ | 
|   | 1875 |     u32 x_delta = start - obj_x;                                              \ | 
|   | 1876 |     middle_x -= x_delta;                                                      \ | 
|   | 1877 |     obj_width -= x_delta;                                                     \ | 
|   | 1878 |     obj_x = start;                                                            \ | 
|   | 1879 |                                                                               \ | 
|   | 1880 |     if((s32)obj_width <= 0)                                                   \ | 
|   | 1881 |       continue;                                                               \ | 
|   | 1882 |   }                                                                           \ | 
|   | 1883 |                                                                               \ | 
|   | 1884 |   if((s32)(obj_x + obj_width) >= (s32)end)                                    \ | 
|   | 1885 |   {                                                                           \ | 
|   | 1886 |     obj_width = end - obj_x;                                                  \ | 
|   | 1887 |                                                                               \ | 
|   | 1888 |     if((s32)obj_width <= 0)                                                   \ | 
|   | 1889 |       continue;                                                               \ | 
|   | 1890 |   }                                                                           \ | 
|   | 1891 |   dest_ptr = scanline + obj_x;                                                \ | 
|   | 1892 |                                                                               \ | 
|   | 1893 |   y_delta = vcount - (obj_y + middle_y);                                      \ | 
|   | 1894 |                                                                               \ | 
|   | 1895 |   obj_get_palette_##color_depth();                                            \ | 
|   | 1896 |                                                                               \ | 
|   | 1897 |   if(dy == 0)                                                                 \ | 
|   | 1898 |   {                                                                           \ | 
|   | 1899 |     obj_render_scale(combine_op, color_depth, alpha_op, map_space);           \ | 
|   | 1900 |   }                                                                           \ | 
|   | 1901 |   else                                                                        \ | 
|   | 1902 |   {                                                                           \ | 
|   | 1903 |     obj_render_rotate(combine_op, color_depth, alpha_op, map_space);          \ | 
|   | 1904 |   }                                                                           \ | 
|   | 1905 | }                                                                             \ | 
|   | 1906 |  | 
|   | 1907 | static const u32 obj_width_table[] = | 
|   | 1908 |   { 8, 16, 32, 64, 16, 32, 32, 64, 8, 8, 16, 32 }; | 
|   | 1909 | static const u32 obj_height_table[] = | 
|   | 1910 |   { 8, 16, 32, 64, 8, 8, 16, 32, 16, 32, 32, 64 }; | 
|   | 1911 |  | 
|   | 1912 | static u8 obj_priority_list[5][160][128]; | 
|   | 1913 | static u32 obj_priority_count[5][160]; | 
|   | 1914 | static u32 obj_alpha_count[160]; | 
|   | 1915 |  | 
|   | 1916 |  | 
|   | 1917 | // Build obj rendering functions | 
|   | 1918 |  | 
|   | 1919 | #ifdef RENDER_COLOR16_NORMAL | 
|   | 1920 |  | 
|   | 1921 | #define render_scanline_obj_extra_variables_normal(bg_type)                   \ | 
|   | 1922 |   const u32 pixel_combine = (1 << 8)                                          \ | 
|   | 1923 |  | 
|   | 1924 | #else | 
|   | 1925 |  | 
|   | 1926 | #define render_scanline_obj_extra_variables_normal(bg_type)                   \ | 
|   | 1927 |   u16 *palette = palette_ram_converted + 256                                  \ | 
|   | 1928 |  | 
|   | 1929 | #endif | 
|   | 1930 |  | 
|   | 1931 |  | 
|   | 1932 | #define render_scanline_obj_extra_variables_color()                           \ | 
|   | 1933 |   u32 pixel_combine = color_combine_mask(4) | (1 << 8)                        \ | 
|   | 1934 |  | 
|   | 1935 | #define render_scanline_obj_extra_variables_alpha_obj(map_space)              \ | 
|   | 1936 |   render_scanline_obj_extra_variables_color();                                \ | 
|   | 1937 |   u32 dest;                                                                   \ | 
|   | 1938 |   if((pixel_combine & 0x00000200) == 0)                                       \ | 
|   | 1939 |   {                                                                           \ | 
|   | 1940 |     render_scanline_obj_color32_##map_space(priority, start, end, scanline);  \ | 
|   | 1941 |     return;                                                                   \ | 
|   | 1942 |   }                                                                           \ | 
|   | 1943 |  | 
|   | 1944 | #define render_scanline_obj_extra_variables_color16(map_space)                \ | 
|   | 1945 |   render_scanline_obj_extra_variables_color()                                 \ | 
|   | 1946 |  | 
|   | 1947 | #define render_scanline_obj_extra_variables_color32(map_space)                \ | 
|   | 1948 |   render_scanline_obj_extra_variables_color()                                 \ | 
|   | 1949 |  | 
|   | 1950 | #define render_scanline_obj_extra_variables_partial_alpha(map_space)          \ | 
|   | 1951 |   render_scanline_obj_extra_variables_color();                                \ | 
|   | 1952 |   u32 base_pixel_combine = pixel_combine;                                     \ | 
|   | 1953 |   u32 dest                                                                    \ | 
|   | 1954 |  | 
|   | 1955 | #define render_scanline_obj_extra_variables_copy(type)                        \ | 
|   | 1956 |   u32 bldcnt = io_registers[REG_BLDCNT];                                      \ | 
|   | 1957 |   u32 dispcnt = io_registers[REG_DISPCNT];                                    \ | 
|   | 1958 |   u32 obj_enable = io_registers[REG_WINOUT] >> 8;                             \ | 
|   | 1959 |   render_scanline_layer_functions_##type();                                   \ | 
|   | 1960 |   u32 copy_start, copy_end;                                                   \ | 
|   | 1961 |   u16 copy_buffer[240];                                                       \ | 
|   | 1962 |   u16 *copy_ptr                                                               \ | 
|   | 1963 |  | 
|   | 1964 | #define render_scanline_obj_extra_variables_copy_tile(map_space)              \ | 
|   | 1965 |   render_scanline_obj_extra_variables_copy(tile)                              \ | 
|   | 1966 |  | 
|   | 1967 | #define render_scanline_obj_extra_variables_copy_bitmap(map_space)            \ | 
|   | 1968 |   render_scanline_obj_extra_variables_copy(bitmap)                            \ | 
|   | 1969 |  | 
|   | 1970 |  | 
|   | 1971 | #define render_scanline_obj_main(combine_op, alpha_op, map_space)             \ | 
|   | 1972 |   if(obj_attribute_0 & 0x100)                                                 \ | 
|   | 1973 |   {                                                                           \ | 
|   | 1974 |     if((obj_attribute_0 >> 13) & 0x01)                                        \ | 
|   | 1975 |     {                                                                         \ | 
|   | 1976 |       obj_render_affine(combine_op, 8bpp, alpha_op, map_space);               \ | 
|   | 1977 |     }                                                                         \ | 
|   | 1978 |     else                                                                      \ | 
|   | 1979 |     {                                                                         \ | 
|   | 1980 |       obj_render_affine(combine_op, 4bpp, alpha_op, map_space);               \ | 
|   | 1981 |     }                                                                         \ | 
|   | 1982 |   }                                                                           \ | 
|   | 1983 |   else                                                                        \ | 
|   | 1984 |   {                                                                           \ | 
|   | 1985 |     vertical_offset = vcount - obj_y;                                         \ | 
|   | 1986 |                                                                               \ | 
|   | 1987 |     if((obj_attribute_1 >> 13) & 0x01)                                        \ | 
|   | 1988 |       vertical_offset = obj_height - vertical_offset - 1;                     \ | 
|   | 1989 |                                                                               \ | 
|   | 1990 |     switch(((obj_attribute_0 >> 12) & 0x02) |                                 \ | 
|   | 1991 |      ((obj_attribute_1 >> 12) & 0x01))                                        \ | 
|   | 1992 |     {                                                                         \ | 
|   | 1993 |       case 0x0:                                                               \ | 
|   | 1994 |         obj_render(combine_op, 4bpp, alpha_op, map_space, noflip);            \ | 
|   | 1995 |         break;                                                                \ | 
|   | 1996 |                                                                               \ | 
|   | 1997 |       case 0x1:                                                               \ | 
|   | 1998 |         obj_render(combine_op, 4bpp, alpha_op, map_space, flip);              \ | 
|   | 1999 |         break;                                                                \ | 
|   | 2000 |                                                                               \ | 
|   | 2001 |       case 0x2:                                                               \ | 
|   | 2002 |         obj_render(combine_op, 8bpp, alpha_op, map_space, noflip);            \ | 
|   | 2003 |         break;                                                                \ | 
|   | 2004 |                                                                               \ | 
|   | 2005 |       case 0x3:                                                               \ | 
|   | 2006 |         obj_render(combine_op, 8bpp, alpha_op, map_space, flip);              \ | 
|   | 2007 |         break;                                                                \ | 
|   | 2008 |     }                                                                         \ | 
|   | 2009 |   }                                                                           \ | 
|   | 2010 |  | 
|   | 2011 | #define render_scanline_obj_no_partial_alpha(combine_op, alpha_op, map_space) \ | 
|   | 2012 |   render_scanline_obj_main(combine_op, alpha_op, map_space)                   \ | 
|   | 2013 |  | 
|   | 2014 | #define render_scanline_obj_partial_alpha(combine_op, alpha_op, map_space)    \ | 
|   | 2015 |   if((obj_attribute_0 >> 10) & 0x03)                                          \ | 
|   | 2016 |   {                                                                           \ | 
|   | 2017 |     pixel_combine = 0x00000300;                                               \ | 
|   | 2018 |     render_scanline_obj_main(combine_op, alpha_obj, map_space);               \ | 
|   | 2019 |   }                                                                           \ | 
|   | 2020 |   else                                                                        \ | 
|   | 2021 |   {                                                                           \ | 
|   | 2022 |     pixel_combine = base_pixel_combine;                                       \ | 
|   | 2023 |     render_scanline_obj_main(combine_op, color32, map_space);                 \ | 
|   | 2024 |   }                                                                           \ | 
|   | 2025 |  | 
|   | 2026 | #define render_scanline_obj_prologue_transparent(alpha_op)                    \ | 
|   | 2027 |  | 
|   | 2028 | #define render_scanline_obj_prologue_copy_body(type)                          \ | 
|   | 2029 |   copy_start = obj_x;                                                         \ | 
|   | 2030 |   if(obj_attribute_0 & 0x200)                                                 \ | 
|   | 2031 |     copy_end = obj_x + (obj_width * 2);                                       \ | 
|   | 2032 |   else                                                                        \ | 
|   | 2033 |     copy_end = obj_x + obj_width;                                             \ | 
|   | 2034 |                                                                               \ | 
|   | 2035 |   if(copy_start < start)                                                      \ | 
|   | 2036 |     copy_start = start;                                                       \ | 
|   | 2037 |   if(copy_end > end)                                                          \ | 
|   | 2038 |     copy_end = end;                                                           \ | 
|   | 2039 |                                                                               \ | 
|   | 2040 |   if((copy_start < end) && (copy_end > start))                                \ | 
|   | 2041 |   {                                                                           \ | 
|   | 2042 |     render_scanline_conditional_##type(copy_start, copy_end, copy_buffer,     \ | 
|   | 2043 |      obj_enable, dispcnt, bldcnt, layer_renderers);                           \ | 
|   | 2044 |     copy_ptr = copy_buffer + copy_start;                                      \ | 
|   | 2045 |   }                                                                           \ | 
|   | 2046 |   else                                                                        \ | 
|   | 2047 |   {                                                                           \ | 
|   | 2048 |     continue;                                                                 \ | 
|   | 2049 |   }                                                                           \ | 
|   | 2050 |  | 
|   | 2051 | #define render_scanline_obj_prologue_copy_tile()                              \ | 
|   | 2052 |   render_scanline_obj_prologue_copy_body(tile)                                \ | 
|   | 2053 |  | 
|   | 2054 | #define render_scanline_obj_prologue_copy_bitmap()                            \ | 
|   | 2055 |   render_scanline_obj_prologue_copy_body(bitmap)                              \ | 
|   | 2056 |  | 
|   | 2057 | #define render_scanline_obj_prologue_copy(alpha_op)                           \ | 
|   | 2058 |   render_scanline_obj_prologue_##alpha_op()                                   \ | 
|   | 2059 |  | 
|   | 2060 |  | 
|   | 2061 | #define render_scanline_obj_builder(combine_op, alpha_op, map_space,          \ | 
|   | 2062 |  partial_alpha_op)                                                            \ | 
|   | 2063 | static void render_scanline_obj_##alpha_op##_##map_space(u32 priority,        \ | 
|   | 2064 |  u32 start, u32 end, render_scanline_dest_##alpha_op *scanline)               \ | 
|   | 2065 | {                                                                             \ | 
|   | 2066 |   render_scanline_obj_extra_variables_##alpha_op(map_space);                  \ | 
|   | 2067 |   s32 obj_num, i;                                                             \ | 
|   | 2068 |   s32 obj_x, obj_y;                                                           \ | 
|   | 2069 |   s32 obj_size;                                                               \ | 
|   | 2070 |   s32 obj_width, obj_height;                                                  \ | 
|   | 2071 |   u32 obj_attribute_0, obj_attribute_1, obj_attribute_2;                      \ | 
|   | 2072 |   s32 vcount = io_registers[REG_VCOUNT];                                      \ | 
|   | 2073 |   u32 tile_run;                                                               \ | 
|   | 2074 |   u32 current_pixels;                                                         \ | 
|   | 2075 |   u32 current_pixel;                                                          \ | 
|   | 2076 |   u32 current_palette;                                                        \ | 
|   | 2077 |   u32 vertical_offset;                                                        \ | 
|   | 2078 |   u32 partial_tile_run, partial_tile_offset;                                  \ | 
|   | 2079 |   u32 pixel_run;                                                              \ | 
|   | 2080 |   u16 *oam_ptr;                                                               \ | 
|   | 2081 |   render_scanline_dest_##alpha_op *dest_ptr;                                  \ | 
|   | 2082 |   u8 *tile_base = vram + 0x10000;                                             \ | 
|   | 2083 |   u8 *tile_ptr;                                                               \ | 
|   | 2084 |   u32 obj_count = obj_priority_count[priority][vcount];                       \ | 
|   | 2085 |   u8 *obj_list = obj_priority_list[priority][vcount];                         \ | 
|   | 2086 |                                                                               \ | 
|   | 2087 |   for(obj_num = 0; obj_num < obj_count; obj_num++)                            \ | 
|   | 2088 |   {                                                                           \ | 
|   | 2089 |     oam_ptr = oam_ram + (obj_list[obj_num] * 4);                              \ | 
|   | 2090 |     obj_attribute_0 = oam_ptr[0];                                             \ | 
|   | 2091 |     obj_attribute_1 = oam_ptr[1];                                             \ | 
|   | 2092 |     obj_attribute_2 = oam_ptr[2];                                             \ | 
|   | 2093 |     obj_size = ((obj_attribute_0 >> 12) & 0x0C) | (obj_attribute_1 >> 14);    \ | 
|   | 2094 |                                                                               \ | 
|   | 2095 |     obj_x = (s32)(obj_attribute_1 << 23) >> 23;                               \ | 
|   | 2096 |     obj_width = obj_width_table[obj_size];                                    \ | 
|   | 2097 |                                                                               \ | 
|   | 2098 |     render_scanline_obj_prologue_##combine_op(alpha_op);                      \ | 
|   | 2099 |                                                                               \ | 
|   | 2100 |     obj_y = obj_attribute_0 & 0xFF;                                           \ | 
|   | 2101 |                                                                               \ | 
|   | 2102 |     if(obj_y > 160)                                                           \ | 
|   | 2103 |       obj_y -= 256;                                                           \ | 
|   | 2104 |                                                                               \ | 
|   | 2105 |     obj_height = obj_height_table[obj_size];                                  \ | 
|   | 2106 |     render_scanline_obj_##partial_alpha_op(combine_op, alpha_op, map_space);  \ | 
|   | 2107 |   }                                                                           \ | 
|   | 2108 | }                                                                             \ | 
|   | 2109 |  | 
|   | 2110 | render_scanline_obj_builder(transparent, normal, 1D, no_partial_alpha); | 
|   | 2111 | render_scanline_obj_builder(transparent, normal, 2D, no_partial_alpha); | 
|   | 2112 | render_scanline_obj_builder(transparent, color16, 1D, no_partial_alpha); | 
|   | 2113 | render_scanline_obj_builder(transparent, color16, 2D, no_partial_alpha); | 
|   | 2114 | render_scanline_obj_builder(transparent, color32, 1D, no_partial_alpha); | 
|   | 2115 | render_scanline_obj_builder(transparent, color32, 2D, no_partial_alpha); | 
|   | 2116 | render_scanline_obj_builder(transparent, alpha_obj, 1D, no_partial_alpha); | 
|   | 2117 | render_scanline_obj_builder(transparent, alpha_obj, 2D, no_partial_alpha); | 
|   | 2118 | render_scanline_obj_builder(transparent, partial_alpha, 1D, partial_alpha); | 
|   | 2119 | render_scanline_obj_builder(transparent, partial_alpha, 2D, partial_alpha); | 
|   | 2120 | render_scanline_obj_builder(copy, copy_tile, 1D, no_partial_alpha); | 
|   | 2121 | render_scanline_obj_builder(copy, copy_tile, 2D, no_partial_alpha); | 
|   | 2122 | render_scanline_obj_builder(copy, copy_bitmap, 1D, no_partial_alpha); | 
|   | 2123 | render_scanline_obj_builder(copy, copy_bitmap, 2D, no_partial_alpha); | 
|   | 2124 |  | 
|   | 2125 |  | 
|   | 2126 |  | 
|   | 2127 | static void order_obj(u32 video_mode) | 
|   | 2128 | { | 
|   | 2129 |   s32 obj_num, priority, row; | 
|   | 2130 |   s32 obj_x, obj_y; | 
|   | 2131 |   s32 obj_size, obj_mode; | 
|   | 2132 |   s32 obj_width, obj_height; | 
|   | 2133 |   u32 obj_priority; | 
|   | 2134 |   u32 obj_attribute_0, obj_attribute_1, obj_attribute_2; | 
|   | 2135 |   u32 current_count; | 
|   | 2136 |   u16 *oam_ptr = oam_ram + 508; | 
|   | 2137 |  | 
|   | 2138 |   for(priority = 0; priority < 5; priority++) | 
|   | 2139 |   { | 
|   | 2140 |     for(row = 0; row < 160; row++) | 
|   | 2141 |     { | 
|   | 2142 |       obj_priority_count[priority][row] = 0; | 
|   | 2143 |     } | 
|   | 2144 |   } | 
|   | 2145 |  | 
|   | 2146 |   for(row = 0; row < 160; row++) | 
|   | 2147 |   { | 
|   | 2148 |     obj_alpha_count[row] = 0; | 
|   | 2149 |   } | 
|   | 2150 |  | 
|   | 2151 |   for(obj_num = 127; obj_num >= 0; obj_num--, oam_ptr -= 4) | 
|   | 2152 |   { | 
|   | 2153 |     obj_attribute_0 = oam_ptr[0]; | 
|   | 2154 |     obj_attribute_2 = oam_ptr[2]; | 
|   | 2155 |     obj_size = obj_attribute_0 & 0xC000; | 
|   | 2156 |     obj_priority = (obj_attribute_2 >> 10) & 0x03; | 
|   | 2157 |     obj_mode = (obj_attribute_0 >> 10) & 0x03; | 
|   | 2158 |  | 
|   | 2159 |     if(((obj_attribute_0 & 0x0300) != 0x0200) && (obj_size != 0xC000) && | 
|   | 2160 |      (obj_mode != 3) && ((video_mode < 3) || | 
|   | 2161 |      ((obj_attribute_2 & 0x3FF) >= 512))) | 
|   | 2162 |     { | 
|   | 2163 |       obj_y = obj_attribute_0 & 0xFF; | 
|   | 2164 |       if(obj_y > 160) | 
|   | 2165 |         obj_y -= 256; | 
|   | 2166 |  | 
|   | 2167 |       obj_attribute_1 = oam_ptr[1]; | 
|   | 2168 |       obj_size = ((obj_size >> 12) & 0x0C) | (obj_attribute_1 >> 14); | 
|   | 2169 |       obj_height = obj_height_table[obj_size]; | 
|   | 2170 |       obj_width = obj_width_table[obj_size]; | 
|   | 2171 |  | 
|   | 2172 |       if(obj_attribute_0 & 0x200) | 
|   | 2173 |       { | 
|   | 2174 |         obj_height *= 2; | 
|   | 2175 |         obj_width *= 2; | 
|   | 2176 |       } | 
|   | 2177 |  | 
|   | 2178 |       if(((obj_y + obj_height) > 0) && (obj_y < 160)) | 
|   | 2179 |       { | 
|   | 2180 |         obj_x = (s32)(obj_attribute_1 << 23) >> 23; | 
|   | 2181 |  | 
|   | 2182 |         if(((obj_x + obj_width) > 0) && (obj_x < 240)) | 
|   | 2183 |         { | 
|   | 2184 |           if(obj_y < 0) | 
|   | 2185 |           { | 
|   | 2186 |             obj_height += obj_y; | 
|   | 2187 |             obj_y = 0; | 
|   | 2188 |           } | 
|   | 2189 |  | 
|   | 2190 |           if((obj_y + obj_height) >= 160) | 
|   | 2191 |           { | 
|   | 2192 |             obj_height = 160 - obj_y; | 
|   | 2193 |           } | 
|   | 2194 |  | 
|   | 2195 |           if(obj_mode == 1) | 
|   | 2196 |           { | 
|   | 2197 |             for(row = obj_y; row < obj_y + obj_height; row++) | 
|   | 2198 |             { | 
|   | 2199 |               current_count = obj_priority_count[obj_priority][row]; | 
|   | 2200 |               obj_priority_list[obj_priority][row][current_count] = obj_num; | 
|   | 2201 |               obj_priority_count[obj_priority][row] = current_count + 1; | 
|   | 2202 |               obj_alpha_count[row]++; | 
|   | 2203 |             } | 
|   | 2204 |           } | 
|   | 2205 |           else | 
|   | 2206 |           { | 
|   | 2207 |             if(obj_mode == 2) | 
|   | 2208 |             { | 
|   | 2209 |               obj_priority = 4; | 
|   | 2210 |             } | 
|   | 2211 |  | 
|   | 2212 |             for(row = obj_y; row < obj_y + obj_height; row++) | 
|   | 2213 |             { | 
|   | 2214 |               current_count = obj_priority_count[obj_priority][row]; | 
|   | 2215 |               obj_priority_list[obj_priority][row][current_count] = obj_num; | 
|   | 2216 |               obj_priority_count[obj_priority][row] = current_count + 1; | 
|   | 2217 |             } | 
|   | 2218 |           } | 
|   | 2219 |         } | 
|   | 2220 |       } | 
|   | 2221 |     } | 
|   | 2222 |   } | 
|   | 2223 | } | 
|   | 2224 |  | 
|   | 2225 | u32 layer_order[16]; | 
|   | 2226 | u32 layer_count; | 
|   | 2227 |  | 
|   | 2228 | static void order_layers(u32 layer_flags) | 
|   | 2229 | { | 
|   | 2230 |   s32 priority, layer_number; | 
|   | 2231 |   layer_count = 0; | 
|   | 2232 |  | 
|   | 2233 |   for(priority = 3; priority >= 0; priority--) | 
|   | 2234 |   { | 
|   | 2235 |     for(layer_number = 3; layer_number >= 0; layer_number--) | 
|   | 2236 |     { | 
|   | 2237 |       if(((layer_flags >> layer_number) & 1) && | 
|   | 2238 |        ((io_registers[REG_BG0CNT + layer_number] & 0x03) == priority)) | 
|   | 2239 |       { | 
|   | 2240 |         layer_order[layer_count] = layer_number; | 
|   | 2241 |         layer_count++; | 
|   | 2242 |       } | 
|   | 2243 |     } | 
|   | 2244 |  | 
|   | 2245 |     if((obj_priority_count[priority][io_registers[REG_VCOUNT]] > 0) | 
|   | 2246 |      && (layer_flags & 0x10)) | 
|   | 2247 |     { | 
|   | 2248 |       layer_order[layer_count] = priority | 0x04; | 
|   | 2249 |       layer_count++; | 
|   | 2250 |     } | 
|   | 2251 |   } | 
|   | 2252 | } | 
|   | 2253 |  | 
|   | 2254 | #define fill_line(_start, _end)                                               \ | 
|   | 2255 |   u32 i;                                                                      \ | 
|   | 2256 |                                                                               \ | 
|   | 2257 |   for(i = _start; i < _end; i++)                                              \ | 
|   | 2258 |   {                                                                           \ | 
|   | 2259 |     dest_ptr[i] = color;                                                      \ | 
|   | 2260 |   }                                                                           \ | 
|   | 2261 |  | 
|   | 2262 |  | 
|   | 2263 | #define fill_line_color_normal()                                              \ | 
|   | 2264 |   color = palette_ram_converted[color]                                        \ | 
|   | 2265 |  | 
|   | 2266 | #define fill_line_color_alpha()                                               \ | 
|   | 2267 |  | 
|   | 2268 | #define fill_line_color_color16()                                             \ | 
|   | 2269 |  | 
|   | 2270 | #define fill_line_color_color32()                                             \ | 
|   | 2271 |  | 
|   | 2272 | #define fill_line_builder(type)                                               \ | 
|   | 2273 | static void fill_line_##type(u16 color, render_scanline_dest_##type *dest_ptr,\ | 
|   | 2274 |  u32 start, u32 end)                                                          \ | 
|   | 2275 | {                                                                             \ | 
|   | 2276 |   fill_line_color_##type();                                                   \ | 
|   | 2277 |   fill_line(start, end);                                                      \ | 
|   | 2278 | }                                                                             \ | 
|   | 2279 |  | 
|   | 2280 | fill_line_builder(normal); | 
|   | 2281 | fill_line_builder(alpha); | 
|   | 2282 | fill_line_builder(color16); | 
|   | 2283 | fill_line_builder(color32); | 
|   | 2284 |  | 
|   | 2285 |  | 
|   | 2286 | // Alpha blend two pixels (pixel_top and pixel_bottom). | 
|   | 2287 |  | 
|   | 2288 | #define blend_pixel()                                                         \ | 
|   | 2289 |   pixel_bottom = palette_ram_converted[(pixel_pair >> 16) & 0x1FF];           \ | 
|   | 2290 |   pixel_bottom = (pixel_bottom | (pixel_bottom << 16)) & 0x07E0F81F;          \ | 
|   | 2291 |   pixel_top = ((pixel_top * blend_a) + (pixel_bottom * blend_b)) >> 4         \ | 
|   | 2292 |  | 
|   | 2293 |  | 
|   | 2294 | // Alpha blend two pixels, allowing for saturation (individual channels > 31). | 
|   | 2295 | // The operation is optimized towards saturation not occuring. | 
|   | 2296 |  | 
|   | 2297 | #define blend_saturate_pixel()                                                \ | 
|   | 2298 |   pixel_bottom = palette_ram_converted[(pixel_pair >> 16) & 0x1FF];           \ | 
|   | 2299 |   pixel_bottom = (pixel_bottom | (pixel_bottom << 16)) & 0x07E0F81F;          \ | 
|   | 2300 |   pixel_top = ((pixel_top * blend_a) + (pixel_bottom * blend_b)) >> 4;        \ | 
|   | 2301 |   if(pixel_top & 0x08010020)                                                  \ | 
|   | 2302 |   {                                                                           \ | 
|   | 2303 |     if(pixel_top & 0x08000000)                                                \ | 
|   | 2304 |       pixel_top |= 0x07E00000;                                                \ | 
|   | 2305 |                                                                               \ | 
|   | 2306 |     if(pixel_top & 0x00010000)                                                \ | 
|   | 2307 |       pixel_top |= 0x0000F800;                                                \ | 
|   | 2308 |                                                                               \ | 
|   | 2309 |     if(pixel_top & 0x00000020)                                                \ | 
|   | 2310 |       pixel_top |= 0x0000001F;                                                \ | 
|   | 2311 |   }                                                                           \ | 
|   | 2312 |  | 
|   | 2313 | #define brighten_pixel()                                                      \ | 
|   | 2314 |   pixel_top = upper + ((pixel_top * blend) >> 4);                             \ | 
|   | 2315 |  | 
|   | 2316 | #define darken_pixel()                                                        \ | 
|   | 2317 |   pixel_top = (pixel_top * blend) >> 4;                                       \ | 
|   | 2318 |  | 
|   | 2319 | #define effect_condition_alpha                                                \ | 
|   | 2320 |   ((pixel_pair & 0x04000200) == 0x04000200)                                   \ | 
|   | 2321 |  | 
|   | 2322 | #define effect_condition_fade(pixel_source)                                   \ | 
|   | 2323 |   ((pixel_source & 0x00000200) == 0x00000200)                                 \ | 
|   | 2324 |  | 
|   | 2325 | #define expand_pixel_no_dest(expand_type, pixel_source)                       \ | 
|   | 2326 |   pixel_top = (pixel_top | (pixel_top << 16)) & 0x07E0F81F;                   \ | 
|   | 2327 |   expand_type##_pixel();                                                      \ | 
|   | 2328 |   pixel_top &= 0x07E0F81F;                                                    \ | 
|   | 2329 |   pixel_top = (pixel_top >> 16) | pixel_top                                   \ | 
|   | 2330 |  | 
|   | 2331 | #define expand_pixel(expand_type, pixel_source)                               \ | 
|   | 2332 |   pixel_top = palette_ram_converted[pixel_source & 0x1FF];                    \ | 
|   | 2333 |   expand_pixel_no_dest(expand_type, pixel_source);                            \ | 
|   | 2334 |   *screen_dest_ptr = pixel_top                                                \ | 
|   | 2335 |  | 
|   | 2336 | #define expand_loop(expand_type, effect_condition, pixel_source)              \ | 
|   | 2337 |   screen_src_ptr += start;                                                    \ | 
|   | 2338 |   screen_dest_ptr += start;                                                   \ | 
|   | 2339 |                                                                               \ | 
|   | 2340 |   end -= start;                                                               \ | 
|   | 2341 |                                                                               \ | 
|   | 2342 |   for(i = 0; i < end; i++)                                                    \ | 
|   | 2343 |   {                                                                           \ | 
|   | 2344 |     pixel_source = *screen_src_ptr;                                           \ | 
|   | 2345 |     if(effect_condition)                                                      \ | 
|   | 2346 |     {                                                                         \ | 
|   | 2347 |       expand_pixel(expand_type, pixel_source);                                \ | 
|   | 2348 |     }                                                                         \ | 
|   | 2349 |     else                                                                      \ | 
|   | 2350 |     {                                                                         \ | 
|   | 2351 |       *screen_dest_ptr =                                                      \ | 
|   | 2352 |        palette_ram_converted[pixel_source & 0x1FF];                           \ | 
|   | 2353 |     }                                                                         \ | 
|   | 2354 |                                                                               \ | 
|   | 2355 |     screen_src_ptr++;                                                         \ | 
|   | 2356 |     screen_dest_ptr++;                                                        \ | 
|   | 2357 |   }                                                                           \ | 
|   | 2358 |  | 
|   | 2359 |  | 
|   | 2360 | #define expand_loop_partial_alpha(alpha_expand, expand_type)                  \ | 
|   | 2361 |   screen_src_ptr += start;                                                    \ | 
|   | 2362 |   screen_dest_ptr += start;                                                   \ | 
|   | 2363 |                                                                               \ | 
|   | 2364 |   end -= start;                                                               \ | 
|   | 2365 |                                                                               \ | 
|   | 2366 |   for(i = 0; i < end; i++)                                                    \ | 
|   | 2367 |   {                                                                           \ | 
|   | 2368 |     pixel_pair = *screen_src_ptr;                                             \ | 
|   | 2369 |     if(effect_condition_fade(pixel_pair))                                     \ | 
|   | 2370 |     {                                                                         \ | 
|   | 2371 |       if(effect_condition_alpha)                                              \ | 
|   | 2372 |       {                                                                       \ | 
|   | 2373 |         expand_pixel(alpha_expand, pixel_pair);                               \ | 
|   | 2374 |       }                                                                       \ | 
|   | 2375 |       else                                                                    \ | 
|   | 2376 |       {                                                                       \ | 
|   | 2377 |         expand_pixel(expand_type, pixel_pair);                                \ | 
|   | 2378 |       }                                                                       \ | 
|   | 2379 |     }                                                                         \ | 
|   | 2380 |     else                                                                      \ | 
|   | 2381 |     {                                                                         \ | 
|   | 2382 |       *screen_dest_ptr =                                                      \ | 
|   | 2383 |        palette_ram_converted[pixel_pair & 0x1FF];                             \ | 
|   | 2384 |     }                                                                         \ | 
|   | 2385 |                                                                               \ | 
|   | 2386 |     screen_src_ptr++;                                                         \ | 
|   | 2387 |     screen_dest_ptr++;                                                        \ | 
|   | 2388 |   }                                                                           \ | 
|   | 2389 |  | 
|   | 2390 |  | 
|   | 2391 | #define expand_partial_alpha(expand_type)                                     \ | 
|   | 2392 |   if((blend_a + blend_b) > 16)                                                \ | 
|   | 2393 |   {                                                                           \ | 
|   | 2394 |     expand_loop_partial_alpha(blend_saturate, expand_type);                   \ | 
|   | 2395 |   }                                                                           \ | 
|   | 2396 |   else                                                                        \ | 
|   | 2397 |   {                                                                           \ | 
|   | 2398 |     expand_loop_partial_alpha(blend, expand_type);                            \ | 
|   | 2399 |   }                                                                           \ | 
|   | 2400 |  | 
|   | 2401 |  | 
|   | 2402 |  | 
|   | 2403 | // Blend top two pixels of scanline with each other. | 
|   | 2404 |  | 
|   | 2405 | #ifdef RENDER_COLOR16_NORMAL | 
|   | 2406 |  | 
|   | 2407 | #ifndef ARM_ARCH | 
|   | 2408 |  | 
|   | 2409 | void expand_normal(u16 *screen_ptr, u32 start, u32 end) | 
|   | 2410 | { | 
|   | 2411 |   u32 i, pixel_source; | 
|   | 2412 |   screen_ptr += start; | 
|   | 2413 |  | 
|   | 2414 |   return; | 
|   | 2415 |  | 
|   | 2416 |   end -= start; | 
|   | 2417 |  | 
|   | 2418 |   for(i = 0; i < end; i++) | 
|   | 2419 |   { | 
|   | 2420 |     pixel_source = *screen_ptr; | 
|   | 2421 |     *screen_ptr = palette_ram_converted[pixel_source]; | 
|   | 2422 |  | 
|   | 2423 |     screen_ptr++; | 
|   | 2424 |   } | 
|   | 2425 | } | 
|   | 2426 |  | 
|   | 2427 | #endif | 
|   | 2428 |  | 
|   | 2429 | #else | 
|   | 2430 |  | 
|   | 2431 | #define expand_normal(screen_ptr, start, end) | 
|   | 2432 |  | 
|   | 2433 | #endif | 
|   | 2434 |  | 
|   | 2435 |  | 
|   | 2436 | void expand_blend(u32 *screen_src_ptr, u16 *screen_dest_ptr, | 
|   | 2437 |  u32 start, u32 end); | 
|   | 2438 |  | 
|   | 2439 | #ifndef ARM_ARCH | 
|   | 2440 |  | 
|   | 2441 | void expand_blend(u32 *screen_src_ptr, u16 *screen_dest_ptr, | 
|   | 2442 |  u32 start, u32 end) | 
|   | 2443 | { | 
|   | 2444 |   u32 pixel_pair; | 
|   | 2445 |   u32 pixel_top, pixel_bottom; | 
|   | 2446 |   u32 bldalpha = io_registers[REG_BLDALPHA]; | 
|   | 2447 |   u32 blend_a = bldalpha & 0x1F; | 
|   | 2448 |   u32 blend_b = (bldalpha >> 8) & 0x1F; | 
|   | 2449 |   u32 i; | 
|   | 2450 |  | 
|   | 2451 |   if(blend_a > 16) | 
|   | 2452 |     blend_a = 16; | 
|   | 2453 |  | 
|   | 2454 |   if(blend_b > 16) | 
|   | 2455 |     blend_b = 16; | 
|   | 2456 |  | 
|   | 2457 |   // The individual colors can saturate over 31, this should be taken | 
|   | 2458 |   // care of in an alternate pass as it incurs a huge additional speedhit. | 
|   | 2459 |   if((blend_a + blend_b) > 16) | 
|   | 2460 |   { | 
|   | 2461 |     expand_loop(blend_saturate, effect_condition_alpha, pixel_pair); | 
|   | 2462 |   } | 
|   | 2463 |   else | 
|   | 2464 |   { | 
|   | 2465 |     expand_loop(blend, effect_condition_alpha, pixel_pair); | 
|   | 2466 |   } | 
|   | 2467 | } | 
|   | 2468 |  | 
|   | 2469 | #endif | 
|   | 2470 |  | 
|   | 2471 | // Blend scanline with white. | 
|   | 2472 |  | 
|   | 2473 | static void expand_darken(u16 *screen_src_ptr, u16 *screen_dest_ptr, | 
|   | 2474 |  u32 start, u32 end) | 
|   | 2475 | { | 
|   | 2476 |   u32 pixel_top; | 
|   | 2477 |   s32 blend = 16 - (io_registers[REG_BLDY] & 0x1F); | 
|   | 2478 |   u32 i; | 
|   | 2479 |  | 
|   | 2480 |   if(blend < 0) | 
|   | 2481 |     blend = 0; | 
|   | 2482 |  | 
|   | 2483 |   expand_loop(darken, effect_condition_fade(pixel_top), pixel_top); | 
|   | 2484 | } | 
|   | 2485 |  | 
|   | 2486 |  | 
|   | 2487 | // Blend scanline with black. | 
|   | 2488 |  | 
|   | 2489 | static void expand_brighten(u16 *screen_src_ptr, u16 *screen_dest_ptr, | 
|   | 2490 |  u32 start, u32 end) | 
|   | 2491 | { | 
|   | 2492 |   u32 pixel_top; | 
|   | 2493 |   u32 blend = io_registers[REG_BLDY] & 0x1F; | 
|   | 2494 |   u32 upper; | 
|   | 2495 |   u32 i; | 
|   | 2496 |  | 
|   | 2497 |   if(blend > 16) | 
|   | 2498 |     blend = 16; | 
|   | 2499 |  | 
|   | 2500 |   upper = ((0x07E0F81F * blend) >> 4) & 0x07E0F81F; | 
|   | 2501 |   blend = 16 - blend; | 
|   | 2502 |  | 
|   | 2503 |   expand_loop(brighten, effect_condition_fade(pixel_top), pixel_top); | 
|   | 2504 |  | 
|   | 2505 | } | 
|   | 2506 |  | 
|   | 2507 |  | 
|   | 2508 | // Expand scanline such that if both top and bottom pass it's alpha, | 
|   | 2509 | // if only top passes it's as specified, and if neither pass it's normal. | 
|   | 2510 |  | 
|   | 2511 | static void expand_darken_partial_alpha(u32 *screen_src_ptr, u16 *screen_dest_ptr, | 
|   | 2512 |  u32 start, u32 end) | 
|   | 2513 | { | 
|   | 2514 |   s32 blend = 16 - (io_registers[REG_BLDY] & 0x1F); | 
|   | 2515 |   u32 pixel_pair; | 
|   | 2516 |   u32 pixel_top, pixel_bottom; | 
|   | 2517 |   u32 bldalpha = io_registers[REG_BLDALPHA]; | 
|   | 2518 |   u32 blend_a = bldalpha & 0x1F; | 
|   | 2519 |   u32 blend_b = (bldalpha >> 8) & 0x1F; | 
|   | 2520 |   u32 i; | 
|   | 2521 |  | 
|   | 2522 |   if(blend < 0) | 
|   | 2523 |     blend = 0; | 
|   | 2524 |  | 
|   | 2525 |   if(blend_a > 16) | 
|   | 2526 |     blend_a = 16; | 
|   | 2527 |  | 
|   | 2528 |   if(blend_b > 16) | 
|   | 2529 |     blend_b = 16; | 
|   | 2530 |  | 
|   | 2531 |   expand_partial_alpha(darken); | 
|   | 2532 | } | 
|   | 2533 |  | 
|   | 2534 |  | 
|   | 2535 | static void expand_brighten_partial_alpha(u32 *screen_src_ptr, u16 *screen_dest_ptr, | 
|   | 2536 |  u32 start, u32 end) | 
|   | 2537 | { | 
|   | 2538 |   s32 blend = io_registers[REG_BLDY] & 0x1F; | 
|   | 2539 |   u32 pixel_pair; | 
|   | 2540 |   u32 pixel_top, pixel_bottom; | 
|   | 2541 |   u32 bldalpha = io_registers[REG_BLDALPHA]; | 
|   | 2542 |   u32 blend_a = bldalpha & 0x1F; | 
|   | 2543 |   u32 blend_b = (bldalpha >> 8) & 0x1F; | 
|   | 2544 |   u32 upper; | 
|   | 2545 |   u32 i; | 
|   | 2546 |  | 
|   | 2547 |   if(blend > 16) | 
|   | 2548 |     blend = 16; | 
|   | 2549 |  | 
|   | 2550 |   upper = ((0x07E0F81F * blend) >> 4) & 0x07E0F81F; | 
|   | 2551 |   blend = 16 - blend; | 
|   | 2552 |  | 
|   | 2553 |   if(blend_a > 16) | 
|   | 2554 |     blend_a = 16; | 
|   | 2555 |  | 
|   | 2556 |   if(blend_b > 16) | 
|   | 2557 |     blend_b = 16; | 
|   | 2558 |  | 
|   | 2559 |   expand_partial_alpha(brighten); | 
|   | 2560 | } | 
|   | 2561 |  | 
|   | 2562 |  | 
|   | 2563 | // Render an OBJ layer from start to end, depending on the type (1D or 2D) | 
|   | 2564 | // stored in dispcnt. | 
|   | 2565 |  | 
|   | 2566 | #define render_obj_layer(type, dest, _start, _end)                            \ | 
|   | 2567 |   current_layer &= ~0x04;                                                     \ | 
|   | 2568 |   if(dispcnt & 0x40)                                                          \ | 
|   | 2569 |     render_scanline_obj_##type##_1D(current_layer, _start, _end, dest);       \ | 
|   | 2570 |   else                                                                        \ | 
|   | 2571 |     render_scanline_obj_##type##_2D(current_layer, _start, _end, dest)        \ | 
|   | 2572 |  | 
|   | 2573 |  | 
|   | 2574 | // Render a target all the way with the background color as taken from the | 
|   | 2575 | // palette. | 
|   | 2576 |  | 
|   | 2577 | #define fill_line_bg(type, dest, _start, _end)                                \ | 
|   | 2578 |   fill_line_##type(0, dest, _start, _end)                                     \ | 
|   | 2579 |  | 
|   | 2580 |  | 
|   | 2581 | // Render all layers as they appear in the layer order. | 
|   | 2582 |  | 
|   | 2583 | #define render_layers(tile_alpha, obj_alpha, dest)                            \ | 
|   | 2584 | {                                                                             \ | 
|   | 2585 |   current_layer = layer_order[0];                                             \ | 
|   | 2586 |   if(current_layer & 0x04)                                                    \ | 
|   | 2587 |   {                                                                           \ | 
|   | 2588 |     /* If the first one is OBJ render the background then render it. */       \ | 
|   | 2589 |     fill_line_bg(tile_alpha, dest, 0, 240);                                   \ | 
|   | 2590 |     render_obj_layer(obj_alpha, dest, 0, 240);                                \ | 
|   | 2591 |   }                                                                           \ | 
|   | 2592 |   else                                                                        \ | 
|   | 2593 |   {                                                                           \ | 
|   | 2594 |     /* Otherwise render a base layer. */                                      \ | 
|   | 2595 |     layer_renderers[current_layer].tile_alpha##_render_base(current_layer,    \ | 
|   | 2596 |      0, 240, dest);                                                           \ | 
|   | 2597 |   }                                                                           \ | 
|   | 2598 |                                                                               \ | 
|   | 2599 |   /* Render the rest of the layers. */                                        \ | 
|   | 2600 |   for(layer_order_pos = 1; layer_order_pos < layer_count; layer_order_pos++)  \ | 
|   | 2601 |   {                                                                           \ | 
|   | 2602 |     current_layer = layer_order[layer_order_pos];                             \ | 
|   | 2603 |     if(current_layer & 0x04)                                                  \ | 
|   | 2604 |     {                                                                         \ | 
|   | 2605 |       render_obj_layer(obj_alpha, dest, 0, 240);                              \ | 
|   | 2606 |     }                                                                         \ | 
|   | 2607 |     else                                                                      \ | 
|   | 2608 |     {                                                                         \ | 
|   | 2609 |       layer_renderers[current_layer].                                         \ | 
|   | 2610 |        tile_alpha##_render_transparent(current_layer, 0, 240, dest);          \ | 
|   | 2611 |     }                                                                         \ | 
|   | 2612 |   }                                                                           \ | 
|   | 2613 | }                                                                             \ | 
|   | 2614 |  | 
|   | 2615 | #define render_condition_alpha                                                \ | 
|   | 2616 |   (((io_registers[REG_BLDALPHA] & 0x1F1F) != 0x001F) &&                       \ | 
|   | 2617 |    ((io_registers[REG_BLDCNT] & 0x3F) != 0) &&                                \ | 
|   | 2618 |    ((io_registers[REG_BLDCNT] & 0x3F00) != 0))                                \ | 
|   | 2619 |  | 
|   | 2620 | #define render_condition_fade                                                 \ | 
|   | 2621 |   (((io_registers[REG_BLDY] & 0x1F) != 0) &&                                  \ | 
|   | 2622 |    ((io_registers[REG_BLDCNT] & 0x3F) != 0))                                  \ | 
|   | 2623 |  | 
|   | 2624 | #define render_layers_color_effect(renderer, layer_condition,                 \ | 
|   | 2625 |  alpha_condition, fade_condition, _start, _end)                               \ | 
|   | 2626 | {                                                                             \ | 
|   | 2627 |   if(layer_condition)                                                         \ | 
|   | 2628 |   {                                                                           \ | 
|   | 2629 |     if(obj_alpha_count[io_registers[REG_VCOUNT]] > 0)                         \ | 
|   | 2630 |     {                                                                         \ | 
|   | 2631 |       /* Render based on special effects mode. */                             \ | 
|   | 2632 |       u32 screen_buffer[240];                                                 \ | 
|   | 2633 |       switch((bldcnt >> 6) & 0x03)                                            \ | 
|   | 2634 |       {                                                                       \ | 
|   | 2635 |         /* Alpha blend */                                                     \ | 
|   | 2636 |         case 0x01:                                                            \ | 
|   | 2637 |         {                                                                     \ | 
|   | 2638 |           if(alpha_condition)                                                 \ | 
|   | 2639 |           {                                                                   \ | 
|   | 2640 |             renderer(alpha, alpha_obj, screen_buffer);                        \ | 
|   | 2641 |             expand_blend(screen_buffer, scanline, _start, _end);              \ | 
|   | 2642 |             return;                                                           \ | 
|   | 2643 |           }                                                                   \ | 
|   | 2644 |           break;                                                              \ | 
|   | 2645 |         }                                                                     \ | 
|   | 2646 |                                                                               \ | 
|   | 2647 |         /* Fade to white */                                                   \ | 
|   | 2648 |         case 0x02:                                                            \ | 
|   | 2649 |         {                                                                     \ | 
|   | 2650 |           if(fade_condition)                                                  \ | 
|   | 2651 |           {                                                                   \ | 
|   | 2652 |             renderer(color32, partial_alpha, screen_buffer);                  \ | 
|   | 2653 |             expand_brighten_partial_alpha(screen_buffer, scanline,            \ | 
|   | 2654 |              _start, _end);                                                   \ | 
|   | 2655 |             return;                                                           \ | 
|   | 2656 |           }                                                                   \ | 
|   | 2657 |           break;                                                              \ | 
|   | 2658 |         }                                                                     \ | 
|   | 2659 |                                                                               \ | 
|   | 2660 |         /* Fade to black */                                                   \ | 
|   | 2661 |         case 0x03:                                                            \ | 
|   | 2662 |         {                                                                     \ | 
|   | 2663 |           if(fade_condition)                                                  \ | 
|   | 2664 |           {                                                                   \ | 
|   | 2665 |             renderer(color32, partial_alpha, screen_buffer);                  \ | 
|   | 2666 |             expand_darken_partial_alpha(screen_buffer, scanline,              \ | 
|   | 2667 |              _start, _end);                                                   \ | 
|   | 2668 |             return;                                                           \ | 
|   | 2669 |           }                                                                   \ | 
|   | 2670 |           break;                                                              \ | 
|   | 2671 |         }                                                                     \ | 
|   | 2672 |       }                                                                       \ | 
|   | 2673 |                                                                               \ | 
|   | 2674 |       renderer(color32, partial_alpha, screen_buffer);                        \ | 
|   | 2675 |       expand_blend(screen_buffer, scanline, _start, _end);                    \ | 
|   | 2676 |     }                                                                         \ | 
|   | 2677 |     else                                                                      \ | 
|   | 2678 |     {                                                                         \ | 
|   | 2679 |       /* Render based on special effects mode. */                             \ | 
|   | 2680 |       switch((bldcnt >> 6) & 0x03)                                            \ | 
|   | 2681 |       {                                                                       \ | 
|   | 2682 |         /* Alpha blend */                                                     \ | 
|   | 2683 |         case 0x01:                                                            \ | 
|   | 2684 |         {                                                                     \ | 
|   | 2685 |           if(alpha_condition)                                                 \ | 
|   | 2686 |           {                                                                   \ | 
|   | 2687 |             u32 screen_buffer[240];                                           \ | 
|   | 2688 |             renderer(alpha, alpha_obj, screen_buffer);                        \ | 
|   | 2689 |             expand_blend(screen_buffer, scanline, _start, _end);              \ | 
|   | 2690 |             return;                                                           \ | 
|   | 2691 |           }                                                                   \ | 
|   | 2692 |           break;                                                              \ | 
|   | 2693 |         }                                                                     \ | 
|   | 2694 |                                                                               \ | 
|   | 2695 |         /* Fade to white */                                                   \ | 
|   | 2696 |         case 0x02:                                                            \ | 
|   | 2697 |         {                                                                     \ | 
|   | 2698 |           if(fade_condition)                                                  \ | 
|   | 2699 |           {                                                                   \ | 
|   | 2700 |             renderer(color16, color16, scanline);                             \ | 
|   | 2701 |             expand_brighten(scanline, scanline, _start, _end);                \ | 
|   | 2702 |             return;                                                           \ | 
|   | 2703 |           }                                                                   \ | 
|   | 2704 |           break;                                                              \ | 
|   | 2705 |         }                                                                     \ | 
|   | 2706 |                                                                               \ | 
|   | 2707 |         /* Fade to black */                                                   \ | 
|   | 2708 |         case 0x03:                                                            \ | 
|   | 2709 |         {                                                                     \ | 
|   | 2710 |           if(fade_condition)                                                  \ | 
|   | 2711 |           {                                                                   \ | 
|   | 2712 |             renderer(color16, color16, scanline);                             \ | 
|   | 2713 |             expand_darken(scanline, scanline, _start, _end);                  \ | 
|   | 2714 |             return;                                                           \ | 
|   | 2715 |           }                                                                   \ | 
|   | 2716 |           break;                                                              \ | 
|   | 2717 |         }                                                                     \ | 
|   | 2718 |       }                                                                       \ | 
|   | 2719 |                                                                               \ | 
|   | 2720 |       renderer(normal, normal, scanline);                                     \ | 
|   | 2721 |       expand_normal(scanline, _start, _end);                                  \ | 
|   | 2722 |     }                                                                         \ | 
|   | 2723 |   }                                                                           \ | 
|   | 2724 |   else                                                                        \ | 
|   | 2725 |   {                                                                           \ | 
|   | 2726 |     u32 pixel_top = palette_ram_converted[0];                                 \ | 
|   | 2727 |     switch((bldcnt >> 6) & 0x03)                                              \ | 
|   | 2728 |     {                                                                         \ | 
|   | 2729 |       /* Fade to white */                                                     \ | 
|   | 2730 |       case 0x02:                                                              \ | 
|   | 2731 |       {                                                                       \ | 
|   | 2732 |         if(color_combine_mask_a(5))                                           \ | 
|   | 2733 |         {                                                                     \ | 
|   | 2734 |           u32 blend = io_registers[REG_BLDY] & 0x1F;                          \ | 
|   | 2735 |           u32 upper;                                                          \ | 
|   | 2736 |                                                                               \ | 
|   | 2737 |           if(blend > 16)                                                      \ | 
|   | 2738 |             blend = 16;                                                       \ | 
|   | 2739 |                                                                               \ | 
|   | 2740 |           upper = ((0x07E0F81F * blend) >> 4) & 0x07E0F81F;                   \ | 
|   | 2741 |           blend = 16 - blend;                                                 \ | 
|   | 2742 |                                                                               \ | 
|   | 2743 |           expand_pixel_no_dest(brighten, pixel_top);                          \ | 
|   | 2744 |         }                                                                     \ | 
|   | 2745 |         break;                                                                \ | 
|   | 2746 |       }                                                                       \ | 
|   | 2747 |                                                                               \ | 
|   | 2748 |       /* Fade to black */                                                     \ | 
|   | 2749 |       case 0x03:                                                              \ | 
|   | 2750 |       {                                                                       \ | 
|   | 2751 |         if(color_combine_mask_a(5))                                           \ | 
|   | 2752 |         {                                                                     \ | 
|   | 2753 |           s32 blend = 16 - (io_registers[REG_BLDY] & 0x1F);                   \ | 
|   | 2754 |                                                                               \ | 
|   | 2755 |           if(blend < 0)                                                       \ | 
|   | 2756 |             blend = 0;                                                        \ | 
|   | 2757 |                                                                               \ | 
|   | 2758 |           expand_pixel_no_dest(darken, pixel_top);                            \ | 
|   | 2759 |         }                                                                     \ | 
|   | 2760 |         break;                                                                \ | 
|   | 2761 |       }                                                                       \ | 
|   | 2762 |     }                                                                         \ | 
|   | 2763 |     fill_line_color16(pixel_top, scanline, _start, _end);                     \ | 
|   | 2764 |   }                                                                           \ | 
|   | 2765 | }                                                                             \ | 
|   | 2766 |  | 
|   | 2767 |  | 
|   | 2768 | // Renders an entire scanline from 0 to 240, based on current color mode. | 
|   | 2769 |  | 
|   | 2770 | static void render_scanline_tile(u16 *scanline, u32 dispcnt) | 
|   | 2771 | { | 
|   | 2772 |   u32 current_layer; | 
|   | 2773 |   u32 layer_order_pos; | 
|   | 2774 |   u32 bldcnt = io_registers[REG_BLDCNT]; | 
|   | 2775 |   render_scanline_layer_functions_tile(); | 
|   | 2776 |  | 
|   | 2777 |   render_layers_color_effect(render_layers, layer_count, | 
|   | 2778 |    render_condition_alpha, render_condition_fade, 0, 240); | 
|   | 2779 | } | 
|   | 2780 |  | 
|   | 2781 | static void render_scanline_bitmap(u16 *scanline, u32 dispcnt) | 
|   | 2782 | { | 
|   | 2783 |   render_scanline_layer_functions_bitmap(); | 
|   | 2784 |   u32 current_layer; | 
|   | 2785 |   u32 layer_order_pos; | 
|   | 2786 |  | 
|   | 2787 |   fill_line_bg(normal, scanline, 0, 240); | 
|   | 2788 |  | 
|   | 2789 |   for(layer_order_pos = 0; layer_order_pos < layer_count; layer_order_pos++) | 
|   | 2790 |   { | 
|   | 2791 |     current_layer = layer_order[layer_order_pos]; | 
|   | 2792 |     if(current_layer & 0x04) | 
|   | 2793 |     { | 
|   | 2794 |       render_obj_layer(normal, scanline, 0, 240); | 
|   | 2795 |     } | 
|   | 2796 |     else | 
|   | 2797 |     { | 
|   | 2798 |       layer_renderers->normal_render(0, 240, scanline); | 
|   | 2799 |     } | 
|   | 2800 |   } | 
|   | 2801 | } | 
|   | 2802 |  | 
|   | 2803 | // Render layers from start to end based on if they're allowed in the | 
|   | 2804 | // enable flags. | 
|   | 2805 |  | 
|   | 2806 | #define render_layers_conditional(tile_alpha, obj_alpha, dest)                \ | 
|   | 2807 | {                                                                             \ | 
|   | 2808 |   __label__ skip;                                                             \ | 
|   | 2809 |   current_layer = layer_order[layer_order_pos];                               \ | 
|   | 2810 |   /* If OBJ aren't enabled skip to the first non-OBJ layer */                 \ | 
|   | 2811 |   if(!(enable_flags & 0x10))                                                  \ | 
|   | 2812 |   {                                                                           \ | 
|   | 2813 |     while((current_layer & 0x04) || !((1 << current_layer) & enable_flags))   \ | 
|   | 2814 |     {                                                                         \ | 
|   | 2815 |       layer_order_pos++;                                                      \ | 
|   | 2816 |       current_layer = layer_order[layer_order_pos];                           \ | 
|   | 2817 |                                                                               \ | 
|   | 2818 |       /* Oops, ran out of layers, render the background. */                   \ | 
|   | 2819 |       if(layer_order_pos == layer_count)                                      \ | 
|   | 2820 |       {                                                                       \ | 
|   | 2821 |         fill_line_bg(tile_alpha, dest, start, end);                           \ | 
|   | 2822 |         goto skip;                                                            \ | 
|   | 2823 |       }                                                                       \ | 
|   | 2824 |     }                                                                         \ | 
|   | 2825 |                                                                               \ | 
|   | 2826 |     /* Render the first valid layer */                                        \ | 
|   | 2827 |     layer_renderers[current_layer].tile_alpha##_render_base(current_layer,    \ | 
|   | 2828 |      start, end, dest);                                                       \ | 
|   | 2829 |                                                                               \ | 
|   | 2830 |     layer_order_pos++;                                                        \ | 
|   | 2831 |                                                                               \ | 
|   | 2832 |     /* Render the rest of the layers if active, skipping OBJ ones. */         \ | 
|   | 2833 |     for(; layer_order_pos < layer_count; layer_order_pos++)                   \ | 
|   | 2834 |     {                                                                         \ | 
|   | 2835 |       current_layer = layer_order[layer_order_pos];                           \ | 
|   | 2836 |       if(!(current_layer & 0x04) && ((1 << current_layer) & enable_flags))    \ | 
|   | 2837 |       {                                                                       \ | 
|   | 2838 |         layer_renderers[current_layer].                                       \ | 
|   | 2839 |          tile_alpha##_render_transparent(current_layer, start, end, dest);    \ | 
|   | 2840 |       }                                                                       \ | 
|   | 2841 |     }                                                                         \ | 
|   | 2842 |   }                                                                           \ | 
|   | 2843 |   else                                                                        \ | 
|   | 2844 |   {                                                                           \ | 
|   | 2845 |     /* Find the first active layer, skip all of the inactive ones */          \ | 
|   | 2846 |     while(!((current_layer & 0x04) || ((1 << current_layer) & enable_flags))) \ | 
|   | 2847 |     {                                                                         \ | 
|   | 2848 |       layer_order_pos++;                                                      \ | 
|   | 2849 |       current_layer = layer_order[layer_order_pos];                           \ | 
|   | 2850 |                                                                               \ | 
|   | 2851 |       /* Oops, ran out of layers, render the background. */                   \ | 
|   | 2852 |       if(layer_order_pos == layer_count)                                      \ | 
|   | 2853 |       {                                                                       \ | 
|   | 2854 |         fill_line_bg(tile_alpha, dest, start, end);                           \ | 
|   | 2855 |         goto skip;                                                            \ | 
|   | 2856 |       }                                                                       \ | 
|   | 2857 |     }                                                                         \ | 
|   | 2858 |                                                                               \ | 
|   | 2859 |     if(current_layer & 0x04)                                                  \ | 
|   | 2860 |     {                                                                         \ | 
|   | 2861 |       /* If the first one is OBJ render the background then render it. */     \ | 
|   | 2862 |       fill_line_bg(tile_alpha, dest, start, end);                             \ | 
|   | 2863 |       render_obj_layer(obj_alpha, dest, start, end);                          \ | 
|   | 2864 |     }                                                                         \ | 
|   | 2865 |     else                                                                      \ | 
|   | 2866 |     {                                                                         \ | 
|   | 2867 |       /* Otherwise render a base layer. */                                    \ | 
|   | 2868 |       layer_renderers[current_layer].                                         \ | 
|   | 2869 |        tile_alpha##_render_base(current_layer, start, end, dest);             \ | 
|   | 2870 |     }                                                                         \ | 
|   | 2871 |                                                                               \ | 
|   | 2872 |     layer_order_pos++;                                                        \ | 
|   | 2873 |                                                                               \ | 
|   | 2874 |     /* Render the rest of the layers. */                                      \ | 
|   | 2875 |     for(; layer_order_pos < layer_count; layer_order_pos++)                   \ | 
|   | 2876 |     {                                                                         \ | 
|   | 2877 |       current_layer = layer_order[layer_order_pos];                           \ | 
|   | 2878 |       if(current_layer & 0x04)                                                \ | 
|   | 2879 |       {                                                                       \ | 
|   | 2880 |         render_obj_layer(obj_alpha, dest, start, end);                        \ | 
|   | 2881 |       }                                                                       \ | 
|   | 2882 |       else                                                                    \ | 
|   | 2883 |       {                                                                       \ | 
|   | 2884 |         if(enable_flags & (1 << current_layer))                               \ | 
|   | 2885 |         {                                                                     \ | 
|   | 2886 |           layer_renderers[current_layer].                                     \ | 
|   | 2887 |            tile_alpha##_render_transparent(current_layer, start, end, dest);  \ | 
|   | 2888 |         }                                                                     \ | 
|   | 2889 |       }                                                                       \ | 
|   | 2890 |     }                                                                         \ | 
|   | 2891 |   }                                                                           \ | 
|   | 2892 |                                                                               \ | 
|   | 2893 |   skip:                                                                       \ | 
|   | 2894 |     ;                                                                         \ | 
|   | 2895 | }                                                                             \ | 
|   | 2896 |  | 
|   | 2897 |  | 
|   | 2898 | // Render all of the BG and OBJ in a tiled scanline from start to end ONLY if | 
|   | 2899 | // enable_flag allows that layer/OBJ. Also conditionally render color effects. | 
|   | 2900 |  | 
|   | 2901 | static void render_scanline_conditional_tile(u32 start, u32 end, u16 *scanline, | 
|   | 2902 |  u32 enable_flags, u32 dispcnt, u32 bldcnt, const tile_layer_render_struct | 
|   | 2903 |  *layer_renderers) | 
|   | 2904 | { | 
|   | 2905 |   u32 current_layer; | 
|   | 2906 |   u32 layer_order_pos = 0; | 
|   | 2907 |  | 
|   | 2908 |   render_layers_color_effect(render_layers_conditional, | 
|   | 2909 |    (layer_count && (enable_flags & 0x1F)), | 
|   | 2910 |    ((enable_flags & 0x20) && render_condition_alpha), | 
|   | 2911 |    ((enable_flags & 0x20) && render_condition_fade), start, end); | 
|   | 2912 | } | 
|   | 2913 |  | 
|   | 2914 |  | 
|   | 2915 | // Render the BG and OBJ in a bitmap scanline from start to end ONLY if | 
|   | 2916 | // enable_flag allows that layer/OBJ. Also conditionally render color effects. | 
|   | 2917 |  | 
|   | 2918 | static void render_scanline_conditional_bitmap(u32 start, u32 end, u16 *scanline, | 
|   | 2919 |  u32 enable_flags, u32 dispcnt, u32 bldcnt, const bitmap_layer_render_struct | 
|   | 2920 |  *layer_renderers) | 
|   | 2921 | { | 
|   | 2922 |   u32 current_layer; | 
|   | 2923 |   u32 layer_order_pos; | 
|   | 2924 |  | 
|   | 2925 |   fill_line_bg(normal, scanline, start, end); | 
|   | 2926 |  | 
|   | 2927 |   for(layer_order_pos = 0; layer_order_pos < layer_count; layer_order_pos++) | 
|   | 2928 |   { | 
|   | 2929 |     current_layer = layer_order[layer_order_pos]; | 
|   | 2930 |     if(current_layer & 0x04) | 
|   | 2931 |     { | 
|   | 2932 |       if(enable_flags & 0x10) | 
|   | 2933 |       { | 
|   | 2934 |         render_obj_layer(normal, scanline, start, end); | 
|   | 2935 |       } | 
|   | 2936 |     } | 
|   | 2937 |     else | 
|   | 2938 |     { | 
|   | 2939 |       if(enable_flags & 0x04) | 
|   | 2940 |         layer_renderers->normal_render(start, end, scanline); | 
|   | 2941 |     } | 
|   | 2942 |   } | 
|   | 2943 | } | 
|   | 2944 |  | 
|   | 2945 |  | 
|   | 2946 | #define window_x_coords(window_number)                                        \ | 
|   | 2947 |   window_##window_number##_x1 =                                               \ | 
|   | 2948 |    io_registers[REG_WIN##window_number##H] >> 8;                              \ | 
|   | 2949 |   window_##window_number##_x2 =                                               \ | 
|   | 2950 |    io_registers[REG_WIN##window_number##H] & 0xFF;                            \ | 
|   | 2951 |   window_##window_number##_enable =                                           \ | 
|   | 2952 |    (winin >> (window_number * 8)) & 0x3F;                                     \ | 
|   | 2953 |                                                                               \ | 
|   | 2954 |   if(window_##window_number##_x1 > 240)                                       \ | 
|   | 2955 |     window_##window_number##_x1 = 240;                                        \ | 
|   | 2956 |                                                                               \ | 
|   | 2957 |   if(window_##window_number##_x2 > 240)                                       \ | 
|   | 2958 |     window_##window_number##_x2 = 240                                         \ | 
|   | 2959 |  | 
|   | 2960 | #define window_coords(window_number)                                          \ | 
|   | 2961 |   u32 window_##window_number##_x1, window_##window_number##_x2;               \ | 
|   | 2962 |   u32 window_##window_number##_y1, window_##window_number##_y2;               \ | 
|   | 2963 |   u32 window_##window_number##_enable = 0;                                    \ | 
|   | 2964 |   window_##window_number##_y1 =                                               \ | 
|   | 2965 |    io_registers[REG_WIN##window_number##V] >> 8;                              \ | 
|   | 2966 |   window_##window_number##_y2 =                                               \ | 
|   | 2967 |    io_registers[REG_WIN##window_number##V] & 0xFF;                            \ | 
|   | 2968 |                                                                               \ | 
|   | 2969 |   if(window_##window_number##_y1 > window_##window_number##_y2)               \ | 
|   | 2970 |   {                                                                           \ | 
|   | 2971 |     if((((vcount <= window_##window_number##_y2) ||                           \ | 
|   | 2972 |      (vcount > window_##window_number##_y1)) ||                               \ | 
|   | 2973 |      (window_##window_number##_y2 > 227)) &&                                  \ | 
|   | 2974 |      (window_##window_number##_y1 <= 227))                                    \ | 
|   | 2975 |     {                                                                         \ | 
|   | 2976 |       window_x_coords(window_number);                                         \ | 
|   | 2977 |     }                                                                         \ | 
|   | 2978 |     else                                                                      \ | 
|   | 2979 |     {                                                                         \ | 
|   | 2980 |       window_##window_number##_x1 = 240;                                      \ | 
|   | 2981 |       window_##window_number##_x2 = 240;                                      \ | 
|   | 2982 |     }                                                                         \ | 
|   | 2983 |   }                                                                           \ | 
|   | 2984 |   else                                                                        \ | 
|   | 2985 |   {                                                                           \ | 
|   | 2986 |     if((((vcount >= window_##window_number##_y1) &&                           \ | 
|   | 2987 |      (vcount < window_##window_number##_y2)) ||                               \ | 
|   | 2988 |      (window_##window_number##_y2 > 227)) &&                                  \ | 
|   | 2989 |      (window_##window_number##_y1 <= 227))                                    \ | 
|   | 2990 |     {                                                                         \ | 
|   | 2991 |       window_x_coords(window_number);                                         \ | 
|   | 2992 |     }                                                                         \ | 
|   | 2993 |     else                                                                      \ | 
|   | 2994 |     {                                                                         \ | 
|   | 2995 |       window_##window_number##_x1 = 240;                                      \ | 
|   | 2996 |       window_##window_number##_x2 = 240;                                      \ | 
|   | 2997 |     }                                                                         \ | 
|   | 2998 |   }                                                                           \ | 
|   | 2999 |  | 
|   | 3000 | #define render_window_segment(type, start, end, window_type)                  \ | 
|   | 3001 |   if(start != end)                                                            \ | 
|   | 3002 |   {                                                                           \ | 
|   | 3003 |     render_scanline_conditional_##type(start, end, scanline,                  \ | 
|   | 3004 |      window_##window_type##_enable, dispcnt, bldcnt, layer_renderers);        \ | 
|   | 3005 |   }                                                                           \ | 
|   | 3006 |  | 
|   | 3007 | #define render_window_segment_unequal(type, start, end, window_type)          \ | 
|   | 3008 |   render_scanline_conditional_##type(start, end, scanline,                    \ | 
|   | 3009 |    window_##window_type##_enable, dispcnt, bldcnt, layer_renderers)           \ | 
|   | 3010 |  | 
|   | 3011 | #define render_window_segment_clip(type, clip_start, clip_end, start, end,    \ | 
|   | 3012 |  window_type)                                                                 \ | 
|   | 3013 | {                                                                             \ | 
|   | 3014 |   if(start != end)                                                            \ | 
|   | 3015 |   {                                                                           \ | 
|   | 3016 |     if(start < clip_start)                                                    \ | 
|   | 3017 |     {                                                                         \ | 
|   | 3018 |       if(end > clip_start)                                                    \ | 
|   | 3019 |       {                                                                       \ | 
|   | 3020 |         if(end > clip_end)                                                    \ | 
|   | 3021 |         {                                                                     \ | 
|   | 3022 |           render_window_segment_unequal(type, clip_start, clip_end,           \ | 
|   | 3023 |            window_type);                                                      \ | 
|   | 3024 |         }                                                                     \ | 
|   | 3025 |         else                                                                  \ | 
|   | 3026 |         {                                                                     \ | 
|   | 3027 |           render_window_segment_unequal(type, clip_start, end, window_type);  \ | 
|   | 3028 |         }                                                                     \ | 
|   | 3029 |       }                                                                       \ | 
|   | 3030 |     }                                                                         \ | 
|   | 3031 |     else                                                                      \ | 
|   | 3032 |                                                                               \ | 
|   | 3033 |     if(end > clip_end)                                                        \ | 
|   | 3034 |     {                                                                         \ | 
|   | 3035 |       if(start < clip_end)                                                    \ | 
|   | 3036 |         render_window_segment_unequal(type, start, clip_end, window_type);    \ | 
|   | 3037 |     }                                                                         \ | 
|   | 3038 |     else                                                                      \ | 
|   | 3039 |     {                                                                         \ | 
|   | 3040 |       render_window_segment_unequal(type, start, end, window_type);           \ | 
|   | 3041 |     }                                                                         \ | 
|   | 3042 |   }                                                                           \ | 
|   | 3043 | }                                                                             \ | 
|   | 3044 |  | 
|   | 3045 | #define render_window_clip_1(type, start, end)                                \ | 
|   | 3046 |   if(window_1_x1 != 240)                                                      \ | 
|   | 3047 |   {                                                                           \ | 
|   | 3048 |     if(window_1_x1 > window_1_x2)                                             \ | 
|   | 3049 |     {                                                                         \ | 
|   | 3050 |       render_window_segment_clip(type, start, end, 0, window_1_x2, 1);        \ | 
|   | 3051 |       render_window_segment_clip(type, start, end, window_1_x2, window_1_x1,  \ | 
|   | 3052 |        out);                                                                  \ | 
|   | 3053 |       render_window_segment_clip(type, start, end, window_1_x1, 240, 1);      \ | 
|   | 3054 |     }                                                                         \ | 
|   | 3055 |     else                                                                      \ | 
|   | 3056 |     {                                                                         \ | 
|   | 3057 |       render_window_segment_clip(type, start, end, 0, window_1_x1, out);      \ | 
|   | 3058 |       render_window_segment_clip(type, start, end, window_1_x1, window_1_x2,  \ | 
|   | 3059 |        1);                                                                    \ | 
|   | 3060 |       render_window_segment_clip(type, start, end, window_1_x2, 240, out);    \ | 
|   | 3061 |     }                                                                         \ | 
|   | 3062 |   }                                                                           \ | 
|   | 3063 |   else                                                                        \ | 
|   | 3064 |   {                                                                           \ | 
|   | 3065 |     render_window_segment(type, start, end, out);                             \ | 
|   | 3066 |   }                                                                           \ | 
|   | 3067 |  | 
|   | 3068 | #define render_window_clip_obj(type, start, end);                             \ | 
|   | 3069 |   render_window_segment(type, start, end, out);                               \ | 
|   | 3070 |   if(dispcnt & 0x40)                                                          \ | 
|   | 3071 |     render_scanline_obj_copy_##type##_1D(4, start, end, scanline);            \ | 
|   | 3072 |   else                                                                        \ | 
|   | 3073 |     render_scanline_obj_copy_##type##_2D(4, start, end, scanline)             \ | 
|   | 3074 |  | 
|   | 3075 |  | 
|   | 3076 | #define render_window_segment_clip_obj(type, clip_start, clip_end, start,     \ | 
|   | 3077 |  end)                                                                         \ | 
|   | 3078 | {                                                                             \ | 
|   | 3079 |   if(start != end)                                                            \ | 
|   | 3080 |   {                                                                           \ | 
|   | 3081 |     if(start < clip_start)                                                    \ | 
|   | 3082 |     {                                                                         \ | 
|   | 3083 |       if(end > clip_start)                                                    \ | 
|   | 3084 |       {                                                                       \ | 
|   | 3085 |         if(end > clip_end)                                                    \ | 
|   | 3086 |         {                                                                     \ | 
|   | 3087 |           render_window_clip_obj(type, clip_start, clip_end);                 \ | 
|   | 3088 |         }                                                                     \ | 
|   | 3089 |         else                                                                  \ | 
|   | 3090 |         {                                                                     \ | 
|   | 3091 |           render_window_clip_obj(type, clip_start, end);                      \ | 
|   | 3092 |         }                                                                     \ | 
|   | 3093 |       }                                                                       \ | 
|   | 3094 |     }                                                                         \ | 
|   | 3095 |     else                                                                      \ | 
|   | 3096 |                                                                               \ | 
|   | 3097 |     if(end > clip_end)                                                        \ | 
|   | 3098 |     {                                                                         \ | 
|   | 3099 |       if(start < clip_end)                                                    \ | 
|   | 3100 |       {                                                                       \ | 
|   | 3101 |         render_window_clip_obj(type, start, clip_end);                        \ | 
|   | 3102 |       }                                                                       \ | 
|   | 3103 |     }                                                                         \ | 
|   | 3104 |     else                                                                      \ | 
|   | 3105 |     {                                                                         \ | 
|   | 3106 |       render_window_clip_obj(type, start, end);                               \ | 
|   | 3107 |     }                                                                         \ | 
|   | 3108 |   }                                                                           \ | 
|   | 3109 | }                                                                             \ | 
|   | 3110 |  | 
|   | 3111 |  | 
|   | 3112 | #define render_window_clip_1_obj(type, start, end)                            \ | 
|   | 3113 |   if(window_1_x1 != 240)                                                      \ | 
|   | 3114 |   {                                                                           \ | 
|   | 3115 |     if(window_1_x1 > window_1_x2)                                             \ | 
|   | 3116 |     {                                                                         \ | 
|   | 3117 |       render_window_segment_clip(type, start, end, 0, window_1_x2, 1);        \ | 
|   | 3118 |       render_window_segment_clip_obj(type, start, end, window_1_x2,           \ | 
|   | 3119 |        window_1_x1);                                                          \ | 
|   | 3120 |       render_window_segment_clip(type, start, end, window_1_x1, 240, 1);      \ | 
|   | 3121 |     }                                                                         \ | 
|   | 3122 |     else                                                                      \ | 
|   | 3123 |     {                                                                         \ | 
|   | 3124 |       render_window_segment_clip_obj(type, start, end, 0, window_1_x1);       \ | 
|   | 3125 |       render_window_segment_clip(type, start, end, window_1_x1, window_1_x2,  \ | 
|   | 3126 |        1);                                                                    \ | 
|   | 3127 |       render_window_segment_clip_obj(type, start, end, window_1_x2, 240);     \ | 
|   | 3128 |     }                                                                         \ | 
|   | 3129 |   }                                                                           \ | 
|   | 3130 |   else                                                                        \ | 
|   | 3131 |   {                                                                           \ | 
|   | 3132 |     render_window_clip_obj(type, start, end);                                 \ | 
|   | 3133 |   }                                                                           \ | 
|   | 3134 |  | 
|   | 3135 |  | 
|   | 3136 |  | 
|   | 3137 | #define render_window_single(type, window_number)                             \ | 
|   | 3138 |   u32 winin = io_registers[REG_WININ];                                        \ | 
|   | 3139 |   window_coords(window_number);                                               \ | 
|   | 3140 |   if(window_##window_number##_x1 > window_##window_number##_x2)               \ | 
|   | 3141 |   {                                                                           \ | 
|   | 3142 |     render_window_segment(type, 0, window_##window_number##_x2,               \ | 
|   | 3143 |      window_number);                                                          \ | 
|   | 3144 |     render_window_segment(type, window_##window_number##_x2,                  \ | 
|   | 3145 |      window_##window_number##_x1, out);                                       \ | 
|   | 3146 |     render_window_segment(type, window_##window_number##_x1, 240,             \ | 
|   | 3147 |      window_number);                                                          \ | 
|   | 3148 |   }                                                                           \ | 
|   | 3149 |   else                                                                        \ | 
|   | 3150 |   {                                                                           \ | 
|   | 3151 |     render_window_segment(type, 0, window_##window_number##_x1, out);         \ | 
|   | 3152 |     render_window_segment(type, window_##window_number##_x1,                  \ | 
|   | 3153 |      window_##window_number##_x2, window_number);                             \ | 
|   | 3154 |     render_window_segment(type, window_##window_number##_x2, 240, out);       \ | 
|   | 3155 |   }                                                                           \ | 
|   | 3156 |  | 
|   | 3157 | #define render_window_multi(type, front, back)                                \ | 
|   | 3158 |   if(window_##front##_x1 > window_##front##_x2)                               \ | 
|   | 3159 |   {                                                                           \ | 
|   | 3160 |     render_window_segment(type, 0, window_##front##_x2, front);               \ | 
|   | 3161 |     render_window_clip_##back(type, window_##front##_x2,                      \ | 
|   | 3162 |      window_##front##_x1);                                                    \ | 
|   | 3163 |     render_window_segment(type, window_##front##_x1, 240, front);             \ | 
|   | 3164 |   }                                                                           \ | 
|   | 3165 |   else                                                                        \ | 
|   | 3166 |   {                                                                           \ | 
|   | 3167 |     render_window_clip_##back(type, 0, window_##front##_x1);                  \ | 
|   | 3168 |     render_window_segment(type, window_##front##_x1, window_##front##_x2,     \ | 
|   | 3169 |      front);                                                                  \ | 
|   | 3170 |     render_window_clip_##back(type, window_##front##_x2, 240);                \ | 
|   | 3171 |   }                                                                           \ | 
|   | 3172 |  | 
|   | 3173 | #define render_scanline_window_builder(type)                                  \ | 
|   | 3174 | static void render_scanline_window_##type(u16 *scanline, u32 dispcnt)         \ | 
|   | 3175 | {                                                                             \ | 
|   | 3176 |   u32 vcount = io_registers[REG_VCOUNT];                                      \ | 
|   | 3177 |   u32 winout = io_registers[REG_WINOUT];                                      \ | 
|   | 3178 |   u32 bldcnt = io_registers[REG_BLDCNT];                                      \ | 
|   | 3179 |   u32 window_out_enable = winout & 0x3F;                                      \ | 
|   | 3180 |                                                                               \ | 
|   | 3181 |   render_scanline_layer_functions_##type();                                   \ | 
|   | 3182 |                                                                               \ | 
|   | 3183 |   switch(dispcnt >> 13)                                                       \ | 
|   | 3184 |   {                                                                           \ | 
|   | 3185 |     /* Just window 0 */                                                       \ | 
|   | 3186 |     case 0x01:                                                                \ | 
|   | 3187 |     {                                                                         \ | 
|   | 3188 |       render_window_single(type, 0);                                          \ | 
|   | 3189 |       break;                                                                  \ | 
|   | 3190 |     }                                                                         \ | 
|   | 3191 |                                                                               \ | 
|   | 3192 |     /* Just window 1 */                                                       \ | 
|   | 3193 |     case 0x02:                                                                \ | 
|   | 3194 |     {                                                                         \ | 
|   | 3195 |       render_window_single(type, 1);                                          \ | 
|   | 3196 |       break;                                                                  \ | 
|   | 3197 |     }                                                                         \ | 
|   | 3198 |                                                                               \ | 
|   | 3199 |     /* Windows 1 and 2 */                                                     \ | 
|   | 3200 |     case 0x03:                                                                \ | 
|   | 3201 |     {                                                                         \ | 
|   | 3202 |       u32 winin = io_registers[REG_WININ];                                    \ | 
|   | 3203 |       window_coords(0);                                                       \ | 
|   | 3204 |       window_coords(1);                                                       \ | 
|   | 3205 |       render_window_multi(type, 0, 1);                                        \ | 
|   | 3206 |       break;                                                                  \ | 
|   | 3207 |     }                                                                         \ | 
|   | 3208 |                                                                               \ | 
|   | 3209 |     /* Just OBJ windows */                                                    \ | 
|   | 3210 |     case 0x04:                                                                \ | 
|   | 3211 |     {                                                                         \ | 
|   | 3212 |       render_window_clip_obj(type, 0, 240);                                   \ | 
|   | 3213 |       break;                                                                  \ | 
|   | 3214 |     }                                                                         \ | 
|   | 3215 |                                                                               \ | 
|   | 3216 |     /* Window 0 and OBJ window */                                             \ | 
|   | 3217 |     case 0x05:                                                                \ | 
|   | 3218 |     {                                                                         \ | 
|   | 3219 |       u32 winin = io_registers[REG_WININ];                                    \ | 
|   | 3220 |       window_coords(0);                                                       \ | 
|   | 3221 |       render_window_multi(type, 0, obj);                                      \ | 
|   | 3222 |       break;                                                                  \ | 
|   | 3223 |     }                                                                         \ | 
|   | 3224 |                                                                               \ | 
|   | 3225 |     /* Window 1 and OBJ window */                                             \ | 
|   | 3226 |     case 0x06:                                                                \ | 
|   | 3227 |     {                                                                         \ | 
|   | 3228 |       u32 winin = io_registers[REG_WININ];                                    \ | 
|   | 3229 |       window_coords(1);                                                       \ | 
|   | 3230 |       render_window_multi(type, 1, obj);                                      \ | 
|   | 3231 |       break;                                                                  \ | 
|   | 3232 |     }                                                                         \ | 
|   | 3233 |                                                                               \ | 
|   | 3234 |     /* Window 0, 1, and OBJ window */                                         \ | 
|   | 3235 |     case 0x07:                                                                \ | 
|   | 3236 |     {                                                                         \ | 
|   | 3237 |       u32 winin = io_registers[REG_WININ];                                    \ | 
|   | 3238 |       window_coords(0);                                                       \ | 
|   | 3239 |       window_coords(1);                                                       \ | 
|   | 3240 |       render_window_multi(type, 0, 1_obj);                                    \ | 
|   | 3241 |       break;                                                                  \ | 
|   | 3242 |     }                                                                         \ | 
|   | 3243 |   }                                                                           \ | 
|   | 3244 | }                                                                             \ | 
|   | 3245 |  | 
|   | 3246 | render_scanline_window_builder(tile); | 
|   | 3247 | render_scanline_window_builder(bitmap); | 
|   | 3248 |  | 
|   | 3249 | static const u32 active_layers[6] = { 0x1F, 0x17, 0x1C, 0x14, 0x14, 0x14 }; | 
|   | 3250 |  | 
|   | 3251 | u32 small_resolution_width = 240; | 
|   | 3252 | u32 small_resolution_height = 160; | 
|   | 3253 | u32 resolution_width, resolution_height; | 
|   | 3254 |  | 
|   | 3255 | void update_scanline() | 
|   | 3256 | { | 
|   | 3257 |   u32 pitch = get_screen_pitch(); | 
|   | 3258 |   u32 dispcnt = io_registers[REG_DISPCNT]; | 
|   | 3259 |   u32 vcount = io_registers[REG_VCOUNT]; | 
|   | 3260 |   u16 *screen_offset = get_screen_pixels() + (vcount * pitch); | 
|   | 3261 |   u32 video_mode = dispcnt & 0x07; | 
|   | 3262 |  | 
|   | 3263 |   // If OAM has been modified since the last scanline has been updated then | 
|   | 3264 |   // reorder and reprofile the OBJ lists. | 
|   | 3265 |   if(oam_update) | 
|   | 3266 |   { | 
|   | 3267 |     order_obj(video_mode); | 
|   | 3268 |     oam_update = 0; | 
|   | 3269 |   } | 
|   | 3270 |  | 
|   | 3271 |   order_layers((dispcnt >> 8) & active_layers[video_mode]); | 
|   | 3272 |  | 
|   | 3273 |   if(skip_next_frame) | 
|   | 3274 |     return; | 
|   | 3275 |  | 
|   | 3276 | #ifdef WIZ_BUILD | 
|   | 3277 |   if (screen_scale == unscaled_rot || screen_scale == scaled_aspect_rot) | 
|   | 3278 |   { | 
|   | 3279 |     if (rot_line_count == rot_lines_total) | 
|   | 3280 |     { | 
|   | 3281 |       rot_line_count = 0; | 
|   | 3282 |       if (vcount - rot_lines_total < FONT_HEIGHT && rot_msg_buff[0]) | 
|   | 3283 |       { | 
|   | 3284 |         print_string_ext(rot_msg_buff, 0xFFFF, 0x0000, 0, 0, | 
|   | 3285 |           rot_buffer, 240, 0, vcount - rot_lines_total, rot_lines_total); | 
|   | 3286 |         if (vcount >= FONT_HEIGHT) | 
|   | 3287 |           rot_msg_buff[0] = 0; | 
|   | 3288 |       } | 
|   | 3289 |       if (screen_scale == unscaled_rot) | 
|   | 3290 |         do_rotated_blit(gpsp_gp2x_screen, rot_buffer, vcount); | 
|   | 3291 |       else | 
|   | 3292 |         upscale_aspect_row(gpsp_gp2x_screen, rot_buffer, vcount/3); | 
|   | 3293 |     } | 
|   | 3294 |     screen_offset = &rot_buffer[rot_line_count++ * 240]; | 
|   | 3295 |   } | 
|   | 3296 | #endif | 
|   | 3297 |  | 
|   | 3298 |   // If the screen is in in forced blank draw pure white. | 
|   | 3299 |   if(dispcnt & 0x80) | 
|   | 3300 |   { | 
|   | 3301 |     fill_line_color16(0xFFFF, screen_offset, 0, 240); | 
|   | 3302 |   } | 
|   | 3303 |   else | 
|   | 3304 |   { | 
|   | 3305 |     if(video_mode < 3) | 
|   | 3306 |     { | 
|   | 3307 |       if(dispcnt >> 13) | 
|   | 3308 |       { | 
|   | 3309 |         render_scanline_window_tile(screen_offset, dispcnt); | 
|   | 3310 |       } | 
|   | 3311 |       else | 
|   | 3312 |       { | 
|   | 3313 |         render_scanline_tile(screen_offset, dispcnt); | 
|   | 3314 |       } | 
|   | 3315 |     } | 
|   | 3316 |     else | 
|   | 3317 |     { | 
|   | 3318 |       if(dispcnt >> 13) | 
|   | 3319 |         render_scanline_window_bitmap(screen_offset, dispcnt); | 
|   | 3320 |       else | 
|   | 3321 |         render_scanline_bitmap(screen_offset, dispcnt); | 
|   | 3322 |     } | 
|   | 3323 |   } | 
|   | 3324 |  | 
|   | 3325 |   affine_reference_x[0] += (s16)io_registers[REG_BG2PB]; | 
|   | 3326 |   affine_reference_y[0] += (s16)io_registers[REG_BG2PD]; | 
|   | 3327 |   affine_reference_x[1] += (s16)io_registers[REG_BG3PB]; | 
|   | 3328 |   affine_reference_y[1] += (s16)io_registers[REG_BG3PD]; | 
|   | 3329 | } | 
|   | 3330 |  | 
|   | 3331 | #ifdef PSP_BUILD | 
|   | 3332 |  | 
|   | 3333 | u32 screen_flip = 0; | 
|   | 3334 |  | 
|   | 3335 | void flip_screen() | 
|   | 3336 | { | 
|   | 3337 |   if(video_direct == 0) | 
|   | 3338 |   { | 
|   | 3339 |     u32 *old_ge_cmd_ptr = ge_cmd_ptr; | 
|   | 3340 |     sceKernelDcacheWritebackAll(); | 
|   | 3341 |  | 
|   | 3342 |     // Render the current screen | 
|   | 3343 |     ge_cmd_ptr = ge_cmd + 2; | 
|   | 3344 |     GE_CMD(TBP0, ((u32)screen_pixels & 0x00FFFFFF)); | 
|   | 3345 |     GE_CMD(TBW0, (((u32)screen_pixels & 0xFF000000) >> 8) | | 
|   | 3346 |      GBA_SCREEN_WIDTH); | 
|   | 3347 |     ge_cmd_ptr = old_ge_cmd_ptr; | 
|   | 3348 |  | 
|   | 3349 |     sceGeListEnQueue(ge_cmd, ge_cmd_ptr, gecbid, NULL); | 
|   | 3350 |  | 
|   | 3351 |     // Flip to the next screen | 
|   | 3352 |     screen_flip ^= 1; | 
|   | 3353 |  | 
|   | 3354 |     if(screen_flip) | 
|   | 3355 |       screen_pixels = screen_texture + (240 * 160 * 2); | 
|   | 3356 |     else | 
|   | 3357 |       screen_pixels = screen_texture; | 
|   | 3358 |   } | 
|   | 3359 | } | 
|   | 3360 |  | 
|   | 3361 | #elif defined(POLLUX_BUILD) | 
|   | 3362 |  | 
|   | 3363 | void flip_screen() | 
|   | 3364 | { | 
|   | 3365 |   if((resolution_width == small_resolution_width) && | 
|   | 3366 |    (resolution_height == small_resolution_height)) | 
|   | 3367 |   { | 
|   | 3368 |     switch(screen_scale) | 
|   | 3369 |     { | 
|   | 3370 |       case unscaled: | 
|   | 3371 |         break; | 
|   | 3372 |       case scaled_aspect: | 
|   | 3373 |         upscale_aspect(gpsp_gp2x_screen, screen_pixels); | 
|   | 3374 |         break; | 
|   | 3375 |       case unscaled_rot: | 
|   | 3376 |         do_rotated_blit(gpsp_gp2x_screen, rot_buffer, 160); | 
|   | 3377 |         rot_line_count = 0; | 
|   | 3378 |         goto no_clean; | 
|   | 3379 |       case scaled_aspect_rot: | 
|   | 3380 |         rot_line_count = 0; | 
|   | 3381 |         goto no_clean; | 
|   | 3382 |     } | 
|   | 3383 |   } | 
|   | 3384 |   warm_cache_op_all(WOP_D_CLEAN); | 
|   | 3385 |  | 
|   | 3386 | no_clean: | 
|   | 3387 |   pollux_video_flip(); | 
|   | 3388 |   screen_pixels = (u16 *)gpsp_gp2x_screen + screen_offset; | 
|   | 3389 | } | 
|   | 3390 |  | 
|   | 3391 | #elif defined(PND_BUILD) || defined(RPI_BUILD) | 
|   | 3392 |  | 
|   | 3393 | void flip_screen() | 
|   | 3394 | { | 
|   | 3395 |   screen_pixels = fb_flip_screen(); | 
|   | 3396 | } | 
|   | 3397 |  | 
|   | 3398 | #else | 
|   | 3399 |  | 
|   | 3400 | #define integer_scale_copy_2()                                                \ | 
|   | 3401 |   current_scanline_ptr[x2] = current_pixel;                                   \ | 
|   | 3402 |   current_scanline_ptr[x2 - 1] = current_pixel;                               \ | 
|   | 3403 |   x2 -= 2                                                                     \ | 
|   | 3404 |  | 
|   | 3405 | #define integer_scale_copy_3()                                                \ | 
|   | 3406 |   current_scanline_ptr[x2] = current_pixel;                                   \ | 
|   | 3407 |   current_scanline_ptr[x2 - 1] = current_pixel;                               \ | 
|   | 3408 |   current_scanline_ptr[x2 - 2] = current_pixel;                               \ | 
|   | 3409 |   x2 -= 3                                                                     \ | 
|   | 3410 |  | 
|   | 3411 | #define integer_scale_copy_4()                                                \ | 
|   | 3412 |   current_scanline_ptr[x2] = current_pixel;                                   \ | 
|   | 3413 |   current_scanline_ptr[x2 - 1] = current_pixel;                               \ | 
|   | 3414 |   current_scanline_ptr[x2 - 2] = current_pixel;                               \ | 
|   | 3415 |   current_scanline_ptr[x2 - 3] = current_pixel;                               \ | 
|   | 3416 |   x2 -= 4                                                                     \ | 
|   | 3417 |  | 
|   | 3418 | #define integer_scale_horizontal(scale_factor)                                \ | 
|   | 3419 |   for(y = 0; y < 160; y++)                                                    \ | 
|   | 3420 |   {                                                                           \ | 
|   | 3421 |     for(x = 239, x2 = (240 * video_scale) - 1; x >= 0; x--)                   \ | 
|   | 3422 |     {                                                                         \ | 
|   | 3423 |       current_pixel = current_scanline_ptr[x];                                \ | 
|   | 3424 |       integer_scale_copy_##scale_factor();                                    \ | 
|   | 3425 |       current_scanline_ptr[x2] = current_scanline_ptr[x];                     \ | 
|   | 3426 |       current_scanline_ptr[x2 - 1] = current_scanline_ptr[x];                 \ | 
|   | 3427 |       current_scanline_ptr[x2 - 2] = current_scanline_ptr[x];                 \ | 
|   | 3428 |     }                                                                         \ | 
|   | 3429 |     current_scanline_ptr += pitch;                                            \ | 
|   | 3430 |   }                                                                           \ | 
|   | 3431 |  | 
|   | 3432 | void flip_screen() | 
|   | 3433 | { | 
|   | 3434 |   if((video_scale != 1) && (current_scale != unscaled)) | 
|   | 3435 |   { | 
|   | 3436 |     s32 x, y; | 
|   | 3437 |     s32 x2, y2; | 
|   | 3438 |     u16 *screen_ptr = get_screen_pixels(); | 
|   | 3439 |     u16 *current_scanline_ptr = screen_ptr; | 
|   | 3440 |     u32 pitch = get_screen_pitch(); | 
|   | 3441 |     u16 current_pixel; | 
|   | 3442 |     u32 i; | 
|   | 3443 |  | 
|   | 3444 |     switch(video_scale) | 
|   | 3445 |     { | 
|   | 3446 |       case 2: | 
|   | 3447 |         integer_scale_horizontal(2); | 
|   | 3448 |         break; | 
|   | 3449 |  | 
|   | 3450 |       case 3: | 
|   | 3451 |         integer_scale_horizontal(3); | 
|   | 3452 |         break; | 
|   | 3453 |  | 
|   | 3454 |       default: | 
|   | 3455 |       case 4: | 
|   | 3456 |         integer_scale_horizontal(4); | 
|   | 3457 |         break; | 
|   | 3458 |  | 
|   | 3459 |     } | 
|   | 3460 |  | 
|   | 3461 |     for(y = 159, y2 = (160 * video_scale) - 1; y >= 0; y--) | 
|   | 3462 |     { | 
|   | 3463 |       for(i = 0; i < video_scale; i++) | 
|   | 3464 |       { | 
|   | 3465 |         memcpy(screen_ptr + (y2 * pitch), | 
|   | 3466 |          screen_ptr + (y * pitch), 480 * video_scale); | 
|   | 3467 |         y2--; | 
|   | 3468 |       } | 
|   | 3469 |     } | 
|   | 3470 |   } | 
|   | 3471 | #ifdef GP2X_BUILD | 
|   | 3472 |   { | 
|   | 3473 |     if((resolution_width == small_resolution_width) && | 
|   | 3474 |      (resolution_height == small_resolution_height)) | 
|   | 3475 |     { | 
|   | 3476 |       switch (screen_scale) | 
|   | 3477 |       { | 
|   | 3478 |         case unscaled: | 
|   | 3479 |         { | 
|   | 3480 |           SDL_Rect srect = {0, 0, 240, 160}; | 
|   | 3481 |           SDL_Rect drect = {40, 40, 240, 160}; | 
|   | 3482 |           warm_cache_op_all(WOP_D_CLEAN); | 
|   | 3483 |           SDL_BlitSurface(screen, &srect, hw_screen, &drect); | 
|   | 3484 |           return; | 
|   | 3485 |         } | 
|   | 3486 |         case scaled_aspect: | 
|   | 3487 |         { | 
|   | 3488 |           SDL_Rect drect = {0, 10, 0, 0}; | 
|   | 3489 |           warm_cache_op_all(WOP_D_CLEAN); | 
|   | 3490 |           SDL_BlitSurface(screen, NULL, hw_screen, &drect); | 
|   | 3491 |           return; | 
|   | 3492 |         } | 
|   | 3493 |         case scaled_aspect_sw: | 
|   | 3494 |         { | 
|   | 3495 |           upscale_aspect(hw_screen->pixels, get_screen_pixels()); | 
|   | 3496 |           return; | 
|   | 3497 |         } | 
|   | 3498 |         case fullscreen: | 
|   | 3499 |           break; | 
|   | 3500 |       } | 
|   | 3501 |     } | 
|   | 3502 |     warm_cache_op_all(WOP_D_CLEAN); | 
|   | 3503 |     SDL_BlitSurface(screen, NULL, hw_screen, NULL); | 
|   | 3504 |   } | 
|   | 3505 | #else | 
|   | 3506 |   SDL_Flip(screen); | 
|   | 3507 | #endif | 
|   | 3508 | } | 
|   | 3509 |  | 
|   | 3510 | #endif | 
|   | 3511 |  | 
|   | 3512 | u32 frame_to_render; | 
|   | 3513 |  | 
|   | 3514 | void update_screen() | 
|   | 3515 | { | 
|   | 3516 |   if(!skip_next_frame) | 
|   | 3517 |     flip_screen(); | 
|   | 3518 | } | 
|   | 3519 |  | 
|   | 3520 | #ifdef PSP_BUILD | 
|   | 3521 |  | 
|   | 3522 | void init_video() | 
|   | 3523 | { | 
|   | 3524 |   sceDisplaySetMode(0, PSP_SCREEN_WIDTH, PSP_SCREEN_HEIGHT); | 
|   | 3525 |  | 
|   | 3526 |   sceDisplayWaitVblankStart(); | 
|   | 3527 |   sceDisplaySetFrameBuf((void*)psp_gu_vram_base, PSP_LINE_SIZE, | 
|   | 3528 |    PSP_DISPLAY_PIXEL_FORMAT_565, PSP_DISPLAY_SETBUF_NEXTFRAME); | 
|   | 3529 |  | 
|   | 3530 |   sceGuInit(); | 
|   | 3531 |  | 
|   | 3532 |   sceGuStart(GU_DIRECT, display_list); | 
|   | 3533 |   sceGuDrawBuffer(GU_PSM_5650, (void*)0, PSP_LINE_SIZE); | 
|   | 3534 |   sceGuDispBuffer(PSP_SCREEN_WIDTH, PSP_SCREEN_HEIGHT, | 
|   | 3535 |    (void*)0, PSP_LINE_SIZE); | 
|   | 3536 |   sceGuClear(GU_COLOR_BUFFER_BIT); | 
|   | 3537 |  | 
|   | 3538 |   sceGuOffset(2048 - (PSP_SCREEN_WIDTH / 2), 2048 - (PSP_SCREEN_HEIGHT / 2)); | 
|   | 3539 |   sceGuViewport(2048, 2048, PSP_SCREEN_WIDTH, PSP_SCREEN_HEIGHT); | 
|   | 3540 |  | 
|   | 3541 |   sceGuScissor(0, 0, PSP_SCREEN_WIDTH + 1, PSP_SCREEN_HEIGHT + 1); | 
|   | 3542 |   sceGuEnable(GU_SCISSOR_TEST); | 
|   | 3543 |   sceGuTexMode(GU_PSM_5650, 0, 0, GU_FALSE); | 
|   | 3544 |   sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGBA); | 
|   | 3545 |   sceGuTexFilter(GU_LINEAR, GU_LINEAR); | 
|   | 3546 |   sceGuEnable(GU_TEXTURE_2D); | 
|   | 3547 |  | 
|   | 3548 |   sceGuFrontFace(GU_CW); | 
|   | 3549 |   sceGuDisable(GU_BLEND); | 
|   | 3550 |  | 
|   | 3551 |   sceGuFinish(); | 
|   | 3552 |   sceGuSync(0, 0); | 
|   | 3553 |  | 
|   | 3554 |   sceDisplayWaitVblankStart(); | 
|   | 3555 |   sceGuDisplay(GU_TRUE); | 
|   | 3556 |  | 
|   | 3557 |   PspGeCallbackData gecb; | 
|   | 3558 |   gecb.signal_func = NULL; | 
|   | 3559 |   gecb.signal_arg = NULL; | 
|   | 3560 |   gecb.finish_func = Ge_Finish_Callback; | 
|   | 3561 |   gecb.finish_arg = NULL; | 
|   | 3562 |   gecbid = sceGeSetCallback(&gecb); | 
|   | 3563 |  | 
|   | 3564 |   screen_vertex[0] = 0 + 0.5; | 
|   | 3565 |   screen_vertex[1] = 0 + 0.5; | 
|   | 3566 |   screen_vertex[2] = 0 + 0.5; | 
|   | 3567 |   screen_vertex[3] = 0 + 0.5; | 
|   | 3568 |   screen_vertex[4] = 0; | 
|   | 3569 |   screen_vertex[5] = GBA_SCREEN_WIDTH - 0.5; | 
|   | 3570 |   screen_vertex[6] = GBA_SCREEN_HEIGHT - 0.5; | 
|   | 3571 |   screen_vertex[7] = PSP_SCREEN_WIDTH - 0.5; | 
|   | 3572 |   screen_vertex[8] = PSP_SCREEN_HEIGHT - 0.5; | 
|   | 3573 |   screen_vertex[9] = 0; | 
|   | 3574 |  | 
|   | 3575 |   // Set framebuffer to PSP VRAM | 
|   | 3576 |   GE_CMD(FBP, ((u32)psp_gu_vram_base & 0x00FFFFFF)); | 
|   | 3577 |   GE_CMD(FBW, (((u32)psp_gu_vram_base & 0xFF000000) >> 8) | PSP_LINE_SIZE); | 
|   | 3578 |   // Set texture 0 to the screen texture | 
|   | 3579 |   GE_CMD(TBP0, ((u32)screen_texture & 0x00FFFFFF)); | 
|   | 3580 |   GE_CMD(TBW0, (((u32)screen_texture & 0xFF000000) >> 8) | GBA_SCREEN_WIDTH); | 
|   | 3581 |   // Set the texture size to 256 by 256 (2^8 by 2^8) | 
|   | 3582 |   GE_CMD(TSIZE0, (8 << 8) | 8); | 
|   | 3583 |   // Flush the texture cache | 
|   | 3584 |   GE_CMD(TFLUSH, 0); | 
|   | 3585 |   // Use 2D coordinates, no indeces, no weights, 32bit float positions, | 
|   | 3586 |   // 32bit float texture coordinates | 
|   | 3587 |   GE_CMD(VTYPE, (1 << 23) | (0 << 11) | (0 << 9) | | 
|   | 3588 |    (3 << 7) | (0 << 5) | (0 << 2) | 3); | 
|   | 3589 |   // Set the base of the index list pointer to 0 | 
|   | 3590 |   GE_CMD(BASE, 0); | 
|   | 3591 |   // Set the rest of index list pointer to 0 (not being used) | 
|   | 3592 |   GE_CMD(IADDR, 0); | 
|   | 3593 |   // Set the base of the screen vertex list pointer | 
|   | 3594 |   GE_CMD(BASE, ((u32)screen_vertex & 0xFF000000) >> 8); | 
|   | 3595 |   // Set the rest of the screen vertex list pointer | 
|   | 3596 |   GE_CMD(VADDR, ((u32)screen_vertex & 0x00FFFFFF)); | 
|   | 3597 |   // Primitive kick: render sprite (primitive 6), 2 vertices | 
|   | 3598 |   GE_CMD(PRIM, (6 << 16) | 2); | 
|   | 3599 |   // Done with commands | 
|   | 3600 |   GE_CMD(FINISH, 0); | 
|   | 3601 |   // Raise signal interrupt | 
|   | 3602 |   GE_CMD(SIGNAL, 0); | 
|   | 3603 |   GE_CMD(NOP, 0); | 
|   | 3604 |   GE_CMD(NOP, 0); | 
|   | 3605 | } | 
|   | 3606 |  | 
|   | 3607 | #elif defined(WIZ_BUILD) || defined(PND_BUILD) || defined (RPI_BUILD) | 
|   | 3608 |  | 
|   | 3609 | void init_video() | 
|   | 3610 | { | 
|   | 3611 | } | 
|   | 3612 |  | 
|   | 3613 | #else | 
|   | 3614 |  | 
|   | 3615 | void init_video() | 
|   | 3616 | { | 
|   | 3617 |   SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_NOPARACHUTE); | 
|   | 3618 |  | 
|   | 3619 | #ifdef GP2X_BUILD | 
|   | 3620 |   SDL_GP2X_AllowGfxMemory(NULL, 0); | 
|   | 3621 |  | 
|   | 3622 |   hw_screen = SDL_SetVideoMode(320 * video_scale, 240 * video_scale, | 
|   | 3623 |    16, SDL_HWSURFACE); | 
|   | 3624 |  | 
|   | 3625 |   screen = SDL_CreateRGBSurface(SDL_HWSURFACE, 240 * video_scale, | 
|   | 3626 |    160 * video_scale, 16, 0xFFFF, 0xFFFF, 0xFFFF, 0); | 
|   | 3627 |  | 
|   | 3628 |   warm_change_cb_upper(WCB_C_BIT|WCB_B_BIT, 1); | 
|   | 3629 | #else | 
|   | 3630 |   screen = SDL_SetVideoMode(240 * video_scale, 160 * video_scale, 16, 0); | 
|   | 3631 | #endif | 
|   | 3632 |   SDL_ShowCursor(0); | 
|   | 3633 | } | 
|   | 3634 |  | 
|   | 3635 | #endif | 
|   | 3636 |  | 
|   | 3637 | video_scale_type screen_scale = scaled_aspect; | 
|   | 3638 | video_scale_type current_scale = scaled_aspect; | 
|   | 3639 | video_filter_type screen_filter = filter_bilinear; | 
|   | 3640 | video_filter_type2 screen_filter2 = filter2_none; | 
|   | 3641 |  | 
|   | 3642 |  | 
|   | 3643 | #ifdef PSP_BUILD | 
|   | 3644 |  | 
|   | 3645 | void video_resolution_large() | 
|   | 3646 | { | 
|   | 3647 |   if(video_direct != 1) | 
|   | 3648 |   { | 
|   | 3649 |     video_direct = 1; | 
|   | 3650 |     screen_pixels = psp_gu_vram_base; | 
|   | 3651 |     screen_pitch = 512; | 
|   | 3652 |     sceGuStart(GU_DIRECT, display_list); | 
|   | 3653 |     sceGuDispBuffer(PSP_SCREEN_WIDTH, PSP_SCREEN_HEIGHT, | 
|   | 3654 |      (void*)0, PSP_LINE_SIZE); | 
|   | 3655 |     sceGuFinish(); | 
|   | 3656 |   } | 
|   | 3657 | } | 
|   | 3658 |  | 
|   | 3659 | void set_gba_resolution(video_scale_type scale) | 
|   | 3660 | { | 
|   | 3661 |   u32 filter_linear = 0; | 
|   | 3662 |   screen_scale = scale; | 
|   | 3663 |   switch(scale) | 
|   | 3664 |   { | 
|   | 3665 |     case unscaled: | 
|   | 3666 |       screen_vertex[2] = 120 + 0.5; | 
|   | 3667 |       screen_vertex[3] = 56 + 0.5; | 
|   | 3668 |       screen_vertex[7] = GBA_SCREEN_WIDTH + 120 - 0.5; | 
|   | 3669 |       screen_vertex[8] = GBA_SCREEN_HEIGHT + 56 - 0.5; | 
|   | 3670 |       break; | 
|   | 3671 |  | 
|   | 3672 |     case scaled_aspect: | 
|   | 3673 |       screen_vertex[2] = 36 + 0.5; | 
|   | 3674 |       screen_vertex[3] = 0 + 0.5; | 
|   | 3675 |       screen_vertex[7] = 408 + 36 - 0.5; | 
|   | 3676 |       screen_vertex[8] = PSP_SCREEN_HEIGHT - 0.5; | 
|   | 3677 |       break; | 
|   | 3678 |  | 
|   | 3679 |     case fullscreen: | 
|   | 3680 |       screen_vertex[2] = 0; | 
|   | 3681 |       screen_vertex[3] = 0; | 
|   | 3682 |       screen_vertex[7] = PSP_SCREEN_WIDTH; | 
|   | 3683 |       screen_vertex[8] = PSP_SCREEN_HEIGHT; | 
|   | 3684 |       break; | 
|   | 3685 |   } | 
|   | 3686 |  | 
|   | 3687 |   sceGuStart(GU_DIRECT, display_list); | 
|   | 3688 |   if(screen_filter == filter_bilinear) | 
|   | 3689 |     sceGuTexFilter(GU_LINEAR, GU_LINEAR); | 
|   | 3690 |   else | 
|   | 3691 |     sceGuTexFilter(GU_NEAREST, GU_NEAREST); | 
|   | 3692 |  | 
|   | 3693 |   sceGuFinish(); | 
|   | 3694 |   sceGuSync(0, 0); | 
|   | 3695 |  | 
|   | 3696 |   clear_screen(0x0000); | 
|   | 3697 | } | 
|   | 3698 |  | 
|   | 3699 | void video_resolution_small() | 
|   | 3700 | { | 
|   | 3701 |   if(video_direct != 0) | 
|   | 3702 |   { | 
|   | 3703 |     set_gba_resolution(screen_scale); | 
|   | 3704 |     video_direct = 0; | 
|   | 3705 |     screen_pixels = screen_texture; | 
|   | 3706 |     screen_flip = 0; | 
|   | 3707 |     screen_pitch = 240; | 
|   | 3708 |     sceGuStart(GU_DIRECT, display_list); | 
|   | 3709 |     sceGuDispBuffer(PSP_SCREEN_WIDTH, PSP_SCREEN_HEIGHT, | 
|   | 3710 |      (void*)0, PSP_LINE_SIZE); | 
|   | 3711 |     sceGuFinish(); | 
|   | 3712 |   } | 
|   | 3713 | } | 
|   | 3714 |  | 
|   | 3715 | void clear_screen(u16 color) | 
|   | 3716 | { | 
|   | 3717 |   u32 i; | 
|   | 3718 |   u16 *src_ptr = get_screen_pixels(); | 
|   | 3719 |  | 
|   | 3720 |   sceGuSync(0, 0); | 
|   | 3721 |  | 
|   | 3722 |   for(i = 0; i < (512 * 272); i++, src_ptr++) | 
|   | 3723 |   { | 
|   | 3724 |     *src_ptr = color; | 
|   | 3725 |   } | 
|   | 3726 |  | 
|   | 3727 |   // I don't know why this doesn't work. | 
|   | 3728 | /*  color = (((color & 0x1F) * 255 / 31) << 0) | | 
|   | 3729 |    ((((color >> 5) & 0x3F) * 255 / 63) << 8) | | 
|   | 3730 |    ((((color >> 11) & 0x1F) * 255 / 31) << 16) | (0xFF << 24); | 
|   | 3731 |  | 
|   | 3732 |   sceGuStart(GU_DIRECT, display_list); | 
|   | 3733 |   sceGuDrawBuffer(GU_PSM_5650, (void*)0, PSP_LINE_SIZE); | 
|   | 3734 |   //sceGuDispBuffer(PSP_SCREEN_WIDTH, PSP_SCREEN_HEIGHT, | 
|   | 3735 |   // (void*)0, PSP_LINE_SIZE); | 
|   | 3736 |   sceGuClearColor(color); | 
|   | 3737 |   sceGuClear(GU_COLOR_BUFFER_BIT); | 
|   | 3738 |   sceGuFinish(); | 
|   | 3739 |   sceGuSync(0, 0); */ | 
|   | 3740 | } | 
|   | 3741 |  | 
|   | 3742 | #elif defined(POLLUX_BUILD) | 
|   | 3743 |  | 
|   | 3744 | void video_resolution_large() | 
|   | 3745 | { | 
|   | 3746 |   screen_offset = 0; | 
|   | 3747 |   resolution_width = 320; | 
|   | 3748 |   resolution_height = 240; | 
|   | 3749 |  | 
|   | 3750 |   fb_use_buffers(1); | 
|   | 3751 |   flip_screen(); | 
|   | 3752 |   clear_screen(0); | 
|   | 3753 |   wiz_lcd_set_portrait(0); | 
|   | 3754 | } | 
|   | 3755 |  | 
|   | 3756 | void video_resolution_small() | 
|   | 3757 | { | 
|   | 3758 |   fb_use_buffers(4); | 
|   | 3759 |  | 
|   | 3760 |   switch (screen_scale) | 
|   | 3761 |   { | 
|   | 3762 |     case unscaled: | 
|   | 3763 |       screen_offset = 320*40 + 40; | 
|   | 3764 |       wiz_lcd_set_portrait(0); | 
|   | 3765 |       break; | 
|   | 3766 |     case scaled_aspect: | 
|   | 3767 |       screen_offset = 320*(80 - 14) + 80; | 
|   | 3768 |       wiz_lcd_set_portrait(0); | 
|   | 3769 |       break; | 
|   | 3770 |     case unscaled_rot: | 
|   | 3771 |       wiz_lcd_set_portrait(1); | 
|   | 3772 |       rot_lines_total = 4; | 
|   | 3773 |       rot_line_count = 0; | 
|   | 3774 |       break; | 
|   | 3775 |     case scaled_aspect_rot: | 
|   | 3776 |       wiz_lcd_set_portrait(1); | 
|   | 3777 |       rot_lines_total = 3; | 
|   | 3778 |       rot_line_count = 0; | 
|   | 3779 |       break; | 
|   | 3780 |   } | 
|   | 3781 |  | 
|   | 3782 |   flip_screen(); | 
|   | 3783 |   clear_screen(0); | 
|   | 3784 |  | 
|   | 3785 |   resolution_width = 240; | 
|   | 3786 |   resolution_height = 160; | 
|   | 3787 | } | 
|   | 3788 |  | 
|   | 3789 | void set_gba_resolution(video_scale_type scale) | 
|   | 3790 | { | 
|   | 3791 |   screen_scale = scale; | 
|   | 3792 | } | 
|   | 3793 |  | 
|   | 3794 | void clear_screen(u16 color) | 
|   | 3795 | { | 
|   | 3796 |   u32 col = ((u32)color << 16) | color; | 
|   | 3797 |   u32 *p = gpsp_gp2x_screen; | 
|   | 3798 |   int c = 320*240/2; | 
|   | 3799 |   while (c-- > 0) | 
|   | 3800 |     *p++ = col; | 
|   | 3801 | } | 
|   | 3802 |  | 
|   | 3803 | #elif defined(PND_BUILD) || defined(RPI_BUILD) | 
|   | 3804 |  | 
|   | 3805 | void video_resolution_large() | 
|   | 3806 | { | 
|   | 3807 | #if defined (RPI_BUILD) | 
|   | 3808 |   resolution_width = 480; | 
|   | 3809 | #else | 
|   | 3810 |   resolution_width = 400; | 
|   | 3811 | #endif | 
|   | 3812 |   resolution_height = 272; | 
|   | 3813 |  | 
|   | 3814 |   fb_set_mode(resolution_width, resolution_height, 1, 15, screen_filter, screen_filter2); | 
|   | 3815 |   flip_screen(); | 
|   | 3816 |   clear_screen(0); | 
|   | 3817 | } | 
|   | 3818 |  | 
|   | 3819 | void video_resolution_small() | 
|   | 3820 | { | 
|   | 3821 |   resolution_width = 240; | 
|   | 3822 |   resolution_height = 160; | 
|   | 3823 |  | 
|   | 3824 |   fb_set_mode(resolution_width, resolution_height, 3, screen_scale, screen_filter, screen_filter2); | 
|   | 3825 |   flip_screen(); | 
|   | 3826 |   clear_screen(0); | 
|   | 3827 | } | 
|   | 3828 |  | 
|   | 3829 | void set_gba_resolution(video_scale_type scale) | 
|   | 3830 | { | 
|   | 3831 |   screen_scale = scale; | 
|   | 3832 | } | 
|   | 3833 |  | 
|   | 3834 | void clear_screen(u16 color) | 
|   | 3835 | { | 
|   | 3836 |   u32 col = ((u32)color << 16) | color; | 
|   | 3837 |   u32 *p = (u32 *)get_screen_pixels(); | 
|   | 3838 |   int c = resolution_width * resolution_height / 2; | 
|   | 3839 |   while (c-- > 0) | 
|   | 3840 |     *p++ = col; | 
|   | 3841 | } | 
|   | 3842 |  | 
|   | 3843 | #else | 
|   | 3844 |  | 
|   | 3845 | void video_resolution_large() | 
|   | 3846 | { | 
|   | 3847 |   current_scale = unscaled; | 
|   | 3848 |  | 
|   | 3849 | #ifdef GP2X_BUILD | 
|   | 3850 |   SDL_FreeSurface(screen); | 
|   | 3851 |   SDL_GP2X_AllowGfxMemory(NULL, 0); | 
|   | 3852 |     hw_screen = SDL_SetVideoMode(320, 240, 16, SDL_HWSURFACE); | 
|   | 3853 |   screen = SDL_CreateRGBSurface(SDL_HWSURFACE, 320, 240, 16, 0xFFFF, | 
|   | 3854 |    0xFFFF, 0xFFFF, 0); | 
|   | 3855 |   resolution_width = 320; | 
|   | 3856 |     resolution_height = 240; | 
|   | 3857 |   SDL_ShowCursor(0); | 
|   | 3858 |  | 
|   | 3859 |   warm_change_cb_upper(WCB_C_BIT|WCB_B_BIT, 1); | 
|   | 3860 | #else | 
|   | 3861 |   screen = SDL_SetVideoMode(480, 272, 16, 0); | 
|   | 3862 |   resolution_width = 480; | 
|   | 3863 |   resolution_height = 272; | 
|   | 3864 | #endif | 
|   | 3865 | } | 
|   | 3866 |  | 
|   | 3867 | void video_resolution_small() | 
|   | 3868 | { | 
|   | 3869 |   current_scale = screen_scale; | 
|   | 3870 |  | 
|   | 3871 | #ifdef GP2X_BUILD | 
|   | 3872 |   int w, h; | 
|   | 3873 |   SDL_FreeSurface(screen); | 
|   | 3874 |   SDL_GP2X_AllowGfxMemory(NULL, 0); | 
|   | 3875 |  | 
|   | 3876 |   w = 320; h = 240; | 
|   | 3877 |   if (screen_scale == scaled_aspect || screen_scale == fullscreen) | 
|   | 3878 |   { | 
|   | 3879 |     w = small_resolution_width * video_scale; | 
|   | 3880 |     h = small_resolution_height * video_scale; | 
|   | 3881 |   } | 
|   | 3882 |   if (screen_scale == scaled_aspect) h += 20; | 
|   | 3883 |   hw_screen = SDL_SetVideoMode(w, h, 16, SDL_HWSURFACE); | 
|   | 3884 |  | 
|   | 3885 |   w = small_resolution_width * video_scale; | 
|   | 3886 |   if (screen_scale == scaled_aspect_sw) | 
|   | 3887 |     w = 320; | 
|   | 3888 |   screen = SDL_CreateRGBSurface(SDL_HWSURFACE, | 
|   | 3889 |    w, small_resolution_height * video_scale, | 
|   | 3890 |    16, 0xFFFF, 0xFFFF, 0xFFFF, 0); | 
|   | 3891 |  | 
|   | 3892 |   SDL_ShowCursor(0); | 
|   | 3893 |  | 
|   | 3894 |   warm_change_cb_upper(WCB_C_BIT|WCB_B_BIT, 1); | 
|   | 3895 | #else | 
|   | 3896 |   screen = SDL_SetVideoMode(small_resolution_width * video_scale, | 
|   | 3897 |    small_resolution_height * video_scale, 16, 0); | 
|   | 3898 | #endif | 
|   | 3899 |   resolution_width = small_resolution_width; | 
|   | 3900 |   resolution_height = small_resolution_height; | 
|   | 3901 | } | 
|   | 3902 |  | 
|   | 3903 | void set_gba_resolution(video_scale_type scale) | 
|   | 3904 | { | 
|   | 3905 |   if(screen_scale != scale) | 
|   | 3906 |   { | 
|   | 3907 |     screen_scale = scale; | 
|   | 3908 |     small_resolution_width = 240 * video_scale; | 
|   | 3909 |     small_resolution_height = 160 * video_scale; | 
|   | 3910 |   } | 
|   | 3911 | } | 
|   | 3912 |  | 
|   | 3913 | void clear_screen(u16 color) | 
|   | 3914 | { | 
|   | 3915 |   u16 *dest_ptr = get_screen_pixels(); | 
|   | 3916 |   u32 line_skip = get_screen_pitch() - screen->w; | 
|   | 3917 |   u32 x, y; | 
|   | 3918 |  | 
|   | 3919 |   for(y = 0; y < screen->h; y++) | 
|   | 3920 |   { | 
|   | 3921 |     for(x = 0; x < screen->w; x++, dest_ptr++) | 
|   | 3922 |     { | 
|   | 3923 |       *dest_ptr = color; | 
|   | 3924 |     } | 
|   | 3925 |     dest_ptr += line_skip; | 
|   | 3926 |   } | 
|   | 3927 | } | 
|   | 3928 |  | 
|   | 3929 | #endif | 
|   | 3930 |  | 
|   | 3931 | u16 *copy_screen() | 
|   | 3932 | { | 
|   | 3933 |   u16 *copy = malloc(240 * 160 * 2); | 
|   | 3934 |   memcpy(copy, get_screen_pixels(), 240 * 160 * 2); | 
|   | 3935 |   return copy; | 
|   | 3936 | } | 
|   | 3937 |  | 
|   | 3938 | void blit_to_screen(u16 *src, u32 w, u32 h, u32 dest_x, u32 dest_y) | 
|   | 3939 | { | 
|   | 3940 |   u32 pitch = get_screen_pitch(); | 
|   | 3941 |   u16 *dest_ptr = get_screen_pixels() + dest_x + (dest_y * pitch); | 
|   | 3942 |  | 
|   | 3943 |   s32 w1 = dest_x + w > pitch ? pitch - dest_x : w; | 
|   | 3944 |   u16 *src_ptr = src; | 
|   | 3945 |   s32 x, y; | 
|   | 3946 |  | 
|   | 3947 |   for(y = 0; y < h; y++) | 
|   | 3948 |   { | 
|   | 3949 |     for(x = 0; x < w1; x++) | 
|   | 3950 |     { | 
|   | 3951 |       dest_ptr[x] = src_ptr[x]; | 
|   | 3952 |     } | 
|   | 3953 |     src_ptr += w; | 
|   | 3954 |     dest_ptr += pitch; | 
|   | 3955 |   } | 
|   | 3956 | } | 
|   | 3957 |  | 
|   | 3958 | void print_string_ext(const char *str, u16 fg_color, u16 bg_color, | 
|   | 3959 |  u32 x, u32 y, void *_dest_ptr, u32 pitch, u32 pad, u32 h_offset, u32 height) | 
|   | 3960 | { | 
|   | 3961 |   u16 *dest_ptr = (u16 *)_dest_ptr + (y * pitch) + x; | 
|   | 3962 |   u8 current_char = str[0]; | 
|   | 3963 |   u32 current_row; | 
|   | 3964 |   u32 glyph_offset; | 
|   | 3965 |   u32 i = 0, i2, i3, h; | 
|   | 3966 |   u32 str_index = 1; | 
|   | 3967 |   u32 current_x = x; | 
|   | 3968 |  | 
|   | 3969 |   if(y + height > resolution_height) | 
|   | 3970 |       return; | 
|   | 3971 |  | 
|   | 3972 |   while(current_char) | 
|   | 3973 |   { | 
|   | 3974 |     if(current_char == '\n') | 
|   | 3975 |     { | 
|   | 3976 |       y += FONT_HEIGHT; | 
|   | 3977 |       current_x = x; | 
|   | 3978 |       dest_ptr = get_screen_pixels() + (y * pitch) + x; | 
|   | 3979 |     } | 
|   | 3980 |     else | 
|   | 3981 |     { | 
|   | 3982 |       glyph_offset = _font_offset[current_char]; | 
|   | 3983 |       current_x += FONT_WIDTH; | 
|   | 3984 |       glyph_offset += h_offset; | 
|   | 3985 |       for(i2 = h_offset, h = 0; i2 < FONT_HEIGHT && h < height; i2++, h++, glyph_offset++) | 
|   | 3986 |       { | 
|   | 3987 |         current_row = _font_bits[glyph_offset]; | 
|   | 3988 |         for(i3 = 0; i3 < FONT_WIDTH; i3++) | 
|   | 3989 |         { | 
|   | 3990 |           if((current_row >> (15 - i3)) & 0x01) | 
|   | 3991 |             *dest_ptr = fg_color; | 
|   | 3992 |           else | 
|   | 3993 |             *dest_ptr = bg_color; | 
|   | 3994 |           dest_ptr++; | 
|   | 3995 |         } | 
|   | 3996 |         dest_ptr += (pitch - FONT_WIDTH); | 
|   | 3997 |       } | 
|   | 3998 |       dest_ptr = dest_ptr - (pitch * h) + FONT_WIDTH; | 
|   | 3999 |     } | 
|   | 4000 |  | 
|   | 4001 |     i++; | 
|   | 4002 |  | 
|   | 4003 |     current_char = str[str_index]; | 
|   | 4004 |  | 
|   | 4005 |     if((i < pad) && (current_char == 0)) | 
|   | 4006 |     { | 
|   | 4007 |       current_char = ' '; | 
|   | 4008 |     } | 
|   | 4009 |     else | 
|   | 4010 |     { | 
|   | 4011 |       str_index++; | 
|   | 4012 |     } | 
|   | 4013 |  | 
|   | 4014 |     if(current_x + FONT_WIDTH > resolution_width /* EDIT */) | 
|   | 4015 |     { | 
|   | 4016 |       while (current_char && current_char != '\n') | 
|   | 4017 |       { | 
|   | 4018 |         current_char = str[str_index++]; | 
|   | 4019 |       } | 
|   | 4020 |     } | 
|   | 4021 |   } | 
|   | 4022 | } | 
|   | 4023 |  | 
|   | 4024 | void print_string(const char *str, u16 fg_color, u16 bg_color, | 
|   | 4025 |  u32 x, u32 y) | 
|   | 4026 | { | 
|   | 4027 | #ifdef WIZ_BUILD | 
|   | 4028 |   if ((screen_scale == unscaled_rot || screen_scale == scaled_aspect_rot) && | 
|   | 4029 |    (resolution_width == small_resolution_width) && | 
|   | 4030 |    (resolution_height == small_resolution_height)) | 
|   | 4031 |   { | 
|   | 4032 |     snprintf(rot_msg_buff, sizeof(rot_msg_buff), "%s", str); | 
|   | 4033 |     return; | 
|   | 4034 |   } | 
|   | 4035 | #endif | 
|   | 4036 |   print_string_ext(str, fg_color, bg_color, x, y, get_screen_pixels(), | 
|   | 4037 |    get_screen_pitch(), 0, 0, FONT_HEIGHT); | 
|   | 4038 | } | 
|   | 4039 |  | 
|   | 4040 | void print_string_pad(const char *str, u16 fg_color, u16 bg_color, | 
|   | 4041 |  u32 x, u32 y, u32 pad) | 
|   | 4042 | { | 
|   | 4043 |   print_string_ext(str, fg_color, bg_color, x, y, get_screen_pixels(), | 
|   | 4044 |    get_screen_pitch(), pad, 0, FONT_HEIGHT); | 
|   | 4045 | } | 
|   | 4046 |  | 
|   | 4047 | u32 debug_cursor_x = 0; | 
|   | 4048 | u32 debug_cursor_y = 0; | 
|   | 4049 |  | 
|   | 4050 | #ifdef STDIO_DEBUG | 
|   | 4051 |  | 
|   | 4052 | void debug_screen_clear() | 
|   | 4053 | { | 
|   | 4054 | } | 
|   | 4055 |  | 
|   | 4056 | void debug_screen_start() | 
|   | 4057 | { | 
|   | 4058 | } | 
|   | 4059 |  | 
|   | 4060 | void debug_screen_end() | 
|   | 4061 | { | 
|   | 4062 | } | 
|   | 4063 |  | 
|   | 4064 | void debug_screen_update() | 
|   | 4065 | { | 
|   | 4066 | } | 
|   | 4067 |  | 
|   | 4068 | void debug_screen_printf(const char *format, ...) | 
|   | 4069 | { | 
|   | 4070 |   va_list ap; | 
|   | 4071 |  | 
|   | 4072 |   va_start(ap, format); | 
|   | 4073 |   vprintf(format, ap); | 
|   | 4074 |   va_end(ap); | 
|   | 4075 | } | 
|   | 4076 |  | 
|   | 4077 | void debug_screen_newline(u32 count) | 
|   | 4078 | { | 
|   | 4079 |   printf("\n"); | 
|   | 4080 | } | 
|   | 4081 |  | 
|   | 4082 |  | 
|   | 4083 | #else | 
|   | 4084 |  | 
|   | 4085 | void debug_screen_clear() | 
|   | 4086 | { | 
|   | 4087 |   debug_cursor_x = 0; | 
|   | 4088 |   debug_cursor_y = 0; | 
|   | 4089 |   clear_screen(0x0000); | 
|   | 4090 | } | 
|   | 4091 |  | 
|   | 4092 | void debug_screen_start() | 
|   | 4093 | { | 
|   | 4094 |   video_resolution_large(); | 
|   | 4095 |   debug_screen_clear(); | 
|   | 4096 | } | 
|   | 4097 |  | 
|   | 4098 | void debug_screen_end() | 
|   | 4099 | { | 
|   | 4100 |   video_resolution_small(); | 
|   | 4101 | } | 
|   | 4102 |  | 
|   | 4103 | void debug_screen_update() | 
|   | 4104 | { | 
|   | 4105 |   flip_screen(); | 
|   | 4106 | } | 
|   | 4107 |  | 
|   | 4108 | void debug_screen_printf(const char *format, ...) | 
|   | 4109 | { | 
|   | 4110 |   char str_buffer[512]; | 
|   | 4111 |   u32 str_buffer_length; | 
|   | 4112 |   va_list ap; | 
|   | 4113 |  | 
|   | 4114 |   va_start(ap, format); | 
|   | 4115 |   str_buffer_length = vsnprintf(str_buffer, 512, format, ap); | 
|   | 4116 |   va_end(ap); | 
|   | 4117 |  | 
|   | 4118 |   printf("printing debug string %s at %d %d\n", str_buffer, | 
|   | 4119 |    debug_cursor_x, debug_cursor_y); | 
|   | 4120 |  | 
|   | 4121 |   print_string(str_buffer, 0xFFFF, 0x0000, debug_cursor_x, debug_cursor_y); | 
|   | 4122 |   debug_cursor_x += FONT_WIDTH * str_buffer_length; | 
|   | 4123 | } | 
|   | 4124 |  | 
|   | 4125 | void debug_screen_newline(u32 count) | 
|   | 4126 | { | 
|   | 4127 |   debug_cursor_x = 0; | 
|   | 4128 |   debug_cursor_y += FONT_HEIGHT * count; | 
|   | 4129 | } | 
|   | 4130 |  | 
|   | 4131 | #endif | 
|   | 4132 |  | 
|   | 4133 | void debug_screen_printl(const char *format, ...) | 
|   | 4134 | { | 
|   | 4135 |   va_list ap; | 
|   | 4136 |  | 
|   | 4137 |   va_start(ap, format); | 
|   | 4138 |   debug_screen_printf(format, ap); | 
|   | 4139 |   debug_screen_newline(1); | 
|   | 4140 | //  debug_screen_printf("\n"); | 
|   | 4141 |   va_end(ap); | 
|   | 4142 | } | 
|   | 4143 |  | 
|   | 4144 |  | 
|   | 4145 | #define video_savestate_builder(type)                                         \ | 
|   | 4146 | void video_##type##_savestate(file_tag_type savestate_file)                   \ | 
|   | 4147 | {                                                                             \ | 
|   | 4148 |   file_##type##_array(savestate_file, affine_reference_x);                    \ | 
|   | 4149 |   file_##type##_array(savestate_file, affine_reference_y);                    \ | 
|   | 4150 | }                                                                             \ | 
|   | 4151 |  | 
|   | 4152 | video_savestate_builder(read); | 
|   | 4153 | video_savestate_builder(write_mem); | 
|   | 4154 |  | 
|   | 4155 |  |