Search
lxdream.org :: lxdream/src/bootstrap.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/bootstrap.c
changeset 1099:566cdeb157ec
prev1095:a8b798030464
author nkeynes
date Wed Mar 21 14:44:14 2012 +1000 (12 years ago)
permissions -rw-r--r--
last change Dreamcast.stop() on pause, get rid of unnecessary onAppPause()/onAppResume() methods
Set the run menu item to the right icon/state on pause as well.
view annotate diff log raw
     1 /**
     2  * $Id$
     3  *
     4  * CD Bootstrap header parsing. Mostly for informational purposes.
     5  *
     6  * Copyright (c) 2005 Nathan Keynes.
     7  *
     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.
    12  *
    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.
    17  */
    19 #include "dream.h"
    20 #include "bootstrap.h"
    22 static uint32_t compute_crc16( dc_bootstrap_head_t h )
    23 {
    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++)
    28     {
    29         n ^= (data[i]<<8);
    30         for (c = 0; c < 8; c++)
    31             if (n & 0x8000)
    32                 n = (n << 1) ^ 4129;
    33             else
    34                 n = (n << 1);
    35     }
    36     return n & 0xffff;
    37 }
    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" };
    57 /* Expansion units */
    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
    83 /**
    84  * Dump the bootstrap info to the output log for infomational/debugging
    85  * purposes.
    86  * @param detail true to include a ful information dump, false for just
    87  *  the facts, maam.
    88  */
    89 void bootstrap_dump( void *data, gboolean detail )
    90 {
    91     struct dc_bootstrap_head *head;
    92     int i, got, periph, crc, hcrc;
    93     char *prot_symbols;
    94     char buf[512];
    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-- );
   101     buf[i] = '\0';
   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 );
   110     if( detail ) {
   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: " );
   116         got = 0;
   117         for( i=0; i<28; i++ ) {
   118             if( periph & (1<<i) ){
   119                 if( got ) strcat( buf, ", " );
   120                 strcat( buf, dc_peripherals[i] );
   121                 got = 1;
   122             }
   123             if( i == 11 ) i = 23; /* Skip 8-23 */
   124         }
   125         INFO( buf, NULL );
   126         strcpy( buf, "     Requires: " );
   127         got = 0;
   128         for( i=12; i<24; i++ ) {
   129             if( periph & (1<<i) ) {
   130                 if( got ) strcat( buf, ", " );
   131                 strcat( buf, dc_peripherals[i] );
   132                 got = 1;
   133             }
   134         }
   135         INFO( buf, NULL );
   136     }
   137 }
   139 /* Scramble/unscramble, based on Marcus Comstedt's algorithm. */
   141 typedef uint16_t randseed;
   143 #define MAXBLOCK (2048*1024)
   144 #define CHUNKSIZE 32
   145 #define NEXT(seed)  (((seed = (seed*2109+9273)&0x7fff) + 0xC000) & 0xFFFF)
   147 void bootprogram_scramble( unsigned char *dest, unsigned char *src, size_t length )
   148 {
   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
   159             }
   160             for( unsigned i = nchunks-1; i != (unsigned)-1; --i ) {
   161                 unsigned j = (NEXT(seed) * i)>>16;
   162                 unsigned tmp = table[i];
   163                 table[i] = table[j];
   164                 table[j] = tmp;
   165                 memcpy( d, s + CHUNKSIZE*table[i], CHUNKSIZE );
   166                 d+= CHUNKSIZE;
   167             }
   168             length -= blocksize;
   169             s += blocksize;
   170         }
   171     }
   172     if( length ) {
   173         memcpy( d, s, length );
   174     }
   175 }
   177 void bootprogram_unscramble( unsigned char *dest, unsigned char *src, size_t length )
   178 {
   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
   189             }
   190             for( unsigned i = nchunks-1; i != (unsigned)-1; --i ) {
   191                 unsigned j = (NEXT(seed) * i)>>16;
   192                 unsigned tmp = table[i];
   193                 table[i] = table[j];
   194                 table[j] = tmp;
   195                 memcpy( d + CHUNKSIZE*table[i], s, CHUNKSIZE );
   196                 s+= CHUNKSIZE;
   197             }
   198             length -= blocksize;
   199             d += blocksize;
   200         }
   201     }
   202     if( length ) {
   203         memcpy( d, s, length );
   204     }
   205 }
.