Update mkoverlay with new overlay strategy
This commit is contained in:
parent
92a6ba68f4
commit
5055b9079f
27
lib/psexe.ld
27
lib/psexe.ld
|
@ -49,8 +49,6 @@ __fdata_len = (__planschi_end - __fdata_start);
|
||||||
|
|
||||||
__stack_start = ORIGIN(ram) + LENGTH(ram);
|
__stack_start = ORIGIN(ram) + LENGTH(ram);
|
||||||
|
|
||||||
__heap_base = __planschi_end;
|
|
||||||
|
|
||||||
SECTIONS {
|
SECTIONS {
|
||||||
/DISCARD/ : { *(.MIPS.abiflags) }
|
/DISCARD/ : { *(.MIPS.abiflags) }
|
||||||
|
|
||||||
|
@ -61,30 +59,7 @@ SECTIONS {
|
||||||
/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) *(.gnu.*) *(.comment) }
|
/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) *(.gnu.*) *(.comment) }
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTIONS {
|
/*Overlay sections created by mkoverlay*/
|
||||||
__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 = .;
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTIONS {
|
SECTIONS {
|
||||||
.PSX_EXE_Header : {
|
.PSX_EXE_Header : {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "mkoverlay"
|
name = "mkoverlay"
|
||||||
version = "1.0.0"
|
version = "1.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# 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 tool_helper::{Error, format_if_error, Output};
|
||||||
use std::io::Write;
|
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> {
|
pub fn write(output: &mut Output, overlay_desc: &OverlayDesc) -> Result<(), Error> {
|
||||||
fn create_heap_base(overlay_desc: &Vec<OverlaySlot>) -> String {
|
fn create_heap_base(overlay_desc: &OverlayDesc) -> String {
|
||||||
let mut heap_start = format!("MAX({}, __{}_end)", OVERLAY_DEFAULT_START, overlay_desc[0].name);
|
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 = format!("MAX(__{}_end, {})", slot.name, heap_start);
|
||||||
}
|
}
|
||||||
heap_start
|
heap_start
|
||||||
|
@ -24,34 +33,26 @@ pub fn write(output: &mut Output, overlay_desc: &Vec<OverlaySlot>) -> Result<(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if overlay_desc.is_empty() {
|
if overlay_desc.additional_slots.is_empty() && overlay_desc.boot_section.is_empty() {
|
||||||
return write_heap_base(output, OVERLAY_DEFAULT_START);
|
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, "")?;
|
||||||
writeln!(output, "SECTIONS {{")?;
|
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, "\t/*{}*/", slot.name)?;
|
||||||
writeln!(output, "\tOVERLAY {} : NOCROSSREFS SUBALIGN(4) {{", get_slot_start_adr(slot))?;
|
writeln!(output, "\tOVERLAY {} : NOCROSSREFS SUBALIGN(4) {{", get_slot_start_adr(slot))?;
|
||||||
for section in &slot.sections {
|
write_section(output, &slot.sections, false)?;
|
||||||
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}}")?;
|
|
||||||
}
|
|
||||||
writeln!(output, "\t}}")?;
|
writeln!(output, "\t}}")?;
|
||||||
writeln!(output, "\t__{}_end = .;", slot.name)?;
|
writeln!(output, "\t__{}_end = .;", slot.name)?;
|
||||||
writeln!(output, "")?;
|
writeln!(output, "")?;
|
||||||
}
|
}
|
||||||
writeln!(output, "\t/DISCARD/ : {{ *(.comment*) *(.gnu.*) *(.mdebug*) *(.debug_*) *(.pdr)}}")?;
|
|
||||||
writeln!(output, "}}")?;
|
writeln!(output, "}}")?;
|
||||||
return Ok(());
|
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}")?;
|
format_if_error!(writeln!(output, "__heap_base = {};", heap_base), "Writing default LD Script failed with: {error_text}")?;
|
||||||
Ok(())
|
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};
|
use tool_helper::{Error, Output};
|
||||||
|
|
||||||
pub fn write(output: &mut Output, overlay_desc: &Vec<OverlaySlot>) -> Result<(), Error> {
|
pub fn write(output: &mut Output, overlay_desc: &OverlayDesc) -> Result<(), Error> {
|
||||||
if !overlay_desc.is_empty() {
|
if !overlay_desc.boot_section.is_empty() || !overlay_desc.additional_slots.is_empty() {
|
||||||
write!(output, "OVERLAYSECTION = ")?;
|
write!(output, "OVERLAYSECTION = ")?;
|
||||||
|
|
||||||
for slot in overlay_desc {
|
for section in &overlay_desc.boot_section.sections {
|
||||||
for overlay in &slot.sections {
|
write!(output, ".{} ", section.name)?;
|
||||||
write!(output, ".{} ", overlay.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};
|
use tool_helper::{Error, format_if_error, Input};
|
||||||
|
|
||||||
const FOLLOW_KEYWORD:&'static str = "following";
|
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 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() {
|
if let Some(objects) = json_reader.as_object() {
|
||||||
for object in objects {
|
for object in objects {
|
||||||
let mut slot = read_as_slot(object)?;
|
let mut slot = read_as_slot(object)?;
|
||||||
if slot.start_adr.is_none() {
|
if slot.start_adr.is_none() {
|
||||||
if let Some(prev_slot) = overlay_slots.last() {
|
if overlay_desc.boot_section.is_empty() {
|
||||||
slot.set_start_adr_as_end_of(prev_slot.name.as_ref());
|
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 {
|
else {
|
||||||
|
|
|
@ -1,6 +1,37 @@
|
||||||
pub mod json_reader;
|
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 struct OverlaySection {
|
||||||
pub(super) name: String,
|
pub(super) name: String,
|
||||||
pub(super) file_pattern: Vec<String>
|
pub(super) file_pattern: Vec<String>
|
||||||
|
@ -16,7 +47,6 @@ impl OverlaySection {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct OverlaySlot {
|
pub struct OverlaySlot {
|
||||||
pub(super) name: String,
|
pub(super) name: String,
|
||||||
pub(super) start_adr: Option<String>,
|
pub(super) start_adr: Option<String>,
|
||||||
|
|
Loading…
Reference in New Issue