1+ #define _CRT_SECURE_NO_WARNINGS
2+
3+ #include <stdio.h>
4+ #include <stdlib.h>
5+ #include <string.h>
6+
7+ #pragma pack(1)
8+ typedef struct header_prg {
9+ int magic ; // 0xa55a5aa5
10+ int file_length ; //payload file lehght
11+ int file_crc ; //payload file CRC32?
12+ int version ;
13+ int volume ; //1
14+ int zero1 ;
15+ char filename [16 ];
16+ char filedate [24 ];
17+ int zeros1 [2 ];
18+ int ffs0 [14 ]; //0xFF
19+ int magic1 ; // 0xa55a5aa5
20+ int zero2 ;
21+ int file_length_prg ; //one more time - payload file lehght
22+ int file_crc1 ; //one more time - payload file CRC32?
23+ int magic2 [3 ]; // const: 0x00104788, 0x04104788, 0x06000010
24+ int ffs1 [16 ]; //0xFF
25+ int ffs2 [16 ]; //0xFF
26+ int ffs3 [16 ]; //0xFF
27+ int ffs4 [16 ]; //0xFF
28+ int ffs5 [16 ]; //0xFF
29+ int ffs6 [8 ]; //0xFF
30+ int ver_crc ; // up to
31+ } header_typeprg ;
32+
33+ #pragma pack(1)
34+ typedef struct header_st {
35+ int magic ; // 0xa55a5aa5 // 00
36+ int len ; // len of ver file // 04
37+ int version ; //version // 08
38+ int volume ; //1 // 0C
39+ int zero1 ; // 10
40+ int a2c ; //2c // 14
41+ int nb0_length ; //payload file lehght //18
42+ int nb0_crc ; //payload file CRC32? //1C
43+ int version1 ; // same version // 20
44+ int volume1 ; //1 // 24
45+ int zero2 ; // 28
46+ int nfiles ; //1 // 2C
47+ int dirdepth ; //1 // 30
48+ char dirname [64 ]; // 34
49+ int filestoprocess ; //1 // 74
50+ char filename [56 ]; // 78
51+ int file_length ; // B0
52+ int file_crc ; // B4
53+ //----
54+ //int magic1; // 0xa55a5aa5 // B8
55+ //int ver_crc; // up to and including magic1 //BC
56+ } header_type ;
57+
58+
59+ static const unsigned int crc32_table [] =
60+ {
61+ 0x00000000 , 0x77073096 , 0xEE0E612C , 0x990951BA , 0x076DC419 , 0x706AF48F , 0xE963A535 , 0x9E6495A3 ,
62+ 0x0EDB8832 , 0x79DCB8A4 , 0xE0D5E91E , 0x97D2D988 , 0x09B64C2B , 0x7EB17CBD , 0xE7B82D07 , 0x90BF1D91 ,
63+ 0x1DB71064 , 0x6AB020F2 , 0xF3B97148 , 0x84BE41DE , 0x1ADAD47D , 0x6DDDE4EB , 0xF4D4B551 , 0x83D385C7 ,
64+ 0x136C9856 , 0x646BA8C0 , 0xFD62F97A , 0x8A65C9EC , 0x14015C4F , 0x63066CD9 , 0xFA0F3D63 , 0x8D080DF5 ,
65+ 0x3B6E20C8 , 0x4C69105E , 0xD56041E4 , 0xA2677172 , 0x3C03E4D1 , 0x4B04D447 , 0xD20D85FD , 0xA50AB56B ,
66+ 0x35B5A8FA , 0x42B2986C , 0xDBBBC9D6 , 0xACBCF940 , 0x32D86CE3 , 0x45DF5C75 , 0xDCD60DCF , 0xABD13D59 ,
67+ 0x26D930AC , 0x51DE003A , 0xC8D75180 , 0xBFD06116 , 0x21B4F4B5 , 0x56B3C423 , 0xCFBA9599 , 0xB8BDA50F ,
68+ 0x2802B89E , 0x5F058808 , 0xC60CD9B2 , 0xB10BE924 , 0x2F6F7C87 , 0x58684C11 , 0xC1611DAB , 0xB6662D3D ,
69+ 0x76DC4190 , 0x01DB7106 , 0x98D220BC , 0xEFD5102A , 0x71B18589 , 0x06B6B51F , 0x9FBFE4A5 , 0xE8B8D433 ,
70+ 0x7807C9A2 , 0x0F00F934 , 0x9609A88E , 0xE10E9818 , 0x7F6A0DBB , 0x086D3D2D , 0x91646C97 , 0xE6635C01 ,
71+ 0x6B6B51F4 , 0x1C6C6162 , 0x856530D8 , 0xF262004E , 0x6C0695ED , 0x1B01A57B , 0x8208F4C1 , 0xF50FC457 ,
72+ 0x65B0D9C6 , 0x12B7E950 , 0x8BBEB8EA , 0xFCB9887C , 0x62DD1DDF , 0x15DA2D49 , 0x8CD37CF3 , 0xFBD44C65 ,
73+ 0x4DB26158 , 0x3AB551CE , 0xA3BC0074 , 0xD4BB30E2 , 0x4ADFA541 , 0x3DD895D7 , 0xA4D1C46D , 0xD3D6F4FB ,
74+ 0x4369E96A , 0x346ED9FC , 0xAD678846 , 0xDA60B8D0 , 0x44042D73 , 0x33031DE5 , 0xAA0A4C5F , 0xDD0D7CC9 ,
75+ 0x5005713C , 0x270241AA , 0xBE0B1010 , 0xC90C2086 , 0x5768B525 , 0x206F85B3 , 0xB966D409 , 0xCE61E49F ,
76+ 0x5EDEF90E , 0x29D9C998 , 0xB0D09822 , 0xC7D7A8B4 , 0x59B33D17 , 0x2EB40D81 , 0xB7BD5C3B , 0xC0BA6CAD ,
77+ 0xEDB88320 , 0x9ABFB3B6 , 0x03B6E20C , 0x74B1D29A , 0xEAD54739 , 0x9DD277AF , 0x04DB2615 , 0x73DC1683 ,
78+ 0xE3630B12 , 0x94643B84 , 0x0D6D6A3E , 0x7A6A5AA8 , 0xE40ECF0B , 0x9309FF9D , 0x0A00AE27 , 0x7D079EB1 ,
79+ 0xF00F9344 , 0x8708A3D2 , 0x1E01F268 , 0x6906C2FE , 0xF762575D , 0x806567CB , 0x196C3671 , 0x6E6B06E7 ,
80+ 0xFED41B76 , 0x89D32BE0 , 0x10DA7A5A , 0x67DD4ACC , 0xF9B9DF6F , 0x8EBEEFF9 , 0x17B7BE43 , 0x60B08ED5 ,
81+ 0xD6D6A3E8 , 0xA1D1937E , 0x38D8C2C4 , 0x4FDFF252 , 0xD1BB67F1 , 0xA6BC5767 , 0x3FB506DD , 0x48B2364B ,
82+ 0xD80D2BDA , 0xAF0A1B4C , 0x36034AF6 , 0x41047A60 , 0xDF60EFC3 , 0xA867DF55 , 0x316E8EEF , 0x4669BE79 ,
83+ 0xCB61B38C , 0xBC66831A , 0x256FD2A0 , 0x5268E236 , 0xCC0C7795 , 0xBB0B4703 , 0x220216B9 , 0x5505262F ,
84+ 0xC5BA3BBE , 0xB2BD0B28 , 0x2BB45A92 , 0x5CB36A04 , 0xC2D7FFA7 , 0xB5D0CF31 , 0x2CD99E8B , 0x5BDEAE1D ,
85+ 0x9B64C2B0 , 0xEC63F226 , 0x756AA39C , 0x026D930A , 0x9C0906A9 , 0xEB0E363F , 0x72076785 , 0x05005713 ,
86+ 0x95BF4A82 , 0xE2B87A14 , 0x7BB12BAE , 0x0CB61B38 , 0x92D28E9B , 0xE5D5BE0D , 0x7CDCEFB7 , 0x0BDBDF21 ,
87+ 0x86D3D2D4 , 0xF1D4E242 , 0x68DDB3F8 , 0x1FDA836E , 0x81BE16CD , 0xF6B9265B , 0x6FB077E1 , 0x18B74777 ,
88+ 0x88085AE6 , 0xFF0F6A70 , 0x66063BCA , 0x11010B5C , 0x8F659EFF , 0xF862AE69 , 0x616BFFD3 , 0x166CCF45 ,
89+ 0xA00AE278 , 0xD70DD2EE , 0x4E048354 , 0x3903B3C2 , 0xA7672661 , 0xD06016F7 , 0x4969474D , 0x3E6E77DB ,
90+ 0xAED16A4A , 0xD9D65ADC , 0x40DF0B66 , 0x37D83BF0 , 0xA9BCAE53 , 0xDEBB9EC5 , 0x47B2CF7F , 0x30B5FFE9 ,
91+ 0xBDBDF21C , 0xCABAC28A , 0x53B39330 , 0x24B4A3A6 , 0xBAD03605 , 0xCDD70693 , 0x54DE5729 , 0x23D967BF ,
92+ 0xB3667A2E , 0xC4614AB8 , 0x5D681B02 , 0x2A6F2B94 , 0xB40BBE37 , 0xC30C8EA1 , 0x5A05DF1B , 0x2D02EF8D
93+ };
94+
95+ unsigned int crc32b (const unsigned char * data , int len ) {
96+
97+ unsigned int crc ;
98+ crc = 0xFFFFFFFF ;
99+
100+ if (len ) do {
101+ crc = (crc >> 8 ) ^ crc32_table [(crc ^ * data ) & 255 ];
102+ data ++ ;
103+ } while (-- len );
104+
105+ return (~crc );
106+ }
107+
108+ unsigned int checksum32 (const unsigned char * data , int len ) {
109+ int i ;
110+ unsigned int crc , tmp , tmp1 ;
111+ crc = 0x00000000 ;
112+ tmp = 0 ;
113+ tmp1 = 0 ;
114+ len = len / 4 ;
115+
116+ if (len > 0 ) do {
117+
118+ for (i = 0 ; i < 4 ; i ++ ) {
119+ tmp1 = * data ;
120+ tmp = tmp + (tmp1 << 8 * i );
121+ data ++ ;
122+ }
123+ crc = crc + tmp ;
124+ tmp = 0 ;
125+
126+ } while (-- len );
127+
128+ return (crc );
129+ }
130+
131+
132+
133+ int main (int argc , char * argv [])
134+ {
135+ printf ("Usage: patchver [PS140PLT.PRG] [PS140PLT.VER] [output.nb0]\n" );
136+
137+ char * prg_filename = "PS140PLT.PRG" ;
138+ char * ver_filename = "PS140PLT.VER" ;
139+ char * nb0_filename = "output.nb0" ;
140+
141+ if (argc == 4 )
142+ {
143+ prg_filename = argv [1 ];
144+ ver_filename = argv [2 ];
145+ nb0_filename = argv [3 ];
146+ }
147+
148+ printf ("Patching: PRG='%s', VER='%s', NB0='%s' ...\n" , prg_filename , ver_filename , nb0_filename );
149+
150+ // read content of nb0 file into memory
151+ FILE * nb0_file = fopen (nb0_filename , "rb" );
152+ if (nb0_file == NULL )
153+ {
154+ printf ("Can't read nb0 file with name '%s'\n" , nb0_filename );
155+ exit (2 );
156+ }
157+ fseek (nb0_file , 0L , SEEK_END );
158+ long nb0_file_size = ftell (nb0_file );
159+ fseek (nb0_file , 0L , SEEK_SET );
160+ void * nb0_buffer = malloc (nb0_file_size );
161+ if (nb0_buffer == NULL )
162+ {
163+ printf ("Can't allocate memory for nb0!\n" );
164+ exit (2 );
165+ }
166+ fread (nb0_buffer , 1 , nb0_file_size , nb0_file );
167+ fclose (nb0_file );
168+ printf ("Read %d bytes from nb0 file with name '%s'\n" , nb0_file_size , nb0_filename );
169+
170+ // read existing header of PRG file
171+ FILE * prg_file = fopen (prg_filename , "rb" );
172+ if (prg_file == NULL )
173+ {
174+ printf ("Can't open PRG file with name '%s'\n" , prg_filename );
175+ exit (2 );
176+ }
177+ header_typeprg prg_header ;
178+ fread (& prg_header , sizeof (header_typeprg ), 1 , prg_file );
179+ fclose (prg_file );
180+
181+ printf ("Read original PRG header version=%x , date='%s'\n" , prg_header .version , prg_header .filedate );
182+
183+ // patching PRG header
184+ prg_header .file_length_prg = prg_header .file_length = nb0_file_size ;
185+ int old_prg_version = prg_header .version ;
186+ prg_header .version = prg_header .version + 1 ;
187+ prg_header .file_crc = prg_header .file_crc1 = checksum32 (nb0_buffer , nb0_file_size );
188+ prg_header .ver_crc = checksum32 (& prg_header , sizeof (prg_header ) - 4 );
189+
190+ long prg_file_new_size = nb0_file_size + sizeof (prg_header );
191+ unsigned char * prg_buffer = malloc (prg_file_new_size );
192+ memcpy (prg_buffer , & prg_header , sizeof (prg_header ));
193+ memcpy (prg_buffer + sizeof (prg_header ), nb0_buffer , nb0_file_size );
194+
195+ FILE * prg_file_new = fopen (prg_filename , "wb" );
196+ fwrite (prg_buffer , 1 , prg_file_new_size , prg_file_new );
197+ fclose (prg_file_new );
198+
199+ printf ("PRG file '%s' successfully patched version %x -> %x .\n" , prg_filename , old_prg_version , prg_header .version );
200+
201+ //reading existing header from VER file
202+ FILE * ver_file = fopen (ver_filename , "rb" );
203+ if (ver_file == NULL )
204+ {
205+ printf ("Can't open VER file with name '%s'\n" , ver_filename );
206+ exit (2 );
207+ }
208+ fseek (ver_file , 0L , SEEK_END );
209+ long ver_file_size = ftell (ver_file );
210+ fseek (ver_file , 0L , SEEK_SET );
211+
212+ unsigned char * ver_buffer = malloc (ver_file_size );
213+ fread (ver_buffer , 1 , ver_file_size , ver_file );
214+ fclose (ver_file );
215+
216+
217+ //patching VER header
218+ header_type * ver_header = (header_type * )ver_buffer ;
219+ char filename_ansi [1024 ];
220+ wcstombs (filename_ansi , ver_header -> filename , 1024 );
221+ if (strcmp (filename_ansi , prg_filename ) != 0 )
222+ {
223+ printf ("Can't replace file with name '%s' to '%s' in VER file\n" , filename_ansi , prg_filename );
224+ exit (2 );
225+ }
226+
227+ int old_ver_version = ver_header -> version ;
228+ ver_header -> version = ver_header -> version1 = ver_header -> version + 1 ;
229+ ver_header -> nb0_length = prg_header .file_length ;
230+ ver_header -> nb0_crc = prg_header .file_crc ;
231+ ver_header -> file_length = prg_file_new_size ;
232+ ver_header -> file_crc = crc32b (prg_buffer , prg_file_new_size );
233+ int * ver_crc_ptr = (int * )(ver_buffer + ver_file_size - 4 );
234+ * ver_crc_ptr = crc32b (ver_buffer , ver_file_size - 4 );
235+
236+ //reading existing header from VER file
237+ FILE * ver_file_new = fopen (ver_filename , "wb" );
238+ fwrite (ver_buffer , 1 , ver_file_size , ver_file_new );
239+ fclose (ver_file_new );
240+
241+ printf ("VER file '%s' successfully patched. version %x -> %x .\n" , ver_filename , old_ver_version , ver_header -> version );
242+
243+ printf ("OK\n" );
244+
245+ }
0 commit comments