18absl::StatusOr<std::vector<OverworldItem>>
LoadItems(
19 Rom* rom, std::vector<OverworldMap>& overworld_maps) {
20 std::vector<OverworldItem> items;
32 uint32_t item_pointer_address =
35 for (
int i = 0; i < max_ow; i++) {
38 int bank = bank_byte & 0x7F;
41 rom->
ReadByte(item_pointer_address + (i * 2)));
43 rom->
ReadByte(item_pointer_address + (i * 2) + 1));
45 uint32_t addr = (bank << 16) +
52 if (overworld_maps[i].parent() != (uint8_t)i) {
62 if (b1 == 0xFF && b2 == 0xFF) {
66 int p = (((b2 & 0x1F) << 8) + b1) >> 1;
71 int fakeID = i % 0x40;
74 int sx = fakeID - (sy * 8);
76 items.emplace_back(b3, (uint16_t)i, (x * 16) + (sx * 512),
77 (y * 16) + (sy * 512),
false);
78 auto size = items.size();
80 items[size - 1].game_x_ = (uint8_t)x;
81 items[size - 1].game_y_ = (uint8_t)y;
88absl::Status
SaveItems(
Rom* rom,
const std::vector<OverworldItem>& items) {
91 std::vector<std::vector<OverworldItem>> room_items(pointer_count);
103 const int map_index =
static_cast<int>(item.room_map_id_);
104 if (map_index < 0 || map_index >= pointer_count) {
106 "Overworld::SaveItems",
107 "Skipping item with map index %d outside pointer table (size=%d)",
108 map_index, pointer_count);
112 room_items[map_index].push_back(item);
114 if (item.id_ == 0x86) {
115 const int lookup_index =
119 static_cast<uint16_t
>((item.game_x_ + (item.game_y_ * 64)) * 2)));
124 std::vector<int> item_pointers(pointer_count, -1);
125 std::vector<int> item_pointers_reuse(pointer_count, -1);
127 for (
int i = 0; i < pointer_count; ++i) {
128 item_pointers_reuse[i] = -1;
129 for (
int ci = 0; ci < i; ++ci) {
130 if (room_items[i].empty()) {
131 item_pointers_reuse[i] = -2;
136 item_pointers_reuse[i] = ci;
144 int empty_pointer = -1;
146 for (
int i = 0; i < pointer_count; ++i) {
147 if (item_pointers_reuse[i] == -1) {
148 item_pointers[i] = data_pos;
150 const uint16_t map_pos =
151 static_cast<uint16_t
>(((item.game_y_ << 6) + item.game_x_) << 1);
152 const uint32_t data =
153 static_cast<uint32_t
>(map_pos & 0xFF) |
154 (
static_cast<uint32_t
>((map_pos >> 8) & 0xFF) << 8) |
155 (
static_cast<uint32_t
>(item.id_) << 16);
161 empty_pointer = data_pos;
164 }
else if (item_pointers_reuse[i] == -2) {
165 if (empty_pointer < 0) {
166 item_pointers[i] = data_pos;
167 empty_pointer = data_pos;
171 item_pointers[i] = empty_pointer;
174 item_pointers[i] = item_pointers[item_pointers_reuse[i]];
179 return absl::AbortedError(
"Too many items");
187 static_cast<uint8_t
>(
196 for (
int i = 0; i < pointer_count; ++i) {
197 const uint32_t snes_addr =
PcToSnes(item_pointers[i]);
200 static_cast<uint16_t
>(snes_addr & 0xFFFF)));
205 return absl::OkStatus();