23 static const int EG_SH = 16;
24 static const unsigned EG_TIMER_OVERFLOW = 1 << EG_SH;
27 static const int ENV_BITS = 10;
28 static const int ENV_LEN = 1 << ENV_BITS;
29 static const float ENV_STEP = 128.0f / ENV_LEN;
30 static const int MAX_ATT_INDEX = (1 << (ENV_BITS - 1)) - 1;
31 static const int MIN_ATT_INDEX = 0;
34 static const int EG_ATT = 4;
35 static const int EG_DEC = 3;
36 static const int EG_SUS = 2;
37 static const int EG_REL = 1;
38 static const int EG_OFF = 0;
40 static const int EG_REV = 5;
41 static const int EG_DMP = 6;
44 static const int pan_left[16] = {
45 0, 8, 16, 24, 32, 40, 48, 256, 256, 0, 0, 0, 0, 0, 0, 0
47 static const int pan_right[16] = {
48 0, 0, 0, 0, 0, 0, 0, 0, 256, 256, 48, 40, 32, 24, 16, 8
52 static const int mix_level[8] = {
53 8, 16, 24, 32, 40, 48, 56, 256
58 #define SC(db) unsigned((db) * (2.0f / ENV_STEP)) 59 static const unsigned dl_tab[16] = {
65 static const byte RATE_STEPS = 8;
66 static const byte eg_inc[15 * RATE_STEPS] = {
68 0, 1, 0, 1, 0, 1, 0, 1,
69 0, 1, 0, 1, 1, 1, 0, 1,
70 0, 1, 1, 1, 0, 1, 1, 1,
71 0, 1, 1, 1, 1, 1, 1, 1,
73 1, 1, 1, 1, 1, 1, 1, 1,
74 1, 1, 1, 2, 1, 1, 1, 2,
75 1, 2, 1, 2, 1, 2, 1, 2,
76 1, 2, 2, 2, 1, 2, 2, 2,
78 2, 2, 2, 2, 2, 2, 2, 2,
79 2, 2, 2, 4, 2, 2, 2, 4,
80 2, 4, 2, 4, 2, 4, 2, 4,
81 2, 4, 4, 4, 2, 4, 4, 4,
83 4, 4, 4, 4, 4, 4, 4, 4,
84 8, 8, 8, 8, 8, 8, 8, 8,
85 0, 0, 0, 0, 0, 0, 0, 0,
88 #define O(a) ((a) * RATE_STEPS) 89 static const byte eg_rate_select[64] = {
90 O( 0),
O( 1),
O( 2),
O( 3),
91 O( 0),
O( 1),
O( 2),
O( 3),
92 O( 0),
O( 1),
O( 2),
O( 3),
93 O( 0),
O( 1),
O( 2),
O( 3),
94 O( 0),
O( 1),
O( 2),
O( 3),
95 O( 0),
O( 1),
O( 2),
O( 3),
96 O( 0),
O( 1),
O( 2),
O( 3),
97 O( 0),
O( 1),
O( 2),
O( 3),
98 O( 0),
O( 1),
O( 2),
O( 3),
99 O( 0),
O( 1),
O( 2),
O( 3),
100 O( 0),
O( 1),
O( 2),
O( 3),
101 O( 0),
O( 1),
O( 2),
O( 3),
102 O( 0),
O( 1),
O( 2),
O( 3),
103 O( 4),
O( 5),
O( 6),
O( 7),
104 O( 8),
O( 9),
O(10),
O(11),
105 O(12),
O(12),
O(12),
O(12),
113 static const byte eg_rate_shift[64] = {
114 O(12),
O(12),
O(12),
O(12),
115 O(11),
O(11),
O(11),
O(11),
116 O(10),
O(10),
O(10),
O(10),
117 O( 9),
O( 9),
O( 9),
O( 9),
118 O( 8),
O( 8),
O( 8),
O( 8),
119 O( 7),
O( 7),
O( 7),
O( 7),
120 O( 6),
O( 6),
O( 6),
O( 6),
121 O( 5),
O( 5),
O( 5),
O( 5),
122 O( 4),
O( 4),
O( 4),
O( 4),
123 O( 3),
O( 3),
O( 3),
O( 3),
124 O( 2),
O( 2),
O( 2),
O( 2),
125 O( 1),
O( 1),
O( 1),
O( 1),
126 O( 0),
O( 0),
O( 0),
O( 0),
127 O( 0),
O( 0),
O( 0),
O( 0),
128 O( 0),
O( 0),
O( 0),
O( 0),
129 O( 0),
O( 0),
O( 0),
O( 0),
136 #define O(a) int((EG_TIMER_OVERFLOW / (a)) / 6) 137 static const int lfo_period[8] = {
138 O(0.168f),
O(2.019f),
O(3.196f),
O(4.206f),
139 O(5.215f),
O(5.888f),
O(6.224f),
O(7.066f)
144 #define O(a) int((a) * 65536) 145 static const int vib_depth[8] = {
146 O( 0.0f ),
O( 3.378f),
O( 5.065f),
O( 6.750f),
147 O(10.114f),
O(20.170f),
O(40.106f),
O(79.307f)
152 #define SC(db) int((db) * (2.0f / ENV_STEP)) 153 static const int am_depth[8] = {
154 SC(0.0f ),
SC(1.781f),
SC(2.906f),
SC( 3.656f),
155 SC(4.406f),
SC(5.906f),
SC(7.406f),
SC(11.91f )
167 static inline int sign_extend_4(
int x)
178 static inline unsigned calcStep(
unsigned oct,
unsigned fn,
unsigned vib = 0)
181 unsigned t = (fn + 1024 + vib) << oct;
185 void YMF278::Slot::reset()
187 wave = FN = OCT = PRVB = LD = TL = pan = lfo = vib = AM = 0;
188 AR = D1R = DL = D2R = RC = RR = 0;
190 step = calcStep(OCT, FN);
191 bits = startaddr = loopaddr = endaddr = 0;
192 env_vol = MAX_ATT_INDEX;
195 lfo_cnt = lfo_step = 0;
196 lfo_max = lfo_period[0];
202 pos = sample1 = sample2 = 0;
205 int YMF278::Slot::compute_rate(
int val)
const 209 }
else if (val == 15) {
215 int oct = sign_extend_4(OCT);
216 res = (oct + RC) * 2 + (FN & 0x200 ? 1 : 0) + val * 4;
222 }
else if (res > 63) {
228 int YMF278::Slot::compute_vib()
const 230 return (((lfo_step << 8) / lfo_max) * vib_depth[
int(vib)]) >> 24;
234 int YMF278::Slot::compute_am()
const 236 if (lfo_active && AM) {
237 return (((lfo_step << 8) / lfo_max) * am_depth[
int(AM)]) >> 12;
243 void YMF278::Slot::set_lfo(
int newlfo)
245 lfo_step = (((lfo_step << 8) / lfo_max) * newlfo) >> 8;
246 lfo_cnt = (((lfo_cnt << 8) / lfo_max) * newlfo) >> 8;
249 lfo_max = lfo_period[int(lfo)];
253 void YMF278::advance()
256 for (
auto& op : slots) {
259 if (op.lfo_cnt < op.lfo_max) {
261 }
else if (op.lfo_cnt < (op.lfo_max * 3)) {
265 if (op.lfo_cnt == (op.lfo_max * 4)) {
274 byte rate = op.compute_rate(op.AR);
278 byte shift = eg_rate_shift[rate];
279 if (!(eg_cnt & ((1 << shift) -1))) {
280 byte select = eg_rate_select[rate];
281 op.env_vol += (~op.env_vol * eg_inc[select + ((eg_cnt >> shift) & 7)]) >> 3;
282 if (op.env_vol <= MIN_ATT_INDEX) {
283 op.env_vol = MIN_ATT_INDEX;
294 byte rate = op.compute_rate(op.D1R);
298 byte shift = eg_rate_shift[rate];
299 if (!(eg_cnt & ((1 << shift) -1))) {
300 byte select = eg_rate_select[rate];
301 op.env_vol += eg_inc[select + ((eg_cnt >> shift) & 7)];
303 if ((
unsigned(op.env_vol) > dl_tab[6]) && op.PRVB) {
306 if (op.env_vol >= op.DL) {
314 byte rate = op.compute_rate(op.D2R);
318 byte shift = eg_rate_shift[rate];
319 if (!(eg_cnt & ((1 << shift) -1))) {
320 byte select = eg_rate_select[rate];
321 op.env_vol += eg_inc[select + ((eg_cnt >> shift) & 7)];
323 if ((
unsigned(op.env_vol) > dl_tab[6]) && op.PRVB) {
326 if (op.env_vol >= MAX_ATT_INDEX) {
327 op.env_vol = MAX_ATT_INDEX;
335 byte rate = op.compute_rate(op.RR);
339 byte shift = eg_rate_shift[rate];
340 if (!(eg_cnt & ((1 << shift) -1))) {
341 byte select = eg_rate_select[rate];
342 op.env_vol += eg_inc[select + ((eg_cnt >> shift) & 7)];
344 if ((
unsigned(op.env_vol) > dl_tab[6]) && op.PRVB) {
347 if (op.env_vol >= MAX_ATT_INDEX) {
348 op.env_vol = MAX_ATT_INDEX;
357 byte rate = op.compute_rate(5);
361 byte shift = eg_rate_shift[rate];
362 if (!(eg_cnt & ((1 << shift) - 1))) {
363 byte select = eg_rate_select[rate];
364 op.env_vol += eg_inc[select + ((eg_cnt >> shift) & 7)];
366 if (op.env_vol >= MAX_ATT_INDEX) {
367 op.env_vol = MAX_ATT_INDEX;
376 byte shift = eg_rate_shift[rate];
377 if (!(eg_cnt & ((1 << shift) - 1))) {
378 byte select = eg_rate_select[rate];
379 op.env_vol += eg_inc[select + ((eg_cnt >> shift) & 7)];
381 if (op.env_vol >= MAX_ATT_INDEX) {
382 op.env_vol = MAX_ATT_INDEX;
398 int16_t YMF278::getSample(Slot& op)
407 sample =
readMem(op.startaddr + op.pos) << 8;
412 unsigned addr = op.startaddr + ((op.pos / 2) * 3);
414 sample =
readMem(addr + 2) << 8 |
415 ((
readMem(addr + 1) << 4) & 0xF0);
417 sample =
readMem(addr + 0) << 8 |
424 unsigned addr = op.startaddr + (op.pos * 2);
425 sample = (
readMem(addr + 0) << 8) |
436 bool YMF278::anyActive()
438 for (
auto& op : slots) {
439 if (op.active)
return true;
444 void YMF278::generateChannels(
int** bufs,
unsigned num)
449 for (
int i = 0; i < 24; ++i) {
455 int vl = mix_level[pcm_l];
456 int vr = mix_level[pcm_r];
457 for (
unsigned j = 0; j < num; ++j) {
458 for (
int i = 0; i < 24; ++i) {
466 int16_t sample = (sl.sample1 * (0x10000 - sl.stepptr) +
467 sl.sample2 * sl.stepptr) >> 16;
468 int vol = sl.TL + (sl.env_vol >> 2) + sl.compute_am();
470 int volLeft = vol + pan_left [int(sl.pan)] + vl;
471 int volRight = vol + pan_right[int(sl.pan)] + vr;
476 bufs[i][2 * j + 0] += (sample * volume[volLeft] ) >> 14;
477 bufs[i][2 * j + 1] += (sample * volume[volRight]) >> 14;
479 unsigned step = (sl.lfo_active && sl.vib)
480 ? calcStep(sl.OCT, sl.FN, sl.compute_vib())
484 while (sl.stepptr >= 0x10000) {
485 sl.stepptr -= 0x10000;
486 sl.sample1 = sl.sample2;
488 if (sl.pos >= sl.endaddr) {
489 sl.pos = sl.loopaddr;
491 sl.sample2 = getSample(sl);
498 void YMF278::keyOnHelper(YMF278::Slot& slot)
505 slot.sample1 = getSample(slot);
507 slot.sample2 = getSample(slot);
513 writeRegDirect(reg, data, time);
516 void YMF278::writeRegDirect(
byte reg,
byte data, EmuTime::param time)
519 if (reg >= 0x08 && reg <= 0xF7) {
520 int snum = (reg - 8) % 24;
521 auto& slot = slots[snum];
522 switch ((reg - 8) / 24) {
524 slot.wave = (slot.wave & 0x100) | data;
525 int wavetblhdr = (regs[2] >> 2) & 0x7;
526 int base = (slot.wave < 384 || !wavetblhdr) ?
528 (wavetblhdr * 0x80000 + ((slot.wave - 384) * 12));
530 for (
int i = 0; i < 12; ++i) {
535 slot.bits = (buf[0] & 0xC0) >> 6;
536 slot.startaddr = buf[2] | (buf[1] << 8) |
537 ((buf[0] & 0x3F) << 16);
538 slot.loopaddr = buf[4] + (buf[3] << 8);
539 slot.endaddr = (((buf[6] + (buf[5] << 8)) ^ 0xFFFF) + 1);
540 for (
int i = 7; i < 12; ++i) {
544 writeRegDirect(8 + snum + (i - 2) * 24, buf[i], time);
546 if ((regs[reg + 0x60] & 0x080)) {
552 slot.wave = (slot.wave & 0xFF) | ((data & 0x1) << 8);
553 slot.FN = (slot.FN & 0x380) | (data >> 1);
554 slot.step = calcStep(slot.OCT, slot.FN);
558 slot.FN = (slot.FN & 0x07F) | ((data & 0x07) << 7);
559 slot.PRVB = ((data & 0x08) >> 3);
560 slot.OCT = ((data & 0xF0) >> 4);
561 slot.step = calcStep(slot.OCT, slot.FN);
566 slot.LD = data & 0x1;
582 slot.pan = data & 0x0F;
587 slot.lfo_active =
false;
589 slot.lfo_max = lfo_period[int(slot.vib)];
593 slot.lfo_active =
true;
598 if (slot.active && (slot.state != EG_REV) ) {
610 if (!slot.active || !(regs[reg] & 0x080)) {
621 slot.vib = data & 0x7;
622 slot.set_lfo((data >> 3) & 0x7);
626 slot.D1R = data & 0xF;
629 slot.DL = dl_tab[data >> 4];
630 slot.D2R = data & 0xF;
634 slot.RR = data & 0xF;
637 slot.AM = data & 0x7;
672 memadr = (regs[3] << 16) | (regs[4] << 8) |
data;
689 fm_r = (data >> 3) & 0x7;
694 pcm_r = (data >> 3) & 0x7;
722 result = (regs[2] & 0x1F) | 0x20;
745 , motherBoard(config.getMotherBoard())
746 , debugRegisters(motherBoard,
getName())
747 , debugMemory (motherBoard,
getName())
748 , rom(
getName() +
" ROM",
"rom", config)
749 , ram(config,
getName() +
" RAM",
"YMF278 sample RAM",
752 if (rom.
getSize() != 0x200000) {
754 "Wrong ROM for MoonSound (YMF278). The ROM (usually " 755 "called yrw801.rom) should have a size of exactly 2MB.");
757 if ((ramSize_ != 0) &&
762 (ramSize_ != 1024) &&
763 (ramSize_ != 2048)) {
765 "Wrong sampleram size for MoonSound (YMF278). " 766 "Got " << ramSize_ <<
", but must be one of " 767 "0, 128, 256, 512, 640, 1024 or 2048.");
778 for (
int i = 0; i < 256; ++i) {
779 volume[i] = int(32768.0 *
exp2((-0.375 / 6) * i));
781 for (
int i = 256; i < 256 * 4; ++i) {
802 for (
auto& op : slots) {
806 for (
int i = 255; i >= 0; --i) {
807 writeRegDirect(i, 0, time);
810 fm_l = fm_r = pcm_l = pcm_r = 0;
859 unsigned YMF278::getRamAddress(
unsigned addr)
const 865 if ((0x180000 <= addr) && (addr <= 0x1FFFFF)) {
867 switch (addr & 0x060000) {
872 if (ram.
getSize() == 256 * 1024) {
893 if (ram.
getSize() == 640 * 1024) {
898 if (addr > 0x080000) {
909 if (address < 0x200000) {
913 unsigned ramAddr = getRamAddress(address);
926 if (address < 0x200000) {
929 unsigned ramAddr = getRamAddress(address);
931 ram.
write(ramAddr, value);
943 template<
typename Archive>
947 ar.serialize(
"startaddr", startaddr);
948 ar.serialize(
"loopaddr", loopaddr);
949 ar.serialize(
"endaddr", endaddr);
950 ar.serialize(
"stepptr", stepptr);
951 ar.serialize(
"pos", pos);
952 ar.serialize(
"sample1", sample1);
953 ar.serialize(
"sample2", sample2);
954 ar.serialize(
"env_vol", env_vol);
955 ar.serialize(
"lfo_cnt", lfo_cnt);
956 ar.serialize(
"lfo_step", lfo_step);
957 ar.serialize(
"lfo_max", lfo_max);
958 ar.serialize(
"DL", DL);
959 ar.serialize(
"wave", wave);
960 ar.serialize(
"FN", FN);
961 if (ar.versionAtLeast(version, 2)) {
962 ar.serialize(
"OCT", OCT);
963 ar.serialize(
"PRVB", PRVB);
964 ar.serialize(
"LD", LD);
965 ar.serialize(
"TL", TL);
966 ar.serialize(
"pan", pan);
967 ar.serialize(
"lfo", lfo);
968 ar.serialize(
"vib", vib);
969 ar.serialize(
"AM", AM);
970 ar.serialize(
"AR", AR);
971 ar.serialize(
"D1R", D1R);
972 ar.serialize(
"D2R", D2R);
973 ar.serialize(
"RC", RC);
974 ar.serialize(
"RR", RR);
976 ar.serializeChar(
"OCT", OCT);
977 ar.serializeChar(
"PRVB", PRVB);
978 ar.serializeChar(
"LD", LD);
979 ar.serializeChar(
"TL", TL);
980 ar.serializeChar(
"pan", pan);
981 ar.serializeChar(
"lfo", lfo);
982 ar.serializeChar(
"vib", vib);
983 ar.serializeChar(
"AM", AM);
984 ar.serializeChar(
"AR", AR);
985 ar.serializeChar(
"D1R", D1R);
986 ar.serializeChar(
"D2R", D2R);
987 ar.serializeChar(
"RC", RC);
988 ar.serializeChar(
"RR", RR);
990 ar.serialize(
"bits", bits);
991 ar.serialize(
"active", active);
992 ar.serialize(
"state", state);
993 ar.serialize(
"lfo_active", lfo_active);
997 step = calcStep(OCT, FN);
1016 template<
typename Archive>
1019 ar.serialize(
"slots", slots);
1020 ar.serialize(
"eg_cnt", eg_cnt);
1021 if (ar.versionAtLeast(version, 4)) {
1022 ar.serialize(
"ram", ram);
1026 ar.serialize_blob(
"registers", regs,
sizeof(regs));
1027 if (ar.versionAtLeast(version, 3)) {
1028 ar.serialize(
"memadr", memadr);
1030 assert(ar.isLoader());
1035 memadr = (regs[3] << 16) | (regs[4] << 8) | regs[5];
1039 static const byte rewriteRegs[] = {
1043 if (ar.isLoader()) {
1045 for (
auto r : rewriteRegs) {
1046 writeRegDirect(r, regs[r], time);
1055 YMF278::DebugRegisters::DebugRegisters(
MSXMotherBoard& motherBoard_,
1056 const std::string& name_)
1058 "OPL4 registers", 0x100)
1062 byte YMF278::DebugRegisters::read(
unsigned address)
1065 return ymf278.peekReg(address);
1068 void YMF278::DebugRegisters::write(
unsigned address,
byte value, EmuTime::param time)
1071 ymf278.writeReg(address, value, time);
1078 const std::string& name_)
1080 "OPL4 memory (includes both ROM and RAM)", 0x400000)
1084 byte YMF278::DebugMemory::read(
unsigned address)
1087 return ymf278.readMem(address);
1090 void YMF278::DebugMemory::write(
unsigned address,
byte value)
1093 ymf278.writeMem(address, value);
const std::string & getName() const
Get the unique name that identifies this sound device.
byte * getWriteBackdoor()
void unregisterSound()
Unregisters this sound device with the Mixer.
uint8_t byte
8 bit unsigned integer
void writeReg(byte reg, byte data, EmuTime::param time)
void writeMem(unsigned address, byte value)
vecN< N, T > max(const vecN< N, T > &x, const vecN< N, T > &y)
void updateStream(EmuTime::param time)
void serialize(Archive &ar, unsigned version)
byte readMem(unsigned address) const
void setInputRate(unsigned sampleRate)
Thanks to enen for testing this on a real cartridge:
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
YMF278(const std::string &name, int ramSize, const DeviceConfig &config)
EmuTime::param getCurrentTime()
Convenience method: This is the same as getScheduler().getCurrentTime().
#define OUTER(type, member)
byte peekReg(byte reg) const
void serialize(Archive &ar, T &t, unsigned version)
void reset(EmuTime::param time)
CONSTEXPR double exp2(double x)
void write(unsigned addr, byte value)
void registerSound(const DeviceConfig &config)
Registers this sound device with the Mixer.