Skip to content

Commit 7a087d6

Browse files
committed
VGMPlayer: fix BSMT2000 playback
also included: - fix VC6 compilation - disable interpolation (because the original chip doesn't do that)
1 parent d361f93 commit 7a087d6

File tree

3 files changed

+53
-54
lines changed

3 files changed

+53
-54
lines changed

emu/cores/bsmt2000.c

Lines changed: 44 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ struct _bsmt2000_state
101101
UINT8 adpcm; // ADPCM/compressed enabled?
102102
UINT8 mode; // current mode (0,1,5,6,7)
103103
UINT8 last_register; // last register written
104+
UINT16 latch; // buffer to combine 8-bit writes to a 16-bit words
104105
UINT32 clock; // Chip clock
105106

106107
// ADPCM/compressed state
@@ -271,9 +272,7 @@ static void device_stop_bsmt2000(void *info)
271272
/* ==== Device Reset ==== */
272273
static void device_reset_bsmt2000(void *info) {
273274
bsmt2000_state *chip = (bsmt2000_state *)info;
274-
UINT32 muteMask;
275275

276-
muteMask = bsmt2000_get_mute_mask(chip);
277276
init_all_voices(chip);
278277
chip->adpcm_current = 0;
279278
chip->adpcm_delta_n = 10;
@@ -313,7 +312,6 @@ static void device_reset_bsmt2000(void *info) {
313312
chip->adpcm = 0;
314313
chip->mode = 6;
315314
break;
316-
317315
/* mode 7: 32kHz, 9 channel PCM, stereo */
318316
case 7:
319317
chip->sample_rate = chip->clock / 750.;
@@ -323,29 +321,26 @@ static void device_reset_bsmt2000(void *info) {
323321
chip->mode = 7;
324322
break;
325323
}
326-
bsmt2000_set_mute_mask(chip, muteMask);
327-
if (chip->SmpRateFunc != NULL)
328-
chip->SmpRateFunc(chip->SmpRateData, chip->sample_rate);
329-
324+
if (chip->SmpRateFunc != NULL)
325+
chip->SmpRateFunc(chip->SmpRateData, (UINT32)chip->sample_rate);
330326
}
331327
/* ==== Register/Command Interface ==== */
332328

333329
static void bsmt2000_w(void *info, UINT8 offset, UINT8 data)
334330
{
335331
bsmt2000_state *chip = (bsmt2000_state *)info;
336-
static UINT16 latch = 0;
337332
switch (offset)
338333
{
339334
case 0:
340-
latch = (latch & 0x00ff) | (data << 8);
335+
chip->latch = (chip->latch & 0x00ff) | (data << 8);
341336
break;
342337
case 1:
343-
latch = (latch & 0xff00) | data;
338+
chip->latch = (chip->latch & 0xff00) | data;
344339
break;
345340
case 2:
346-
bsmt2000_write_data(chip, data, latch);
341+
bsmt2000_write_data(chip, data, chip->latch);
347342
break;
348-
case 3:
343+
case 0x10:
349344
chip->last_register = data;
350345
device_reset_bsmt2000(info);
351346
break;
@@ -448,8 +443,7 @@ static void bsmt2000_write_rom(void *info, UINT32 offset, UINT32 length, const U
448443
if (offset > chip->sample_rom_length) return;
449444
if (offset + length > chip->sample_rom_length)
450445
length = chip->sample_rom_length - offset;
451-
for (UINT32 i = 0; i < length; i++)
452-
chip->sample_rom[offset + i] = data[i];
446+
memcpy(&chip->sample_rom[offset], data, length);
453447
}
454448

455449
/* ==== Mute Mask ==== */
@@ -479,15 +473,16 @@ static void bsmt2000_set_log_cb(void* info, DEVCB_LOG func, void* param)
479473
}
480474

481475
/* ==== Interpolation Macro ==== */
482-
#define INTERPOLATE(s1,s2,frac) (((s1) * (0x10000 - ((frac)&0xffff)) + (s2) * ((frac)&0xffff)) >> 16)
476+
#define INTERPOLATE(s1,s2,frac) (((s1) * (INT32)(0x10000 - ((frac)&0xffff)) + (s2) * (INT32)((frac)&0xffff)) >> 16)
483477

484478
/* ==== Sound Update ==== */
485479
static void bsmt2000_update(void *param, UINT32 samples, DEV_SMPL **outputs)
486480
{
487481
bsmt2000_state *chip = (bsmt2000_state *)param;
488-
INT64 left[BSMT2000_SAMPLE_CHUNK], right[BSMT2000_SAMPLE_CHUNK];
482+
INT32 left[BSMT2000_SAMPLE_CHUNK];
483+
INT32 right[BSMT2000_SAMPLE_CHUNK];
489484
bsmt2000_voice *voice;
490-
int samp, v, length = MIN(samples, BSMT2000_SAMPLE_CHUNK);
485+
int samp, v, length = MIN(samples, BSMT2000_SAMPLE_CHUNK); // TODO: allow updating in larger chunks
491486

492487
if (!chip->sample_rom || !chip->sample_rom_length)
493488
{
@@ -501,27 +496,40 @@ static void bsmt2000_update(void *param, UINT32 samples, DEV_SMPL **outputs)
501496
// PCM voices
502497
for (v = 0; v < chip->voices; v++)
503498
{
499+
UINT8 *base;
500+
UINT32 rate, pos;
501+
INT32 lvol, rvol;
502+
504503
if (chip->Muted[v])
505504
continue;
506505
voice = &chip->voice[v];
507506
if (voice->reg[BSMT2000_REG_BANK] >= chip->total_banks) // REG_BANK
508507
continue;
509-
UINT8 *base = chip->sample_rom + voice->reg[BSMT2000_REG_BANK] * BSMT2000_ROM_BANKSIZE;
510-
UINT32 rate = voice->adjusted_rate;
511-
UINT32 pos = voice->position;
512-
INT32 rvol = voice->reg[BSMT2000_REG_RIGHTVOL]; // REG_RIGHTVOL
513-
INT32 lvol = chip->stereo ? voice->reg[BSMT2000_REG_LEFTVOL] : rvol; // REG_LEFTVOL
508+
base = chip->sample_rom + voice->reg[BSMT2000_REG_BANK] * BSMT2000_ROM_BANKSIZE;
509+
rate = voice->adjusted_rate;
510+
pos = voice->position;
511+
rvol = voice->reg[BSMT2000_REG_RIGHTVOL]; // REG_RIGHTVOL
512+
lvol = chip->stereo ? voice->reg[BSMT2000_REG_LEFTVOL] : rvol; // REG_LEFTVOL
514513
if (chip->stereo && !chip->right_volume_set)
515514
rvol = lvol;
516-
int remaining = length;
517515

518-
while (remaining--) {
516+
for (samp = 0; samp < length; samp ++) {
519517
INT32 idx = pos >> 16;
520-
INT32 s1 = ((INT8)base[idx] << 8);
521-
INT32 s2 = ((INT8)base[idx+1] << 8);
522-
INT32 sample = (s1 * (INT32)(0x10000 - (pos & 0xffff)) + (s2 * (INT32)(pos & 0xffff))) >> 16;
523-
left[length-remaining-1] += sample * lvol;
524-
right[length-remaining-1] += sample * rvol;
518+
INT32 sample;
519+
if (1)
520+
{
521+
// no interpolation (original chip behaviour)
522+
sample = (INT8)base[idx] << 8;
523+
}
524+
else
525+
{
526+
// linear interpolation (softer samples, breaks SFX in "Tales from the Crypt")
527+
INT32 s1 = (INT8)base[idx] << 8;
528+
INT32 s2 = (INT8)base[idx+1] << 8;
529+
sample = INTERPOLATE(s1, s2, pos);
530+
}
531+
left[samp] += (sample * lvol) >> 16;
532+
right[samp] += (sample * rvol) >> 16;
525533
pos += rate;
526534
if (pos >= voice->loop_stop_position)
527535
pos += voice->loop_start_position - voice->loop_stop_position;
@@ -542,13 +550,12 @@ static void bsmt2000_update(void *param, UINT32 samples, DEV_SMPL **outputs)
542550
INT32 lvol = chip->stereo ? voice->reg[BSMT2000_REG_LEFTVOL] : rvol;
543551
if (chip->stereo && !chip->right_volume_set)
544552
rvol = lvol;
545-
int remaining = length;
546553

547-
while (remaining-- && pos < voice->loop_stop_position)
554+
for (samp = 0; samp < length && pos < voice->loop_stop_position; samp ++)
548555
{
549556
UINT32 oldpos = pos;
550-
left[length-remaining-1] += chip->adpcm_current * (lvol * 2);
551-
right[length-remaining-1] += chip->adpcm_current * (rvol * 2);
557+
left[samp] += (chip->adpcm_current * (lvol * 2)) >> 16;
558+
right[samp] += (chip->adpcm_current * (rvol * 2)) >> 16;
552559

553560
pos += rate;
554561
if ((oldpos ^ pos) & 0x8000)
@@ -583,12 +590,12 @@ static void bsmt2000_update(void *param, UINT32 samples, DEV_SMPL **outputs)
583590

584591
// Output clamp and write
585592
for (samp = 0; samp < length; samp++) {
586-
INT64 l = left[samp] >> 16;
587-
INT64 r = right[samp] >> 16;
593+
INT32 l = left[samp];
594+
INT32 r = right[samp];
588595
l = (l > 32767) ? 32767 : (l < -32768) ? -32768 : l;
589596
r = (r > 32767) ? 32767 : (r < -32768) ? -32768 : r;
590-
outputs[0][samp] = l;
591-
outputs[1][samp] = r;
597+
outputs[0][samp] = (DEV_SMPL)l;
598+
outputs[1][samp] = (DEV_SMPL)r;
592599
}
593600
}
594601

player/vgmplayer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@
6363
0x6C, 0x70, 0x74, 0x80, 0x84, 0x88, 0x8C, 0x90,
6464
0x98, 0x9C, 0xA0, 0xA4, 0xA8, 0xAC, 0xB0, 0xB4,
6565
0xB8, 0xC0, 0xC4, 0xC8, 0xCC, 0xD0, 0xD8, 0xDC,
66-
0xE0, 0xE4, 0xE8, 0xEC, 0xF0, 0xF4,
66+
0xE0, 0xE4, 0xE8, 0xEC, 0xF0, 0xF4, 0xF8,
6767
};
6868
/*static*/ const UINT16 VGMPlayer::_CHIP_VOLUME[_CHIP_COUNT] =
6969
{ 0x80, 0x200, 0x100, 0x100, 0x180, 0xB0, 0x100, 0x80,

player/vgmplayer_cmdhandler.cpp

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@
7171
{0x00, 0x02, &VGMPlayer::Cmd_SN76489}, // 30 SN76489 register write (2nd chip)
7272
{0xFF, 0x02, &VGMPlayer::Cmd_AY_Stereo}, // 31 AY8910 stereo mask [chip type depends on data]
7373
{0x2C, 0x02, &VGMPlayer::Cmd_MSM5205_Reg}, // 32 MSM5205 register write
74-
{0x2F, 0x02, &VGMPlayer::Cmd_BSMT2000_Mode}, // 33 BSMT2000 change mode
74+
{0xFF, 0x02, &VGMPlayer::Cmd_unknown}, // 33
7575
{0xFF, 0x02, &VGMPlayer::Cmd_unknown}, // 34
7676
{0xFF, 0x02, &VGMPlayer::Cmd_unknown}, // 35
7777
{0xFF, 0x02, &VGMPlayer::Cmd_unknown}, // 36
@@ -221,7 +221,7 @@
221221
{0x21, 0x04, &VGMPlayer::Cmd_Ofs16_Data8}, // C6 WonderSwan memory write
222222
{0x22, 0x04, &VGMPlayer::Cmd_Ofs16_Data8}, // C7 VSU-VUE (Virtual Boy) register write
223223
{0x26, 0x04, &VGMPlayer::Cmd_Ofs16_Data8}, // C8 X1-010 register write
224-
{0x2F, 0x04, &VGMPlayer::Cmd_BSMT2000_Reg}, // C9 BSMT2000 register write
224+
{0x2E, 0x04, &VGMPlayer::Cmd_BSMT2000_Reg}, // C9 BSMT2000 register write
225225
{0xFF, 0x04, &VGMPlayer::Cmd_unknown}, // CA
226226
{0xFF, 0x04, &VGMPlayer::Cmd_unknown}, // CB
227227
{0xFF, 0x04, &VGMPlayer::Cmd_unknown}, // CC
@@ -370,7 +370,7 @@
370370
{0x27, 0}, // 92 C352
371371
{0x28, 0}, // 93 GA20
372372
{0x2A, 0}, // 94 K007232
373-
{0x2F, 0}, // 95 BSMT2000
373+
{0x2E, 0}, // 95 BSMT2000
374374
{0xFF, 0}, // 96
375375
{0xFF, 0}, // 97
376376
{0xFF, 0}, // 98
@@ -1413,18 +1413,10 @@ void VGMPlayer::Cmd_BSMT2000_Reg(void)
14131413
if (cDev == NULL || cDev->write8 == NULL)
14141414
return;
14151415

1416-
WriteQSound_B(cDev, fData[0x01] & 0x7f, ReadBE16(&fData[0x02]));
1416+
UINT8 ofs = fData[0x01] & 0x7F;
1417+
if (ofs == 0x7F) // special register
1418+
cDev->write8(cDev->base.defInf.dataPtr, 0x10 + fData[0x02], fData[0x03]);
1419+
else
1420+
WriteQSound_B(cDev, ofs, ReadBE16(&fData[0x02]));
14171421
return;
14181422
}
1419-
1420-
void VGMPlayer::Cmd_BSMT2000_Mode(void)
1421-
{
1422-
UINT8 chipType = _CMD_INFO[fData[0x00]].chipType;
1423-
UINT8 chipID = (fData[0x01] & 0x80) >> 7;
1424-
CHIP_DEVICE* cDev = GetDevicePtr(chipType, chipID);
1425-
if (cDev == NULL || cDev->write8 == NULL)
1426-
return;
1427-
1428-
cDev->write8(cDev->base.defInf.dataPtr, 0x03, fData[0x01] & 0x7f);
1429-
return;
1430-
}

0 commit comments

Comments
 (0)