NINTV-DS/arm9/source/emucore/SP0256.cpp
2021-09-02 17:32:31 -04:00

957 lines
29 KiB
C++

#include <nds.h>
#include "SP0256.h"
INT32 repeat __attribute__((section(".dtcm")));
INT32 period __attribute__((section(".dtcm")));
INT32 periodCounter __attribute__((section(".dtcm")));
INT32 amplitude __attribute__((section(".dtcm")));
INT8 b[6] __attribute__((section(".dtcm")));
INT8 f[6] __attribute__((section(".dtcm")));
INT32 y[6][2] __attribute__((section(".dtcm")));
INT8 periodInterpolation __attribute__((section(".dtcm")));
INT8 amplitudeInterpolation __attribute__((section(".dtcm")));
UINT16 bitMasks[16] __attribute__((section(".dtcm"))) = {
0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF,
0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
INT16 qtbl[256] __attribute__((section(".dtcm"))) = {
0, 511, 510, 509, 508, 507, 506, 505,
504, 503, 502, 501, 500, 499, 498, 497,
496, 495, 494, 493, 492, 491, 490, 489,
488, 487, 486, 485, 484, 483, 482, 481,
479, 477, 475, 473, 471, 469, 467, 465,
463, 461, 459, 457, 455, 453, 451, 449,
447, 445, 443, 441, 439, 437, 435, 433,
431, 429, 427, 425, 421, 417, 413, 409,
405, 401, 397, 393, 389, 385, 381, 377,
373, 369, 365, 361, 357, 353, 349, 345,
341, 337, 333, 329, 325, 321, 317, 313,
309, 305, 301, 297, 289, 281, 273, 265,
257, 249, 241, 233, 225, 217, 209, 201,
193, 185, 177, 169, 161, 153, 145, 137,
129, 121, 113, 105, 97, 89, 81, 73,
65, 57, 49, 41, 33, 25, 12, 9,
0, -9, -12, -25, -33, -41, -49, -57,
-65, -73, -81, -89, -97, -105, -113, -121,
-129, -137, -145, -153, -161, -169, -177, -185,
-193, -201, -209, -217, -225, -233, -241, -249,
-257, -265, -273, -281, -289, -297, -301, -305,
-309, -313, -317, -321, -325, -329, -333, -337,
-341, -345, -349, -353, -357, -361, -365, -369,
-373, -377, -381, -385, -389, -393, -397, -401,
-405, -409, -413, -417, -421, -425, -427, -429,
-431, -433, -435, -437, -439, -441, -443, -445,
-447, -449, -451, -453, -455, -457, -459, -461,
-463, -465, -467, -469, -471, -473, -475, -477,
-479, -481, -482, -483, -484, -485, -486, -487,
-488, -489, -490, -491, -492, -493, -494, -495,
-496, -497, -498, -499, -500, -501, -502, -503,
-504, -505, -506, -507, -508, -509, -510, -511
};
SP0256::SP0256()
: Processor("SP0256"),
ivoiceROM("Intellivoice ROM", "ivoice.bin", 0, 1, 0x800, 0x1000, TRUE)
{
registers.init(this);
}
INT32 SP0256::getClockSpeed() {
return 10000;
}
INT32 SP0256::getClocksPerSample() {
return 1;
}
void SP0256::resetProcessor()
{
currentBits = 0;
bitsLeft = 0;
pc = 0;
page = 1;
stack = 0;
mode = 0;
repeatPrefix = 0;
command = 0;
lrqHigh = TRUE;
idle = TRUE;
fifoHead = 0;
fifoSize = 0;
speaking = FALSE;
amplitude = 0;
period = 0;
periodCounter = 0x1;
random = 1;
for (INT32 i = 0; i < 6; i++) {
y[i][0] = 0;
y[i][1] = 0;
}
}
INT32 SP0256::tick(INT32 minimum)
{
if (idle) {
//for (int i = 0; i < minimum; i++)
// audioOutputLine->playSample(0);
return minimum;
}
INT32 totalTicks = 0;
do {
if (!speaking) {
speaking = TRUE;
lrqHigh = TRUE;
pc = 0x1000 | (command << 1);
bitsLeft = 0;
command = 0;
}
//if the speaking filters are empty, fill 'em up
while (!idle && repeat == 0) {
INT32 repeatBefore = repeatPrefix;
decode();
if (repeatBefore != 0)
repeatPrefix = 0;
}
INT32 sample = 0;
if (period == 0) {
if (periodCounter == 0) {
periodCounter = 64;
repeat--;
for (UINT8 j = 0; j < 6; j++)
y[j][0] = y[j][1] = 0;
}
else
periodCounter--;
sample = ((amplitude & 0x1F) << ((amplitude & 0xE0) >> 5));
BOOL noise = ((random & 1) != 0);
random = (random >> 1) ^ (noise ? 0x14000 : 0);
if (!noise)
sample = -sample;
}
else {
if (periodCounter == 0) {
periodCounter = period;
repeat--;
sample = ((amplitude & 0x1F) << ((amplitude & 0xE0) >> 5));
for (INT32 j = 0; j < 6; j++)
y[j][0] = y[j][1] = 0;
}
else
periodCounter--;
}
period = ((period | 0x10000) + periodInterpolation) & 0xFFFF;
amplitude = ((amplitude | 0x10000) + amplitudeInterpolation) & 0xFFFF;
for (INT32 i = 0; i < 6; i++) {
sample += ((qtbl[0x80+b[i]]*y[i][1]) >> 9);
sample += ((qtbl[0x80+f[i]]*y[i][0]) >> 8);
y[i][1] = y[i][0];
y[i][0] = sample;
}
//clamp the sample to a 12-bit range
if (sample > 2047) sample = 2047;
if (sample < -2048) sample = -2048;
audioOutputLine->playSample((INT16)(sample << 4));
totalTicks++;
} while (totalTicks < minimum);
return totalTicks;
}
INT8 SP0256::readDelta(INT32 numBits) {
INT32 value = readBits(numBits);
if ((value & (1 << (numBits - 1))) != 0)
value |= -1 << numBits;
return (INT8)value;
}
INT32 SP0256::readBitsReverse(INT32 numBits)
{
while (bitsLeft < numBits) {
if (pc < 0x1800) {
currentBits |= (ivoiceROM.peek((UINT16)pc) << bitsLeft);
bitsLeft += 8;
pc = (pc+1) & 0xFFFF;
}
else if (pc == 0x1800 && fifoSize > 0) {
currentBits |= (fifoBytes[fifoHead] << bitsLeft);
fifoHead = (fifoHead+1) & 0x3F;
fifoSize--;
bitsLeft += 10;
}
else {
//error, read outside of bounds
currentBits |= (0x03FF << bitsLeft);
bitsLeft += 10;
pc = (pc+1) & 0xFFFF;
}
}
INT32 output = currentBits & bitMasks[numBits-1];
output = flipEndian(output, numBits);
currentBits = currentBits >> numBits;
bitsLeft -= numBits;
return output;
}
INT32 SP0256::readBits(INT32 numBits)
{
while (bitsLeft < numBits) {
if (pc < 0x1800) {
currentBits |= (ivoiceROM.peek((UINT16)pc) << bitsLeft);
bitsLeft += 8;
pc = (pc+1) & 0xFFFF;
}
else if (pc == 0x1800 && fifoSize > 0) {
currentBits |= (fifoBytes[fifoHead] << bitsLeft);
fifoHead = (fifoHead+1) & 0x3F;
fifoSize--;
bitsLeft += 10;
}
else {
//error, read outside of bounds
currentBits |= (0x03FF << bitsLeft);
bitsLeft += 10;
pc = (pc+1) & 0xFFFF;
}
}
INT32 output = currentBits & bitMasks[numBits-1];
currentBits = currentBits >> numBits;
bitsLeft -= numBits;
return output;
}
void SP0256::RTS() {
if (stack == 0) {
if (!lrqHigh) {
pc = 0x1000 | (command << 1);
bitsLeft = 0;
command = 0;
lrqHigh = TRUE;
}
else {
speaking = FALSE;
idle = TRUE;
}
}
else {
pc = stack;
stack = 0;
bitsLeft = 0;
}
}
void SP0256::SETPAGE(INT32 immed4) {
this->page = flipEndian(immed4, 4);
}
void SP0256::LOADALL(INT32 immed4) {
repeat = (repeatPrefix << 4) | immed4;
if (repeat == 0)
return;
amplitude = readBits(8);
period = readBits(8);
//periodCounter = (period == 0 ? 0x100 : period);
b[0] = (INT8)readBits(8);
f[0] = (INT8)readBits(8);
b[1] = (INT8)readBits(8);
f[1] = (INT8)readBits(8);
b[2] = (INT8)readBits(8);
f[2] = (INT8)readBits(8);
b[3] = (INT8)readBits(8);
f[3] = (INT8)readBits(8);
b[4] = (INT8)readBits(8);
f[4] = (INT8)readBits(8);
b[5] = (INT8)readBits(8);
f[5] = (INT8)readBits(8);
if ((mode & 0x01) == 0) {
amplitudeInterpolation = 0;
periodInterpolation = 0;
}
else {
amplitudeInterpolation = (INT8)readBits(8);
periodInterpolation = (INT8)readBits(8);
}
}
void SP0256::LOAD_2(INT32 immed4) {
repeat = (repeatPrefix << 4) | immed4;
if (repeat == 0)
return;
amplitude = (readBits(6) << 2) | (amplitude & 0x03);
period = readBits(8);
//periodCounter = (period == 0 ? 0x100 : period);
switch (mode) {
case 0x0:
b[0] = (INT8)((readBits(3) << 4) | (b[0] & 0x0F));
f[0] = (INT8)((readBits(5) << 3) | (f[0] & 0x07));
b[1] = (INT8)((readBits(3) << 4) | (b[1] & 0x0F));
f[1] = (INT8)((readBits(5) << 3) | (f[1] & 0x07));
b[2] = (INT8)((readBits(3) << 4) | (b[2] & 0x0F));
f[2] = (INT8)((readBits(5) << 3) | (f[2] & 0x07));
b[3] = (INT8)((readBits(4) << 3) | (b[3] & 0x07));
f[3] = (INT8)((readBits(6) << 2) | (f[3] & 0x03));
b[4] = (INT8)((readBits(7) << 1) | (b[4] & 0x01));
f[4] = (INT8)((readBits(6) << 2) | (f[4] & 0x03));
b[5] = 0;
f[5] = 0;
break;
case 0x1:
b[0] = (INT8)((readBits(3) << 4) | (b[0] & 0x0F));
f[0] = (INT8)((readBits(5) << 3) | (f[0] & 0x07));
b[1] = (INT8)((readBits(3) << 4) | (b[1] & 0x0F));
f[1] = (INT8)((readBits(5) << 3) | (f[1] & 0x07));
b[2] = (INT8)((readBits(3) << 4) | (b[2] & 0x0F));
f[2] = (INT8)((readBits(5) << 3) | (f[2] & 0x07));
b[3] = (INT8)((readBits(4) << 3) | (b[3] & 0x07));
f[3] = (INT8)((readBits(6) << 2) | (f[3] & 0x03));
b[4] = (INT8)((readBits(7) << 1) | (b[4] & 0x01));
f[4] = (INT8)((readBits(6) << 2) | (f[4] & 0x03));
b[5] = (INT8)readBits(8);
f[5] = (INT8)readBits(8);
break;
case 0x2:
b[0] = (INT8)((readBits(6) << 1) | (b[0] & 0x01));
f[0] = (INT8)((readBits(6) << 2) | (f[0] & 0x03));
b[1] = (INT8)((readBits(6) << 1) | (b[1] & 0x01));
f[1] = (INT8)((readBits(6) << 2) | (f[1] & 0x03));
b[2] = (INT8)((readBits(6) << 1) | (b[2] & 0x01));
f[2] = (INT8)((readBits(6) << 2) | (f[2] & 0x03));
b[3] = (INT8)((readBits(6) << 1) | (b[3] & 0x01));
f[3] = (INT8)((readBits(7) << 1) | (f[3] & 0x01));
b[4] = (INT8)readBits(8);
f[4] = (INT8)readBits(8);
b[5] = 0;
f[5] = 0;
break;
case 0x3:
b[0] = (INT8)((readBits(6) << 1) | (b[0] & 0x01));
f[0] = (INT8)((readBits(6) << 2) | (f[0] & 0x03));
b[1] = (INT8)((readBits(6) << 1) | (b[1] & 0x01));
f[1] = (INT8)((readBits(6) << 2) | (f[1] & 0x03));
b[2] = (INT8)((readBits(6) << 1) | (b[2] & 0x01));
f[2] = (INT8)((readBits(6) << 2) | (f[2] & 0x03));
b[3] = (INT8)((readBits(6) << 1) | (b[3] & 0x01));
f[3] = (INT8)((readBits(7) << 1) | (f[3] & 0x01));
b[4] = (INT8)readBits(8);
f[4] = (INT8)readBits(8);
b[5] = (INT8)readBits(8);
f[5] = (INT8)readBits(8);
break;
}
amplitudeInterpolation = (INT8)
((amplitudeInterpolation & 0xE0) | (readBits(5)));
periodInterpolation = (INT8)
((periodInterpolation & 0xE0) | (readBits(5)));
}
void SP0256::SETMSB_3(INT32 immed4) {
repeat = (repeatPrefix << 4) | immed4;
if (repeat == 0)
return;
amplitude = (readBits(6) << 2) | (amplitude & 0x03);
if (mode == 0x00 || mode == 0x02) {
b[5] = 0;
f[5] = 0;
}
switch (mode) {
case 0x0:
case 0x1:
f[0] = (INT8)((readBits(5) << 3) | (f[0] & 0x07));
f[1] = (INT8)((readBits(5) << 3) | (f[1] & 0x07));
f[2] = (INT8)((readBits(5) << 3) | (f[2] & 0x07));
break;
case 0x2:
case 0x3:
f[0] = (INT8)((readBits(6) << 2) | (f[0] & 0x03));
f[1] = (INT8)((readBits(6) << 2) | (f[1] & 0x03));
f[2] = (INT8)((readBits(6) << 2) | (f[2] & 0x03));
break;
}
amplitudeInterpolation = (INT8)
((amplitudeInterpolation & 0xE0) | (readBits(5)));
periodInterpolation = (INT8)
((periodInterpolation & 0xE0) | (readBits(5)));
}
void SP0256::LOAD_4(INT32 immed4) {
repeat = (repeatPrefix << 4) | immed4;
if (repeat == 0)
return;
amplitude = (readBits(6) << 2) | (amplitude & 0x03);
period = readBits(8);
//periodCounter = (period == 0 ? 0x100 : period);
b[0] = 0;
f[0] = 0;
b[1] = 0;
f[1] = 0;
b[2] = 0;
f[2] = 0;
switch (mode) {
case 0x0:
b[3] = (INT8)((readBits(4) << 3) | (b[3] & 0x07));
f[3] = (INT8)((readBits(6) << 2) | (f[3] & 0x03));
b[4] = (INT8)((readBits(7) << 1) | (b[4] & 0x01));
f[4] = (INT8)((readBits(6) << 2) | (f[4] & 0x03));
b[5] = 0;
f[5] = 0;
break;
case 0x1:
b[3] = (INT8)((readBits(4) << 3) | (b[3] & 0x07));
f[3] = (INT8)((readBits(6) << 2) | (f[3] & 0x03));
b[4] = (INT8)((readBits(7) << 1) | (b[4] & 0x01));
f[4] = (INT8)((readBits(6) << 2) | (f[4] & 0x03));
b[5] = (INT8)readBits(8);
f[5] = (INT8)readBits(8);
break;
case 0x2:
b[3] = (INT8)((readBits(6) << 1) | (b[3] & 0x01));
f[3] = (INT8)((readBits(7) << 1) | (f[3] & 0x01));
b[4] = (INT8)readBits(8);
f[4] = (INT8)readBits(8);
b[5] = 0;
f[5] = 0;
break;
case 0x3:
b[3] = (INT8)((readBits(6) << 1) | (b[3] & 0x01));
f[3] = (INT8)((readBits(7) << 1) | (f[3] & 0x01));
b[4] = (INT8)readBits(8);
f[4] = (INT8)readBits(8);
b[5] = (INT8)readBits(8);
f[5] = (INT8)readBits(8);
break;
}
amplitudeInterpolation = 0;
periodInterpolation = 0;
}
void SP0256::SETMSB_5(INT32 immed4) {
repeat = (repeatPrefix << 4) | immed4;
if (repeat == 0)
return;
amplitude = (readBits(6) << 2) | (amplitude & 0x03);
period = readBits(8);
//periodCounter = (period == 0 ? 0x100 : period);
if (mode == 0x00 || mode == 0x02) {
b[5] = 0;
f[5] = 0;
}
switch (mode) {
case 0x0:
case 0x1:
f[0] = (INT8)((readBits(5) << 3) | (f[0] & 0x07));
f[1] = (INT8)((readBits(5) << 3) | (f[1] & 0x07));
f[2] = (INT8)((readBits(5) << 3) | (f[2] & 0x07));
break;
case 0x2:
case 0x3:
f[0] = (INT8)((readBits(6) << 2) | (f[0] & 0x03));
f[1] = (INT8)((readBits(6) << 2) | (f[1] & 0x03));
f[2] = (INT8)((readBits(6) << 2) | (f[2] & 0x03));
break;
}
}
void SP0256::SETMSB_6(INT32 immed4) {
repeat = (repeatPrefix << 4) | immed4;
if (repeat == 0)
return;
amplitude = (readBits(6) << 2) | (amplitude & 0x03);
if (mode == 0x00 || mode == 0x02) {
b[5] = 0;
f[5] = 0;
}
switch (mode) {
case 0x0:
f[3] = (INT8)((readBits(6) << 2) | (f[3] & 0x03));
f[4] = (INT8)((readBits(6) << 2) | (f[4] & 0x03));
b[5] = 0;
f[5] = 0;
break;
case 0x1:
f[3] = (INT8)((readBits(6) << 2) | (f[3] & 0x03));
f[4] = (INT8)((readBits(6) << 2) | (f[4] & 0x03));
f[5] = (INT8)readBits(8);
break;
case 0x2:
f[3] = (INT8)((readBits(7) << 1) | (f[3] & 0x01));
f[4] = (INT8)readBits(8);
b[5] = 0;
f[5] = 0;
break;
case 0x3:
f[3] = (INT8)((readBits(7) << 1) | (f[3] & 0x01));
f[4] = (INT8)readBits(8);
f[5] = (INT8)readBits(8);
break;
}
}
void SP0256::JMP(INT32 immed4) {
pc = (page << 12) | (flipEndian(immed4, 4) << 8) | readBitsReverse(8);
bitsLeft = 0;
}
void SP0256::SETMODE(INT32 immed4) {
immed4 = flipEndian(immed4, 4);
mode = immed4 & 0x3;
repeatPrefix = (immed4 & 0xC) >> 2;
}
void SP0256::DELTA_9(INT32 immed4) {
repeat = (repeatPrefix << 4) | immed4;
if (repeat == 0)
return;
amplitude = (amplitude + 0x10000 + (readDelta(4) << 2))
& 0xFFFF;
period = (period + 0x10000 + readDelta(5)) & 0xFFFF;
//periodCounter = (period == 0 ? 0x100 : period);
switch (mode) {
case 0x0:
b[0] += readDelta(3) << 4;
f[0] += readDelta(3) << 3;
b[1] += readDelta(3) << 4;
f[1] += readDelta(3) << 3;
b[2] += readDelta(3) << 4;
f[2] += readDelta(3) << 3;
b[3] += readDelta(3) << 3;
f[3] += readDelta(4) << 2;
b[4] += readDelta(4) << 1;
f[4] += readDelta(4) << 2;
break;
case 0x1:
b[0] += readDelta(3) << 4;
f[0] += readDelta(3) << 3;
b[1] += readDelta(3) << 4;
f[1] += readDelta(3) << 3;
b[2] += readDelta(3) << 4;
f[2] += readDelta(3) << 3;
b[3] += readDelta(3) << 3;
f[3] += readDelta(4) << 2;
b[4] += readDelta(4) << 1;
f[4] += readDelta(4) << 2;
b[5] += readDelta(5) << 0;
f[5] += readDelta(5) << 0;
break;
case 0x2:
b[0] += readDelta(4) << 2;
f[0] += readDelta(4) << 0;
b[1] += readDelta(4) << 1;
f[1] += readDelta(4) << 2;
b[2] += readDelta(4) << 1;
f[2] += readDelta(4) << 2;
b[3] += readDelta(4) << 1;
f[3] += readDelta(5) << 2;
b[4] += readDelta(5) << 1;
f[4] += readDelta(5) << 1;
break;
case 0x3:
b[0] += readDelta(4) << 2;
f[0] += readDelta(4) << 0;
b[1] += readDelta(4) << 1;
f[1] += readDelta(4) << 2;
b[2] += readDelta(4) << 1;
f[2] += readDelta(4) << 2;
b[3] += readDelta(4) << 1;
f[3] += readDelta(5) << 2;
b[4] += readDelta(5) << 1;
f[4] += readDelta(5) << 1;
b[5] += readDelta(5) << 0;
f[5] += readDelta(5) << 0;
break;
}
}
void SP0256::SETMSB_A(INT32 immed4) {
repeat = (repeatPrefix << 4) | immed4;
if (repeat == 0)
return;
amplitude = (readBits(6) << 2) | (amplitude & 0x03);
switch (mode) {
case 0x0:
case 0x1:
f[0] = (INT8)((readBits(5) << 3) | (f[0] & 0x07));
f[1] = (INT8)((readBits(5) << 3) | (f[1] & 0x07));
f[2] = (INT8)((readBits(5) << 3) | (f[2] & 0x07));
break;
case 0x2:
case 0x3:
f[0] = (INT8)((readBits(6) << 2) | (f[0] & 0x03));
f[1] = (INT8)((readBits(6) << 2) | (f[1] & 0x03));
f[2] = (INT8)((readBits(6) << 2) | (f[2] & 0x03));
break;
}
}
void SP0256::JSR(INT32 immed4) {
INT32 newpc = (page << 12) | (flipEndian(immed4, 4) << 8) | readBitsReverse(8);
stack = pc;
pc = newpc;
bitsLeft = 0;
}
void SP0256::LOAD_C(INT32 immed4) {
repeat = (repeatPrefix << 4) | immed4;
if (repeat == 0)
return;
amplitude = (readBits(6) << 2) | (amplitude & 0x03);
period = readBits(8);
//periodCounter = (period == 0 ? 0x100 : period);
switch (mode) {
case 0x0:
b[0] = (INT8)((readBits(3) << 4) | (b[0] & 0x0F));
f[0] = (INT8)((readBits(5) << 3) | (f[0] & 0x07));
b[1] = (INT8)((readBits(3) << 4) | (b[1] & 0x0F));
f[1] = (INT8)((readBits(5) << 3) | (f[1] & 0x07));
b[2] = (INT8)((readBits(3) << 4) | (b[2] & 0x0F));
f[2] = (INT8)((readBits(5) << 3) | (f[2] & 0x07));
b[3] = (INT8)((readBits(4) << 3) | (b[3] & 0x07));
f[3] = (INT8)((readBits(6) << 2) | (f[3] & 0x03));
b[4] = (INT8)((readBits(7) << 1) | (b[4] & 0x01));
f[4] = (INT8)((readBits(6) << 2) | (f[4] & 0x03));
b[5] = 0;
f[5] = 0;
break;
case 0x1:
b[0] = (INT8)((readBits(3) << 4) | (b[0] & 0x0F));
f[0] = (INT8)((readBits(5) << 3) | (f[0] & 0x07));
b[1] = (INT8)((readBits(3) << 4) | (b[1] & 0x0F));
f[1] = (INT8)((readBits(5) << 3) | (f[1] & 0x07));
b[2] = (INT8)((readBits(3) << 4) | (b[2] & 0x0F));
f[2] = (INT8)((readBits(5) << 3) | (f[2] & 0x07));
b[3] = (INT8)((readBits(4) << 3) | (b[3] & 0x07));
f[3] = (INT8)((readBits(6) << 2) | (f[3] & 0x03));
b[4] = (INT8)((readBits(7) << 1) | (b[4] & 0x01));
f[4] = (INT8)((readBits(6) << 2) | (f[4] & 0x03));
b[5] = (INT8)readBits(8);
f[5] = (INT8)readBits(8);
break;
case 0x2:
b[0] = (INT8)((readBits(6) << 1) | (b[0] & 0x01));
f[0] = (INT8)((readBits(6) << 2) | (f[0] & 0x03));
b[1] = (INT8)((readBits(6) << 1) | (b[1] & 0x01));
f[1] = (INT8)((readBits(6) << 2) | (f[1] & 0x03));
b[2] = (INT8)((readBits(6) << 1) | (b[2] & 0x01));
f[2] = (INT8)((readBits(6) << 2) | (f[2] & 0x03));
b[3] = (INT8)((readBits(6) << 1) | (b[3] & 0x01));
f[3] = (INT8)((readBits(7) << 1) | (f[3] & 0x01));
b[4] = (INT8)readBits(8);
f[4] = (INT8)readBits(8);
b[5] = 0;
f[5] = 0;
break;
case 0x3:
b[0] = (INT8)((readBits(6) << 1) | (b[0] & 0x01));
f[0] = (INT8)((readBits(6) << 2) | (f[0] & 0x03));
b[1] = (INT8)((readBits(6) << 1) | (b[1] & 0x01));
f[1] = (INT8)((readBits(6) << 2) | (f[1] & 0x03));
b[2] = (INT8)((readBits(6) << 1) | (b[2] & 0x01));
f[2] = (INT8)((readBits(6) << 2) | (f[2] & 0x03));
b[3] = (INT8)((readBits(6) << 1) | (b[3] & 0x01));
f[3] = (INT8)((readBits(7) << 1) | (f[3] & 0x01));
b[4] = (INT8)readBits(8);
f[4] = (INT8)readBits(8);
b[5] = (INT8)readBits(8);
f[5] = (INT8)readBits(8);
break;
}
amplitudeInterpolation = 0;
periodInterpolation = 0;
}
void SP0256::DELTA_D(INT32 immed4) {
repeat = (repeatPrefix << 4) | immed4;
if (repeat == 0)
return;
amplitude = (amplitude + 0x10000 + (readDelta(4) << 2))
& 0xFFFF;
period = (period + 0x10000 + readDelta(5)) & 0xFFFF;
//periodCounter = (period == 0 ? 0x100 : period);
switch (mode) {
case 0x0:
b[3] += readDelta(3) << 3;
f[3] += readDelta(4) << 2;
b[4] += readDelta(4) << 1;
f[4] += readDelta(4) << 2;
break;
case 0x1:
b[3] += readDelta(3) << 3;
f[3] += readDelta(4) << 2;
b[4] += readDelta(4) << 1;
f[4] += readDelta(4) << 2;
b[5] += readDelta(5) << 0;
f[5] += readDelta(5) << 0;
break;
case 0x2:
b[3] += readDelta(4) << 1;
f[3] += readDelta(5) << 1;
b[4] += readDelta(5) << 0;
f[4] += readDelta(5) << 0;
break;
case 0x3:
b[3] += readDelta(4) << 1;
f[3] += readDelta(5) << 1;
b[4] += readDelta(5) << 0;
f[4] += readDelta(5) << 0;
b[5] += readDelta(5) << 0;
f[5] += readDelta(5) << 0;
break;
}
}
void SP0256::LOAD_E(INT32 immed4) {
repeat = (repeatPrefix << 4) | immed4;
if (repeat == 0)
return;
amplitude = (readBits(6) << 2) | (amplitude & 0x03);
period = readBits(8);
//periodCounter = (period == 0 ? 0x100 : period);
}
void SP0256::PAUSE(INT32 immed4) {
repeat = (repeatPrefix << 4) | immed4;
if (repeat == 0)
return;
//clear everything
amplitude = 0;
period = 0;
for (INT32 j = 0; j < 6; j++) {
b[j] = 0;
f[j] = 0;
}
amplitudeInterpolation = 0;
periodInterpolation = 0;
}
void SP0256::decode() {
INT32 immed4 = readBits(4);
INT32 nextInstruction = readBitsReverse(4);
switch (nextInstruction) {
case 0x0:
if (immed4 == 0)
RTS();
else
SETPAGE(immed4);
break;
case 0x8:
SETMODE(immed4);
break;
case 0x4:
LOAD_4(immed4);
break;
case 0xC:
LOAD_C(immed4);
break;
case 0x2:
LOAD_2(immed4);
break;
case 0xA:
SETMSB_A(immed4);
break;
case 0x6:
SETMSB_6(immed4);
break;
case 0xE:
LOAD_E(immed4);
break;
case 0x1:
LOADALL(immed4);
break;
case 0x9:
DELTA_9(immed4);
break;
case 0x5:
SETMSB_5(immed4);
break;
case 0xD:
DELTA_D(immed4);
break;
case 0x3:
SETMSB_3(immed4);
break;
case 0xB:
JSR(immed4);
break;
case 0x7:
JMP(immed4);
break;
case 0xF:
PAUSE(immed4);
break;
/*
case 0x0:
if (immed4 == 0)
RTS();
else
SETPAGE(immed4);
break;
case 0x1:
SETMODE(immed4);
break;
case 0x2:
LOAD_4(immed4);
break;
case 0x3:
LOAD_C(immed4);
break;
case 0x4:
LOAD_2(immed4);
break;
case 0x5:
SETMSB_A(immed4);
break;
case 0x6:
SETMSB_6(immed4);
break;
case 0x7:
LOAD_E(immed4);
break;
case 0x8:
LOADALL(immed4);
break;
case 0x9:
DELTA_9(immed4);
break;
case 0xA:
SETMSB_5(immed4);
break;
case 0xB:
DELTA_D(immed4);
break;
case 0xC:
SETMSB_3(immed4);
break;
case 0xD:
JSR(immed4);
break;
case 0xE:
JMP(immed4);
break;
case 0xF:
PAUSE(immed4);
break;
*/
}
}
INT32 SP0256::flipEndian(INT32 value, INT32 bits) {
INT32 output = 0;
INT32 bitMask = 1;
for (INT32 i = 0; i < bits; i++) {
INT32 offset = (bits-1)-(i<<1);
if (offset > 0)
output |= (value & bitMask) << offset;
else
output |= (value & bitMask) >> -offset;
bitMask = bitMask << 1;
}
return output;
}
SP0256State SP0256::getState()
{
SP0256State state = {0};
#if 0
state.bitsLeft = this->bitsLeft;
state.currentBits = this->currentBits;
state.pc = this->pc;
state.stack = this->stack;
state.mode = this->mode;
state.repeatPrefix = this->repeatPrefix;
state.page = this->page;
state.command = this->command;
state.idle = this->idle;
state.lrqHigh = this->lrqHigh;
state.speaking = this->speaking;
memcpy(state.fifoBytes, this->fifoBytes, sizeof(this->fifoBytes));
state.fifoHead = this->fifoHead;
state.fifoSize = this->fifoSize;
state.repeat = this->repeat;
state.period = this->period;
state.periodCounter = this->periodCounter;
state.amplitude = this->amplitude;
memcpy(state.b, this->b, sizeof(this->b));
memcpy(state.f, this->f, sizeof(this->f));
memcpy(state.y, this->y, sizeof(this->f));
state.periodInterpolation = this->periodInterpolation;
state.amplitudeInterpolation = this->amplitudeInterpolation;
state.random = this->random;
#endif
return state;
}
void SP0256::setState(SP0256State state)
{
#if 0
this->bitsLeft = state.bitsLeft;
this->currentBits = state.currentBits;
this->pc = state.pc;
this->stack = state.stack;
this->mode = state.mode;
this->repeatPrefix = state.repeatPrefix;
this->page = state.page;
this->command = state.command;
this->idle = state.idle;
this->lrqHigh = state.lrqHigh;
this->speaking = state.speaking;
memcpy(this->fifoBytes, state.fifoBytes, sizeof(this->fifoBytes));
this->fifoHead = state.fifoHead;
this->fifoSize = state.fifoSize;
this->repeat = state.repeat;
this->period = state.period;
this->periodCounter = state.periodCounter;
this->amplitude = state.amplitude;
memcpy(this->b, state.b, sizeof(this->b));
memcpy(this->f, state.f, sizeof(this->f));
memcpy(this->y, state.y, sizeof(this->f));
this->periodInterpolation = state.periodInterpolation;
this->amplitudeInterpolation = state.amplitudeInterpolation;
this->random = state.random;
#endif
}