dw2003's executable is now built from assembly.
This commit is contained in:
parent
b4029f4d01
commit
21930dc8de
13
.vscode/settings.json
vendored
13
.vscode/settings.json
vendored
@ -1,4 +1,13 @@
|
||||
{
|
||||
"cSpell.words": ["bitflags", "byteorder", "cdrom", "seeked", "thiserror"],
|
||||
"python.formatting.provider": "yapf"
|
||||
"cSpell.words": [
|
||||
"bitflags",
|
||||
"byteorder",
|
||||
"cdrom",
|
||||
"psexe",
|
||||
"seeked",
|
||||
"thiserror"
|
||||
],
|
||||
"python.formatting.provider": "yapf",
|
||||
"rust-analyzer.checkOnSave.allTargets": false,
|
||||
"rust-analyzer.linkedProjects": ["tools/Cargo.toml"]
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
<directory_tree>
|
||||
<file name="SYSTEM.CNF" type="data" source="dw2003/SYSTEM.CNF" />
|
||||
<file name="SLES_039.36" type="data" source="dw2003/SLES_039.36" />
|
||||
<file name="SLES_039.36" type="data" source="build/psexe/dw2003/SLES_039.36" />
|
||||
|
||||
<dir name="AAA">
|
||||
<dir name="PRO">
|
||||
|
||||
BIN
dw2003/SLES_039.36
(Stored with Git LFS)
BIN
dw2003/SLES_039.36
(Stored with Git LFS)
Binary file not shown.
8
dw2003/SLES_039.36.ld
Normal file
8
dw2003/SLES_039.36.ld
Normal file
@ -0,0 +1,8 @@
|
||||
SECTIONS {
|
||||
_.text = 0x80010000;
|
||||
.text _.text : {
|
||||
KEEP(*(.text));
|
||||
}
|
||||
}
|
||||
|
||||
ENTRY(start)
|
||||
230419
dw2003/SLES_039.36.s
Normal file
230419
dw2003/SLES_039.36.s
Normal file
File diff suppressed because it is too large
Load Diff
2
tools/.cargo/config.toml
Normal file
2
tools/.cargo/config.toml
Normal file
@ -0,0 +1,2 @@
|
||||
[build]
|
||||
dep-info-basedir = ".."
|
||||
49
tools/Cargo.lock
generated
49
tools/Cargo.lock
generated
@ -143,6 +143,18 @@ dependencies = [
|
||||
"tracing-subscriber",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ddw3-mkpsexe"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"byteorder",
|
||||
"clap",
|
||||
"ddw3-logger",
|
||||
"goblin",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ddw3-uncd"
|
||||
version = "0.1.0"
|
||||
@ -208,6 +220,17 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "goblin"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7666983ed0dd8d21a6f6576ee00053ca0926fb281a5522577a4dbd0f1b54143"
|
||||
dependencies = [
|
||||
"log",
|
||||
"plain",
|
||||
"scroll",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.12.3"
|
||||
@ -318,6 +341,12 @@ version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
|
||||
|
||||
[[package]]
|
||||
name = "plain"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error"
|
||||
version = "1.0.4"
|
||||
@ -419,6 +448,26 @@ version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
|
||||
|
||||
[[package]]
|
||||
name = "scroll"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04c565b551bafbef4157586fa379538366e4385d42082f255bfd96e4fe8519da"
|
||||
dependencies = [
|
||||
"scroll_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scroll_derive"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bdbda6ac5cd1321e724fa9cee216f3a61885889b896f073b8f82322789c5250e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.14"
|
||||
|
||||
@ -9,6 +9,9 @@ members = [
|
||||
"ddw3-iso9660",
|
||||
"ddw3-uniso",
|
||||
|
||||
# Psexe
|
||||
"ddw3-mkpsexe",
|
||||
|
||||
# Util
|
||||
"ddw3-bytes",
|
||||
"ddw3-util",
|
||||
|
||||
24
tools/ddw3-mkpsexe/Cargo.toml
Normal file
24
tools/ddw3-mkpsexe/Cargo.toml
Normal file
@ -0,0 +1,24 @@
|
||||
[package]
|
||||
edition = "2021"
|
||||
name = "ddw3-mkpsexe"
|
||||
version = "0.1.0"
|
||||
|
||||
[dependencies]
|
||||
|
||||
# Ddw3
|
||||
ddw3-logger = { path = "../ddw3-logger" }
|
||||
|
||||
# Cmd
|
||||
clap = { version = "4.0.11", features = ["derive"] }
|
||||
|
||||
# Logging
|
||||
tracing = "0.1.37"
|
||||
|
||||
# Error handling
|
||||
anyhow = "1.0.65"
|
||||
|
||||
# Elf
|
||||
goblin = "0.5.4"
|
||||
|
||||
# Util
|
||||
byteorder = "1.4.3"
|
||||
20
tools/ddw3-mkpsexe/src/args.rs
Normal file
20
tools/ddw3-mkpsexe/src/args.rs
Normal file
@ -0,0 +1,20 @@
|
||||
//! Arguments
|
||||
|
||||
// Imports
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||
#[derive(clap::Parser)]
|
||||
#[clap(author, version, about)]
|
||||
pub struct Args {
|
||||
/// Input file
|
||||
pub input_file: PathBuf,
|
||||
|
||||
/// Output file
|
||||
#[clap(long = "output", short = 'o')]
|
||||
pub output_file: PathBuf,
|
||||
|
||||
/// License file
|
||||
#[clap(long = "license")]
|
||||
pub license_file: PathBuf,
|
||||
}
|
||||
133
tools/ddw3-mkpsexe/src/main.rs
Normal file
133
tools/ddw3-mkpsexe/src/main.rs
Normal file
@ -0,0 +1,133 @@
|
||||
//! `.psexe` packer
|
||||
|
||||
// Features
|
||||
#![feature(seek_stream_len)]
|
||||
|
||||
// Modules
|
||||
mod args;
|
||||
|
||||
// Imports
|
||||
use {
|
||||
anyhow::Context,
|
||||
args::Args,
|
||||
byteorder::{ByteOrder, LittleEndian},
|
||||
clap::Parser,
|
||||
goblin::Object,
|
||||
std::{
|
||||
fs,
|
||||
io::{Seek, SeekFrom, Write},
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
fn main() -> Result<(), anyhow::Error> {
|
||||
// Initialize the logger
|
||||
ddw3_logger::init().context("Unable to initialize logger")?;
|
||||
|
||||
// Get all args
|
||||
let args = Args::parse();
|
||||
tracing::trace!(?args, "Arguments");
|
||||
|
||||
// Open the input file, parse it, and then get it as an elf
|
||||
let input_contents = fs::read(args.input_file).context("Unable to read input file")?;
|
||||
let object = Object::parse(&input_contents).context("Unable to parse input file")?;
|
||||
let elf = match object {
|
||||
Object::Elf(elf) => elf,
|
||||
object => anyhow::bail!("Expected elf input file, found {object:?}"),
|
||||
};
|
||||
|
||||
// Find the `.text` section
|
||||
let text_header = elf
|
||||
.section_headers
|
||||
.iter()
|
||||
.find(|section| {
|
||||
let name = match elf.shdr_strtab.get_at(section.sh_name) {
|
||||
Some(name) => name,
|
||||
None => {
|
||||
tracing::warn!("Skipping section with invalid name {section:?}");
|
||||
return false;
|
||||
},
|
||||
};
|
||||
|
||||
name == ".text"
|
||||
})
|
||||
.context("Unable to find `.text` section")?;
|
||||
tracing::trace!(?text_header);
|
||||
|
||||
// Get the contents
|
||||
let text_range = text_header
|
||||
.file_range()
|
||||
.context("Unable to get `.text` section's span")?;
|
||||
let text = &input_contents[text_range];
|
||||
|
||||
let pc0 = elf.entry.try_into().context("Start address didn't fit into a `u32`")?;
|
||||
let text_base = text_header
|
||||
.sh_addr
|
||||
.try_into()
|
||||
.context("`.text` section address didn't fit into a `u32`")?;
|
||||
tracing::trace!(pc0 = format!("{pc0:#x}"), text_base = format!("{text_base:#x}"));
|
||||
|
||||
// Create the output file
|
||||
let mut output_file = fs::File::create(&args.output_file).context("Unable to create output file")?;
|
||||
|
||||
// Skip the header
|
||||
output_file
|
||||
.seek(SeekFrom::Current(0x800))
|
||||
.context("Unable to seek past header")?;
|
||||
|
||||
// Write all content and pad to `0x800`
|
||||
output_file.write_all(text).context("Unable to write all data")?;
|
||||
let file_size = output_file
|
||||
.stream_len()
|
||||
.context("Unable to get output file length")?
|
||||
.checked_sub(0x800)
|
||||
.context("Reported output file size was less than `0x800` after writing header & data")?;
|
||||
let file_size = match file_size % 0x800 == 0 {
|
||||
true => file_size,
|
||||
false => {
|
||||
let new_file_size = (file_size + 0x7ff) / 0x800 * 0x800;
|
||||
tracing::debug!("Padding output file of length {file_size:#x} to {new_file_size:#x}");
|
||||
output_file
|
||||
.set_len(new_file_size)
|
||||
.context("Unable to pad output file")?;
|
||||
new_file_size
|
||||
},
|
||||
};
|
||||
let file_size = file_size.try_into().context("File size didn't fit into a `u32`")?;
|
||||
tracing::trace!(file_size = format!("{file_size:#x}"));
|
||||
|
||||
// Then go back and write the header
|
||||
output_file.rewind().context("Unable to rewind output file")?;
|
||||
let license = fs::read(args.license_file).context("Unable to read license file")?;
|
||||
self::write_header(&mut output_file, pc0, text_base, file_size, &license)
|
||||
.context("Unable to write output file header")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Writes the output file header
|
||||
fn write_header(
|
||||
output_file: &mut fs::File,
|
||||
pc0: u32,
|
||||
text_base: u32,
|
||||
file_size: u32,
|
||||
license_text: &[u8],
|
||||
) -> Result<(), anyhow::Error> {
|
||||
let mut header = [0; 0x800];
|
||||
header[0x0..0x8].copy_from_slice(b"PS-X EXE");
|
||||
LittleEndian::write_u32(&mut header[0x10..0x14], pc0);
|
||||
LittleEndian::write_u32(&mut header[0x18..0x1c], text_base);
|
||||
LittleEndian::write_u32(&mut header[0x1c..0x20], file_size);
|
||||
|
||||
// TODO: Hard hardcode these?
|
||||
LittleEndian::write_u32(&mut header[0x30..0x34], 0x801ffff0);
|
||||
LittleEndian::write_u32(&mut header[0x34..0x38], 0x0);
|
||||
|
||||
anyhow::ensure!(license_text.len() <= 0x800 - 0x4c, "License text is too big");
|
||||
header[0x4c..0x4c + license_text.len()].copy_from_slice(license_text);
|
||||
|
||||
output_file
|
||||
.write_all(&header)
|
||||
.context("Unable to write to output file")?;
|
||||
Ok(())
|
||||
}
|
||||
72
zbuild.yaml
72
zbuild.yaml
@ -2,6 +2,8 @@
|
||||
alias:
|
||||
# External tools
|
||||
# prettier-ignore
|
||||
as : mips-elf-as
|
||||
ld : mips-elf-ld
|
||||
mkpsxiso : mkpsxiso
|
||||
cargo : cargo
|
||||
sha256sum: sha256sum
|
||||
@ -11,13 +13,16 @@ alias:
|
||||
generate_compare_deps: tools/generate_compare_deps.py
|
||||
|
||||
# Cargo tools
|
||||
|
||||
mkpsexe: $(tools_dir)/ddw3-mkpsexe
|
||||
|
||||
# Directories
|
||||
build_dir : build
|
||||
tools_dir : $(build_dir)/tools
|
||||
misc_dir : $(build_dir)/misc
|
||||
psx_iso_dir: $(build_dir)/iso
|
||||
asm_dir : $(build_dir)/asm
|
||||
elf_dir : $(build_dir)/elf
|
||||
psexe_dir : $(build_dir)/psexe
|
||||
|
||||
# Files
|
||||
checksums : checksums.sha256
|
||||
@ -36,6 +41,22 @@ alias:
|
||||
psx_iso_deps: $(psx_iso_dir)/^(path).d
|
||||
psx_iso_xml : ^(path).xml
|
||||
|
||||
# Assembly
|
||||
asm_obj : $(asm_dir)/^(path).o
|
||||
asm_obj_deps: $(asm_dir)/^(path).d
|
||||
asm_src : ^(path).s
|
||||
|
||||
# Elf
|
||||
# TODO: Not hardcode where the object files come from
|
||||
elf : $(elf_dir)/^(path).elf
|
||||
elf_obj: $(asm_dir)/^(path).o
|
||||
elf_ld : ^(path).ld
|
||||
|
||||
# Elf
|
||||
# TODO: Not hardcode where the elf or license come from
|
||||
psexe : $(psexe_dir)/^(path)
|
||||
psexe_elf: $(elf_dir)/^(path).elf
|
||||
|
||||
# By default built the final `iso`s
|
||||
default:
|
||||
- $(dw3_psx_iso)
|
||||
@ -128,3 +149,52 @@ rules:
|
||||
exec:
|
||||
- [touch, $(dummy_buffer)]
|
||||
- [truncate, --size=35283682, $(dummy_buffer)]
|
||||
|
||||
# Psexe
|
||||
# TODO: Hardcode less
|
||||
psexe:
|
||||
out: [$(psexe)]
|
||||
deps:
|
||||
- $(psexe_elf)
|
||||
- $(license_psexe_eu)
|
||||
- $(mkpsexe)
|
||||
- static: $(psexe::dir_name)/
|
||||
exec:
|
||||
- - $(mkpsexe)
|
||||
- $(psexe_elf)
|
||||
- -o
|
||||
- $(psexe)
|
||||
- --license
|
||||
- $(license_psexe_eu)
|
||||
|
||||
# Elf
|
||||
# TODO: Hardcode les
|
||||
elf:
|
||||
out: [$(elf)]
|
||||
deps: [$(elf_obj), $(elf_ld), static: $(elf::dir_name)/]
|
||||
exec:
|
||||
- - $(ld)
|
||||
- $(elf_obj)
|
||||
- -o
|
||||
- $(elf)
|
||||
- -EL
|
||||
- --script
|
||||
- $(elf_ld)
|
||||
- --warn-section-align
|
||||
|
||||
# Assembly
|
||||
asm:
|
||||
out: [$(asm_obj), deps_file: $(asm_obj_deps)]
|
||||
deps: [$(asm_src), static: $(asm_obj::dir_name)/]
|
||||
exec:
|
||||
- - $(as)
|
||||
- -MD
|
||||
- $(asm_obj_deps)
|
||||
- $(asm_src)
|
||||
- -o
|
||||
- $(asm_obj)
|
||||
- -EL
|
||||
- -mips1
|
||||
- -march=r3000
|
||||
- -msoft-float
|
||||
- -O2
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user