|
| 1 | +static const n10 adpcmAccumulatorStep[16][16] = { |
| 2 | + { 0, 0, 1, 2, 3, 5, 7, 10, 0, 0, -1, -2, -3, -5, -7, -10 }, |
| 3 | + { 0, 1, 2, 3, 4, 6, 8, 13, 0, -1, -2, -3, -4, -6, -8, -13 }, |
| 4 | + { 0, 1, 2, 4, 5, 7, 10, 15, 0, -1, -2, -4, -5, -7, -10, -15 }, |
| 5 | + { 0, 1, 3, 4, 6, 9, 13, 19, 0, -1, -3, -4, -6, -9, -13, -19 }, |
| 6 | + { 0, 2, 3, 5, 8, 11, 15, 23, 0, -2, -3, -5, -8, -11, -15, -23 }, |
| 7 | + { 0, 2, 4, 7, 10, 14, 19, 29, 0, -2, -4, -7, -10, -14, -19, -29 }, |
| 8 | + { 0, 3, 5, 8, 12, 16, 22, 33, 0, -3, -5, -8, -12, -16, -22, -33 }, |
| 9 | + { 1, 4, 7, 10, 15, 20, 29, 43, -1, -4, -7, -10, -15, -20, -29, -43 }, |
| 10 | + { 1, 4, 8, 13, 18, 25, 35, 53, -1, -4, -8, -13, -18, -25, -35, -53 }, |
| 11 | + { 1, 6, 10, 16, 22, 31, 43, 64, -1, -6, -10, -16, -22, -31, -43, -64 }, |
| 12 | + { 2, 7, 12, 19, 27, 37, 51, 76, -2, -7, -12, -19, -27, -37, -51, -76 }, |
| 13 | + { 2, 9, 16, 24, 34, 46, 64, 96, -2, -9, -16, -24, -34, -46, -64, -96 }, |
| 14 | + { 3, 11, 19, 29, 41, 57, 79, 117, -3, -11, -19, -29, -41, -57, -79, -117 }, |
| 15 | + { 4, 13, 24, 36, 50, 69, 96, 143, -4, -13, -24, -36, -50, -69, -96, -143 }, |
| 16 | + { 4, 16, 29, 44, 62, 85, 118, 175, -4, -16, -29, -44, -62, -85, -118, -175 }, |
| 17 | + { 6, 20, 36, 54, 76, 104, 144, 214, -6, -20, -36, -54, -76, -104, -144, -214 } |
| 18 | +}; |
| 19 | +static const i4 adpcmIndexStep[8] = { |
| 20 | + -1, -1, 0, 0, 1, 2, 2, 3 |
| 21 | +}; |
1 | 22 |
|
2 | 23 | auto Cartridge::KARNAK::power() -> void { |
3 | 24 | Thread::create(384'000, std::bind_front(&Cartridge::KARNAK::main, this)); |
4 | 25 |
|
5 | | - timerEnable = 0; |
| 26 | + enable = 0; |
6 | 27 | timerPeriod = 0; |
7 | 28 | timerCounter = 0; |
| 29 | + |
| 30 | + adpcmReset(); |
8 | 31 | } |
9 | 32 |
|
10 | 33 | auto Cartridge::KARNAK::reset() -> void { |
11 | 34 | Thread::destroy(); |
12 | 35 | } |
13 | 36 |
|
| 37 | +auto Cartridge::KARNAK::adpcmReset() -> void { |
| 38 | + adpcmAccumulator = 0x100; |
| 39 | + adpcmInputShift = 0; |
| 40 | + adpcmStepIndex = 0; |
| 41 | +} |
| 42 | + |
| 43 | +auto Cartridge::KARNAK::adpcmNext(n4 sample) -> void { |
| 44 | + adpcmAccumulator += adpcmAccumulatorStep[adpcmStepIndex][sample]; |
| 45 | + adpcmStepIndex = std::clamp(adpcmStepIndex + adpcmIndexStep[sample & 7], 0, 15); |
| 46 | +} |
| 47 | + |
14 | 48 | auto Cartridge::KARNAK::main() -> void { |
15 | | - if(timerEnable) { |
| 49 | + if(enable) { |
16 | 50 | if(!timerCounter) { |
17 | 51 | timerCounter = (timerPeriod + 1) * 2; |
18 | 52 | } |
19 | 53 | timerCounter--; |
20 | 54 | } |
21 | | - cpu.irqLevel(CPU::Interrupt::Cartridge, timerEnable && !timerCounter); |
| 55 | + cpu.irqLevel(CPU::Interrupt::Cartridge, enable && !timerCounter); |
22 | 56 | step(1); |
23 | 57 | } |
24 | 58 |
|
|
0 commit comments