diff options
author | Treeki <treeki@gmail.com> | 2011-07-25 03:16:21 +0200 |
---|---|---|
committer | Treeki <treeki@gmail.com> | 2011-07-25 03:16:21 +0200 |
commit | 4f6633db18e2213a151782d995486491c8db3ff7 (patch) | |
tree | 5b56f33b7214916b6988fb93dfa6cd000c7bf786 | |
parent | 92a54fbb0c075d36da846b5d1b99b67cafc533eb (diff) | |
download | kamek-4f6633db18e2213a151782d995486491c8db3ff7.tar.gz kamek-4f6633db18e2213a151782d995486491c8db3ff7.zip |
Random tiles added. Untested.
Diffstat (limited to '')
-rw-r--r-- | NewerProject.yaml | 1 | ||||
-rwxr-xr-x | include/game.h | 57 | ||||
-rw-r--r-- | kamek_ntsc.x | 7 | ||||
-rw-r--r-- | kamek_ntsc2.x | 7 | ||||
-rw-r--r-- | kamek_pal.x | 7 | ||||
-rw-r--r-- | kamek_pal2.x | 7 | ||||
-rw-r--r-- | randtilegen.rb | 95 | ||||
-rw-r--r-- | randtiles.yaml | 26 | ||||
-rw-r--r-- | src/randtiles.cpp | 158 | ||||
-rw-r--r-- | src/randtiles.h | 80 |
10 files changed, 381 insertions, 64 deletions
diff --git a/NewerProject.yaml b/NewerProject.yaml index ee2ee77..3af233a 100644 --- a/NewerProject.yaml +++ b/NewerProject.yaml @@ -7,6 +7,7 @@ modules: - processed/worldmap.yaml
- processed/levelnames.yaml
- processed/animtiles.yaml
+# - processed/randtiles.yaml
- processed/spritetex.yaml
# - processed/gakenoko.yaml
- processed/poweruphax.yaml
diff --git a/include/game.h b/include/game.h index 7f8dba6..3c631c6 100755 --- a/include/game.h +++ b/include/game.h @@ -40,6 +40,8 @@ inline void *GetDVDClass2() { void *DVD_GetFile(void *dvdclass2, const char *arc, const char *file);
void *DVD_GetFile(void *dvdclass2, const char *arc, const char *file, u32 *length);
+int MakeRandomNumber(int count);
+
extern int Player_Active[4];
extern int Player_ID[4];
@@ -2012,5 +2014,60 @@ namespace m2d { }
+
+/* Tilemap related stuff */
+class TilemapClass {
+ public:
+ virtual ~TilemapClass();
+
+ u16 *allocatedBlocks[256];
+ u32 _404;
+
+ u8 blockLookup[2048];
+
+ u16 blockCount;
+
+ u32 _C0C;
+ u32 ts1ID, ts2ID, ts3ID, layerID, areaID, frmHeap, is2Castle;
+
+ // Only the public API is listed
+ u16 *getPointerToTile(int x, int y, u32 *blockNum = 0, bool unkBool = 0);
+ // TODO: more?
+};
+
+class BGDatClass {
+ public:
+ BGDatClass();
+ virtual ~BGDatClass();
+
+ u8 *bgData[4][3];
+ TilemapClass *tilemaps[4][3];
+ u8 *tsObjIndexData[4][4];
+ u8 *tsObjData[4][4];
+ char tsNames[4][4][0x20];
+ // this is fucked up!
+ // the parent heap is frmHeaps[0][0]
+ // each tileset's heap is frmHeaps[AREA][LAYER+1]
+ void *frmHeaps[4][4];
+
+ static BGDatClass *instance; // 8042A0D0
+
+ // I've only listed the public API because other stuff isn't really needed atm.
+ const char *getTilesetName(int area, int number);
+ // TODO: more?
+};
+
+struct BGRender {
+ u8 unk[0xC00];
+ u8 *objectData;
+ u8 _C04, _C05;
+ u16 _C06, _C08;
+ u16 blockNumber;
+ u16 curX, curY;
+ u16 tileToPlace;
+ u16 objDataOffset, objType, objX, objY, objWidth, objHeight;
+ u16 tileNumberWithinBlock, areaID;
+};
+
#endif
diff --git a/kamek_ntsc.x b/kamek_ntsc.x index 8620d1c..da5f3dd 100644 --- a/kamek_ntsc.x +++ b/kamek_ntsc.x @@ -520,8 +520,13 @@ SECTIONS { GameHeaps = 0x80377C48; BGDatClass = 0x80429DF0; + instance__10BGDatClass = 0x80429DF0; GetTilesetName__FPvii = 0x800813F0; + getTilesetName__10BGDatClassFii = 0x800813F0; + + getPointerToTile__12TilemapClassFiiPUib = 0x80083B40; + IsWideScreen__Fv = 0x800B54B0; Player_Active = 0x80354E50; @@ -998,6 +1003,8 @@ SECTIONS { GetRandomSeed = 0x800B2EC0; RandomSeed = 0x80429F44; + MakeRandomNumber__Fi = 0x800B2EE0; + StrangeReplayValue1 = 0x8042792E; StrangeReplayValue2 = 0x80429D69; StrangeReplayValue3 = 0x80429D6A; diff --git a/kamek_ntsc2.x b/kamek_ntsc2.x index 5a2f6b6..5fc9d3b 100644 --- a/kamek_ntsc2.x +++ b/kamek_ntsc2.x @@ -520,8 +520,13 @@ SECTIONS { GameHeaps = 0x80377C48; BGDatClass = 0x80429DF0; + instance__10BGDatClass = 0x80429DF0; GetTilesetName__FPvii = 0x800813F0; + getTilesetName__10BGDatClassFii = 0x800813F0; + + getPointerToTile__12TilemapClassFiiPUib = 0x80083B40; + IsWideScreen__Fv = 0x800B54B0; Player_Active = 0x80354E50; @@ -998,6 +1003,8 @@ SECTIONS { GetRandomSeed = 0x800B2EC0; RandomSeed = 0x80429F44; + MakeRandomNumber__Fi = 0x800B2EE0; + StrangeReplayValue1 = 0x8042792E; StrangeReplayValue2 = 0x80429D69; StrangeReplayValue3 = 0x80429D6A; diff --git a/kamek_pal.x b/kamek_pal.x index 72adf91..c7a2fb7 100644 --- a/kamek_pal.x +++ b/kamek_pal.x @@ -520,8 +520,13 @@ SECTIONS { GameHeaps = 0x80377F48;
BGDatClass = 0x8042A0D0;
+ instance__10BGDatClass = 0x8042A0D0;
GetTilesetName__FPvii = 0x800813F0;
+ getTilesetName__10BGDatClassFii = 0x800813F0;
+
+ getPointerToTile__12TilemapClassFiiPUib = 0x80083B40;
+
IsWideScreen__Fv = 0x800B5500;
Player_Active = 0x80355150;
@@ -998,6 +1003,8 @@ SECTIONS { GetRandomSeed = 0x800B2EC0;
RandomSeed = 0x8042A224;
+ MakeRandomNumber__Fi = 0x800B2EE0;
+
StrangeReplayValue1 = 0x80427C2E;
StrangeReplayValue2 = 0x8042A049;
StrangeReplayValue3 = 0x8042A04A;
diff --git a/kamek_pal2.x b/kamek_pal2.x index 8f9b2ca..8e1321a 100644 --- a/kamek_pal2.x +++ b/kamek_pal2.x @@ -520,8 +520,13 @@ SECTIONS { GameHeaps = 0xDEADBEEF; BGDatClass = 0xDEADBEEF; + instance__10BGDatClass = 0xDEADBEEF; GetTilesetName__FPvii = 0xDEADBEEF; + getTilesetName__10BGDatClassFii = 0xDEADBEEF; + + getPointerToTile__12TilemapClassFiiPUib = 0xDEADBEEF; + IsWideScreen__Fv = 0xDEADBEEF; Player_Active = 0xDEADBEEF; @@ -998,6 +1003,8 @@ SECTIONS { GetRandomSeed = 0xDEADBEEF; RandomSeed = 0xDEADBEEF; + MakeRandomNumber__Fi = 0xDEADBEEF; + StrangeReplayValue1 = 0xDEADBEEF; StrangeReplayValue2 = 0xDEADBEEF; StrangeReplayValue3 = 0xDEADBEEF; diff --git a/randtilegen.rb b/randtilegen.rb new file mode 100644 index 0000000..f77d333 --- /dev/null +++ b/randtilegen.rb @@ -0,0 +1,95 @@ +class RandTileGenerator + def initialize + @sections = {} + end + + def section(name) + @sections[name] ||= {entries: []} + @current_section = @sections[name] + + yield + end + + def random(range, type=:both, numbers=nil) + numbers = range if numbers.nil? + + @current_section[:entries] << {range: range, type: type, numbers: numbers.to_a} + end + + def pack + # first, work out an offset for every section and entry + # also, collect the data for each individual entry into an Array + current_offset = 8 + (@sections.count * 4) + all_entry_data = [] + + @sections.each_pair do |name, section| + section[:offset] = current_offset + current_offset += 8 + + section[:entries].each do |entry| + entry[:offset] = current_offset + all_entry_data << entry[:numbers] + current_offset += 8 + end + end + + # assign an offset to each piece of entry data + data_offsets = {} + all_entry_data.uniq! + + all_entry_data.each do |data| + data_offsets[data] = current_offset + current_offset += data.size + end + + # assign an offset to each section name + name_offsets = {} + @sections.keys.each do |name| + name_offsets[name] = current_offset + current_offset += name.size + 1 + end + + # now pack it all together + header = ['NwRT', @sections.count].pack('a4 N') + offsets = @sections.each_value.map{|s| s[:offset]}.pack('N*') + + section_data = @sections.each_pair.map do |name, section| + name_offset = name_offsets[name] - section[:offset] + entry_count = section[:entries].count + + entry_data = section[:entries].map do |entry| + lower_bound = entry[:range].min + upper_bound = entry[:range].max + + count = entry[:numbers].count + type = [:none, :horz, :vert, :both].index(entry[:type]) + + num_offset = data_offsets[entry[:numbers]] - entry[:offset] + + [lower_bound, upper_bound, count, type, num_offset].pack('CCCC N') + end + + [name_offset, entry_count].pack('NN') + entry_data.join + end + + output = [header, offsets] + output += section_data + output += all_entry_data.map{|data| data.pack('C*')} + output << @sections.keys.join("\0") + output << "\0" + output.join + end +end + + +g = RandTileGenerator.new +g.section('TestTileset') do + g.random(1..20) + g.random(21..24, :none) + g.random(250..255, :vert, 0..5) +end + +File.open('/home/me/Games/Newer/DolphinPatch/NewerRes/RandTiles.bin', 'wb') do |f| + f.write g.pack +end + diff --git a/randtiles.yaml b/randtiles.yaml new file mode 100644 index 0000000..5ee73aa --- /dev/null +++ b/randtiles.yaml @@ -0,0 +1,26 @@ +--- +source_files: [../src/randtiles.cpp] +hooks: + - name: ModifyTilemapClassSize + type: patch + addr_pal: 0x80083598 + data: '3860 0C3C' + + - name: LoadRandTiles + type: branch_insn + branch_type: b + src_addr_pal: 0x8015BCD0 + target_func: 'RandTileLoadHook' + + - name: HookIdentifyTilesets + type: branch_insn + branch_type: bl + src_addr_pal: 0x800838AC + target_func: 'IdentifyTilesets' + + - name: HookTilePlacer + type: branch_insn + branch_type: bl + src_addr_pal: 0x80086B48 + target_func: 'TryAndRandomise' + diff --git a/src/randtiles.cpp b/src/randtiles.cpp index c7388dd..4af3bf7 100644 --- a/src/randtiles.cpp +++ b/src/randtiles.cpp @@ -1,22 +1,146 @@ -#include "randtiles.h"
-
-u32 djb2(u8 *str) {
- u32 hash = 5381;
- int c;
-
- while (c = *str++)
- hash = ((hash << 5) + hash) + c;
-
- return hash;
-}
+#include <game.h>
+
+class RandomTileData {
+public:
+ enum Type {
+ CHECK_NONE = 0,
+ CHECK_HORZ = 1,
+ CHECK_VERT = 2,
+ CHECK_BOTH = 3
+ };
+
+ class Entry {
+ public:
+ u8 lowerBound, upperBound;
+ u8 count, type;
+ u32 tileNumOffset;
+
+ u8 *getTileNums() {
+ return ((u8*)this) + tileNumOffset;
+ }
+ };
+
+ class Section {
+ public:
+ u32 nameOffset;
+ u32 entryCount;
+ Entry entries[1]; // variable size
+
+ const char *getName() {
+ return ((char*)this) + nameOffset;
+ }
+ };
+
+ u32 magic;
+ u32 sectionCount;
+ u32 offsets[1]; // variable size
+
+ Section *getSection(int id) {
+ return (Section*)(((char*)this) + offsets[id]);
+ }
+
+ Section *getSection(const char *name);
+
+ static RandomTileData *instance;
+};
-RandTiles_Section *RandTiles_Search(void *file, u32 nameHash) {
- for (int i = 0; i < RandTiles_GetSectionCount(file); i++) {
- RandTiles_Section *sect = RandTiles_GetSection(file, i);
-
- if (sect->nameHash == nameHash)
+class RTilemapClass : public TilemapClass {
+public:
+ // NEWER ADDITIONS
+ RandomTileData::Section *sections[4];
+};
+
+RandomTileData::Section *RandomTileData::getSection(const char *name) {
+ for (int i = 0; i < sectionCount; i++) {
+ RandomTileData::Section *sect = getSection(i);
+
+ if (strcmp(name, sect->getName()) == 0) {
return sect;
+ }
}
-
+
return 0;
}
+
+
+// Real tile handling code
+
+RandomTileData *RandomTileData::instance = 0;
+
+dDvdLoader_c RandTileLoader;
+
+extern "C" bool RandTileLoadHook() {
+ OSReport("Trying to load...");
+ void *buf = RandTileLoader.load("/NewerRes/RandTiles.bin");
+ if (buf == 0) {
+ OSReport("Failed.\n");
+ return false;
+ } else {
+ OSReport("Successfully loaded RandTiles.bin.\n");
+ RandomTileData::instance = (RandomTileData*)buf;
+ return true;
+ }
+}
+
+
+extern "C" void IdentifyTilesets(RTilemapClass *self) {
+ self->_C0C = 0xFFFFFFFF;
+
+ for (int i = 0; i < 4; i++) {
+ const char *tilesetName = BGDatClass::instance->getTilesetName(self->areaID, i);
+
+ self->sections[i] = RandomTileData::instance->getSection(tilesetName);
+ }
+}
+
+extern "C" void TryAndRandomise(RTilemapClass *self, BGRender *bgr) {
+ int fullTile = bgr->tileToPlace & 0x3FF;
+ int tile = fullTile & 0xFF;
+ int tileset = fullTile >> 8;
+
+ RandomTileData::Section *rtSect = self->sections[tileset];
+ if (rtSect == 0)
+ return;
+
+ for (int i = 0; i < rtSect->entryCount; i++) {
+ RandomTileData::Entry *entry = &rtSect->entries[i];
+
+ if (tile >= entry->lowerBound && tile <= entry->upperBound) {
+ // Found it!!
+ // Try to make one until we meet the conditions
+ u8 *tileNums = entry->getTileNums();
+ u8 chosen = 0xFF;
+
+ u16 *top = 0, *left = 0, *right = 0, *bottom = 0;
+ if (entry->type == RandomTileData::CHECK_HORZ || entry->type == RandomTileData::CHECK_BOTH) {
+ left = self->getPointerToTile(bgr->curX - 1, bgr->curY);
+ right = self->getPointerToTile(bgr->curX + 1, bgr->curY);
+ }
+
+ if (entry->type == RandomTileData::CHECK_VERT || entry->type == RandomTileData::CHECK_BOTH) {
+ top = self->getPointerToTile(bgr->curX, bgr->curY - 1);
+ bottom = self->getPointerToTile(bgr->curX, bgr->curY + 1);
+ }
+
+ while (true) {
+ chosen = tileNums[MakeRandomNumber(entry->count)];
+
+ if (top != 0 && *top == chosen)
+ continue;
+ if (bottom != 0 && *bottom == chosen)
+ continue;
+ if (left != 0 && *left == chosen)
+ continue;
+ if (right != 0 && *right == chosen)
+ continue;
+ break;
+ }
+
+ bgr->tileToPlace = chosen;
+
+ return;
+ }
+ }
+}
+
+
diff --git a/src/randtiles.h b/src/randtiles.h index ab2553d..03005b2 100644 --- a/src/randtiles.h +++ b/src/randtiles.h @@ -2,62 +2,48 @@ #define __NEWER_RANDTILES_H
#include <common.h>
-#include "fileload.h"
-#define RAND_CHECK_HORZ
-#define RAND_CHECK_VERT
-#define RAND_CHECK_BOTH
+class RandomTileData {
+ enum Type {
+ CHECK_NONE = 0,
+ CHECK_HORZ = 1,
+ CHECK_VERT = 2,
+ CHECK_BOTH = 3
+ };
+
+ class Entry {
+ u8 startTile, endTile;
+ u8 count, type;
+ u32 dataOffset;
+
+ u8 *getData() {
+ return ((u8*)this) + dataOffset;
+ }
+ };
+
+ class Section {
+ u32 nameHash;
+ u32 nameOffset;
+ u32 entryCount;
+ Entry entries[1]; // variable size
+
+ const char *getName() {
+ return ((char*)this) + nameOffset;
+ }
+ };
-struct RandTiles_Header {
u32 magic;
u32 sectionCount;
-};
-
-struct RandTiles_Section {
- u32 nameHash;
- u32 entryCount;
-};
-
-struct RandTiles_Entry {
- u16 startTile;
- u16 endTile;
- u8 count;
- u8 type;
- u16 reserved;
- u32 dataOffset;
-};
+ u32 offsets[1]; // variable size
-inline u32 RandTiles_GetSectionCount(void *file) {
- return ((RandTiles_Header*)file)->sectionCount;
-}
+ Section *getSection(int id) {
+ return (Section*)(((char*)this) + offsets[id]);
+ }
-inline u32 *RandTiles_GetOffsets(void *file) {
- return (u32*)(((RandTiles_Header*)file)+1);
-}
-
-inline RandTiles_Section *RandTiles_GetSection(void *file, int id) {
- u32 offs = RandTiles_GetOffsets(file)[id];
- return (RandTiles_Section*)(((char*)file)+offs);
+ Section *getSection(char *name);
};
-inline RandTiles_Entry *RandTiles_GetTiles(void *file, RandTiles_Section *section) {
- return (RandTiles_Entry*)(section+1);
-}
-
-inline RandTiles_Entry *RandTiles_GetTiles(void *file, int sectionID) {
- return (RandTiles_Entry*)(RandTiles_GetSection(file, sectionID)+1);
-}
-
-inline char *RandTiles_GetName(void *file, RandTiles_Section *section) {
- return ((char*)file)+section->nameOffset;
-}
-
-inline u16 *RandTiles_GetData(void *file, RandTiles_Entry *entry) {
- return (u16*)(((char*)file)+entry->dataOffset);
-}
-
u32 djb2(u8 *str);
-RandTiles_Section *RandTiles_Search(void *file, u32 nameHash);
#endif
|