home *** CD-ROM | disk | FTP | other *** search
/ The Best of Mecomp Multimedia 2 / MECOMP-CD-II.iso / amiga / emulation / n64rom / source / n64rom.c
Encoding:
C/C++ Source or Header  |  1998-01-24  |  6.2 KB  |  334 lines

  1. /****************************************/
  2. /*                    */
  3. /*          N64 Rom Manager        */
  4. /*                    */
  5. /*          By Salim Gasmi        */
  6. /*                    */
  7. /*          salim@gasmi.net        */
  8. /*                    */
  9. /****************************************/
  10.  
  11. #include <stdio.h>
  12. #include <fcntl.h>
  13. #include <unistd.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16.  
  17.  
  18. #define VER    "V1.0"
  19. #define MEGA    (1024*1024)
  20. #define B1    0x80
  21. #define B2    0x37
  22.  
  23. #define max2(a, b) ( (a)>(b) ? (a) : (b) )
  24. #define min2(a, b) ( (a)<(b) ? (a) : (b) )
  25.  
  26. #define BUFSIZE 32768
  27. #define SMALBUF    16384
  28.  
  29. #define CHECKSUM_START 0x1000
  30. #define CHECKSUM_LENGTH 0x100000L
  31. #define CHECKSUM_HEADERPOS 0x10
  32. #define CHECKSUM_END (CHECKSUM_START + CHECKSUM_LENGTH)
  33.  
  34. #define CHECKSUM_STARTVALUE 0xf8ca4ddc
  35.  
  36. #define ROL(i, b) (((i)<<(b)) | ((i)>>(32-(b))))
  37.  
  38. #define BYTES2LONG(b, s) ( (((b)[0^(s)] & 0xffL) << 24) | \
  39.                            (((b)[1^(s)] & 0xffL) << 16) | \
  40.                            (((b)[2^(s)] & 0xffL) <<  8) | \
  41.                            (((b)[3^(s)] & 0xffL)) )
  42.  
  43. #define LONG2BYTES(l, b, s)  (b)[0^(s)] = ((l)>>24)&0xff; \
  44.                              (b)[1^(s)] = ((l)>>16)&0xff; \
  45.                              (b)[2^(s)] = ((l)>> 8)&0xff; \
  46.                              (b)[3^(s)] = ((l)    )&0xff;
  47.  
  48.  
  49. int IsRom(unsigned char *);
  50. void Swap(unsigned char *,int);
  51. int ChkSum(FILE *,int,long,int);
  52.  
  53. int main(int argc,char **argv)
  54. {
  55. int f,i;
  56. long l;
  57. unsigned char v=0;
  58. unsigned char name[64];
  59. unsigned char mode[50];
  60. int ty;
  61. unsigned char *buf;
  62. FILE *file;
  63. unsigned char sbuf[SMALBUF];
  64. int perc,curr;
  65.  
  66. if(argc!=3)
  67.     {
  68.     printf("\nUsage : %s -{hvsSc} rom_file\n\n",argv[0]);
  69.     printf("-h : display info about the ROM\n");
  70.     printf("-v : Verify checksum of the ROM\n");
  71.     printf("-s : Swap little<->Big Endian format (fast but need mem)\n");
  72.     printf("-S : Swap little<->Big Endian format (slow but need no mem)\n");
  73.     printf("-c : Regenerate the checksum of the ROM\n\n");
  74.     printf("---- n64rom %s by Salim Gasmi ---- \n\n",VER);
  75.     return(0);
  76.     }
  77.  
  78. if(strcmp(argv[1],"-h")==0) v=1;
  79. if(strcmp(argv[1],"-v")==0) v=2;
  80. if(strcmp(argv[1],"-s")==0) v=3;
  81. if(strcmp(argv[1],"-c")==0) v=4;
  82. if(strcmp(argv[1],"-S")==0) v=5;
  83.  
  84. if(v==0)
  85.     {
  86.     printf("Unknown switch option %s\n",argv[1]);
  87.     return(0);
  88.     }
  89.  
  90. f=open(argv[2],O_RDWR);
  91. if(f<0)
  92.     {
  93.     printf("file %s not found or write protected\n",argv[2]);
  94.     return(0);
  95.     }
  96.  
  97. read(f,name,2);
  98. lseek(f,0,0);
  99. l=lseek(f,0,2);
  100. lseek(f,0,0);
  101. lseek(f,32,0);
  102.  
  103. ty=IsRom(name);
  104.  
  105. if(ty==-1) 
  106.     {
  107.     printf("%s is not a N64 ROM\n",argv[2]);
  108.     close(f);
  109.     return(0);
  110.     }
  111.  
  112. read(f,name,63);
  113.  
  114. if(ty==1)
  115.     {
  116.      Swap(name,63);
  117.      strcpy(mode,"Little Endian (V64)");
  118.     }
  119.     else strcpy(mode,"Big Endian (Z64)");
  120.  
  121. if(v==1)
  122.     {
  123.     printf("%s : %s %ld MB %s format\n",argv[2],name,l*8/MEGA,mode);
  124.     close(f);
  125.     return(0);
  126.     }
  127.  
  128.  
  129. if(v==3)
  130. {
  131. lseek(f,0,0);
  132.  
  133. /* we load the ROM in RAM */
  134.  
  135. buf=(unsigned char *)malloc(l);
  136. if(buf==NULL)
  137.         {
  138.         close(f);
  139.         printf("malloc failed\n");
  140.         return(0);
  141.         }
  142.  
  143.  
  144. printf("reading && Swaping file %s (%ld bytes) (fast mode).... \n",argv[2],l);
  145.  
  146. read(f,buf,l);
  147. lseek(f,0,0);
  148. Swap(buf,l);
  149. write(f,buf,l);
  150. free(buf);
  151. }
  152.  
  153. if(v==5)
  154. {
  155. ty=1;
  156.  
  157. printf("reading && Swaping file %s (%ld bytes) (slow mode).... \n",argv[2],l);
  158.  
  159.  
  160. printf("%% done :");
  161. fflush(stdout);
  162. perc=l/10;
  163. curr=0;
  164.  
  165. i=0;
  166. while(i!=l)
  167. {
  168. lseek(f,i,0);
  169. read(f,sbuf,SMALBUF);
  170. Swap(sbuf,SMALBUF);
  171. lseek(f,i,0);
  172. write(f,sbuf,SMALBUF);
  173.  
  174. if(i/perc>curr)
  175.     {
  176.     curr=i/perc;
  177.     printf("%d%% ",curr*10);
  178.     fflush(stdout);
  179.     }
  180.  
  181. i+=SMALBUF;
  182. }
  183. printf("100%%\n");
  184. fflush(stdout);
  185. }
  186.  
  187.  
  188.  
  189. if(v==2 || v==4)
  190. {
  191. file=fopen(argv[2],"r+b");
  192. if(file==NULL)
  193.     {
  194.     printf("file %s not found or write protected\n",argv[1]);
  195.     return(0);
  196.     }
  197. }
  198.  
  199. if(v==2)
  200. {
  201. if(ChkSum(file,ty,l,1)==0) printf("Checksum of %s is good\n",argv[2]);
  202. else printf("Checksum of %s is wrong\n",argv[2]);
  203. fclose(file);
  204. }
  205.  
  206. if(v==4)
  207. {
  208. if(ChkSum(file,ty,l,0)==0) printf("Checksum of %s regenerated\n",argv[2]);
  209. else printf("Error writing Checksum of %s\n",argv[2]);
  210. fclose(file);
  211. }
  212.  
  213.  
  214. close(f);
  215. return(0);
  216. }
  217.  
  218.  
  219. int IsRom(unsigned char *a)
  220. {
  221. if(a[0]==B1 && a[1]==B2) return(0);
  222. if(a[0]==B2 && a[1]==B1) return(1);
  223. return(-1);
  224. }
  225.  
  226.  
  227. void Swap(unsigned char *buffer,int l)
  228. {
  229. int i;
  230. unsigned char p;
  231.  
  232. for(i=0;i<l-1;i=i+2)
  233.         {
  234.         p=buffer[i];
  235.         buffer[i]=buffer[i+1];
  236.         buffer[i+1]=p;
  237.         }
  238. }
  239.  
  240.  
  241. int ChkSum(FILE *file,int swapped,long flen,int readonly)
  242. {
  243.     unsigned char *buffer;
  244.     unsigned long sum1, sum2;
  245.     unsigned long i;
  246.     unsigned long c1, k1, k2;
  247.     unsigned long t1, t2, t3, t4;
  248.     unsigned long t5, t6;
  249.     unsigned int n;
  250.     long clen = CHECKSUM_LENGTH;
  251.     long rlen = flen - CHECKSUM_START;
  252.     int wrong,jj,ret;
  253.  
  254.     buffer=(unsigned char *)malloc(BUFSIZE);
  255.     if(buffer==NULL) return(-99);
  256.  
  257.  
  258.     t1 = CHECKSUM_STARTVALUE;
  259.     t2 = CHECKSUM_STARTVALUE;
  260.     t3 = CHECKSUM_STARTVALUE;
  261.     t4 = CHECKSUM_STARTVALUE;
  262.     t5 = CHECKSUM_STARTVALUE;
  263.     t6 = CHECKSUM_STARTVALUE;
  264.  
  265. fseek(file, CHECKSUM_START, SEEK_SET);
  266.  
  267.     for( ;; ) {
  268.       if( rlen > 0 ) {
  269.         n = fread(buffer, 1, min2(BUFSIZE, clen), file);
  270.         if( (n & 0x03) != 0 ) {
  271.           n += fread(buffer+n, 1, 4-(n&3), file);
  272.         }
  273.       } else {
  274.         n = min2(BUFSIZE, clen);
  275.       }
  276.       if( (n == 0) || ((n&3) != 0) ) {
  277.         if( (clen != 0) || (n != 0) ) {
  278.       if(readonly==1) 
  279.         {
  280.         free(buffer);
  281.         return(-1);
  282.         }
  283.         }
  284.         break;
  285.       }
  286.       for( i=0; i<n; i+=4 ) {
  287.         c1 = BYTES2LONG(&buffer[i], swapped);
  288.         k1 = t6 + c1;
  289.         if( k1 < t6 ) t4++;
  290.         t6 = k1;
  291.         t3 ^= c1;
  292.         k2 = c1 & 0x1f;
  293.         k1 = ROL(c1, k2);
  294.         t5 += k1;
  295.         if( c1 < t2 ) {
  296.           t2 ^= k1;
  297.         } else {
  298.           t2 ^= t6 ^ c1;
  299.         }
  300.         t1 += c1 ^ t5;
  301.       }
  302.       if( rlen > 0 ) {
  303.         rlen -= n;
  304.         if( rlen <= 0 ) memset(buffer, 0, BUFSIZE);
  305.       }
  306.       clen -= n;
  307.     }
  308.     sum1 = t6 ^ t4 ^ t3;
  309.     sum2 = t5 ^ t2 ^ t1;
  310.  
  311.   LONG2BYTES(sum1, &buffer[0], 0);
  312.   LONG2BYTES(sum2, &buffer[4], 0);
  313.   fseek(file, CHECKSUM_HEADERPOS, SEEK_SET);
  314.   fread(buffer+8, 1, 8, file);
  315.  
  316.   wrong=0;
  317.  
  318.   for(jj=0;jj<=7;jj++)
  319.     if(buffer[(jj+8)^swapped]!=buffer[jj]) wrong=-1;
  320.  
  321.     if(readonly==0) 
  322.     {
  323.             fseek(file, CHECKSUM_HEADERPOS, SEEK_SET);
  324.             LONG2BYTES(sum1, &buffer[16], swapped);
  325.             LONG2BYTES(sum2, &buffer[20], swapped);
  326.             if( fwrite(buffer+16, 1, 8, file) != 8 ) ret=-1; else ret=0;
  327.     }
  328.     else ret=wrong;
  329.  
  330. free(buffer);
  331. return(ret);
  332. }
  333.  
  334.