Update mkoverlay with new overlay strategy
This commit is contained in:
parent
a3a757e170
commit
4d6c701a22
27
lib/psexe.ld
27
lib/psexe.ld
|
@ -49,8 +49,6 @@ __fdata_len = (__planschi_end - __fdata_start);
|
|||
|
||||
__stack_start = ORIGIN(ram) + LENGTH(ram);
|
||||
|
||||
__heap_base = __planschi_end;
|
||||
|
||||
SECTIONS {
|
||||
/DISCARD/ : { *(.MIPS.abiflags) }
|
||||
|
||||
|
@ -61,30 +59,7 @@ SECTIONS {
|
|||
/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) *(.gnu.*) *(.comment) }
|
||||
}
|
||||
|
||||
SECTIONS {
|
||||
__boot_loader_start = .;
|
||||
__planschi_start = .;
|
||||
OVERLAY __bss_end : NOCROSSREFS SUBALIGN(4)
|
||||
{
|
||||
.planschi
|
||||
{
|
||||
*libJabyEngine.a:*_boot.o(.text.startup._GLOBAL__*)
|
||||
*libJabyEngine.a:*_boot.o(.ctors)
|
||||
|
||||
*libJabyEngine.a:*_boot.o(.text.*)
|
||||
*libJabyEngine.a:*_boot.o(.rodata*)
|
||||
*libJabyEngine.a:*_boot.o(.sdata*)
|
||||
*libJabyEngine.a::*_boot.o(.data*)
|
||||
*libJabyEngine.a::*_boot.o(.sbss*)
|
||||
*libJabyEngine.a::*_boot.o(.bss*)
|
||||
*libJabyEngine.a::*_boot.o(*)
|
||||
}
|
||||
}
|
||||
__boot_loader_end = .;
|
||||
/*Only needed for the PSX BIOS to load the entire game*/
|
||||
. = ALIGN(2048);
|
||||
__planschi_end = .;
|
||||
}
|
||||
/*Overlay sections created by mkoverlay*/
|
||||
|
||||
SECTIONS {
|
||||
.PSX_EXE_Header : {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "mkoverlay"
|
||||
version = "1.0.0"
|
||||
version = "1.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
|
|
@ -1,14 +1,23 @@
|
|||
use super::super::types::OverlaySlot;
|
||||
use super::super::types::{BootOverlaySection, OverlayDesc, OverlaySection, OverlaySlot};
|
||||
use tool_helper::{Error, format_if_error, Output};
|
||||
use std::io::Write;
|
||||
|
||||
const OVERLAY_DEFAULT_START:&'static str = "__boot_loader_end"; // < will probably be "__boot_loader_start" later
|
||||
const OVERLAY_DEFAULT_START:&'static str = "__planschi_start"; // < will probably be "__boot_loader_start" later
|
||||
|
||||
pub fn write(output: &mut Output, overlay_desc: &Vec<OverlaySlot>) -> Result<(), Error> {
|
||||
fn create_heap_base(overlay_desc: &Vec<OverlaySlot>) -> String {
|
||||
let mut heap_start = format!("MAX({}, __{}_end)", OVERLAY_DEFAULT_START, overlay_desc[0].name);
|
||||
pub fn write(output: &mut Output, overlay_desc: &OverlayDesc) -> Result<(), Error> {
|
||||
fn create_heap_base(overlay_desc: &OverlayDesc) -> String {
|
||||
let (first_entry,additional_slots_iter) = {
|
||||
if overlay_desc.boot_section.is_empty() {
|
||||
(&overlay_desc.additional_slots[0].name, overlay_desc.additional_slots.iter().skip(1))
|
||||
}
|
||||
|
||||
for slot in overlay_desc.iter().skip(1) {
|
||||
else {
|
||||
(&overlay_desc.boot_section.name, overlay_desc.additional_slots.iter().skip(0))
|
||||
}
|
||||
};
|
||||
|
||||
let mut heap_start = format!("MAX({}, __{}_end)", OVERLAY_DEFAULT_START, first_entry);
|
||||
for slot in additional_slots_iter {
|
||||
heap_start = format!("MAX(__{}_end, {})", slot.name, heap_start);
|
||||
}
|
||||
heap_start
|
||||
|
@ -24,34 +33,26 @@ pub fn write(output: &mut Output, overlay_desc: &Vec<OverlaySlot>) -> Result<(),
|
|||
}
|
||||
}
|
||||
|
||||
if overlay_desc.is_empty() {
|
||||
return write_heap_base(output, OVERLAY_DEFAULT_START);
|
||||
if overlay_desc.additional_slots.is_empty() && overlay_desc.boot_section.is_empty() {
|
||||
write_heap_base(output, OVERLAY_DEFAULT_START)?;
|
||||
}
|
||||
|
||||
else {
|
||||
write_heap_base(output, &create_heap_base(&overlay_desc))?;
|
||||
}
|
||||
|
||||
write_heap_base(output, &create_heap_base(overlay_desc))?;
|
||||
writeln!(output, "")?;
|
||||
writeln!(output, "SECTIONS {{")?;
|
||||
for slot in overlay_desc {
|
||||
writeln!(output, "\t/DISCARD/ : {{ *(.comment*) *(.gnu.*) *(.mdebug*) *(.debug_*) *(.pdr)}}")?;
|
||||
write_planschi_section(output, &overlay_desc.boot_section)?;
|
||||
for slot in &overlay_desc.additional_slots {
|
||||
writeln!(output, "\t/*{}*/", slot.name)?;
|
||||
writeln!(output, "\tOVERLAY {} : NOCROSSREFS SUBALIGN(4) {{", get_slot_start_adr(slot))?;
|
||||
for section in &slot.sections {
|
||||
writeln!(output, "\t\t.{} {{", section.name)?;
|
||||
writeln!(output, "\t\t\t__{}_start = .;", section.name)?;
|
||||
section.file_pattern.iter().try_for_each(|patr| writeln!(output, "\t\t\tKEEP({}(.header))", patr))?;
|
||||
writeln!(output, "\t\t\t__{}_lbas = .;", section.name)?;
|
||||
section.file_pattern.iter().try_for_each(|patr| writeln!(output, "\t\t\tKEEP({}(.header.lbas))", patr))?;
|
||||
writeln!(output, "\t\t\t__{}_ctor = .;", section.name)?;
|
||||
|
||||
for section_type in [".text.startup._GLOBAL__*", ".ctors", ".text.*", ".rodata*", ".sdata*", ".data*", ".sbss*", ".bss*"] {
|
||||
section.file_pattern.iter().try_for_each(|patr| writeln!(output, "\t\t\t{}({})", patr, section_type))?;
|
||||
}
|
||||
writeln!(output, "\t\t}}")?;
|
||||
}
|
||||
write_section(output, &slot.sections, false)?;
|
||||
writeln!(output, "\t}}")?;
|
||||
writeln!(output, "\t__{}_end = .;", slot.name)?;
|
||||
writeln!(output, "")?;
|
||||
}
|
||||
writeln!(output, "\t/DISCARD/ : {{ *(.comment*) *(.gnu.*) *(.mdebug*) *(.debug_*) *(.pdr)}}")?;
|
||||
writeln!(output, "}}")?;
|
||||
return Ok(());
|
||||
}
|
||||
|
@ -60,3 +61,66 @@ fn write_heap_base(output: &mut Output, heap_base: &str) -> Result<(), Error> {
|
|||
format_if_error!(writeln!(output, "__heap_base = {};", heap_base), "Writing default LD Script failed with: {error_text}")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_planschi_section(output: &mut Output, boot_overlay: &BootOverlaySection) -> Result<(), Error> {
|
||||
writeln!(output, "\tOVERLAY __bss_end : NOCROSSREFS SUBALIGN(4) {{")?;
|
||||
writeln!(output, "\t\t.planschi {{")?;
|
||||
writeln!(output, "\t\t\t__planschi_start = .;")?;
|
||||
writeln!(output, "\t\t\t__boot_loader_start = .;")?;
|
||||
writeln!(output, "")?;
|
||||
writeln!(output, "\t\t\t*libJabyEngine.a:*_boot.o(.text.startup._GLOBAL__*)")?;
|
||||
writeln!(output, "\t\t\t*_boot.o(.text.startup._GLOBAL__*)")?;
|
||||
writeln!(output, "\t\t\t*libJabyEngine.a:*_boot.o(.ctors)")?;
|
||||
writeln!(output, "\t\t\t*_boot.o(.ctors)")?;
|
||||
writeln!(output, "")?;
|
||||
writeln!(output, "\t\t\t*libJabyEngine.a:*_boot.o(.text.*)")?;
|
||||
writeln!(output, "\t\t\t*_boot.o(.text.*)")?;
|
||||
writeln!(output, "\t\t\t*libJabyEngine.a:*_boot.o(.rodata*)")?;
|
||||
writeln!(output, "\t\t\t*_boot.o(.rodata*)")?;
|
||||
writeln!(output, "\t\t\t*libJabyEngine.a:*_boot.o(.sdata*)")?;
|
||||
writeln!(output, "\t\t\t*_boot.o(.sdata*)")?;
|
||||
writeln!(output, "\t\t\t*libJabyEngine.a:*_boot.o(.data*)")?;
|
||||
writeln!(output, "\t\t\t*_boot.o(.data*)")?;
|
||||
writeln!(output, "\t\t\t*libJabyEngine.a:*_boot.o(.sbss*)")?;
|
||||
writeln!(output, "\t\t\t*_boot.o(.sbss*)")?;
|
||||
writeln!(output, "\t\t\t*libJabyEngine.a:*_boot.o(.bss*)")?;
|
||||
writeln!(output, "\t\t\t*_boot.o(.bss*)")?;
|
||||
writeln!(output, "\t\t\t*libJabyEngine.a:*_boot.o(*)")?;
|
||||
writeln!(output, "\t\t\t*_boot.o(*)")?;
|
||||
writeln!(output, "")?;
|
||||
writeln!(output, "\t\t\t__boot_loader_end = .;")?;
|
||||
writeln!(output, "\t\t\t/*Only needed for the PSX BIOS to load the entire game*/")?;
|
||||
writeln!(output, "\t\t\t. = ALIGN(2048);")?;
|
||||
writeln!(output, "\t\t\t__planschi_end = .;")?;
|
||||
writeln!(output, "\t\t}}")?;
|
||||
writeln!(output, "")?;
|
||||
writeln!(output, "\t\t/*{}*/", boot_overlay.name)?;
|
||||
write_section(output, &boot_overlay.sections, true)?;
|
||||
writeln!(output, "\t}}")?;
|
||||
writeln!(output, "\t__{}_end = .;", boot_overlay.name)?;
|
||||
writeln!(output, "")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_section(output: &mut Output, sections: &Vec<OverlaySection>, add_end_name: bool) -> Result<(), Error> {
|
||||
for section in sections {
|
||||
writeln!(output, "\t\t.{} {{", section.name)?;
|
||||
writeln!(output, "\t\t\t__{}_start = .;", section.name)?;
|
||||
section.file_pattern.iter().try_for_each(|patr| writeln!(output, "\t\t\tKEEP({}(.header))", patr))?;
|
||||
writeln!(output, "\t\t\t__{}_lbas = .;", section.name)?;
|
||||
section.file_pattern.iter().try_for_each(|patr| writeln!(output, "\t\t\tKEEP({}(.header.lbas))", patr))?;
|
||||
writeln!(output, "\t\t\t__{}_ctor = .;", section.name)?;
|
||||
|
||||
for section_type in [".text.startup._GLOBAL__*", ".ctors", ".text.*", ".rodata*", ".sdata*", ".data*", ".sbss*", ".bss*"] {
|
||||
section.file_pattern.iter().try_for_each(|patr| writeln!(output, "\t\t\t{}({})", patr, section_type))?;
|
||||
}
|
||||
|
||||
if add_end_name {
|
||||
writeln!(output, "\t\t\t__{}_end = .;", section.name)?;
|
||||
}
|
||||
writeln!(output, "\t\t}}")?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -1,13 +1,17 @@
|
|||
use super::super::types::OverlaySlot;
|
||||
use super::super::types::OverlayDesc;
|
||||
use tool_helper::{Error, Output};
|
||||
|
||||
pub fn write(output: &mut Output, overlay_desc: &Vec<OverlaySlot>) -> Result<(), Error> {
|
||||
if !overlay_desc.is_empty() {
|
||||
pub fn write(output: &mut Output, overlay_desc: &OverlayDesc) -> Result<(), Error> {
|
||||
if !overlay_desc.boot_section.is_empty() || !overlay_desc.additional_slots.is_empty() {
|
||||
write!(output, "OVERLAYSECTION = ")?;
|
||||
|
||||
for slot in overlay_desc {
|
||||
for overlay in &slot.sections {
|
||||
write!(output, ".{} ", overlay.name)?;
|
||||
for section in &overlay_desc.boot_section.sections {
|
||||
write!(output, ".{} ", section.name)?;
|
||||
}
|
||||
|
||||
for slot in &overlay_desc.additional_slots {
|
||||
for section in &slot.sections {
|
||||
write!(output, ".{} ", section.name)?;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,25 +1,38 @@
|
|||
use super::{OverlaySection, OverlaySlot};
|
||||
use super::{BootOverlaySection, OverlayDesc, OverlaySection, OverlaySlot};
|
||||
use tool_helper::{Error, format_if_error, Input};
|
||||
|
||||
const FOLLOW_KEYWORD:&'static str = "following";
|
||||
|
||||
pub fn read_config(input: Input) -> Result<Vec<OverlaySlot>, Error> {
|
||||
pub fn read_config(input: Input) -> Result<OverlayDesc, Error> {
|
||||
let json_reader:serde_json::Value = format_if_error!(serde_json::from_reader(input), "Parsing JSON failed with: {error_text}")?;
|
||||
let mut overlay_slots = Vec::<OverlaySlot>::new();
|
||||
let mut overlay_desc = OverlayDesc::new();
|
||||
|
||||
if let Some(objects) = json_reader.as_object() {
|
||||
for object in objects {
|
||||
let mut slot = read_as_slot(object)?;
|
||||
if slot.start_adr.is_none() {
|
||||
if let Some(prev_slot) = overlay_slots.last() {
|
||||
slot.set_start_adr_as_end_of(prev_slot.name.as_ref());
|
||||
if overlay_desc.boot_section.is_empty() {
|
||||
overlay_desc.boot_section = BootOverlaySection::new(slot.name, slot.sections);
|
||||
}
|
||||
|
||||
else {
|
||||
if let Some(prev_slot) = overlay_desc.additional_slots.last() {
|
||||
slot.set_start_adr_as_end_of(prev_slot.name.as_ref());
|
||||
}
|
||||
|
||||
else {
|
||||
slot.set_start_adr_as_end_of("planschi");
|
||||
}
|
||||
overlay_desc.additional_slots.push(slot);
|
||||
}
|
||||
}
|
||||
|
||||
overlay_slots.push(slot);
|
||||
else {
|
||||
overlay_desc.additional_slots.push(slot);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(overlay_slots)
|
||||
Ok(overlay_desc)
|
||||
}
|
||||
|
||||
else {
|
||||
|
|
|
@ -1,6 +1,37 @@
|
|||
pub mod json_reader;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct OverlayDesc {
|
||||
pub(super) boot_section: BootOverlaySection,
|
||||
pub(super) additional_slots: Vec<OverlaySlot>
|
||||
}
|
||||
|
||||
impl OverlayDesc {
|
||||
pub fn new() -> OverlayDesc {
|
||||
OverlayDesc{boot_section: BootOverlaySection::default(), additional_slots: Vec::new()}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BootOverlaySection {
|
||||
pub(super) name: String,
|
||||
pub(super) sections: Vec<OverlaySection>,
|
||||
}
|
||||
|
||||
impl BootOverlaySection {
|
||||
pub fn new(name: String, sections: Vec<OverlaySection>) -> BootOverlaySection {
|
||||
BootOverlaySection{name, sections}
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.sections.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::default::Default for BootOverlaySection {
|
||||
fn default() -> Self {
|
||||
BootOverlaySection{name: String::new(), sections: Vec::new()}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct OverlaySection {
|
||||
pub(super) name: String,
|
||||
pub(super) file_pattern: Vec<String>
|
||||
|
@ -16,7 +47,6 @@ impl OverlaySection {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct OverlaySlot {
|
||||
pub(super) name: String,
|
||||
pub(super) start_adr: Option<String>,
|
||||
|
|
Loading…
Reference in New Issue