comparison sidlib.c @ 163:179ffe97599c

Implement support for the "new" MD5 format of SLDB.
author Matti Hamalainen <ccr@tnsp.org>
date Fri, 16 Feb 2018 22:07:19 +0200
parents 7359170fbb7f
children e6c8a235ce2f
comparison
equal deleted inserted replaced
162:7359170fbb7f 163:179ffe97599c
45 th_free(tmp); 45 th_free(tmp);
46 return FALSE; 46 return FALSE;
47 } 47 }
48 48
49 49
50 int si_read_sid_file(th_ioctx *ctx, PSIDHeader **ppsid) 50 static BOOL si_read_hash_data(th_ioctx *ctx, PSIDHeader *psid,
51 { 51 th_md5state_t *state, BOOL first)
52 PSIDHeader *psid = NULL; 52 {
53 th_md5state_t state; 53 uint8_t *data = NULL;
54 uint8_t tmp8, *data = NULL; 54 BOOL ret = FALSE;
55 int index, ret = -1;
56 size_t read; 55 size_t read;
57 BOOL first;
58 56
59 if ((data = (uint8_t *) th_malloc(PSID_BUFFER_SIZE)) == NULL) 57 if ((data = (uint8_t *) th_malloc(PSID_BUFFER_SIZE)) == NULL)
60 { 58 {
61 th_io_error(ctx, THERR_MALLOC, 59 th_io_error(ctx, THERR_MALLOC,
62 "Error allocating temporary data buffer of %d bytes.\n", 60 "Error allocating temporary data buffer of %d bytes.\n",
63 PSID_BUFFER_SIZE); 61 PSID_BUFFER_SIZE);
64 goto error; 62 goto error;
65 } 63 }
66 64
65 psid->dataSize = 0;
66 do
67 {
68 read = thfread(data, sizeof(uint8_t), PSID_BUFFER_SIZE, ctx);
69 psid->dataSize += read;
70
71 // If load address is 0 in header and we have the first block, grab it
72 if (first && psid->loadAddress == 0)
73 {
74 if (read < 4)
75 {
76 th_io_error(ctx, THERR_FREAD,
77 "Error reading song data, unexpectedly small file.\n");
78 goto error;
79 }
80
81 // Grab the load address
82 psid->loadAddress = TH_LE16_TO_NATIVE(*(uint16_t *) data);
83
84 // .. do not include the load address to the hash
85 th_md5_append(state, &data[2], read - 2);
86 first = FALSE;
87 }
88 else
89 if (read > 0)
90 {
91 // Append data "as is"
92 th_md5_append(state, data, read);
93 }
94 } while (read > 0 && !thfeof(ctx));
95
96 ret = TRUE;
97
98 error:
99 th_free(data);
100 return ret;
101 }
102
103
104 BOOL si_read_sid_file(th_ioctx *ctx, PSIDHeader **ppsid, const BOOL newSLDB)
105 {
106 PSIDHeader *psid = NULL;
107 th_md5state_t state;
108 BOOL ret = FALSE;
109 off_t hdrStart, hdrEnd;
110
67 if ((psid = *ppsid = th_malloc0(sizeof(PSIDHeader))) == NULL) 111 if ((psid = *ppsid = th_malloc0(sizeof(PSIDHeader))) == NULL)
68 { 112 {
69 th_io_error(ctx, THERR_MALLOC, 113 th_io_error(ctx, THERR_MALLOC,
70 "Error PSID context struct.\n"); 114 "Error PSID context struct.\n");
71 goto error; 115 goto error;
72 } 116 }
117
118 hdrStart = thftell(ctx);
73 119
74 // Read PSID header in 120 // Read PSID header in
75 if (!thfread_str(ctx, (uint8_t *) psid->magic, PSID_MAGIC_LEN) || 121 if (!thfread_str(ctx, (uint8_t *) psid->magic, PSID_MAGIC_LEN) ||
76 !thfread_be16(ctx, &psid->version) || 122 !thfread_be16(ctx, &psid->version) ||
77 !thfread_be16(ctx, &psid->dataOffset) || 123 !thfread_be16(ctx, &psid->dataOffset) ||
126 th_error_str(ctx->status)); 172 th_error_str(ctx->status));
127 goto error; 173 goto error;
128 } 174 }
129 } 175 }
130 176
177 hdrEnd = thftell(ctx);
178
131 // Initialize MD5-hash calculation 179 // Initialize MD5-hash calculation
132 th_md5_init(&state); 180 th_md5_init(&state);
133 181
134 // Process actual data 182 if (newSLDB)
135 psid->dataSize = 0; 183 {
136 first = TRUE; 184 // New Songlengths.md5 style hash calculation:
137 do 185 // We just hash the whole file, so seek back to beginning ..
138 { 186 thfseek(ctx, hdrStart, SEEK_SET);
139 read = thfread(data, sizeof(uint8_t), PSID_BUFFER_SIZE, ctx); 187
140 psid->dataSize += read; 188 if (!si_read_hash_data(ctx, psid, &state, FALSE))
141 189 goto error;
142 // If load address is 0 in header and we have the first block, grab it 190
143 if (first && psid->loadAddress == 0) 191 psid->dataSize -= hdrEnd - hdrStart;
144 { 192 }
145 if (read < 4) 193 else
146 { 194 {
147 th_io_error(ctx, THERR_FREAD, 195 // "Old" Songlengths.txt style MD5 hash calculation
148 "Error reading song data, unexpectedly small file.\n"); 196 // We need to separately hash data etc.
149 goto error; 197 if (!si_read_hash_data(ctx, psid, &state, TRUE))
150 } 198 goto error;
151 199
152 // Grab the load address 200 // Append header data to hash
153 psid->loadAddress = TH_LE16_TO_NATIVE(*(uint16_t *) data); 201 th_md5_append_le16(&state, psid->initAddress);
154 202 th_md5_append_le16(&state, psid->playAddress);
155 // .. do not include the load address to the hash 203 th_md5_append_le16(&state, psid->nSongs);
156 th_md5_append(&state, &data[2], read - 2); 204
157 first = FALSE; 205 // Append song speed data to hash
158 } 206 uint8_t tmp8 = psid->isRSID ? 60 : 0;
159 else 207 for (int index = 0; index < psid->nSongs && index < 32; index++)
160 if (read > 0) 208 {
161 { 209 if (psid->isRSID)
162 // Append data "as is" 210 tmp8 = 60;
163 th_md5_append(&state, data, read); 211 else
164 } 212 tmp8 = (psid->speed & (1 << index)) ? 60 : 0;
165 } while (read > 0 && !thfeof(ctx)); 213
166
167 // Append header data to hash
168 th_md5_append_le16(&state, psid->initAddress);
169 th_md5_append_le16(&state, psid->playAddress);
170 th_md5_append_le16(&state, psid->nSongs);
171
172 // Append song speed data to hash
173 tmp8 = psid->isRSID ? 60 : 0;
174 for (index = 0; index < psid->nSongs && index < 32; index++)
175 {
176 if (psid->isRSID)
177 tmp8 = 60;
178 else
179 tmp8 = (psid->speed & (1 << index)) ? 60 : 0;
180
181 th_md5_append(&state, &tmp8, sizeof(tmp8));
182 }
183
184 // Rest of songs (more than 32)
185 for (index = 32; index < psid->nSongs; index++)
186 th_md5_append(&state, &tmp8, sizeof(tmp8));
187
188 // PSIDv2NG specific
189 if (psid->version >= 2)
190 {
191 // REFER TO SIDPLAY HEADERS FOR MORE INFORMATION
192 tmp8 = (psid->flags >> 2) & 3;
193 if (tmp8 == 2)
194 th_md5_append(&state, &tmp8, sizeof(tmp8)); 214 th_md5_append(&state, &tmp8, sizeof(tmp8));
215 }
216
217 // Rest of songs (more than 32)
218 for (int index = 32; index < psid->nSongs; index++)
219 th_md5_append(&state, &tmp8, sizeof(tmp8));
220
221 // PSIDv2NG specific
222 if (psid->version >= 2)
223 {
224 // REFER TO SIDPLAY HEADERS FOR MORE INFORMATION
225 tmp8 = (psid->flags >> 2) & 3;
226 if (tmp8 == 2)
227 th_md5_append(&state, &tmp8, sizeof(tmp8));
228 }
195 } 229 }
196 230
197 // Calculate the hash 231 // Calculate the hash
198 th_md5_finish(&state, psid->hash); 232 th_md5_finish(&state, psid->hash);
199 ret = 0; 233 ret = TRUE;
200 234
201 error: 235 error:
202 // Free buffer 236 // Free buffer
203 th_free(data);
204 return ret; 237 return ret;
205 } 238 }
206 239
207 240
208 void si_free_sid_file(PSIDHeader *psid) 241 void si_free_sid_file(PSIDHeader *psid)