Previous Thread
Next Thread
Print Thread
Page 2 of 3 1 2 3
Joined: Aug 2008
Posts: 24
R
Member
Offline
Member
R
Joined: Aug 2008
Posts: 24
I somehow integrate this to work with my 2 screen setup (1 is for the marquees).

I have to ask though, could there be a way to make this work with other systems? Gameboy, game gear, master system, megadrive, ...?

I'm sure there's no one size fits all but I'd like to see this as a feature, if at all possible, at some point because it's really cool.

Anyway, thanks and thanks to the whole team as well.

Joined: Feb 2014
Posts: 1,019
Likes: 110
G
Very Senior Member
Online Content
Very Senior Member
G
Joined: Feb 2014
Posts: 1,019
Likes: 110
It should be possible to do this for any system because the input system works in the same way.

so for instance, looking at genesis, to get the list of ports:

function printt(t) for i,j in pairs(t) do print (i,j) end end
printt(manager.machine.ioport.ports)

:RESET sol.ioport_port*: 0x564f7ec6e7d8
:ctrl1:mdpad:PAD sol.ioport_port*: 0x564f7ec202c8
:ctrl2:mdpad:PAD sol.ioport_port*: 0x564f7ecfc988

then get the fields:

printt(manager.machine.ioport.ports[":ctrl1:mdpad:PAD"].fields)
P1 B sol.ioport_field*: 0x564f7ec3fff8
%p B sol.ioport_field*: 0x564f7ec46198
%p A sol.ioport_field*: 0x564f7ec56848
P1 Right sol.ioport_field*: 0x564f7ec2b2b8
P1 Up sol.ioport_field*: 0x564f7ecfc988
P1 A sol.ioport_field*: 0x564f7ec202c8
P1 Start sol.ioport_field*: 0x564f7ec41338
%p C sol.ioport_field*: 0x564f7ec567f8
P1 C sol.ioport_field*: 0x564f7ec5a1d8
P1 Down sol.ioport_field*: 0x564f7f703e88
P1 Left sol.ioport_field*: 0x564f7ec60e08


and then look at the mask:

for i,j in pairs(manager.machine.ioport.ports[":ctrl1:mdpad:PAD"].fields) do print(i, j.mask) end
P1 Down 2
P1 C 32
P1 Left 4
P1 Up 1
P1 B 16
%p A 64
%p C 32
%p B 16
P1 Start 128
P1 Right 8
P1 A 64

Last edited by Golden Child; 11/01/23 06:41 PM.
Joined: Aug 2008
Posts: 24
R
Member
Offline
Member
R
Joined: Aug 2008
Posts: 24
EDIT:
Corrected 1 problem, got another smile
Turns out it was a misplaced /n
No more errors but I can't see the text on the buttons, still.

/edit


I'm probably doing something stupid as it is my 1st time looking at LUA but I have trouble making this work for the genesis. I can see the layout but the boxes are not filled with the text. They change to red in the correct positions when I press the buttons too, so I'm assuming the pad is detected correctly.

The error is in line 13 on this .lua script

The error is: "attempt to index a nil value (field ':screen')" and line 13 would be "manager.machine.screens[":screen"]:draw_box(buttonpos[i][1],buttonpos[i][2],buttonpos[i][1]+20,buttonpos[i][2]+20,"
For the sake of debug I removed the "manager.machine.screens[":screen"]" and then the error moves to draw_box

Quote
function iifnot0(a,b,c) if a~=0 then return b else return c end end

displayoverlay=true
originx,originy=50,170
alphavalue=0.5

function drawoverlay()
dpadx,dpady = 50,originy padx,pady = 30,30 cposx,cposy = 120,originy rposx,rposy = 190,originy
buttons = {up = 1, down = 2, left = 4, right = 8, b = 16, c = 32, a = 64, start = 128}
buttonpos = {up = {dpadx, dpady-pady}, down = {dpadx,dpady+pady}, right = {dpadx+padx, dpady}, left={dpadx-padx, dpady}, c={cposx, cposy}, start={cposx+padx, cposy}, b={rposx,rposy}, a={rposx+padx, rposy}}
if displayoverlay==true then
for i,j in pairs(buttons) do
manager.machine.screens[":screen"]:draw_box(buttonpos[i][1],buttonpos[i][2],buttonpos[i][1]+20,buttonpos[i][2]+20,
0x00ffffff | math.floor(alphavalue*255)<<24,
iifnot0(manager.machine.ioport.ports[":ctrl1:mdpad:PAD"]:read() & buttons[i],
0x00ff0000 | math.floor(alphavalue*255)<<24,
0x00000000 | math.floor(alphavalue*255)<<24))
manager.machine.screens[":screen"]:draw_text(buttonpos[i][1]+2, buttonpos[i][2]+4, i,
0xffffff | math.floor(alphavalue*255)<<24)
end
end
input=manager.machine.input
if input:code_pressed(input:code_from_token("KEYCODE_OPENBRACE")) then displayoverlay = false end
if input:code_pressed(input:code_from_token("KEYCODE_CLOSEBRACE")) then displayoverlay = true end
if input:code_pressed(input:code_from_token("KEYCODE_8PAD")) then originy = originy - 1 end
if input:code_pressed(input:code_from_token("KEYCODE_2PAD")) then originy = originy + 1 end
if input:code_pressed(input:code_from_token("KEYCODE_4PAD")) then alphavalue = alphavalue-0.01 if alphavalue<0 then alphavalue=0 end end
if input:code_pressed(input:code_from_token("KEYCODE_6PAD")) then alphavalue = alphavalue+0.01 if alphavalue>1.0 then alphavalue=1.0 end end
end

emu.register_frame_done(drawoverlay)

So, if this is something quick and you have a spare 5m I'll like your help on this.
Thanks in advance.

Last edited by RomKnight; 11/02/23 01:35 PM.
Joined: Feb 2014
Posts: 1,019
Likes: 110
G
Very Senior Member
Online Content
Very Senior Member
G
Joined: Feb 2014
Posts: 1,019
Likes: 110
Each driver is free to name its screens differently, so in this case the screen is named ":megadriv"

Run a search and replace from ":screen" to ":megadriv" and it should work

function printt(t) for i,j in pairs(t) do print (i,j) end end printt(manager.machine.screens)
:megadriv sol.screen_device*: 0x557f97832d78


Code
function iifnot0(a,b,c) if a~=0 then return b else return c end end

displayoverlay=true
originx,originy=50,170
alphavalue=0.5

function calcalpha() return math.floor(alphavalue*255)<<24 end
function pressed(token) input=manager.machine.input return input:code_pressed(input:code_from_token(token)) end

function drawoverlay()
dpadx,dpady = 50,originy padx,pady = 30,30 cposx,cposy = 120,originy rposx,rposy = 190,originy
buttons = {up = 1, down = 2, left = 4, right = 8, b = 16, c = 32, a = 64, start = 128}
buttonpos = {up = {dpadx, dpady-pady}, down = {dpadx,dpady+pady}, right = {dpadx+padx, dpady}, left={dpadx-padx, dpady}, c={cposx, cposy}, start={cposx+padx, cposy}, b={rposx,rposy}, a={rposx+padx, rposy}}
if displayoverlay==true then
screenname = ":screen"
screenname = ":megadriv"
screen = manager.machine.screens[screenname]
for i,j in pairs(buttons) do
screen:draw_box(buttonpos[i][1],buttonpos[i][2],buttonpos[i][1]+20,buttonpos[i][2]+20,
0x00ffffff | calcalpha(),
iifnot0(manager.machine.ioport.ports[":ctrl1:mdpad:PAD"]:read() & buttons[i],
0x00ff0000 | calcalpha(),
0x00000000 | calcalpha()))
screen:draw_text(buttonpos[i][1]+2, buttonpos[i][2]+4, i, 0xffffff | calcalpha())
end
end
if pressed("KEYCODE_OPENBRACE") then displayoverlay = false end
if pressed("KEYCODE_CLOSEBRACE") then displayoverlay = true end
if pressed("KEYCODE_8PAD") then originy = originy - 1 end
if pressed("KEYCODE_2PAD") then originy = originy + 1 end
if pressed("KEYCODE_4PAD") then alphavalue = alphavalue-0.01 if alphavalue<0 then alphavalue=0 end end
if pressed("KEYCODE_6PAD") then alphavalue = alphavalue+0.01 if alphavalue>1.0 then alphavalue=1.0 end end
end

emu.register_frame_done(drawoverlay)

Last edited by Golden Child; 11/02/23 04:02 PM.
Joined: Aug 2008
Posts: 24
R
Member
Offline
Member
R
Joined: Aug 2008
Posts: 24
Perfect.
Thanks for the time explaining it.

Joined: Feb 2014
Posts: 1,019
Likes: 110
G
Very Senior Member
Online Content
Very Senior Member
G
Joined: Feb 2014
Posts: 1,019
Likes: 110
For fun, I wanted to see if I could get lua to generate some xml. So this makes a list of elements from drawing boxes and text, then prints some xml.

Code
elementlist = {} 
 
function iifnot0(a,b,c) if a~=0 then return b else return c end end

function mydrawbox(x,y,x1,y1,portname,mask,bordercolor,inside1,inside0)
 manager.machine.screens[":screen"]:draw_box(x,y,x1,y1,bordercolor, iifnot0(manager.machine.ioport.ports[portname]:read() & mask, inside1, inside0))
table.insert(elementlist, {type="box",x=x,y=y,x1=x1,y1=y1,portname=portname,mask=mask,bordercolor=bordercolor,inside1=inside1,inside0=inside0})
 end
 
 
function mydrawtext(x,y,text,col)
manager.machine.screens[":screen"]:draw_text(x,y,text,col) 
table.insert(elementlist, {type="text",x=x,y=y,text=text,col=col})
end

function otag(t,attrs,inside) attrs=attrs or "" return "<"..t.." "..attrs..">\n" end -- open tag
function ctag(t) return "</"..t..">\n" end -- close tag
function tag(t,attrs,inside) attrs=attrs or "" inside = inside or "" return "<"..t.." "..attrs..">\n"..inside.."</"..t..">\n" end -- complete tag
function stag(t,attrs) attrs=attrs or "" return "<"..t.." "..attrs.."/>\n"end -- singleton tag
function attr(a,v) return a.."=\""..v.."\"".." " end  -- attribute


function makelayout()
print(otag("mamelayout",attr("version",2)))
print(tag("element",attr("name","button"),
tag("rect","",stag("color",attr("red",1.0)..attr("green",1.0)..attr("blue",1.0)))..
tag("rect",attr("state",1),stag("color",attr("red",1.0)..attr("green",0.0)..attr("blue",0.0))..
stag("bounds",attr("x",0.05)..attr("y",0.05)..attr("width",0.90)..attr("height",0.90)))..
tag("rect",attr("state",0),stag("color",attr("red",0.0)..attr("green",0.0)..attr("blue",0.0))..
stag("bounds",attr("x",0.05)..attr("y",0.05)..attr("width",0.90)..attr("height",0.90))) ))
for i,j in pairs(elementlist) do
if j.type=="text" then print(tag("element",attr("name","text"..j.text),stag("text",attr("string",j.text)))) end
end
print(otag("view",attr("name","Overlay")))
print([[<screen index="0">
<bounds x="0" y="0" width="256" height="240" />
</screen>]])
for i,j in pairs(elementlist) do
if j.type=="text" then print(tag("element",attr("ref","text"..j.text),stag("bounds",attr("top",j.y)..attr("left",j.x)..attr("bottom",j.y+10)..attr("right",j.x+4*j.text:len())))) end
if j.type=="box" then print(tag("element",attr("ref","button")..attr("inputtag",j.portname)..attr("inputmask",j.mask),stag("bounds",attr("top",j.y)..attr("left",j.x)..attr("bottom",j.y1)..attr("right",j.x1)))) end
end
print(ctag("view"))
print(ctag("mamelayout"))
end


function drawoverlay()
elementlist = {} 
dpadx,dpady = 50, 170 padx,pady = 30, 30 cposx,cposy = 120, 170 rposx, rposy = 190,170
buttons = {up = 16, down = 32, left = 64, right = 128, a=1, b=2, select=4, start=8} 
buttonpos = {up = {dpadx, dpady-pady},  down = {dpadx,dpady + pady}, right = {dpadx+padx, dpady}, left={dpadx-padx, dpady}, select={cposx, cposy}, start={cposx+padx,cposy}, b={rposx,rposy},a={rposx+padx,rposy}}
for i,j in pairs(buttons) do 
 mydrawbox(buttonpos[i][1],buttonpos[i][2],buttonpos[i][1]+20,buttonpos[i][2]+20, 
 ":ctrl1:joypad:JOYPAD",buttons[i], 0x88ffffff, 0x88ff0000, 0x88000000) 
mydrawtext(buttonpos[i][1]+2,buttonpos[i][2]+4,i,0x88ffffff)
end
end

emu.register_frame_done(drawoverlay)

makelayout()


and the xml it generates:

Code
<mamelayout version="2" >

<element name="button" >
<rect >
<color red="1.0" green="1.0" blue="1.0" />
</rect>
<rect state="1" >
<color red="1.0" green="0.0" blue="0.0" />
<bounds x="0.05" y="0.05" width="0.9" height="0.9" />
</rect>
<rect state="0" >
<color red="0.0" green="0.0" blue="0.0" />
<bounds x="0.05" y="0.05" width="0.9" height="0.9" />
</rect>
</element>

<element name="textright" >
<text string="right" />
</element>

<element name="textup" >
<text string="up" />
</element>

<element name="texta" >
<text string="a" />
</element>

<element name="textdown" >
<text string="down" />
</element>

<element name="textleft" >
<text string="left" />
</element>

<element name="textb" >
<text string="b" />
</element>

<element name="textstart" >
<text string="start" />
</element>

<element name="textselect" >
<text string="select" />
</element>

<view name="Overlay" >

<screen index="0">
<bounds x="0" y="0" width="256" height="240" />
</screen>
<element ref="button" inputtag=":ctrl1:joypad:JOYPAD" inputmask="128" >
<bounds top="170" left="80" bottom="190" right="100" />
</element>

<element ref="textright" >
<bounds top="174" left="82" bottom="184" right="102" />
</element>

<element ref="button" inputtag=":ctrl1:joypad:JOYPAD" inputmask="16" >
<bounds top="140" left="50" bottom="160" right="70" />
</element>

<element ref="textup" >
<bounds top="144" left="52" bottom="154" right="60" />
</element>

<element ref="button" inputtag=":ctrl1:joypad:JOYPAD" inputmask="1" >
<bounds top="170" left="220" bottom="190" right="240" />
</element>

<element ref="texta" >
<bounds top="174" left="222" bottom="184" right="226" />
</element>

<element ref="button" inputtag=":ctrl1:joypad:JOYPAD" inputmask="32" >
<bounds top="200" left="50" bottom="220" right="70" />
</element>

<element ref="textdown" >
<bounds top="204" left="52" bottom="214" right="68" />
</element>

<element ref="button" inputtag=":ctrl1:joypad:JOYPAD" inputmask="64" >
<bounds top="170" left="20" bottom="190" right="40" />
</element>

<element ref="textleft" >
<bounds top="174" left="22" bottom="184" right="38" />
</element>

<element ref="button" inputtag=":ctrl1:joypad:JOYPAD" inputmask="2" >
<bounds top="170" left="190" bottom="190" right="210" />
</element>

<element ref="textb" >
<bounds top="174" left="192" bottom="184" right="196" />
</element>

<element ref="button" inputtag=":ctrl1:joypad:JOYPAD" inputmask="8" >
<bounds top="170" left="150" bottom="190" right="170" />
</element>

<element ref="textstart" >
<bounds top="174" left="152" bottom="184" right="172" />
</element>

<element ref="button" inputtag=":ctrl1:joypad:JOYPAD" inputmask="4" >
<bounds top="170" left="120" bottom="190" right="140" />
</element>

<element ref="textselect" >
<bounds top="174" left="122" bottom="184" right="146" />
</element>

</view>

</mamelayout>



[Linked Image from i.imgur.com]

2 members like this: u-man, robcfg
Joined: Aug 2008
Posts: 24
R
Member
Offline
Member
R
Joined: Aug 2008
Posts: 24
This is cool and useful.
thanks.

Joined: Feb 2014
Posts: 1,019
Likes: 110
G
Very Senior Member
Online Content
Very Senior Member
G
Joined: Feb 2014
Posts: 1,019
Likes: 110
I had an idea of having a set of "macro buttons" that you could click on to help you control a system.

For example, on the apple II you could have a button that would do "CTRL+RESET" or would type a system command like "CATALOG" or "CALL -151".

This would be useful for helping navigate unfamiliar systems or to type unusual commands.

For proof of concept, I wanted to make clickable buttons on a layout, which means adding an input port.


So taking the apple2e driver, I added a dummy input port "keyb_dummy"


Code
static INPUT_PORTS_START( apple2e_common )

	PORT_START("keyb_dummy")
	PORT_BIT(0x001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("DUMMY0")
	PORT_BIT(0x002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("DUMMY1")
	PORT_BIT(0x004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("DUMMY2")
	PORT_BIT(0x008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("DUMMY3")
	PORT_BIT(0x010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("DUMMY4")
	PORT_BIT(0x020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("DUMMY5")
	PORT_BIT(0x040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("DUMMY6")
	PORT_BIT(0x080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("DUMMY7")
	PORT_BIT(0x100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("DUMMY8")
	PORT_BIT(0x200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("DUMMY9")


...
		m_kbspecial(*this, "keyb_special"),
		m_kbdummy(*this, "keyb_dummy"),
		m_sysconfig(*this, "a2_config"),
...
	required_ioport m_kbspecial;
	required_ioport m_kbdummy;
	optional_ioport m_sysconfig;

...


so now I've got some dummy buttons I can hook up to a layout.


So now I can make a layout file:

Taking my layout file from the nes and hacking up on it:


Code
<mamelayout version="2" >

<element name="button" >
<rect >
<color red="1.0" green="1.0" blue="1.0" />
</rect>
<rect state="1" >
<color red="1.0" green="0.0" blue="0.0" />
<bounds x="0.05" y="0.05" width="0.9" height="0.9" />
</rect>
<rect state="0" >
<color red="0.0" green="0.0" blue="0.0" />
<bounds x="0.05" y="0.05" width="0.9" height="0.9" />
</rect>
</element>

<element name="textreset" >
<text string="Reset" />
</element>

<element name="textctrl" >
<text string="Control" />
</element>

<element name="textctrlreset" >
<text string="Control-Reset" />
</element>

<element name="textctrlcenter" >
<text string="^C + CR" />
</element>

<element name="textcall151" >
<text string="CALL -151" />
</element>


<group name="buttons">
<element ref="button" inputtag=":keyb_special" inputmask="8" >
<bounds top="170" left="20" bottom="190" right="40" />
</element>

<element ref="textctrl" >
<bounds top="174" left="22" bottom="184" right="38" />
</element>

<element ref="button" inputtag=":keyb_dummy" inputmask="2" >
<bounds top="170" left="160" bottom="190" right="190" />
</element>

<element ref="textctrlcenter" >
<bounds top="174" left="162" bottom="184" right="182" />
</element>

<element ref="button" inputtag=":keyb_dummy" inputmask="4" >
<bounds top="170" left="120" bottom="190" right="150" />
</element>

<element ref="textctrlreset" >
<bounds top="174" left="122" bottom="184" right="146" />
</element>

<element ref="button" inputtag=":keyb_dummy" inputmask="8" >
<bounds top="170" left="210" bottom="190" right="240" />
</element>

<element ref="textcall151" >
<bounds top="174" left="212" bottom="184" right="236" />
</element>

<element ref="button" inputtag=":keyb_special" inputmask="128" >
<bounds top="170" left="80" bottom="190" right="100" />
</element>

<element ref="textreset" >
<bounds top="174" left="82" bottom="184" right="102" />
</element>


</group>
<view name="Helper" >
<screen index="0">
<bounds x="0" y="0" width="280" height="240" />
</screen>
<group ref="buttons">
<bounds left="-160" right="0" top="0" bottom="20"/>
</group>
</view>

</mamelayout>


and a lua script (executed with dofile) that simply watches the dummy port and executes a command based on the port being pressed.

Code
function press(port,field)
  manager.machine.ioport.ports[port].fields[field]:set_value(1)
end

function release(port,field)
  manager.machine.ioport.ports[port].fields[field]:clear_value()
end
  


function do_reset()
  press(":keyb_special","Control")
  press(":keyb_special","RESET")
  emu.wait(2/60)
  release(":keyb_special","RESET")
  release(":keyb_special","Control")
  emu.wait(1/60)
end


function do_ctrlc()
  press(":keyb_special","Control")
  press(":X3","C  c") -- was aborting because it was looking for "c"
  emu.wait(2/60)
  release(":X3","C  c")
  emu.wait(1/60)
  release(":keyb_special","Control")
  emu.wait(1/60)
  press(":X6","Return")  -- not in X5 it's in X6!!!
  emu.wait(1/60)
  release(":X6","Return")
   emu.wait(1/60)
end





function check_dummy()
  if lastdummyread == nil then lastdummyread=0 end
  dummyread = manager.machine.ioport.ports[":keyb_dummy"]:read()
  if dummyread ~= 0 and lastdummyread==0 then
    if dummyread & 4 ~= 0 then
       co1=coroutine.create(do_reset) coroutine.resume(co1)
    end
    if dummyread & 2 ~= 0 then
       co1=coroutine.create(do_ctrlc) coroutine.resume(co1)
    end
  end
  lastdummyread = dummyread
end


emu.register_frame_done(check_dummy)



It's kind of primitive, but it works.

[Linked Image from i.imgur.com]

Joined: May 1999
Posts: 609
Likes: 1
Senior Member
Offline
Senior Member
Joined: May 1999
Posts: 609
Likes: 1
Interesting, Golden Child, but for this to work I have to modify the source code, if I understand it correctly, right?

Joined: Mar 2001
Posts: 17,125
Likes: 163
R
Very Senior Member
Online Content
Very Senior Member
R
Joined: Mar 2001
Posts: 17,125
Likes: 163
Right, that's a source mod. The Franklin clones have F1-F12 keys that are programmable macros but the emulation isn't 100% correct.

Page 2 of 3 1 2 3

Link Copied to Clipboard
Who's Online Now
3 members (Golden Child, AJR, 1 invisible), 53 guests, and 1 robot.
Key: Admin, Global Mod, Mod
ShoutChat
Comment Guidelines: Do post respectful and insightful comments. Don't flame, hate, spam.
Forum Statistics
Forums9
Topics9,260
Posts121,258
Members5,064
Most Online1,283
Dec 21st, 2022
Our Sponsor
These forums are sponsored by Superior Solitaire, an ad-free card game collection for macOS and iOS. Download it today!

Superior Solitaire
Forum hosted by www.retrogamesformac.com