Previous Thread
Next Thread
Print Thread
Page 34 of 78 1 2 32 33 34 35 36 77 78
Joined: Feb 2014
Posts: 852
Likes: 48
G
Senior Member
Online Content
Senior Member
G
Joined: Feb 2014
Posts: 852
Likes: 48
One of the great mysteries to me was why calling write on an io port was ineffective.

I wanted to set the Apple II's configuration for the Composite monitor type and it wouldn't work at all.
0 = color
1 = bw
2 = green
3 = amber


Calling manager:machine():ioport().ports[":a2_config"]:write(1) would seemingly have no effect,

I could then print it out and see that there was no change:

Code
[MAME]> print(manager:machine():ioport().ports[":a2_config"]:read())
0
[MAME]> print(manager:machine():ioport().ports[":a2_config"]:write(1))

[MAME]> print(manager:machine():ioport().ports[":a2_config"]:read())
0


and the trying of the field's set_value behaved strangely: only by passing it values of 1 or 0 would
get it to "cycle" through the possible values.

manager:machine():ioport().ports[":a2_config"].fields["Composite monitor type"]:set_value(0)
manager:machine():ioport().ports[":a2_config"].fields["Composite monitor type"]:set_value(1)

This made no sense to me at all.

But looking at the code to set the ioport_fields in ioport.cpp gave some clues:

Code
void ioport_field::set_value(ioport_value value)
{
        m_digital_value = value != 0;
}



So here the m_digital value is only getting a value of 1 or 0.


So I thought, why not set the live value directly:

Adding a set_value function to the ioport_field_live in ioport.h

Code
// internal live state of an input field
struct ioport_field_live
{
        // construction/destruction
        ioport_field_live(ioport_field &field, analog_field *analog);

        void set_value(ioport_value newvalue) {value = newvalue;};


and adding set_value and value to the ioport_field_live usertype in luaengine.cpp

Code
/* field.live
 */
	sol().registry().new_usertype<ioport_field_live>("ioport_field_live", "new", sol::no_constructor,
                        "set_value", &ioport_field_live::set_value,  // added set_value function
			"name", &ioport_field_live::name,
                        "value", &ioport_field_live::value);     // added access to member value


Now I can set the value directly:


Code
[MAME]> manager:machine():ioport().ports[":a2_config"].fields["Composite monitor type"].live:set_value(0)
[MAME]> manager:machine():ioport().ports[":a2_config"].fields["Composite monitor type"].live:set_value(1)
[MAME]> manager:machine():ioport().ports[":a2_config"].fields["Composite monitor type"].live:set_value(2)
[MAME]> manager:machine():ioport().ports[":a2_config"].fields["Composite monitor type"].live:set_value(3)
[MAME]> manager:machine():ioport().ports[":a2_config"].fields["Composite monitor type"].live.value=2     
[MAME]> manager:machine():ioport().ports[":a2_config"].fields["Composite monitor type"].live.value=0
[MAME]> print(manager:machine():ioport().ports[":a2_config"].fields["Composite monitor type"].live.value) 
0
[MAME]> manager:machine():ioport().ports[":a2_config"].fields["Composite monitor type"].live.value=3
[MAME]> print(manager:machine():ioport().ports[":a2_config"].fields["Composite monitor type"].live.value)
3
[MAME]> print(manager:machine():ioport().ports[":a2_config"].fields["Composite monitor type"].live:set_value(5))

[MAME]> print(manager:machine():ioport().ports[":a2_config"].fields["Composite monitor type"].live.value)
5
[MAME]> print(manager:machine():ioport().ports[":a2_config"].fields["Composite monitor type"].live:set_value(2))

[MAME]> print(manager:machine():ioport().ports[":a2_config"].fields["Composite monitor type"].live.value)
2
[MAME]> print(manager:machine():ioport().ports[":a2_config"].fields["Shift key mod"].live.value)
4
[MAME]> print(manager:machine():ioport().ports[":a2_config"]:read())
6
[MAME]> manager:machine():ioport().ports[":a2_config"].fields["Shift key mod"].live.value=0 
[MAME]> print(manager:machine():ioport().ports[":a2_config"].fields["Shift key mod"].live.value)
0
[MAME]> print(manager:machine():ioport().ports[":a2_config"]:read())
2



If I set the value "out of bounds" like setting the monitor type to 5 the mame control panel will complain INVALID, but it doesn't seem to hurt anything since it gets masked off.

One thing I realize now is that .live.value=x and .live:set_value(x) are equivalent, so the set_value function probably isn't needed.

Another thing that is a bit perplexing is that you don't want to mix these two accesses:


This is the field set_value:
Code
manager:machine():ioport().ports[":a2_config"].fields["Composite monitor type"].set_value(1)

and this is the field.live.value or field.live.set_value()
Code
manager:machine():ioport().ports[":a2_config"].fields["Composite monitor type"].live.value=1
manager:machine():ioport().ports[":a2_config"].fields["Composite monitor type"].live.set_value(1)

When you use the field set_value, it causes strange behaviors when you use the live set_value, like inverting the field bits. So use the live one 8-)


[Linked Image]

And one last bit: here's a print table function where you pass a lambda function that will print the .live.value for each field in the table:

It's pretty handy to show you all of the values of each field.

Code
[MAME]> function printtf(a,f) for i,j in pairs(a) do print(i,f(j)) end end

[MAME]> printtf(manager:machine():ioport().ports[":a2_config"].fields, function(b) return b.live.value end)
Composite monitor type	2
Shift key mod	0




And if you want to get tricky with lambda functions, this will print all of the values of the ports and fields:
Code
[MAME]> function dopairs(a,f) for i,j in pairs(a) do f(i,j) end end     -- calls f on each pair i,j in the table
[MAME]> dopairs(manager:machine():ioport().ports,function(a,b) print("ports[\""..a.."\"]:read()="..b:read()) dopairs(b.fields,function(i,j) print("ports[\""..a.."\"].".."fields[\""..i.."\"]"..".live.value="..j.live.value) end) end)

ports[":a2_config"]:read()=2
ports[":a2_config"].fields["Composite monitor type"].live.value=2
ports[":a2_config"].fields["Shift key mod"].live.value=0
ports[":sl2:agraphtablet:a2mse_x"]:read()=64608
ports[":sl2:agraphtablet:a2mse_x"].fields["Mouse X 3"].live.value=0
... etc

Last edited by Golden Child; 04/21/19 04:27 PM.
Joined: Feb 2004
Posts: 2,383
Likes: 98
Very Senior Member
Offline
Very Senior Member
Joined: Feb 2004
Posts: 2,383
Likes: 98
The write method on an I/O port isn't for setting the value of input fields. I/O ports can have output fields as well, with handlers supplied by a device. That's what write is for.

Joined: Feb 2014
Posts: 852
Likes: 48
G
Senior Member
Online Content
Senior Member
G
Joined: Feb 2014
Posts: 852
Likes: 48
So why not get the tablet to do some turtlegraphics?

[Linked Image] [Linked Image]

Code
function hgrclr() for i=16384,16384+8192-1 do manager:machine().devices[":maincpu"].spaces["program"]:write_u8(i,0) end end

function pu() manager:machine():ioport().ports[":sl2:agraphtablet:joystick_3_buttons"].fields["P5 Button 2"].live.value = 0x0 end
function pd() manager:machine():ioport().ports[":sl2:agraphtablet:joystick_3_buttons"].fields["P5 Button 2"].live.value = 0x20 end

function setxy(x,y) manager:machine():ioport().ports[":sl2:agraphtablet:joystick_3_x"].fields["P3 Joystick X"].live:set_analog_value(math.floor((x)*1024),math.floor((x)*1024),0) manager:machine():ioport().ports[":sl2:agraphtablet:joystick_3_y"].fields["P3 Joystick Y"].live:set_analog_value(math.floor((y)*1024),math.floor((y)*1024),0) end

function fd(dist) turtlex = turtlex + math.cos(turtledir/360.0*2*math.pi)*dist turtley=turtley-math.sin(turtledir/360.0*2*math.pi)*dist setxy(turtlex,turtley) fr() end

function fd(dist) pieces=10 dist=dist/pieces for i=0,9 do turtlex = turtlex + math.cos(turtledir/360.0*2*math.pi)*dist turtley=turtley-math.sin(turtledir/360.0*2*math.pi)*dist setxy(turtlex,turtley) fr() end end

function bk(dist) fd(-dist) end
function rt(tang) turtledir = (turtledir - tang) % 360.0 end
function lt(tang) rt(-tang) end
function fr(f) f = f or 1 emu.wait(f/60+.001) end
function home() hgrclr() turtlex=0 turtley=0 turtledir=0 pu() fr() setxy(turtlex,turtley) fr() end

function docircle() home() pd() for j=0,35 do rt(10) fr() print(j,turtledir) for i=0,35 do fd(8) fr() rt(10) end  end end

function doco(f,...) co1=coroutine.create(f) ok,err = coroutine.resume(co1,...) print("coroutine.resume -> ",ok,err) end

-- doco = do coroutine
--doco(docircle)

manager:machine():options().entries["snapsize"]:value("560x384")

function drawsquiral() home() for i=0,63 do pu() fr(8) pd() fr(8) fd(i/.7+3) fr(8) rt(88) end print("DONE") end 
-- much smoother if you keep the pen down
function drawsquiral() home() pd() for i=0,63 do fr(8) fd(i/.7+3) fr(8) rt(88) end print("DONE") pu() fr() end  

doco(drawsquiral)

-- function clickat(x,y) pu() fr(3) setxy(x-128,y-128) fr(3) pd() fr(3) end

-- applesoft can't keep up with "quick" pendowns and penups, so give it plenty of time to react

function clickat(x,y) pu() fr(3) setxy(x-128,y-128) print("click at ",x,y) fr(15) pd() fr(20) pu() fr(25) setxy(0,0) fr(2) end

function clickb(x,y,size) buttonsize=size/22 clickat(x*buttonsize+buttonsize/2+13,4) end


doco(clickb,9,4,194) -- click on pencolor button
doco(clickb,0,4,194) -- click on reset button



And I can click on the tablet menu overlays manually: doco(clickb,15,4,194) will click on the "CATALOG" button.

Joined: Feb 2014
Posts: 852
Likes: 48
G
Senior Member
Online Content
Senior Member
G
Joined: Feb 2014
Posts: 852
Likes: 48
I don't have a real graphics tablet to calibrate against, however there is calibration information on the various software disks available.

The tablet calibration file is stored in TAB.INFORMATION and it has a really simple format:

slot #, upper left x1,y1 and lower right x2,y2

490 PRINT D$;"OPEN TAB.INFORMATION"
500 PRINT D$;"WRITE TAB.INFORMATION"
510 PRINT SL: PRINT X1: PRINT Y1: PRINT X2: PRINT Y2
520 PRINT D$;"CLOSE TAB.INFORMATION"
525 PRINT D$;"LOCK TAB.INFORMATION"

The scale is set to 2 in the MENU ALIGNMENT calibration program so those numbers should be multiplied by 2 to get the actual results.


Code
[MAME]> loaddisk("../../APPLE GRAPHICS TABLET pristine.dsk")
[MAME]> hexdump(getfileraw("TAB.INFORMATION"))
(11,0f) 00  *A 006 HELLO                          TS List=(13,0f)
(11,0f) 01  *B 022 GRAPHICS TABLET LOGO           TS List=(14,0f)
(11,0f) 02  *A 012 MENU ALIGNMENT                 TS List=(15,0f)
(11,0f) 03  *T 002 GRAPHICS TABLET SOFTWARE       TS List=(16,0f)
(11,0f) 04  *A 00a QUICK-DRAW                     TS List=(17,0f)
(11,0f) 05  *B 005 UTILITIES                      TS List=(18,0f)
(11,0e) 01  *T 002 TAB.INFORMATION                TS List=(20,0f)
matched "TAB.INFORMATION" with "TAB.INFORMATION               "
00   b2 8d b2 b9 b3 8d b3 b2  |  b6 8d b3 b0 b9 b0 8d b3  |  2.293.326.3090.3
10   b1 b1 b8 8d 00 00 00 00  |  00 00 00 00 00 00 00 00  |  118.............
20   00 00 00 00 00 00 00 00  |  00 00 00 00 00 00 00 00  |  ................
30   00 00 00 00 00 00 00 00  |  00 00 00 00 00 00 00 00  |  ................
40   00 00 00 00 00 00 00 00  |  00 00 00 00 00 00 00 00  |  ................
50   00 00 00 00 00 00 00 00  |  00 00 00 00 00 00 00 00  |  ................
60   00 00 00 00 00 00 00 00  |  00 00 00 00 00 00 00 00  |  ................

[MAME]> loaddisk("../../Apple Graphics Tablet - Applesoft BASIC.dsk")
[MAME]> hexdump(getfileraw("TAB.INFORMATION"))
(11,0f) 00  *A 006 HELLO                          TS List=(12,0f)
(11,0f) 01  *B 022 GRAPHICS TABLET LOGO           TS List=(13,0f)
(11,0f) 02  *A 012 MENU ALIGNMENT                 TS List=(16,0f)
(11,0f) 03  *A 002 DOCUMENT FILE LENGTHS          TS List=(0c,0f)
(11,0f) 04  *B 005 UTILITIES                      TS List=(0a,0d)
(11,0f) 05  *T 002 TAB.INFORMATION                TS List=(09,0f)
matched "TAB.INFORMATION" with "TAB.INFORMATION               "
00   b5 8d b2 b8 b5 8d b2 b7  |  b1 8d b3 b0 b7 b1 8d b3  |  5.285.271.3071.3
10   b0 b5 b6 8d 00 00 00 00  |  00 00 00 00 00 00 00 00  |  056.............
20   00 00 00 00 00 00 00 00  |  00 00 00 00 00 00 00 00  |  ................
30   00 00 00 00 00 00 00 00  |  00 00 00 00 00 00 00 00  |  ................
40   00 00 00 00 00 00 00 00  |  00 00 00 00 00 00 00 00  |  ................
50   00 00 00 00 00 00 00 00  |  00 00 00 00 00 00 00 00  |  ................


So it looks like the numbers are pretty consistent, around 290 and 3090. X and Y are approx the same so we'll assume they will be the same. Multiplying by 2 we get around 580 for upper left and 6200 for lower right.

If we divide those numbers by 3 we get approx 193 and 2066 for our tablet calibration.

[MAME]> print(580/3)
193.33333333333
[MAME]> print(6200/3)
2066.6666666667
[MAME]>

and we'll change those sliders to match:

Some fine tuning of the values gives us 2064 and 193.

[Linked Image]

Now the tablet is pretty well calibrated for the graphics software,

[MAME]> setxy(-127,0) -- puts cursor on the far left edge
[MAME]> setxy(127,0) -- puts cursor on the far right edge

[MAME]> setxy(-128,0) -- puts cursor off the screen
[MAME]> setxy(128,0)

The tablet software seems to work better with the ability to have the cursor off the screen at the edges.

Computing the position of the buttons is a lot easier with the possible joystick range from -128 to 128 going from screen edge to screen edge.

Code
function clickat(x,y) pu() fr(3) setxy(x-128,y-128) print("click at ",x,y) fr(15) pd() fr(20) pu() fr(25) setxy(0,0) fr(2) end
function clickb(x,y,size,offset) size = size or 255 offset = offset or 0 buttonsize=size/22 clickat(x*buttonsize+buttonsize/2+offset,4) end   -- 22 buttons across
function doco(f,...) co1=coroutine.create(f) ok,err = coroutine.resume(co1,...) print("coroutine.resume -> ",ok,err) end

doco(clickb,9)   -- clicks on Pen Color
doco(clickb,3)  -- click on BG Color


and I can do my own Jackson Pollock.

[Linked Image]

Joined: Jul 2007
Posts: 37
Member
Offline
Member
Joined: Jul 2007
Posts: 37
FYI - The latest WOZ disks for Adventureland and Pirate Adventure do not appear to work in MAME once you get to the actual game. Could this be
more weak bit issues from the copy protection?

4AM similar crack info

Video below is a playthrough of Adventureland for reference:

Playthrough of Adventureland

Thanks,

A-Noid

Joined: Mar 2001
Posts: 16,923
Likes: 57
R
Very Senior Member
Offline
Very Senior Member
R
Joined: Mar 2001
Posts: 16,923
Likes: 57
Those don't have weak bits from what I've read of the protection, it's a deeper issue. Probably the same one that prevents us from implementing the weak bits. I'm gonna have to write my own damn floppy subsystem at this rate.

Joined: Jul 2007
Posts: 37
Member
Offline
Member
Joined: Jul 2007
Posts: 37
Thanks Arbee! Impossible Mission WOZ was released today and has it's own, but different difficulties.


It will be nice to play these with graphics. Also, has Votrax speech!


A-Noid

Joined: Feb 2014
Posts: 852
Likes: 48
G
Senior Member
Online Content
Senior Member
G
Joined: Feb 2014
Posts: 852
Likes: 48
[Linked Image]

Managed to figure out enough about layouts to make a row of buttons.

Launching mame with -override_artwork my_art_directory works pretty well.

I have to be careful with this XML stuff, if there's any errors mame segfaults on startup. Segfault! (sung to the Freak out song) Segfault!

xmllint is pretty darn useful in this case to zero in on the erroneous xml. It's so easy to lose a quote here and there.

Code
Segmentation fault (core dumped)

$ xmllint artwork/segfault_apple2p/default.lay  
artwork/segfault_apple2p/default.lay:165: parser error : Unescaped '<' not allowed in attributes values
"menu~menunum~" inputtag=" sl2:agraphtablet:joystick_3_buttons" inputmask="0x10>
                                                                               ^
artwork/segfault_apple2p/default.lay:165: parser error : attributes construct error
"menu~menunum~" inputtag=" sl2:agraphtablet:joystick_3_buttons" inputmask="0x10>
                                                                               ^

Joined: Feb 2004
Posts: 2,383
Likes: 98
Very Senior Member
Offline
Very Senior Member
Joined: Feb 2004
Posts: 2,383
Likes: 98
You realise the format is documented, and we include a script that validates a lot of stuff in XML layouts, right?

Joined: Feb 2014
Posts: 852
Likes: 48
G
Senior Member
Online Content
Senior Member
G
Joined: Feb 2014
Posts: 852
Likes: 48
Hi Vas,

I read the page at https://docs.mamedev.org/techspecs/layout_files.html which is a lot to digest for a noob.

and now I see there's a section on error handling that says:
Quote

Error handling

For internal (developer-supplied) layout files, errors detected by the complay.py script result in a build failure.
MAME will stop loading a layout file if a syntax error is encountered. No views from the layout will be available. Examples of syntax errors include undefined element or group references, invalid bounds, invalid colours, recursively nested groups, and redefined generator parameters.
When loading a layout file, if a view references a non-existent screen, MAME will print a warning message and continue. Views referencing non-existent screens are considered unviable and not available to the user.



Oh now I see the part about complay.py:
Quote

Using complay.py

The MAME source contains a Python script called complay.py, found in the scripts/build subdirectory. This script is used as part of MAME’s build process to reduce the size of data for internal layouts and convert it to a form that can be built into the executable. However, it can also detect many common layout file format errors, and generally provides better error messages than MAME does when loading a layout file. Note that it doesn’t actually run the whole layout engine, so it can’t detect errors like undefined element references when parameters are used, or recursively nested groups. The complay.py script is compatible with both Python 2.7 and Python 3 interpreters.

To check a layout file for common errors, run the script with the path to the file no check and no output file name or base variable name. For example:

python scripts/build/complay.py artwork/dino/default.lay




And complay.py will tell me the line and the character position of the malformed token. Thanks for the pointer. I learn something new about mame every day.

Code
$ python scripts/build/complay.py artwork/segfault_apple2p/default.lay
fatal error: artwork/segfault_apple2p/default.lay:164:98: not well-formed (invalid token)



Last edited by Golden Child; 04/24/19 05:08 PM.
Page 34 of 78 1 2 32 33 34 35 36 77 78

Link Copied to Clipboard
Who's Online Now
3 members (Praxis, Cpt. Pugwash, 1 invisible), 21 guests, and 10 robots.
Key: Admin, Global Mod, Mod
ShoutChat
Comment Guidelines: Do post respectful and insightful comments. Don't flame, hate, spam.
Forum Statistics
Forums9
Topics9,100
Posts119,253
Members5,019
Most Online890
Jan 17th, 2020
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