137 lines
2.9 KiB
C++
137 lines
2.9 KiB
C++
![]() |
/*
|
||
|
License: BSD-3-Clause
|
||
|
see https://github.com/cam900/vgsound_emu/LICENSE for more details
|
||
|
|
||
|
Copyright holder(s): cam900
|
||
|
Konami SCC emulation core
|
||
|
|
||
|
See scc.cpp for more info.
|
||
|
*/
|
||
|
|
||
|
#include <algorithm>
|
||
|
#include <memory>
|
||
|
|
||
|
#ifndef _VGSOUND_EMU_SCC_HPP
|
||
|
#define _VGSOUND_EMU_SCC_HPP
|
||
|
|
||
|
#pragma once
|
||
|
|
||
|
namespace scc
|
||
|
{
|
||
|
typedef unsigned char u8;
|
||
|
typedef signed char s8;
|
||
|
typedef unsigned short u16;
|
||
|
typedef signed short s16;
|
||
|
typedef unsigned int u32;
|
||
|
typedef signed int s32;
|
||
|
|
||
|
// get bitfield, bitfield(input, position, len)
|
||
|
template<typename T> T bitfield(T in, u8 pos, u8 len = 1)
|
||
|
{
|
||
|
return (in >> pos) & (len ? (T(1 << len) - 1) : 1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
using namespace scc;
|
||
|
// shared for SCCs
|
||
|
class scc_core
|
||
|
{
|
||
|
public:
|
||
|
// constructor
|
||
|
scc_core()
|
||
|
: m_voice{*this,*this,*this,*this,*this}
|
||
|
{};
|
||
|
|
||
|
// accessors
|
||
|
virtual u8 scc_r(bool is_sccplus, u8 address) = 0;
|
||
|
virtual void scc_w(bool is_sccplus, u8 address, u8 data) = 0;
|
||
|
|
||
|
// internal state
|
||
|
virtual void reset();
|
||
|
void tick();
|
||
|
|
||
|
// getters
|
||
|
s32 out() { return m_out; } // output to DA0...DA10 pin
|
||
|
s32 chan_out(u8 ch) { return m_voice[ch].out; }
|
||
|
u8 reg(u8 address) { return m_reg[address]; }
|
||
|
|
||
|
protected:
|
||
|
// voice structs
|
||
|
struct voice_t
|
||
|
{
|
||
|
// constructor
|
||
|
voice_t(scc_core &host) : m_host(host) {};
|
||
|
|
||
|
// internal state
|
||
|
void reset();
|
||
|
void tick();
|
||
|
|
||
|
// registers
|
||
|
scc_core &m_host;
|
||
|
s8 wave[32] = {0}; // internal waveform
|
||
|
bool enable = false; // output enable flag
|
||
|
u16 pitch = 0; // pitch
|
||
|
u8 volume = 0; // volume
|
||
|
u8 addr = 0; // waveform pointer
|
||
|
u16 counter = 0; // frequency counter
|
||
|
s32 out = 0; // current output
|
||
|
};
|
||
|
voice_t m_voice[5]; // 5 voices
|
||
|
|
||
|
// accessor
|
||
|
u8 wave_r(bool is_sccplus, u8 address);
|
||
|
void wave_w(bool is_sccplus, u8 address, u8 data);
|
||
|
void freq_vol_enable_w(u8 address, u8 data);
|
||
|
|
||
|
struct test_t
|
||
|
{
|
||
|
// constructor
|
||
|
test_t()
|
||
|
: freq_4bit(0)
|
||
|
, freq_8bit(0)
|
||
|
, resetpos(0)
|
||
|
, rotate(0)
|
||
|
, rotate4(0)
|
||
|
{ };
|
||
|
|
||
|
void reset()
|
||
|
{
|
||
|
freq_4bit = 0;
|
||
|
freq_8bit = 0;
|
||
|
resetpos = 0;
|
||
|
rotate = 0;
|
||
|
rotate4 = 0;
|
||
|
}
|
||
|
|
||
|
u8 freq_4bit : 1; // 4 bit frequency
|
||
|
u8 freq_8bit : 1; // 8 bit frequency
|
||
|
u8 resetpos : 1; // reset counter after pitch writes
|
||
|
u8 rotate : 1; // rotate and write protect waveform for all channels
|
||
|
u8 rotate4 : 1; // same as above but for channel 4 only
|
||
|
};
|
||
|
|
||
|
test_t m_test; // test register
|
||
|
s32 m_out = 0; // output to DA0...10
|
||
|
|
||
|
u8 m_reg[256] = {0}; // register pool
|
||
|
};
|
||
|
|
||
|
// SCC core
|
||
|
class k051649_scc_core : public scc_core
|
||
|
{
|
||
|
public:
|
||
|
// accessors
|
||
|
virtual u8 scc_r(bool is_sccplus, u8 address) override;
|
||
|
virtual void scc_w(bool is_sccplus, u8 address, u8 data) override;
|
||
|
};
|
||
|
|
||
|
class k052539_scc_core : public k051649_scc_core
|
||
|
{
|
||
|
public:
|
||
|
// accessors
|
||
|
virtual u8 scc_r(bool is_sccplus, u8 address) override;
|
||
|
virtual void scc_w(bool is_sccplus, u8 address, u8 data) override;
|
||
|
};
|
||
|
|
||
|
#endif
|