Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/quicknes/nes_emu/Nes_File.cpp
2 views
1
2
// Nes_Emu 0.7.0. http://www.slack.net/~ant/
3
4
#include "Nes_File.h"
5
6
#include "blargg_endian.h"
7
8
/* Copyright (C) 2004-2006 Shay Green. This module is free software; you
9
can redistribute it and/or modify it under the terms of the GNU Lesser
10
General Public License as published by the Free Software Foundation; either
11
version 2.1 of the License, or (at your option) any later version. This
12
module is distributed in the hope that it will be useful, but WITHOUT ANY
13
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
15
more details. You should have received a copy of the GNU Lesser General
16
Public License along with this module; if not, write to the Free Software
17
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
18
19
#include "blargg_source.h"
20
21
// Nes_File_Writer
22
23
Nes_File_Writer::Nes_File_Writer()
24
{
25
write_remain = 0;
26
depth_ = 0;
27
}
28
29
Nes_File_Writer::~Nes_File_Writer()
30
{
31
}
32
33
blargg_err_t Nes_File_Writer::begin( Auto_File_Writer dw, nes_tag_t tag )
34
{
35
require( !out );
36
out = dw;
37
RETURN_ERR( out.open_comp() );
38
return begin_group( tag );
39
}
40
41
blargg_err_t Nes_File_Writer::begin_group( nes_tag_t tag )
42
{
43
depth_++;
44
return write_header( tag, group_begin_size );
45
}
46
47
blargg_err_t Nes_File_Writer::write_header( nes_tag_t tag, long size )
48
{
49
nes_block_t h;
50
h.tag = tag;
51
h.size = size;
52
h.swap();
53
return out->write( &h, sizeof h );
54
}
55
56
blargg_err_t Nes_File_Writer::write_block( nes_tag_t tag, void const* data, long size )
57
{
58
RETURN_ERR( write_block_header( tag, size ) );
59
return write( data, size );
60
}
61
62
blargg_err_t Nes_File_Writer::write_block_header( nes_tag_t tag, long size )
63
{
64
require( !write_remain );
65
write_remain = size;
66
return write_header( tag, size );
67
}
68
69
Nes_File_Writer::error_t Nes_File_Writer::write( void const* p, long s )
70
{
71
write_remain -= s;
72
require( write_remain >= 0 );
73
return out->write( p, s );
74
}
75
76
blargg_err_t Nes_File_Writer::end()
77
{
78
require( depth_ == 1 );
79
return end_group();
80
}
81
82
blargg_err_t Nes_File_Writer::end_group()
83
{
84
require( depth_ > 0 );
85
depth_--;
86
return write_header( group_end_tag, 0 );
87
}
88
89
// Nes_File_Reader
90
91
Nes_File_Reader::Nes_File_Reader()
92
{
93
h.tag = 0;
94
h.size = 0;
95
block_type_ = invalid;
96
depth_ = -1;
97
}
98
99
Nes_File_Reader::~Nes_File_Reader()
100
{
101
}
102
103
blargg_err_t Nes_File_Reader::read_block_data( void* p, long s )
104
{
105
long extra = remain();
106
if ( s > extra )
107
s = extra;
108
extra -= s;
109
RETURN_ERR( read( p, s ) );
110
if ( extra )
111
RETURN_ERR( skip( extra ) );
112
return 0;
113
}
114
115
blargg_err_t Nes_File_Reader::begin( Auto_File_Reader dr )
116
{
117
require( !in );
118
RETURN_ERR( dr.open() );
119
in = dr;
120
RETURN_ERR( read_header() );
121
if ( block_type() != group_begin )
122
return "File is wrong type";
123
return enter_group();
124
}
125
126
blargg_err_t Nes_File_Reader::read_header()
127
{
128
RETURN_ERR( in->read( &h, sizeof h ) );
129
h.swap();
130
block_type_ = data_block;
131
if ( h.size == group_begin_size )
132
{
133
block_type_ = group_begin;
134
h.size = 0;
135
}
136
if ( (long) h.tag == group_end_tag )
137
{
138
block_type_ = group_end;
139
h.tag = 0;
140
}
141
set_remain( h.size );
142
return 0;
143
}
144
145
blargg_err_t Nes_File_Reader::next_block()
146
{
147
require( depth() >= 0 );
148
switch ( block_type() )
149
{
150
case group_end:
151
require( false );
152
return "Tried to go past end of blocks";
153
154
case group_begin: {
155
int d = 1;
156
do
157
{
158
RETURN_ERR( skip( h.size ) );
159
RETURN_ERR( read_header() );
160
if ( block_type() == group_begin )
161
d++;
162
if ( block_type() == group_end )
163
d--;
164
}
165
while ( d > 0);
166
break;
167
}
168
169
case data_block:
170
RETURN_ERR( skip( h.size ) );
171
break;
172
173
case invalid:
174
break;
175
}
176
return read_header();
177
}
178
179
blargg_err_t Nes_File_Reader::enter_group()
180
{
181
require( block_type() == group_begin );
182
block_type_ = invalid; // cause next_block() not to skip group
183
depth_++;
184
return 0;
185
}
186
187
blargg_err_t Nes_File_Reader::exit_group()
188
{
189
require( depth() > 0 );
190
int d = 1;
191
while ( true )
192
{
193
if ( block_type() == group_end )
194
d--;
195
if ( block_type() == group_begin )
196
d++;
197
if ( d == 0 )
198
break;
199
RETURN_ERR( skip( h.size ) );
200
RETURN_ERR( read_header() );
201
}
202
203
block_type_ = invalid; // cause next_block() to read past end block
204
depth_--;
205
return 0;
206
}
207
208
blargg_err_t Nes_File_Reader::skip_v( int s )
209
{
210
require( block_type() == data_block );
211
if ( (unsigned long) s > h.size )
212
return "Tried to skip past end of data";
213
h.size -= s;
214
set_remain( h.size );
215
return in->skip( s );
216
}
217
218
blargg_err_t Nes_File_Reader::read_v( void* p, int n )
219
{
220
require( block_type() == data_block );
221
if ( (unsigned long) n > h.size )
222
n = h.size;
223
h.size -= n;
224
set_remain( h.size );
225
return in->read( p, n );
226
}
227
228