Waternoose, the XBOX 360 emulator
A very young XBOX 360 emulator that aims to boot games some day
Loading...
Searching...
No Matches
lzx.cpp
1#include "lzx.h"
2#include <algorithm>
3#include <climits>
4#include <cstring>
5
6#include <mspack.h>
7#include <thirdparty/lzx.h>
8
9typedef struct
10{
11 mspack_system sys;
12 void* buffer;
13 off_t buffer_size;
14 off_t offset;
16
17inline bool bit_scan_forward(uint32_t v, uint32_t* out_first_set_index) {
18 int i = ffs(v);
19 *out_first_set_index = i - 1;
20 return i != 0;
21}
22inline bool bit_scan_forward(uint64_t v, uint32_t* out_first_set_index) {
23 int i = __builtin_ffsll(v);
24 *out_first_set_index = i - 1;
25 return i != 0;
26}
27
28inline bool bit_scan_forward(int32_t v, uint32_t* out_first_set_index) {
29 return bit_scan_forward(static_cast<uint32_t>(v), out_first_set_index);
30}
31inline bool bit_scan_forward(int64_t v, uint32_t* out_first_set_index) {
32 return bit_scan_forward(static_cast<uint64_t>(v), out_first_set_index);
33}
34
35mspackMemoryFile_t* mspack_memory_open(mspack_system* sys, void* buffer, const size_t size)
36{
37 auto memfile = (mspackMemoryFile_t*)calloc(1, sizeof(mspackMemoryFile_t));
38 if (!memfile)
39 return NULL;
40 memfile->buffer = buffer;
41 memfile->buffer_size = (off_t)size;
42 memfile->offset = 0;
43 return memfile;
44}
45
46void mspack_memory_close(mspackMemoryFile_t* file)
47{
48 auto memfile = (mspackMemoryFile_t*)file;
49 free(memfile);
50}
51
52int mspack_memory_read(mspack_file* file, void* buffer, int chars)
53{
54 auto memfile = (mspackMemoryFile_t*)file;
55 const off_t remaining = memfile->buffer_size - memfile->offset;
56 const off_t total = std::min(static_cast<off_t>(chars), remaining);
57 std::memcpy(buffer, (uint8_t*)memfile->buffer + memfile->offset, total);
58 memfile->offset += total;
59 return (int)total;
60}
61
62int mspack_memory_write(mspack_file* file, void* buffer, int chars)
63{
64 auto memfile = (mspackMemoryFile_t*)file;
65 const off_t remaining = memfile->buffer_size - memfile->offset;
66 const off_t total = std::min(static_cast<off_t>(chars), remaining);
67 std::memcpy((uint8_t*)memfile->buffer + memfile->offset, buffer, total);
68 memfile->offset += total;
69 return (int)total;
70}
71
72void* mspack_memory_alloc(mspack_system*, size_t chars)
73{
74 return calloc(chars, 1);
75}
76
77void mspack_memory_free(void* ptr)
78{
79 free(ptr);
80}
81
82void mspack_memory_copy(void* src, void* dest, size_t chars)
83{
84 memcpy(dest, src, chars);
85}
86
87mspack_system* mspack_memory_sys_create()
88{
89 auto sys = (mspack_system*)calloc(1, sizeof(mspack_system));
90 if (!sys)
91 return NULL;
92 sys->read = mspack_memory_read;
93 sys->write = mspack_memory_write;
94 sys->alloc = mspack_memory_alloc;
95 sys->free = mspack_memory_free;
96 sys->copy = mspack_memory_copy;
97 return sys;
98}
99
100void mspack_memory_sys_destroy(struct mspack_system* sys) { free(sys); }
101
102int lzx_decompress(const void *lzx_data, size_t lzx_len, void *dest, size_t dest_len, uint32_t window_size, void *window_data, size_t window_data_len)
103{
104 int res = 1;
105
106 uint32_t window_bits;
107 if (!bit_scan_forward(window_size, &window_bits))
108 return res;
109
110 mspack_system* sys = mspack_memory_sys_create();
111 mspackMemoryFile_t* lzxsrc = mspack_memory_open(sys, (void*)lzx_data, lzx_len);
112 mspackMemoryFile_t* lzxdst = mspack_memory_open(sys, dest, dest_len);
113 lzxd_stream* lzxd = lzxd_init(sys, (mspack_file*)lzxsrc, (mspack_file*)lzxdst, window_bits, 0, 0x8000, (off_t)dest_len, 0);
114
115 if (lzxd)
116 {
117 if (window_data)
118 {
119 auto padding_len = window_size - window_data_len;
120 memset(&lzxd->window[0], 0, padding_len);
121 memcpy(&lzxd->window[padding_len], window_data, window_data_len);
122 lzxd->ref_data_size = window_size;
123 }
124
125 res = lzxd_decompress(lzxd, (off_t)dest_len);
126
127 lzxd_free(lzxd);
128 lzxd = NULL;
129 }
130
131 if (lzxsrc)
132 {
133 mspack_memory_close(lzxsrc);
134 lzxsrc = NULL;
135 }
136
137 if (lzxdst)
138 {
139 mspack_memory_close(lzxdst);
140 lzxdst = NULL;
141 }
142
143 if (sys)
144 {
145 mspack_memory_sys_destroy(sys);
146 sys = NULL;
147 }
148
149 return res;
150}