summaryrefslogtreecommitdiff
path: root/src/koopatlas/map.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/koopatlas/map.cpp')
-rw-r--r--src/koopatlas/map.cpp259
1 files changed, 259 insertions, 0 deletions
diff --git a/src/koopatlas/map.cpp b/src/koopatlas/map.cpp
new file mode 100644
index 0000000..ef63eb1
--- /dev/null
+++ b/src/koopatlas/map.cpp
@@ -0,0 +1,259 @@
+#include "koopatlas/map.h"
+#include "koopatlas/camera.h"
+
+//#define TILE_DEBUGGING
+//#define BOUND_DEBUGGING
+
+#ifdef TILE_DEBUGGING
+#define TileReport OSReport
+#else
+inline void TileReport(const char *str, ...) { }
+#endif
+
+#ifdef BOUND_DEBUGGING
+#define BoundReport OSReport
+#else
+inline void BoundReport(const char *str, ...) { }
+#endif
+
+dWMMap_c *dWMMap_c::instance = 0;
+
+dWMMap_c *dWMMap_c::build() {
+ OSReport("Creating WM_Map\n");
+
+ void *buffer = AllocFromGameHeap1(sizeof(dWMMap_c));
+ dWMMap_c *c = new(buffer) dWMMap_c;
+
+ OSReport("Created WM_Map @ %p\n", c);
+
+ instance = c;
+ return c;
+}
+
+
+
+dWMMap_c::dWMMap_c() {
+}
+
+
+int dWMMap_c::onCreate() {
+ renderer.allocator.setup(GameHeaps[0], 0x20);
+ OSReport("Setting up Renderer\n");
+ bool result = renderer.setup(&renderer.allocator);
+ if (result)
+ OSReport("Set up Renderer\n");
+ else
+ OSReport(":(\n");
+
+ return true;
+}
+
+int dWMMap_c::onDelete() { return true; }
+int dWMMap_c::onExecute() { return true; }
+
+int dWMMap_c::onDraw() {
+ renderer.scheduleForDrawing();
+
+ return true;
+}
+
+
+
+
+void dWMMap_c::renderer_c::drawOpa() {
+ //drawTiles();
+}
+
+void dWMMap_c::renderer_c::drawXlu() {
+ drawTiles();
+}
+
+
+
+void dWMMap_c::renderer_c::drawTiles() {
+ beginRendering();
+
+ dKPMapData_c *dataCls = &dScKoopatlas_c::instance->mapData;
+ dKPMapFile_s *data = dataCls->data;
+
+ baseZ = 1000 - (10 * data->layerCount);
+
+ for (int iLayer = data->layerCount - 1; iLayer >= 0; iLayer--) {
+ dKPLayer_s *layer = data->layers[iLayer];
+
+ TileReport("Checking layer %d with type %d\n", iLayer, layer->type);
+ if (layer->type == dKPLayer_s::OBJECTS)
+ renderTileLayer(layer, data->sectors);
+ }
+
+ endRendering();
+}
+
+void dWMMap_c::renderer_c::beginRendering() {
+ currentTexture = 0;
+
+ nw4r::g3d::Camera cam3d(GetCameraByID(0));
+ cam3d.GetCameraMtx(&renderMtx);
+ MTXTransApply(renderMtx, renderMtx, 0, 0, baseZ);
+ /*OSReport("MTX:\n");
+ OSReport("%f, %f, %f, %f:\n", renderMtx[0][0], renderMtx[0][1], renderMtx[0][2], renderMtx[0][3]);
+ OSReport("%f, %f, %f, %f:\n", renderMtx[1][0], renderMtx[1][1], renderMtx[1][2], renderMtx[1][3]);
+ OSReport("%f, %f, %f, %f:\n", renderMtx[2][0], renderMtx[2][1], renderMtx[2][2], renderMtx[2][3]);//*/
+
+ GXSetCurrentMtx(GX_PNMTX0);
+
+ dWorldCamera_c *camObj = dWorldCamera_c::instance;
+ minX = ((int)camObj->screenLeft) / 16;
+ minY = ((int)(-camObj->screenTop)) / 16;
+ maxX = (((int)(camObj->screenLeft + camObj->screenWidth)) + 15) / 16;
+ maxY = (((int)(-camObj->screenTop + camObj->screenHeight)) + 15) / 16;
+
+ GXClearVtxDesc();
+
+ GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
+ GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
+
+ GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XY, GX_S16, 0);
+ GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_U8, 8);
+
+ GXSetNumIndStages(0);
+ for (int i = 0; i < 0x10; i++)
+ GXSetTevDirect((GXTevStageID)i);
+
+ GXSetNumChans(0);
+ GXSetNumTexGens(1);
+
+ GXSetTexCoordGen2(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY, GX_FALSE, GX_PTIDENTITY);
+
+ GXSetNumTevStages(1);
+ GXSetNumIndStages(0);
+
+ GXSetTevSwapModeTable(GX_TEV_SWAP0, GX_CH_RED, GX_CH_GREEN, GX_CH_BLUE, GX_CH_ALPHA);
+
+ GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
+ GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_C1, GX_CC_C0, GX_CC_TEXC, GX_CC_ZERO);
+ GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
+ GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_A0, GX_CA_TEXA, GX_CA_ZERO);
+ GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
+
+ GXSetZCompLoc(GX_FALSE);
+ GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_SET);
+ GXSetZMode(GX_TRUE, GX_LEQUAL, GX_FALSE);
+ GXSetAlphaCompare(GX_GREATER, 0, GX_AOP_OR, GX_GREATER, 0);
+
+ GXSetFog(GX_FOG_NONE, 0, 0, 0, 0, (GXColor){0,0,0,0});
+ GXSetFogRangeAdj(GX_FALSE, 0, 0);
+
+ GXSetCullMode(GX_CULL_NONE);
+
+ GXSetDither(GX_TRUE);
+
+ GXSetTevColor(GX_TEVREG0, (GXColor){255,255,255,255});
+ GXSetTevColor(GX_TEVREG1, (GXColor){0,0,0,255});
+}
+
+void dWMMap_c::renderer_c::renderTileLayer(dKPLayer_s *layer, dKPLayer_s::sector_s *sectors) {
+ //TileReport("Rendering layer %p\n", layer);
+ renderMtx[2][3] += 10;
+
+ // don't render it if we don't need to
+ if (maxX < layer->left || minX > layer->right)
+ return;
+ if (maxY < layer->top || minY > layer->bottom)
+ return;
+
+ // set up
+ loadCamera();
+
+ loadTexture(layer->tileset);
+
+ // figure out -what- to render
+ BoundReport("Regular render area: %d,%d to %d,%d\n", minX, minY, maxX, maxY);
+ BoundReport("Layer bounds: %d,%d to %d,%d\n", layer->left, layer->top, layer->right, layer->bottom);
+ int toRenderMinX = max(minX, layer->left);
+ int toRenderMinY = max(minY, layer->top);
+
+ int toRenderMaxX = min(maxX, layer->right);
+ int toRenderMaxY = min(maxY, layer->bottom);
+
+ int sectorBaseX = layer->sectorLeft;
+ int sectorBaseY = layer->sectorTop;
+ int sectorIndexStride = (layer->sectorRight - layer->sectorLeft + 1);
+
+ int sectorMinX = toRenderMinX / 16;
+ int sectorMinY = toRenderMinY / 16;
+ int sectorMaxX = toRenderMaxX / 16;
+ int sectorMaxY = toRenderMaxY / 16;
+ BoundReport("To render: %d,%d to %d,%d\n", toRenderMinX, toRenderMinY, toRenderMaxX, toRenderMaxY);
+ BoundReport("sectors %d,%d to %d,%d\n", sectorMinX, sectorMinY, sectorMaxX, sectorMaxY);
+
+ for (int sectorY = sectorMinY; sectorY <= sectorMaxY; sectorY++) {
+ int baseIndex = (sectorY - sectorBaseY) * sectorIndexStride;
+
+ int iMinY = (sectorY == sectorMinY) ? (toRenderMinY & 0xF) : 0;
+ int iMaxY = (sectorY == sectorMaxY) ? (toRenderMaxY & 0xF) : 15;
+
+ int worldSectorY = sectorY << 4;
+
+ for (int sectorX = sectorMinX; sectorX <= sectorMaxX; sectorX++) {
+ u16 index = layer->indices[baseIndex + sectorX - sectorBaseX];
+ TileReport("Sector index @ %d,%d: %d\n", sectorX, sectorY, index);
+ if (index == 0xFFFF)
+ continue;
+
+ dKPLayer_s::sector_s *sector = &sectors[index];
+
+ int iMinX = (sectorX == sectorMinX) ? (toRenderMinX & 0xF) : 0;
+ int iMaxX = (sectorX == sectorMaxX) ? (toRenderMaxX & 0xF) : 15;
+ TileReport("Min/Max: X: %d,%d Y: %d,%d\n", iMinX, iMaxX, iMinY, iMaxY);
+
+ int worldSectorX = sectorX << 4;
+
+ for (int inY = iMinY; inY <= iMaxY; inY++) {
+ for (int inX = iMinX; inX <= iMaxX; inX++) {
+ u16 tileID = (*sector)[inY][inX];
+ if (tileID == 0xFFFF)
+ continue;
+
+ s16 worldX = (worldSectorX | inX) << 4;
+ s16 worldY = -((worldSectorY | inY) << 4);
+
+ u8 tileX = (tileID & 0x1F) * 8;
+ u8 tileY = ((tileID & 0x1E0) / 32) * 16;
+ TileReport("Drawing tile %d at %d,%d\n", tileID, worldX, worldY);
+
+ GXBegin(GX_QUADS, GX_VTXFMT0, 4);
+ GXPosition2s16(worldX + 16, worldY - 16);
+ GXTexCoord2u8(tileX + 7, tileY + 14);
+ GXPosition2s16(worldX + 16, worldY);
+ GXTexCoord2u8(tileX + 7, tileY + 2);
+ GXPosition2s16(worldX, worldY);
+ GXTexCoord2u8(tileX + 1, tileY + 2);
+ GXPosition2s16(worldX, worldY - 16);
+ GXTexCoord2u8(tileX + 1, tileY + 14);//*/
+ GXEnd();
+ }
+ }
+
+ TileReport("Sector complete\n");
+ }
+ }
+
+ //TileReport("Layer complete\n");
+}
+
+void dWMMap_c::renderer_c::endRendering() {
+}
+
+void dWMMap_c::renderer_c::loadTexture(GXTexObj *obj) {
+ if (currentTexture == obj)
+ return;
+
+ GXLoadTexObj(obj, GX_TEXMAP0);
+ currentTexture = obj;
+}
+
+void dWMMap_c::renderer_c::loadCamera() {
+ GXLoadPosMtxImm(renderMtx, GX_PNMTX0);
+}
+