home *** CD-ROM | disk | FTP | other *** search
/ ftp.whtech.com / ftp.whtech.com.7z / ftp.whtech.com / emulators / v9t9 / linux / sources / V9t9 / source / roms.c < prev    next >
Encoding:
C/C++ Source or Header  |  2006-10-19  |  9.0 KB  |  366 lines

  1.  
  2. /*
  3.         ======
  4.         ROMS.C
  5.         ======
  6.  
  7.         This file manages loading of binary data in ROMs or cartridges.
  8.         For cartridge lists, etc., see moduledb.c.
  9. */
  10.  
  11. #include "OSLib.h"
  12.  
  13. #include "v9t9_common.h"
  14. #include "memory.h"
  15. #include "roms.h"
  16. #include "fiad.h"
  17.  
  18. #define _L     LOG_ROMS | LOG_INFO
  19.  
  20. /*
  21.     Find the location for a binary image and return size.
  22.  */
  23. int  
  24. findbinary(char *path, char *syspath, char *filename, OSSpec *spec)
  25. {
  26.     OSRef       ref;
  27.     OSSize      size;
  28.     OSError     err;
  29.  
  30.     if (!filename)
  31.         return 0;
  32.  
  33.     if (OS_GetFileNamePtr(filename) != filename &&
  34.         (err = OS_MakeFileSpec(filename, spec)) == OS_NOERR &&
  35.         OS_Status(spec) == OS_NOERR) {
  36.         // found it
  37.     } else if ((err = OS_FindFileInPath(filename, path, spec)) != OS_NOERR &&
  38.                (err = OS_FindFileInPath(filename, syspath, spec)) != OS_NOERR) {
  39.         return 0;
  40.     }
  41.  
  42.  
  43.     if ((err = OS_Open(spec, OSReadOnly, &ref)) != OS_NOERR) {
  44.         OSerror(err, "\n");
  45.         return 0;
  46.     }
  47.  
  48.     OS_GetSize(ref, &size);
  49.  
  50.     OS_Close(ref);
  51.  
  52.     return size;
  53. }
  54.  
  55. /*
  56.     Load a binary image, return # bytes read.
  57. */
  58. int  
  59. loadbinary(char *path, char *syspath, char *filename, char *type,
  60.            u8 * loadat, int swap, int fileoffs, int imagesize, 
  61.            int maxsize)
  62. {
  63.     OSRef       ref;
  64.     OSSize      size;
  65.     OSError     err;
  66.     OSSpec      spec;
  67.  
  68.     size = findbinary(path, syspath, filename, &spec);
  69.  
  70.     if (!size) {
  71.         if (*filename) {
  72.             logger(_L |LOG_USER|LOG_ERROR, "Cannot find '%s' in paths:\n%s or\n%s", filename, 
  73.                     path, syspath);
  74.         }
  75.         return 0;
  76.     }
  77.     logger(_L|L_0, "Loading %s image %s... ", type, OS_SpecToString1(&spec));
  78.  
  79.     if (imagesize)
  80.         size = imagesize;
  81.     else if (size - fileoffs > maxsize) {
  82.         logger(_L | LOG_WARN | LOG_USER, "%s too long, only %d bytes of %d read... ",
  83.              OS_SpecToString1(&spec), maxsize, size);
  84.         size = maxsize - fileoffs;
  85.     }
  86.  
  87.     if ((err = OS_Open(&spec, OSReadOnly, &ref)) != OS_NOERR) {
  88.         OSerror(err, "\n");
  89.         return 0;
  90.     }
  91.  
  92. //    size -= offset;
  93. //    loadat += offset;
  94.  
  95.     if ((err = OS_Seek(ref, OSSeekAbs, fileoffs)) != OS_NOERR ||
  96.         (err = OS_Read(ref, loadat, &size)) != OS_NOERR) {
  97.         OSerror(err, "could not read\n");
  98.         return 0;
  99.     }
  100.  
  101.     if (swap) {
  102.         logger(_L, "swapping bytes... ");
  103.         swab((const void *) loadat, (void *) loadat, size);
  104.     }
  105.  
  106.     logger(_L| L_0, "done\n");
  107.  
  108.     OS_Close(ref);
  109.     return size;
  110. }
  111.  
  112. /*
  113.     Save a binary image, return # bytes written.
  114. */
  115. #if BEWORKS_FS
  116. OSFileType  osBinaryType = { 0666, "x/v9t9-memory-image" };
  117. #elif POSIX_FS
  118. OSFileType  osBinaryType = { 0666 };
  119. #elif WIN32_FS
  120. OSFileType  osBinaryType = 0;
  121. #elif MAC_FS
  122. OSFileType  osBinaryType = 'BIN ';
  123. #endif
  124.  
  125. /*
  126.  *    Save data to an image found somewhere in 'path' or 'syspath'
  127.  *    (if not existing, placed in first entry of 'path').
  128.  *    Existing file is not overwritten.
  129.  *
  130.  *    path / syspath:    search paths
  131.  *    type:            string emitted in error, i.e., "RAM image"
  132.  *    filename:        name of image
  133.  *    fileoffs:        offset into file to write
  134.  *    saveat:            start of memory to write 
  135.  *    swap:            if true, byteswap word data to TI format
  136.  *    memsize:        size of memory to write
  137.  */
  138. int  
  139. savebinary(char *path, char *syspath, char *type,
  140.            char *filename, int fileoffs,
  141.            u8 * saveat, int swap, int memsize)
  142. {
  143.     OSRef       ref;
  144.     OSSize      size;
  145.     OSError     err;
  146.     OSSpec      spec;
  147.  
  148.     if ((size = findbinary(path, syspath, filename, &spec)) == 0) {
  149.         if ((err = OS_CreateFileInPath(filename, 
  150.                                        *path ? path : syspath, 
  151.                                        &spec, 
  152.                                        &osBinaryType)) != OS_NOERR) {
  153.             OSerror(err, "Couldn't create %s image %s anywhere in path: %s\n",
  154.                     type, filename, path);
  155.             return 0;
  156.         }
  157.     }
  158.  
  159.     logger(_L |L_0, "Writing %s image %s... ", type, OS_SpecToString1(&spec));
  160.  
  161.     if ((err = OS_Open(&spec, OSReadWrite, &ref)) != OS_NOERR) {
  162.         OSerror(err, "\n");
  163.         return 0;
  164.     }
  165.  
  166.     //size = memsize - offset;
  167.     //saveat += offset;
  168.  
  169.     if (swap) {
  170.         logger(_L, "swapping bytes to save... ");
  171.         swab((const void *) saveat, (void *) saveat, size);
  172.     }
  173.  
  174.     if ((err = OS_Seek(ref, OSSeekAbs, fileoffs)) != OS_NOERR ||
  175.         (err = OS_Write(ref, saveat, &size)) != OS_NOERR) {
  176.         OSerror(err, "could not write\n");
  177.         return 0;
  178.     }
  179.  
  180.     if (swap) {
  181.         logger(_L, "swapping bytes back... ");
  182.         swab((const void *) saveat, (void *) saveat, size);
  183.     }
  184.  
  185.     logger(_L|L_0, "done\n");
  186.  
  187.     OS_Close(ref);
  188.     return size;
  189. }
  190.  
  191. /*
  192.     Return 1 if loaded.
  193. */
  194. int
  195. loaddsr(char *path, char *syspath, char *filename, char *name, void *mem)
  196. {
  197.     return loadbinary(path, syspath, filename, name, mem, 1, 0, 8192, 8192);
  198. }
  199.  
  200. /*
  201.     Return 1 if loaded.
  202. */
  203. /*
  204. int
  205. loadspeech(char *path, char *syspath, char *filename, void *mem)
  206. {
  207.     return loadbinary(path, syspath, filename, "Speech ROM", mem, 0, 
  208.                       0, 32768, 32768);
  209. }
  210. */
  211.  
  212. /*
  213.  
  214. Each GRAM Kracker stores an 8K ROM or GROM bank.  The first six bytes
  215. are an extension of the memory image program standard.  Here is what the
  216. bytes mean:
  217.  
  218. Byte 0: "More to load" flag, values:
  219. >FF = There's another file to load
  220. >80 = There's a "UTIL" file to load (I don't think this is ever used).
  221. >00 = This is the last file
  222.  
  223. Byte 1: Bank of GRAM/RAM to load file into, values:
  224. >01 = GROM/GRAM bank 0 (>0000)
  225. >02 = GROM/GRAM bank 1 (>2000)
  226. >03 = GROM/GRAM bank 2 (>4000)
  227. >04 = GROM/GRAM bank 3 (>6000)
  228. >05 = GROM/GRAM bank 4 (>8000)
  229. >06 = GROM/GRAM bank 5 (>A000)
  230. >07 = GROM/GRAM bank 6 (>C000)
  231. >08 = GROM/GRAM bank 7 (>E000)
  232. >09 = ROM bank 1 (>6000)
  233. >0A = ROM bank 2 (second >6000)
  234. >00 or >FF = Assembly language program, not a cartridge file
  235.  
  236. Bytes 2 and 3: Number of bytes to load (normally 8192)
  237. Bytes 4 and 5: Actual address to start loading at (e.g. >6000)
  238.  
  239. As an example, Extended BASIC gets saved as files "XB" to "XB5", which
  240. have headers as follows:
  241. XB      FF0A 2000 6000 (ROM bank 2)
  242. XB1     FF09 2000 6000 (ROM bank 1)
  243. XB2     FF07 2000 C000 (GRAM bank 6)
  244. XB3     FF06 2000 A000 (GRAM bank 5)
  245. XB4     FF05 2000 8000 (GRAM bank 4)
  246. XB5     0004 2000 6000
  247.  
  248. Even though TI GROMS only use 6K of each 8K bank, all 8K is stored so people
  249. can add their own GPL code as extensions to modules.  Extended BASIC has
  250. a number of enhancements available.
  251. */
  252.  
  253. /*
  254.  *    Search paths for a file matching 'filename'.
  255.  *    If found, and it is a valid GRAM-Kracker file,
  256.  *    set 'spec' to point to it, and return its header info in 'header'
  257.  *    
  258.  */
  259. int roms_find_gram_kracker(char *path, char *systempath, char *filename, 
  260.                            OSSpec *spec, gram_kracker_header *header)
  261. {
  262.     int size;
  263.     fiad_logger_func old;
  264.     int old_unknownfileistext;
  265.     fiad_tifile tf;
  266.     OSError err;
  267.     OSRef ref;
  268.     bool is_v9t9_file;
  269.  
  270.     memset(header, 0, sizeof(gram_kracker_header));
  271.  
  272.     /* Can we find the file? */
  273.     size = findbinary(path, systempath, filename, spec);
  274.     if (!size)
  275.         return 0;
  276.  
  277.     /* See if it's a V9t9/TIFILES file or perhaps a plain binary */
  278.     old = fiad_set_logger(0L);
  279.     old_unknownfileistext = unknownfileistext;
  280.     unknownfileistext = 0;
  281.  
  282.     if (fiad_tifile_setup_spec_with_spec(&tf, spec) != OS_NOERR) {
  283.         goto error_exit;
  284.     }
  285.  
  286.     /* Is it a V9t9 file? */
  287.     if (fiad_tifile_get_info(&tf)) {
  288.         if (!(tf.fdr.flags & ff_program)) {
  289.             logger(_L|LOG_ERROR|LOG_USER, "GRAM Kracker segment '%s' is not a PROGRAM file (it's %s)\n",
  290.                    OS_SpecToString1(spec), fiad_catalog_get_file_type_string(&tf.fdr));
  291.             goto error_exit;
  292.         }
  293.         // allow enough space for the data, header, and extra sector
  294.         if (FDR_FILESIZE(&tf.fdr) > 8198+256) {
  295.             logger(_L|LOG_ERROR|LOG_USER, "GRAM Kracker segment '%s' is too long\n"
  296.                    "to be a segment (%d bytes > 8192+6 bytes)\n",
  297.                    OS_SpecToString1(spec), FDR_FILESIZE(&tf.fdr));
  298.             goto error_exit;
  299.         }
  300.         is_v9t9_file = true;
  301.     } else {
  302.         is_v9t9_file = false;
  303.     }
  304.  
  305.     /* Read header from first sector */
  306.     if (is_v9t9_file) {
  307.         u16 headersize = 6;
  308.         if (fiad_tifile_open_file(&tf, newfileformat, 
  309.                                    false /*create*/,
  310.                                    false /*always*/,
  311.                                    true /*readonly*/) != OS_NOERR 
  312.             ||
  313.             fiad_tifile_read_binary_image(&tf,
  314.                                           (u8 *)header,
  315.                                           headersize,
  316.                                           &headersize) != 0
  317.             ||
  318.             headersize < 6)
  319.         {
  320.             logger(_L|LOG_ERROR|LOG_USER, "Could not read signature for GRAM Kracker segment in V9t9 file '%s' (%s)\n",
  321.                    OS_SpecToString1(spec), OS_GetErrText(tf.error));
  322.             goto error_exit;
  323.         }
  324.         header->absolute_image_file_offset = sizeof(v9t9_fdr) + 6;
  325.     } else {
  326.         OSSize headersize = 6;
  327.  
  328.         if ((err = OS_Open(spec, OSReadOnly, &ref)) != OS_NOERR ||
  329.             (err = OS_Read(ref, (void *)header, &headersize)) != OS_NOERR ||
  330.             (err = OS_Close(ref)) != OS_NOERR)
  331.         {
  332.             logger(_L|LOG_ERROR|LOG_USER, "Could not read signature for GRAM Kracker segment in binary file '%s' (%s)\n",
  333.                    OS_SpecToString1(spec), OS_GetErrText(err));
  334.             goto error_exit;
  335.         }
  336.         header->absolute_image_file_offset = 6;
  337.     }
  338.  
  339.     /* Make header suitable for v9t9 */
  340.     header->address = TI2HOST(header->address);
  341.     header->length = TI2HOST(header->length);
  342.  
  343.     if (header->more_to_load == 0x80)
  344.     {
  345.         logger(_L|LOG_ERROR|LOG_USER, "GRAM Kracker segment '%s' is a 'UTIL' segment (not supported)\n",
  346.                OS_SpecToString1(spec));
  347.         goto error_exit;
  348.     }
  349.  
  350.     if (header->gk_type == 0x00 ||
  351.         header->gk_type == 0xff ||
  352.         header->gk_type > GK_TYPE_ROM_2)
  353.     {
  354.         logger(_L|LOG_ERROR|LOG_USER, "GRAM Kracker segment '%s' is not a ROM file (got >%02X)\n",
  355.                OS_SpecToString1(spec), header->gk_type);
  356.         goto error_exit;
  357.     }
  358.  
  359.     return size;
  360.  
  361. error_exit:
  362.     fiad_set_logger(old);
  363.     unknownfileistext = old_unknownfileistext;
  364.     return 0;
  365. }
  366.