1 #include "interface/c-interface.hpp"
2 #include "interface/callbacks.hpp"
3 #include "interface/romtype.hpp"
4 #include "interface/setting.hpp"
5 #include "interface/disassembler.hpp"
6 #include "library/string.hpp"
7 #include "library/portctrl-parse.hpp"
8 #include "library/framebuffer.hpp"
9 #include "library/framebuffer-pixfmt-rgb15.hpp"
10 #include "library/framebuffer-pixfmt-rgb16.hpp"
11 #include "library/framebuffer-pixfmt-rgb24.hpp"
12 #include "library/framebuffer-pixfmt-rgb32.hpp"
13 #include "library/framebuffer-pixfmt-lrgb.hpp"
14 #include "fonts/wrapper.hpp"
15 #include "core/audioapi.hpp"
16 #include "core/instance.hpp"
17 #include "core/messages.hpp"
19 template<> int ccore_call_param_map
<lsnes_core_enumerate_cores
>::id
= LSNES_CORE_ENUMERATE_CORES
;
20 template<> int ccore_call_param_map
<lsnes_core_get_core_info
>::id
= LSNES_CORE_GET_CORE_INFO
;
21 template<> int ccore_call_param_map
<lsnes_core_get_type_info
>::id
= LSNES_CORE_GET_TYPE_INFO
;
22 template<> int ccore_call_param_map
<lsnes_core_get_region_info
>::id
= LSNES_CORE_GET_REGION_INFO
;
23 template<> int ccore_call_param_map
<lsnes_core_get_sysregion_info
>::id
= LSNES_CORE_GET_SYSREGION_INFO
;
24 template<> int ccore_call_param_map
<lsnes_core_get_av_state
>::id
= LSNES_CORE_GET_AV_STATE
;
25 template<> int ccore_call_param_map
<lsnes_core_emulate
>::id
= LSNES_CORE_EMULATE
;
26 template<> int ccore_call_param_map
<lsnes_core_savestate
>::id
= LSNES_CORE_SAVESTATE
;
27 template<> int ccore_call_param_map
<lsnes_core_loadstate
>::id
= LSNES_CORE_LOADSTATE
;
28 template<> int ccore_call_param_map
<lsnes_core_get_controllerconfig
>::id
= LSNES_CORE_GET_CONTROLLERCONFIG
;
29 template<> int ccore_call_param_map
<lsnes_core_load_rom
>::id
= LSNES_CORE_LOAD_ROM
;
30 template<> int ccore_call_param_map
<lsnes_core_get_region
>::id
= LSNES_CORE_GET_REGION
;
31 template<> int ccore_call_param_map
<lsnes_core_set_region
>::id
= LSNES_CORE_SET_REGION
;
32 template<> int ccore_call_param_map
<lsnes_core_deinitialize
>::id
= LSNES_CORE_DEINITIALIZE
;
33 template<> int ccore_call_param_map
<lsnes_core_get_pflag
>::id
= LSNES_CORE_GET_PFLAG
;
34 template<> int ccore_call_param_map
<lsnes_core_set_pflag
>::id
= LSNES_CORE_SET_PFLAG
;
35 template<> int ccore_call_param_map
<lsnes_core_get_action_flags
>::id
= LSNES_CORE_GET_ACTION_FLAGS
;
36 template<> int ccore_call_param_map
<lsnes_core_execute_action
>::id
= LSNES_CORE_EXECUTE_ACTION
;
37 template<> int ccore_call_param_map
<lsnes_core_get_bus_mapping
>::id
= LSNES_CORE_GET_BUS_MAPPING
;
38 template<> int ccore_call_param_map
<lsnes_core_enumerate_sram
>::id
= LSNES_CORE_ENUMERATE_SRAM
;
39 template<> int ccore_call_param_map
<lsnes_core_save_sram
>::id
= LSNES_CORE_SAVE_SRAM
;
40 template<> int ccore_call_param_map
<lsnes_core_load_sram
>::id
= LSNES_CORE_LOAD_SRAM
;
41 template<> int ccore_call_param_map
<lsnes_core_get_reset_action
>::id
= LSNES_CORE_GET_RESET_ACTION
;
42 template<> int ccore_call_param_map
<lsnes_core_compute_scale
>::id
= LSNES_CORE_COMPUTE_SCALE
;
43 template<> int ccore_call_param_map
<lsnes_core_runtosave
>::id
= LSNES_CORE_RUNTOSAVE
;
44 template<> int ccore_call_param_map
<lsnes_core_poweron
>::id
= LSNES_CORE_POWERON
;
45 template<> int ccore_call_param_map
<lsnes_core_unload_cartridge
>::id
= LSNES_CORE_UNLOAD_CARTRIDGE
;
46 template<> int ccore_call_param_map
<lsnes_core_debug_reset
>::id
= LSNES_CORE_DEBUG_RESET
;
47 template<> int ccore_call_param_map
<lsnes_core_set_debug_flags
>::id
= LSNES_CORE_SET_DEBUG_FLAGS
;
48 template<> int ccore_call_param_map
<lsnes_core_set_cheat
>::id
= LSNES_CORE_SET_CHEAT
;
49 template<> int ccore_call_param_map
<lsnes_core_draw_cover
>::id
= LSNES_CORE_DRAW_COVER
;
50 template<> int ccore_call_param_map
<lsnes_core_pre_emulate
>::id
= LSNES_CORE_PRE_EMULATE
;
51 template<> int ccore_call_param_map
<lsnes_core_get_device_regs
>::id
= LSNES_CORE_GET_DEVICE_REGS
;
52 template<> int ccore_call_param_map
<lsnes_core_get_vma_list
>::id
= LSNES_CORE_GET_VMA_LIST
;
54 template<> const char* ccore_call_param_map
<lsnes_core_enumerate_cores
>::name
= "LSNES_CORE_ENUMERATE_CORES";
55 template<> const char* ccore_call_param_map
<lsnes_core_get_core_info
>::name
= "LSNES_CORE_GET_CORE_INFO";
56 template<> const char* ccore_call_param_map
<lsnes_core_get_type_info
>::name
= "LSNES_CORE_GET_TYPE_INFO";
57 template<> const char* ccore_call_param_map
<lsnes_core_get_region_info
>::name
= "LSNES_CORE_GET_REGION_INFO";
58 template<> const char* ccore_call_param_map
<lsnes_core_get_sysregion_info
>::name
= "LSNES_CORE_GET_SYSREGION_INFO";
59 template<> const char* ccore_call_param_map
<lsnes_core_get_av_state
>::name
= "LSNES_CORE_GET_AV_STATE";
60 template<> const char* ccore_call_param_map
<lsnes_core_emulate
>::name
= "LSNES_CORE_EMULATE";
61 template<> const char* ccore_call_param_map
<lsnes_core_savestate
>::name
= "LSNES_CORE_SAVESTATE";
62 template<> const char* ccore_call_param_map
<lsnes_core_loadstate
>::name
= "LSNES_CORE_LOADSTATE";
63 template<> const char* ccore_call_param_map
<lsnes_core_get_controllerconfig
>::name
=
64 "LSNES_CORE_GET_CONTROLLERCONFIG";
65 template<> const char* ccore_call_param_map
<lsnes_core_load_rom
>::name
= "LSNES_CORE_LOAD_ROM";
66 template<> const char* ccore_call_param_map
<lsnes_core_get_region
>::name
= "LSNES_CORE_GET_REGION";
67 template<> const char* ccore_call_param_map
<lsnes_core_set_region
>::name
= "LSNES_CORE_SET_REGION";
68 template<> const char* ccore_call_param_map
<lsnes_core_deinitialize
>::name
= "LSNES_CORE_DEINITIALIZE";
69 template<> const char* ccore_call_param_map
<lsnes_core_get_pflag
>::name
= "LSNES_CORE_GET_PFLAG";
70 template<> const char* ccore_call_param_map
<lsnes_core_set_pflag
>::name
= "LSNES_CORE_SET_PFLAG";
71 template<> const char* ccore_call_param_map
<lsnes_core_get_action_flags
>::name
= "LSNES_CORE_GET_ACTION_FLAGS";
72 template<> const char* ccore_call_param_map
<lsnes_core_execute_action
>::name
= "LSNES_CORE_EXECUTE_ACTION";
73 template<> const char* ccore_call_param_map
<lsnes_core_get_bus_mapping
>::name
= "LSNES_CORE_GET_BUS_MAPPING";
74 template<> const char* ccore_call_param_map
<lsnes_core_enumerate_sram
>::name
= "LSNES_CORE_ENUMERATE_SRAM";
75 template<> const char* ccore_call_param_map
<lsnes_core_save_sram
>::name
= "LSNES_CORE_SAVE_SRAM";
76 template<> const char* ccore_call_param_map
<lsnes_core_load_sram
>::name
= "LSNES_CORE_LOAD_SRAM";
77 template<> const char* ccore_call_param_map
<lsnes_core_get_reset_action
>::name
= "LSNES_CORE_GET_RESET_ACTION";
78 template<> const char* ccore_call_param_map
<lsnes_core_compute_scale
>::name
= "LSNES_CORE_COMPUTE_SCALE";
79 template<> const char* ccore_call_param_map
<lsnes_core_runtosave
>::name
= "LSNES_CORE_RUNTOSAVE";
80 template<> const char* ccore_call_param_map
<lsnes_core_poweron
>::name
= "LSNES_CORE_POWERON";
81 template<> const char* ccore_call_param_map
<lsnes_core_unload_cartridge
>::name
= "LSNES_CORE_UNLOAD_CARTRIDGE";
82 template<> const char* ccore_call_param_map
<lsnes_core_debug_reset
>::name
= "LSNES_CORE_DEBUG_RESET";
83 template<> const char* ccore_call_param_map
<lsnes_core_set_debug_flags
>::name
= "LSNES_CORE_SET_DEBUG_FLAGS";
84 template<> const char* ccore_call_param_map
<lsnes_core_set_cheat
>::name
= "LSNES_CORE_SET_CHEAT";
85 template<> const char* ccore_call_param_map
<lsnes_core_draw_cover
>::name
= "LSNES_CORE_DRAW_COVER";
86 template<> const char* ccore_call_param_map
<lsnes_core_pre_emulate
>::name
= "LSNES_CORE_PRE_EMULATE";
87 template<> const char* ccore_call_param_map
<lsnes_core_get_device_regs
>::name
= "LSNES_CORE_GET_DEVICE_REGS";
88 template<> const char* ccore_call_param_map
<lsnes_core_get_vma_list
>::name
= "LSNES_CORE_GET_VMA_LIST";
93 c_core_core
* current_core
= NULL
;
95 char* strduplicate(const char* x
)
98 char* out
= (char*)malloc(strlen(x
) + 1);
100 throw std::bad_alloc();
105 std::list
<lsnes_core_func_t
>& corequeue()
107 static std::list
<lsnes_core_func_t
> x
;
111 void default_error_function(const char* callname
, const char* err
)
113 messages
<< "Warning: " << callname
<< " failed: " << err
<< std::endl
;
116 framebuffer::info
translate_info(lsnes_core_framebuffer_info
* _fb
)
118 framebuffer::info fbinfo
;
120 case LSNES_CORE_PIXFMT_RGB15
: fbinfo
.type
= &framebuffer::pixfmt_rgb15
; break;
121 case LSNES_CORE_PIXFMT_BGR15
: fbinfo
.type
= &framebuffer::pixfmt_bgr15
; break;
122 case LSNES_CORE_PIXFMT_RGB16
: fbinfo
.type
= &framebuffer::pixfmt_rgb16
; break;
123 case LSNES_CORE_PIXFMT_BGR16
: fbinfo
.type
= &framebuffer::pixfmt_bgr16
; break;
124 case LSNES_CORE_PIXFMT_RGB24
: fbinfo
.type
= &framebuffer::pixfmt_rgb24
; break;
125 case LSNES_CORE_PIXFMT_BGR24
: fbinfo
.type
= &framebuffer::pixfmt_bgr24
; break;
126 case LSNES_CORE_PIXFMT_RGB32
: fbinfo
.type
= &framebuffer::pixfmt_rgb32
; break;
127 case LSNES_CORE_PIXFMT_LRGB
: fbinfo
.type
= &framebuffer::pixfmt_lrgb
; break;
129 fbinfo
.mem
= (char*)_fb
->mem
;
130 fbinfo
.physwidth
= _fb
->physwidth
;
131 fbinfo
.physheight
= _fb
->physheight
;
132 fbinfo
.physstride
= _fb
->physstride
;
133 fbinfo
.width
= _fb
->width
;
134 fbinfo
.height
= _fb
->height
;
135 fbinfo
.stride
= _fb
->stride
;
136 fbinfo
.offset_x
= _fb
->offset_x
;
137 fbinfo
.offset_y
= _fb
->offset_y
;
143 entrypoint_fn(lsnes_core_func_t _fn
) : fn(_fn
) {}
144 template<typename T
> bool operator()(unsigned item
, T
& args
,
145 std::function
<void(const char* callname
, const char* err
)> onerror
)
147 const char* err
= NULL
;
148 int r
= fn(ccore_call_param_map
<T
>::id
, item
, &args
, &err
);
150 onerror(ccore_call_param_map
<T
>::name
, err
);
153 template<typename T
> bool operator()(unsigned item
, T
& args
)
155 return (*this)(item
, args
, default_error_function
);
158 lsnes_core_func_t fn
;
164 c_lib_init(entrypoint_fn _entrypoint
)
165 : entrypoint(_entrypoint
)
177 lsnes_core_deinitialize s
;
181 entrypoint_fn
get_entrypoint()
187 entrypoint_fn entrypoint
;
190 struct c_core_core_params
192 std::vector
<interface_action
> actions
;
193 std::vector
<std::string
> trace_cpus
;
194 std::vector
<portctrl::type
*> ports
;
195 const char* shortname
;
196 const char* fullname
;
199 std::map
<unsigned, core_region
*> regions
;
203 struct c_core_core
: public core_core
205 c_core_core(c_core_core_params
& p
)
206 : core_core(p
.ports
, p
.actions
), entrypoint(p
.library
->get_entrypoint()), plugin(p
.library
)
208 fullname
= p
.fullname
;
209 shortname
= p
.shortname
;
211 internal_pflag
= false;
215 trace_cpus
= p
.trace_cpus
;
216 for(size_t i
= 0; i
< p
.ports
.size(); i
++)
217 ports
[i
] = p
.ports
[i
];
219 ~c_core_core() throw();
220 std::string
c_core_identifier() const
224 bool get_av_state(lsnes_core_get_av_state
& s
)
226 return entrypoint(id
, s
);
228 std::pair
<uint32_t, uint32_t> c_video_rate()
230 lsnes_core_get_av_state s
;
231 if(!entrypoint(id
, s
))
232 return std::make_pair(60, 1);
233 return std::make_pair(s
.fps_n
, s
.fps_d
);
237 lsnes_core_get_av_state s
;
238 return entrypoint(id
, s
) ? s
.par
: 1.0;
240 std::pair
<uint32_t, uint32_t> c_audio_rate()
242 lsnes_core_get_av_state s
;
243 return entrypoint(id
, s
) ? std::make_pair(s
.rate_n
, s
.rate_d
) : std::make_pair(48000U, 1U);
247 lsnes_core_poweron s
;
248 if(caps1
& LSNES_CORE_CAP1_POWERON
) entrypoint(id
, s
);
250 void c_unload_cartridge()
252 lsnes_core_unload_cartridge s
;
253 if(caps1
& LSNES_CORE_CAP1_UNLOAD
) entrypoint(id
, s
);
257 lsnes_core_runtosave s
;
258 if(caps1
& LSNES_CORE_CAP1_RUNTOSAVE
) entrypoint(id
, s
);
263 lsnes_core_emulate s
;
269 lsnes_core_get_pflag s
;
270 if(!(caps1
& LSNES_CORE_CAP1_PFLAG
) || !entrypoint(id
, s
))
271 return internal_pflag
;
272 return (s
.pflag
!= 0);
274 void c_set_pflag(bool pflag
)
276 lsnes_core_set_pflag s
;
277 s
.pflag
= pflag
? 1 : 0;
278 if(!(caps1
& LSNES_CORE_CAP1_PFLAG
) || !entrypoint(id
, s
))
279 internal_pflag
= pflag
;
281 std::string
c_get_core_shortname() const
287 lsnes_core_debug_reset s
;
288 if(caps1
& (LSNES_CORE_CAP1_DEBUG
| LSNES_CORE_CAP1_TRACE
| LSNES_CORE_CAP1_CHEAT
))
291 std::pair
<unsigned, unsigned> c_lightgun_scale()
293 lsnes_core_get_av_state s
;
294 if(!(caps1
& LSNES_CORE_CAP1_LIGHTGUN
) || !entrypoint(id
, s
))
295 return std::make_pair(0, 0);
296 return std::make_pair(s
.lightgun_width
, s
.lightgun_height
);
298 std::pair
<uint64_t, uint64_t> c_get_bus_map()
300 lsnes_core_get_bus_mapping s
;
301 if(!(caps1
& LSNES_CORE_CAP1_BUSMAP
) || !entrypoint(id
, s
))
302 return std::make_pair(0, 0);
303 return std::make_pair(s
.base
, s
.size
);
305 int c_reset_action(bool hard
)
307 lsnes_core_get_reset_action s
;
308 if(!(caps1
& LSNES_CORE_CAP1_RESET
) || !entrypoint(id
, s
))
310 return hard
? s
.hardreset
: s
.softreset
;
312 std::pair
<uint32_t, uint32_t> c_get_scale_factors(uint32_t width
, uint32_t height
)
314 lsnes_core_compute_scale s
;
315 uint32_t hscale
, vscale
;
316 if(width
>= 360) hscale
= 1;
317 else hscale
= 360 / width
+ 1;
318 if(height
>= 320) vscale
= 1;
319 else vscale
= 320 / height
+ 1;
320 if(caps1
& LSNES_CORE_CAP1_SCALE
) {
323 if(entrypoint(id
, s
)) {
328 return std::make_pair(hscale
, vscale
);
330 void c_pre_emulate_frame(portctrl::frame
& cf
)
332 lsnes_core_pre_emulate s
;
333 if(caps1
& LSNES_CORE_CAP1_PREEMULATE
) {
335 s
.set_input
= [](void* context
, unsigned port
, unsigned controller
, unsigned index
,
336 short value
) -> void {
337 portctrl::frame
& cf
= *(portctrl::frame
*)context
;
338 cf
.axis3(port
, controller
, index
, value
);
343 std::set
<std::string
> c_srams()
345 lsnes_core_enumerate_sram s
;
346 std::set
<std::string
> ret
;
347 if(caps1
& LSNES_CORE_CAP1_SRAM
) {
348 if(entrypoint(id
, s
)) {
349 const char** sr
= s
.srams
;
358 void c_load_sram(std::map
<std::string
, std::vector
<char>>& sram
) throw(std::bad_alloc
)
360 lsnes_core_load_sram s
;
361 if(caps1
& LSNES_CORE_CAP1_SRAM
) {
362 std::vector
<lsnes_core_sram
> srams
;
363 std::vector
<lsnes_core_sram
*> sramsp
;
364 std::vector
<char> names
;
365 srams
.resize(sram
.size() + 1);
366 srams
[sram
.size()].name
= NULL
;
370 nlength
+= i
.first
.length() + 1;
371 names
.resize(nlength
);
373 for(auto& i
: sram
) {
375 std::copy(i
.first
.begin(), i
.first
.end(), names
.begin() + nidx
);
376 nidx
+= i
.first
.length();
377 names
[nidx
++] = '\0';
378 srams
[idx
].size
= i
.second
.size();
379 srams
[idx
].data
= &i
.second
[0];
380 srams
[idx
].name
= &names
[ntmp
];
387 std::map
<std::string
, std::vector
<char>> c_save_sram() throw(std::bad_alloc
)
389 lsnes_core_save_sram s
;
390 std::map
<std::string
, std::vector
<char>> ret
;
391 if(caps1
& LSNES_CORE_CAP1_SRAM
) {
392 if(entrypoint(id
, s
)) {
393 lsnes_core_sram
* p
= s
.srams
;
395 ret
[p
->name
].resize(p
->size
);
396 memcpy(&ret
[p
->name
][0], p
->data
, p
->size
);
403 void c_unserialize(const char* in
, size_t insize
)
405 lsnes_core_loadstate s
;
408 entrypoint(id
, s
, [](const char* name
, const char* err
) {
409 throw std::runtime_error("Loadstate failed: " + std::string(err
));
412 void c_serialize(std::vector
<char>& out
)
414 lsnes_core_savestate s
;
415 entrypoint(id
, s
, [](const char* name
, const char* err
) {
416 throw std::runtime_error("Savestate failed: " + std::string(err
));
419 memcpy(&out
[0], s
.data
, s
.size
);
421 unsigned c_action_flags(unsigned _id
)
423 lsnes_core_get_action_flags s
;
424 if(caps1
& LSNES_CORE_CAP1_ACTION
) {
426 return entrypoint(id
, s
) ? s
.flags
: 0;
430 std::vector
<std::string
> c_get_trace_cpus()
434 bool c_set_region(core_region
& region
)
436 lsnes_core_set_region s
;
437 if(caps1
& LSNES_CORE_CAP1_MULTIREGION
) {
439 for(auto i
: regions
)
440 if(i
.second
== ®ion
) {
445 return false; //Bad region.
446 return entrypoint(id
, s
);
448 return (regions
.count(0) && regions
[0] == ®ion
);
451 core_region
& c_get_region()
453 lsnes_core_get_region s
;
454 if(caps1
& LSNES_CORE_CAP1_MULTIREGION
) {
455 if(!entrypoint(id
, s
)) {
457 throw std::runtime_error("No valid regions");
458 return *(regions
.begin()->second
);
460 if(regions
.count(s
.region
))
461 return *regions
[s
.region
];
462 messages
<< "Internal error: Core gave invalid region number."
465 throw std::runtime_error("No valid regions");
466 return *(regions
.begin()->second
);
472 messages
<< "Internal error: Not multi-region core and region 0 not present."
475 throw std::runtime_error("No valid regions");
476 return *(regions
.begin()->second
);
480 const struct interface_device_reg
* c_get_registers()
482 static std::vector
<interface_device_reg
> regs
;
483 static std::vector
<char> namebuf
;
484 static interface_device_reg reg_null
= {NULL
};
485 lsnes_core_get_device_regs s
;
486 if(caps1
& LSNES_CORE_CAP1_REGISTERS
) {
487 if(!entrypoint(id
, s
)) {
494 namelen
+= strlen(tregs
->name
) + 1;
499 if(regs
.size() < count
+ 1)
500 regs
.resize(count
+ 1);
501 if(namelen
> namebuf
.size())
502 namebuf
.resize(namelen
);
506 strcpy(&namebuf
[nameptr
], tregs
->name
);
507 regs
[idx
].name
= &namebuf
[nameptr
];
508 regs
[idx
].read
= tregs
->read
;
509 regs
[idx
].write
= tregs
->write
;
510 regs
[idx
].boolean
= tregs
->boolean
;
511 nameptr
+= strlen(tregs
->name
) + 1;
515 regs
[idx
].name
= NULL
; //The sentinel.
522 void c_install_handler()
524 plugin
->initialize();
526 void c_uninstall_handler()
528 plugin
->deinitialize();
530 void c_set_debug_flags(uint64_t addr
, unsigned flags_set
, unsigned flags_clear
)
532 lsnes_core_set_debug_flags s
;
535 s
.clear
= flags_clear
;
536 if(caps1
& LSNES_CORE_CAP1_DEBUG
)
539 messages
<< "Debugging functions not supported by core" << std::endl
;
541 void c_set_cheat(uint64_t addr
, uint64_t value
, bool set
)
543 lsnes_core_set_cheat s
;
547 if(caps1
& LSNES_CORE_CAP1_CHEAT
)
550 messages
<< "Cheat functions not supported by core" << std::endl
;
552 void c_execute_action(unsigned aid
, const std::vector
<interface_action_paramval
>& p
)
554 if(!(caps1
& LSNES_CORE_CAP1_ACTION
)) {
555 messages
<< "Core does not support actions." << std::endl
;
558 interface_action
* act
= NULL
;
559 for(auto& i
: actions
) {
566 messages
<< "Unknown action id #" << aid
<< std::endl
;
570 std::vector
<lsnes_core_execute_action_param
> parameters
;
571 std::list
<std::vector
<char>> strtmp
;
572 for(auto& b
: act
->params
) {
573 std::string m
= b
.model
;
576 lsnes_core_execute_action_param tp
;
577 tp
.boolean
= p
[j
++].b
;
578 parameters
.push_back(tp
);
579 } else if(regex_match("int:.*", m
)) {
581 lsnes_core_execute_action_param tp
;
582 tp
.integer
= p
[j
++].i
;
583 parameters
.push_back(tp
);
584 } else if(regex_match("string(:.*)?", m
) || regex_match("enum:.*", m
)) {
586 strtmp
.push_back(std::vector
<char>());
587 auto& i
= strtmp
.back();
588 i
.resize(p
[j
].s
.length() + 1);
589 std::copy(p
[j
].s
.begin(), p
[j
].s
.end(), i
.begin());
590 lsnes_core_execute_action_param tp
;
591 tp
.string
.base
= &i
[0];
592 tp
.string
.length
= p
[j
++].s
.length();
593 parameters
.push_back(tp
);
594 } else if(m
== "toggle") {
597 messages
<< "Unknown model '" << m
<< "' in action id #" << aid
<< std::endl
;
601 lsnes_core_execute_action s
;
603 s
.params
= ¶meters
[0];
606 framebuffer::raw
& c_draw_cover()
608 lsnes_core_draw_cover r
;
609 if(caps1
& LSNES_CORE_CAP1_COVER
) {
610 if(!entrypoint(id
, r
))
612 framebuffer::info fbinfo
= translate_info(r
.coverpage
);
613 size_t needed
= fbinfo
.physwidth
* fbinfo
.physheight
* fbinfo
.type
->get_bpp();
614 if(covermem
.size() < needed
) covermem
.resize(needed
);
615 memcpy(&covermem
[0], fbinfo
.mem
, needed
);
616 fbinfo
.mem
= &covermem
[0];
617 cover
= framebuffer::raw(fbinfo
);
621 if(covermem
.size() < 1024) covermem
.resize(1024);
622 framebuffer::info fbi
;
623 fbi
.type
= &framebuffer::pixfmt_rgb16
;
624 fbi
.mem
= &covermem
[0];
626 fbi
.physheight
= 448;
633 cover
= framebuffer::raw(fbi
);
636 std::list
<core_vma_info
> c_vma_list()
638 lsnes_core_get_vma_list r
;
639 if(caps1
& LSNES_CORE_CAP1_MEMWATCH
) {
640 if(!entrypoint(id
, r
))
642 std::list
<core_vma_info
> vmalist
;
643 for(lsnes_core_get_vma_list_vma
** vmas
= r
.vmas
; *vmas
; vmas
++) {
644 lsnes_core_get_vma_list_vma
* vma
= *vmas
;
646 _vma
.name
= vma
->name
;
647 _vma
.base
= vma
->base
;
648 _vma
.size
= vma
->size
;
649 _vma
.endian
= vma
->endian
;
650 _vma
.readonly
= ((vma
->flags
& LSNES_CORE_VMA_READONLY
) != 0);
651 _vma
.special
= ((vma
->flags
& LSNES_CORE_VMA_SPECIAL
) != 0);
652 _vma
.volatile_flag
= ((vma
->flags
& LSNES_CORE_VMA_VOLATILE
) != 0);
653 _vma
.backing_ram
= vma
->direct_map
;
654 _vma
.read
= vma
->read
;
655 _vma
.write
= vma
->write
;
656 vmalist
.push_back(_vma
);
661 return std::list
<core_vma_info
>();
663 std::map
<unsigned, portctrl::type
*> get_ports()
667 void set_internal_pflag()
669 internal_pflag
= true;
672 std::string fullname
;
673 std::string shortname
;
677 std::vector
<std::string
> trace_cpus
;
678 std::map
<unsigned, portctrl::type
*> ports
;
679 std::map
<unsigned, core_region
*> regions
;
680 std::vector
<interface_action
> actions
;
681 framebuffer::raw cover
;
682 std::vector
<char> covermem
;
683 entrypoint_fn entrypoint
;
687 c_core_core::~c_core_core() throw()
691 struct c_core_type
: public core_type
693 c_core_type(c_lib_init
& lib
, core_type_params
& p
, std::map
<unsigned, portctrl::type
*> _ports
,
694 unsigned _rcount
, unsigned _id
)
695 : core_type(p
), ports(_ports
), entrypoint(lib
.get_entrypoint()), rcount(_rcount
), id(_id
)
698 ~c_core_type() throw()
701 int t_load_rom(core_romimage
* images
, std::map
<std::string
, std::string
>& settings
, uint64_t rtc_sec
,
704 lsnes_core_load_rom r
;
705 std::vector
<char> tmpmem
;
706 std::vector
<lsnes_core_system_setting
> tmpmem2
;
708 r
.rtc_subsec
= rtc_subsec
;
709 copy_settings(tmpmem
, tmpmem2
, settings
);
710 r
.settings
= &tmpmem2
[0];
712 std::vector
<lsnes_core_load_rom_image
> imgs
;
714 for(unsigned i
= 0; i
< rcount
; i
++) {
715 imgs
[i
].data
= (const char*)images
[i
].data
;
716 imgs
[i
].size
= images
[i
].size
;
717 imgs
[i
].markup
= images
[i
].markup
;
721 entrypoint(_id
, r
, [_id
](const char* name
, const char* err
) {
722 (stringfmt() << "LSNES_CORE_LOAD_ROM(" << _id
<< ") failed: " << err
).throwex();
726 controller_set
t_controllerconfig(std::map
<std::string
, std::string
>& settings
)
728 lsnes_core_get_controllerconfig r
;
729 std::vector
<char> tmpmem
;
730 std::vector
<lsnes_core_system_setting
> tmpmem2
;
731 copy_settings(tmpmem
, tmpmem2
, settings
);
732 r
.settings
= &tmpmem2
[0];
734 entrypoint(_id
, r
, [_id
](const char* name
, const char* err
) {
735 (stringfmt() << "LSNES_CORE_GET_CONTROLLERCONFIG(" << _id
<< ") failed: "
739 for(unsigned* pt
= r
.controller_types
; *pt
!= 0xFFFFFFFFU
; pt
++) {
741 if(!ports
.count(_pt
))
742 throw std::runtime_error("Illegal port type selected by core");
743 portctrl::type
* pt2
= ports
[_pt
];
744 cset
.ports
.push_back(pt2
);
746 for(lsnes_core_get_controllerconfig_logical_entry
* le
= r
.logical_map
;
747 le
->port
| le
->controller
; le
++) {
748 cset
.logical_map
.push_back(std::make_pair(le
->port
, le
->controller
));
753 void copy_settings(std::vector
<char>& tmpmem
, std::vector
<lsnes_core_system_setting
>& tmpmem2
,
754 std::map
<std::string
, std::string
>& settings
)
757 for(auto i
: settings
)
758 asize
+= i
.first
.length() + i
.second
.length() + 2;
759 tmpmem
.resize(asize
);
761 for(auto i
: settings
) {
762 lsnes_core_system_setting s
;
763 std::copy(i
.first
.begin(), i
.first
.end(), tmpmem
.begin() + asize
);
764 s
.name
= &tmpmem
[asize
];
765 asize
+= i
.first
.length();
767 std::copy(i
.second
.begin(), i
.second
.end(), tmpmem
.begin() + asize
);
768 s
.value
= &tmpmem
[asize
];
769 asize
+= i
.second
.length();
771 tmpmem2
.push_back(s
);
773 lsnes_core_system_setting s
;
776 tmpmem2
.push_back(s
);
778 std::map
<unsigned, portctrl::type
*> ports
;
779 entrypoint_fn entrypoint
;
784 std::vector
<char> msgbuf
;
786 void callback_message(const char* msg
, size_t length
)
788 std::string
_msg(msg
, msg
+ length
);
789 messages
<< _msg
<< std::endl
;
792 short callback_get_input(unsigned port
, unsigned index
, unsigned control
)
794 short v
= ecore_callbacks
->get_input(port
, index
, control
);
795 if(current_core
&& (port
|| index
|| v
))
796 current_core
->set_internal_pflag();
800 void callback_notify_action_update()
802 ecore_callbacks
->action_state_updated();
805 void callback_timer_tick(uint32_t increment
, uint32_t per_second
)
807 ecore_callbacks
->timer_tick(increment
, per_second
);
810 const char* callback_get_firmware_path()
812 std::string fwp
= ecore_callbacks
->get_firmware_path();
813 msgbuf
.resize(fwp
.length() + 1);
814 std::copy(fwp
.begin(), fwp
.end(), msgbuf
.begin());
815 msgbuf
[fwp
.length()] = 0;
819 const char* callback_get_base_path()
821 std::string fwp
= ecore_callbacks
->get_base_path();
822 msgbuf
.resize(fwp
.length() + 1);
823 std::copy(fwp
.begin(), fwp
.end(), msgbuf
.begin());
824 msgbuf
[fwp
.length()] = 0;
828 time_t callback_get_time()
830 return ecore_callbacks
->get_time();
833 time_t callback_get_randomseed()
835 return ecore_callbacks
->get_randomseed();
838 void callback_memory_read(uint64_t addr
, uint64_t value
)
840 ecore_callbacks
->memory_read(addr
, value
);
843 void callback_memory_write(uint64_t addr
, uint64_t value
)
845 ecore_callbacks
->memory_write(addr
, value
);
848 void callback_memory_execute(uint64_t addr
, uint64_t cpunum
)
850 ecore_callbacks
->memory_execute(addr
, cpunum
);
853 void callback_memory_trace(uint64_t proc
, const char* str
, int insn
)
855 ecore_callbacks
->memory_trace(proc
, str
, insn
);
858 void callback_submit_sound(const int16_t* samples
, size_t count
, int stereo
, double rate
)
860 CORE().audio
->submit_buffer((int16_t*)samples
, count
, stereo
, rate
);
863 void callback_notify_latch(const char** params
)
865 std::list
<std::string
> ps
;
867 for(const char** p
= params
; *p
; p
++)
869 ecore_callbacks
->notify_latch(ps
);
872 void callback_submit_frame(struct lsnes_core_framebuffer_info
* _fb
, uint32_t fps_n
, uint32_t fps_d
)
874 framebuffer::info fbinfo
= translate_info(_fb
);
875 framebuffer::raw
fb(fbinfo
);
876 ecore_callbacks
->output_frame(fb
, fps_n
, fps_d
);
881 std::function
<unsigned char()> fn
;
882 static unsigned char call(void* ctx
)
884 return reinterpret_cast<fpcfn
*>(ctx
)->fn();
888 class ccore_disasm
: public disassembler
891 ccore_disasm(struct lsnes_core_disassembler
* disasm
)
892 : disassembler(disasm
->name
)
899 std::string
disassemble(uint64_t base
, std::function
<unsigned char()> fetchpc
)
903 const char* out
= fn(base
, fpcfn::call
, &y
);
907 const char* (*fn
)(uint64_t base
, unsigned char(*fetch
)(void* ctx
), void* ctx
);
910 void* callback_add_disasm(struct lsnes_core_disassembler
* disasm
)
912 return new ccore_disasm(disasm
);
915 void callback_remove_disasm(void* handle
)
917 delete reinterpret_cast<ccore_disasm
*>(handle
);
920 struct utf8_strlen_iter
922 utf8_strlen_iter() { str_len
= 0; }
923 utf8_strlen_iter
& operator++() { str_len
++; return *this; }
924 uint32_t& operator*() { return dummy
; }
930 void callback_render_text2(struct lsnes_core_fontrender_req
& req
, const std::string
& str
)
932 auto size
= main_font
.get_metrics(str
);
933 auto layout
= main_font
.dolayout(str
);
934 size_t memreq
= size
.first
* size
.second
* sizeof(T
);
935 if(!memreq
) memreq
= 1;
936 if(size
.first
&& memreq
/ size
.first
/ sizeof(T
) < size
.second
)
937 throw std::bad_alloc(); //Not enough memory.
938 req
.bitmap
= req
.alloc(req
.cb_ctx
, memreq
);
940 throw std::bad_alloc(); //Not enough memory.
941 T fg
= (T
)req
.fg_color
;
942 T bg
= (T
)req
.bg_color
;
943 T
* bmp
= (T
*)req
.bitmap
;
945 for(auto i
: layout
) {
947 T
* _bmp
= bmp
+ (i
.y
* size
.first
+ i
.x
);
948 size_t w
= g
.wide
? 16 : 8;
949 size_t skip
= size
.first
- w
;
950 for(size_t _y
= 0; _y
< 16; _y
++) {
951 uint32_t d
= g
.data
[_y
>> (g
.wide
? 1 : 2)];
953 d
>>= 16 - ((_y
& 1) << 4);
955 d
>>= 24 - ((_y
& 3) << 3);
956 for(size_t _x
= 0; _x
< w
; _x
++, _bmp
++) {
957 uint32_t b
= w
- _x
- 1;
958 *_bmp
= ((d
>> b
) & 1) ? fg
: bg
;
963 req
.width
= size
.first
;
964 req
.height
= size
.second
;
967 void callback_render_text1(struct lsnes_core_fontrender_req
& req
, const std::string
& str
)
969 switch(req
.bytes_pp
) {
971 callback_render_text2
<uint8_t>(req
, str
);
974 callback_render_text2
<uint16_t>(req
, str
);
977 callback_render_text2
<ss_uint24_t
>(req
, str
);
980 callback_render_text2
<uint32_t>(req
, str
);
983 throw std::runtime_error("Invalid req.bytes_pp");
987 int callback_render_text(struct lsnes_core_fontrender_req
* req
)
990 //If indeterminate length, make it determinate.
991 if(req
->text_len
< 0)
992 req
->text_len
= strlen(req
->text
);
993 const char* text_start
= req
->text
;
994 const char* text_end
= req
->text
+ req
->text_len
;
996 std::string
str(text_start
, text_end
);
997 callback_render_text1(*req
, str
);
1004 core_sysregion
* create_sysregion(entrypoint_fn
& entrypoint
, std::map
<unsigned, core_region
*>& regions
,
1005 std::map
<unsigned, c_core_type
*>& types
, unsigned sysreg
)
1007 struct lsnes_core_get_sysregion_info r
;
1008 entrypoint(sysreg
, r
, [sysreg
](const char* name
, const char* err
) {
1009 (stringfmt() << "LSNES_CORE_GET_SYSREGION_INFO(" << sysreg
<< ") failed: " << err
).throwex();
1011 register_sysregion_mapping(r
.name
, r
.for_system
);
1012 if(!types
.count(r
.type
))
1013 throw std::runtime_error("create_sysregion: Unknown type");
1014 if(!regions
.count(r
.region
))
1015 throw std::runtime_error("create_sysregion: Unknown region");
1016 return new core_sysregion(r
.name
, *types
[r
.type
], *regions
[r
.region
]);
1019 core_region
* create_region(entrypoint_fn
& entrypoint
, unsigned region
)
1021 struct lsnes_core_get_region_info r
;
1022 entrypoint(region
, r
, [region
](const char* name
, const char* err
) {
1023 (stringfmt() << "LSNES_CORE_GET_REGION_INFO(" << region
<< ") failed: " << err
).throwex();
1025 core_region_params p
;
1028 p
.priority
= r
.priority
;
1031 p
.framemagic
[0] = r
.fps_n
;
1032 p
.framemagic
[1] = r
.fps_d
;
1033 for(size_t i
= 0; r
.compatible_runs
[i
] != 0xFFFFFFFFU
; i
++)
1034 p
.compatible_runs
.push_back(r
.compatible_runs
[i
]);
1035 return new core_region(p
);
1038 c_core_core
* create_core(c_lib_init
& lib
, entrypoint_fn
& entrypoint
,
1039 std::map
<unsigned, core_region
*>& regions
, unsigned core
)
1041 c_core_core_params p
;
1042 struct lsnes_core_get_core_info r
;
1043 entrypoint(core
, r
, [core
](const char* name
, const char* err
) {
1044 (stringfmt() << "LSNES_CORE_GET_CORE_INFO(" << core
<< ") failed: " << err
).throwex();
1047 JSON::node
root(r
.json
);
1048 JSON::pointer
rootptr(r
.root_ptr
);
1049 size_t count
= root
[rootptr
].index_count();
1050 for(size_t i
= 0; i
< count
; i
++) {
1051 JSON::pointer j
= rootptr
.index(i
);
1052 p
.ports
.push_back(new portctrl::type_generic(root
, j
.as_string8()));
1055 if(r
.cap_flags1
& LSNES_CORE_CAP1_ACTION
) {
1056 for(lsnes_core_get_core_info_action
* i
= r
.actions
; i
->iname
; i
++) {
1059 a
._symbol
= i
->iname
;
1060 a
._title
= i
->hname
;
1063 for(lsnes_core_get_core_info_aparam
* k
= i
->parameters
; k
->name
; k
++) {
1064 interface_action_param b
;
1065 b
.name
= strduplicate(k
->name
);
1066 b
.model
= strduplicate(k
->model
);
1067 a
.params
.push_back(b
);
1070 p
.actions
.push_back(a
);
1074 if(r
.cap_flags1
& LSNES_CORE_CAP1_TRACE
) {
1075 for(const char** i
= r
.trace_cpu_list
; *i
; i
++) {
1076 p
.trace_cpus
.push_back(*i
);
1079 for(auto & j
: regions
)
1080 p
.regions
[j
.first
] = j
.second
;
1081 p
.shortname
= r
.shortname
;
1082 p
.fullname
= r
.fullname
;
1083 p
.flags
= r
.cap_flags1
;
1086 return new c_core_core(p
);
1089 c_core_type
* create_type(c_lib_init
& lib
, entrypoint_fn
& entrypoint
, std::map
<unsigned, c_core_core
*>& cores
,
1090 std::map
<unsigned, core_region
*>& regions
, unsigned type
)
1092 std::vector
<core_romimage_info_params
> rlist
;
1093 std::vector
<core_setting_param
> plist
;
1095 struct lsnes_core_get_type_info r
;
1096 entrypoint(type
, r
, [type
](const char* name
, const char* err
) {
1097 (stringfmt() << "LSNES_CORE_GET_TYPE_INFO(" << type
<< ") failed: " << err
).throwex();
1100 for(lsnes_core_get_type_info_param
* param
= r
.settings
; param
->iname
; param
++) {
1101 core_setting_param _pr
;
1102 _pr
.iname
= strduplicate(param
->iname
);
1103 _pr
.hname
= strduplicate(param
->hname
);
1104 _pr
.dflt
= strduplicate(param
->dflt
);
1105 _pr
.regex
= strduplicate(param
->regex
);
1108 for(lsnes_core_get_type_info_paramval
* pval
= param
->values
; pval
->iname
; pval
++) {
1109 core_setting_value_param pv
;
1110 pv
.iname
= strduplicate(pval
->iname
);
1111 pv
.hname
= strduplicate(pval
->hname
);
1112 pv
.index
= pval
->index
;
1113 _pr
.values
.push_back(pv
);
1116 plist
.push_back(_pr
);
1119 unsigned rcount
= 0;
1121 for(lsnes_core_get_type_info_romimage
* rimg
= r
.images
; rimg
->iname
; rimg
++) {
1122 core_romimage_info_params rp
;
1123 rp
.iname
= rimg
->iname
;
1124 rp
.hname
= rimg
->hname
;
1125 rp
.mandatory
= rimg
->mandatory
;
1126 rp
.pass_mode
= rimg
->pass_mode
;
1127 rp
.headersize
= rimg
->headersize
;
1128 rp
.extensions
= rimg
->extensions
;
1129 rlist
.push_back(rp
);
1133 unsigned _core
= r
.core
;
1137 p
.sysname
= r
.sysname
;
1141 if(!cores
.count(_core
))
1142 throw std::runtime_error("create_type: Unknown core");
1143 p
.core
= cores
[_core
];
1144 for(unsigned* reg
= r
.regions
; *reg
!= 0xFFFFFFFFU
; reg
++) {
1145 if(!regions
.count(*reg
))
1146 throw std::runtime_error("create_type: Unknown region");
1147 p
.regions
.push_back(regions
[*reg
]);
1149 return new c_core_type(lib
, p
, cores
[_core
]->get_ports(), rcount
, type
);
1152 std::map
<const void*, std::list
<core_sysregion
*>> bylib_sysregion
;
1153 std::map
<const void*, std::list
<core_region
*>> bylib_region
;
1154 std::map
<const void*, std::list
<core_type
*>> bylib_type
;
1155 std::map
<const void*, std::list
<core_core
*>> bylib_core
;
1156 std::map
<const void*, c_lib_init
*> bylib_init
;
1158 void initialize_core2(entrypoint_fn fn
, std::map
<unsigned, core_sysregion
*>& sysregs
,
1159 std::map
<unsigned, core_region
*>& regions
, std::map
<unsigned, c_core_type
*>& types
,
1160 std::map
<unsigned, c_core_core
*>& cores
, const void* mod_id
)
1162 c_lib_init
& lib
= *new c_lib_init(fn
);
1163 for(auto& i
: regions
)
1164 i
.second
= create_region(fn
, i
.first
);
1165 for(auto& i
: cores
)
1166 i
.second
= create_core(lib
, fn
, regions
, i
.first
);
1167 for(auto& i
: types
)
1168 i
.second
= create_type(lib
, fn
, cores
, regions
, i
.first
);
1169 for(auto& i
: sysregs
)
1170 i
.second
= create_sysregion(fn
, regions
, types
, i
.first
);
1173 for(auto& i
: sysregs
) bylib_sysregion
[mod_id
].push_back(i
.second
);
1174 for(auto& i
: regions
) bylib_region
[mod_id
].push_back(i
.second
);
1175 for(auto& i
: types
) bylib_type
[mod_id
].push_back(i
.second
);
1176 for(auto& i
: cores
) bylib_core
[mod_id
].push_back(i
.second
);
1177 bylib_init
[mod_id
] = &lib
;
1179 //We don't call install_handler, because that is done automatically.
1182 void initialize_core(lsnes_core_func_t fn
, const void* mod_id
)
1184 //Enumerate what the thing supports.
1185 entrypoint_fn
entrypoint(fn
);
1186 lsnes_core_enumerate_cores r
;
1188 r
.message
= callback_message
;
1189 r
.get_input
= callback_get_input
;
1190 r
.notify_action_update
= callback_notify_action_update
;
1191 r
.timer_tick
= callback_timer_tick
;
1192 r
.get_firmware_path
= callback_get_firmware_path
;
1193 r
.get_base_path
= callback_get_base_path
;
1194 r
.get_time
= callback_get_time
;
1195 r
.get_randomseed
= callback_get_randomseed
;
1196 r
.memory_read
= callback_memory_read
;
1197 r
.memory_write
= callback_memory_write
;
1198 r
.memory_execute
= callback_memory_execute
;
1199 r
.memory_trace
= callback_memory_trace
;
1200 r
.submit_sound
= callback_submit_sound
;
1201 r
.notify_latch
= callback_notify_latch
;
1202 r
.submit_frame
= callback_submit_frame
;
1203 r
.add_disasm
= callback_add_disasm
;
1204 r
.remove_disasm
= callback_remove_disasm
;
1205 r
.render_text
= callback_render_text
;
1206 entrypoint(0, r
, [](const char* name
, const char* err
) {
1207 (stringfmt() << "LSNES_CORE_ENUMERATE_CORES(0) failed: " << err
).throwex();
1209 //Collect sysregions, types and cores.
1210 std::map
<unsigned, core_region
*> regions
;
1211 std::map
<unsigned, core_sysregion
*> sysregs
;
1212 std::map
<unsigned, c_core_type
*> types
;
1213 std::map
<unsigned, c_core_core
*> cores
;
1214 for(size_t i
= 0; r
.sysregions
[i
] != 0xFFFFFFFFU
; i
++) {
1215 unsigned sysreg
= r
.sysregions
[i
];
1216 sysregs
.insert(std::make_pair(sysreg
, nullptr));
1217 struct lsnes_core_get_sysregion_info r2
;
1218 entrypoint(sysreg
, r2
, [sysreg
](const char* name
, const char* err
) {
1219 (stringfmt() << "LSNES_CORE_GET_SYSREGION_INFO(" << sysreg
<< ") failed: "
1222 unsigned type
= r2
.type
;
1223 types
.insert(std::make_pair(type
, nullptr));
1224 struct lsnes_core_get_type_info r3
;
1225 entrypoint(type
, r3
, [type
](const char* name
, const char* err
) {
1226 (stringfmt() << "LSNES_CORE_GET_TYPE_INFO(" << type
<< ") failed: "
1229 cores
.insert(std::make_pair(r3
.core
, nullptr));
1230 for(size_t j
= 0; r3
.regions
[j
] != 0xFFFFFFFFU
; j
++) {
1231 regions
.insert(std::make_pair(r3
.regions
[j
], nullptr));
1235 initialize_core2(entrypoint
, sysregs
, regions
, types
, cores
, mod_id
);
1238 template<typename T
> void cleanup_list(std::map
<const void*, std::list
<T
*>>& list
, const void* handle
)
1240 if(!list
.count(handle
))
1242 for(auto i
: list
[handle
])
1247 template<typename T
> void cleanup_entry(std::map
<const void*, T
*>& list
, const void* handle
)
1249 if(!list
.count(handle
))
1251 delete list
[handle
];
1257 void lsnes_register_builtin_core(lsnes_core_func_t fn
)
1259 corequeue().push_back(fn
);
1262 void try_init_c_module(const loadlib::module
& module
)
1265 lsnes_core_func_t fn
= module
.fn
<int, unsigned, unsigned, void*,
1266 const char**>("lsnes_core_entrypoint");
1267 initialize_core(fn
, &module
);
1268 } catch(std::exception
& e
) {
1269 messages
<< "Can't initialize core: " << e
.what() << std::endl
;
1273 void try_uninit_c_module(const loadlib::module
& module
)
1275 if(bylib_core
.count(&module
))
1276 for(auto i
: bylib_core
[&module
])
1277 i
->uninstall_handler();
1278 cleanup_list(bylib_sysregion
, &module
);
1279 cleanup_list(bylib_region
, &module
);
1280 cleanup_list(bylib_type
, &module
);
1281 cleanup_list(bylib_core
, &module
);
1282 cleanup_entry(bylib_init
, &module
);
1285 bool core_uses_module(core_core
* core
, const loadlib::module
& module
)
1287 if(!bylib_core
.count(&module
))
1289 for(auto i
: bylib_core
[&module
])
1295 void initialize_all_builtin_c_cores()
1297 while(!corequeue().empty()) {
1298 lsnes_core_func_t fn
= corequeue().front();
1299 corequeue().pop_front();
1301 initialize_core(fn
, NULL
);
1302 } catch(std::exception
& e
) {
1303 messages
<< "Can't initialize core: " << e
.what() << std::endl
;