summaryrefslogtreecommitdiff
path: root/apps/plugins/xworld/bank.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/xworld/bank.c')
-rw-r--r--apps/plugins/xworld/bank.c153
1 files changed, 153 insertions, 0 deletions
diff --git a/apps/plugins/xworld/bank.c b/apps/plugins/xworld/bank.c
new file mode 100644
index 0000000000..e2cfbd4680
--- /dev/null
+++ b/apps/plugins/xworld/bank.c
@@ -0,0 +1,153 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2014 Franklin Wei, Benjamin Brown
11 * Copyright (C) 2004 Gregory Montoir
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ***************************************************************************/
22
23#include "plugin.h"
24#include "bank.h"
25#include "file.h"
26#include "resource.h"
27
28void bank_create(struct Bank* b, const char *dataDir)
29{
30 b->_dataDir = dataDir;
31}
32
33bool bank_read(struct Bank* b, const struct MemEntry *me, uint8_t *buf) {
34
35 bool ret = false;
36 char bankName[10];
37 rb->snprintf(bankName, 10, "bank%02x", me->bankId);
38 File f;
39 file_create(&f, false);
40 if (!file_open(&f, bankName, b->_dataDir, "rb"))
41 error("bank_read() unable to open '%s' in dir '%s'", bankName, b->_dataDir);
42
43 file_seek(&f, me->bankOffset);
44
45 /* Depending if the resource is packed or not we */
46 /* can read directly or unpack it. */
47 if (me->packedSize == me->size) {
48 file_read(&f, buf, me->packedSize);
49 ret = true;
50 } else {
51 file_read(&f, buf, me->packedSize);
52 b->_startBuf = buf;
53 b->_iBuf = buf + me->packedSize - 4;
54 ret = bank_unpack(b);
55 }
56 file_close(&f);
57 return ret;
58}
59
60void bank_decUnk1(struct Bank* b, uint8_t numChunks, uint8_t addCount) {
61 uint16_t count = bank_getCode(b, numChunks) + addCount + 1;
62 debug(DBG_BANK, "bank_decUnk1(%d, %d) count=%d", numChunks, addCount, count);
63 b->_unpCtx.datasize -= count;
64 while (count--) {
65 assert(b->_oBuf >= b->_iBuf && b->_oBuf >= b->_startBuf);
66 *b->_oBuf = (uint8_t)bank_getCode(b, 8);
67 --b->_oBuf;
68 }
69}
70
71/*
72 Note from fab: This look like run-length encoding.
73*/
74void bank_decUnk2(struct Bank* b, uint8_t numChunks) {
75 uint16_t i = bank_getCode(b, numChunks);
76 uint16_t count = b->_unpCtx.size + 1;
77 debug(DBG_BANK, "bank_decUnk2(%d) i=%d count=%d", numChunks, i, count);
78 b->_unpCtx.datasize -= count;
79 while (count--) {
80 assert(b->_oBuf >= b->_iBuf && b->_oBuf >= b->_startBuf);
81 *b->_oBuf = *(b->_oBuf + i);
82 --b->_oBuf;
83 }
84}
85
86/*
87 Most resource in the banks are compacted.
88*/
89bool bank_unpack(struct Bank* b) {
90 b->_unpCtx.size = 0;
91 b->_unpCtx.datasize = READ_BE_UINT32(b->_iBuf);
92 b->_iBuf -= 4;
93 b->_oBuf = b->_startBuf + b->_unpCtx.datasize - 1;
94 b->_unpCtx.crc = READ_BE_UINT32(b->_iBuf);
95 b->_iBuf -= 4;
96 b->_unpCtx.chk = READ_BE_UINT32(b->_iBuf);
97 b->_iBuf -= 4;
98 b->_unpCtx.crc ^= b->_unpCtx.chk;
99 do {
100 if (!bank_nextChunk(b)) {
101 b->_unpCtx.size = 1;
102 if (!bank_nextChunk(b)) {
103 bank_decUnk1(b, 3, 0);
104 } else {
105 bank_decUnk2(b, 8);
106 }
107 } else {
108 uint16_t c = bank_getCode(b, 2);
109 if (c == 3) {
110 bank_decUnk1(b, 8, 8);
111 } else {
112 if (c < 2) {
113 b->_unpCtx.size = c + 2;
114 bank_decUnk2(b, c + 9);
115 } else {
116 b->_unpCtx.size = bank_getCode(b, 8);
117 bank_decUnk2(b, 12);
118 }
119 }
120 }
121 } while (b->_unpCtx.datasize > 0);
122 return (b->_unpCtx.crc == 0);
123}
124
125uint16_t bank_getCode(struct Bank* b, uint8_t numChunks) {
126 uint16_t c = 0;
127 while (numChunks--) {
128 c <<= 1;
129 if (bank_nextChunk(b)) {
130 c |= 1;
131 }
132 }
133 return c;
134}
135
136bool bank_nextChunk(struct Bank* b) {
137 bool CF = bank_rcr(b, false);
138 if (b->_unpCtx.chk == 0) {
139 assert(b->_iBuf >= b->_startBuf);
140 b->_unpCtx.chk = READ_BE_UINT32(b->_iBuf);
141 b->_iBuf -= 4;
142 b->_unpCtx.crc ^= b->_unpCtx.chk;
143 CF = bank_rcr(b, true);
144 }
145 return CF;
146}
147
148bool bank_rcr(struct Bank* b, bool CF) {
149 bool rCF = (b->_unpCtx.chk & 1);
150 b->_unpCtx.chk >>= 1;
151 if (CF) b->_unpCtx.chk |= 0x80000000;
152 return rCF;
153}