vdc.c
  1  
  2  #include "shared.h"
  3  
  4  #define LOG_DMA     0
  5  
  6  uint32 y_offset=0;
  7  uint32 byr=0;
  8  //uint8 vram[0x10000];
  9  //uint16 *vramw = (uint16 *)&vram[0];
 10  //uint8 objram[0x200];
 11  //uint16 *objramw = (uint16 *)&objram[0];
 12  uint16 reg[0x20];
 13  uint8 status;
 14  uint8 latch;
 15  uint8 addr_inc;
 16  uint8 vram_data_latch = 0;
 17  uint8 dvssr_trigger = 0;
 18  int playfield_shift = 6;
 19  uint32 playfield_col_mask = 0xFF;
 20  uint32 playfield_row_mask = 0x1F;
 21  int disp_width;
 22  int disp_height;
 23  uint32 disp_nt_width;
 24  int old_width = 0;
 25  int old_height = 0;
 26  int playfield_shift_table[] = {6, 7, 8, 8};
 27  int playfield_row_mask_table[] = {0x1F, 0x3F, 0x7F, 0x7F};
 28  
 29  
 30  //uint8 bg_name_dirty[0x800];
 31  //uint16 bg_name_list[0x800];
 32  uint16 bg_list_index;
 33  //uint8 * bg_pattern_cache;
 34  
 35  //uint16 obj_name_dirty[0x200];
 36  //uint16 obj_name_list[0x200];
 37  uint16 obj_list_index;
 38  //uint8 * obj_pattern_cache; 
 39  
 40  #define MARK_BG_DIRTY(addr)                                     \
 41  {                                                               \
 42      int name = (addr >> 4) & 0x7FF;                             \
 43      if(bg_name_dirty[name] == 0)                                \
 44      {                                                           \
 45          bg_name_list[bg_list_index] = name;                     \
 46          bg_list_index += 1;                                     \
 47      }                                                           \
 48      bg_name_dirty[name] |= (1 << (addr & 0x07));                                 \
 49  }
 50  
 51  #define MARK_OBJ_DIRTY(addr)                                    \
 52  {                                                               \
 53      int name = (addr >> 6) & 0x1FF;                             \
 54      if(obj_name_dirty[name] == 0)                               \
 55      {                                                           \
 56          obj_name_list[obj_list_index] = name;                   \
 57          obj_list_index += 1;                                    \
 58      }                                                           \
 59      obj_name_dirty[name] |= (1 << (addr & 0x0F));               \
 60  }
 61  
 62  
 63  
 64  /*--------------------------------------------------------------------------*/
 65  /* Memory handlers                                                          */
 66  /*--------------------------------------------------------------------------*/
 67  
 68  int vdc_r(int offset)
 69  {
 70      uint8 temp;
 71      uint8 msb = (offset & 1);
 72  
 73      switch(offset)
 74      {
 75          case 0x0000: /* Register latch / status flags */
 76              temp = status;
 77              status = 0;
 78              h6280_set_irq_line(0, CLEAR_LINE);
 79              return (temp);
 80  
 81          case 0x0002: /* Data port (LSB) */
 82          case 0x0003: /* Data port (MSB) */
 83              if(latch == 0x02)
 84              {
 85                  temp = (vram[((reg[1] << 1) | (msb)) & 0xFFFF]);
 86                  if(msb) reg[1] += addr_inc;
 87                  return (temp);
 88              }
 89              break;
 90      }
 91  
 92      return (0xFF);
 93  }
 94  
 95  void vdc_w(int offset, int data)
 96  {
 97      uint8 msb = (offset & 1);
 98  
 99      switch(offset)
100      {
101          case 0x0000: /* Register latch / status flags */
102              latch = (data & 0x1F);
103              break;
104  
105          case 0x0002: /* Data port (LSB) */
106          case 0x0003: /* Data port (MSB) */
107  
108              if(msb)
109                  reg[latch] = (reg[latch] & 0x00FF) | (data << 8);
110              else
111                  reg[latch] = (reg[latch] & 0xFF00) | (data);
112  
113              switch(latch)
114              {
115                  case 0x02: 
116                      if(msb)
117                      {
118                          /* Form complete VRAM word */
119                          uint16 vram_word = (data << 8 | vram_data_latch);
120  
121                          /* Check if data is new or not */
122                          if(vram_word != vramw[(reg[0] & 0x7FFF)])
123                          {
124                              /* Write data to VRAM */
125                              vramw[(reg[0] & 0x7FFF)] = vram_word;
126  
127                              /* Mark pattern dirty tables */
128                              MARK_BG_DIRTY(reg[0]);
129                              MARK_OBJ_DIRTY(reg[0]);
130                          }
131  
132                          reg[0] += addr_inc;
133                      }
134                      else
135                      {
136                          vram_data_latch = data;
137                      }
138                      break;
139  
140                  case 0x08:
141                      y_offset = byr = (reg[0x08] & 0x1FF);
142                      y_offset &= playfield_col_mask;
143                      break;
144  
145                  case 0x05:
146                      if(msb) {
147                          static uint8 add_tbl[] = {1, 32, 64, 128};
148                          addr_inc = add_tbl[(data >> 3) & 3];
149                      }
150                      break;
151  
152                  case 0x09:
153                      if(!msb) {
154                          playfield_shift = playfield_shift_table[(data >> 4) & 3];
155                          playfield_row_mask = playfield_row_mask_table[(data >> 4) & 3];
156                          playfield_col_mask = ((data >> 6) & 1) ? 0x01FF : 0x00FF;
157                      }
158                      break;
159  
160                  case 0x0B:
161                      disp_width = (1+(reg[0x0B] & 0x3F)) << 3;
162                      disp_nt_width = (disp_width >> 3);
163  
164  //                    if(disp_width != old_width) {
165  //                        bitmap.viewport.ow = bitmap.viewport.w;
166  //                        bitmap.viewport.w = old_width = disp_width;
167  //                        bitmap.viewport.changed = 1;
168  //                    }
169  
170                      break;
171  
172                  case 0x0D:
173                      disp_height = 1+(reg[0x0D] & 0x01FF);
174  
175  //                    if(disp_height != old_height) {
176  //                        bitmap.viewport.oh = bitmap.viewport.h;
177  //                        bitmap.viewport.h = old_height = disp_height;
178  //                        bitmap.viewport.changed = 1;
179  //                    }
180                      break;
181  
182                  case 0x12:
183                      if(msb) vdc_do_dma();
184                      break;
185  
186                  case 0x13:
187                      if(msb) dvssr_trigger = 1;
188                      break;
189              }
190      }
191  }
192  
193  /*--------------------------------------------------------------------------*/
194  /* Init, reset, shutdown routines                                           */
195  /*--------------------------------------------------------------------------*/
196  
197  int vdc_init(void)
198  {
199      return (0);
200  }
201  
202  void vdc_reset(void)
203  {
204      memset(vram, 0, 0x10000);
205      memset(reg, 0, 0x20);
206      status = latch = 0;
207      addr_inc = 1;
208      dvssr_trigger = 0;
209  
210      playfield_shift = 6;
211      playfield_row_mask = 0x1f;
212      playfield_col_mask = 0xff;
213  
214      memset(bg_name_dirty, 0, 0x800);
215      memset(bg_name_list, 0, 0x800*2);
216      memset(bg_pattern_cache, 0, BG_CACHE_SIZE);
217      bg_list_index = 0;
218  
219      memset(obj_name_dirty, 0, 0x200*2);
220      memset(obj_name_list, 0, 0x200*2);
221      memset(obj_pattern_cache, 0, OBJ_CACHE_SIZE);
222      obj_list_index = 0;
223  }
224  
225  
226  void vdc_shutdown(void)
227  {
228  }
229  
230  
231  void vdc_do_dma(void)
232  {
233      int did = (reg[0x0F] >> 3) & 1;
234      int sid = (reg[0x0F] >> 2) & 1;
235      int dvc = (reg[0x0F] >> 1) & 1;
236      int sour = (reg[0x10] & 0x7FFF);
237      int desr = (reg[0x11] & 0x7FFF);
238      int lenr = (reg[0x12] & 0x7FFF);
239  
240  #if LOG_DMA
241      error("DMA S:%04X%c D:%04X%c L:%04X\n", sour, (sid) ? '-' : '+', desr, (did) ? '-' : '+', lenr);
242  #endif
243  
244      /* Do VRAM -> VRAM transfer and update pattern caches */
245      do {
246          uint16 temp = vramw[(sour & 0x7FFF)];
247  
248          if(temp != vramw[(desr & 0x7FFF)])
249          {
250              vramw[(desr & 0x7FFF)] = temp;
251              MARK_BG_DIRTY(desr);
252              MARK_OBJ_DIRTY(desr);
253          }
254  
255          sour = (sid) ? (sour - 1) : (sour + 1);
256          desr = (did) ? (desr - 1) : (desr + 1);
257      } while (lenr--);
258  
259      /* Set VRAM -> VRAM transfer completed flag */
260      status |= STATUS_DV;
261  
262      /* Cause IRQ1 if enabled */
263      if(dvc)
264      {
265          h6280_set_irq_line(0, ASSERT_LINE);
266      }
267  }
268  
269  
270  /*--------------------------------------------------------------------------*/
271