nkeynes@26: /** nkeynes@35: * $Id: bootstrap.c,v 1.5 2005-12-26 03:54:52 nkeynes Exp $ nkeynes@26: * nkeynes@26: * CD Bootstrap header parsing. Mostly for informational purposes. nkeynes@26: * nkeynes@26: * Copyright (c) 2005 Nathan Keynes. nkeynes@26: * nkeynes@26: * This program is free software; you can redistribute it and/or modify nkeynes@26: * it under the terms of the GNU General Public License as published by nkeynes@26: * the Free Software Foundation; either version 2 of the License, or nkeynes@26: * (at your option) any later version. nkeynes@26: * nkeynes@26: * This program is distributed in the hope that it will be useful, nkeynes@26: * but WITHOUT ANY WARRANTY; without even the implied warranty of nkeynes@26: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the nkeynes@26: * GNU General Public License for more details. nkeynes@26: */ nkeynes@1: nkeynes@26: #include "dream.h" nkeynes@26: #include "bootstrap.h" nkeynes@26: nkeynes@26: /** nkeynes@26: * Bootstrap header structure nkeynes@26: */ nkeynes@26: typedef struct dc_bootstrap_head { nkeynes@26: char hardware_id[16]; /* must be "SEGA SEGAKATANA " */ nkeynes@26: char maker_id[16]; /* ditto, "SEGA ENTERPRISES" */ nkeynes@26: char crc[4]; nkeynes@26: char padding; /* normally ascii space */ nkeynes@26: char gdrom_id[6]; nkeynes@26: char disc_no[5]; nkeynes@26: char regions[8]; nkeynes@26: char peripherals[8]; nkeynes@26: char product_id[10]; nkeynes@26: char product_ver[6]; nkeynes@26: char product_date[16]; nkeynes@26: char boot_file[16]; nkeynes@26: char vendor_id[16]; nkeynes@26: char product_name[128]; nkeynes@26: } *dc_bootstrap_head_t; nkeynes@1: nkeynes@1: static uint32_t compute_crc16( dc_bootstrap_head_t h ) nkeynes@1: { nkeynes@1: /* Note: Algorithm taken from http://mc.pp.se/dc/ip0000.bin.html */ nkeynes@1: uint32_t i, c, n = 0xffff; nkeynes@1: char *data = h->product_id; nkeynes@1: for (i = 0; i < 16; i++) nkeynes@1: { nkeynes@1: n ^= (data[i]<<8); nkeynes@1: for (c = 0; c < 8; c++) nkeynes@1: if (n & 0x8000) nkeynes@1: n = (n << 1) ^ 4129; nkeynes@1: else nkeynes@1: n = (n << 1); nkeynes@1: } nkeynes@1: return n & 0xffff; nkeynes@1: } nkeynes@1: nkeynes@26: nkeynes@26: static char *dc_peripherals[] = { "Uses WinCE", "Unknown (0x0000002)", nkeynes@26: "Unknown (0x0000004)", "Unknown (0x0000008)", nkeynes@26: "VGA Box", "Unknown (0x0000020)", nkeynes@26: "Unknown (0x0000040)", "Unknown (0x0000080)", nkeynes@26: "Other Expansions", "Puru Puru pack", nkeynes@26: "Mike", "Memory card", nkeynes@26: "Basic controller", "C button", nkeynes@26: "D button", "X button", nkeynes@26: "Y button", "Z button", nkeynes@26: "Expanded direction buttons", nkeynes@26: "Analog R trigger", "Analog L trigger", nkeynes@26: "Analog horizontal", "Analog vertical", nkeynes@26: "Expanded analog horizontal", nkeynes@26: "Expanded analog vertical", nkeynes@26: "Gun", "Keyboard", "Mouse" }; nkeynes@26: nkeynes@26: nkeynes@26: /* Expansion units */ nkeynes@26: #define DC_PERIPH_WINCE 0x0000001 nkeynes@26: #define DC_PERIPH_VGABOX 0x0000010 nkeynes@26: #define DC_PERIPH_OTHER 0x0000100 nkeynes@26: #define DC_PERIPH_PURUPURU 0x0000200 nkeynes@26: #define DC_PERIPH_MIKE 0x0000400 nkeynes@26: #define DC_PERIPH_MEMCARD 0x0000800 nkeynes@26: /* Basic requirements */ nkeynes@26: #define DC_PERIPH_BASIC 0x0001000 /* Basic controls - start, a, b, arrows */ nkeynes@26: #define DC_PERIPH_C_BUTTON 0x0002000 nkeynes@26: #define DC_PERIPH_D_BUTTON 0x0004000 nkeynes@26: #define DC_PERIPH_X_BUTTON 0x0008000 nkeynes@26: #define DC_PERIPH_Y_BUTTON 0x0010000 nkeynes@26: #define DC_PERIPH_Z_BUTTON 0x0020000 nkeynes@26: #define DC_PERIPH_EXP_DIR 0x0040000 /* Expanded direction buttons */ nkeynes@26: #define DC_PERIPH_ANALOG_R 0x0080000 /* Analog R trigger */ nkeynes@26: #define DC_PERIPH_ANALOG_L 0x0100000 /* Analog L trigger */ nkeynes@26: #define DC_PERIPH_ANALOG_H 0x0200000 /* Analog horizontal controller */ nkeynes@26: #define DC_PERIPH_ANALOG_V 0x0400000 /* Analog vertical controller */ nkeynes@26: #define DC_PERIPH_EXP_AH 0x0800000 /* Expanded analog horizontal (?) */ nkeynes@26: #define DC_PERIPH_EXP_AV 0x1000000 /* Expanded analog vertical (?) */ nkeynes@26: /* Optional peripherals */ nkeynes@26: #define DC_PERIPH_GUN 0x2000000 nkeynes@26: #define DC_PERIPH_KEYBOARD 0x4000000 nkeynes@26: #define DC_PERIPH_MOUSE 0x8000000 nkeynes@26: nkeynes@26: /** nkeynes@26: * Dump the bootstrap info to the output log for infomational/debugging nkeynes@26: * purposes. nkeynes@26: */ nkeynes@26: void bootstrap_dump( char *data ) nkeynes@1: { nkeynes@1: struct dc_bootstrap_head *head; nkeynes@1: int i, got, periph, crc, hcrc; nkeynes@1: char *prot_symbols; nkeynes@1: char buf[512]; nkeynes@1: nkeynes@1: /* Dump out the bootstrap metadata table */ nkeynes@1: head = (struct dc_bootstrap_head *)data; nkeynes@1: prot_symbols = ((char *)data) + 0x3700; nkeynes@1: memcpy( buf, head->product_name, 128 ); nkeynes@1: for( i=127; i>0 && buf[i] == ' '; i-- ); nkeynes@1: buf[i] = '\0'; nkeynes@1: periph = strtol( head->peripherals, NULL, 16 ); nkeynes@26: INFO( "Bootstrap Name: %s Author: %-16.16s", nkeynes@1: buf, head->vendor_id ); nkeynes@1: sprintf( buf, "%4.4s", head->crc ); nkeynes@1: crc = compute_crc16(head); nkeynes@1: hcrc = strtol( buf, NULL, 16 ); nkeynes@35: emit( NULL, crc == hcrc ? EMIT_INFO : EMIT_WARN, "File", nkeynes@1: " Header CRC: %04X (Computed %04X)", hcrc, crc ); nkeynes@1: INFO( " Boot File: %-16.16s", head->boot_file ); nkeynes@1: INFO( " Product ID: %-10.10s Product Ver: %-6.6s Date: %-8.8s", nkeynes@1: head->product_id, head->product_ver, head->product_date ); nkeynes@1: INFO( " Disc ID: %-11.11s Regions: %-8.8s Peripherals: %07X", nkeynes@1: head->gdrom_id, head->regions, periph ); nkeynes@1: strcpy( buf, " Supports: " ); nkeynes@1: got = 0; nkeynes@1: for( i=0; i<28; i++ ) { nkeynes@1: if( periph & (1<