Update overworld map properties and overlay functionality

- Changed the included assembly file for custom overworld to version 3 for improved features.
- Enhanced documentation in the overworld loading guide to clarify overlay effects and configurations.
- Refactored MapPropertiesSystem to support overlay previews and improved mosaic controls.
- Added functionality for loading vanilla overlays and displaying overlay descriptions in the editor.
- Updated UI components in OverworldEditor to integrate new overlay settings and preview options.
This commit is contained in:
scawful
2025-09-24 20:16:53 -04:00
parent b633e57ae7
commit 912cc3fb56
8 changed files with 860 additions and 526 deletions

View File

@@ -58,6 +58,7 @@ absl::Status OverworldMap::BuildMap(int count, int game_state, int world,
RETURN_IF_ERROR(BuildTileset())
RETURN_IF_ERROR(BuildTiles16Gfx(tiles16, count))
RETURN_IF_ERROR(LoadPalette());
RETURN_IF_ERROR(LoadVanillaOverlay());
RETURN_IF_ERROR(BuildBitmap(world_blockset))
built_ = true;
return absl::OkStatus();
@@ -824,6 +825,138 @@ absl::Status OverworldMap::LoadPalette() {
return absl::OkStatus();
}
absl::Status OverworldMap::LoadVanillaOverlay() {
uint8_t asm_version = (*rom_)[OverworldCustomASMHasBeenApplied];
// Only load vanilla overlays if this is a vanilla ROM (asm_version == 0xFF)
if (asm_version != 0xFF) {
has_vanilla_overlay_ = false;
vanilla_overlay_id_ = 0;
vanilla_overlay_data_.clear();
return absl::OkStatus();
}
// Load vanilla overlay for this map
int address = (kOverlayPointersBank << 16) +
((*rom_)[kOverlayPointers + (index_ * 2) + 1] << 8) +
(*rom_)[kOverlayPointers + (index_ * 2)];
// Convert SNES address to PC address
address = ((address & 0x7F0000) >> 1) | (address & 0x7FFF);
// Check if custom overlay code is present
if ((*rom_)[kOverlayData1] == 0x6B) {
// Use custom overlay data pointer
address = ((*rom_)[kOverlayData2 + 2 + (index_ * 3)] << 16) +
((*rom_)[kOverlayData2 + 1 + (index_ * 3)] << 8) +
(*rom_)[kOverlayData2 + (index_ * 3)];
address = ((address & 0x7F0000) >> 1) | (address & 0x7FFF);
}
// Validate address
if (address >= rom_->size()) {
has_vanilla_overlay_ = false;
vanilla_overlay_id_ = 0;
vanilla_overlay_data_.clear();
return absl::OkStatus();
}
// Parse overlay data
vanilla_overlay_data_.clear();
uint8_t b = (*rom_)[address];
// Parse overlay commands until we hit END (0x60)
while (b != 0x60 && address < rom_->size()) {
vanilla_overlay_data_.push_back(b);
// Handle different overlay commands
switch (b) {
case 0xA9: // LDA #$
if (address + 2 < rom_->size()) {
vanilla_overlay_data_.push_back((*rom_)[address + 1]);
vanilla_overlay_data_.push_back((*rom_)[address + 2]);
address += 3;
} else {
address++;
}
break;
case 0xA2: // LDX #$
if (address + 2 < rom_->size()) {
vanilla_overlay_data_.push_back((*rom_)[address + 1]);
vanilla_overlay_data_.push_back((*rom_)[address + 2]);
address += 3;
} else {
address++;
}
break;
case 0x8D: // STA $xxxx
if (address + 3 < rom_->size()) {
vanilla_overlay_data_.push_back((*rom_)[address + 1]);
vanilla_overlay_data_.push_back((*rom_)[address + 2]);
vanilla_overlay_data_.push_back((*rom_)[address + 3]);
address += 4;
} else {
address++;
}
break;
case 0x9D: // STA $xxxx,x
if (address + 3 < rom_->size()) {
vanilla_overlay_data_.push_back((*rom_)[address + 1]);
vanilla_overlay_data_.push_back((*rom_)[address + 2]);
vanilla_overlay_data_.push_back((*rom_)[address + 3]);
address += 4;
} else {
address++;
}
break;
case 0x8F: // STA $xxxxxx
if (address + 4 < rom_->size()) {
vanilla_overlay_data_.push_back((*rom_)[address + 1]);
vanilla_overlay_data_.push_back((*rom_)[address + 2]);
vanilla_overlay_data_.push_back((*rom_)[address + 3]);
vanilla_overlay_data_.push_back((*rom_)[address + 4]);
address += 5;
} else {
address++;
}
break;
case 0x1A: // INC A
address++;
break;
case 0x4C: // JMP
if (address + 3 < rom_->size()) {
vanilla_overlay_data_.push_back((*rom_)[address + 1]);
vanilla_overlay_data_.push_back((*rom_)[address + 2]);
vanilla_overlay_data_.push_back((*rom_)[address + 3]);
address += 4;
} else {
address++;
}
break;
default:
address++;
break;
}
if (address < rom_->size()) {
b = (*rom_)[address];
} else {
break;
}
}
// Add the END command if we found it
if (b == 0x60) {
vanilla_overlay_data_.push_back(0x60);
}
// Set overlay ID based on map index (simplified)
vanilla_overlay_id_ = index_;
has_vanilla_overlay_ = !vanilla_overlay_data_.empty();
return absl::OkStatus();
}
void OverworldMap::ProcessGraphicsBuffer(int index, int static_graphics_offset,
int size, uint8_t *all_gfx) {
// Ensure we don't go out of bounds

View File

@@ -36,6 +36,13 @@ constexpr int OverworldCustomTileGFXGroupEnabled = 0x140148; // 1 byte, not 0 i
constexpr int OverworldCustomMosaicArray = 0x140200; // 1 byte for each overworld area (0xA0)
constexpr int OverworldCustomMosaicEnabled = 0x140142; // 1 byte, not 0 if enabled
// Vanilla overlay constants
constexpr int kOverlayPointers = 0x77664; // 2 bytes for each overworld area (0x100)
constexpr int kOverlayPointersBank = 0x0E; // Bank for overlay pointers
constexpr int kOverlayData1 = 0x77676; // Check for custom overlay code
constexpr int kOverlayData2 = 0x77677; // Custom overlay data pointer
constexpr int kOverlayCodeStart = 0x77657; // Start of overlay code
// 1 byte for each overworld area (0xA0)
constexpr int OverworldCustomMainPaletteArray = 0x140160;
// 1 byte, not 0 if enabled
@@ -98,6 +105,7 @@ class OverworldMap : public gfx::GfxContext {
void LoadAreaGraphics();
absl::Status LoadPalette();
absl::Status LoadVanillaOverlay();
absl::Status BuildTileset();
absl::Status BuildTiles16Gfx(std::vector<gfx::Tile16>& tiles16, int count);
absl::Status BuildBitmap(OverworldBlockset& world_blockset);
@@ -139,6 +147,15 @@ class OverworldMap : public gfx::GfxContext {
void set_animated_gfx(uint8_t gfx) { animated_gfx_ = gfx; }
auto custom_tileset(int index) const { return custom_gfx_ids_[index]; }
// Vanilla overlay accessors
auto vanilla_overlay_id() const { return vanilla_overlay_id_; }
auto has_vanilla_overlay() const { return has_vanilla_overlay_; }
const auto& vanilla_overlay_data() const { return vanilla_overlay_data_; }
// Mosaic expanded accessors
const std::array<bool, 4>& mosaic_expanded() const { return mosaic_expanded_; }
void set_mosaic_expanded(int index, bool value) { mosaic_expanded_[index] = value; }
void set_custom_tileset(int index, uint8_t value) { custom_gfx_ids_[index] = value; }
auto mutable_current_graphics() { return &current_gfx_; }
@@ -216,6 +233,9 @@ class OverworldMap : public gfx::GfxContext {
static_graphics_.fill(0);
mosaic_expanded_.fill(false);
area_size_ = AreaSizeEnum::SmallArea;
vanilla_overlay_id_ = 0;
has_vanilla_overlay_ = false;
vanilla_overlay_data_.clear();
}
private:
@@ -267,6 +287,11 @@ class OverworldMap : public gfx::GfxContext {
std::array<bool, 4> mosaic_expanded_;
// Vanilla overlay support
uint16_t vanilla_overlay_id_ = 0;
bool has_vanilla_overlay_ = false;
std::vector<uint8_t> vanilla_overlay_data_;
std::vector<uint8_t> current_blockset_;
std::vector<uint8_t> current_gfx_;
std::vector<uint8_t> bitmap_data_;