nkeynes@26 | 1 | /**
|
nkeynes@561 | 2 | * $Id$
|
nkeynes@26 | 3 | *
|
nkeynes@26 | 4 | * CD Bootstrap header parsing. Mostly for informational purposes.
|
nkeynes@26 | 5 | *
|
nkeynes@26 | 6 | * Copyright (c) 2005 Nathan Keynes.
|
nkeynes@26 | 7 | *
|
nkeynes@26 | 8 | * This program is free software; you can redistribute it and/or modify
|
nkeynes@26 | 9 | * it under the terms of the GNU General Public License as published by
|
nkeynes@26 | 10 | * the Free Software Foundation; either version 2 of the License, or
|
nkeynes@26 | 11 | * (at your option) any later version.
|
nkeynes@26 | 12 | *
|
nkeynes@26 | 13 | * This program is distributed in the hope that it will be useful,
|
nkeynes@26 | 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
nkeynes@26 | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
nkeynes@26 | 16 | * GNU General Public License for more details.
|
nkeynes@26 | 17 | */
|
nkeynes@1 | 18 |
|
nkeynes@26 | 19 | #include "dream.h"
|
nkeynes@26 | 20 | #include "bootstrap.h"
|
nkeynes@26 | 21 |
|
nkeynes@26 | 22 | /**
|
nkeynes@26 | 23 | * Bootstrap header structure
|
nkeynes@26 | 24 | */
|
nkeynes@26 | 25 | typedef struct dc_bootstrap_head {
|
nkeynes@26 | 26 | char hardware_id[16]; /* must be "SEGA SEGAKATANA " */
|
nkeynes@26 | 27 | char maker_id[16]; /* ditto, "SEGA ENTERPRISES" */
|
nkeynes@26 | 28 | char crc[4];
|
nkeynes@26 | 29 | char padding; /* normally ascii space */
|
nkeynes@26 | 30 | char gdrom_id[6];
|
nkeynes@26 | 31 | char disc_no[5];
|
nkeynes@26 | 32 | char regions[8];
|
nkeynes@26 | 33 | char peripherals[8];
|
nkeynes@26 | 34 | char product_id[10];
|
nkeynes@26 | 35 | char product_ver[6];
|
nkeynes@26 | 36 | char product_date[16];
|
nkeynes@26 | 37 | char boot_file[16];
|
nkeynes@26 | 38 | char vendor_id[16];
|
nkeynes@26 | 39 | char product_name[128];
|
nkeynes@26 | 40 | } *dc_bootstrap_head_t;
|
nkeynes@1 | 41 |
|
nkeynes@1 | 42 | static uint32_t compute_crc16( dc_bootstrap_head_t h )
|
nkeynes@1 | 43 | {
|
nkeynes@1 | 44 | /* Note: Algorithm taken from http://mc.pp.se/dc/ip0000.bin.html */
|
nkeynes@1 | 45 | uint32_t i, c, n = 0xffff;
|
nkeynes@1 | 46 | char *data = h->product_id;
|
nkeynes@1 | 47 | for (i = 0; i < 16; i++)
|
nkeynes@1 | 48 | {
|
nkeynes@1 | 49 | n ^= (data[i]<<8);
|
nkeynes@1 | 50 | for (c = 0; c < 8; c++)
|
nkeynes@1 | 51 | if (n & 0x8000)
|
nkeynes@1 | 52 | n = (n << 1) ^ 4129;
|
nkeynes@1 | 53 | else
|
nkeynes@1 | 54 | n = (n << 1);
|
nkeynes@1 | 55 | }
|
nkeynes@1 | 56 | return n & 0xffff;
|
nkeynes@1 | 57 | }
|
nkeynes@1 | 58 |
|
nkeynes@26 | 59 |
|
nkeynes@26 | 60 | static char *dc_peripherals[] = { "Uses WinCE", "Unknown (0x0000002)",
|
nkeynes@736 | 61 | "Unknown (0x0000004)", "Unknown (0x0000008)",
|
nkeynes@736 | 62 | "VGA Box", "Unknown (0x0000020)",
|
nkeynes@736 | 63 | "Unknown (0x0000040)", "Unknown (0x0000080)",
|
nkeynes@736 | 64 | "Other Expansions", "Puru Puru pack",
|
nkeynes@736 | 65 | "Mike", "Memory card",
|
nkeynes@736 | 66 | "Basic controller", "C button",
|
nkeynes@736 | 67 | "D button", "X button",
|
nkeynes@736 | 68 | "Y button", "Z button",
|
nkeynes@736 | 69 | "Expanded direction buttons",
|
nkeynes@736 | 70 | "Analog R trigger", "Analog L trigger",
|
nkeynes@736 | 71 | "Analog horizontal", "Analog vertical",
|
nkeynes@736 | 72 | "Expanded analog horizontal",
|
nkeynes@736 | 73 | "Expanded analog vertical",
|
nkeynes@736 | 74 | "Gun", "Keyboard", "Mouse" };
|
nkeynes@26 | 75 |
|
nkeynes@26 | 76 |
|
nkeynes@26 | 77 | /* Expansion units */
|
nkeynes@26 | 78 | #define DC_PERIPH_WINCE 0x0000001
|
nkeynes@26 | 79 | #define DC_PERIPH_VGABOX 0x0000010
|
nkeynes@26 | 80 | #define DC_PERIPH_OTHER 0x0000100
|
nkeynes@26 | 81 | #define DC_PERIPH_PURUPURU 0x0000200
|
nkeynes@26 | 82 | #define DC_PERIPH_MIKE 0x0000400
|
nkeynes@26 | 83 | #define DC_PERIPH_MEMCARD 0x0000800
|
nkeynes@26 | 84 | /* Basic requirements */
|
nkeynes@26 | 85 | #define DC_PERIPH_BASIC 0x0001000 /* Basic controls - start, a, b, arrows */
|
nkeynes@26 | 86 | #define DC_PERIPH_C_BUTTON 0x0002000
|
nkeynes@26 | 87 | #define DC_PERIPH_D_BUTTON 0x0004000
|
nkeynes@26 | 88 | #define DC_PERIPH_X_BUTTON 0x0008000
|
nkeynes@26 | 89 | #define DC_PERIPH_Y_BUTTON 0x0010000
|
nkeynes@26 | 90 | #define DC_PERIPH_Z_BUTTON 0x0020000
|
nkeynes@26 | 91 | #define DC_PERIPH_EXP_DIR 0x0040000 /* Expanded direction buttons */
|
nkeynes@26 | 92 | #define DC_PERIPH_ANALOG_R 0x0080000 /* Analog R trigger */
|
nkeynes@26 | 93 | #define DC_PERIPH_ANALOG_L 0x0100000 /* Analog L trigger */
|
nkeynes@26 | 94 | #define DC_PERIPH_ANALOG_H 0x0200000 /* Analog horizontal controller */
|
nkeynes@26 | 95 | #define DC_PERIPH_ANALOG_V 0x0400000 /* Analog vertical controller */
|
nkeynes@26 | 96 | #define DC_PERIPH_EXP_AH 0x0800000 /* Expanded analog horizontal (?) */
|
nkeynes@26 | 97 | #define DC_PERIPH_EXP_AV 0x1000000 /* Expanded analog vertical (?) */
|
nkeynes@26 | 98 | /* Optional peripherals */
|
nkeynes@26 | 99 | #define DC_PERIPH_GUN 0x2000000
|
nkeynes@26 | 100 | #define DC_PERIPH_KEYBOARD 0x4000000
|
nkeynes@26 | 101 | #define DC_PERIPH_MOUSE 0x8000000
|
nkeynes@26 | 102 |
|
nkeynes@26 | 103 | /**
|
nkeynes@26 | 104 | * Dump the bootstrap info to the output log for infomational/debugging
|
nkeynes@26 | 105 | * purposes.
|
nkeynes@167 | 106 | * @param detail true to include a ful information dump, false for just
|
nkeynes@167 | 107 | * the facts, maam.
|
nkeynes@26 | 108 | */
|
nkeynes@502 | 109 | void bootstrap_dump( void *data, gboolean detail )
|
nkeynes@1 | 110 | {
|
nkeynes@1 | 111 | struct dc_bootstrap_head *head;
|
nkeynes@1 | 112 | int i, got, periph, crc, hcrc;
|
nkeynes@1 | 113 | char *prot_symbols;
|
nkeynes@1 | 114 | char buf[512];
|
nkeynes@1 | 115 |
|
nkeynes@1 | 116 | /* Dump out the bootstrap metadata table */
|
nkeynes@1 | 117 | head = (struct dc_bootstrap_head *)data;
|
nkeynes@1 | 118 | prot_symbols = ((char *)data) + 0x3700;
|
nkeynes@1 | 119 | memcpy( buf, head->product_name, 128 );
|
nkeynes@1 | 120 | for( i=127; i>0 && buf[i] == ' '; i-- );
|
nkeynes@1 | 121 | buf[i] = '\0';
|
nkeynes@1 | 122 | periph = strtol( head->peripherals, NULL, 16 );
|
nkeynes@167 | 123 | INFO( "Name: %s Author: %-16.16s",
|
nkeynes@1 | 124 | buf, head->vendor_id );
|
nkeynes@1 | 125 | sprintf( buf, "%4.4s", head->crc );
|
nkeynes@1 | 126 | crc = compute_crc16(head);
|
nkeynes@1 | 127 | hcrc = strtol( buf, NULL, 16 );
|
nkeynes@1 | 128 | INFO( " Product ID: %-10.10s Product Ver: %-6.6s Date: %-8.8s",
|
nkeynes@1 | 129 | head->product_id, head->product_ver, head->product_date );
|
nkeynes@167 | 130 | if( detail ) {
|
nkeynes@736 | 131 | INFO( " Header CRC: %04X (Computed %04X)", hcrc, crc );
|
nkeynes@736 | 132 | INFO( " Boot File: %-16.16s", head->boot_file );
|
nkeynes@736 | 133 | INFO( " Disc ID: %-11.11s Regions: %-8.8s Peripherals: %07X",
|
nkeynes@736 | 134 | head->gdrom_id, head->regions, periph );
|
nkeynes@736 | 135 | strcpy( buf, " Supports: " );
|
nkeynes@736 | 136 | got = 0;
|
nkeynes@736 | 137 | for( i=0; i<28; i++ ) {
|
nkeynes@736 | 138 | if( periph & (1<<i) ){
|
nkeynes@736 | 139 | if( got ) strcat( buf, ", " );
|
nkeynes@736 | 140 | strcat( buf, dc_peripherals[i] );
|
nkeynes@736 | 141 | got = 1;
|
nkeynes@736 | 142 | }
|
nkeynes@736 | 143 | if( i == 11 ) i = 23; /* Skip 8-23 */
|
nkeynes@736 | 144 | }
|
nkeynes@736 | 145 | INFO( buf, NULL );
|
nkeynes@736 | 146 | strcpy( buf, " Requires: " );
|
nkeynes@736 | 147 | got = 0;
|
nkeynes@736 | 148 | for( i=12; i<24; i++ ) {
|
nkeynes@736 | 149 | if( periph & (1<<i) ) {
|
nkeynes@736 | 150 | if( got ) strcat( buf, ", " );
|
nkeynes@736 | 151 | strcat( buf, dc_peripherals[i] );
|
nkeynes@736 | 152 | got = 1;
|
nkeynes@736 | 153 | }
|
nkeynes@736 | 154 | }
|
nkeynes@736 | 155 | INFO( buf, NULL );
|
nkeynes@1 | 156 | }
|
nkeynes@1 | 157 | }
|