Hi Anoid,

I thought I'd give the HERO woz a spin and sure enough, it doesn't work properly, dropping dynamite every time you land (until you run out of dynamite, of course). According to the atari 2600 manual for hero, when you pull the stick down its supposed to put down some dynamite. So that must be what's happening.

When I was playing with the joystick calibration values, I would just put some different values in and with trial and error and much recompiling I came up with some good values. Waiting for the compile and link became intolerable. So then I thought, what if I could change the calibration "on the fly" while mame was running.

I thought a slider would be cool, but that would mean messing about in the sliders with ui.cpp.

WARNING: HORRIBLE HACK ALERT!

I did a terrible hack of luaengine.cpp and the apple2.cpp, a terrible terrible hack but it seems to work. (For proof of concept)


So I added m_x_calibration, and m_y_calibration to the save_item list:

Code
	save_item(NAME(m_an0));
	save_item(NAME(m_an1));
	save_item(NAME(m_an2));
	save_item(NAME(m_an3));
	save_item(NAME(m_anykeydown));
        save_item(NAME(m_x_calibration));
        save_item(NAME(m_y_calibration));


And then did a horrible hack of emu.item, adding readasdouble and writeasdouble:

Code

*
 * emu.item(item_index)
 * item.size - size of the raw data type
 * item.count - number of entries
 * item:read(offset) - read entry value by index
 * item:read_block(offset, count) - read a block of entry values as a string (byte addressing)
 * item:write(offset, value) - write entry value by index
 */

	emu.new_usertype<save_item>("item", sol::call_constructor, sol::initializers([this](save_item &item, int index) {
					if(!machine().save().indexed_item(index, item.base, item.size, item.count))
					{
						item.base = nullptr;
						item.size = 0;
						item.count= 0;
					}
				}),
			"size", sol::readonly(&save_item::size),
			"count", sol::readonly(&save_item::count),
			"read", [this](save_item &item, int offset) -> sol::object {
					uint64_t ret = 0;
					if(!item.base || (offset > item.count))
						return sol::make_object(sol(), sol::nil);
					switch(item.size)
					{
						case 1:
						default:
							ret = ((uint8_t *)item.base)[offset];
							break;
						case 2:
							ret = ((uint16_t *)item.base)[offset];
							break;
						case 4:
							ret = ((uint32_t *)item.base)[offset];
							break;
						case 8:
							ret = ((uint64_t *)item.base)[offset];
							break;
					}
					return sol::make_object(sol(), ret);
				},
			"readasdouble", [this](save_item &item, int offset) -> sol::object {
					uint64_t ret = 0;
                                        double retfloat = 0;					
					if(!item.base || (offset > item.count))
						return sol::make_object(sol(), sol::nil);
					switch(item.size)
					{
						case 1:
						default:
							ret = ((uint8_t *)item.base)[offset];
							break;
						case 2:
							ret = ((uint16_t *)item.base)[offset];
							break;
						case 4:
							ret = ((uint32_t *)item.base)[offset];
							break;
						case 8:
							ret = ((uint64_t *)item.base)[offset];
							break;
					}
                                        retfloat = (*(double *) &ret);                         // get the return value as a float
					return sol::make_object(sol(), retfloat);
				},	

			"read_block", [](save_item &item, int offset, sol::buffer *buff) {
					if(!item.base || ((offset + buff->get_len()) > (item.size * item.count)))
						buff->set_len(0);
					else
						memcpy(buff->get_ptr(), (uint8_t *)item.base + offset, buff->get_len());
					return buff;
				},
			"write", [](save_item &item, int offset, uint64_t value) {
					if(!item.base || (offset > item.count))
						return;
					switch(item.size)
					{
						case 1:
						default:
							((uint8_t *)item.base)[offset] = (uint8_t)value;
							break;
						case 2:
							((uint16_t *)item.base)[offset] = (uint16_t)value;
							break;
						case 4:
							((uint32_t *)item.base)[offset] = (uint32_t)value;
							break;
						case 8:
							((uint64_t *)item.base)[offset] = (uint64_t)value;
							break;
					}
				},
			"writeasdouble", [](save_item &item, int offset, double value) {
					if(!item.base || (offset > item.count))
						return;
					switch(item.size)
					{
						case 1:
						default:
							((uint8_t *)item.base)[offset] = (uint8_t)value;
							break;
						case 2:
							((uint16_t *)item.base)[offset] = (uint16_t)value;
							break;
						case 4:
							((uint32_t *)item.base)[offset] = (uint32_t)value;
							break;
						case 8:
							((double *)item.base)[offset] = value;        // write the double value
							break;
					}
				});




and I also made a new device method to return all of items in the item list: allitems

Why did I do that? Because the items in the apple2 state are inaccessible. I can see them in the Memory Window in the debugger, but not with lua.

If I execute this lua one-liner, my x and y calibration don't show up in the device list.

for devname,devdevice in pairs(manager:machine().devices) do print (devname,devdevice) for i,j in pairs(devdevice.items) do print(i,j) end end

But device.items[] iterates through the whole list, checking the devicetag to match, why not just make a variation called allitems that will just add them all.
So it you look below, it just has an if (1).

Code

/* machine.devices[device_tag]
 * device:name() - device long name
 * device:shortname() - device short name
 * device:tag() - device tree tag
 * device:owner() - device parent tag
 * device:debug() - debug interface, cpus only
 * device.spaces[] - device address spaces table
 * device.state[] - device state entries table
 * device.items[] - device save state items table (item name is key, item index is value)
 */

	sol().registry().new_usertype<device_t>("device", "new", sol::no_constructor,
			"name", &device_t::name,
			"shortname", &device_t::shortname,
			"tag", &device_t::tag,
			"owner", &device_t::owner,
			"debug", [this](device_t &dev) -> sol::object {
					if(!(dev.machine().debug_flags & DEBUG_FLAG_ENABLED) || !dynamic_cast<cpu_device *>(&dev)) // debugger not enabled or not cpu
						return sol::make_object(sol(), sol::nil);
					return sol::make_object(sol(), dev.debug());
				},
			"spaces", sol::property([this](device_t &dev) {
					device_memory_interface *memdev = dynamic_cast<device_memory_interface *>(&dev);
					sol::table sp_table = sol().create_table();
					if(!memdev)
						return sp_table;
					for(int sp = 0; sp < memdev->max_space_count(); ++sp)
					{
						if(memdev->has_space(sp))
							sp_table[memdev->space(sp).name()] = addr_space(memdev->space(sp), *memdev);
					}
					return sp_table;
				}),
			"state", sol::property([this](device_t &dev) {
					sol::table st_table = sol().create_table();
					if(!dynamic_cast<device_state_interface *>(&dev))
						return st_table;
					// XXX: refrain from exporting non-visible entries?
					for(auto &s : dev.state().state_entries())
						st_table[s->symbol()] = s.get();
					return st_table;
				}),
			"items", sol::property([this](device_t &dev) {
					sol::table table = sol().create_table();
					std::string tag = dev.tag();
					// 10000 is enough?
					for(int i = 0; i < 10000; i++)
					{
						std::string name;
						const char *item;
						unsigned int size, count;
						void *base;
						item = dev.machine().save().indexed_item(i, base, size, count);
						if(!item)
							break;
						name = &(strchr(item, '/')[1]);
						if(name.substr(0, name.find("/")) == tag)
						{
							name = name.substr(name.find("/") + 1, std::string::npos);
							table[name] = i;
						}
					}
					return table;
				}),

			"allitems", sol::property([this](device_t &dev) {
					sol::table table = sol().create_table();
					std::string tag = dev.tag();
					// 10000 is enough?
					for(int i = 0; i < 10000; i++)
					{
						std::string name;
						const char *item;
						unsigned int size, count;
						void *base;
						item = dev.machine().save().indexed_item(i, base, size, count);
						if(!item)
							break;
						name = &(strchr(item, '/')[1]);
					//if(name.substr(0, name.find("/")) == tag)
					if(1)
						{
							name = name.substr(name.find("/") + 1, std::string::npos);
							table[name] = i;
						}
					}
					return table;
				})

			);


so once that's done I can do this:

emu.item(manager:machine().devices[":maincpu"].allitems["0/m_y_calibration"]):writeasdouble(0,9800e-9)
emu.item(manager:machine().devices[":maincpu"].allitems["0/m_y_calibration"]):writeasdouble(0,9800e-9)


If you read it as an integer, it is nonsense.

print(emu.item(manager:machine().devices[":maincpu"].allitems["0/m_x_calibration"]):read(0))
4533201175231652948

You want to use my new function readasdouble:

print(emu.item(manager:machine().devices[":maincpu"].allitems["0/m_x_calibration"]):readasdouble(0))
1.2e-05


[MAME]> function printt(a) for i,j in pairs(a) do print(i,j) end end
[MAME]>
[MAME]> printt(manager:machine().devices[":maincpu"].allitems)
m_lastcoin 610
10/m_stored_vector 351
0/TMP 319
0/m_last_update_time.attoseconds 264
31/m_stored_vector 456
21/m_stored_vector 405
41/m_stored_vector 507
2E/m_curstate 442
1E/m_curstate 391
0/m_y_calibration 234
0/m_totalcycles 341
0/m_step_samples 308
... etc



Okay, so back to HERO:

Just trying some different values I can get the joystick to work properly and not drop the dynamite:


9800 nsec seems to work:

[MAME]> print(emu.item(manager:machine().devices[":maincpu"].allitems["0/m_x_calibration"]):writeasdouble(0,9800e-9))

[MAME]> print(emu.item(manager:machine().devices[":maincpu"].allitems["0/m_y_calibration"]):writeasdouble(0,9800e-9))


[MAME]> print(emu.item(manager:machine().devices[":maincpu"].allitems["0/m_x_calibration"]):readasdouble(0))
9.8e-06
[MAME]> print(emu.item(manager:machine().devices[":maincpu"].allitems["0/m_y_calibration"]):readasdouble(0))
9.8e-06


Actually, 10800 nsec works too (I forgot that I was using the old 12 msec values to start with)

print(emu.item(manager:machine().devices[":maincpu"].allitems["0/m_x_calibration"]):writeasdouble(0,10800e-9))
print(emu.item(manager:machine().devices[":maincpu"].allitems["0/m_y_calibration"]):writeasdouble(0,10800e-9))



Last edited by Golden Child; 02/17/19 04:01 AM.