Previous Thread
Next Thread
Print Thread
Page 27 of 39 1 2 25 26 27 28 29 38 39
Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: anoid] #114696
02/17/19 03:45 AM
02/17/19 03:45 AM
Joined: Feb 2014
Posts: 251
G
Golden Child Offline
Senior Member
Golden Child  Offline
Senior Member
G
Joined: Feb 2014
Posts: 251
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.
Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: Golden Child] #114697
02/17/19 04:11 AM
02/17/19 04:11 AM
Joined: Feb 2014
Posts: 251
G
Golden Child Offline
Senior Member
Golden Child  Offline
Senior Member
G
Joined: Feb 2014
Posts: 251
Horrible hack part #2 - finding the optimum value for the Apple IIGS and Stellar 7 on fast cpu mode.

I added the m_x_calibration and m_y_calibration to the save item list in the apple2gs.cpp driver.


So I located the joystick read routine for Stellar 7 by putting a watchpoint on C064 (analog paddle 0 read)

[Linked Image]

then I put some breakpoints on every RTS from the read joystick subroutine that would print out the joystick return values:

wp c064,1,r

bp 7ca1,1,{printf "x=%02x y=%02x",x,y;g}
bp 7cb2,1,{printf "x=%02x y=%02x",x,y;g}
bp 7cc3,1,{printf "x=%02x y=%02x",x,y;g}

wpdis 1

[Linked Image]


then I could fine-tune my joystick calibration values with some lua commands in real time:

print(emu.item(manager:machine().devices[":maincpu"].allitems["0/m_x_calibration"]):writeasdouble(0,2500e-9)) -- maximum is 3E

print(emu.item(manager:machine().devices[":maincpu"].allitems["0/m_x_calibration"]):writeasdouble(0,4800e-9)) -- maximum is 7e, half 3c

print(emu.item(manager:machine().devices[":maincpu"].allitems["0/m_x_calibration"]):writeasdouble(0,5150e-9)) -- maximum is 7F, half is 40
print(emu.item(manager:machine().devices[":maincpu"].allitems["0/m_y_calibration"]):writeasdouble(0,5150e-9))


So it looks like the "perfect" calibration for Stellar 7 running in fast mode is 5150 nsec.


Last edited by Golden Child; 02/17/19 04:12 AM.
Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01] #114698
02/17/19 05:03 AM
02/17/19 05:03 AM
Joined: Jul 2007
Posts: 30
Georgia, USA
anoid Offline
Member
anoid  Offline
Member
Joined: Jul 2007
Posts: 30
Georgia, USA
Golden Child,

Thanks for the information. I guess that the fix Arbee did earlier may actually fix the problem in HERO by changing to 10800 nsec.

I do remember manually centering the joysticks on the Apple II back in the day...

A-Noid

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: anoid] #114708
02/17/19 06:10 PM
02/17/19 06:10 PM
Joined: Feb 2014
Posts: 251
G
Golden Child Offline
Senior Member
Golden Child  Offline
Senior Member
G
Joined: Feb 2014
Posts: 251
Horrible hack part #3:

I wanted to see if I could create a function under the emu table that would give me all of the items:

Code
// New function emu["items"]

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


Now I can do this:

Code
print(emu.item(emu.items()["Apple //e/:/0/m_y_calibration"]):readasdouble(0))
1.3e-05


If I uncomment the //name = &(strchr(item, '/')[1]); it will strip off the leading part up to the first / but I kind of like having the full name. It also matches the names that show up in the Debug: Memory View.


function printt(a) for i,j in pairs(a) do print(i,j) end end
function printto(a) local b={} for i,j in pairs(a) do b[j]=i end printt(b) end

[MAME]> printto(emu.items())
1 5.25" single density floppy drive/:sl6:diskiing:0:525/0/m_clock
2 5.25" single density floppy drive/:sl6:diskiing:0:525/0/m_clock_scale
...
142 Apple //e/:/0/m_x_calibration
143 Apple //e/:/0/m_xirq
144 Apple //e/:/0/m_xy
145 Apple //e/:/0/m_y0
146 Apple //e/:/0/m_y0edge
147 Apple //e/:/0/m_y1
148 Apple //e/:/0/m_y_calibration
149 Apple //e/:/0/m_yirq
...
828 timer/sound_manager::update/0/m_start.attoseconds
829 timer/sound_manager::update/0/m_start.seconds

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: Golden Child] #114709
02/17/19 07:48 PM
02/17/19 07:48 PM
Joined: Feb 2014
Posts: 251
G
Golden Child Offline
Senior Member
Golden Child  Offline
Senior Member
G
Joined: Feb 2014
Posts: 251
More hacking on luaengine:

why not just directly get the item?

If I create this function (it's horribly inefficient but proof of concept:) I can just go ahead and get an item directly from a string:
Code
      emu["getitem"] = [this](const char* itemname){ 	sol::table table = sol().create_table();
					// 10000 is enough?
					int index = -1;
					save_item return_item;
					if (!(itemname == 0))					
					for(int i = 0; i < 10000; i++)
					{
						std::string name;
						const char *item;
						unsigned int size, count;
						void *base;
						item = machine().save().indexed_item(i, base, size, count);
						if(!item) break;
						//name = &(strchr(item, '/')[1]);
						name = item;
						table[name] = i;
                                                if (itemname == name) index = i;						
					}
				if (index == -1 || !machine().save().indexed_item(index, return_item.base, return_item.size, return_item.count))	
					{	return_item.base = nullptr;
						return_item.size = 0;
						return_item.count= 0;
					};
					return return_item;
				};



Code
[MAME]> print(emu.item(emu.items()["Apple //e/:/0/m_y_calibration"]):readasdouble(0))
1.3e-05
[MAME]> print(emu.getitem("Apple //e/:/0/m_y_calibration"):readasdouble(0))
1.3e-05
[MAME]> print(emu.getitem("Apple //e/:/0/m_x_calibration"):readasdouble(0))
1.2e-05
[MAME]> print(emu.getitem("Apple misspelled"):readasdouble(0))
nil
[MAME]> print(emu.getitem("doesnt exist"):readasdouble(0))
nil
[MAME]> print(emu.getitem():readasdouble(0))
nil



Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01] #114711
02/17/19 11:51 PM
02/17/19 11:51 PM
Joined: Jun 2014
Posts: 83
P
peter ferrie Offline
Member
peter ferrie  Offline
Member
P
Joined: Jun 2014
Posts: 83
It's funny about Joust. I never tested it in MAME, apparently.
I've known about Serpentine for ages. I thought that I submitted the fix for it, but clearly not.
A couple of other games had the same requirement.
I think that Pooyan and Lady Tut also rely on uninitialised memory, but the effects aren't detrimental.

Yes, Hero is very sensitive to the joystick calibration.

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01] #114712
02/18/19 12:12 AM
02/18/19 12:12 AM
Joined: Jul 2007
Posts: 30
Georgia, USA
anoid Offline
Member
anoid  Offline
Member
Joined: Jul 2007
Posts: 30
Georgia, USA
A couple more...

Congo Bongo (WOZ) won't boot in MAME, but the crack works from the software list.

I've noticed longer delays in Drol (WOZ) when loading the 3rd level (snakes) and winning cut scene after 3rd level. Levels 1 and 2 seem to have load times similar to cracked version.

A-Noid

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01] #114713
02/18/19 12:23 AM
02/18/19 12:23 AM
Joined: Mar 2001
Posts: 16,204
USA
R
R. Belmont Online content
Very Senior Member
R. Belmont  Online Content
Very Senior Member
R
Joined: Mar 2001
Posts: 16,204
USA
Regarding load times, originals oftentimes will take longer because they're doing a protection check instead of just loading the data.

Peter: does Congo Bongo use weak bits?

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01] #114714
02/18/19 12:25 AM
02/18/19 12:25 AM
Joined: Jun 2014
Posts: 83
P
peter ferrie Offline
Member
peter ferrie  Offline
Member
P
Joined: Jun 2014
Posts: 83
RB: yes, along with Bruce Lee and Mr. Do.

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01] #114715
02/18/19 12:30 AM
02/18/19 12:30 AM
Joined: Jun 2014
Posts: 83
P
peter ferrie Offline
Member
peter ferrie  Offline
Member
P
Joined: Jun 2014
Posts: 83
Regarding Drol, those two sections are huge compared to the other two, and the protection is alternating quarter-track, so it's very slow to load.
Try our Lode Runner crack vs the original for extreme speed difference! :-)

Page 27 of 39 1 2 25 26 27 28 29 38 39

Who's Online Now
3 registered members (R. Belmont, zillion, 1 invisible), 38 guests, and 3 spiders.
Key: Admin, Global Mod, Mod
Shout Box
Forum Statistics
Forums9
Topics8,653
Posts113,409
Members4,846
Most Online324
Dec 20th, 2018
Powered by UBB.threads™ PHP Forum Software 7.6.1.1
(Release build 20180111)
Page Time: 0.058s Queries: 14 (0.036s) Memory: 5.7515 MB (Peak: 5.9723 MB) Zlib enabled. Server Time: 2019-05-23 14:48:37 UTC