// Filename: p3dEmbed.cxx // Created by: rdb (07Dec09) // //////////////////////////////////////////////////////////////////// // // PANDA 3D SOFTWARE // Copyright (c) Carnegie Mellon University. All rights reserved. // // All use of this software is subject to the terms of the revised BSD // license. You should have received a copy of this license along // with this source code in a file named "LICENSE." // //////////////////////////////////////////////////////////////////// #define P3D_FUNCTION_PROTOTYPES #include "p3dEmbed.h" #include "load_plugin.h" //////////////////////////////////////////////////////////////////// // Function: P3DEmbed::Constructor // Access: Public // Description: //////////////////////////////////////////////////////////////////// P3DEmbed:: P3DEmbed(bool console_environment) : Panda3DBase(console_environment) { } //////////////////////////////////////////////////////////////////// // Function: P3DEmbed::run_embedded // Access: Public // Description: Runs with the data embedded in the current // executable, at the specified offset. //////////////////////////////////////////////////////////////////// int P3DEmbed:: run_embedded(streampos read_offset, int argc, char *argv[]) { // Check to see if we've actually got an application embedded. If // we do, read_offset will have been modified to contain a different // value than the one we compiled in, above. We test against // read_offset + 1, because any appearances of this exact number // within the binary will be replaced (including this one). // We also have to store this computation in a member variable, to // work around a compiler optimization that might otherwise remove // the + 1 from the test. _read_offset_check = read_offset + (streampos)1; if (_read_offset_check == (streampos)0xFF3D3D01) { cerr << "This program is not intended to be run directly.\nIt is used by pdeploy to construct an embedded Panda3D application.\n"; return 1; } // Make sure the splash window will be put in the center of the screen _win_x = -2; _win_y = -2; // Read out some parameters from the binary pifstream read; Filename f = ExecutionEnvironment::get_binary_name(); f.make_absolute(); f.set_binary(); if (!f.open_read(read)) { cerr << "Failed to read from stream. Maybe the binary is corrupt?\n"; return 1; } read.seekg(read_offset); int curchr = read.get(); if (curchr == EOF) { cerr << "Couldn't seek to " << read_offset << "\n"; return 1; } string curstr; bool havenull = false; P3D_token token; token._keyword = NULL; token._value = NULL; string keyword; string value; string root_dir; while (true) { if (curchr == EOF) { cerr << "Truncated stream\n"; return(1); } else if (curchr == 0) { // Two null bytes in a row means we've reached the end of the data. if (havenull) { break; } // This means we haven't seen an '=' character yet. if (keyword == "") { if (curstr != "") { cerr << "Ignoring token '" << curstr << "' without value\n"; } } else { value.assign(curstr); P3D_token token; token._keyword = strdup(keyword.c_str()); token._value = strdup(value.c_str()); _tokens.push_back(token); // Read out the tokens that may interest us if (keyword == "width") { _win_width = atoi(value.c_str()); } else if (keyword == "height") { _win_height = atoi(value.c_str()); } else if (keyword == "root_dir") { root_dir = value; } } curstr = ""; havenull = true; } else if (curchr == '=') { keyword.assign(curstr); curstr = ""; havenull = false; } else { curstr += curchr; havenull = false; } curchr = read.get(); } // Update the offset to the current read pointer. // This is where the multifile really starts. read_offset = read.tellg(); read.close(); // Make the root directory absolute Filename root_dir_f(root_dir); root_dir_f.make_absolute(f.get_dirname()); // Initialize the core API by directly assigning all of the function // pointers. P3D_initialize_ptr = &P3D_initialize; P3D_finalize_ptr = &P3D_finalize; P3D_set_plugin_version_ptr = &P3D_set_plugin_version; P3D_set_super_mirror_ptr = &P3D_set_super_mirror; P3D_new_instance_ptr = &P3D_new_instance; P3D_instance_start_ptr = &P3D_instance_start; P3D_instance_start_stream_ptr = &P3D_instance_start_stream; P3D_instance_finish_ptr = &P3D_instance_finish; P3D_instance_setup_window_ptr = &P3D_instance_setup_window; P3D_object_get_type_ptr = &P3D_object_get_type; P3D_object_get_bool_ptr = &P3D_object_get_bool; P3D_object_get_int_ptr = &P3D_object_get_int; P3D_object_get_float_ptr = &P3D_object_get_float; P3D_object_get_string_ptr = &P3D_object_get_string; P3D_object_get_repr_ptr = &P3D_object_get_repr; P3D_object_get_property_ptr = &P3D_object_get_property; P3D_object_set_property_ptr = &P3D_object_set_property; P3D_object_has_method_ptr = &P3D_object_has_method; P3D_object_call_ptr = &P3D_object_call; P3D_object_eval_ptr = &P3D_object_eval; P3D_object_incref_ptr = &P3D_object_incref; P3D_object_decref_ptr = &P3D_object_decref; P3D_make_class_definition_ptr = &P3D_make_class_definition; P3D_new_undefined_object_ptr = &P3D_new_undefined_object; P3D_new_none_object_ptr = &P3D_new_none_object; P3D_new_bool_object_ptr = &P3D_new_bool_object; P3D_new_int_object_ptr = &P3D_new_int_object; P3D_new_float_object_ptr = &P3D_new_float_object; P3D_new_string_object_ptr = &P3D_new_string_object; P3D_instance_get_panda_script_object_ptr = &P3D_instance_get_panda_script_object; P3D_instance_set_browser_script_object_ptr = &P3D_instance_set_browser_script_object; P3D_instance_get_request_ptr = &P3D_instance_get_request; P3D_check_request_ptr = &P3D_check_request; P3D_request_finish_ptr = &P3D_request_finish; P3D_instance_feed_url_stream_ptr = &P3D_instance_feed_url_stream; P3D_instance_handle_event_ptr = &P3D_instance_handle_event; // Now call init_plugin() to verify that we got all of the required // function pointers. This will also call P3D_initialize(). if (!init_plugin("", _host_url, _verify_contents, _this_platform, _log_dirname, _log_basename, true, _console_environment, root_dir_f.to_os_specific(), cerr)) { cerr << "Unable to launch core API\n"; return 1; } // Create a plugin instance and run the program P3D_instance *inst = create_instance (f, true, _win_x, _win_y, _win_width, _win_height, argv, argc, read_offset); _instances.insert(inst); run_main_loop(); unload_plugin(); return 0; }