trunk/src/mess/drivers/starwbc.c
| r242188 | r242189 | |
| 2 | 2 | // copyright-holders:hap |
| 3 | 3 | /*************************************************************************** |
| 4 | 4 | |
| 5 | | Kenner Star Wars: Electronic Battle Command Game |
| 6 | | * TMS1100 MCU, marked MP3438A |
| 5 | Kenner Star Wars - Electronic Battle Command |
| 6 | * TMS1100 MCU, labeled MP3438A |
| 7 | |
| 8 | This is a small tabletop space-dogfighting game. |
| 7 | 9 | |
| 8 | 10 | |
| 9 | 11 | ***************************************************************************/ |
| 10 | 12 | |
| 11 | 13 | #include "emu.h" |
| 12 | 14 | #include "cpu/tms0980/tms0980.h" |
| 15 | #include "sound/speaker.h" |
| 13 | 16 | |
| 14 | 17 | #include "starwbc.lh" |
| 15 | 18 | |
| 16 | 19 | |
| 20 | // master clock is unknown, the value below is an approximation |
| 21 | #define MASTER_CLOCK (350000) |
| 22 | |
| 23 | |
| 17 | 24 | class starwbc_state : public driver_device |
| 18 | 25 | { |
| 19 | 26 | public: |
| 20 | 27 | starwbc_state(const machine_config &mconfig, device_type type, const char *tag) |
| 21 | 28 | : driver_device(mconfig, type, tag), |
| 22 | | m_maincpu(*this, "maincpu") |
| 29 | m_maincpu(*this, "maincpu"), |
| 30 | m_button_matrix(*this, "IN"), |
| 31 | m_speaker(*this, "speaker") |
| 23 | 32 | { } |
| 24 | 33 | |
| 25 | 34 | required_device<cpu_device> m_maincpu; |
| 35 | required_ioport_array<11> m_button_matrix; |
| 36 | required_device<speaker_sound_device> m_speaker; |
| 26 | 37 | |
| 27 | 38 | UINT16 m_r; |
| 28 | 39 | UINT16 m_o; |
| 29 | 40 | |
| 41 | UINT16 m_leds_state[0x10]; |
| 42 | UINT16 m_leds_cache[0x10]; |
| 43 | UINT8 m_leds_decay[0x100]; |
| 44 | |
| 30 | 45 | DECLARE_READ8_MEMBER(read_k); |
| 31 | 46 | DECLARE_WRITE16_MEMBER(write_o); |
| 32 | 47 | DECLARE_WRITE16_MEMBER(write_r); |
| 48 | |
| 49 | TIMER_DEVICE_CALLBACK_MEMBER(leds_decay_tick); |
| 50 | void leds_update(); |
| 51 | void prepare_and_update(); |
| 33 | 52 | |
| 34 | 53 | virtual void machine_start(); |
| 35 | 54 | }; |
| r242188 | r242189 | |
| 38 | 57 | |
| 39 | 58 | /*************************************************************************** |
| 40 | 59 | |
| 60 | LEDs |
| 61 | |
| 62 | ***************************************************************************/ |
| 63 | |
| 64 | // The device strobes the outputs very fast, it is unnoticeable to the user. |
| 65 | // To prevent flickering here, we need to simulate a decay. |
| 66 | |
| 67 | // decay time, in steps of 10ms |
| 68 | #define LEDS_DECAY_TIME 4 |
| 69 | |
| 70 | void starwbc_state::leds_update() |
| 71 | { |
| 72 | UINT16 active_state[0x10]; |
| 73 | |
| 74 | for (int i = 0; i < 0x10; i++) |
| 75 | { |
| 76 | active_state[i] = 0; |
| 77 | |
| 78 | for (int j = 0; j < 0x10; j++) |
| 79 | { |
| 80 | int di = j << 4 | i; |
| 81 | |
| 82 | // turn on powered leds |
| 83 | if (m_leds_state[i] >> j & 1) |
| 84 | m_leds_decay[di] = LEDS_DECAY_TIME; |
| 85 | |
| 86 | // determine active state |
| 87 | int ds = (m_leds_decay[di] != 0) ? 1 : 0; |
| 88 | active_state[i] |= (ds << j); |
| 89 | } |
| 90 | } |
| 91 | |
| 92 | // on difference, send to output |
| 93 | for (int i = 0; i < 0x10; i++) |
| 94 | if (m_leds_cache[i] != active_state[i]) |
| 95 | { |
| 96 | output_set_digit_value(i, active_state[i]); |
| 97 | |
| 98 | for (int j = 0; j < 8; j++) |
| 99 | output_set_lamp_value(i*10 + j, active_state[i] >> j & 1); |
| 100 | } |
| 101 | |
| 102 | memcpy(m_leds_cache, active_state, sizeof(m_leds_cache)); |
| 103 | } |
| 104 | |
| 105 | TIMER_DEVICE_CALLBACK_MEMBER(starwbc_state::leds_decay_tick) |
| 106 | { |
| 107 | // slowly turn off unpowered leds |
| 108 | for (int i = 0; i < 0x100; i++) |
| 109 | if (!(m_leds_state[i & 0xf] >> (i>>4) & 1) && m_leds_decay[i]) |
| 110 | m_leds_decay[i]--; |
| 111 | |
| 112 | leds_update(); |
| 113 | } |
| 114 | |
| 115 | void starwbc_state::prepare_and_update() |
| 116 | { |
| 117 | UINT8 o = (m_o << 4 & 0xf0) | (m_o >> 4 & 0x0f); |
| 118 | const UINT8 mask[5] = { 0x30, 0xff, 0xff, 0x7f, 0x7f }; |
| 119 | |
| 120 | // R0,R2,R4,R6,R8 |
| 121 | for (int i = 0; i < 5; i++) |
| 122 | m_leds_state[i*2] = (m_r >> (i*2) & 1) ? (o & mask[i]) : 0; |
| 123 | |
| 124 | leds_update(); |
| 125 | } |
| 126 | |
| 127 | |
| 128 | |
| 129 | /*************************************************************************** |
| 130 | |
| 41 | 131 | I/O |
| 42 | 132 | |
| 43 | 133 | ***************************************************************************/ |
| 44 | 134 | |
| 45 | 135 | READ8_MEMBER(starwbc_state::read_k) |
| 46 | 136 | { |
| 47 | | return 0; |
| 137 | UINT8 k = 0; |
| 138 | |
| 139 | // read selected button rows |
| 140 | for (int i = 0; i < 11; i++) |
| 141 | if (m_r >> i & 1) |
| 142 | k |= m_button_matrix[i]->read(); |
| 143 | |
| 144 | // const int r[5] = { 3, 5, 6, 7, 9 }; //nope |
| 145 | //printf("%04X ",m_r); |
| 146 | |
| 147 | return k; |
| 48 | 148 | } |
| 49 | 149 | |
| 50 | 150 | WRITE16_MEMBER(starwbc_state::write_r) |
| 51 | 151 | { |
| 152 | // R0,R2,R4: select lamp row |
| 153 | // R6,R8: select digit |
| 154 | // R3,R5-R7,R9: input mux |
| 155 | // R9: piezo speaker |
| 156 | m_speaker->level_w(data >> 9 & 1); |
| 157 | |
| 52 | 158 | m_r = data; |
| 159 | prepare_and_update(); |
| 53 | 160 | } |
| 54 | 161 | |
| 55 | 162 | WRITE16_MEMBER(starwbc_state::write_o) |
| 56 | 163 | { |
| 164 | // O0-O7: leds state |
| 57 | 165 | m_o = data; |
| 166 | prepare_and_update(); |
| 58 | 167 | } |
| 59 | 168 | |
| 60 | 169 | |
| r242188 | r242189 | |
| 66 | 175 | ***************************************************************************/ |
| 67 | 176 | |
| 68 | 177 | static INPUT_PORTS_START( starwbc ) |
| 178 | PORT_START("IN.0") |
| 179 | PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) |
| 180 | PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) |
| 181 | PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) |
| 182 | PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) |
| 183 | |
| 184 | PORT_START("IN.1") |
| 185 | PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) |
| 186 | PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) |
| 187 | PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) |
| 188 | PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) |
| 189 | |
| 190 | PORT_START("IN.2") |
| 191 | PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) |
| 192 | PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) |
| 193 | PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) |
| 194 | PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) |
| 195 | |
| 196 | PORT_START("IN.3") |
| 197 | PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) |
| 198 | PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) |
| 199 | PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) |
| 200 | PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) |
| 201 | |
| 202 | PORT_START("IN.4") |
| 203 | PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) |
| 204 | PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) |
| 205 | PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) |
| 206 | PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) |
| 207 | |
| 208 | PORT_START("IN.5") |
| 209 | PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) |
| 210 | PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) |
| 211 | PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) |
| 212 | PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) |
| 213 | |
| 214 | PORT_START("IN.6") |
| 215 | PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) |
| 216 | PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) |
| 217 | PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) |
| 218 | PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) |
| 219 | |
| 220 | PORT_START("IN.7") |
| 221 | PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) |
| 222 | PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) |
| 223 | PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) |
| 224 | PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) |
| 225 | |
| 226 | PORT_START("IN.8") |
| 227 | PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) |
| 228 | PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) |
| 229 | PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) |
| 230 | PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) |
| 231 | |
| 232 | PORT_START("IN.9") |
| 233 | PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) |
| 234 | PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) |
| 235 | PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) |
| 236 | PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) |
| 237 | |
| 238 | PORT_START("IN.10") |
| 239 | PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_1_PAD) |
| 240 | PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_2_PAD) |
| 241 | PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_3_PAD) |
| 242 | PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_4_PAD) |
| 69 | 243 | INPUT_PORTS_END |
| 70 | 244 | |
| 71 | 245 | |
| r242188 | r242189 | |
| 78 | 252 | |
| 79 | 253 | void starwbc_state::machine_start() |
| 80 | 254 | { |
| 255 | memset(m_leds_state, 0, sizeof(m_leds_state)); |
| 256 | memset(m_leds_cache, 0, sizeof(m_leds_cache)); |
| 257 | memset(m_leds_decay, 0, sizeof(m_leds_decay)); |
| 81 | 258 | m_r = 0; |
| 82 | 259 | m_o = 0; |
| 83 | 260 | |
| 261 | save_item(NAME(m_leds_state)); |
| 262 | save_item(NAME(m_leds_cache)); |
| 263 | save_item(NAME(m_leds_decay)); |
| 84 | 264 | save_item(NAME(m_r)); |
| 85 | 265 | save_item(NAME(m_o)); |
| 86 | 266 | } |
| r242188 | r242189 | |
| 89 | 269 | static MACHINE_CONFIG_START( starwbc, starwbc_state ) |
| 90 | 270 | |
| 91 | 271 | /* basic machine hardware */ |
| 92 | | MCFG_CPU_ADD("maincpu", TMS1100, 400000) |
| 272 | MCFG_CPU_ADD("maincpu", TMS1100, MASTER_CLOCK) |
| 93 | 273 | MCFG_TMS1XXX_READ_K_CB(READ8(starwbc_state, read_k)) |
| 94 | 274 | MCFG_TMS1XXX_WRITE_O_CB(WRITE16(starwbc_state, write_o)) |
| 95 | 275 | MCFG_TMS1XXX_WRITE_R_CB(WRITE16(starwbc_state, write_r)) |
| 276 | |
| 277 | MCFG_TIMER_DRIVER_ADD_PERIODIC("leds_decay", starwbc_state, leds_decay_tick, attotime::from_msec(10)) |
| 96 | 278 | |
| 97 | 279 | MCFG_DEFAULT_LAYOUT(layout_starwbc) |
| 98 | 280 | |
| 99 | 281 | /* no video! */ |
| 100 | 282 | |
| 101 | 283 | /* sound hardware */ |
| 102 | | // MCFG_SPEAKER_STANDARD_MONO("mono") |
| 284 | MCFG_SPEAKER_STANDARD_MONO("mono") |
| 285 | MCFG_SOUND_ADD("speaker", SPEAKER_SOUND, 0) |
| 286 | MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25) |
| 103 | 287 | MACHINE_CONFIG_END |
| 104 | 288 | |
| 105 | 289 | |
| r242188 | r242189 | |
| 121 | 305 | ROM_END |
| 122 | 306 | |
| 123 | 307 | |
| 124 | | CONS( 1979, starwbc, 0, 0, starwbc, starwbc, driver_device, 0, "Kenner", "Star Wars: Electronic Battle Command Game", GAME_NOT_WORKING | GAME_SUPPORTS_SAVE | GAME_NO_SOUND ) |
| 308 | CONS( 1979, starwbc, 0, 0, starwbc, starwbc, driver_device, 0, "Kenner", "Star Wars - Electronic Battle Command", GAME_NOT_WORKING | GAME_SUPPORTS_SAVE ) |