furnace/src/engine/platform/sound/x1_010/x1_010.hpp
tildearrow c0e9b48b5b per-channel oscilloscope, part 5
SAA1099 (SAASound and MAME), Lynx, MMC5, N163, PC Engine, PC Speaker,
PET, QSound, WonderSwan, VERA, VIC-20, VRC6 and X1-010!
2022-05-01 02:40:03 -05:00

134 lines
2.4 KiB
C++

/*
License: BSD-3-Clause
see https://github.com/cam900/vgsound_emu/LICENSE for more details
Copyright holders: cam900
Seta/Allumer X1-010 Emulation core
See x1_010.cpp for more info.
*/
#include <algorithm>
#include <memory>
#ifndef _VGSOUND_EMU_X1_010_HPP
#define _VGSOUND_EMU_X1_010_HPP
#pragma once
namespace x1_010
{
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef signed char s8;
typedef signed int s32;
template<typename T> T bitfield(T in, u8 pos, u8 len = 1)
{
return (in >> pos) & (len ? (T(1 << len) - 1) : 1);
}
}
using namespace x1_010;
class x1_010_mem_intf
{
public:
virtual u8 read_byte(u32 address) { return 0; }
};
using namespace x1_010;
class x1_010_core
{
friend class x1_010_mem_intf;
public:
// constructor
x1_010_core(x1_010_mem_intf &intf)
: m_voice{*this,*this,*this,*this,
*this,*this,*this,*this,
*this,*this,*this,*this,
*this,*this,*this,*this}
, m_intf(intf)
{
m_envelope = std::make_unique<u8[]>(0x1000);
m_wave = std::make_unique<u8[]>(0x1000);
std::fill_n(&m_envelope[0], 0x1000, 0);
std::fill_n(&m_wave[0], 0x1000, 0);
}
// register accessor
u8 ram_r(u16 offset);
void ram_w(u16 offset, u8 data);
// getters
s32 output(u8 channel) { return m_out[channel & 1]; }
s32 chan_out(u8 channel) { return (m_voice[channel].data * (m_voice[channel].vol_out[0]+m_voice[channel].vol_out[1]))<<2; }
// internal state
void reset();
void tick();
private:
// 16 voices in chip
struct voice_t
{
// constructor
voice_t(x1_010_core &host) : m_host(host) {}
// internal state
void reset();
void tick();
// register accessor
u8 reg_r(u8 offset);
void reg_w(u8 offset, u8 data);
// registers
x1_010_core &m_host;
struct flag_t
{
u8 div : 1;
u8 env_oneshot : 1;
u8 wavetable : 1;
u8 keyon : 1;
void reset()
{
div = 0;
env_oneshot = 0;
wavetable = 0;
keyon = 0;
}
flag_t()
: div(0)
, env_oneshot(0)
, wavetable(0)
, keyon(0)
{ }
};
flag_t flag;
u8 vol_wave = 0;
u16 freq = 0;
u8 start_envfreq = 0;
u8 end_envshape = 0;
// internal registers
u32 acc = 0;
u32 env_acc = 0;
s8 data = 0;
u8 vol_out[2] = {0};
};
voice_t m_voice[16];
// RAM
std::unique_ptr<u8[]> m_envelope = nullptr;
std::unique_ptr<u8[]> m_wave = nullptr;
// output data
s32 m_out[2] = {0};
x1_010_mem_intf &m_intf;
};
#endif