39 constexpr
int DMAX = 0x6000;
48 const std::string& name,
unsigned sampleRam)
51 , ram(config, name +
" RAM",
"Y8950 sample RAM", sampleRam)
52 , clock(config.getMotherBoard().getCurrentTime())
72 addrMask = (1 << 18) - 1;
85 bool Y8950Adpcm::isPlaying()
const
87 return (reg7 & 0xC0) == 0x80;
94 void Y8950Adpcm::restart(PlayData& pd)
96 pd.memPtr = startAddr;
110 for (
unsigned i = 0; isPlaying() && (i < ticks); ++i) {
117 void Y8950Adpcm::schedule()
120 if ((stopAddr > startAddr) && (delta != 0)) {
127 uint64_t samples = stopAddr - emu.memPtr + 1;
131 stop += unsigned(
length / delta);
141 void Y8950Adpcm::executeUntil(EmuTime::param time)
172 emu.memPtr = startAddr;
173 aud.memPtr = startAddr;
175 if ((reg7 & 0xA0) == 0x20) {
192 addrMask = data &
R08_64K ? (1 << 16) - 1 : (1 << 18) - 1;
196 startAddr = (startAddr & 0x7F807) | (data << 3);
199 startAddr = (startAddr & 0x007FF) | (data << 11);
203 stopAddr = (stopAddr & 0x7F807) | (data << 3);
210 stopAddr = (stopAddr & 0x007FF) | (data << 11);
222 delta = (delta & 0xFF00) | data;
223 volumeWStep = (volume * delta) >>
STEP_BITS;
230 delta = (delta & 0x00FF) | (data << 8);
231 volumeWStep = (volume * delta) >>
STEP_BITS;
240 volumeWStep = (volume * delta) >>
STEP_BITS;
254 void Y8950Adpcm::writeData(
byte data)
259 assert(!isPlaying());
261 emu.memPtr = startAddr;
264 if (emu.memPtr <= stopAddr) {
265 writeMemory(emu.memPtr, data);
281 if (emu.memPtr > stopAddr) {
288 emu.memPtr = startAddr;
292 }
else if ((reg7 &
R07_MODE) == 0x80) {
304 byte result = (rg == 0x0F)
325 return (emu.output >> 8) & 0xFF;
327 return emu.output >> 16;
358 byte Y8950Adpcm::readData()
362 assert(!isPlaying());
364 emu.memPtr = startAddr;
367 byte result = peekData();
369 assert(!isPlaying());
374 }
else if (emu.memPtr > stopAddr) {
397 byte Y8950Adpcm::peekData()
const
401 assert(!isPlaying());
404 }
else if (emu.memPtr > stopAddr) {
407 return readMemory(emu.memPtr);
414 void Y8950Adpcm::writeMemory(
unsigned memPtr,
byte value)
416 unsigned addr = (memPtr / 2) & addrMask;
417 if ((addr < ram.
getSize()) && !romBank) {
418 ram.
write(addr, value);
421 byte Y8950Adpcm::readMemory(
unsigned memPtr)
const
423 unsigned addr = (memPtr / 2) & addrMask;
424 if (romBank || (addr >= ram.
getSize())) {
434 if (!isPlaying())
return 0;
442 static constexpr
int F1[16] = { 1, 3, 5, 7, 9, 11, 13, 15,
443 -1, -3, -5, -7, -9, -11, -13, -15 };
444 static constexpr
int F2[16] = { 57, 57, 57, 57, 77, 102, 128, 153,
445 57, 57, 57, 57, 77, 102, 128, 153 };
449 PlayData& pd = doEmu ? emu : aud;
454 if (!(pd.memPtr & 1)) {
457 pd.adpcm_data = readMemory(pd.memPtr);
459 pd.adpcm_data = reg15;
465 return pd.adpcm_data >> 4;
468 return pd.adpcm_data & 0x0F;
471 int prevOut = pd.out;
475 int prevLeveling = pd.nextLeveling;
476 pd.nextLeveling = (prevOut + pd.out) / 2;
477 int deltaLeveling = pd.nextLeveling - prevLeveling;
478 pd.sampleStep = deltaLeveling * volumeWStep;
479 int tmp = deltaLeveling * ((volume * pd.nowStep) >>
STEP_BITS);
480 pd.output = prevLeveling * volume + tmp;
484 (pd.memPtr > stopAddr)) {
504 pd.output += pd.sampleStep;
506 return pd.output >> 12;
516 template<
typename Archive>
519 ar.template serializeBase<Schedulable>(*
this);
520 ar.serialize(
"ram", ram,
521 "startAddr", startAddr,
522 "stopAddr", stopAddr,
523 "addrMask", addrMask,
525 "volumeWStep", volumeWStep,
526 "readDelay", readDelay,
532 "memPntr", emu.memPtr,
533 "nowStep", emu.nowStep,
535 "output", emu.output,
537 "nextLeveling", emu.nextLeveling,
538 "sampleStep", emu.sampleStep,
539 "adpcm_data", emu.adpcm_data);
540 if constexpr (Archive::IS_LOADER) {
546 if (ar.versionBelow(version, 2)) {
556 ar.serialize(
"clock", clock);
Represents a clock with a fixed frequency.
constexpr void reset(EmuTime::param e)
Reset the clock to start ticking at the given time.
constexpr void advance(EmuTime::param e)
Advance this clock in time until the last tick which is not past the given time.
constexpr unsigned getTicksTill(EmuTime::param e) const
Calculate the number of ticks for this clock until the given time.
Every class that wants to get scheduled at some point must inherit from this class.
void setSyncPoint(EmuTime::param timestamp)
EmuTime::param getCurrentTime() const
Convenience method: This is the same as getScheduler().getCurrentTime().
void write(unsigned addr, byte value)
void sync(EmuTime::param time)
byte readReg(byte rg, EmuTime::param time)
byte peekReg(byte rg, EmuTime::param time) const
Y8950Adpcm(Y8950 &y8950, const DeviceConfig &config, const std::string &name, unsigned sampleRam)
void writeReg(byte rg, byte data, EmuTime::param time)
void serialize(Archive &ar, unsigned version)
void reset(EmuTime::param time)
static constexpr int STATUS_BUF_RDY
byte peekRawStatus() const
static constexpr int STATUS_PCM_BSY
void resetStatus(byte flags)
void setStatus(byte flags)
static constexpr int STATUS_EOS
int16_t clipIntToShort(int x)
Clip x to range [-32768,32767].
T length(const vecN< N, T > &x)
constexpr vecN< N, T > clamp(const vecN< N, T > &x, const vecN< N, T > &minVal, const vecN< N, T > &maxVal)
This file implemented 3 utility functions:
constexpr int R08_NOTE_SET
constexpr int R07_MEMORY_DATA
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)