render.c
1 #include "shared.h" 2 3 4 /* Bit 0 : BG enable, Bit 1 : OBJ enable */ 5 int plane_enable = -1; 6 7 /* VCE color data to 16-bit pixel table */ 8 uint16 pixel[2][0x100]; 9 10 /* Precalculated 16-bit pixel values */ 11 uint16 pixel_lut[0x200]; 12 13 /* Pointer to 8 or 16-bit version of render_line() */ 14 void (*render_line)(int line) = NULL; 15 16 /* List of precalculated sprite data */ 17 t_sprite sprite_list[0x40]; 18 19 /* Bitplane to packed pixel lookup table */ 20 //uint32 bp_lut[0x10000]; 21 #include "bp_lut.h" 22 23 /* Used sprite data */ 24 uint8 used_sprite_list[0x40]; 25 uint8 used_sprite_index; 26 27 28 extern void emu_DrawLine16(unsigned short *src, int width , int height, int line); 29 extern void emu_printf(char * text); 30 31 32 33 /*--------------------------------------------------------------------------*/ 34 /* Init, reset, shutdown functions */ 35 /*--------------------------------------------------------------------------*/ 36 37 int render_init(void) 38 { 39 int i, j; 40 41 /* Make VCE data to raw pixel look-up table */ 42 for(i = 0; i < 0x200; i += 1) 43 { 44 int r = (i >> 3) & 7; 45 int g = (i >> 6) & 7; 46 int b = (i >> 0) & 7; 47 pixel_lut[i] = (r << 13 | g << 8 | b << 2) & 0xE71C; 48 } 49 50 render_line = render_line_generic; 51 return (1); 52 } 53 54 55 void render_reset(void) 56 { 57 render_line = render_line_generic; 58 } 59 60 61 void render_shutdown(void) 62 { 63 } 64 65 66 int make_sprite_list(void) 67 { 68 uint16 *sat = &objramw[0]; 69 int xpos, ypos, name, attr; 70 int cgx, xflip, cgy, yflip; 71 int width, height; 72 int i; 73 uint32 flip; 74 75 used_sprite_index = 0; 76 memset(&used_sprite_list, 0, sizeof(used_sprite_list)); 77 78 memset(&sprite_list, 0, sizeof(sprite_list)); 79 80 for(i = 0; i < 0x40; i += 1) 81 { 82 ypos = sat[(i << 2) | (0)]; 83 xpos = sat[(i << 2) | (1)]; 84 name = sat[(i << 2) | (2)]; 85 attr = sat[(i << 2) | (3)]; 86 87 ypos &= 0x3FF; 88 xpos &= 0x3FF; 89 90 if(xpos && ypos) 91 { 92 ypos -= 64; 93 if(ypos >= 0x100) continue; 94 cgy = (attr >> 12) & 3; 95 cgy |= (cgy >> 1); 96 height = (cgy + 1) << 4; 97 if((ypos + height) < 0) continue; 98 99 xpos -= 32; 100 if(xpos >= 0x200) continue; 101 cgx = (attr >> 8) & 1; 102 width = (cgx) ? 32 : 16; 103 if((xpos + width) < 0) continue; 104 105 xflip = (attr >> 11) & 1; 106 yflip = (attr >> 15) & 1; 107 flip = ((xflip << 9) /*| (yflip << 10)*/) & 0x600; 108 109 name = (name >> 1) & 0x1FF; 110 name &= ~((cgy << 1) | cgx); 111 name |= flip; 112 if(xflip && cgx) name ^= 1; 113 114 sprite_list[i].top = ypos; 115 sprite_list[i].bottom = ypos + height; 116 sprite_list[i].xpos = xpos; 117 sprite_list[i].name_left = name; 118 sprite_list[i].name_right = name ^ 1; 119 sprite_list[i].height = (height - 1); 120 sprite_list[i].palette = (attr & 0x0F) << 4; 121 122 if(yflip) 123 sprite_list[i].flags |= FLAG_YFLIP; 124 125 if(cgx) 126 sprite_list[i].flags |= FLAG_CGX; 127 128 if(!(attr & 0x80)) 129 sprite_list[i].flags |= FLAG_PRIORITY; 130 131 used_sprite_list[used_sprite_index] = (i); 132 used_sprite_index += 1; 133 } 134 } 135 136 return (used_sprite_index); 137 } 138 139 140 /*--------------------------------------------------------------------------*/ 141 /* Pattern and object cache update routines */ 142 /*--------------------------------------------------------------------------*/ 143 144 void update_bg_pattern_cache(void) 145 { 146 int i; 147 uint8 x, y, c; 148 uint16 name, index1, index2; 149 uint32 temp; 150 151 if(!bg_list_index) return; 152 153 for(i = 0; i < bg_list_index; i += 1) 154 { 155 name = bg_name_list[i]; 156 bg_name_list[i] = 0; 157 158 for(y = 0; y < 8; y += 1) 159 { 160 if(bg_name_dirty[name] & (1 << y)) 161 { 162 index1 = vramw[(name << 4) | (y)]; 163 index2 = vramw[(name << 4) | (y) | (8)]; 164 165 temp = (bp_lut[index1] >> 2) | bp_lut[index2]; 166 167 for(x = 0; x < 8; x += 1) 168 { 169 c = (temp >> (x << 2)) & 0x0F; 170 bg_pattern_cache[(name << 6) | (y << 3) | (x)] = (c); 171 } 172 } 173 } 174 bg_name_dirty[name] = 0; 175 } 176 177 bg_list_index = 0; 178 } 179 180 181 182 void update_obj_pattern_cache(void) 183 { 184 int i; 185 uint16 name; 186 uint16 b0, b1, b2, b3; 187 uint8 i0, i1, i2, i3; 188 uint8 x, y, c; 189 190 if(!obj_list_index) return; 191 192 for(i = 0; i < obj_list_index; i += 1) 193 { 194 name = obj_name_list[i]; 195 obj_name_list[i] = 0; 196 197 for(y = 0; y < 0x10; y += 1) 198 { 199 if(obj_name_dirty[name] & (1 << y)) 200 { 201 b0 = vramw[(name << 6) + (y) + (0x00)]; 202 b1 = vramw[(name << 6) + (y) + (0x10)]; 203 b2 = vramw[(name << 6) + (y) + (0x20)]; 204 b3 = vramw[(name << 6) + (y) + (0x30)]; 205 206 for(x = 0; x < 0x10; x += 1) 207 { 208 i0 = (b0 >> (x ^ 0x0F)) & 1; 209 i1 = (b1 >> (x ^ 0x0F)) & 1; 210 i2 = (b2 >> (x ^ 0x0F)) & 1; 211 i3 = (b3 >> (x ^ 0x0F)) & 1; 212 213 c = (i3 << 3 | i2 << 2 | i1 << 1 | i0); 214 215 obj_pattern_cache[(name << 8) | (y << 4) | (x)] = (c); 216 //if (OBJ_CACHE_SIZE > 0x20000) 217 obj_pattern_cache[0x20000 | (name << 8) | (y << 4) | (x ^ 0x0F)] = (c); 218 //if (OBJ_CACHE_SIZE > 0x40000) 219 // obj_pattern_cache[0x40000 | (name << 8) | ((y ^ 0x0F) << 4) | (x)] = (c); 220 //if (OBJ_CACHE_SIZE > 0x60000) 221 // obj_pattern_cache[0x60000 | (name << 8) | ((y ^ 0x0F) << 4) | (x ^ 0x0F)] = (c); 222 } 223 } 224 } 225 obj_name_dirty[name] = 0; 226 } 227 obj_list_index = 0; 228 } 229 230 231 /*--------------------------------------------------------------------------*/ 232 /* Render functions */ 233 /*--------------------------------------------------------------------------*/ 234 235 // 16 bits line rendering 236 static unsigned short linebuf[1024]; 237 238 #define MIN(a,b) (a<b?a:b) 239 void render_line_generic(int line) 240 { 241 if((reg[0x05] & 0x80) && (plane_enable & 1)) 242 { 243 update_bg_pattern_cache(); 244 render_bg(line); 245 } 246 else 247 { 248 int i; 249 uint16 *ptr = (uint16 *)&linebuf[XOFFSET]; //&bitmap.data[(line * bitmap.pitch) + (XOFFSET * bitmap.granularity)]; 250 for(i = 0; i < disp_width; i += 1) ptr[i] = pixel[0][0]; 251 } 252 253 if((reg[0x05] & 0x40) && (plane_enable & 2)) 254 { 255 update_obj_pattern_cache(); 256 render_obj(line); 257 } 258 259 emu_DrawLine16(&linebuf[XOFFSET], MIN(disp_width,256) , 240, line); 260 261 } 262 263 264 265 void render_bg(int line) 266 { 267 uint16 *nt; 268 uint8 *src, palette; 269 uint16 *dst; 270 int column, name, attr, x, shift, v_line, nt_scroll; 271 int xscroll = (reg[7] & 0x03FF); 272 int end = disp_nt_width; 273 274 /* Offset in pattern, in lines */ 275 v_line = (y_offset & 7); 276 277 /* Offset in name table, in columns */ 278 nt_scroll = (xscroll >> 3); 279 280 /* Offset in column, in pixels */ 281 shift = (xscroll & 7); 282 283 /* Draw an extra tile for the last column */ 284 if(shift) end += 1; 285 286 /* Point to current offset within name table */ 287 nt = (uint16 *)&vram[(y_offset >> 3) << playfield_shift]; 288 289 /* Point to start in line buffer */ 290 dst = (uint16 *)&linebuf[XOFFSET - shift]; //&bitmap.data[(line * bitmap.pitch) + ((XOFFSET + (0 - shift)) << 1)]; 291 292 /* Draw columns */ 293 for(column = 0; column < end; column += 1) 294 { 295 /* Get attribute */ 296 attr = nt[(column + nt_scroll) & playfield_row_mask]; 297 298 /* Extract name and palette bits */ 299 name = (attr & 0x07FF); 300 palette = (attr >> 8) & 0xF0; 301 302 /* Point to current pattern line */ 303 src = &bg_pattern_cache[(name << 6) + (v_line << 3)]; 304 305 /* Draw column */ 306 for(x = 0; x < 8; x += 1) 307 { 308 dst[(column << 3) | (x)] = pixel[0][(src[x] | palette)]; 309 } 310 } 311 } 312 313 314 void render_obj(int line) 315 { 316 t_sprite *p; 317 int j, i, x, c; 318 int name, name_mask; 319 int v_line; 320 uint8 *src; 321 int nt_line; 322 uint16 *dst; 323 324 for(j = (used_sprite_index - 1); j >= 0; j -= 1) 325 { 326 i = used_sprite_list[j]; 327 p = &sprite_list[i]; 328 329 if( (line >= p->top) && (line < p->bottom)) 330 { 331 v_line = (line - p->top) & p->height; 332 nt_line = v_line; 333 if(p->flags & FLAG_YFLIP) nt_line = (p->height - nt_line); 334 name_mask = ((nt_line >> 4) & 3) << 1; 335 name = (p->name_left | name_mask); 336 v_line &= 0x0F; 337 //src = &obj_pattern_cache[(name << 8) | ((v_line & 0x0f) << 4)]; 338 src = &obj_pattern_cache[(name << 8) | ( (p->flags & FLAG_YFLIP?v_line ^ 0x0F:v_line) << 4)]; 339 dst = (uint16 *)&linebuf[((XOFFSET+p->xpos) & 0x1ff)]; //&bitmap.data[(line * bitmap.pitch) + (((XOFFSET+p->xpos) & 0x1ff) * (bitmap.granularity))]; 340 for(x = 0; x < 0x10; x += 1) 341 { 342 c = src[x]; 343 //if ((unsigned int)&dst[x] < (unsigned int)&linebuf[400]) 344 if(c) dst[x] = pixel[1][((c) | p->palette)]; 345 } 346 347 if(p->flags & FLAG_CGX) 348 { 349 name = (p->name_right | name_mask); 350 //src = &obj_pattern_cache[(name << 8) | ((v_line & 0x0f) << 4)]; 351 src = &obj_pattern_cache[(name << 8) | ( (p->flags & FLAG_YFLIP?v_line^ 0x0F:v_line) << 4)]; 352 dst += 0x10; 353 354 for(x = 0; x < 0x10; x += 1) 355 { 356 c = src[x]; 357 //if ((unsigned int)&dst[x] < (unsigned int)&linebuf[400]) 358 if(c) dst[x] = pixel[1][((c) | p->palette)]; 359 } 360 } 361 362 } 363 364 } 365 }