Vram classes aim to help reduce duplicated data across the segments and more clearly organize the memory layout. This is not a common linker script concept. It was designed for the ease of use with complex memory layouts between multiple segments.
A vram class specifies a place in memory, which may be described in a somewhat complex way, so one or more segments can point to this class instead of try to describe the memory layout on the segment itself.
A vram class may describy a memory location by simply specifying a hardcoded
vram
(virtual RAM) location, the same address of an
existing symbol or something more complex like the address of
a vram class starts where one or more other vram classes ends
(follow_classes).
A vram class is composed by two mandatory fields, the name
field and
exactly one of the fields that describe address memory locations. Specifying
more than one or not specifying any of them is invalid.
Linker symbols for start, end and size are emitted for vram classes, similarly
to how segments have linker symbols for their start, end and size. See
linker_symbols_style
.
- The start symbol is defined depending on the given field that describe a memory location.
- The end symbol is defined as equal to the end symbol of the largest segment that uses this vram class.
- The size symbol is defined by the subtraction of the end and the start symbols.
This field is required.
The name of the corresponding vram class.
The name of a vram class must be unique between all the vram classes.
vram_classes:
- { name: battle_partner, fixed_vram: 0x80238000 }
Non empty string.
Forces the given vram class to be at a fixed vram
address.
The start symbol for this vram classs will be hardcoded to the given value.
vram_classes:
- { name: segment_05, fixed_vram: 0x05000000 }
segments:
- name: assets1
vram_class: segment_05
files:
- { path: src/assets/assets1/texture.o }
- { path: src/assets/assets1/dlist.o }
- name: assets2
vram_class: segment_05
files:
- { path: src/assets/assets2/texture.o }
- { path: src/assets/assets2/dlist.o }
- name: assets3
vram_class: segment_05
files:
- { path: src/assets/assets3/texture.o }
- { path: src/assets/assets3/dlist.o }
Any unsigned integer.
Forces the given vram class to have the same address as the given symbol.
The start symbol for this vram classs will be hardcoded to the given symbol.
vram_classes:
- { name: battle_area2, fixed_symbol: Vine1Base }
segments:
- name: omo2_1
vram_class: battle_area2
files:
- { path: actor/shy_squad.o }
- name: omo2_2
vram_class: battle_area2
files:
- { path: actor/stilt_guy.o }
- name: omo2_3
vram_class: battle_area2
files:
- { path: actor/shy_stack.o }
Non empty string.
A list of names of other vram classes.
Specifies that this vram class must follow the end of the largest vram class of the given list.
The start symbol for this vram classs will be equal to the largest end of the given vram classes.
vram_classes:
- { name: battle_partner, fixed_vram: 0x80238000 }
- { name: battle_code, follows_classes: [battle_partner] }
- { name: heaps2, fixed_vram: 0x80267FF0 }
- { name: world_script_api, follows_classes: [heaps2] }
- { name: texture_memory, follows_classes: [battle_partner, world_script_api] }
segments:
- name: battle_partner_goompa
vram_class: battle_partner
files:
- { path: src/battle_partner/goompa.o }
- name: battle_partner_goombario
vram_class: battle_partner
files:
- { path: src/battle_partner/goombario.o }
- name: battle_code
vram_class: battle_code
files:
- { path: src/battle_code/btl_states_actions.o }
- { path: src/battle_code/camera.o }
- name: heaps2
vram_class: heaps2
files:
- { path: src/heaps2/heaps2.o }
- name: world_script_api
vram_class: world_script_api
files:
- { path: src/world/script_api/shops.o }
- { path: src/world/script_api/rooms.o }
- name: texture_memory
vram_class: texture_memory
files:
- { path: src/texture_memory/texture_memory.o }
This example describes the following interactions between segments and vram classes:
- The
battle_partner_goompa
andbattle_partner_goombario
segments will have the samevram
address as thebattle_partner
vram class, which has a fixedvram
address of0x80238000
. battle_partner
's end symbol will be set to the end symbol of eitherbattle_partner_goompa
orbattle_partner_goombario
. If thebattle_partner_goompa
segment is bigger then its end symbol will be used, otherwise the end symbol ofbattle_partner_goombario
will be used.- The
battle_code
segment will have the samevram
address as thebattle_code
vram class. - The vram address of the
battle_code
vram class will be the same as the end address of thebattle_partner
vram class (which is defined depending on the corresponding segments that use that vram class). - The
heaps2
segment will have the samevram
address as theheaps2
vram class which has a hardcoded address of0x80267FF0
. - The
world_script_api
segment will have thevram
address of theworld_script_api
vram class, which itsvram
address is the same as the end address of theheaps2
vram class. - The
texture_memory
segment has the samevram
as thetexture_memory
vram class. The vram address of thetexture_memory
vram class will be the same as the end symbol of the largest vram class betweenbattle_partner
andworld_script_api
.
TODO: Add images to explain this memory layout visually.
A list of strings. The strings must be names of existing vram classes.
Wraps the file entries from the segments that reference this vram class with
KEEP
attributes.
KEEP
is only relevant when link time garbage collection is enabled (the
--gc-sections
flag of GNU LD), since wrapping a section with a KEEP
attribute tells the
linker that this section should not be garbage collected, even if none of the
symbols on that section is referenced by anything else that is actually used.
If link time garbage collection is enabled then it is recommended to set the
entrypoint of this program by setting the slinky top-level attribute entry
.
The keep_sections
attribute allow specify if all the input sections (say
.text
, .data
, etc) of a given file entry should be wrapped by KEEP
or not.
Alternatively a list of strings may be provided instead to specify which
specific sections should be wrapped with KEEP
, allowing for a more fine
grained customization of this behavior.
Every segment referencing a vram class will inherit its keep_sections
attribute, propagating this setting to all those segments and allowing the user
to avoid unnecessary duplication. This setting may be overriden for specific
segments that still want to reference the given vram class. See specifying a
keep_sections
attribute on the segments
document
for more information.
GNU LD documentation for
KEEP
.
vram_classes:
- { name: battle_partner, fixed_vram: 0x80238000, keep_sections: [.text] }
- { name: segment_05, fixed_vram: 0x05000000, keep_sections: True }
segments:
- name: battle_partner_goompa
vram_class: battle_partner
files:
- { path: src/battle_partner/goompa.o }
- name: battle_partner_goombario
vram_class: battle_partner
keep_sections: False
files:
- { path: src/battle_partner/goombario.o }
- name: assets1
vram_class: segment_05
files:
- { path: src/assets/texture.o }
- { path: src/assets/dlist.o }
The above example defines two vram classes, battle_partner
which defines
keep_sections
to keep only the .text
section of the files of the segments
that will reference thise vram class, and segment_05
which will keep every
section of every segment referencing it.
The battle_partner_goompa
segment references the battle_partner
vram class
and neither the segment itself or the files within the segment specify their own
keep_sections
, meaning all the .text
sections of all the files of this
segment will be wrapped with KEEP
s.
On the other hand, the battle_partner_goombario
segment (which references the
battle_partner
vram class too) sets its keep_sections
attribute to False
,
meaning that no file of this segment should be wrapped with KEEP
s, overriding
the configuration of the battle_partner
vram class for this specific segment.
Finally the assets1
segment will emit KEEP
s for all the sections of every
file on the segment since the segment_05
vram class did set True
to the
keep_sections
attribute.
Either a boolean or a list of sections (list of strings).
False