openMSX
YMF278.hh
Go to the documentation of this file.
1#ifndef YMF278_HH
2#define YMF278_HH
3
5
6#include "EmuTime.hh"
7#include "Rom.hh"
8#include "SimpleDebuggable.hh"
9#include "TrackedRam.hh"
10#include "serialize_meta.hh"
11
13
14#include <array>
15#include <cstdint>
16#include <functional>
17#include <span>
18#include <string>
19
20namespace openmsx {
21
22class DeviceConfig;
23
24class YMF278 final : public ResampledSoundDevice
25{
26public:
27 static constexpr auto k128 = size_t(128 * 1024); // 128kB
28 using Block128 = optional_fixed_span<const uint8_t, k128>; // a 128kB read-only memory block
29
30 using SetupMemPtrFunc = std::function<void(
31 bool /*mode0*/,
32 std::span<const uint8_t> /*rom*/,
33 std::span<const uint8_t> /*ram*/,
34 std::span<YMF278::Block128, 32> /*memPtrs*/)>;
35
36public:
37 YMF278(const std::string& name, size_t ramSize, const DeviceConfig& config,
38 SetupMemPtrFunc setupMemPtrs_);
39 ~YMF278();
40 void clearRam();
41 void reset(EmuTime::param time);
42 void writeReg(uint8_t reg, uint8_t data, EmuTime::param time);
43 [[nodiscard]] uint8_t readReg(uint8_t reg);
44 [[nodiscard]] uint8_t peekReg(uint8_t reg) const;
45
46 [[nodiscard]] uint8_t readMem(unsigned address) const;
47 void writeMem(unsigned address, uint8_t value);
48
49 void setMixLevel(uint8_t x, EmuTime::param time);
50
52
53 template<typename Archive>
54 void serialize(Archive& ar, unsigned version);
55
56private:
57 class Slot {
58 public:
59 Slot();
60 void reset();
61 [[nodiscard]] uint8_t compute_rate(int val) const;
62 [[nodiscard]] uint8_t compute_decay_rate(int val) const;
63 [[nodiscard]] unsigned decay_rate(int num, int sample_rate);
64 void envelope_next(int sample_rate);
65 [[nodiscard]] int16_t compute_vib() const;
66 [[nodiscard]] uint16_t compute_am() const;
67
68 template<typename Archive>
69 void serialize(Archive& ar, unsigned version);
70
71 uint32_t startAddr;
72 uint16_t loopAddr;
73 uint16_t endAddr; // Note: stored in 2s complement (0x0000 = 0, 0x0001 = -65536, 0xffff = -1)
74 uint32_t step; // fixed-point frequency step
75 // invariant: step == calcStep(OCT, FN)
76 uint32_t stepPtr; // fixed-point pointer into the sample
77 uint16_t pos;
78
79 int16_t env_vol;
80
81 uint32_t lfo_cnt;
82
83 int16_t DL;
84 uint16_t wave; // wave table number
85 uint16_t FN; // f-number TODO store 'FN | 1024'?
86 int8_t OCT; // octave [-8..+7]
87 bool PRVB; // pseudo-reverb
88 uint8_t TLdest; // destination total level
89 uint8_t TL; // total level (goes towards TLdest)
90 uint8_t pan; // pan-pot 0..15
91 bool keyon; // slot keyed on
92 bool DAMP;
93 uint8_t lfo; // LFO speed 0..7
94 uint8_t vib; // vibrato 0..7
95 uint8_t AM; // AM level 0..7
96 uint8_t AR; // 0..15
97 uint8_t D1R; // 0..15
98 uint8_t D2R; // 0..15
99 uint8_t RC; // rate correction 0..15
100 uint8_t RR; // 0..15
101
102 uint8_t bits; // width of the samples
103
104 uint8_t state; // envelope generator state
105 bool lfo_active;
106 };
107
108 // SoundDevice
109 void generateChannels(std::span<float*> bufs, unsigned num) override;
110
111 void writeRegDirect(uint8_t reg, uint8_t data, EmuTime::param time);
112 [[nodiscard]] unsigned getRamAddress(unsigned addr) const;
113 [[nodiscard]] int16_t getSample(const Slot& slot, uint16_t pos) const;
114 [[nodiscard]] static uint16_t nextPos(const Slot& slot, uint16_t pos, uint16_t increment);
115 void advance();
116 [[nodiscard]] bool anyActive();
117 void keyOnHelper(Slot& slot) const;
118
119 MSXMotherBoard& motherBoard;
120
121 struct DebugRegisters final : SimpleDebuggable {
122 DebugRegisters(MSXMotherBoard& motherBoard, const std::string& name);
123 [[nodiscard]] uint8_t read(unsigned address) override;
124 void write(unsigned address, uint8_t value, EmuTime::param time) override;
125 } debugRegisters;
126
127 struct DebugMemory final : SimpleDebuggable {
128 DebugMemory(MSXMotherBoard& motherBoard, const std::string& name);
129 [[nodiscard]] uint8_t read(unsigned address) override;
130 void write(unsigned address, uint8_t value) override;
131 } debugMemory;
132
133 std::array<Slot, 24> slots;
134
136 unsigned eg_cnt;
137
138 int memAdr;
139
140 Rom rom;
141 TrackedRam ram;
142
143 std::array<uint8_t, 256> regs;
144
145 // To speed-up memory access we divide the 4MB address-space in 32 blocks of 128kB.
146 // For each block we point to the corresponding region inside 'rom' or 'ram',
147 // or 'nullBlock' means this region is unmapped.
148 // Note: we can only _read_ via these pointers, not write.
149 std::array<Block128, 32> memPtrs;
150
151 // callback-function that fills in the above array
152 SetupMemPtrFunc setupMemPtrs;
153};
154SERIALIZE_CLASS_VERSION(YMF278::Slot, 6);
156
157} // namespace openmsx
158
159#endif
uint8_t readReg(uint8_t reg)
Definition YMF278.cc:760
static constexpr auto k128
Definition YMF278.hh:27
void writeReg(uint8_t reg, uint8_t data, EmuTime::param time)
Definition YMF278.cc:582
void setMixLevel(uint8_t x, EmuTime::param time)
Definition YMF278.cc:492
void reset(EmuTime::param time)
Definition YMF278.cc:830
void writeMem(unsigned address, uint8_t value)
Definition YMF278.cc:883
uint8_t readMem(unsigned address) const
Definition YMF278.cc:873
void clearRam()
Definition YMF278.cc:825
void setupMemoryPointers()
Definition YMF278.cc:867
std::function< void(bool, std::span< const uint8_t >, std::span< const uint8_t >, std::span< YMF278::Block128, 32 >)> SetupMemPtrFunc
Definition YMF278.hh:34
void serialize(Archive &ar, unsigned version)
Definition YMF278.cc:1000
uint8_t peekReg(uint8_t reg) const
Definition YMF278.cc:775
This file implemented 3 utility functions:
Definition Autofire.cc:11
void serialize(Archive &ar, T &t, unsigned version)
#define SERIALIZE_CLASS_VERSION(CLASS, VERSION)