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_goompaandbattle_partner_goombariosegments will have the samevramaddress as thebattle_partnervram class, which has a fixedvramaddress of0x80238000. battle_partner's end symbol will be set to the end symbol of eitherbattle_partner_goompaorbattle_partner_goombario. If thebattle_partner_goompasegment is bigger then its end symbol will be used, otherwise the end symbol ofbattle_partner_goombariowill be used.- The
battle_codesegment will have the samevramaddress as thebattle_codevram class. - The vram address of the
battle_codevram class will be the same as the end address of thebattle_partnervram class (which is defined depending on the corresponding segments that use that vram class). - The
heaps2segment will have the samevramaddress as theheaps2vram class which has a hardcoded address of0x80267FF0. - The
world_script_apisegment will have thevramaddress of theworld_script_apivram class, which itsvramaddress is the same as the end address of theheaps2vram class. - The
texture_memorysegment has the samevramas thetexture_memoryvram class. The vram address of thetexture_memoryvram class will be the same as the end symbol of the largest vram class betweenbattle_partnerandworld_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 KEEPs.
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 KEEPs, overriding
the configuration of the battle_partner vram class for this specific segment.
Finally the assets1 segment will emit KEEPs 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