cheat lua plugins
- Pugsy
- Posts: 3686
- Joined: Fri Aug 17, 2001 12:59 am
- Location: North Wales, UK.
- Has thanked: 1 time
- Been thanked: 19 times
- Contact:
Re: cheat lua plugins
Hi crazyc
I've had a request from someone who wants to make some cheats for the PC Engine CD swlist games.
There seems to be an issue with loading any cheats from xml or cheat.simple for specific games.
As a straightforward example it's possible to make this cheat with the cheatfind plugin and save it to cheat.simple.
pce/fraycd,:maincpu,105785,b,8,Infinite Energy
But it will not load it back in.
I don't know if this issue is possible to fix without some major changes...
Unsurprisingly, it doesn't work in the non-plugin cheat engine either.
Tafoid has mentioned this in the past that when there are devices on other machines which "play" other cartridges through a slotted or installed device (psu has a "gamebooster" which is gameboy/gameboy color player) the cheats don't load. So I guess this is similar.
Basically I'm asking is making PCE CD cheats on MAME a non-starter?
I've had a request from someone who wants to make some cheats for the PC Engine CD swlist games.
There seems to be an issue with loading any cheats from xml or cheat.simple for specific games.
As a straightforward example it's possible to make this cheat with the cheatfind plugin and save it to cheat.simple.
pce/fraycd,:maincpu,105785,b,8,Infinite Energy
But it will not load it back in.
I don't know if this issue is possible to fix without some major changes...
Unsurprisingly, it doesn't work in the non-plugin cheat engine either.
Tafoid has mentioned this in the past that when there are devices on other machines which "play" other cartridges through a slotted or installed device (psu has a "gamebooster" which is gameboy/gameboy color player) the cheats don't load. So I guess this is similar.
Basically I'm asking is making PCE CD cheats on MAME a non-starter?
Pugsy
Servicing your cheating needs since 1985
Grab the latest cheat collection:
MAME 0.264 XML cheat collection (3 APRIL 2024) from http://www.mamecheat.co.uk or direct from:-
https://mega.nz/file/SxsQUJoT#jBdz6GLm_ ... QzFGSMms2c (ZIP Archive 3.8 MB)
Servicing your cheating needs since 1985

Grab the latest cheat collection:
MAME 0.264 XML cheat collection (3 APRIL 2024) from http://www.mamecheat.co.uk or direct from:-
https://mega.nz/file/SxsQUJoT#jBdz6GLm_ ... QzFGSMms2c (ZIP Archive 3.8 MB)
Re: cheat lua plugins
What do you mean it won't load back in? What does it do when you try to use it?
- Pugsy
- Posts: 3686
- Joined: Fri Aug 17, 2001 12:59 am
- Location: North Wales, UK.
- Has thanked: 1 time
- Been thanked: 19 times
- Contact:
Re: cheat lua plugins
Put this in cheat.simple:-
On the commandline:
mame pce bombman <-- the above cheat for bombman appears in the plugin cheat menu
mame pce fraycd <-- the above cheat for fraycd doesnt appear in the plugin cheat menu
This issue is not specific to the plugin cheat engine or to cheat.simple. It's the same issue with the standard cheat engine - I think it's maybe to do with the fact the pce_cd is a subsystem of pce.
so
"mame pce fraycd" == "mame pce -cart pce_cd fraycd"
if I place this in cheat.simple:
Then the cheat for fraycd appears, but obviously when there are 489 swlist CD games for the PCE this would lead to an enormous cheat menu to navigate through for the user.
Code: Select all
pce/fraycd,:maincpu,105785,b,6,Infinite Lives DOESNT LOAD
pce/bombman,:maincpu,1F0D8E,b,39,Infinite Time LOADS FINE
mame pce bombman <-- the above cheat for bombman appears in the plugin cheat menu
mame pce fraycd <-- the above cheat for fraycd doesnt appear in the plugin cheat menu
This issue is not specific to the plugin cheat engine or to cheat.simple. It's the same issue with the standard cheat engine - I think it's maybe to do with the fact the pce_cd is a subsystem of pce.
so
"mame pce fraycd" == "mame pce -cart pce_cd fraycd"
if I place this in cheat.simple:
Code: Select all
pce/scdsys,:maincpu,105785,b,6,Infinite Lives SCDSYS FRAYCD
Pugsy
Servicing your cheating needs since 1985
Grab the latest cheat collection:
MAME 0.264 XML cheat collection (3 APRIL 2024) from http://www.mamecheat.co.uk or direct from:-
https://mega.nz/file/SxsQUJoT#jBdz6GLm_ ... QzFGSMms2c (ZIP Archive 3.8 MB)
Servicing your cheating needs since 1985

Grab the latest cheat collection:
MAME 0.264 XML cheat collection (3 APRIL 2024) from http://www.mamecheat.co.uk or direct from:-
https://mega.nz/file/SxsQUJoT#jBdz6GLm_ ... QzFGSMms2c (ZIP Archive 3.8 MB)
Re: cheat lua plugins
Does it work if you put pce_cd/fraycd instead?
If it doesn't try that with this patch:
If it doesn't try that with this patch:
Code: Select all
diff --git a/plugins/cheat/init.lua b/plugins/cheat/init.lua
index 896fc1e101b..bc581b42b35 100644
--- a/plugins/cheat/init.lua
+++ b/plugins/cheat/init.lua
@@ -92,17 +92,21 @@ function cheat.startplugin()
local inputs = {}
local function load_cheats()
- local filename = emu.romname()
+ local filenames = {}
local newcheats = {}
local file = emu.file(manager.machine.options.entries.cheatpath:value():gsub("([^;]+)", "%1;%1/cheat") , 1)
for name, image in pairs(manager.machine.images) do
if image.exists and image.software_list_name ~= "" then
- filename = image.software_list_name .. "/" .. image.filename
+ filenames[#filenames + 1] = image.software_list_name .. "/" .. image.filename
end
end
- cheatname = filename
+ if #filenames == 0 then
+ filenames = { emu.romname() }
+ end
+
+ cheatname = filenames[1]
local function add(addcheats)
if not next(newcheats) then
newcheats = addcheats
@@ -112,15 +116,17 @@ function cheat.startplugin()
end
end
end
- for scrfile in lfs.dir(cheat.path) do
- local name = string.match(scrfile, "^(cheat_.*).lua$")
- if name then
- local conv = require("cheat/" .. name)
- if conv then
- local ret = file:open(conv.filename(filename))
- while not ret do
- add(conv.conv_cheat(file:read(file:size())))
- ret = file:open_next()
+ for num, filename in pairs(filenames) do
+ for scrfile in lfs.dir(cheat.path) do
+ local name = string.match(scrfile, "^(cheat_.*).lua$")
+ if name then
+ local conv = require("cheat/" .. name)
+ if conv then
+ local ret = file:open(conv.filename(filename))
+ while not ret do
+ add(conv.conv_cheat(file:read(file:size())))
+ ret = file:open_next()
+ end
end
end
end
Re: cheat lua plugins
Happy new year 2023.
I want to insert memory region at boot. For example galaga, address $4000-$4fff in maincpu is unmapped so that I desire to replace with RAM region without source change.
Is it possible via LUA script? If so, please tell me sample code. If not, is it possible to implement?
I want to insert memory region at boot. For example galaga, address $4000-$4fff in maincpu is unmapped so that I desire to replace with RAM region without source change.
Is it possible via LUA script? If so, please tell me sample code. If not, is it possible to implement?
Re: cheat lua plugins
What are you trying to do? That's beyond the scope of cheats but luaengine supports adding taps which can allow you to get a callback when a memory region is accessed.
Re: cheat lua plugins
Thanks reply.
For example, andromed...
$2fe9 - $2fff in ROM seem to be "unused" memory because it is filled with 0x00. Therefore, I embed "bullet speed" routine in this area.
But rest of "unused" memory is between $2ffa - $2fff (6-bytes).
It's not enough to embed other routines and I can't find enough memory area in ROM region.
So I want to use $3000 - $3fff because of unmapped.
I know that I can insert address map "map(0x3000, 0x3fff).rom()" in irem/m10.cpp then recompile it to use this "unmapped" region as ROM.
My question is that this is enable via LUA script without source change too?
I'm trying embeding the "game" program routine into "unused" memory area via cheat.crazyc wrote:What are you trying to do? That's beyond the scope of cheats but luaengine supports adding taps which can allow you to get a callback when a memory region is accessed.
For example, andromed...
Code: Select all
2FA0: 05 07 07 09 A2 04 A5 43 4A 90 02 A2 06 20 D0 12 .......CJ.... ..
2FB0: A6 07 60 A0 E0 A2 00 E8 D0 FD C8 D0 FA 60 A0 3B ..`..........`.;
2FC0: A9 00 99 60 51 88 10 FA 60 20 B1 2E AD 00 A3 60 ...`Q...` .....`
2FD0: 20 5E 15 4C 39 19 30 EA E0 30 D0 E6 C6 91 A5 91 ^.L9.0..0......
2FE0: C9 30 B0 04 A9 CF 85 91 60 00 00 00 00 00 00 00 .0......`.......
2FF0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
Code: Select all
<cheat desc="bullet speed">
<parameter min="0x01" max="0x05" step="0x01" />
<script state="on">
<action>maincpu.mb@272a = 2f</action>
<action>maincpu.mb@274a = e8</action>
<action>maincpu.mq@2fe9 = a8682b00204800a9</action>
<action>maincpu.mq@2ff1 = f2d0988804f07aa5</action>
<action>maincpu.mq@2ff9 = 0000000000000060</action>
<!--
2fe9 | a9 xx : lda #$xx
2feb | 48 : pha
2fec | 20 00 2b : jsr $2b00
2fef | 68 : pla
2ff0 | a8 : tay
2ff1 | a5 7a : lda $7a
2ff3 | f0 04 : beq $2ff9
2ff5 | 88 : dey
2ff6 | 98 : tya
2ff7 | d0 f2 : bne $2feb
2ff9 | 60 : rts
-->
</script>
<script state="change">
<action>maincpu.mb@2fea = param</action>
</script>
<script state="off">
<action>maincpu.mb@272a = 2a</action>
<action>maincpu.mb@274a = ff</action>
<action>maincpu.mq@2fe9 = 0000000000000000</action>
<action>maincpu.mq@2ff1 = 0000000000000000</action>
<action>maincpu.mq@2ff9 = 0000000000000000</action>
</script>
</cheat>
It's not enough to embed other routines and I can't find enough memory area in ROM region.
So I want to use $3000 - $3fff because of unmapped.
I know that I can insert address map "map(0x3000, 0x3fff).rom()" in irem/m10.cpp then recompile it to use this "unmapped" region as ROM.
Code: Select all
void m10_state::m10_main(address_map &map)
{
map(0x0000, 0x02ff).ram(); // scratch ram
map(0x1000, 0x2fff).rom();
[b][i] map(0x3000, 0x3fff).rom(); <-- add new[/i][/b]
map(0x4000, 0x43ff).ram().share(m_videoram);
map(0x4800, 0x4bff).ram().w(FUNC(m10_state::colorram_w)).share(m_colorram); // foreground colour
map(0x5000, 0x53ff).ram().w(FUNC(m10_state::chargen_w)).share(m_chargen); // background ?????
map(0xa200, 0xa200).portr("DSW");
map(0xa300, 0xa300).portr("INPUTS");
map(0xa400, 0xa400).w(FUNC(m10_state::m10_ctrl_w)); // line at bottom of screen?, sound, flip screen
map(0xa500, 0xa500).w(FUNC(m10_state::m10_a500_w)); // ???
map(0xa700, 0xa700).r(FUNC(m10_state::clear_74123_r));
map(0xfc00, 0xffff).rom(); // for the reset / interrupt vectors
}
Re: cheat lua plugins
I try installing handler via "install_read_tap" in LUA console but it causes crash...
Code: Select all
Currently targeting btime (Burger Time (Data East set 1))
[MAME]> function foo()
[MAME]>> print("test")
[MAME]>> end
[MAME]> manager.machine.devices[":maincpu"].spaces["program"].install_read_tap(0x2000,0x2fff,"test",foo())
test
-----------------------------------------------------
Exception at EIP=00007ff79bedbfb3 (sol::function_detail::upvalue_free_function<std::unique_ptr<lua_engine::tap_helper, std::default_delete<lua_engine::tap_helper> > (*)(lua_engine::addr_space&, unsigned int, unsigned int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&, sol::basic_protected_function<sol::basic_reference<false>, false, sol::basic_reference<false> >&&), false>::real_call(lua_State*)+0x0053): ACCESS VIOLATION
While attempting to read memory at 0000000000000000
-----------------------------------------------------
RAX=0000000000000000 RBX=00000152adcccc18 RCX=0000000000000000 RDX=0000000000000000
RSI=00000152ae0e31b0 RDI=00007ff799284c80 RBP=0000001376df8b60 RSP=0000001376df8ad0
R8=00000152b60f1b40 R9=0000000000000002 R10=0000000000000000 R11=0000000000000246
R12=0000000000000000 R13=00007ff79bedbe20 R14=00007ff7a2173508 R15=0000000000000000
-----------------------------------------------------
Stack crawl:
0000001376df8b10: 00007ff79bedbfb3 (sol::function_detail::upvalue_free_function<std::unique_ptr<lua_engine::tap_helper, std::default_delete<lua_engine::tap_helper> > (*)(lua_engine::addr_space&, unsigned int, unsigned int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&, sol::basic_protected_function<sol::basic_reference<false>, false, sol::basic_reference<false> >&&), false>::real_call(lua_State*)+0x0053)
0000001376df8c00: 00007ff79bedbe35 (sol::function_detail::upvalue_free_function<std::unique_ptr<lua_engine::tap_helper, std::default_delete<lua_engine::tap_helper> > (*)(lua_engine::addr_space&, unsigned int, unsigned int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&, sol::basic_protected_function<sol::basic_reference<false>, false, sol::basic_reference<false> >&&), false>::call(lua_State*)+0x0015)
0000001376df8c80: 00007ff799398880 (luaD_precall+0x0340)
0000001376df8d80: 00007ff7993b1bd3 (luaV_execute+0x0383)
0000001376df8dc0: 00007ff799398be8 (luaD_callnoyield+0x0088)
0000001376df8df0: 00007ff79938f5b7 (f_call+0x0017)
0000001376df8f50: 00007ff799397a30 (luaD_rawrunprotected+0x0060)
0000001376df8fc0: 00007ff799399066 (luaD_pcall+0x0046)
0000001376df9030: 00007ff7993926e5 (lua_pcallk+0x0085)
0000001376df9080: 00007ff7993b5109 (luaB_pcall+0x0069)
0000001376df9100: 00007ff799398880 (luaD_precall+0x0340)
0000001376df9200: 00007ff7993b1bd3 (luaV_execute+0x0383)
0000001376df9240: 00007ff799398be8 (luaD_callnoyield+0x0088)
0000001376df9270: 00007ff79938f5b7 (f_call+0x0017)
0000001376df93d0: 00007ff799397a30 (luaD_rawrunprotected+0x0060)
0000001376df9440: 00007ff799399066 (luaD_pcall+0x0046)
0000001376df94b0: 00007ff7993926e5 (lua_pcallk+0x0085)
0000001376df9520: 00007ff799187ffb (sol::protected_function_result sol::basic_protected_function<sol::basic_reference<false>, false, sol::basic_reference<false> >::invoke<false>(sol::types<>, std::integer_sequence<unsigned long long>, long long, sol::detail::protected_handler<false, sol::basic_reference<false> >&) const [clone .isra.0]+0x005b)
0000001376df9720: 00007ff79918ba88 (unsigned long long lua_engine::enumerate_functions<lua_engine::execute_function(char const*)::{lambda(sol::basic_protected_function<sol::basic_reference<false>, false, sol::basic_reference<false> > const&)#1}>(char const*, lua_engine::execute_function(char const*)::{lambda(sol::basic_protected_function<sol::basic_reference<false>, false, sol::basic_reference<false> > const&)#1}&&) [clone .isra.0]+0x0638)
0000001376df9750: 00007ff79918be04 (lua_engine::on_periodic()+0x0014)
0000001376df9780: 00007ff79908e908 (emulator_info::periodic_check()+0x0018)
0000001376df9820: 00007ff79872eb63 (video_manager::frame_update(bool)+0x0183)
0000001376df9890: 00007ff7986eb0aa (screen_device::vblank_begin(int)+0x022a)
0000001376df9900: 00007ff7986e5941 (device_scheduler::timeslice()+0x0151)
0000001376df9a90: 00007ff798693e18 (running_machine::run(bool)+0x0198)
0000001376dfef20: 00007ff799093a84 (mame_machine_manager::execute()+0x0224)
0000001376dff310: 00007ff7991259ff (cli_frontend::start_execution(mame_machine_manager*, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&)+0x039f)
0000001376dff620: 00007ff799125fbb (cli_frontend::execute(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&)+0x007b)
0000001376dff680: 00007ff79908e88c (emulator_info::start_frontend(emu_options&, osd_interface&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&)+0x002c)
0000001376dffa60: 00007ff79e5056a5 (main+0x0185)
0000001376dffab0: 00007ff7925b12ee (__tmainCRTStartup+0x016e)
0000001376dffae0: 00007ff7925b1406 (mainCRTStartup+0x0016)
0000001376dffb10: 00007ff9b4c555a0 (BaseThreadInitThunk+0x0010)
0000001376dffb90: 00007ff9b620485b (RtlUserThreadStart+0x002b)
Re: cheat lua plugins
> [MAME]> manager.machine.devices[":maincpu"].spaces["program"].install_read_tap(0x2000,0x2fff,"test",foo())
foo() is calls foo and install_read_tap gets the return value from foo() (nil) as the tap callback function.
foo() is calls foo and install_read_tap gets the return value from foo() (nil) as the tap callback function.
Re: cheat lua plugins
I understand. Test script works after I change "foo()" to "foo".crazyc wrote: foo() is calls foo and install_read_tap gets the return value from foo() (nil) as the tap callback function.
Anyway I create simple "andromed.lua" to use "unmapped" memory region ($0x3000 - $0x3fff).
Code: Select all
if manager.machine.time.is_zero then
memory = {}
function read(offset)
return memory[offset]
end
function write(offset, value)
memory[offset] = value
end
space = manager.machine.devices[":maincpu"].spaces["program"]
space:install_read_tap(0x3000,0x3fff,"read",read)
space:install_write_tap(0x3000,0x3fff,"write",write)
end
...But I'm faced with a problem. "install_read/write_tap()" has lifetime? it revert to normal after a few seconds.
1. start the game with "mame andromed -autoboot_script andromed.lua"
2. confirm installed handler with "map" command in the debugger
3. hold "insert" key for 5 seconds.
4. confirm again

read/write handler is missing...
Re: cheat lua plugins
Anyway, I try to create "memoryinstall" plug-in based on "cheat.simple" but I'm faced with crash problem.
init.lua
"emu.romname()" causes MAME crash though. Why?
init.lua
Code: Select all
local exports = {
name = 'memoryinstall',
version = '0.0.1',
description = 'test',
license = '',
author = { name = 'jman' } }
local meminst = exports
function meminst.startplugin()
local target = emu.romname()
local file = io.open("memoryinstall.map", "r")
for line in file:lines() do
local set, cputag, space, addrstart, addrend = line:match('([^,]+),([^,]+),([^,]+),([^,]+),([^,]+)')
end
file:close()
end
return exports
Re: cheat lua plugins
A plugin starts before anything is loaded. You need to use register_start to get a callback once the emulation starts.
Re: cheat lua plugins
Thanks advice. I finish simple (and no error check) "memoryinstall" code.
init.lua
memoryinstall.map
...But I'm faced with the same problem (handler lifetime). How to install handler "permanently"?
init.lua
Code: Select all
local exports = {
name = 'memoryinstall',
version = '0.0.1',
description = 'test',
license = '',
author = { name = 'jman' } }
local meminst = exports
function meminst.startplugin()
local memory = {}
local function read_memory(offset)
return memory[offset]
end
local function write_memory(offset, value)
memory[offset] = value
end
emu.register_start(function()
local target = emu.romname()
local file = io.open("memoryinstall.map", "r")
for line in file:lines() do
local set, cputag, space, addrstart, addrend = line:match('([^,]+),([^,]+),([^,]+),([^,]+),([^,]+)')
if set == target then
space = manager.machine.devices[cputag].spaces[space]
space:install_read_tap(addrstart,addrend,"read",read_memory)
space:install_write_tap(addrstart,addrend,"write",write_memory)
end
end
file:close()
end)
end
return exports
Code: Select all
andromed,:maincpu,program,0x3000,0x3fff
galaga,:maincpu,program,0x4000,0x4fff
Re: cheat lua plugins
Solved!
change
to
change
Code: Select all
space:install_read_tap(addrstart,addrend,"read",read_memory)
space:install_write_tap(addrstart,addrend,"write",write_memory)
Code: Select all
read = space:install_read_tap(addrstart,addrend,"read",read_memory)
write = space:install_write_tap(addrstart,addrend,"write",write_memory)
Re: cheat lua plugins
I upload "memory install helper" plug-in and data files. Please review this "test" plug-in.
"https://dotup.org/uploda/dotup.org2923969.7z.html"
[password] jman
1. create "memory" folder in your "plugins" folder
2. install plugins/memory/init.lua and plugins/memory/plugin.json into "memory" folder.
3. open "plugin.ini" file with text editor.
4. add strings : "memory 1" at the bottom line in this ini file.
5. close "plugin.ini"
6. put "memory.dat" into your "mame" main folder in which you install "mame.exe".
7. execute MAME with debugger (input "mame -d andromed" in command prompt)
8. input "map 3000" in the debugger prompt.
9. confirm "lua_read_memory" and "lua_write_memory".
"memory.dat" is simple text file. Format is "<romname>,<device>,<space>,<start_address>,<end_address>".
Sample code
"galaga,:maincpu,program,0x4000,0x4fff"
Whitespace is stripped and "--" works as comment like lua language.
Sample :
"galaga, :maincpu, program, 0x4000, 0x4fff -- install read/write memories in $0x4000 - $0x4fff"
Also I post the cheat codes which uses installed memory ($3000 - $3020).
Check "http://www.mamecheat.co.uk/forums/viewtopic.php?f=16&t=13305".
"https://dotup.org/uploda/dotup.org2923969.7z.html"
[password] jman
1. create "memory" folder in your "plugins" folder
2. install plugins/memory/init.lua and plugins/memory/plugin.json into "memory" folder.
3. open "plugin.ini" file with text editor.
4. add strings : "memory 1" at the bottom line in this ini file.
5. close "plugin.ini"
6. put "memory.dat" into your "mame" main folder in which you install "mame.exe".
7. execute MAME with debugger (input "mame -d andromed" in command prompt)
8. input "map 3000" in the debugger prompt.
9. confirm "lua_read_memory" and "lua_write_memory".
"memory.dat" is simple text file. Format is "<romname>,<device>,<space>,<start_address>,<end_address>".
Sample code
"galaga,:maincpu,program,0x4000,0x4fff"
Whitespace is stripped and "--" works as comment like lua language.
Sample :
"galaga, :maincpu, program, 0x4000, 0x4fff -- install read/write memories in $0x4000 - $0x4fff"
Also I post the cheat codes which uses installed memory ($3000 - $3020).
Check "http://www.mamecheat.co.uk/forums/viewtopic.php?f=16&t=13305".
Re: cheat lua plugins
"game speed down" sample - wyvernf0 :
Add the following code into "memory.dat".
Add the following code into "wyvernf0.xml".
I confirm "speed down" with 48% in the sound test mode.
Add the following code into "memory.dat".
Code: Select all
-- wyvern f-0
wyvernf0 ,:maincpu,program,0xe000,0xe0ff
wyvernf0a,:maincpu,program,0xe000,0xe0ff
Code: Select all
<cheat desc="sound test mode">
<comment>set "skip rom chekc" then reset the game (F3)</comment>
<script state="on">
<action>maincpu.mw@0302 = e010</action>
<action>maincpu.pq@e010 = 5bed810021efef3e</action>
<action>maincpu.pq@e018 = 4f070730e67ad604</action>
<action>maincpu.pq@e020 = 04fef02847b8b17b</action>
<action>maincpu.pq@e028 = 34012008fe350120</action>
<action>maincpu.pq@e030 = 0618f03e042010fe</action>
<action>maincpu.pq@e038 = 7786103e052020fe</action>
<action>maincpu.pq@e040 = 05187e032080fe78</action>
<action>maincpu.pq@e048 = c618efaf022040fe</action>
<!--
e010 | 3e ef : ld a,$EF // enable sound
e012 | ef : rst $28
e013 | 21 00 81 : ld hl,$8100 // sound code address
e016 | ed 5b 04 d6 : ld de,($D604) // read inputs
e01a | 7a : ld a,d
e01b | e6 30 : and $30
e01d | 07 : rlca
e01e | 07 : rlca
e01f | 4f : ld c,a
e020 | 7b : ld a,e
e021 | b1 : or c
e022 | b8 : cp b
e023 | 47 : ld b,a
e024 | 28 f0 : jr z,$E016
e026 | fe 04 : cp $04
e028 | 20 01 : jr nz,$E02B
e02a | 35 : dec (hl) // decrease code -01
e02b | fe 08 : cp $08
e02d | 20 01 : jr nz,$E030
e02f | 34 : inc (hl) // increase code +01
e030 | fe 10 : cp $10
e032 | 20 04 : jr nz,$E038
e034 | 3e f0 : ld a,$F0 // decrease code -10
e036 | 18 06 : jr $E03E
e038 | fe 20 : cp $20
e03a | 20 05 : jr nz,$E041
e03c | 3e 10 : ld a,$10 // increase code +10
e03e | 86 : add a,(hl)
e03f | 77 : ld (hl),a
e040 | 78 : ld a,b
e041 | fe 80 : cp $80
e043 | 20 03 : jr nz,$E048
e045 | 7e : ld a,(hl) // play sound
e046 | 18 05 : jr $E04D
e048 | fe 40 : cp $40
e04a | 20 02 : jr nz,$E04E
e04c | af : xor a // stop sound
e04d | ef : rst $28 // send sound code
e04e | 18 c6 : jr $E016
-->
</script>
<script state="run">
<output format="----- wyvern f-0 sound test mode -----" line="10" align="center" />
<output format="left : decrease code -01" line="11" align="center" />
<output format="right : increase code +01" line="12" align="center" />
<output format="down : decrease code -10" line="13" align="center" />
<output format="up : increase code +10" line="14" align="center" />
<output format="button 1 : play sound" line="15" align="center" />
<output format="button 2 : stop sound" line="16" align="center" />
<output format="----------------------------" line="17" align="center" />
<output format="<< sound code %2.2X >>" line="19" align="center" >
<argument>maincpu.pb@8100</argument>
</output>
</script>
<script state="off">
<action>maincpu.mw@0302 = 0c8d</action>
<action>maincpu.pq@e010 = 0000000000000000</action>
<action>maincpu.pq@e018 = 0000000000000000</action>
<action>maincpu.pq@e020 = 0000000000000000</action>
<action>maincpu.pq@e028 = 0000000000000000</action>
<action>maincpu.pq@e030 = 0000000000000000</action>
<action>maincpu.pq@e038 = 0000000000000000</action>
<action>maincpu.pq@e040 = 0000000000000000</action>
<action>maincpu.pq@e048 = 0000000000000000</action>
</script>
</cheat>