compress DOL files before sending them to clients
This commit is contained in:
@@ -309,6 +309,11 @@
|
||||
// enable Episode 3 patches by default; it only does so if this option is on.
|
||||
// "EnableEpisode3SendFunctionCall": true,
|
||||
|
||||
// If this setting is enabled, newserv will compress DOL files at startup
|
||||
// time. This makes startup time slower but makes clients' loading time much
|
||||
// faster.
|
||||
"CompressDOLFiles": true,
|
||||
|
||||
// By default, the server keeps track of items in all games, even for versions
|
||||
// other than Blue Burst. This enables use of the $what command, as well as
|
||||
// protection against item duplication cheats (the cheater is disconnected
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
prs_decompress__start:
|
||||
# r3 = dest ptr (used as write ptr)
|
||||
subi r3, r3, 1
|
||||
# r4 = src ptr (used as read ptr)
|
||||
subi r4, r4, 1
|
||||
# r5 = dest size (converted to ptr to last valid output byte)
|
||||
add r5, r5, r3
|
||||
# r6 = src size (converted to ptr to last valid input byte)
|
||||
add r6, r6, r4
|
||||
# r7 = control bits + guard bits
|
||||
li r7, 0
|
||||
# r8 = temp for offset/count
|
||||
# r9 = original dest ptr - 1 (used for computing return value)
|
||||
mr r9, r3
|
||||
# r10 = temp for reading/writing data
|
||||
# r11 = second-level saved LR, temp for offset/count
|
||||
# r12 = saved LR
|
||||
mflr r12
|
||||
|
||||
prs_decompress__next_opcode:
|
||||
bl prs_decompress__cmp_control_bit_and_return_in_r10
|
||||
beq prs_decompress__control_0
|
||||
|
||||
prs_decompress__control_1:
|
||||
bl prs_decompress__read_byte_to_r10
|
||||
bl prs_decompress__write_byte_from_r10
|
||||
b prs_decompress__next_opcode
|
||||
|
||||
prs_decompress__control_0:
|
||||
bl prs_decompress__cmp_control_bit_and_return_in_r10
|
||||
beq prs_decompress__control_00
|
||||
|
||||
prs_decompress__control_01:
|
||||
bl prs_decompress__read_byte_to_r10
|
||||
rlwinm r8, r10, 29, 27, 31 # low 5 bits of offset
|
||||
rlwinm r11, r10, 0, 29, 31 # size
|
||||
addi r11, r11, 2
|
||||
bl prs_decompress__read_byte_to_r10
|
||||
rlwimi. r8, r10, 5, 19, 26 # high 8 bits of offset
|
||||
bne prs_decompress__control_01_not_stop_opcode
|
||||
sub r3, r3, r9
|
||||
mtlr r12
|
||||
blr
|
||||
prs_decompress__control_01_not_stop_opcode:
|
||||
ori r8, r8, 0xE000
|
||||
cmplwi r11, 2
|
||||
bne prs_decompress__control_01_not_extended_count
|
||||
bl prs_decompress__read_byte_to_r10
|
||||
addi r11, r10, 1
|
||||
prs_decompress__control_01_not_extended_count:
|
||||
mtctr r11
|
||||
b prs_decompress__control_00_01_copy
|
||||
|
||||
prs_decompress__control_00:
|
||||
bl prs_decompress__cmp_control_bit_and_return_in_r10
|
||||
rlwinm r11, r10, 1, 30, 30
|
||||
bl prs_decompress__cmp_control_bit_and_return_in_r10
|
||||
rlwimi r11, r10, 0, 31, 31
|
||||
addi r11, r11, 2
|
||||
mtctr r11
|
||||
bl prs_decompress__read_byte_to_r10
|
||||
ori r8, r10, 0xFF00
|
||||
|
||||
prs_decompress__control_00_01_copy:
|
||||
# r8 = src offset (negative 16-bit value)
|
||||
# ctr = byte count to copy
|
||||
oris r8, r8, 0xFFFF
|
||||
add r8, r8, r3 # r8 = copy src ptr (minus 1, for lbzu)
|
||||
prs_decompress__control_00_01_copy_again:
|
||||
lbzu r10, [r8 + 1]
|
||||
bl prs_decompress__write_byte_from_r10
|
||||
bdnz prs_decompress__control_00_01_copy_again
|
||||
b prs_decompress__next_opcode
|
||||
|
||||
prs_decompress__cmp_control_bit_and_return_in_r10:
|
||||
andi. r10, r7, 0x0100
|
||||
bne prs_decompress__skip_read
|
||||
mflr r8
|
||||
bl prs_decompress__read_byte_to_r10
|
||||
mtlr r8
|
||||
mr r7, r10
|
||||
ori r7, r7, 0xFF00
|
||||
prs_decompress__skip_read:
|
||||
andi. r10, r7, 1
|
||||
rlwinm r7, r7, 31, 17, 31
|
||||
blr
|
||||
|
||||
prs_decompress__read_byte_to_r10:
|
||||
cmp r4, r6
|
||||
bge prs_decompress__return_error
|
||||
lbzu r10, [r4 + 1]
|
||||
blr
|
||||
|
||||
prs_decompress__write_byte_from_r10:
|
||||
cmp r3, r5
|
||||
bge prs_decompress__return_error
|
||||
stbu [r3 + 1], r10
|
||||
blr
|
||||
|
||||
prs_decompress__return_error:
|
||||
li r3, -1
|
||||
mtlr r12
|
||||
blr
|
||||
+23
-1
@@ -53,8 +53,25 @@ copy_code_to_low_memory__again:
|
||||
|
||||
|
||||
run_dol:
|
||||
lwz r30, [r31 + 0x10] # r30 = DOL base ptr
|
||||
lwz r30, [r31 + 0x10] # r30 = data base ptr
|
||||
|
||||
# Decompress the file first. If the compressed size is zero, then skip this
|
||||
# step (the file is not compressed). The header consists of two fields:
|
||||
# compressed size followed by decompressed size.
|
||||
lwz r6, [r30]
|
||||
cmplwi r6, 0
|
||||
beq run_dol__not_compressed
|
||||
lwz r5, [r30 + 4]
|
||||
addi r4, r30, 8 # Compressed data immediately follows the 2 header fields
|
||||
sub r3, r30, r5 # Decompress to immediately before the compressed data
|
||||
mr r30, r3 # Save DOL header pointer for after decompression
|
||||
bl prs_decompress
|
||||
b run_dol__decompressed
|
||||
|
||||
run_dol__not_compressed:
|
||||
addi r30, r30, 8
|
||||
|
||||
run_dol__decompressed:
|
||||
# DOL files are very simple: they have up to 7 text sections, up to 11 data
|
||||
# sections, and a BSS section and an entrypoint. No imports or other fancy
|
||||
# things to do - we just have to move a bunch of bytes around.
|
||||
@@ -119,6 +136,11 @@ flush_cached_code_writes:
|
||||
|
||||
|
||||
|
||||
prs_decompress:
|
||||
.include PRSDecompress
|
||||
|
||||
|
||||
|
||||
return_end_ptr:
|
||||
mflr r3
|
||||
bctr
|
||||
|
||||
Reference in New Issue
Block a user