2 * Copyright (c) 2007-2013, Czirkos Zoltan http://code.google.com/p/gdash/
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 #include "fileops/loadfile.hpp"
19 #include <glib/gi18n.h>
22 #include "cave/caveset.hpp"
23 #include "fileops/binaryimport.hpp"
24 #include "fileops/brcimport.hpp"
25 #include "fileops/c64import.hpp"
26 #include "fileops/bdcffload.hpp"
27 #include "misc/logger.hpp"
28 #include "misc/util.hpp"
30 /** load some caveset from the binary data in the buffer.
31 * the length may be -1, if the caller is pretty sure of what he's doing. */
32 CaveSet
create_from_buffer(const unsigned char *buffer
, int length
, char const *filename
) {
33 /* set logging context to filename */
34 SetLoggerContextForFunction
finally(gd_tostring_free(g_filename_display_basename(filename
)));
36 /* try to load as a .GDS file */
37 if ((length
>= 12 || length
== -1) && C64Import::imported_get_format(buffer
) != C64Import::GD_FORMAT_UNKNOWN
) {
38 std::vector
<CaveStored
*> new_caveset
= C64Import::caves_import_from_buffer(buffer
, length
);
39 /* if unable to load, exit here. error was reported by import_from_buffer() */
40 if (new_caveset
.empty())
41 throw std::runtime_error(_("Error loading GDS file."));
42 /* no serious error :) */
44 for (std::vector
<CaveStored
*>::iterator it
=new_caveset
.begin(); it
!=new_caveset
.end(); ++it
)
45 newcaves
.caves
.push_back_adopt(*it
);
46 newcaves
.last_selected_cave
=newcaves
.first_selectable_cave_index();
47 newcaves
.set_name_from_filename(filename
);
51 /* try to load as a BRC file (boulder remake) */
52 if (g_str_has_suffix(filename
, ".brc") || g_str_has_suffix(filename
, "*.BRC")) {
53 if (length
!= 96000) {
54 throw std::runtime_error(_("BRC files must be 96000 bytes long."));
57 brc_import(newcaves
, (guint8
*) buffer
);
58 newcaves
.last_selected_cave
= newcaves
.first_selectable_cave_index();
59 newcaves
.set_name_from_filename(filename
);
63 /* try to load as BDCFF */
64 if (g_str_has_suffix(filename
, ".bd") || g_str_has_suffix(filename
, ".BD")) {
65 CaveSet newcaves
= load_from_bdcff((char const *) buffer
);
66 newcaves
.last_selected_cave
= newcaves
.first_selectable_cave_index();
67 /* remember filename, as the input is a bdcff file */
68 newcaves
.filename
= filename
;
72 /* if could not determine file format so far, try to load as a snapshot file */
73 if (g_str_has_suffix(filename
, ".vsf") || g_str_has_suffix(filename
, ".VSF")
74 || length
== 65536 || length
== 65538) {
75 std::vector
<unsigned char> memory
= load_memory_dump(buffer
, length
);
76 std::vector
<unsigned char> imported
= gdash_binary_import(memory
);
77 return create_from_buffer(&imported
[0], imported
.size(), filename
);
80 throw std::runtime_error(_("Cannot determine file format."));
85 * Create a caveset by loading it from a file.
86 * @param filename The name of the file, which can be BDCFF or other binary formats.
87 * @return The caveset loaded. If impossible to load, throws an exception.
89 CaveSet
create_from_file(const char *filename
) throw (std::runtime_error
) {
90 std::vector
<unsigned char> contents
= load_file_to_vector(filename
);
91 /* -1 because the loader adds a terminating zero */
92 return create_from_buffer(&contents
[0], contents
.size()-1, filename
);
97 * Load a file to an array of bytes.
98 * @param filename The name of the file.
99 * @return The file loaded. If impossible to load, throws an exception.
101 std::vector
<unsigned char> load_file_to_vector(char const *filename
) {
104 is
.open(filename
, std::ios::in
| std::ios::binary
);
106 throw std::runtime_error(_("Unable to open file."));
109 int filesize
= is
.tellg();
111 if (filesize
> (2 * 1<<20))
112 throw std::runtime_error(_("File bigger than 2MiB, refusing to load."));
113 /* read file. the vector will be one bytes bigger, so it can be added a terminating zero char. */
114 std::vector
<unsigned char> contents(filesize
+1);
115 if (!is
.read((char *) &contents
[0], filesize
))
116 throw std::runtime_error(_("Unable to read file."));
118 contents
[filesize
] = '\0';