sms.c
  1  #include "shared.h"
  2  
  3  /* SMS context */
  4  t_sms sms;
  5  t_input input;       /* Controller input */
  6  
  7  /* Run the virtual console emulation for one frame */
  8  void sms_frame(int skip_render)
  9  {
 10      /* Take care of hard resets */
 11      if(input.system & INPUT_HARD_RESET)
 12      {
 13          system_reset();
 14      }
 15  
 16      /* Debounce pause key */
 17      if(input.system & INPUT_PAUSE)
 18      {
 19          if(!sms.paused)
 20          {
 21              sms.paused = 1;
 22  
 23              z80_set_nmi_line(ASSERT_LINE);
 24              z80_set_nmi_line(CLEAR_LINE);
 25          }
 26      }
 27      else
 28      {
 29           sms.paused = 0;
 30      }
 31  
 32      if(smssnd.log) smssnd.callback(0x00);
 33  
 34      for(vdp.line = 0; vdp.line < 262; vdp.line += 1)
 35      {
 36          /* Handle VDP line events */
 37          vdp_run();
 38  
 39          /* Draw the current frame */
 40          if(!skip_render) render_line(vdp.line);
 41  
 42          /* Run the Z80 for a line */
 43          z80_execute(227);
 44      }
 45  }
 46  
 47  void audio_play_sample(int16 *bufl, int16 *bufr, int length)
 48  {
 49      length = length/2;
 50  
 51      if(smssnd.enabled) 
 52      {
 53          int count;
 54  
 55          SN76496Update(0, smssnd.psg_buffer, length, sms.psg_mask);
 56          if(sms.use_fm) YM3812UpdateOne(ym3812, smssnd.fm_buffer, length);
 57  
 58          for(count = 0; count < length; count += 1)
 59          {
 60              signed short left   = 0;
 61              signed short right  = 0;
 62              if (sms.use_fm) left = right = smssnd.fm_buffer[count];
 63              left  += smssnd.psg_buffer[0][count];
 64              right += smssnd.psg_buffer[1][count];
 65              *bufl++ = left;
 66              *bufl++ = right;
 67          }
 68      }
 69       
 70  }
 71  
 72  
 73  
 74  void sms_init(void)
 75  {
 76  #if PSX
 77      z80_set_context((void *)0x1F800000);
 78  #endif
 79      cpu_reset();
 80      sms_reset();
 81  }
 82  
 83  
 84  void sms_reset(void)
 85  {
 86      memset(&input, 0, sizeof(t_input));
 87  
 88      /* Clear SMS context */
 89      memset(sms.dummy, 0, 0x2000);
 90      memset(sms.ram, 0, 0x2000);
 91      memset(sms.sram, 0, 0x8000);
 92      sms.paused = sms.save = sms.port_3F = sms.port_F2 = sms.irq = 0x00;
 93      sms.psg_mask = 0xFF;
 94  
 95      /* Load memory maps with default values */
 96      cpu_readmap[0] = 0x0000;
 97      cpu_readmap[1] = 0x2000;
 98      cpu_readmap[2] = 0x4000;
 99      cpu_readmap[3] = 0x6000;
100      cpu_readmap[4] = 0x0000;
101      cpu_readmap[5] = 0x2000;
102      cpu_readmap[6] = sms.ram;            
103      cpu_readmap[7] = sms.ram;
104  
105      cpu_writemap[0] = sms.dummy;         
106      cpu_writemap[1] = sms.dummy;
107      cpu_writemap[2] = sms.dummy;         
108      cpu_writemap[3] = sms.dummy;
109      cpu_writemap[4] = sms.dummy;         
110      cpu_writemap[5] = sms.dummy;
111      cpu_writemap[6] = sms.ram;           
112      cpu_writemap[7] = sms.ram;
113  
114      sms.fcr[0] = 0x00;
115      sms.fcr[1] = 0x00;
116      sms.fcr[2] = 0x01;
117      sms.fcr[3] = 0x00;
118  }
119  
120  
121  /* Reset Z80 emulator */
122  void cpu_reset(void)
123  {
124      z80_reset(0);
125      z80_set_irq_callback(sms_irq_callback);
126  }
127  
128  
129  /* Write to memory */
130  void cpu_writemem16(int address, int data)
131  {
132      cpu_writemap[(address >> 13)][(address & 0x1FFF)] = data;
133      if(address >= 0xFFFC) sms_mapper_w(address & 3, data);
134  }
135  
136  
137  /* Write to an I/O port */
138  void cpu_writeport(int port, int data)
139  {
140      switch(port & 0xFF)
141      {
142          case 0x01: /* GG SIO */
143          case 0x02:
144          case 0x03:
145          case 0x04:
146          case 0x05:
147              break;
148  
149          case 0x06: /* GG STEREO */
150              if(smssnd.log) {
151              smssnd.callback(0x04);
152              smssnd.callback(data);
153              }
154              sms.psg_mask = (data & 0xFF);
155              break;
156  
157          case 0x7E: /* SN76489 PSG */
158          case 0x7F:
159              if(smssnd.log) {
160              smssnd.callback(0x03);
161              smssnd.callback(data);
162              }
163              if(smssnd.enabled) SN76496Write(0, data);
164              break;
165  
166          case 0xBE: /* VDP DATA */
167              vdp_data_w(data);
168              break;
169  
170          case 0xBD: /* VDP CTRL */ 
171          case 0xBF:
172              vdp_ctrl_w(data);
173              break;
174  
175          case 0xF0: /* YM2413 */
176          case 0xF1:
177              if(smssnd.log) {
178              smssnd.callback((port & 1) ? 0x06 : 0x05);
179              smssnd.callback(data);
180              }
181              if(smssnd.enabled && sms.use_fm) ym2413_write(0, port & 1, data);
182              break;
183  
184          case 0xF2: /* YM2413 DETECT */
185              if(sms.use_fm) sms.port_F2 = (data & 1);
186              break;
187  
188          case 0x3F: /* TERRITORY CTRL. */
189               sms.port_3F = ((data & 0x80) | (data & 0x20) << 1) & 0xC0;
190              if(sms.country == TYPE_DOMESTIC) sms.port_3F ^= 0xC0;
191              break;
192      }
193  }
194  
195  
196  /* Read from an I/O port */
197  int cpu_readport(int port)
198  {
199      byte temp = 0xFF;
200  
201      switch(port & 0xFF)
202      {
203          case 0x01: /* GG SIO */
204          case 0x02:
205          case 0x03:
206          case 0x04:
207          case 0x05:
208              return (0x00);
209      
210          case 0x7E: /* V COUNTER */
211              return (vdp_vcounter_r());
212              break;
213      
214          case 0x7F: /* H COUNTER */
215              return (vdp_hcounter_r());
216              break;
217      
218          case 0x00: /* INPUT #2 */
219              temp = 0xFF;
220              if(input.system & INPUT_START) temp &= ~0x80;
221              if(sms.country == TYPE_DOMESTIC) temp &= ~0x40;
222              return (temp);
223      
224          case 0xC0: /* INPUT #0 */  
225          case 0xDC:
226              temp = 0xFF;
227              if(input.pad[0] & INPUT_UP)      temp &= ~0x01;
228              if(input.pad[0] & INPUT_DOWN)    temp &= ~0x02;
229              if(input.pad[0] & INPUT_LEFT)    temp &= ~0x04;
230              if(input.pad[0] & INPUT_RIGHT)   temp &= ~0x08;
231              if(input.pad[0] & INPUT_BUTTON2) temp &= ~0x10;
232              if(input.pad[0] & INPUT_BUTTON1) temp &= ~0x20;
233              if(input.pad[1] & INPUT_UP)      temp &= ~0x40;
234              if(input.pad[1] & INPUT_DOWN)    temp &= ~0x80;
235              return (temp);
236      
237          case 0xC1: /* INPUT #1 */
238          case 0xDD:
239              temp = 0xFF;
240              if(input.pad[1] & INPUT_LEFT)    temp &= ~0x01;
241              if(input.pad[1] & INPUT_RIGHT)   temp &= ~0x02;
242              if(input.pad[1] & INPUT_BUTTON2) temp &= ~0x04;
243              if(input.pad[1] & INPUT_BUTTON1) temp &= ~0x08;
244              if(input.system & INPUT_SOFT_RESET) temp &= ~0x10;
245              return ((temp & 0x3F) | (sms.port_3F & 0xC0));
246  
247          case 0xBE: /* VDP DATA */
248              return (vdp_data_r());
249      
250          case 0xBD:
251          case 0xBF: /* VDP CTRL */
252              return (vdp_ctrl_r());
253  
254          case 0xF2: /* YM2413 DETECT */
255              if(sms.use_fm) return (sms.port_F2);
256              break;
257      }
258      return (0xFF);     
259  }
260  
261  
262  void sms_mapper_w(int address, int data)
263  {
264      /* Calculate ROM page index */
265      byte page = (data % cart.pages);
266  
267      /* Save frame control register data */
268      sms.fcr[address] = data;
269  
270      switch(address)
271      {
272          case 0:
273              if(data & 8)
274              {
275                  sms.save = 1;
276                  /* Page in ROM */
277                  cpu_readmap[4]  = &sms.sram[(data & 4) ? 0x4000 : 0x0000];
278                  cpu_readmap[5]  = &sms.sram[(data & 4) ? 0x6000 : 0x2000];
279                  cpu_writemap[4] = &sms.sram[(data & 4) ? 0x4000 : 0x0000];
280                  cpu_writemap[5] = &sms.sram[(data & 4) ? 0x6000 : 0x2000];
281              }
282              else
283              {
284                  /* Page in RAM */
285                  cpu_readmap[4]  = ((sms.fcr[3] % cart.pages) << 14) + 0x0000;
286                  cpu_readmap[5]  = ((sms.fcr[3] % cart.pages) << 14) + 0x2000;
287                  cpu_writemap[4] = sms.dummy;
288                  cpu_writemap[5] = sms.dummy;
289              }
290              break;
291  
292          case 1:
293              cpu_readmap[0] = (page << 14) + 0x0000;
294              cpu_readmap[1] = (page << 14) + 0x2000;
295              break;
296  
297          case 2:
298              cpu_readmap[2] = (page << 14) + 0x0000;
299              cpu_readmap[3] = (page << 14) + 0x2000;
300              break;
301  
302          case 3:
303              if(!(sms.fcr[0] & 0x08))
304              {
305                  cpu_readmap[4] = (page << 14) + 0x0000;
306                  cpu_readmap[5] = (page << 14) + 0x2000;
307              }
308              break;
309      }
310  }
311  
312  
313  int sms_irq_callback(int param)
314  {
315      return (0xFF);
316  }