/ MCUME_teensy / teensypce / render.c
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  }