Inform the console when an unsupported WMA flavor is played.
[kugel-rb.git] / tools / creative.c
blobb9041ca5131dbe91e86766bb529f1f7979f7e12e
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2008 by Maurus Cuelenaere
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
20 #include <stdio.h>
21 #include <stdbool.h>
22 #include <stdlib.h>
23 #include <string.h>
25 #include "creative.h"
26 #include "hmac-sha1.h"
28 static const char null_key_v1[] = "CTL:N0MAD|PDE0.SIGN.";
29 static const char null_key_v2[] = "CTL:N0MAD|PDE0.DPMP.";
30 static const char null_key_v3[] = "CTL:Z3N07|PDE0.DPMP.";
31 static const char null_key_v4[] = "CTL:N0MAD|PDE0.DPFP.";
33 static const struct device_info devices[] =
35 {"C\0r\0e\0a\0t\0i\0v\0e\0 \0Z\0e\0n\0 \0V\0i\0s\0i\0o\0n\0:\0M",
36 42, null_key_v2},
37 {"C\0r\0e\0a\0t\0i\0v\0e\0 \0Z\0e\0n\0 \0V\0i\0s\0i\0o\0n\0:\0M\0 \0G\0o\0!",
38 50, null_key_v2},
39 {"C\0r\0e\0a\0t\0i\0v\0e\0 \0Z\0e\0n\0 \0V\0i\0s\0i\0o\0n\0 \0©\0T\0L",
40 48, null_key_v2},
41 {"C\0r\0e\0a\0t\0i\0v\0e\0 \0Z\0E\0N\0 \0V", 42, null_key_v4}
46 Create a Zen Vision:M FRESCUE structure file
48 extern void int2le(unsigned int val, unsigned char* addr);
49 extern unsigned int le2int(unsigned char* buf);
52 static int make_ciff_file(unsigned char *inbuf, int length,
53 unsigned char *outbuf, int device)
55 unsigned char key[20];
56 memcpy(outbuf, "FFIC", 4);
57 int2le(length+90, &outbuf[4]);
58 memcpy(&outbuf[8], "FNIC", 4);
59 int2le(96, &outbuf[0xC]);
60 memcpy(&outbuf[0x10], devices[device].cinf, devices[device].cinf_size);
61 memset(&outbuf[0x10+devices[device].cinf_size], 0,
62 96 - devices[device].cinf_size);
63 memcpy(&outbuf[0x70], "ATAD", 4);
64 int2le(length+32, &outbuf[0x74]);
65 memcpy(&outbuf[0x78], "H\0j\0u\0k\0e\0b\0o\0x\0\x32\0.\0j\0r\0m",
66 32); /*Unicode encoded*/
67 memcpy(&outbuf[0x98], inbuf, length);
68 memcpy(&outbuf[0x98+length], "LLUN", 4);
69 int2le(20, &outbuf[0x98+length+4]);
70 /* Do checksum */
71 hmac_sha1((unsigned char *)devices[device].null, strlen(devices[device].null),
72 outbuf, 0x98+length, key);
73 memcpy(&outbuf[0x98+length+8], key, 20);
74 return length+0x90+0x1C+8;
77 static int make_jrm_file(unsigned char *inbuf, int length,
78 unsigned char *outbuf)
80 int i;
81 unsigned int sum = 0;
82 /* Calculate checksum for later use in header */
83 for(i=0; i<length; i+= 4)
84 sum += le2int(&inbuf[i]) + (le2int(&inbuf[i])>>16);
86 /* Clear the header area to zero */
87 memset(outbuf, 0, 0x18);
89 /* Header (EDOC) */
90 memcpy(outbuf, "EDOC", 4);
91 /* Total Size */
92 int2le(length+0x20, &outbuf[0x4]);
93 /* 4 bytes of zero */
95 /* Address = 0x900000 */
96 int2le(0x900000, &outbuf[0xC]);
97 /* Size */
98 int2le(length, &outbuf[0x10]);
99 /* Checksum */
100 int2le(sum, &outbuf[0x14]);
101 outbuf[0x16] = 0;
102 outbuf[0x17] = 0;
103 /* Data starts here... */
104 memcpy(&outbuf[0x18], inbuf, length);
106 /* Second block starts here ... */
107 /* Address = 0x0 */
108 /* Size */
109 int2le(0x4, &outbuf[0x18+length+0x4]);
110 /* Checksum */
111 outbuf[0x18+length+0x8] = 0xA9;
112 outbuf[0x18+length+0x9] = 0xD9;
113 /* Data: MOV PC, 0x900000 */
114 outbuf[0x18+length+0xC] = 0x09;
115 outbuf[0x18+length+0xD] = 0xF6;
116 outbuf[0x18+length+0xE] = 0xA0;
117 outbuf[0x18+length+0xF] = 0xE3;
119 return length+0x18+0x10;
122 int zvm_encode(char *iname, char *oname, int device)
124 size_t len;
125 int length;
126 FILE *file;
127 unsigned char *outbuf;
128 unsigned char *buf;
130 file = fopen(iname, "rb");
131 if (!file) {
132 perror(iname);
133 return -1;
135 fseek(file, 0, SEEK_END);
136 length = ftell(file);
138 fseek(file, 0, SEEK_SET);
140 buf = (unsigned char*)malloc(length);
141 if ( !buf ) {
142 printf("out of memory!\n");
143 return -1;
146 len = fread(buf, 1, length, file);
147 if(len < (size_t)length) {
148 perror(iname);
149 return -2;
151 fclose(file);
153 outbuf = (unsigned char*)malloc(length+0x300);
154 if ( !outbuf ) {
155 free(buf);
156 printf("out of memory!\n");
157 return -1;
159 length = make_jrm_file(buf, len, outbuf);
160 free(buf);
161 buf = (unsigned char*)malloc(length+0x200);
162 memset(buf, 0, length+0x200);
163 length = make_ciff_file(outbuf, length, buf, device);
164 free(outbuf);
166 file = fopen(oname, "wb");
167 if (!file) {
168 free(buf);
169 perror(oname);
170 return -3;
173 len = fwrite(buf, 1, length, file);
174 if(len < (size_t)length) {
175 free(buf);
176 perror(oname);
177 return -4;
180 free(buf);
182 fclose(file);
184 return 0;