Skip to content

Commit c0ddb35

Browse files
committed
Making raw files generated by ps1-packer fully PIC
1 parent 3604766 commit c0ddb35

File tree

1 file changed

+23
-13
lines changed

1 file changed

+23
-13
lines changed

src/supportpsx/ps1-packer.cc

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ int16_t getLO(uint32_t v) {
7979

8080
void PCSX::PS1Packer::pack(IO<File> src, IO<File> dest, uint32_t addr, uint32_t pc, uint32_t gp, uint32_t sp,
8181
const Options& options) {
82-
constexpr size_t stubSize = 8;
82+
constexpr size_t stubSize = 7 * 4;
8383
std::vector<uint8_t> dataIn;
8484
dataIn.resize(src->size());
8585
src->read(dataIn.data(), dataIn.size());
@@ -98,21 +98,21 @@ void PCSX::PS1Packer::pack(IO<File> src, IO<File> dest, uint32_t addr, uint32_t
9898
if (r != UCL_E_OK) {
9999
throw std::runtime_error("Fatal error during data compression.\n");
100100
}
101-
dataOut.resize(outSize + (options.raw ? 16 : 0));
102-
uint32_t newPC;
103-
uint32_t compLoad;
104-
101+
dataOut.resize(outSize + (options.raw ? stubSize : 0));
105102
while ((dataOut.size() & 3) != 0) {
106103
dataOut.push_back(0);
107104
}
105+
uint32_t newPC = dataOut.size();
106+
uint32_t compLoad = 0;
107+
108108
// If we're outputting a rom file, our tload will be fixed
109109
// at 0x1f000110, after the license string.
110-
uint32_t tload = options.rom ? 0x1f000110 : options.tload;
110+
uint32_t tload = options.raw ? 0 : options.rom ? 0x1f000110 : options.tload;
111111

112112
if (tload != 0) {
113113
newPC = tload + dataOut.size();
114114
compLoad = tload;
115-
} else {
115+
} else if (!options.raw) {
116116
// If we don't have a tload, it means we're doing
117117
// in-place decompression. We need to make sure
118118
// we have enough space to decompress our binary
@@ -132,10 +132,18 @@ void PCSX::PS1Packer::pack(IO<File> src, IO<File> dest, uint32_t addr, uint32_t
132132
if (options.raw) {
133133
// If outputting a raw file, our start address is going
134134
// to be the same as our tload address, so we need to inject
135-
// a jump to the start of our code.
135+
// a jump to the start of our code. We are doing this in
136+
// a fully position-independent way, so raw files can be
137+
// loaded anywhere in memory.
138+
auto offset = newPC - 4 * 4;
136139
std::vector<uint8_t> stub;
137-
pushBytes(stub, j(newPC));
138-
pushBytes(stub, nop());
140+
pushBytes(stub, addiu(Reg::T8, Reg::RA, 0));
141+
pushBytes(stub, lui(Reg::T1, getHI(offset)));
142+
pushBytes(stub, bgezal(Reg::R0, 4));
143+
pushBytes(stub, addiu(Reg::T1, Reg::T1, getLO(offset)));
144+
pushBytes(stub, addu(Reg::T0, Reg::RA, Reg::T1));
145+
pushBytes(stub, jr(Reg::T0));
146+
pushBytes(stub, addiu(Reg::A0, Reg::RA, 12));
139147

140148
assert(stub.size() == stubSize);
141149

@@ -163,7 +171,7 @@ void PCSX::PS1Packer::pack(IO<File> src, IO<File> dest, uint32_t addr, uint32_t
163171
// binary file, and so the next instructions will
164172
// be the very first our binary will run.
165173

166-
if (!options.shell) {
174+
if (!options.shell && !options.raw) {
167175
// We save $ra to $t8, so we can restore it later. This breaks ABI,
168176
// but the ucl-nrv2e decompressor won't use it. This isn't useful
169177
// for the shell trick, since we're just going to reboot the machine.
@@ -173,8 +181,10 @@ void PCSX::PS1Packer::pack(IO<File> src, IO<File> dest, uint32_t addr, uint32_t
173181
pushBytes(dataOut, lui(Reg::V1, 0x1f80));
174182
pushBytes(dataOut, sw(Reg::R0, 0x1074, Reg::V1));
175183
// Calls the ucl-nrv2e decompressor.
176-
pushBytes(dataOut, lui(Reg::A0, getHI(compLoad)));
177-
pushBytes(dataOut, addiu(Reg::A0, Reg::A0, getLO(compLoad)));
184+
if (!options.raw) {
185+
pushBytes(dataOut, lui(Reg::A0, getHI(compLoad)));
186+
pushBytes(dataOut, addiu(Reg::A0, Reg::A0, getLO(compLoad)));
187+
}
178188
pushBytes(dataOut, lui(Reg::A1, getHI(addr)));
179189
pushBytes(dataOut, bgezal(Reg::R0, -((int16_t)(dataOut.size() + 4 - n2estart))));
180190
pushBytes(dataOut, addiu(Reg::A1, Reg::A1, getLO(addr)));

0 commit comments

Comments
 (0)