mirror of
https://github.com/holub/mame
synced 2025-07-01 16:19:38 +03:00
-emu/render.cpp: Load from all external artwork paths.
-emu/rendlay.cpp: Made real component drawing code a bit less gross. -emu/debugcon.cpp: Less screaming now that things aren't macros.
This commit is contained in:
parent
d6f7c7febf
commit
853fdf7542
@ -650,12 +650,12 @@ bool debugger_commands::debug_command_parameter_command(const char *param)
|
|||||||
|
|
||||||
/* validate the comment; success if no error */
|
/* validate the comment; success if no error */
|
||||||
CMDERR err = m_console.validate_command(param);
|
CMDERR err = m_console.validate_command(param);
|
||||||
if (err.ERROR_CLASS() == CMDERR::NONE)
|
if (err.error_class() == CMDERR::NONE)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
/* output an error */
|
/* output an error */
|
||||||
m_console.printf("Error in command: %s\n", param);
|
m_console.printf("Error in command: %s\n", param);
|
||||||
m_console.printf(" %*s^", err.ERROR_OFFSET(), "");
|
m_console.printf(" %*s^", err.error_offset(), "");
|
||||||
m_console.printf("%s\n", debugger_console::cmderr_to_string(err));
|
m_console.printf("%s\n", debugger_console::cmderr_to_string(err));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -250,7 +250,7 @@ CMDERR debugger_console::internal_execute_command(bool execute, int params, char
|
|||||||
|
|
||||||
/* no params is an error */
|
/* no params is an error */
|
||||||
if (params == 0)
|
if (params == 0)
|
||||||
return CMDERR(CMDERR::NONE, 0);
|
return CMDERR::none();
|
||||||
|
|
||||||
/* the first parameter has the command and the real first parameter; separate them */
|
/* the first parameter has the command and the real first parameter; separate them */
|
||||||
for (p = param[0]; *p && isspace(u8(*p)); p++) { }
|
for (p = param[0]; *p && isspace(u8(*p)); p++) { }
|
||||||
@ -287,9 +287,9 @@ CMDERR debugger_console::internal_execute_command(bool execute, int params, char
|
|||||||
|
|
||||||
/* error if not found */
|
/* error if not found */
|
||||||
if (!found)
|
if (!found)
|
||||||
return CMDERR::MAKE_UNKNOWN_COMMAND(0);
|
return CMDERR::unknown_command(0);
|
||||||
if (foundcount > 1)
|
if (foundcount > 1)
|
||||||
return CMDERR::MAKE_AMBIGUOUS_COMMAND(0);
|
return CMDERR::ambiguous_command(0);
|
||||||
|
|
||||||
/* NULL-terminate and trim space around all the parameters */
|
/* NULL-terminate and trim space around all the parameters */
|
||||||
for (i = 1; i < params; i++)
|
for (i = 1; i < params; i++)
|
||||||
@ -301,9 +301,9 @@ CMDERR debugger_console::internal_execute_command(bool execute, int params, char
|
|||||||
|
|
||||||
/* see if we have the right number of parameters */
|
/* see if we have the right number of parameters */
|
||||||
if (params < found->minparams)
|
if (params < found->minparams)
|
||||||
return CMDERR::MAKE_NOT_ENOUGH_PARAMS(0);
|
return CMDERR::not_enough_params(0);
|
||||||
if (params > found->maxparams)
|
if (params > found->maxparams)
|
||||||
return CMDERR::MAKE_TOO_MANY_PARAMS(0);
|
return CMDERR::too_many_params(0);
|
||||||
|
|
||||||
/* execute the handler */
|
/* execute the handler */
|
||||||
if (execute)
|
if (execute)
|
||||||
@ -311,7 +311,7 @@ CMDERR debugger_console::internal_execute_command(bool execute, int params, char
|
|||||||
std::vector<std::string> params_vec(param, param + params);
|
std::vector<std::string> params_vec(param, param + params);
|
||||||
found->handler(found->ref, params_vec);
|
found->handler(found->ref, params_vec);
|
||||||
}
|
}
|
||||||
return CMDERR(CMDERR::NONE, 0);
|
return CMDERR::none();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -353,9 +353,9 @@ CMDERR debugger_console::internal_parse_command(const std::string &original_comm
|
|||||||
case '(':
|
case '(':
|
||||||
case '[':
|
case '[':
|
||||||
case '{': parens[parendex++] = c; break;
|
case '{': parens[parendex++] = c; break;
|
||||||
case ')': if (parendex == 0 || parens[--parendex] != '(') return CMDERR::MAKE_UNBALANCED_PARENS(p - command); break;
|
case ')': if (parendex == 0 || parens[--parendex] != '(') return CMDERR::unbalanced_parens(p - command); break;
|
||||||
case ']': if (parendex == 0 || parens[--parendex] != '[') return CMDERR::MAKE_UNBALANCED_PARENS(p - command); break;
|
case ']': if (parendex == 0 || parens[--parendex] != '[') return CMDERR::unbalanced_parens(p - command); break;
|
||||||
case '}': if (parendex == 0 || parens[--parendex] != '{') return CMDERR::MAKE_UNBALANCED_PARENS(p - command); break;
|
case '}': if (parendex == 0 || parens[--parendex] != '{') return CMDERR::unbalanced_parens(p - command); break;
|
||||||
case ',': if (parendex == 0) params[paramcount++] = p; break;
|
case ',': if (parendex == 0) params[paramcount++] = p; break;
|
||||||
case ';': if (parendex == 0) foundend = true; break;
|
case ';': if (parendex == 0) foundend = true; break;
|
||||||
case '-': if (parendex == 0 && paramcount == 1 && p[1] == '-') isexpr = true; *p = c; break;
|
case '-': if (parendex == 0 && paramcount == 1 && p[1] == '-') isexpr = true; *p = c; break;
|
||||||
@ -369,9 +369,9 @@ CMDERR debugger_console::internal_parse_command(const std::string &original_comm
|
|||||||
|
|
||||||
/* check for unbalanced parentheses or quotes */
|
/* check for unbalanced parentheses or quotes */
|
||||||
if (instring)
|
if (instring)
|
||||||
return CMDERR::MAKE_UNBALANCED_QUOTES(p - command);
|
return CMDERR::unbalanced_quotes(p - command);
|
||||||
if (parendex != 0)
|
if (parendex != 0)
|
||||||
return CMDERR::MAKE_UNBALANCED_PARENS(p - command);
|
return CMDERR::unbalanced_parens(p - command);
|
||||||
|
|
||||||
/* NULL-terminate if we ended in a semicolon */
|
/* NULL-terminate if we ended in a semicolon */
|
||||||
p--;
|
p--;
|
||||||
@ -396,17 +396,17 @@ CMDERR debugger_console::internal_parse_command(const std::string &original_comm
|
|||||||
}
|
}
|
||||||
catch (expression_error &err)
|
catch (expression_error &err)
|
||||||
{
|
{
|
||||||
return CMDERR::MAKE_EXPRESSION_ERROR(err);
|
return CMDERR::expression_error(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const CMDERR result = internal_execute_command(execute, paramcount, ¶ms[0]);
|
const CMDERR result = internal_execute_command(execute, paramcount, ¶ms[0]);
|
||||||
if (result.ERROR_CLASS() != CMDERR::NONE)
|
if (result.error_class() != CMDERR::NONE)
|
||||||
return CMDERR(result.ERROR_CLASS(), command_start - command);
|
return CMDERR(result.error_class(), command_start - command);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return CMDERR(CMDERR::NONE, 0);
|
return CMDERR::none();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -424,11 +424,11 @@ CMDERR debugger_console::execute_command(const std::string &command, bool echo)
|
|||||||
const CMDERR result = internal_parse_command(command, true);
|
const CMDERR result = internal_parse_command(command, true);
|
||||||
|
|
||||||
/* display errors */
|
/* display errors */
|
||||||
if (result.ERROR_CLASS() != CMDERR::NONE)
|
if (result.error_class() != CMDERR::NONE)
|
||||||
{
|
{
|
||||||
if (!echo)
|
if (!echo)
|
||||||
printf(">%s\n", command.c_str());
|
printf(">%s\n", command.c_str());
|
||||||
printf(" %*s^\n", result.ERROR_OFFSET(), "");
|
printf(" %*s^\n", result.error_offset(), "");
|
||||||
printf("%s\n", cmderr_to_string(result).c_str());
|
printf("%s\n", cmderr_to_string(result).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -547,8 +547,8 @@ void debugger_console::process_source_file()
|
|||||||
|
|
||||||
std::string debugger_console::cmderr_to_string(CMDERR error)
|
std::string debugger_console::cmderr_to_string(CMDERR error)
|
||||||
{
|
{
|
||||||
const int offset = error.ERROR_OFFSET();
|
const int offset = error.error_offset();
|
||||||
switch (error.ERROR_CLASS())
|
switch (error.error_class())
|
||||||
{
|
{
|
||||||
case CMDERR::UNKNOWN_COMMAND: return "unknown command";
|
case CMDERR::UNKNOWN_COMMAND: return "unknown command";
|
||||||
case CMDERR::AMBIGUOUS_COMMAND: return "ambiguous command";
|
case CMDERR::AMBIGUOUS_COMMAND: return "ambiguous command";
|
||||||
|
@ -41,33 +41,37 @@ constexpr u32 CMDFLAG_CUSTOM_HELP = 0x0002;
|
|||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
// CMDERR is an error code for command evaluation
|
// CMDERR is an error code for command evaluation
|
||||||
struct CMDERR
|
class CMDERR
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
// values for the error code in a command error
|
// values for the error code in a command error
|
||||||
static constexpr u32 NONE = 0;
|
static constexpr u16 NONE = 0;
|
||||||
static constexpr u32 UNKNOWN_COMMAND = 1;
|
static constexpr u16 UNKNOWN_COMMAND = 1;
|
||||||
static constexpr u32 AMBIGUOUS_COMMAND = 2;
|
static constexpr u16 AMBIGUOUS_COMMAND = 2;
|
||||||
static constexpr u32 UNBALANCED_PARENS = 3;
|
static constexpr u16 UNBALANCED_PARENS = 3;
|
||||||
static constexpr u32 UNBALANCED_QUOTES = 4;
|
static constexpr u16 UNBALANCED_QUOTES = 4;
|
||||||
static constexpr u32 NOT_ENOUGH_PARAMS = 5;
|
static constexpr u16 NOT_ENOUGH_PARAMS = 5;
|
||||||
static constexpr u32 TOO_MANY_PARAMS = 6;
|
static constexpr u16 TOO_MANY_PARAMS = 6;
|
||||||
static constexpr u32 EXPRESSION_ERROR = 7;
|
static constexpr u16 EXPRESSION_ERROR = 7;
|
||||||
|
|
||||||
u32 val;
|
|
||||||
|
|
||||||
// command error assembly/disassembly
|
// command error assembly/disassembly
|
||||||
constexpr CMDERR(u32 a, u32 b) : val((a << 16) | (b & 0xffff)) { }
|
constexpr CMDERR(u16 c, u16 o) : m_error_class(c), m_error_offset(o) { }
|
||||||
constexpr u32 ERROR_CLASS() const { return val >> 16; }
|
constexpr u16 error_class() const { return m_error_class; }
|
||||||
constexpr u32 ERROR_OFFSET() const { return val & 0xffff; }
|
constexpr u16 error_offset() const { return m_error_offset; }
|
||||||
|
|
||||||
// assemble specific error conditions
|
// assemble specific error conditions
|
||||||
static constexpr CMDERR MAKE_UNKNOWN_COMMAND(u32 x) { return CMDERR(UNKNOWN_COMMAND, x); }
|
static constexpr CMDERR none() { return CMDERR(NONE, 0); }
|
||||||
static constexpr CMDERR MAKE_AMBIGUOUS_COMMAND(u32 x) { return CMDERR(AMBIGUOUS_COMMAND, x); }
|
static constexpr CMDERR unknown_command(u16 x) { return CMDERR(UNKNOWN_COMMAND, x); }
|
||||||
static constexpr CMDERR MAKE_UNBALANCED_PARENS(u32 x) { return CMDERR(UNBALANCED_PARENS, x); }
|
static constexpr CMDERR ambiguous_command(u16 x) { return CMDERR(AMBIGUOUS_COMMAND, x); }
|
||||||
static constexpr CMDERR MAKE_UNBALANCED_QUOTES(u32 x) { return CMDERR(UNBALANCED_QUOTES, x); }
|
static constexpr CMDERR unbalanced_parens(u16 x) { return CMDERR(UNBALANCED_PARENS, x); }
|
||||||
static constexpr CMDERR MAKE_NOT_ENOUGH_PARAMS(u32 x) { return CMDERR(NOT_ENOUGH_PARAMS, x); }
|
static constexpr CMDERR unbalanced_quotes(u16 x) { return CMDERR(UNBALANCED_QUOTES, x); }
|
||||||
static constexpr CMDERR MAKE_TOO_MANY_PARAMS(u32 x) { return CMDERR(TOO_MANY_PARAMS, x); }
|
static constexpr CMDERR not_enough_params(u16 x) { return CMDERR(NOT_ENOUGH_PARAMS, x); }
|
||||||
static constexpr CMDERR MAKE_EXPRESSION_ERROR(u32 x) { return CMDERR(EXPRESSION_ERROR, x); }
|
static constexpr CMDERR too_many_params(u16 x) { return CMDERR(TOO_MANY_PARAMS, x); }
|
||||||
|
static constexpr CMDERR expression_error(u16 x) { return CMDERR(EXPRESSION_ERROR, x); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
u16 m_error_class, m_error_offset;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1665,7 +1665,7 @@ void render_target::load_layout_files(util::xml::data_node const &rootnode, bool
|
|||||||
|
|
||||||
// if there's an explicit file, load that first
|
// if there's an explicit file, load that first
|
||||||
const std::string &basename = m_manager.machine().basename();
|
const std::string &basename = m_manager.machine().basename();
|
||||||
have_artwork |= load_layout_file(m_manager.machine().root_device(), basename.c_str(), rootnode);
|
have_artwork |= load_layout_file(m_manager.machine().root_device(), rootnode, m_manager.machine().options().art_path(), basename.c_str());
|
||||||
|
|
||||||
// if we're only loading this file, we know our final result
|
// if we're only loading this file, we know our final result
|
||||||
if (!singlefile)
|
if (!singlefile)
|
||||||
@ -2084,7 +2084,7 @@ void render_target::load_additional_layout_files(const char *basename, bool have
|
|||||||
}
|
}
|
||||||
|
|
||||||
// try to parse it
|
// try to parse it
|
||||||
if (!load_layout_file(m_manager.machine().root_device(), nullptr, *root))
|
if (!load_layout_file(m_manager.machine().root_device(), *root, m_manager.machine().options().art_path(), nullptr))
|
||||||
throw emu_fatalerror("Couldn't parse generated layout??");
|
throw emu_fatalerror("Couldn't parse generated layout??");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2111,7 +2111,7 @@ bool render_target::load_layout_file(const char *dirname, const internal_layout
|
|||||||
zerr = inflateInit(&stream);
|
zerr = inflateInit(&stream);
|
||||||
if (zerr != Z_OK)
|
if (zerr != Z_OK)
|
||||||
{
|
{
|
||||||
fatalerror("could not inflateInit");
|
osd_printf_error("render_target::load_layout_file: zlib initialization error\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2127,23 +2127,21 @@ bool render_target::load_layout_file(const char *dirname, const internal_layout
|
|||||||
}
|
}
|
||||||
else if (zerr != Z_OK)
|
else if (zerr != Z_OK)
|
||||||
{
|
{
|
||||||
fatalerror("decompression error\n");
|
osd_printf_error("render_target::load_layout_file: zlib decompression error\n");
|
||||||
|
inflateEnd(&stream);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// clean up
|
// clean up
|
||||||
zerr = inflateEnd(&stream);
|
zerr = inflateEnd(&stream);
|
||||||
if (zerr != Z_OK)
|
if (zerr != Z_OK)
|
||||||
{
|
osd_printf_error("render_target::load_layout_file: zlib cleanup error\n");
|
||||||
fatalerror("inflateEnd error\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
util::xml::file::ptr rootnode(util::xml::file::string_read(reinterpret_cast<char const *>(tempout.get()), nullptr));
|
util::xml::file::ptr rootnode(util::xml::file::string_read(reinterpret_cast<char const *>(tempout.get()), nullptr));
|
||||||
tempout.reset();
|
tempout.reset();
|
||||||
|
|
||||||
// if we didn't get a properly-formatted XML file, record a warning and exit
|
// if we didn't get a properly-formatted XML file, record a warning and exit
|
||||||
if (!load_layout_file(device ? *device : m_manager.machine().root_device(), dirname, *rootnode))
|
if (!load_layout_file(device ? *device : m_manager.machine().root_device(), *rootnode, m_manager.machine().options().art_path(), dirname))
|
||||||
{
|
{
|
||||||
osd_printf_warning("Improperly formatted XML string, ignoring\n");
|
osd_printf_warning("Improperly formatted XML string, ignoring\n");
|
||||||
return false;
|
return false;
|
||||||
@ -2157,28 +2155,39 @@ bool render_target::load_layout_file(const char *dirname, const internal_layout
|
|||||||
bool render_target::load_layout_file(const char *dirname, const char *filename)
|
bool render_target::load_layout_file(const char *dirname, const char *filename)
|
||||||
{
|
{
|
||||||
// build the path and optionally prepend the directory
|
// build the path and optionally prepend the directory
|
||||||
std::string fname = std::string(filename).append(".lay");
|
std::string fname;
|
||||||
if (dirname)
|
if (dirname)
|
||||||
fname.insert(0, PATH_SEPARATOR).insert(0, dirname);
|
fname.append(dirname).append(PATH_SEPARATOR);
|
||||||
|
fname.append(filename).append(".lay");
|
||||||
|
|
||||||
// attempt to open the file; bail if we can't
|
// attempt to open matching files
|
||||||
emu_file layoutfile(m_manager.machine().options().art_path(), OPEN_FLAG_READ);
|
|
||||||
layoutfile.set_restrict_to_mediapath(1);
|
|
||||||
osd_file::error const filerr(layoutfile.open(fname));
|
|
||||||
if (filerr != osd_file::error::NONE)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// read the file
|
|
||||||
util::xml::parse_options parseopt;
|
util::xml::parse_options parseopt;
|
||||||
util::xml::parse_error parseerr;
|
util::xml::parse_error parseerr;
|
||||||
parseopt.error = &parseerr;
|
parseopt.error = &parseerr;
|
||||||
util::xml::file::ptr rootnode(util::xml::file::read(layoutfile, &parseopt));
|
emu_file layoutfile(m_manager.machine().options().art_path(), OPEN_FLAG_READ);
|
||||||
if (!rootnode)
|
layoutfile.set_restrict_to_mediapath(1);
|
||||||
|
bool result(false);
|
||||||
|
for (osd_file::error filerr = layoutfile.open(fname); osd_file::error::NONE == filerr; filerr = layoutfile.open_next())
|
||||||
{
|
{
|
||||||
if (parseerr.error_message)
|
// read the file and parse as XML
|
||||||
|
util::xml::file::ptr const rootnode(util::xml::file::read(layoutfile, &parseopt));
|
||||||
|
if (rootnode)
|
||||||
|
{
|
||||||
|
// extract directory name from location of layout file
|
||||||
|
std::string artdir(layoutfile.fullpath());
|
||||||
|
auto const dirsep(std::find_if(artdir.rbegin(), artdir.rend(), &util::is_directory_separator));
|
||||||
|
artdir.erase(dirsep.base(), artdir.end());
|
||||||
|
|
||||||
|
// record a warning if we didn't get a properly-formatted XML file
|
||||||
|
if (!load_layout_file(m_manager.machine().root_device(), *rootnode, nullptr, artdir.c_str()))
|
||||||
|
osd_printf_warning("Improperly formatted XML layout file '%s', ignoring\n", filename);
|
||||||
|
else
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
else if (parseerr.error_message)
|
||||||
{
|
{
|
||||||
osd_printf_warning(
|
osd_printf_warning(
|
||||||
"Error parsing XML file '%s' at line %d column %d: %s, ignoring\n",
|
"Error parsing XML layout file '%s' at line %d column %d: %s, ignoring\n",
|
||||||
filename,
|
filename,
|
||||||
parseerr.error_line,
|
parseerr.error_line,
|
||||||
parseerr.error_column,
|
parseerr.error_column,
|
||||||
@ -2186,29 +2195,18 @@ bool render_target::load_layout_file(const char *dirname, const char *filename)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
osd_printf_warning("Error parsing XML file '%s', ignorning\n", filename);
|
osd_printf_warning("Error parsing XML layout file '%s', ignorning\n", filename);
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we didn't get a properly-formatted XML file, record a warning and exit
|
|
||||||
if (!load_layout_file(m_manager.machine().root_device(), dirname, *rootnode))
|
|
||||||
{
|
|
||||||
osd_printf_warning("Improperly formatted XML file '%s', ignoring\n", filename);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool render_target::load_layout_file(device_t &device, const char *dirname, util::xml::data_node const &rootnode)
|
bool render_target::load_layout_file(device_t &device, util::xml::data_node const &rootnode, const char *searchpath, const char *dirname)
|
||||||
{
|
{
|
||||||
// parse and catch any errors
|
// parse and catch any errors
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
m_filelist.emplace_back(device, rootnode, dirname);
|
m_filelist.emplace_back(device, rootnode, searchpath, dirname);
|
||||||
}
|
}
|
||||||
catch (emu_fatalerror &)
|
catch (emu_fatalerror &)
|
||||||
{
|
{
|
||||||
|
@ -538,7 +538,7 @@ public:
|
|||||||
using environment = emu::render::detail::layout_environment;
|
using environment = emu::render::detail::layout_environment;
|
||||||
|
|
||||||
// construction/destruction
|
// construction/destruction
|
||||||
layout_element(environment &env, util::xml::data_node const &elemnode, const char *dirname);
|
layout_element(environment &env, util::xml::data_node const &elemnode);
|
||||||
virtual ~layout_element();
|
virtual ~layout_element();
|
||||||
|
|
||||||
// getters
|
// getters
|
||||||
@ -563,7 +563,7 @@ private:
|
|||||||
typedef std::unique_ptr<component> ptr;
|
typedef std::unique_ptr<component> ptr;
|
||||||
|
|
||||||
// construction/destruction
|
// construction/destruction
|
||||||
component(environment &env, util::xml::data_node const &compnode, const char *dirname);
|
component(environment &env, util::xml::data_node const &compnode);
|
||||||
virtual ~component() = default;
|
virtual ~component() = default;
|
||||||
|
|
||||||
// setup
|
// setup
|
||||||
@ -641,13 +641,13 @@ private:
|
|||||||
int m_state; // associated state number
|
int m_state; // associated state number
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef component::ptr (*make_component_func)(environment &env, util::xml::data_node const &compnode, const char *dirname);
|
typedef component::ptr (*make_component_func)(environment &env, util::xml::data_node const &compnode);
|
||||||
typedef std::map<std::string, make_component_func> make_component_map;
|
typedef std::map<std::string, make_component_func> make_component_map;
|
||||||
|
|
||||||
// internal helpers
|
// internal helpers
|
||||||
static void element_scale(bitmap_argb32 &dest, bitmap_argb32 &source, const rectangle &sbounds, void *param);
|
static void element_scale(bitmap_argb32 &dest, bitmap_argb32 &source, const rectangle &sbounds, void *param);
|
||||||
template <typename T> static component::ptr make_component(environment &env, util::xml::data_node const &compnode, const char *dirname);
|
template <typename T> static component::ptr make_component(environment &env, util::xml::data_node const &compnode);
|
||||||
template <int D> static component::ptr make_dotmatrix_component(environment &env, util::xml::data_node const &compnode, const char *dirname);
|
template <int D> static component::ptr make_dotmatrix_component(environment &env, util::xml::data_node const &compnode);
|
||||||
|
|
||||||
static make_component_map const s_make_component; // maps component XML names to creator functions
|
static make_component_map const s_make_component; // maps component XML names to creator functions
|
||||||
|
|
||||||
@ -946,7 +946,7 @@ public:
|
|||||||
using view_list = std::list<layout_view>;
|
using view_list = std::list<layout_view>;
|
||||||
|
|
||||||
// construction/destruction
|
// construction/destruction
|
||||||
layout_file(device_t &device, util::xml::data_node const &rootnode, char const *dirname);
|
layout_file(device_t &device, util::xml::data_node const &rootnode, char const *searchpath, char const *dirname);
|
||||||
~layout_file();
|
~layout_file();
|
||||||
|
|
||||||
// getters
|
// getters
|
||||||
@ -959,7 +959,6 @@ private:
|
|||||||
|
|
||||||
// add elements and parameters
|
// add elements and parameters
|
||||||
void add_elements(
|
void add_elements(
|
||||||
char const *dirname,
|
|
||||||
environment &env,
|
environment &env,
|
||||||
util::xml::data_node const &parentnode,
|
util::xml::data_node const &parentnode,
|
||||||
group_map &groupmap,
|
group_map &groupmap,
|
||||||
@ -1068,7 +1067,7 @@ private:
|
|||||||
void load_additional_layout_files(const char *basename, bool have_artwork);
|
void load_additional_layout_files(const char *basename, bool have_artwork);
|
||||||
bool load_layout_file(const char *dirname, const char *filename);
|
bool load_layout_file(const char *dirname, const char *filename);
|
||||||
bool load_layout_file(const char *dirname, const internal_layout &layout_data, device_t *device = nullptr);
|
bool load_layout_file(const char *dirname, const internal_layout &layout_data, device_t *device = nullptr);
|
||||||
bool load_layout_file(device_t &device, const char *dirname, util::xml::data_node const &rootnode);
|
bool load_layout_file(device_t &device, util::xml::data_node const &rootnode, const char *searchpath, const char *dirname);
|
||||||
void add_container_primitives(render_primitive_list &list, const object_transform &root_xform, const object_transform &xform, render_container &container, int blendmode);
|
void add_container_primitives(render_primitive_list &list, const object_transform &root_xform, const object_transform &xform, render_container &container, int blendmode);
|
||||||
void add_element_primitives(render_primitive_list &list, const object_transform &xform, layout_element &element, int state, int blendmode);
|
void add_element_primitives(render_primitive_list &list, const object_transform &xform, layout_element &element, int state, int blendmode);
|
||||||
std::pair<float, float> map_point_internal(s32 target_x, s32 target_y);
|
std::pair<float, float> map_point_internal(s32 target_x, s32 target_y);
|
||||||
|
@ -582,18 +582,24 @@ private:
|
|||||||
util::ovectorstream m_buffer;
|
util::ovectorstream m_buffer;
|
||||||
std::shared_ptr<NSVGrasterizer> const m_svg_rasterizer;
|
std::shared_ptr<NSVGrasterizer> const m_svg_rasterizer;
|
||||||
device_t &m_device;
|
device_t &m_device;
|
||||||
|
char const *const m_search_path;
|
||||||
|
char const *const m_directory_name;
|
||||||
layout_environment *const m_next = nullptr;
|
layout_environment *const m_next = nullptr;
|
||||||
bool m_cached = false;
|
bool m_cached = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit layout_environment(device_t &device)
|
layout_environment(device_t &device, char const *searchpath, char const *dirname)
|
||||||
: m_svg_rasterizer(nsvgCreateRasterizer(), util::nsvg_deleter())
|
: m_svg_rasterizer(nsvgCreateRasterizer(), util::nsvg_deleter())
|
||||||
, m_device(device)
|
, m_device(device)
|
||||||
|
, m_search_path(searchpath)
|
||||||
|
, m_directory_name(dirname)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
explicit layout_environment(layout_environment &next)
|
explicit layout_environment(layout_environment &next)
|
||||||
: m_svg_rasterizer(next.m_svg_rasterizer)
|
: m_svg_rasterizer(next.m_svg_rasterizer)
|
||||||
, m_device(next.m_device)
|
, m_device(next.m_device)
|
||||||
|
, m_search_path(next.m_search_path)
|
||||||
|
, m_directory_name(next.m_directory_name)
|
||||||
, m_next(&next)
|
, m_next(&next)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -602,6 +608,8 @@ public:
|
|||||||
device_t &device() const { return m_device; }
|
device_t &device() const { return m_device; }
|
||||||
running_machine &machine() const { return device().machine(); }
|
running_machine &machine() const { return device().machine(); }
|
||||||
bool is_root_device() const { return &device() == &machine().root_device(); }
|
bool is_root_device() const { return &device() == &machine().root_device(); }
|
||||||
|
char const *search_path() const { return m_search_path; }
|
||||||
|
char const *directory_name() const { return m_directory_name; }
|
||||||
std::shared_ptr<NSVGrasterizer> const &svg_rasterizer() const { return m_svg_rasterizer; }
|
std::shared_ptr<NSVGrasterizer> const &svg_rasterizer() const { return m_svg_rasterizer; }
|
||||||
|
|
||||||
void set_parameter(std::string &&name, std::string &&value)
|
void set_parameter(std::string &&name, std::string &&value)
|
||||||
@ -1117,7 +1125,7 @@ layout_element::make_component_map const layout_element::s_make_component{
|
|||||||
// layout_element - constructor
|
// layout_element - constructor
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
layout_element::layout_element(environment &env, util::xml::data_node const &elemnode, const char *dirname)
|
layout_element::layout_element(environment &env, util::xml::data_node const &elemnode)
|
||||||
: m_machine(env.machine())
|
: m_machine(env.machine())
|
||||||
, m_defstate(env.get_attribute_int(elemnode, "defstate", -1))
|
, m_defstate(env.get_attribute_int(elemnode, "defstate", -1))
|
||||||
, m_statemask(0)
|
, m_statemask(0)
|
||||||
@ -1133,7 +1141,7 @@ layout_element::layout_element(environment &env, util::xml::data_node const &ele
|
|||||||
throw layout_syntax_error(util::string_format("unknown element component %s", compnode->get_name()));
|
throw layout_syntax_error(util::string_format("unknown element component %s", compnode->get_name()));
|
||||||
|
|
||||||
// insert the new component into the list
|
// insert the new component into the list
|
||||||
component const &newcomp(**m_complist.emplace(m_complist.end(), make_func->second(env, *compnode, dirname)));
|
component const &newcomp(**m_complist.emplace(m_complist.end(), make_func->second(env, *compnode)));
|
||||||
|
|
||||||
// accumulate bounds
|
// accumulate bounds
|
||||||
if (first)
|
if (first)
|
||||||
@ -1539,10 +1547,11 @@ class layout_element::image_component : public component
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// construction/destruction
|
// construction/destruction
|
||||||
image_component(environment &env, util::xml::data_node const &compnode, char const *dirname)
|
image_component(environment &env, util::xml::data_node const &compnode)
|
||||||
: component(env, compnode, dirname)
|
: component(env, compnode)
|
||||||
, m_rasterizer(env.svg_rasterizer())
|
, m_rasterizer(env.svg_rasterizer())
|
||||||
, m_dirname(dirname ? dirname : "")
|
, m_searchpath(env.search_path() ? env.search_path() : "")
|
||||||
|
, m_dirname(env.directory_name() ? env.directory_name() : "")
|
||||||
, m_imagefile(env.get_attribute_string(compnode, "file", ""))
|
, m_imagefile(env.get_attribute_string(compnode, "file", ""))
|
||||||
, m_alphafile(env.get_attribute_string(compnode, "alphafile", ""))
|
, m_alphafile(env.get_attribute_string(compnode, "alphafile", ""))
|
||||||
, m_data(get_data(compnode))
|
, m_data(get_data(compnode))
|
||||||
@ -1552,7 +1561,7 @@ public:
|
|||||||
// overrides
|
// overrides
|
||||||
virtual void preload(running_machine &machine) override
|
virtual void preload(running_machine &machine) override
|
||||||
{
|
{
|
||||||
if (!m_bitmap.valid())
|
if (!m_bitmap.valid() && !m_svg)
|
||||||
load_image(machine);
|
load_image(machine);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1685,11 +1694,17 @@ private:
|
|||||||
void load_image(running_machine &machine)
|
void load_image(running_machine &machine)
|
||||||
{
|
{
|
||||||
// if we have a filename, go with that
|
// if we have a filename, go with that
|
||||||
emu_file file(machine.options().art_path(), OPEN_FLAG_READ);
|
emu_file file(m_searchpath.empty() ? m_dirname : m_searchpath, OPEN_FLAG_READ);
|
||||||
if (!m_imagefile.empty())
|
if (!m_imagefile.empty())
|
||||||
{
|
{
|
||||||
LOGMASKED(LOG_IMAGE_LOAD, "Image component attempt to load image file '%s%s%s'\n", m_dirname, PATH_SEPARATOR, m_imagefile);
|
std::string filename;
|
||||||
osd_file::error const imgerr = file.open(m_dirname.empty() ? m_imagefile : (m_dirname + PATH_SEPARATOR + m_imagefile));
|
if (!m_searchpath.empty())
|
||||||
|
filename = m_dirname;
|
||||||
|
if (!filename.empty() && !util::is_directory_separator(filename[filename.size() - 1]))
|
||||||
|
filename.append(PATH_SEPARATOR);
|
||||||
|
filename.append(m_imagefile);
|
||||||
|
LOGMASKED(LOG_IMAGE_LOAD, "Image component attempt to load image file '%s'\n", filename);
|
||||||
|
osd_file::error const imgerr = file.open(filename);
|
||||||
if (osd_file::error::NONE == imgerr)
|
if (osd_file::error::NONE == imgerr)
|
||||||
{
|
{
|
||||||
if (!load_bitmap(file))
|
if (!load_bitmap(file))
|
||||||
@ -1701,10 +1716,10 @@ private:
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOGMASKED(LOG_IMAGE_LOAD, "Image component unable to open image file '%s%s%s'\n", m_dirname, PATH_SEPARATOR, m_imagefile);
|
LOGMASKED(LOG_IMAGE_LOAD, "Image component unable to open image file '%s'\n", filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else if (!m_data.empty())
|
||||||
{
|
{
|
||||||
load_image_data();
|
load_image_data();
|
||||||
}
|
}
|
||||||
@ -1714,8 +1729,14 @@ private:
|
|||||||
{
|
{
|
||||||
if (m_bitmap.valid())
|
if (m_bitmap.valid())
|
||||||
{
|
{
|
||||||
LOGMASKED(LOG_IMAGE_LOAD, "Image component attempt to load alpha channel from file '%s%s%s'\n", m_dirname, PATH_SEPARATOR, m_alphafile);
|
std::string filename;
|
||||||
osd_file::error const alferr = file.open(m_dirname.empty() ? m_alphafile : (m_dirname + PATH_SEPARATOR + m_alphafile));
|
if (!m_searchpath.empty())
|
||||||
|
filename = m_dirname;
|
||||||
|
if (!filename.empty() && !util::is_directory_separator(filename[filename.size() - 1]))
|
||||||
|
filename.append(PATH_SEPARATOR);
|
||||||
|
filename.append(m_alphafile);
|
||||||
|
LOGMASKED(LOG_IMAGE_LOAD, "Image component attempt to load alpha channel from file '%s'\n", filename);
|
||||||
|
osd_file::error const alferr = file.open(filename);
|
||||||
if (osd_file::error::NONE == alferr)
|
if (osd_file::error::NONE == alferr)
|
||||||
{
|
{
|
||||||
// TODO: no way to detect corner case where we had alpha from the image but the alpha PNG makes it entirely opaque
|
// TODO: no way to detect corner case where we had alpha from the image but the alpha PNG makes it entirely opaque
|
||||||
@ -1725,7 +1746,7 @@ private:
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOGMASKED(LOG_IMAGE_LOAD, "Image component unable to open alpha channel file '%s%s%s'\n", m_dirname, PATH_SEPARATOR, m_alphafile);
|
LOGMASKED(LOG_IMAGE_LOAD, "Image component unable to open alpha channel file '%s'\n", filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (m_svg)
|
else if (m_svg)
|
||||||
@ -1754,6 +1775,7 @@ private:
|
|||||||
// clear out this stuff in case it's large
|
// clear out this stuff in case it's large
|
||||||
if (!m_svg)
|
if (!m_svg)
|
||||||
m_rasterizer.reset();
|
m_rasterizer.reset();
|
||||||
|
m_searchpath.clear();
|
||||||
m_dirname.clear();
|
m_dirname.clear();
|
||||||
m_imagefile.clear();
|
m_imagefile.clear();
|
||||||
m_alphafile.clear();
|
m_alphafile.clear();
|
||||||
@ -1773,7 +1795,7 @@ private:
|
|||||||
std::string::size_type const end(m_data.find_first_not_of(base64tail, tail));
|
std::string::size_type const end(m_data.find_first_not_of(base64tail, tail));
|
||||||
if (std::string::npos == end)
|
if (std::string::npos == end)
|
||||||
{
|
{
|
||||||
LOGMASKED(LOG_IMAGE_LOAD, "Image component decoding Base64 image m_data\n");
|
LOGMASKED(LOG_IMAGE_LOAD, "Image component decoding Base64 image data\n");
|
||||||
char *dst(&m_data[0]);
|
char *dst(&m_data[0]);
|
||||||
unsigned trailing(0U);
|
unsigned trailing(0U);
|
||||||
for (std::string::size_type i = 0U; (m_data.size() > i) && ('=' != m_data[i]); ++i)
|
for (std::string::size_type i = 0U; (m_data.size() > i) && ('=' != m_data[i]); ++i)
|
||||||
@ -1923,6 +1945,7 @@ private:
|
|||||||
bool m_hasalpha = false; // is there any alpha component present?
|
bool m_hasalpha = false; // is there any alpha component present?
|
||||||
|
|
||||||
// cold state
|
// cold state
|
||||||
|
std::string m_searchpath; // asset search path (for lazy loading)
|
||||||
std::string m_dirname; // directory name of image file (for lazy loading)
|
std::string m_dirname; // directory name of image file (for lazy loading)
|
||||||
std::string m_imagefile; // name of the image file (for lazy loading)
|
std::string m_imagefile; // name of the image file (for lazy loading)
|
||||||
std::string m_alphafile; // name of the alpha file (for lazy loading)
|
std::string m_alphafile; // name of the alpha file (for lazy loading)
|
||||||
@ -1935,8 +1958,8 @@ class layout_element::rect_component : public component
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// construction/destruction
|
// construction/destruction
|
||||||
rect_component(environment &env, util::xml::data_node const &compnode, const char *dirname)
|
rect_component(environment &env, util::xml::data_node const &compnode)
|
||||||
: component(env, compnode, dirname)
|
: component(env, compnode)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1988,8 +2011,8 @@ class layout_element::disk_component : public component
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// construction/destruction
|
// construction/destruction
|
||||||
disk_component(environment &env, util::xml::data_node const &compnode, const char *dirname)
|
disk_component(environment &env, util::xml::data_node const &compnode)
|
||||||
: component(env, compnode, dirname)
|
: component(env, compnode)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2054,8 +2077,8 @@ class layout_element::text_component : public component
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// construction/destruction
|
// construction/destruction
|
||||||
text_component(environment &env, util::xml::data_node const &compnode, const char *dirname)
|
text_component(environment &env, util::xml::data_node const &compnode)
|
||||||
: component(env, compnode, dirname)
|
: component(env, compnode)
|
||||||
{
|
{
|
||||||
m_string = env.get_attribute_string(compnode, "string", "");
|
m_string = env.get_attribute_string(compnode, "string", "");
|
||||||
m_textalign = env.get_attribute_int(compnode, "align", 0);
|
m_textalign = env.get_attribute_int(compnode, "align", 0);
|
||||||
@ -2081,8 +2104,8 @@ class layout_element::led7seg_component : public component
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// construction/destruction
|
// construction/destruction
|
||||||
led7seg_component(environment &env, util::xml::data_node const &compnode, const char *dirname)
|
led7seg_component(environment &env, util::xml::data_node const &compnode)
|
||||||
: component(env, compnode, dirname)
|
: component(env, compnode)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2143,8 +2166,8 @@ class layout_element::led8seg_gts1_component : public component
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// construction/destruction
|
// construction/destruction
|
||||||
led8seg_gts1_component(environment &env, util::xml::data_node const &compnode, const char *dirname)
|
led8seg_gts1_component(environment &env, util::xml::data_node const &compnode)
|
||||||
: component(env, compnode, dirname)
|
: component(env, compnode)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2211,8 +2234,8 @@ class layout_element::led14seg_component : public component
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// construction/destruction
|
// construction/destruction
|
||||||
led14seg_component(environment &env, util::xml::data_node const &compnode, const char *dirname)
|
led14seg_component(environment &env, util::xml::data_node const &compnode)
|
||||||
: component(env, compnode, dirname)
|
: component(env, compnode)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2323,8 +2346,8 @@ class layout_element::led16seg_component : public component
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// construction/destruction
|
// construction/destruction
|
||||||
led16seg_component(environment &env, util::xml::data_node const &compnode, const char *dirname)
|
led16seg_component(environment &env, util::xml::data_node const &compnode)
|
||||||
: component(env, compnode, dirname)
|
: component(env, compnode)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2445,8 +2468,8 @@ class layout_element::led14segsc_component : public component
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// construction/destruction
|
// construction/destruction
|
||||||
led14segsc_component(environment &env, util::xml::data_node const &compnode, const char *dirname)
|
led14segsc_component(environment &env, util::xml::data_node const &compnode)
|
||||||
: component(env, compnode, dirname)
|
: component(env, compnode)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2568,8 +2591,8 @@ class layout_element::led16segsc_component : public component
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// construction/destruction
|
// construction/destruction
|
||||||
led16segsc_component(environment &env, util::xml::data_node const &compnode, const char *dirname)
|
led16segsc_component(environment &env, util::xml::data_node const &compnode)
|
||||||
: component(env, compnode, dirname)
|
: component(env, compnode)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2700,8 +2723,8 @@ class layout_element::dotmatrix_component : public component
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// construction/destruction
|
// construction/destruction
|
||||||
dotmatrix_component(int dots, environment &env, util::xml::data_node const &compnode, const char *dirname)
|
dotmatrix_component(int dots, environment &env, util::xml::data_node const &compnode)
|
||||||
: component(env, compnode, dirname)
|
: component(env, compnode)
|
||||||
, m_dots(dots)
|
, m_dots(dots)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -2741,8 +2764,8 @@ class layout_element::simplecounter_component : public component
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// construction/destruction
|
// construction/destruction
|
||||||
simplecounter_component(environment &env, util::xml::data_node const &compnode, const char *dirname)
|
simplecounter_component(environment &env, util::xml::data_node const &compnode)
|
||||||
: component(env, compnode, dirname)
|
: component(env, compnode)
|
||||||
, m_digits(env.get_attribute_int(compnode, "digits", 2))
|
, m_digits(env.get_attribute_int(compnode, "digits", 2))
|
||||||
, m_textalign(env.get_attribute_int(compnode, "align", 0))
|
, m_textalign(env.get_attribute_int(compnode, "align", 0))
|
||||||
, m_maxstate(env.get_attribute_int(compnode, "maxstate", 999))
|
, m_maxstate(env.get_attribute_int(compnode, "maxstate", 999))
|
||||||
@ -2774,49 +2797,30 @@ class layout_element::reel_component : public component
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
// construction/destruction
|
// construction/destruction
|
||||||
reel_component(environment &env, util::xml::data_node const &compnode, const char *dirname)
|
reel_component(environment &env, util::xml::data_node const &compnode)
|
||||||
: component(env, compnode, dirname)
|
: component(env, compnode)
|
||||||
|
, m_searchpath(env.search_path() ? env.search_path() : "")
|
||||||
|
, m_dirname(env.directory_name() ? env.directory_name() : "")
|
||||||
{
|
{
|
||||||
for (auto & elem : m_hasalpha)
|
|
||||||
elem = false;
|
|
||||||
|
|
||||||
std::string symbollist = env.get_attribute_string(compnode, "symbollist", "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15");
|
std::string symbollist = env.get_attribute_string(compnode, "symbollist", "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15");
|
||||||
|
|
||||||
// split out position names from string and figure out our number of symbols
|
// split out position names from string and figure out our number of symbols
|
||||||
int location;
|
|
||||||
m_numstops = 0;
|
m_numstops = 0;
|
||||||
location=symbollist.find(',');
|
for (std::string::size_type location = symbollist.find(','); std::string::npos != location; location = symbollist.find(','))
|
||||||
while (location!=-1)
|
|
||||||
{
|
{
|
||||||
m_stopnames[m_numstops] = symbollist;
|
m_stopnames[m_numstops] = symbollist.substr(0, location);
|
||||||
m_stopnames[m_numstops] = m_stopnames[m_numstops].substr(0, location);
|
symbollist.erase(0, location + 1);
|
||||||
symbollist = symbollist.substr(location+1, symbollist.length()-(location-1));
|
|
||||||
m_numstops++;
|
m_numstops++;
|
||||||
location=symbollist.find(',');
|
|
||||||
}
|
}
|
||||||
m_stopnames[m_numstops++] = symbollist;
|
m_stopnames[m_numstops++] = symbollist;
|
||||||
|
|
||||||
// careful, dirname is nullptr if we're coming from internal layout, and our string assignment doesn't like that
|
for (int i = 0; i < m_numstops; i++)
|
||||||
if (dirname != nullptr)
|
|
||||||
m_dirname = dirname;
|
|
||||||
|
|
||||||
for (int i=0;i<m_numstops;i++)
|
|
||||||
{
|
{
|
||||||
location=m_stopnames[i].find(':');
|
std::string::size_type const location = m_stopnames[i].find(':');
|
||||||
if (location!=-1)
|
if (location != std::string::npos)
|
||||||
{
|
{
|
||||||
m_imagefile[i] = m_stopnames[i];
|
m_imagefile[i] = m_stopnames[i].substr(location + 1);
|
||||||
m_stopnames[i] = m_stopnames[i].substr(0, location);
|
m_stopnames[i].erase(location);
|
||||||
m_imagefile[i] = m_imagefile[i].substr(location+1, m_imagefile[i].length()-(location-1));
|
|
||||||
|
|
||||||
//m_alphafile[i] =
|
|
||||||
m_file[i] = std::make_unique<emu_file>(env.machine().options().art_path(), OPEN_FLAG_READ);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//m_imagefile[i] = 0;
|
|
||||||
//m_alphafile[i] = 0;
|
|
||||||
m_file[i].reset();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2829,6 +2833,17 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
// overrides
|
// overrides
|
||||||
virtual int maxstate() const override { return 65535; }
|
virtual int maxstate() const override { return 65535; }
|
||||||
|
|
||||||
|
virtual void preload(running_machine &machine) override
|
||||||
|
{
|
||||||
|
for (int i = 0; i < m_numstops; i++)
|
||||||
|
{
|
||||||
|
if (!m_imagefile[i].empty() && !m_bitmap[i].valid())
|
||||||
|
load_reel_bitmap(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
virtual void draw(running_machine &machine, bitmap_argb32 &dest, const rectangle &bounds, int state) override
|
virtual void draw(running_machine &machine, bitmap_argb32 &dest, const rectangle &bounds, int state) override
|
||||||
{
|
{
|
||||||
if (m_beltreel)
|
if (m_beltreel)
|
||||||
@ -2850,16 +2865,12 @@ protected:
|
|||||||
u32 const b = c.b * 255.0f;
|
u32 const b = c.b * 255.0f;
|
||||||
u32 const a = c.a * 255.0f;
|
u32 const a = c.a * 255.0f;
|
||||||
|
|
||||||
// get the width of the string
|
|
||||||
auto font = machine.render().font_alloc("default");
|
|
||||||
float aspect = 1.0f;
|
|
||||||
s32 width;
|
|
||||||
|
|
||||||
int curry = 0;
|
int curry = 0;
|
||||||
int num_shown = m_numsymbolsvisible;
|
int num_shown = m_numsymbolsvisible;
|
||||||
|
|
||||||
int ourheight = bounds.height();
|
int ourheight = bounds.height();
|
||||||
|
|
||||||
|
auto font = machine.render().font_alloc("default");
|
||||||
for (int fruit = 0;fruit<m_numstops;fruit++)
|
for (int fruit = 0;fruit<m_numstops;fruit++)
|
||||||
{
|
{
|
||||||
int basey;
|
int basey;
|
||||||
@ -2884,47 +2895,31 @@ protected:
|
|||||||
// only render the symbol / text if it's actually in view because the code is SLOW
|
// only render the symbol / text if it's actually in view because the code is SLOW
|
||||||
if ((endpos >= bounds.top()) && (basey <= bounds.bottom()))
|
if ((endpos >= bounds.top()) && (basey <= bounds.bottom()))
|
||||||
{
|
{
|
||||||
while (1)
|
if (!m_imagefile[fruit].empty() && !m_bitmap[fruit].valid())
|
||||||
{
|
load_reel_bitmap(fruit);
|
||||||
width = font->string_width(ourheight / num_shown, aspect, m_stopnames[fruit].c_str());
|
|
||||||
if (width < bounds.width())
|
|
||||||
break;
|
|
||||||
aspect *= 0.9f;
|
|
||||||
}
|
|
||||||
|
|
||||||
s32 curx;
|
if (m_bitmap[fruit].valid()) // render gfx
|
||||||
curx = bounds.left() + (bounds.width() - width) / 2;
|
|
||||||
|
|
||||||
if (m_file[fruit])
|
|
||||||
if (!m_bitmap[fruit].valid())
|
|
||||||
load_reel_bitmap(fruit);
|
|
||||||
|
|
||||||
if (m_file[fruit]) // render gfx
|
|
||||||
{
|
{
|
||||||
bitmap_argb32 tempbitmap2(dest.width(), ourheight/num_shown);
|
bitmap_argb32 tempbitmap2(dest.width(), ourheight/num_shown);
|
||||||
|
render_resample_argb_bitmap_hq(tempbitmap2, m_bitmap[fruit], c);
|
||||||
|
|
||||||
if (m_bitmap[fruit].valid())
|
for (int y = 0; y < ourheight/num_shown; y++)
|
||||||
{
|
{
|
||||||
render_resample_argb_bitmap_hq(tempbitmap2, m_bitmap[fruit], c);
|
int effy = basey + y;
|
||||||
|
|
||||||
for (int y = 0; y < ourheight/num_shown; y++)
|
if (effy >= bounds.top() && effy <= bounds.bottom())
|
||||||
{
|
{
|
||||||
int effy = basey + y;
|
u32 const *const src = &tempbitmap2.pix(y);
|
||||||
|
u32 *const d = &dest.pix(effy);
|
||||||
if (effy >= bounds.top() && effy <= bounds.bottom())
|
for (int x = 0; x < dest.width(); x++)
|
||||||
{
|
{
|
||||||
u32 const *const src = &tempbitmap2.pix(y);
|
int effx = x;
|
||||||
u32 *const d = &dest.pix(effy);
|
if (effx >= bounds.left() && effx <= bounds.right())
|
||||||
for (int x = 0; x < dest.width(); x++)
|
|
||||||
{
|
{
|
||||||
int effx = x;
|
u32 spix = rgb_t(src[x]).a();
|
||||||
if (effx >= bounds.left() && effx <= bounds.right())
|
if (spix != 0)
|
||||||
{
|
{
|
||||||
u32 spix = rgb_t(src[x]).a();
|
d[effx] = src[x];
|
||||||
if (spix != 0)
|
|
||||||
{
|
|
||||||
d[effx] = src[x];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2941,6 +2936,20 @@ protected:
|
|||||||
const char *s = origs;
|
const char *s = origs;
|
||||||
char32_t schar;
|
char32_t schar;
|
||||||
|
|
||||||
|
// get the width of the string
|
||||||
|
float aspect = 1.0f;
|
||||||
|
s32 width;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
width = font->string_width(ourheight / num_shown, aspect, m_stopnames[fruit].c_str());
|
||||||
|
if (width < bounds.width())
|
||||||
|
break;
|
||||||
|
aspect *= 0.9f;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 curx = bounds.left() + (bounds.width() - width) / 2;
|
||||||
|
|
||||||
// loop over characters
|
// loop over characters
|
||||||
while (*s != 0)
|
while (*s != 0)
|
||||||
{
|
{
|
||||||
@ -3011,15 +3020,12 @@ private:
|
|||||||
u32 const b = c.b * 255.0f;
|
u32 const b = c.b * 255.0f;
|
||||||
u32 const a = c.a * 255.0f;
|
u32 const a = c.a * 255.0f;
|
||||||
|
|
||||||
// get the width of the string
|
|
||||||
auto font = machine.render().font_alloc("default");
|
|
||||||
float aspect = 1.0f;
|
|
||||||
s32 width;
|
|
||||||
int currx = 0;
|
int currx = 0;
|
||||||
int num_shown = m_numsymbolsvisible;
|
int num_shown = m_numsymbolsvisible;
|
||||||
|
|
||||||
int ourwidth = bounds.width();
|
int ourwidth = bounds.width();
|
||||||
|
|
||||||
|
auto font = machine.render().font_alloc("default");
|
||||||
for (int fruit = 0;fruit<m_numstops;fruit++)
|
for (int fruit = 0;fruit<m_numstops;fruit++)
|
||||||
{
|
{
|
||||||
int basex;
|
int basex;
|
||||||
@ -3043,56 +3049,53 @@ private:
|
|||||||
// only render the symbol / text if it's actually in view because the code is SLOW
|
// only render the symbol / text if it's actually in view because the code is SLOW
|
||||||
if ((endpos >= bounds.left()) && (basex <= bounds.right()))
|
if ((endpos >= bounds.left()) && (basex <= bounds.right()))
|
||||||
{
|
{
|
||||||
while (1)
|
if (!m_imagefile[fruit].empty() && !m_bitmap[fruit].valid())
|
||||||
{
|
load_reel_bitmap(fruit);
|
||||||
width = font->string_width(dest.height(), aspect, m_stopnames[fruit].c_str());
|
|
||||||
if (width < bounds.width())
|
|
||||||
break;
|
|
||||||
aspect *= 0.9f;
|
|
||||||
}
|
|
||||||
|
|
||||||
s32 curx;
|
if (m_bitmap[fruit].valid()) // render gfx
|
||||||
curx = bounds.left();
|
|
||||||
|
|
||||||
if (m_file[fruit])
|
|
||||||
if (!m_bitmap[fruit].valid())
|
|
||||||
load_reel_bitmap(fruit);
|
|
||||||
|
|
||||||
if (m_file[fruit]) // render gfx
|
|
||||||
{
|
{
|
||||||
bitmap_argb32 tempbitmap2(ourwidth/num_shown, dest.height());
|
bitmap_argb32 tempbitmap2(ourwidth/num_shown, dest.height());
|
||||||
|
render_resample_argb_bitmap_hq(tempbitmap2, m_bitmap[fruit], c);
|
||||||
|
|
||||||
if (m_bitmap[fruit].valid())
|
for (int y = 0; y < dest.height(); y++)
|
||||||
{
|
{
|
||||||
render_resample_argb_bitmap_hq(tempbitmap2, m_bitmap[fruit], c);
|
int effy = y;
|
||||||
|
|
||||||
for (int y = 0; y < dest.height(); y++)
|
if (effy >= bounds.top() && effy <= bounds.bottom())
|
||||||
{
|
{
|
||||||
int effy = y;
|
u32 const *const src = &tempbitmap2.pix(y);
|
||||||
|
u32 *const d = &dest.pix(effy);
|
||||||
if (effy >= bounds.top() && effy <= bounds.bottom())
|
for (int x = 0; x < ourwidth/num_shown; x++)
|
||||||
{
|
{
|
||||||
u32 const *const src = &tempbitmap2.pix(y);
|
int effx = basex + x;
|
||||||
u32 *const d = &dest.pix(effy);
|
if (effx >= bounds.left() && effx <= bounds.right())
|
||||||
for (int x = 0; x < ourwidth/num_shown; x++)
|
|
||||||
{
|
{
|
||||||
int effx = basex + x;
|
u32 spix = rgb_t(src[x]).a();
|
||||||
if (effx >= bounds.left() && effx <= bounds.right())
|
if (spix != 0)
|
||||||
{
|
{
|
||||||
u32 spix = rgb_t(src[x]).a();
|
d[effx] = src[x];
|
||||||
if (spix != 0)
|
|
||||||
{
|
|
||||||
d[effx] = src[x];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // render text (fallback)
|
else // render text (fallback)
|
||||||
{
|
{
|
||||||
|
// get the width of the string
|
||||||
|
float aspect = 1.0f;
|
||||||
|
s32 width;
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
width = font->string_width(dest.height(), aspect, m_stopnames[fruit].c_str());
|
||||||
|
if (width < bounds.width())
|
||||||
|
break;
|
||||||
|
aspect *= 0.9f;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 curx = bounds.left();
|
||||||
|
|
||||||
// allocate a temporary bitmap
|
// allocate a temporary bitmap
|
||||||
bitmap_argb32 tempbitmap(dest.width(), dest.height());
|
bitmap_argb32 tempbitmap(dest.width(), dest.height());
|
||||||
|
|
||||||
@ -3157,34 +3160,29 @@ private:
|
|||||||
|
|
||||||
void load_reel_bitmap(int number)
|
void load_reel_bitmap(int number)
|
||||||
{
|
{
|
||||||
// load the basic bitmap
|
emu_file file(m_searchpath.empty() ? m_dirname : m_searchpath, OPEN_FLAG_READ);
|
||||||
assert(m_file != nullptr);
|
std::string filename;
|
||||||
if (m_file[number]->open(m_dirname + PATH_SEPARATOR + m_imagefile[number]) == osd_file::error::NONE)
|
if (!m_searchpath.empty())
|
||||||
{
|
filename = m_dirname;
|
||||||
/*m_hasalpha[number] = */ render_load_png(m_bitmap[number], *m_file[number]);
|
if (!filename.empty() && !util::is_directory_separator(filename[filename.size() - 1]))
|
||||||
m_file[number]->close();
|
filename.append(PATH_SEPARATOR);
|
||||||
}
|
filename.append(m_imagefile[number]);
|
||||||
|
|
||||||
// load the alpha bitmap if specified
|
// load the basic bitmap
|
||||||
//if (m_bitmap[number].valid() && m_alphafile[number])
|
if (file.open(filename) == osd_file::error::NONE)
|
||||||
// render_load_png(m_bitmap[number], *m_file[number], m_dirname, m_alphafile[number], true);
|
render_load_png(m_bitmap[number], file);
|
||||||
|
|
||||||
// if we can't load the bitmap just use text rendering
|
// if we can't load the bitmap just use text rendering
|
||||||
if (!m_bitmap[number].valid())
|
if (!m_bitmap[number].valid())
|
||||||
{
|
m_imagefile[number].clear();
|
||||||
// fallback to text rendering
|
|
||||||
m_file[number].reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// internal state
|
// internal state
|
||||||
bitmap_argb32 m_bitmap[MAX_BITMAPS]; // source bitmap for images
|
bitmap_argb32 m_bitmap[MAX_BITMAPS]; // source bitmap for images
|
||||||
|
std::string m_searchpath; // asset search path (for lazy loading)
|
||||||
std::string m_dirname; // directory name of image file (for lazy loading)
|
std::string m_dirname; // directory name of image file (for lazy loading)
|
||||||
std::unique_ptr<emu_file> m_file[MAX_BITMAPS]; // file object for reading image/alpha files
|
|
||||||
std::string m_imagefile[MAX_BITMAPS]; // name of the image file (for lazy loading)
|
std::string m_imagefile[MAX_BITMAPS]; // name of the image file (for lazy loading)
|
||||||
std::string m_alphafile[MAX_BITMAPS]; // name of the alpha file (for lazy loading)
|
|
||||||
bool m_hasalpha[MAX_BITMAPS]; // is there any alpha component present?
|
|
||||||
|
|
||||||
// basically made up of multiple text strings / gfx
|
// basically made up of multiple text strings / gfx
|
||||||
int m_numstops;
|
int m_numstops;
|
||||||
@ -3201,9 +3199,9 @@ private:
|
|||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
layout_element::component::ptr layout_element::make_component(environment &env, util::xml::data_node const &compnode, const char *dirname)
|
layout_element::component::ptr layout_element::make_component(environment &env, util::xml::data_node const &compnode)
|
||||||
{
|
{
|
||||||
return std::make_unique<T>(env, compnode, dirname);
|
return std::make_unique<T>(env, compnode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3213,9 +3211,9 @@ layout_element::component::ptr layout_element::make_component(environment &env,
|
|||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
template <int D>
|
template <int D>
|
||||||
layout_element::component::ptr layout_element::make_dotmatrix_component(environment &env, util::xml::data_node const &compnode, const char *dirname)
|
layout_element::component::ptr layout_element::make_dotmatrix_component(environment &env, util::xml::data_node const &compnode)
|
||||||
{
|
{
|
||||||
return std::make_unique<dotmatrix_component>(D, env, compnode, dirname);
|
return std::make_unique<dotmatrix_component>(D, env, compnode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3276,7 +3274,7 @@ layout_element::texture &layout_element::texture::operator=(texture &&that)
|
|||||||
// component - constructor
|
// component - constructor
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
layout_element::component::component(environment &env, util::xml::data_node const &compnode, const char *dirname)
|
layout_element::component::component(environment &env, util::xml::data_node const &compnode)
|
||||||
: m_statemask(env.get_attribute_int(compnode, "statemask", env.get_attribute_string(compnode, "state", "")[0] ? ~0 : 0))
|
: m_statemask(env.get_attribute_int(compnode, "statemask", env.get_attribute_string(compnode, "state", "")[0] ? ~0 : 0))
|
||||||
, m_stateval(env.get_attribute_int(compnode, "state", m_statemask) & m_statemask)
|
, m_stateval(env.get_attribute_int(compnode, "state", m_statemask) & m_statemask)
|
||||||
{
|
{
|
||||||
@ -4576,13 +4574,17 @@ layout_view::visibility_toggle::visibility_toggle(std::string &&name, u32 mask)
|
|||||||
// layout_file - constructor
|
// layout_file - constructor
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
layout_file::layout_file(device_t &device, util::xml::data_node const &rootnode, char const *dirname)
|
layout_file::layout_file(
|
||||||
|
device_t &device,
|
||||||
|
util::xml::data_node const &rootnode,
|
||||||
|
char const *searchpath,
|
||||||
|
char const *dirname)
|
||||||
: m_elemmap()
|
: m_elemmap()
|
||||||
, m_viewlist()
|
, m_viewlist()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
environment env(device);
|
environment env(device, searchpath, dirname);
|
||||||
|
|
||||||
// find the layout node
|
// find the layout node
|
||||||
util::xml::data_node const *const mamelayoutnode = rootnode.get_child("mamelayout");
|
util::xml::data_node const *const mamelayoutnode = rootnode.get_child("mamelayout");
|
||||||
@ -4596,7 +4598,7 @@ layout_file::layout_file(device_t &device, util::xml::data_node const &rootnode,
|
|||||||
|
|
||||||
// parse all the parameters, elements and groups
|
// parse all the parameters, elements and groups
|
||||||
group_map groupmap;
|
group_map groupmap;
|
||||||
add_elements(dirname, env, *mamelayoutnode, groupmap, false, true);
|
add_elements(env, *mamelayoutnode, groupmap, false, true);
|
||||||
|
|
||||||
// parse all the views
|
// parse all the views
|
||||||
for (util::xml::data_node const *viewnode = mamelayoutnode->get_child("view"); viewnode != nullptr; viewnode = viewnode->get_next_sibling("view"))
|
for (util::xml::data_node const *viewnode = mamelayoutnode->get_child("view"); viewnode != nullptr; viewnode = viewnode->get_next_sibling("view"))
|
||||||
@ -4633,7 +4635,6 @@ layout_file::~layout_file()
|
|||||||
|
|
||||||
|
|
||||||
void layout_file::add_elements(
|
void layout_file::add_elements(
|
||||||
char const *dirname,
|
|
||||||
environment &env,
|
environment &env,
|
||||||
util::xml::data_node const &parentnode,
|
util::xml::data_node const &parentnode,
|
||||||
group_map &groupmap,
|
group_map &groupmap,
|
||||||
@ -4654,7 +4655,7 @@ void layout_file::add_elements(
|
|||||||
char const *const name(env.get_attribute_string(*childnode, "name", nullptr));
|
char const *const name(env.get_attribute_string(*childnode, "name", nullptr));
|
||||||
if (!name)
|
if (!name)
|
||||||
throw layout_syntax_error("element lacks name attribute");
|
throw layout_syntax_error("element lacks name attribute");
|
||||||
if (!m_elemmap.emplace(std::piecewise_construct, std::forward_as_tuple(name), std::forward_as_tuple(env, *childnode, dirname)).second)
|
if (!m_elemmap.emplace(std::piecewise_construct, std::forward_as_tuple(name), std::forward_as_tuple(env, *childnode)).second)
|
||||||
throw layout_syntax_error(util::string_format("duplicate element name %s", name));
|
throw layout_syntax_error(util::string_format("duplicate element name %s", name));
|
||||||
}
|
}
|
||||||
else if (!strcmp(childnode->get_name(), "group"))
|
else if (!strcmp(childnode->get_name(), "group"))
|
||||||
@ -4673,7 +4674,7 @@ void layout_file::add_elements(
|
|||||||
environment local(env);
|
environment local(env);
|
||||||
for (int i = 0; count > i; ++i)
|
for (int i = 0; count > i; ++i)
|
||||||
{
|
{
|
||||||
add_elements(dirname, local, *childnode, groupmap, true, !i);
|
add_elements(local, *childnode, groupmap, true, !i);
|
||||||
local.increment_parameters();
|
local.increment_parameters();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user