1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
//! The sprite sheet compiler, for compiling a set of sprite sheets into a pattern table and C/ASM headers.
//!
//! The usage can be retrieved exactly how you'd expect:
//!
//! ```sh
//! $ spritesheetc -h
//! Usage: spritesheetc [options]
//!
//! Options:
//! -i, --input FILE input yaml description file. Defaults to stdin.
//! -o, --char FILE output NES char file name. Defaults to stdout.
//! -c, --header FILE output C header file name. Not generated if not specified.
//! -a, --asm FILE output asm header file name. Not generated if not specified.
//! -p, --prefix PREFIX the prefix for the header defines. Defaults to blank.
//! -h, --help print this help menu
//! ```
//!
//! The format of the input file should be a YAML file that is deserializable by serde_yaml. An
//! example input might look something like this:
//!
//! ```yaml
//! left:
//! - type: Animation
//! file: first.png
//! frame_height: 2
//! frame_width: 2
//! frames: 4
//! name: first
//! - type: Slice
//! file: second.png
//! height: 4
//! name: second
//! slices:
//! - [15, 12, 7]
//! - [0, 4, 5]
//! width: 4
//! right:
//! - type: Fill
//! value: 0
//! count: 1
//! - type: Simple
//! file: third.png
//! height: 8
//! name: third
//! width: 8
//! - type: Animation
//! file: fourth.png
//! frame_height: 4
//! frame_width: 3
//! frames: 3
//! name: fourth
//! ```
//!
//! The sheet types are described in in
//! [`nestools::sprites::sheet`](sprites/sheet/enum.Sheet.html), but should be largely
//! self-explanatory. The tiles are loaded into their relevant section of the PatternTable in
//! order, tightly-packed, and the remaining tiles are filled with blanks. All file paths are
//! processed relative to your current working directory.
//!
//! # Types
//!
//! Each type is specified in the individual sprite's `type` attribute. All types have a `file`
//! field and a `name` field. The `file` field is the png file that the sprite is extracted from.
//! The `name` field is used as the `NAME` part of the generated C/ASM header field, as described
//! in the individual type below. `PREFIX` is set by the program in a flag. `SHEET` is either LEFT
//! or RIGHT
//!
//! In this readme, "tile" refers to a single 8x8 pixel NES tile, "sprite" refers to one or more of
//! these tiles as intended to be rendered to form something on the screen, and "sheet" or "sprite
//! sheet" refers to the sprites as laid out before being pulled in. In this way, these types are
//! "sprites", and they pull in "sheets", in order to generate "tiles", and header files with names
//! referring to the indices of the "tiles" in their respective pattern table.
//!
//! ## Fill
//!
//! The simplest sprite type. Simply uses the value given and fills the tile with it. Useful for
//! blank background tiles, solid fill tiles that don't need files, and for explicitly spacing out
//! other tiles (though that shouldn't be very useful). Primarily, it's just a filler to make it
//! easy to default all background tiles to a blank background while selectively filling real
//! background tiles where needed.
//!
//! ### Attributes
//!
//! * `value`
//! * A value from 0 to 3 inclusive, stating which index to use to fill the tile.
//! * `count`
//! * The number of tiles to fill with this value.
//!
//! ### Name
//!
//! This sprite's parts in the files generated will be
//! `{PREFIX}{SHEET}_{NAME}_{TILE}`, where `TILE` ranges from `0` up to but not including `count`.
//!
//! ## Simple
//!
//! The simplest file sprite type, typically useful for individual 8x8 tiles that are related and
//! may be useful to be contiguous, such as numbers or alphabet tiles, or sets of scenery tiles for
//! laying out. The sprite sheet is used as a whole, and numbered from left-to-right,
//! top-to-bottom.
//!
//! ### Attributes
//!
//! * `height`
//! * The height of the sheet in tiles (that is, in `pixels / 8`)
//! * `width`
//! * The width of the sheet in tiles (that is, in `pixels / 8`)
//!
//! ### Name
//!
//! This sprite's parts in the files generated will be
//! `{PREFIX}{SHEET}_{NAME}_{TILE}`, where `TILE` ranges from `0` up to but not including `height *
//! width`.
//!
//! ## Animation
//!
//! A type that is used for animated sprites of a solid size. This isn't ideal for things like
//! Mega Man, which use partially-animated sprites to save space. It works fine for things like
//! Mario, which use a fully animated sprite that has every tile change with every animation frame.
//! Animations are expected to have a horizontal layout, with each frame to the right of its
//! previous one. This can also be useful simply for a set of related sprites of the same size
//! that can easily share a name, like a set of 16x16 number tiles. The sheet is pulled in and
//! divided into `frames` frames each `frame_width` in width, which are then divided into
//! `frame_width * frame_height` tiles each.
//!
//! ### Attributes
//!
//! * `frame_height`
//! * The height of an individual frame in tiles (that is, in `pixels / 8`)
//! * `frame_width`
//! * The width of an individual frame in tiles (that is, in `pixels / 8`)
//! * `frames`
//! * The actual amount of frames in the sheet
//!
//! The total width of the sheet in pixels is therefore `8 * frame_width * frames`
//!
//! ### Name
//!
//! This sprite's parts in the files generated will be
//! `{PREFIX}{SHEET}_{NAME}_{FRAME}_{FRAMETILE}`, where `FRAME` ranges from `0` up to but not
//! including `frames`, arranged left-to-right top-to-bottom, and `FRAMETILE` ranges from `0` up to
//! but not including `frame_width * frame_height`, arranged within the frame left-to-right and
//! top-to-bottom.
//!
//! ## Slice
//!
//! A sprite type for frames that should be divided into chunks, like `Animation`, but not chunks
//! that can easily be laid out in the same arrangement or aren't all necessarily the same size.
//! This can be useful for partially-animated sprites like in MegaMan, but in a way that doesn't
//! force you to use two different sprites (an `Animation` bottom and a `Simple` top, for
//! instance, or having to do the whole thing with a `Simple`). This is also useful for pieces of
//! scenery and things that should share a name but not necessarily have the same size. The
//! `Slice` format also allows you to throw away unused tiles, so you can arrange them however you
//! like in your sheet and not worry about blank space, which won't take up space in your pattern
//! table.
//!
//! ### Attributes
//!
//! * `height`
//! * The height of the sheet in tiles (that is, in `pixels / 8`)
//! * `width`
//! * The width of the sheet in tiles (that is, in `pixels / 8`)
//! * `slices`
//! * An array of arrays. Each inner array is a list of numbers each specifying an individual
//! tile in the sheet (indexed in the usual left-to-right, top-to-bottom manner)
//!
//! The total width of the sheet in pixels is therefore `8 * frame_width * frames`
//!
//! ### Name
//!
//! This sprite's parts in the files generated will be
//! `{PREFIX}{SHEET}_{NAME}_{SLICE}_{SLICETILE}`, where `SLICE` ranges from `0` up to but not
//! including the number of sub-arrays in `slices`, in the order specified, and `SLICETILE` ranges
//! from `0` up to but not including the size of the slice in question, also in the order
//! specified.
extern crate serde_yaml;
use ;
use File;
use error;
use fmt;
use SheetPatternTable;
use PatternTable;
/// Config type, built from command line or however you'd like.
/// Simple boxing error type for easier handling.
/// Write out the C header file. This is used as an easy grouping mechanism in order to catch all
/// possible IO errors and report them with a helpful error message.
/// Write out the ASM header file. This is used as an easy grouping mechanism in order to catch
/// all possible IO errors and report them with a helpful error message.
/// Entry point for actual running. Propagates all errors upward.