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 }