mirror of
https://github.com/rt64/rt64.git
synced 2024-12-25 18:14:31 +00:00
Add egbi command to bypass the segment table for K0 CPU addresses to allow extending rdram (#54)
* Add egbi command to bypass the segment table for K0 CPU addresses to allow extending rdram * Fix capitalization of RDRAM for consistency
This commit is contained in:
parent
5c1562d66a
commit
eb981eb47b
@ -72,7 +72,8 @@
|
||||
#define G_EX_PUSHGEOMETRYMODE_V1 0x000029
|
||||
#define G_EX_POPGEOMETRYMODE_V1 0x00002A
|
||||
#define G_EX_SETDITHERNOISESTRENGTH_V1 0x00002B
|
||||
#define G_EX_MAX 0x00002C
|
||||
#define G_EX_SETRDRAMEXTENDED_V1 0x00002C
|
||||
#define G_EX_MAX 0x00002D
|
||||
|
||||
#define G_EX_ORIGIN_NONE 0x800
|
||||
#define G_EX_ORIGIN_LEFT 0x0
|
||||
@ -508,4 +509,10 @@ typedef union {
|
||||
PARAM((value) * 1024, 16, 0) \
|
||||
)
|
||||
|
||||
#define gEXSetRDRAMExtended(cmd, isExtended) \
|
||||
G_EX_COMMAND1(cmd, \
|
||||
PARAM(RT64_EXTENDED_OPCODE, 8, 24) | PARAM(G_EX_SETRDRAMEXTENDED_V1, 24, 0), \
|
||||
PARAM(isExtended, 1, 0) \
|
||||
)
|
||||
|
||||
#endif // RT64_EXTENDED_GBI
|
||||
|
@ -286,6 +286,11 @@ namespace RT64 {
|
||||
state->setDitherNoiseStrength(noiseStrength / 1024.0f);
|
||||
}
|
||||
|
||||
void setRDRAMExtendedV1(State *state, DisplayList **dl) {
|
||||
const uint8_t extended = (*dl)->p1(0, 1);
|
||||
state->setExtendedRDRAM(extended);
|
||||
}
|
||||
|
||||
void noOpHook(State *state, DisplayList **dl) {
|
||||
uint32_t magicNumber = (*dl)->p0(0, 24);
|
||||
if (magicNumber == RT64_HOOK_MAGIC_NUMBER) {
|
||||
@ -293,7 +298,7 @@ namespace RT64 {
|
||||
uint32_t hookOp = (*dl)->p1(28, 4);
|
||||
switch (hookOp) {
|
||||
case RT64_HOOK_OP_GETVERSION: {
|
||||
const uint32_t rdramAddress = state->rsp->fromSegmented(hookValue);
|
||||
const uint32_t rdramAddress = state->rsp->fromSegmentedMasked(hookValue);
|
||||
uint32_t *returnRDRAM = reinterpret_cast<uint32_t *>(state->fromRDRAM(rdramAddress));
|
||||
*returnRDRAM = G_EX_VERSION;
|
||||
break;
|
||||
@ -317,7 +322,7 @@ namespace RT64 {
|
||||
state->pushReturnAddress(*dl);
|
||||
}
|
||||
|
||||
const uint32_t rdramAddress = state->rsp->fromSegmented(hookValue);
|
||||
const uint32_t rdramAddress = state->rsp->fromSegmentedMasked(hookValue);
|
||||
*dl = reinterpret_cast<DisplayList *>(state->fromRDRAM(rdramAddress)) - 1;
|
||||
break;
|
||||
}
|
||||
@ -386,6 +391,7 @@ namespace RT64 {
|
||||
Map[G_EX_PUSHGEOMETRYMODE_V1] = &pushGeometryModeV1;
|
||||
Map[G_EX_POPGEOMETRYMODE_V1] = &popGeometryModeV1;
|
||||
Map[G_EX_SETDITHERNOISESTRENGTH_V1] = &setDitherNoiseStrengthV1;
|
||||
Map[G_EX_SETRDRAMEXTENDED_V1] = &setRDRAMExtendedV1;
|
||||
MapInitialized = true;
|
||||
}
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ namespace RT64 {
|
||||
state->pushReturnAddress(*dl);
|
||||
}
|
||||
|
||||
const uint32_t rdramAddress = state->rsp->fromSegmented((*dl)->w1);
|
||||
const uint32_t rdramAddress = state->rsp->fromSegmentedMasked((*dl)->w1);
|
||||
*dl = reinterpret_cast<DisplayList *>(state->fromRDRAM(rdramAddress)) - 1;
|
||||
}
|
||||
|
||||
@ -121,7 +121,7 @@ namespace RT64 {
|
||||
// TODO
|
||||
break;
|
||||
case G_MW_SEGMENT:
|
||||
state->rsp->setSegment((*dl)->p0(10, 4), (*dl)->w1 & 0x00FFFFFF);
|
||||
state->rsp->setSegment((*dl)->p0(10, 4), (*dl)->w1);
|
||||
break;
|
||||
case G_MW_FOG:
|
||||
state->rsp->setFog((int16_t)((*dl)->p1(16, 16)), (int16_t)((*dl)->p1(0, 16)));
|
||||
|
@ -77,7 +77,7 @@ namespace RT64 {
|
||||
state->rsp->setClipRatio((*dl)->w1);
|
||||
break;
|
||||
case G_MW_SEGMENT:
|
||||
state->rsp->setSegment((*dl)->p0(2, 4), (*dl)->w1 & 0x00FFFFFF);
|
||||
state->rsp->setSegment((*dl)->p0(2, 4), (*dl)->w1);
|
||||
break;
|
||||
case G_MW_FOG:
|
||||
state->rsp->setFog((int16_t)((*dl)->p1(16, 16)), (int16_t)((*dl)->p1(0, 16)));
|
||||
|
@ -133,7 +133,7 @@ namespace RT64 {
|
||||
|
||||
RDP *rdp = state->rdp.get();
|
||||
RSP *rsp = state->rsp.get();
|
||||
const uint32_t rdramAddress = state->rsp->fromSegmented((*dl)->w1);
|
||||
const uint32_t rdramAddress = state->rsp->fromSegmentedMasked((*dl)->w1);
|
||||
// TODO load this into the S2D struct buffer for a more accurate implementation in case there's ever command state bleed.
|
||||
const uObjBg *bgObject = reinterpret_cast<const uObjBg *>(state->fromRDRAM(rdramAddress));
|
||||
const uObjBg_t &bg = bgObject->bg;
|
||||
@ -398,7 +398,7 @@ namespace RT64 {
|
||||
|
||||
RDP *rdp = state->rdp.get();
|
||||
RSP* rsp = state->rsp.get();
|
||||
const uint32_t rdramAddress = state->rsp->fromSegmented((*dl)->w1);
|
||||
const uint32_t rdramAddress = state->rsp->fromSegmentedMasked((*dl)->w1);
|
||||
// TODO load this into the S2D struct buffer for a more accurate implementation in case there's ever command state bleed.
|
||||
const uObjBg *bgObject = reinterpret_cast<const uObjBg *>(state->fromRDRAM(rdramAddress));
|
||||
const uObjBg_t &bg = bgObject->bg;
|
||||
@ -451,7 +451,7 @@ namespace RT64 {
|
||||
|
||||
void readS2DStruct(State *state, uint32_t ptr, uint32_t loadSize) {
|
||||
// Convert the segmented obj pointer
|
||||
uint32_t rdramAddress = state->rsp->fromSegmented(ptr);
|
||||
uint32_t rdramAddress = state->rsp->fromSegmentedMasked(ptr);
|
||||
// Mask the address as the RSP DMA hardware would
|
||||
rdramAddress &= RSP_DMA_MASK;
|
||||
// Truncate the load size as the ucode does
|
||||
|
@ -222,10 +222,17 @@ namespace RT64 {
|
||||
}
|
||||
};
|
||||
|
||||
uint32_t RDP::maskAddress(uint32_t address) {
|
||||
if (state->extended.extendRDRAM && ((address & 0xF0000000) == 0x80000000)) {
|
||||
return address - 0x80000000;
|
||||
}
|
||||
return address & RDP_ADDRESS_MASK;
|
||||
}
|
||||
|
||||
void RDP::setColorImage(uint8_t fmt, uint8_t siz, uint16_t width, uint32_t address) {
|
||||
// Make sure the new color image is actually different. Some games will set the color image
|
||||
// multiple times despite setting the exact same parameters.
|
||||
const uint32_t newAddress = address & RDP_ADDRESS_MASK;
|
||||
const uint32_t newAddress = maskAddress(address);
|
||||
if ((colorImage.fmt != fmt) ||
|
||||
(colorImage.siz != siz) ||
|
||||
(colorImage.width != width) ||
|
||||
@ -244,7 +251,7 @@ namespace RT64 {
|
||||
}
|
||||
|
||||
void RDP::setDepthImage(uint32_t address) {
|
||||
const uint32_t newAddress = address & RDP_ADDRESS_MASK;
|
||||
const uint32_t newAddress = maskAddress(address);
|
||||
if (depthImage.address != newAddress) {
|
||||
depthImage.address = newAddress;
|
||||
depthImage.changed = true;
|
||||
@ -259,7 +266,7 @@ namespace RT64 {
|
||||
texture.fmt = fmt;
|
||||
texture.siz = siz;
|
||||
texture.width = width;
|
||||
texture.address = address & RDP_ADDRESS_MASK;
|
||||
texture.address = maskAddress(address);
|
||||
state->updateDrawStatusAttribute(DrawAttribute::Texture);
|
||||
|
||||
# ifdef LOG_TEXTURE_IMAGE_METHODS
|
||||
|
@ -142,6 +142,7 @@ namespace RT64 {
|
||||
void checkFramebufferOverlap(uint32_t tmemStart, uint32_t tmemWords, uint32_t tmemMask, uint32_t addressStart, uint32_t addressEnd, uint32_t tileWidth, uint32_t tileHeight, bool RGBA32, bool makeTileCopy);
|
||||
void checkImageOverlap(uint32_t addressStart, uint32_t addressEnd);
|
||||
int32_t movedFromOrigin(int32_t x, uint16_t ori);
|
||||
uint32_t maskAddress(uint32_t address);
|
||||
void setColorImage(uint8_t fmt, uint8_t siz, uint16_t width, uint32_t address);
|
||||
void setDepthImage(uint32_t address);
|
||||
void setTextureImage(uint8_t fmt, uint8_t siz, uint16_t width, uint32_t address);
|
||||
|
@ -90,17 +90,35 @@ namespace RT64 {
|
||||
clearExtended();
|
||||
}
|
||||
|
||||
// Masks addresses as the RSP DMA hardware would.
|
||||
uint32_t RSP::maskPhysicalAddress(uint32_t address) {
|
||||
if (state->extended.extendRDRAM && ((address & 0xF0000000) == 0x80000000)) {
|
||||
return address - 0x80000000;
|
||||
}
|
||||
return address & 0x00FFFFF8;
|
||||
}
|
||||
|
||||
// Performs a lookup in the segment table to convert the given address.
|
||||
uint32_t RSP::fromSegmented(uint32_t segAddress) {
|
||||
if (state->extended.extendRDRAM && ((segAddress & 0xF0000000) == 0x80000000)) {
|
||||
return segAddress;
|
||||
}
|
||||
return segments[((segAddress) >> 24) & 0x0F] + ((segAddress) & 0x00FFFFFF);
|
||||
}
|
||||
|
||||
// Converts the given segmented address and then applies the RSP DMA physical address mask.
|
||||
// Used in cases where the RSP performs a DMA with a segmented address as the input.
|
||||
uint32_t RSP::fromSegmentedMasked(uint32_t segAddress) {
|
||||
return maskPhysicalAddress(fromSegmented(segAddress));
|
||||
}
|
||||
|
||||
void RSP::setSegment(uint32_t seg, uint32_t address) {
|
||||
assert(seg < RSP_MAX_SEGMENTS);
|
||||
segments[seg] = address;
|
||||
}
|
||||
|
||||
void RSP::matrix(uint32_t address, uint8_t params) {
|
||||
const uint32_t rdramAddress = fromSegmented(address);
|
||||
const uint32_t rdramAddress = fromSegmentedMasked(address);
|
||||
const FixedMatrix *fixedMatrix = reinterpret_cast<FixedMatrix *>(state->fromRDRAM(rdramAddress));
|
||||
const hlslpp::float4x4 floatMatrix = fixedMatrix->toMatrix4x4();
|
||||
|
||||
@ -258,7 +276,7 @@ namespace RT64 {
|
||||
RT64_LOG_PRINTF("RSP::forceMatrix(0x%08X)", address);
|
||||
# endif
|
||||
|
||||
const uint32_t rdramAddress = fromSegmented(address);
|
||||
const uint32_t rdramAddress = fromSegmentedMasked(address);
|
||||
const FixedMatrix *fixedMatrix = reinterpret_cast<FixedMatrix *>(state->fromRDRAM(rdramAddress));
|
||||
modelViewProjMatrix = fixedMatrix->toMatrix4x4();
|
||||
modelViewProjInserted = true;
|
||||
@ -294,7 +312,7 @@ namespace RT64 {
|
||||
return;
|
||||
}
|
||||
|
||||
const uint32_t rdramAddress = fromSegmented(address);
|
||||
const uint32_t rdramAddress = fromSegmentedMasked(address);
|
||||
const Vertex *dlVerts = reinterpret_cast<const Vertex *>(state->fromRDRAM(rdramAddress));
|
||||
memcpy(&vertices[dstIndex], dlVerts, sizeof(Vertex) * vtxCount);
|
||||
setVertexCommon<true>(dstIndex, dstIndex + vtxCount);
|
||||
@ -306,7 +324,7 @@ namespace RT64 {
|
||||
return;
|
||||
}
|
||||
|
||||
const uint32_t rdramAddress = fromSegmented(address);
|
||||
const uint32_t rdramAddress = fromSegmentedMasked(address);
|
||||
const VertexPD *dlVerts = reinterpret_cast<const VertexPD *>(state->fromRDRAM(rdramAddress));
|
||||
for (uint32_t i = 0; i < vtxCount; i++) {
|
||||
Vertex &dst = vertices[dstIndex + i];
|
||||
@ -334,7 +352,7 @@ namespace RT64 {
|
||||
|
||||
const int workloadCursor = state->ext.workloadQueue->writeCursor;
|
||||
Workload &workload = state->ext.workloadQueue->workloads[workloadCursor];
|
||||
const uint32_t rdramAddress = fromSegmented(address);
|
||||
const uint32_t rdramAddress = fromSegmentedMasked(address);
|
||||
const VertexEXV1 *dlVerts = reinterpret_cast<const VertexEXV1 *>(state->fromRDRAM(rdramAddress));
|
||||
auto &velShorts = workload.drawData.velShorts;
|
||||
for (uint32_t i = 0; i < vtxCount; i++) {
|
||||
@ -349,7 +367,7 @@ namespace RT64 {
|
||||
}
|
||||
|
||||
void RSP::setVertexColorPD(uint32_t address) {
|
||||
vertexColorPDAddress = fromSegmented(address);
|
||||
vertexColorPDAddress = fromSegmentedMasked(address);
|
||||
}
|
||||
|
||||
Projection::Type RSP::getCurrentProjectionType() const {
|
||||
@ -720,7 +738,7 @@ namespace RT64 {
|
||||
const float screenZ = workload.drawData.posScreen[globalIndex][2] * DepthRange;
|
||||
const float zValueFloat = zValue / 65536.0f;
|
||||
if (forceBranch || (screenZ < zValueFloat)) {
|
||||
const uint32_t rdramAddress = fromSegmented(branchDl);
|
||||
const uint32_t rdramAddress = fromSegmentedMasked(branchDl);
|
||||
*dl = reinterpret_cast<DisplayList *>(state->fromRDRAM(rdramAddress)) - 1;
|
||||
}
|
||||
}
|
||||
@ -732,7 +750,7 @@ namespace RT64 {
|
||||
const uint32_t globalIndex = indices[vtxIndex];
|
||||
const float posW = workload.drawData.posTransformed[globalIndex][3];
|
||||
if (forceBranch || (posW < static_cast<float>(wValue))) {
|
||||
const uint32_t rdramAddress = fromSegmented(branchDl);
|
||||
const uint32_t rdramAddress = fromSegmentedMasked(branchDl);
|
||||
*dl = reinterpret_cast<DisplayList *>(state->fromRDRAM(rdramAddress)) - 1;
|
||||
}
|
||||
}
|
||||
@ -778,7 +796,7 @@ namespace RT64 {
|
||||
}
|
||||
|
||||
void RSP::setViewport(uint32_t address, uint16_t ori, int16_t offx, int16_t offy) {
|
||||
const uint32_t rdramAddress = fromSegmented(address);
|
||||
const uint32_t rdramAddress = fromSegmentedMasked(address);
|
||||
const Vp_t *vp = reinterpret_cast<const Vp_t *>(state->fromRDRAM(rdramAddress));
|
||||
interop::RSPViewport &viewport = viewportStack[viewportStackSize - 1];
|
||||
viewport.scale.x = float(vp->vscale[1]) / 4.0f;
|
||||
@ -807,7 +825,7 @@ namespace RT64 {
|
||||
|
||||
void RSP::setLight(uint8_t index, uint32_t address) {
|
||||
assert((index >= 0) && (index <= RSP_MAX_LIGHTS));
|
||||
const uint32_t rdramAddress = fromSegmented(address);
|
||||
const uint32_t rdramAddress = fromSegmentedMasked(address);
|
||||
const uint8_t *data = reinterpret_cast<const uint8_t *>(state->fromRDRAM(rdramAddress));
|
||||
memcpy(&lights[index], data, sizeof(Light));
|
||||
lightsChanged = true;
|
||||
@ -836,7 +854,7 @@ namespace RT64 {
|
||||
|
||||
void RSP::setLookAt(uint8_t index, uint32_t address) {
|
||||
assert(index < 2);
|
||||
const uint32_t rdramAddress = fromSegmented(address);
|
||||
const uint32_t rdramAddress = fromSegmentedMasked(address);
|
||||
const DirLight *dirLight = reinterpret_cast<const DirLight *>(state->fromRDRAM(rdramAddress));
|
||||
auto &dstLookAt = (index == 1) ? lookAt.y : lookAt.x;
|
||||
if ((dirLight->dirx != 0) || (dirLight->diry != 0) || (dirLight->dirz != 0)) {
|
||||
@ -1077,7 +1095,7 @@ namespace RT64 {
|
||||
};
|
||||
|
||||
if (idIsAddress && editGroup) {
|
||||
const uint32_t rdramAddress = fromSegmented(id);
|
||||
const uint32_t rdramAddress = fromSegmentedMasked(id);
|
||||
const int workloadCursor = state->ext.workloadQueue->writeCursor;
|
||||
Workload &workload = state->ext.workloadQueue->workloads[workloadCursor];
|
||||
|
||||
|
@ -221,7 +221,9 @@ namespace RT64 {
|
||||
void reset();
|
||||
Projection::Type getCurrentProjectionType() const;
|
||||
void addCurrentProjection(Projection::Type type);
|
||||
uint32_t maskPhysicalAddress(uint32_t address);
|
||||
uint32_t fromSegmented(uint32_t segAddress);
|
||||
uint32_t fromSegmentedMasked(uint32_t segAddress);
|
||||
void setSegment(uint32_t seg, uint32_t address);
|
||||
void matrix(uint32_t address, uint8_t params);
|
||||
void popMatrix(uint32_t count);
|
||||
@ -276,6 +278,7 @@ namespace RT64 {
|
||||
void matrixId(uint32_t id, bool push, bool proj, bool decompose, uint8_t pos, uint8_t rot, uint8_t scale, uint8_t skew, uint8_t persp, uint8_t vert, uint8_t tile, uint8_t order, uint8_t editable, bool idIsAddress, bool editGroup);
|
||||
void popMatrixId(uint8_t count, bool proj);
|
||||
void forceBranch(bool force);
|
||||
void extendRDRAM(bool isExtended);
|
||||
void clearExtended();
|
||||
void setGBI(GBI *gbi);
|
||||
};
|
||||
|
@ -2369,6 +2369,10 @@ namespace RT64 {
|
||||
void State::setDitherNoiseStrength(float noiseStrength) {
|
||||
extended.ditherNoiseStrength = noiseStrength;
|
||||
}
|
||||
|
||||
void State::setExtendedRDRAM(bool isExtended) {
|
||||
extended.extendRDRAM = isExtended;
|
||||
}
|
||||
|
||||
uint8_t *State::fromRDRAM(uint32_t rdramAddress) const {
|
||||
return &RDRAM[rdramAddress];
|
||||
|
@ -125,6 +125,7 @@ namespace RT64 {
|
||||
uint8_t renderToRAM = UINT8_MAX;
|
||||
bool vertexTestZActive = false;
|
||||
float ditherNoiseStrength = 1.0f;
|
||||
bool extendRDRAM = false;
|
||||
};
|
||||
|
||||
Extended extended;
|
||||
@ -157,6 +158,7 @@ namespace RT64 {
|
||||
void setRefreshRate(uint16_t refreshRate);
|
||||
void setRenderToRAM(uint8_t renderToRAM);
|
||||
void setDitherNoiseStrength(float noiseStrength);
|
||||
void setExtendedRDRAM(bool isExtended);
|
||||
uint8_t *fromRDRAM(uint32_t rdramAddress) const;
|
||||
void dumpRDRAM(const std::string &path);
|
||||
void enableExtendedGBI(uint8_t opCode);
|
||||
|
Loading…
Reference in New Issue
Block a user