4 * CD Bootstrap header parsing. Mostly for informational purposes.
6 * Copyright (c) 2005 Nathan Keynes.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
20 #include "bootstrap.h"
22 static uint32_t compute_crc16( dc_bootstrap_head_t h )
24 /* Note: Algorithm taken from http://mc.pp.se/dc/ip0000.bin.html */
25 uint32_t i, c, n = 0xffff;
26 char *data = h->product_id;
27 for (i = 0; i < 16; i++)
30 for (c = 0; c < 8; c++)
40 static char *dc_peripherals[] = { "Uses WinCE", "Unknown (0x0000002)",
41 "Unknown (0x0000004)", "Unknown (0x0000008)",
42 "VGA Box", "Unknown (0x0000020)",
43 "Unknown (0x0000040)", "Unknown (0x0000080)",
44 "Other Expansions", "Puru Puru pack",
45 "Mike", "Memory card",
46 "Basic controller", "C button",
47 "D button", "X button",
48 "Y button", "Z button",
49 "Expanded direction buttons",
50 "Analog R trigger", "Analog L trigger",
51 "Analog horizontal", "Analog vertical",
52 "Expanded analog horizontal",
53 "Expanded analog vertical",
54 "Gun", "Keyboard", "Mouse" };
58 #define DC_PERIPH_WINCE 0x0000001
59 #define DC_PERIPH_VGABOX 0x0000010
60 #define DC_PERIPH_OTHER 0x0000100
61 #define DC_PERIPH_PURUPURU 0x0000200
62 #define DC_PERIPH_MIKE 0x0000400
63 #define DC_PERIPH_MEMCARD 0x0000800
64 /* Basic requirements */
65 #define DC_PERIPH_BASIC 0x0001000 /* Basic controls - start, a, b, arrows */
66 #define DC_PERIPH_C_BUTTON 0x0002000
67 #define DC_PERIPH_D_BUTTON 0x0004000
68 #define DC_PERIPH_X_BUTTON 0x0008000
69 #define DC_PERIPH_Y_BUTTON 0x0010000
70 #define DC_PERIPH_Z_BUTTON 0x0020000
71 #define DC_PERIPH_EXP_DIR 0x0040000 /* Expanded direction buttons */
72 #define DC_PERIPH_ANALOG_R 0x0080000 /* Analog R trigger */
73 #define DC_PERIPH_ANALOG_L 0x0100000 /* Analog L trigger */
74 #define DC_PERIPH_ANALOG_H 0x0200000 /* Analog horizontal controller */
75 #define DC_PERIPH_ANALOG_V 0x0400000 /* Analog vertical controller */
76 #define DC_PERIPH_EXP_AH 0x0800000 /* Expanded analog horizontal (?) */
77 #define DC_PERIPH_EXP_AV 0x1000000 /* Expanded analog vertical (?) */
78 /* Optional peripherals */
79 #define DC_PERIPH_GUN 0x2000000
80 #define DC_PERIPH_KEYBOARD 0x4000000
81 #define DC_PERIPH_MOUSE 0x8000000
84 * Dump the bootstrap info to the output log for infomational/debugging
86 * @param detail true to include a ful information dump, false for just
89 void bootstrap_dump( void *data, gboolean detail )
91 struct dc_bootstrap_head *head;
92 int i, got, periph, crc, hcrc;
96 /* Dump out the bootstrap metadata table */
97 head = (struct dc_bootstrap_head *)data;
98 prot_symbols = ((char *)data) + 0x3700;
99 memcpy( buf, head->product_name, 128 );
100 for( i=127; i>0 && buf[i] == ' '; i-- );
102 periph = strtol( head->peripherals, NULL, 16 );
103 INFO( "Name: %s Author: %-16.16s",
104 buf, head->vendor_id );
105 sprintf( buf, "%4.4s", head->crc );
106 crc = compute_crc16(head);
107 hcrc = strtol( buf, NULL, 16 );
108 INFO( " Product ID: %-10.10s Product Ver: %-6.6s Date: %-8.8s",
109 head->product_id, head->product_ver, head->product_date );
111 INFO( " Header CRC: %04X (Computed %04X)", hcrc, crc );
112 INFO( " Boot File: %-16.16s", head->boot_file );
113 INFO( " Disc ID: %-11.11s Regions: %-8.8s Peripherals: %07X",
114 head->gdrom_id, head->regions, periph );
115 strcpy( buf, " Supports: " );
117 for( i=0; i<28; i++ ) {
118 if( periph & (1<<i) ){
119 if( got ) strcat( buf, ", " );
120 strcat( buf, dc_peripherals[i] );
123 if( i == 11 ) i = 23; /* Skip 8-23 */
126 strcpy( buf, " Requires: " );
128 for( i=12; i<24; i++ ) {
129 if( periph & (1<<i) ) {
130 if( got ) strcat( buf, ", " );
131 strcat( buf, dc_peripherals[i] );
139 /* Scramble/unscramble, based on Marcus Comstedt's algorithm. */
141 typedef uint16_t randseed;
143 #define MAXBLOCK (2048*1024)
145 #define NEXT(seed) (((seed = (seed*2109+9273)&0x7fff) + 0xC000) & 0xFFFF)
147 void bootprogram_scramble( unsigned char *dest, unsigned char *src, size_t length )
149 randseed seed = length & 0xFFFF;
150 unsigned table[MAXBLOCK/32];
151 unsigned char *s = src;
152 unsigned char *d = dest;
154 for( unsigned blocksize = MAXBLOCK; blocksize >= CHUNKSIZE; blocksize >>= 1 ) {
155 while( length >= blocksize ) {
156 unsigned nchunks = blocksize/CHUNKSIZE;
157 for( unsigned i=0; i<nchunks; i++ ) {
158 table[i] = i; // Identity
160 for( unsigned i = nchunks-1; i != (unsigned)-1; --i ) {
161 unsigned j = (NEXT(seed) * i)>>16;
162 unsigned tmp = table[i];
165 memcpy( d, s + CHUNKSIZE*table[i], CHUNKSIZE );
173 memcpy( d, s, length );
177 void bootprogram_unscramble( unsigned char *dest, unsigned char *src, size_t length )
179 randseed seed = length & 0xFFFF;
180 unsigned table[MAXBLOCK/32];
181 unsigned char *s = src;
182 unsigned char *d = dest;
184 for( unsigned blocksize = MAXBLOCK; blocksize >= CHUNKSIZE; blocksize >>= 1 ) {
185 while( length >= blocksize ) {
186 unsigned nchunks = blocksize/CHUNKSIZE;
187 for( unsigned i=0; i<nchunks; i++ ) {
188 table[i] = i; // Identity
190 for( unsigned i = nchunks-1; i != (unsigned)-1; --i ) {
191 unsigned j = (NEXT(seed) * i)>>16;
192 unsigned tmp = table[i];
195 memcpy( d + CHUNKSIZE*table[i], s, CHUNKSIZE );
203 memcpy( d, s, length );
.