trunk/src/mame/drivers/galaxia.c
| r24877 | r24878 | |
| 61 | 61 | */ |
| 62 | 62 | |
| 63 | 63 | #include "emu.h" |
| 64 | | #include "sound/s2636.h" |
| 64 | #include "machine/s2636.h" |
| 65 | 65 | #include "cpu/s2650/s2650.h" |
| 66 | 66 | #include "includes/galaxia.h" |
| 67 | 67 | |
| r24877 | r24878 | |
| 276 | 276 | |
| 277 | 277 | static const s2636_interface galaxia_s2636_config[3] = |
| 278 | 278 | { |
| 279 | | { 0x100, 3, -26, "s2636snd_0" }, |
| 280 | | { 0x100, 3, -26, "s2636snd_1" }, |
| 281 | | { 0x100, 3, -26, "s2636snd_2" } |
| 279 | { 0x100, 3, -26 }, |
| 280 | { 0x100, 3, -26 }, |
| 281 | { 0x100, 3, -26 } |
| 282 | 282 | }; |
| 283 | 283 | |
| 284 | 284 | static const s2636_interface astrowar_s2636_config = |
| 285 | 285 | { |
| 286 | 286 | 0x100, |
| 287 | | 3, 0, |
| 288 | | "s2636snd_0" |
| 287 | 3, 0 |
| 289 | 288 | }; |
| 290 | 289 | |
| 291 | 290 | |
| r24877 | r24878 | |
| 312 | 311 | MCFG_VIDEO_START_OVERRIDE(galaxia_state,galaxia) |
| 313 | 312 | |
| 314 | 313 | MCFG_S2636_ADD("s2636_0", galaxia_s2636_config[0]) |
| 314 | MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25) |
| 315 | 315 | MCFG_S2636_ADD("s2636_1", galaxia_s2636_config[1]) |
| 316 | MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25) |
| 316 | 317 | MCFG_S2636_ADD("s2636_2", galaxia_s2636_config[2]) |
| 317 | | |
| 318 | MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25) |
| 319 | |
| 318 | 320 | /* sound hardware */ |
| 319 | 321 | MCFG_SPEAKER_STANDARD_MONO("mono") |
| 320 | 322 | |
| 321 | | MCFG_SOUND_ADD("s2636snd_0", S2636_SOUND, 0) |
| 322 | | MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25) |
| 323 | | |
| 324 | | MCFG_SOUND_ADD("s2636snd_1", S2636_SOUND, 0) |
| 325 | | MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25) |
| 326 | | |
| 327 | | MCFG_SOUND_ADD("s2636snd_2", S2636_SOUND, 0) |
| 328 | | MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25) |
| 329 | 323 | MACHINE_CONFIG_END |
| 330 | 324 | |
| 331 | 325 | |
| r24877 | r24878 | |
| 352 | 346 | MCFG_VIDEO_START_OVERRIDE(galaxia_state,astrowar) |
| 353 | 347 | |
| 354 | 348 | MCFG_S2636_ADD("s2636_0", astrowar_s2636_config) |
| 349 | MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25) |
| 355 | 350 | |
| 356 | 351 | /* sound hardware */ |
| 357 | 352 | MCFG_SPEAKER_STANDARD_MONO("mono") |
| 358 | 353 | |
| 359 | | MCFG_SOUND_ADD("s2636snd_0", S2636_SOUND, 0) |
| 360 | | MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25) |
| 354 | |
| 361 | 355 | MACHINE_CONFIG_END |
| 362 | 356 | |
| 363 | 357 | |
trunk/src/emu/video/s2636.c
| r24877 | r24878 | |
| 1 | | /********************************************************************** |
| 2 | | |
| 3 | | Signetics 2636 video chip |
| 4 | | |
| 5 | | Copyright Nicola Salmoria and the MAME Team. |
| 6 | | Visit http://mamedev.org for licensing and usage restrictions. |
| 7 | | |
| 8 | | |
| 9 | | PVI REGISTER DESCRIPTION |
| 10 | | ------------------------ |
| 11 | | |
| 12 | | | bit |R/W| description |
| 13 | | byte | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | | |
| 14 | | | | | |
| 15 | | FC0 | size 4| size 3| size 2| size 1| W | size of the 4 objects(=sprites) |
| 16 | | | | | |
| 17 | | FC1 | |C1 |C2 |C3 |C1 |C2 |C3 | W | colors of the 4 objects |
| 18 | | | | color 1 | color 2 | | |
| 19 | | FC2 | |C1 |C2 |C3 |C1 |C2 |C3 | W | |
| 20 | | | | color 3 | color 4 | | |
| 21 | | | | | |
| 22 | | FC3 | |sh |pos| W | 1=shape 0=position |
| 23 | | | | | display format and position |
| 24 | | FC4 | (free) | | |
| 25 | | FC5 | (free) | | |
| 26 | | | | | |
| 27 | | FC6 | |C1 |C2 |C3 |BG |scrn colr | W | background lock and color |
| 28 | | | |backg colr |enb|C1 |C2 |C3 | | 3="enable" |
| 29 | | | | | |
| 30 | | FC7 | sound | W | squarewave output |
| 31 | | | | | |
| 32 | | FC8 | N1 | N2 | W | range of the 4 display digits |
| 33 | | FC9 | N3 | N4 | W | |
| 34 | | | | | |
| 35 | | |obj/backgrnd |complete object| R | |
| 36 | | FCA | 1 | 2 | 3 | 4 | 1 | 2 | 3 | 4 | | |
| 37 | | | | | |
| 38 | | FCB | |VR-| object collisions | R | Composition of object and back- |
| 39 | | | |LE |1/2|1/3|1/3|1/4|2/4|3/4| | ground,collision detection and |
| 40 | | | | | object display as a state display |
| 41 | | | | | for the status register.Set VRLE. |
| 42 | | | | | wait for VRST.Read out or transmit |
| 43 | | | | | [copy?] all bits until reset by |
| 44 | | | | | VRST. |
| 45 | | | | | |
| 46 | | FCC | PORT1 | R | PORT1 and PORT2 for the range of |
| 47 | | FCD | PORT2 | | the A/D conversion.Cleared by VRST |
| 48 | | FCE | (free) | | |
| 49 | | FCF | (free) | | |
| 50 | | |
| 51 | | |
| 52 | | Size control by byte FC0 |
| 53 | | |
| 54 | | bit matrix |
| 55 | | |0|0| 8x10 |
| 56 | | |0|1| 16x20 |
| 57 | | |1|0| 32x40 |
| 58 | | |1|1| 64x80 |
| 59 | | |
| 60 | | CE1 and not-CE2 are outputs from the PVI.$E80..$EFF also controls the |
| 61 | | analog multiplexer. |
| 62 | | |
| 63 | | |
| 64 | | SPRITES |
| 65 | | ------- |
| 66 | | |
| 67 | | each object field: (=sprite data structure) |
| 68 | | |
| 69 | | 0 \ 10 bytes of bitmap (Each object is 8 pixels wide.) |
| 70 | | 9 / |
| 71 | | A HC horizontal object coordinate |
| 72 | | B HCB horizontal duplicate coordinate |
| 73 | | C VC vertical object coordinate |
| 74 | | D VCB vertical duplicate coordinate |
| 75 | | |
| 76 | | *************************************************************/ |
| 77 | | |
| 78 | | #include "emu.h" |
| 79 | | #include "video/s2636.h" |
| 80 | | #include "sound/s2636.h" |
| 81 | | |
| 82 | | |
| 83 | | |
| 84 | | /************************************* |
| 85 | | * |
| 86 | | * Device interface |
| 87 | | * |
| 88 | | *************************************/ |
| 89 | | |
| 90 | | const device_type S2636 = &device_creator<s2636_device>; |
| 91 | | |
| 92 | | s2636_device::s2636_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 93 | | : device_t(mconfig, S2636, "Signetics 2636", tag, owner, clock, "s2636", __FILE__), |
| 94 | | device_video_interface(mconfig, *this), |
| 95 | | m_work_ram(NULL), |
| 96 | | m_bitmap(NULL), |
| 97 | | m_collision_bitmap(NULL) |
| 98 | | { |
| 99 | | } |
| 100 | | |
| 101 | | //------------------------------------------------- |
| 102 | | // device_config_complete - perform any |
| 103 | | // operations now that the configuration is |
| 104 | | // complete |
| 105 | | //------------------------------------------------- |
| 106 | | |
| 107 | | void s2636_device::device_config_complete() |
| 108 | | { |
| 109 | | // inherit a copy of the static data |
| 110 | | const s2636_interface *intf = reinterpret_cast<const s2636_interface *>(static_config()); |
| 111 | | if (intf != NULL) |
| 112 | | *static_cast<s2636_interface *>(this) = *intf; |
| 113 | | |
| 114 | | // or initialize to defaults if none provided |
| 115 | | else |
| 116 | | { |
| 117 | | m_work_ram_size = 0; |
| 118 | | m_y_offset = 0; |
| 119 | | m_x_offset = 0; |
| 120 | | m_sound_tag = ""; |
| 121 | | } |
| 122 | | } |
| 123 | | |
| 124 | | //------------------------------------------------- |
| 125 | | // device_start - device-specific startup |
| 126 | | //------------------------------------------------- |
| 127 | | |
| 128 | | void s2636_device::device_start() |
| 129 | | { |
| 130 | | int width = m_screen->width(); |
| 131 | | int height = m_screen->height(); |
| 132 | | |
| 133 | | m_work_ram = auto_alloc_array_clear(machine(), UINT8, m_work_ram_size); |
| 134 | | m_bitmap = auto_bitmap_ind16_alloc(machine(), width, height); |
| 135 | | m_collision_bitmap = auto_bitmap_ind16_alloc(machine(), width, height); |
| 136 | | |
| 137 | | save_item(NAME(m_x_offset)); |
| 138 | | save_item(NAME(m_y_offset)); |
| 139 | | save_pointer(NAME(m_work_ram), m_work_ram_size); |
| 140 | | save_item(NAME(*m_bitmap)); |
| 141 | | save_item(NAME(*m_collision_bitmap)); |
| 142 | | } |
| 143 | | |
| 144 | | /************************************* |
| 145 | | * |
| 146 | | * Constants |
| 147 | | * |
| 148 | | *************************************/ |
| 149 | | |
| 150 | | #define SPRITE_WIDTH (8) |
| 151 | | #define SPRITE_HEIGHT (10) |
| 152 | | |
| 153 | | static const int sprite_offsets[4] = { 0x00, 0x10, 0x20, 0x40 }; |
| 154 | | |
| 155 | | |
| 156 | | |
| 157 | | |
| 158 | | /************************************* |
| 159 | | * |
| 160 | | * Draw a sprite |
| 161 | | * |
| 162 | | *************************************/ |
| 163 | | |
| 164 | | static void draw_sprite( UINT8 *gfx, int color, int y, int x, int expand, int or_mode, bitmap_ind16 &bitmap, const rectangle &cliprect ) |
| 165 | | { |
| 166 | | int sy; |
| 167 | | |
| 168 | | /* for each row */ |
| 169 | | for (sy = 0; sy < SPRITE_HEIGHT; sy++) |
| 170 | | { |
| 171 | | int sx; |
| 172 | | |
| 173 | | /* for each pixel on the row */ |
| 174 | | for (sx = 0; sx < SPRITE_WIDTH; sx++) |
| 175 | | { |
| 176 | | int ey; |
| 177 | | |
| 178 | | /* each pixel can be expanded */ |
| 179 | | for (ey = 0; ey <= expand; ey++) |
| 180 | | { |
| 181 | | int ex; |
| 182 | | |
| 183 | | for (ex = 0; ex <= expand; ex++) |
| 184 | | { |
| 185 | | /* compute effective destination pixel */ |
| 186 | | int ty = y + sy * (expand + 1) + ey; |
| 187 | | int tx = x + sx * (expand + 1) + ex; |
| 188 | | |
| 189 | | /* get out if outside the drawing region */ |
| 190 | | if (!cliprect.contains(tx, ty)) |
| 191 | | continue; |
| 192 | | |
| 193 | | /* get out if current image bit is transparent */ |
| 194 | | if (((gfx[sy] << sx) & 0x80) == 0x00) |
| 195 | | continue; |
| 196 | | |
| 197 | | if (or_mode) |
| 198 | | bitmap.pix16(ty, tx) = 0x08 | bitmap.pix16(ty, tx) | color; |
| 199 | | else |
| 200 | | bitmap.pix16(ty, tx) = 0x08 | color; |
| 201 | | } |
| 202 | | } |
| 203 | | } |
| 204 | | } |
| 205 | | } |
| 206 | | |
| 207 | | |
| 208 | | |
| 209 | | /************************************* |
| 210 | | * |
| 211 | | * Collision detection |
| 212 | | * |
| 213 | | *************************************/ |
| 214 | | |
| 215 | | int s2636_device::check_collision( int spriteno1, int spriteno2, const rectangle &cliprect ) |
| 216 | | { |
| 217 | | int checksum = 0; |
| 218 | | |
| 219 | | UINT8* attr1 = &m_work_ram[sprite_offsets[spriteno1]]; |
| 220 | | UINT8* attr2 = &m_work_ram[sprite_offsets[spriteno2]]; |
| 221 | | |
| 222 | | /* TODO: does not check shadow sprites yet */ |
| 223 | | |
| 224 | | m_collision_bitmap->fill(0, cliprect); |
| 225 | | |
| 226 | | if ((attr1[0x0a] != 0xff) && (attr2[0x0a] != 0xff)) |
| 227 | | { |
| 228 | | int x, y; |
| 229 | | |
| 230 | | int x1 = attr1[0x0a] + m_x_offset; |
| 231 | | int y1 = attr1[0x0c] + m_y_offset; |
| 232 | | int x2 = attr2[0x0a] + m_x_offset; |
| 233 | | int y2 = attr2[0x0c] + m_y_offset; |
| 234 | | |
| 235 | | int expand1 = (m_work_ram[0xc0] >> (spriteno1 << 1)) & 0x03; |
| 236 | | int expand2 = (m_work_ram[0xc0] >> (spriteno2 << 1)) & 0x03; |
| 237 | | |
| 238 | | /* draw first sprite */ |
| 239 | | draw_sprite(attr1, 1, y1, x1, expand1, FALSE, *m_collision_bitmap, cliprect); |
| 240 | | |
| 241 | | /* get fingerprint */ |
| 242 | | for (x = x1; x < x1 + SPRITE_WIDTH; x++) |
| 243 | | for (y = y1; y < y1 + SPRITE_HEIGHT; y++) |
| 244 | | { |
| 245 | | if (!cliprect.contains(x, y)) |
| 246 | | continue; |
| 247 | | |
| 248 | | checksum = checksum + m_collision_bitmap->pix16(y, x); |
| 249 | | } |
| 250 | | |
| 251 | | /* black out second sprite */ |
| 252 | | draw_sprite(attr2, 0, y2, x2, expand2, FALSE, *m_collision_bitmap, cliprect); |
| 253 | | |
| 254 | | /* remove fingerprint */ |
| 255 | | for (x = x1; x < x1 + SPRITE_WIDTH; x++) |
| 256 | | for (y = y1; y < y1 + SPRITE_HEIGHT; y++) |
| 257 | | { |
| 258 | | if (!cliprect.contains(x, y)) |
| 259 | | continue; |
| 260 | | |
| 261 | | checksum = checksum - m_collision_bitmap->pix16(y, x); |
| 262 | | } |
| 263 | | } |
| 264 | | |
| 265 | | return (checksum != 0); |
| 266 | | } |
| 267 | | |
| 268 | | |
| 269 | | |
| 270 | | /************************************* |
| 271 | | * |
| 272 | | * Main drawing |
| 273 | | * |
| 274 | | *************************************/ |
| 275 | | |
| 276 | | bitmap_ind16 &s2636_device::update( const rectangle &cliprect ) |
| 277 | | { |
| 278 | | UINT8 collision = 0; |
| 279 | | int spriteno; |
| 280 | | |
| 281 | | m_bitmap->fill(0, cliprect); |
| 282 | | |
| 283 | | for (spriteno = 0; spriteno < 4; spriteno++) |
| 284 | | { |
| 285 | | int color, expand, x, y; |
| 286 | | UINT8* attr = &m_work_ram[sprite_offsets[spriteno]]; |
| 287 | | |
| 288 | | /* get out if sprite is turned off */ |
| 289 | | if (attr[0x0a] == 0xff) |
| 290 | | continue; |
| 291 | | |
| 292 | | x = attr[0x0a] + m_x_offset; |
| 293 | | y = attr[0x0c] + m_y_offset; |
| 294 | | |
| 295 | | color = (m_work_ram[0xc1 + (spriteno >> 1)] >> ((spriteno & 1) ? 0 : 3)) & 0x07; |
| 296 | | expand = (m_work_ram[0xc0] >> (spriteno << 1)) & 0x03; |
| 297 | | |
| 298 | | draw_sprite(attr, color, y, x, expand, TRUE, *m_bitmap, cliprect); |
| 299 | | |
| 300 | | /* bail if no shadow sprites */ |
| 301 | | if ((attr[0x0b] == 0xff) || (attr[0x0d] == 0xfe)) |
| 302 | | continue; |
| 303 | | |
| 304 | | x = attr[0x0b] + m_x_offset; |
| 305 | | |
| 306 | | while (y < 0xff) |
| 307 | | { |
| 308 | | y = y + SPRITE_HEIGHT + attr[0x0d]; |
| 309 | | |
| 310 | | draw_sprite(attr, color, y, x, expand, TRUE, *m_bitmap, cliprect); |
| 311 | | } |
| 312 | | } |
| 313 | | |
| 314 | | /* collision detection */ |
| 315 | | if (check_collision(0, 1, cliprect)) collision |= 0x20; |
| 316 | | if (check_collision(0, 2, cliprect)) collision |= 0x10; |
| 317 | | if (check_collision(0, 3, cliprect)) collision |= 0x08; |
| 318 | | if (check_collision(1, 2, cliprect)) collision |= 0x04; |
| 319 | | if (check_collision(1, 3, cliprect)) collision |= 0x02; |
| 320 | | if (check_collision(2, 3, cliprect)) collision |= 0x01; |
| 321 | | |
| 322 | | m_work_ram[0xcb] = collision; |
| 323 | | |
| 324 | | return *m_bitmap; |
| 325 | | } |
| 326 | | |
| 327 | | |
| 328 | | /************************************* |
| 329 | | * |
| 330 | | * Work RAM access handlers |
| 331 | | * |
| 332 | | *************************************/ |
| 333 | | |
| 334 | | WRITE8_MEMBER( s2636_device::work_ram_w ) |
| 335 | | { |
| 336 | | assert(offset < m_work_ram_size); |
| 337 | | |
| 338 | | if ( offset == 0xc7 ) |
| 339 | | { |
| 340 | | if ( m_sound_tag && *m_sound_tag ) |
| 341 | | { |
| 342 | | machine().device<s2636_sound_device>(m_sound_tag)->soundport_w(0, data); |
| 343 | | } |
| 344 | | } |
| 345 | | |
| 346 | | m_work_ram[offset] = data; |
| 347 | | } |
| 348 | | |
| 349 | | |
| 350 | | READ8_MEMBER( s2636_device::work_ram_r ) |
| 351 | | { |
| 352 | | assert(offset < m_work_ram_size); |
| 353 | | |
| 354 | | return m_work_ram[offset]; |
| 355 | | } |
trunk/src/emu/sound/s2636.c
| r24877 | r24878 | |
| 1 | | /*************************************************************************** |
| 2 | | |
| 3 | | PeT mess@utanet.at |
| 4 | | |
| 5 | | ***************************************************************************/ |
| 6 | | |
| 7 | | #include "emu.h" |
| 8 | | #include "sound/s2636.h" |
| 9 | | |
| 10 | | const device_type S2636_SOUND = &device_creator<s2636_sound_device>; |
| 11 | | |
| 12 | | s2636_sound_device::s2636_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 13 | | : device_t(mconfig, S2636_SOUND, "S2636", tag, owner, clock, "s2636", __FILE__), |
| 14 | | device_sound_interface(mconfig, *this), |
| 15 | | m_channel(NULL), |
| 16 | | m_size(0), |
| 17 | | m_pos(0), |
| 18 | | m_level(0) |
| 19 | | { |
| 20 | | for (int i = 0; i < 1; i++) |
| 21 | | m_reg[i] = 0; |
| 22 | | } |
| 23 | | |
| 24 | | //------------------------------------------------- |
| 25 | | // device_config_complete - perform any |
| 26 | | // operations now that the configuration is |
| 27 | | // complete |
| 28 | | //------------------------------------------------- |
| 29 | | |
| 30 | | void s2636_sound_device::device_config_complete() |
| 31 | | { |
| 32 | | } |
| 33 | | |
| 34 | | //------------------------------------------------- |
| 35 | | // device_start - device-specific startup |
| 36 | | //------------------------------------------------- |
| 37 | | |
| 38 | | void s2636_sound_device::device_start() |
| 39 | | { |
| 40 | | m_channel = machine().sound().stream_alloc(*this, 0, 1, machine().sample_rate(), this); |
| 41 | | save_item(NAME(m_size)); |
| 42 | | save_item(NAME(m_pos)); |
| 43 | | save_item(NAME(m_level)); |
| 44 | | |
| 45 | | for (int i = 0; i < 1; i++) |
| 46 | | save_item(NAME(m_reg[i]), i); |
| 47 | | } |
| 48 | | |
| 49 | | |
| 50 | | void s2636_sound_device::soundport_w (int offset, int data) |
| 51 | | { |
| 52 | | m_channel->update(); |
| 53 | | m_reg[offset] = data; |
| 54 | | switch (offset) |
| 55 | | { |
| 56 | | case 0: |
| 57 | | m_pos = 0; |
| 58 | | m_level = TRUE; |
| 59 | | // frequency 7874/(data+1) |
| 60 | | m_size = machine().sample_rate() * (data + 1) /7874; |
| 61 | | break; |
| 62 | | } |
| 63 | | } |
| 64 | | |
| 65 | | |
| 66 | | //------------------------------------------------- |
| 67 | | // sound_stream_update - handle a stream update |
| 68 | | //------------------------------------------------- |
| 69 | | |
| 70 | | void s2636_sound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) |
| 71 | | { |
| 72 | | int i; |
| 73 | | stream_sample_t *buffer = outputs[0]; |
| 74 | | |
| 75 | | for (i = 0; i < samples; i++, buffer++) |
| 76 | | { |
| 77 | | *buffer = 0; |
| 78 | | if (m_reg[0] && m_pos <= m_size / 2) |
| 79 | | { |
| 80 | | *buffer = 0x7fff; |
| 81 | | } |
| 82 | | if (m_pos <= m_size) |
| 83 | | m_pos++; |
| 84 | | if (m_pos > m_size) |
| 85 | | m_pos = 0; |
| 86 | | } |
| 87 | | } |