summaryrefslogtreecommitdiff
path: root/ips-patcher.lua
blob: 316f8dafa6c594da6bb2ddba3a872b97a315ede3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
-- based on http://zerosoft.zophar.net/ips.php (note the data is big endian - this isn't clear from the text)

local function read_some_bytes(fin, siz)
    local ret = 0

    for _ = 1, siz do
        ret = ret * 256 + fin:readU8()
    end

    return ret
end

function ips_patch(buffer, ips)
    local header, offset, size, b = "", 0, 0
    
    for _ = 1, 5 do
        header = header .. string.char(ips:readU8())
    end
    
    if header ~= "PATCH" then error "Wrong IPS file format - bad header" end
    
    while true do
        offset = read_some_bytes(ips, 3)
    
        -- that's one of the most stupid thing ever... you can NOT patch the offset
        -- 0x454F46 since this is the end of the ips file marker... whomever came
        -- with this brillant design needs a smack in the face.
        if offset == 0x454F46 then
            break
        end
    
        buffer:seek(offset)
        if buffer.wseek then buffer:wseek(offset) end

        size = read_some_bytes(ips, 2)

        if size == 0 then
            size = read_some_bytes(ips, 2)
            b = ips:readU8()
            for _ = 1, size do buffer:writeU8(b) end
        else
            ips:copyto(buffer, size)
        end
    end

    buffer:seek(0)
    if buffer.wseek then buffer:wseek(0) end
end