24 static const int R07_RESET = 0x01;
25 static const int R07_SP_OFF = 0x08;
26 static const int R07_REPEAT = 0x10;
27 static const int R07_MEMORY_DATA = 0x20;
28 static const int R07_REC = 0x40;
29 static const int R07_START = 0x80;
30 static const int R07_MODE = 0xE0;
33 static const int R08_ROM = 0x01;
34 static const int R08_64K = 0x02;
35 static const int R08_DA_AD = 0x04;
36 static const int R08_SAMPL = 0x08;
37 static const int R08_NOTE_SET = 0x40;
38 static const int R08_CSM = 0x80;
40 static const int DMAX = 0x6000;
41 static const int DMIN = 0x7F;
42 static const int DDEF = 0x7F;
44 static const int STEP_BITS = 16;
45 static const int STEP_MASK = (1 << STEP_BITS) -1;
49 const std::string& name,
unsigned sampleRam)
53 config, name +
" RAM",
"Y8950 sample RAM", sampleRam))
54 , clock(config.getMotherBoard().getCurrentTime())
66 memset(&(*ram)[0], 0xFF, ram->getSize());
78 addrMask = (1 << 18) - 1;
91 bool Y8950Adpcm::isPlaying()
const
93 return (reg7 & 0xC0) == 0x80;
97 return !isPlaying() || (reg7 & R07_SP_OFF);
100 void Y8950Adpcm::restart(PlayData& pd)
102 pd.memPntr = startAddr;
103 pd.nowStep = (1 << STEP_BITS) - delta;
116 for (
unsigned i = 0; isPlaying() && (i < ticks); ++i) {
123 void Y8950Adpcm::schedule()
126 if ((stopAddr > startAddr) && (delta != 0)) {
130 if (reg7 & R07_MEMORY_DATA) {
133 uint64_t samples = stopAddr - emu.memPntr + 1;
134 uint64_t length = (samples << STEP_BITS) +
135 ((1 << STEP_BITS) - emu.nowStep) +
137 stop += unsigned(length / delta);
152 if (isPlaying() && (reg7 & R07_REPEAT)) {
163 if (reg7 & R07_RESET) {
166 if (reg7 & R07_START) {
171 if (reg7 & R07_MEMORY_DATA) {
173 emu.memPntr = startAddr;
174 aud.memPntr = startAddr;
176 if ((reg7 & 0xA0) == 0x20) {
192 romBank = data & R08_ROM;
193 addrMask = data & R08_64K ? (1 << 16) - 1 : (1 << 18) - 1;
197 startAddr = (startAddr & 0x7F807) | (data << 3);
200 startAddr = (startAddr & 0x007FF) | (data << 11);
204 stopAddr = (stopAddr & 0x7F807) | (data << 3);
211 stopAddr = (stopAddr & 0x007FF) | (data << 11);
223 delta = (delta & 0xFF00) | data;
224 volumeWStep = (volume * delta) >> STEP_BITS;
231 delta = (delta & 0x00FF) | (data << 8);
232 volumeWStep = (volume * delta) >> STEP_BITS;
241 volumeWStep = (volume * delta) >> STEP_BITS;
255 void Y8950Adpcm::writeData(
byte data)
258 if ((reg7 & R07_MODE) == 0x60) {
260 assert(!isPlaying());
262 emu.memPntr = startAddr;
265 if (emu.memPntr <= stopAddr) {
266 writeMemory(emu.memPntr, data);
288 }
else if ((reg7 & R07_MODE) == 0x80) {
300 byte result = (rg == 0x0F)
321 return (emu.output >> 8) & 0xFF;
323 return emu.output >> 16;
347 if (((reg7 & R07_MODE & ~R07_REC) == R07_MEMORY_DATA) ||
348 ((reg7 & R07_MODE) == 0)){
354 byte Y8950Adpcm::readData()
356 if ((reg7 & R07_MODE) == R07_MEMORY_DATA) {
358 assert(!isPlaying());
360 emu.memPntr = startAddr;
363 byte result = peekData();
364 if ((reg7 & R07_MODE) == R07_MEMORY_DATA) {
365 assert(!isPlaying());
370 }
else if (emu.memPntr > stopAddr) {
393 byte Y8950Adpcm::peekData()
const
395 if ((reg7 & R07_MODE) == R07_MEMORY_DATA) {
397 assert(!isPlaying());
400 }
else if (emu.memPntr > stopAddr) {
403 return readMemory(emu.memPntr);
410 void Y8950Adpcm::writeMemory(
unsigned memPntr,
byte value)
412 unsigned addr = (memPntr / 2) & addrMask;
413 if ((addr < ram->getSize()) && !romBank) {
414 (*ram)[addr] = value;
417 byte Y8950Adpcm::readMemory(
unsigned memPntr)
const
419 unsigned addr = (memPntr / 2) & addrMask;
420 if (romBank || (addr >= ram->getSize())) {
430 if (!isPlaying())
return 0;
432 return (reg7 & R07_SP_OFF) ? 0 : output;
438 static const int F1[16] = { 1, 3, 5, 7, 9, 11, 13, 15,
439 -1, -3, -5, -7, -9, -11, -13, -15 };
440 static const int F2[16] = { 57, 57, 57, 57, 77, 102, 128, 153,
441 57, 57, 57, 57, 77, 102, 128, 153 };
445 PlayData& pd = doEmu ? emu : aud;
447 if (pd.nowStep & ~STEP_MASK) {
448 pd.nowStep &= STEP_MASK;
450 if (!(pd.memPntr & 1)) {
452 if (reg7 & R07_MEMORY_DATA) {
453 pd.adpcm_data = readMemory(pd.memPntr);
455 pd.adpcm_data = reg15;
461 val = pd.adpcm_data >> 4;
464 val = pd.adpcm_data & 0x0F;
466 int prevOut = pd.out;
468 pd.diff = Math::clip<DMIN, DMAX>((pd.diff * F2[val]) / 64);
470 int prevLeveling = pd.nextLeveling;
471 pd.nextLeveling = (prevOut + pd.out) / 2;
472 int deltaLeveling = pd.nextLeveling - prevLeveling;
473 pd.sampleStep = deltaLeveling * volumeWStep;
474 int tmp = deltaLeveling * ((volume * pd.nowStep) >> STEP_BITS);
475 pd.output = prevLeveling * volume + tmp;
478 if ((reg7 & R07_MEMORY_DATA) &&
479 (pd.memPntr > stopAddr)) {
489 if (reg7 & R07_REPEAT) {
499 pd.output += pd.sampleStep;
501 return pd.output >> 12;
511 template<
typename Archive>
514 ar.template serializeBase<Schedulable>(*this);
515 ar.serialize(
"ram", *ram);
516 ar.serialize(
"startAddr", startAddr);
517 ar.serialize(
"stopAddr", stopAddr);
518 ar.serialize(
"addrMask", addrMask);
519 ar.serialize(
"volume", volume);
520 ar.serialize(
"volumeWStep", volumeWStep);
521 ar.serialize(
"readDelay", readDelay);
522 ar.serialize(
"delta", delta);
523 ar.serialize(
"reg7", reg7);
524 ar.serialize(
"reg15", reg15);
525 ar.serialize(
"romBank", romBank);
527 ar.serialize(
"memPntr", emu.memPntr);
528 ar.serialize(
"nowStep", emu.nowStep);
529 ar.serialize(
"out", emu.out);
530 ar.serialize(
"output", emu.output);
531 ar.serialize(
"diff", emu.diff);
532 ar.serialize(
"nextLeveling", emu.nextLeveling);
533 ar.serialize(
"sampleStep", emu.sampleStep);
534 ar.serialize(
"adpcm_data", emu.adpcm_data);
541 if (ar.versionBelow(version, 2)) {
551 ar.serialize(
"clock", clock);