mirror of
https://github.com/tildearrow/furnace.git
synced 2025-01-03 14:11:11 +00:00
SegaPCM: prepare to actually emulate it
This commit is contained in:
parent
00b329b896
commit
0d424c7962
4 changed files with 178 additions and 0 deletions
|
@ -365,6 +365,7 @@ src/engine/platform/sound/sn76496.cpp
|
||||||
src/engine/platform/sound/ay8910.cpp
|
src/engine/platform/sound/ay8910.cpp
|
||||||
src/engine/platform/sound/saa1099.cpp
|
src/engine/platform/sound/saa1099.cpp
|
||||||
src/engine/platform/sound/namco.cpp
|
src/engine/platform/sound/namco.cpp
|
||||||
|
src/engine/platform/sound/segapcm.cpp
|
||||||
src/engine/platform/sound/gb/apu.c
|
src/engine/platform/sound/gb/apu.c
|
||||||
src/engine/platform/sound/gb/timing.c
|
src/engine/platform/sound/gb/timing.c
|
||||||
src/engine/platform/sound/pce_psg.cpp
|
src/engine/platform/sound/pce_psg.cpp
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
|
|
||||||
#include "../dispatch.h"
|
#include "../dispatch.h"
|
||||||
#include "../instrument.h"
|
#include "../instrument.h"
|
||||||
|
#include "sound/segapcm.h"
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
class DivPlatformSegaPCM: public DivDispatch {
|
class DivPlatformSegaPCM: public DivDispatch {
|
||||||
|
@ -59,6 +60,7 @@ class DivPlatformSegaPCM: public DivDispatch {
|
||||||
QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v), addrOrVal(false) {}
|
QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v), addrOrVal(false) {}
|
||||||
};
|
};
|
||||||
std::queue<QueuedWrite> writes;
|
std::queue<QueuedWrite> writes;
|
||||||
|
segapcm_device pcm;
|
||||||
int delay;
|
int delay;
|
||||||
int pcmL, pcmR, pcmCycles;
|
int pcmL, pcmR, pcmCycles;
|
||||||
unsigned char sampleBank;
|
unsigned char sampleBank;
|
||||||
|
|
125
src/engine/platform/sound/segapcm.cpp
Normal file
125
src/engine/platform/sound/segapcm.cpp
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
// license:BSD-3-Clause
|
||||||
|
// copyright-holders:Hiromitsu Shioya, Olivier Galibert
|
||||||
|
/*********************************************************/
|
||||||
|
/* SEGA 16ch 8bit PCM */
|
||||||
|
/*********************************************************/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "segapcm.h"
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// segapcm_device - constructor
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
segapcm_device::segapcm_device()
|
||||||
|
: m_bankshift(12)
|
||||||
|
, m_bankmask(0x70)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// device_start - device-specific startup
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
void segapcm_device::device_start()
|
||||||
|
{
|
||||||
|
memset(m_ram,255,0x800);
|
||||||
|
memset(m_low,0,16);
|
||||||
|
memset(lastOut,0,16*2*sizeof(short));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// sound_stream_update - handle a stream update
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
void segapcm_device::sound_stream_update(int* outputs)
|
||||||
|
{
|
||||||
|
/* clear the buffers */
|
||||||
|
outputs[0]=0;
|
||||||
|
outputs[1]=0;
|
||||||
|
|
||||||
|
// reg function
|
||||||
|
// ------------------------------------------------
|
||||||
|
// 0x00 ?
|
||||||
|
// 0x01 ?
|
||||||
|
// 0x02 volume left
|
||||||
|
// 0x03 volume right
|
||||||
|
// 0x04 loop address (08-15)
|
||||||
|
// 0x05 loop address (16-23)
|
||||||
|
// 0x06 end address
|
||||||
|
// 0x07 address delta
|
||||||
|
// 0x80 ?
|
||||||
|
// 0x81 ?
|
||||||
|
// 0x82 ?
|
||||||
|
// 0x83 ?
|
||||||
|
// 0x84 current address (08-15), 00-07 is internal?
|
||||||
|
// 0x85 current address (16-23)
|
||||||
|
// 0x86 bit 0: channel disable?
|
||||||
|
// bit 1: loop disable
|
||||||
|
// other bits: bank
|
||||||
|
// 0x87 ?
|
||||||
|
|
||||||
|
/* loop over channels */
|
||||||
|
for (int ch = 0; ch < 16; ch++)
|
||||||
|
{
|
||||||
|
uint8_t *regs = &m_ram[8*ch];
|
||||||
|
|
||||||
|
/* only process active channels */
|
||||||
|
if (!(regs[0x86]&1))
|
||||||
|
{
|
||||||
|
int offset = (regs[0x86] & m_bankmask) << m_bankshift;
|
||||||
|
uint32_t addr = (regs[0x85] << 16) | (regs[0x84] << 8) | m_low[ch];
|
||||||
|
uint32_t loop = (regs[0x05] << 16) | (regs[0x04] << 8);
|
||||||
|
uint8_t end = regs[6] + 1;
|
||||||
|
|
||||||
|
int8_t v;
|
||||||
|
bool fetch=true;
|
||||||
|
|
||||||
|
/* handle looping if we've hit the end */
|
||||||
|
if ((addr >> 16) == end)
|
||||||
|
{
|
||||||
|
if (regs[0x86] & 2)
|
||||||
|
{
|
||||||
|
regs[0x86] |= 1;
|
||||||
|
fetch=false;
|
||||||
|
}
|
||||||
|
else addr = loop;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fetch the sample */
|
||||||
|
if (fetch) {
|
||||||
|
v = read_byte(offset + (addr >> 8)) - 0x80;
|
||||||
|
|
||||||
|
/* apply panning and advance */
|
||||||
|
lastOut[ch][0]=v * (regs[2] & 0x7f);
|
||||||
|
lastOut[ch][1]=v * (regs[3] & 0x7f);
|
||||||
|
outputs[0]+=lastOut[ch][0];
|
||||||
|
outputs[1]+=lastOut[ch][1];
|
||||||
|
addr = (addr + regs[7]) & 0xffffff;
|
||||||
|
} else {
|
||||||
|
lastOut[ch][0]=0;
|
||||||
|
lastOut[ch][1]=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* store back the updated address */
|
||||||
|
regs[0x84] = addr >> 8;
|
||||||
|
regs[0x85] = addr >> 16;
|
||||||
|
m_low[ch] = regs[0x86] & 1 ? 0 : addr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void segapcm_device::write(unsigned int offset, uint8_t data)
|
||||||
|
{
|
||||||
|
m_ram[offset & 0x07ff] = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t segapcm_device::read(unsigned int offset)
|
||||||
|
{
|
||||||
|
return m_ram[offset & 0x07ff];
|
||||||
|
}
|
50
src/engine/platform/sound/segapcm.h
Normal file
50
src/engine/platform/sound/segapcm.h
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
// license:BSD-3-Clause
|
||||||
|
// copyright-holders:Hiromitsu Shioya, Olivier Galibert
|
||||||
|
/*********************************************************/
|
||||||
|
/* SEGA 8bit PCM */
|
||||||
|
/*********************************************************/
|
||||||
|
|
||||||
|
#ifndef MAMESOUND_SEGAPCM_H
|
||||||
|
#define MAMESOUND_SEGAPCM_H
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
//**************************************************************************
|
||||||
|
// TYPE DEFINITIONS
|
||||||
|
//**************************************************************************
|
||||||
|
|
||||||
|
class segapcm_device {
|
||||||
|
public:
|
||||||
|
static constexpr int BANK_256 = 11;
|
||||||
|
static constexpr int BANK_512 = 12;
|
||||||
|
static constexpr int BANK_12M = 13;
|
||||||
|
static constexpr int BANK_MASK7 = 0x70 << 16;
|
||||||
|
static constexpr int BANK_MASKF = 0xf0 << 16;
|
||||||
|
static constexpr int BANK_MASKF8 = 0xf8 << 16;
|
||||||
|
|
||||||
|
short lastOut[16][2];
|
||||||
|
|
||||||
|
segapcm_device();
|
||||||
|
|
||||||
|
// configuration
|
||||||
|
void set_bank(int bank) { m_bankshift = (bank & 0xf); m_bankmask = (0x70|((bank >> 16) & 0xfc)); }
|
||||||
|
void set_read(std::function<unsigned char(unsigned int)> r) { read_byte = r; }
|
||||||
|
|
||||||
|
void write(unsigned int offset, uint8_t data);
|
||||||
|
uint8_t read(unsigned int offset);
|
||||||
|
|
||||||
|
// device-level overrides
|
||||||
|
void device_start();
|
||||||
|
|
||||||
|
// sound stream update overrides
|
||||||
|
void sound_stream_update(int* outputs);
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8_t m_ram[0x800];
|
||||||
|
uint8_t m_low[16];
|
||||||
|
int m_bankshift;
|
||||||
|
int m_bankmask;
|
||||||
|
std::function<unsigned char(unsigned int)> read_byte;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MAMESOUND_SEGAPCM_H
|
Loading…
Reference in a new issue