<?php // Copyright (C) 2007 Cygnus <cygnus2 at post.cz> // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or (at // your option) any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 // USA define ("CTRY","\033[1;34;40m -\033[0m "); define ("COK","\033[1;32;40m *\033[0m "); define ("CWARN","\033[1;33;40m ?\033[0m "); define ("CFAIL","\033[1;31;40m !\033[0m "); define ("CWHITE","\033[1;37;40m"); define ("CDEF","\033[0m"); // configuration define ('HEX_PREFIX', '0'); // 0x # $ define ('HEX_SUFFIX', 'h'); // $ h define ('BIN_PREFIX', ''); // % define ('BIN_SUFFIX', 'b'); // b $cfg_infile = './infile.bin'; $cfg_outfile = './outfile.za'; $cfg_first_address = 0; // first address in binary file $cfg_from_address = 36644; // convert from address $cfg_length = 64; // 0 = no limit (input file) $cfg_output_format = 'b'; // a = ascii, b = binary, h = hex, d = dec $cfg_bytes_per_line = 1; // bytes per line in db // (1 = enable, 0 = disable) $cfg_hex_labels = 0; // generate labels with hexadecimal address on every line $cfg_dec_labels = 0; // generate labels with decadic address on every line $cfg_hex_caps = 0; // big letters in hexadecimal numbers $cfg_dec_comments = 1; // decadic addresses in comments $cfg_hex_comments = 1; // hexadecimal addresses in comments $cfg_double_tabs = 1; // 2x tab on every start of line $cfg_db = 1; // generate db for Z80 assembler AS $cfg_ram_limit = 1; // if enabled, last address will 65535 // -------------------------------------------------------------------------------------- function to_hex ($byte) { global $cfg_hex_caps; if ($cfg_hex_caps) $hextab = array ('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'); else $hextab = array ('0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'); $b = floor($byte / 16); $a = $byte - ($b * 16); return ($hextab[$b].$hextab[$a]); } function to_hex_16b ($word) { $h = floor ($word / 256); $l = $word - 256 * $h; return (to_hex($h).to_hex($l)); } function to_binary ($byte) { $bin = decbin($byte); return (substr("00000000",0,8 - strlen($bin)).$bin); } function to_ascii ($byte) { if ($byte < 32) $a = 32; if ($byte == 127) $a = 'c'; if ($byte >= 32 && $byte < 127) $a = $byte; if ($byte > 127) $a = '.'; return ($a); } // -------------------------------------------------------------------------------------- function line_out ($ln, $out) { global $cfg_dec_comments; global $cfg_hex_comments; global $cfg_output_format; if ($cfg_dec_comments || $cfg_hex_comments) { if ($cfg_output_format == 'a') $ln['string'] .= '"'; $ln['string'] .= "\t\t; "; if ($cfg_dec_comments) { $ln['string'] .= '('.$ln['address'].')'; if ($cfg_hex_comments) $ln['string'] .= ', '; } if ($cfg_hex_comments) $ln['string'] .= '('.to_hex_16b($ln['address']).')'; } $ln['string'] .= "\n"; fwrite ($out, $ln['string']); } function convert ($in, $out) { global $cfg_first_address; // values global $cfg_from_address; global $cfg_length; global $cfg_output_format; global $cfg_bytes_per_line; global $cfg_hex_labels; // (1 = enable, 0 = disable) global $cfg_dec_labels; global $cfg_dec_comments; global $cfg_hex_comments; global $cfg_double_tabs; global $cfg_db; $error = 0; $error_msg = ''; // skip bytes if needed if ($cfg_from_address > 0 && $error == 0) { // skip snapshot header (sna) $counter = 0; while ($error == 0) { $byte = fread($in, 1); $counter++; if ($byte === false) { $error = 1; $error_msg = CFAIL."You trying skip more bytes than are in file.\n".CDEF; break; } if ($counter >= $cfg_from_address) { echo COK."$counter bytes skipped\n".CDEF; break; } } } if ($error == 0) echo COK."Converting from address ".($cfg_first_address + $cfg_from_address)."\n".CDEF; // convert $byte_counter = 0; $ln['address'] = $cfg_first_address + $cfg_from_address; $ln['bytes'] = 0; $ln['counter'] = 0; $ln['string'] = ''; while (1) { $char = fread($in, 1); // end of file? if ($char === false || feof($in)) { if ($ln['string'] != '') line_out ($ln, $out); echo COK."All OK\n".CDEF; break; } // Z80 address space limit? if ($cfg_ram_limit == 1 && ($byte_counter + $cfg_first_address + $cfg_from_address) > 65535) { if ($ln['string'] != '') line_out ($ln, $out); $error = 1; echo CFAIL."Wrong address - cannot be bigger than 65535!\n".CDEF; break; } $byte = unpack ('C', $char); // character must be unpacked to byte = unsigned char // length limit? if ($error == 0 && $cfg_length > 0 && $byte_counter >= $cfg_length) { if ($ln['string'] != '') line_out ($ln, $out); echo COK."All OK\n".CDEF; break; } // beginning of new line if ($error == 0 && $ln['bytes'] == 0) { if ($cfg_hex_labels) { $ln['string'] .= ('A_'.to_hex_16b($ln['address'])); } else { if ($cfg_dec_labels) $ln['string'] .= ('A_'.$ln['address']); } if ($cfg_db) $ln['string'] .= "\t\tdb\t"; else if ($cfg_double_tabs) $ln['string'] .= "\t\t\t"; else { if ($cfg_hex_labels || $cfg_dec_labels) $ln['string'] .= "\t"; } } // convert byte from file to correct text form (ASL compatible) switch ($cfg_output_format) { // a = ascii, b = binary, h = hex, d = dec case 'a': if ($ln['bytes'] == 0) $ln['string'] .= "\""; $ln['string'] .= to_ascii ($byte[1]); $byte_counter++; $ln['bytes']++; break; case 'b': if ($ln['bytes'] > 0) $ln['string'] .= ", "; $ln['string'] .= BIN_PREFIX.to_binary ($byte[1]).BIN_SUFFIX; $byte_counter++; $ln['bytes']++; break; case 'h': if ($ln['bytes'] > 0) $ln['string'] .= ", "; $ln['string'] .= HEX_PREFIX.to_hex($byte[1]).HEX_SUFFIX; $byte_counter++; $ln['bytes']++; break; case 'd': if ($ln['bytes'] > 0) $ln['string'] .= ", "; $ln['string'] .= $byte[1]; $byte_counter++; $ln['bytes']++; break; } // detect end of line for all cases if ($error == 0 && $ln['bytes'] >= $cfg_bytes_per_line) { line_out ($ln, $out); $ln['address'] += $ln['bytes']; $ln['bytes'] = 0; $ln['counter']++; $ln['string'] = ''; } } if ($error) echo $error_msg; } // -------------------------------------------------------------------------------------- $in = fopen ($cfg_infile, "r"); $out = fopen ($cfg_outfile, "w"); if ($in && $out) { convert ($in, $out); } else { if (!$in) echo CFAIL."Warning: opening input file \"$cfg_infile\" failed.\n".CDEF; if (!$out) echo CFAIL."Warning: opening output file \"$cfg_outfile\" failed.\n".CDEF; } if ($in) fclose ($in); if ($out) fclose ($out); return (0); ?>