Get rid of porttype_t and devicetype_t
This commit is contained in:
parent
767b9719c2
commit
e27d4374dc
17 changed files with 312 additions and 325 deletions
|
@ -61,73 +61,6 @@
|
|||
*/
|
||||
#define MAX_ANALOG 3
|
||||
|
||||
|
||||
/**
|
||||
* This enumeration gives the type of port.
|
||||
*/
|
||||
enum porttype_t
|
||||
{
|
||||
/**
|
||||
* No device
|
||||
*/
|
||||
PT_NONE = 0, //Nothing connected to port.
|
||||
/**
|
||||
* Gamepad
|
||||
*/
|
||||
PT_GAMEPAD = 1,
|
||||
/**
|
||||
* Multitap (with 4 gamepads connected)
|
||||
*/
|
||||
PT_MULTITAP = 2,
|
||||
/**
|
||||
* Mouse
|
||||
*/
|
||||
PT_MOUSE = 3,
|
||||
/**
|
||||
* Superscope (only allowed for port 2).
|
||||
*/
|
||||
PT_SUPERSCOPE = 4,
|
||||
/**
|
||||
* Justifier (only allowed for port 2).
|
||||
*/
|
||||
PT_JUSTIFIER = 5,
|
||||
/**
|
||||
* 2 Justifiers (only allowed for port 2).
|
||||
*/
|
||||
PT_JUSTIFIERS = 6,
|
||||
/**
|
||||
* Number of controller types.
|
||||
*/
|
||||
PT_LAST_CTYPE = 6,
|
||||
/**
|
||||
* Invalid controller type.
|
||||
*/
|
||||
PT_INVALID = PT_LAST_CTYPE + 1
|
||||
};
|
||||
|
||||
/**
|
||||
* This enumeration gives the type of device.
|
||||
*/
|
||||
enum devicetype_t
|
||||
{
|
||||
/**
|
||||
* No device
|
||||
*/
|
||||
DT_NONE = 0,
|
||||
/**
|
||||
* Gamepad (note that multitap controllers are gamepads)
|
||||
*/
|
||||
DT_GAMEPAD = 1,
|
||||
/**
|
||||
* Mouse
|
||||
*/
|
||||
DT_MOUSE = 2,
|
||||
/**
|
||||
* Lightgun
|
||||
*/
|
||||
DT_LIGHTGUN = 3,
|
||||
};
|
||||
|
||||
/**
|
||||
* Is not field terminator.
|
||||
*
|
||||
|
@ -212,14 +145,6 @@ inline short unserialize_short(const unsigned char* buf)
|
|||
*/
|
||||
struct porttype_info
|
||||
{
|
||||
/**
|
||||
* Look up information about port type.
|
||||
*
|
||||
* Parameter p: The port type.
|
||||
* Returns: Infor about port type.
|
||||
* Throws std::runtime_error: Invalid port type.
|
||||
*/
|
||||
static const porttype_info& lookup(porttype_t p) throw(std::runtime_error);
|
||||
/**
|
||||
* Look up information about port type.
|
||||
*
|
||||
|
@ -227,16 +152,28 @@ struct porttype_info
|
|||
* Returns: Infor about port type.
|
||||
* Throws std::runtime_error: Invalid port type.
|
||||
*/
|
||||
static const porttype_info& lookup(const std::string& p) throw(std::runtime_error);
|
||||
static porttype_info& lookup(const std::string& p) throw(std::runtime_error);
|
||||
/**
|
||||
* Get set of all available port types.
|
||||
*/
|
||||
static std::set<porttype_info*> get_all();
|
||||
/**
|
||||
* Get some default port type.
|
||||
*/
|
||||
static porttype_info& default_type();
|
||||
/**
|
||||
* Get port default type.
|
||||
*/
|
||||
static porttype_info& port_default(unsigned port);
|
||||
/**
|
||||
* Register port type.
|
||||
*
|
||||
* Parameter ptype: Type value for port type.
|
||||
* Parameter pname: The name of port type.
|
||||
* Parameter hname: Human-readable name of the port type.
|
||||
* Parameter psize: The size of storage for this type.
|
||||
* Throws std::bad_alloc: Not enough memory.
|
||||
*/
|
||||
porttype_info(porttype_t ptype, const std::string& pname, size_t psize) throw(std::bad_alloc);
|
||||
porttype_info(const std::string& pname, const std::string& hname, size_t psize) throw(std::bad_alloc);
|
||||
/**
|
||||
* Unregister port type.
|
||||
*/
|
||||
|
@ -289,12 +226,22 @@ struct porttype_info
|
|||
*/
|
||||
size_t (*deserialize)(unsigned char* buffer, const char* textbuf);
|
||||
/**
|
||||
* Return device type for given index.
|
||||
* Get device flags for given index.
|
||||
*
|
||||
* Parameter idx: The index of controller.
|
||||
* Returns: The type of device.
|
||||
* Returns: The device flags.
|
||||
* Bit 0: Present.
|
||||
* Bit 1: Has absolute analog axes 0 and 1.
|
||||
* Bit 2: Has relative analog axes 0 and 1.
|
||||
*/
|
||||
devicetype_t (*devicetype)(unsigned idx);
|
||||
unsigned (*deviceflags)(unsigned idx);
|
||||
/**
|
||||
* Is the device legal for port?
|
||||
*
|
||||
* Parameter port: Port to query.
|
||||
* Returns: Nonzero if legal, zero if illegal.
|
||||
*/
|
||||
int (*legal)(unsigned port);
|
||||
/**
|
||||
* Number of controllers connected to this port.
|
||||
*/
|
||||
|
@ -313,6 +260,12 @@ struct porttype_info
|
|||
* Parameter port: Port to set to.
|
||||
*/
|
||||
void (*set_core_controller)(unsigned port);
|
||||
/**
|
||||
* Does the controller exist?
|
||||
*
|
||||
* Parameter controller: Controller number.
|
||||
*/
|
||||
bool is_present(unsigned controller) const throw();
|
||||
/**
|
||||
* Does the controller have analog function?
|
||||
*
|
||||
|
@ -326,9 +279,9 @@ struct porttype_info
|
|||
*/
|
||||
bool is_mouse(unsigned controller) const throw();
|
||||
/**
|
||||
* Port type value.
|
||||
* Human-readable name.
|
||||
*/
|
||||
porttype_t value;
|
||||
std::string hname;
|
||||
/**
|
||||
* Number of bytes it takes to store this.
|
||||
*/
|
||||
|
@ -337,6 +290,10 @@ struct porttype_info
|
|||
* Name of port type.
|
||||
*/
|
||||
std::string name;
|
||||
/**
|
||||
* Name of controller.
|
||||
*/
|
||||
std::string ctrlname;
|
||||
private:
|
||||
porttype_info(const porttype_info&);
|
||||
porttype_info& operator=(const porttype_info&);
|
||||
|
@ -477,7 +434,7 @@ public:
|
|||
*
|
||||
* Throws std::runtime_error: Invalid port type.
|
||||
*/
|
||||
controller_frame(porttype_t p1, porttype_t p2) throw(std::runtime_error);
|
||||
controller_frame(porttype_info& p1, porttype_info& p2) throw(std::runtime_error);
|
||||
/**
|
||||
* Create subframe of controls with specified controller types and specified memory.
|
||||
*
|
||||
|
@ -487,7 +444,7 @@ public:
|
|||
*
|
||||
* Throws std::runtime_error: Invalid port type or NULL memory.
|
||||
*/
|
||||
controller_frame(unsigned char* memory, porttype_t p1 = PT_GAMEPAD, porttype_t p2 = PT_NONE)
|
||||
controller_frame(unsigned char* memory, porttype_info& p1, porttype_info& p2)
|
||||
throw(std::runtime_error);
|
||||
/**
|
||||
* Copy construct a frame. The memory will be dedicated.
|
||||
|
@ -509,9 +466,9 @@ public:
|
|||
* Parameter port: Number of port.
|
||||
* Returns: The type of port.
|
||||
*/
|
||||
porttype_t get_port_type(unsigned port) throw()
|
||||
porttype_info& get_port_type(unsigned port) throw()
|
||||
{
|
||||
return (port < MAX_PORTS) ? types[port] : PT_NONE;
|
||||
return (port < MAX_PORTS) ? *types[port] : porttype_info::default_type();
|
||||
}
|
||||
/**
|
||||
* Get blank dedicated frame of same port types.
|
||||
|
@ -520,7 +477,7 @@ public:
|
|||
*/
|
||||
controller_frame blank_frame() throw()
|
||||
{
|
||||
return controller_frame(types[0], types[1]);
|
||||
return controller_frame(*types[0], *types[1]);
|
||||
}
|
||||
/**
|
||||
* Set type of port. Input for that port is zeroized.
|
||||
|
@ -529,7 +486,7 @@ public:
|
|||
* Parameter type: The new type.
|
||||
* Throws std::runtime_error: Bad port type or non-dedicated memory.
|
||||
*/
|
||||
void set_port_type(unsigned port, porttype_t ptype) throw(std::runtime_error);
|
||||
void set_port_type(unsigned port, porttype_info& ptype) throw(std::runtime_error);
|
||||
/**
|
||||
* Check that types match.
|
||||
*
|
||||
|
@ -654,7 +611,7 @@ public:
|
|||
void axis(unsigned pcid, unsigned ctrl, short x) throw()
|
||||
{
|
||||
unsigned port = (pcid / MAX_CONTROLLERS_PER_PORT) % MAX_PORTS;
|
||||
pinfo[port]->write(backing + offsets[port], pcid % MAX_CONTROLLERS_PER_PORT, ctrl, x);
|
||||
types[port]->write(backing + offsets[port], pcid % MAX_CONTROLLERS_PER_PORT, ctrl, x);
|
||||
}
|
||||
/**
|
||||
* Set axis/button value.
|
||||
|
@ -676,7 +633,7 @@ public:
|
|||
short axis(unsigned pcid, unsigned ctrl) throw()
|
||||
{
|
||||
unsigned port = (pcid / MAX_CONTROLLERS_PER_PORT) % MAX_PORTS;
|
||||
return pinfo[port]->read(backing + offsets[port], pcid % MAX_CONTROLLERS_PER_PORT, ctrl);
|
||||
return types[port]->read(backing + offsets[port], pcid % MAX_CONTROLLERS_PER_PORT, ctrl);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -698,18 +655,18 @@ public:
|
|||
void display(unsigned pcid, char* buf) throw()
|
||||
{
|
||||
unsigned port = (pcid / MAX_CONTROLLERS_PER_PORT) % MAX_PORTS;
|
||||
return pinfo[port]->display(backing + offsets[port], pcid % MAX_CONTROLLERS_PER_PORT, buf);
|
||||
return types[port]->display(backing + offsets[port], pcid % MAX_CONTROLLERS_PER_PORT, buf);
|
||||
}
|
||||
/**
|
||||
* Get device type.
|
||||
* Is device present?
|
||||
*
|
||||
* Parameter pcid: Physical controller id.
|
||||
* Returns: Device type.
|
||||
* Returns: True if present, false if not.
|
||||
*/
|
||||
devicetype_t devicetype(unsigned pcid) throw()
|
||||
bool is_present(unsigned pcid) throw()
|
||||
{
|
||||
unsigned port = (pcid / MAX_CONTROLLERS_PER_PORT) % MAX_PORTS;
|
||||
return pinfo[port]->devicetype(pcid % MAX_CONTROLLERS_PER_PORT);
|
||||
return types[port]->is_present(pcid % MAX_CONTROLLERS_PER_PORT);
|
||||
}
|
||||
/**
|
||||
* Deserialize frame from text format.
|
||||
|
@ -724,7 +681,7 @@ public:
|
|||
if(buf[offset] == '|')
|
||||
offset++;
|
||||
for(size_t i = 0; i < MAX_PORTS; i++) {
|
||||
size_t s = pinfo[i]->deserialize(backing + offsets[i], buf + offset);
|
||||
size_t s = types[i]->deserialize(backing + offsets[i], buf + offset);
|
||||
if(s != DESERIALIZE_SPECIAL_BLANK) {
|
||||
offset += s;
|
||||
if(buf[offset] == '|')
|
||||
|
@ -742,7 +699,7 @@ public:
|
|||
size_t offset = 0;
|
||||
offset += system_serialize(backing, buf);
|
||||
for(size_t i = 0; i < MAX_PORTS; i++)
|
||||
offset += pinfo[i]->serialize(backing + offsets[i], buf + offset);
|
||||
offset += types[i]->serialize(backing + offsets[i], buf + offset);
|
||||
buf[offset++] = '\0';
|
||||
}
|
||||
/**
|
||||
|
@ -789,7 +746,7 @@ public:
|
|||
int button_id(unsigned pcid, unsigned lbid)
|
||||
{
|
||||
unsigned port = (pcid / MAX_CONTROLLERS_PER_PORT) % MAX_PORTS;
|
||||
return pinfo[port]->button_id(pcid % MAX_CONTROLLERS_PER_PORT, lbid);
|
||||
return types[port]->button_id(pcid % MAX_CONTROLLERS_PER_PORT, lbid);
|
||||
}
|
||||
/**
|
||||
* Does the specified controller have analog function.
|
||||
|
@ -799,7 +756,7 @@ public:
|
|||
bool is_analog(unsigned pcid)
|
||||
{
|
||||
unsigned port = (pcid / MAX_CONTROLLERS_PER_PORT) % MAX_PORTS;
|
||||
return pinfo[port]->is_analog(pcid % MAX_CONTROLLERS_PER_PORT);
|
||||
return types[port]->is_analog(pcid % MAX_CONTROLLERS_PER_PORT);
|
||||
}
|
||||
/**
|
||||
* Does the specified controller have mouse-type function.
|
||||
|
@ -809,18 +766,17 @@ public:
|
|||
bool is_mouse(unsigned pcid)
|
||||
{
|
||||
unsigned port = (pcid / MAX_CONTROLLERS_PER_PORT) % MAX_PORTS;
|
||||
return pinfo[port]->is_mouse(pcid % MAX_CONTROLLERS_PER_PORT);
|
||||
return types[port]->is_mouse(pcid % MAX_CONTROLLERS_PER_PORT);
|
||||
}
|
||||
private:
|
||||
size_t totalsize;
|
||||
unsigned char memory[MAXIMUM_CONTROLLER_FRAME_SIZE];
|
||||
unsigned char* backing;
|
||||
porttype_t types[MAX_PORTS];
|
||||
porttype_info* types[MAX_PORTS];
|
||||
size_t offsets[MAX_PORTS];
|
||||
const porttype_info* pinfo[MAX_PORTS];
|
||||
static size_t system_serialize(const unsigned char* buffer, char* textbuf);
|
||||
static size_t system_deserialize(unsigned char* buffer, const char* textbuf);
|
||||
void set_types(const porttype_t* tarr);
|
||||
void set_types(porttype_info** tarr);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -829,6 +785,10 @@ private:
|
|||
class controller_frame_vector
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Construct new controller frame vector.
|
||||
*/
|
||||
controller_frame_vector() throw(std::runtime_error);
|
||||
/**
|
||||
* Construct new controller frame vector.
|
||||
*
|
||||
|
@ -836,8 +796,7 @@ public:
|
|||
* Parameter p2: Type of port 2.
|
||||
* Throws std::runtime_error: Illegal port types.
|
||||
*/
|
||||
controller_frame_vector(enum porttype_t p1 = PT_INVALID, enum porttype_t p2 = PT_INVALID)
|
||||
throw(std::runtime_error);
|
||||
controller_frame_vector(porttype_info& p1, porttype_info& p2) throw(std::runtime_error);
|
||||
/**
|
||||
* Destroy controller frame vector
|
||||
*/
|
||||
|
@ -864,13 +823,13 @@ public:
|
|||
* Parameter p2: Type of port 2.
|
||||
* Throws std::runtime_error: Illegal port types.
|
||||
*/
|
||||
void clear(enum porttype_t p1, enum porttype_t p2) throw(std::runtime_error);
|
||||
void clear(porttype_info& p1, porttype_info& p2) throw(std::runtime_error);
|
||||
/**
|
||||
* Blank vector.
|
||||
*/
|
||||
void clear() throw()
|
||||
{
|
||||
clear(types[0], types[1]);
|
||||
clear(*types[0], *types[1]);
|
||||
}
|
||||
/**
|
||||
* Get number of subframes.
|
||||
|
@ -896,7 +855,7 @@ public:
|
|||
cache_page = &pages[page];
|
||||
cache_page_num = page;
|
||||
}
|
||||
return controller_frame(cache_page->content + pageoffset, types[0], types[1]);
|
||||
return controller_frame(cache_page->content + pageoffset, *types[0], *types[1]);
|
||||
}
|
||||
/**
|
||||
* Append a subframe.
|
||||
|
@ -957,7 +916,7 @@ public:
|
|||
*/
|
||||
controller_frame blank_frame(bool sync)
|
||||
{
|
||||
controller_frame c(types[0], types[1]);
|
||||
controller_frame c(*types[0], *types[1]);
|
||||
c.sync(sync);
|
||||
return c;
|
||||
}
|
||||
|
@ -971,7 +930,7 @@ private:
|
|||
size_t frames_per_page;
|
||||
size_t frame_size;
|
||||
size_t frames;
|
||||
porttype_t types[MAX_PORTS];
|
||||
porttype_info* types[MAX_PORTS];
|
||||
size_t cache_page_num;
|
||||
page* cache_page;
|
||||
std::map<size_t, page> pages;
|
||||
|
@ -1016,12 +975,12 @@ public:
|
|||
*/
|
||||
bool acid_is_mouse(unsigned acid) throw();
|
||||
/**
|
||||
* Look up device type type of given pcid.
|
||||
* Is given pcid present?
|
||||
*
|
||||
* Parameter pcid: The physical controller id.
|
||||
* Returns: The type of device.
|
||||
* Returns: True if present, false if not.
|
||||
*/
|
||||
devicetype_t pcid_to_type(unsigned pcid) throw();
|
||||
bool pcid_present(unsigned pcid) throw();
|
||||
/**
|
||||
* Set type of port.
|
||||
*
|
||||
|
@ -1030,7 +989,7 @@ public:
|
|||
* Parameter set_core: If true, set the core port type too, otherwise don't do that.
|
||||
* Throws std::runtime_error: Illegal port type.
|
||||
*/
|
||||
void set_port(unsigned port, porttype_t ptype, bool set_core) throw(std::runtime_error);
|
||||
void set_port(unsigned port, porttype_info& ptype, bool set_core) throw(std::runtime_error);
|
||||
/**
|
||||
* Get status of current controls (with autohold/autofire factored in).
|
||||
*
|
||||
|
@ -1142,6 +1101,10 @@ public:
|
|||
* Returns: The physical button id, or -1 if no such button.
|
||||
*/
|
||||
int button_id(unsigned pcid, unsigned lbid) throw();
|
||||
/**
|
||||
* TODO: Document.
|
||||
*/
|
||||
bool is_present(unsigned pcid) throw();
|
||||
/**
|
||||
* TODO: Document.
|
||||
*/
|
||||
|
@ -1151,8 +1114,7 @@ public:
|
|||
*/
|
||||
bool is_mouse(unsigned pcid) throw();
|
||||
private:
|
||||
const porttype_info* porttypeinfo[MAX_PORTS];
|
||||
porttype_t porttypes[MAX_PORTS];
|
||||
porttype_info* porttypes[MAX_PORTS];
|
||||
int analog_indices[MAX_ANALOG];
|
||||
bool analog_mouse[MAX_ANALOG];
|
||||
controller_frame _input;
|
||||
|
@ -1284,7 +1246,7 @@ inline size_t generic_port_deserialize(unsigned char* buffer, const char* textbu
|
|||
}
|
||||
|
||||
template<unsigned mask>
|
||||
inline bool generic_port_legal(unsigned port) throw()
|
||||
inline int generic_port_legal(unsigned port) throw()
|
||||
{
|
||||
if(port >= CHAR_BIT * sizeof(unsigned))
|
||||
port = CHAR_BIT * sizeof(unsigned) - 1;
|
||||
|
@ -1294,10 +1256,10 @@ inline bool generic_port_legal(unsigned port) throw()
|
|||
/**
|
||||
* Generic port type function.
|
||||
*/
|
||||
template<unsigned controllers, devicetype_t dtype>
|
||||
inline devicetype_t generic_port_devicetype(unsigned idx) throw()
|
||||
template<unsigned controllers, unsigned flags>
|
||||
inline unsigned generic_port_deviceflags(unsigned idx) throw()
|
||||
{
|
||||
return (idx < controllers) ? dtype : DT_NONE;
|
||||
return (idx < controllers) ? flags : 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -41,6 +41,8 @@ uint32_t get_snes_cpu_rate();
|
|||
uint32_t get_snes_apu_rate();
|
||||
//Get the core identifier.
|
||||
std::string get_core_identifier();
|
||||
//Get the default controller type for specified port.
|
||||
std::string get_core_default_port(unsigned port);
|
||||
//Do basic core initialization (to get it to stable state).
|
||||
void do_basic_core_init();
|
||||
//Get set of SRAMs.
|
||||
|
|
|
@ -51,11 +51,11 @@ struct moviefile
|
|||
/**
|
||||
* What's in port #1?
|
||||
*/
|
||||
porttype_t port1;
|
||||
porttype_info* port1;
|
||||
/**
|
||||
* What's in port #2?
|
||||
*/
|
||||
porttype_t port2;
|
||||
porttype_info* port2;
|
||||
/**
|
||||
* Emulator Core version string.
|
||||
*/
|
||||
|
|
|
@ -251,6 +251,14 @@ void core_install_handler()
|
|||
SNES::system.init();
|
||||
}
|
||||
|
||||
std::string get_core_default_port(unsigned port)
|
||||
{
|
||||
if(port == 0)
|
||||
return "gamepad";
|
||||
else
|
||||
return "none";
|
||||
}
|
||||
|
||||
void core_uninstall_handler()
|
||||
{
|
||||
SNES::interface = old;
|
||||
|
|
|
@ -25,14 +25,16 @@ namespace
|
|||
|
||||
struct porttype_invalid : public porttype_info
|
||||
{
|
||||
porttype_invalid() : porttype_info(PT_INVALID, "invalid-port-type", 0)
|
||||
porttype_invalid() : porttype_info("invalid-port-type", "invalid-port-type", 0)
|
||||
{
|
||||
write = NULL;
|
||||
read = NULL;
|
||||
display = NULL;
|
||||
serialize = NULL;
|
||||
deserialize = NULL;
|
||||
devicetype = generic_port_devicetype<0, DT_NONE>;
|
||||
legal = NULL;
|
||||
deviceflags = generic_port_deviceflags<0, 0>;
|
||||
ctrlname = "";
|
||||
controllers = 0;
|
||||
set_core_controller = set_core_controller_illegal;
|
||||
}
|
||||
|
@ -45,14 +47,16 @@ namespace
|
|||
|
||||
struct porttype_gamepad : public porttype_info
|
||||
{
|
||||
porttype_gamepad() : porttype_info(PT_GAMEPAD, "gamepad", generic_port_size<1, 0, 12>())
|
||||
porttype_gamepad() : porttype_info("gamepad", "Gamepad", generic_port_size<1, 0, 12>())
|
||||
{
|
||||
write = generic_port_write<1, 0, 12>;
|
||||
read = generic_port_read<1, 0, 12>;
|
||||
display = generic_port_display<1, 0, 12, 0>;
|
||||
serialize = generic_port_serialize<1, 0, 12, 0>;
|
||||
deserialize = generic_port_deserialize<1, 0, 12>;
|
||||
devicetype = generic_port_devicetype<1, DT_GAMEPAD>;
|
||||
legal = generic_port_legal<3>;
|
||||
deviceflags = generic_port_deviceflags<1, 1>;
|
||||
ctrlname = "gamepad";
|
||||
controllers = 1;
|
||||
set_core_controller = set_core_controller_gamepad;
|
||||
}
|
||||
|
@ -65,14 +69,16 @@ namespace
|
|||
|
||||
struct porttype_justifier : public porttype_info
|
||||
{
|
||||
porttype_justifier() : porttype_info(PT_JUSTIFIER, "justifier", generic_port_size<1, 2, 2>())
|
||||
porttype_justifier() : porttype_info("justifier", "Justifier", generic_port_size<1, 2, 2>())
|
||||
{
|
||||
write = generic_port_write<1, 2, 2>;
|
||||
read = generic_port_read<1, 2, 2>;
|
||||
display = generic_port_display<1, 2, 2, 12>;
|
||||
serialize = generic_port_serialize<1, 2, 2, 12>;
|
||||
deserialize = generic_port_deserialize<1, 2, 2>;
|
||||
devicetype = generic_port_devicetype<1, DT_LIGHTGUN>;
|
||||
legal = generic_port_legal<2>;
|
||||
deviceflags = generic_port_deviceflags<1, 3>;
|
||||
ctrlname = "justifier";
|
||||
controllers = 1;
|
||||
set_core_controller = set_core_controller_justifier;
|
||||
}
|
||||
|
@ -85,14 +91,16 @@ namespace
|
|||
|
||||
struct porttype_justifiers : public porttype_info
|
||||
{
|
||||
porttype_justifiers() : porttype_info(PT_JUSTIFIERS, "justifiers", generic_port_size<2, 2, 2>())
|
||||
porttype_justifiers() : porttype_info("justifiers", "2 Justifiers", generic_port_size<2, 2, 2>())
|
||||
{
|
||||
write = generic_port_write<2, 2, 2>;
|
||||
read = generic_port_read<2, 2, 2>;
|
||||
display = generic_port_display<2, 2, 2, 0>;
|
||||
serialize = generic_port_serialize<2, 2, 2, 12>;
|
||||
deserialize = generic_port_deserialize<2, 2, 2>;
|
||||
devicetype = generic_port_devicetype<2, DT_LIGHTGUN>;
|
||||
legal = generic_port_legal<2>;
|
||||
deviceflags = generic_port_deviceflags<2, 3>;
|
||||
ctrlname = "justifier";
|
||||
controllers = 2;
|
||||
set_core_controller = set_core_controller_justifiers;
|
||||
}
|
||||
|
@ -105,14 +113,16 @@ namespace
|
|||
|
||||
struct porttype_mouse : public porttype_info
|
||||
{
|
||||
porttype_mouse() : porttype_info(PT_MOUSE, "mouse", generic_port_size<1, 2, 2>())
|
||||
porttype_mouse() : porttype_info("mouse", "Mouse", generic_port_size<1, 2, 2>())
|
||||
{
|
||||
write = generic_port_write<1, 2, 2>;
|
||||
read = generic_port_read<1, 2, 2>;
|
||||
display = generic_port_display<1, 2, 2, 0>;
|
||||
serialize = generic_port_serialize<1, 2, 2, 12>;
|
||||
deserialize = generic_port_deserialize<1, 2, 2>;
|
||||
devicetype = generic_port_devicetype<1, DT_MOUSE>;
|
||||
legal = generic_port_legal<3>;
|
||||
deviceflags = generic_port_deviceflags<1, 5>;
|
||||
ctrlname = "mouse";
|
||||
controllers = 1;
|
||||
set_core_controller = set_core_controller_mouse;
|
||||
}
|
||||
|
@ -125,14 +135,16 @@ namespace
|
|||
|
||||
struct porttype_multitap : public porttype_info
|
||||
{
|
||||
porttype_multitap() : porttype_info(PT_MULTITAP, "multitap", generic_port_size<4, 0, 12>())
|
||||
porttype_multitap() : porttype_info("multitap", "Multitap", generic_port_size<4, 0, 12>())
|
||||
{
|
||||
write = generic_port_write<4, 0, 12>;
|
||||
read = generic_port_read<4, 0, 12>;
|
||||
display = generic_port_display<4, 0, 12, 0>;
|
||||
serialize = generic_port_serialize<4, 0, 12, 0>;
|
||||
deserialize = generic_port_deserialize<4, 0, 12>;
|
||||
devicetype = generic_port_devicetype<4, DT_GAMEPAD>;
|
||||
legal = generic_port_legal<3>;
|
||||
deviceflags = generic_port_deviceflags<4, 1>;
|
||||
ctrlname = "multitap";
|
||||
controllers = 4;
|
||||
set_core_controller = set_core_controller_multitap;
|
||||
}
|
||||
|
@ -145,14 +157,16 @@ namespace
|
|||
|
||||
struct porttype_none : public porttype_info
|
||||
{
|
||||
porttype_none() : porttype_info(PT_NONE, "none", generic_port_size<0, 0, 0>())
|
||||
porttype_none() : porttype_info("none", "None", generic_port_size<0, 0, 0>())
|
||||
{
|
||||
write = generic_port_write<0, 0, 0>;
|
||||
read = generic_port_read<0, 0, 0>;
|
||||
display = generic_port_display<0, 0, 0, 0>;
|
||||
serialize = generic_port_serialize<0, 0, 0, 0>;
|
||||
deserialize = generic_port_deserialize<0, 0, 0>;
|
||||
devicetype = generic_port_devicetype<0, DT_GAMEPAD>;
|
||||
legal = generic_port_legal<3>;
|
||||
deviceflags = generic_port_deviceflags<0, 0>;
|
||||
ctrlname = "";
|
||||
controllers = 0;
|
||||
set_core_controller = set_core_controller_none;
|
||||
}
|
||||
|
@ -165,14 +179,15 @@ namespace
|
|||
|
||||
struct porttype_superscope : public porttype_info
|
||||
{
|
||||
porttype_superscope() : porttype_info(PT_SUPERSCOPE, "superscope", generic_port_size<1, 2, 4>())
|
||||
porttype_superscope() : porttype_info("superscope", "Super Scope", generic_port_size<1, 2, 4>())
|
||||
{
|
||||
write = generic_port_write<1, 2, 4>;
|
||||
read = generic_port_read<1, 2, 4>;
|
||||
display = generic_port_display<1, 2, 4, 0>;
|
||||
serialize = generic_port_serialize<1, 2, 4, 14>;
|
||||
deserialize = generic_port_deserialize<1, 2, 4>;
|
||||
devicetype = generic_port_devicetype<1, DT_LIGHTGUN>;
|
||||
legal = generic_port_legal<2>;
|
||||
ctrlname = "superscope";
|
||||
controllers = 1;
|
||||
set_core_controller = set_core_controller_superscope;
|
||||
}
|
||||
|
@ -190,22 +205,18 @@ namespace
|
|||
}
|
||||
}
|
||||
|
||||
const porttype_info& porttype_info::lookup(porttype_t p) throw(std::runtime_error)
|
||||
porttype_info& porttype_info::lookup(const std::string& p) throw(std::runtime_error)
|
||||
{
|
||||
get_invalid_port_type();
|
||||
for(auto i : porttypes())
|
||||
if(p == i->value)
|
||||
if(p == i->name && i->legal)
|
||||
return *i;
|
||||
throw std::runtime_error("Bad port type");
|
||||
}
|
||||
|
||||
const porttype_info& porttype_info::lookup(const std::string& p) throw(std::runtime_error)
|
||||
porttype_info& porttype_info::port_default(unsigned port)
|
||||
{
|
||||
get_invalid_port_type();
|
||||
for(auto i : porttypes())
|
||||
if(p == i->name && i->value != PT_INVALID)
|
||||
return *i;
|
||||
throw std::runtime_error("Bad port type");
|
||||
return lookup(get_core_default_port(port));
|
||||
}
|
||||
|
||||
porttype_info::~porttype_info() throw()
|
||||
|
@ -213,23 +224,43 @@ porttype_info::~porttype_info() throw()
|
|||
porttypes().erase(this);
|
||||
}
|
||||
|
||||
porttype_info::porttype_info(porttype_t ptype, const std::string& pname, size_t psize) throw(std::bad_alloc)
|
||||
porttype_info::porttype_info(const std::string& pname, const std::string& _hname, size_t psize) throw(std::bad_alloc)
|
||||
{
|
||||
value = ptype;
|
||||
name = pname;
|
||||
hname = _hname;
|
||||
storage_size = psize;
|
||||
porttypes().insert(this);
|
||||
}
|
||||
|
||||
porttype_info& porttype_info::default_type()
|
||||
{
|
||||
return get_invalid_port_type();
|
||||
}
|
||||
|
||||
std::set<porttype_info*> porttype_info::get_all()
|
||||
{
|
||||
std::set<porttype_info*> p;
|
||||
for(auto i : porttypes())
|
||||
if(i->legal)
|
||||
p.insert(i);
|
||||
return p;
|
||||
}
|
||||
|
||||
bool porttype_info::is_present(unsigned controller) const throw()
|
||||
{
|
||||
unsigned d = deviceflags(controller);
|
||||
return ((d & 1) != 0);
|
||||
}
|
||||
|
||||
bool porttype_info::is_analog(unsigned controller) const throw()
|
||||
{
|
||||
devicetype_t d = devicetype(controller);
|
||||
return (d == DT_MOUSE || d == DT_LIGHTGUN);
|
||||
unsigned d = deviceflags(controller);
|
||||
return ((d & 1) != 0) && ((d & 6) != 0);
|
||||
}
|
||||
|
||||
bool porttype_info::is_mouse(unsigned controller) const throw()
|
||||
{
|
||||
return (devicetype(controller) == DT_MOUSE);
|
||||
return ((deviceflags(controller) & 5) == 5);
|
||||
}
|
||||
|
||||
pollcounter_vector::pollcounter_vector() throw()
|
||||
|
@ -327,23 +358,23 @@ bool pollcounter_vector::check(const std::vector<uint32_t>& mem) throw()
|
|||
}
|
||||
|
||||
|
||||
controller_frame::controller_frame(porttype_t p1, porttype_t p2) throw(std::runtime_error)
|
||||
controller_frame::controller_frame(porttype_info& p1, porttype_info& p2) throw(std::runtime_error)
|
||||
{
|
||||
memset(memory, 0, sizeof(memory));
|
||||
backing = memory;
|
||||
types[0] = p1;
|
||||
types[1] = p2;
|
||||
types[0] = &p1;
|
||||
types[1] = &p2;
|
||||
set_types(types);
|
||||
}
|
||||
|
||||
controller_frame::controller_frame(unsigned char* mem, porttype_t p1, porttype_t p2) throw(std::runtime_error)
|
||||
controller_frame::controller_frame(unsigned char* mem, porttype_info& p1, porttype_info& p2) throw(std::runtime_error)
|
||||
{
|
||||
if(!mem)
|
||||
throw std::runtime_error("NULL backing memory not allowed");
|
||||
memset(memory, 0, sizeof(memory));
|
||||
backing = mem;
|
||||
types[0] = p1;
|
||||
types[1] = p2;
|
||||
types[0] = &p1;
|
||||
types[1] = &p2;
|
||||
set_types(types);
|
||||
}
|
||||
|
||||
|
@ -351,17 +382,17 @@ controller_frame::controller_frame(const controller_frame& obj) throw()
|
|||
{
|
||||
memset(memory, 0, sizeof(memory));
|
||||
backing = memory;
|
||||
set_types(obj.types);
|
||||
set_types(const_cast<porttype_info**>(obj.types));
|
||||
memcpy(backing, obj.backing, totalsize);
|
||||
}
|
||||
|
||||
controller_frame& controller_frame::operator=(const controller_frame& obj) throw(std::runtime_error)
|
||||
{
|
||||
set_types(obj.types);
|
||||
set_types(const_cast<porttype_info**>(obj.types));
|
||||
memcpy(backing, obj.backing, totalsize);
|
||||
}
|
||||
|
||||
void controller_frame::set_types(const porttype_t* tarr)
|
||||
void controller_frame::set_types(porttype_info** tarr)
|
||||
{
|
||||
for(unsigned i = 0; i < MAX_PORTS; i++) {
|
||||
if(memory != backing && types[i] != tarr[i])
|
||||
|
@ -371,8 +402,7 @@ void controller_frame::set_types(const porttype_t* tarr)
|
|||
for(unsigned i = 0; i < MAX_PORTS; i++) {
|
||||
offsets[i] = offset;
|
||||
types[i] = tarr[i];
|
||||
pinfo[i] = &porttype_info::lookup(tarr[i]);
|
||||
offset += pinfo[i]->storage_size;
|
||||
offset += types[i]->storage_size;
|
||||
}
|
||||
totalsize = offset;
|
||||
}
|
||||
|
@ -432,14 +462,14 @@ size_t controller_frame_vector::count_frames() throw()
|
|||
return ret;
|
||||
}
|
||||
|
||||
void controller_frame_vector::clear(enum porttype_t p1, enum porttype_t p2) throw(std::runtime_error)
|
||||
void controller_frame_vector::clear(porttype_info& p1, porttype_info& p2) throw(std::runtime_error)
|
||||
{
|
||||
controller_frame check(p1, p2);
|
||||
frame_size = check.size();
|
||||
frames_per_page = CONTROLLER_PAGE_SIZE / frame_size;
|
||||
frames = 0;
|
||||
types[0] = p1;
|
||||
types[1] = p2;
|
||||
types[0] = &p1;
|
||||
types[1] = &p2;
|
||||
clear_cache();
|
||||
pages.clear();
|
||||
}
|
||||
|
@ -450,14 +480,19 @@ controller_frame_vector::~controller_frame_vector() throw()
|
|||
cache_page = NULL;
|
||||
}
|
||||
|
||||
controller_frame_vector::controller_frame_vector(enum porttype_t p1, enum porttype_t p2) throw(std::runtime_error)
|
||||
controller_frame_vector::controller_frame_vector() throw(std::runtime_error)
|
||||
{
|
||||
clear(porttype_info::default_type(), porttype_info::default_type());
|
||||
}
|
||||
|
||||
controller_frame_vector::controller_frame_vector(porttype_info& p1, porttype_info& p2) throw(std::runtime_error)
|
||||
{
|
||||
clear(p1, p2);
|
||||
}
|
||||
|
||||
void controller_frame_vector::append(controller_frame frame) throw(std::bad_alloc, std::runtime_error)
|
||||
{
|
||||
controller_frame check(types[0], types[1]);
|
||||
controller_frame check(*types[0], *types[1]);
|
||||
if(!check.types_match(frame))
|
||||
throw std::runtime_error("controller_frame_vector::append: Type mismatch");
|
||||
if(frames % frames_per_page == 0) {
|
||||
|
@ -471,13 +506,13 @@ void controller_frame_vector::append(controller_frame frame) throw(std::bad_allo
|
|||
cache_page_num = page;
|
||||
cache_page = &pages[page];
|
||||
}
|
||||
controller_frame(cache_page->content + offset, types[0], types[1]) = frame;
|
||||
controller_frame(cache_page->content + offset, *types[0], *types[1]) = frame;
|
||||
frames++;
|
||||
}
|
||||
|
||||
controller_frame_vector::controller_frame_vector(const controller_frame_vector& vector) throw(std::bad_alloc)
|
||||
{
|
||||
clear(vector.types[0], vector.types[1]);
|
||||
clear(*vector.types[0], *vector.types[1]);
|
||||
*this = vector;
|
||||
}
|
||||
|
||||
|
@ -609,27 +644,26 @@ controller_frame::controller_frame() throw()
|
|||
backing = memory;
|
||||
for(unsigned i = 0; i < MAX_PORTS; i++) {
|
||||
offsets[i] = SYSTEM_BYTES;
|
||||
types[i] = PT_INVALID;
|
||||
pinfo[i] = NULL;
|
||||
types[i] = &porttype_info::default_type();
|
||||
}
|
||||
totalsize = SYSTEM_BYTES;
|
||||
}
|
||||
|
||||
void controller_frame::set_port_type(unsigned port, porttype_t ptype) throw(std::runtime_error)
|
||||
void controller_frame::set_port_type(unsigned port, porttype_info& ptype) throw(std::runtime_error)
|
||||
{
|
||||
char tmp[MAXIMUM_CONTROLLER_FRAME_SIZE] = {0};
|
||||
if(memory != backing)
|
||||
throw std::runtime_error("Can't set port type on non-dedicated controller frame");
|
||||
if(port >= MAX_PORTS)
|
||||
return;
|
||||
const porttype_info* newpinfo[MAX_PORTS];
|
||||
porttype_info* newpinfo[MAX_PORTS];
|
||||
size_t newoffsets[MAX_PORTS];
|
||||
size_t offset = SYSTEM_BYTES;
|
||||
for(size_t i = 0; i < MAX_PORTS; i++) {
|
||||
if(i != port)
|
||||
newpinfo[i] = pinfo[i];
|
||||
newpinfo[i] = types[i];
|
||||
else
|
||||
newpinfo[i] = &porttype_info::lookup(ptype);
|
||||
newpinfo[i] = &ptype;
|
||||
newoffsets[i] = offset;
|
||||
if(newpinfo[i])
|
||||
offset += newpinfo[i]->storage_size;
|
||||
|
@ -637,8 +671,7 @@ void controller_frame::set_port_type(unsigned port, porttype_t ptype) throw(std:
|
|||
memcpy(tmp + newoffsets[i], backing + offsets[i], newpinfo[i]->storage_size);
|
||||
}
|
||||
memcpy(memory, tmp, MAXIMUM_CONTROLLER_FRAME_SIZE);
|
||||
types[port] = ptype;
|
||||
pinfo[port] = newpinfo[port];
|
||||
types[port] = &ptype;
|
||||
for(size_t i = 0; i < MAX_PORTS; i++)
|
||||
offsets[i] = newoffsets[i];
|
||||
totalsize = offset;
|
||||
|
@ -651,17 +684,16 @@ controller_state::controller_state() throw()
|
|||
analog_mouse[i] = false;
|
||||
}
|
||||
for(size_t i = 0; i < MAX_PORTS; i++) {
|
||||
porttypes[i] = PT_INVALID;
|
||||
porttypeinfo[i] = NULL;
|
||||
porttypes[i] = &porttype_info::default_type();
|
||||
}
|
||||
}
|
||||
|
||||
int controller_state::lcid_to_pcid(unsigned lcid) throw()
|
||||
{
|
||||
if(!porttypeinfo[0] || !porttypeinfo[1])
|
||||
if(!porttypes[0] || !porttypes[1])
|
||||
return -1;
|
||||
unsigned p1devs = porttypeinfo[0]->controllers;
|
||||
unsigned p2devs = porttypeinfo[1]->controllers;
|
||||
unsigned p1devs = porttypes[0]->controllers;
|
||||
unsigned p2devs = porttypes[1]->controllers;
|
||||
if(lcid >= p1devs + p2devs)
|
||||
return -1;
|
||||
//Exceptional: If p1 is none, map all to p2.
|
||||
|
@ -693,14 +725,6 @@ bool controller_state::acid_is_mouse(unsigned acid) throw()
|
|||
|
||||
}
|
||||
|
||||
devicetype_t controller_state::pcid_to_type(unsigned pcid) throw()
|
||||
{
|
||||
size_t port = pcid / MAX_CONTROLLERS_PER_PORT;
|
||||
if(port >= MAX_PORTS)
|
||||
return DT_NONE;
|
||||
return porttypeinfo[port]->devicetype(pcid % MAX_CONTROLLERS_PER_PORT);
|
||||
}
|
||||
|
||||
controller_frame controller_state::get(uint64_t framenum) throw()
|
||||
{
|
||||
if(_autofire.size())
|
||||
|
@ -776,18 +800,18 @@ int controller_state::button_id(unsigned pcid, unsigned lbid) throw()
|
|||
size_t port = pcid / MAX_CONTROLLERS_PER_PORT;
|
||||
if(port >= MAX_PORTS)
|
||||
return -1;
|
||||
return porttypeinfo[port]->button_id(pcid % MAX_CONTROLLERS_PER_PORT, lbid);
|
||||
return porttypes[port]->button_id(pcid % MAX_CONTROLLERS_PER_PORT, lbid);
|
||||
}
|
||||
|
||||
void controller_state::set_port(unsigned port, porttype_t ptype, bool set_core) throw(std::runtime_error)
|
||||
void controller_state::set_port(unsigned port, porttype_info& ptype, bool set_core) throw(std::runtime_error)
|
||||
{
|
||||
if(port >= MAX_PORTS)
|
||||
throw std::runtime_error("Port number invalid");
|
||||
const porttype_info* info = &porttype_info::lookup(ptype);
|
||||
porttype_info* info = &ptype;
|
||||
if(set_core)
|
||||
info->set_core_controller(port);
|
||||
porttype_t oldtype = porttypes[port];
|
||||
if(oldtype != ptype) {
|
||||
porttype_info* oldtype = porttypes[port];
|
||||
if(oldtype != &ptype) {
|
||||
_input.set_port_type(port, ptype);
|
||||
_autohold.set_port_type(port, ptype);
|
||||
_committed.set_port_type(port, ptype);
|
||||
|
@ -795,27 +819,19 @@ void controller_state::set_port(unsigned port, porttype_t ptype, bool set_core)
|
|||
//The old autofire pattern no longer applies.
|
||||
_autofire.clear();
|
||||
}
|
||||
porttypes[port] = ptype;
|
||||
porttypeinfo[port] = info;
|
||||
porttypes[port] = &ptype;
|
||||
int i = 0;
|
||||
for(unsigned j = 0; j < MAX_ANALOG; j++)
|
||||
analog_indices[j] = -1;
|
||||
for(unsigned j = 0; j < MAX_PORTS * MAX_CONTROLLERS_PER_PORT; j++) {
|
||||
if(!porttypeinfo[j / MAX_CONTROLLERS_PER_PORT])
|
||||
if(!porttypes[j / MAX_CONTROLLERS_PER_PORT])
|
||||
continue;
|
||||
devicetype_t d = porttypeinfo[j / MAX_CONTROLLERS_PER_PORT]->devicetype(j % MAX_CONTROLLERS_PER_PORT);
|
||||
switch(d) {
|
||||
case DT_NONE:
|
||||
case DT_GAMEPAD:
|
||||
break;
|
||||
case DT_MOUSE:
|
||||
if(porttypes[j / MAX_CONTROLLERS_PER_PORT]->is_mouse(j % MAX_CONTROLLERS_PER_PORT)) {
|
||||
analog_mouse[i] = true;
|
||||
analog_indices[i++] = j;
|
||||
break;
|
||||
case DT_LIGHTGUN:
|
||||
} else if(porttypes[j / MAX_CONTROLLERS_PER_PORT]->is_analog(j % MAX_CONTROLLERS_PER_PORT)) {
|
||||
analog_mouse[i] = false;
|
||||
analog_indices[i++] = j;
|
||||
break;
|
||||
}
|
||||
if(i == MAX_ANALOG)
|
||||
break;
|
||||
|
@ -846,6 +862,11 @@ controller_frame controller_state::commit(controller_frame controls) throw()
|
|||
return _committed;
|
||||
}
|
||||
|
||||
bool controller_state::is_present(unsigned pcid) throw()
|
||||
{
|
||||
return _input.is_present(pcid);
|
||||
}
|
||||
|
||||
bool controller_state::is_analog(unsigned pcid) throw()
|
||||
{
|
||||
return _input.is_analog(pcid);
|
||||
|
|
|
@ -250,16 +250,13 @@ void update_movie_state()
|
|||
c = movb.get_movie().get_controls();
|
||||
else
|
||||
c = controls.get_committed();
|
||||
for(unsigned i = 0; i < 8; i++) {
|
||||
for(unsigned i = 0; i < MAX_LOGICAL_CONTROLLERS; i++) {
|
||||
unsigned pindex = controls.lcid_to_pcid(i);
|
||||
devicetype_t dtype = controls.pcid_to_type(pindex);
|
||||
if(dtype == DT_NONE)
|
||||
if(!controls.is_present(pindex))
|
||||
continue;
|
||||
char buffer[MAX_DISPLAY_LENGTH];
|
||||
c.display(pindex, buffer);
|
||||
char y[3] = {'P', 0, 0};
|
||||
y[1] = 49 + i;
|
||||
_status.set(y, buffer);
|
||||
_status.set((stringfmt() << "P" << (i + 1)).str(), buffer);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -361,13 +361,13 @@ void do_load_state(struct moviefile& _movie, int lmode)
|
|||
if(will_load_state) {
|
||||
//Load the savestate and movie state.
|
||||
//Set the core ports in order to avoid port state being reinitialized when loading.
|
||||
controls.set_port(0, _movie.port1, true);
|
||||
controls.set_port(1, _movie.port2, true);
|
||||
controls.set_port(0, *_movie.port1, true);
|
||||
controls.set_port(1, *_movie.port2, true);
|
||||
load_core_state(_movie.savestate);
|
||||
} else {
|
||||
load_sram(_movie.movie_sram);
|
||||
controls.set_port(0, _movie.port1, true);
|
||||
controls.set_port(1, _movie.port2, true);
|
||||
controls.set_port(0, *_movie.port1, true);
|
||||
controls.set_port(1, *_movie.port2, true);
|
||||
_movie.rtc_second = _movie.movie_rtc_second;
|
||||
_movie.rtc_subsecond = _movie.movie_rtc_subsecond;
|
||||
}
|
||||
|
|
|
@ -195,7 +195,7 @@ void write_authors_file(zip_writer& w, std::vector<std::pair<std::string, std::s
|
|||
}
|
||||
}
|
||||
|
||||
void write_input(zip_writer& w, controller_frame_vector& input, porttype_t port1, porttype_t port2)
|
||||
void write_input(zip_writer& w, controller_frame_vector& input)
|
||||
throw(std::bad_alloc, std::runtime_error)
|
||||
{
|
||||
std::ostream& m = w.create_file("input");
|
||||
|
@ -214,8 +214,8 @@ void write_input(zip_writer& w, controller_frame_vector& input, porttype_t port1
|
|||
}
|
||||
}
|
||||
|
||||
void read_input(zip_reader& r, controller_frame_vector& input, porttype_t port1, porttype_t port2, unsigned version)
|
||||
throw(std::bad_alloc, std::runtime_error)
|
||||
void read_input(zip_reader& r, controller_frame_vector& input, unsigned version) throw(std::bad_alloc,
|
||||
std::runtime_error)
|
||||
{
|
||||
controller_frame tmp = input.blank_frame(false);
|
||||
std::istream& m = r["input"];
|
||||
|
@ -280,13 +280,15 @@ void write_pollcounters(zip_writer& w, const std::string& file, const std::vecto
|
|||
}
|
||||
}
|
||||
|
||||
porttype_t parse_controller_type(const std::string& type, bool port) throw(std::bad_alloc, std::runtime_error)
|
||||
porttype_info& parse_controller_type(const std::string& type, unsigned port) throw(std::bad_alloc, std::runtime_error)
|
||||
{
|
||||
try {
|
||||
const porttype_info& i = porttype_info::lookup(type);
|
||||
return i.value;
|
||||
porttype_info& i = porttype_info::lookup(type);
|
||||
if(!i.legal || !(i.legal(port)))
|
||||
throw 42;
|
||||
return i;
|
||||
} catch(...) {
|
||||
throw std::runtime_error(std::string("Illegal port") + (port ? "2" : "1") + " device '" + type + "'");
|
||||
(stringfmt() << "Illegal port " << (port + 1) << " device '" << type << "'").throwex();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -295,8 +297,8 @@ moviefile::moviefile() throw(std::bad_alloc)
|
|||
{
|
||||
force_corrupt = false;
|
||||
gametype = GT_INVALID;
|
||||
port1 = PT_INVALID;
|
||||
port2 = PT_INVALID;
|
||||
port1 = &porttype_info::default_type();
|
||||
port2 = &porttype_info::default_type();
|
||||
coreversion = "";
|
||||
projectid = "";
|
||||
rerecords = "0";
|
||||
|
@ -327,13 +329,13 @@ moviefile::moviefile(const std::string& movie) throw(std::bad_alloc, std::runtim
|
|||
} catch(std::exception& e) {
|
||||
throw std::runtime_error("Illegal game type '" + tmp + "'");
|
||||
}
|
||||
tmp = "gamepad";
|
||||
tmp = porttype_info::port_default(0).name;
|
||||
read_linefile(r, "port1", tmp, true);
|
||||
port1 = porttype_info::lookup(tmp).value;
|
||||
tmp = "none";
|
||||
port1 = &porttype_info::lookup(tmp);
|
||||
tmp = porttype_info::port_default(1).name;
|
||||
read_linefile(r, "port2", tmp, true);
|
||||
port2 = porttype_info::lookup(tmp).value;
|
||||
input.clear(port1, port2);
|
||||
port2 = &porttype_info::lookup(tmp);
|
||||
input.clear(*port1, *port2);
|
||||
read_linefile(r, "gamename", gamename, true);
|
||||
read_linefile(r, "projectid", projectid);
|
||||
rerecords = read_rrdata(r, c_rrdata);
|
||||
|
@ -380,17 +382,17 @@ moviefile::moviefile(const std::string& movie) throw(std::bad_alloc, std::runtim
|
|||
if(name.length() >= 10 && name.substr(0, 10) == "moviesram.")
|
||||
movie_sram[name.substr(10)] = read_raw_file(r, name);
|
||||
read_authors_file(r, authors);
|
||||
read_input(r, input, port1, port2, 0);
|
||||
read_input(r, input, 0);
|
||||
}
|
||||
|
||||
void moviefile::save(const std::string& movie, unsigned compression) throw(std::bad_alloc, std::runtime_error)
|
||||
{
|
||||
zip_writer w(movie, compression);
|
||||
write_linefile(w, "gametype", gtype::tostring(gametype));
|
||||
if(port1 != PT_GAMEPAD)
|
||||
write_linefile(w, "port1", porttype_info::lookup(port1).name);
|
||||
if(port2 != PT_NONE)
|
||||
write_linefile(w, "port2", porttype_info::lookup(port2).name);
|
||||
if(port1->name != porttype_info::port_default(0).name)
|
||||
write_linefile(w, "port1", port1->name);
|
||||
if(port2->name != porttype_info::port_default(1).name)
|
||||
write_linefile(w, "port2", port2->name);
|
||||
write_linefile(w, "gamename", gamename, true);
|
||||
write_linefile(w, "systemid", "lsnes-rr1");
|
||||
write_linefile(w, "controlsversion", "0");
|
||||
|
@ -422,7 +424,7 @@ void moviefile::save(const std::string& movie, unsigned compression) throw(std::
|
|||
write_numeric_file(w, "savetime.subsecond", rtc_subsecond);
|
||||
}
|
||||
write_authors_file(w, authors);
|
||||
write_input(w, input, port1, port2);
|
||||
write_input(w, input);
|
||||
|
||||
w.commit();
|
||||
}
|
||||
|
|
|
@ -331,8 +331,11 @@ void framebuffer<X>::copy_from(framebuffer_raw& scr, size_t hscale, size_t vscal
|
|||
{
|
||||
typename framebuffer<X>::element_t decbuf[DECBUF_SIZE];
|
||||
|
||||
if(!scr.fmt)
|
||||
throw std::runtime_error("Source screen has invalid pixel format");
|
||||
if(!scr.fmt) {
|
||||
for(size_t y = 0; y < height; y++)
|
||||
memset(rowptr(y), 0, sizeof(typename framebuffer<X>::element_t) * width);
|
||||
return;
|
||||
}
|
||||
if(scr.fmt != current_fmt || active_rshift != auxpal.rshift || active_gshift != auxpal.gshift ||
|
||||
active_bshift != auxpal.bshift) {
|
||||
scr.fmt->set_palette(auxpal, active_rshift, active_gshift, active_bshift);
|
||||
|
|
|
@ -64,26 +64,13 @@ namespace
|
|||
unsigned controller = get_numeric_argument<unsigned>(LS, 1, fname.c_str());
|
||||
auto& m = get_movie();
|
||||
controller_frame f = m.read_subframe(m.get_current_frame(), 0);
|
||||
porttype_t p = f.get_port_type(controller / MAX_CONTROLLERS_PER_PORT);
|
||||
const porttype_info& i = porttype_info::lookup(p);
|
||||
if(i.controllers <= controller % MAX_CONTROLLERS_PER_PORT)
|
||||
porttype_info& p = f.get_port_type(controller / MAX_CONTROLLERS_PER_PORT);
|
||||
if(p.controllers <= controller % MAX_CONTROLLERS_PER_PORT)
|
||||
lua_pushnil(LS);
|
||||
else if(p == PT_NONE)
|
||||
else if(p.ctrlname == "")
|
||||
lua_pushnil(LS);
|
||||
else if(p == PT_GAMEPAD)
|
||||
lua_pushstring(LS, "gamepad");
|
||||
else if(p == PT_MULTITAP)
|
||||
lua_pushstring(LS, "gamepad");
|
||||
else if(p == PT_MOUSE)
|
||||
lua_pushstring(LS, "mouse");
|
||||
else if(p == PT_SUPERSCOPE)
|
||||
lua_pushstring(LS, "superscope");
|
||||
else if(p == PT_JUSTIFIER)
|
||||
lua_pushstring(LS, "justifier");
|
||||
else if(p == PT_JUSTIFIERS)
|
||||
lua_pushstring(LS, "justifier");
|
||||
else
|
||||
lua_pushstring(LS, "unknown");
|
||||
lua_pushstring(LS, p.ctrlname.c_str());
|
||||
return 1;
|
||||
});
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "core/misc.hpp"
|
||||
#include "fonts/wrapper.hpp"
|
||||
#include "platform/sdl/platform.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
|
@ -183,18 +184,25 @@ namespace
|
|||
for(auto si : s) {
|
||||
uint32_t old_x = pos_x;
|
||||
uint32_t old_y = pos_y;
|
||||
auto g = find_glyph(si, pos_x, pos_y, 0, pos_x, pos_y);
|
||||
auto g = main_font.get_glyph(si);
|
||||
if(si == 9)
|
||||
pos_x = (pos_x + 63) / 64 * 64;
|
||||
else if(si == 10) {
|
||||
pos_x = 0;
|
||||
pos_y += 16;
|
||||
} else
|
||||
pos_x += (g.wide ? 16 : 8);
|
||||
uint32_t mw = maxwidth - old_x;
|
||||
if(maxwidth < old_x)
|
||||
mw = 0;
|
||||
if(mw > g.first)
|
||||
mw = g.first;
|
||||
if(mw > (g.wide ? 16 : 8))
|
||||
mw = (g.wide ? 16 : 8);
|
||||
uint8_t* cbase = base + (y + old_y) * yo + (x + old_x) * xo;
|
||||
if(g.second == NULL)
|
||||
draw_blank_glyph(cbase, pitch, pbytes, g.first, mw, color,
|
||||
if(g.data == NULL)
|
||||
draw_blank_glyph(cbase, pitch, pbytes, (g.wide ? 16 : 8), mw, color,
|
||||
(c == hilite_pos) ? hilite_mode : 0);
|
||||
else
|
||||
draw_glyph(cbase, pitch, pbytes, g.second, g.first, mw, color,
|
||||
draw_glyph(cbase, pitch, pbytes, g.data, (g.wide ? 16 : 8), mw, color,
|
||||
(c == hilite_pos) ? hilite_mode : 0);
|
||||
c++;
|
||||
}
|
||||
|
|
|
@ -25,8 +25,8 @@
|
|||
struct moviefile generate_movie_template(std::vector<std::string> cmdline, loaded_rom& r)
|
||||
{
|
||||
struct moviefile movie;
|
||||
movie.port1 = PT_GAMEPAD;
|
||||
movie.port2 = PT_NONE;
|
||||
movie.port1 = &porttype_info::port_default(0);
|
||||
movie.port2 = &porttype_info::port_default(1);
|
||||
movie.coreversion = bsnes_core_version;
|
||||
movie.projectid = get_random_hexstring(40);
|
||||
movie.gametype = gtype::togametype(r.rtype, r.region);
|
||||
|
@ -42,9 +42,9 @@ struct moviefile generate_movie_template(std::vector<std::string> cmdline, loade
|
|||
if(o.length() >= 9 && o.substr(0, 9) == "--prefix=")
|
||||
movie.prefix = sanitize_prefix(o.substr(9));
|
||||
if(o.length() >= 8 && o.substr(0, 8) == "--port1=")
|
||||
movie.port1 = porttype_info::lookup(o.substr(8)).value;
|
||||
movie.port1 = &porttype_info::lookup(o.substr(8));
|
||||
if(o.length() >= 8 && o.substr(0, 8) == "--port2=")
|
||||
movie.port2 = porttype_info::lookup(o.substr(8)).value;
|
||||
movie.port2 = &porttype_info::lookup(o.substr(8));
|
||||
if(o.length() >= 11 && o.substr(0, 11) == "--gamename=")
|
||||
movie.gamename = o.substr(11);
|
||||
if(o.length() >= 9 && o.substr(0, 9) == "--author=") {
|
||||
|
@ -61,7 +61,7 @@ struct moviefile generate_movie_template(std::vector<std::string> cmdline, loade
|
|||
throw std::runtime_error("Bad RTC subsecond value (range is 0-3462619485019)");
|
||||
}
|
||||
}
|
||||
movie.input.clear(movie.port1, movie.port2);
|
||||
movie.input.clear(*movie.port1, *movie.port2);
|
||||
|
||||
return movie;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "core/framebuffer.hpp"
|
||||
#include "fonts/wrapper.hpp"
|
||||
#include "platform/sdl/platform.hpp"
|
||||
|
||||
void statusarea_model::paint(SDL_Surface* surf, uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t color,
|
||||
|
@ -112,9 +113,17 @@ void paint_modal_dialog(SDL_Surface* surf, const std::string& text, bool confirm
|
|||
int32_t y = 0;
|
||||
auto s2 = decode_utf8(rtext);
|
||||
for(auto i : s2) {
|
||||
auto g = find_glyph(i, x, y, 0, x, y);
|
||||
if(x + g.first > text_w)
|
||||
text_w = static_cast<uint32_t>(x + g.first);
|
||||
auto g = main_font.get_glyph(i);
|
||||
if(i == 9)
|
||||
x = (x + 63) / 64 * 64;
|
||||
else if(i == 10) {
|
||||
x = 0;
|
||||
y += 16;
|
||||
} else {
|
||||
x += (g.wide ? 16 : 8);
|
||||
}
|
||||
if(x + (g.wide ? 16 : 8) > text_w)
|
||||
text_w = static_cast<uint32_t>(x + (g.wide ? 16 : 8));
|
||||
if(y + 16 > static_cast<int32_t>(text_h))
|
||||
text_h = static_cast<uint32_t>(y + 16);
|
||||
}
|
||||
|
@ -311,8 +320,8 @@ namespace
|
|||
void screen_model::repaint_full() throw()
|
||||
{
|
||||
render_framebuffer();
|
||||
uint32_t current_w = main_screen.width;
|
||||
uint32_t current_h = main_screen.height;
|
||||
uint32_t current_w = main_screen.get_width();
|
||||
uint32_t current_h = main_screen.get_height();
|
||||
if(!surf || old_screen_w != current_w || old_screen_h != current_h) {
|
||||
layout.real_width = current_w;
|
||||
layout.real_height = current_h;
|
||||
|
@ -363,8 +372,8 @@ void screen_model::repaint_modal() throw()
|
|||
void screen_model::_repaint_screen() throw()
|
||||
{
|
||||
render_framebuffer();
|
||||
uint32_t current_w = main_screen.width;
|
||||
uint32_t current_h = main_screen.height;
|
||||
uint32_t current_w = main_screen.get_width();
|
||||
uint32_t current_h = main_screen.get_height();
|
||||
//Optimize for case where the screen is not resized.
|
||||
{
|
||||
SDL_LockSurface(surf);
|
||||
|
|
|
@ -354,8 +354,8 @@ bool lsnes_app::OnInit()
|
|||
messages << "BSNES version: " << bsnes_core_version << std::endl;
|
||||
messages << "lsnes version: lsnes rr" << lsnes_version << std::endl;
|
||||
|
||||
controls.set_port(0, PT_NONE, false);
|
||||
controls.set_port(1, PT_NONE, false);
|
||||
controls.set_port(0, porttype_info::port_default(0), false);
|
||||
controls.set_port(1, porttype_info::port_default(1), false);
|
||||
|
||||
std::string cfgpath = get_config_path();
|
||||
messages << "Saving per-user data to: " << get_config_path() << std::endl;
|
||||
|
|
|
@ -219,7 +219,7 @@ namespace
|
|||
class controller_autohold_menu : public wxMenu
|
||||
{
|
||||
public:
|
||||
controller_autohold_menu(unsigned lid, enum devicetype_t dtype);
|
||||
controller_autohold_menu(unsigned lid);
|
||||
void change_type();
|
||||
bool is_dummy();
|
||||
void on_select(wxCommandEvent& e);
|
||||
|
@ -272,7 +272,7 @@ namespace
|
|||
autohold_menu* ahmenu;
|
||||
};
|
||||
|
||||
controller_autohold_menu::controller_autohold_menu(unsigned lid, enum devicetype_t dtype)
|
||||
controller_autohold_menu::controller_autohold_menu(unsigned lid)
|
||||
{
|
||||
modal_pause_holder hld;
|
||||
our_lid = lid;
|
||||
|
@ -347,7 +347,7 @@ namespace
|
|||
for(unsigned i = 0; i < MAX_LOGICAL_CONTROLLERS; i++) {
|
||||
std::ostringstream str;
|
||||
str << "Controller #&" << (i + 1);
|
||||
menus[i] = new controller_autohold_menu(i, DT_NONE);
|
||||
menus[i] = new controller_autohold_menu(i);
|
||||
entries[i] = AppendSubMenu(menus[i], towxstring(str.str()));
|
||||
entries[i]->Enable(!menus[i]->is_dummy());
|
||||
}
|
||||
|
|
|
@ -54,23 +54,27 @@ void patching_done(struct loaded_rom& rom, wxWindow* modwin);
|
|||
|
||||
namespace
|
||||
{
|
||||
porttype_t get_controller_type(const std::string& s)
|
||||
porttype_info& get_controller_type(const std::string& s)
|
||||
{
|
||||
if(s == CNAME_NONE)
|
||||
return PT_NONE;
|
||||
if(s == CNAME_GAMEPAD)
|
||||
return PT_GAMEPAD;
|
||||
if(s == CNAME_MULTITAP)
|
||||
return PT_MULTITAP;
|
||||
if(s == CNAME_MOUSE)
|
||||
return PT_MOUSE;
|
||||
if(s == CNAME_SUPERSCOPE)
|
||||
return PT_SUPERSCOPE;
|
||||
if(s == CNAME_JUSTIFIER)
|
||||
return PT_JUSTIFIER;
|
||||
if(s == CNAME_JUSTIFIERS)
|
||||
return PT_JUSTIFIERS;
|
||||
return PT_INVALID;
|
||||
auto types = porttype_info::get_all();
|
||||
for(auto i : types)
|
||||
if(s == i->hname)
|
||||
return *i;
|
||||
return porttype_info::default_type();
|
||||
}
|
||||
|
||||
void load_cchoices(std::vector<wxString>& cc, unsigned port, unsigned& dfltidx)
|
||||
{
|
||||
cc.clear();
|
||||
porttype_info& dflt = porttype_info::port_default(port);
|
||||
dfltidx = 0;
|
||||
auto types = porttype_info::get_all();
|
||||
for(auto i : types)
|
||||
if(i->legal && i->legal(port)) {
|
||||
cc.push_back(towxstring(i->hname));
|
||||
if(i == &dflt)
|
||||
dfltidx = cc.size() - 1;
|
||||
}
|
||||
}
|
||||
|
||||
struct loaded_slot& get_rom_slot(struct loaded_rom& rom, unsigned index)
|
||||
|
@ -806,14 +810,8 @@ wxwin_project::wxwin_project(loaded_rom& rom)
|
|||
wxMINIMIZE_BOX | wxSYSTEM_MENU | wxCAPTION | wxCLIP_CHILDREN | wxCLOSE_BOX)
|
||||
{
|
||||
our_rom = &rom;
|
||||
wxString cchoices[CONTROLLERTYPES];
|
||||
cchoices[0] = wxT(CNAME_NONE);
|
||||
cchoices[1] = wxT(CNAME_GAMEPAD);
|
||||
cchoices[2] = wxT(CNAME_MULTITAP);
|
||||
cchoices[3] = wxT(CNAME_MOUSE);
|
||||
cchoices[4] = wxT(CNAME_SUPERSCOPE);
|
||||
cchoices[5] = wxT(CNAME_JUSTIFIER);
|
||||
cchoices[6] = wxT(CNAME_JUSTIFIERS);
|
||||
std::vector<wxString> cchoices;
|
||||
unsigned dfltidx;
|
||||
|
||||
std::set<std::string> sram_set = get_sram_set();
|
||||
|
||||
|
@ -855,11 +853,13 @@ wxwin_project::wxwin_project(loaded_rom& rom)
|
|||
//Controllertypes/Gamename/initRTC/SRAMs.
|
||||
wxFlexGridSizer* mainblock = new wxFlexGridSizer(5 + sram_set.size(), 2, 0, 0);
|
||||
mainblock->Add(new wxStaticText(new_panel, wxID_ANY, wxT("Controller 1 Type:")), 0, wxGROW);
|
||||
mainblock->Add(controller1type = new wxComboBox(new_panel, wxID_ANY, cchoices[1], wxDefaultPosition,
|
||||
wxDefaultSize, CONTROLLERTYPES, cchoices, wxCB_READONLY), 0, wxGROW);
|
||||
load_cchoices(cchoices, 0, dfltidx);
|
||||
mainblock->Add(controller1type = new wxComboBox(new_panel, wxID_ANY, cchoices[dfltidx], wxDefaultPosition,
|
||||
wxDefaultSize, cchoices.size(), &cchoices[0], wxCB_READONLY), 0, wxGROW);
|
||||
load_cchoices(cchoices, 1, dfltidx);
|
||||
mainblock->Add(new wxStaticText(new_panel, wxID_ANY, wxT("Controller 2 Type:")), 0, wxGROW);
|
||||
mainblock->Add(controller2type = new wxComboBox(new_panel, wxID_ANY, cchoices[0], wxDefaultPosition,
|
||||
wxDefaultSize, CONTROLLERTYPES, cchoices, wxCB_READONLY), 0, wxGROW);
|
||||
mainblock->Add(controller2type = new wxComboBox(new_panel, wxID_ANY, cchoices[dfltidx], wxDefaultPosition,
|
||||
wxDefaultSize, cchoices.size(), &cchoices[0], wxCB_READONLY), 0, wxGROW);
|
||||
mainblock->Add(new wxStaticText(new_panel, wxID_ANY, wxT("Initial RTC value:")), 0, wxGROW);
|
||||
wxFlexGridSizer* initrtc = new wxFlexGridSizer(1, 3, 0, 0);
|
||||
initrtc->Add(rtc_sec = new wxTextCtrl(new_panel, wxID_ANY, wxT("1000000000"), wxDefaultPosition,
|
||||
|
@ -1029,8 +1029,8 @@ struct moviefile wxwin_project::make_movie()
|
|||
moviefile f;
|
||||
f.force_corrupt = false;
|
||||
f.gametype = gtype::togametype(our_rom->rtype, our_rom->region);
|
||||
f.port1 = get_controller_type(tostdstring(controller1type->GetValue()));
|
||||
f.port2 = get_controller_type(tostdstring(controller2type->GetValue()));
|
||||
f.port1 = &get_controller_type(tostdstring(controller1type->GetValue()));
|
||||
f.port2 = &get_controller_type(tostdstring(controller2type->GetValue()));
|
||||
f.coreversion = bsnes_core_version;
|
||||
f.gamename = tostdstring(projectname->GetValue());
|
||||
f.prefix = sanitize_prefix(tostdstring(prefix->GetValue()));
|
||||
|
@ -1058,7 +1058,7 @@ struct moviefile wxwin_project::make_movie()
|
|||
f.movie_rtc_subsecond = f.rtc_subsecond = boost::lexical_cast<int64_t>(tostdstring(rtc_subsec->GetValue()));
|
||||
if(f.movie_rtc_subsecond < 0)
|
||||
throw std::runtime_error("RTC subsecond must be positive");
|
||||
f.input.clear(f.port1, f.port2);
|
||||
f.input.clear(*f.port1, *f.port2);
|
||||
return f;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,18 +23,6 @@ std::string name_region(rom_region r)
|
|||
return "Unknown";
|
||||
}
|
||||
|
||||
std::string name_porttype(porttype_t r)
|
||||
{
|
||||
if(r == PT_NONE) return "No device";
|
||||
if(r == PT_GAMEPAD) return "Gamepad";
|
||||
if(r == PT_MULTITAP) return "Multitap";
|
||||
if(r == PT_MOUSE) return "Mouse";
|
||||
if(r == PT_SUPERSCOPE) return "Super Scope";
|
||||
if(r == PT_JUSTIFIER) return "Justifier";
|
||||
if(r == PT_JUSTIFIERS) return "2 Justifiers";
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
std::string escape_string(std::string x)
|
||||
{
|
||||
std::ostringstream out;
|
||||
|
@ -64,8 +52,8 @@ int main(int argc, char** argv)
|
|||
rom_region reg = gtype::toromregion(m.gametype);
|
||||
std::cout << "Console: " << name_romtype(rtype) << std::endl;
|
||||
std::cout << "Region: " << name_region(reg) << std::endl;
|
||||
std::cout << "Port #1: " << name_porttype(m.port1) << std::endl;
|
||||
std::cout << "Port #2: " << name_porttype(m.port2) << std::endl;
|
||||
std::cout << "Port #1: " << m.port1->hname << std::endl;
|
||||
std::cout << "Port #2: " << m.port2->hname << std::endl;
|
||||
std::cout << "Used emulator core: " << escape_string(m.coreversion) << std::endl;
|
||||
if(m.gamename != "")
|
||||
std::cout << "Game name: " << escape_string(m.gamename) << std::endl;
|
||||
|
|
Loading…
Add table
Reference in a new issue