Fixed various bugs:

bus/nubus/nubus_image.cpp: Fixed failure to allocate memory for the
image (regressed in b8c338858a).

bus/nes/karastudio.cpp, bus/nes/sunsoft_dcs.cpp: Fixed stack smash when
loading loose software.

Addressed some Lua engine fallout from running things in coroutines:
* Don't crash accessing dead Lua thread state from callbacks.
* Allow returning values via yielding functions.
* Don't run address space tap and layout view callbacks in coroutines to
  save overhead.
* Better logging of errors from callbacks.
This commit is contained in:
Vas Crabb 2023-04-06 04:49:10 +10:00
parent 9922c964c9
commit 0f785dee8f
35 changed files with 210 additions and 175 deletions

View File

@ -621,16 +621,15 @@ std::error_condition gba_cart_slot_device::call_load()
{
if (m_cart)
{
uint8_t *ROM;
uint32_t size = loaded_through_softlist() ? get_software_region_length("rom") : length();
if (size > 0x4000000)
uint32_t const size = loaded_through_softlist() ? get_software_region_length("rom") : length();
if (size > 0x400'0000)
{
osd_printf_error("%s: Attempted loading a cart larger than 64MB\n", basename());
return image_error::INVALIDLENGTH;
}
m_cart->rom_alloc(size, tag());
ROM = (uint8_t *)m_cart->get_rom_base();
uint8_t *const ROM = (uint8_t *)m_cart->get_rom_base();
if (!loaded_through_softlist())
{
@ -670,9 +669,9 @@ std::error_condition gba_cart_slot_device::call_load()
memcpy(ROM + 0x1000000, ROM, 0x1000000);
break;
}
if (size == 0x4000000)
if (size == 0x400'0000)
{
memcpy((uint8_t *)m_cart->get_romhlp_base(), ROM, 0x2000000);
memcpy(m_cart->get_romhlp_base(), ROM, 0x2000000);
for (uint32_t i = 0; i < 16; i++)
{
memcpy((uint8_t *)m_cart->get_romhlp_base() + i * 0x1000, ROM + 0x200, 0x1000);
@ -682,8 +681,6 @@ std::error_condition gba_cart_slot_device::call_load()
if (m_cart->get_nvram_size())
battery_load(m_cart->get_nvram_base(), m_cart->get_nvram_size(), 0x00);
return std::error_condition();
}
return std::error_condition();

View File

@ -159,11 +159,10 @@ std::error_condition iq151cart_slot_device::call_load()
{
if (m_cart)
{
offs_t read_length;
uint8_t *cart_base = m_cart->get_cart_base();
if (cart_base != nullptr)
uint8_t *const cart_base = m_cart->get_cart_base();
if (cart_base)
{
offs_t read_length;
if (!loaded_through_softlist())
{
read_length = length();

View File

@ -53,7 +53,7 @@ public:
// construction/destruction
omti_disk_image_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// image-level overrides
// device_image_interface implementation
virtual bool support_command_line_image_creation() const noexcept override { return true; }
virtual const char *file_extensions() const noexcept override { return "awd"; }
virtual const char *image_type_name() const noexcept override { return "winchester"; }
@ -62,7 +62,7 @@ public:
virtual std::error_condition call_create(int format_type, util::option_resolution *format_options) override;
protected:
// device-level overrides
// device_t implementation
virtual void device_start() override;
virtual void device_reset() override;
@ -1478,11 +1478,8 @@ std::error_condition omti_disk_image_device::call_create(int format_type, util::
for (int x = 0; x < m_sector_count; x++)
{
if (fwrite(sectordata, OMTI_DISK_SECTOR_SIZE)
< OMTI_DISK_SECTOR_SIZE)
{
if (fwrite(sectordata, OMTI_DISK_SECTOR_SIZE) < OMTI_DISK_SECTOR_SIZE)
return image_error::UNSPECIFIED;
}
}
return std::error_condition();

View File

@ -16,8 +16,10 @@
#pragma once
#include "isa.h"
#include "machine/upd765.h"
#include "imagedev/floppy.h"
#include "machine/upd765.h"
/***************************************************************************
FUNCTION PROTOTYPES
@ -44,7 +46,7 @@ protected:
device_t *owner,
uint32_t clock);
// device-level overrides
// device_t implementation
virtual void device_start() override;
virtual void device_reset() override;
virtual const tiny_rom_entry *device_rom_region() const override;

View File

@ -1320,3 +1320,7 @@ void sc499_ctape_image_device::call_unload()
// fwrite(m_ctape_data, m_ctape_data.size);
//}
}
void sc499_ctape_image_device::device_start()
{
}

View File

@ -13,7 +13,8 @@
#pragma once
#include "bus/isa/isa.h"
#include "isa.h"
#include "imagedev/magtape.h"
@ -29,7 +30,7 @@ public:
// construction/destruction
sc499_ctape_image_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// image-level overrides
// device_image_interface implementation
virtual std::error_condition call_load() override;
virtual void call_unload() override;
@ -44,8 +45,8 @@ public:
uint64_t tapelen() { return m_ctape_data.size(); }
protected:
// device-level overrides
virtual void device_start() override { }
// device_t implementation
virtual void device_start() override;
std::vector<uint8_t> m_ctape_data;
};

View File

@ -129,12 +129,11 @@ std::error_condition jakks_gamekey_slot_device::call_load()
{
if (m_cart)
{
uint8_t *ROM;
uint32_t len = !loaded_through_softlist() ? length() : get_software_region_length("rom");
uint32_t const len = !loaded_through_softlist() ? length() : get_software_region_length("rom");
m_cart->rom_alloc(len, tag());
ROM = m_cart->get_rom_base();
uint8_t *const ROM = m_cart->get_rom_base();
if (!loaded_through_softlist())
fread(ROM, len);
@ -153,8 +152,6 @@ std::error_condition jakks_gamekey_slot_device::call_load()
if (pcb_name)
m_type = jakks_gamekey_get_pcb_id(pcb_name);
}
return std::error_condition();
}
return std::error_condition();

View File

@ -320,11 +320,10 @@ std::error_condition kccart_slot_device::call_load()
{
if (m_cart)
{
offs_t read_length;
uint8_t *cart_base = m_cart->get_cart_base();
if (cart_base != nullptr)
uint8_t *const cart_base = m_cart->get_cart_base();
if (cart_base)
{
offs_t read_length;
if (!loaded_through_softlist())
{
read_length = length();

View File

@ -110,14 +110,14 @@ public:
kccart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual ~kccart_slot_device();
// image-level overrides
// device_image_interface implementation
virtual std::error_condition call_load() override;
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "kc_cart"; }
virtual const char *file_extensions() const noexcept override { return "bin"; }
// slot interface overrides
// device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
};

View File

@ -27,7 +27,7 @@ public:
protected:
mc10_pak_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
// device-level overrides
// device_t implementation
virtual void device_start() override;
};

View File

@ -22,7 +22,7 @@ class msx_cart_beepack_device : public device_t
public:
msx_cart_beepack_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
// image-level overrides
// device_image_interface implementation
virtual std::error_condition call_load() override;
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "bee_card"; }

View File

@ -46,7 +46,7 @@ std::error_condition msx_cart_softcard_device::call_load()
{
if (loaded_through_softlist())
{
u32 length = get_software_region_length("rom");
u32 const length = get_software_region_length("rom");
// Only 32KB images are supported
if (length != 0x8000)
{
@ -56,7 +56,7 @@ std::error_condition msx_cart_softcard_device::call_load()
}
else
{
u32 length = this->length();
u32 const length = this->length();
// Only 32KB images are supported
if (length != 0x8000)
{

View File

@ -22,7 +22,7 @@ class msx_cart_softcard_device : public device_t
public:
msx_cart_softcard_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
// image-level overrides
// device_image_interface implementation
virtual std::error_condition call_load() override;
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "softcard"; }

View File

@ -93,7 +93,7 @@ std::error_condition mtx_exp_slot_device::call_load()
{
if (m_card)
{
uint32_t size = !loaded_through_softlist() ? length() : get_software_region_length("rom");
uint32_t const size = !loaded_through_softlist() ? length() : get_software_region_length("rom");
if (size % 0x2000)
{

View File

@ -303,8 +303,6 @@ std::error_condition neogeo_cart_slot_device::call_load()
// SPEED UP WORKAROUND: to speed up sprite drawing routine, let us store the sprite data in
// a different format (we then always access such alt format for drawing)
m_cart->optimize_sprites(m_cart->get_sprites_base(), m_cart->get_sprites_size());
return std::error_condition();
}
}

View File

@ -203,7 +203,7 @@ public:
neogeo_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint16_t clock);
virtual ~neogeo_cart_slot_device();
// image-level overrides
// device_image_interface implementation
virtual std::error_condition call_load() override;
virtual void call_unload() override;
@ -211,7 +211,7 @@ public:
virtual const char *image_interface() const noexcept override { return "neo_cart"; }
virtual const char *file_extensions() const noexcept override { return "bin"; }
// slot interface overrides
// device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
// reading and writing
@ -328,9 +328,8 @@ public:
get_audio_base(), get_audio_size(),
get_audiocrypt_base(), get_audiocrypt_size()); }
protected:
// device-level overrides
// device_t implementation
virtual void device_start() override;
private:

View File

@ -97,12 +97,11 @@ std::error_condition nes_aladdin_slot_device::call_load()
{
if (m_cart)
{
uint8_t *ROM = m_cart->get_cart_base();
uint32_t size;
uint8_t *const ROM = m_cart->get_cart_base();
if (!ROM)
return image_error::INTERNAL;
uint32_t size;
if (!loaded_through_softlist())
{
if (length() != 0x20010 && length() != 0x40010)
@ -114,19 +113,17 @@ std::error_condition nes_aladdin_slot_device::call_load()
memcpy(ROM, temp + 0x10, size);
// double check that iNES files are really mapper 71 or 232
{
uint8_t mapper = (temp[6] & 0xf0) >> 4;
mapper |= temp[7] & 0xf0;
if (mapper != 71 && mapper != 232)
return image_error::INVALIDIMAGE;
}
uint8_t mapper = (temp[6] & 0xf0) >> 4;
mapper |= temp[7] & 0xf0;
if (mapper != 71 && mapper != 232)
return image_error::INVALIDIMAGE;
}
else
{
if (get_software_region_length("rom") != 0x20000 && get_software_region_length("rom") != 0x40000)
size = get_software_region_length("rom");
if (size != 0x2'0000 && size != 0x4'0000)
return image_error::BADSOFTWARE;
size = get_software_region_length("rom");
memcpy(ROM, get_software_region("rom"), size);
}

View File

@ -63,24 +63,24 @@ public:
nes_aladdin_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual ~nes_aladdin_slot_device();
// image-level overrides
// device_image_interface implementation
virtual std::error_condition call_load() override;
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "ade_cart"; }
virtual const char *file_extensions() const noexcept override { return "nes,bin"; }
// slot interface overrides
// device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
uint8_t read(offs_t offset);
void write_prg(uint32_t offset, uint8_t data) { if (m_cart) m_cart->write_prg(offset, data); }
protected:
// device-level overrides
// device_t implementation
virtual void device_start() override;
aladdin_cart_interface* m_cart;
aladdin_cart_interface *m_cart;
};
// device type definition
@ -160,9 +160,8 @@ public:
virtual void pcb_reset() override;
protected:
// device-level overrides
// device_t implementation
virtual void device_start() override;
virtual void device_add_mconfig(machine_config &config) override;
required_device<nes_aladdin_slot_device> m_subslot;

View File

@ -96,8 +96,7 @@ std::error_condition nes_datach_slot_device::call_load()
{
if (m_cart)
{
uint8_t *ROM = m_cart->get_cart_base();
uint8_t *const ROM = m_cart->get_cart_base();
if (!ROM)
return image_error::INTERNAL;

View File

@ -64,24 +64,24 @@ public:
nes_datach_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual ~nes_datach_slot_device();
// image-level overrides
// device_image_interface implementation
virtual std::error_condition call_load() override;
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "datach_cart"; }
virtual const char *file_extensions() const noexcept override { return "nes,bin"; }
// slot interface overrides
// device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
uint8_t read(offs_t offset);
void write_prg_bank(uint8_t bank) { if (m_cart) m_cart->write_prg_bank(bank); }
protected:
// device-level overrides
// device_t implementation
virtual void device_start() override;
datach_cart_interface* m_cart;
datach_cart_interface *m_cart;
};
// device type definition
@ -102,16 +102,15 @@ public:
// construction/destruction
nes_datach_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// optional information overrides
virtual const tiny_rom_entry *device_rom_region() const override;
virtual uint8_t* get_cart_base();
virtual uint8_t *get_cart_base();
protected:
nes_datach_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
// device-level overrides
// device_t implementation
virtual void device_start() override;
virtual void device_reset() override;
virtual const tiny_rom_entry *device_rom_region() const override;
};
// ======================> nes_datach_24c01_device
@ -123,7 +122,7 @@ public:
nes_datach_24c01_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
// optional information overrides
// device_t implementation
virtual void device_add_mconfig(machine_config &config) override;
};
@ -153,7 +152,7 @@ public:
virtual void pcb_reset() override;
protected:
// device-level overrides
// device_t implementation
virtual void device_start() override;
virtual void device_add_mconfig(machine_config &config) override;

View File

@ -100,8 +100,7 @@ std::error_condition nes_kstudio_slot_device::call_load()
{
if (m_cart)
{
uint8_t *ROM = m_cart->get_cart_base();
uint8_t *const ROM = m_cart->get_cart_base();
if (!ROM)
return image_error::INTERNAL;
@ -111,7 +110,7 @@ std::error_condition nes_kstudio_slot_device::call_load()
if (length() != 0x20000)
return image_error::INVALIDLENGTH;
fread(&ROM, 0x20000);
fread(ROM, 0x20000);
}
else
{

View File

@ -62,24 +62,24 @@ public:
nes_kstudio_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual ~nes_kstudio_slot_device();
// image-level overrides
// device_image_interface implementation
virtual std::error_condition call_load() override;
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "ks_cart"; }
virtual const char *file_extensions() const noexcept override { return "bin"; }
// slot interface overrides
// device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
uint8_t read(offs_t offset);
void write_prg_bank(uint8_t bank) { if (m_cart) m_cart->write_prg_bank(bank); }
protected:
// device-level overrides
// device_t implementation
virtual void device_start() override;
kstudio_cart_interface* m_cart;
kstudio_cart_interface *m_cart;
};
// device type definition
@ -101,14 +101,13 @@ public:
// construction/destruction
nes_kstudio_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// optional information overrides
virtual const tiny_rom_entry *device_rom_region() const override;
virtual uint8_t* get_cart_base();
virtual uint8_t *get_cart_base();
protected:
// device-level overrides
// device_t implementation
virtual void device_start() override;
virtual void device_reset() override;
virtual const tiny_rom_entry *device_rom_region() const override;
};
// device type definition

View File

@ -81,8 +81,7 @@ std::error_condition nes_ntb_slot_device::call_load()
{
if (m_cart)
{
uint8_t *ROM = m_cart->get_cart_base();
uint8_t *const ROM = m_cart->get_cart_base();
if (!ROM)
return image_error::INTERNAL;
@ -91,7 +90,7 @@ std::error_condition nes_ntb_slot_device::call_load()
if (length() != 0x4000)
return image_error::INVALIDLENGTH;
fread(&ROM, 0x4000);
fread(ROM, 0x4000);
}
else
{

View File

@ -59,23 +59,23 @@ public:
nes_ntb_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual ~nes_ntb_slot_device();
// image-level overrides
// device_image_interface implementation
virtual std::error_condition call_load() override;
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "ntb_cart"; }
virtual const char *file_extensions() const noexcept override { return "bin"; }
// slot interface overrides
// device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
virtual uint8_t read(offs_t offset);
protected:
// device-level overrides
// device_t implementation
virtual void device_start() override;
ntb_cart_interface* m_cart;
ntb_cart_interface *m_cart;
};
// device type definition
@ -97,13 +97,12 @@ public:
// construction/destruction
nes_ntb_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// optional information overrides
virtual const tiny_rom_entry *device_rom_region() const override;
virtual uint8_t* get_cart_base();
virtual uint8_t *get_cart_base();
protected:
// device-level overrides
// device_t implementation
virtual void device_start() override;
virtual const tiny_rom_entry *device_rom_region() const override;
};
// device type definition

View File

@ -40,7 +40,7 @@ public:
// construction/destruction
messimg_disk_image_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// image-level overrides
// device_image_interface implementation
virtual bool is_readable() const noexcept override { return true; }
virtual bool is_writeable() const noexcept override { return true; }
virtual bool is_creatable() const noexcept override { return false; }
@ -91,8 +91,7 @@ void nubus_image_device::messimg_disk_image_device::device_start()
std::error_condition nubus_image_device::messimg_disk_image_device::call_load()
{
fseek(0, SEEK_END);
m_size = uint32_t(ftell());
m_size = length();
if (m_size > (256*1024*1024))
{
osd_printf_error("Mac image too large: must be 256MB or less!\n");
@ -100,8 +99,12 @@ std::error_condition nubus_image_device::messimg_disk_image_device::call_load()
return image_error::INVALIDLENGTH;
}
m_data.reset(new (std::nothrow) uint8_t [m_size]);
if (!m_data)
return std::errc::not_enough_memory;
fseek(0, SEEK_SET);
fread(m_data, m_size);
fread(m_data.get(), m_size);
m_ejected = false;
return std::error_condition();

View File

@ -152,7 +152,7 @@ std::error_condition o2_cart_slot_device::call_load()
}
else
{
u32 size = length();
u32 const size = length();
fread(m_cart->m_rom, size);
m_cart->m_rom_size = size;

View File

@ -214,39 +214,36 @@ std::error_condition pce_cart_slot_device::call_load()
{
if (m_cart)
{
uint32_t offset;
uint32_t len = !loaded_through_softlist() ? length() : get_software_region_length("rom");
uint8_t *ROM;
// From fullpath, check for presence of a header and skip it
if (!loaded_through_softlist() && (len % 0x4000) == 512)
{
logerror("Rom-header found, skipping\n");
offset = 512;
logerror("ROM header found, skipping\n");
uint32_t const offset = 512;
len -= offset;
fseek(offset, SEEK_SET);
}
m_cart->rom_alloc(len);
ROM = m_cart->get_rom_base();
uint8_t *const ROM = m_cart->get_rom_base();
if (!loaded_through_softlist())
fread(ROM, len);
else
memcpy(ROM, get_software_region("rom"), len);
// check for encryption (US carts)
// check for bit-reversal (US carts)
if (ROM[0x1fff] < 0xe0)
{
uint8_t decrypted[256];
/* Initialize decryption table */
// Initialize unscrambling table
uint8_t unscrambled[256];
for (int i = 0; i < 256; i++)
decrypted[i] = ((i & 0x01) << 7) | ((i & 0x02) << 5) | ((i & 0x04) << 3) | ((i & 0x08) << 1) | ((i & 0x10) >> 1) | ((i & 0x20 ) >> 3) | ((i & 0x40) >> 5) | ((i & 0x80) >> 7);
unscrambled[i] = bitswap<8>(i, 0, 1, 2, 3, 4, 5, 6, 7);
/* Decrypt ROM image */
// Unscramble ROM image
for (int i = 0; i < len; i++)
ROM[i] = decrypted[ROM[i]];
ROM[i] = unscrambled[ROM[i]];
}
m_cart->rom_map_setup(len);
@ -265,8 +262,6 @@ std::error_condition pce_cart_slot_device::call_load()
m_cart->ram_alloc(0x8000);
if (m_type == PCE_CDSYS3J || m_type == PCE_CDSYS3U)
m_cart->ram_alloc(0x30000);
return std::error_condition();
}
return std::error_condition();

View File

@ -310,19 +310,17 @@ std::error_condition psxcard_device::call_load()
std::error_condition psxcard_device::call_create(int format_type, util::option_resolution *format_options)
{
uint8_t block[block_size];
int i, ret;
if(m_disabled)
{
logerror("psxcard: port disabled\n");
return image_error::UNSUPPORTED;
}
uint8_t block[block_size];
memset(block, '\0', block_size);
for(i = 0; i < (card_size/block_size); i++)
for(int i = 0; i < (card_size/block_size); i++)
{
ret = fwrite(block, block_size);
auto const ret = fwrite(block, block_size);
if(ret != block_size)
return image_error::UNSPECIFIED;
}

View File

@ -715,7 +715,7 @@ void lua_engine::initialize()
* emu.unpause() - unpause emulation
* emu.step() - advance one frame
* emu.keypost(keys) - post keys to natural keyboard
* emu.wait(len) - wait for len within coroutine
* emu.wait(duration, ...) - wait for duration within coroutine
* emu.lang_translate(str) - get translation for str if available
* emu.subst_env(str) - substitute environment variables with values for str (semantics are OS-specific)
*
@ -822,45 +822,48 @@ void lua_engine::initialize()
return sol::make_object(s, driver_list::driver(i));
};
emu["wait"] = sol::yielding(
[this] (sol::this_state s, sol::object arg)
[this] (sol::this_state s, sol::object duration, sol::variadic_args args)
{
attotime duration;
if (!arg)
attotime delay;
if (!duration)
{
luaL_error(s, "waiting duration expected");
}
else if (arg.is<attotime>())
else if (duration.is<attotime>())
{
duration = arg.as<attotime>();
delay = duration.as<attotime>();
}
else
{
auto seconds = arg.as<std::optional<double> >();
auto seconds = duration.as<std::optional<double> >();
if (!seconds)
luaL_error(s, "waiting duration must be attotime or number");
duration = attotime::from_double(*seconds);
delay = attotime::from_double(*seconds);
}
int const ret = lua_pushthread(s);
if (ret == 1)
luaL_error(s, "cannot wait from outside coroutine");
int const ref = luaL_ref(s, LUA_REGISTRYINDEX);
machine().scheduler().timer_set(duration, timer_expired_delegate(FUNC(lua_engine::resume), this), ref);
machine().scheduler().timer_set(delay, timer_expired_delegate(FUNC(lua_engine::resume), this), ref);
return sol::variadic_results(args.begin(), args.end());
});
emu["wait_next_update"] = sol::yielding(
[this] (sol::this_state s)
[this] (sol::this_state s, sol::variadic_args args)
{
int const ret = lua_pushthread(s);
if (ret == 1)
luaL_error(s, "cannot wait from outside coroutine");
m_update_tasks.emplace_back(luaL_ref(s, LUA_REGISTRYINDEX));
return sol::variadic_results(args.begin(), args.end());
});
emu["wait_next_frame"] = sol::yielding(
[this] (sol::this_state s)
[this] (sol::this_state s, sol::variadic_args args)
{
int const ret = lua_pushthread(s);
if (ret == 1)
luaL_error(s, "cannot wait from outside coroutine");
m_frame_tasks.emplace_back(luaL_ref(s, LUA_REGISTRYINDEX));
return sol::variadic_results(args.begin(), args.end());
});
emu["lang_translate"] = sol::overload(
static_cast<char const *(*)(char const *)>(&lang_translate),

View File

@ -131,6 +131,13 @@ public:
return cr(std::forward<Params>(args)...);
}
template <typename Func, typename... Params>
static auto invoke_direct(Func &&func, Params&&... args)
{
auto profile = g_profiler.start(PROFILER_LUA);
return func(std::forward<Params>(args)...);
}
private:
template <typename T, size_t Size> class enum_parser;

View File

@ -592,27 +592,36 @@ auto lua_engine::make_simple_callback_setter(void (T::*setter)(delegate<R ()> &&
else if (cb.is<sol::protected_function>())
{
(self.*setter)(delegate<R ()>(
[this, dflt, desc, cbfunc = cb.as<sol::protected_function>()] () -> R
[this, dflt, desc, cbfunc = sol::protected_function(m_lua_state, cb)] () -> R
{
if constexpr (std::is_same_v<R, void>)
auto status(invoke_direct(cbfunc));
if (status.valid())
{
(void)dflt;
(void)desc;
invoke(cbfunc);
}
else
{
auto result(invoke(cbfunc).get<std::optional<R> >());
if (result)
if constexpr (std::is_same_v<R, void>)
{
return *result;
std::ignore = dflt;
}
else
{
osd_printf_error("[LUA ERROR] invalid return from %s callback\n", desc);
return dflt();
auto result(status.get<std::optional<R> >());
if (result)
{
return *result;
}
else
{
osd_printf_error("[LUA ERROR] invalid return from %s callback\n", desc);
return dflt();
}
}
}
else
{
sol::error err(status);
osd_printf_error("[LUA ERROR] error in %s callback: %s\n", desc, err.what());
if constexpr (!std::is_same_v<R, void>)
return dflt();
}
}));
}
else

View File

@ -106,21 +106,37 @@ public:
{
symbol_table::setter_func setfun;
if (setter)
setfun = [this, cbfunc = std::move(*setter)] (u64 value) { m_host.invoke(cbfunc, value); };
{
setfun =
[this, cbfunc = sol::protected_function(m_host.m_lua_state, *setter)] (u64 value)
{
auto status = m_host.invoke(cbfunc, value);
if (!status.valid())
{
sol::error err = status;
osd_printf_error("[LUA EROR] in symbol value setter callback: %s\n", err.what());
}
};
}
return m_table.add(
name,
[this, cbfunc = std::move(getter)] () -> u64
[this, cbfunc = sol::protected_function(m_host.m_lua_state, getter)] () -> u64
{
auto result = m_host.invoke(cbfunc).get<std::optional<u64> >();
if (result)
auto status = m_host.invoke(cbfunc);
if (status.valid())
{
return *result;
auto result = status.get<std::optional<u64> >();
if (result)
return *result;
osd_printf_error("[LUA EROR] invalid return from symbol value getter callback\n");
}
else
{
osd_printf_error("[LUA EROR] invalid return from symbol value getter callback\n");
return 0;
sol::error err = status;
osd_printf_error("[LUA EROR] in symbol value getter callback: %s\n", err.what());
}
return 0;
},
std::move(setfun),
(format && *format) ? *format : "");
@ -245,7 +261,7 @@ void lua_engine::initialize_debug(sol::table &emu)
if (cb == sol::lua_nil)
st.table().set_memory_modified_func(nullptr);
else if (cb.is<sol::protected_function>())
st.table().set_memory_modified_func([this, cbfunc = cb.as<sol::protected_function>()] () { invoke(cbfunc); });
st.table().set_memory_modified_func([this, cbfunc = sol::protected_function(m_lua_state, cb)] () { invoke(cbfunc); });
else
osd_printf_error("[LUA ERROR] must call set_memory_modified_func with function or nil\n");
});
@ -269,22 +285,40 @@ void lua_engine::initialize_debug(sol::table &emu)
{
return st.add(name, getter, std::nullopt, nullptr);
},
[] (symbol_table_wrapper &st, sol::this_state s, char const *name, int minparams, int maxparams, sol::protected_function execute) -> symbol_entry &
[this] (symbol_table_wrapper &st, char const *name, int minparams, int maxparams, sol::protected_function execute) -> symbol_entry &
{
return st.table().add(
name,
minparams,
maxparams,
[L = s.L, cbref = sol::reference(execute)] (int numparams, u64 const *paramlist) -> u64
[this, cb = sol::protected_function(m_lua_state, execute)] (int numparams, u64 const *paramlist) -> u64
{
sol::stack_reference traceback(L, -sol::stack::push(L, sol::default_traceback_error_handler));
cbref.push();
sol::stack_aligned_stack_handler_function func(L, -1, traceback);
for (int i = 0; numparams > i; ++i)
lua_pushinteger(L, paramlist[i]);
auto result = func(sol::stack_count(numparams)).get<std::optional<u64> >();
traceback.pop();
return result ? *result : 0;
// TODO: C++20 will make this obsolete
class helper
{
private:
u64 const *b, *e;
public:
helper(int n, u64 const *p) : b(p), e(p + n) { }
auto begin() const { return b; }
auto end() const { return e; }
};
auto status(invoke(cb, sol::as_args(helper(numparams, paramlist))));
if (status.valid())
{
auto result = status.get<std::optional<u64> >();
if (result)
return *result;
osd_printf_error("[LUA EROR] invalid return from symbol execute callback\n");
}
else
{
sol::error err = status;
osd_printf_error("[LUA EROR] in symbol execute callback: %s\n", err.what());
}
return 0;
});
});
symbol_table_type.set_function("find", &symbol_table_wrapper::find);

View File

@ -202,8 +202,7 @@ public:
offs_t end,
std::string &&name,
sol::protected_function &&callback)
: m_host(host)
, m_callback(std::move(callback))
: m_callback(host.m_lua_state, std::move(callback))
, m_space(space)
, m_handler()
, m_name(std::move(name))
@ -270,7 +269,7 @@ private:
m_name,
[this] (offs_t offset, T &data, T mem_mask)
{
auto result = m_host.invoke(m_callback, offset, data, mem_mask).template get<std::optional<T> >();
auto result = invoke_direct(m_callback, offset, data, mem_mask).template get<std::optional<T> >();
if (result)
data = *result;
},
@ -283,7 +282,7 @@ private:
m_name,
[this] (offs_t offset, T &data, T mem_mask)
{
auto result = m_host.invoke(m_callback, offset, data, mem_mask).template get<std::optional<T> >();
auto result = invoke_direct(m_callback, offset, data, mem_mask).template get<std::optional<T> >();
if (result)
data = *result;
},
@ -302,7 +301,6 @@ private:
--m_installing;
};
lua_engine &m_host;
sol::protected_function m_callback;
address_space &m_space;
memory_passthrough_handler m_handler;
@ -660,7 +658,12 @@ void lua_engine::initialize_memory(sol::table &emu)
case read_or_write::WRITE: modestr = "w"; break;
case read_or_write::READWRITE: modestr = "rw"; break;
}
invoke(callback, modestr);
auto status = invoke(callback, modestr);
if (!status.valid())
{
sol::error err = status;
osd_printf_error("[LUA ERROR] in address space change notifier: %s\n", err.what());
}
});
});
addr_space_type.set_function("install_read_tap",

View File

@ -747,19 +747,19 @@ void lua_engine::initialize_render(sol::table &emu)
&layout_view::set_prepare_items_callback,
nullptr,
"set_prepare_items_callback",
nullptr);
"prepare items");
layout_view_type["set_preload_callback"] =
make_simple_callback_setter<void>(
&layout_view::set_preload_callback,
nullptr,
"set_preload_callback",
nullptr);
"preload");
layout_view_type["set_recomputed_callback"] =
make_simple_callback_setter<void>(
&layout_view::set_recomputed_callback,
nullptr,
"set_recomputed_callback",
nullptr);
"recomputed");
layout_view_type["items"] = sol::property([] (layout_view &v) { return layout_view_items(v); });
layout_view_type["name"] = sol::property(&layout_view::name);
layout_view_type["unqualified_name"] = sol::property(&layout_view::unqualified_name);
@ -857,7 +857,7 @@ void lua_engine::initialize_render(sol::table &emu)
&layout_file::set_resolve_tags_callback,
nullptr,
"set_resolve_tags_callback",
nullptr);
"resolve tags");
layout_file_type["device"] = sol::property(&layout_file::device);
layout_file_type["views"] = sol::property([] (layout_file &f) { return layout_file_views(f); });

View File

@ -2,7 +2,7 @@
// copyright-holders:Miodrag Milanovic
/*********************************************************************
Neo Geo Memory card functions.
Neo Geo Memory card functions
JEIDA V3 SRAM cards. The BIOS supports 8-bit and 16-bit cards,
in 2KiB, 4KiB, 6KiB, 8KiB, 10KiB, 14KiB and 16KiB capacities.