19absl::StatusOr<std::vector<OverworldItem>>
LoadItems(
20 Rom* rom, std::vector<OverworldMap>& overworld_maps) {
21 std::vector<OverworldItem> items;
34 uint32_t item_pointer_address =
37 for (
int i = 0; i < max_ow; i++) {
40 int bank = bank_byte & 0x7F;
43 rom->
ReadByte(item_pointer_address + (i * 2)));
45 rom->
ReadByte(item_pointer_address + (i * 2) + 1));
47 uint32_t addr = (bank << 16) +
54 if (overworld_maps[i].parent() != (uint8_t)i) {
64 if (b1 == 0xFF && b2 == 0xFF) {
68 int p = (((b2 & 0x1F) << 8) + b1) >> 1;
73 int fakeID = i % 0x40;
76 int sx = fakeID - (sy * 8);
78 items.emplace_back(b3, (uint16_t)i, (x * 16) + (sx * 512),
79 (y * 16) + (sy * 512),
false);
80 auto size = items.size();
82 items[size - 1].game_x_ = (uint8_t)x;
83 items[size - 1].game_y_ = (uint8_t)y;
90absl::Status
SaveItems(
Rom* rom,
const std::vector<OverworldItem>& items) {
96 std::vector<std::vector<OverworldItem>> room_items(pointer_count);
99 for (
int i = 0; i < pointer_count; ++i) {
108 const int map_index =
static_cast<int>(item.room_map_id_);
109 if (map_index < 0 || map_index >= pointer_count) {
111 "Overworld::SaveItems",
112 "Skipping item with map index %d outside pointer table (size=%d)",
113 map_index, pointer_count);
117 room_items[map_index].push_back(item);
119 if (item.id_ == 0x86) {
120 const int lookup_index = std::min(map_index, pointer_count - 1);
123 static_cast<uint16_t
>((item.game_x_ + (item.game_y_ * 64)) * 2)));
128 std::vector<int> item_pointers(pointer_count, -1);
129 std::vector<int> item_pointers_reuse(pointer_count, -1);
131 for (
int i = 0; i < pointer_count; ++i) {
132 item_pointers_reuse[i] = -1;
133 for (
int ci = 0; ci < i; ++ci) {
134 if (room_items[i].empty()) {
135 item_pointers_reuse[i] = -2;
140 item_pointers_reuse[i] = ci;
148 int empty_pointer = -1;
150 for (
int i = 0; i < pointer_count; ++i) {
151 if (item_pointers_reuse[i] == -1) {
152 item_pointers[i] = data_pos;
154 const uint16_t map_pos =
155 static_cast<uint16_t
>(((item.game_y_ << 6) + item.game_x_) << 1);
156 const uint32_t data =
157 static_cast<uint32_t
>(map_pos & 0xFF) |
158 (
static_cast<uint32_t
>((map_pos >> 8) & 0xFF) << 8) |
159 (
static_cast<uint32_t
>(item.id_) << 16);
165 empty_pointer = data_pos;
168 }
else if (item_pointers_reuse[i] == -2) {
169 if (empty_pointer < 0) {
170 item_pointers[i] = data_pos;
171 empty_pointer = data_pos;
175 item_pointers[i] = empty_pointer;
178 item_pointers[i] = item_pointers[item_pointers_reuse[i]];
183 return absl::AbortedError(
"Too many items");
191 static_cast<uint8_t
>(
196 for (
int i = 0; i < pointer_count; ++i) {
201 for (
int i = 0; i < pointer_count; ++i) {
202 const uint32_t snes_addr =
PcToSnes(item_pointers[i]);
205 static_cast<uint16_t
>(snes_addr & 0xFFFF)));
210 return absl::OkStatus();