diff --git a/bsnes/nall/snes/cartridge.hpp b/bsnes/nall/snes/cartridge.hpp index 7d5a9399..485e91eb 100755 --- a/bsnes/nall/snes/cartridge.hpp +++ b/bsnes/nall/snes/cartridge.hpp @@ -408,7 +408,7 @@ SNESCartridge::SNESCartridge(const uint8_t *data, unsigned size) { } if(has_dsp1) { - xml << " \n"; + xml << " \n"; if(dsp1_mapper == DSP1LoROM1MB) { xml << " \n"; xml << " \n"; diff --git a/bsnes/snes/Makefile b/bsnes/snes/Makefile index ed3a9b99..b3ac7ea4 100755 --- a/bsnes/snes/Makefile +++ b/bsnes/snes/Makefile @@ -4,8 +4,7 @@ snes_objects += snes-cartridge snes-cheat snes_objects += snes-memory snes-cpucore snes-smpcore snes_objects += snes-cpu snes-smp snes-dsp snes-ppu snes_objects += snes-supergameboy snes-superfx snes-sa1 snes-upd77c25 -snes_objects += snes-bsx snes-srtc snes-sdd1 snes-spc7110 -snes_objects += snes-cx4 snes-dsp1 snes-dsp2 snes-dsp3 snes-dsp4 +snes_objects += snes-bsx snes-srtc snes-sdd1 snes-spc7110 snes-cx4 snes_objects += snes-obc1 snes-st0010 snes-st0011 snes-st0018 snes_objects += snes-msu1 snes-serial objects += $(snes_objects) @@ -53,10 +52,6 @@ obj/snes-srtc.o : $(snes)/chip/srtc/srtc.cpp $(snes)/chip/srtc/* obj/snes-sdd1.o : $(snes)/chip/sdd1/sdd1.cpp $(snes)/chip/sdd1/* obj/snes-spc7110.o : $(snes)/chip/spc7110/spc7110.cpp $(snes)/chip/spc7110/* obj/snes-cx4.o : $(snes)/chip/cx4/cx4.cpp $(snes)/chip/cx4/* -obj/snes-dsp1.o : $(snes)/chip/dsp1/dsp1.cpp $(snes)/chip/dsp1/* -obj/snes-dsp2.o : $(snes)/chip/dsp2/dsp2.cpp $(snes)/chip/dsp2/* -obj/snes-dsp3.o : $(snes)/chip/dsp3/dsp3.cpp $(snes)/chip/dsp3/* -obj/snes-dsp4.o : $(snes)/chip/dsp4/dsp4.cpp $(snes)/chip/dsp4/* obj/snes-obc1.o : $(snes)/chip/obc1/obc1.cpp $(snes)/chip/obc1/* obj/snes-st0010.o : $(snes)/chip/st0010/st0010.cpp $(snes)/chip/st0010/* obj/snes-st0011.o : $(snes)/chip/st0011/st0011.cpp $(snes)/chip/st0011/* diff --git a/bsnes/snes/cartridge/cartridge.cpp b/bsnes/snes/cartridge/cartridge.cpp index dae1f05e..8f2f9b0f 100755 --- a/bsnes/snes/cartridge/cartridge.cpp +++ b/bsnes/snes/cartridge/cartridge.cpp @@ -37,10 +37,6 @@ void Cartridge::load(Mode cartridge_mode, const lstring &xml_list) { has_spc7110 = false; has_spc7110rtc = false; has_cx4 = false; - has_dsp1 = false; - has_dsp2 = false; - has_dsp3 = false; - has_dsp4 = false; has_obc1 = false; has_st0010 = false; has_st0011 = false; diff --git a/bsnes/snes/cartridge/cartridge.hpp b/bsnes/snes/cartridge/cartridge.hpp index 62c69fc3..fe0b7d08 100755 --- a/bsnes/snes/cartridge/cartridge.hpp +++ b/bsnes/snes/cartridge/cartridge.hpp @@ -43,10 +43,6 @@ public: readonly has_spc7110; readonly has_spc7110rtc; readonly has_cx4; - readonly has_dsp1; - readonly has_dsp2; - readonly has_dsp3; - readonly has_dsp4; readonly has_obc1; readonly has_st0010; readonly has_st0011; diff --git a/bsnes/snes/cartridge/xml.cpp b/bsnes/snes/cartridge/xml.cpp index 8a8352d0..518e9496 100755 --- a/bsnes/snes/cartridge/xml.cpp +++ b/bsnes/snes/cartridge/xml.cpp @@ -42,7 +42,6 @@ void Cartridge::parse_xml_cartridge(const char *data) { if(node.name == "sdd1") xml_parse_sdd1(node); if(node.name == "spc7110") xml_parse_spc7110(node); if(node.name == "cx4") xml_parse_cx4(node); - if(node.name == "necdsp") xml_parse_necdsp(node); if(node.name == "obc1") xml_parse_obc1(node); if(node.name == "setadsp") xml_parse_setadsp(node); if(node.name == "setarisc") xml_parse_setarisc(node); @@ -230,10 +229,21 @@ void Cartridge::xml_parse_sa1(xml_element &root) { void Cartridge::xml_parse_upd77c25(xml_element &root) { has_upd77c25 = true; + bool program = false; + bool sha256 = false; + string xml_hash; + string rom_hash; + + for(unsigned n = 0; n < 2048; n++) upd77c25.programROM[n] = 0; + for(unsigned n = 0; n < 1024; n++) upd77c25.dataROM[n] = 0; + foreach(attr, root.attribute) { if(attr.name == "program") { file fp; - if(fp.open(string(dir(basename()), attr.content), file::mode::read)) { + fp.open(string(dir(basename()), attr.content), file::mode::read); + if(fp.open() && fp.size() == 8192) { + program = true; + for(unsigned n = 0; n < 2048; n++) { upd77c25.programROM[n] = fp.readm(3); } @@ -247,12 +257,16 @@ void Cartridge::xml_parse_upd77c25(xml_element &root) { fp.close(); sha256_ctx sha; - uint8_t shahash[32]; + uint8 shahash[32]; sha256_init(&sha); sha256_chunk(&sha, data, 8192); sha256_final(&sha); sha256_hash(&sha, shahash); + foreach(n, shahash) rom_hash.append(hex<2>(n)); } + } else if(attr.name == "sha256") { + sha256 = true; + xml_hash = attr.content; } } @@ -279,6 +293,16 @@ void Cartridge::xml_parse_upd77c25(xml_element &root) { } } } + + if(program == false) { + system.interface->message("Warning: uPD77C25 program is missing."); + } else if(sha256 == true && xml_hash != rom_hash) { + system.interface->message({ + "Warning: uPD77C25 program SHA256 is incorrect.\n\n" + "Expected:\n", xml_hash, "\n\n" + "Actual:\n", rom_hash + }); + } } void Cartridge::xml_parse_bsx(xml_element &root) { @@ -515,55 +539,6 @@ void Cartridge::xml_parse_cx4(xml_element &root) { } } -void Cartridge::xml_parse_necdsp(xml_element &root) { - unsigned program = 0; - - foreach(attr, root.attribute) { - if(attr.name == "program") { - if(attr.content == "DSP-1" || attr.content == "DSP-1A" || attr.content == "DSP-1B") { - program = 1; - has_dsp1 = true; - } else if(attr.content == "DSP-2") { - program = 2; - has_dsp2 = true; - } else if(attr.content == "DSP-3") { - program = 3; - has_dsp3 = true; - } else if(attr.content == "DSP-4") { - program = 4; - has_dsp4 = true; - } - } - } - - Memory *dr[5] = { 0, &dsp1dr, &dsp2dr, &dsp3, &dsp4 }; - Memory *sr[5] = { 0, &dsp1sr, &dsp2sr, &dsp3, &dsp4 }; - - foreach(node, root.element) { - if(node.name == "dr" && dr[program]) { - foreach(leaf, node.element) { - if(leaf.name == "map") { - Mapping m(*dr[program]); - foreach(attr, leaf.attribute) { - if(attr.name == "address") xml_parse_address(m, attr.content); - } - mapping.append(m); - } - } - } else if(node.name == "sr" && sr[program]) { - foreach(leaf, node.element) { - if(leaf.name == "map") { - Mapping m(*sr[program]); - foreach(attr, leaf.attribute) { - if(attr.name == "address") xml_parse_address(m, attr.content); - } - mapping.append(m); - } - } - } - } -} - void Cartridge::xml_parse_obc1(xml_element &root) { has_obc1 = true; diff --git a/bsnes/snes/chip/chip.hpp b/bsnes/snes/chip/chip.hpp index 221847d2..17067beb 100755 --- a/bsnes/snes/chip/chip.hpp +++ b/bsnes/snes/chip/chip.hpp @@ -12,10 +12,6 @@ struct Coprocessor : Processor { #include #include #include -#include -#include -#include -#include #include #include #include diff --git a/bsnes/snes/chip/dsp1/dsp1.cpp b/bsnes/snes/chip/dsp1/dsp1.cpp deleted file mode 100755 index ae71d3bf..00000000 --- a/bsnes/snes/chip/dsp1/dsp1.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include - -#define DSP1_CPP -namespace SNES { - -DSP1 dsp1; -DSP1DR dsp1dr; -DSP1SR dsp1sr; - -#include "serialization.cpp" -#include "dsp1emu.cpp" - -void DSP1::init() { -} - -void DSP1::enable() { -} - -void DSP1::power() { - reset(); -} - -void DSP1::reset() { - dsp1.reset(); -} - -uint8 DSP1DR::read(unsigned addr) { return dsp1.dsp1.getDr(); } -void DSP1DR::write(unsigned addr, uint8 data) { dsp1.dsp1.setDr(data); } - -uint8 DSP1SR::read(unsigned addr) { return dsp1.dsp1.getSr(); } -void DSP1SR::write(unsigned addr, uint8 data) {} - -} diff --git a/bsnes/snes/chip/dsp1/dsp1.hpp b/bsnes/snes/chip/dsp1/dsp1.hpp deleted file mode 100755 index 5e373be2..00000000 --- a/bsnes/snes/chip/dsp1/dsp1.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#include "dsp1emu.hpp" - -class DSP1 { -public: - void init(); - void enable(); - void power(); - void reset(); - - void serialize(serializer&); - -private: - Dsp1 dsp1; - friend class DSP1DR; - friend class DSP1SR; -}; - -class DSP1DR : public Memory { - uint8 read(unsigned addr); - void write(unsigned addr, uint8 data); -}; - -class DSP1SR : public Memory { - uint8 read(unsigned addr); - void write(unsigned addr, uint8 data); -}; - -extern DSP1 dsp1; -extern DSP1DR dsp1dr; -extern DSP1SR dsp1sr; diff --git a/bsnes/snes/chip/dsp1/dsp1emu.cpp b/bsnes/snes/chip/dsp1/dsp1emu.cpp deleted file mode 100755 index 5138126e..00000000 --- a/bsnes/snes/chip/dsp1/dsp1emu.cpp +++ /dev/null @@ -1,1627 +0,0 @@ -#ifdef DSP1_CPP - -// DSP-1's emulation code -// -// Based on research by Overload, The Dumper, Neviksti and Andreas Naive -// Date: June 2006 - -////////////////////////////////////////////////////////////////// - -Dsp1::Dsp1() -{ - reset(); -} - -////////////////////////////////////////////////////////////////// - -uint8 Dsp1::getSr() -{ - mSrLowByteAccess = ~mSrLowByteAccess; -//Overload: only high 8-bits are accessible externally -//this is required for "Ace wo Nerae!" -// if (mSrLowByteAccess) -// return 0; -// else - return mSr; -} - -////////////////////////////////////////////////////////////////// - -uint8 Dsp1::getDr() -{ - uint8 oDr; - - fsmStep(true, oDr); - return oDr; -} - -////////////////////////////////////////////////////////////////// - -void Dsp1::setDr(uint8 iDr) -{ - fsmStep(false, iDr); -} - -////////////////////////////////////////////////////////////////// - -void Dsp1::reset() -{ - mSr = DRC|RQM; - mSrLowByteAccess = false; - mDr = 0x0080; // Only a supposition. Is this correct? - mFreeze = false; - mFsmMajorState = WAIT_COMMAND; - memset(&shared, 0, sizeof(SharedData)); // another supposition -} - -////////////////////////////////////////////////////////////////// - -// Though the DSP-1 is unaware of the type of operation (read or write) -// we need to know what is being done by the program, as the class -// is responsible for maintaining the binding between the -// "external" and "internal" representations of the DR (data register). - -void Dsp1::fsmStep(bool read, uint8 &data) -{ - if (0 == (mSr&RQM)) return; - // Now RQM would be cleared; however, as this code is not to be used in - // a multithread environment, we will simply fake RQM operation. - // (The only exception would be Op1A's freeze.) - - // binding - if (read) - { - if (mSr&DRS) - data = static_cast(mDr>>8); - else - data = static_cast(mDr); - } - else - { - if (mSr&DRS) - { - mDr &= 0x00ff; - mDr |= data<<8; - } - else - { - mDr &= 0xff00; - mDr |= data; - } - } - - - switch (mFsmMajorState) - { - case WAIT_COMMAND: - mCommand = static_cast(mDr); - if (!(mCommand & 0xc0)) // valid command? - { - switch(mCommand) - { - // freeze cases - case 0x1a: - case 0x2a: - case 0x3a: - mFreeze = true; - break; - // normal cases - default: - mDataCounter=0; - mFsmMajorState = READ_DATA; - mSr &= ~DRC; - break; - } - } - break; - case READ_DATA: - mSr ^= DRS; - if (!(mSr&DRS)) - { - mReadBuffer[mDataCounter++] = static_cast(mDr); - if (mDataCounter >= mCommandTable[mCommand].reads) - { - (this->*mCommandTable[mCommand].callback)(mReadBuffer, mWriteBuffer); - if (0 != mCommandTable[mCommand].writes) // any output? - { - mDataCounter = 0; - mDr = static_cast(mWriteBuffer[mDataCounter]); - mFsmMajorState = WRITE_DATA; - } - else - { - mDr = 0x0080; // valid command completion - mFsmMajorState = WAIT_COMMAND; - mSr |= DRC; - } - } - } - break; - case WRITE_DATA: - mSr ^= DRS; - if (!(mSr&DRS)) - { - ++mDataCounter; - if (mDataCounter >= mCommandTable[mCommand].writes) - { - if ((mCommand == 0x0a)&&(mDr != 0x8000)) - { - // works in continuous mode - mReadBuffer[0]++; // next raster line - (this->*mCommandTable[mCommand].callback)(mReadBuffer, mWriteBuffer); - mDataCounter = 0; - mDr = static_cast(mWriteBuffer[mDataCounter]); - } - else - { - mDr = 0x0080; // valid command completion - mFsmMajorState = WAIT_COMMAND; - mSr |= DRC; - } - } - else - { - mDr = static_cast(mWriteBuffer[mDataCounter]); - } - } - break; - } - - - - // Now RQM would be set (except when executing Op1A -command equals 0x1a, 0x2a or 0x3a-). - if (mFreeze) - mSr &= ~RQM; -} - -////////////////////////////////////////////////////////////////// - -// The info on this table follows Overload's docs. - -const Dsp1::Command Dsp1::mCommandTable[0x40] = { - {&Dsp1::multiply, 2, 1}, //0x00 - {&Dsp1::attitudeA, 4, 0}, //0x01 - {&Dsp1::parameter, 7, 4}, //0x02 - {&Dsp1::subjectiveA, 3, 3}, //0x03 - {&Dsp1::triangle, 2, 2}, //0x04 - {&Dsp1::attitudeA, 4, 0}, //0x01 - {&Dsp1::project, 3, 3}, //0x06 - {&Dsp1::memoryTest, 1, 1}, //0x0f - {&Dsp1::radius, 3, 2}, //0x08 - {&Dsp1::objectiveA, 3, 3}, //0x0d - {&Dsp1::raster, 1, 4}, // 0x0a. This will normally work in continuous mode - {&Dsp1::scalarA, 3, 1}, //0x0b - {&Dsp1::rotate, 3, 2}, //0x0c - {&Dsp1::objectiveA, 3, 3}, //0x0d - {&Dsp1::target, 2, 2}, //0x0e - {&Dsp1::memoryTest, 1, 1}, //0x0f - - {&Dsp1::inverse, 2, 2}, //0x10 - {&Dsp1::attitudeB, 4, 0}, //0x11 - {&Dsp1::parameter, 7, 4}, //0x02 - {&Dsp1::subjectiveB, 3, 3}, //0x13 - {&Dsp1::gyrate, 6, 3}, //0x14 - {&Dsp1::attitudeB, 4, 0}, //0x11 - {&Dsp1::project, 3, 3}, //0x06 - {&Dsp1::memoryDump, 1, 1024}, //0x1f - {&Dsp1::range, 4, 1}, //0x18 - {&Dsp1::objectiveB, 3, 3}, //0x1d - {0, 0, 0}, // 0x1a; the chip freezes - {&Dsp1::scalarB, 3, 1}, //0x1b - {&Dsp1::polar, 6, 3}, //0x1c - {&Dsp1::objectiveB, 3, 3}, //0x1d - {&Dsp1::target, 2, 2}, //0x0e - {&Dsp1::memoryDump, 1, 1024}, //0x1f - - {&Dsp1::multiply2, 2, 1}, //0x20 - {&Dsp1::attitudeC, 4, 0}, //0x21 - {&Dsp1::parameter, 7, 4}, //0x02 - {&Dsp1::subjectiveC, 3, 3}, //0x23 - {&Dsp1::triangle, 2, 2}, //0x04 - {&Dsp1::attitudeC, 4, 0}, //0x21 - {&Dsp1::project, 3, 3}, //0x06 - {&Dsp1::memorySize, 1, 1}, //0x2f - {&Dsp1::distance, 3, 1}, //0x28 - {&Dsp1::objectiveC, 3, 3}, //0x2d - {0, 0, 0}, // 0x1a; the chip freezes - {&Dsp1::scalarC, 3, 1}, //0x2b - {&Dsp1::rotate, 3, 2}, //0x0c - {&Dsp1::objectiveC, 3, 3}, //0x2d - {&Dsp1::target, 2, 2}, //0x0e - {&Dsp1::memorySize, 1, 1}, //0x2f - - {&Dsp1::inverse, 2, 2}, //0x10 - {&Dsp1::attitudeA, 4, 0}, //0x01 - {&Dsp1::parameter, 7, 4}, //0x02 - {&Dsp1::subjectiveA, 3, 3}, //0x03 - {&Dsp1::gyrate, 6, 3}, //0x14 - {&Dsp1::attitudeA, 4, 0}, //0x01 - {&Dsp1::project, 3, 3}, //0x06 - {&Dsp1::memoryDump, 1, 1024}, //0x1f - {&Dsp1::range2, 4, 1}, //0x38 - {&Dsp1::objectiveA, 3, 3}, //0x0d - {0, 0, 0}, // 0x1a; the chip freezes - {&Dsp1::scalarA, 3, 1}, //0x0b - {&Dsp1::polar, 6, 3}, //0x1c - {&Dsp1::objectiveA, 3, 3}, //0x0d - {&Dsp1::target, 2, 2}, //0x0e - {&Dsp1::memoryDump, 1, 1024}, //0x1f -}; - -////////////////////////////////////////////////////////////////// - -void Dsp1::memoryTest(int16 *input, int16 *output) -{ - int16& Size = input[0]; - int16& Result = output[0]; - - Result = 0x0000; -} - -////////////////////////////////////////////////////////////////// - -void Dsp1::memoryDump(int16 *input, int16 *output) -{ - memcpy(output, DataRom, 1024); -} - -////////////////////////////////////////////////////////////////// - -void Dsp1::memorySize(int16 *input, int16 *output) -{ - int16& Size = output[0]; - - Size = 0x0100; -} - -////////////////////////////////////////////////////////////////// - -// 16-bit multiplication - -void Dsp1::multiply(int16 *input, int16 *output) -{ - int16& Multiplicand = input[0]; - int16& Multiplier = input[1]; - int16& Product = output[0]; - - Product = Multiplicand * Multiplier >> 15; -} - -////////////////////////////////////////////////////////////////// - -// 16-bit multiplication. 'Alternative' method. Can anyone check this carefully? - -void Dsp1::multiply2(int16 *input, int16 *output) -{ - int16& Multiplicand = input[0]; - int16& Multiplier = input[1]; - int16& Product = output[0]; - - Product = (Multiplicand * Multiplier >> 15)+1; -} - -////////////////////////////////////////////////////////////////// - -// This command determines the inverse of a floating point decimal number. - -void Dsp1::inverse(int16 *input, int16 *output) -{ - int16& Coefficient = input[0]; - int16& Exponent = input[1]; - int16& iCoefficient = output[0]; - int16& iExponent = output[1]; - - inverse(Coefficient, Exponent, iCoefficient, iExponent); -} - -////////////////////////////////////////////////////////////////// - -// Vector component calculation. Determines the X and Y components for a -// two-dimensional vector whose size and direction is known. -// Y = Radius * sin(Angle) -// X = Radius * cos(Angle) - -void Dsp1::triangle(int16 *input, int16 *output) -{ - int16& Angle = input[0]; - int16& Radius = input[1]; - int16& Y = output[0]; - int16& X = output[1]; - - Y = sin(Angle) * Radius >> 15; - X = cos(Angle) * Radius >> 15; -} - -////////////////////////////////////////////////////////////////// - -// Determines the squared norm of a vector (X,Y,Z) -// The output is Radius = X^2+Y^2+Z^2 (double integer) - -void Dsp1::radius(int16 *input, int16 *output) -{ - int16& X = input[0]; - int16& Y = input[1]; - int16& Z = input[2]; - int16& RadiusLow = output[0]; - int16& RadiusHigh = output[1]; - - int32 Radius; - - Radius = (X * X + Y * Y + Z * Z) << 1; - RadiusLow = static_cast(Radius); - RadiusHigh = static_cast(Radius>>16); -} - -////////////////////////////////////////////////////////////////// - -// Vector size comparison. This command compares the size of the vector (X,Y,Z) and the distance (R) -// from a particular point, and so may be used to determine if a point is within the sphere or radius R. -// The output is D = X^2+Y^2+Z^2-R^2 - -void Dsp1::range(int16 *input, int16 *output) -{ - int16& X = input[0]; - int16& Y = input[1]; - int16& Z = input[2]; - int16& Radius = input[3]; - int16& Range = output[0]; - - Range = (X * X + Y * Y + Z * Z - Radius * Radius) >> 15; -} - -////////////////////////////////////////////////////////////////// - -// Vector size comparison. 'Alternative' method. - -void Dsp1::range2(int16 *input, int16 *output) -{ - int16& X = input[0]; - int16& Y = input[1]; - int16& Z = input[2]; - int16& Radius = input[3]; - int16& Range = output[0]; - - Range = ((X * X + Y * Y + Z * Z - Radius * Radius) >> 15) + 1; -} - -////////////////////////////////////////////////////////////////// - -// This command calculates the norm of a (X,Y,Z) vector, or the distance from -// the point (X,Y,Z) to (0,0,0), as you prefer to see it. -// Distance = sqrt(X^2+Y^2+Z^2) -// The square root of a number 'a' is calculated by doing this: you -// write 'a' as b*2^2n, with 'b' between 1/4 and 1; then, you calculate -// c=sqrt(b) by using lineal interpolation between points of a -// look-up table and, finally, you output the result as c*2^n. - -void Dsp1::distance(int16 *input, int16 *output) -{ - int16& X = input[0]; - int16& Y = input[1]; - int16& Z = input[2]; - int16& Distance = output[0]; - - int32 Radius = X * X + Y * Y + Z * Z; - - if (Radius == 0) Distance = 0; - else - { - int16 C, E; - normalizeDouble(Radius, C, E); - if (E & 1) C = C * 0x4000 >> 15; - - int16 Pos = C * 0x0040 >> 15; - - int16 Node1 = DataRom[0x00d5 + Pos]; - int16 Node2 = DataRom[0x00d6 + Pos]; - - Distance = ((Node2 - Node1) * (C & 0x1ff) >> 9) + Node1; - -#if DSP1_VERSION < 0x0102 - if (Pos & 1) Distance -= (Node2 - Node1); -#endif - Distance >>= (E >> 1); - } -} - -////////////////////////////////////////////////////////////////// - -// Determines the (X2, Y2) coordinates obtained by rotating (X1, Y1) -// clockwise for an angle 'Angle'. The official documentation says -// 'counterclockwise', but it's obviously wrong (surprise! :P) -// -// In matrix notation: -// |X2| |cos(Angle) sin(Angle)| |X1| -// | | = | | | | -// |Y2| |-sin(Angle cos(Angle)| |Y1| - -void Dsp1::rotate(int16 *input, int16 *output) -{ - int16& Angle = input[0]; - int16& X1 = input[1]; - int16& Y1 = input[2]; - int16& X2 = output[0]; - int16& Y2 = output[1]; - - X2 = (Y1 * sin(Angle) >> 15) + (X1 * cos(Angle) >> 15); - Y2 = (Y1 * cos(Angle) >> 15) - (X1 * sin(Angle) >> 15); -} - -////////////////////////////////////////////////////////////////// - -// Calculate the coordinates (X2, Y2, Z2) obtained when rotating (X1, Y1, Z1) -// three-dimensionally. Rotation is done in the order of Az around the Z axis, -// Ay around the Y axis and Ax around the X axis. As occur with the "attitude" commands -// (see comments in the "gyrate" command), this doesn't match what explained in -// the official documentation, but it's coherent with what it is done in the "attitude" -// command (but not with the "gyrate" command). -// -// In matrix notation: -// |X2| |1 0 0 | |cosRy 0 -sinRy| | cosRz sinRz 0| |X1| -// |Y2| = |0 cosRx sinRx| | 0 1 0 | |-sinRz cosRz 0| |Y1| -// |Z2| |0 -sinRx cosRx| |sinRy 0 cosRy| | 0 0 1| |Z1| - -void Dsp1::polar(int16 *input, int16 *output) -{ - int16& Az = input[0]; - int16& Ay = input[1]; - int16& Ax = input[2]; - int16& X1 = input[3]; - int16& Y1 = input[4]; - int16& Z1 = input[5]; - int16& X2 = output[0]; - int16& Y2 = output[1]; - int16& Z2 = output[2]; - - int16 X, Y, Z; - - // Rotate Around Z - X = (Y1 * sin(Az) >> 15) + (X1 * cos(Az) >> 15); - Y = (Y1 * cos(Az) >> 15) - (X1 * sin(Az) >> 15); - X1 = X; Y1 = Y; - - // Rotate Around Y - Z = (X1 * sin(Ay) >> 15) + (Z1 * cos(Ay) >> 15); - X = (X1 * cos(Ay) >> 15) - (Z1 * sin(Ay) >> 15); - X2 = X; Z1 = Z; - - // Rotate Around X - Y = (Z1 * sin(Ax) >> 15) + (Y1 * cos(Ax) >> 15); - Z = (Z1 * cos(Ax) >> 15) - (Y1 * sin(Ax) >> 15); - Y2 = Y; Z2 = Z; -} - -////////////////////////////////////////////////////////////////// - -// Set up the elements of an "attitude matrix" (there are other ones): -// S | cosRz sinRz 0| |cosRy 0 -sinRy| |1 0 0 | -// MatrixA = - |-sinRz cosRz 0| | 0 1 0 | |0 cosRx sinRx| -// 2 | 0 0 1| |sinRy 0 cosRy| |0 -sinRx cosRx| -// This matrix is thought to be used within the following framework: -// let's suppose we define positive rotations around a system of orthogonal axes in this manner: -// a rotation of +90 degrees around axis3 converts axis2 into axis1 -// a rotation of +90 degrees around axis2 converts axis1 into axis3 -// a rotation of +90 degrees around axis1 converts axis3 into axis2 -// and let's suppose that we have defined a new orthonormal axes system (FLU) -// by doing the following operations about the standard one (XYZ): -// first rotating the XYZ system around Z by an angle Rz (obtaining X'Y'Z'), -// then rotating the resulting system around Y by an angle Ry (obtaining X''Y''Z'') -// and, finally, rotating the resulting system around X by an angle Rx (obtaining FLU) -// This FLU (forward/left/up) system represents an "attitude" and, then, the matrix here defined -// is the change of coordinates matrix that transform coordinates in the FLU -// system (the "object coordinates") into the standard XYZ system (the "global coordinates"), -// multiplied by a scale factor S/2, that is: -// |x| S |f| -// |y| * - = MatrixA * |l| -// |z| 2 |u| -// In a similar way, if we use the transpose of the matrix, we can transform global coordinates -// into object coordinates: -// |f| S |x| -// |l| * - = MatrixA_transposed * |y| -// |u| 2 |z| -// -// input[0]: S -// input[1]: Rz -// input[2]: Ry -// input[3]: Rx - -void Dsp1::attitudeA(int16 *input, int16 *output) -{ - int16& S = input[0]; - int16& Rz = input[1]; - int16& Ry = input[2]; - int16& Rx = input[3]; - - int16 SinRz = sin(Rz); - int16 CosRz = cos(Rz); - int16 SinRy = sin(Ry); - int16 CosRy = cos(Ry); - int16 SinRx = sin(Rx); - int16 CosRx = cos(Rx); - - S >>= 1; - - shared.MatrixA[0][0] = (S * CosRz >> 15) * CosRy >> 15; - shared.MatrixA[0][1] = ((S * SinRz >> 15) * CosRx >> 15) + (((S * CosRz >> 15) * SinRx >> 15) * SinRy >> 15); - shared.MatrixA[0][2] = ((S * SinRz >> 15) * SinRx >> 15) - (((S * CosRz >> 15) * CosRx >> 15) * SinRy >> 15); - - shared.MatrixA[1][0] = -((S * SinRz >> 15) * CosRy >> 15); - shared.MatrixA[1][1] = ((S * CosRz >> 15) * CosRx >> 15) - (((S * SinRz >> 15) * SinRx >> 15) * SinRy >> 15); - shared.MatrixA[1][2] = ((S * CosRz >> 15) * SinRx >> 15) + (((S * SinRz >> 15) * CosRx >> 15) * SinRy >> 15); - - shared.MatrixA[2][0] = S * SinRy >> 15; - shared.MatrixA[2][1] = -((S * SinRx >> 15) * CosRy >> 15); - shared.MatrixA[2][2] = (S * CosRx >> 15) * CosRy >> 15; -} - -////////////////////////////////////////////////////////////////// - -// Same than 'attitudeA', but with a difference attitude matrix (matrixB) - -void Dsp1::attitudeB(int16 *input, int16 *output) -{ - int16& S = input[0]; - int16& Rz = input[1]; - int16& Ry = input[2]; - int16& Rx = input[3]; - - int16 SinRz = sin(Rz); - int16 CosRz = cos(Rz); - int16 SinRy = sin(Ry); - int16 CosRy = cos(Ry); - int16 SinRx = sin(Rx); - int16 CosRx = cos(Rx); - - S >>= 1; - - shared.MatrixB[0][0] = (S * CosRz >> 15) * CosRy >> 15; - shared.MatrixB[0][1] = ((S * SinRz >> 15) * CosRx >> 15) + (((S * CosRz >> 15) * SinRx >> 15) * SinRy >> 15); - shared.MatrixB[0][2] = ((S * SinRz >> 15) * SinRx >> 15) - (((S * CosRz >> 15) * CosRx >> 15) * SinRy >> 15); - - shared.MatrixB[1][0] = -((S * SinRz >> 15) * CosRy >> 15); - shared.MatrixB[1][1] = ((S * CosRz >> 15) * CosRx >> 15) - (((S * SinRz >> 15) * SinRx >> 15) * SinRy >> 15); - shared.MatrixB[1][2] = ((S * CosRz >> 15) * SinRx >> 15) + (((S * SinRz >> 15) * CosRx >> 15) * SinRy >> 15); - - shared.MatrixB[2][0] = S * SinRy >> 15; - shared.MatrixB[2][1] = -((S * SinRx >> 15) * CosRy >> 15); - shared.MatrixB[2][2] = (S * CosRx >> 15) * CosRy >> 15; -} - -////////////////////////////////////////////////////////////////// - -// Same than 'attitudeA', but with a difference attitude matrix (matrixC) - -void Dsp1::attitudeC(int16 *input, int16 *output) -{ - int16& S = input[0]; - int16& Rz = input[1]; - int16& Ry = input[2]; - int16& Rx = input[3]; - - int16 SinRz = sin(Rz); - int16 CosRz = cos(Rz); - int16 SinRy = sin(Ry); - int16 CosRy = cos(Ry); - int16 SinRx = sin(Rx); - int16 CosRx = cos(Rx); - - S >>= 1; - - shared.MatrixC[0][0] = (S * CosRz >> 15) * CosRy >> 15; - shared.MatrixC[0][1] = ((S * SinRz >> 15) * CosRx >> 15) + (((S * CosRz >> 15) * SinRx >> 15) * SinRy >> 15); - shared.MatrixC[0][2] = ((S * SinRz >> 15) * SinRx >> 15) - (((S * CosRz >> 15) * CosRx >> 15) * SinRy >> 15); - - shared.MatrixC[1][0] = -((S * SinRz >> 15) * CosRy >> 15); - shared.MatrixC[1][1] = ((S * CosRz >> 15) * CosRx >> 15) - (((S * SinRz >> 15) * SinRx >> 15) * SinRy >> 15); - shared.MatrixC[1][2] = ((S * CosRz >> 15) * SinRx >> 15) + (((S * SinRz >> 15) * CosRx >> 15) * SinRy >> 15); - - shared.MatrixC[2][0] = S * SinRy >> 15; - shared.MatrixC[2][1] = -((S * SinRx >> 15) * CosRy >> 15); - shared.MatrixC[2][2] = (S * CosRx >> 15) * CosRy >> 15; -} - -////////////////////////////////////////////////////////////////// - -// Convert global coordinates (X,Y,Z) to object coordinates (F,L,U) -// See the comment in "attitudeA" for a explanation about the calculation. -// -// input[0]: X ; input[1]: Y ; input[2]: Z -// output[0]: F ; output[1]: L ; output[2]: U - -void Dsp1::objectiveA(int16 *input, int16 *output) -{ - int16& X = input[0]; - int16& Y = input[1]; - int16& Z = input[2]; - int16& F = output[0]; - int16& L = output[1]; - int16& U = output[2]; - - F = (shared.MatrixA[0][0] * X >> 15) + (shared.MatrixA[1][0] * Y >> 15) + (shared.MatrixA[2][0] * Z >> 15); - L = (shared.MatrixA[0][1] * X >> 15) + (shared.MatrixA[1][1] * Y >> 15) + (shared.MatrixA[2][1] * Z >> 15); - U = (shared.MatrixA[0][2] * X >> 15) + (shared.MatrixA[1][2] * Y >> 15) + (shared.MatrixA[2][2] * Z >> 15); -} - -////////////////////////////////////////////////////////////////// - -// Same than 'objectiveA', but for the 'B' attitude - -void Dsp1::objectiveB(int16 *input, int16 *output) -{ - int16& X = input[0]; - int16& Y = input[1]; - int16& Z = input[2]; - int16& F = output[0]; - int16& L = output[1]; - int16& U = output[2]; - - F = (shared.MatrixB[0][0] * X >> 15) + (shared.MatrixB[1][0] * Y >> 15) + (shared.MatrixB[2][0] * Z >> 15); - L = (shared.MatrixB[0][1] * X >> 15) + (shared.MatrixB[1][1] * Y >> 15) + (shared.MatrixB[2][1] * Z >> 15); - U = (shared.MatrixB[0][2] * X >> 15) + (shared.MatrixB[1][2] * Y >> 15) + (shared.MatrixB[2][2] * Z >> 15); -} - -////////////////////////////////////////////////////////////////// - -// Same than 'objectiveA', but for the 'C' attitude - -void Dsp1::objectiveC(int16 *input, int16 *output) -{ - int16& X = input[0]; - int16& Y = input[1]; - int16& Z = input[2]; - int16& F = output[0]; - int16& L = output[1]; - int16& U = output[2]; - - F = (shared.MatrixC[0][0] * X >> 15) + (shared.MatrixC[1][0] * Y >> 15) + (shared.MatrixC[2][0] * Z >> 15); - L = (shared.MatrixC[0][1] * X >> 15) + (shared.MatrixC[1][1] * Y >> 15) + (shared.MatrixC[2][1] * Z >> 15); - U = (shared.MatrixC[0][2] * X >> 15) + (shared.MatrixC[1][2] * Y >> 15) + (shared.MatrixC[2][2] * Z >> 15); -} - -////////////////////////////////////////////////////////////////// - -// Convert object coordinates (F,L,U) to object coordinates (X,Y,Z) -// See the comment in "attitudeA" for a explanation about the calculation. -// -// input[0]: F ; input[1]: L ; input[2]: U -// output[0]: X ; output[1]: Y ; output[2]: Z - -void Dsp1::subjectiveA(int16 *input, int16 *output) -{ - int16& F = input[0]; - int16& L = input[1]; - int16& U = input[2]; - int16& X = output[0]; - int16& Y = output[1]; - int16& Z = output[2]; - - X = (shared.MatrixA[0][0] * F >> 15) + (shared.MatrixA[0][1] * L >> 15) + (shared.MatrixA[0][2] * U >> 15); - Y = (shared.MatrixA[1][0] * F >> 15) + (shared.MatrixA[1][1] * L >> 15) + (shared.MatrixA[1][2] * U >> 15); - Z = (shared.MatrixA[2][0] * F >> 15) + (shared.MatrixA[2][1] * L >> 15) + (shared.MatrixA[2][2] * U >> 15); -} - -////////////////////////////////////////////////////////////////// - -// Same than 'subjectiveA', but for the 'B' attitude - -void Dsp1::subjectiveB(int16 *input, int16 *output) -{ - int16& F = input[0]; - int16& L = input[1]; - int16& U = input[2]; - int16& X = output[0]; - int16& Y = output[1]; - int16& Z = output[2]; - - X = (shared.MatrixB[0][0] * F >> 15) + (shared.MatrixB[0][1] * L >> 15) + (shared.MatrixB[0][2] * U >> 15); - Y = (shared.MatrixB[1][0] * F >> 15) + (shared.MatrixB[1][1] * L >> 15) + (shared.MatrixB[1][2] * U >> 15); - Z = (shared.MatrixB[2][0] * F >> 15) + (shared.MatrixB[2][1] * L >> 15) + (shared.MatrixB[2][2] * U >> 15); -} - -////////////////////////////////////////////////////////////////// - -// Same than 'subjectiveA', but for the 'C' attitude - -void Dsp1::subjectiveC(int16 *input, int16 *output) -{ - int16& F = input[0]; - int16& L = input[1]; - int16& U = input[2]; - int16& X = output[0]; - int16& Y = output[1]; - int16& Z = output[2]; - - X = (shared.MatrixC[0][0] * F >> 15) + (shared.MatrixC[0][1] * L >> 15) + (shared.MatrixC[0][2] * U >> 15); - Y = (shared.MatrixC[1][0] * F >> 15) + (shared.MatrixC[1][1] * L >> 15) + (shared.MatrixC[1][2] * U >> 15); - Z = (shared.MatrixC[2][0] * F >> 15) + (shared.MatrixC[2][1] * L >> 15) + (shared.MatrixC[2][2] * U >> 15); -} - -////////////////////////////////////////////////////////////////// - -// This command calculates the inner product (S) of a vector (X,Y,Z) and -// the first column of MatrixA. It should be noted that that first column -// represent the global coordinates of an unity vector in the forward -// direction in the object coordinate system (coordinates (1,0,0) in the FLU -// axes system). -// -// input[0]: X ; input[1]: Y ; input[2]: Z -// output[0]: S - -void Dsp1::scalarA(int16 *input, int16 *output) -{ - int16& X = input[0]; - int16& Y = input[1]; - int16& Z = input[2]; - int16& S = output[0]; - - S = (X * shared.MatrixA[0][0] + Y * shared.MatrixA[1][0] + Z * shared.MatrixA[2][0]) >> 15; -} - -////////////////////////////////////////////////////////////////// - -// Same than 'scalarA', but for the 'B' attitude - -void Dsp1::scalarB(int16 *input, int16 *output) -{ - int16& X = input[0]; - int16& Y = input[1]; - int16& Z = input[2]; - int16& S = output[0]; - - S = (X * shared.MatrixB[0][0] + Y * shared.MatrixB[1][0] + Z * shared.MatrixB[2][0]) >> 15; -} - -////////////////////////////////////////////////////////////////// - -// Same than 'scalarA', but for the 'C' attitude - -void Dsp1::scalarC(int16 *input, int16 *output) -{ - int16& X = input[0]; - int16& Y = input[1]; - int16& Z = input[2]; - int16& S = output[0]; - - S = (X * shared.MatrixC[0][0] + Y * shared.MatrixC[1][0] + Z * shared.MatrixC[2][0]) >> 15; -} - -////////////////////////////////////////////////////////////////// - -// This command determines the final attitude angles after the body with attitude angles (Ax, Ay, Az) with -// respect to the global coordinates is rotated by the minor angular displacements (DeltaF, DeltaL, DeltaU). -// It means that the XYZ axes are rotated by (Ax, Ay, Az) to obtain the FLU axes and, then, these -// are rotated by (DeltaF, DeltaL, DeltaU). The command calculates and return the new FLU angles respect to the -// XYZ system (Rx, Ry, Rz) -// The formulae are: -// Rx = Ax + (DeltaU*sin(Ay)+DeltaF*cos(Ay)) -// Ry = Ay + DeltaL - tan(Ax)*(DeltaU*cos(Ay)+DeltaF*sin(Ay)) -// Rz = Az + sec(Ax)*(DeltaU*cos(Ay)-DeltaF*sin(Ay)) -// -// Now the discussion: according to the official documentation, as described in various commands, you pass from -// XYZ to FLU by doing the rotations in the order Y, X, Z. In this command, the formulae are coherent with the -// fact that Y is the first axis to do a rotation around it. However, in the "attitude" command, while the official -// document describe it that way, we have discovered, when reverse engineering the command, that the calculated -// matrix do the rotation around Y in the second place. This incoherent behaviour of various commands is, in my -// opinion, a pretty severe implementation error. However, if you only use small "minor displacements", the error term -// introduced by that incoherence should be almost negligible. - -void Dsp1::gyrate(int16 *input, int16 *output) -{ - int16& Az = input[0]; - int16& Ax = input[1]; - int16& Ay = input[2]; - int16& U = input[3]; - int16& F = input[4]; - int16& L = input[5]; - int16& Rz = output[0]; - int16& Rx = output[1]; - int16& Ry = output[2]; - - int16 CSec, ESec, CSin, C, E; - int16 SinAy = sin(Ay); - int16 CosAy = cos(Ay); - - inverse(cos(Ax), 0, CSec, ESec); - - // Rotation Around Z - normalizeDouble(U * CosAy - F * SinAy, C, E); - - E = ESec - E; - - normalize(C * CSec >> 15, C, E); - - Rz = Az + denormalizeAndClip(C, E); - - // Rotation Around X - Rx = Ax + (U * SinAy >> 15) + (F * CosAy >> 15); - - // Rotation Around Y - normalizeDouble(U * CosAy + F * SinAy, C, E); - - E = ESec - E; - - normalize(sin(Ax), CSin, E); - - normalize(-(C * (CSec * CSin >> 15) >> 15), C, E); - - Ry = Ay + denormalizeAndClip(C, E) + L; -} - -////////////////////////////////////////////////////////////////// - -const int16 Dsp1::MaxAZS_Exp[16] = { - 0x38b4, 0x38b7, 0x38ba, 0x38be, 0x38c0, 0x38c4, 0x38c7, 0x38ca, - 0x38ce, 0x38d0, 0x38d4, 0x38d7, 0x38da, 0x38dd, 0x38e0, 0x38e4 -}; - -////////////////////////////////////////////////////////////////// - - -// Set-up the projection framework. Besides returning some values, it store in RAM some values that -// will be used by the other three projection commands (raster, target an project) -// Input: -// (Fx, Fy, Fz)-> coordinates of base point (global coordinates) -// Lfe-> distance between the base point and the viewpoint (center of projection) -// Les-> distance between the base point and the screen -// Aas-> azimuth angle (0 degrees is east; 90 degrees is north) -// Azs-> zenith angle (0 degrees is zenith) -// Output: -// Vof-> raster line of imaginary center (whatever it means ;) ) -// Vva-> raster line representing the horizon line -// (Cx, Cy)-> coordinates of the projection of the center of the screen over the ground (ground coordinates) - -void Dsp1::parameter(int16 *input, int16 *output) -{ - int16& Fx = input[0]; - int16& Fy = input[1]; - int16& Fz = input[2]; - int16& Lfe = input[3]; - int16& Les = input[4]; - int16& Aas = input[5]; - int16& Azs = input[6]; - int16& Vof = output[0]; - int16& Vva = output[1]; - int16& Cx = output[2]; - int16& Cy = output[3]; - - int16 CSec, C, E; - int16 LfeNx, LfeNy, LfeNz; - int16 LesNx, LesNy, LesNz; - - // Copy Zenith angle for clipping - int16 AZS = Azs; - - // Store Les and his coefficient and exponent when normalized - shared.Les = Les; - shared.E_Les=0; - normalize(Les, shared.C_Les, shared.E_Les); - - // Store Sine and Cosine of Azimuth and Zenith angle - shared.SinAas = sin(Aas); - shared.CosAas = cos(Aas); - shared.SinAzs = sin(Azs); - shared.CosAzs = cos(Azs); - - // normal vector to the screen (norm 1, points toward the center of projection) - shared.Nx = shared.SinAzs * -shared.SinAas >> 15; - shared.Ny = shared.SinAzs * shared.CosAas >> 15; - shared.Nz = shared.CosAzs * 0x7fff >> 15; - - // horizontal vector of the screen (Hz=0, norm 1, points toward the right of the screen) - shared.Hx = shared.CosAas*0x7fff>>15; - shared.Hy = shared.SinAas*0x7fff>>15; - - // vertical vector of the screen (norm 1, points toward the top of the screen) - shared.Vx = shared.CosAzs*-shared.SinAas>>15; - shared.Vy = shared.CosAzs*shared.CosAas>>15; - shared.Vz = -shared.SinAzs*0x7fff>>15; - - LfeNx = Lfe*shared.Nx>>15; - LfeNy = Lfe*shared.Ny>>15; - LfeNz = Lfe*shared.Nz>>15; - - // Center of Projection - shared.CentreX = Fx+LfeNx; - shared.CentreY = Fy+LfeNy; - shared.CentreZ = Fz+LfeNz; - - LesNx = Les*shared.Nx>>15; - LesNy = Les*shared.Ny>>15; - LesNz = Les*shared.Nz>>15; - - // center of the screen (global coordinates) - shared.Gx=shared.CentreX-LesNx; - shared.Gy=shared.CentreY-LesNy; - shared.Gz=shared.CentreZ-LesNz; - - - E = 0; - normalize(shared.CentreZ, C, E); - - shared.CentreZ_C = C; - shared.CentreZ_E = E; - - // Determine clip boundary and clip Zenith angle if necessary - // (Why to clip? Maybe to avoid the screen can only show sky with no ground? Only a guess...) - int16 MaxAZS = MaxAZS_Exp[-E]; - - if (AZS < 0) { - MaxAZS = -MaxAZS; - if (AZS < MaxAZS + 1) AZS = MaxAZS + 1; - } else { - if (AZS > MaxAZS) AZS = MaxAZS; - } - - // Store Sine and Cosine of clipped Zenith angle - shared.SinAZS = sin(AZS); - shared.CosAZS = cos(AZS); - - // calculate the separation of (cx, cy) from the projection of - // the 'centre of projection' over the ground... (CentreZ*tg(AZS)) - inverse(shared.CosAZS, 0, shared.SecAZS_C1, shared.SecAZS_E1); - normalize(C * shared.SecAZS_C1 >> 15, C, E); - E += shared.SecAZS_E1; - C = denormalizeAndClip(C, E) * shared.SinAZS >> 15; - - // ... and then take into account the position of the centre of - // projection and the azimuth angle - shared.CentreX += C * shared.SinAas >> 15; - shared.CentreY -= C * shared.CosAas >> 15; - - Cx = shared.CentreX; - Cy = shared.CentreY; - - // Raster number of imaginary center and horizontal line - Vof = 0; - - if ((Azs != AZS) || (Azs == MaxAZS)) - { - // correct vof and vva when Azs is outside the 'non-clipping interval' - // we have only some few Taylor coefficients, so we cannot guess which ones - // are the approximated functions and, what is worse, we don't know why - // the own clipping stuff (and, particularly, this correction) is done - if (Azs == -32768) Azs = -32767; - - C = Azs - MaxAZS; - if (C >= 0) C--; - int16 Aux = ~(C << 2); - - // Vof += x+(1/3)*x^3, where x ranges from 0 to PI/4 when Azs-MaxAZS goes from 0 to 0x2000 - C = Aux * DataRom[0x0328] >> 15; - C = (C * Aux >> 15) + DataRom[0x0327]; - Vof -= (C * Aux >> 15) * Les >> 15; - - // CosAZS *= 1+(1/2)*x^2+(5/24)*x^24, where x ranges from 0 to PI/4 when Azs-MaxAZS goes from 0 to 0x2000 - C = Aux * Aux >> 15; - Aux = (C * DataRom[0x0324] >> 15) + DataRom[0x0325]; - shared.CosAZS += (C * Aux >> 15) * shared.CosAZS >> 15; - } - - // vertical offset of the screen with regard to the horizontal plane - // containing the centre of projection - shared.VOffset = Les * shared.CosAZS >> 15; - - // The horizon line (the line in the screen that is crossed by the horizon plane - // -the horizontal plane containing the 'centre of projection'-), - // will be at distance Les*cotg(AZS) from the centre of the screen. This is difficult - // to explain but easily seen in a graph. To better see it, consider it in this way: - // Les*tg(AZS-90), draw some lines and apply basic trigonometry. ;) - inverse(shared.SinAZS, 0, CSec, E); - normalize(shared.VOffset, C, E); - normalize(C * CSec >> 15, C, E); - - if (C == -32768) { C >>= 1; E++; } - - Vva = denormalizeAndClip(-C, E); - - // Store Secant of clipped Zenith angle - inverse(shared.CosAZS, 0, shared.SecAZS_C2, shared.SecAZS_E2); -} - -////////////////////////////////////////////////////////////////// - -// Calculates the matrix which transform an object situated on a raster line (Vs) into -// his projection over the ground. The modified SecAZS is used here, so -// i don't understand the fine details, but, basically, it's done -// this way: The vertical offset between the point of projection and the -// raster line is calculated (Vs*SinAzs>>15)+VOffset, then the height of -// the center of projection is measured in that units (*CentreZ_C). If, now -// you consider the "reference case" (center of projection at an unit of height), -// the projection of a thin strip containing the raster line will have the same -// width (as the raster line would be on the ground in this case, but will suffer a -// change of scale in height (as the ground and the vertical axis would form an angle of 180-Azs degrees). -// This scale factor, when the angle 'center of screen-center of projection-raster line' is small, -// can be aproximated by the one of the center of the screen, 1/cos(Azs).(**) (Here is when it's used -// SecAZS). By last, you have to consider the effect of the azimuth angle Aas, and you are done. -// -// Using matrix notation: -// |A B| Centre_ZS | cos(Aas) -sin(Aas)| |1 0| -// ProjectionMatrix = | | = ----------- * | | * | | -// |C D| Vs*sin(Azs) |sin(Aas) cos(Aas)| |0 sec(Azs)| -// -// (**) -// If Les=1, the vertical offset between the center -// of projection and the center of the screen is Cos(Azs); then, if the vertical -// offset is 1, the ratio of the projection over the ground respect to the -// line on the screen is 1/cos(Azs). - -void Dsp1::raster(int16 *input, int16 *output) -{ - int16& Vs = input[0]; - int16& An = output[0]; - int16& Bn = output[1]; - int16& Cn = output[2]; - int16& Dn = output[3]; - - int16 C, E, C1, E1; - - inverse((Vs * shared.SinAzs >> 15) + shared.VOffset, 7, C, E); - - E += shared.CentreZ_E; - C1 = C * shared.CentreZ_C >> 15; - - E1 = E + shared.SecAZS_E2; - - normalize(C1, C, E); - C = denormalizeAndClip(C, E); - - An = C * shared.CosAas >> 15; - Cn = C * shared.SinAas >> 15; - - normalize(C1 * shared.SecAZS_C2 >> 15, C, E1); - C = denormalizeAndClip(C, E1); - - Bn = C * -shared.SinAas >> 15; - Dn = C * shared.CosAas >> 15; -} - -////////////////////////////////////////////////////////////////// - -// Calculate the projection over the ground of a selected point of screen -// It simply apply the projection matrix described in the "Raster" command -// to the vector (H,V) transposed, and add the result to the position of -// the centre of projection. -// The only special point to take into account is the directions on the screen: -// H is positive rightward, but V is positive downward; this is why -// the signs take that configuration - -void Dsp1::target(int16 *input, int16 *output) -{ - int16& H = input[0]; - int16& V = input[1]; - int16& X = output[0]; - int16& Y = output[1]; - - int16 C, E, C1, E1; - - inverse((V * shared.SinAzs >> 15) + shared.VOffset, 8, C, E); - - E += shared.CentreZ_E; - C1 = C * shared.CentreZ_C >> 15; - - E1 = E + shared.SecAZS_E1; - - H <<= 8; - normalize(C1, C, E); - C = denormalizeAndClip(C, E) * H >> 15; - - X = shared.CentreX + (C * shared.CosAas >> 15); - Y = shared.CentreY - (C * shared.SinAas >> 15); - - V <<= 8; - normalize(C1 * shared.SecAZS_C1 >> 15, C, E1); - C = denormalizeAndClip(C, E1) * V >> 15; - - X += C * -shared.SinAas >> 15; - Y += C * shared.CosAas >> 15; -} - -////////////////////////////////////////////////////////////////// - -// Calculation of the projection over the screen (H,V) of an object (X,Y,Z) and his -// 'enlargement ratio' (M). The positive directions on the screen are as described -// in the targe command. M is scaled down by 2^-7, that is, M==0x0100 means ratio 1:1 - - void Dsp1::project(int16 *input, int16 *output) -{ - int16& X = input[0]; - int16& Y = input[1]; - int16& Z = input[2]; - int16& H = output[0]; - int16& V = output[1]; - int16& M = output[2]; - - int32 aux, aux4; - int16 E, E2, E3, E4, E5, refE, E6, E7; - int16 C2, C4, C6, C8, C9, C10, C11, C12, C16, C17, C18, C19, C20, C21, C22, C23, C24, C25, C26; - int16 Px, Py, Pz; - - E4=E3=E2=E=E5=0; - - normalizeDouble(int32(X)-shared.Gx, Px, E4); - normalizeDouble(int32(Y)-shared.Gy, Py, E); - normalizeDouble(int32(Z)-shared.Gz, Pz, E3); - Px>>=1; E4--; // to avoid overflows when calculating the scalar products - Py>>=1; E--; - Pz>>=1; E3--; - - refE = (E>15); - C8=- (Py*shared.Ny>>15); - C9=- (Pz*shared.Nz>>15); - C12=C11+C8+C9; // this cannot overflow! - - aux4=C12; // de-normalization with 32-bits arithmetic - refE = 16-refE; // refE can be up to 3 - if (refE>=0) - aux4 <<=(refE); - else - aux4 >>=-(refE); - if (aux4==-1) aux4 = 0; // why? - aux4>>=1; - - aux = static_cast(shared.Les) + aux4; // Les - the scalar product of P with the normal vector of the screen - normalizeDouble(aux, C10, E2); - E2 = 15-E2; - - inverse(C10, 0, C4, E4); - C2=C4*shared.C_Les>>15; // scale factor - - - // H - E7=0; - C16= (Px*shared.Hx>>15); - C20= (Py*shared.Hy>>15); - C17=C16+C20; // scalar product of P with the normalized horizontal vector of the screen... - - C18=C17*C2>>15; // ... multiplied by the scale factor - normalize(C18, C19, E7); - H=denormalizeAndClip(C19, shared.E_Les-E2+refE+E7); - - // V - E6=0; - C21 = Px*shared.Vx>>15; - C22 = Py*shared.Vy>>15; - C23 = Pz*shared.Vz>>15; - C24=C21+C22+C23; // scalar product of P with the normalized vertical vector of the screen... - - C26=C24*C2>>15; // ... multiplied by the scale factor - normalize(C26, C25, E6); - V=denormalizeAndClip(C25, shared.E_Les-E2+refE+E6); - - // M - normalize(C2, C6, E4); - M=denormalizeAndClip(C6, E4+shared.E_Les-E2-7); // M is the scale factor divided by 2^7 -} - -////////////////////////////////////////////////////////////////// - -// Calculate the sine of the input parameter -// this is done by linear interpolation between -// the points of a look-up table - -int16 Dsp1::sin(int16 Angle) -{ - if (Angle < 0) { - if (Angle == -32768) return 0; - return -sin(-Angle); - } - int32 S = SinTable[Angle >> 8] + (MulTable[Angle & 0xff] * SinTable[0x40 + (Angle >> 8)] >> 15); - if (S > 32767) S = 32767; - return (int16) S; -} - -////////////////////////////////////////////////////////////////// - -// Calculate the cosine of the input parameter. -// It's used the same method than in sin(int16) - -int16 Dsp1::cos(int16 Angle) -{ - if (Angle < 0) { - if (Angle == -32768) return -32768; - Angle = -Angle; - } - int32 S = SinTable[0x40 + (Angle >> 8)] - (MulTable[Angle & 0xff] * SinTable[Angle >> 8] >> 15); - if (S < -32768) S = -32767; - return (int16) S; -} - -////////////////////////////////////////////////////////////////// - -// Determines the inverse of a floating point decimal number -// iCoefficient*2^iExponent = 1/(Coefficient*2^Exponent), with the output -// normalized (iCoefficient represents a number whose absolute value is between 1/2 and 1) -// To invert 'Coefficient' a first initial guess is taken from a look-up table -// and, then, two iterations of the Newton method (applied to the function -// f(x)=1/(2*x)-Coefficient) are done. This results in a close approximation (iCoefficient) to a number 'y' -// that verify Coefficient*y=1/2. This is why you have to correct the exponent by one -// unit at the end. - -void Dsp1::inverse(int16 Coefficient, int16 Exponent, int16 &iCoefficient, int16 &iExponent) -{ - // Step One: Division by Zero - if (Coefficient == 0x0000) - { - iCoefficient = 0x7fff; - iExponent = 0x002f; - } - else - { - int16 Sign = 1; - - // Step Two: Remove Sign - if (Coefficient < 0) - { - if (Coefficient < -32767) Coefficient = -32767; - Coefficient = -Coefficient; - Sign = -1; - } - - // Step Three: Normalize - while (Coefficient < 0x4000) - { - Coefficient <<= 1; - Exponent--; - } - - // Step Four: Special Case - if (Coefficient == 0x4000) - if (Sign == 1) iCoefficient = 0x7fff; - else { - iCoefficient = -0x4000; - Exponent--; - } - else { - // Step Five: Initial Guess - int16 i = DataRom[((Coefficient - 0x4000) >> 7) + 0x0065]; - - // Step Six: Iterate Newton's Method - i = (i + (-i * (Coefficient * i >> 15) >> 15)) << 1; - i = (i + (-i * (Coefficient * i >> 15) >> 15)) << 1; - - iCoefficient = i * Sign; - } - - iExponent = 1 - Exponent; - } -} - -////////////////////////////////////////////////////////////////// - -int16 Dsp1::denormalizeAndClip(int16 C, int16 E) -{ - if (E > 0) { - if (C > 0) return 32767; else if (C < 0) return -32767; - } else { - if (E < 0) return C * DataRom[0x0031 + E] >> 15; - } - return C; -} - -////////////////////////////////////////////////////////////////// - -// Normalize the input number (m), understood as ranging from -1 to 1, -// to the form: Coefficient*2^Exponent, -// where the absolute value of Coefficient is >= 1/2 -// (Coefficient>=0x4000 or Coefficient <= (int16)0xc001) - -void Dsp1::normalize(int16 m, int16 &Coefficient, int16 &Exponent) -{ - int16 i = 0x4000; - int16 e = 0; - - if (m < 0) - while ((m & i) && i) - { - i >>= 1; - e++; - } - else - while (!(m & i) && i) - { - i >>= 1; - e++; - } - - if (e > 0) - Coefficient = m * DataRom[0x21 + e] << 1; - else - Coefficient = m; - - Exponent -= e; -} - -////////////////////////////////////////////////////////////////// - -// Same than 'normalize' but with an int32 input - -void Dsp1::normalizeDouble(int32 Product, int16 &Coefficient, int16 &Exponent) -{ - int16 n = Product & 0x7fff; - int16 m = Product >> 15; - int16 i = 0x4000; - int16 e = 0; - - if (m < 0) - while ((m & i) && i) - { - i >>= 1; - e++; - } - else - while (!(m & i) && i) - { - i >>= 1; - e++; - } - - if (e > 0) - { - Coefficient = m * DataRom[0x0021 + e] << 1; - - if (e < 15) - Coefficient += n * DataRom[0x0040 - e] >> 15; - else - { - i = 0x4000; - - if (m < 0) - while ((n & i) && i) - { - i >>= 1; - e++; - } - else - while (!(n & i) && i) - { - i >>= 1; - e++; - } - - if (e > 15) - Coefficient = n * DataRom[0x0012 + e] << 1; - else - Coefficient += n; - } - } - else - Coefficient = m; - - Exponent = e; -} - -////////////////////////////////////////////////////////////////// - -// Shift to the right - -int16 Dsp1::shiftR(int16 C, int16 E) -{ - return (C * DataRom[0x0031 + E] >> 15); -} - -////////////////////////////////////////////////////////////////// - -// this is, indeed, only part of the Data ROM -const int16 Dsp1::SinTable[256] = { - 0x0000, 0x0324, 0x0647, 0x096a, 0x0c8b, 0x0fab, 0x12c8, 0x15e2, - 0x18f8, 0x1c0b, 0x1f19, 0x2223, 0x2528, 0x2826, 0x2b1f, 0x2e11, - 0x30fb, 0x33de, 0x36ba, 0x398c, 0x3c56, 0x3f17, 0x41ce, 0x447a, - 0x471c, 0x49b4, 0x4c3f, 0x4ebf, 0x5133, 0x539b, 0x55f5, 0x5842, - 0x5a82, 0x5cb4, 0x5ed7, 0x60ec, 0x62f2, 0x64e8, 0x66cf, 0x68a6, - 0x6a6d, 0x6c24, 0x6dca, 0x6f5f, 0x70e2, 0x7255, 0x73b5, 0x7504, - 0x7641, 0x776c, 0x7884, 0x798a, 0x7a7d, 0x7b5d, 0x7c29, 0x7ce3, - 0x7d8a, 0x7e1d, 0x7e9d, 0x7f09, 0x7f62, 0x7fa7, 0x7fd8, 0x7ff6, - 0x7fff, 0x7ff6, 0x7fd8, 0x7fa7, 0x7f62, 0x7f09, 0x7e9d, 0x7e1d, - 0x7d8a, 0x7ce3, 0x7c29, 0x7b5d, 0x7a7d, 0x798a, 0x7884, 0x776c, - 0x7641, 0x7504, 0x73b5, 0x7255, 0x70e2, 0x6f5f, 0x6dca, 0x6c24, - 0x6a6d, 0x68a6, 0x66cf, 0x64e8, 0x62f2, 0x60ec, 0x5ed7, 0x5cb4, - 0x5a82, 0x5842, 0x55f5, 0x539b, 0x5133, 0x4ebf, 0x4c3f, 0x49b4, - 0x471c, 0x447a, 0x41ce, 0x3f17, 0x3c56, 0x398c, 0x36ba, 0x33de, - 0x30fb, 0x2e11, 0x2b1f, 0x2826, 0x2528, 0x2223, 0x1f19, 0x1c0b, - 0x18f8, 0x15e2, 0x12c8, 0x0fab, 0x0c8b, 0x096a, 0x0647, 0x0324, - -0x0000, -0x0324, -0x0647, -0x096a, -0x0c8b, -0x0fab, -0x12c8, -0x15e2, - -0x18f8, -0x1c0b, -0x1f19, -0x2223, -0x2528, -0x2826, -0x2b1f, -0x2e11, - -0x30fb, -0x33de, -0x36ba, -0x398c, -0x3c56, -0x3f17, -0x41ce, -0x447a, - -0x471c, -0x49b4, -0x4c3f, -0x4ebf, -0x5133, -0x539b, -0x55f5, -0x5842, - -0x5a82, -0x5cb4, -0x5ed7, -0x60ec, -0x62f2, -0x64e8, -0x66cf, -0x68a6, - -0x6a6d, -0x6c24, -0x6dca, -0x6f5f, -0x70e2, -0x7255, -0x73b5, -0x7504, - -0x7641, -0x776c, -0x7884, -0x798a, -0x7a7d, -0x7b5d, -0x7c29, -0x7ce3, - -0x7d8a, -0x7e1d, -0x7e9d, -0x7f09, -0x7f62, -0x7fa7, -0x7fd8, -0x7ff6, - -0x7fff, -0x7ff6, -0x7fd8, -0x7fa7, -0x7f62, -0x7f09, -0x7e9d, -0x7e1d, - -0x7d8a, -0x7ce3, -0x7c29, -0x7b5d, -0x7a7d, -0x798a, -0x7884, -0x776c, - -0x7641, -0x7504, -0x73b5, -0x7255, -0x70e2, -0x6f5f, -0x6dca, -0x6c24, - -0x6a6d, -0x68a6, -0x66cf, -0x64e8, -0x62f2, -0x60ec, -0x5ed7, -0x5cb4, - -0x5a82, -0x5842, -0x55f5, -0x539b, -0x5133, -0x4ebf, -0x4c3f, -0x49b4, - -0x471c, -0x447a, -0x41ce, -0x3f17, -0x3c56, -0x398c, -0x36ba, -0x33de, - -0x30fb, -0x2e11, -0x2b1f, -0x2826, -0x2528, -0x2223, -0x1f19, -0x1c0b, - -0x18f8, -0x15e2, -0x12c8, -0x0fab, -0x0c8b, -0x096a, -0x0647, -0x0324}; - - ////////////////////////////////////////////////////////////////// - -// Optimised for Performance - const int16 Dsp1::MulTable[256] = { - 0x0000, 0x0003, 0x0006, 0x0009, 0x000c, 0x000f, 0x0012, 0x0015, - 0x0019, 0x001c, 0x001f, 0x0022, 0x0025, 0x0028, 0x002b, 0x002f, - 0x0032, 0x0035, 0x0038, 0x003b, 0x003e, 0x0041, 0x0045, 0x0048, - 0x004b, 0x004e, 0x0051, 0x0054, 0x0057, 0x005b, 0x005e, 0x0061, - 0x0064, 0x0067, 0x006a, 0x006d, 0x0071, 0x0074, 0x0077, 0x007a, - 0x007d, 0x0080, 0x0083, 0x0087, 0x008a, 0x008d, 0x0090, 0x0093, - 0x0096, 0x0099, 0x009d, 0x00a0, 0x00a3, 0x00a6, 0x00a9, 0x00ac, - 0x00af, 0x00b3, 0x00b6, 0x00b9, 0x00bc, 0x00bf, 0x00c2, 0x00c5, - 0x00c9, 0x00cc, 0x00cf, 0x00d2, 0x00d5, 0x00d8, 0x00db, 0x00df, - 0x00e2, 0x00e5, 0x00e8, 0x00eb, 0x00ee, 0x00f1, 0x00f5, 0x00f8, - 0x00fb, 0x00fe, 0x0101, 0x0104, 0x0107, 0x010b, 0x010e, 0x0111, - 0x0114, 0x0117, 0x011a, 0x011d, 0x0121, 0x0124, 0x0127, 0x012a, - 0x012d, 0x0130, 0x0133, 0x0137, 0x013a, 0x013d, 0x0140, 0x0143, - 0x0146, 0x0149, 0x014d, 0x0150, 0x0153, 0x0156, 0x0159, 0x015c, - 0x015f, 0x0163, 0x0166, 0x0169, 0x016c, 0x016f, 0x0172, 0x0175, - 0x0178, 0x017c, 0x017f, 0x0182, 0x0185, 0x0188, 0x018b, 0x018e, - 0x0192, 0x0195, 0x0198, 0x019b, 0x019e, 0x01a1, 0x01a4, 0x01a8, - 0x01ab, 0x01ae, 0x01b1, 0x01b4, 0x01b7, 0x01ba, 0x01be, 0x01c1, - 0x01c4, 0x01c7, 0x01ca, 0x01cd, 0x01d0, 0x01d4, 0x01d7, 0x01da, - 0x01dd, 0x01e0, 0x01e3, 0x01e6, 0x01ea, 0x01ed, 0x01f0, 0x01f3, - 0x01f6, 0x01f9, 0x01fc, 0x0200, 0x0203, 0x0206, 0x0209, 0x020c, - 0x020f, 0x0212, 0x0216, 0x0219, 0x021c, 0x021f, 0x0222, 0x0225, - 0x0228, 0x022c, 0x022f, 0x0232, 0x0235, 0x0238, 0x023b, 0x023e, - 0x0242, 0x0245, 0x0248, 0x024b, 0x024e, 0x0251, 0x0254, 0x0258, - 0x025b, 0x025e, 0x0261, 0x0264, 0x0267, 0x026a, 0x026e, 0x0271, - 0x0274, 0x0277, 0x027a, 0x027d, 0x0280, 0x0284, 0x0287, 0x028a, - 0x028d, 0x0290, 0x0293, 0x0296, 0x029a, 0x029d, 0x02a0, 0x02a3, - 0x02a6, 0x02a9, 0x02ac, 0x02b0, 0x02b3, 0x02b6, 0x02b9, 0x02bc, - 0x02bf, 0x02c2, 0x02c6, 0x02c9, 0x02cc, 0x02cf, 0x02d2, 0x02d5, - 0x02d8, 0x02db, 0x02df, 0x02e2, 0x02e5, 0x02e8, 0x02eb, 0x02ee, - 0x02f1, 0x02f5, 0x02f8, 0x02fb, 0x02fe, 0x0301, 0x0304, 0x0307, - 0x030b, 0x030e, 0x0311, 0x0314, 0x0317, 0x031a, 0x031d, 0x0321}; - -////////////////////////////////////////////////////////////////// - -// Data ROM, as logged from a DSP-1B with the 0x1f command; -// it contains the tables and constants used by the commands. -// The tables used are: two shift tables (0x022-0x031 and 0x031-0x040 -this last one -// with an error in 0x03c which has survived to all the DSP-1 revisions-); a inverse -// table (used as initial guess) at 0x065-0x0e4; a square root table (used also -// as initial guess) at 0x0e5-0x115; two sin and cos tables (used as nodes to construct -// a interpolation curve) at, respectively, 0x116-0x197 and 0x196-0x215. -// As a curiosity, in the positions 0x21c-0x31c it's contained a -// 257-points arccos table that, apparently, have been not used anywhere -// (maybe for the MaxAZS_Exp table?). - const uint16 Dsp1::DataRom[1024] = { - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, - 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, - 0x4000, 0x7fff, 0x4000, 0x2000, 0x1000, 0x0800, 0x0400, 0x0200, - 0x0100, 0x0080, 0x0040, 0x0020, 0x0001, 0x0008, 0x0004, 0x0002, - 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x8000, 0xffe5, 0x0100, 0x7fff, 0x7f02, 0x7e08, - 0x7d12, 0x7c1f, 0x7b30, 0x7a45, 0x795d, 0x7878, 0x7797, 0x76ba, - 0x75df, 0x7507, 0x7433, 0x7361, 0x7293, 0x71c7, 0x70fe, 0x7038, - 0x6f75, 0x6eb4, 0x6df6, 0x6d3a, 0x6c81, 0x6bca, 0x6b16, 0x6a64, - 0x69b4, 0x6907, 0x685b, 0x67b2, 0x670b, 0x6666, 0x65c4, 0x6523, - 0x6484, 0x63e7, 0x634c, 0x62b3, 0x621c, 0x6186, 0x60f2, 0x6060, - 0x5fd0, 0x5f41, 0x5eb5, 0x5e29, 0x5d9f, 0x5d17, 0x5c91, 0x5c0c, - 0x5b88, 0x5b06, 0x5a85, 0x5a06, 0x5988, 0x590b, 0x5890, 0x5816, - 0x579d, 0x5726, 0x56b0, 0x563b, 0x55c8, 0x5555, 0x54e4, 0x5474, - 0x5405, 0x5398, 0x532b, 0x52bf, 0x5255, 0x51ec, 0x5183, 0x511c, - 0x50b6, 0x5050, 0x4fec, 0x4f89, 0x4f26, 0x4ec5, 0x4e64, 0x4e05, - 0x4da6, 0x4d48, 0x4cec, 0x4c90, 0x4c34, 0x4bda, 0x4b81, 0x4b28, - 0x4ad0, 0x4a79, 0x4a23, 0x49cd, 0x4979, 0x4925, 0x48d1, 0x487f, - 0x482d, 0x47dc, 0x478c, 0x473c, 0x46ed, 0x469f, 0x4651, 0x4604, - 0x45b8, 0x456c, 0x4521, 0x44d7, 0x448d, 0x4444, 0x43fc, 0x43b4, - 0x436d, 0x4326, 0x42e0, 0x429a, 0x4255, 0x4211, 0x41cd, 0x4189, - 0x4146, 0x4104, 0x40c2, 0x4081, 0x4040, 0x3fff, 0x41f7, 0x43e1, - 0x45bd, 0x478d, 0x4951, 0x4b0b, 0x4cbb, 0x4e61, 0x4fff, 0x5194, - 0x5322, 0x54a9, 0x5628, 0x57a2, 0x5914, 0x5a81, 0x5be9, 0x5d4a, - 0x5ea7, 0x5fff, 0x6152, 0x62a0, 0x63ea, 0x6530, 0x6672, 0x67b0, - 0x68ea, 0x6a20, 0x6b53, 0x6c83, 0x6daf, 0x6ed9, 0x6fff, 0x7122, - 0x7242, 0x735f, 0x747a, 0x7592, 0x76a7, 0x77ba, 0x78cb, 0x79d9, - 0x7ae5, 0x7bee, 0x7cf5, 0x7dfa, 0x7efe, 0x7fff, 0x0000, 0x0324, - 0x0647, 0x096a, 0x0c8b, 0x0fab, 0x12c8, 0x15e2, 0x18f8, 0x1c0b, - 0x1f19, 0x2223, 0x2528, 0x2826, 0x2b1f, 0x2e11, 0x30fb, 0x33de, - 0x36ba, 0x398c, 0x3c56, 0x3f17, 0x41ce, 0x447a, 0x471c, 0x49b4, - 0x4c3f, 0x4ebf, 0x5133, 0x539b, 0x55f5, 0x5842, 0x5a82, 0x5cb4, - 0x5ed7, 0x60ec, 0x62f2, 0x64e8, 0x66cf, 0x68a6, 0x6a6d, 0x6c24, - 0x6dca, 0x6f5f, 0x70e2, 0x7255, 0x73b5, 0x7504, 0x7641, 0x776c, - 0x7884, 0x798a, 0x7a7d, 0x7b5d, 0x7c29, 0x7ce3, 0x7d8a, 0x7e1d, - 0x7e9d, 0x7f09, 0x7f62, 0x7fa7, 0x7fd8, 0x7ff6, 0x7fff, 0x7ff6, - 0x7fd8, 0x7fa7, 0x7f62, 0x7f09, 0x7e9d, 0x7e1d, 0x7d8a, 0x7ce3, - 0x7c29, 0x7b5d, 0x7a7d, 0x798a, 0x7884, 0x776c, 0x7641, 0x7504, - 0x73b5, 0x7255, 0x70e2, 0x6f5f, 0x6dca, 0x6c24, 0x6a6d, 0x68a6, - 0x66cf, 0x64e8, 0x62f2, 0x60ec, 0x5ed7, 0x5cb4, 0x5a82, 0x5842, - 0x55f5, 0x539b, 0x5133, 0x4ebf, 0x4c3f, 0x49b4, 0x471c, 0x447a, - 0x41ce, 0x3f17, 0x3c56, 0x398c, 0x36ba, 0x33de, 0x30fb, 0x2e11, - 0x2b1f, 0x2826, 0x2528, 0x2223, 0x1f19, 0x1c0b, 0x18f8, 0x15e2, - 0x12c8, 0x0fab, 0x0c8b, 0x096a, 0x0647, 0x0324, 0x7fff, 0x7ff6, - 0x7fd8, 0x7fa7, 0x7f62, 0x7f09, 0x7e9d, 0x7e1d, 0x7d8a, 0x7ce3, - 0x7c29, 0x7b5d, 0x7a7d, 0x798a, 0x7884, 0x776c, 0x7641, 0x7504, - 0x73b5, 0x7255, 0x70e2, 0x6f5f, 0x6dca, 0x6c24, 0x6a6d, 0x68a6, - 0x66cf, 0x64e8, 0x62f2, 0x60ec, 0x5ed7, 0x5cb4, 0x5a82, 0x5842, - 0x55f5, 0x539b, 0x5133, 0x4ebf, 0x4c3f, 0x49b4, 0x471c, 0x447a, - 0x41ce, 0x3f17, 0x3c56, 0x398c, 0x36ba, 0x33de, 0x30fb, 0x2e11, - 0x2b1f, 0x2826, 0x2528, 0x2223, 0x1f19, 0x1c0b, 0x18f8, 0x15e2, - 0x12c8, 0x0fab, 0x0c8b, 0x096a, 0x0647, 0x0324, 0x0000, 0xfcdc, - 0xf9b9, 0xf696, 0xf375, 0xf055, 0xed38, 0xea1e, 0xe708, 0xe3f5, - 0xe0e7, 0xdddd, 0xdad8, 0xd7da, 0xd4e1, 0xd1ef, 0xcf05, 0xcc22, - 0xc946, 0xc674, 0xc3aa, 0xc0e9, 0xbe32, 0xbb86, 0xb8e4, 0xb64c, - 0xb3c1, 0xb141, 0xaecd, 0xac65, 0xaa0b, 0xa7be, 0xa57e, 0xa34c, - 0xa129, 0x9f14, 0x9d0e, 0x9b18, 0x9931, 0x975a, 0x9593, 0x93dc, - 0x9236, 0x90a1, 0x8f1e, 0x8dab, 0x8c4b, 0x8afc, 0x89bf, 0x8894, - 0x877c, 0x8676, 0x8583, 0x84a3, 0x83d7, 0x831d, 0x8276, 0x81e3, - 0x8163, 0x80f7, 0x809e, 0x8059, 0x8028, 0x800a, 0x6488, 0x0080, - 0x03ff, 0x0116, 0x0002, 0x0080, 0x4000, 0x3fd7, 0x3faf, 0x3f86, - 0x3f5d, 0x3f34, 0x3f0c, 0x3ee3, 0x3eba, 0x3e91, 0x3e68, 0x3e40, - 0x3e17, 0x3dee, 0x3dc5, 0x3d9c, 0x3d74, 0x3d4b, 0x3d22, 0x3cf9, - 0x3cd0, 0x3ca7, 0x3c7f, 0x3c56, 0x3c2d, 0x3c04, 0x3bdb, 0x3bb2, - 0x3b89, 0x3b60, 0x3b37, 0x3b0e, 0x3ae5, 0x3abc, 0x3a93, 0x3a69, - 0x3a40, 0x3a17, 0x39ee, 0x39c5, 0x399c, 0x3972, 0x3949, 0x3920, - 0x38f6, 0x38cd, 0x38a4, 0x387a, 0x3851, 0x3827, 0x37fe, 0x37d4, - 0x37aa, 0x3781, 0x3757, 0x372d, 0x3704, 0x36da, 0x36b0, 0x3686, - 0x365c, 0x3632, 0x3609, 0x35df, 0x35b4, 0x358a, 0x3560, 0x3536, - 0x350c, 0x34e1, 0x34b7, 0x348d, 0x3462, 0x3438, 0x340d, 0x33e3, - 0x33b8, 0x338d, 0x3363, 0x3338, 0x330d, 0x32e2, 0x32b7, 0x328c, - 0x3261, 0x3236, 0x320b, 0x31df, 0x31b4, 0x3188, 0x315d, 0x3131, - 0x3106, 0x30da, 0x30ae, 0x3083, 0x3057, 0x302b, 0x2fff, 0x2fd2, - 0x2fa6, 0x2f7a, 0x2f4d, 0x2f21, 0x2ef4, 0x2ec8, 0x2e9b, 0x2e6e, - 0x2e41, 0x2e14, 0x2de7, 0x2dba, 0x2d8d, 0x2d60, 0x2d32, 0x2d05, - 0x2cd7, 0x2ca9, 0x2c7b, 0x2c4d, 0x2c1f, 0x2bf1, 0x2bc3, 0x2b94, - 0x2b66, 0x2b37, 0x2b09, 0x2ada, 0x2aab, 0x2a7c, 0x2a4c, 0x2a1d, - 0x29ed, 0x29be, 0x298e, 0x295e, 0x292e, 0x28fe, 0x28ce, 0x289d, - 0x286d, 0x283c, 0x280b, 0x27da, 0x27a9, 0x2777, 0x2746, 0x2714, - 0x26e2, 0x26b0, 0x267e, 0x264c, 0x2619, 0x25e7, 0x25b4, 0x2581, - 0x254d, 0x251a, 0x24e6, 0x24b2, 0x247e, 0x244a, 0x2415, 0x23e1, - 0x23ac, 0x2376, 0x2341, 0x230b, 0x22d6, 0x229f, 0x2269, 0x2232, - 0x21fc, 0x21c4, 0x218d, 0x2155, 0x211d, 0x20e5, 0x20ad, 0x2074, - 0x203b, 0x2001, 0x1fc7, 0x1f8d, 0x1f53, 0x1f18, 0x1edd, 0x1ea1, - 0x1e66, 0x1e29, 0x1ded, 0x1db0, 0x1d72, 0x1d35, 0x1cf6, 0x1cb8, - 0x1c79, 0x1c39, 0x1bf9, 0x1bb8, 0x1b77, 0x1b36, 0x1af4, 0x1ab1, - 0x1a6e, 0x1a2a, 0x19e6, 0x19a1, 0x195c, 0x1915, 0x18ce, 0x1887, - 0x183f, 0x17f5, 0x17ac, 0x1761, 0x1715, 0x16c9, 0x167c, 0x162e, - 0x15df, 0x158e, 0x153d, 0x14eb, 0x1497, 0x1442, 0x13ec, 0x1395, - 0x133c, 0x12e2, 0x1286, 0x1228, 0x11c9, 0x1167, 0x1104, 0x109e, - 0x1036, 0x0fcc, 0x0f5f, 0x0eef, 0x0e7b, 0x0e04, 0x0d89, 0x0d0a, - 0x0c86, 0x0bfd, 0x0b6d, 0x0ad6, 0x0a36, 0x098d, 0x08d7, 0x0811, - 0x0736, 0x063e, 0x0519, 0x039a, 0x0000, 0x7fff, 0x0100, 0x0080, - 0x021d, 0x00c8, 0x00ce, 0x0048, 0x0a26, 0x277a, 0x00ce, 0x6488, - 0x14ac, 0x0001, 0x00f9, 0x00fc, 0x00ff, 0x00fc, 0x00f9, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}; - -////////////////////////////////////////////////////////////////// - -#endif diff --git a/bsnes/snes/chip/dsp1/dsp1emu.hpp b/bsnes/snes/chip/dsp1/dsp1emu.hpp deleted file mode 100755 index 9ae313ac..00000000 --- a/bsnes/snes/chip/dsp1/dsp1emu.hpp +++ /dev/null @@ -1,129 +0,0 @@ -// DSP-1's emulation code -// -// Based on research by Overload, The Dumper, Neviksti and Andreas Naive -// Date: June 2006 - -#ifndef __DSP1EMUL_H -#define __DSP1EMUL_H - -#define DSP1_VERSION 0x0102 - -class Dsp1 -{ - public: - // The DSP-1 status register has 16 bits, but only - // the upper 8 bits can be accessed from an external device, so all these - // positions are referred to the upper byte (bits D8 to D15) - enum SrFlags {DRC=0x04, DRS=0x10, RQM=0x80}; - - // According to Overload's docs, these are the meanings of the flags: - // DRC: The Data Register Control (DRC) bit specifies the data transfer length to and from the host CPU. - // 0: Data transfer to and from the DSP-1 is 16 bits. - // 1: Data transfer to and from the DSP-1 is 8 bits. - // DRS: The Data Register Status (DRS) bit indicates the data transfer status in the case of transfering 16-bit data. - // 0: Data transfer has terminated. - // 1: Data transfer in progress. - // RQM: The Request for Master (RQM) indicates that the DSP1 is requesting host CPU for data read/write. - // 0: Internal Data Register Transfer. - // 1: External Data Register Transfer. - - Dsp1(); - uint8 getSr(); // return the status register's high byte - uint8 getDr(); - void setDr(uint8 iDr); - void reset(); - - void serialize(serializer&); - - private: - enum FsmMajorState {WAIT_COMMAND, READ_DATA, WRITE_DATA}; - enum MaxDataAccesses {MAX_READS=7, MAX_WRITES=1024}; - - struct Command { - void (Dsp1::*callback)(int16 *, int16 *); - unsigned int reads; - unsigned int writes; - }; - - static const Command mCommandTable[]; - static const int16 MaxAZS_Exp[16]; - static const int16 SinTable[]; - static const int16 MulTable[]; - static const uint16 DataRom[]; - - struct SharedData { // some RAM variables shared between commands - int16 MatrixA[3][3]; // attitude matrix A - int16 MatrixB[3][3]; - int16 MatrixC[3][3]; - int16 CentreX, CentreY, CentreZ; // center of projection - int16 CentreZ_C, CentreZ_E; - int16 VOffset; // vertical offset of the screen with regard to the centre of projection - int16 Les, C_Les, E_Les; - int16 SinAas, CosAas; - int16 SinAzs, CosAzs; - int16 SinAZS, CosAZS; - int16 SecAZS_C1, SecAZS_E1; - int16 SecAZS_C2, SecAZS_E2; - int16 Nx, Ny, Nz; // normal vector to the screen (norm 1, points toward the center of projection) - int16 Gx, Gy, Gz; // center of the screen (global coordinates) - int16 Hx, Hy; // horizontal vector of the screen (Hz=0, norm 1, points toward the right of the screen) - int16 Vx, Vy, Vz; // vertical vector of the screen (norm 1, points toward the top of the screen) - - } shared; - - uint8 mSr; // status register - int mSrLowByteAccess; - uint16 mDr; // "internal" representation of the data register - unsigned mFsmMajorState; // current major state of the FSM - uint8 mCommand; // current command processed by the FSM - uint8 mDataCounter; // #uint16 read/writes counter used by the FSM - int16 mReadBuffer[MAX_READS]; - int16 mWriteBuffer[MAX_WRITES]; - bool mFreeze; // need explanation? ;) - - void fsmStep(bool read, uint8 &data); // FSM logic - - // commands - void memoryTest(int16 *input, int16 *output); - void memoryDump(int16 *input, int16 *output); - void memorySize(int16 *input, int16 *output); - void multiply(int16* input, int16* output); - void multiply2(int16* input, int16* output); - void inverse(int16 *input, int16 *output); - void triangle(int16 *input, int16 *output); - void radius(int16 *input, int16 *output); - void range(int16 *input, int16 *output); - void range2(int16 *input, int16 *output); - void distance(int16 *input, int16 *output); - void rotate(int16 *input, int16 *output); - void polar(int16 *input, int16 *output); - void attitudeA(int16 *input, int16 *output); - void attitudeB(int16 *input, int16 *output); - void attitudeC(int16 *input, int16 *output); - void objectiveA(int16 *input, int16 *output); - void objectiveB(int16 *input, int16 *output); - void objectiveC(int16 *input, int16 *output); - void subjectiveA(int16 *input, int16 *output); - void subjectiveB(int16 *input, int16 *output); - void subjectiveC(int16 *input, int16 *output); - void scalarA(int16 *input, int16 *output); - void scalarB(int16 *input, int16 *output); - void scalarC(int16 *input, int16 *output); - void gyrate(int16 *input, int16 *output); - void parameter(int16 *input, int16 *output); - void raster(int16 *input, int16 *output); - void target(int16 *input, int16 *output); - void project(int16 *input, int16 *output); - - // auxiliar functions - int16 sin(int16 Angle); - int16 cos(int16 Angle); - void inverse(int16 Coefficient, int16 Exponent, int16 &iCoefficient, int16 &iExponent); - int16 denormalizeAndClip(int16 C, int16 E); - void normalize(int16 m, int16 &Coefficient, int16 &Exponent); - void normalizeDouble(int32 Product, int16 &Coefficient, int16 &Exponent); - int16 shiftR(int16 C, int16 E); -}; - -#endif - diff --git a/bsnes/snes/chip/dsp1/serialization.cpp b/bsnes/snes/chip/dsp1/serialization.cpp deleted file mode 100755 index f7edb381..00000000 --- a/bsnes/snes/chip/dsp1/serialization.cpp +++ /dev/null @@ -1,56 +0,0 @@ -#ifdef DSP1_CPP - -void DSP1::serialize(serializer &s) { - dsp1.serialize(s); -} - -void Dsp1::serialize(serializer &s) { - for(unsigned i = 0; i < 3; i++) { - s.array(shared.MatrixA[i]); - s.array(shared.MatrixB[i]); - s.array(shared.MatrixC[i]); - } - - s.integer(shared.CentreX); - s.integer(shared.CentreY); - s.integer(shared.CentreZ); - s.integer(shared.CentreZ_C); - s.integer(shared.CentreZ_E); - s.integer(shared.VOffset); - s.integer(shared.Les); - s.integer(shared.C_Les); - s.integer(shared.E_Les); - s.integer(shared.SinAas); - s.integer(shared.CosAas); - s.integer(shared.SinAzs); - s.integer(shared.CosAzs); - s.integer(shared.SinAZS); - s.integer(shared.CosAZS); - s.integer(shared.SecAZS_C1); - s.integer(shared.SecAZS_E1); - s.integer(shared.SecAZS_C2); - s.integer(shared.SecAZS_E2); - s.integer(shared.Nx); - s.integer(shared.Ny); - s.integer(shared.Nz); - s.integer(shared.Gx); - s.integer(shared.Gy); - s.integer(shared.Gz); - s.integer(shared.Hx); - s.integer(shared.Hy); - s.integer(shared.Vx); - s.integer(shared.Vy); - s.integer(shared.Vz); - - s.integer(mSr); - s.integer(mSrLowByteAccess); - s.integer(mDr); - s.integer(mFsmMajorState); - s.integer(mCommand); - s.integer(mDataCounter); - s.array(mReadBuffer); - s.array(mWriteBuffer); - s.integer(mFreeze); -} - -#endif diff --git a/bsnes/snes/chip/dsp2/dsp2.cpp b/bsnes/snes/chip/dsp2/dsp2.cpp deleted file mode 100755 index bb33ba35..00000000 --- a/bsnes/snes/chip/dsp2/dsp2.cpp +++ /dev/null @@ -1,153 +0,0 @@ -#include - -#define DSP2_CPP -namespace SNES { - -DSP2 dsp2; -DSP2DR dsp2dr; -DSP2SR dsp2sr; - -#include "serialization.cpp" -#include "opcodes.cpp" - -void DSP2::init() { -} - -void DSP2::enable() { -} - -void DSP2::power() { - reset(); -} - -void DSP2::reset() { - status.waiting_for_command = true; - status.in_count = 0; - status.in_index = 0; - status.out_count = 0; - status.out_index = 0; - - status.op05transparent = 0; - status.op05haslen = false; - status.op05len = 0; - status.op06haslen = false; - status.op06len = 0; - status.op09word1 = 0; - status.op09word2 = 0; - status.op0dhaslen = false; - status.op0doutlen = 0; - status.op0dinlen = 0; -} - -uint8 DSP2::read(unsigned addr) { - uint8 r = 0xff; - if(status.out_count) { - r = status.output[status.out_index++]; - status.out_index &= 511; - if(status.out_count == status.out_index) { - status.out_count = 0; - } - } - return r; -} - -void DSP2::write(unsigned addr, uint8 data) { - if(status.waiting_for_command) { - status.command = data; - status.in_index = 0; - status.waiting_for_command = false; - - switch(data) { - case 0x01: status.in_count = 32; break; - case 0x03: status.in_count = 1; break; - case 0x05: status.in_count = 1; break; - case 0x06: status.in_count = 1; break; - case 0x07: break; - case 0x08: break; - case 0x09: status.in_count = 4; break; - case 0x0d: status.in_count = 2; break; - case 0x0f: status.in_count = 0; break; - } - } else { - status.parameters[status.in_index++] = data; - status.in_index &= 511; - } - - if(status.in_count == status.in_index) { - status.waiting_for_command = true; - status.out_index = 0; - switch(status.command) { - case 0x01: { - status.out_count = 32; - op01(); - } break; - - case 0x03: { - op03(); - } break; - - case 0x05: { - if(status.op05haslen) { - status.op05haslen = false; - status.out_count = status.op05len; - op05(); - } else { - status.op05len = status.parameters[0]; - status.in_index = 0; - status.in_count = status.op05len * 2; - status.op05haslen = true; - if(data)status.waiting_for_command = false; - } - } break; - - case 0x06: { - if(status.op06haslen) { - status.op06haslen = false; - status.out_count = status.op06len; - op06(); - } else { - status.op06len = status.parameters[0]; - status.in_index = 0; - status.in_count = status.op06len; - status.op06haslen = true; - if(data)status.waiting_for_command = false; - } - } break; - - case 0x07: break; - case 0x08: break; - - case 0x09: { - op09(); - } break; - - case 0x0d: { - if(status.op0dhaslen) { - status.op0dhaslen = false; - status.out_count = status.op0doutlen; - op0d(); - } else { - status.op0dinlen = status.parameters[0]; - status.op0doutlen = status.parameters[1]; - status.in_index = 0; - status.in_count = (status.op0dinlen + 1) >> 1; - status.op0dhaslen = true; - if(data)status.waiting_for_command = false; - } - } break; - - case 0x0f: break; - } - } -} - -DSP2::DSP2() {} -DSP2::~DSP2() {} - -uint8 DSP2DR::read(unsigned addr) { return dsp2.read(addr); } -void DSP2DR::write(unsigned addr, uint8 data) { dsp2.write(addr, data); } - -uint8 DSP2SR::read(unsigned addr) { return 0x00; } -void DSP2SR::write(unsigned addr, uint8 data) {} - -} diff --git a/bsnes/snes/chip/dsp2/dsp2.hpp b/bsnes/snes/chip/dsp2/dsp2.hpp deleted file mode 100755 index bc14a5bf..00000000 --- a/bsnes/snes/chip/dsp2/dsp2.hpp +++ /dev/null @@ -1,57 +0,0 @@ -class DSP2 { -public: - struct { - bool waiting_for_command; - unsigned command; - unsigned in_count, in_index; - unsigned out_count, out_index; - - uint8 parameters[512]; - uint8 output[512]; - - uint8 op05transparent; - bool op05haslen; - int op05len; - bool op06haslen; - int op06len; - uint16 op09word1; - uint16 op09word2; - bool op0dhaslen; - int op0doutlen; - int op0dinlen; - } status; - - void init(); - void enable(); - void power(); - void reset(); - - uint8 read(unsigned addr); - void write(unsigned addr, uint8 data); - - void serialize(serializer&); - DSP2(); - ~DSP2(); - -protected: - void op01(); - void op03(); - void op05(); - void op06(); - void op09(); - void op0d(); -}; - -class DSP2DR : public Memory { - uint8 read(unsigned addr); - void write(unsigned addr, uint8 data); -}; - -class DSP2SR : public Memory { - uint8 read(unsigned addr); - void write(unsigned addr, uint8 data); -}; - -extern DSP2 dsp2; -extern DSP2DR dsp2dr; -extern DSP2SR dsp2sr; diff --git a/bsnes/snes/chip/dsp2/opcodes.cpp b/bsnes/snes/chip/dsp2/opcodes.cpp deleted file mode 100755 index f015ac32..00000000 --- a/bsnes/snes/chip/dsp2/opcodes.cpp +++ /dev/null @@ -1,177 +0,0 @@ -#ifdef DSP2_CPP - -//convert bitmap to bitplane tile -void DSP2::op01() { -//op01 size is always 32 bytes input and output -//the hardware does strange things if you vary the size - -unsigned char c0, c1, c2, c3; -unsigned char *p1 = status.parameters; -unsigned char *p2a = status.output; -unsigned char *p2b = status.output + 16; //halfway - -//process 8 blocks of 4 bytes each - for(int j = 0; j < 8; j++) { - c0 = *p1++; - c1 = *p1++; - c2 = *p1++; - c3 = *p1++; - - *p2a++ = (c0 & 0x10) << 3 | - (c0 & 0x01) << 6 | - (c1 & 0x10) << 1 | - (c1 & 0x01) << 4 | - (c2 & 0x10) >> 1 | - (c2 & 0x01) << 2 | - (c3 & 0x10) >> 3 | - (c3 & 0x01); - - *p2a++ = (c0 & 0x20) << 2 | - (c0 & 0x02) << 5 | - (c1 & 0x20) | - (c1 & 0x02) << 3 | - (c2 & 0x20) >> 2 | - (c2 & 0x02) << 1 | - (c3 & 0x20) >> 4 | - (c3 & 0x02) >> 1; - - *p2b++ = (c0 & 0x40) << 1 | - (c0 & 0x04) << 4 | - (c1 & 0x40) >> 1 | - (c1 & 0x04) << 2 | - (c2 & 0x40) >> 3 | - (c2 & 0x04) | - (c3 & 0x40) >> 5 | - (c3 & 0x04) >> 2; - - *p2b++ = (c0 & 0x80) | - (c0 & 0x08) << 3 | - (c1 & 0x80) >> 2 | - (c1 & 0x08) << 1 | - (c2 & 0x80) >> 4 | - (c2 & 0x08) >> 1 | - (c3 & 0x80) >> 6 | - (c3 & 0x08) >> 3; - } -} - -//set transparent color -void DSP2::op03() { - status.op05transparent = status.parameters[0]; -} - -//replace bitmap using transparent color -void DSP2::op05() { -uint8 color; -// Overlay bitmap with transparency. -// Input: -// -// Bitmap 1: i[0] <=> i[size-1] -// Bitmap 2: i[size] <=> i[2*size-1] -// -// Output: -// -// Bitmap 3: o[0] <=> o[size-1] -// -// Processing: -// -// Process all 4-bit pixels (nibbles) in the bitmap -// -// if ( BM2_pixel == transparent_color ) -// pixelout = BM1_pixel -// else -// pixelout = BM2_pixel - -// The max size bitmap is limited to 255 because the size parameter is a byte -// I think size=0 is an error. The behavior of the chip on size=0 is to -// return the last value written to DR if you read DR on Op05 with -// size = 0. I don't think it's worth implementing this quirk unless it's -// proven necessary. - -unsigned char c1, c2; -unsigned char *p1 = status.parameters; -unsigned char *p2 = status.parameters + status.op05len; -unsigned char *p3 = status.output; - - color = status.op05transparent & 0x0f; - - for(int n = 0; n < status.op05len; n++) { - c1 = *p1++; - c2 = *p2++; - *p3++ = ( ((c2 >> 4) == color ) ? c1 & 0xf0 : c2 & 0xf0 ) | - ( ((c2 & 0x0f) == color ) ? c1 & 0x0f : c2 & 0x0f ); - } -} - -//reverse bitmap -void DSP2::op06() { -// Input: -// size -// bitmap - -int i, j; - for(i = 0, j = status.op06len - 1; i < status.op06len; i++, j--) { - status.output[j] = (status.parameters[i] << 4) | (status.parameters[i] >> 4); - } -} - -//multiply -void DSP2::op09() { - status.out_count = 4; - - status.op09word1 = status.parameters[0] | (status.parameters[1] << 8); - status.op09word2 = status.parameters[2] | (status.parameters[3] << 8); - -uint32 r; - r = status.op09word1 * status.op09word2; - status.output[0] = r; - status.output[1] = r >> 8; - status.output[2] = r >> 16; - status.output[3] = r >> 24; -} - -//scale bitmap -void DSP2::op0d() { -// Bit accurate hardware algorithm - uses fixed point math -// This should match the DSP2 Op0D output exactly -// I wouldn't recommend using this unless you're doing hardware debug. -// In some situations it has small visual artifacts that -// are not readily apparent on a TV screen but show up clearly -// on a monitor. Use Overload's scaling instead. -// This is for hardware verification testing. -// -// One note: the HW can do odd byte scaling but since we divide -// by two to get the count of bytes this won't work well for -// odd byte scaling (in any of the current algorithm implementations). -// So far I haven't seen Dungeon Master use it. -// If it does we can adjust the parameters and code to work with it - -uint32 multiplier; // Any size int >= 32-bits -uint32 pixloc; // match size of multiplier -int i, j; -uint8 pixelarray[512]; - if(status.op0dinlen <= status.op0doutlen) { - multiplier = 0x10000; // In our self defined fixed point 0x10000 == 1 - } else { - multiplier = (status.op0dinlen << 17) / ((status.op0doutlen << 1) + 1); - } - - pixloc = 0; - for(i = 0; i < status.op0doutlen * 2; i++) { - j = pixloc >> 16; - - if(j & 1) { - pixelarray[i] = (status.parameters[j >> 1] & 0x0f); - } else { - pixelarray[i] = (status.parameters[j >> 1] & 0xf0) >> 4; - } - - pixloc += multiplier; - } - - for(i = 0; i < status.op0doutlen; i++) { - status.output[i] = (pixelarray[i << 1] << 4) | pixelarray[(i << 1) + 1]; - } -} - -#endif diff --git a/bsnes/snes/chip/dsp2/serialization.cpp b/bsnes/snes/chip/dsp2/serialization.cpp deleted file mode 100755 index d089b0fe..00000000 --- a/bsnes/snes/chip/dsp2/serialization.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#ifdef DSP2_CPP - -void DSP2::serialize(serializer &s) { - s.integer(status.waiting_for_command); - s.integer(status.command); - s.integer(status.in_count); - s.integer(status.in_index); - s.integer(status.out_count); - s.integer(status.out_index); - - s.array(status.parameters); - s.array(status.output); - - s.integer(status.op05transparent); - s.integer(status.op05haslen); - s.integer(status.op05len); - s.integer(status.op06haslen); - s.integer(status.op06len); - s.integer(status.op09word1); - s.integer(status.op09word2); - s.integer(status.op0dhaslen); - s.integer(status.op0doutlen); - s.integer(status.op0dinlen); -} - -#endif diff --git a/bsnes/snes/chip/dsp3/dsp3.cpp b/bsnes/snes/chip/dsp3/dsp3.cpp deleted file mode 100755 index bf60c578..00000000 --- a/bsnes/snes/chip/dsp3/dsp3.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include - -#define DSP3_CPP -namespace SNES { - -DSP3 dsp3; - -namespace DSP3i { - #define bool8 uint8 - #include "dsp3emu.c" - #undef bool8 -}; - -void DSP3::init() { -} - -void DSP3::enable() { -} - -void DSP3::power() { - reset(); -} - -void DSP3::reset() { - DSP3i::DSP3_Reset(); -} - -uint8 DSP3::read(unsigned addr) { - DSP3i::dsp3_address = addr & 0xffff; - DSP3i::DSP3GetByte(); - return DSP3i::dsp3_byte; -} - -void DSP3::write(unsigned addr, uint8 data) { - DSP3i::dsp3_address = addr & 0xffff; - DSP3i::dsp3_byte = data; - DSP3i::DSP3SetByte(); -} - -} diff --git a/bsnes/snes/chip/dsp3/dsp3.hpp b/bsnes/snes/chip/dsp3/dsp3.hpp deleted file mode 100755 index b3353e33..00000000 --- a/bsnes/snes/chip/dsp3/dsp3.hpp +++ /dev/null @@ -1,12 +0,0 @@ -class DSP3 : public Memory { -public: - void init(); - void enable(); - void power(); - void reset(); - - uint8 read (unsigned addr); - void write(unsigned addr, uint8 data); -}; - -extern DSP3 dsp3; diff --git a/bsnes/snes/chip/dsp3/dsp3emu.c b/bsnes/snes/chip/dsp3/dsp3emu.c deleted file mode 100755 index 9e656776..00000000 --- a/bsnes/snes/chip/dsp3/dsp3emu.c +++ /dev/null @@ -1,1146 +0,0 @@ -#ifdef DSP3_CPP - -//DSP-3 emulator code -//Copyright (c) 2003-2006 John Weidman, Kris Bleakley, Lancer, z80 gaiden - -uint16 DSP3_DataROM[1024] = { - 0x8000, 0x4000, 0x2000, 0x1000, 0x0800, 0x0400, 0x0200, 0x0100, - 0x0080, 0x0040, 0x0020, 0x0010, 0x0008, 0x0004, 0x0002, 0x0001, - 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, - 0x0000, 0x000f, 0x0400, 0x0200, 0x0140, 0x0400, 0x0200, 0x0040, - 0x007d, 0x007e, 0x007e, 0x007b, 0x007c, 0x007d, 0x007b, 0x007c, - 0x0002, 0x0020, 0x0030, 0x0000, 0x000d, 0x0019, 0x0026, 0x0032, - 0x003e, 0x004a, 0x0056, 0x0062, 0x006d, 0x0079, 0x0084, 0x008e, - 0x0098, 0x00a2, 0x00ac, 0x00b5, 0x00be, 0x00c6, 0x00ce, 0x00d5, - 0x00dc, 0x00e2, 0x00e7, 0x00ec, 0x00f1, 0x00f5, 0x00f8, 0x00fb, - 0x00fd, 0x00ff, 0x0100, 0x0100, 0x0100, 0x00ff, 0x00fd, 0x00fb, - 0x00f8, 0x00f5, 0x00f1, 0x00ed, 0x00e7, 0x00e2, 0x00dc, 0x00d5, - 0x00ce, 0x00c6, 0x00be, 0x00b5, 0x00ac, 0x00a2, 0x0099, 0x008e, - 0x0084, 0x0079, 0x006e, 0x0062, 0x0056, 0x004a, 0x003e, 0x0032, - 0x0026, 0x0019, 0x000d, 0x0000, 0xfff3, 0xffe7, 0xffdb, 0xffce, - 0xffc2, 0xffb6, 0xffaa, 0xff9e, 0xff93, 0xff87, 0xff7d, 0xff72, - 0xff68, 0xff5e, 0xff54, 0xff4b, 0xff42, 0xff3a, 0xff32, 0xff2b, - 0xff25, 0xff1e, 0xff19, 0xff14, 0xff0f, 0xff0b, 0xff08, 0xff05, - 0xff03, 0xff01, 0xff00, 0xff00, 0xff00, 0xff01, 0xff03, 0xff05, - 0xff08, 0xff0b, 0xff0f, 0xff13, 0xff18, 0xff1e, 0xff24, 0xff2b, - 0xff32, 0xff3a, 0xff42, 0xff4b, 0xff54, 0xff5d, 0xff67, 0xff72, - 0xff7c, 0xff87, 0xff92, 0xff9e, 0xffa9, 0xffb5, 0xffc2, 0xffce, - 0xffda, 0xffe7, 0xfff3, 0x002b, 0x007f, 0x0020, 0x00ff, 0xff00, - 0xffbe, 0x0000, 0x0044, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0xffc1, 0x0001, 0x0002, 0x0045, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0xffc5, 0x0003, 0x0004, 0x0005, 0x0047, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0xffca, 0x0006, 0x0007, 0x0008, - 0x0009, 0x004a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0xffd0, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x004e, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0xffd7, 0x000f, 0x0010, 0x0011, - 0x0012, 0x0013, 0x0014, 0x0053, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0xffdf, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, - 0x0059, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0xffe8, 0x001c, 0x001d, 0x001e, - 0x001f, 0x0020, 0x0021, 0x0022, 0x0023, 0x0060, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0xfff2, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, - 0x002b, 0x002c, 0x0068, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0xfffd, 0x002d, 0x002e, 0x002f, - 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0071, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0xffc7, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, - 0x003e, 0x003f, 0x0040, 0x0041, 0x007b, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0xffd4, 0x0000, 0x0001, 0x0002, - 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, - 0x000b, 0x0044, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0xffe2, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010, 0x0011, 0x0012, - 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0050, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0xfff1, 0x0019, 0x001a, 0x001b, - 0x001c, 0x001d, 0x001e, 0x001f, 0x0020, 0x0021, 0x0022, 0x0023, - 0x0024, 0x0025, 0x0026, 0x005d, 0x0000, 0x0000, 0x0000, 0x0000, - 0xffcb, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, - 0x002e, 0x002f, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, - 0x006b, 0x0000, 0x0000, 0x0000, 0xffdc, 0x0000, 0x0001, 0x0002, - 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, - 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0044, 0x0000, 0x0000, - 0xffee, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, - 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, - 0x001f, 0x0020, 0x0054, 0x0000, 0xffee, 0x0021, 0x0022, 0x0023, - 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, - 0x002c, 0x002d, 0x002e, 0x002f, 0x0030, 0x0031, 0x0032, 0x0065, - 0xffbe, 0x0000, 0xfeac, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0xffc1, 0x0001, 0x0002, 0xfead, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0xffc5, 0x0003, 0x0004, 0x0005, 0xfeaf, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0xffca, 0x0006, 0x0007, 0x0008, - 0x0009, 0xfeb2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0xffd0, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0xfeb6, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0xffd7, 0x000f, 0x0010, 0x0011, - 0x0012, 0x0013, 0x0014, 0xfebb, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0xffdf, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, - 0xfec1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0xffe8, 0x001c, 0x001d, 0x001e, - 0x001f, 0x0020, 0x0021, 0x0022, 0x0023, 0xfec8, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0xfff2, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, - 0x002b, 0x002c, 0xfed0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0xfffd, 0x002d, 0x002e, 0x002f, - 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0xfed9, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0xffc7, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, - 0x003e, 0x003f, 0x0040, 0x0041, 0xfee3, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0xffd4, 0x0000, 0x0001, 0x0002, - 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, - 0x000b, 0xfeac, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0xffe2, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010, 0x0011, 0x0012, - 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0xfeb8, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0xfff1, 0x0019, 0x001a, 0x001b, - 0x001c, 0x001d, 0x001e, 0x001f, 0x0020, 0x0021, 0x0022, 0x0023, - 0x0024, 0x0025, 0x0026, 0xfec5, 0x0000, 0x0000, 0x0000, 0x0000, - 0xffcb, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, - 0x002e, 0x002f, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, - 0xfed3, 0x0000, 0x0000, 0x0000, 0xffdc, 0x0000, 0x0001, 0x0002, - 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, - 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0xfeac, 0x0000, 0x0000, - 0xffee, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, - 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, - 0x001f, 0x0020, 0xfebc, 0x0000, 0xffee, 0x0021, 0x0022, 0x0023, - 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, - 0x002c, 0x002d, 0x002e, 0x002f, 0x0030, 0x0031, 0x0032, 0xfecd, - 0x0154, 0x0218, 0x0110, 0x00b0, 0x00cc, 0x00b0, 0x0088, 0x00b0, - 0x0044, 0x00b0, 0x0000, 0x00b0, 0x00fe, 0xff07, 0x0002, 0x00ff, - 0x00f8, 0x0007, 0x00fe, 0x00ee, 0x07ff, 0x0200, 0x00ef, 0xf800, - 0x0700, 0x00ee, 0xffff, 0xffff, 0xffff, 0x0000, 0x0000, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, - 0xffff, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, - 0x0000, 0xffff, 0xffff, 0x0000, 0xffff, 0x0001, 0x0000, 0x0001, - 0x0001, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, - 0xffff, 0x0001, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0xffff, - 0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0044, 0x0088, 0x00cc, - 0x0110, 0x0154, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff -}; - -void (*SetDSP3)(); -void DSP3_Command(); - -uint16 DSP3_DR; -uint16 DSP3_SR; -uint16 DSP3_MemoryIndex; - -void DSP3_Reset() -{ - DSP3_DR = 0x0080; - DSP3_SR = 0x0084; - SetDSP3 = &DSP3_Command; -} - -void DSP3_MemorySize() -{ - DSP3_DR = 0x0300; - SetDSP3 = &DSP3_Reset; -} - -void DSP3_TestMemory() -{ - DSP3_DR = 0x0000; - SetDSP3 = &DSP3_Reset; -} - -void DSP3_DumpDataROM() -{ - DSP3_DR = DSP3_DataROM[DSP3_MemoryIndex++]; - if (DSP3_MemoryIndex == 1024) - SetDSP3 = &DSP3_Reset; -} - -void DSP3_MemoryDump() -{ - DSP3_MemoryIndex = 0; - SetDSP3 = &DSP3_DumpDataROM; - DSP3_DumpDataROM(); -} - -int16 DSP3_WinLo; -int16 DSP3_WinHi; - -void DSP3_OP06() -{ - DSP3_WinLo = (uint8)(DSP3_DR); - DSP3_WinHi = (uint8)(DSP3_DR >> 8); - DSP3_Reset(); -} - -void DSP3_OP03() -{ - int16 Lo = (uint8)(DSP3_DR); - int16 Hi = (uint8)(DSP3_DR >> 8); - int16 Ofs = (DSP3_WinLo * Hi << 1) + (Lo << 1); - DSP3_DR = Ofs >> 1; - SetDSP3 = &DSP3_Reset; -} - -int16 DSP3_AddLo; -int16 DSP3_AddHi; - -void DSP3_OP07_B() -{ - int16 Ofs = (DSP3_WinLo * DSP3_AddHi << 1) + (DSP3_AddLo << 1); - DSP3_DR = Ofs >> 1; - SetDSP3 = &DSP3_Reset; -} - -void DSP3_OP07_A() -{ - int16 Lo = (uint8)(DSP3_DR); - int16 Hi = (uint8)(DSP3_DR >> 8); - - if (Lo & 1) Hi += (DSP3_AddLo & 1); - - DSP3_AddLo += Lo; - DSP3_AddHi += Hi; - - if (DSP3_AddLo < 0) - DSP3_AddLo += DSP3_WinLo; - else - if (DSP3_AddLo >= DSP3_WinLo) - DSP3_AddLo -= DSP3_WinLo; - - if (DSP3_AddHi < 0) - DSP3_AddHi += DSP3_WinHi; - else - if (DSP3_AddHi >= DSP3_WinHi) - DSP3_AddHi -= DSP3_WinHi; - - DSP3_DR = DSP3_AddLo | (DSP3_AddHi << 8) | ((DSP3_AddHi >> 8) & 0xff); - SetDSP3 = &DSP3_OP07_B; -} - -void DSP3_OP07() -{ - uint32 dataOfs = ((DSP3_DR << 1) + 0x03b2) & 0x03ff; - - DSP3_AddHi = DSP3_DataROM[dataOfs]; - DSP3_AddLo = DSP3_DataROM[dataOfs + 1]; - - SetDSP3 = &DSP3_OP07_A; - DSP3_SR = 0x0080; -} - -uint16 DSP3_Codewords; -uint16 DSP3_Outwords; -uint16 DSP3_Symbol; -uint16 DSP3_BitCount; -uint16 DSP3_Index; -uint16 DSP3_Codes[512]; -uint16 DSP3_BitsLeft; -uint16 DSP3_ReqBits; -uint16 DSP3_ReqData; -uint16 DSP3_BitCommand; -uint8 DSP3_BaseLength; -uint16 DSP3_BaseCodes; -uint16 DSP3_BaseCode; -uint8 DSP3_CodeLengths[8]; -uint16 DSP3_CodeOffsets[8]; -uint16 DSP3_LZCode; -uint8 DSP3_LZLength; - -uint16 DSP3_X; -uint16 DSP3_Y; - -void DSP3_Coordinate() -{ - DSP3_Index++; - - switch (DSP3_Index) - { - case 3: - { - if (DSP3_DR == 0xffff) - DSP3_Reset(); - break; - } - case 4: - { - DSP3_X = DSP3_DR; - break; - } - case 5: - { - DSP3_Y = DSP3_DR; - DSP3_DR = 1; - break; - } - case 6: - { - DSP3_DR = DSP3_X; - break; - } - case 7: - { - DSP3_DR = DSP3_Y; - DSP3_Index = 0; - break; - } - } -} - -uint8 DSP3_Bitmap[8]; -uint8 DSP3_Bitplane[8]; -uint16 DSP3_BMIndex; -uint16 DSP3_BPIndex; -uint16 DSP3_Count; - -void DSP3_Convert_A() -{ - if (DSP3_BMIndex < 8) - { - DSP3_Bitmap[DSP3_BMIndex++] = (uint8) (DSP3_DR); - DSP3_Bitmap[DSP3_BMIndex++] = (uint8) (DSP3_DR >> 8); - - if (DSP3_BMIndex == 8) - { - short i, j; - for (i=0; i < 8; i++) - for (j=0; j < 8; j++) - { - DSP3_Bitplane[j] <<= 1; - DSP3_Bitplane[j] |= (DSP3_Bitmap[i] >> j) & 1; - } - - DSP3_BPIndex = 0; - DSP3_Count--; - } - } - - if (DSP3_BMIndex == 8) - { - if (DSP3_BPIndex == 8) - { - if (!DSP3_Count) DSP3_Reset(); - DSP3_BMIndex = 0; - } - else - { - DSP3_DR = DSP3_Bitplane[DSP3_BPIndex++]; - DSP3_DR |= DSP3_Bitplane[DSP3_BPIndex++] << 8; - } - } -} - -void DSP3_Convert() -{ - DSP3_Count = DSP3_DR; - DSP3_BMIndex = 0; - SetDSP3 = &DSP3_Convert_A; -} - -bool DSP3_GetBits(uint8 Count) -{ - if (!DSP3_BitsLeft) - { - DSP3_BitsLeft = Count; - DSP3_ReqBits = 0; - } - - do { - if (!DSP3_BitCount) - { - DSP3_SR = 0xC0; - return false; - } - - DSP3_ReqBits <<= 1; - if (DSP3_ReqData & 0x8000) DSP3_ReqBits++; - DSP3_ReqData <<= 1; - - DSP3_BitCount--; - DSP3_BitsLeft--; - - } while (DSP3_BitsLeft); - - return true; -} - -void DSP3_Decode_Data() -{ - if (!DSP3_BitCount) - { - if (DSP3_SR & 0x40) - { - DSP3_ReqData = DSP3_DR; - DSP3_BitCount += 16; - } - else - { - DSP3_SR = 0xC0; - return; - } - } - - if (DSP3_LZCode == 1) - { - if (!DSP3_GetBits(1)) - return; - - if (DSP3_ReqBits) - DSP3_LZLength = 12; - else - DSP3_LZLength = 8; - - DSP3_LZCode++; - } - - if (DSP3_LZCode == 2) - { - if (!DSP3_GetBits(DSP3_LZLength)) - return; - - DSP3_LZCode = 0; - DSP3_Outwords--; - if (!DSP3_Outwords) SetDSP3 = &DSP3_Reset; - - DSP3_SR = 0x80; - DSP3_DR = DSP3_ReqBits; - return; - } - - if (DSP3_BaseCode == 0xffff) - { - if (!DSP3_GetBits(DSP3_BaseLength)) - return; - - DSP3_BaseCode = DSP3_ReqBits; - } - - if (!DSP3_GetBits(DSP3_CodeLengths[DSP3_BaseCode])) - return; - - DSP3_Symbol = DSP3_Codes[DSP3_CodeOffsets[DSP3_BaseCode] + DSP3_ReqBits]; - DSP3_BaseCode = 0xffff; - - if (DSP3_Symbol & 0xff00) - { - DSP3_Symbol += 0x7f02; - DSP3_LZCode++; - } - else - { - DSP3_Outwords--; - if (!DSP3_Outwords) - SetDSP3 = &DSP3_Reset; - } - - DSP3_SR = 0x80; - DSP3_DR = DSP3_Symbol; -} - -void DSP3_Decode_Tree() -{ - if (!DSP3_BitCount) - { - DSP3_ReqData = DSP3_DR; - DSP3_BitCount += 16; - } - - if (!DSP3_BaseCodes) - { - DSP3_GetBits(1); - if (DSP3_ReqBits) - { - DSP3_BaseLength = 3; - DSP3_BaseCodes = 8; - } - else - { - DSP3_BaseLength = 2; - DSP3_BaseCodes = 4; - } - } - - while (DSP3_BaseCodes) - { - if (!DSP3_GetBits(3)) - return; - - DSP3_ReqBits++; - - DSP3_CodeLengths[DSP3_Index] = (uint8) DSP3_ReqBits; - DSP3_CodeOffsets[DSP3_Index] = DSP3_Symbol; - DSP3_Index++; - - DSP3_Symbol += 1 << DSP3_ReqBits; - DSP3_BaseCodes--; - } - - DSP3_BaseCode = 0xffff; - DSP3_LZCode = 0; - - SetDSP3 = &DSP3_Decode_Data; - if (DSP3_BitCount) DSP3_Decode_Data(); -} - -void DSP3_Decode_Symbols() -{ - DSP3_ReqData = DSP3_DR; - DSP3_BitCount += 16; - - do { - - if (DSP3_BitCommand == 0xffff) - { - if (!DSP3_GetBits(2)) return; - DSP3_BitCommand = DSP3_ReqBits; - } - - switch (DSP3_BitCommand) - { - case 0: - { - if (!DSP3_GetBits(9)) return; - DSP3_Symbol = DSP3_ReqBits; - break; - } - case 1: - { - DSP3_Symbol++; - break; - } - case 2: - { - if (!DSP3_GetBits(1)) return; - DSP3_Symbol += 2 + DSP3_ReqBits; - break; - } - case 3: - { - if (!DSP3_GetBits(4)) return; - DSP3_Symbol += 4 + DSP3_ReqBits; - break; - } - } - - DSP3_BitCommand = 0xffff; - - DSP3_Codes[DSP3_Index++] = DSP3_Symbol; - DSP3_Codewords--; - - } while (DSP3_Codewords); - - DSP3_Index = 0; - DSP3_Symbol = 0; - DSP3_BaseCodes = 0; - - SetDSP3 = &DSP3_Decode_Tree; - if (DSP3_BitCount) DSP3_Decode_Tree(); -} - -void DSP3_Decode_A() -{ - DSP3_Outwords = DSP3_DR; - SetDSP3 = &DSP3_Decode_Symbols; - DSP3_BitCount = 0; - DSP3_BitsLeft = 0; - DSP3_Symbol = 0; - DSP3_Index = 0; - DSP3_BitCommand = 0xffff; - DSP3_SR = 0xC0; -} - -void DSP3_Decode() -{ - DSP3_Codewords = DSP3_DR; - SetDSP3 = &DSP3_Decode_A; -} - - -// Opcodes 1E/3E bit-perfect to 'dsp3-intro' log -// src: adapted from SD Gundam X/G-Next - -int16 op3e_x; -int16 op3e_y; - -int16 op1e_terrain[0x2000]; -int16 op1e_cost[0x2000]; -int16 op1e_weight[0x2000]; - -int16 op1e_cell; -int16 op1e_turn; -int16 op1e_search; - -int16 op1e_x; -int16 op1e_y; - -int16 op1e_min_radius; -int16 op1e_max_radius; - -int16 op1e_max_search_radius; -int16 op1e_max_path_radius; - -int16 op1e_lcv_radius; -int16 op1e_lcv_steps; -int16 op1e_lcv_turns; - -void DSP3_OP3E() -{ - op3e_x = (uint8)(DSP3_DR & 0x00ff); - op3e_y = (uint8)((DSP3_DR & 0xff00)>>8); - - DSP3_OP03(); - - op1e_terrain[ DSP3_DR ] = 0x00; - op1e_cost[ DSP3_DR ] = 0xff; - op1e_weight[ DSP3_DR ] = 0; - - op1e_max_search_radius = 0; - op1e_max_path_radius = 0; -} - -void DSP3_OP1E_A(); -void DSP3_OP1E_A1(); -void DSP3_OP1E_A2(); -void DSP3_OP1E_A3(); - -void DSP3_OP1E_B(); -void DSP3_OP1E_B1(); -void DSP3_OP1E_B2(); - -void DSP3_OP1E_C(); -void DSP3_OP1E_C1(); -void DSP3_OP1E_C2(); - -void DSP3_OP1E_D( int16, int16 *, int16 * ); -void DSP3_OP1E_D1( int16 move, int16 *lo, int16 *hi ); - -void DSP3_OP1E() -{ - int lcv; - - op1e_min_radius = (uint8)(DSP3_DR & 0x00ff); - op1e_max_radius = (uint8)((DSP3_DR & 0xff00)>>8); - - if( op1e_min_radius == 0 ) - op1e_min_radius++; - - if( op1e_max_search_radius >= op1e_min_radius ) - op1e_min_radius = op1e_max_search_radius+1; - - if( op1e_max_radius > op1e_max_search_radius ) - op1e_max_search_radius = op1e_max_radius; - - op1e_lcv_radius = op1e_min_radius; - op1e_lcv_steps = op1e_min_radius; - - op1e_lcv_turns = 6; - op1e_turn = 0; - - op1e_x = op3e_x; - op1e_y = op3e_y; - - for( lcv = 0; lcv < op1e_min_radius; lcv++ ) - DSP3_OP1E_D( op1e_turn, &op1e_x, &op1e_y ); - - DSP3_OP1E_A(); -} - -void DSP3_OP1E_A() -{ - int lcv; - - if( op1e_lcv_steps == 0 ) { - op1e_lcv_radius++; - - op1e_lcv_steps = op1e_lcv_radius; - - op1e_x = op3e_x; - op1e_y = op3e_y; - - for( lcv = 0; lcv < op1e_lcv_radius; lcv++ ) - DSP3_OP1E_D( op1e_turn, &op1e_x, &op1e_y ); - } - - if( op1e_lcv_radius > op1e_max_radius ) { - op1e_turn++; - op1e_lcv_turns--; - - op1e_lcv_radius = op1e_min_radius; - op1e_lcv_steps = op1e_min_radius; - - op1e_x = op3e_x; - op1e_y = op3e_y; - - for( lcv = 0; lcv < op1e_min_radius; lcv++ ) - DSP3_OP1E_D( op1e_turn, &op1e_x, &op1e_y ); - } - - if( op1e_lcv_turns == 0 ) { - DSP3_DR = 0xffff; - DSP3_SR = 0x0080; - SetDSP3 = &DSP3_OP1E_B; - return; - } - - DSP3_DR = (uint8)(op1e_x) | ((uint8)(op1e_y)<<8); - DSP3_OP03(); - - op1e_cell = DSP3_DR; - - DSP3_SR = 0x0080; - SetDSP3 = &DSP3_OP1E_A1; -} - -void DSP3_OP1E_A1() -{ - DSP3_SR = 0x0084; - SetDSP3 = &DSP3_OP1E_A2; -} - -void DSP3_OP1E_A2() -{ - op1e_terrain[ op1e_cell ] = (uint8)(DSP3_DR & 0x00ff); - - DSP3_SR = 0x0084; - SetDSP3 = &DSP3_OP1E_A3; -} - -void DSP3_OP1E_A3() -{ - op1e_cost[ op1e_cell ] = (uint8)(DSP3_DR & 0x00ff); - - if( op1e_lcv_radius == 1 ) { - if( op1e_terrain[ op1e_cell ] & 1 ) { - op1e_weight[ op1e_cell ] = 0xff; - } else { - op1e_weight[ op1e_cell ] = op1e_cost[ op1e_cell ]; - } - } - else { - op1e_weight[ op1e_cell ] = 0xff; - } - - DSP3_OP1E_D( (int16)(op1e_turn+2), &op1e_x, &op1e_y ); - op1e_lcv_steps--; - - DSP3_SR = 0x0080; - DSP3_OP1E_A(); -} - - -void DSP3_OP1E_B() -{ - op1e_x = op3e_x; - op1e_y = op3e_y; - op1e_lcv_radius = 1; - - op1e_search = 0; - - DSP3_OP1E_B1(); - - SetDSP3 = &DSP3_OP1E_C; -} - - -void DSP3_OP1E_B1() -{ - while( op1e_lcv_radius < op1e_max_radius ) { - op1e_y--; - - op1e_lcv_turns = 6; - op1e_turn = 5; - - while( op1e_lcv_turns ) { - op1e_lcv_steps = op1e_lcv_radius; - - while( op1e_lcv_steps ) { - DSP3_OP1E_D1( op1e_turn, &op1e_x, &op1e_y ); - - if( 0 <= op1e_y && op1e_y < DSP3_WinHi && - 0 <= op1e_x && op1e_x < DSP3_WinLo ) { - DSP3_DR = (uint8)(op1e_x) | ((uint8)(op1e_y)<<8); - DSP3_OP03(); - - op1e_cell = DSP3_DR; - if( op1e_cost[ op1e_cell ] < 0x80 && - op1e_terrain[ op1e_cell ] < 0x40 ) { - DSP3_OP1E_B2(); - } // end cell perimeter - } - - op1e_lcv_steps--; - } // end search line - - op1e_turn--; - if( op1e_turn == 0 ) op1e_turn = 6; - - op1e_lcv_turns--; - } // end circle search - - op1e_lcv_radius++; - } // end radius search -} - - -void DSP3_OP1E_B2() -{ - int16 cell; - int16 path; - int16 x,y; - int16 lcv_turns; - - path = 0xff; - lcv_turns = 6; - - while( lcv_turns ) { - x = op1e_x; - y = op1e_y; - - DSP3_OP1E_D1( lcv_turns, &x, &y ); - - DSP3_DR = (uint8)(x) | ((uint8)(y)<<8); - DSP3_OP03(); - - cell = DSP3_DR; - - if( 0 <= y && y < DSP3_WinHi && - 0 <= x && x < DSP3_WinLo ) { - - if( op1e_terrain[ cell ] < 0x80 || op1e_weight[ cell ] == 0 ) { - if( op1e_weight[ cell ] < path ) { - path = op1e_weight[ cell ]; - } - } - } // end step travel - - lcv_turns--; - } // end while turns - - if( path != 0xff ) { - op1e_weight[ op1e_cell ] = path + op1e_cost[ op1e_cell ]; - } -} - - -void DSP3_OP1E_C() -{ - int lcv; - - op1e_min_radius = (uint8)(DSP3_DR & 0x00ff); - op1e_max_radius = (uint8)((DSP3_DR & 0xff00)>>8); - - if( op1e_min_radius == 0 ) - op1e_min_radius++; - - if( op1e_max_path_radius >= op1e_min_radius ) - op1e_min_radius = op1e_max_path_radius+1; - - if( op1e_max_radius > op1e_max_path_radius ) - op1e_max_path_radius = op1e_max_radius; - - op1e_lcv_radius = op1e_min_radius; - op1e_lcv_steps = op1e_min_radius; - - op1e_lcv_turns = 6; - op1e_turn = 0; - - op1e_x = op3e_x; - op1e_y = op3e_y; - - for( lcv = 0; lcv < op1e_min_radius; lcv++ ) - DSP3_OP1E_D( op1e_turn, &op1e_x, &op1e_y ); - - DSP3_OP1E_C1(); -} - - -void DSP3_OP1E_C1() -{ - int lcv; - - if( op1e_lcv_steps == 0 ) { - op1e_lcv_radius++; - - op1e_lcv_steps = op1e_lcv_radius; - - op1e_x = op3e_x; - op1e_y = op3e_y; - - for( lcv = 0; lcv < op1e_lcv_radius; lcv++ ) - DSP3_OP1E_D( op1e_turn, &op1e_x, &op1e_y ); - } - - if( op1e_lcv_radius > op1e_max_radius ) { - op1e_turn++; - op1e_lcv_turns--; - - op1e_lcv_radius = op1e_min_radius; - op1e_lcv_steps = op1e_min_radius; - - op1e_x = op3e_x; - op1e_y = op3e_y; - - for( lcv = 0; lcv < op1e_min_radius; lcv++ ) - DSP3_OP1E_D( op1e_turn, &op1e_x, &op1e_y ); - } - - if( op1e_lcv_turns == 0 ) { - DSP3_DR = 0xffff; - DSP3_SR = 0x0080; - SetDSP3 = &DSP3_Reset; - return; - } - - DSP3_DR = (uint8)(op1e_x) | ((uint8)(op1e_y)<<8); - DSP3_OP03(); - - op1e_cell = DSP3_DR; - - DSP3_SR = 0x0080; - SetDSP3 = &DSP3_OP1E_C2; -} - - -void DSP3_OP1E_C2() -{ - DSP3_DR = op1e_weight[ op1e_cell ]; - - DSP3_OP1E_D( (int16)(op1e_turn+2), &op1e_x, &op1e_y ); - op1e_lcv_steps--; - - DSP3_SR = 0x0084; - SetDSP3 = &DSP3_OP1E_C1; -} - - -void DSP3_OP1E_D( int16 move, int16 *lo, int16 *hi ) -{ - uint32 dataOfs = ((move << 1) + 0x03b2) & 0x03ff; - int16 Lo; - int16 Hi; - - DSP3_AddHi = DSP3_DataROM[dataOfs]; - DSP3_AddLo = DSP3_DataROM[dataOfs + 1]; - - Lo = (uint8)(*lo); - Hi = (uint8)(*hi); - - if (Lo & 1) Hi += (DSP3_AddLo & 1); - - DSP3_AddLo += Lo; - DSP3_AddHi += Hi; - - if (DSP3_AddLo < 0) - DSP3_AddLo += DSP3_WinLo; - else - if (DSP3_AddLo >= DSP3_WinLo) - DSP3_AddLo -= DSP3_WinLo; - - if (DSP3_AddHi < 0) - DSP3_AddHi += DSP3_WinHi; - else - if (DSP3_AddHi >= DSP3_WinHi) - DSP3_AddHi -= DSP3_WinHi; - - *lo = DSP3_AddLo; - *hi = DSP3_AddHi; -} - - -void DSP3_OP1E_D1( int16 move, int16 *lo, int16 *hi ) -{ - //uint32 dataOfs = ((move << 1) + 0x03b2) & 0x03ff; - int16 Lo; - int16 Hi; - - const unsigned short HiAdd[] = { - 0x00, 0xFF, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, - 0x00, 0xFF, 0xFF, 0x00, 0x01, 0x00, 0xFF, 0x00 - }; - const unsigned short LoAdd[] = { - 0x00, 0x00, 0x01, 0x01, 0x00, 0xFF, 0xFF, 0x00 - }; - - if( (*lo) & 1 ) - DSP3_AddHi = HiAdd[ move + 8 ]; - else - DSP3_AddHi = HiAdd[ move + 0 ]; - DSP3_AddLo = LoAdd[ move ]; - - Lo = (uint8)(*lo); - Hi = (uint8)(*hi); - - if (Lo & 1) Hi += (DSP3_AddLo & 1); - - DSP3_AddLo += Lo; - DSP3_AddHi += Hi; - - *lo = DSP3_AddLo; - *hi = DSP3_AddHi; -} - - -void DSP3_OP10() -{ - if( DSP3_DR == 0xffff ) { - DSP3_Reset(); - } else { - // absorb 2 bytes - DSP3_DR = DSP3_DR; - } -} - - -void DSP3_OP0C_A() -{ - // absorb 2 bytes - - DSP3_DR = 0; - SetDSP3 = &DSP3_Reset; -} - - -void DSP3_OP0C() -{ - // absorb 2 bytes - - DSP3_DR = 0; - //SetDSP3 = &DSP3_OP0C_A; - SetDSP3 = &DSP3_Reset; -} - - -void DSP3_OP1C_C() -{ - // return 2 bytes - DSP3_DR = 0; - SetDSP3 = &DSP3_Reset; -} - - -void DSP3_OP1C_B() -{ - // absorb 2 bytes - - // return 2 bytes - DSP3_DR = 0; - SetDSP3 = &DSP3_OP1C_C; -} - - -void DSP3_OP1C_A() -{ - // absorb 2 bytes - - SetDSP3 = &DSP3_OP1C_B; -} - - -void DSP3_OP1C() -{ - // absorb 2 bytes - - SetDSP3 = &DSP3_OP1C_A; -} - - -void DSP3_Command() -{ - if (DSP3_DR < 0x40) - { - switch (DSP3_DR) - { - case 0x02: SetDSP3 = &DSP3_Coordinate; break; - case 0x03: SetDSP3 = &DSP3_OP03; break; - case 0x06: SetDSP3 = &DSP3_OP06; break; - case 0x07: SetDSP3 = &DSP3_OP07; return; - case 0x0c: SetDSP3 = &DSP3_OP0C; break; - case 0x0f: SetDSP3 = &DSP3_TestMemory; break; - case 0x10: SetDSP3 = &DSP3_OP10; break; - case 0x18: SetDSP3 = &DSP3_Convert; break; - case 0x1c: SetDSP3 = &DSP3_OP1C; break; - case 0x1e: SetDSP3 = &DSP3_OP1E; break; - case 0x1f: SetDSP3 = &DSP3_MemoryDump; break; - case 0x38: SetDSP3 = &DSP3_Decode; break; - case 0x3e: SetDSP3 = &DSP3_OP3E; break; - default: - return; - } - DSP3_SR = 0x0080; - DSP3_Index = 0; - } -} - -uint8 dsp3_byte; -uint16 dsp3_address; - -void DSP3SetByte() -{ - if (dsp3_address < 0xC000) - { - if (DSP3_SR & 0x04) - { - DSP3_DR = (DSP3_DR & 0xff00) + dsp3_byte; - (*SetDSP3)(); - } - else - { - DSP3_SR ^= 0x10; - - if (DSP3_SR & 0x10) - DSP3_DR = (DSP3_DR & 0xff00) + dsp3_byte; - else - { - DSP3_DR = (DSP3_DR & 0x00ff) + (dsp3_byte << 8); - (*SetDSP3)(); - } - } - } -} - -void DSP3GetByte() -{ - if (dsp3_address < 0xC000) - { - if (DSP3_SR & 0x04) - { - dsp3_byte = (uint8) DSP3_DR; - (*SetDSP3)(); - } - else - { - DSP3_SR ^= 0x10; - - if (DSP3_SR & 0x10) - dsp3_byte = (uint8) (DSP3_DR); - else - { - dsp3_byte = (uint8) (DSP3_DR >> 8); - (*SetDSP3)(); - } - } - - } - else - { - dsp3_byte = (uint8) DSP3_SR; - } -} - -void InitDSP3() -{ - DSP3_Reset(); -} - -#endif diff --git a/bsnes/snes/chip/dsp4/dsp4.cpp b/bsnes/snes/chip/dsp4/dsp4.cpp deleted file mode 100755 index c568c728..00000000 --- a/bsnes/snes/chip/dsp4/dsp4.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#include - -#define DSP4_CPP -namespace SNES { - -DSP4 dsp4; - -void DSP4::init() { -} - -void DSP4::enable() { -} - -namespace DSP4i { - inline uint16 READ_WORD(uint8 *addr) { - return (addr[0]) + (addr[1] << 8); - } - - inline uint32 READ_DWORD(uint8 *addr) { - return (addr[0]) + (addr[1] << 8) + (addr[2] << 16) + (addr[3] << 24); - } - - inline void WRITE_WORD(uint8 *addr, uint16 data) { - addr[0] = data; - addr[1] = data >> 8; - } - - #define bool8 uint8 - #include "dsp4emu.c" - #undef bool8 -}; - -void DSP4::power() { - reset(); -} - -void DSP4::reset() { - DSP4i::InitDSP4(); -} - -uint8 DSP4::read(unsigned addr) { - addr &= 0xffff; - if(addr < 0xc000) { - DSP4i::dsp4_address = addr; - DSP4i::DSP4GetByte(); - return DSP4i::dsp4_byte; - } - return 0x80; -} - -void DSP4::write(unsigned addr, uint8 data) { - addr &= 0xffff; - if(addr < 0xc000) { - DSP4i::dsp4_address = addr; - DSP4i::dsp4_byte = data; - DSP4i::DSP4SetByte(); - } -} - -} diff --git a/bsnes/snes/chip/dsp4/dsp4.hpp b/bsnes/snes/chip/dsp4/dsp4.hpp deleted file mode 100755 index 7a261192..00000000 --- a/bsnes/snes/chip/dsp4/dsp4.hpp +++ /dev/null @@ -1,12 +0,0 @@ -class DSP4 : public Memory { -public: - void init(); - void enable(); - void power(); - void reset(); - - uint8 read (unsigned addr); - void write(unsigned addr, uint8 data); -}; - -extern DSP4 dsp4; diff --git a/bsnes/snes/chip/dsp4/dsp4emu.c b/bsnes/snes/chip/dsp4/dsp4emu.c deleted file mode 100755 index 73c1ec3d..00000000 --- a/bsnes/snes/chip/dsp4/dsp4emu.c +++ /dev/null @@ -1,2150 +0,0 @@ -#ifdef DSP4_CPP - -//DSP-4 emulator code -//Copyright (c) 2004-2006 Dreamer Nom, John Weidman, Kris Bleakley, Nach, z80 gaiden - -/* -Due recognition and credit are given on Overload's DSP website. -Thank those contributors for their hard work on this chip. - - -Fixed-point math reminder: - -[sign, integer, fraction] -1.15.00 * 1.15.00 = 2.30.00 -> 1.30.00 (DSP) -> 1.31.00 (LSB is '0') -1.15.00 * 1.00.15 = 2.15.15 -> 1.15.15 (DSP) -> 1.15.16 (LSB is '0') -*/ - -#include "dsp4emu.h" - -struct DSP4_t DSP4; -struct DSP4_vars_t DSP4_vars; - -////////////////////////////////////////////////////////////// - -// input protocol - -static int16 DSP4_READ_WORD() -{ - int16 out; - - out = READ_WORD(DSP4.parameters + DSP4.in_index); - DSP4.in_index += 2; - - return out; -} - -static int32 DSP4_READ_DWORD() -{ - int32 out; - - out = READ_DWORD(DSP4.parameters + DSP4.in_index); - DSP4.in_index += 4; - - return out; -} - - -////////////////////////////////////////////////////////////// - -// output protocol - -#define DSP4_CLEAR_OUT() \ -{ DSP4.out_count = 0; DSP4.out_index = 0; } - -#define DSP4_WRITE_BYTE( d ) \ -{ WRITE_WORD( DSP4.output + DSP4.out_count, ( d ) ); DSP4.out_count++; } - -#define DSP4_WRITE_WORD( d ) \ -{ WRITE_WORD( DSP4.output + DSP4.out_count, ( d ) ); DSP4.out_count += 2; } - -#ifndef MSB_FIRST -#define DSP4_WRITE_16_WORD( d ) \ -{ memcpy(DSP4.output + DSP4.out_count, ( d ), 32); DSP4.out_count += 32; } -#else -#define DSP4_WRITE_16_WORD( d ) \ -{ int16 *p = ( d ), *end = ( d )+16; \ - for (; p != end; p++) \ - { \ - WRITE_WORD( DSP4.output + DSP4.out_count, *p ); \ - } \ - DSP4.out_count += 32; \ -} -#endif - -#ifdef PRINT_OP -#define DSP4_WRITE_DEBUG( x, d ) \ - WRITE_WORD( nop + x, d ); -#endif - -#ifdef DEBUG_DSP -#define DSP4_WRITE_DEBUG( x, d ) \ - WRITE_WORD( nop + x, d ); -#endif - -////////////////////////////////////////////////////////////// - -// used to wait for dsp i/o - -#define DSP4_WAIT( x ) \ - DSP4.in_index = 0; DSP4_vars.DSP4_Logic = x; return; - -////////////////////////////////////////////////////////////// - -// 1.7.8 -> 1.15.16 -#define SEX78( a ) ( ( (int32) ( (int16) (a) ) ) << 8 ) - -// 1.15.0 -> 1.15.16 -#define SEX16( a ) ( ( (int32) ( (int16) (a) ) ) << 16 ) - -#ifdef PRINT_OP -#define U16( a ) ( (uint16) ( a ) ) -#endif - -#ifdef DEBUG_DSP -#define U16( a ) ( (uint16) ( a ) ) -#endif - -////////////////////////////////////////////////////////////// - -// Attention: This lookup table is not verified -static const uint16 div_lut[64] = { 0x0000, 0x8000, 0x4000, 0x2aaa, 0x2000, 0x1999, 0x1555, 0x1249, 0x1000, 0x0e38, - 0x0ccc, 0x0ba2, 0x0aaa, 0x09d8, 0x0924, 0x0888, 0x0800, 0x0787, 0x071c, 0x06bc, - 0x0666, 0x0618, 0x05d1, 0x0590, 0x0555, 0x051e, 0x04ec, 0x04bd, 0x0492, 0x0469, - 0x0444, 0x0421, 0x0400, 0x03e0, 0x03c3, 0x03a8, 0x038e, 0x0375, 0x035e, 0x0348, - 0x0333, 0x031f, 0x030c, 0x02fa, 0x02e8, 0x02d8, 0x02c8, 0x02b9, 0x02aa, 0x029c, - 0x028f, 0x0282, 0x0276, 0x026a, 0x025e, 0x0253, 0x0249, 0x023e, 0x0234, 0x022b, - 0x0222, 0x0219, 0x0210, 0x0208, }; -int16 DSP4_Inverse(int16 value) -{ - // saturate bounds - if (value < 0) - { - value = 0; - } - if (value > 63) - { - value = 63; - } - - return div_lut[value]; -} - -////////////////////////////////////////////////////////////// - -// Prototype -void DSP4_OP0B(bool8 *draw, int16 sp_x, int16 sp_y, int16 sp_attr, bool8 size, bool8 stop); - -////////////////////////////////////////////////////////////// - -// OP00 -void DSP4_Multiply(int16 Multiplicand, int16 Multiplier, int32 *Product) -{ - *Product = (Multiplicand * Multiplier << 1) >> 1; -} - -////////////////////////////////////////////////////////////// - - -void DSP4_OP01() -{ - DSP4.waiting4command = FALSE; - - // op flow control - switch (DSP4_vars.DSP4_Logic) - { - case 1: - goto resume1; break; - case 2: - goto resume2; break; - case 3: - goto resume3; break; - } - - //////////////////////////////////////////////////// - // process initial inputs - - // sort inputs - DSP4_vars.world_y = DSP4_READ_DWORD(); - DSP4_vars.poly_bottom[0][0] = DSP4_READ_WORD(); - DSP4_vars.poly_top[0][0] = DSP4_READ_WORD(); - DSP4_vars.poly_cx[1][0] = DSP4_READ_WORD(); - DSP4_vars.viewport_bottom = DSP4_READ_WORD(); - DSP4_vars.world_x = DSP4_READ_DWORD(); - DSP4_vars.poly_cx[0][0] = DSP4_READ_WORD(); - DSP4_vars.poly_ptr[0][0] = DSP4_READ_WORD(); - DSP4_vars.world_yofs = DSP4_READ_WORD(); - DSP4_vars.world_dy = DSP4_READ_DWORD(); - DSP4_vars.world_dx = DSP4_READ_DWORD(); - DSP4_vars.distance = DSP4_READ_WORD(); - DSP4_READ_WORD(); // 0x0000 - DSP4_vars.world_xenv = DSP4_READ_DWORD(); - DSP4_vars.world_ddy = DSP4_READ_WORD(); - DSP4_vars.world_ddx = DSP4_READ_WORD(); - DSP4_vars.view_yofsenv = DSP4_READ_WORD(); - - // initial (x,y,offset) at starting DSP4_vars.raster line - DSP4_vars.view_x1 = (int16)((DSP4_vars.world_x + DSP4_vars.world_xenv) >> 16); - DSP4_vars.view_y1 = (int16)(DSP4_vars.world_y >> 16); - DSP4_vars.view_xofs1 = (int16)(DSP4_vars.world_x >> 16); - DSP4_vars.view_yofs1 = DSP4_vars.world_yofs; - DSP4_vars.view_turnoff_x = 0; - DSP4_vars.view_turnoff_dx = 0; - - // first DSP4_vars.raster line - DSP4_vars.poly_raster[0][0] = DSP4_vars.poly_bottom[0][0]; - - do - { - //////////////////////////////////////////////////// - // process one iteration of projection - - // perspective projection of world (x,y,scroll) points - // based on the current projection lines - DSP4_vars.view_x2 = (int16)(( ( ( DSP4_vars.world_x + DSP4_vars.world_xenv ) >> 16 ) * DSP4_vars.distance >> 15 ) + ( DSP4_vars.view_turnoff_x * DSP4_vars.distance >> 15 )); - DSP4_vars.view_y2 = (int16)((DSP4_vars.world_y >> 16) * DSP4_vars.distance >> 15); - DSP4_vars.view_xofs2 = DSP4_vars.view_x2; - DSP4_vars.view_yofs2 = (DSP4_vars.world_yofs * DSP4_vars.distance >> 15) + DSP4_vars.poly_bottom[0][0] - DSP4_vars.view_y2; - - - // 1. World x-location before transformation - // 2. Viewer x-position at the next - // 3. World y-location before perspective projection - // 4. Viewer y-position below the horizon - // 5. Number of DSP4_vars.raster lines drawn in this iteration - - DSP4_CLEAR_OUT(); - DSP4_WRITE_WORD((uint16)((DSP4_vars.world_x + DSP4_vars.world_xenv) >> 16)); - DSP4_WRITE_WORD(DSP4_vars.view_x2); - DSP4_WRITE_WORD((uint16)(DSP4_vars.world_y >> 16)); - DSP4_WRITE_WORD(DSP4_vars.view_y2); - - ////////////////////////////////////////////////////// - - // SR = 0x00 - - // determine # of DSP4_vars.raster lines used - DSP4_vars.segments = DSP4_vars.poly_raster[0][0] - DSP4_vars.view_y2; - - // prevent overdraw - if (DSP4_vars.view_y2 >= DSP4_vars.poly_raster[0][0]) - DSP4_vars.segments = 0; - else - DSP4_vars.poly_raster[0][0] = DSP4_vars.view_y2; - - // don't draw outside the window - if (DSP4_vars.view_y2 < DSP4_vars.poly_top[0][0]) - { - DSP4_vars.segments = 0; - - // flush remaining DSP4_vars.raster lines - if (DSP4_vars.view_y1 >= DSP4_vars.poly_top[0][0]) - DSP4_vars.segments = DSP4_vars.view_y1 - DSP4_vars.poly_top[0][0]; - } - - // SR = 0x80 - - DSP4_WRITE_WORD(DSP4_vars.segments); - - ////////////////////////////////////////////////////// - - // scan next command if no SR check needed - if (DSP4_vars.segments) - { - int32 px_dx, py_dy; - int32 x_scroll, y_scroll; - - // SR = 0x00 - - // linear interpolation (lerp) between projected points - px_dx = (DSP4_vars.view_xofs2 - DSP4_vars.view_xofs1) * DSP4_Inverse(DSP4_vars.segments) << 1; - py_dy = (DSP4_vars.view_yofs2 - DSP4_vars.view_yofs1) * DSP4_Inverse(DSP4_vars.segments) << 1; - - // starting step values - x_scroll = SEX16(DSP4_vars.poly_cx[0][0] + DSP4_vars.view_xofs1); - y_scroll = SEX16(-DSP4_vars.viewport_bottom + DSP4_vars.view_yofs1 + DSP4_vars.view_yofsenv + DSP4_vars.poly_cx[1][0] - DSP4_vars.world_yofs); - - // SR = 0x80 - - // rasterize line - for (DSP4_vars.lcv = 0; DSP4_vars.lcv < DSP4_vars.segments; DSP4_vars.lcv++) - { - // 1. HDMA memory pointer (bg1) - // 2. vertical scroll offset ($210E) - // 3. horizontal scroll offset ($210D) - - DSP4_WRITE_WORD(DSP4_vars.poly_ptr[0][0]); - DSP4_WRITE_WORD((uint16)((y_scroll + 0x8000) >> 16)); - DSP4_WRITE_WORD((uint16)((x_scroll + 0x8000) >> 16)); - - - // update memory address - DSP4_vars.poly_ptr[0][0] -= 4; - - // update screen values - x_scroll += px_dx; - y_scroll += py_dy; - } - } - - //////////////////////////////////////////////////// - // Post-update - - // update new viewer (x,y,scroll) to last DSP4_vars.raster line drawn - DSP4_vars.view_x1 = DSP4_vars.view_x2; - DSP4_vars.view_y1 = DSP4_vars.view_y2; - DSP4_vars.view_xofs1 = DSP4_vars.view_xofs2; - DSP4_vars.view_yofs1 = DSP4_vars.view_yofs2; - - // add deltas for projection lines - DSP4_vars.world_dx += SEX78(DSP4_vars.world_ddx); - DSP4_vars.world_dy += SEX78(DSP4_vars.world_ddy); - - // update projection lines - DSP4_vars.world_x += (DSP4_vars.world_dx + DSP4_vars.world_xenv); - DSP4_vars.world_y += DSP4_vars.world_dy; - - // update road turnoff position - DSP4_vars.view_turnoff_x += DSP4_vars.view_turnoff_dx; - - //////////////////////////////////////////////////// - // command check - - // scan next command - DSP4.in_count = 2; - DSP4_WAIT(1) resume1 : - - // check for termination - DSP4_vars.distance = DSP4_READ_WORD(); - if (DSP4_vars.distance == -0x8000) - break; - - // road turnoff - if( (uint16) DSP4_vars.distance == 0x8001 ) - { - DSP4.in_count = 6; - DSP4_WAIT(2) resume2: - - DSP4_vars.distance = DSP4_READ_WORD(); - DSP4_vars.view_turnoff_x = DSP4_READ_WORD(); - DSP4_vars.view_turnoff_dx = DSP4_READ_WORD(); - - // factor in new changes - DSP4_vars.view_x1 += ( DSP4_vars.view_turnoff_x * DSP4_vars.distance >> 15 ); - DSP4_vars.view_xofs1 += ( DSP4_vars.view_turnoff_x * DSP4_vars.distance >> 15 ); - - // update stepping values - DSP4_vars.view_turnoff_x += DSP4_vars.view_turnoff_dx; - - DSP4.in_count = 2; - DSP4_WAIT(1) - } - - // already have 2 bytes read - DSP4.in_count = 6; - DSP4_WAIT(3) resume3 : - - // inspect inputs - DSP4_vars.world_ddy = DSP4_READ_WORD(); - DSP4_vars.world_ddx = DSP4_READ_WORD(); - DSP4_vars.view_yofsenv = DSP4_READ_WORD(); - - // no envelope here - DSP4_vars.world_xenv = 0; - } - while (1); - - // terminate op - DSP4.waiting4command = TRUE; -} - -////////////////////////////////////////////////////////////// - - -void DSP4_OP03() -{ - DSP4_vars.OAM_RowMax = 33; - memset(DSP4_vars.OAM_Row, 0, 64); -} - - -////////////////////////////////////////////////////////////// - - -void DSP4_OP05() -{ - DSP4_vars.OAM_index = 0; - DSP4_vars.OAM_bits = 0; - memset(DSP4_vars.OAM_attr, 0, 32); - DSP4_vars.sprite_count = 0; -} - - -////////////////////////////////////////////////////////////// - -void DSP4_OP06() -{ - DSP4_CLEAR_OUT(); - DSP4_WRITE_16_WORD(DSP4_vars.OAM_attr); -} - -////////////////////////////////////////////////////////////// - - -void DSP4_OP07() -{ - DSP4.waiting4command = FALSE; - - // op flow control - switch (DSP4_vars.DSP4_Logic) - { - case 1: - goto resume1; break; - case 2: - goto resume2; break; - } - - //////////////////////////////////////////////////// - // sort inputs - - DSP4_vars.world_y = DSP4_READ_DWORD(); - DSP4_vars.poly_bottom[0][0] = DSP4_READ_WORD(); - DSP4_vars.poly_top[0][0] = DSP4_READ_WORD(); - DSP4_vars.poly_cx[1][0] = DSP4_READ_WORD(); - DSP4_vars.viewport_bottom = DSP4_READ_WORD(); - DSP4_vars.world_x = DSP4_READ_DWORD(); - DSP4_vars.poly_cx[0][0] = DSP4_READ_WORD(); - DSP4_vars.poly_ptr[0][0] = DSP4_READ_WORD(); - DSP4_vars.world_yofs = DSP4_READ_WORD(); - DSP4_vars.distance = DSP4_READ_WORD(); - DSP4_vars.view_y2 = DSP4_READ_WORD(); - DSP4_vars.view_dy = DSP4_READ_WORD() * DSP4_vars.distance >> 15; - DSP4_vars.view_x2 = DSP4_READ_WORD(); - DSP4_vars.view_dx = DSP4_READ_WORD() * DSP4_vars.distance >> 15; - DSP4_vars.view_yofsenv = DSP4_READ_WORD(); - - // initial (x,y,offset) at starting DSP4_vars.raster line - DSP4_vars.view_x1 = (int16)(DSP4_vars.world_x >> 16); - DSP4_vars.view_y1 = (int16)(DSP4_vars.world_y >> 16); - DSP4_vars.view_xofs1 = DSP4_vars.view_x1; - DSP4_vars.view_yofs1 = DSP4_vars.world_yofs; - - // first DSP4_vars.raster line - DSP4_vars.poly_raster[0][0] = DSP4_vars.poly_bottom[0][0]; - - - do - { - //////////////////////////////////////////////////// - // process one iteration of projection - - // add shaping - DSP4_vars.view_x2 += DSP4_vars.view_dx; - DSP4_vars.view_y2 += DSP4_vars.view_dy; - - // vertical scroll calculation - DSP4_vars.view_xofs2 = DSP4_vars.view_x2; - DSP4_vars.view_yofs2 = (DSP4_vars.world_yofs * DSP4_vars.distance >> 15) + DSP4_vars.poly_bottom[0][0] - DSP4_vars.view_y2; - - // 1. Viewer x-position at the next - // 2. Viewer y-position below the horizon - // 3. Number of DSP4_vars.raster lines drawn in this iteration - - DSP4_CLEAR_OUT(); - DSP4_WRITE_WORD(DSP4_vars.view_x2); - DSP4_WRITE_WORD(DSP4_vars.view_y2); - - ////////////////////////////////////////////////////// - - // SR = 0x00 - - // determine # of DSP4_vars.raster lines used - DSP4_vars.segments = DSP4_vars.view_y1 - DSP4_vars.view_y2; - - // prevent overdraw - if (DSP4_vars.view_y2 >= DSP4_vars.poly_raster[0][0]) - DSP4_vars.segments = 0; - else - DSP4_vars.poly_raster[0][0] = DSP4_vars.view_y2; - - // don't draw outside the window - if (DSP4_vars.view_y2 < DSP4_vars.poly_top[0][0]) - { - DSP4_vars.segments = 0; - - // flush remaining DSP4_vars.raster lines - if (DSP4_vars.view_y1 >= DSP4_vars.poly_top[0][0]) - DSP4_vars.segments = DSP4_vars.view_y1 - DSP4_vars.poly_top[0][0]; - } - - // SR = 0x80 - - DSP4_WRITE_WORD(DSP4_vars.segments); - - ////////////////////////////////////////////////////// - - // scan next command if no SR check needed - if (DSP4_vars.segments) - { - int32 px_dx, py_dy; - int32 x_scroll, y_scroll; - - // SR = 0x00 - - // linear interpolation (lerp) between projected points - px_dx = (DSP4_vars.view_xofs2 - DSP4_vars.view_xofs1) * DSP4_Inverse(DSP4_vars.segments) << 1; - py_dy = (DSP4_vars.view_yofs2 - DSP4_vars.view_yofs1) * DSP4_Inverse(DSP4_vars.segments) << 1; - - // starting step values - x_scroll = SEX16(DSP4_vars.poly_cx[0][0] + DSP4_vars.view_xofs1); - y_scroll = SEX16(-DSP4_vars.viewport_bottom + DSP4_vars.view_yofs1 + DSP4_vars.view_yofsenv + DSP4_vars.poly_cx[1][0] - DSP4_vars.world_yofs); - - // SR = 0x80 - - // rasterize line - for (DSP4_vars.lcv = 0; DSP4_vars.lcv < DSP4_vars.segments; DSP4_vars.lcv++) - { - // 1. HDMA memory pointer (bg2) - // 2. vertical scroll offset ($2110) - // 3. horizontal scroll offset ($210F) - - DSP4_WRITE_WORD(DSP4_vars.poly_ptr[0][0]); - DSP4_WRITE_WORD((uint16)((y_scroll + 0x8000) >> 16)); - DSP4_WRITE_WORD((uint16)((x_scroll + 0x8000) >> 16)); - - // update memory address - DSP4_vars.poly_ptr[0][0] -= 4; - - // update screen values - x_scroll += px_dx; - y_scroll += py_dy; - } - } - - ///////////////////////////////////////////////////// - // Post-update - - // update new viewer (x,y,scroll) to last DSP4_vars.raster line drawn - DSP4_vars.view_x1 = DSP4_vars.view_x2; - DSP4_vars.view_y1 = DSP4_vars.view_y2; - DSP4_vars.view_xofs1 = DSP4_vars.view_xofs2; - DSP4_vars.view_yofs1 = DSP4_vars.view_yofs2; - - //////////////////////////////////////////////////// - // command check - - // scan next command - DSP4.in_count = 2; - DSP4_WAIT(1) resume1 : - - // check for opcode termination - DSP4_vars.distance = DSP4_READ_WORD(); - if (DSP4_vars.distance == -0x8000) - break; - - // already have 2 bytes in queue - DSP4.in_count = 10; - DSP4_WAIT(2) resume2 : - - // inspect inputs - DSP4_vars.view_y2 = DSP4_READ_WORD(); - DSP4_vars.view_dy = DSP4_READ_WORD() * DSP4_vars.distance >> 15; - DSP4_vars.view_x2 = DSP4_READ_WORD(); - DSP4_vars.view_dx = DSP4_READ_WORD() * DSP4_vars.distance >> 15; - DSP4_vars.view_yofsenv = DSP4_READ_WORD(); - } - while (1); - - DSP4.waiting4command = TRUE; -} - -////////////////////////////////////////////////////////////// - -void DSP4_OP08() -{ - int16 win_left, win_right; - int16 view_x[2], view_y[2]; - int16 envelope[2][2]; - - DSP4.waiting4command = FALSE; - - // op flow control - switch (DSP4_vars.DSP4_Logic) - { - case 1: - goto resume1; break; - case 2: - goto resume2; break; - } - - //////////////////////////////////////////////////// - // process initial inputs for two polygons - - // clip values - DSP4_vars.poly_clipRt[0][0] = DSP4_READ_WORD(); - DSP4_vars.poly_clipRt[0][1] = DSP4_READ_WORD(); - DSP4_vars.poly_clipRt[1][0] = DSP4_READ_WORD(); - DSP4_vars.poly_clipRt[1][1] = DSP4_READ_WORD(); - - DSP4_vars.poly_clipLf[0][0] = DSP4_READ_WORD(); - DSP4_vars.poly_clipLf[0][1] = DSP4_READ_WORD(); - DSP4_vars.poly_clipLf[1][0] = DSP4_READ_WORD(); - DSP4_vars.poly_clipLf[1][1] = DSP4_READ_WORD(); - - // unknown (constant) (ex. 1P/2P = $00A6, $00A6, $00A6, $00A6) - DSP4_READ_WORD(); - DSP4_READ_WORD(); - DSP4_READ_WORD(); - DSP4_READ_WORD(); - - // unknown (constant) (ex. 1P/2P = $00A5, $00A5, $00A7, $00A7) - DSP4_READ_WORD(); - DSP4_READ_WORD(); - DSP4_READ_WORD(); - DSP4_READ_WORD(); - - // polygon centering (left,right) - DSP4_vars.poly_cx[0][0] = DSP4_READ_WORD(); - DSP4_vars.poly_cx[0][1] = DSP4_READ_WORD(); - DSP4_vars.poly_cx[1][0] = DSP4_READ_WORD(); - DSP4_vars.poly_cx[1][1] = DSP4_READ_WORD(); - - // HDMA pointer locations - DSP4_vars.poly_ptr[0][0] = DSP4_READ_WORD(); - DSP4_vars.poly_ptr[0][1] = DSP4_READ_WORD(); - DSP4_vars.poly_ptr[1][0] = DSP4_READ_WORD(); - DSP4_vars.poly_ptr[1][1] = DSP4_READ_WORD(); - - // starting DSP4_vars.raster line below the horizon - DSP4_vars.poly_bottom[0][0] = DSP4_READ_WORD(); - DSP4_vars.poly_bottom[0][1] = DSP4_READ_WORD(); - DSP4_vars.poly_bottom[1][0] = DSP4_READ_WORD(); - DSP4_vars.poly_bottom[1][1] = DSP4_READ_WORD(); - - // top boundary line to clip - DSP4_vars.poly_top[0][0] = DSP4_READ_WORD(); - DSP4_vars.poly_top[0][1] = DSP4_READ_WORD(); - DSP4_vars.poly_top[1][0] = DSP4_READ_WORD(); - DSP4_vars.poly_top[1][1] = DSP4_READ_WORD(); - - // unknown - // (ex. 1P = $2FC8, $0034, $FF5C, $0035) - // - // (ex. 2P = $3178, $0034, $FFCC, $0035) - // (ex. 2P = $2FC8, $0034, $FFCC, $0035) - - DSP4_READ_WORD(); - DSP4_READ_WORD(); - DSP4_READ_WORD(); - DSP4_READ_WORD(); - - // look at guidelines for both polygon shapes - DSP4_vars.distance = DSP4_READ_WORD(); - view_x[0] = DSP4_READ_WORD(); - view_y[0] = DSP4_READ_WORD(); - view_x[1] = DSP4_READ_WORD(); - view_y[1] = DSP4_READ_WORD(); - - // envelope shaping guidelines (one frame only) - envelope[0][0] = DSP4_READ_WORD(); - envelope[0][1] = DSP4_READ_WORD(); - envelope[1][0] = DSP4_READ_WORD(); - envelope[1][1] = DSP4_READ_WORD(); - - // starting base values to project from - DSP4_vars.poly_start[0] = view_x[0]; - DSP4_vars.poly_start[1] = view_x[1]; - - // starting DSP4_vars.raster lines to begin drawing - DSP4_vars.poly_raster[0][0] = view_y[0]; - DSP4_vars.poly_raster[0][1] = view_y[0]; - DSP4_vars.poly_raster[1][0] = view_y[1]; - DSP4_vars.poly_raster[1][1] = view_y[1]; - - // starting distances - DSP4_vars.poly_plane[0] = DSP4_vars.distance; - DSP4_vars.poly_plane[1] = DSP4_vars.distance; - - // SR = 0x00 - - // re-center coordinates - win_left = DSP4_vars.poly_cx[0][0] - view_x[0] + envelope[0][0]; - win_right = DSP4_vars.poly_cx[0][1] - view_x[0] + envelope[0][1]; - - // saturate offscreen data for polygon #1 - if (win_left < DSP4_vars.poly_clipLf[0][0]) - { - win_left = DSP4_vars.poly_clipLf[0][0]; - } - if (win_left > DSP4_vars.poly_clipRt[0][0]) - { - win_left = DSP4_vars.poly_clipRt[0][0]; - } - if (win_right < DSP4_vars.poly_clipLf[0][1]) - { - win_right = DSP4_vars.poly_clipLf[0][1]; - } - if (win_right > DSP4_vars.poly_clipRt[0][1]) - { - win_right = DSP4_vars.poly_clipRt[0][1]; - } - - // SR = 0x80 - - // initial output for polygon #1 - DSP4_CLEAR_OUT(); - DSP4_WRITE_BYTE(win_left & 0xff); - DSP4_WRITE_BYTE(win_right & 0xff); - - - do - { - int16 polygon; - //////////////////////////////////////////////////// - // command check - - // scan next command - DSP4.in_count = 2; - DSP4_WAIT(1) resume1 : - - // terminate op - DSP4_vars.distance = DSP4_READ_WORD(); - if (DSP4_vars.distance == -0x8000) - break; - - // already have 2 bytes in queue - DSP4.in_count = 16; - - DSP4_WAIT(2) resume2 : - - // look at guidelines for both polygon shapes - view_x[0] = DSP4_READ_WORD(); - view_y[0] = DSP4_READ_WORD(); - view_x[1] = DSP4_READ_WORD(); - view_y[1] = DSP4_READ_WORD(); - - // envelope shaping guidelines (one frame only) - envelope[0][0] = DSP4_READ_WORD(); - envelope[0][1] = DSP4_READ_WORD(); - envelope[1][0] = DSP4_READ_WORD(); - envelope[1][1] = DSP4_READ_WORD(); - - //////////////////////////////////////////////////// - // projection begins - - // init - DSP4_CLEAR_OUT(); - - - ////////////////////////////////////////////// - // solid polygon renderer - 2 shapes - - for (polygon = 0; polygon < 2; polygon++) - { - int32 left_inc, right_inc; - int16 x1_final, x2_final; - int16 env[2][2]; - int16 poly; - - // SR = 0x00 - - // # DSP4_vars.raster lines to draw - DSP4_vars.segments = DSP4_vars.poly_raster[polygon][0] - view_y[polygon]; - - // prevent overdraw - if (DSP4_vars.segments > 0) - { - // bump drawing cursor - DSP4_vars.poly_raster[polygon][0] = view_y[polygon]; - DSP4_vars.poly_raster[polygon][1] = view_y[polygon]; - } - else - DSP4_vars.segments = 0; - - // don't draw outside the window - if (view_y[polygon] < DSP4_vars.poly_top[polygon][0]) - { - DSP4_vars.segments = 0; - - // flush remaining DSP4_vars.raster lines - if (view_y[polygon] >= DSP4_vars.poly_top[polygon][0]) - DSP4_vars.segments = view_y[polygon] - DSP4_vars.poly_top[polygon][0]; - } - - // SR = 0x80 - - // tell user how many DSP4_vars.raster structures to read in - DSP4_WRITE_WORD(DSP4_vars.segments); - - // normal parameters - poly = polygon; - - ///////////////////////////////////////////////////// - - // scan next command if no SR check needed - if (DSP4_vars.segments) - { - int32 win_left, win_right; - - // road turnoff selection - if( (uint16) envelope[ polygon ][ 0 ] == (uint16) 0xc001 ) - poly = 1; - else if( envelope[ polygon ][ 1 ] == 0x3fff ) - poly = 1; - - /////////////////////////////////////////////// - // left side of polygon - - // perspective correction on additional shaping parameters - env[0][0] = envelope[polygon][0] * DSP4_vars.poly_plane[poly] >> 15; - env[0][1] = envelope[polygon][0] * DSP4_vars.distance >> 15; - - // project new shapes (left side) - x1_final = view_x[poly] + env[0][0]; - x2_final = DSP4_vars.poly_start[poly] + env[0][1]; - - // interpolate between projected points with shaping - left_inc = (x2_final - x1_final) * DSP4_Inverse(DSP4_vars.segments) << 1; - if (DSP4_vars.segments == 1) - left_inc = -left_inc; - - /////////////////////////////////////////////// - // right side of polygon - - // perspective correction on additional shaping parameters - env[1][0] = envelope[polygon][1] * DSP4_vars.poly_plane[poly] >> 15;; - env[1][1] = envelope[polygon][1] * DSP4_vars.distance >> 15; - - // project new shapes (right side) - x1_final = view_x[poly] + env[1][0]; - x2_final = DSP4_vars.poly_start[poly] + env[1][1]; - - - // interpolate between projected points with shaping - right_inc = (x2_final - x1_final) * DSP4_Inverse(DSP4_vars.segments) << 1; - if (DSP4_vars.segments == 1) - right_inc = -right_inc; - - /////////////////////////////////////////////// - // update each point on the line - - win_left = SEX16(DSP4_vars.poly_cx[polygon][0] - DSP4_vars.poly_start[poly] + env[0][0]); - win_right = SEX16(DSP4_vars.poly_cx[polygon][1] - DSP4_vars.poly_start[poly] + env[1][0]); - - // update DSP4_vars.distance drawn into world - DSP4_vars.poly_plane[polygon] = DSP4_vars.distance; - - // rasterize line - for (DSP4_vars.lcv = 0; DSP4_vars.lcv < DSP4_vars.segments; DSP4_vars.lcv++) - { - int16 x_left, x_right; - - // project new coordinates - win_left += left_inc; - win_right += right_inc; - - // grab integer portion, drop fraction (no rounding) - x_left = (int16)(win_left >> 16); - x_right = (int16)(win_right >> 16); - - // saturate offscreen data - if (x_left < DSP4_vars.poly_clipLf[polygon][0]) - x_left = DSP4_vars.poly_clipLf[polygon][0]; - if (x_left > DSP4_vars.poly_clipRt[polygon][0]) - x_left = DSP4_vars.poly_clipRt[polygon][0]; - if (x_right < DSP4_vars.poly_clipLf[polygon][1]) - x_right = DSP4_vars.poly_clipLf[polygon][1]; - if (x_right > DSP4_vars.poly_clipRt[polygon][1]) - x_right = DSP4_vars.poly_clipRt[polygon][1]; - - // 1. HDMA memory pointer - // 2. Left window position ($2126/$2128) - // 3. Right window position ($2127/$2129) - - DSP4_WRITE_WORD(DSP4_vars.poly_ptr[polygon][0]); - DSP4_WRITE_BYTE(x_left & 0xff); - DSP4_WRITE_BYTE(x_right & 0xff); - - - // update memory pointers - DSP4_vars.poly_ptr[polygon][0] -= 4; - DSP4_vars.poly_ptr[polygon][1] -= 4; - } // end rasterize line - } - - //////////////////////////////////////////////// - // Post-update - - // new projection spot to continue rasterizing from - DSP4_vars.poly_start[polygon] = view_x[poly]; - } // end polygon rasterizer - } - while (1); - - // unknown output - DSP4_CLEAR_OUT(); - DSP4_WRITE_WORD(0); - - - DSP4.waiting4command = TRUE; -} - -////////////////////////////////////////////////////////////// - -void DSP4_OP09() -{ - DSP4.waiting4command = FALSE; - - // op flow control - switch (DSP4_vars.DSP4_Logic) - { - case 1: - goto resume1; break; - case 2: - goto resume2; break; - case 3: - goto resume3; break; - case 4: - goto resume4; break; - case 5: - goto resume5; break; - case 6: - goto resume6; break; - } - - //////////////////////////////////////////////////// - // process initial inputs - - // grab screen information - DSP4_vars.viewport_cx = DSP4_READ_WORD(); - DSP4_vars.viewport_cy = DSP4_READ_WORD(); - DSP4_READ_WORD(); // 0x0000 - DSP4_vars.viewport_left = DSP4_READ_WORD(); - DSP4_vars.viewport_right = DSP4_READ_WORD(); - DSP4_vars.viewport_top = DSP4_READ_WORD(); - DSP4_vars.viewport_bottom = DSP4_READ_WORD(); - - // starting DSP4_vars.raster line below the horizon - DSP4_vars.poly_bottom[0][0] = DSP4_vars.viewport_bottom - DSP4_vars.viewport_cy; - DSP4_vars.poly_raster[0][0] = 0x100; - - do - { - //////////////////////////////////////////////////// - // check for new sprites - - DSP4.in_count = 4; - DSP4_WAIT(1) resume1 : - - //////////////////////////////////////////////// - // DSP4_vars.raster overdraw check - - DSP4_vars.raster = DSP4_READ_WORD(); - - // continue updating the DSP4_vars.raster line where overdraw begins - if (DSP4_vars.raster < DSP4_vars.poly_raster[0][0]) - { - DSP4_vars.sprite_clipy = DSP4_vars.viewport_bottom - (DSP4_vars.poly_bottom[0][0] - DSP4_vars.raster); - DSP4_vars.poly_raster[0][0] = DSP4_vars.raster; - } - - ///////////////////////////////////////////////// - // identify sprite - - // op termination - DSP4_vars.distance = DSP4_READ_WORD(); - if (DSP4_vars.distance == -0x8000) - goto terminate; - - - // no sprite - if (DSP4_vars.distance == 0x0000) - { - continue; - } - - //////////////////////////////////////////////////// - // process projection information - - // vehicle sprite - if ((uint16) DSP4_vars.distance == 0x9000) - { - int16 car_left, car_right, car_back; - int16 impact_left, impact_back; - int16 world_spx, world_spy; - int16 view_spx, view_spy; - uint16 energy; - - // we already have 4 bytes we want - DSP4.in_count = 14; - DSP4_WAIT(2) resume2 : - - // filter inputs - energy = DSP4_READ_WORD(); - impact_back = DSP4_READ_WORD(); - car_back = DSP4_READ_WORD(); - impact_left = DSP4_READ_WORD(); - car_left = DSP4_READ_WORD(); - DSP4_vars.distance = DSP4_READ_WORD(); - car_right = DSP4_READ_WORD(); - - // calculate car's world (x,y) values - world_spx = car_right - car_left; - world_spy = car_back; - - // add in collision vector [needs bit-twiddling] - world_spx -= energy * (impact_left - car_left) >> 16; - world_spy -= energy * (car_back - impact_back) >> 16; - - // perspective correction for world (x,y) - view_spx = world_spx * DSP4_vars.distance >> 15; - view_spy = world_spy * DSP4_vars.distance >> 15; - - // convert to screen values - DSP4_vars.sprite_x = DSP4_vars.viewport_cx + view_spx; - DSP4_vars.sprite_y = DSP4_vars.viewport_bottom - (DSP4_vars.poly_bottom[0][0] - view_spy); - - // make the car's (x)-coordinate available - DSP4_CLEAR_OUT(); - DSP4_WRITE_WORD(world_spx); - - // grab a few remaining vehicle values - DSP4.in_count = 4; - DSP4_WAIT(3) resume3 : - - // add vertical lift factor - DSP4_vars.sprite_y += DSP4_READ_WORD(); - } - // terrain sprite - else - { - int16 world_spx, world_spy; - int16 view_spx, view_spy; - - // we already have 4 bytes we want - DSP4.in_count = 10; - DSP4_WAIT(4) resume4 : - - // sort loop inputs - DSP4_vars.poly_cx[0][0] = DSP4_READ_WORD(); - DSP4_vars.poly_raster[0][1] = DSP4_READ_WORD(); - world_spx = DSP4_READ_WORD(); - world_spy = DSP4_READ_WORD(); - - // compute base DSP4_vars.raster line from the bottom - DSP4_vars.segments = DSP4_vars.poly_bottom[0][0] - DSP4_vars.raster; - - // perspective correction for world (x,y) - view_spx = world_spx * DSP4_vars.distance >> 15; - view_spy = world_spy * DSP4_vars.distance >> 15; - - // convert to screen values - DSP4_vars.sprite_x = DSP4_vars.viewport_cx + view_spx - DSP4_vars.poly_cx[0][0]; - DSP4_vars.sprite_y = DSP4_vars.viewport_bottom - DSP4_vars.segments + view_spy; - } - - // default sprite size: 16x16 - DSP4_vars.sprite_size = 1; - DSP4_vars.sprite_attr = DSP4_READ_WORD(); - - //////////////////////////////////////////////////// - // convert tile data to SNES OAM format - - do - { - uint16 header; - - int16 sp_x, sp_y, sp_attr, sp_dattr; - int16 sp_dx, sp_dy; - int16 pixels; - - bool8 draw; - - DSP4.in_count = 2; - DSP4_WAIT(5) resume5 : - - draw = TRUE; - - // opcode termination - DSP4_vars.raster = DSP4_READ_WORD(); - if (DSP4_vars.raster == -0x8000) - goto terminate; - - // stop code - if (DSP4_vars.raster == 0x0000 && !DSP4_vars.sprite_size) - break; - - // toggle sprite size - if (DSP4_vars.raster == 0x0000) - { - DSP4_vars.sprite_size = !DSP4_vars.sprite_size; - continue; - } - - // check for valid sprite header - header = DSP4_vars.raster; - header >>= 8; - if (header != 0x20 && - header != 0x2e && //This is for attractor sprite - header != 0x40 && - header != 0x60 && - header != 0xa0 && - header != 0xc0 && - header != 0xe0) - break; - - // read in rest of sprite data - DSP4.in_count = 4; - DSP4_WAIT(6) resume6 : - - draw = TRUE; - - ///////////////////////////////////// - // process tile data - - // sprite deltas - sp_dattr = DSP4_vars.raster; - sp_dy = DSP4_READ_WORD(); - sp_dx = DSP4_READ_WORD(); - - // update coordinates to screen space - sp_x = DSP4_vars.sprite_x + sp_dx; - sp_y = DSP4_vars.sprite_y + sp_dy; - - // update sprite nametable/attribute information - sp_attr = DSP4_vars.sprite_attr + sp_dattr; - - // allow partially visibile tiles - pixels = DSP4_vars.sprite_size ? 15 : 7; - - DSP4_CLEAR_OUT(); - - // transparent tile to clip off parts of a sprite (overdraw) - if (DSP4_vars.sprite_clipy - pixels <= sp_y && - sp_y <= DSP4_vars.sprite_clipy && - sp_x >= DSP4_vars.viewport_left - pixels && - sp_x <= DSP4_vars.viewport_right && - DSP4_vars.sprite_clipy >= DSP4_vars.viewport_top - pixels && - DSP4_vars.sprite_clipy <= DSP4_vars.viewport_bottom) - { - DSP4_OP0B(&draw, sp_x, DSP4_vars.sprite_clipy, 0x00EE, DSP4_vars.sprite_size, 0); - } - - - // normal sprite tile - if (sp_x >= DSP4_vars.viewport_left - pixels && - sp_x <= DSP4_vars.viewport_right && - sp_y >= DSP4_vars.viewport_top - pixels && - sp_y <= DSP4_vars.viewport_bottom && - sp_y <= DSP4_vars.sprite_clipy) - { - DSP4_OP0B(&draw, sp_x, sp_y, sp_attr, DSP4_vars.sprite_size, 0); - } - - - // no following OAM data - DSP4_OP0B(&draw, 0, 0x0100, 0, 0, 1); - } - while (1); - } - while (1); - - terminate : DSP4.waiting4command = TRUE; -} - -////////////////////////////////////////////////////////////// - -const uint16 OP0A_Values[16] = { 0x0000, 0x0030, 0x0060, 0x0090, 0x00c0, 0x00f0, 0x0120, 0x0150, 0xfe80, - 0xfeb0, 0xfee0, 0xff10, 0xff40, 0xff70, 0xffa0, 0xffd0 }; - -void DSP4_OP0A(int16 n2, int16 *o1, int16 *o2, int16 *o3, int16 *o4) -{ - *o4 = OP0A_Values[(n2 & 0x000f)]; - *o3 = OP0A_Values[(n2 & 0x00f0) >> 4]; - *o2 = OP0A_Values[(n2 & 0x0f00) >> 8]; - *o1 = OP0A_Values[(n2 & 0xf000) >> 12]; -} - -////////////////////////////////////////////////////////////// - -void DSP4_OP0B(bool8 *draw, int16 sp_x, int16 sp_y, int16 sp_attr, bool8 size, bool8 stop) -{ - int16 Row1, Row2; - - // SR = 0x00 - - // align to nearest 8-pixel row - Row1 = (sp_y >> 3) & 0x1f; - Row2 = (Row1 + 1) & 0x1f; - - // check boundaries - if (!((sp_y < 0) || ((sp_y & 0x01ff) < 0x00eb))) - { - *draw = 0; - } - if (size) - { - if (DSP4_vars.OAM_Row[Row1] + 1 >= DSP4_vars.OAM_RowMax) - *draw = 0; - if (DSP4_vars.OAM_Row[Row2] + 1 >= DSP4_vars.OAM_RowMax) - *draw = 0; - } - else - { - if (DSP4_vars.OAM_Row[Row1] >= DSP4_vars.OAM_RowMax) - { - *draw = 0; - } - } - - // emulator fail-safe (unknown if this really exists) - if (DSP4_vars.sprite_count >= 128) - { - *draw = 0; - } - - // SR = 0x80 - - if (*draw) - { - // Row tiles - if (size) - { - DSP4_vars.OAM_Row[Row1] += 2; - DSP4_vars.OAM_Row[Row2] += 2; - } - else - { - DSP4_vars.OAM_Row[Row1]++; - } - - // yield OAM output - DSP4_WRITE_WORD(1); - - // pack OAM data: x,y,name,attr - DSP4_WRITE_BYTE(sp_x & 0xff); - DSP4_WRITE_BYTE(sp_y & 0xff); - DSP4_WRITE_WORD(sp_attr); - - DSP4_vars.sprite_count++; - - // OAM: size,msb data - // save post-oam table data for future retrieval - DSP4_vars.OAM_attr[DSP4_vars.OAM_index] |= ((sp_x <0 || sp_x> 255) << DSP4_vars.OAM_bits); - DSP4_vars.OAM_bits++; - - DSP4_vars.OAM_attr[DSP4_vars.OAM_index] |= (size << DSP4_vars.OAM_bits); - DSP4_vars.OAM_bits++; - - // move to next byte in buffer - if (DSP4_vars.OAM_bits == 16) - { - DSP4_vars.OAM_bits = 0; - DSP4_vars.OAM_index++; - } - } - else if (stop) - { - // yield no OAM output - DSP4_WRITE_WORD(0); - } -} - -////////////////////////////////////////////////////////////// - -void DSP4_OP0D() -{ - DSP4.waiting4command = FALSE; - - // op flow control - switch (DSP4_vars.DSP4_Logic) - { - case 1: - goto resume1; break; - case 2: - goto resume2; break; - } - - //////////////////////////////////////////////////// - // process initial inputs - - // sort inputs - DSP4_vars.world_y = DSP4_READ_DWORD(); - DSP4_vars.poly_bottom[0][0] = DSP4_READ_WORD(); - DSP4_vars.poly_top[0][0] = DSP4_READ_WORD(); - DSP4_vars.poly_cx[1][0] = DSP4_READ_WORD(); - DSP4_vars.viewport_bottom = DSP4_READ_WORD(); - DSP4_vars.world_x = DSP4_READ_DWORD(); - DSP4_vars.poly_cx[0][0] = DSP4_READ_WORD(); - DSP4_vars.poly_ptr[0][0] = DSP4_READ_WORD(); - DSP4_vars.world_yofs = DSP4_READ_WORD(); - DSP4_vars.world_dy = DSP4_READ_DWORD(); - DSP4_vars.world_dx = DSP4_READ_DWORD(); - DSP4_vars.distance = DSP4_READ_WORD(); - DSP4_READ_WORD(); // 0x0000 - DSP4_vars.world_xenv = SEX78(DSP4_READ_WORD()); - DSP4_vars.world_ddy = DSP4_READ_WORD(); - DSP4_vars.world_ddx = DSP4_READ_WORD(); - DSP4_vars.view_yofsenv = DSP4_READ_WORD(); - - // initial (x,y,offset) at starting DSP4_vars.raster line - DSP4_vars.view_x1 = (int16)((DSP4_vars.world_x + DSP4_vars.world_xenv) >> 16); - DSP4_vars.view_y1 = (int16)(DSP4_vars.world_y >> 16); - DSP4_vars.view_xofs1 = (int16)(DSP4_vars.world_x >> 16); - DSP4_vars.view_yofs1 = DSP4_vars.world_yofs; - - // first DSP4_vars.raster line - DSP4_vars.poly_raster[0][0] = DSP4_vars.poly_bottom[0][0]; - - - do - { - //////////////////////////////////////////////////// - // process one iteration of projection - - // perspective projection of world (x,y,scroll) points - // based on the current projection lines - DSP4_vars.view_x2 = (int16)(( ( ( DSP4_vars.world_x + DSP4_vars.world_xenv ) >> 16 ) * DSP4_vars.distance >> 15 ) + ( DSP4_vars.view_turnoff_x * DSP4_vars.distance >> 15 )); - DSP4_vars.view_y2 = (int16)((DSP4_vars.world_y >> 16) * DSP4_vars.distance >> 15); - DSP4_vars.view_xofs2 = DSP4_vars.view_x2; - DSP4_vars.view_yofs2 = (DSP4_vars.world_yofs * DSP4_vars.distance >> 15) + DSP4_vars.poly_bottom[0][0] - DSP4_vars.view_y2; - - // 1. World x-location before transformation - // 2. Viewer x-position at the current - // 3. World y-location before perspective projection - // 4. Viewer y-position below the horizon - // 5. Number of DSP4_vars.raster lines drawn in this iteration - - DSP4_CLEAR_OUT(); - DSP4_WRITE_WORD((uint16)((DSP4_vars.world_x + DSP4_vars.world_xenv) >> 16)); - DSP4_WRITE_WORD(DSP4_vars.view_x2); - DSP4_WRITE_WORD((uint16)(DSP4_vars.world_y >> 16)); - DSP4_WRITE_WORD(DSP4_vars.view_y2); - - ////////////////////////////////////////////////////////// - - // SR = 0x00 - - // determine # of DSP4_vars.raster lines used - DSP4_vars.segments = DSP4_vars.view_y1 - DSP4_vars.view_y2; - - // prevent overdraw - if (DSP4_vars.view_y2 >= DSP4_vars.poly_raster[0][0]) - DSP4_vars.segments = 0; - else - DSP4_vars.poly_raster[0][0] = DSP4_vars.view_y2; - - // don't draw outside the window - if (DSP4_vars.view_y2 < DSP4_vars.poly_top[0][0]) - { - DSP4_vars.segments = 0; - - // flush remaining DSP4_vars.raster lines - if (DSP4_vars.view_y1 >= DSP4_vars.poly_top[0][0]) - DSP4_vars.segments = DSP4_vars.view_y1 - DSP4_vars.poly_top[0][0]; - } - - // SR = 0x80 - - DSP4_WRITE_WORD(DSP4_vars.segments); - - ////////////////////////////////////////////////////////// - - // scan next command if no SR check needed - if (DSP4_vars.segments) - { - int32 px_dx, py_dy; - int32 x_scroll, y_scroll; - - // SR = 0x00 - - // linear interpolation (lerp) between projected points - px_dx = (DSP4_vars.view_xofs2 - DSP4_vars.view_xofs1) * DSP4_Inverse(DSP4_vars.segments) << 1; - py_dy = (DSP4_vars.view_yofs2 - DSP4_vars.view_yofs1) * DSP4_Inverse(DSP4_vars.segments) << 1; - - // starting step values - x_scroll = SEX16(DSP4_vars.poly_cx[0][0] + DSP4_vars.view_xofs1); - y_scroll = SEX16(-DSP4_vars.viewport_bottom + DSP4_vars.view_yofs1 + DSP4_vars.view_yofsenv + DSP4_vars.poly_cx[1][0] - DSP4_vars.world_yofs); - - // SR = 0x80 - - // rasterize line - for (DSP4_vars.lcv = 0; DSP4_vars.lcv < DSP4_vars.segments; DSP4_vars.lcv++) - { - // 1. HDMA memory pointer (bg1) - // 2. vertical scroll offset ($210E) - // 3. horizontal scroll offset ($210D) - - DSP4_WRITE_WORD(DSP4_vars.poly_ptr[0][0]); - DSP4_WRITE_WORD((uint16)((y_scroll + 0x8000) >> 16)); - DSP4_WRITE_WORD((uint16)((x_scroll + 0x8000) >> 16)); - - - // update memory address - DSP4_vars.poly_ptr[0][0] -= 4; - - // update screen values - x_scroll += px_dx; - y_scroll += py_dy; - } - } - - ///////////////////////////////////////////////////// - // Post-update - - // update new viewer (x,y,scroll) to last DSP4_vars.raster line drawn - DSP4_vars.view_x1 = DSP4_vars.view_x2; - DSP4_vars.view_y1 = DSP4_vars.view_y2; - DSP4_vars.view_xofs1 = DSP4_vars.view_xofs2; - DSP4_vars.view_yofs1 = DSP4_vars.view_yofs2; - - // add deltas for projection lines - DSP4_vars.world_dx += SEX78(DSP4_vars.world_ddx); - DSP4_vars.world_dy += SEX78(DSP4_vars.world_ddy); - - // update projection lines - DSP4_vars.world_x += (DSP4_vars.world_dx + DSP4_vars.world_xenv); - DSP4_vars.world_y += DSP4_vars.world_dy; - - //////////////////////////////////////////////////// - // command check - - // scan next command - DSP4.in_count = 2; - DSP4_WAIT(1) resume1 : - - // inspect input - DSP4_vars.distance = DSP4_READ_WORD(); - - // terminate op - if (DSP4_vars.distance == -0x8000) - break; - - // already have 2 bytes in queue - DSP4.in_count = 6; - DSP4_WAIT(2) resume2: - - // inspect inputs - DSP4_vars.world_ddy = DSP4_READ_WORD(); - DSP4_vars.world_ddx = DSP4_READ_WORD(); - DSP4_vars.view_yofsenv = DSP4_READ_WORD(); - - // no envelope here - DSP4_vars.world_xenv = 0; - } - while (1); - - DSP4.waiting4command = TRUE; -} - -////////////////////////////////////////////////////////////// - - -void DSP4_OP0E() -{ - DSP4_vars.OAM_RowMax = 16; - memset(DSP4_vars.OAM_Row, 0, 64); -} - - -////////////////////////////////////////////////////////////// - -void DSP4_OP0F() -{ - DSP4.waiting4command = FALSE; - - // op flow control - switch (DSP4_vars.DSP4_Logic) - { - case 1: - goto resume1; break; - case 2: - goto resume2; break; - case 3: - goto resume3; break; - case 4: - goto resume4; break; - } - - //////////////////////////////////////////////////// - // process initial inputs - - // sort inputs - DSP4_READ_WORD(); // 0x0000 - DSP4_vars.world_y = DSP4_READ_DWORD(); - DSP4_vars.poly_bottom[0][0] = DSP4_READ_WORD(); - DSP4_vars.poly_top[0][0] = DSP4_READ_WORD(); - DSP4_vars.poly_cx[1][0] = DSP4_READ_WORD(); - DSP4_vars.viewport_bottom = DSP4_READ_WORD(); - DSP4_vars.world_x = DSP4_READ_DWORD(); - DSP4_vars.poly_cx[0][0] = DSP4_READ_WORD(); - DSP4_vars.poly_ptr[0][0] = DSP4_READ_WORD(); - DSP4_vars.world_yofs = DSP4_READ_WORD(); - DSP4_vars.world_dy = DSP4_READ_DWORD(); - DSP4_vars.world_dx = DSP4_READ_DWORD(); - DSP4_vars.distance = DSP4_READ_WORD(); - DSP4_READ_WORD(); // 0x0000 - DSP4_vars.world_xenv = DSP4_READ_DWORD(); - DSP4_vars.world_ddy = DSP4_READ_WORD(); - DSP4_vars.world_ddx = DSP4_READ_WORD(); - DSP4_vars.view_yofsenv = DSP4_READ_WORD(); - - // initial (x,y,offset) at starting DSP4_vars.raster line - DSP4_vars.view_x1 = (int16)((DSP4_vars.world_x + DSP4_vars.world_xenv) >> 16); - DSP4_vars.view_y1 = (int16)(DSP4_vars.world_y >> 16); - DSP4_vars.view_xofs1 = (int16)(DSP4_vars.world_x >> 16); - DSP4_vars.view_yofs1 = DSP4_vars.world_yofs; - DSP4_vars.view_turnoff_x = 0; - DSP4_vars.view_turnoff_dx = 0; - - // first DSP4_vars.raster line - DSP4_vars.poly_raster[0][0] = DSP4_vars.poly_bottom[0][0]; - - - do - { - //////////////////////////////////////////////////// - // process one iteration of projection - - // perspective projection of world (x,y,scroll) points - // based on the current projection lines - DSP4_vars.view_x2 = (int16)(((DSP4_vars.world_x + DSP4_vars.world_xenv) >> 16) * DSP4_vars.distance >> 15); - DSP4_vars.view_y2 = (int16)((DSP4_vars.world_y >> 16) * DSP4_vars.distance >> 15); - DSP4_vars.view_xofs2 = DSP4_vars.view_x2; - DSP4_vars.view_yofs2 = (DSP4_vars.world_yofs * DSP4_vars.distance >> 15) + DSP4_vars.poly_bottom[0][0] - DSP4_vars.view_y2; - - // 1. World x-location before transformation - // 2. Viewer x-position at the next - // 3. World y-location before perspective projection - // 4. Viewer y-position below the horizon - // 5. Number of DSP4_vars.raster lines drawn in this iteration - - DSP4_CLEAR_OUT(); - DSP4_WRITE_WORD((uint16)((DSP4_vars.world_x + DSP4_vars.world_xenv) >> 16)); - DSP4_WRITE_WORD(DSP4_vars.view_x2); - DSP4_WRITE_WORD((uint16)(DSP4_vars.world_y >> 16)); - DSP4_WRITE_WORD(DSP4_vars.view_y2); - - ////////////////////////////////////////////////////// - - // SR = 0x00 - - // determine # of DSP4_vars.raster lines used - DSP4_vars.segments = DSP4_vars.poly_raster[0][0] - DSP4_vars.view_y2; - - // prevent overdraw - if (DSP4_vars.view_y2 >= DSP4_vars.poly_raster[0][0]) - DSP4_vars.segments = 0; - else - DSP4_vars.poly_raster[0][0] = DSP4_vars.view_y2; - - // don't draw outside the window - if (DSP4_vars.view_y2 < DSP4_vars.poly_top[0][0]) - { - DSP4_vars.segments = 0; - - // flush remaining DSP4_vars.raster lines - if (DSP4_vars.view_y1 >= DSP4_vars.poly_top[0][0]) - DSP4_vars.segments = DSP4_vars.view_y1 - DSP4_vars.poly_top[0][0]; - } - - // SR = 0x80 - - DSP4_WRITE_WORD(DSP4_vars.segments); - - ////////////////////////////////////////////////////// - - // scan next command if no SR check needed - if (DSP4_vars.segments) - { - int32 px_dx, py_dy; - int32 x_scroll, y_scroll; - - for (DSP4_vars.lcv = 0; DSP4_vars.lcv < 4; DSP4_vars.lcv++) - { - // grab inputs - DSP4.in_count = 4; - DSP4_WAIT(1); - resume1 : - for (;;) - { - int16 distance; - int16 color, red, green, blue; - - distance = DSP4_READ_WORD(); - color = DSP4_READ_WORD(); - - // U1+B5+G5+R5 - red = color & 0x1f; - green = (color >> 5) & 0x1f; - blue = (color >> 10) & 0x1f; - - // dynamic lighting - red = (red * distance >> 15) & 0x1f; - green = (green * distance >> 15) & 0x1f; - blue = (blue * distance >> 15) & 0x1f; - color = red | (green << 5) | (blue << 10); - - DSP4_CLEAR_OUT(); - DSP4_WRITE_WORD(color); - break; - } - } - - ////////////////////////////////////////////////////// - - // SR = 0x00 - - // linear interpolation (lerp) between projected points - px_dx = (DSP4_vars.view_xofs2 - DSP4_vars.view_xofs1) * DSP4_Inverse(DSP4_vars.segments) << 1; - py_dy = (DSP4_vars.view_yofs2 - DSP4_vars.view_yofs1) * DSP4_Inverse(DSP4_vars.segments) << 1; - - - // starting step values - x_scroll = SEX16(DSP4_vars.poly_cx[0][0] + DSP4_vars.view_xofs1); - y_scroll = SEX16(-DSP4_vars.viewport_bottom + DSP4_vars.view_yofs1 + DSP4_vars.view_yofsenv + DSP4_vars.poly_cx[1][0] - DSP4_vars.world_yofs); - - // SR = 0x80 - - // rasterize line - for (DSP4_vars.lcv = 0; DSP4_vars.lcv < DSP4_vars.segments; DSP4_vars.lcv++) - { - // 1. HDMA memory pointer - // 2. vertical scroll offset ($210E) - // 3. horizontal scroll offset ($210D) - - DSP4_WRITE_WORD(DSP4_vars.poly_ptr[0][0]); - DSP4_WRITE_WORD((uint16)((y_scroll + 0x8000) >> 16)); - DSP4_WRITE_WORD((uint16)((x_scroll + 0x8000) >> 16)); - - // update memory address - DSP4_vars.poly_ptr[0][0] -= 4; - - // update screen values - x_scroll += px_dx; - y_scroll += py_dy; - } - } - - //////////////////////////////////////////////////// - // Post-update - - // update new viewer (x,y,scroll) to last DSP4_vars.raster line drawn - DSP4_vars.view_x1 = DSP4_vars.view_x2; - DSP4_vars.view_y1 = DSP4_vars.view_y2; - DSP4_vars.view_xofs1 = DSP4_vars.view_xofs2; - DSP4_vars.view_yofs1 = DSP4_vars.view_yofs2; - - // add deltas for projection lines - DSP4_vars.world_dx += SEX78(DSP4_vars.world_ddx); - DSP4_vars.world_dy += SEX78(DSP4_vars.world_ddy); - - // update projection lines - DSP4_vars.world_x += (DSP4_vars.world_dx + DSP4_vars.world_xenv); - DSP4_vars.world_y += DSP4_vars.world_dy; - - // update road turnoff position - DSP4_vars.view_turnoff_x += DSP4_vars.view_turnoff_dx; - - //////////////////////////////////////////////////// - // command check - - // scan next command - DSP4.in_count = 2; - DSP4_WAIT(2) resume2: - - // check for termination - DSP4_vars.distance = DSP4_READ_WORD(); - if (DSP4_vars.distance == -0x8000) - break; - - // road splice - if( (uint16) DSP4_vars.distance == 0x8001 ) - { - DSP4.in_count = 6; - DSP4_WAIT(3) resume3: - - DSP4_vars.distance = DSP4_READ_WORD(); - DSP4_vars.view_turnoff_x = DSP4_READ_WORD(); - DSP4_vars.view_turnoff_dx = DSP4_READ_WORD(); - - // factor in new changes - DSP4_vars.view_x1 += ( DSP4_vars.view_turnoff_x * DSP4_vars.distance >> 15 ); - DSP4_vars.view_xofs1 += ( DSP4_vars.view_turnoff_x * DSP4_vars.distance >> 15 ); - - // update stepping values - DSP4_vars.view_turnoff_x += DSP4_vars.view_turnoff_dx; - - DSP4.in_count = 2; - DSP4_WAIT(2) - } - - // already have 2 bytes in queue - DSP4.in_count = 6; - DSP4_WAIT(4) resume4 : - - // inspect inputs - DSP4_vars.world_ddy = DSP4_READ_WORD(); - DSP4_vars.world_ddx = DSP4_READ_WORD(); - DSP4_vars.view_yofsenv = DSP4_READ_WORD(); - - // no envelope here - DSP4_vars.world_xenv = 0; - } - while (1); - - // terminate op - DSP4.waiting4command = TRUE; -} - -////////////////////////////////////////////////////////////// - - -void DSP4_OP10() -{ - DSP4.waiting4command = FALSE; - - // op flow control - switch (DSP4_vars.DSP4_Logic) - { - case 1: - goto resume1; break; - case 2: - goto resume2; break; - case 3: - goto resume3; break; - } - - //////////////////////////////////////////////////// - // sort inputs - - DSP4_READ_WORD(); // 0x0000 - DSP4_vars.world_y = DSP4_READ_DWORD(); - DSP4_vars.poly_bottom[0][0] = DSP4_READ_WORD(); - DSP4_vars.poly_top[0][0] = DSP4_READ_WORD(); - DSP4_vars.poly_cx[1][0] = DSP4_READ_WORD(); - DSP4_vars.viewport_bottom = DSP4_READ_WORD(); - DSP4_vars.world_x = DSP4_READ_DWORD(); - DSP4_vars.poly_cx[0][0] = DSP4_READ_WORD(); - DSP4_vars.poly_ptr[0][0] = DSP4_READ_WORD(); - DSP4_vars.world_yofs = DSP4_READ_WORD(); - DSP4_vars.distance = DSP4_READ_WORD(); - DSP4_vars.view_y2 = DSP4_READ_WORD(); - DSP4_vars.view_dy = DSP4_READ_WORD() * DSP4_vars.distance >> 15; - DSP4_vars.view_x2 = DSP4_READ_WORD(); - DSP4_vars.view_dx = DSP4_READ_WORD() * DSP4_vars.distance >> 15; - DSP4_vars.view_yofsenv = DSP4_READ_WORD(); - - // initial (x,y,offset) at starting DSP4_vars.raster line - DSP4_vars.view_x1 = (int16)(DSP4_vars.world_x >> 16); - DSP4_vars.view_y1 = (int16)(DSP4_vars.world_y >> 16); - DSP4_vars.view_xofs1 = DSP4_vars.view_x1; - DSP4_vars.view_yofs1 = DSP4_vars.world_yofs; - - // first DSP4_vars.raster line - DSP4_vars.poly_raster[0][0] = DSP4_vars.poly_bottom[0][0]; - - do - { - //////////////////////////////////////////////////// - // process one iteration of projection - - // add shaping - DSP4_vars.view_x2 += DSP4_vars.view_dx; - DSP4_vars.view_y2 += DSP4_vars.view_dy; - - // vertical scroll calculation - DSP4_vars.view_xofs2 = DSP4_vars.view_x2; - DSP4_vars.view_yofs2 = (DSP4_vars.world_yofs * DSP4_vars.distance >> 15) + DSP4_vars.poly_bottom[0][0] - DSP4_vars.view_y2; - - // 1. Viewer x-position at the next - // 2. Viewer y-position below the horizon - // 3. Number of DSP4_vars.raster lines drawn in this iteration - - DSP4_CLEAR_OUT(); - DSP4_WRITE_WORD(DSP4_vars.view_x2); - DSP4_WRITE_WORD(DSP4_vars.view_y2); - - ////////////////////////////////////////////////////// - - // SR = 0x00 - - // determine # of DSP4_vars.raster lines used - DSP4_vars.segments = DSP4_vars.view_y1 - DSP4_vars.view_y2; - - // prevent overdraw - if (DSP4_vars.view_y2 >= DSP4_vars.poly_raster[0][0]) - DSP4_vars.segments = 0; - else - DSP4_vars.poly_raster[0][0] = DSP4_vars.view_y2; - - // don't draw outside the window - if (DSP4_vars.view_y2 < DSP4_vars.poly_top[0][0]) - { - DSP4_vars.segments = 0; - - // flush remaining DSP4_vars.raster lines - if (DSP4_vars.view_y1 >= DSP4_vars.poly_top[0][0]) - DSP4_vars.segments = DSP4_vars.view_y1 - DSP4_vars.poly_top[0][0]; - } - - // SR = 0x80 - - DSP4_WRITE_WORD(DSP4_vars.segments); - - ////////////////////////////////////////////////////// - - // scan next command if no SR check needed - if (DSP4_vars.segments) - { - for (DSP4_vars.lcv = 0; DSP4_vars.lcv < 4; DSP4_vars.lcv++) - { - // grab inputs - DSP4.in_count = 4; - DSP4_WAIT(1); - resume1 : - for (;;) - { - int16 distance; - int16 color, red, green, blue; - - distance = DSP4_READ_WORD(); - color = DSP4_READ_WORD(); - - // U1+B5+G5+R5 - red = color & 0x1f; - green = (color >> 5) & 0x1f; - blue = (color >> 10) & 0x1f; - - // dynamic lighting - red = (red * distance >> 15) & 0x1f; - green = (green * distance >> 15) & 0x1f; - blue = (blue * distance >> 15) & 0x1f; - color = red | (green << 5) | (blue << 10); - - DSP4_CLEAR_OUT(); - DSP4_WRITE_WORD(color); - break; - } - } - } - - ////////////////////////////////////////////////////// - - // scan next command if no SR check needed - if (DSP4_vars.segments) - { - int32 px_dx, py_dy; - int32 x_scroll, y_scroll; - - // SR = 0x00 - - // linear interpolation (lerp) between projected points - px_dx = (DSP4_vars.view_xofs2 - DSP4_vars.view_xofs1) * DSP4_Inverse(DSP4_vars.segments) << 1; - py_dy = (DSP4_vars.view_yofs2 - DSP4_vars.view_yofs1) * DSP4_Inverse(DSP4_vars.segments) << 1; - - // starting step values - x_scroll = SEX16(DSP4_vars.poly_cx[0][0] + DSP4_vars.view_xofs1); - y_scroll = SEX16(-DSP4_vars.viewport_bottom + DSP4_vars.view_yofs1 + DSP4_vars.view_yofsenv + DSP4_vars.poly_cx[1][0] - DSP4_vars.world_yofs); - - // SR = 0x80 - - // rasterize line - for (DSP4_vars.lcv = 0; DSP4_vars.lcv < DSP4_vars.segments; DSP4_vars.lcv++) - { - // 1. HDMA memory pointer (bg2) - // 2. vertical scroll offset ($2110) - // 3. horizontal scroll offset ($210F) - - DSP4_WRITE_WORD(DSP4_vars.poly_ptr[0][0]); - DSP4_WRITE_WORD((uint16)((y_scroll + 0x8000) >> 16)); - DSP4_WRITE_WORD((uint16)((x_scroll + 0x8000) >> 16)); - - // update memory address - DSP4_vars.poly_ptr[0][0] -= 4; - - // update screen values - x_scroll += px_dx; - y_scroll += py_dy; - } - } - - ///////////////////////////////////////////////////// - // Post-update - - // update new viewer (x,y,scroll) to last DSP4_vars.raster line drawn - DSP4_vars.view_x1 = DSP4_vars.view_x2; - DSP4_vars.view_y1 = DSP4_vars.view_y2; - DSP4_vars.view_xofs1 = DSP4_vars.view_xofs2; - DSP4_vars.view_yofs1 = DSP4_vars.view_yofs2; - - //////////////////////////////////////////////////// - // command check - - // scan next command - DSP4.in_count = 2; - DSP4_WAIT(2) resume2 : - - // check for opcode termination - DSP4_vars.distance = DSP4_READ_WORD(); - if (DSP4_vars.distance == -0x8000) - break; - - // already have 2 bytes in queue - DSP4.in_count = 10; - DSP4_WAIT(3) resume3 : - - - // inspect inputs - DSP4_vars.view_y2 = DSP4_READ_WORD(); - DSP4_vars.view_dy = DSP4_READ_WORD() * DSP4_vars.distance >> 15; - DSP4_vars.view_x2 = DSP4_READ_WORD(); - DSP4_vars.view_dx = DSP4_READ_WORD() * DSP4_vars.distance >> 15; - } - while (1); - - DSP4.waiting4command = TRUE; -} - -////////////////////////////////////////////////////////////// - -void DSP4_OP11(int16 A, int16 B, int16 C, int16 D, int16 *M) -{ - // 0x155 = 341 = Horizontal Width of the Screen - *M = ((A * 0x0155 >> 2) & 0xf000) | - ((B * 0x0155 >> 6) & 0x0f00) | - ((C * 0x0155 >> 10) & 0x00f0) | - ((D * 0x0155 >> 14) & 0x000f); -} - - - - - -///////////////////////////////////////////////////////////// -//Processing Code -///////////////////////////////////////////////////////////// -uint8 dsp4_byte; -uint16 dsp4_address; - -void InitDSP4() -{ - memset(&DSP4, 0, sizeof(DSP4)); - DSP4.waiting4command = TRUE; -} - -void DSP4SetByte() -{ - // clear pending read - if (DSP4.out_index < DSP4.out_count) - { - DSP4.out_index++; - return; - } - - if (DSP4.waiting4command) - { - if (DSP4.half_command) - { - DSP4.command |= (dsp4_byte << 8); - DSP4.in_index = 0; - DSP4.waiting4command = FALSE; - DSP4.half_command = FALSE; - DSP4.out_count = 0; - DSP4.out_index = 0; - - DSP4_vars.DSP4_Logic = 0; - - - switch (DSP4.command) - { - case 0x0000: - DSP4.in_count = 4; break; - case 0x0001: - DSP4.in_count = 44; break; - case 0x0003: - DSP4.in_count = 0; break; - case 0x0005: - DSP4.in_count = 0; break; - case 0x0006: - DSP4.in_count = 0; break; - case 0x0007: - DSP4.in_count = 34; break; - case 0x0008: - DSP4.in_count = 90; break; - case 0x0009: - DSP4.in_count = 14; break; - case 0x000a: - DSP4.in_count = 6; break; - case 0x000b: - DSP4.in_count = 6; break; - case 0x000d: - DSP4.in_count = 42; break; - case 0x000e: - DSP4.in_count = 0; break; - case 0x000f: - DSP4.in_count = 46; break; - case 0x0010: - DSP4.in_count = 36; break; - case 0x0011: - DSP4.in_count = 8; break; - default: - DSP4.waiting4command = TRUE; - break; - } - } - else - { - DSP4.command = dsp4_byte; - DSP4.half_command = TRUE; - } - } - else - { - DSP4.parameters[DSP4.in_index] = dsp4_byte; - DSP4.in_index++; - } - - if (!DSP4.waiting4command && DSP4.in_count == DSP4.in_index) - { - // Actually execute the command - DSP4.waiting4command = TRUE; - DSP4.out_index = 0; - DSP4.in_index = 0; - - switch (DSP4.command) - { - // 16-bit multiplication - case 0x0000: - { - int16 multiplier, multiplicand; - int32 product; - - multiplier = DSP4_READ_WORD(); - multiplicand = DSP4_READ_WORD(); - - DSP4_Multiply(multiplicand, multiplier, &product); - - DSP4_CLEAR_OUT(); - DSP4_WRITE_WORD((uint16)(product)); - DSP4_WRITE_WORD((uint16)(product >> 16)); - } - break; - - // single-player track projection - case 0x0001: - DSP4_OP01(); break; - - // single-player selection - case 0x0003: - DSP4_OP03(); break; - - // clear OAM - case 0x0005: - DSP4_OP05(); break; - - // transfer OAM - case 0x0006: - DSP4_OP06(); break; - - // single-player track turnoff projection - case 0x0007: - DSP4_OP07(); break; - - // solid polygon projection - case 0x0008: - DSP4_OP08(); break; - - // sprite projection - case 0x0009: - DSP4_OP09(); break; - - // unknown - case 0x000A: - { - int16 in1a = DSP4_READ_WORD(); - int16 in2a = DSP4_READ_WORD(); - int16 in3a = DSP4_READ_WORD(); - int16 out1a, out2a, out3a, out4a; - - DSP4_OP0A(in2a, &out2a, &out1a, &out4a, &out3a); - - DSP4_CLEAR_OUT(); - DSP4_WRITE_WORD(out1a); - DSP4_WRITE_WORD(out2a); - DSP4_WRITE_WORD(out3a); - DSP4_WRITE_WORD(out4a); - } - break; - - // set OAM - case 0x000B: - { - int16 sp_x = DSP4_READ_WORD(); - int16 sp_y = DSP4_READ_WORD(); - int16 sp_attr = DSP4_READ_WORD(); - bool8 draw = 1; - - DSP4_CLEAR_OUT(); - - DSP4_OP0B(&draw, sp_x, sp_y, sp_attr, 0, 1); - } - break; - - // multi-player track projection - case 0x000D: - DSP4_OP0D(); break; - - // multi-player selection - case 0x000E: - DSP4_OP0E(); break; - - // single-player track projection with lighting - case 0x000F: - DSP4_OP0F(); break; - - // single-player track turnoff projection with lighting - case 0x0010: - DSP4_OP10(); break; - - // unknown: horizontal mapping command - case 0x0011: - { - int16 a, b, c, d, m; - - - d = DSP4_READ_WORD(); - c = DSP4_READ_WORD(); - b = DSP4_READ_WORD(); - a = DSP4_READ_WORD(); - - DSP4_OP11(a, b, c, d, &m); - - DSP4_CLEAR_OUT(); - DSP4_WRITE_WORD(m); - - break; - } - - default: - break; - } - } -} - -void DSP4GetByte() -{ - if (DSP4.out_count) - { - dsp4_byte = (uint8) DSP4.output[DSP4.out_index&0x1FF]; - DSP4.out_index++; - if (DSP4.out_count == DSP4.out_index) - DSP4.out_count = 0; - } - else - { - dsp4_byte = 0xff; - } -} - -#endif diff --git a/bsnes/snes/chip/dsp4/dsp4emu.h b/bsnes/snes/chip/dsp4/dsp4emu.h deleted file mode 100755 index 834b33de..00000000 --- a/bsnes/snes/chip/dsp4/dsp4emu.h +++ /dev/null @@ -1,108 +0,0 @@ -//DSP-4 emulator code -//Copyright (c) 2004-2006 Dreamer Nom, John Weidman, Kris Bleakley, Nach, z80 gaiden - -#ifndef DSP4EMU_H -#define DSP4EMU_H - -#undef TRUE -#undef FALSE -#define TRUE true -#define FALSE false - -struct DSP4_t -{ - bool8 waiting4command; - bool8 half_command; - uint16 command; - uint32 in_count; - uint32 in_index; - uint32 out_count; - uint32 out_index; - uint8 parameters[512]; - uint8 output[512]; -}; - -extern struct DSP4_t DSP4; - -struct DSP4_vars_t -{ - // op control - int8 DSP4_Logic; // controls op flow - - - // projection format - int16 lcv; // loop-control variable - int16 distance; // z-position into virtual world - int16 raster; // current raster line - int16 segments; // number of raster lines drawn - - // 1.15.16 or 1.15.0 [sign, integer, fraction] - int32 world_x; // line of x-projection in world - int32 world_y; // line of y-projection in world - int32 world_dx; // projection line x-delta - int32 world_dy; // projection line y-delta - int16 world_ddx; // x-delta increment - int16 world_ddy; // y-delta increment - int32 world_xenv; // world x-shaping factor - int16 world_yofs; // world y-vertical scroll - - int16 view_x1; // current viewer-x - int16 view_y1; // current viewer-y - int16 view_x2; // future viewer-x - int16 view_y2; // future viewer-y - int16 view_dx; // view x-delta factor - int16 view_dy; // view y-delta factor - int16 view_xofs1; // current viewer x-vertical scroll - int16 view_yofs1; // current viewer y-vertical scroll - int16 view_xofs2; // future viewer x-vertical scroll - int16 view_yofs2; // future viewer y-vertical scroll - int16 view_yofsenv; // y-scroll shaping factor - int16 view_turnoff_x; // road turnoff data - int16 view_turnoff_dx; // road turnoff delta factor - - - // drawing area - - int16 viewport_cx; // x-center of viewport window - int16 viewport_cy; // y-center of render window - int16 viewport_left; // x-left of viewport - int16 viewport_right; // x-right of viewport - int16 viewport_top; // y-top of viewport - int16 viewport_bottom; // y-bottom of viewport - - - // sprite structure - - int16 sprite_x; // projected x-pos of sprite - int16 sprite_y; // projected y-pos of sprite - int16 sprite_attr; // obj attributes - bool8 sprite_size; // sprite size: 8x8 or 16x16 - int16 sprite_clipy; // visible line to clip pixels off - int16 sprite_count; - - // generic projection variables designed for - // two solid polygons + two polygon sides - - int16 poly_clipLf[2][2]; // left clip boundary - int16 poly_clipRt[2][2]; // right clip boundary - int16 poly_ptr[2][2]; // HDMA structure pointers - int16 poly_raster[2][2]; // current raster line below horizon - int16 poly_top[2][2]; // top clip boundary - int16 poly_bottom[2][2]; // bottom clip boundary - int16 poly_cx[2][2]; // center for left/right points - int16 poly_start[2]; // current projection points - int16 poly_plane[2]; // previous z-plane distance - - - // OAM - int16 OAM_attr[16]; // OAM (size,MSB) data - int16 OAM_index; // index into OAM table - int16 OAM_bits; // offset into OAM table - - int16 OAM_RowMax; // maximum number of tiles per 8 aligned pixels (row) - int16 OAM_Row[32]; // current number of tiles per row -}; - -extern struct DSP4_vars_t DSP4_vars; - -#endif diff --git a/bsnes/snes/chip/upd77c25/upd77c25.cpp b/bsnes/snes/chip/upd77c25/upd77c25.cpp index abc0ae05..99a3d540 100755 --- a/bsnes/snes/chip/upd77c25/upd77c25.cpp +++ b/bsnes/snes/chip/upd77c25/upd77c25.cpp @@ -2,6 +2,11 @@ //author: byuu //license: public domain +//unsupported components: +//* serial input/output +//* interrupts +//* DMA + #include #define UPD77C25_CPP @@ -98,8 +103,8 @@ void UPD77C25::exec_op(uint24 opcode) { case 10: r = ~q; break; //CMP case 11: r = (q >> 1) | (q & 0x8000); break; //SHR1 (ASR) case 12: r = (q << 1) | c; break; //SHL1 (ROL) - case 13: r = (q << 2); break; //SHL2 - case 14: r = (q << 4); break; //SHL4 + case 13: r = (q << 2) | 3; break; //SHL2 + case 14: r = (q << 4) | 15; break; //SHL4 case 15: r = (q << 8) | (q >> 8); break; //XCHG } @@ -310,7 +315,7 @@ void UPD77C25::enable() { } void UPD77C25::power() { - for(unsigned i = 0; i < 256; i++) dataRAM[i] = 0x0000; + for(unsigned i = 0; i < 256; i++) dataRAM[i] = 0x0000; reset(); } diff --git a/bsnes/snes/interface/interface.hpp b/bsnes/snes/interface/interface.hpp index e9ec2635..fb236aea 100755 --- a/bsnes/snes/interface/interface.hpp +++ b/bsnes/snes/interface/interface.hpp @@ -4,4 +4,6 @@ public: virtual void audio_sample(uint16_t l_sample, uint16_t r_sample) {} virtual void input_poll() {} virtual int16_t input_poll(bool port, Input::Device device, unsigned index, unsigned id) { return 0; } + + virtual void message(const string &text) { print(text, "\n"); } }; diff --git a/bsnes/snes/snes.hpp b/bsnes/snes/snes.hpp index 97ac04fa..858d3756 100755 --- a/bsnes/snes/snes.hpp +++ b/bsnes/snes/snes.hpp @@ -1,7 +1,7 @@ namespace SNES { namespace Info { static const char Name[] = "bsnes"; - static const char Version[] = "072.13"; + static const char Version[] = "072.14"; static const unsigned SerializerVersion = 14; } } diff --git a/bsnes/snes/system/serialization.cpp b/bsnes/snes/system/serialization.cpp index 4fbce43e..1b87ce51 100755 --- a/bsnes/snes/system/serialization.cpp +++ b/bsnes/snes/system/serialization.cpp @@ -65,8 +65,6 @@ void System::serialize_all(serializer &s) { if(cartridge.has_sdd1()) sdd1.serialize(s); if(cartridge.has_spc7110()) spc7110.serialize(s); if(cartridge.has_cx4()) cx4.serialize(s); - if(cartridge.has_dsp1()) dsp1.serialize(s); - if(cartridge.has_dsp2()) dsp2.serialize(s); if(cartridge.has_obc1()) obc1.serialize(s); if(cartridge.has_st0010()) st0010.serialize(s); if(cartridge.has_msu1()) msu1.serialize(s); diff --git a/bsnes/snes/system/system.cpp b/bsnes/snes/system/system.cpp index 23476238..bebd7258 100755 --- a/bsnes/snes/system/system.cpp +++ b/bsnes/snes/system/system.cpp @@ -79,10 +79,6 @@ void System::init(Interface *interface_) { sdd1.init(); spc7110.init(); cx4.init(); - dsp1.init(); - dsp2.init(); - dsp3.init(); - dsp4.init(); obc1.init(); st0010.init(); st0011.init(); @@ -132,10 +128,6 @@ void System::power() { if(cartridge.has_sdd1()) sdd1.enable(); if(cartridge.has_spc7110()) spc7110.enable(); if(cartridge.has_cx4()) cx4.enable(); - if(cartridge.has_dsp1()) dsp1.enable(); - if(cartridge.has_dsp2()) dsp2.enable(); - if(cartridge.has_dsp3()) dsp3.enable(); - if(cartridge.has_dsp4()) dsp4.enable(); if(cartridge.has_obc1()) obc1.enable(); if(cartridge.has_st0010()) st0010.enable(); if(cartridge.has_st0011()) st0011.enable(); @@ -160,10 +152,6 @@ void System::power() { if(cartridge.has_sdd1()) sdd1.power(); if(cartridge.has_spc7110()) spc7110.power(); if(cartridge.has_cx4()) cx4.power(); - if(cartridge.has_dsp1()) dsp1.power(); - if(cartridge.has_dsp2()) dsp2.power(); - if(cartridge.has_dsp3()) dsp3.power(); - if(cartridge.has_dsp4()) dsp4.power(); if(cartridge.has_obc1()) obc1.power(); if(cartridge.has_st0010()) st0010.power(); if(cartridge.has_st0011()) st0011.power(); @@ -203,10 +191,6 @@ void System::reset() { if(cartridge.has_sdd1()) sdd1.reset(); if(cartridge.has_spc7110()) spc7110.reset(); if(cartridge.has_cx4()) cx4.reset(); - if(cartridge.has_dsp1()) dsp1.reset(); - if(cartridge.has_dsp2()) dsp2.reset(); - if(cartridge.has_dsp3()) dsp3.reset(); - if(cartridge.has_dsp4()) dsp4.reset(); if(cartridge.has_obc1()) obc1.reset(); if(cartridge.has_st0010()) st0010.reset(); if(cartridge.has_st0011()) st0011.reset(); diff --git a/bsnes/ui-phoenix/interface.cpp b/bsnes/ui-phoenix/interface.cpp index e35af270..143c6048 100755 --- a/bsnes/ui-phoenix/interface.cpp +++ b/bsnes/ui-phoenix/interface.cpp @@ -133,3 +133,7 @@ int16_t Interface::input_poll(bool port, SNES::Input::Device device, unsigned in if(config.settings.focusPolicy == 1 && mainWindow.focused() == false) return 0; return inputMapper.poll(port, device, index, id); } + +void Interface::message(const string &text) { + MessageWindow::information(mainWindow, text); +} diff --git a/bsnes/ui-phoenix/interface.hpp b/bsnes/ui-phoenix/interface.hpp index fbc22036..34f795c0 100755 --- a/bsnes/ui-phoenix/interface.hpp +++ b/bsnes/ui-phoenix/interface.hpp @@ -19,6 +19,8 @@ struct Interface : public SNES::Interface { void audio_sample(uint16_t left, uint16_t right); void input_poll(); int16_t input_poll(bool port, SNES::Input::Device device, unsigned index, unsigned id); + + void message(const string &text); }; extern Palette palette; diff --git a/bsnes/ui-qt/cartridge/cartridge.cpp b/bsnes/ui-qt/cartridge/cartridge.cpp index 520848c7..77754d14 100755 --- a/bsnes/ui-qt/cartridge/cartridge.cpp +++ b/bsnes/ui-qt/cartridge/cartridge.cpp @@ -45,8 +45,6 @@ bool Cartridge::information(const char *filename, Cartridge::Information &info) bool Cartridge::saveStatesSupported() { if(SNES::cartridge.mode() == SNES::Cartridge::Mode::Bsx) return false; - if(SNES::cartridge.has_dsp3()) return false; - if(SNES::cartridge.has_dsp4()) return false; if(SNES::cartridge.has_st0011()) return false; if(SNES::cartridge.has_st0018()) return false; if(SNES::cartridge.has_serial()) return false; diff --git a/bsnes/ui-qt/utility/system-state.cpp b/bsnes/ui-qt/utility/system-state.cpp index 42a6e26d..c4afb4b0 100755 --- a/bsnes/ui-qt/utility/system-state.cpp +++ b/bsnes/ui-qt/utility/system-state.cpp @@ -19,7 +19,6 @@ void Utility::modifySystemState(system_state_t systemState) { //warn if unsupported hardware detected string chip; if(0); - else if(SNES::cartridge.has_dsp3()) chip = "DSP-3"; else if(SNES::cartridge.has_st0011()) chip = "ST-0011"; else if(SNES::cartridge.has_st0018()) chip = "ST-0018"; if(chip != "") {