1 /* -*- C++ -*-
2 *
3 * NsaReader.cpp - Reader from a NSA archive
4 *
5 * Copyright (c) 2001-2019 Ogapee. All rights reserved.
6 *
7 * ogapee@aqua.dti2.ne.jp
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24 #include "NsaReader.h"
25 #include <string.h>
26
NsaReader(unsigned int nsa_offset,char * path,int archive_type,const unsigned char * key_table)27 NsaReader::NsaReader( unsigned int nsa_offset, char *path, int archive_type, const unsigned char *key_table )
28 :SarReader( path, key_table )
29 {
30 sar_flag = true;
31 this->nsa_offset = nsa_offset;
32 this->archive_type = archive_type;
33 num_of_nsa_archives[0] = 0;
34 num_of_nsa_archives[1] = 0;
35 num_of_ns2_archives = 0;
36
37 if (key_table)
38 nsa_archive_ext = "___";
39 else
40 nsa_archive_ext = "nsa";
41
42 ns2_archive_ext = "ns2";
43 }
44
~NsaReader()45 NsaReader::~NsaReader()
46 {
47 }
48
open(const char * nsa_path)49 int NsaReader::open( const char *nsa_path )
50 {
51 bool archive_found = false;
52 char archive_name[256];
53
54 if (!SarReader::open("arc.sar")) return 0;
55
56 sar_flag = false;
57
58 if (archive_type & ARCHIVE_TYPE_NS2){
59 for (int i=0; i<MAX_NS2_ARCHIVE; i++){
60 sprintf(archive_name, "%s%02d.%s", nsa_path?nsa_path:"", i, ns2_archive_ext);
61 if ((archive_info_ns2[i].file_handle = fopen(archive_name, "rb")) == NULL) break;
62
63 ArchiveInfo *ai = &archive_info_ns2[i];
64 archive_found = true;
65 ai->file_name = new char[strlen(archive_name)+1];
66 memcpy(ai->file_name, archive_name, strlen(archive_name)+1);
67 readArchive(ai, ARCHIVE_TYPE_NS2, nsa_offset);
68 num_of_ns2_archives = i+1;
69 }
70 }
71
72 if (num_of_ns2_archives ==0 && archive_type & ARCHIVE_TYPE_NSA){
73 for (int k=0; k<2; k++){
74 for (int i=-1; i<MAX_EXTRA_ARCHIVE; i++){
75 ArchiveInfo *ai;
76
77 if (i == -1){
78 sprintf(archive_name, "%s%sarc.%s", nsa_path?nsa_path:"", k==0?"patch/":"", nsa_archive_ext);
79 ai = k==0?(&archive_info_patch):(&archive_info);
80 }
81 else{
82 sprintf(archive_name, "%s%sarc%d.%s", nsa_path?nsa_path:"", k==0?"patch/":"", i+1, nsa_archive_ext);
83 ai = &archive_info2[k][i];
84 }
85
86 if ((ai->file_handle = fopen(archive_name, "rb")) == NULL) break;
87
88 archive_found = true;
89 ai->file_name = new char[strlen(archive_name)+1];
90 memcpy(ai->file_name, archive_name, strlen(archive_name)+1);
91 readArchive(ai, ARCHIVE_TYPE_NSA, nsa_offset);
92 num_of_nsa_archives[k] = i+1;
93 }
94 }
95 }
96
97 if (!archive_found) return -1;
98
99 return 0;
100 }
101
openForConvert(char * nsa_name,int archive_type,unsigned int nsa_offset)102 int NsaReader::openForConvert( char *nsa_name, int archive_type, unsigned int nsa_offset )
103 {
104 sar_flag = false;
105 if ( ( archive_info.file_handle = ::fopen( nsa_name, "rb" ) ) == NULL ){
106 fprintf( stderr, "can't open file %s\n", nsa_name );
107 return -1;
108 }
109
110 readArchive( &archive_info, archive_type, nsa_offset );
111
112 return 0;
113 }
114
writeHeader(FILE * fp,int archive_type,int nsa_offset)115 int NsaReader::writeHeader( FILE *fp, int archive_type, int nsa_offset )
116 {
117 ArchiveInfo *ai = &archive_info;
118 return writeHeaderSub( ai, fp, archive_type, nsa_offset );
119 }
120
putFile(FILE * fp,int no,size_t offset,size_t length,size_t original_length,int compression_type,bool modified_flag,unsigned char * buffer)121 size_t NsaReader::putFile( FILE *fp, int no, size_t offset, size_t length, size_t original_length, int compression_type, bool modified_flag, unsigned char *buffer )
122 {
123 ArchiveInfo *ai = &archive_info;
124 return putFileSub( ai, fp, no, offset, length, original_length , compression_type, modified_flag, buffer );
125 }
126
getArchiveName() const127 const char *NsaReader::getArchiveName() const
128 {
129 return "nsa";
130 }
131
getNumFiles()132 int NsaReader::getNumFiles()
133 {
134 int total = 0;
135
136 ArchiveInfo* ai[2] = {&archive_info_patch, &archive_info};
137 for (int k=0; k<2; k++){
138 total += ai[k]->num_of_files;
139 for (int i=0; i<num_of_nsa_archives[k]; i++)
140 total += archive_info2[k][i].num_of_files;
141 }
142
143 for (int i=0; i<num_of_ns2_archives; i++)
144 total += archive_info_ns2[i].num_of_files;
145
146 return total;
147 }
148
getFileLengthSub(ArchiveInfo * ai,const char * file_name)149 size_t NsaReader::getFileLengthSub( ArchiveInfo *ai, const char *file_name )
150 {
151 unsigned int i = getIndexFromFile( ai, file_name );
152
153 if ( i == ai->num_of_files ) return 0;
154
155 if ( ai->fi_list[i].original_length != 0 )
156 return ai->fi_list[i].original_length;
157
158 int type = ai->fi_list[i].compression_type;
159 if ( type == NO_COMPRESSION )
160 type = getRegisteredCompressionType( file_name );
161 if ( type == NBZ_COMPRESSION || type == SPB_COMPRESSION ) {
162 ai->fi_list[i].original_length = getDecompressedFileLength( type, ai->file_handle, ai->fi_list[i].offset );
163 }
164
165 return ai->fi_list[i].original_length;
166 }
167
getFileLength(const char * file_name)168 size_t NsaReader::getFileLength(const char *file_name)
169 {
170 if (sar_flag) return SarReader::getFileLength(file_name);
171
172 size_t ret;
173
174 if ((ret = DirectReader::getFileLength(file_name))) return ret;
175
176 for (int i=0; i<num_of_ns2_archives; i++)
177 if ((ret = getFileLengthSub(&archive_info_ns2[i], file_name))) return ret;
178
179 ArchiveInfo* ai[2] = {&archive_info_patch, &archive_info};
180 for (int k=0; k<2; k++){
181 if ((ret = getFileLengthSub(ai[k], file_name))) return ret;
182
183 for (int i=0; i<num_of_nsa_archives[k]; i++)
184 if ((ret = getFileLengthSub(&archive_info2[k][i], file_name))) return ret;
185 }
186
187 return 0;
188 }
189
getFile(const char * file_name,unsigned char * buffer,int * location)190 size_t NsaReader::getFile(const char *file_name, unsigned char *buffer, int *location)
191 {
192 size_t ret;
193
194 if (sar_flag) return SarReader::getFile( file_name, buffer, location );
195
196 if ((ret = DirectReader::getFile(file_name, buffer, location))) return ret;
197
198 for (int i=0; i<num_of_ns2_archives; i++){
199 if ((ret = getFileSub(&archive_info_ns2[i], file_name, buffer))){
200 if (location) *location = ARCHIVE_TYPE_NS2;
201 return ret;
202 }
203 }
204
205 ArchiveInfo* ai[2] = {&archive_info_patch, &archive_info};
206 for (int k=0; k<2; k++){
207 if ((ret = getFileSub(ai[k], file_name, buffer))){
208 if (location) *location = ARCHIVE_TYPE_NSA;
209 return ret;
210 }
211
212 for (int i=0; i<num_of_nsa_archives[k]; i++){
213 if ((ret = getFileSub(&archive_info2[k][i], file_name, buffer))){
214 if (location) *location = ARCHIVE_TYPE_NSA;
215 return ret;
216 }
217 }
218 }
219
220 return 0;
221 }
222
getFileByIndex(unsigned int index)223 NsaReader::FileInfo NsaReader::getFileByIndex(unsigned int index)
224 {
225 for (int i=0; i<num_of_ns2_archives; i++){
226 if (index < archive_info_ns2[i].num_of_files) return archive_info_ns2[i].fi_list[index];
227 index -= archive_info_ns2[i].num_of_files;
228 }
229
230 ArchiveInfo* ai[2] = {&archive_info_patch, &archive_info};
231 for (int k=0; k<2; k++){
232 if (index < ai[k]->num_of_files) return archive_info.fi_list[index];
233 index -= ai[k]->num_of_files;
234
235 for (int i=0; i<num_of_nsa_archives[k]; i++){
236 if (index < archive_info2[k][i].num_of_files) return archive_info2[k][i].fi_list[index];
237 index -= archive_info2[k][i].num_of_files;
238 }
239 }
240
241 fprintf( stderr, "NsaReader::getFileByIndex Index %d is out of range\n", index );
242
243 return archive_info.fi_list[0];
244 }
245