mirror of
https://github.com/Ed94/pikuma_ps1.git
synced 2026-08-07 16:18:51 +00:00
lua metaprogram adjustments
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
// Auto-generated by gen_atom_offsets.lua — DO NOT EDIT
|
// Auto-generated by tape_atom_offset_gen.meta.lua — DO NOT EDIT
|
||||||
// Source: C:\projects\Pikuma\ps1\code\duffle\lottes_tape.h
|
// Source: C:\projects\Pikuma\ps1\code\duffle\lottes_tape.h
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Auto-generated by gen_atom_offsets.lua — DO NOT EDIT
|
// Auto-generated by tape_atom_offset_gen.meta.lua — DO NOT EDIT
|
||||||
// Source: C:\projects\Pikuma\ps1\code\gte_hello\hello_gte_tape.c
|
// Source: C:\projects\Pikuma\ps1\code\gte_hello\hello_gte_tape.c
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
|||||||
+107
-107
@@ -7,123 +7,123 @@ Converts a raw binary file to PlayStation 1 (PS-X) executable format.
|
|||||||
]]
|
]]
|
||||||
|
|
||||||
function file_size(filename)
|
function file_size(filename)
|
||||||
local file = io.open(filename, "rb")
|
local file = io.open(filename, "rb")
|
||||||
if not file then return nil end
|
if not file then return nil end
|
||||||
local size = file:seek("end")
|
local size = file:seek("end")
|
||||||
file:close()
|
file:close()
|
||||||
return size
|
return size
|
||||||
end
|
end
|
||||||
|
|
||||||
function main(args)
|
function main(args)
|
||||||
if #args ~= 2 then
|
if #args ~= 2 then
|
||||||
io.stderr:write(usage)
|
io.stderr:write(usage)
|
||||||
os.exit(1)
|
os.exit(1)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- print(string.format("Input file: %s", args[1]))
|
-- print(string.format("Input file: %s", args[1]))
|
||||||
-- print(string.format("Output file: %s", args[2]))
|
-- print(string.format("Output file: %s", args[2]))
|
||||||
|
|
||||||
-- PS1 executables have a maximum size limit of 2MB
|
-- PS1 executables have a maximum size limit of 2MB
|
||||||
local max_size = 0x200000
|
local max_size = 0x200000
|
||||||
-- print(string.format("\nChecking input file size (max: %d bytes)...", max_size))
|
-- print(string.format("\nChecking input file size (max: %d bytes)...", max_size))
|
||||||
|
|
||||||
local infile_size = file_size(args[1])
|
local infile_size = file_size(args[1])
|
||||||
if not infile_size then
|
if not infile_size then
|
||||||
io.stderr:write("Error: Cannot open input file " .. args[1] .. "\n")
|
io.stderr:write("Error: Cannot open input file " .. args[1] .. "\n")
|
||||||
os.exit(1)
|
os.exit(1)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- print(string.format("Input file size: %d bytes", infile_size))
|
-- print(string.format("Input file size: %d bytes", infile_size))
|
||||||
|
|
||||||
if infile_size > max_size then
|
if infile_size > max_size then
|
||||||
io.stderr:write(string.format("Error: Input file %s longer than %d bytes\n", args[1], max_size))
|
io.stderr:write(string.format("Error: Input file %s longer than %d bytes\n", args[1], max_size))
|
||||||
os.exit(1)
|
os.exit(1)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- print("\nOpening files...")
|
-- print("\nOpening files...")
|
||||||
local ofile = io.open(args[2], "wb")
|
local ofile = io.open(args[2], "wb")
|
||||||
if not ofile then
|
if not ofile then
|
||||||
io.stderr:write("Error: Cannot open output file " .. args[2] .. "\n")
|
io.stderr:write("Error: Cannot open output file " .. args[2] .. "\n")
|
||||||
os.exit(1)
|
os.exit(1)
|
||||||
end
|
end
|
||||||
|
|
||||||
local ifile = io.open(args[1], "rb")
|
local ifile = io.open(args[1], "rb")
|
||||||
if not ifile then
|
if not ifile then
|
||||||
io.stderr:write("Error: Cannot open input file " .. args[1] .. "\n")
|
io.stderr:write("Error: Cannot open input file " .. args[1] .. "\n")
|
||||||
os.exit(1)
|
os.exit(1)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- PS1 executables start with "PS-X EXE" magic string
|
-- PS1 executables start with "PS-X EXE" magic string
|
||||||
-- print("Writing PS-X executable header...")
|
-- print("Writing PS-X executable header...")
|
||||||
ofile:write("PS-X EXE")
|
ofile:write("PS-X EXE")
|
||||||
|
|
||||||
-- Write entry point address (where the PS1 will jump to start execution)
|
-- Write entry point address (where the PS1 will jump to start execution)
|
||||||
-- 0x80010000 is a standard entry point in PS1 RAM
|
-- 0x80010000 is a standard entry point in PS1 RAM
|
||||||
ofile:seek("set", 0x10)
|
ofile:seek("set", 0x10)
|
||||||
ofile:write(string.pack("<I4", 0x80010000))
|
ofile:write(string.pack("<I4", 0x80010000))
|
||||||
-- print(" Entry point: 0x80010000")
|
-- print(" Entry point: 0x80010000")
|
||||||
|
|
||||||
-- Initial GP/R28 register value (Global Pointer for data addressing)
|
-- Initial GP/R28 register value (Global Pointer for data addressing)
|
||||||
-- 0xFFFFFFFF means it will be set by crt0.S startup code
|
-- 0xFFFFFFFF means it will be set by crt0.S startup code
|
||||||
ofile:write(string.pack("<I4", 0xFFFFFFFF))
|
ofile:write(string.pack("<I4", 0xFFFFFFFF))
|
||||||
|
|
||||||
-- Destination address in RAM where the executable will be loaded
|
-- Destination address in RAM where the executable will be loaded
|
||||||
ofile:write(string.pack("<I4", 0x80010000))
|
ofile:write(string.pack("<I4", 0x80010000))
|
||||||
-- print(" Load address: 0x80010000")
|
-- print(" Load address: 0x80010000")
|
||||||
|
|
||||||
-- Initial stack pointer (SP/R29) and frame pointer (FP/R30)
|
-- Initial stack pointer (SP/R29) and frame pointer (FP/R30)
|
||||||
-- 0x801FFF00 points near the top of the 2MB main RAM
|
-- 0x801FFF00 points near the top of the 2MB main RAM
|
||||||
ofile:seek("set", 0x30)
|
ofile:seek("set", 0x30)
|
||||||
ofile:write(string.pack("<I4", 0x801FFF00))
|
ofile:write(string.pack("<I4", 0x801FFF00))
|
||||||
-- print(" Stack pointer: 0x801FFF00")
|
-- print(" Stack pointer: 0x801FFF00")
|
||||||
|
|
||||||
-- PS1 executables have an 0x800 (2048) byte header
|
-- PS1 executables have an 0x800 (2048) byte header
|
||||||
-- Zero fill the rest of the header
|
-- Zero fill the rest of the header
|
||||||
ofile:seek("set", 0x800)
|
ofile:seek("set", 0x800)
|
||||||
-- print(" Header padding complete (2048 bytes)")
|
-- print(" Header padding complete (2048 bytes)")
|
||||||
|
|
||||||
-- Copy the actual program binary data after the header
|
-- Copy the actual program binary data after the header
|
||||||
-- print("\nCopying program data...")
|
-- print("\nCopying program data...")
|
||||||
local buffer_size = 0x2000 -- 8KB chunks for efficient copying
|
local buffer_size = 0x2000 -- 8KB chunks for efficient copying
|
||||||
local bytes_copied = 0
|
local bytes_copied = 0
|
||||||
|
|
||||||
for i = 0, math.ceil(infile_size / buffer_size) - 1 do
|
for i = 0, math.ceil(infile_size / buffer_size) - 1 do
|
||||||
local buffer = ifile:read(buffer_size)
|
local buffer = ifile:read(buffer_size)
|
||||||
if buffer then
|
if buffer then
|
||||||
ofile:write(buffer)
|
ofile:write(buffer)
|
||||||
bytes_copied = bytes_copied + #buffer
|
bytes_copied = bytes_copied + #buffer
|
||||||
-- Show progress every 64KB
|
-- Show progress every 64KB
|
||||||
if bytes_copied % 0x10000 == 0 or bytes_copied == infile_size then
|
if bytes_copied % 0x10000 == 0 or bytes_copied == infile_size then
|
||||||
print(string.format(" Copied %d/%d bytes (%.1f%%)",
|
print(string.format(" Copied %d/%d bytes (%.1f%%)",
|
||||||
bytes_copied, infile_size, (bytes_copied / infile_size) * 100))
|
bytes_copied, infile_size, (bytes_copied / infile_size) * 100))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- PS1 executables must be padded to 0x800 (2048) byte boundaries
|
-- PS1 executables must be padded to 0x800 (2048) byte boundaries
|
||||||
print("\nAligning to 2048-byte boundary...")
|
print("\nAligning to 2048-byte boundary...")
|
||||||
local exe_size = ofile:seek()
|
local exe_size = ofile:seek()
|
||||||
if exe_size % 0x800 ~= 0 then
|
if exe_size % 0x800 ~= 0 then
|
||||||
local padding = 0x800 - (exe_size % 0x800)
|
local padding = 0x800 - (exe_size % 0x800)
|
||||||
exe_size = exe_size + padding
|
exe_size = exe_size + padding
|
||||||
ofile:seek("set", exe_size - 1)
|
ofile:seek("set", exe_size - 1)
|
||||||
ofile:write(string.pack("B", 0))
|
ofile:write(string.pack("B", 0))
|
||||||
print(string.format(" Added %d bytes of padding", padding))
|
print(string.format(" Added %d bytes of padding", padding))
|
||||||
else
|
else
|
||||||
print(" No padding needed")
|
print(" No padding needed")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Write the size of the executable (excluding the 0x800 byte header)
|
-- Write the size of the executable (excluding the 0x800 byte header)
|
||||||
-- This goes at offset 0x1C in the header
|
-- This goes at offset 0x1C in the header
|
||||||
ofile:seek("set", 0x1C)
|
ofile:seek("set", 0x1C)
|
||||||
ofile:write(string.pack("<I4", exe_size - 0x800))
|
ofile:write(string.pack("<I4", exe_size - 0x800))
|
||||||
-- print(string.format("\nProgram size field set to: %d bytes", exe_size - 0x800))
|
-- print(string.format("\nProgram size field set to: %d bytes", exe_size - 0x800))
|
||||||
|
|
||||||
ifile:close()
|
ifile:close()
|
||||||
ofile:close()
|
ofile:close()
|
||||||
|
|
||||||
-- print(string.format("\nSuccess! PS1 executable created: %s", args[2]))
|
-- print(string.format("\nSuccess! PS1 executable created: %s", args[2]))
|
||||||
print(string.format("Total file size: %d bytes\n", exe_size))
|
print(string.format("Total file size: %d bytes\n", exe_size))
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Run main with command line arguments
|
-- Run main with command line arguments
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user