1 2 3
8 9
upthorn
He/Him
Emulator Coder, Active player (392)
Joined: 3/24/2006
Posts: 1802
DeHackEd wrote:
If you want to convert to negative, subtract 256 or 65536 from the number as appropriate for the data size.
But since the number is stored as 32 bits, for lua, wouldn't this result in numbers always being read as negative? EG: you get "1 - 256 = -255" rather than the "1 - 256 = 1" that you'd get with a char or signed char in C?
How fleeting are all human passions compared with the massive continuity of ducks.
Emulator Coder, Site Developer, Former player
Joined: 11/6/2004
Posts: 833
Okay then. I'll add it. memory.read{byte,word}signed will return a number in the range of -32768 to 32767 or -128 to 127 as the case may be. Added to the API.
Joined: 12/29/2006
Posts: 119
Location: Japan, Anjo
It quoted it from windef.h as follows.
typedef unsigned long       DWORD;
typedef int                 BOOL;
typedef unsigned char       BYTE;
typedef unsigned short      WORD;
typedef float               FLOAT;
typedef FLOAT               *PFLOAT;
typedef BOOL near           *PBOOL;
typedef BOOL far            *LPBOOL;
typedef BYTE near           *PBYTE;
typedef BYTE far            *LPBYTE;
typedef int near            *PINT;
typedef int far             *LPINT;
typedef WORD near           *PWORD;
typedef WORD far            *LPWORD;
typedef long far            *LPLONG;
typedef DWORD near          *PDWORD;
typedef DWORD far           *LPDWORD;
typedef void far            *LPVOID;
typedef CONST void far      *LPCVOID;
DiffCalc .NET Frameworks 3.5 required.
Emulator Coder, Site Developer, Former player
Joined: 11/6/2004
Posts: 833
Naohiro19 wrote:
It quoted it from windef.h as follows.
<omit reason="brevity" />
?? Huh?
Post subject: Super Idiot World
Joined: 10/3/2005
Posts: 1332
Just when I thought this Lua thing couldn't get more awesome, I realized it could be used for botting, and created a rudimentary bot script for SMW. How it works is, it runs to the right while holding Y, and randomly presses B. Brilliant, isn't it? Here's a movie of it in action... sort of. I had to help it a lot with the savestates, because it does not yet know how to avoid getting caught in an infinite death loop. Linky Here's the general outline of what I'm planning:
local buttons = { Y = 1, right = 1 }
local sol = savestate.create(5)
savestate.save(sol)

--start movie recording to random filename, set speed to maximum
while true do
    joypad.set(1, buttons)

    --if mario dies, reload.
    if (memory.readbyte(0x7e0071)) == 9 then
        savestate.load(sol)
        --compare input to previous inputs, dump results into a buttons table
    end

    --TODO: pseudo-randomize input, weighted according to previous attempts
    --but for now, just jump up and down like an idiot
    resetbuttons = math.random(0,20)
    if resetbuttons == 1 then
        buttons.B = math.random(0,2)
        if buttons.B == 0 then buttons.B = nil end
    end

    --incrementally save every N frames
    --detect instant death
    --detect end of level, drop out of warp
    snes9x.frameadvance();
end
I think it has potential. More ideas, anyone?
DeHackEd wrote:
Anything else requested?
It would be nice (if not incredibly handy) if movies could be handled as objects, the way savestates are- particularly with regards to the creation of temporary files. Edit: Also, I couldn't get savestate.create() to work without passing an integer. Bah. It sorted itself out. Nevermind. Sorry for the edits, IRC. ;)
Post subject: LUA bot scripting
Player (105)
Joined: 1/30/2005
Posts: 564
Location: Québec, Canada
Dromiceius wrote:
I realized it could be used for botting
You mean, like this? Uniracers Stunts & Jump Optimizer v13 (file too big to be pasted in a code block) This bot produces frame-perfect input to create the most elaborate stunt possible for a given jump (for the game Uniracers, obviously). You set the emulator before a jump, and run the LUA script. The bot will then intelligently attempt different stunt combos and optimize for speed, and when it's done, it replays the best stunt it could find, and if you happened to be recording, it records it for you! DeHackEd: I think this bot is a good example of an alternate usage of lua scripting that isn't just for gui displays. You might want to take an in-depth look at this ;) EDIT: Forgot to add, this bot is best watched holding down Frame Advance. It optimizes in 10s of seconds what takes a human hours. If you don't watch it in Frame Advance, you might miss all the action as it happens too fast.
Active player (356)
Joined: 1/16/2008
Posts: 358
Location: The Netherlands
Dromiceius wrote:
Just when I thought this Lua thing couldn't get more awesome, I realized it could be used for botting, and created a rudimentary bot script for SMW. How it works is, it runs to the right while holding Y, and randomly presses B. Brilliant, isn't it?
looks very nice to me tbh, you plan to expand it? :) would be great to see a more general version (e.g. one that does not assume that holding right+Y is best, and one that might start flying? :D) I tried something similar for Mr. Nutz using several different approaches but failed miserably :P (it'd only get to about 30% of the (by my knowledge) best possible) @Halamantariel, very nice script :D perhaps using more savestates a tree-search would result in a major speedup for scripts like that? (default backtracking)
TASes: [URL=http://tasvideos.org/Movies-298up-Obs.html]Mr. Nutz (SNES), Young Merlin 100% (SNES), Animaniacs 100% (SNES)[/URL]
Joined: 10/3/2005
Posts: 1332
DaTeL237 wrote:
looks very nice to me tbh, you plan to expand it? :) would be great to see a more general version (e.g. one that does not assume that holding right+Y is best, and one that might start flying? :D)
Yeah, definitely. Hal's ridiculously awesome script has blown my mind and inspired me to brute force the hell out of 7th Saga, so I'm somewhat diverted, though. The inputs will become more random in the next version. It might also be cool to use hard-coded input sets to affect flying and certain glitches from the TASes, but I expect that it will be stuck as a dodo, considering the unlikelihood of Mario grabbing a feather. ;)
Active player (356)
Joined: 1/16/2008
Posts: 358
Location: The Netherlands
Dromiceius wrote:
The inputs will become more random in the next version. It might also be cool to use hard-coded input sets to affect flying and certain glitches from the TASes, but I expect that it will be stuck as a dodo, considering the unlikelihood of Mario grabbing a feather. ;)
perhaps writing an evaluation/utility function that is as general as possible would improve the bot (and then just go for a greedy approach) it could incorporate anything from having a feather, being in flight, being in the water, or level-specific stuff such as 'having gone through pipe X' etc etc) all these ideas .. ;)
TASes: [URL=http://tasvideos.org/Movies-298up-Obs.html]Mr. Nutz (SNES), Young Merlin 100% (SNES), Animaniacs 100% (SNES)[/URL]
Post subject: Re: Super Idiot World
Joined: 10/24/2005
Posts: 1080
Location: San Jose
Dromiceius wrote:
Just when I thought this Lua thing couldn't get more awesome, I realized it could be used for botting,
Reminds me of when I created this topic? I've fiddled with smw bots this LUA scripting, mainly for determining fadeout lag (pseudo code here)
while(score < MAX_SCORE){
score = 0; 
save state 1 frame before the gate; 
poke score with desired score;  
when lagging increment a lag counter; //hard part
stop incrementing lag counter;//stop time not important as long as all lag is recorded
file I/O;
score++; 
load state
}
It's touch-and-go for me to say the least, but the only thing stopping it from working perfectly were finding out how to correctly determine what a lag frame was, and make sure that the amount of lag does correspond with a "poked" score. Also, I haven't touched my work in a while, because work has been draining my time. Also, leaving this bot on overnight when before I realized there used to be a memory leak wasn't fun.
<agill> banana banana banana terracotta pie! <Shinryuu> ho-la terracotta barba-ra anal-o~
Emulator Coder, Site Developer, Former player
Joined: 11/6/2004
Posts: 833
Sorry about the long delay.
  • Source code. Windows users are encouraged to build using Makefile.mingw because you're on your own any other way. Linux users should build as usual. Some assembly required.
  • The memory.register function is finally written!
  • gui code expanded. You might want to look into this one.
  • Binary functions added For Your Convenience (tm)
  • If you accidentally send a script running unchecked, you will be prompted to kill it.
  • The signed version of the memory functions now exist
  • Windows EXE will load external libs now. As a side effect, there's now a lua51.dll pulled out of the main EXE because it's needed.
I think that covers it. Version 0.04 windows EXE Edit: EXE replaced with a fixed version. Lua DLL will cause a crash otherwise. I previously fixed this bug, then zipped up the wrong EXE. Stupid me.
Post subject: Re: LUA bot scripting
Emulator Coder, Site Developer, Former player
Joined: 11/6/2004
Posts: 833
Halamantariel wrote:
DeHackEd: I think this bot is a good example of an alternate usage of lua scripting that isn't just for gui displays. You might want to take an in-depth look at this ;)
Umm.. I DID kinda plan for that possibility. That's why you have the savestate engine at your disposal and the ability to push your own buttons. The GUI didn't come until the third release.
gocha
Any
Emulator Coder, Former player
Joined: 6/21/2006
Posts: 401
Location: Japan, Nagoya
improvement 11 + lua 0.04 = improvement 12 (beta) Changes: - "Text in image" now works for lua. - Fixed a crash problem in S9xLuaWriteInform.
getset.h.orig wrote:
	if (!(address >= 0x7e0000 && address <= 0x7fffff))
		return;

	// These might be better using binary arithmatic -- a shift and an AND
	int slot = address / 8;
	int bits = address % 8;

	extern unsigned char lua_watch_bitfield[16384];

	// Check the slot
	if (lua_watch_bitfield[slot] & (1 << bits))
		S9xLuaWrite(address);
I am usually available on Discord server or Twitter.
Post subject: Re: Super Idiot World
Joined: 10/3/2005
Posts: 1332
DK64_MASTER wrote:
Reminds me of when I created this topic?
Kind of. I did want to make a "learning program" that didn't need heuristics, but heuristics and randomization is all I've used so far. Now it's stuck at the start of Yoshi's Island 3 because I've not been able to explain that "you're just running back and forth, not getting anywhere! Try walking slowly and jumping more." Methinks it's time Mario became acquainted with his own X/Y coords and a little modal logic...
It's touch-and-go for me to say the least, but the only thing stopping it from working perfectly were finding out how to correctly determine what a lag frame was, and make sure that the amount of lag does correspond with a "poked" score.
Wouldn't the overall frame count be adequate? I guess it's one thing if you want to figure out how it works, but for the purposes of TASing, I wouldn't think it really matters. Unrelated note: v0.04 is crashing whenever I load a ROM. I'm just going to assume the problem is my system, until someone else reports the same problem.
Post subject: Re: Super Idiot World
gocha
Any
Emulator Coder, Former player
Joined: 6/21/2006
Posts: 401
Location: Japan, Nagoya
Dromiceius wrote:
v0.04 is crashing whenever I load a ROM. I'm just going to assume the problem is my system, until someone else reports the same problem.
Doesn't improvement 12 beta fix the problem? By the way, I noticed that the link for 0.04 (in first post of the topic) is actually linked to 0.02.
I am usually available on Discord server or Twitter.
Joined: 10/3/2005
Posts: 1332
Doesn't improvement 12 beta fix the problem?
Why, yes it does! :D Thanks, Gocha.
Emulator Coder, Site Developer, Former player
Joined: 11/6/2004
Posts: 833
To gocha: I knew I forgot something about 0x7e0000... I just couldn't remember what... ugh, I do that kind of thing a LOT To Dromiceius: I accidentally zipped up the wrong EXE when making the 7z. It was replaced with a fixed one. Something went wrong in a recompile of the EXE. Just redownload. Or use improvement 12...
Player (199)
Joined: 12/3/2006
Posts: 151
I must say the new features look really nice, but I'm a bit lost on how to use the memory.register function. When I use the following code:
function func(address)
	snes9x.message("Written: "..address)
end

memory.register(0x7E0521,func(0x7E0521))

while true do
	snes9x.frameadvance()
end
I get an error about the second argument not being a function or nil. The same thing happens when I put the memory.register function inside the while loop. EDIT: I know this function is kind of silly since it shows the address in decimals, but that shouldn't matter. ;)
Active player (356)
Joined: 1/16/2008
Posts: 358
Location: The Netherlands
myFunction = function(address)
	snes9x.message("Written: "..address)
end

memory.register(0x7E0521,myFunction)

while true do
	snes9x.frameadvance()
end
I think this' the way to do it (functions are varaiables too) edited
TASes: [URL=http://tasvideos.org/Movies-298up-Obs.html]Mr. Nutz (SNES), Young Merlin 100% (SNES), Animaniacs 100% (SNES)[/URL]
Emulator Coder, Site Developer, Former player
Joined: 11/6/2004
Posts: 833
While Datel's style of writing function bodies is no different (lua silently rewrites gunty's code to look identical to Datel's during compilation), there's a two problems to be addressed as well. The first is the change to the actual memory.register line. You want to give the function by name, not by actually calling it, which is what you do. The second regards the parameters the function itself gets. No parameter is given to the called function. Lua fills in the name you given with nil to compensate. It may sound stupid, but it's sorta built on the assumption that you'd use a different function for each memory address. Alternatively, you can use upvalues...
-- a "do/end" is a block of scope, just like within a function, while loop, or other indented code block.
do
  local addr = 0x7e0101
  local function registered()
    snes9x.message("Written: "..addr)
  end
  memory.register(addr, registered)
end
Even though "addr" falls out of scope, the function "registered" can still access it, and get its value from there. Every time the flow of code would execute a function() block, a function is actually created out of the local variables in place at the time.

-- We construct 3 "functions" (technically call closures) with identical code,
-- but different upvalues for "addr" in each one. So while it's technically 
-- one function, we can give the illusion that it knows some magic value
-- for its specific invocation
addresses = { 0x7e0001, 0x7e0002, 0x7e0003} -- Just go with it
for key,value in pairs(addresses) do

  -- We need a distinct local for each function
  local addr = value
  local function registered()
     ... -- Use "addr" in here somewhere
  end
  memory.register(addr, registered)
end
... Or should I just add it anyways?
Player (199)
Joined: 12/3/2006
Posts: 151
I don't think it's necessary to add arguments to the registered functions, I only wrote this (useless) function as an example. However, when using the (edited) code DaTeL237 posted, I'm getting an error about attempting to index a nil value. Even when removing all arguments like this:
myFunction = function()
   snes9x.message("Written: 7E0521")
end

memory.register(0x7E0521,myFunction)

while true do
   snes9x.frameadvance()
end
Emulator Coder, Site Developer, Former player
Joined: 11/6/2004
Posts: 833
Thanks for the new code. I've tracked it down to a bug in my own code. It's crashing in memory.register itself, isn't it.... I can fix this in a matter of minutes. While I'm at it, is there any suggestion for features that should be added? I have a few minor additions to gui to allow for pop-ups to the user and stuff.... good idea?
Player (199)
Joined: 12/3/2006
Posts: 151
I'm not sure if this is possible yet, but it might be nice if there's a way to make the emulator pause without having to stop the script or use the "memory.register" function. Something simple like snes9x.pause() or snes9x.speedmode("pause").
Emulator Coder, Site Developer, Former player
Joined: 11/6/2004
Posts: 833
Done. Anything else? (check around and you'll see what else I've added)
Emulator Coder, Site Developer, Former player
Joined: 11/6/2004
Posts: 833
Version 0.05 has escaped. The source code was horribly mangled but managed to drag itself to safety.
  • memory.register works for real now. I tried it. I spent an hour or two figuring out how snes9x's memory maps work before giving up and cheating.
  • New gui code, including a user popup option. Even works under linux if you install xmessage
  • More binary manipulation functions
  • snes9x.pause() will pause the emulator (and the script) until the user unpauses
More later.
1 2 3
8 9