yaze
0.3.2
Link to the Past ROM Editor
Loading...
Searching...
No Matches
dungeon_block_codec.h
Go to the documentation of this file.
1
#ifndef YAZE_ZELDA3_DUNGEON_DUNGEON_BLOCK_CODEC_H_
2
#define YAZE_ZELDA3_DUNGEON_DUNGEON_BLOCK_CODEC_H_
3
4
#include <cstdint>
5
6
namespace
yaze
{
7
namespace
zelda3 {
8
9
// Pure encode/decode helpers for the vanilla pushable-block save table at
10
// `SpecialUnderworldObjects_pushable_block` ($04:F1DE..$04:F3DD, 512 bytes,
11
// 128 max entries × 4 bytes). The runtime scan in bank_01.asm:1162 walks the
12
// flat table entry-by-entry and matches on `room_id`; there is no per-room
13
// terminator. The renderer entry `RoomDraw_PushableBlock` at $01:B4D6 reads
14
// the encoded word with `AND.w #$3FFF` before using it as a tilemap index.
15
// That 14-bit index contains a 13-bit 64x64 tile position plus bit 13, which
16
// selects the lower/BG2 tilemap. `PushBlock_CheckForPit` at $01:D8D4 tests bit
17
// 14 independently when selecting the behavior/collision layer.
18
//
19
// Word layout (b4 << 8 | b3):
20
// bit 0 : unused (always 0; LSL-by-1 padding)
21
// bits 1..6 : px (6 bits, range 0..63)
22
// bits 7..12 : py (6 bits, range 0..63)
23
// bit 13 : draw target (0 = upper/BG1, 1 = lower/BG2)
24
// bit 14 : behavior/pit selector (0 = upper, 1 = lower)
25
// bit 15 : unused (always 0 in vanilla)
26
//
27
// This module replaces ad-hoc bit twiddling that previously lived in
28
// `Room::LoadBlocks`. Bit 13 was previously misidentified as the high bit of
29
// py, causing three vanilla lower-layer blocks (rooms 0xA8, 0x66, and 0x2C)
30
// to load 64 tiles too low and render on BG1.
31
32
struct
PushableBlockEntry
{
33
uint16_t
room_id
= 0;
34
uint8_t
px
= 0;
// 0..63
35
uint8_t
py
= 0;
// 0..63
36
uint8_t
draw_layer
= 0;
// bit 13: 0=upper/BG1, 1=lower/BG2
37
uint8_t
behavior_layer
= 0;
// bit 14: pit/collision layer selector
38
};
39
40
struct
PushableBlockBytes
{
41
uint8_t
b1
= 0;
// room_id low byte
42
uint8_t
b2
= 0;
// room_id high byte
43
uint8_t
b3
= 0;
// position+layer word, low byte
44
uint8_t
b4
= 0;
// position+layer word, high byte
45
};
46
47
inline
PushableBlockEntry
DecodePushableBlockEntry
(
48
const
PushableBlockBytes
& bytes) {
49
PushableBlockEntry
out;
50
out.
room_id
=
static_cast<
uint16_t
>
(bytes.
b1
| (bytes.
b2
<< 8));
51
const
uint16_t word =
static_cast<
uint16_t
>
(bytes.
b3
| (bytes.
b4
<< 8));
52
out.
px
=
static_cast<
uint8_t
>
((word >> 1) & 0x3F);
53
out.
py
=
static_cast<
uint8_t
>
((word >> 7) & 0x3F);
54
out.
draw_layer
=
static_cast<
uint8_t
>
((word >> 13) & 0x01);
55
out.
behavior_layer
=
static_cast<
uint8_t
>
((word >> 14) & 0x01);
56
return
out;
57
}
58
59
inline
PushableBlockBytes
EncodePushableBlockEntry
(
60
const
PushableBlockEntry
& entry) {
61
PushableBlockBytes
out;
62
out.
b1
=
static_cast<
uint8_t
>
(entry.
room_id
& 0xFF);
63
out.
b2
=
static_cast<
uint8_t
>
((entry.
room_id
>> 8) & 0xFF);
64
const
uint16_t word =
static_cast<
uint16_t
>
(
65
((entry.
px
& 0x3F) << 1) | ((entry.
py
& 0x3F) << 7) |
66
((entry.
draw_layer
& 0x01) << 13) |
67
((entry.
behavior_layer
& 0x01) << 14));
68
out.
b3
=
static_cast<
uint8_t
>
(word & 0xFF);
69
out.
b4
=
static_cast<
uint8_t
>
((word >> 8) & 0xFF);
70
return
out;
71
}
72
73
}
// namespace zelda3
74
}
// namespace yaze
75
76
#endif
// YAZE_ZELDA3_DUNGEON_DUNGEON_BLOCK_CODEC_H_
yaze::zelda3::EncodePushableBlockEntry
PushableBlockBytes EncodePushableBlockEntry(const PushableBlockEntry &entry)
Definition
dungeon_block_codec.h:59
yaze::zelda3::DecodePushableBlockEntry
PushableBlockEntry DecodePushableBlockEntry(const PushableBlockBytes &bytes)
Definition
dungeon_block_codec.h:47
yaze
Definition
patch_export_usage.cc:8
yaze::zelda3::PushableBlockBytes
Definition
dungeon_block_codec.h:40
yaze::zelda3::PushableBlockBytes::b2
uint8_t b2
Definition
dungeon_block_codec.h:42
yaze::zelda3::PushableBlockBytes::b1
uint8_t b1
Definition
dungeon_block_codec.h:41
yaze::zelda3::PushableBlockBytes::b3
uint8_t b3
Definition
dungeon_block_codec.h:43
yaze::zelda3::PushableBlockBytes::b4
uint8_t b4
Definition
dungeon_block_codec.h:44
yaze::zelda3::PushableBlockEntry
Definition
dungeon_block_codec.h:32
yaze::zelda3::PushableBlockEntry::room_id
uint16_t room_id
Definition
dungeon_block_codec.h:33
yaze::zelda3::PushableBlockEntry::py
uint8_t py
Definition
dungeon_block_codec.h:35
yaze::zelda3::PushableBlockEntry::draw_layer
uint8_t draw_layer
Definition
dungeon_block_codec.h:36
yaze::zelda3::PushableBlockEntry::px
uint8_t px
Definition
dungeon_block_codec.h:34
yaze::zelda3::PushableBlockEntry::behavior_layer
uint8_t behavior_layer
Definition
dungeon_block_codec.h:37
src
zelda3
dungeon
dungeon_block_codec.h
Generated by
1.10.0