0) ? $datalen : (strlen($vms)-$start); $data = substr($vms, $start, $length); // returns the data string return $data; } //////////////////////////////////////////////////////////////////////// // Function: getDataLen() // // Description: get the size in bytes of actual file data following // // header, icon(s) and graphic eyecatch in VMS files // // Parameters: // // $vms: string containing the VMS file // // Return Values: an int corresponding to the data length // //////////////////////////////////////////////////////////////////////// function getDataLen($vms) { // long int (little endian) representing the number of bytes // of actual file data following header icon(s) and graphic eyecatch $datalen = ord($vms[72]) + (ord($vms[73]) * 256) + (ord($vms[74]) * 256 * 256) + (ord($vms[75]) * 256 * 256 * 256); // returns the data length return $data_len; } //////////////////////////////////////////////////////////////////////// // Function: vmiDecode() // // Description: decode the header part of the value returned by the // // vm input of a form into an array used to create a VMI // // file // // Parameters: // // $header: string containing the header part of the vmfile field's // // value sent by the form // // Return Values: an array containing variables used to create a VMI // // file // // VMI array keys: // // 'filename': 12 chars string containing the name of the vm file // // 'fs': int corresponding to the size of the VMS file in bytes // // 'bl': int corresponding to the size of the VMS file in blocks // // 'tp': boolean corresponding to the type of file: 0=DATA, 1=GAME // // 'fl': boolean always 0 unknown (maybe copy protection) // // 'of': boolean always 0 unknown (maybe copy protection) // // 'tm': 15 chars string containing the creation date and time of the // // VM file using YmdHisw format: // // Y: full numeric representation of the year, 4 digits // // m: numeric representation of the month, with leading zeros // // d: day of the month, 2 digits with leading zeros // // H: 24-hour format of the hour with leading zeros // // i: minutes with leading zeros // // s: seconds, with leading zeros // // w: numeric representation of the day of the week (0=sunday) // //////////////////////////////////////////////////////////////////////// function vmiDecode($header) { // creates name=value pairs by splitting the header by each '&' $pairs = explode('&', $header); // creates array keys and values by splitting the pairs by each '=' foreach ($pairs as $pair) { list($key, $value) = split('=', $pair, 2); $vmiarr[$key] = urldecode($value); } // returns the VMI array return $vmiarr; } //////////////////////////////////////////////////////////////////////// // Function: vmsDecode() // // Description: decode the body part of the value returned by the // // vm input of a form into an array containing infos // // about the VMS file // // Parameters: // // $body: string containing the body part of the vmfile field's // // value sent by the form // // Return Values: an array containing infos about the VMS file // // VMS array keys: // // 'vmdesc': 16 chars string containing the description shown in the // // VMU file manager // // 'bootdesc': 32 chars string containing the description shown in // // the DC boot file manager // // 'appname': 16 chars string containing the name of the application // // that created the file // // 'icons_nb': [1-3] int corresponding to the number of icons // // (>1 for animated icons) // // 'icons_anim_spd': int corresponding to the icon animation speed // // 'eyec_type': [0-3] int corresponding to the graphic eyecatch type // // (0=none) // // 'crc': int corresponding to the CRC checksum // // (ignored for GAME files) // // 'data_len': int corresponding to the size in bytes of actual file // // data following header, icon(s) and graphic eyecatch // // 'icons_pal': 32 chars string corresponding to the icon's palette // // in asm // // 'icons_bit': (512*'icons_nb') chars string containing the icon(s) // // bitmap(s) in asm // // 'eyec': string containing the graphic eyecatch palette and bitmap // // in asm. The number of chars depends on 'eyec_type' // // (type 0: 0, type 1: 8064, type 2: 4544, type 3: 2048) // // 'data': 'data_len' chars string containing the actual file data // // following header, icon(s) and graphic eyecatch // //////////////////////////////////////////////////////////////////////// function vmsDecode($body) { // gets the vms content string $vms = getVms($body); // gets the vm description string $vmsarr['vmdesc'] = substr($vms, 0, 16); // gets the boot description string $vmsarr['bootdesc'] = substr($vms, 16, 32); // gets the application name string $vmsarr['appname'] = substr($vms, 32, 16); // gets the icons number short little endian int $vmsarr['icons_nb'] = ord($vms[64]) + (ord($vms[65]) * 256); // gets the icons animation speed short little endian int $vmsarr['icons_anim_spd'] = ord($vms[66]) + (ord($vms[67]) * 256); // gets the graphic eyecatch type short little endian int $vmsarr['eyec_type'] = ord($vms[68]) + (ord($vms[69]) * 256); // gets the CRC value short little endian int $vmsarr['crc'] = ord($vms[70]) + (ord($vms[71]) * 256); // gets the data length long little endian int $vmsarr['data_len'] = getDataLen($vms); // gets the icon palette string $vmsarr['icons_pal'] = ''; for ($i=96; $i<128; $i++) $vmsarr['icons_pal'] .= $vms[$i]; // gets the icon bitmaps string $icons_bit_start = 128; $icons_bit_end = 128; $vmsarr['icons_bit'] = ''; for ($i=0; $i<$vmsarr['icons_nb']; $i++) { $icons_bit_end = $icons_bit_start + 512; for ($j=$icons_bit_start; $j<$icons_bit_end; $j++) $vmsarr['icons_bit'] .= $vms[$j]; $icons_bit_start = $icons_bit_end; } // gets the graphic eyecatch string $eyec_len = array(0, 8064, 4544, 2048); $eyec_end = $icons_bit_end + $eyec_len[$vmsarr[$eyec_type]]; $vmsarr['eyec'] = ''; for ($i=$icons_bit_end; $i<$eyec_end; $i++) $vmsarr['eyec'] .= $vms[$i]; // gets the data string $length = ($vmsarr['data_len'] > 0) ? $vmsarr['data_len'] : (strlen($vms)-$eyec_end); $vmsarr['data'] = substr($vms, $eyec_end, $length); // returns the VMS array return $vmsarr; } //////////////////////////////////////////////////////////////////////// // // // 3) Functions used to create files content // // // //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// // Function: makeVmi() // // Description: creates a string containing the VMI file // // Parameters: // // $title: [0-32] chars string containing the description of the file // // shown in the download window // // $creator: [0-32] chars string containing the author of the file // // shown in the download window // // $resource: [0-8] chars string containing the vms file name without // // the extension // // $tm: null, '' or 15 chars string containing the creation date and // // time of the VM file using YmdHisw format: // // Y: full numeric representation of the year, 4 digits // // m: numeric representation of the month, with leading zeros // // d: day of the month, 2 digits with leading zeros // // H: 24-hour format of the hour with leading zeros // // i: minutes with leading zeros // // s: seconds, with leading zeros // // w: numeric representation of the day of the week (0=sunday) // // (if null or '' the current date and time will be used) // // $filename: [0-12] chars string containing the name of the vm file // // $tp: boolean corresponding to the type of file: 0=DATA, 1=GAME // // $fs: int corresponding to the size of the VMS file in bytes // // Return Values: 108 chars string containing the VMI file // //////////////////////////////////////////////////////////////////////// function makeVmi($title, $creator, $tm, $resource, $filename, $tp, $fs) { $vmi = ''; // SEGA checksum $cs = "SEGA"; for ($i=0; $i<4; $i++) $vmi .= chr(ord($cs[$i]) & ord($resource[$i])); // title string, 32 bytes padded with spaces (0x20) for ($i=0; $i<32; $i++) $vmi .= (ord($title[$i]) != 0) ? $title[$i] : " "; // creator string, 32 bytes padded with spaces (0x20) for ($i=0; $i<32; $i++) $vmi .= (ord($creator[$i]) != 0) ? $creator[$i] : " "; // creation date and time string, 15 bytes: // if $tm is null or '' it will use the current date and time if (!$tm || $tm=='') $tm = date("YmdHisw", time()); $y = substr($tm, 0, 4); $vmi .= chr($y % 256).chr($y / 256); // year (0000-9999) $vmi .= chr(substr($tm, 4, 2)); // month (01-12) $vmi .= chr(substr($tm, 6, 2)); // monthday (01-31) $vmi .= chr(substr($tm, 8, 2)); // hours (00-23) $vmi .= chr(substr($tm, 10, 2)); // minutes (00-59) $vmi .= chr(substr($tm, 12, 2)); // seconds (00-59) $vmi .= chr(substr($tm, 14, 1)); // weekday (0-7, 0=sun, 7=sat) // version, set to 1.5 $vmi .= chr(50).chr(1); // number of files, set to 1 $vmi .= chr(1).chr(0); // resource name corresponding to the vms file name without extension // 8 bytes padded with NUL (0x00) for ($i=0; $i<8; $i++) $vmi .= (ord($resource[$i]) != 0) ? $resource[$i] : chr(0); // vm file name string used by the Dreamcast application // 12 bytes padded with space (0x20) for ($i=0; $i<12; $i++) $vmi .= (ord($filename[$i]) != 0) ? $filename[$i] : chr(32); // file type, 0=DATA, 1=GAME // the copy protection is disabled $vmi .= chr(BinDec($tp."0")).chr(0); // reserved $vmi .= chr(0).chr(0); // vms file size, long int (little endian) /* $len = $fs; $size[3] = floor($len / (256 * 256 * 256)); $len -= $size[3] * 256 * 256 * 256; $size[2] = floor($len / (256 * 256)); $len -= $size[2] * 256 * 256; $size[1] = floor($len / 256); $len -= $size[1] * 256; $size[0] = $len; for ($i=0; $i<4; $i++) $vmi .= chr($size[$i]); */ $vmi .= doWord($fs, 4, 'le'); // returns the vmi string return $vmi; } //////////////////////////////////////////////////////////////////////// // Function: makeVms() // // Description: creates a string containing the VMS file // // Parameters: // // $vmdesc: [0-16] chars string containing the description shown in // // the VMU file manager // // $bootdesc: [0-32] chars string containing the description shown in // // the DC boot file manager // // $appname': [0-16] chars string containing the name of the // // application that created the file // // $data: string containing the actual file data following header, // // icon(s) and graphic eyecatch // // Return Values: a string containing the VMS file // // Todo: accept $icons, $icons_anim_speed, $eyec_type and // // $eyec arguments // //////////////////////////////////////////////////////////////////////// function makeVms($vmdesc, $bootdesc, $appname, $data) { $vms = ''; // vm description string, 16 bytes padded with spaces (0x20) for ($i=0; $i<16; $i++) $vms .= (ord($vmdesc[$i]) != 0) ? $vmdesc[$i] : " "; // boot description string, 32 bytes padded with spaces (0x20) for ($i=0; $i<32; $i++) $vms .= (ord($bootdesc[$i]) != 0) ? $bootdesc[$i] : " "; // application name string, 16 bytes padded with spaces (0x20) for ($i=0; $i<16; $i++) $vms .= (ord($appname[$i]) != 0) ? $appname[$i] : " "; // inserts NUL chars where the icon must reside for ($i=64; $i<640; $i++) $vms .= chr(0); // data string $vms .= $data; // inserts data length infos in the vms file content string $len = strlen($data); $size[3] = floor($len / (256 * 256 * 256)); $len -= $size[3] * 256 * 256 * 256; $size[2] = floor($len / (256 * 256)); $len -= $size[2] * 256 * 256; $size[1] = floor($len / 256); $len -= $size[1] * 256; $size[0] = $len; for ($i=0; $i<4; $i++) $vms[72+$i] = chr($size[$i]); // calculates new CRC $crc = calcCRC($vms, strlen($vms)); $vms[70] = chr($crc % 256); $vms[71] = chr($crc / 256); // padds with NUL chars (0x00) until the file size // in bytes is a multiple of 512 while ((strlen($vms)%512) != 0) $vms .= chr(0); // returns the VMS string return $vms; } //////////////////////////////////////////////////////////////////////// // // // 4) Functions used to create specific parts of the files content // // // //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// // Function: calcCRC() // // Description: calculates the CRC to insert in a VMS file // // Parameters: // // $vms: string containing the VMS file // // $size: int corresponding to the size in bytes of the VMS file // // without padding // // Return Values: an int corresponding to the CRC value or -1 if an // // error occurs // //////////////////////////////////////////////////////////////////////// function calcCRC($vms, $size) { if ($size > strlen($vms)) return -1; $n = 0; for ($i=0; $i<$size; $i++) { // the actual value of the CRC field is ignored $vms[$i] = ($i==70 || $i==71) ? chr(0) : $vms[$i]; $n ^= (ord($vms[$i]) << 8); for ($c=0; $c<8; $c++) $n = ($n & 0x8000) ? ($n << 1) ^ 4129 : ($n << 1); } // returns the CRC as a short little endian int return $n & 0xffff; } //////////////////////////////////////////////////////////////////////// // Function: pngToAsm() // // Requirements: image library GD // // Description: converts a png image to an asm string containing the // // icon to insert in a VMS file // // Note: only there for backward compability, use GDToAsm() instead // // Parameters: // // $png: string containing the path of the png image // // Return Values: a string containing the asm icon // //////////////////////////////////////////////////////////////////////// function pngtoasm($png) { // creates a new image object with GD from the png image $img = imagecreatefrompng($png); // creates the asm icon GDToAsm($img); } //////////////////////////////////////////////////////////////////////// // Function: GDToAsm() // // Requirements: image library GD // // Description: creates an asm string containing the icon to insert // // in a VMS file from a GD image object // // Parameters: // // $img: GD image object // // Return Values: a string containing the asm icon // //////////////////////////////////////////////////////////////////////// function GDtoasm($img) { // loops the 32 pixels rows of the image for ($y=0; $y<32; $y++) { // loops the 32 pixels cols of the image for ($x=0; $x<32; $x++) { // gets colour index of each pixel $rgb = imagecolorat($img, $x, $y); // converts the colour index to 4-bit binary and // assigns it to a new nybble for the bitmap $colindex = DecBin($rgb); while (strlen($colindex) < 4) $colindex = "0$colindex"; $nyb[sizeof($nyb)] = $colindex; // gets the RGB values of the colour from the palette $col = imagecolorsforindex($img, $rgb); // alpha component is ignored and set to 15 (0x0F) // for maximum opacity $a = '1111'; // gets the red component and converts it to 4-bit binary $r = DecBin($col['red'] / 17); while (strlen($r) < 4) $r = "0$r"; // gets the green component and converts it to 4-bit binary $g = DecBin($col['green'] / 17); while (strlen($g) < 4) $g = "0$g"; // gets the blue component and converts it to 4-bit binary $b = DecBin($col['blue'] / 17); while (strlen($b) < 4) $b = "0$b"; // if the palette entry of the icon is not yet used assigns // to it the 2 bytes corresponding to the binary values of // the ARGB components if (!$pal[$rgb]) $pal[$rgb] = chr(BinDec("$g$b")).chr(BinDec("$a$r")); } } // destroys the image object created by GD //imagedestroy($img); $asm = ''; // creates the assembly palette from the $pal array // 1 colour is composed of 2 bytes for ($i=0; $i<16; $i++) $asm .= ($pal[$i]) ? $pal[$i] : chr(0).chr(0); // creates the assembly bitmap from the $nyb array // 2 nybbles correspond to 1 byte for ($i=0; $i<1024; $i+=2) $asm .= chr(BinDec($nyb[$i].$nyb[$i+1])); // returns a string containing the assembly icon // composed of the palette and the bitmap return $asm; } //////////////////////////////////////////////////////////////////////// // Function: lcdToGD() // // Requirements: image library GD // // Description: creates a GD image object from the content of a LCD // // icon // // Parameters: // // $lcdcontent: string containing a LCD file // // $framenum: [1-255] int corresponding to the frame's rank for // // animated LCD icons // // Return Values: an image object for GD // //////////////////////////////////////////////////////////////////////// function lcdtoGD($lcdcontent, $framenum) { // creates the GD image object $im = imagecreate(48, 32); // define the 2 colors of the image $green = imagecolorallocate($im, 143, 207, 143); $black = imagecolorallocate($im, 0, 0, 0); // get the icon frames number $frames = ord($lcdcontent[14]) + (ord($lcdcontent[15]) * 256); if ($frames < 1) $frames = 1; // if $framenum is out of the anim limits or is not precised // the default frame used will be the first frame $argsnum = func_num_args(); if ($framenum<0 || $framenum>($frames-1) || $argsnum<2) $framenum = 0; // get the bitmap start offset $start = 16 + (4 * $frames) + ($framenum * 1536); // read each pixel of the specific frame for ($y=0; $y<32; $y++) { for ($x=0; $x<48; $x++) { $n = ($y * 48) + $x + $start; $pxl = ord($lcdcontent[$n]); // set the image pixel color // depending of the icon pixel value $color = ($pxl == 8) ? $black : $green; imagesetpixel($im, $x, $y, $color); } } // returns the GD image object return $im; } //////////////////////////////////////////////////////////////////////// // Function: doWord() // // Description: creates a string from an int // // Parameters: // // $int: int corresponding to the value to convert // // $len: int corresponding to the size in bytes of the string to // // create // // $order: 2 chars string corresponding to the order of the string: // // 'be': the string is made using big endian order // // 'le': the string is made using little endian order // // anything but 'be' will be read as 'le' // // Return Values: a $len chars string // //////////////////////////////////////////////////////////////////////// function doWord($int, $len, $order) { $word = ''; while ($int >= 256) { $n = $int % 256; $word = chr($n).$word; $int = floor($int / 256); } $word = chr($int).$word; if (strlen($word) > $len) $word = substr($word, strlen($word)-$len); while (strlen($word) < $len) $word = chr(0).$word; if ($order != 'be') $word = strrev($word); return $word; } //////////////////////////////////////////////////////////////////////// // Function: dciToVm() // // Description: creates an array containing an array used to create // // VMI files and a string containing the VMS files from // // the content of a DCI file (Nexus cards format) // // Parameters: // // $dci: string containing the DCI file // // Return Values: -1 if an error occurs or an array composed of // // 2 elements as follows: // // array[0]: an array used to create VMI files similar to the one // // returned by the function vmiDecode() // // array[1]: a string containing the VMS file // //////////////////////////////////////////////////////////////////////// function dciToVm($dci) { $header = substr($dci, 0, 32); $body = substr($dci, 32); $vmiarray['tp'] = (ord($header[0]) == 204) ? '1' : '0'; $vmiarray['fl'] = '0'; $vmiarray['of'] = '0'; $vmiarray['filename'] = substr($header, 4, 12); for ($i=16; $i<16+7; $i++) { $tm = DecHex(ord($header[$i])); $vmiarray['tm'] .= ($tm < 10) ? '0'.$tm : $tm; } $tm = DecHex(ord($header[23])) + 1; if ($tm > 6) $tm = 0; $vmiarray['tm'] .= $tm; $vmiarray['bl'] = ord($header[24]) + (ord($header[25]) * 256); $vmiarray['fs'] = $vmiarray['bl'] * 512; $vms = ''; for ($i=0; $i=0; $j--) $vms .= $body[$i+$j]; if ($vmiarray['fs'] != strlen($vms)) return -1; return array($vmiarray, $vms); } //////////////////////////////////////////////////////////////////////// // Function: vmToDci() // // Description: creates a string containing the DCI file from VMI and // // VMS files contents // // Parameters: // // $vmi: string containing the VMI file // // $vms: string containing the VMS file // // Return Values: a string containing the DCI file or -1 if an error // // occurs // //////////////////////////////////////////////////////////////////////// function vmToDci($vmi, $vms) { $dci = ''; //TYPE $mode = DecBin(ord($vmi[100])); $type = $mode[strlen($mode)-2]; if (chr($type) == chr(0)) $dci .= chr(51); elseif (chr($type) == chr(1)) $dci .= chr(204); else $dci .= chr(0); //COPY $dci .= chr(0); //1ST BLOCK LOCATION $dci .= chr(0).chr(0); //FILENAME for ($i=88; $i<100; $i++) $dci .= $vmi[$i]; //CREATION DATE //YEAR $y = ord($vmi[68]) + (ord($vmi[69]) * 256); while (strlen($y) < 4) $y = chr(48).$y; $dci .= chr(HexDec(substr($y,0,2))).chr(HexDec(substr($y,2,2))); //MONTH $dci .= chr(HexDec(ord($vmi[70]))); //DAY $dci .= chr(HexDec(ord($vmi[71]))); //HOURS $dci .= chr(HexDec(ord($vmi[72]))); //MINS $dci .= chr(HexDec(ord($vmi[73]))); //SECS $dci .= chr(HexDec(ord($vmi[74]))); //WEEKDAY $wd = chr(HexDec(ord($vmi[75]))) - 1; if ($wd < 0) $wd = 6; $dci .= $wd; //SIZE IN BLOCKS $fs = ord($vmi[104]) + (ord($vmi[105]) * 256) + (ord($vmi[106]) * 256 * 256) + (ord($vmi[107]) * 256 * 256 * 256); if ($fs != strlen($vms)) return -1; $dci .= chr($fs / 512).chr(0); //HEADER OFFSET $dci .= chr($type).chr(0); //UNUSED $dci .= chr(0).chr(0).chr(0).chr(0); //BODY if (strlen($dci) != 32) return -1; for ($i=0; $i=0; $j--) $dci .= $vms[$i + $j]; if (strlen($dci) != 32 + $fs) return -1; return $dci; } //////////////////////////////////////////////////////////////////////// // // // 5) Functions used to modify files content // // // //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// // Function: insertIcon() // // Description: insert a string corresponding to the icon's palette // // and bitmap in asm into a VMS file's header // // Parameters: // // $asm: string containing the icon palette and bitmap in asm // // $vms: string containing the VMS file // // $type: [0-2] int corresponding to the type of VM file // // type 0: DATA // // type 1: GAME // // type 2: ICONDATA // // Return Values: a string containing the modified VMS file // // Todo: inserting instead of replacing in the case of several // // bitmaps // //////////////////////////////////////////////////////////////////////// function insertIcon($asm, $vms, $type) { // separates the assembly icon into palette and bitmap(s) $icons_pal = substr($asm, 0, 32); $icons_bit = substr($asm, 32); // calculates icons number $icons_nb = strlen($icons_bit) / 512; // for DATA files the icon starts at offset 0x60 if ($type == 0) $pal_start=96; // for GAME files the icon starts at offset 0x260 elseif ($type == 1) $pal_start=608; // for ICONDATA files the icon starts at offset 0xA0 else $pal_start=160; $bit_start = $pal_start + 32; // sets vms header infos for a DATA file if ($type == 0) { $vms[64] = chr($icons_nb); // number of icons $vms[65] = chr(0); $vms[66] = chr(1); // animation speed $vms[67] = chr(0); // sets vms header infos for a GAME file } elseif ($type == 1) { $vms[576] = chr($icons_nb); // number of icons $vms[577] = chr(0); $vms[578] = chr(1); // animation speed $vms[579] = chr(0); // sets vms header infos for an ICONDATA file } elseif ($type == 2) { $vms[20] = chr(160); // offset of colour icon } // replaces the bytes of the icon palette // in the vms file content string for ($i=$pal_start; $i<$bit_start; $i++) $vms[$i] = $asm[$i-$pal_start]; // replaces the bytes of the icon bitmaps // in the vms file content string for ($i=0; $i<$icons_nb; $i++) { for ($i=$bit_start; $i<$bit_start+512; $i++) $vms[$i] = $asm[$i-($bit_start-32)]; $bit_start += 512; } // calculates new CRC $crc = calcCRC($vms, getDataLen($vms)); $vms[70] = chr($crc % 256); $vms[71] = chr($crc / 256); // returns the string corresponding // to the modified vms file content return $vms; } //////////////////////////////////////////////////////////////////////// // // // 6) Functions used to inspect files content // // // //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// // Function: iconExtract() // // Description: creates an array used to create an image from the // // content of a VMS file // // Parameters: // // $vms: string containing the VMS file // // $type: [0-2] int corresponding to the type of VM file // // type 0: DATA // // type 1: GAME // // type 2: ICONDATA // // $frame: for DATA or GAME file: // // [0-2] int corresponding to the index of the bitmap to // // extract, 0 is the first bitmap // // for ICONDATA file: // // boolean: 0 for monochrome or 1 for 16 colours (if exists) // // Return Values: an array containing 2 elements as follow: // // array[0]: array containing the 16 ARGB components of the palette, // // each entry is an array composed of the following keys: // // 'alpha': alpha component of the palette entry // // 'red': red component of the palette entry // // 'green': green component of the palette entry // // 'blue': blue component of the palette entry // // array[1]: GD image object containing the extracted frame // //////////////////////////////////////////////////////////////////////// function iconExtract($vms, $type, $frame) { // used for backward compatibility if ($type == 'data') $type = 0; elseif ($type == 'game') $type = 1; elseif ($type == 'icon') $type = 2; // the vms file contains a save if ($type == 0) { $pal_pos = 96; $bit_pos = 128 + ($frame * 512); // the vms file contains a mini-game } elseif ($type == 1) { $pal_pos = 512 + 96; $bit_pos = 512 + 128 + ($frame * 512); // the vms file contains a vm icon } elseif ($type == 2) { $pal_pos = ord($vms[20]) + (ord($vms[21]) * 256) + (ord($vms[22]) * 256 * 256) + (ord($vms[23]) * 256 * 256 * 256); $bit_pos = $pal_pos + 32; } // creates a new 32x32 image object with GD $im = ImageCreate(32, 32); // icon for ICONDATA file in monochrome mode if ($type==2 && ($frame==0 || $pal_pos==0)) { $start = ord($vms[16]) + (ord($vms[17]) * 256) + (ord($vms[18]) * 256 * 256) + (ord($vms[19]) * 256 * 256 * 256); $palette[0] = array('alpha' => 255, 'red' => 255, 'green' => 255, 'blue' => 255); for ($i=1; $i<16; $i++) $palette[$i] = array('alpha' => 255, 'red' => 0, 'green' => 0, 'blue' => 0); $off = imagecolorallocate($im, $palette[0]['red'], $palette[0]['green'], $palette[0]['blue']); $on = imagecolorallocate($im, $palette[1]['red'], $palette[1]['green'], $palette[1]['blue']); for ($i=0; $i<128; $i++) { $bin = DecBin(ord($vms[$start+$i])); while (strlen($bin) < 8) $bin = '0'.$bin; for ($j=0; $j<8; $j++) { $n = ($i * 8) + $j; $x = $n % 32; $y = intval($n / 32); $col = ($bin[$j] == '1') ? $on : $off; imagesetpixel($im, $x, $y, $col); } } return array($palette, $im); } // regular 16 colours icon for DATA and GAME file // or ICONDATA in 16 colours mode // creates the image's palette $j = -1; for ($i=0; $i<32; $i+=2) { $j ++; $dec1 = ord($vms[$pal_pos+$i]); $bin1 = DecBin($dec1); while (strlen($bin1) < 8) $bin1 = "0$bin1"; $qrt1 = substr($bin1, 0, 4); $green = BinDec($qrt1); $qrt2 = substr($bin1, 4, 4); $blue = BinDec($qrt2); $dec2 = ord($vms[$pal_pos+$i+1]); $bin2 = DecBin($dec2); while (strlen($bin2) < 8) $bin2 = "0$bin2"; $qrt3 = substr($bin2, 0, 4); $alpha = BinDec($qrt3); $qrt4 = substr($bin2, 4, 4); $red = BinDec($qrt4); if ($pal_pos == 0) {$alpha=0; $red=0; $green=0; $blue=0;} // uncomment one of these 2 parts to choose between // pseudo-alpha rendering and normal rendering /* // pseudo-alpha rendering else { $red = $red*($alpha+2); $green = $green*($alpha+2); $blue = $blue*($alpha+2); $alpha = $alpha*17; } */ // normal rendering else { $red = $red*17; $green = $green*17; $blue = $blue*17; $alpha = $alpha*17; } ImageColorAllocate($im, $red, $green, $blue); $palette[$j] = array('alpha' => $alpha, 'red' => $red, 'green' => $green, 'blue' => $blue); } // colours the image's pixels $j = 0; for ($i=0; $i<512; $i++) { $decbyte = ord($vms[$bit_pos+$i]); $binbyte = DecBin($decbyte); while (strlen($binbyte) < 8) $binbyte = "0$binbyte"; $binnyb1 = substr($binbyte, 0, 4); // normal // $binnyb1 = substr($binbyte, 4, 4); // reversed $decnyb1 = BinDec($binnyb1); $y = floor($j / 32); $x = $j - ($y * 32); ImageSetPixel($im, $x, $y, $decnyb1); $binnyb2 = substr($binbyte, 4, 4); // normal // $binnyb2 = substr($binbyte, 0, 4); // reversed $decnyb2 = BinDec($binnyb2); ImageSetPixel($im, $x+1, $y, $decnyb2); $j += 2; } // returns the array return array($palette, $im); } ?>