-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Add typedefs for MAPSEC and METLOC values #2183
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Initial attempt at adding typedefs for MAPSEC and METLOC values. There are some rough edges that could do with smoothing out, but for now, this gets us close to ideal with a ROM that compares equal.
Per feedback, renamed all typedefs to mention the underlying type within the typedef name. Rewrote the documentation comments to reflect and to explain the new naming convention. Updated comments to reflect the fact that we're no longer using SET8 for a Pokemon's met locations, in favor of a new macro (added by this PR) that adjusts to match the width of whatever is being set.
Had Notepad++ set to case-insensitive to find mapsec values. Forgot to set it back to case-sensitive before find-and-replacing the typedef names in the last commit...
Per discussion on the Discord server, updated typedef name format to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome work!
I have one general comment, I think we could put the #include "gametypes.h"
in global.h
and not write it anywhere else (I think technically it's already included in global via pokemon.h
, global.fieldmap.h
, and global.tv.h
). Our header situation is far from best practice afaict, but untangling that seems tricky.
include/gametypes.h
Outdated
typedef u8 mapsec_u8_t; | ||
typedef u16 mapsec_u16_t; | ||
typedef s16 mapsec_s16_t; | ||
typedef int mapsec_int_t; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
iiuc the int
s still in the codebase are a leftover from early in the decomp process and today we'd use s32
:
typedef int mapsec_int_t; | |
typedef s32 mapsec_s32_t; |
include/region_map.h
Outdated
MAPSECTYPE_CITY_CANTFLY, | ||
MAPSECTYPE_BATTLE_FRONTIER, | ||
NUM_MAPSEC_TYPES | ||
NUM_mapsec_u8_tYPES |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm sure there's a reason why this name has changed, but I was wondering if you could elaborate on that reason?
Typo:
NUM_mapsec_u8_tYPES | |
NUM_mapsec_u8_TYPES |
src/pokemon.c
Outdated
#define SET_BY_WIDTH(lhs) \ | ||
if (sizeof(lhs) == 1) { \ | ||
SET8(lhs); \ | ||
} else if (sizeof(lhs) == 2) { \ | ||
SET16(lhs); \ | ||
} else if (sizeof(lhs) == 4) { \ | ||
SET32(lhs); \ | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great addition!
Minor style suggestion, wrapping the body of the macro in do { ... } while (0)
, and not using braces for single-line statements:
#define SET_BY_WIDTH(lhs) \ | |
if (sizeof(lhs) == 1) { \ | |
SET8(lhs); \ | |
} else if (sizeof(lhs) == 2) { \ | |
SET16(lhs); \ | |
} else if (sizeof(lhs) == 4) { \ | |
SET32(lhs); \ | |
} | |
#define SET_BY_WIDTH(lhs) \ | |
do { \ | |
if (sizeof(lhs) == 1) \ | |
SET8(lhs); \ | |
else if (sizeof(lhs) == 2) \ | |
SET16(lhs); \ | |
else if (sizeof(lhs) == 4) \ | |
SET32(lhs); \ | |
} while (0) |
Changed `mapsec_int_t` to `mapsec_s32_t` per maintainer feedback. Fixed a bad (case-insensitive) find-and-replace that had incorrectly damaged the identifier `NUM_MAPSEC_TYPES`. Converted SET_BY_WIDTH, used in SetMonData and SetBoxMonData, to a do-while-style macro. Stripped braces from its inner single-statement ifs to match the repo's overall coding style.
Per feedback, removed direct includes of the game-types header in favor of transitive includes through global.h, for consistency with the repo's overall status quo.
Per feedback:
|
This PR adds a
gametypes.h
header with typedefs formapsec_t
,metloc_t
, and variants.Description
Per discussion on the Discord, it's common for people to have to extend the ranges of certain enums, such as
MAPSEC
values, but because these don't have dedicated typedefs in the repo, doing so becomes clumsy. Defining a single typedef for each enumeration is complicated, though, because the codebase isn't consistent about sizes (e.g. met locations are stored asu8
, but they and map sections are frequently handled asu16
s and occasionally ass16
s andint
s).This PR introduces typedefs for
MAPSEC
andMETLOC
values, borrowing a convention from the<inttypes.h>
header:foo_t
is the smallest type used for "foo" values.foo_min#_t
is the naming convention for wider types; for example,foo_min16_t
is a "foo" that is at least 16 bits wide.foo_t
is unsigned,foo_min#_s_t
is the naming convention for a wider type that is also signed.foo_t
is signed,foo_min#_u_t
is the naming convention for a wider type that is also unsigned.foo_int_t
is the naming convention for when a "foo" is represented as anint
.It matches per
make compare
on my machine.Weird edge cases that remain incompletely addressed
frontier_pass.c
:AllocateFrontierPassData
: The locali
variable is first used as amapsec_t
, and later as a bareu8
for a loop index. Anonymous unions don't work here (at least with agbcc), and a named union would be unnecessarily ugly (i.e._.mapSecId
and_.i
). As such, this variable is amapsec_t
with a code comment explaining that it gets repurposed as a bare integer later on.pokedex_area_screen.c
:sLandmarkData
us au16[][2]
wherein the first short is amapsec_min16_t
and the second is an event flag index. Currently, this array's element type ismapsec_min16_t
, but if we ever introduce e.g.eventflag_t
I'm not sure what we'll want to do here.sRedOutlineFlyDestinations
inregion_map.c
.pokemon.c
:CreateBoxMon
: The localvalue
variable is used for several different things, and so can't be given a meaningful type. It's au32
.Questions
Assuming we want to do something like this for more types/enumerations, do we want to put all of the typedefs in a single header, or do we want to have one header per collection of related types? The former option keeps the number of files to a minimum and allows you to review these types (and any others we add in the future) all at once, but it means that widening a type will cause you to have to recompile, like, 90% of the game (already a major issue with headers like
global.h
).If we're open to using one header per "family" of typedefs, then IMO it seems like a good idea to define the paths as e.g.
include/game_types/mapsec_metloc.h
,include/game_types/task_id.h
, and so on. We can take the code comment that explains the naming conventions and reasoning, and move it to aREADME.md
file in that subfolder.What other types do we want to do this for? I have my own ideas which I'll present here, but it seemed best to ask before just going and doing them all.
battler_t
ball_id_t
easychatword_t
item_id_t
language_t
mapgroup_t
andmapnum_t
move_id_t
pokepersonality_t
(unlikely anyone will want to widen this, but it did get widened to 64 bits in Gen VI)pokespecies_t
font_id_t
gfxtag_t
andpaltag_t
sprite_id_t
task_id_t
window_id_t
If we do want to do this for multiple types, do we want one PR per [group of related] typedef[s] (probably easier), or an all-in-one PR?
Discord contact info
@davidjcobb