Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php
- if (defined('__TURBOC__') && !defined('MSDOS')) {
- define('MSDOS', true);
- }
- define('VERSION', '1.8.2');
- define('DEFAULT_OUTPUT', 'out.tap');
- define('REM_TOKEN_NUM', 234);
- define('PEEK_TOKEN_NUM', 190); // Added ZX Spectrum PEEK token code (v1.5.2)
- define('BIN_TOKEN_NUM', 196);
- define('DEFFN_TOKEN_NUM', 206);
- define('VAL_TOKEN_NUM', 176); // Added ZX Spectrum VAL token code (v1.7.2)
- define('ON_TOKEN_NUM', 144);
- define('ON_ERR_TOKEN_NUM', 123);
- define('ERR_TOKEN', 'err ');
- define('ERR_TOKEN_LEN', strlen(ERR_TOKEN) - 1);
- // tokens are stored (and looked for) in reverse speccy-char-set order
- // to avoid def fn/fn and go to/to screwups. There are two entries for each token.
- $tokens = [
- "%listen #", "%listen#",
- "%accept #", "%accept#",
- "%close #", "%close#",
- "%fopen #", "%fopen#",
- "%oneof", "",
- "%mount", "",
- "%umount", "",
- "%cat", "",
- "%cd", "",
- "%fs", "",
- "%load", "",
- "%save", "",
- "%aload", "",
- "%asave", "",
- "%tapein", "",
- "%loadsnap", "",
- "%connect", "",
- "%opendir", "",
- "%reclaim", "",
- "%control", "",
- "-----", "",
- "copy", "",
- "return", "",
- "clear", "",
- "draw", "",
- "cls", "",
- "if", "",
- "randomize", "randomise",
- "save", "",
- "run", "",
- "plot", "",
- "print", "",
- "poke", "",
- "next", "",
- "pause", "",
- "let", "",
- "list", "",
- "load", "",
- "input", "",
- "go sub", "gosub",
- "go to", "goto",
- "for", "",
- "rem", "",
- "dim", "",
- "continue", "",
- "border", "",
- "new", "",
- "restore", "",
- "data", "",
- "read", "",
- "stop", "",
- "llist", "",
- "lprint", "",
- "out", "",
- "over", "",
- "inverse", "",
- "bright", "",
- "flash", "",
- "paper", "",
- "ink", "",
- "circle", "",
- "beep", "",
- "verify", "",
- "merge", "",
- "close #", "close#",
- "open #", "open#",
- "erase", "",
- "move", "",
- "format", "",
- "cat", "",
- "def fn", "deffn",
- "step", "",
- "to", "",
- "then", "",
- "line", "",
- "<>", "",
- ">=", "",
- "<=", "",
- "and", "",
- "or", "",
- "bin", "",
- "not", "",
- "chr$", "",
- "str$", "",
- "usr", "",
- "in", "",
- "peek", "",
- "abs", "",
- "sgn", "",
- "sqr", "",
- "int", "",
- "exp", "",
- "ln", "",
- "atn", "",
- "acs", "",
- "asn", "",
- "tan", "",
- "cos", "",
- "sin", "",
- "len", "",
- "val", "",
- "code", "",
- "val$", "",
- "tab", "",
- "at", "",
- "attr", "",
- "screen$", "",
- "point", "",
- "fn", "",
- "pi", "",
- "inkey$", "",
- "rnd", "",
- "play", "",
- "spectrum", "",
- "rmdir", "", // Added ZX Spectrum Next keywords (v1.5.2)
- "mkdir", "",
- "cd", "",
- "pwd", "",
- "sprite", "",
- "palette", "",
- "layer", "",
- "tile", "",
- "bank", "",
- "remount", "",
- "else", "",
- "repeat", "",
- "while", "",
- "driver", "",
- "local", "",
- "proc", "",
- "end proc", "endproc",
- "def proc", "defproc",
- "on", "",
- "error", "",
- "until", "",
- ">>", "",
- "<<", "",
- "mod", "",
- "dpeek", "",
- "dpoke", "",
- "reg", "",
- "peek$", "",
- "", "",
- "", "",
- "", "",
- "", "",
- "", "",
- "", "",
- "reset", "",
- "free", "",
- "sound", "",
- "stick", "",
- "onerr", "",
- NULL
- ];
- $special_tokens = [NULL];
- $tokens81 = [
- "copy", "",
- "return", "",
- "clear", "",
- "unplot", "",
- "cls", "",
- "if", "",
- "rand", "",
- "save", "",
- "run", "",
- "plot", "",
- "print", "",
- "poke", "",
- "next", "",
- "pause", "",
- "let", "",
- "list", "",
- "load", "",
- "input", "",
- "go sub", "gosub",
- "go to", "goto",
- "for", "",
- "rem", "",
- "dim", "",
- "cont", "",
- "scroll", "",
- "new", "",
- "fast", "",
- "slow", "",
- "stop", "",
- "llist", "",
- "lprint", "",
- "step", "",
- "to", "",
- "then", "",
- "<>", "",
- ">=", "",
- "<=", "",
- "and", "",
- "or", "",
- "**", "",
- "not", "",
- "chr$", "",
- "str$", "",
- "usr", "",
- "peek", "",
- "abs", "",
- "sgn", "",
- "sqr", "",
- "int", "",
- "exp", "",
- "ln", "",
- "atn", "",
- "acs", "",
- "asn", "",
- "tan", "",
- "cos", "",
- "sin", "",
- "len", "",
- "val", "",
- "code", "",
- "", "",
- "tab", "",
- "at", "",
- "", "",
- "pi", "",
- "inkey$", "",
- "rnd", "",
- NULL
- ];
- // The raw BASIC file is written to filebuf; no output is generated
- // until the whole program has been converted. This is to allow a TAP
- // to be output on a non-seekable file (stdout).
- if (defined('MSDOS')) {
- $MAX_LABELS = 500;
- $filebuf = array_fill(0, 32768, 0); // Adjust size accordingly
- $infile = '';
- $outfile = '';
- } else {
- $MAX_LABELS = 2000;
- $filebuf = array_fill(0, 49152, 0); // Adjust size accordingly
- $infile = '';
- $outfile = '';
- }
- //define('MAX_LABEL_LEN', 16);
- const MAX_LABEL_LEN=10;
- // This is needed for tap and +3 files too
- $headerbuf = array_fill(0, 0x80, 0);
- $output_tape = 1;
- $output_dos = 0;
- $use_labels = 0;
- $zx81mode = 0;
- $startline = 0x8000;
- $autostart = 10;
- $autoincr = 2;
- $autoincr_opt = 2;
- $speccy_filename = '';
- $labelend = 0;
- $labels = array_fill(0, $MAX_LABELS, array_fill(0, MAX_LABEL_LEN + 1, 0));
- $label_lines = array_fill(0, $MAX_LABELS, 0);
- $startlabel = array_fill(0, MAX_LABEL_LEN + 1, 0);
- // Simulating the getopt function in PHP
- if (!defined('HAVE_GETOPT')) {
- // Variables that would normally be used in the C version
- $optopt = 0;
- $opterr = 0;
- $optind = 1;
- $optarg = null;
- // Holds the offset in current argv[] value
- $optpos = 1;
- /**
- * Simulated getopt function in PHP.
- * This function assumes the caller uses it correctly and does not pass invalid optstring or varying argc/argv.
- */
- function getopt111($argc, $argv, $optstring) {
- global $optopt, $opterr, $optind, $optarg, $optpos;
- // Check for the end of the argument list
- if ($optind == $argc || $argv[$optind][0] != '-' || strlen($argv[$optind]) <= 1) {
- return -1; // No more options or invalid option
- }
- // Check if the option exists in the optstring
- $ptr = strpos($optstring, $argv[$optind][$optpos]);
- if ($ptr === false) {
- return '?'; // Error: unknown option
- } else {
- $optopt = $argv[$optind][$optpos];
- if ($ptr + 1 < strlen($optstring) && $optstring[$ptr + 1] == ':') {
- // Option expects an argument
- if ($optind == $argc - 1) {
- return ':'; // Error: missing argument for the option
- }
- $optarg = $argv[$optind + 1];
- $optpos = 1;
- $optind += 2;
- return $optopt; // Return early, avoiding the normal increment
- }
- }
- // Now increment the position ready for the next time.
- $optpos++;
- if ($optpos >= strlen($argv[$optind])) {
- $optpos = 1;
- $optind++;
- }
- return $optopt; // Return the found option
- }
- }
- /**
- * This routine converts normal ASCII code to special code used in ZX81.
- */
- function memcpycnv(&$dst, $src) {
- $num = strlen($src); // Get the length of the source string
- $dst = ''; // Initialize the destination as an empty string
- for ($i = 0; $i < $num; $i++) {
- $in = ord($src[$i]); // Get ASCII value of the character
- if ($in >= ord('0') && $in <= ord('9')) {
- $dst .= chr($in - 20);
- } elseif ($in >= ord('A') && $in <= ord('Z')) {
- $dst .= chr($in - 27);
- } elseif ($in >= ord('a') && $in <= ord('z')) {
- $dst .= chr($in + 69);
- } else {
- switch ($in) {
- case 0x0d: $dst .= chr(0x76); break; // enter
- case 0x20: $dst .= chr(0x00); break; // space
- case 0x22: $dst .= chr(0x0b); break; // "
- case 0x24: $dst .= chr(0x0d); break; // $
- case 0x28: $dst .= chr(0x10); break; // (
- case 0x29: $dst .= chr(0x11); break; // )
- case 0x2a: $dst .= chr(0x17); break; // *
- case 0x2b: $dst .= chr(0x15); break; // +
- case 0x2c: $dst .= chr(0x1a); break; // ,
- case 0x2d: $dst .= chr(0x16); break; // -
- case 0x2e: $dst .= chr(0x1b); break; // .
- case 0x2f: $dst .= chr(0x18); break; // /
- case 0x3a: $dst .= chr(0x0e); break; // :
- case 0x3b: $dst .= chr(0x19); break; // ;
- case 0x3c: $dst .= chr(0x13); break; // <
- case 0x3d: $dst .= chr(0x14); break; // =
- case 0x3e: $dst .= chr(0x12); break; // >
- case 0x3f: $dst .= chr(0x0f); break; // ?
- case 0x60: $dst .= chr(0xc0); break; // Backtick (`) to Quote Image
- case 0x7c: $dst .= chr(0x41); break; // INKEY$
- case 0x7d: $dst .= chr(0x40); break; // RND
- case 0x7e:
- $dst .= chr($in); // number
- // Append next 5 characters
- $dst .= substr($src, $i + 1, 5);
- $i += 5; // Skip the 5 characters we just added
- break;
- case 0x7f: $dst .= chr(0x42); break; // PI
- default: $dst .= chr($in); // Default, just append the character
- }
- }
- }
- }
- // Example usage:
- $src = "Hello, world! 12345";
- $dst = '';
- memcpycnv($dst, $src);
- echo "Converted string: " . $dst . "\n";
- ?>
- <?php
- /**
- * dbl2spec converts a double to an inline-basic-style speccy FP number.
- *
- * num is the double to convert.
- * $pexp is the variable where the exponent byte will be returned.
- * $pman is the variable where the 4 mantissa bytes will be returned.
- * Bit 31 is bit 7 of the 0th (first) mantissa byte, and bit 0 is bit 0 of the 3rd (last).
- * As such, the unsigned long returned *must* be written in big-endian format to make sense on a ZX81.
- *
- * Returns 1 if successful, 0 if exponent is too large.
- */
- function dbl2spec($num, &$pexp, &$pman) {
- $exp = 0;
- $man = 0;
- // Check for small integers
- if ($num == (int)$num && $num >= -65535.0 && $num <= 65535.0) {
- // Ignores sign, as specified in the comment (applies to ints too).
- $tmp = abs((int)$num);
- $exp = 0;
- $man = (($tmp % 256) << 16) | (($tmp >> 8) << 8);
- } else {
- // Ignore the sign of the number (ZX81 uses '-' to determine negativity)
- $num = abs($num);
- // Binary standard form goes from 0.50000... to 0.9999...(decimal), similar to how numbers are represented in decimal (0.10000... to 0.9999...)
- // Adjust the number based on its value
- while ($num >= 1.0) {
- $num /= 2.0;
- $exp++;
- }
- while ($num != 0 && $num < 0.5) {
- $num *= 2.0;
- $exp--;
- }
- // Now, the number is in binary standard form in $exp and $num.
- // Check the range of $exp (-128 <= $exp <= 127). If it's out of range, return error (0).
- if ($exp < -128 || $exp > 127) {
- return 0;
- }
- if ($num != 0) {
- $exp = 128 + $exp; // Adjust exponent by adding 128
- }
- // Now roll the bits off the mantissa
- $num *= 2.0; // Make it so the 0.5ths bit is the integer part, and the rest is fractional.
- $man = 0;
- for ($f = 0; $f < 32; $f++) {
- $man <<= 1;
- $man |= (int)$num;
- $num -= (int)$num;
- $num *= 2.0;
- }
- // Round up if the integer part of $num is non-zero, but prevent overflow in mantissa.
- if ((int)$num && $man != 0xFFFFFFFF) {
- $man++;
- }
- // Finally, zero out the top bit (bit 31).
- $man &= 0x7FFFFFFF;
- }
- // Assign the calculated exponent and mantissa
- $pexp = $exp;
- $pman = $man;
- return 1;
- }
- // Example usage:
- $num = 1234.5678;
- $pexp = 0;
- $pman = 0;
- if (dbl2spec($num, $pexp, $pman)) {
- echo "Exponent: " . $pexp . "\n";
- echo "Mantissa: " . dechex($pman) . "\n";
- } else {
- echo "Exponent too large.\n";
- }
- ?>
- <?php
- /**
- * grok_hex converts a hexadecimal string (starting with "0x") into an unsigned long.
- *
- * @param string &$ptrp A reference to the string that contains the hexadecimal number.
- * @param int $textlinenum The line number to be used in error messages.
- *
- * @return int The unsigned long value of the hexadecimal number.
- */
- function grok_hex(&$ptrp, $textlinenum) {
- $hexits = "0123456789abcdefABCDEF"; // Valid hexadecimal characters
- $ptr = &$ptrp; // Pointer to the current position in the string
- $v = 0; // Initialize the value to 0
- // We know the number starts with "0x", so skip the first 2 characters
- $ptr = substr($ptr, 2);
- if (strpos($hexits, $ptr[0]) === false) {
- // If the next character is not a valid hex character, print an error and exit
- echo "line $textlinenum: bad BIN 0x... number\n";
- exit(1);
- }
- // Process the rest of the string
- while (strlen($ptr) > 0 && strpos($hexits, $ptr[0]) !== false) {
- $n = strpos($hexits, $ptr[0]);
- // Adjust the value of n if it's a letter (A-F or a-f)
- if ($n > 15) {
- $n -= 6;
- }
- // Update the value of v based on the hex character
- $v = $v * 16 + $n;
- $ptr = substr($ptr, 1); // Move the pointer to the next character
- }
- // Update the pointer reference with the new position in the string
- $ptrp = $ptr;
- // Return the calculated unsigned long value
- return $v;
- }
- // Example usage:
- $hexString = "0x1f4e"; // Hexadecimal string with the "0x" prefix
- $textlinenum = 10; // Example line number for error reporting
- $value = grok_hex($hexString, $textlinenum);
- echo "The unsigned long value is: $value\n";
- ?>
- <?php
- /**
- * grok_binary converts a binary string (starting with "0" or "1") to an unsigned long.
- * If the binary string is prefixed with "0x" or "0X", it converts it as a hexadecimal number.
- *
- * @param string &$ptrp A reference to the string containing the binary number.
- * @param int $textlinenum The line number for error reporting.
- *
- * @return int The unsigned long value of the binary number.
- */
- function grok_binary(&$ptrp, $textlinenum) {
- $v = 0; // Initialize the result value to 0
- $ptr = &$ptrp; // Pointer to the current position in the string
- // Skip any whitespace characters at the beginning
- $ptr = ltrim($ptr);
- // Check if the first character is '0' or '1'
- if ($ptr[0] !== '0' && $ptr[0] !== '1') {
- // If it's not, print an error message and exit
- echo "line $textlinenum: bad BIN number\n";
- exit(1);
- }
- // Check for hexadecimal prefix "0x" or "0X"
- if (isset($ptr[1]) && ($ptr[1] === 'x' || $ptr[1] === 'X')) {
- // If it's hexadecimal, call the grok_hex function to process it
- return grok_hex($ptrp, $textlinenum);
- }
- // Process the binary number
- while ($ptr[0] === '0' || $ptr[0] === '1') {
- $v *= 2; // Shift the current value by one bit to the left
- $v += $ptr[0] === '1' ? 1 : 0; // Add 1 if the current bit is '1'
- $ptr = substr($ptr, 1); // Move to the next character
- }
- // Update the reference with the new pointer position
- $ptrp = $ptr;
- // Return the resulting unsigned long value
- return $v;
- }
- ?>
- <?php
- /**
- * Displays the usage help for the zmakebas program.
- */
- function usage_help() {
- // Print general information about the program
- echo "zmakebas - public domain by Russell Marks.\n\n";
- // Print usage instruction
- echo "usage: zmakebas [-hlpr3v] [-a line] [-i incr] [-n speccy_filename]\n";
- echo " [-o output_file] [-s line] [input_file]\n\n";
- // List of options with descriptions
- echo " -v output version number.\n";
- echo " -a set auto-start line of basic file (default none).\n";
- echo " -h give this usage help.\n";
- echo " -i in labels mode, set line number incr. (default 2).\n";
- echo " -l use labels rather than line numbers.\n";
- echo " -n set Spectrum filename (to be given in tape header).\n";
- echo " -o specify output file (default 'out.tap').\n"; // Replace with the default output
- echo " -p output .p instead (set ZX81 mode).\n";
- echo " -r output raw headerless file (default is .tap file).\n";
- echo " -3 output a +3DOS compatible file (default is .tap file).\n";
- echo " -s in labels mode, set starting line number (default 10).\n";
- }
- ?>
- <?php
- //define('MAX_LABEL_LEN', 10);
- const MAX_LABEL_LEN=10;
- define('VERSION', '1.0'); // Replace with your actual version
- $zx81mode = 0;
- $startlabel = '';
- $startline = 0;
- $autoincr_opt = 0;
- $use_labels = 0;
- $speccy_filename = '';
- $outfile = 'out.tap'; // Default output file
- $output_tape = 1;
- $output_dos = 0;
- $autostart = 0;
- $infile = '';
- // Simulate the getopt function, similar to how it's used in C
- function parse_options($argc, $argv) {
- global $zx81mode, $startlabel, $startline, $autoincr_opt, $use_labels, $speccy_filename, $outfile, $output_tape, $output_dos, $autostart, $infile;
- $options = getopt("pa:hi:ln:o:r3s:v");
- if (isset($options['p'])) {
- $zx81mode = 1;
- }
- if (isset($options['a'])) {
- $optarg = $options['a'];
- if ($optarg[0] === '@') {
- if (strlen($optarg) - 1 > MAX_LABEL_LEN) {
- echo "Auto-start label too long\n";
- exit(1);
- }
- $startlabel = substr($optarg, 1);
- } else {
- $startline = (int)$optarg;
- if ($startline > 9999) {
- echo "Auto-start line must be in the range 0 to 9999.\n";
- exit(1);
- }
- }
- }
- if (isset($options['v'])) {
- echo VERSION . "\n";
- exit(1);
- }
- if (isset($options['h'])) { // usage help
- usage_help();
- exit(1);
- }
- if (isset($options['i'])) {
- $autoincr_opt = (int)$options['i'];
- if ($autoincr_opt < 1 || $autoincr_opt > 1000) {
- echo "Label line incr. must be in the range 1 to 1000.\n";
- exit(1);
- }
- }
- if (isset($options['l'])) {
- $use_labels = 1;
- }
- if (isset($options['n'])) {
- $speccy_filename = substr($options['n'], 0, 10);
- }
- if (isset($options['o'])) {
- $outfile = $options['o'];
- }
- if (isset($options['r'])) { // output raw file
- $output_tape = 0;
- }
- if (isset($options['3'])) { // output PLUS3DOS file
- $output_tape = 0;
- $output_dos = 1;
- }
- if (isset($options['s'])) {
- $autostart = (int)$options['s'];
- if ($autostart < 0 || $autostart > 9999) {
- echo "Label start line must be in the range 0 to 9999.\n";
- exit(1);
- }
- }
- // Handle missing arguments (for example, --a needs a value)
- foreach ($options as $key => $value) {
- if ($value === false) {
- switch ($key) {
- case 'a':
- echo "The `a' option takes a line number arg.\n";
- break;
- case 'i':
- echo "The `i' option takes a line incr. arg.\n";
- break;
- case 'n':
- echo "The `n' option takes a Spectrum filename arg.\n";
- break;
- case 'o':
- echo "The `o' option takes a filename arg.\n";
- break;
- case 's':
- echo "The `s' option takes a line number arg.\n";
- break;
- default:
- echo "Option `$key' not recognised.\n";
- }
- exit(1);
- }
- }
- // Check if there are any extra arguments
- if ($argc > count($options) + 1) {
- usage_help();
- exit(1);
- }
- // Check for input file (last argument)
- if ($argc == count($options) + 1) {
- $infile = $argv[$argc - 1];
- }
- }
- ?>
- <?php
- function grok_block($ptr, $textlinenum) {
- static $lookup = [
- " ", " '", "' ", "''", " .", " :", "'.", "':",
- ". ", ".'", ": ", ":'", "..", ".:", ":.", "::",
- NULL
- ];
- static $lookup81 = [
- " ", "' ", " '", "''", ". ", ": ", ".'", ":'",
- "::", ".:", ":.", "..", "':", " :", "'.", " .",
- "!:", "!.", "!'", "|:", "|.", "|'",
- NULL
- ];
- $f = 0;
- $v = -1;
- $zx81mode = false; // Assume some flag indicating ZX81 mode
- // Choose the appropriate lookup table based on $zx81mode
- $lookupTable = $zx81mode ? $lookup81 : $lookup;
- foreach ($lookupTable as $lptr) {
- if ($lptr === NULL) break;
- if (strncmp(substr($ptr, 1), $lptr, 2) === 0) {
- if ($zx81mode) {
- if ($f < 8) {
- $v = $f;
- } elseif ($f < 16) {
- $v = $f + 0x78;
- } elseif ($f < 19) {
- $v = $f - 8;
- } else {
- $v = $f + 117;
- }
- } else {
- $v = $f + 128;
- }
- break;
- }
- $f++;
- }
- if ($v === -1) {
- fprintf(STDERR, "line %d: invalid block graphics escape\n", $textlinenum);
- exit(1);
- }
- return $v;
- }
- ?>
- <?php
- // Simulate constants for platform detection
- define('MSDOS', false); // Change this to true for MSDOS simulation
- // Define the buffer sizes based on platform
- if (MSDOS) {
- $buf = str_repeat("\0", 512);
- $lcasebuf = str_repeat("\0", 512);
- $outbuf = str_repeat("\0", 1024);
- } else {
- $buf = str_repeat("\0", 2048);
- $lcasebuf = str_repeat("\0", 2048);
- $outbuf = str_repeat("\0", 4096);
- }
- // Declare other variables
- $f = $toknum = $toklen = $linenum = $linelen = 0;
- $in_quotes = $in_rem = $in_deffn = $in_spec = $lastline = 0;
- $tarrptr = [];
- $ptr = $ptr2 = $linestart = $outptr = $remptr = $fileptr = $asciiptr = null;
- $num = $num_exp = 0;
- $num_mantissa = $num_ascii = 0;
- $chk = 0;
- $alttok = 0;
- $passnum = 1;
- $in = fopen("php://stdin", "r");
- $out = fopen("php://stdout", "w");
- // Initialize variables for file names
- $speccy_filename = '';
- $infile = '-';
- $outfile = 'default_output.txt'; // Default output file
- // Parse the options (a function to handle command-line arguments)
- parse_options($argc, $argv);
- ?>
- <?php
- // Example setup (you should define these variables or get them from the program's context)
- $zx81mode = true; // Example flag, set to true or false based on your logic
- define('DEFAULT_OUTPUT', 'default_output.txt');
- $outfile = 'default_output.txt'; // The output file name
- $infile = '-'; // The input file name (could be '-' for stdin or a file path)
- $filebuf = ''; // The file buffer (you'll want to initialize this based on actual use)
- $fileptr = ''; // The file pointer
- $linenum = -1; // Line number initialization
- // Check if in ZX81 mode and output file is the default
- if ($zx81mode && $outfile === DEFAULT_OUTPUT) {
- // In C, this would set outfile[4] and outfile[5] to 'p' and 0, respectively
- // In PHP, we manipulate the string directly
- $outfile[4] = 'p';
- $outfile[5] = '';
- }
- // If infile is not '-' and we cannot open the file, show an error and exit
- if ($infile !== "-" && !($in = fopen($infile, "r"))) {
- echo "Couldn't open input file.\n";
- exit(1);
- }
- // Initialize fileptr with the file buffer (this part depends on actual use of $filebuf)
- $fileptr = $filebuf;
- // Set linenum to -1 to indicate the first line (as per your original C code)
- $linenum = -1; // to set lastline
- // In the original code, there was a comment about making one pass for line numbers and two for labels
- // You would need to implement this logic here, depending on how you handle lines and labels in your code.
- ?>
- <?php
- // ... (other variables and functions from the original code) ...
- do {
- $autoincr = $autoincr_opt;
- if ($use_labels) {
- $linenum = $autostart - $autoincr;
- }
- $textlinenum = 0;
- if ($passnum > 1 && fseek($in, 0, SEEK_SET) !== 0) {
- fprintf(STDERR, "Need seekable input for label support\n");
- exit(1);
- }
- while (($line = fgets($in)) !== false) {
- $line = " " . $line; // Add space at beginning for ptr[-1]
- $textlinenum++;
- $lastline = $linenum;
- // Remove trailing newline
- $line = rtrim($line, "\n");
- // Ignore comments and blank lines
- if (strlen($line) < 2 || $line[1] === '#' || $line[1] === 0) {
- continue;
- }
- // Handle line continuation
- while (substr($line, -1) === '\\') {
- $f = strlen($line) - 1;
- $line = substr($line, 0, $f) . fgets($in);
- $textlinenum++;
- $line = rtrim($line, "\n");
- }
- // Line too long for buffer
- if (strlen($line) >= sizeof($buf) - $MAX_LABEL_LEN - 1) {
- fprintf(STDERR, "line %d: line too big for input buffer\n", $textlinenum);
- exit(1);
- }
- // Get line number (or assign one)
- if ($use_labels) {
- $linestart = $line;
- $linenum += $autoincr;
- if ($linenum > 9999) {
- fprintf(STDERR, "Generated line number is >9999 - %s\n",
- ($autostart > 1 || $autoincr > 1) ? "try using `-s 1 -i 1'"
- : "too many lines!"
- );
- exit(1);
- }
- } else {
- $ptr = $line;
- while (ctype_space($ptr[0])) {
- $ptr++;
- }
- if (!is_numeric($ptr[0])) {
- fprintf(STDERR, "line %d: missing line number\n", $textlinenum);
- exit(1);
- }
- $linenum = (int) strtol($ptr, $linestart, 10);
- if ($linenum <= $lastline) {
- fprintf(STDERR, "line %d: line no. not greater than previous one\n",
- $textlinenum
- );
- exit(1);
- }
- }
- if ($linenum < 0 || $linenum > 9999) {
- fprintf(STDERR, "line %d: line no. out of range\n", $textlinenum);
- exit(1);
- }
- // Skip remaining spaces
- while (ctype_space($linestart[0])) {
- $linestart++;
- }
- // Check for line number in labels mode
- if ($use_labels && is_numeric($linestart[0])) {
- $linenum = (int) strtol($linestart, $linestart, 10);
- if ($linenum <= $lastline) {
- fprintf(STDERR, "line %d: line no. %d not greater than previous one (%d)\n",
- $textlinenum, $linenum, $lastline
- );
- exit(1);
- }
- if ($linestart[0] === '+' && is_numeric($linestart[1])) {
- $linestart++;
- $autoincr = (int) strtol($linestart, $linestart, 10);
- $autoincr += $autoincr === 0;
- }
- // Skip remaining spaces
- while (ctype_space($linestart[0])) {
- $linestart++;
- }
- }
- // Handle labels
- if ($use_labels && $linestart[0] === '@') {
- // Find the colon
- $ptr = strchr($linestart, ':');
- if ($ptr === false) {
- fprintf(STDERR, "line %d: incomplete token definition\n", $textlinenum);
- exit(1);
- }
- $labelLength = $ptr - $linestart - 1;
- if ($labelLength > $MAX_LABEL_LEN) {
- fprintf(STDERR, "line %d: token too long\n", $textlinenum);
- exit(1);
- }
- if ($passnum === 1) {
- $label = substr($linestart, 1, $labelLength);
- $label_lines[$labelend] = $linenum;
- $labels[$labelend++] = $label;
- if ($labelend >= $MAX_LABELS) {
- fprintf(STDERR, "line %d: too many labels\n", $textlinenum);
- exit(1);
- }
- // Check for duplicate labels
- for ($f = 0; $f < $labelend - 1; $f++) {
- if ($labels[$f] === $label) {
- fprintf(STDERR, "line %d: attempt to redefine label\n", $textlinenum);
- exit(1);
- }
- }
- }
- $linestart = substr($linestart, $labelLength + 2);
- while (ctype_space($linestart[0])) {
- $linestart++;
- }
- // Skip blank lines after labels
- if ($linestart === "") {
- $linenum -= $autoincr;
- continue;
- }
- }
- // Skip first pass for labels
- if ($use_labels && $passnum === 1) {
- continue;
- }
- // Convert line to lowercase and remove strings
- $ptr = $linestart;
- $in_quotes = false;
- $ptr2 = "";
- while ($ptr !== false) {
- if ($ptr[0] === '"') {
- $in_quotes = !$in_quotes;
- }
- if ($in_quotes && $ptr[0] !== '"') {
- $ptr2 .= " ";
- } else {
- $ptr2 .= strtolower($ptr[0]);
- }
- $ptr = mb_substr($ptr, 1);
- }
- // Tokenize the line
- $remptr = null;
- if (($ptr = strpos($ptr2, "rem")) !== false &&
- !ctype_alpha($ptr2[$ptr - 1]) && !ctype_alpha($ptr2[$ptr + 3])) {
- $ptr2 = substr_replace($ptr2, "\0", $ptr, strlen("rem"));
- $remptr = $ptr;
- $linestart = substr_replace($linestart, "\0", $ptr, strlen("rem"));
- $linestart = substr_replace($linestart, chr(1), $ptr, 1);
- $linestart = substr_replace($linestart, chr(1), $ptr + 1, 1);
- $linestart = substr_replace($linestart, chr(1), $ptr + 2, 1);
- if ($ptr2[$ptr + 3] === ' ') {
- $linestart = substr_replace($linestart, chr(1), $ptr + 3, 1);
- }
- }
- // Tokenize the line using standard tokens table
- $toknum = $zx81mode ? 256 : 151;
- $alttok = 1;
- foreach ($zx81mode ? $tokens81 : $tokens as $tarrptr) {
- if ($alttok) {
- $toknum--;
- }
- $alttok = !$alttok;
- if ($tarrptr === "") {
- continue;
- }
- $toklen = strlen($tarrptr);
- if ($tarrptr === "-----") {
- $toknum = 256;
- $alttok = 0;
- continue;
- }
- $ptr = $ptr2;
- while (($ptr = strpos($ptr, $tarrptr)) !== false) {
- // Skip special commands
- if ($ptr2[$ptr] === '%' && $tarrptr[0] === '%') {
- $ptr += $toklen;
- continue;
- }
- if ($ptr2[$ptr - 1] === '%' && $tarrptr[0] !== '%') {
- $ptr += $toklen;
- continue;
- }
- // Check for valid token placement
- if ($tarrptr[0] === '<' || $tarrptr[1] === '=' ||
- ((!ctype_alpha($ptr2[$ptr - 1]) && !ctype_alpha($ptr2[$ptr + $toklen]) && !( !$zx81mode && (($toknum === $PEEK_TOKEN_NUM) || ($toknum === $VAL_TOKEN_NUM)) && ($ptr2[$ptr + $toklen] === '$'))) &&
- $toknum >= 123)) {
- // Handle ON keyword for both ZX Spectrum Next and T/S 2000
- if (!$zx81mode && $toknum === $ON_TOKEN_NUM) {
- $ptr2_temp = substr($ptr2, $ptr + $toklen);
- while (ctype_space($ptr2_temp[0])) {
- $ptr2_temp = substr($ptr2_temp, 1);
- }
- if (strncmp($ptr2_temp, $ERR_TOKEN, $ERR_TOKEN_LEN) === 0) {
- $toknum = $ON_ERR_TOKEN_NUM;
- $toklen = $ptr + $ERR_TOKEN_LEN - 1 - $ptr;
- }
- }
- // Replace token with token number
- if ($zx81mode && $toknum > 0xbc && $toknum < 0xc0) {
- $linestart = substr_replace($linestart, chr($toknum === 0xbe ? 0x7c : $toknum - 0x40), $ptr, $toklen);
- } else {
- $linestart = substr_replace($linestart, chr($toknum), $ptr, $toklen);
- }
- // Replace token in the lowercase copy
- $ptr2 = substr_replace($ptr2, chr(1), $ptr, $toklen);
- // Skip spaces after token
- $ptr += $toklen;
- while (ctype_space($ptr2[$ptr])) {
- $ptr2 = substr_replace($ptr2, chr(1), $ptr, 1);
- $ptr++;
- }
- // Special case for BIN token
- if (!$zx81mode && $toknum === $BIN_TOKEN_NUM) {
- $linestart = substr_replace($linestart, chr(1), $ptr - 1, 1);
- $linestart = substr_replace($linestart, chr($toknum), $ptr, 1);
- $ptr2 = substr_replace($ptr2, chr(1), $ptr - 1, 1);
- $ptr2 = substr_replace($ptr2, chr($toknum), $ptr, 1);
- }
- }
- $ptr += $toklen;
- }
- }
- // Replace labels with line numbers
- if ($use_labels) {
- $ptr = $linestart;
- while (($ptr = strpos($ptr, '@')) !== false) {
- if ($ptr2[$ptr - 1] === '\\') {
- $ptr++;
- continue;
- }
- // Find matching label
- $ptr++;
- for ($f = 0; $f < $labelend; $f++) {
- $len = strlen($labels[$f]);
- if (strncmp($labels[$f], substr($linestart, $ptr, $len), $len) === 0 &&
- (ord(substr($linestart, $ptr + $len, 1)) < 33 || ord(substr($linestart, $ptr + $len, 1)) > 126 || ispunct(substr($linestart, $ptr + $len, 1)))) {
- // Remove REM temporarily
- if ($remptr) {
- $linestart = substr_replace($linestart, chr(1), $remptr, 1);
- }
- // Replace label with line number
- $linestart = substr_replace($linestart, strval($label_lines[$f]), $ptr - 1, $len + 1);
- // Update $remptr if it exists
- if ($remptr) {
- $remptr = $remptr - ($len + 1) + strlen(strval($label_lines[$f]));
- $linestart = substr_replace($linestart, "\0", $remptr, 1);
- }
- break;
- }
- }
- if ($f === $labelend) {
- fprintf(STDERR, "line %d: undefined label\n", $textlinenum);
- exit(1);
- }
- $ptr += strlen(strval($label_lines[$f])); // Update $ptr to the new position
- }
- }
- // Replace REM token
- if ($remptr !== null) {
- $linestart = substr_replace($linestart, chr($REM_TOKEN_NUM), $remptr, 1);
- }
- // Convert the line to bytes, handle escapes, and add numbers
- $ptr = $linestart;
- $outptr = "";
- $in_rem = $in_deffn = $in_quotes = $in_spec = false;
- while ($ptr !== false) {
- if (strlen($outptr) > sizeof($outbuf) - 10) {
- fprintf(STDERR, "line %d: line too big\n", $textlinenum);
- exit(1);
- }
- if ($ptr[0] === '"') {
- $in_quotes = !$in_quotes;
- } else if ($ptr[0] === chr(1) || $ptr[0] === ' ' || ($ptr[0] === ' ' && !$in_quotes && !$in_rem && !$in_spec)) {
- // Skip spaces and 0x01 chars
- $ptr = mb_substr($ptr, 1);
- continue;
- } else if ($ptr[0] === chr($DEFFN_TOKEN_NUM)) {
- $in_deffn = true;
- } else if ($ptr[0] === chr($REM_TOKEN_NUM)) {
- $in_rem = true;
- } else if ($ptr[0] === '%' && !$in_rem && !$in_quotes) {
- // Handle special commands
- $in_spec = true;
- if ($ptr === $linestart) {
- $outptr .= " ";
- }
- } else if ($ptr[0] === '\\') {
- $ptr = mb_substr($ptr, 1);
- if (ctype_alpha($ptr[0]) && !str_contains("VWXYZvwxyz", $ptr[0])) {
- $outptr .= chr(144 + ord(strtolower($ptr[0])) - ord('a'));
- } else if ($zx81mode) {
- switch ($ptr[0]) {
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- $outptr .= chr(ord($ptr[0]) + 108);
- break;
- case '"':
- $outptr .= chr(0x8b);
- break;
- case '$':
- $outptr .= chr(0x8d);
- break;
- case ':':
- if (!str_contains("'.: ", substr($ptr, 1, 1))) {
- $outptr .= chr(0x8e);
- } else {
- $outptr .= chr(grok_block($ptr, $textlinenum));
- $ptr = mb_substr($ptr, 1);
- }
- break;
- case '?':
- $outptr .= chr(0x8f);
- break;
- case '(':
- $outptr .= chr(0x90);
- break;
- case ')':
- $outptr .= chr(0x91);
- break;
- case '>':
- $outptr .= chr(0x92);
- break;
- case '<':
- $outptr .= chr(0x93);
- break;
- case '=':
- $outptr .= chr(0x94);
- break;
- case '+':
- $outptr .= chr(0x95);
- break;
- case '-':
- $outptr .= chr(0x96);
- break;
- case '*':
- $outptr .= chr(0x97);
- break;
- case '/':
- $outptr .= chr(0x98);
- break;
- case ';':
- $outptr .= chr(0x99);
- break;
- case ',':
- $outptr .= chr(0x9a);
- break;
- case '.':
- if (!str_contains("'.: ", substr($ptr, 1, 1))) {
- $outptr .= chr(0x9b);
- } else {
- $outptr .= chr(grok_block($ptr, $textlinenum));
- $ptr = mb_substr($ptr, 1);
- }
- break;
- case '\\':
- $outptr .= chr(0x0c); // Pound symbol
- break;
- case '@':
- $outptr .= chr(0x8c); // Inverse pound symbol
- break;
- case '\'': case '!': case '|': case ' ':
- $outptr .= chr(grok_block($ptr, $textlinenum));
- $ptr = mb_substr($ptr, 1);
- break;
- case '{': // Directly specify output code
- // Find end of number
- $asciiptr = strrpos($ptr, '}');
- if ($asciiptr === false) {
- fprintf(STDERR, "line %d: unclosed brace in eight-bit character code\n", $textlinenum);
- exit(1);
- }
- // Parse number in decimal, octal, or hex
- $num_ascii = strtoul(substr($ptr, 1, $asciiptr - 1), null, 0);
- if ($num_ascii > 255) {
- fprintf(STDERR, "line %d: eight-bit character code out of range\n", $textlinenum);
- exit(1);
- }
- $outptr .= chr($num_ascii);
- $ptr = substr($ptr, $asciiptr); // Move $ptr to the end of the code
- break;
- default:
- fprintf(STDERR, "line %d: warning: unknown escape `%c', inserting literally\n", $textlinenum, $ptr[0]);
- $outptr .= $ptr[0];
- }
- } else {
- switch ($ptr[0]) {
- case '\\':
- $outptr .= '\\';
- break;
- case '@':
- $outptr .= '@';
- break;
- case '*':
- $outptr .= chr(127); // Copyright symbol
- break;
- case '\'': case '.': case ':': case ' ': // Block graphics char
- $outptr .= chr(grok_block($ptr, $textlinenum));
- $ptr = mb_substr($ptr, 1);
- break;
- case '{': // Directly specify output code
- // Find end of number
- $asciiptr = strrpos($ptr, '}');
- if ($asciiptr === false) {
- fprintf(STDERR, "line %d: unclosed brace in eight-bit character code\n", $textlinenum);
- exit(1);
- }
- // Parse number in decimal, octal, or hex
- $num_ascii = strtoul(substr($ptr, 1, $asciiptr - 1), null, 0);
- if ($num_ascii > 255) {
- fprintf(STDERR, "line %d: eight-bit character code out of range\n", $textlinenum);
- exit(1);
- }
- $outptr .= chr($num_ascii);
- $ptr = substr($ptr, $asciiptr); // Move $ptr to the end of the code
- break;
- default:
- fprintf(STDERR, "line %d: warning: unknown escape `%c', inserting literally\n", $textlinenum, $ptr[0]);
- $outptr .= $ptr[0];
- }
- }
- $ptr = mb_substr($ptr, 1); // Move $ptr to the next character
- continue;
- }
- // Handle numbers
- if (!$in_rem && !$in_quotes && !ctype_alpha($ptr[0]) &&
- (is_numeric($ptr[0]) ||
- (($ptr[0] === '-' || $ptr[0] === '+' || $ptr[0] === '.') && is_numeric(substr($ptr, 1, 1))) ||
- (($ptr[0] === '-' || $ptr[0] === '+') && substr($ptr, 1, 1) === '.' && is_numeric(substr($ptr, 2, 1))))) {
- if ($zx81mode || $ptr2[$ptr - 1] !== chr($BIN_TOKEN_NUM)) {
- // Parse number with strtod()
- $num = (double) strtod($ptr, $ptr2);
- } else {
- // Parse binary number after BIN token
- $ptr2 = $ptr;
- $num = (double) grok_binary($ptr2, $textlinenum);
- }
- // Add number to output
- $outptr .= substr($linestart, $ptr, $ptr2 - $ptr);
- $outptr .= chr($zx81mode ? 0x7e : 0x0e);
- // Convert number to inline FP representation
- if (!dbl2spec($num, $num_exp, $num_mantissa)) {
- fprintf(STDERR, "line %d: exponent out of range (number too big)\n", $textlinenum);
- exit(1);
- }
- $outptr .= chr($num_exp);
- $outptr .= chr($num_mantissa >> 24);
- $outptr .= chr($num_mantissa >> 16);
- $outptr .= chr($num_mantissa >> 8);
- $outptr .= chr($num_mantissa & 255);
- $ptr = $ptr2;
- } else {
- // Handle def fn case
- if ($in_deffn) {
- if ($ptr[0] === '=') {
- $in_deffn = false;
- } else if ($ptr[0] === ',' || $ptr[0] === ')') {
- $outptr .= chr(0x0e);
- $outptr .= chr(0);
- $outptr .= chr(0);
- $outptr .= chr(0);
- $outptr .= chr(0);
- $outptr .= chr(0);
- $outptr .= $ptr[0];
- $ptr = mb_substr($ptr, 1);
- }
- if ($ptr[0] !== ' ') {
- $outptr .= $ptr[0];
- $ptr = mb_substr($ptr, 1);
- }
- } else {
- // Add character to output
- if ($zx81mode) {
- $outptr .= mb_convert_encoding(mb_substr($ptr, 0, 1), 'CP437', 'UTF-8');
- } else {
- $outptr .= $ptr[0];
- }
- $ptr = mb_substr($ptr, 1);
- }
- }
- }
- $outptr .= chr($zx81mode ? 0x76 : 0x0d); // Add terminating CR
- // Output line
- $linelen = strlen($outptr);
- if (strlen($filebuf) + 4 + $linelen >= sizeof($filebuf)) {
- fprintf(STDERR, "program too big!\n");
- exit(1);
- }
- // Handle ZX81 start line adjustment
- if ($zx81mode && $startline === $linenum) {
- $startline = strlen($filebuf) - $zx81mode++;
- }
- $filebuf .= chr($linenum >> 8);
- $filebuf .= chr($linenum & 255);
- $filebuf .= chr($linelen & 255);
- $filebuf .= chr($linelen >> 8);
- $filebuf .= $outptr;
- }
- $passnum++;
- } while ($use_labels && $passnum <= 2);
- if ($in !== STDIN) {
- fclose($in);
- }
- /* we only need to do this if outputting a .tap, but might as well do
- * it to check the label's ok anyway.
- */
- if (!empty($startlabel)) {
- /* this is nearly a can't happen error, but FWIW... */
- if (!$use_labels) {
- fprintf(STDERR, "Auto-start label specified, but not using labels!\n");
- exit(1);
- }
- for ($f = 0; $f < $labelend; $f++) {
- if (strcmp($startlabel, $labels[$f]) === 0) {
- $startline = $label_lines[$f];
- break;
- }
- }
- if ($f === $labelend) {
- fprintf(STDERR, "Auto-start label is undefined\n");
- exit(1);
- }
- }
- /* write output file */
- if (strcmp($outfile, "-") !== 0) {
- $out = fopen($outfile, "wb");
- if ($out === false) {
- fprintf(STDERR, "Couldn't open output file.\n");
- exit(1);
- }
- }
- if ($output_tape) {
- $siz = $fileptr - $filebuf;
- if ($zx81mode) {
- /* make header */
- // $headerbuf[0] = 0; // VERSN
- // *(short*)($headerbuf + 1) = 0; // E_PPC
- $headerbuf[3] = $siz + 0x407d; // D_FILE
- $headerbuf[5] = $siz + 0x407e; // DF_CC
- $headerbuf[7] = $siz + 0x4096; // VARS
- // *(short*)($headerbuf + 9) = 0; // DEST
- $headerbuf[11] = $siz + 0x4097; // E_LINE
- $headerbuf[13] = $siz + 0x4096; // CH_ADD
- // *(short*)($headerbuf + 15) = 0; // X_PTR
- $headerbuf[17] = $siz + 0x4097; // STKBOT
- $headerbuf[19] = $siz + 0x4097; // STKEND
- // $headerbuf[21] = 0; // BERG
- $headerbuf[22] = 0x405d; // MEM
- // $headerbuf[24] = 0; // not used
- $headerbuf[25] = 2; // DF_SZ
- $headerbuf[26] = 1; // S_TOP
- $headerbuf[28] = -1; // LAST_K
- $headerbuf[29] = -1;
- $headerbuf[31] = 55; // MARGIN
- $headerbuf[32] = ($zx81mode - 2) // NXTLIN
- ? $siz + 0x407d
- : $startline + 0x407e;
- // *(short*)($headerbuf + 34) = 0; // OLDPPC
- // $headerbuf[36] = 0; // FLAGX
- // *(short*)($headerbuf + 37) = 0; // STRLEN
- $headerbuf[39] = 0x0c8d; // T_ADDR
- // *(short*)($headerbuf + 41) = 0; // SEED
- $headerbuf[43] = -1; // FRAMES
- // *(short*)($headerbuf + 45) = 0; // COORDS
- $headerbuf[47] = 0xbc; // PR_CC
- $headerbuf[48] = 33; // S_POSN
- $headerbuf[49] = 24;
- $headerbuf[50] = 0x40; // CDFLAG
- /* write header */
- fwrite($out, $headerbuf, 0x74);
- } else {
- /* make header */
- $headerbuf[0] = 0;
- for ($f = strlen($speccy_filename); $f < 10; $f++) {
- $speccy_filename[$f] = ' ';
- }
- strncpy($headerbuf + 1, $speccy_filename, 10);
- $headerbuf[11] = ($siz & 255);
- $headerbuf[12] = ($siz / 256);
- $headerbuf[13] = ($startline & 255);
- $headerbuf[14] = ($startline / 256);
- $headerbuf[15] = ($siz & 255);
- $headerbuf[16] = ($siz / 256);
- /* write header */
- fprintf($out, "%c%c%c", 19, 0, $chk = 0);
- for ($f = 0; $f < 17; $f++) {
- $chk ^= $headerbuf[$f];
- }
- fwrite($out, $headerbuf, 17);
- fputc($out, $chk);
- /* write (most of) tap bit for data block */
- fprintf($out, "%c%c%c", ($siz + 2) & 255, ($siz + 2) >> 8, $chk = 255);
- for ($f = 0; $f < $siz; $f++) {
- $chk ^= $filebuf[$f];
- }
- }
- } elseif ($output_dos) {
- $siz = $fileptr - $filebuf;
- $dossiz = $siz + 128;
- /* +3DOS header */
- $headerbuf[0] = 'P';
- $headerbuf[1] = 'L';
- $headerbuf[2] = 'U';
- $headerbuf[3] = 'S';
- $headerbuf[4] = '3';
- $headerbuf[5] = 'D';
- $headerbuf[6] = 'O';
- $headerbuf[7] = 'S'; // PLUS3DOS
- $headerbuf[8] = 0x1a; // Soft-EOF
- $headerbuf[9] = 0x01; // Issue number
- $headerbuf[10] = 0x00; // Version number
- $headerbuf[11] = ($dossiz & 255); // File size
- $headerbuf[12] = ($dossiz / 256); // including header
- $headerbuf[13] = 0; // Also size, but BASIC header
- $headerbuf[14] = 0; // only 16-bits so don't need these
- $headerbuf[15] = 0; // Program
- $headerbuf[16] = ($siz & 255); // Size again
- $headerbuf[17] = ($siz / 256); // but 16-bit
- $headerbuf[18] = ($startline & 255); // Start line
- $headerbuf[19] = ($startline / 256); // " "
- $headerbuf[20] = ($siz & 255); // Offset to prog
- $headerbuf[21] = ($siz / 256); // ZXOS puts the size in here again
- $headerbuf[22] = 0; // Not used
- for ($f = 23; $f < 127; $f++) {
- $headerbuf[$f] = 0x00; // Not used
- }
- /* calculate checksum */
- $chk = 0;
- for ($f = 0; $f < 127; $f++) {
- $chk += $headerbuf[$f];
- }
- $headerbuf[127] = $chk % 256;
- fwrite($out, $headerbuf, 128);
- }
- fwrite($out, $filebuf, $fileptr - $filebuf);
- if ($output_tape) {
- if ($zx81mode) {
- for ($i = 0; $i < 25; $i++) {
- fputc($out, 0x76);
- }
- fputc($out, 0x80);
- } else {
- fputc($out, $chk);
- }
- }
- if ($out !== STDOUT) {
- fclose($out);
- }
- exit(0);
- ?>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement