trunk/src/mess/drivers/wildfire.c
| r243591 | r243592 | |
| 13 | 13 | |
| 14 | 14 | |
| 15 | 15 | TODO: |
| 16 | | - bad sound, A12 seems to strobe too fast |
| 16 | - sound emulation could still be improved |
| 17 | 17 | - when the game strobes a led faster, it should appear brighter, for example when |
| 18 | 18 | the ball hits one of the bumpers |
| 19 | 19 | - some 7segs digits are wrong (mcu on-die decoder is customizable?) |
| r243591 | r243592 | |
| 28 | 28 | #include "wildfire.lh" // this is a test layout, external artwork is necessary |
| 29 | 29 | |
| 30 | 30 | // master clock is a single stage RC oscillator: R=?K, C=?pf, |
| 31 | | // S2150 default frequency is 850kHz |
| 31 | // S2000 default frequency is 850kHz |
| 32 | 32 | #define MASTER_CLOCK (850000) |
| 33 | 33 | |
| 34 | 34 | |
| r243591 | r243592 | |
| 38 | 38 | wildfire_state(const machine_config &mconfig, device_type type, const char *tag) |
| 39 | 39 | : driver_device(mconfig, type, tag), |
| 40 | 40 | m_maincpu(*this, "maincpu"), |
| 41 | | m_speaker(*this, "speaker") |
| 41 | m_speaker(*this, "speaker"), |
| 42 | m_a12_decay_timer(*this, "a12_decay") |
| 42 | 43 | { } |
| 43 | 44 | |
| 44 | 45 | required_device<cpu_device> m_maincpu; |
| 45 | 46 | required_device<speaker_sound_device> m_speaker; |
| 47 | required_device<timer_device> m_a12_decay_timer; |
| 46 | 48 | |
| 47 | 49 | UINT8 m_d; |
| 48 | 50 | UINT16 m_a; |
| 49 | | UINT8 m_f; |
| 51 | UINT8 m_q2; |
| 52 | UINT8 m_q3; |
| 50 | 53 | |
| 51 | 54 | UINT16 m_display_state[0x10]; |
| 52 | 55 | UINT16 m_display_cache[0x10]; |
| r243591 | r243592 | |
| 59 | 62 | TIMER_DEVICE_CALLBACK_MEMBER(display_decay_tick); |
| 60 | 63 | bool index_is_7segled(int index); |
| 61 | 64 | void display_update(); |
| 65 | |
| 66 | TIMER_DEVICE_CALLBACK_MEMBER(reset_q2); |
| 67 | void write_a12(int state); |
| 62 | 68 | void sound_update(); |
| 63 | 69 | |
| 64 | 70 | virtual void machine_start(); |
| r243591 | r243592 | |
| 153 | 159 | |
| 154 | 160 | /*************************************************************************** |
| 155 | 161 | |
| 162 | Sound |
| 163 | |
| 164 | ***************************************************************************/ |
| 165 | |
| 166 | // Sound output is via a speaker between transistors Q2(from A12) and Q3(from F_out) |
| 167 | // A12 to Q2 has a little electronic circuit going, causing a slight delay. |
| 168 | // (see patent US4334679 FIG.5, the 2 resistors are 10K and the cap is a 4.7uF electrolytic) |
| 169 | |
| 170 | // decay time, in steps of 1ms |
| 171 | #define A12_DECAY_TIME 5 /* a complete guess */ |
| 172 | |
| 173 | void wildfire_state::sound_update() |
| 174 | { |
| 175 | m_speaker->level_w(m_q2 & m_q3); |
| 176 | } |
| 177 | |
| 178 | WRITE_LINE_MEMBER(wildfire_state::write_f) |
| 179 | { |
| 180 | // F_out pin: speaker out |
| 181 | m_q3 = (state) ? 1 : 0; |
| 182 | sound_update(); |
| 183 | } |
| 184 | |
| 185 | TIMER_DEVICE_CALLBACK_MEMBER(wildfire_state::reset_q2) |
| 186 | { |
| 187 | m_q2 = 0; |
| 188 | sound_update(); |
| 189 | } |
| 190 | |
| 191 | void wildfire_state::write_a12(int state) |
| 192 | { |
| 193 | if (state) |
| 194 | { |
| 195 | m_a12_decay_timer->adjust(attotime::never); |
| 196 | m_q2 = state; |
| 197 | sound_update(); |
| 198 | } |
| 199 | else if (m_a >> 12 & 1) |
| 200 | { |
| 201 | // falling edge |
| 202 | m_a12_decay_timer->adjust(attotime::from_msec(A12_DECAY_TIME)); |
| 203 | } |
| 204 | } |
| 205 | |
| 206 | |
| 207 | |
| 208 | /*************************************************************************** |
| 209 | |
| 156 | 210 | I/O |
| 157 | 211 | |
| 158 | 212 | ***************************************************************************/ |
| r243591 | r243592 | |
| 166 | 220 | |
| 167 | 221 | WRITE16_MEMBER(wildfire_state::write_a) |
| 168 | 222 | { |
| 223 | data ^= 0x1fff; // active-low |
| 224 | |
| 225 | // A12: enable speaker |
| 226 | write_a12(data >> 12 & 1); |
| 227 | |
| 169 | 228 | // A0-A2: select 7segleds |
| 170 | 229 | // A3-A11: select other leds |
| 171 | | m_a = data ^ 0x1fff; // active-low |
| 230 | m_a = data; |
| 172 | 231 | display_update(); |
| 173 | | |
| 174 | | // A12: enable speaker |
| 175 | | sound_update(); |
| 176 | 232 | } |
| 177 | 233 | |
| 178 | | WRITE_LINE_MEMBER(wildfire_state::write_f) |
| 179 | | { |
| 180 | | m_f = (state) ? 1 : 0; |
| 181 | | sound_update(); |
| 182 | | } |
| 183 | 234 | |
| 184 | | void wildfire_state::sound_update() |
| 185 | | { |
| 186 | | m_speaker->level_w(m_a >> 12 & m_f); |
| 187 | | } |
| 188 | 235 | |
| 189 | | |
| 190 | | |
| 191 | 236 | /*************************************************************************** |
| 192 | 237 | |
| 193 | 238 | Inputs |
| r243591 | r243592 | |
| 219 | 264 | |
| 220 | 265 | m_d = 0; |
| 221 | 266 | m_a = 0; |
| 222 | | m_f = 0; |
| 267 | m_q2 = 0; |
| 268 | m_q3 = 0; |
| 223 | 269 | |
| 224 | 270 | // register for savestates |
| 225 | 271 | save_item(NAME(m_display_state)); |
| r243591 | r243592 | |
| 228 | 274 | |
| 229 | 275 | save_item(NAME(m_d)); |
| 230 | 276 | save_item(NAME(m_a)); |
| 231 | | save_item(NAME(m_f)); |
| 277 | save_item(NAME(m_q2)); |
| 278 | save_item(NAME(m_q3)); |
| 232 | 279 | } |
| 233 | 280 | |
| 234 | 281 | |
| r243591 | r243592 | |
| 242 | 289 | MCFG_AMI_S2152_FOUT_CB(WRITELINE(wildfire_state, write_f)) |
| 243 | 290 | |
| 244 | 291 | MCFG_TIMER_DRIVER_ADD_PERIODIC("display_decay", wildfire_state, display_decay_tick, attotime::from_msec(1)) |
| 292 | MCFG_TIMER_DRIVER_ADD("a12_decay", wildfire_state, reset_q2) |
| 245 | 293 | |
| 246 | 294 | MCFG_DEFAULT_LAYOUT(layout_wildfire) |
| 247 | 295 | |