Update mkoverlay with new overlay strategy

This commit is contained in:
Jaby 2022-12-20 20:34:03 +01:00 committed by Jaby
parent 82c25693a9
commit c6c0f10143
6 changed files with 152 additions and 66 deletions

View File

@ -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 : {

View File

@ -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

View File

@ -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(())
}

View File

@ -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)?;
}
}

View File

@ -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 {

View File

@ -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>,