src/emu/sound/sn76496.c
| r6400 | r6401 | |
| 11 | 11 | channel sound generator, with three squarewave channels and a noise/arbitrary |
| 12 | 12 | duty cycle channel. |
| 13 | 13 | |
| 14 | | Noise emulation for all chips should be accurate: |
| 15 | | SN76489 uses a 15-bit shift register with taps on bits D and E, output on E, |
| 14 | Noise emulation for all verified chips should be accurate: |
| 15 | |
| 16 | ** SN76489 uses a 15-bit shift register with taps on bits D and E, output on E, |
| 16 | 17 | XOR function; SN94624 is identical to SN76489. |
| 17 | | * It uses a 15-bit ring buffer for periodic noise/arbitrary duty cycle. |
| 18 | | SN76489A uses a 16-bit shift register with taps on bits D and E, output on F, |
| 18 | It uses a 15-bit ring buffer for periodic noise/arbitrary duty cycle. |
| 19 | ** SN76489A uses a 16-bit shift register with taps on bits D and E, output on F, |
| 19 | 20 | XNOR function |
| 20 | | * It uses a 16-bit ring buffer for periodic noise/arbitrary duty cycle. |
| 21 | | SN76494 and SN76496 are PROBABLY identical in operation to the SN76489A |
| 22 | | * They have an audio input line which is mixed with the 4 channels of output. |
| 23 | | Sega Master System III/MD/Genesis PSG uses a 16-bit shift register with taps |
| 21 | It uses a 16-bit ring buffer for periodic noise/arbitrary duty cycle. |
| 22 | ** SN76494 and SN76496 are PROBABLY identical in operation to the SN76489A |
| 23 | They have an audio input line which is mixed with the 4 channels of output. |
| 24 | ** Sega Master System III/MD/Genesis PSG uses a 16-bit shift register with taps |
| 24 | 25 | on bits C and F, output on F |
| 25 | | * It uses a 16-bit ring buffer for periodic noise/arbitrary duty cycle. |
| 26 | | Sega Game Gear PSG is identical to the SMS3/MD/Genesis one except it has an |
| 26 | It uses a 16-bit ring buffer for periodic noise/arbitrary duty cycle. |
| 27 | (whether it uses an XOR or XNOR needs to be verified) |
| 28 | ** Sega Game Gear PSG is identical to the SMS3/MD/Genesis one except it has an |
| 27 | 29 | extra register for mapping which channels go to which speaker. |
| 28 | | |
| 30 | The register, connected to a z80 port, means: |
| 31 | for bits 7 6 5 4 3 2 1 0 |
| 32 | L3 L2 L1 L0 R3 R2 R1 R0 |
| 33 | ** NCR7496 (as used on the Tandy 1000) is similar to the SN76489 but with a |
| 34 | different noise LFSR patttern: taps on bits A and E, output on E |
| 35 | It uses a 15-bit ring buffer for periodic noise/arbitrary duty cycle. |
| 36 | (all this chip's info needs to be verified) |
| 37 | |
| 29 | 38 | 28/03/2005 : Sebastien Chevalier |
| 30 | 39 | Update th SN76496Write func, according to SN76489 doc found on SMSPower. |
| 31 | 40 | - On write with 0x80 set to 0, when LastRegister is other then TONE, |
| r6400 | r6401 | |
| 52 | 61 | 16/11/2009 : Lord Nightmare |
| 53 | 62 | Fix screeching in regulus: When summing together four equal channels, the |
| 54 | 63 | size of the max amplitude per channel should be 1/4 of the max range, not |
| 55 | | 1/3. |
| 64 | 1/3. Added NCR7496. Changed sega psg/gamegear from XNOR to XOR. |
| 56 | 65 | |
| 57 | 66 | TODO: * Implement a function for setting stereo regs for the game gear. |
| 58 | 67 | Requires making the core support both mono and stereo, and have |
| r6400 | r6401 | |
| 63 | 72 | max of 4Mhz and 32 clocks per sample on the SN76489A. |
| 64 | 73 | * Implement the T6W28; has registers in a weird order, needs writes |
| 65 | 74 | to be 'sanitized' first. Also is stereo, similar to game gear. |
| 66 | | * Implement the NCR 7496; Is probably 100% compatible with SN76496, |
| 67 | | but the whitenoise taps could be different. Needs someone with a |
| 68 | | Tandy 1200 or whatever it was which uses this to run some tests. |
| 75 | * Test the NCR7496; Smspower says the whitenoise taps are A and E, |
| 76 | but this needs verification on real hardware. |
| 77 | * Test the SMS PSG/Gamegear PSG to see whether it uses XOR or XNOR |
| 78 | taps. |
| 69 | 79 | * Factor out common code so that the SAA1099 can share some code. |
| 70 | 80 | ***************************************************************************/ |
| 71 | 81 | |
| r6400 | r6401 | |
| 109 | 119 | sound_get_type(device) == SOUND_SN76489A || |
| 110 | 120 | sound_get_type(device) == SOUND_SN76494 || |
| 111 | 121 | sound_get_type(device) == SOUND_SN94624 || |
| 122 | sound_get_type(device) == SOUND_NCR7496 || |
| 112 | 123 | sound_get_type(device) == SOUND_GAMEGEAR || |
| 113 | 124 | sound_get_type(device) == SOUND_SMSIII); |
| 114 | 125 | return (sn76496_state *)device->token; |
| r6400 | r6401 | |
| 359 | 370 | |
| 360 | 371 | static DEVICE_START( sn76489 ) |
| 361 | 372 | { |
| 362 | | generic_start(device, 0x4000, 0x03, FALSE); |
| 373 | generic_start(device, 0x4000, 0x03, FALSE); // todo: verify; assumed to be the same as sn94624 |
| 363 | 374 | } |
| 364 | 375 | |
| 365 | 376 | static DEVICE_START( sn76489a ) |
| 366 | 377 | { |
| 367 | | generic_start(device, 0x8000, 0x06, TRUE); |
| 378 | generic_start(device, 0x8000, 0x06, TRUE); // verified by plgdavid |
| 368 | 379 | } |
| 369 | 380 | |
| 370 | 381 | static DEVICE_START( sn76494 ) |
| 371 | 382 | { |
| 372 | | generic_start(device, 0x8000, 0x06, TRUE); |
| 383 | generic_start(device, 0x8000, 0x06, TRUE); // todo: verify; assumed to be the same as sn76489a |
| 373 | 384 | } |
| 374 | 385 | |
| 375 | 386 | static DEVICE_START( sn76496 ) |
| 376 | 387 | { |
| 377 | | generic_start(device, 0x8000, 0x06, TRUE); |
| 388 | generic_start(device, 0x8000, 0x06, TRUE); // todo: verify; assumed to be the same as sn76489a |
| 378 | 389 | } |
| 379 | 390 | |
| 380 | 391 | static DEVICE_START( sn94624 ) |
| 381 | 392 | { |
| 382 | | generic_start(device, 0x4000, 0x03, FALSE); |
| 393 | generic_start(device, 0x4000, 0x03, FALSE); // verified by plgdavid |
| 383 | 394 | } |
| 384 | 395 | |
| 396 | static DEVICE_START( ncr7496 ) |
| 397 | { |
| 398 | generic_start(device, 0x4000, 0x11, FALSE); // todo: verify; from smspower wiki |
| 399 | } |
| 400 | |
| 385 | 401 | static DEVICE_START( gamegear ) |
| 386 | 402 | { |
| 387 | | generic_start(device, 0x8000, 0x09, TRUE); |
| 403 | generic_start(device, 0x8000, 0x09, FALSE); // todo: verify; from smspower wiki |
| 388 | 404 | } |
| 389 | 405 | |
| 390 | 406 | static DEVICE_START( smsiii ) |
| 391 | 407 | { |
| 392 | | generic_start(device, 0x8000, 0x09, TRUE); |
| 408 | generic_start(device, 0x8000, 0x09, FALSE); // todo: verify; from smspower wiki |
| 393 | 409 | } |
| 394 | 410 | |
| 395 | 411 | |
| r6400 | r6401 | |
| 428 | 444 | } |
| 429 | 445 | } |
| 430 | 446 | |
| 431 | | DEVICE_GET_INFO( sn94624 ) |
| 447 | DEVICE_GET_INFO( sn76489a ) |
| 432 | 448 | { |
| 433 | 449 | switch (state) |
| 434 | 450 | { |
| 435 | | case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( sn94624 ); break; |
| 436 | | case DEVINFO_STR_NAME: strcpy(info->s, "SN94624"); break; |
| 451 | case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( sn76489a ); break; |
| 452 | case DEVINFO_STR_NAME: strcpy(info->s, "SN76489A"); break; |
| 437 | 453 | default: DEVICE_GET_INFO_CALL(sn76496); break; |
| 438 | 454 | } |
| 439 | 455 | } |
| 440 | 456 | |
| 441 | | DEVICE_GET_INFO( sn76489a ) |
| 457 | DEVICE_GET_INFO( sn76494 ) |
| 442 | 458 | { |
| 443 | 459 | switch (state) |
| 444 | 460 | { |
| 445 | | case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( sn76489a ); break; |
| 446 | | case DEVINFO_STR_NAME: strcpy(info->s, "SN76489A"); break; |
| 461 | case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( sn76494 ); break; |
| 462 | case DEVINFO_STR_NAME: strcpy(info->s, "SN76494"); break; |
| 447 | 463 | default: DEVICE_GET_INFO_CALL(sn76496); break; |
| 448 | 464 | } |
| 449 | 465 | } |
| 450 | 466 | |
| 451 | | DEVICE_GET_INFO( sn76494 ) |
| 467 | DEVICE_GET_INFO( sn94624 ) |
| 452 | 468 | { |
| 453 | 469 | switch (state) |
| 454 | 470 | { |
| 455 | | case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( sn76494 ); break; |
| 456 | | case DEVINFO_STR_NAME: strcpy(info->s, "SN76494"); break; |
| 471 | case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( sn94624 ); break; |
| 472 | case DEVINFO_STR_NAME: strcpy(info->s, "SN94624"); break; |
| 457 | 473 | default: DEVICE_GET_INFO_CALL(sn76496); break; |
| 458 | 474 | } |
| 459 | 475 | } |
| 460 | 476 | |
| 477 | DEVICE_GET_INFO( ncr7496 ) |
| 478 | { |
| 479 | switch (state) |
| 480 | { |
| 481 | case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( ncr7496 ); break; |
| 482 | case DEVINFO_STR_NAME: strcpy(info->s, "NCR7496"); break; |
| 483 | default: DEVICE_GET_INFO_CALL(sn76496); break; |
| 484 | } |
| 485 | } |
| 486 | |
| 461 | 487 | DEVICE_GET_INFO( gamegear ) |
| 462 | 488 | { |
| 463 | 489 | switch (state) |