Previous Thread
Next Thread
Print Thread
Page 1 of 12 1 2 3 11 12
#108050 - 11/29/16 08:27 PM 8bit Apples - Apple I, II, /// and the 16 bit GS  
Joined: Jan 2012
Posts: 774
rfka01 Offline
Senior Member
rfka01  Offline
Senior Member

Joined: Jan 2012
Posts: 774
Bavaria
I think we don't have a dedicated 8 bit Apple thread yet - I came across an Apple /// blog that also has disk images, rom listings and a lot of information.

http://drop-iii-inches.com/

The earlier posts warp back to the time the Apple III driver in MESS became funcional smile

Last edited by rfka01; 11/29/16 08:41 PM.

NCR DMV- DEC Rainbow- Siemens PCD- ITT 3030-Oly People- Acorn A5000- Olivetti M20
#108051 - 11/29/16 08:35 PM Re: 8bit Apples - Apple I, II, /// and GS [Re: rfka01]  
Joined: Mar 2001
Posts: 15,752
R. Belmont Offline
R. Belmont  Offline

Very Senior Member

Joined: Mar 2001
Posts: 15,752
USA
Yeah, I've been following their podcast since it started. I might even actually be on it sometime.

Also, the IIgs isn't an 8-bit Apple smile

#108052 - 11/29/16 08:42 PM Re: 8bit Apples - Apple I, II, /// and GS [Re: rfka01]  
Joined: Jan 2012
Posts: 774
rfka01 Offline
Senior Member
rfka01  Offline
Senior Member

Joined: Jan 2012
Posts: 774
Bavaria
noted and reflected in the edited title smile


NCR DMV- DEC Rainbow- Siemens PCD- ITT 3030-Oly People- Acorn A5000- Olivetti M20
#108053 - 11/29/16 09:04 PM Re: 8bit Apples - Apple I, II, /// and GS [Re: rfka01]  
Joined: Mar 2008
Posts: 163
robcfg Online content
Senior Member
robcfg  Online Content
Senior Member

Joined: Mar 2008
Posts: 163
Madrid, Spain
I'm after a friend of mine to dump a german IIe.

Will be telling you when I achieve it.

#108054 - 11/29/16 09:16 PM Re: 8bit Apples - Apple I, II, /// and GS [Re: rfka01]  
Joined: Jan 2012
Posts: 774
rfka01 Offline
Senior Member
rfka01  Offline
Senior Member

Joined: Jan 2012
Posts: 774
Bavaria
@robcfg
A quick search shows the ROMs for a German IIe are available.


NCR DMV- DEC Rainbow- Siemens PCD- ITT 3030-Oly People- Acorn A5000- Olivetti M20
#108056 - 11/29/16 10:53 PM Re: 8bit Apples - Apple I, II, /// and GS [Re: rfka01]  
Joined: Mar 2008
Posts: 163
robcfg Online content
Senior Member
robcfg  Online Content
Senior Member

Joined: Mar 2008
Posts: 163
Madrid, Spain
Well, nobody knows for sure what you'll find inside an old computer laugh

It could have a less known rom set or an unusual expansion card... You get what I mean.

I'll also be scanning the PCB and taking pictures.

#108057 - 11/29/16 11:02 PM Re: 8bit Apples - Apple I, II, /// and GS [Re: rfka01]  
Joined: Jan 2012
Posts: 774
rfka01 Offline
Senior Member
rfka01  Offline
Senior Member

Joined: Jan 2012
Posts: 774
Bavaria
True dat smile


NCR DMV- DEC Rainbow- Siemens PCD- ITT 3030-Oly People- Acorn A5000- Olivetti M20
#109048 - 03/02/17 06:30 PM Re: 8bit Apples - Apple I, II, /// and GS [Re: rfka01]  
Joined: Jan 2012
Posts: 774
rfka01 Offline
Senior Member
rfka01  Offline
Senior Member

Joined: Jan 2012
Posts: 774
Bavaria
This thread

https://groups.google.com/forum/#!topic/comp.sys.apple2/19Q2hVgAS18

has links to Ramfast SCSI ROMs.


NCR DMV- DEC Rainbow- Siemens PCD- ITT 3030-Oly People- Acorn A5000- Olivetti M20
#109049 - 03/02/17 07:18 PM Re: 8bit Apples - Apple I, II, /// and GS [Re: rfka01]  
Joined: Mar 2001
Posts: 15,752
R. Belmont Offline
R. Belmont  Offline

Very Senior Member

Joined: Mar 2001
Posts: 15,752
USA
Thanks! I actually have my own Ramfast rev. D board I can dump, and the Apple II Documentation Project has both the Apple II and Z180 ROMs for rev. C and D, but more versions are always better smile

#109503 - 05/01/17 06:19 PM Konan David Jr II [Re: rfka01]  
Joined: Jan 2012
Posts: 774
rfka01 Offline
Senior Member
rfka01  Offline
Senior Member

Joined: Jan 2012
Posts: 774
Bavaria


NCR DMV- DEC Rainbow- Siemens PCD- ITT 3030-Oly People- Acorn A5000- Olivetti M20
#109567 - 05/11/17 01:25 PM Re: 8bit Apples - Apple I, II, /// and GS [Re: rfka01]  
Joined: Mar 2001
Posts: 15,752
R. Belmont Offline
R. Belmont  Offline

Very Senior Member

Joined: Mar 2001
Posts: 15,752
USA
The site What Is The Apple IIgs? put together a hard disk image of all of MECC's educational software for the Apple II that boots into a menu. Yes, Oregon Trail is included smile

I've converted it to CHD for the CFFA2 card here: https://mega.nz/#!8iRhHbwK!lcOVKK_BTo1wVvQFfRjZmPRgyulEFQisOnmrtUnXKSI

You can run it like so:

mess64 apple2ee -sl7 cffa2 -hard1 MECC.chd

Or if you want to risk some games being a bit fast:

mess64 apple2gs -sl7 cffa2 -hard1 MECC.chd

As a bonus, load times are far, far faster on the CFFA2 than even a mechanical HDD, and it blows floppies out of the water.

Last edited by R. Belmont; 05/11/17 01:28 PM.
#109577 - 05/14/17 10:32 AM Re: 8bit Apples - Apple I, II, /// and GS [Re: R. Belmont]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
I thought I'd try the MECC.chd and it's pretty cool.

A couple of problems though, on the apple2gs for some reason the auto repeat doesn't work for the arrow keys. The arrow key repeat works fine on the apple2ee. This makes the menu really hard to navigate as you can't get to the bottom of the list without pressing down arrow over and over. I did find that the open-apple or closed-apple plus arrow keys moves by a page in the menu.

And I can't seem to get the apple2gs into the text control panel with ctrl+open apple+escape. I tried everything I could think of, but it just won't go. (I was able to get into the text control panel by holding down closed apple on booting and choosing 1 for control panel)

On the apple2ee the Word Munchers game has all kinds of horizontal glitching on the screen when you're on the word grid. I don't see the horizontal glitching when run on the apple2gs driver.

I'm finding out that I'm not very good at matching the vowel sounds in word munchers. Guess I need some remedial practice.

I'm a bit of a noob with mame and the apple drivers so sorry if these are dumb questions.


Pics of the horizontal glitch on apple2ee on ubuntu 16.04 and mame185 compiled from source:
[Linked Image]
[Linked Image]

Last edited by Golden Child; 05/14/17 03:03 PM. Reason: added pics
#109580 - 05/14/17 04:10 PM Re: 8bit Apples - Apple I, II, /// and GS [Re: rfka01]  
Joined: Mar 2001
Posts: 15,752
R. Belmont Offline
R. Belmont  Offline

Very Senior Member

Joined: Mar 2001
Posts: 15,752
USA
The 8-bit drivers are more modern and complete than the apple2gs driver, which dates to 2005 and has pretty much just been hacked to death since then. The 8-bit drivers support raster splits in order to (not always successfully) support the French Touch demos; the IIgs driver doesn't attempt to support 8-bit raster effects because they were basically unknown in 2005. My guess is the issue with Word Munchers is that it's inadvertently causing that support to engage when it shouldn't, I'll take a look.

I'm writing a new IIgs driver when I have time, which isn't often. It emulates the IIgs at a lower level than any existing emulator, and so progress is slower than I want it to be, but it's IMO necessary to do it that way.

Last edited by R. Belmont; 05/14/17 04:10 PM.
#110635 - 08/21/17 05:50 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Jan 2012
Posts: 774
rfka01 Offline
Senior Member
rfka01  Offline
Senior Member

Joined: Jan 2012
Posts: 774
Bavaria
This thread

http://forum.classic-computing.de/index.php?page=Thread&postID=123001#post123001

contains a link to a book with hardware descriptions and circuit diagrams of the German Apple II clone maker, IBS.


NCR DMV- DEC Rainbow- Siemens PCD- ITT 3030-Oly People- Acorn A5000- Olivetti M20
#110636 - 08/21/17 06:25 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Mar 2001
Posts: 15,752
R. Belmont Offline
R. Belmont  Offline

Very Senior Member

Joined: Mar 2001
Posts: 15,752
USA
I couldn't immediately find that link, but all of the IBS hardware seems to be exact clones, not enhanced or modified so it's all good.

#110651 - 08/23/17 11:50 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Jun 2014
Posts: 64
peter ferrie Offline
Member
peter ferrie  Offline
Member

Joined: Jun 2014
Posts: 64
The glitching might be caused by the game touching the graphics soft-switches while already in graphics mode, as a II+ compatible refresh-polling.
Canyon Climber did exactly that. I have fixed the driver for that case.

#110655 - 08/24/17 06:38 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: peter ferrie]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
I just cloned current git and compiled it and I saw some glitching when doing hgr while in 80 column mode on the apple2e driver.

Just start up, interrupt the boot with CTRL+F12, PR#3, HGR, and then hitting enter repeatedly causes the text screen to scroll and while it's scrolling, there's a bunch of glitching. Once the scroll stops, the glitching disappears.


[Linked Image]

#110658 - 08/24/17 10:51 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Jun 2014
Posts: 64
peter ferrie Offline
Member
peter ferrie  Offline
Member

Joined: Jun 2014
Posts: 64
It's likely to be same issue, but caused by another switch access which I overlooked.

#110659 - 08/25/17 01:38 AM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: peter ferrie]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
Cool. Thanks for looking into the glitching issue.

On another note, I was having some trouble getting a printout from applesoft basic using the ssc and pr#1.

I can get it to output to a file, but the high bit on each byte seems to be set. A quick "tr '\200-\377' '\000-\177' " will strip the high bit from the output file but I was wondering if that's normal.

./mame64 apple2e -sl1 ssc -sl1:ssc:ssc_rs232 printer -printout outputfile.bin

and making sure that the printer and the ssc are using the same bps of 9600 in the Dip Switches and Machine Configuration menus

and then PR#1 and PRINT "HELLO" and PR#0


cat outputfile.bin | hexdump -C
00000000 8d 8a dd d0 d2 c9 ce d4 a0 a2 c8 c5 cc cc cf a2 |................|
00000010 8d 8a c8 c5 cc cc cf 8d 8a 8d 8a dd d0 d2 a3 b0 |................|
00000020

cat outputfile.bin | tr '\200-\377' '\000-\177' | hexdump -C
00000000 0d 0a 5d 50 52 49 4e 54 20 22 48 45 4c 4c 4f 22 |..]PRINT "HELLO"|
00000010 0d 0a 48 45 4c 4c 4f 0d 0a 0d 0a 5d 50 52 23 30 |..HELLO....]PR#0|
00000020

cat outputfile.bin | tr '\200-\377' '\000-\177'

]PRINT "HELLO"
HELLO

]PR#0

#110664 - 08/25/17 01:38 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Mar 2001
Posts: 15,752
R. Belmont Offline
R. Belmont  Offline

Very Senior Member

Joined: Mar 2001
Posts: 15,752
USA
It's normal AFAIK for PR#1 to output Apple high-ASCII since the text screen requires the high bit to be set. Changing the SSC DIP switches to a 7-bit data format might help, assuming the serial printer device can also be changed to that format.

#110665 - 08/25/17 03:27 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: R. Belmont]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
That makes sense with regards to the high-bit.

I tried setting the ssc to 7 bit and the printer to 7 bit but it didn't seem to work properly, inserting spurious 7f characters.

PR#1, PRINT "TESTING 7 BIT" and it comes out mangled. Looks like 8 bit is the way to go.

Code
hexdump -C test7bit5.bin  
00000000  0d 29 5d 7f 50 52 7f 49  7f 4e 54 7f 20 7f 22 54  |.)].PR.I.NT. ."T|
00000010  7f 45 7f 53 54 7f 49 7f  4e 47 20 7f 37 7f 20 7f  |.E.ST.I.NG .7. .|
00000020  42 49 7f 54 7f 22 0d 29  54 15 4d 54 25 39 47 20  |BI.T.".)T.MT%9G |
00000030  5d 05 25 49 51 7f 0d 29  0d 29 5d 7f 50 52 7f 23  |].%IQ..).)].PR.#|
00000040  7f 30                                             |.0|
00000042

#110666 - 08/25/17 06:55 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Jun 2014
Posts: 64
peter ferrie Offline
Member
peter ferrie  Offline
Member

Joined: Jun 2014
Posts: 64
Yes, it's normal behavior, as RB said. Apple "normal" mode text has at least the seventh bit set (i.e. #$80-FF); flash mode has only the sixth bit set (#$40-7F), inverse has neither bit set (i.e. #$00-3F), and you might notice that there's no lowercase in flash or inverse because of the restricted range.
No, you can't switch to 7-bit, because when it was 8-bit originally, you'll get the marker to say that a conversion happened, as you can see.
You'll have to send in 8-bit form, and then perform the conversion after the data arrive.

#110670 - 08/26/17 12:35 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
Just for fun, I was fiddling with the arcbd and was able to get the MLDEMO to do something by adding this to a2arcadebd.cpp.

I don't know how correct this is, but they seem to run.

void a2bus_arcboard_device::write_c0nx(address_space &space, uint8_t offset, uint8_t data)
{
switch (offset)
{
case 0:
m_tms->vram_write(space, 0, data);
break;
case 1:
m_tms->register_write(space, 0, data);
break;


./mame64 apple2e -sl4 arcbd -flop1 Amparcade_1983_Third_Millenium_Engineering_Corporation.do -debug


[Linked Image]
[Linked Image]
[Linked Image]

It's interesting that in this article from Creative Computing that the mountain scene gets horizontally flipped left/right.

[Linked Image]


and the VDPTEST program runs now

before:
[Linked Image]
with the change:
[Linked Image]

#110674 - 08/27/17 11:55 AM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: Golden Child]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
I got inspired and thought I'd take a stab at making a driver for the supersprite board basically copying the arcbd source and it works!

I hooked up the tms5220 and it has speech too. Amazing.

./mame64 apple2e -sl7 ssprite -flop1 StarSprite\ Demonstration.DSK -debug

[Linked Image]
[Linked Image]
[Linked Image]
[Linked Image]
[Linked Image]


[Linked Image]

Last edited by Golden Child; 08/27/17 12:34 PM.
#110693 - 09/01/17 02:01 AM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: peter ferrie]  
Joined: Jun 2014
Posts: 64
peter ferrie Offline
Member
peter ferrie  Offline
Member

Joined: Jun 2014
Posts: 64
The glitching is caused by the same issue, but I can't see how to fix it without rewriting the driver to use a timer to control screen updating.
The 80-column firmware does a lot of switching between pages, faster than the hardware can refresh the display, but each switch triggers a screen update in MAME.

#110694 - 09/01/17 12:14 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Mar 2001
Posts: 15,752
R. Belmont Offline
R. Belmont  Offline

Very Senior Member

Joined: Mar 2001
Posts: 15,752
USA
Oh, that sucks. The French Touch demos flip page 1 / page 2 mid-scanline and expect it to change the display immediately. (BTW, they posted the source for all their stuff if you missed it).

#110696 - 09/01/17 05:52 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Jan 2012
Posts: 774
rfka01 Offline
Senior Member
rfka01  Offline
Senior Member

Joined: Jan 2012
Posts: 774
Bavaria
Alive as ... a Do-Do

http://forum.classic-computing.de/index.php?page=Thread&threadID=11845

This thread contains the ROMs for an Apple II clone which has "Do-Do" as its signon message smile


NCR DMV- DEC Rainbow- Siemens PCD- ITT 3030-Oly People- Acorn A5000- Olivetti M20
#110745 - 09/06/17 08:12 AM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
I've been noticing that the sound output from the apple2e driver has a lot of "pops and crackles." It must be coming from the Mockingboard because it disappears if I bring up the ` volume sliders and set the volume for each AY channel to zero. It has a very regular pattern, almost like someone typing.

Is there a way to disable the Mockingboard from the command line as it seems to be hard wired in the driver? Like -sl4 empty_slot? I suppose I could always just comment it out and recompile.

MCFG_A2BUS_SLOT_ADD("a2bus", "sl4", apple2_cards, "mockingboard")

You can hear it in this video in the background:


#110746 - 09/06/17 08:23 AM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Feb 2004
Posts: 1,864
Vas Crabb Online content
Very Senior Member
Vas Crabb  Online Content
Very Senior Member

Joined: Feb 2004
Posts: 1,864
Sydney, Australia
You can empty a slot from the command line, e.g. -sl4 "" (two double quotes with nothing between them), or you can put something like a mouse card in the slot instead.

#110747 - 09/06/17 12:09 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Mar 2001
Posts: 15,752
R. Belmont Offline
R. Belmont  Offline

Very Senior Member

Joined: Mar 2001
Posts: 15,752
USA
I've never gotten that noise. I suspect your system isn't able to keep up with full frame rate with the Mockingboard installed. Enable the MAME keys and press F11 to monitor that - if it drops below 100% when you hear the crackles that's what's happening.

#110748 - 09/06/17 03:49 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
I brought up the F11 display and sure enough, it was tracking below 100% at times. Most of the time it would hover from 90% to 100%. The pops would definitely get worse when momentarily it would drop to around 60%.

I'm running Ubuntu on a core i5 2.67G x 4, should that be able to keep up?

Unfortunately, the on board sound doesn't work under ubuntu, so I've got a USB audio adapter and I wonder if that contributes to any slowdowns.

Thanks for the -sl4 "" tip, that empties out the Mockingboard.

#110749 - 09/06/17 04:23 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Mar 2001
Posts: 15,752
R. Belmont Offline
R. Belmont  Offline

Very Senior Member

Joined: Mar 2001
Posts: 15,752
USA
2.67 i5 should be fine. Do you have some background process that's using a lot of CPU?

#110750 - 09/06/17 04:37 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Jul 2015
Posts: 33
anikom15 Offline
Member
anikom15  Offline
Member

Joined: Jul 2015
Posts: 33
I know if I don't plug in my laptop, CPU governing kills performance on Windows.

#110751 - 09/06/17 05:07 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
I can close pretty much everything (including firefox) and I still get the pops. It all works so well graphics and soundwise aside from the pops. If it didn't pop I wouldn't even notice that it wasn't running 100%.


I have ubuntu's system monitor running and it doesn't show excessive cpu.

edit:

using F8 and F9 to adjust the frameskip, along with F10 to toggle the throttle makes a big difference.

Setting frameskip to 4/10 and keeping throttle on results in virtually no popping/crackling at all.

I fiddled with some pulseaudio tips at https://wiki.archlinux.org/index.php/PulseAudio/Troubleshooting#Glitches.2C_skips_or_crackling but that didn't seem to make any difference for me.


Last edited by Golden Child; 09/06/17 06:37 PM.
#110752 - 09/07/17 09:31 AM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Feb 2004
Posts: 1,864
Vas Crabb Online content
Very Senior Member
Vas Crabb  Online Content
Very Senior Member

Joined: Feb 2004
Posts: 1,864
Sydney, Australia
If increasing frameskip improves performance, and MAME isn't pegged at 100% on a CPU core when you're experiencing the issues, it suggests an issue with video card drivers/configuration.

#110753 - 09/07/17 12:58 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Mar 2001
Posts: 15,752
R. Belmont Offline
R. Belmont  Offline

Very Senior Member

Joined: Mar 2001
Posts: 15,752
USA
-sdlvideofps will give an idea how performant your video output is. Running an HP9000/320 on my MacBook, it says this:

Code
  0.01s,    1 F, avrg game: 68.78 FPS 14.54 ms/f, avrg video: 414.14 FPS 2.41 ms/f, last video:   inf FPS 1.26 ms/f
  1.03s,   72 F, avrg game: 70.02 FPS 14.28 ms/f, avrg video: 708.18 FPS 1.41 ms/f, last video:   inf FPS 1.18 ms/f
  2.03s,  142 F, avrg game: 69.98 FPS 14.29 ms/f, avrg video: 700.22 FPS 1.43 ms/f, last video:   inf FPS 2.07 ms/f
  3.04s,  213 F, avrg game: 70.01 FPS 14.28 ms/f, avrg video: 719.18 FPS 1.39 ms/f, last video:   inf FPS 1.15 ms/f
  4.06s,  284 F, avrg game: 70.00 FPS 14.29 ms/f, avrg video: 735.14 FPS 1.36 ms/f, last video:   inf FPS 1.47 ms/f
  5.07s,  355 F, avrg game: 70.00 FPS 14.28 ms/f, avrg video: 738.10 FPS 1.35 ms/f, last video:   inf FPS 1.19 ms/f


The "avrg game" is the core emulation's frame rate (this system is a computer putting out a 1024x768@70 Hz screen, so the 70.00 once it settles in is correct), and "avrg video" shows how fast MAME would run if all it did was upload frames in the current configuration. With decent GL drivers that should be above 300%; if it's much below that you might have problems.

#110754 - 09/07/17 04:25 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
I tried -sdlvideofps with both -video opengl and -video soft and

Code
./mame64 apple2e -sdlvideofps -video opengl
  0.02s,    1 F, avrg game: 60.09 FPS 16.64 ms/f, avrg video: 115.03 FPS 8.69 ms/f, last video:   inf FPS 4.33 ms/f
  1.02s,   57 F, avrg game: 55.82 FPS 17.91 ms/f, avrg video: 169.71 FPS 5.89 ms/f, last video:   inf FPS 1.17 ms/f
  2.04s,  115 F, avrg game: 56.45 FPS 17.71 ms/f, avrg video: 164.82 FPS 6.07 ms/f, last video:   inf FPS 2.71 ms/f
  3.04s,  171 F, avrg game: 56.27 FPS 17.77 ms/f, avrg video: 165.24 FPS 6.05 ms/f, last video:   inf FPS 1.96 ms/f
  4.05s,  230 F, avrg game: 56.74 FPS 17.62 ms/f, avrg video: 170.18 FPS 5.88 ms/f, last video:   inf FPS 16.02 ms/f
  5.07s,  289 F, avrg game: 57.04 FPS 17.53 ms/f, avrg video: 184.40 FPS 5.42 ms/f, last video:   inf FPS 7.71 ms/f
  6.08s,  349 F, avrg game: 57.40 FPS 17.42 ms/f, avrg video: 196.23 FPS 5.10 ms/f, last video:   inf FPS 1.16 ms/f
  7.09s,  408 F, avrg game: 57.53 FPS 17.38 ms/f, avrg video: 193.83 FPS 5.16 ms/f, last video:   inf FPS 15.00 ms/f

./mame64 apple2e -video soft
  0.01s,    1 F, avrg game: 78.69 FPS 12.71 ms/f, avrg video: 75.66 FPS 13.22 ms/f, last video:   inf FPS 6.12 ms/f
  1.02s,   59 F, avrg game: 57.62 FPS 17.36 ms/f, avrg video: 135.10 FPS 7.40 ms/f, last video:   inf FPS 5.98 ms/f
  2.04s,  117 F, avrg game: 57.42 FPS 17.41 ms/f, avrg video: 121.47 FPS 8.23 ms/f, last video:   inf FPS 6.30 ms/f
  3.06s,  175 F, avrg game: 57.12 FPS 17.51 ms/f, avrg video: 120.19 FPS 8.32 ms/f, last video:   inf FPS 19.81 ms/f
  4.07s,  231 F, avrg game: 56.75 FPS 17.62 ms/f, avrg video: 114.54 FPS 8.73 ms/f, last video:   inf FPS 29.81 ms/f
  5.08s,  289 F, avrg game: 56.92 FPS 17.57 ms/f, avrg video: 114.66 FPS 8.72 ms/f, last video:   inf FPS 6.87 ms/f
  6.10s,  348 F, avrg game: 57.02 FPS 17.54 ms/f, avrg video: 112.14 FPS 8.92 ms/f, last video:   inf FPS 19.09 ms/f
  7.12s,  408 F, avrg game: 57.33 FPS 17.44 ms/f, avrg video: 115.75 FPS 8.64 ms/f, last video:   inf FPS 6.46 ms/f



-nowaitvsync doesn't seem to make any difference.

lspci tells me that I'm running a:
01:00.0 VGA compatible controller: Advanced Micro Devices, Inc. [AMD/ATI] RV710 [Radeon HD 4550]

glxinfo | grep AMD
Device: AMD RV710 (DRM 2.49.0 / 4.10.0-33-generic, LLVM 4.0.0) (0x9540)
OpenGL renderer string: Gallium 0.4 on AMD RV710 (DRM 2.49.0 / 4.10.0-33-generic, LLVM 4.0.0)

#110773 - 09/11/17 10:01 AM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
I was fiddling with the apple2e driver's Machine Configuration/Composite Monitor Type options and I noticed that the B+W/green/amber don't properly show the shift from the high bit.

So if I do this:

HGR
HCOLOR=1
HPLOT 0,0 TO 8,0
HPLOT 0,1 TO 8,1
POKE 8192,PEEK(8192)+128

and if you are in the black and white modes,
the pixels in the top row should have a horizontal shift to them.

[Linked Image]

and here's another small program to illustrate:

100 HGR:DATA 1,5,2,6:FOR I = 1 TO 4:READ C:HCOLOR=C:HPLOT 0,I TO 279,I:NEXT

[Linked Image]
[Linked Image]

and this is the result running the applepc emulator under dosbox

[Linked Image]
[Linked Image]

Last edited by Golden Child; 09/11/17 12:04 PM.
#110774 - 09/11/17 12:13 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Mar 2001
Posts: 15,752
R. Belmont Offline
R. Belmont  Offline

Very Senior Member

Joined: Mar 2001
Posts: 15,752
USA
Yes, that's known. It'll get fixed whenever we end up doing correct NTSC decoding in-line.

#110781 - 09/12/17 01:57 AM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
Is there a way to keep mame from exiting when you hit ESC when in Partial Keyboard Mode?

When using the apple2e driver, I find myself hitting ESC to do stuff like apple ESC-IJKM text screen editing and mame drops out immediately. It'd be awesome if there was a delay or something that you had to hold ESC for 3 seconds or some kind of exit confirmation. "Are you sure you want to exit?"

I must've done this 100 times now.

#110782 - 09/12/17 02:02 AM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: Golden Child]  
Joined: Apr 2012
Posts: 185
Pernod Online content
Senior Member
Pernod  Online Content
Senior Member

Joined: Apr 2012
Posts: 185
UK
Originally Posted by Golden Child
Is there a way to keep mame from exiting when you hit ESC when in Partial Keyboard Mode?

Yep, add this to your mame.ini:
Code
confirm_quit              1

It'll be in the CORE MISC OPTIONS section.


BBC Micro
#110783 - 09/12/17 04:03 AM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: Pernod]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
ahhhh, thank you.

I see there's a command line option -confirm_quit also.

I kept looking for the mame.ini file and I see that I have to create it with ./mame64 -createconfig

#110787 - 09/12/17 02:15 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: Golden Child]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
It'd be cool if mame had a quit delay where you could just hit ESC, it would pop up a notification of an impending quit and if you were quiet for say 5 seconds without hitting any keystrokes it would exit, otherwise it would cancel the quit.

You'd have the convenience of -noconfirm_quit with the ability to recover if you accidentally hit ESC.

That would save you a keystroke of hitting the enter key.

Last edited by Golden Child; 09/12/17 02:15 PM.
#110789 - 09/12/17 11:47 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: R. Belmont]  
Joined: Jun 2014
Posts: 64
peter ferrie Offline
Member
peter ferrie  Offline
Member

Joined: Jun 2014
Posts: 64
Originally Posted by R. Belmont
Oh, that sucks. The French Touch demos flip page 1 / page 2 mid-scanline and expect it to change the display immediately. (BTW, they posted the source for all their stuff if you missed it).


I've added a check for 80-column mode, which seems to solve the problem.
The 40-col screen updates immediately, the 80-col one doesn't.
And yes, I saw the French Touch stuff. He was one person. His name is Arnaud. We got to know each other a little bit before he retired.

#110790 - 09/12/17 11:54 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Mar 2001
Posts: 15,752
R. Belmont Offline
R. Belmont  Offline

Very Senior Member

Joined: Mar 2001
Posts: 15,752
USA
Great, thanks Peter!

#110792 - 09/14/17 07:50 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: Golden Child]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
I got an Intel Core i3-2120 based system running the integrated graphics and sound and that seems to have totally fixed the audio stuttering that I was seeing before:

According to Ubuntu's System Information:
Processor: Intel® Core™ i3-2120 CPU @ 3.30GHz × 4 (2 cores with hyperthreading)
Graphics: Intel® Sandybridge Desktop

I took the hard drive of my original Ubuntu 17.04 system, made an image with dd and copied that to the new system so it's the exact same system running on different hardware.

I hear no popping at all unless I fiddle with the bgfx video filter sliders and get to the slow ones.

On this computer, the onboard Intel audio works fine and I don't get pops even with the -video soft.

Code

./mame64 apple2e  -sdlvideofps -video bgfx  -prescale 2
  0.02s,    1 F, avrg game: 59.75 FPS 16.74 ms/f, avrg video: 1561.91 FPS 0.64 ms/f, last video:   inf FPS 0.36 ms/f
  1.03s,   62 F, avrg game: 60.00 FPS 16.67 ms/f, avrg video: 3662.88 FPS 0.27 ms/f, last video:   inf FPS 0.28 ms/f
  2.05s,  123 F, avrg game: 60.00 FPS 16.67 ms/f, avrg video: 3540.34 FPS 0.28 ms/f, last video:   inf FPS 0.33 ms/f


./mame64 apple2e -sdlvideofps -video opengl -prescale 2
  0.02s,    1 F, avrg game: 60.02 FPS 16.66 ms/f, avrg video: 487.59 FPS 2.05 ms/f, last video:   inf FPS 1.01 ms/f
  1.03s,   62 F, avrg game: 60.00 FPS 16.67 ms/f, avrg video: 821.80 FPS 1.22 ms/f, last video:   inf FPS 1.01 ms/f
  2.05s,  123 F, avrg game: 60.00 FPS 16.67 ms/f, avrg video: 814.30 FPS 1.23 ms/f, last video:   inf FPS 1.08 ms/f
 

./mame64 apple2e -sdlvideofps -video soft -prescale 2
  0.02s,    1 F, avrg game: 61.71 FPS 16.21 ms/f, avrg video: 77.32 FPS 12.93 ms/f, last video:   inf FPS 6.24 ms/f
  1.03s,   62 F, avrg game: 60.05 FPS 16.65 ms/f, avrg video: 152.53 FPS 6.56 ms/f, last video:   inf FPS 5.82 ms/f
  2.03s,  122 F, avrg game: 60.00 FPS 16.67 ms/f, avrg video: 151.10 FPS 6.62 ms/f, last video:   inf FPS 6.66 ms/f


Are those bgfx numbers for real? 3662 FPS?

So I did learn a couple of things:

Onboard video can be faster than a discrete card. (really!)

You can change the audio driver with:

export SDL_AUDIODRIVER=pulseaudio
export SDL_AUDIODRIVER=alsa

and -frameskip 6 will do exactly 30 FPS if you're into 30 fps video:

I pulled the usb audio device and put it on the new system and the pops are back. So I'm going to blame it on the usb sound dongle.

I feel like widlarizing that thing.

#110793 - 09/14/17 08:47 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Mar 2001
Posts: 15,752
R. Belmont Offline
R. Belmont  Offline

Very Senior Member

Joined: Mar 2001
Posts: 15,752
USA
That's much better performance, glad you found the issue!

BGFX uses modern OpenGL on Linux, which is likely a faster path on the Intel drivers than the ancient GL 1.2/2.0 stuff -video opengl uses, although that much speedup is still kind of unexpected.

#110794 - 09/14/17 10:54 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: R. Belmont]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
Thanks for your help, RB. I am sure enjoying playing with the apple2e driver, especially now with no pops 8-)

#110827 - 09/23/17 08:33 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: Golden Child]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
I've been fiddling with trying to write to the TMS9918 on the ssprite from Applesoft Basic. But for some reason it doesn't work correctly.

The ssprite board sits in slot 7, so it has the io addresses $C0Fx.

I set an address $C0F1 in the variable AD, then poke AD twice, which should set one of the TMS registers, but it doesn't, because it's reading from $C0F1 before it writes, which creates the side effect of resetting the TMS9918 address that it's going to write to. So it keeps thinking that it's getting the low byte of the address forever.

AD = 12*16*256+15*16+1:POKE AD,4:POKE AD, 128+7

(that should write 4 to the TMS9918 register 7, but it has no effect)


[Linked Image]


But doing the same thing from machine language doesn't introduce a read before the write.

CALL -151
4000: AD F1 C0 A9 F2 8D F1 C0 A9 87 8D F1 C0 60
which is just
LDA $C0F1
LDA #$F2
STA $C0F1
LDA #$87
STA $C0F1
RTS

4000G to execute it, and it works.


[Linked Image]

This is totally baffling me.

Is there something about the way applesoft does a poke, using

STA ($50),y

that activates a read before the write?

#110829 - 09/23/17 10:30 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: May 2010
Posts: 860
seanriddle Offline
Senior Member
seanriddle  Offline
Senior Member

Joined: May 2010
Posts: 860
Although my 6502 books don't seem to mention it, it looks like indirect indexed mode does a read from the effective address.

From the MAME source:
https://git.redump.net/mame/tree/src/devices/cpu/m6502/om6502.lst
Code
sta_idy
	TMP2 = read_pc();
	TMP = read(TMP2);
	TMP = set_h(TMP, read((TMP2+1) & 0xff));
	read(set_l(TMP, TMP+Y));
	write(TMP+Y, A);
	prefetch();


Another reference:
https://github.com/eteran/pretendo/blob/master/doc/cpu/6502.txt
Code
Indirect indexed addressing
Write instructions (STA, SHA)

        #    address   R/W description
       --- ----------- --- ------------------------------------------
        1      PC       R  fetch opcode, increment PC
        2      PC       R  fetch pointer address, increment PC
        3    pointer    R  fetch effective address low
        4   pointer+1   R  fetch effective address high,
                           add Y to low byte of effective address
        5   address+Y*  R  read from effective address,
                           fix high byte of effective address
        6   address+Y   W  write to effective address

       Notes: The effective address is always fetched from zero page,
              i.e. the zero page boundary crossing is not handled.

              * The high byte of the effective address may be invalid
                at this time, i.e. it may be smaller by $100.

#110830 - 09/24/17 01:22 AM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: seanriddle]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
Hi Sean,

Thanks for looking that up. I was totally bewildered why machine language would work, but Applesoft pokes would not. That may explain why the Third Millennium Arcade Board has its write register port at $C0C1 and $C0C3 and the read register port at $C0C1 so it could work from both machine language and also Applesoft BASIC POKEing. If you POKE to $C0C3, on the Arcade Board, the STA ($50),Y read is harmless.

I was trying to do a little demo with both the Third Millennium Arcade Board in slot 4 and the Super Sprite in slot 7 and both have them display something, Now I know why my POKEs were ineffective. Man, that was driving me bats.


Last edited by Golden Child; 09/24/17 01:40 AM.
#110835 - 09/24/17 01:03 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: Golden Child]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
I was using PR#1 along with specifying the ssc and a printer, but for some reason the DIP switches would reset themselves to "Communications Mode" along with "19200 baud". I'd set them to "Printer Mode / 9600" and that would disappear sometimes.

./mame64 apple2e -sl1 ssc -sl1:ssc:ssc_rs232 printer -printout myprintout.bin

What I discovered is that you have to keep specifying the "-sl1 ssc -sl1:ssc:ssc_rs232 printer -printout myprintout.bin" part on the command line.

If you don't, the DIP switches disappear from the UI menus and the next time you specify the ssc, those values will reset themselves to communications mode/19200 and your printout file will be scrambled eggs instead of sunny side up.


Is there a way to specify those settings from the command line?

Last edited by Golden Child; 09/24/17 01:04 PM.
#110836 - 09/24/17 02:08 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Mar 2001
Posts: 15,752
R. Belmont Offline
R. Belmont  Offline

Very Senior Member

Joined: Mar 2001
Posts: 15,752
USA
Right, the switches are only saved if the card is present, because otherwise you could put a different card with different switches in slot 1 and really confuse things. Your best bet is probably to make a batch file that runs MAME with the -sl1 ssc and so on.

#110837 - 09/24/17 02:31 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Feb 2004
Posts: 1,864
Vas Crabb Online content
Very Senior Member
Vas Crabb  Online Content
Very Senior Member

Joined: Feb 2004
Posts: 1,864
Sydney, Australia
There's no way to set DIP switches on the command line right now, and the options system is rather buggy and limited. It's being rewritten, it's just time-consuming. This will open up more possibilities.

#110838 - 09/24/17 03:53 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
One last question for today: I was trying to edit my basic program in a text editor and paste it into the apple2e driver with UI Paste (Left Shift+Scroll Lock).

Some characters on the PC keyboard don't get typed properly:

" turns into @
* turns into nothing
() turns into *(
& turns into ^
@ turns into nothing

which makes it hard to paste programs.

pasting the following text into the apple2e driver:

Code
    exclaim!atsign@hash#dollarsign$percent%caret^amper&asterisk*leftparen(rightparen)
    dash-underscore_plus+equals=bracket[]curly{}backslash\verticalbar|
    tick`tilde~
    comma,period.lessthan<greaterthan>slash/question?semicolon;colon:singlequote'doublequote"
    abcdefghijklmnopqrstuvwxyz
    ABCDEFGHJIJKLMNOPQRSTUVWXYZ

[Linked Image]



so for instance:
Code
50 PRINT "ADDR WRITE SLOT=";S;" VALUE LO=";W0;" HI=";W1
51 SB = 49280:S0 = SB + 16 * S:S1 = S0 + 1:IP = 16384+20:I0=IP
52 POKE IP,160 + 13: POKE IP + 1, FN LO(S1): POKE IP + 2, FN HI(S1): IP = IP + 3 REM  AD LDA $C0C1

turns into:

Code
50 PRINT @ADDR WRITE SLOT=@;S;@ VALUE LO=@;W0;@ HI=@;W1
51 SB = 49280:S0 = SB + 16  S:S1 = S0 + 1:IP = 16384+20:I0=IP
52 POKE IP,160 + 13: POKE IP + 1, FN LO*S1(: POKE IP + 2, FN HI*S1(: IP = IP + 3 REM  AD LDA $C0C1




and a couple of things about UI Paste:

ALT+TAB to switch to my text editor, copy with CTRL+C, ALT+TAB to go back to the apple2e driver, ends up putting a CTRL+I into the text buffer so you have to hit enter to clear the input line.

if you type ? ASC(" then hit alt+tab then go back to mame with alt+tab then type ") you get a 9 (a CTRL+I).



You have to be really quick to hit Left Shift+Scroll Lock and let go of the Left Shift or 1234 PRINT turns into !@#$ PRINT.

It'd be cool if there was a delay before it actually started typing, and maybe even have a notification that comes on screen saying : UI Paste in progress. Perhaps even an abort mechanism that can stop a UI Paste in progress.


When a CR is encountered, the basic interpreter can't keep up with the keystrokes sometimes while it's processing the line and will sometimes drop the first character of the next line which can easily stomp other basic lines since the line number isn't right.

Note how the pasted text has missing characters at the beginning of the line.

Maybe there could be a CR delay that's longer than the normal character send time.


Upper and lowercase is a bit of a problem since caps lock is a must for Applesoft Basic programming, but if you were to paste UI lowercase text it wouldn't come out properly.

#110839 - 09/24/17 06:08 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: Golden Child]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
Silly fun with having both the Arcade Board and the Super Sprite active.

./mame64 apple2e -sl4 arcbd -sl7 ssprite

[Linked Image]

edit:

and even more silly fun:

./mame64 apple2e -sl4 arcbd -sl5 arcbd -sl7 ssprite

[Linked Image]

trying to do more gets me a segfault:

./mame64 apple2e -sl7 ssprite -sl4 arcbd -sl5 arcbd -sl2 arcbd
Segmentation fault (core dumped)

Last edited by Golden Child; 09/24/17 11:45 PM.
#110845 - 09/25/17 12:00 AM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Mar 2001
Posts: 15,752
R. Belmont Offline
R. Belmont  Offline

Very Senior Member

Joined: Mar 2001
Posts: 15,752
USA
MAME has a hardcoded max of 4 screens. I'm not sure where it comes from, it limits my ability to put 6 NuBus video cards in a Mac II and have real fun frown

#110846 - 09/25/17 01:54 AM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Feb 2004
Posts: 1,864
Vas Crabb Online content
Very Senior Member
Vas Crabb  Online Content
Very Senior Member

Joined: Feb 2004
Posts: 1,864
Sydney, Australia
The maximum screen count comes from the built-in layouts. MAME can't dynamically generate layouts for an arbitrary number of screens. Make a github issue and assign it to me - I'll get around to it at some point.

#110863 - 09/26/17 12:33 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: Golden Child]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
Some baby steps with lua: I thought I'd see if I could "dump" the Apple 2 text screen memory to the lua console.


./mame64 apple2e -plugin console


Code
cpu = manager:machine().devices[":maincpu"];mem = cpu.spaces["program"]

for i=0,23 do appletextaddress=0x400+(math.floor(i/8)*40+128*(i%8)); print(i.."  "..appletextaddress.."") end

for i=0,23 do appletextaddress=0x400+(math.floor(i/8)*40+128*(i%8)); a="";for k=0,39 do newchar = mem:read_i8(appletextaddress+k); newchar = newchar & 127 ; if newchar < 32 then newchar = newchar + 64; end; a=a..string.char(newchar); end; print (i.."  "..appletextaddress.." "..a); end



There's a minimal amount of character fixing, just take the char, strip the high bit and turn characters less than 32 into something recognizable by adding 64.


Running the little program:

100 HOME : FOR I = 1 TO 24: HTAB 1 : VTAB I: PRINT "Apple Text Line: ";I;: NEXT : VTAB 1

[Linked Image]


Code
0  1024 Apple Text Line: 1                      
1  1152 ]pple Text Line: 2                      
2  1280 Apple Text Line: 3                      
3  1408 Apple Text Line: 4                      
4  1536 Apple Text Line: 5                      
5  1664 Apple Text Line: 6                      
6  1792 Apple Text Line: 7                      
7  1920 Apple Text Line: 8                      
8  1064 Apple Text Line: 9                      
9  1192 Apple Text Line: 10                     
10  1320 Apple Text Line: 11                     
11  1448 Apple Text Line: 12                     
12  1576 Apple Text Line: 13                     
13  1704 Apple Text Line: 14                     
14  1832 Apple Text Line: 15                     
15  1960 Apple Text Line: 16                     
16  1104 Apple Text Line: 17                     
17  1232 Apple Text Line: 18                     
18  1360 Apple Text Line: 19                     
19  1488 Apple Text Line: 20                     
20  1616 Apple Text Line: 21                     
21  1744 Apple Text Line: 22                     
22  1872 Apple Text Line: 23                     
23  2000 Apple Text Line: 24                     


and my UI paste test becomes:

Code
0  1024                                         
1  1152 ]    EXCLAIM!ATSIGNHASH#DOLLARSIGN$PERCE
2  1280 NT%CARETAMPER^ASTERISKLEFTPAREN*RIGHTPAR
3  1408 EN(                                     
4  1536                                         
5  1664 ?SYNTAX ERROR                           
6  1792 ]ASH-UNDERSCORE_PLUS+EQUALS=BRACKET[]CUR
7  1920 LY{}BACKSLASH\VERTICALBAR|              
8  1064                                         
9  1192 ?SYNTAX ERROR                           
10  1320 ]TICK`TILDE~                            
11  1448                                         
12  1576 ?SYNTAX ERROR                           
13  1704 ]    COMMA,PERIOD.LESSTHAN<GREATERTHAN>S
14  1832 LASH/QUESTION?SEMICOLON;COLON:SINGLEQUOT
15  1960 E&DOUBLEQUOTE@                          
16  1104                                         
17  1232 ?SYNTAX ERROR                           
18  1360 ]BCDEFGHIJKLMNOPQRSTUVWXYZ              
19  1488                                         
20  1616 ?SYNTAX ERROR                           
21  1744 ]   ABCDEFGHJIJKLMNOPQRSTUVWXYZ         
22  1872                                         
23  2000                                         

#110868 - 09/26/17 10:33 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: Golden Child]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
This lua stuff is really cool.

I wanted to see if it could write to the TMS9918 on the arcade board and I was able to write to the VRAM, but I couldn't find a way to access the TMS9918 registers programmatically.

I think that the TMS9918 have to be initialized with a real program, because there are side effects from the code that sets the registers. Once it's initialized, then I can just write stuff to the VRAM space and it displays.

Wow, this is so much faster to run than my Applesoft programs. The effects are seen virtually instantaneously.

Now if I just had a way to do an emu.frameadvance() (which doesn't work) or some kind of way to do a delay like wait for vblank.


[Linked Image]



A very short program to initialize the TMS 9918 registers.

Code
1  DEF  FN LO(X) = ((X / 256) -  INT (X / 256)) * 256: DEF  FN HI(X) =  INT (X / 256)

4  GOTO 100
5  PRINT "REG WRITE: SLOT=";S;" VALUE=";W0;" REG=";W1
6 SB = 49280:S0 = SB + 16 * S:S1 = S0 + 1
7 IP = 16384
8  POKE IP,160 + 13: POKE IP + 1, FN LO(S1): POKE IP + 2, FN HI(S1): REM LDA $C0C1
9 IP = IP + 3: POKE IP,160 + 9: POKE IP + 1,W0:IP = IP + 2: REM LDA #$W0
10  POKE IP,128 + 13: POKE IP + 1, FN LO(S1): POKE IP + 2, FN HI(S1):IP = IP + 3: REM STA $C0C1
11 IP = IP + 0: POKE IP,160 + 9: POKE IP + 1,W1:IP = IP + 2: REM LDA #$W1
13 IP = IP + 0: POKE IP,128 + 13: POKE IP + 1, FN LO(S1): POKE IP + 2, FN HI(S1):IP = IP + 3: REM STA $C0C1
14  POKE IP,6 * 16:IP = IP + 1: REM  RTS
15  CALL 16384
16  RETURN 

100 S = 4:W0 = 2:W1 = 128 + 0: GOSUB 5
101 S = 4:W0 = 193:W1 = 128 + 1: GOSUB 5
102 S = 4:W0 = 14:W1 = 128 + 2: GOSUB 5
103 S = 4:W0 = 255:W1 = 128 + 3: GOSUB 5
104 S = 4:W0 = 3:W1 = 128 + 4: GOSUB 5
105 S = 4:W0 = 118:W1 = 128 + 5: GOSUB 5
106 S = 4:W0 = 3:W1 = 128 + 6: GOSUB 5
107 S = 4:W0 = 15:W1 = 128 + 7: GOSUB 5
108  END 


Then I can run this lua program with dofile("fontarray_tms.lua")


Code
tms= manager:machine().devices[":sl4:arcbd:arcbd_tms"]
mem = tms.spaces["vram"]

fontarray = {32, 0,0,0,0,0,0,0,0,
33, 24,60,60,24,24,0,24,0,
34, 108,108,0,0,0,0,0,0,
35, 108,108,254,108,254,108,108,0,
36, 24,62,96,60,6,124,24,0,
37, 0,198,204,24,48,102,198,0,
38, 56,108,104,118,220,204,118,0,
39, 24,24,48,0,0,0,0,0,
40, 12,24,48,48,48,24,12,0,
41, 48,24,12,12,12,24,48,0,
42, 0,102,60,255,60,102,0,0,
43, 0,24,24,126,24,24,0,0,
44, 0,0,0,0,0,24,24,48,
45, 0,0,0,126,0,0,0,0,
46, 0,0,0,0,0,24,24,0,
47, 3,6,12,24,48,96,192,0,
48, 60,102,110,126,118,102,60,0,
49, 24,56,24,24,24,24,126,0,
50, 60,102,6,28,48,102,126,0,
51, 60,102,6,28,6,102,60,0,
52, 28,60,108,204,254,12,30,0,
53, 126,96,124,6,6,102,60,0,
54, 28,48,96,124,102,102,60,0,
55, 126,102,6,12,24,24,24,0,
56, 60,102,102,60,102,102,60,0,
57, 60,102,102,62,6,12,56,0,
58, 0,24,24,0,0,24,24,0,
59, 0,24,24,0,0,24,24,48,
60, 12,24,48,96,48,24,12,0,
61, 0,0,126,0,0,126,0,0,
62, 48,24,12,6,12,24,48,0,
63, 60,102,6,12,24,0,24,0,
64, 124,198,222,222,222,192,120,0,
65, 24,60,60,102,126,195,195,0,
66, 252,102,102,124,102,102,252,0,
67, 60,102,192,192,192,102,60,0,
68, 248,108,102,102,102,108,248,0,
69, 254,102,96,120,96,102,254,0,
70, 254,102,96,120,96,96,240,0,
71, 60,102,192,206,198,102,62,0,
72, 102,102,102,126,102,102,102,0,
73, 126,24,24,24,24,24,126,0,
74, 14,6,6,6,102,102,60,0,
75, 230,102,108,120,108,102,230,0,
76, 240,96,96,96,98,102,254,0,
77, 130,198,238,254,214,198,198,0,
78, 198,230,246,222,206,198,198,0,
79, 56,108,198,198,198,108,56,0,
80, 252,102,102,124,96,96,240,0,
81, 56,108,198,198,198,108,60,6,
82, 252,102,102,124,108,102,227,0,
83, 60,102,112,56,14,102,60,0,
84, 126,90,24,24,24,24,60,0,
85, 102,102,102,102,102,102,62,0,
86, 195,195,102,102,60,60,24,0,
87, 198,198,198,214,254,238,198,0,
88, 195,102,60,24,60,102,195,0,
89, 195,195,102,60,24,24,60,0,
90, 254,198,140,24,50,102,254,0,
91, 60,48,48,48,48,48,60,0,
92, 192,96,48,24,12,6,3,0,
93, 60,12,12,12,12,12,60,0,
94, 16,56,108,198,0,0,0,0,
95, 0,0,0,0,0,0,0,254,
96, 24,24,12,0,0,0,0,0,
97, 0,0,60,6,30,102,59,0,
98, 224,96,108,118,102,102,60,0,
99, 0,0,60,102,96,102,60,0,
100, 14,6,54,110,102,102,59,0,
101, 0,0,60,102,126,96,60,0,
102, 28,54,48,120,48,48,120,0,
103, 0,0,59,102,102,60,198,124,
104, 224,96,108,118,102,102,230,0,
105, 24,0,56,24,24,24,60,0,
106, 6,0,6,6,6,6,102,60,
107, 224,96,102,108,120,108,230,0,
108, 56,24,24,24,24,24,60,0,
109, 0,0,102,119,107,99,99,0,
110, 0,0,124,102,102,102,102,0,
111, 0,0,60,102,102,102,60,0,
112, 0,0,220,102,102,124,96,240,
113, 0,0,61,102,102,62,6,7,
114, 0,0,236,118,102,96,240,0,
115, 0,0,62,96,60,6,124,0,
116, 16,48,124,48,48,52,24,0,
117, 0,0,204,204,204,204,118,0,
118, 0,0,204,204,204,120,48,0,
119, 0,0,198,214,214,108,108,0,
120, 0,0,99,54,28,54,99,0,
121, 0,0,102,102,102,60,24,112,
122, 0,0,126,76,24,50,126,0,
123, 14,24,24,112,24,24,14,0,
124, 24,24,24,24,24,24,24,0,
125, 112,24,24,14,24,24,112,0,
126, 114,156,0,0,0,0,0,0,
127, 0,0,0,0,0,0,0,0
}

-- pattern table at 0x0000

i=1
bytepos=0x0000+32*8
while(true) do
 if i>table.maxn(fontarray) then break; end;
  charnum = fontarray[i];
  i = i + 1;
  for j=1,8 do  mem:write_i8(bytepos,fontarray[i]); i = i + 1; bytepos = bytepos+1; end
end

-- name table at 0x3800

bytepos = 0x3800

for j=0,2 do
for i=0,255 do mem:write_i8(bytepos,i); bytepos = bytepos+1; end
end

-- color table at 0x2000

bytepos = 0x2000

for i=0,6143 do mem:write_i8(bytepos,15*16+4); bytepos = bytepos+1; end

-- use our font array for a sprite pattern table also

i=1
bytepos=0x1800+32*8
while(true) do
 if i>table.maxn(fontarray) then break; end;
  charnum = fontarray[i];
  i = i + 1;
  for j=1,8 do  mem:write_i8(bytepos,fontarray[i]); i = i + 1; bytepos = bytepos+1; end
end

function setsprite(sprite,x,y,pattern,color)
bytepos=0x3b00+sprite*4
if y>=0 then mem:write_i8(bytepos,y) end -- vertical first
if x>=0 then mem:write_i8(bytepos+1,x)  end
if pattern>=0 then mem:write_i8(bytepos+2,pattern) end
if color >=0 then mem:write_i8(bytepos+3,color) end
end


a = "MameTMS 99184 spriteper line max"

for i=0,string.len(a)-1 do
 setsprite(i,50+(i%4)*20,30+math.floor(i/4)*20,string.byte(a,i+1),(i*2+1)%16);
end

-- dofile("fontarray_tms.lua")



#110869 - 09/26/17 11:55 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Mar 2001
Posts: 15,752
R. Belmont Offline
R. Belmont  Offline

Very Senior Member

Joined: Mar 2001
Posts: 15,752
USA
You could write the TMS registers from Lua by going through the Apple II's address space, I think. Obviously it wouldn't be slot-independent then, but smile

#110870 - 09/27/17 12:13 AM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: Golden Child]  
Joined: Jan 2012
Posts: 688
crazyc Offline
Senior Member
crazyc  Offline
Senior Member

Joined: Jan 2012
Posts: 688
Originally Posted by Golden Child
Now if I just had a way to do an emu.frameadvance() (which doesn't work) or some kind of way to do a delay like wait for vblank.

emu.register_frame(cbfunction) will call cbfunction at vblank. If you want to draw to the screen though lua (directly, not by writing to the emulated vram) you need to use emu.register_frame_done(cbfunction) which calls cbfunction after the frame is drawn to the host screen.

#110877 - 09/27/17 03:29 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: R. Belmont]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
Thanks RB, you're right, I can just mem:write_i8(0xc0c1,data).

I don't know why I couldn't get it to work before, probably because I had an OBOE where I write the registers.

I had a for loop whose index started at 1 but the register write was mem:write_i8(0xc0c1,128+i) instead of write_i8(0xc0c1,128+(i-1)) so the wrong register was getting the value.


Code
cpu = manager:machine().devices[":maincpu"];mem = cpu.spaces["program"]

reginitarray = {2,196,14,255,3,118,3,15}

for i=1,table.maxn(reginitarray) do 
dummy=mem:read_i8(0xc0c1);
mem:write_i8(0xc0c1,reginitarray[i]); mem:write_i8(0xc0c1,128+(i-1)); end



Code
-- dofile("tms9918_apple_memspace.lua")

fontarray = {32, 0,0,0,0,0,0,0,0,
33, 24,60,60,24,24,0,24,0,
34, 108,108,0,0,0,0,0,0,
35, 108,108,254,108,254,108,108,0,
36, 24,62,96,60,6,124,24,0,
37, 0,198,204,24,48,102,198,0,
38, 56,108,104,118,220,204,118,0,
39, 24,24,48,0,0,0,0,0,
40, 12,24,48,48,48,24,12,0,
41, 48,24,12,12,12,24,48,0,
42, 0,102,60,255,60,102,0,0,
43, 0,24,24,126,24,24,0,0,
44, 0,0,0,0,0,24,24,48,
45, 0,0,0,126,0,0,0,0,
46, 0,0,0,0,0,24,24,0,
47, 3,6,12,24,48,96,192,0,
48, 60,102,110,126,118,102,60,0,
49, 24,56,24,24,24,24,126,0,
50, 60,102,6,28,48,102,126,0,
51, 60,102,6,28,6,102,60,0,
52, 28,60,108,204,254,12,30,0,
53, 126,96,124,6,6,102,60,0,
54, 28,48,96,124,102,102,60,0,
55, 126,102,6,12,24,24,24,0,
56, 60,102,102,60,102,102,60,0,
57, 60,102,102,62,6,12,56,0,
58, 0,24,24,0,0,24,24,0,
59, 0,24,24,0,0,24,24,48,
60, 12,24,48,96,48,24,12,0,
61, 0,0,126,0,0,126,0,0,
62, 48,24,12,6,12,24,48,0,
63, 60,102,6,12,24,0,24,0,
64, 124,198,222,222,222,192,120,0,
65, 24,60,60,102,126,195,195,0,
66, 252,102,102,124,102,102,252,0,
67, 60,102,192,192,192,102,60,0,
68, 248,108,102,102,102,108,248,0,
69, 254,102,96,120,96,102,254,0,
70, 254,102,96,120,96,96,240,0,
71, 60,102,192,206,198,102,62,0,
72, 102,102,102,126,102,102,102,0,
73, 126,24,24,24,24,24,126,0,
74, 14,6,6,6,102,102,60,0,
75, 230,102,108,120,108,102,230,0,
76, 240,96,96,96,98,102,254,0,
77, 130,198,238,254,214,198,198,0,
78, 198,230,246,222,206,198,198,0,
79, 56,108,198,198,198,108,56,0,
80, 252,102,102,124,96,96,240,0,
81, 56,108,198,198,198,108,60,6,
82, 252,102,102,124,108,102,227,0,
83, 60,102,112,56,14,102,60,0,
84, 126,90,24,24,24,24,60,0,
85, 102,102,102,102,102,102,62,0,
86, 195,195,102,102,60,60,24,0,
87, 198,198,198,214,254,238,198,0,
88, 195,102,60,24,60,102,195,0,
89, 195,195,102,60,24,24,60,0,
90, 254,198,140,24,50,102,254,0,
91, 60,48,48,48,48,48,60,0,
92, 192,96,48,24,12,6,3,0,
93, 60,12,12,12,12,12,60,0,
94, 16,56,108,198,0,0,0,0,
95, 0,0,0,0,0,0,0,254,
96, 24,24,12,0,0,0,0,0,
97, 0,0,60,6,30,102,59,0,
98, 224,96,108,118,102,102,60,0,
99, 0,0,60,102,96,102,60,0,
100, 14,6,54,110,102,102,59,0,
101, 0,0,60,102,126,96,60,0,
102, 28,54,48,120,48,48,120,0,
103, 0,0,59,102,102,60,198,124,
104, 224,96,108,118,102,102,230,0,
105, 24,0,56,24,24,24,60,0,
106, 6,0,6,6,6,6,102,60,
107, 224,96,102,108,120,108,230,0,
108, 56,24,24,24,24,24,60,0,
109, 0,0,102,119,107,99,99,0,
110, 0,0,124,102,102,102,102,0,
111, 0,0,60,102,102,102,60,0,
112, 0,0,220,102,102,124,96,240,
113, 0,0,61,102,102,62,6,7,
114, 0,0,236,118,102,96,240,0,
115, 0,0,62,96,60,6,124,0,
116, 16,48,124,48,48,52,24,0,
117, 0,0,204,204,204,204,118,0,
118, 0,0,204,204,204,120,48,0,
119, 0,0,198,214,214,108,108,0,
120, 0,0,99,54,28,54,99,0,
121, 0,0,102,102,102,60,24,112,
122, 0,0,126,76,24,50,126,0,
123, 14,24,24,112,24,24,14,0,
124, 24,24,24,24,24,24,24,0,
125, 112,24,24,14,24,24,112,0,
126, 114,156,0,0,0,0,0,0,
127, 0,0,0,0,0,0,0,0
}

cpu = manager:machine().devices[":maincpu"];mem = cpu.spaces["program"]

reginitarray = {2,196,14,255,3,118,3,15}

for i=1,table.maxn(reginitarray) do 
dummy=mem:read_i8(0xc0c1);
mem:write_i8(0xc0c1,reginitarray[i]); mem:write_i8(0xc0c1,128+(i-1)); end

-- name table at 0x3800

mem:write_i8(0xc0c1,0x0);
mem:write_i8(0xc0c1,0x38+64);

for j=0,2 do
for i=0,255 do mem:write_i8(0xc0c0,i) end
end

-- color table at 0x2000

mem:write_i8(0xc0c1,0x0);
mem:write_i8(0xc0c1,0x20+64);

for i=0,6143 do mem:write_i8(0xc0c0,15*16+4) end


-- pattern table at 0, but we'll start at 0x100 because our character data starts at 32

mem:write_i8(0xc0c1,0x0);
mem:write_i8(0xc0c1,0x0+1+64);  -- going to write data, so we add 64

i=1
while(true) do
 if i>table.maxn(fontarray) then break; end;
  charnum = fontarray[i];
  i = i + 1;
  for j=1,8 do  mem:write_i8(0xc0c0,fontarray[i]); i = i + 1; end
end

a = "Writing to the TMS9918 using addresses C0C0 and C0C1 with Lua"

xpos = 0  -- horizontal character pos (in characters)
ypos = 16*8  -- y character pos (in pixels)

copychar = {}  -- init array copychar

for aindex = 1,string.len(a) do

screenaddr = math.floor(ypos/8)*256+xpos*8 + (ypos % 8)

char = string.byte(a,aindex)
charaddr = char*8

-- get char into copychar array
mem:write_i8(0xc0c1,charaddr % 256);
mem:write_i8(0xc0c1,math.floor(charaddr/256));  -- going to read data, don't need to add anything

for i = 0,7 do copychar[i]=mem:read_i8(0xc0c0) end
mem:write_i8(0xc0c1,screenaddr % 256);
mem:write_i8(0xc0c1,math.floor(screenaddr/256)+64);  -- going to write data, add 64

for i= 0,7 do mem:write_i8(0xc0c0,copychar[i]); end
xpos = xpos + 1
end

#110878 - 09/27/17 03:37 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: crazyc]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
Thanks for the emu.register_frame(cbfunction) suggestion. I'll give it a try. For some reason I had always had problems wrapping my head around that style of programming where you have functions that are called.

I've always thought linearly where the program follows a strict sequence. I like the concept of having a regular function that can pause itself and pick right up where it left off.

#110879 - 09/27/17 05:01 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: Golden Child]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
Ok, just tried writing a little routine for emu.register_frame()

This will make the TMS9918 sprites swing back and forth.

I did run into a little trouble with write_i8 because it wants integer values, not floating point. If you send it a floating point value, it will write a zero.

-- mem:write_i8(0,255)
-- mem:write_i8(0,5.5) writes a ZERO for a floating point value, so we'd better use math.floor to integerize it.

So I can register_frame(), how do I unregister a function?

Every time I execute this lua script, it calls emu.register_frame again and swings back and forth faster and faster. Whee!


Code
-- dofile("tms_frame_call.lua")

framecount = 0

function tms_frame_call()

framecount = framecount + 4
sinoffset = math.floor(math.sin((framecount % 360)/360*(2*math.pi))*20);
for i=0,string.len(a)-1 do
 setsprite(i,math.floor(50+(i%4)*20+sinoffset),30+math.floor(i/4)*20,string.byte(a,i+1),(i*2+1)%16);
end
end

emu.register_frame(tms_frame_call)





This script sets everything up beforehand:

Code

-- dofile("fontarray_tms.lua")

tms= manager:machine().devices[":sl4:arcbd:arcbd_tms"]

-- tms= manager:machine().devices[":sl4:ezcgi:ezcgi_tms"]

mem = tms.spaces["vram"]


fontarray = {32, 0,0,0,0,0,0,0,0,
33, 24,60,60,24,24,0,24,0,
34, 108,108,0,0,0,0,0,0,
35, 108,108,254,108,254,108,108,0,
36, 24,62,96,60,6,124,24,0,
37, 0,198,204,24,48,102,198,0,
38, 56,108,104,118,220,204,118,0,
39, 24,24,48,0,0,0,0,0,
40, 12,24,48,48,48,24,12,0,
41, 48,24,12,12,12,24,48,0,
42, 0,102,60,255,60,102,0,0,
43, 0,24,24,126,24,24,0,0,
44, 0,0,0,0,0,24,24,48,
45, 0,0,0,126,0,0,0,0,
46, 0,0,0,0,0,24,24,0,
47, 3,6,12,24,48,96,192,0,
48, 60,102,110,126,118,102,60,0,
49, 24,56,24,24,24,24,126,0,
50, 60,102,6,28,48,102,126,0,
51, 60,102,6,28,6,102,60,0,
52, 28,60,108,204,254,12,30,0,
53, 126,96,124,6,6,102,60,0,
54, 28,48,96,124,102,102,60,0,
55, 126,102,6,12,24,24,24,0,
56, 60,102,102,60,102,102,60,0,
57, 60,102,102,62,6,12,56,0,
58, 0,24,24,0,0,24,24,0,
59, 0,24,24,0,0,24,24,48,
60, 12,24,48,96,48,24,12,0,
61, 0,0,126,0,0,126,0,0,
62, 48,24,12,6,12,24,48,0,
63, 60,102,6,12,24,0,24,0,
64, 124,198,222,222,222,192,120,0,
65, 24,60,60,102,126,195,195,0,
66, 252,102,102,124,102,102,252,0,
67, 60,102,192,192,192,102,60,0,
68, 248,108,102,102,102,108,248,0,
69, 254,102,96,120,96,102,254,0,
70, 254,102,96,120,96,96,240,0,
71, 60,102,192,206,198,102,62,0,
72, 102,102,102,126,102,102,102,0,
73, 126,24,24,24,24,24,126,0,
74, 14,6,6,6,102,102,60,0,
75, 230,102,108,120,108,102,230,0,
76, 240,96,96,96,98,102,254,0,
77, 130,198,238,254,214,198,198,0,
78, 198,230,246,222,206,198,198,0,
79, 56,108,198,198,198,108,56,0,
80, 252,102,102,124,96,96,240,0,
81, 56,108,198,198,198,108,60,6,
82, 252,102,102,124,108,102,227,0,
83, 60,102,112,56,14,102,60,0,
84, 126,90,24,24,24,24,60,0,
85, 102,102,102,102,102,102,62,0,
86, 195,195,102,102,60,60,24,0,
87, 198,198,198,214,254,238,198,0,
88, 195,102,60,24,60,102,195,0,
89, 195,195,102,60,24,24,60,0,
90, 254,198,140,24,50,102,254,0,
91, 60,48,48,48,48,48,60,0,
92, 192,96,48,24,12,6,3,0,
93, 60,12,12,12,12,12,60,0,
94, 16,56,108,198,0,0,0,0,
95, 0,0,0,0,0,0,0,254,
96, 24,24,12,0,0,0,0,0,
97, 0,0,60,6,30,102,59,0,
98, 224,96,108,118,102,102,60,0,
99, 0,0,60,102,96,102,60,0,
100, 14,6,54,110,102,102,59,0,
101, 0,0,60,102,126,96,60,0,
102, 28,54,48,120,48,48,120,0,
103, 0,0,59,102,102,60,198,124,
104, 224,96,108,118,102,102,230,0,
105, 24,0,56,24,24,24,60,0,
106, 6,0,6,6,6,6,102,60,
107, 224,96,102,108,120,108,230,0,
108, 56,24,24,24,24,24,60,0,
109, 0,0,102,119,107,99,99,0,
110, 0,0,124,102,102,102,102,0,
111, 0,0,60,102,102,102,60,0,
112, 0,0,220,102,102,124,96,240,
113, 0,0,61,102,102,62,6,7,
114, 0,0,236,118,102,96,240,0,
115, 0,0,62,96,60,6,124,0,
116, 16,48,124,48,48,52,24,0,
117, 0,0,204,204,204,204,118,0,
118, 0,0,204,204,204,120,48,0,
119, 0,0,198,214,214,108,108,0,
120, 0,0,99,54,28,54,99,0,
121, 0,0,102,102,102,60,24,112,
122, 0,0,126,76,24,50,126,0,
123, 14,24,24,112,24,24,14,0,
124, 24,24,24,24,24,24,24,0,
125, 112,24,24,14,24,24,112,0,
126, 114,156,0,0,0,0,0,0,
127, 0,0,0,0,0,0,0,0
}

cpu = manager:machine().devices[":maincpu"];apmem = cpu.spaces["program"]


reginitarray = {2,197,14,255,3,118,3,15}

for i=1,table.maxn(reginitarray) do 
dummy=apmem:read_i8(0xc0c1);
apmem:write_i8(0xc0c1,reginitarray[i]); apmem:write_i8(0xc0c1,128+(i-1)); end

-- pattern table at 0x0000

i=1
bytepos=0x0000+32*8
while(true) do
 if i>table.maxn(fontarray) then break; end;
  charnum = fontarray[i];
  i = i + 1;
  for j=1,8 do  mem:write_i8(bytepos,fontarray[i]); i = i + 1; bytepos = bytepos+1; end
end



-- name table at 0x3800

bytepos = 0x3800

for j=0,2 do
for i=0,255 do mem:write_i8(bytepos,i); bytepos = bytepos+1; end
end


-- color table at 0x2000

bytepos = 0x2000

for i=0,6143 do mem:write_i8(bytepos,15*16+4); bytepos = bytepos+1; end


-- use our font array for a sprite pattern table also

i=1
bytepos=0x1800+32*8
while(true) do
 if i>table.maxn(fontarray) then break; end;
  charnum = fontarray[i];
  i = i + 1;
  for j=1,8 do  mem:write_i8(bytepos,fontarray[i]); i = i + 1; bytepos = bytepos+1; end
end




function setsprite(sprite,x,y,pattern,color)

--print ("sprite: " .. sprite .. " x: " .. x)
bytepos=0x3b00+sprite*4
if y>=0 then mem:write_i8(bytepos,y) end -- vertical first
if x>=0 then mem:write_i8(bytepos+1,x)  end
if pattern>=0 then mem:write_i8(bytepos+2,pattern) end
if color >=0 then mem:write_i8(bytepos+3,color) end
end


a = "MameTMS 99184 spriteper line max"

for i=0,string.len(a)-1 do
 setsprite(i,50+(i%4)*20,30+math.floor(i/4)*20,string.byte(a,i+1),(i*2+1)%16);
end


#110882 - 09/27/17 07:47 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: Golden Child]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
A couple of modifications to my little routine so you can control it from the console:

deactivate = true to stop it
speed = 8 to change the speed
speed = 184 looks kind of ghostly with each frame alternating out of phase


Code
deactivate = false
speed = 4
framecount = 0

function tms_frame_call()

if not deactivate then
framecount = framecount + speed
sinoffset = math.floor(math.sin((framecount % 360)/360*(2*math.pi))*20);
for i=0,string.len(a)-1 do
 setsprite(i,math.floor(50+(i%4)*20+sinoffset),30+math.floor(i/4)*20,string.byte(a,i+1),(i*2+1)%16);
end
end
end

emu.register_frame(tms_frame_call)

#110893 - 09/28/17 05:19 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: Golden Child]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
I saw the Coleco Adam SmartLogo demo where it shows all 32 sprites flying around the screen and wanted to see if I could reproduce it.

I run the adam driver and wrote a little lua script to save out the vram to a file.


[Linked Image]


So we launch the adam driver with "./mame64 adam smartlog -plugin console" and get to the examples screen so we can dump the vram. We run the following script with dofile("adam_dump_vram.lua")

Code
-- Coleco Adam calls its tms device ":tms9928a"

tms= manager:machine().devices[":tms9928a"]

mem = tms.spaces["vram"]

-- read vram and save to a file

outfile = assert(io.open("vram_dump_file", "wb"))

for i=0,16384-1 do
  outfile:write(string.char(mem:read_u8(i)))
end

assert(outfile:close())



I take the vram dump and load it into the apple2 arcade board's memory.

"./mame64 apple2e -sl4 arcbd -plugin console" and run this script to load the vram dump: dofile("arcbd_load_vram.lua")

Code
tms= manager:machine().devices[":sl4:arcbd:arcbd_tms"]

mem = tms.spaces["vram"]

-- read vram from a file and close it

infile = assert(io.open("vram_dump_file", "rb"))

datablock = infile:read("*all")    

assert(infile:close())

for i=0,16384-1 do
  mem:write_i8(i,string.byte(datablock,(i+1)))  -- datablock index starts at 1
end



and init the TMS9918 registers to match (since it puts its sprite attribute tables in a different spot than I was using at 1F80).


dofile("smartlogo_demo.lua")

Code
cpu = manager:machine().devices[":maincpu"];apmem = cpu.spaces["program"]

reginitarray = {2,194,14,255,3,63,3,1}

for i=1,table.maxn(reginitarray) do 
dummy=apmem:read_i8(0xc0c1);
apmem:write_i8(0xc0c1,reginitarray[i]); apmem:write_i8(0xc0c1,128+(i-1)); end


myspriteattributes = {}

for i=0,31 do
  myspriteattributes[i]={ }
end

for i = 0,31 do
  myspriteattributes[i][0] = 128
  myspriteattributes[i][1] = 96
  myspriteattributes[i][2] = (i+1)*4  -- pattern  (since we are doing 16x16 sprites must be multiples of 4
  myspriteattributes[i][3] = (i % 14) + 2   --color
  myspriteattributes[i][4] = .5   --speed
  myspriteattributes[i][5] = i * (360/32) -- heading
end


function setspritetable(tablepos,sprite,x,y,pattern,color)
  bytepos=tablepos+sprite*4
  if y>=0 then mem:write_i8(bytepos,y) end
  if x>=0 then mem:write_i8(bytepos+1,x)  end
  if pattern>=0 then mem:write_i8(bytepos+2,pattern) end
  if color >=0 then mem:write_i8(bytepos+3,color) end
end


deactivate = false


function do_each_frame()

  if not deactivate then 
  for i=0,31 do
    xoffset = spritespeed*math.cos(myspriteattributes[i][5]/360*2*math.pi)
    yoffset = spritespeed*math.sin(myspriteattributes[i][5]/360*2*math.pi) 

    myspriteattributes[i][0] =   myspriteattributes[i][0] + xoffset
    myspriteattributes[i][1] =   myspriteattributes[i][1] - yoffset 

    if myspriteattributes[i][0] < 0 then  myspriteattributes[i][0] = 256  end
    if myspriteattributes[i][0] > 256 then myspriteattributes[i][0] = 0 end

    if myspriteattributes[i][1] < 0 then myspriteattributes[i][1] = 192 end
    if myspriteattributes[i][1] > 192 then myspriteattributes[i][1] = 0 end

    setspritetable(0x1f80,i,math.floor(myspriteattributes[i][0]),
                            math.floor(myspriteattributes[i][1]),
                            myspriteattributes[i][2],
                            myspriteattributes[i][3])
  end -- for
  end -- if
end -- function

print("do you want to add the function do each frame to emu.register_frame?")
if io.read() == "y" then emu.register_frame(do_each_frame) end

spritespeed = 4



What's cool is to modify the myspriteattributes array in real time from the console and see the result.

For example:
for i = 0,31 do myspriteattributes[i][2]=36*4 end
spritespeed = 0.5

#110894 - 09/28/17 06:21 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Mar 2001
Posts: 15,752
R. Belmont Offline
R. Belmont  Offline

Very Senior Member

Joined: Mar 2001
Posts: 15,752
USA
That's really awesome. I'm glad to see someone combining MAME capabilities in unexpected-to-us ways smile

#110910 - 09/29/17 09:59 AM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: R. Belmont]  
Joined: Feb 2004
Posts: 1,864
Vas Crabb Online content
Very Senior Member
Vas Crabb  Online Content
Very Senior Member

Joined: Feb 2004
Posts: 1,864
Sydney, Australia
Originally Posted by Golden Child
trying to do more gets me a segfault:

./mame64 apple2e -sl7 ssprite -sl4 arcbd -sl5 arcbd -sl2 arcbd
Segmentation fault (core dumped)


Originally Posted by R. Belmont
MAME has a hardcoded max of 4 screens. I'm not sure where it comes from, it limits my ability to put 6 NuBus video cards in a Mac II and have real fun frown


Happy new year

#110913 - 09/29/17 04:03 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: R. Belmont]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
Thanks RB,

Mame is super addictive and fun. I figure something new out every day. It's like a learning lab for old systems. I was struggling so hard trying to get the tms9918 to do something interesting with applesoft and now I've discovered lua is 300x faster and easier. I wish I'd had this back in the days of the apple 2.

I remember reading about the SuperSprite / Arcade Board in Creative Computing back in 1984 and being fascinated with the concept. Now I finally get a chance to actually give it a try.

BTW, thanks for putting in the ssprite stuff in for 0.190.


My discovery for today: how to roll your own dispatch function in lua. I'd make a mistake in a lua function that I called emu.register_frame() on and it would run away happily typing garbage in the console forever until you killed it (and your whole mame session) with CTRL+C.


Once you get a runaway, you can't see what you're typing at all with all of the output clogging the terminal.
So if you get in trouble, just type "cld()" and hit enter and that clears the dispatch_list.
Or if you like to type, type "dispatch_list = {}"



Code

dispatch_list = { }


function frame_dispatcher()
for index,my_func in pairs(dispatch_list) do  my_func() end
end


function print_hello() print("hello") end
function print_there() print("there") end
function print_howareyou() print("how are you") end

function dispatch_list_remove(a_func)
for my_index,my_func in pairs(dispatch_list) do if my_func == a_func then table.remove(dispatch_list,my_index) end end
end

function print_dispatch_list() for my_index,my_func in pairs(dispatch_list) do print(my_func) end end


table.insert(dispatch_list,print_hello) 
table.insert(dispatch_list,print_there) 
table.insert(dispatch_list,print_howareyou)


frame_dispatcher()
print_dispatch_list()

dispatch_list_remove(print_there)

frame_dispatcher()

print_dispatch_list()


function cld()
dispatch_list = {}
end


-- emu.register_frame(frame_dispatcher);
print("type cld(); to stop a runaway dispatch");
print("copy the next line and paste to execute to add our frame dispatcher:");
print("emu.register_frame(frame_dispatcher);");


#110917 - 09/29/17 07:13 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: Golden Child]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
So why not make it so you can control the little turtle guy with the keyboard?

The ultimate goal would be to program a game in mame with lua.

[Linked Image]

This lua script assumes that you've already got the vram loaded with the dump from the smartlogo program, and you've initialized the TMS9918 registers:

Code
function heading_to_spritenumber(heading)
  local heading24
  -- reverse the heading direction and rotate by 90 degrees and scale to 0..23
  heading24 = ((-1*(heading - 90)) % 360) *(24/360)
  return  math.floor(36+heading24)*4  -- turtles run from 36 to 59 (24 different sprites patterns)
end

myspriteattributes = {}

for i=0,31 do
  myspriteattributes[i]={ }
end

for i = 0,31 do
  myspriteattributes[i][0] = 128
  myspriteattributes[i][1] = 96
  myspriteattributes[i][2] = (i+1)*4  -- pattern  (since we are doing 16x16 sprites must be multiples of 4
  myspriteattributes[i][3] = (i % 14) + 2   --color
  myspriteattributes[i][4] = .5   --speed
  myspriteattributes[i][5] = i * (360/32) -- heading
  spritespeed = 1
  myspriteattributes[i]["xvel"] = math.cos(myspriteattributes[i][5]*(2*math.pi/360))
  myspriteattributes[i]["yvel"] = math.sin(myspriteattributes[i][5]*(2*math.pi/360))
end


function setspritetable(tablepos,sprite,x,y,pattern,color)
bytepos=tablepos+sprite*4
if y>=0 then mem:write_i8(bytepos,y) end -- vertical first
if x>=0 then mem:write_i8(bytepos+1,x)  end
if pattern>=0 then mem:write_i8(bytepos+2,pattern) end
if color >=0 then mem:write_i8(bytepos+3,color) end
end


function read_keys()
inp = manager:machine():input()
thrust_value = 0.05

if inp:code_pressed(inp:code_from_token("KEYCODE_UP")) then 
myspriteattributes[0]["xvel"] = myspriteattributes[0]["xvel"] + math.cos(myspriteattributes[0][5]*(2*math.pi/360)) * thrust_value
myspriteattributes[0]["yvel"] = myspriteattributes[0]["yvel"] - math.sin(myspriteattributes[0][5]*(2*math.pi/360)) * thrust_value
end

if inp:code_pressed(inp:code_from_token("KEYCODE_DOWN")) then 
myspriteattributes[0]["xvel"] = myspriteattributes[0]["xvel"] * 0.9
myspriteattributes[0]["yvel"] = myspriteattributes[0]["yvel"] * 0.9
end


if inp:code_pressed(inp:code_from_token("KEYCODE_LEFT")) then myspriteattributes[0][5] = myspriteattributes[0][5] + 2 end
if inp:code_pressed(inp:code_from_token("KEYCODE_RIGHT")) then myspriteattributes[0][5] = myspriteattributes[0][5] - 2 end

myspriteattributes[0][2] = heading_to_spritenumber(myspriteattributes[0][5])

if inp:code_pressed(inp:code_from_token("KEYCODE_C")) then setotherspritepattern(128) end
if inp:code_pressed(inp:code_from_token("KEYCODE_D")) then setotherspritepattern(0) end

end




function update_sprites()

for i=0,31 do
  myspriteattributes[i][0] =   myspriteattributes[i][0] + myspriteattributes[i]["xvel"]
  myspriteattributes[i][1] =   myspriteattributes[i][1] + myspriteattributes[i]["yvel"]

if myspriteattributes[i][0] < 0 then  myspriteattributes[i][0] = 256  end
 if myspriteattributes[i][0] > 256 then myspriteattributes[i][0] = 0 end

if myspriteattributes[i][1] < 0 then myspriteattributes[i][1] = 192 end
 if myspriteattributes[i][1] > 192 then myspriteattributes[i][1] = 0 end

  setspritetable(0x1f80,i,math.floor(myspriteattributes[i][0]),
              math.floor(myspriteattributes[i][1]),myspriteattributes[i][2],myspriteattributes[i][3])
end

end




dispatch_list = { }

function frame_dispatcher()
for index,my_func in pairs(dispatch_list) do  my_func() end
end

function dispatch_list_remove(a_func)
for my_index,my_func in pairs(dispatch_list) do if my_func == a_func then table.remove(dispatch_list,my_index) end end
end

function print_dispatch_list() for my_index,my_func in pairs(dispatch_list) do print(my_func) end end

function cld()
dispatch_list = {}
end

print ("cld() installed type cld() and hit enter to stop dispatch")
print()

table.insert(dispatch_list,update_sprites)
table.insert(dispatch_list,read_keys)

print("table.insert(dispatch_list,update_sprites)")
print("table.insert(dispatch_list,read_keys)")
print()
print(" you will need to manually register frame since I don't want to have it done every time I run the lua file")
print()
print(" so copy and paste the following line on the console")
print()
print("emu.register_frame(frame_dispatcher)")
--print("   equivalent to: emu.register_frame(read_keys)")
print()
print("C key to clear the other sprites")
print("D key to bring the other sprites back")
print("UP key for thrust   DOWN key to slow down")
print("LEFT RIGHT to turn")

function setotherspritepattern(spritepattern)
  for i=1,31 do myspriteattributes[i][2]=spritepattern end
end



#110932 - 09/30/17 10:13 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: Vas Crabb]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
Thanks Vas,

I had to try the new screens capability with the apple 2.

Here's a 6 TMS9918 board demo in addition to the apple screen to make 7 total:

./mame64 apple2e -sl1 ezcgi -sl2 arcbd -sl3 arcbd -sl4 arcbd -sl5 arcbd -sl7 ssprite

I can choose a 4x2 layout that looks good:

[Linked Image]

mame's screen shot still gives me 7 across:

[Linked Image]

Very cool!

Code
-- dofile("apple_6_board_demo.lua")
-- uses the vram_dump_file from coleco adam smartlog

function read_tms_vram_from_file(tms,filename)
mem = tms.spaces["vram"]
infile = assert(io.open("vram_dump_file", "rb"))
datablock = infile:read("*all")    
assert(infile:close())
for i=0,16384-1 do
  mem:write_u8(i,string.byte(datablock,(i+1)))
end
end

function init_tms_registers(slotnum)
cpu = manager:machine().devices[":maincpu"];apmem = cpu.spaces["program"]
reginitarray = {2,194,14,255,3,63,3,1}
regaddress = 0xc080+slotnum*16+1
for i=1,table.maxn(reginitarray) do 
dummy=apmem:read_u8(regaddress);
apmem:write_u8(regaddress,reginitarray[i]); 
apmem:write_u8(regaddress,128+(i-1)); 
end
end

-- ./mame64 apple2e -sl1 ezcgi -sl2 arcbd -sl3 arcbd -sl4 arcbd -sl5 arcbd -sl7 ssprite 

tms=manager:machine().devices[":sl1:ezcgi:ezcgi_tms"]
read_tms_vram_from_file(tms,"vram_dump_file")
init_tms_registers(1)

tms=manager:machine().devices[":sl2:arcbd:arcbd_tms"]
read_tms_vram_from_file(tms,"vram_dump_file")
init_tms_registers(2)

tms=manager:machine().devices[":sl3:arcbd:arcbd_tms"]
read_tms_vram_from_file(tms,"vram_dump_file")
init_tms_registers(3)

tms=manager:machine().devices[":sl4:arcbd:arcbd_tms"]
read_tms_vram_from_file(tms,"vram_dump_file")
init_tms_registers(4)

tms=manager:machine().devices[":sl5:arcbd:arcbd_tms"]
read_tms_vram_from_file(tms,"vram_dump_file")
init_tms_registers(5)

tms=manager:machine().devices[":sl7:ssprite:ssprite_tms"]
read_tms_vram_from_file(tms,"vram_dump_file")
init_tms_registers(7)

#110945 - 10/02/17 07:51 AM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: Golden Child]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
Just came across this while searching around on the internet and thought it was cool: A demo of Captain Pixel which ran on a "flippy card" that had a TMS 34010 and had interfaces to the Apple II and IBM PC.


According to the description:

Quote
arhenderson2006
Published on Jul 17, 2007
This was an interactive graphics demonstration that ran on the 34010 S.D.B. (software development board) and the TMS34010 "Flippy".

The "Flippy" was a 34010 graphics card with an Apple // compatible edge connector on one side and a PC compat. connector on the other. There was a machine specific "loader" module for each platform but a single executable. "Flippy" code was cross platform compatible because the actual application executed on the 34010.

Captain Pixel went on to have two offspring: Captain Comic for the PC by Michael Denio and a version of Captain Comic for the NES that Mike and I collaborated on.

This video does not have audio...


https://www.youtube.com/watch?v=Rn9KTTqN0pw


#110947 - 10/02/17 12:34 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Mar 2001
Posts: 15,752
R. Belmont Offline
R. Belmont  Offline

Very Senior Member

Joined: Mar 2001
Posts: 15,752
USA
Wow, that would've been a very powerful card. Games like the arcade versions of Smash TV and Mortal Kombat ran entirely on a 34010. If the Apple II software exists (or the PC software, but A2 would be more fun) we could definitely emulate it.

TI tried to push 34010 ISA cards on the PC as a "TIGA" standard but they were too pricey to catch on.

#110948 - 10/02/17 12:59 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: R. Belmont]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
I came across this page that was interesting regarding some tms 34010 development:

http://about.endlessskye.com/

Quote
The TMS34010

Texas Instruments came to Media Cybernetics as a then market leader with their latest bleeding edge graphics chip, the TMS34010. The 34010 was a true 32-bit processor with thirty-two 32-bit registers, bit addressability (and variable field width!), and a few graphics instructions. It sat in its own address space on an ISA card, where it communicated with the outside world through memory mapped registers. It was basically an embedded device that ran in true parallel with the host processor. Our development board had no BIOS, no OS, only the 34010 and its own address space. Only the open steppe. So management in its infinite wisdom agreed to port the HALO 2D graphics library in time for the upcoming trade show in San Jose, a ridiculously short 6 weeks away. I didn't step back fast enough when they asked for volunteers, so I "volunteered" for the work. Between myself and another guy on my HALO team we managed to port the entire HALO graphics kernel from 8086 assembler to 34010 assembler.(As a principal engineer and manager I rated a screaming 10 Mhz 286 with a full 640 KB, he had only a 6 Mhz 286 with 512 KB of memory.) I designed a way to download and bootstrap the HALO 34010 kernel onto the 34010 device, using only a simulator and a serial port built into the 34010 device. We had no hardware assistance for debugging. A truly Herculean achievement. You could do a warm reboot and the 34010 device would still be running, merrily drawing graphics from a vector list on its own display. Way cool. And this was way back in prehistory, in 1988. Truly revolutionary. Try doing that with a dual-core x64, dual-graphics card computer.


http://34010.endlessskye.com/

Quote
The TMS34010:Two Generations Too Soon?

Recently I received an out of the blue inquiry from a hobbyist requesting some information on the TMS34010. Interestingly a few days prior I had run across my design notes for the TMS34010 where I had detailed the port of the Media Cybernetics Halo graphics kernel onto the 34010 for an upcoming trade show. Talk about deja vu all over again.

The TMS34010 was a fully independent processor that ran in it's own address space, a relatively small memory window being mapped into the host adress space for data transfer and control. You could program the word size from 1 to 32 bits. You could also read or write the arbitrary word size from or to an arbitrary bit address. Totally awesome! Quite an advantage in the mid-80s when pixels were smaller than bytes, and had to be read and written using shifts and bitwise logical operations. Processor speed on a high end PC AT was 10 mHz, so this provided a significant speed advantage.

Even though the herculean effort to design and port the Halo graphics kernel was a success, the TMS34010 never seemed to find widespread success in the graphics card market. I heard rumors of it being used in the unglamorous niche markets of fax machines and printers, where it's bit twiddling prowess would have provided a significant benefit. So to me the TMS34010 drifted out of thought, to be relegated to that twilight of yet another technology that was just too far ahead of its time.

So imagine my surprise when I heard the hobbyist was tinkering with an arcade game complete with 34010 processor on board. (Below are a closeup of the 34010 on the board and the entire arcade game board.) I've been meaning for years to transfer the 34010 compiler and other tools from the aging 5-1/4" floppies (with the gargantuan capacity of 360 KB!) Hopefully they still are readable. (I was told that VHS tapes would lose the image in a few years but I still have movies taped from HBO in 1984 that are still alive and well, so I'm optimistic.) I hope to make this page a resource for others trying to breathe life into an old 34010 system or trying to port 34010 code onto a more modern platform. I still have the 34010 programmer's manual (a fascinating architecture, a 32-bit word with Motorola like instructions and a scan line by scan line programmable palette) but whereas I may try to set up an old machine to read the floppies I can't see myself scanning the manual. Any links to a digital version of the programmer's manual would be awesome.

#110949 - 10/02/17 02:55 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Mar 2001
Posts: 15,752
R. Belmont Offline
R. Belmont  Offline

Very Senior Member

Joined: Mar 2001
Posts: 15,752
USA
Same guy posted this video: https://www.youtube.com/watch?v=730tmDmzeDE

There's a shadebobs-like effect in the video that well predates any demoscene version AFAIK, so that's interesting.

#110960 - 10/03/17 02:02 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: R. Belmont]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
Here's a rare unicorn that would be awesome to see in mame one day.



This was the Apple2 DTV before there was even a C64 DTV or a C64 mini.

#110961 - 10/03/17 02:35 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Mar 2001
Posts: 15,752
R. Belmont Offline
R. Belmont  Offline

Very Senior Member

Joined: Mar 2001
Posts: 15,752
USA
Oh, I'd *love* to see a dump of that thing.

#110962 - 10/03/17 03:21 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: Golden Child]  
Joined: Jan 2011
Posts: 161
Al Kossow Offline
Senior Member
Al Kossow  Offline
Senior Member

Joined: Jan 2011
Posts: 161
"I can't see myself scanning the manual."

wtf is the point, I did that 10+ years ago
he apparently has never heard of the 34020 either.

#110963 - 10/03/17 04:38 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: Golden Child]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
There's a cool gallery of the Tiger Learning computer and carts at:

https://juiced.gs/2012/01/tiger-learning-computer-gallery/

along with a shot of the motherboard.

#110971 - 10/04/17 11:56 AM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: Golden Child]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
I was trying to wrap my head around the code of how mame does its UI Paste function (and also the lua does its emu.keypost()) because the text pasting in the apple2e driver seems to scramble the input.

Grep is pretty useful to scan the whole source tree because I couldn't figure out where things are:

-r is recursive
-i is ignore case

Code
grep -r -i "keypost" src/
src/frontend/mame/luaengine.cpp: * emu.keypost(keys) - post keys to natural keyboard
src/frontend/mame/luaengine.cpp:	emu["keypost"] = [this](const char *keys){ machine().ioport().natkeyboard().post_utf8(keys); };
src/frontend/mame/mame.cpp:		std::string val = std::string("emu.keypost('").append(cmd).append("')");


grep -r -i "post_utf8" src/
src/emu/natkeyboard.cpp://  post_utf8 - post a UTF-8 encoded string
src/emu/natkeyboard.cpp:void natural_keyboard::post_utf8(const char *text, size_t length, const attotime &rate)
src/emu/natkeyboard.h:	void post_utf8(const char *text, size_t length = 0, const attotime &rate = attotime::zero);
src/frontend/mame/ui/ui.cpp:		machine().ioport().natkeyboard().post_utf8(text);
src/frontend/mame/luaengine.cpp:	emu["keypost"] = [this](const char *keys){ machine().ioport().natkeyboard().post_utf8(keys); };


grep -r -i "paste" src/
...
src/frontend/mame/ui/ui.h:	bool can_paste();
src/frontend/mame/ui/ui.h:	void paste();
src/frontend/mame/ui/ui.cpp://  can_paste
src/frontend/mame/ui/ui.cpp:bool mame_ui_manager::can_paste()
src/frontend/mame/ui/ui.cpp://  paste - does a paste from the keyboard
src/frontend/mame/ui/ui.cpp:void mame_ui_manager::paste()
src/frontend/mame/ui/ui.cpp:		// paste command
src/frontend/mame/ui/ui.cpp:		if (machine().ui_input().pressed(IPT_UI_PASTE))
src/frontend/mame/ui/ui.cpp:			paste();


and the actual paste code in ui.cpp:

//-------------------------------------------------
//  paste - does a paste from the keyboard
//-------------------------------------------------

void mame_ui_manager::paste()
{
	// retrieve the clipboard text
	char *text = osd_get_clipboard_text();

	// was a result returned?
	if (text != nullptr)
	{
		// post the text
		machine().ioport().natkeyboard().post_utf8(text);

		// free the string
		free(text);
	}
}





So it uses the natural keyboard mapping, and what's interesting is if I launch mame with the -natural option, I lose a lot of keyboard functionality.

./mame64 apple2e -natural

Ctrl+C, Ctrl+F doesn't work, left and right arrow don't work, ESC key doesn't work, and the @ disappear and various symbols are shifted.

Also it seems that the keyboard has gotten a lot slower in the "natural mode", there's a bunch of latency and it can't keep up with fast typing.

#110974 - 10/04/17 01:38 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Feb 2004
Posts: 1,864
Vas Crabb Online content
Very Senior Member
Vas Crabb  Online Content
Very Senior Member

Joined: Feb 2004
Posts: 1,864
Sydney, Australia
Natural keyboard mode will never work particularly well, since it's a pretty much impossible set of requirements. It's supposed to translate host character input to emulated keystrokes. Not all keystrokes produce characters, some characters require multiple keystrokes to produce, and IME edit opens another whole can of worms. It kinda works for simple cases, but it's always going to be something that's nice if it works at best.

#110976 - 10/04/17 01:42 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: Vas Crabb]  
Joined: May 2009
Posts: 1,602
Just Desserts Offline
Very Senior Member
Just Desserts  Offline
Very Senior Member

Joined: May 2009
Posts: 1,602
Sounds like something that should be implemented or enabled on a per-driver basis, then. Otherwise it seems like exactly the sort of half-baked, user-hostile, anti-feature that MAME is infamous for. It violates the hell out of the rule of least surprise.

#110978 - 10/04/17 02:11 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Feb 2004
Posts: 1,864
Vas Crabb Online content
Very Senior Member
Vas Crabb  Online Content
Very Senior Member

Joined: Feb 2004
Posts: 1,864
Sydney, Australia
Natural keyboard mode isn't enabled by default, you have to use -natural on command line or go into the menu and switch it on. It works a lot better than it used to provided the PORT_CHAR declarations for the driver are done properly. It also performs a bit better in 0.190 than it did before, as I eliminated an O(n) lookup, but the speed at which it generates keystrokes is still pretty conservative, as it has to work with some slow systems.

I had a quick look at the apple2e driver and it seems to have the wrong PORT_CHAR for a few keys, as though it was quickly copy/pasted from the Apple II+ and not fully updated (Apple II+ uses a "bitshift" style layout, while Apple IIe uses a "typewriter shift" style layout). I'm not going to mess with trying to make control keys work in natural mode, as that's problematic, but I've tried to at least fix the shifted digits and arrow keys in natural keyboard mode with 64ac8e4. I've only tried fixing the US Apple IIe and variants, not the UK, French and Spanish versions.

Note that the Apple II drivers are set up to translate uppercase letters to unshifted letter keys for natural keyboard/UI paste/keypost. If you type/paste/post lowercase letters, it will press the emulated shift key when typing each one.

#110983 - 10/04/17 05:31 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: Vas Crabb]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
Thanks Vas,

I just gave it a try and the missing characters type properly now in a paste. Yay!

#111004 - 10/09/17 11:58 AM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: Vas Crabb]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
I really wanted to have a proper "delay after a CR" during a paste so that after a CR, you'd have a delay while the computer would process the line of input.

If you have a key pressed too long on the Apple2e, it starts to auto repeat. So you want your delay AFTER the CR has been pressed and released.

Calling m_timer->adjust(choose_delay(m_buffer[m_bufbegin])); doesn't really give you a proper delay amount, especially since this function gets executed at least twice for each keypress/release.

I wrestled mightily with the function natural_keyboard::timer to get a delay that was "long" without triggering the autorepeat.

This function actually first "presses" all of the fields for a given keycode, then it releases them one by one each time it gets called after that. It seems really counter-intuitive. One of the things that really threw me for a loop is that it does things "reversed" like field->set_value(!m_status_keydown). m_status_keydown comes in as false, it sets all the fields, then it flips the m_status_keydown.

I haven't tested this very much, but it seems to work for the couple of pastes I've thrown at it.


Code
void natural_keyboard::timer(void *ptr, int param)
{

attotime next_delay = attotime::from_msec(20);  
	if (!m_queue_chars.isnull())
	{
		// the driver has a queue_chars handler
		while (!empty() && m_queue_chars(&m_buffer[m_bufbegin], 1))
		{
			m_bufbegin = (m_bufbegin + 1) % m_buffer.size();
			if (m_current_rate != attotime::zero)
				break;
		}
	}
	else
	{
		// the driver does not have a queue_chars handler

		// loop through this character's component codes
		const keycode_map_entry *const code = find_code(m_buffer[m_bufbegin]);
		bool advance;
		if (code)
		{
			do
			{
				assert(m_fieldnum < ARRAY_LENGTH(code->field));
				ioport_field *const field = code->field[m_fieldnum];
				if (field)
				{
					// special handling for toggle fields
					if (!field->live().toggle)
						field->set_value(!m_status_keydown);
					else if (!m_status_keydown)
						field->set_value(!field->digital_value());
				}
			}
			while (code->field[m_fieldnum] && (++m_fieldnum < ARRAY_LENGTH(code->field)) && m_status_keydown);
			advance = (m_fieldnum >= ARRAY_LENGTH(code->field)) || !code->field[m_fieldnum];

// if we're at a CR then let's set the next delay for 5 seconds
 if (m_status_keydown && (m_buffer[m_bufbegin] == '\r') && (advance)) next_delay = attotime::from_msec(5000);
		}
		else
		{
			advance = true;
		}

		if (advance)
		{
			m_fieldnum = 0;
			m_status_keydown = !m_status_keydown;

			// proceed to next character when keydown expires
			if (!m_status_keydown)
				m_bufbegin = (m_bufbegin + 1) % m_buffer.size();

		}
	}

       // m_status_keydown has already been flipped for the next invocation
	// need to make sure timerproc is called again if buffer not empty
	if (!empty())
m_timer->adjust(next_delay);

}


#111005 - 10/09/17 01:16 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: Just Desserts]  
Joined: Mar 2001
Posts: 15,752
R. Belmont Offline
R. Belmont  Offline

Very Senior Member

Joined: Mar 2001
Posts: 15,752
USA
Originally Posted by Just Desserts
Sounds like something that should be implemented or enabled on a per-driver basis, then. Otherwise it seems like exactly the sort of half-baked, user-hostile, anti-feature that MAME is infamous for. It violates the hell out of the rule of least surprise.


On the contrary, it's exactly the sort of user-friendliness you advocate: it changes the keyboard emulation from matching the layout of the original at the expense of what's actually marked on your PC keyboard to (attempting to) make it so e.g. shift-2 on a US keyboard is always @, even on machines where shift-2 is " or a UK pound sign or whatever. I would argue that having keys on your PC keyboard *not* generate the same thing on the emulated system is actually the major violation of least-surprise here. In particular, pretty much all other computer emulators *only* have an equivalent of natural keyboard mode.

#111006 - 10/09/17 01:31 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: May 2004
Posts: 1,398
Haze Offline
Very Senior Member
Haze  Offline
Very Senior Member

Joined: May 2004
Posts: 1,398
it's user unfriendly when it doesn't work for games etc. because it never really seems to register keys as held down, only 'pressed once' especially if they're shifted keys or whatever else..

while the idea is good in concept, the implementation of it is definitely horrible and acts in completely unexpected ways and how you toggle it on / off at runtime doesn't seem to be common knowledge either.



Last edited by Haze; 10/09/17 01:32 PM.
#111007 - 10/09/17 01:43 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Mar 2001
Posts: 15,752
R. Belmont Offline
R. Belmont  Offline

Very Senior Member

Joined: Mar 2001
Posts: 15,752
USA
Yes, we all agree the implementation sucks; it should hold down the keys on the emulated keyboard for the same amount of time that the user holds down the original key(s) etc. But the concept is pretty much industry-standard.

#111013 - 10/10/17 02:09 AM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Feb 2004
Posts: 1,864
Vas Crabb Online content
Very Senior Member
Vas Crabb  Online Content
Very Senior Member

Joined: Feb 2004
Posts: 1,864
Sydney, Australia
What are all the PC emulators doing "natural keyboard' translation? It definitely isn't VirtualBox or VMware - both of those map keys directly. DOSbox kind of does for DOS itself by virtue of the fact that it's HLE'ing the character input function, but when a program accesses the keyboard directly it reads the keys that are down directly.

It's impossible to hold the same amount of time, because there isn't a 1:1 correspondence between keys and characters. It's also impossible to "translate" modifiers since it's all over the shop with whether something uses a modifier or not. Let's use some real-world examples of why you can't do perfect translation.

Emulated system has a JIS "bitshift" keyboard, host system has a US "typewriter" layout keyboard:
  • User presses Right Shift
  • User presses 2 (on host this types an '@' character)
  • User releases 2
  • User releases RIght Shift


On the emulated system, typing '@' does not involve the shift key at all - it's the key to the right of P unshifted (this key has '[' on the host keyboard). So if you're trying to translate modifiers, what do you do? Press the emulated shift key, then release it for some amount of time before pressing the @ key, then press it again after releasing the emulated @ key?

Same emulated and host configurations:
  • User presses ' (on host this types a "single straight quote")
  • User releases '


The emulated system requires you to type Shift-7 to type a ' character. You're going to need to press the emulated shift key, wait long enough to ensure matrix scanning can detect it, press the emulated 7 key, and then release both keys.

It gets even messier with dead keys. Emulated system had a German DIN keyboard, host has Windows US International layout:
  • User presses Left Shift
  • User presses ' (on host system this initiates a dead key sequence)
  • User releases '
  • User releases Left Shift
  • User presses U (on host system this types ü because of the current dead key state)
  • User releases U


On the emulated system, this is a single keystroke - the key to the right of P, with no modifiers at all. You can't translate all the keystrokes leading up to the character being typed, because they don't actually produce characters.

What about a failed dead key sequence? Same emulated and host configurations:
  • User presses Left Shift
  • User presses ' (on host system this initiates a dead key sequence)
  • User releases '
  • User releases Left Shift
  • User presses X (on host system this types "x because there's no mapping for X in the current dead key state)
  • User releases X


You can't press the emulated keys for the " (shift-2) when the user starts the dead key sequence, because you can't anticipate the next character they'll type. You need to do the whole sequence when they press X.

You have no way of knowing whether the emulated system is running a game or other program that processes raw keystrokes and works best with everything passed through based on position, or it's running something accepting character input and you should translate characters to keystrokes. And what if it's both? You could be typing into a text editor while some other program is snooping the keyboard directly.

Also, if you want to be able to hold the key for a corresponding amount of time, you need to be doing key translation yourself. You don't get information on when a key is pressed/released from character input events. To be able to pass that through to the emulated system (assuming you had correspondence between keystrokes on both sides to begin with), you'd need to load the host system's keyboard layout, do translation from keystrokes to characters yourself, including dead key mapping, etc. and then pass it through. This would be a big mess of OS-dependent code, and it would have no chance of working at all for languages with IME edit.

If I'm completely missing something that makes this simple, please point it out to me. But I'm really sick of people saying natural keyboard is best and should work properly, when decades of dealing with multiple language support across operating systems tells me it's impossible to do in a satisfactory way, and what we've got now is about the best compromise we're going to get.

#111014 - 10/10/17 02:20 AM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: Golden Child]  
Joined: Feb 2004
Posts: 1,864
Vas Crabb Online content
Very Senior Member
Vas Crabb  Online Content
Very Senior Member

Joined: Feb 2004
Posts: 1,864
Sydney, Australia
Originally Posted by Golden Child
This function actually first "presses" all of the fields for a given keycode, then it releases them one by one each time it gets called after that. It seems really counter-intuitive. One of the things that really threw me for a loop is that it does things "reversed" like field->set_value(!m_status_keydown). m_status_keydown comes in as false, it sets all the fields, then it flips the m_status_keydown.


You've missed some of the subtlety - it presses the keys one-at-a-time with a delay between each to ensure there's time for matrix scanning to detect the modifiers before the character key is pressed. Without this, uppercase letters, shifted numbers etc. don't work on Amiga, Sun, RM Nimbus, and a host of other systems (I implemented this myself after over a year of complaints about it not working but none of the natural keyboard advocates addressing it). However it releases all the emulated keys at the same time - it doesn't wait for the timer to fire between releasing keys.

Yes, it's "dumb" in cases where a sequence of shifted keys are typed in a row - it presses and releases shift for each one - but making it "smarter" about this would complicated the code quite a bit.

The trouble with adding a delay on CR is it's going to be a real pain for actually typing into a text editor, and even at a command prompt, different commands all take different amounts of time.

#111018 - 10/10/17 12:48 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: Vas Crabb]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
Hi Vas,

Yes I think I've missed a lot of the subtlety of how it works and how it needs to work across a spectrum of different machines.

Perhaps some of the problem is trying to get the natural keyboard to do a paste function with the same routine that handles normal user input.

A paste doesn't have to be fast, it could be on its own timer (and buffer) and just feed its keystrokes into the natural keyboard's posting systems on its own timetable. Then you could do it as slowly as you wish and not affect the normal typing.

#111022 - 10/10/17 04:24 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Dec 1999
Posts: 1,162
Justin Offline
Very Senior Member
Justin  Offline
Very Senior Member

Joined: Dec 1999
Posts: 1,162
Vancouver Island, BC, Canada
I could have sworn this was all working in the (distant) past with natural keyboard mappings for apple2 (which I set up iirc) and a coded delay after carriage returns when pasting, I guess various refactorings over the years KO'd it.

#111023 - 10/10/17 05:59 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Mar 2001
Posts: 15,752
R. Belmont Offline
R. Belmont  Offline

Very Senior Member

Joined: Mar 2001
Posts: 15,752
USA
It can't work with a fixed delay, because Applesoft takes more or less an unbounded amount of time to process a line. (Up to the limits of what you can fit on one line, of course). You'd probably want to use something like CiderPress which can convert tokenized .BAS files to and from .TXT listing files.

#111040 - 10/12/17 12:25 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: R. Belmont]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
I thought I'd see if I could do something with lua and coroutines to feed keystrokes with delays.

So I create a lua coroutine to pump keystrokes from a buffer. It's called every frame and calls coroutine.yield() when it's done.

After a normal keystroke, it delays 3 frames. After a cr, it will delay 5*60 frames.

What's kind of cool about lua coroutines is that you can call them with parameters if you like. So to add text I call the coroutine with a parameter.

Just an experiment...


Code

-- you must initialize these globals or the routine won't work, any error in the coroutine kills it so coroutine.status is dead

keyfeed_buffer = ""
keydelay = -1
keyfeed_buffer_pos = 1

normalkeydelay = 3
crkeydelay = 5 * 60

function keyboard_feeder()
 while 1 do
   --print("going to yield")
   newparam = coroutine.yield()
   --print ("keyboard_feeder_coroutine")
   if newparam == nil then

      --print("keydelay" .. keydelay)
      if keydelay < 0 then  -- get the next character

      nextkeytofeed = string.sub(keyfeed_buffer,keyfeed_buffer_pos,keyfeed_buffer_pos)
      keyfeed_buffer_pos = keyfeed_buffer_pos+1
      emu.keypost(nextkeytofeed)
      
      if nextkeytofeed == "" then keydelay = -1; keyfeed_buffer  = ""; keyfeed_buffer_pos = 1
      elseif nextkeytofeed == "\n" then keydelay = crkeydelay
      else keydelay = normalkeydelay
      end

      else
         keydelay = keydelay -1
      end
   else 
      -- print("adding " .. newparam .. " to buffer");
      keyfeed_buffer=keyfeed_buffer .. newparam; 
      -- print(keyfeed_buffer);
   end -- if
 end -- while
end -- function


function call_keyboard_feeder()
   --print ("call keyboard feeder")
   coroutine.resume(keyboard_feeder_coroutine)
   --print ("done call keyboard feeder")
end

function add_text(newtext)
   coroutine.resume(keyboard_feeder_coroutine,newtext)
end

function register_keyboard_feeder()
   keyboard_feeder_coroutine=coroutine.create(keyboard_feeder)
   table.insert(dispatch_list,call_keyboard_feeder)   
end


dispatch_list = { }

function frame_dispatcher()
for index,my_func in pairs(dispatch_list) do  my_func() end
end

if already_registered_frame_dispatcher == nil then
   emu.register_frame(frame_dispatcher);
   already_registered_frame_dispatcher = 1
end

function cld()
dispatch_list = {}
end

print("type cld(); to stop a runaway dispatch");

cld()
register_keyboard_feeder()

add_text("this is a test of the emergency broadcast system.\n")
add_text("this is only a test.\n")
add_text("FEEDING 255 CHARACTERS.\n")
for i=1,255 do add_text(string.char(string.byte("0")+i%10)) end
add_text("\n")
add_text("That's 255 characters\n")

#111042 - 10/12/17 02:28 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Mar 2001
Posts: 15,752
R. Belmont Offline
R. Belmont  Offline

Very Senior Member

Joined: Mar 2001
Posts: 15,752
USA
If you're feeding from Lua, you should be able to check the Apple II zero page variables to determine when Applesoft is ready to accept input.

#111043 - 10/12/17 05:01 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: R. Belmont]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
Perhaps I could watch the PC of the apple and see when it hits the loop to accept user input. I don't know where it actually stores the buffer position in the zero page. I was thinking that it just kept it in the X register as far as I could tell.

I could register a function that would watch the PC.


for key,value in pairs(manager:machine().devices[":maincpu"].state) do print(key,value) end
PC sol.device_state_entry*: 0x55a370aea448
CURFLAGS sol.device_state_entry*: 0x55a370aea598
IR sol.device_state_entry*: 0x55a370ae9848
CURSP sol.device_state_entry*: 0x55a370aea848
P sol.device_state_entry*: 0x55a370ae9c48
SP sol.device_state_entry*: 0x55a370ae9998
CURPC sol.device_state_entry*: 0x55a370aeac48
A sol.device_state_entry*: 0x55a370aea198
GENPC sol.device_state_entry*: 0x55a370aead98
Y sol.device_state_entry*: 0x55a370ae9d98
X sol.device_state_entry*: 0x55a370aea048


print(manager:machine().devices[":maincpu"].state["PC"].value)
64903


Maybe I could even stuff the keys into the $200-2FF input buffer rather than going through posting keystrokes.

#111044 - 10/12/17 06:12 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Mar 2001
Posts: 15,752
R. Belmont Offline
R. Belmont  Offline

Very Senior Member

Joined: Mar 2001
Posts: 15,752
USA
That's an idea as well - put a whole line into the buffer, adjust the buffer position accordingly, and send an Enter keypress.

#111047 - 10/12/17 11:02 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Jan 2012
Posts: 688
crazyc Offline
Senior Member
crazyc  Offline
Senior Member

Joined: Jan 2012
Posts: 688
It's an Applesoft TAS!

Last edited by crazyc; 10/12/17 11:02 PM.
#111060 - 10/15/17 08:12 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Jan 2012
Posts: 774
rfka01 Offline
Senior Member
rfka01  Offline
Senior Member

Joined: Jan 2012
Posts: 774
Bavaria
Originally Posted by rfka01
Alive as ... a Do-Do

http://forum.classic-computing.de/index.php?page=Thread&threadID=11845

This thread contains the ROMs for an Apple II clone which has "Do-Do" as its signon message smile


Do-Do ROMs on the FTP and here ... now including the Chargen, thanks to Toshi on the German VzEkC forum

https://forum.classic-computing.org/index.php?page=Thread&postID=127185#post127185

GTAC/Do-Do ROMs

http://john.ccac.rwth-aachen.de:8000/patrick/MEWA48.htm

No pull request, as I couldn't get it beyond garbled text.

Last edited by rfka01; 10/15/17 08:12 PM.

NCR DMV- DEC Rainbow- Siemens PCD- ITT 3030-Oly People- Acorn A5000- Olivetti M20
#111101 - 10/17/17 06:06 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: Golden Child]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
I figured out why using the debugger memory view to change the TMS9918 registers doesn't work.

so I try to set the TMS registers by hand with the debugger memory view, but it doesn't have any effect.

Because when you do it with the debugger memory view, it doesn't update the corresponding member variables. So not only do you have to set the m_Regs[x] variable, you also have to change the member variables.

In the file src/devices/video/tms9928.cpp when you write the registers with tms9928a_device::change_register, it updates other variables inside the driver, so for register 0, it will update m_color and m_pattern. Likewise for other registers.


Code
void tms9928a_device::change_register(uint8_t reg, uint8_t val)
{

...
		switch (reg)
	{
	case 0:
		/* re-calculate masks and pattern generator & colour */
		if (val & 2)
		{
			m_colour = ((m_Regs[3] & 0x80) * 64) & (m_vram_size - 1);
			m_pattern = ((m_Regs[4] & 4) * 2048) & (m_vram_size - 1);
			update_table_masks();
		}
		else
		{
			m_colour = (m_Regs[3] * 64) & (m_vram_size - 1);
			m_pattern = (m_Regs[4] * 2048) & (m_vram_size - 1);
		}
		m_mode = ( (m_reva ? (m_Regs[0] & 2) : 0) | ((m_Regs[1] & 0x10)>>4) | ((m_Regs[1] & 8)>>1));
		if ((val ^ prev) & 1)
			update_backdrop();
		if (TRACE_MODE) logerror("TMS9928A('%s'): %s\n", tag(), modes[m_mode]);
		break;



So I load my vram dump into the TMS.

The values to load into the registers are as follows:

Code
reginitarray = {2,194,14,255,3,63,3,1}; for index,val in pairs(reginitarray) do print(index-1,string.format("%x",val)) end
0	2
1	c2
2	e
3	ff
4	3
5	3f
6	3
7	1



so I set by hand with the debugger:

TMS9918A VDP/:sl4:arcbd:arcbd_tms/0/m_Regs[0] to 2
TMS9918A VDP/:sl4:arcbd:arcbd_tms/0/m_Regs[1] to c2
TMS9918A VDP/:sl4:arcbd:arcbd_tms/0/m_pattern to 0 (address of the pattern table)
TMS9918A VDP/:sl4:arcbd:arcbd_tms/0/m_colour to 2000 (address of the color table)
TMS9918A VDP/:sl4:arcbd:arcbd_tms/0/m_nametbl to 3800 (address of the name table)
TMS9918A VDP/:sl4:arcbd:arcbd_tms/0/m_mode to 2 (graphics mode 2)

then I can see the bitmap display.

and if I further set:

TMS9918A VDP/:sl4:arcbd:arcbd_tms/0/m_spritepattern to 1800
TMS9918A VDP/:sl4:arcbd:arcbd_tms/0/m_spriteattribute to 1f80

then I can see the sprites.

And if you want some weird effects, just set m_pattern to 1 to 7 (something you could never have on real hardware) or to 1800 (where the sprite patterns are).



I can see a table with the items in lua but it's just a list of items with the corresponding number.

Code
for i,j in pairs(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items) do print(i,j) end
1/0/m_start.seconds	610
0/0/m_start.seconds	605
0/m_clock_scale	439
0/m_Regs[6]	437
0/m_pattern	448
0/m_colour	441
0/m_colourmask	442
0/m_palette	446
0/m_patternmask	449
0/m_Regs[7]	440
0/m_spriteattribute	450
0/m_spritepattern	451
0/m_FifthSprite	428
0/m_nametbl	445
0/m_Regs[1]	432
0/m_Regs[0]	431
0/0/m_enabled	594
1/0/m_enabled	602
1/0/m_start.attoseconds	609
0/0/m_start.attoseconds	601
1/0/m_param	606
0/0/m_param	598
0/m_ReadAhead	429
0/m_Regs[2]	433
0/m_unscaled_clock	452
1/00000000-0000ffff	673
1/0/m_period.seconds	608
0/0/m_period.seconds	600
0/m_Regs[4]	435
0/m_StatusReg	444
0/m_INT	427
1/0/m_expire.attoseconds	603
0/m_latch	447
0/0/m_expire.seconds	596
1/0/m_expire.seconds	604
0/0/m_period.attoseconds	599
0/m_clock	438
0/0/m_expire.attoseconds	595
1/0/m_period.attoseconds	607
0/m_mode	443
0/m_Regs[5]	436
0/m_Addr	425
0/m_Regs[3]	434



I wish that I could read/write these items with lua in the same way that I can read/write them with the debugger memory view window.

#111102 - 10/17/17 06:17 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: Golden Child]  
Joined: Jan 2012
Posts: 688
crazyc Offline
Senior Member
crazyc  Offline
Senior Member

Joined: Jan 2012
Posts: 688
try emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["1/0/m_start.seconds"]):read(offset) or :write(offset, newval) or :read_block(byte_offset, len).

Last edited by crazyc; 10/17/17 06:17 PM.
#111106 - 10/18/17 03:41 AM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: crazyc]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
Thank you, crazyc! That's exactly what I was looking for. Beauty!

#111107 - 10/18/17 02:42 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: Golden Child]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
So with emu.item I can do this:

Code
dofile("../../arcbd_load_vram.lua")

emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_Regs[0]"]):write(0,2)
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_Regs[1]"]):write(0,0xc2)
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_pattern"]):write(0,0)
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_colour"]):write(0,0x2000)
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_nametbl"]):write(0,0x3800)
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_mode"]):write(0,2)

emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_spritepattern"]):write(0,0x1800)
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_spriteattribute"]):write(0,0x1f80)




There's a couple of other properties of emu.item that are interesting too, like .size and .count that are interesting to examine.

Item "0/m_pattern" has a size of 2 and count 1 while item "0/m_Regs[0]" has size of 1 and count 1.

Item "1/00000000-0000ffff" has a size of 1 and count 65536, and I can read/write into the vram with it.

Very cool. This lua engine is awesome!


Code
for i,j in pairs(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items) do print(i,j) end
print(emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_pattern"]).size)
print(emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_pattern"]).count)
print(emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_Regs[0]"]).size)
print(emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_Regs[0]"]).count)
print(emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["1/00000000-0000ffff"]).size)
print(emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["1/00000000-0000ffff"]).count)

emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["1/00000000-0000ffff"]):write(0,255)
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["1/00000000-0000ffff"]):write(1,0xaa)
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["1/00000000-0000ffff"]):write(2,0x55)

print(emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["1/00000000-0000ffff"]):read(0))
print(emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["1/00000000-0000ffff"]):read(1))
print(emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["1/00000000-0000ffff"]):read(2))


#111108 - 10/18/17 03:02 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Jan 2012
Posts: 688
crazyc Offline
Senior Member
crazyc  Offline
Senior Member

Joined: Jan 2012
Posts: 688
Right, size is the native byte width of an entry (like sizeof()) while count is number of size width words. If there are any other mame internals that you think would be useful to access from lua let me know. Also, if you haven't looked at the Scripty Things thead above, there's some neat stuff in there (and maybe post some of your stuff in it too).

Last edited by crazyc; 10/18/17 03:05 PM.
#111110 - 10/18/17 07:53 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: crazyc]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
Thanks again, CrazyC!

I am having such a blast fiddling with lua and mame. I haven't had this much fun programming for a long time.

I am still learning lua but it's so forgiving. And the console has auto-completion. Awesome! TAB for the win! This is pure genius.


I haven't quite figured out what the difference is between : and .

According to something I read, "The colon is for implementing methods that pass self as the first parameter. So x:bar(3,4) should be the same as x.bar(x,3,4)."


To start up the machine if you have the debugger active:
Code
manager:machine().devices[":maincpu"]:debug():go() 


And in trying to figure out the syntax I invariably interchange : with .

Code
print(manager:machine().devices[":maincpu"]:debug())
sol.device_debug*: 0x559857771518


but if I call the same thing, without the colon syntax, it blows with a segfault.

Code
print(manager:machine().devices[":maincpu"].debug())
Segmentation fault (core dumped)




The console plug in history is only 10 entries, but we can fix that easily by changing the line in plugins/console.init.lua
ln.historysetmaxlen(10) to something like 30.

#111117 - 10/19/17 08:17 AM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: Golden Child]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
And one of the interesting things about older systems is that you often have to write your own routines to do graphics, like linedraws on the TMS9918. Drawing lines is actually pretty easy, just plot a pixel in the pattern memory by setting a bit, and set the color byte in the color memory.


[Linked Image]


Code
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_Regs[0]"]):write(0,2)
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_Regs[1]"]):write(0,0xc2)
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_pattern"]):write(0,0)
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_colour"]):write(0,0x2000)
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_nametbl"]):write(0,0x3800)
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_mode"]):write(0,2)
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_spritepattern"]):write(0,0x1800)
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_spriteattribute"]):write(0,0x1f80)
--set background to 4
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_Regs[7]"]):write(0,0xf4)

mem=manager:machine().devices[":sl4:arcbd:arcbd_tms"].spaces["vram"]

function plotpixel(screenaddr,x,y)
local byteaddr = screenaddr + math.floor(y/8) * 256 + (y % 8) + math.floor(x/8) * 8
if x>=0 and x <=255 and y>=0 and y <=191 then
mem:write_u8(byteaddr,mem:read_u8(byteaddr)| (1 << (7-(x%8))))
end
end


function plotcolor(screenaddr,x,y,colorfg)
local byteaddr = screenaddr + math.floor(y/8) * 256 + (y % 8) + math.floor(x/8) * 8
if x>=0 and x<=255 and y>=0 and y<=191 then
--foreground single color
mem:write_u8(byteaddr,(mem:read_u8(byteaddr)& 0x0) | (math.floor(colorfg) << (4)) )
end
end


function deltasign(x)
if x<0 then return -1
elseif x==0 then return 0
elseif x>0 then return 1
else return 0
end
end


function linedraw(x1,y1,x2,y2,colorfg)
-- using basic code converted to lua from:
-- https://rosettacode.org/wiki/Bitmap/Bresenham's_line_algorithm
--[[
 1500 REM === DRAW a LINE. Ported from C version
 1510 REM Inputs are X1, Y1, X2, Y2: Destroys value of X1, Y1
 1520 DX = ABS(X2 - X1):SX = -1:IF X1 < X2 THEN SX = 1
 1530 DY = ABS(Y2 - Y1):SY = -1:IF Y1 < Y2 THEN SY = 1
 1540 ER = -DY:IF DX > DY THEN ER = DX
 1550 ER = INT(ER / 2)
 1560 PLOT X1,Y1:REM This command may differ depending ON BASIC dialect
 1570 IF X1 = X2 AND Y1 = Y2 THEN RETURN
 1580 E2 = ER
 1590 IF E2 > -DX THEN ER = ER - DY:X1 = X1 + SX
 1600 IF E2 < DY THEN ER = ER + DX:Y1 = Y1 + SY
 1610 GOTO 1560
--]]

x1 = math.floor(x1)
x2 = math.floor(x2)
y1 = math.floor(y1)
y2 = math.floor(y2)
 dx = x2-x1
 dy = y2-y1
 sx = deltasign(dx)
 sy = deltasign(dy)
 local x = x1
 local y = y1
 local adx = math.abs(dx)
 local ady = math.abs(dy)
 local er,e2

if adx > ady then er =  adx 
else er = - ady
end 

er = math.floor(er / 2)

while 1 do
  plotpixel(0,x,y)
  plotcolor(8192,x,y,colorfg)
  if x == x2 and y == y2 then return end
  e2 = er
  if e2 > -adx then er = er - ady; x = x + sx  end
  if e2 <  ady then er = er + adx; y = y + sy  end
  if x<0 or x > 255 or y < 0 or y > 191 then return end
end  -- while
end -- function


function clearscreentms()
tms= manager:machine().devices[":sl4:arcbd:arcbd_tms"]
mem = tms.spaces["vram"]
local addr
for addr = 0,6143 do mem:write_u8(addr,0) end
end

function circlerandomcolor(step,size)
local i
for i=0,360,step do linedraw(128,96,128+math.cos(i/360*2*math.pi)*size,96+math.sin(i/360*2*math.pi)*size,math.floor(math.random()*15)) end
end

function initpatterntms()
local pat
for pat = 0,768-1 do
   mem:write_u8(pat+0x3800,pat % 256)
end
end


clearscreentms()
initpatterntms()
for i = 0,255,16 do linedraw(i,0,0,192,math.floor(i/16)) end
circlerandomcolor(1,50)
for i = 0,255,16 do linedraw(i,0,255,191,math.floor(i/16)) end

#111152 - 10/25/17 02:40 AM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: Golden Child]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
I wanted to see if I could rip atari 2600 graphics from the game Stampede, so I wrote a little lua script to dump the ram from the 2600.

I didn't know how much to grab, so I went for 4k. I now know that Stampede is a 2k cartridge.

Code
mem=manager:machine().devices[":maincpu"].spaces["program"]

-- read ram and save to a file

outfile = assert(io.open("2600_dump_file", "wb"))

for i=0x1000,0x2000-1 do
  outfile:write(string.char(mem:read_u8(i)))
end

assert(outfile:close())


and once you have the 2600_dump_file saved, you can run this script on the apple2e driver with -sl4 arcbd which will make the following display:

The horse animates and you can move it left right/up and down.


I always wondered why the legs of the horse had an interlaced effect. That's because of the HMOVEs so the legs can split and display wider than the 8 pixels in a byte.

[Linked Image]

Code
-- ==============================================================
-- read datablock from a file and close it

infile = assert(io.open("2600_dump_file", "rb"))

datablock = infile:read("*all")    

assert(infile:close())

-- ====================================================================

emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_Regs[0]"]):write(0,2)
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_Regs[1]"]):write(0,0xc2)
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_Regs[1]"]):write(0,0xc3) -- dbl size
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_pattern"]):write(0,0)
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_colour"]):write(0,0x2000)
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_nametbl"]):write(0,0x3800)
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_mode"]):write(0,2)
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_spritepattern"]):write(0,0x1800)
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_spriteattribute"]):write(0,0x1f80)
--set background to 4
emu.item(manager:machine().devices[":sl4:arcbd:arcbd_tms"].items["0/m_Regs[7]"]):write(0,0xf4)

mem=manager:machine().devices[":sl4:arcbd:arcbd_tms"].spaces["vram"]

function plotpixel(screenaddr,x,y)
local byteaddr = screenaddr + math.floor(y/8) * 256 + math.floor(y % 8) + math.floor(x/8) * 8
if x>=0 and x <=255 and y>=0 and y <=191 then
mem:write_u8(byteaddr,mem:read_u8(byteaddr)| (1 << (7-(x%8))))
end
end


function plotcolor(screenaddr,x,y,colorfg)
local byteaddr = screenaddr + math.floor(y/8) * 256 + math.floor(y % 8) + math.floor(x/8) * 8
if x>=0 and x<=255 and y>=0 and y<=191 then
--foreground single color
mem:write_u8(byteaddr,(mem:read_u8(byteaddr)& 0x0) | (math.floor(colorfg) << (4)) )
end
end

function deltasign(x)
if x<0 then return -1
elseif x==0 then return 0
elseif x>0 then return 1
else return 0
end
end

function linedraw(x1,y1,x2,y2,colorfg)
-- using basic code converted to lua from:
-- https://rosettacode.org/wiki/Bitmap/Bresenham's_line_algorithm

 x1 = math.floor(x1);x2 = math.floor(x2);y1 = math.floor(y1);y2 = math.floor(y2)
 dx = x2-x1; dy = y2-y1
 sx = deltasign(dx); sy = deltasign(dy)
 local x = x1; local y = y1
 local adx = math.abs(dx)
 local ady = math.abs(dy)
 local er,e2

if adx > ady then er =  adx 
else er = - ady
end 

er = math.floor((er / 2)+0.5)  -- INT rounding because math.floor rounding doesn't work for 1 pixel lines

while 1 do
  plotpixel(0,x,y)
  plotcolor(8192,x,y,colorfg)
  if x == x2 and y == y2 then return end
  e2 = er
  if e2 > -adx then er = er - ady; x = x + sx  end
  if e2 <  ady then er = er + adx; y = y + sy  end
  if x<0 or x > 255 or y < 0 or y > 191 then print("hit edge",x1,y1,x2,y2) return end
end  -- while
end -- function

function drawbox(x1,y1,x2,y2,col)
 linedraw(x1,y1,x2,y1,col)
 linedraw(x2,y1,x2,y2,col)
 linedraw(x2,y2,x1,y2,col)
 linedraw(x1,y2,x1,y1,col)
end


function clearscreentms()
tms= manager:machine().devices[":sl4:arcbd:arcbd_tms"]
mem = tms.spaces["vram"]
local addr
for addr = 0,6143 do mem:write_u8(addr,0) end
end

function initpatterntms()
local pat
for pat = 0,768-1 do
   mem:write_u8(pat+0x3800,pat % 256)
end
end

function initcolortms(fg,bg)
for addr = 0,6143 do mem:write_u8(addr+8192,bg|(fg<<4)) end end


function clstms()
clearscreentms()
initpatterntms()
initcolortms(15,4)
end

clstms()

function reversebits(x)
local outbyte = 0
for bit=0,7 do
  if(x & (1<<bit))~=0 then outbyte = outbyte | (1<<(7-bit)) end
end
return outbyte
end

function draw2600intoscreendirect()
for i=0,4096-1 do
  mem:write_u8(i,reversebits(string.byte(datablock,(i+1))))  -- datablock index starts at 1
end
end

clstms()

function draw2600intoscreen()
xpos = 0; ypos = 0
for i = 4096-1,4096-2048-1,-1 do
  for bit=0,7 do
    if (reversebits(string.byte(datablock,(i+1))) & (1<<bit))~=0 then linedraw(xpos+bit,ypos,xpos+bit,ypos,7) end
  end
  ypos = ypos + 1
  if ypos >= 128+16 then ypos = 0; xpos = xpos + 16; end
end
end

clstms()
draw2600intoscreen()

function stampededogie(p8d,p8f)
--linedraw(xpos,ypos,xpos,ypos,1)
for offset = 0xf,1,-1 do
grp1 =p8f+offset
hmove=p8d+offset-1
  for bit=0,7 do
    if (reversebits(string.byte(datablock,(grp1+1))) & (1<<bit))~=0 then linedraw(xpos+bit,ypos,xpos+bit,ypos,7) end
  end
  hmoveval = (string.byte(datablock,(hmove+1))>>4)
  if hmoveval >= 8 then hmoveval = hmoveval - 16 end
  xpos = xpos - hmoveval
  ypos = ypos + 1
  if ypos >= 128+64 then ypos = 128+32; xpos = xpos + 16; end
end
end

xpos = 32;       ypos = 128+48; stampededogie(0x6c9,0x67d);
xpos = 32+1*16;  ypos = 128+48; stampededogie(0x6c9,0x66e);
xpos = 32+2*16+6;ypos = 128+48; stampededogie(0x6ac,0x68b)

function stampede_horse(p8b,p8d,p8f) 
--p8b is ptr to hmp0, p8d is ptr to nusiz0, p8f is ptr to grp0
xpos = xpos + 32
ypos = 128+24
for offset=0x19,1,-1 do
grp0 =p8f+offset
hmove=p8b+offset-1  -- hmove happens to "next line"
nusiz=p8d+offset
-- follows the atari 2600 stampede code which ORs these 2 together
nusiz=string.byte(datablock,(nusiz+1)) | (string.byte(datablock,(hmove+1+1))&5)
nusiz=nusiz & 0xd
  if (nusiz & 7) == 5 then dbl=2 else dbl=1 end
  for bit=0,7 do
    if (reversebits(string.byte(datablock,(grp0+1))) & (1<<bit))~=0 then 
          linedraw(xpos+bit*dbl,ypos,xpos+(bit+1)*dbl-1,ypos,7+dbl)
    end
  end
  hmovedelta = (string.byte(datablock,(hmove+1))>>4)
  if hmovedelta >= 8 then hmovedelta = hmovedelta - 16 end
  xpos = xpos - hmovedelta
  ypos = ypos + 1
  if ypos >= 128+64 then ypos = 128+24; xpos = xpos + 32; end
end
end

xpos=64;      stampede_horse(0x74d,0x6c7,0x71a); 
xpos=64+1*32; stampede_horse(0x766,0x6c7,0x700); 
xpos=64+2*32; stampede_horse(0x74d,0x6c7,0x700); 
xpos=64+3*32; stampede_horse(0x77f,0x6c3,0x734);

function drawblock(addr,offset1,offset2)
ypos0 = ypos
for i=addr+offset1,addr+offset2,-1 do
  for bit=0,7 do
    if (reversebits(string.byte(datablock,(i+1))) & (1<<bit))~=0 then 
       linedraw(xpos+bit,ypos,xpos+bit,ypos,10)
    end
  end    
  ypos = ypos + 1
end
xpos = xpos + 8
ypos = ypos0
end

function stampede_activision()
drawblock(0x668,6,0) -- act
drawblock(0x660,6,0) -- iv
drawblock(0x658,6,0) -- isi
drawblock(0x650,6,0) -- on
end

xpos = 128; ypos= 128+56
stampede_activision()

function stampede_skull()
drawblock(0x69b,9,1)
end

xpos = 64;ypos = 128+20
stampede_skull()

function stampede_0123456789()
for num = 0,9 do
drawblock(0x600+num*8,6,0)
end
end

xpos = 0;  ypos = 128+30; stampede_0123456789()

function xytoaddress(x,y)
--print(x,y,math.floor(y/8)*256+(y%8)+math.floor(x/8)*8)
x = math.floor(x)
y = math.floor(y)
return math.floor(y/8)*256+(y%8)+math.floor(x/8)*8
end

for box=0,3 do drawbox(80+32*box,150,80+32*(box+1)-1,150+31,9) end

-- 4 different 16x16 blocks

bytepos=0x1800; 
for box = 0,3 do
for cellx = 0,1 do for celly = 0,1 do for j = 0,1 do for i=0,15 do mem:write_u8(bytepos,mem:read_u8(xytoaddress(80+8*j+16*cellx+box*32,150+i+16*celly))); bytepos = bytepos + 1; end end end end end


spriteatt = 0x1f80

horsex = 25
horsey = 25

scale = 2

function setsprite(sprnum,sprimgnum)
for celly = 0,1 do
for cellx = 0,1 do
mem:write_u8(spriteatt + cellx*2*4 + celly*4 + 0, horsey+16*celly*scale)
mem:write_u8(spriteatt + cellx*2*4 + celly*4 + 1, horsex+16*cellx*scale)
mem:write_u8(spriteatt + cellx*2*4 + celly*4 + 2,(cellx * 2 + celly)*4+16*sprimgnum)
mem:write_u8(spriteatt + cellx*2*4 + celly*4 + 3, 11)
end
end
end


setsprite(0,0)


dispatch_list={}


function frame_dispatcher()
for index,my_func in pairs(dispatch_list) do  my_func() end
end


function dispatch_list_remove(a_func)
for my_index,my_func in pairs(dispatch_list) do if my_func == a_func then table.remove(dispatch_list,my_index) end end
end

function print_dispatch_list() for my_index,my_func in pairs(dispatch_list) do print(my_func) end end



if already_registered_frame_dispatcher == nil then
   emu.register_frame(frame_dispatcher);
   already_registered_frame_dispatcher = 1
end

function cld()
dispatch_list = {}
end


delaycounter1 = 0
spriteimageseq = {0,1,2,1}
spriteimageseqnum = 1


function every_frame()
--  everydelay(1,delaycounter1)
  
  delaycounter1 = (delaycounter1+1)%5
  if delaycounter1 == 0 then 
           spriteimageseqnum = (((spriteimageseqnum + 1)-1) % #spriteimageseq)+1
  end

  inp = manager:machine():input()
  if inp:code_pressed(inp:code_from_token("KEYCODE_UP")) then 
     horsey = horsey - 2
   end

  if inp:code_pressed(inp:code_from_token("KEYCODE_DOWN")) then 
     horsey = horsey + 2
  end
      
  if inp:code_pressed(inp:code_from_token("KEYCODE_RIGHT")) then 
    horsex = horsex + 2
  end
  if inp:code_pressed(inp:code_from_token("KEYCODE_LEFT")) then 
    horsex = horsex - 2
  end


  setsprite(0,spriteimageseq[spriteimageseqnum])
  

end

table.insert(dispatch_list,every_frame)

#111210 - 11/01/17 12:02 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Mar 2001
Posts: 15,752
R. Belmont Offline
R. Belmont  Offline

Very Senior Member

Joined: Mar 2001
Posts: 15,752
USA
Coming soon....

[Linked Image]

It actually works except for detecting slot 6 and dropping the speed right now, so obviously the Disk II is unhappy with that smile

#111230 - 11/05/17 04:58 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: Golden Child]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
I finally figured out how to read the apple joystick from lua.

Code
-- this is a little function to print a table

function printt(a) local i,j; for i,j in pairs(a) do print(i,j) end end


 printt(manager:machine():ioport().ports)

:X5	sol.ioport_port*: 0x55d3d11cd778
:joystick_1_y	sol.ioport_port*: 0x55d3d11cd7f8
:X3	sol.ioport_port*: 0x55d3d11d2fa8
:keyb_special	sol.ioport_port*: 0x55d3d11cd958
:joystick_buttons	sol.ioport_port*: 0x55d3d11cd9c8
:joystick_2_y	sol.ioport_port*: 0x55d3d11cda38
:X7	sol.ioport_port*: 0x55d3d11cd698
:joystick_2_x	sol.ioport_port*: 0x55d3d11cdaa8
:a2_config	sol.ioport_port*: 0x55d3d11cd5b8
:X4	sol.ioport_port*: 0x55d3d11cd7b8
:joystick_1_x	sol.ioport_port*: 0x55d3d11cd548
:X2	sol.ioport_port*: 0x55d3d52ee878
:X1	sol.ioport_port*: 0x55d3d52ee8f8
:X8	sol.ioport_port*: 0x55d3d11cd628
:X0	sol.ioport_port*: 0x55d3d11d2cd8
:X6	sol.ioport_port*: 0x55d3d11cd708


and if you look at the apple2e.cpp code, you can see that it maps right up to this:

Code
	PORT_START("joystick_buttons")
	PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON1)  PORT_PLAYER(1)            PORT_CODE(KEYCODE_0_PAD)    PORT_CODE(JOYCODE_BUTTON1)
	PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_BUTTON2)  PORT_PLAYER(1)            PORT_CODE(KEYCODE_ENTER_PAD)PORT_CODE(JOYCODE_BUTTON2)
	PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON1)  PORT_PLAYER(2)            PORT_CODE(JOYCODE_BUTTON1)


so to read the buttons you can do:

Code
print(manager:machine():ioport().ports[":joystick_buttons"]:read())
0

and to test it in an if statement:

Code
if (manager:machine():ioport().ports[":joystick_buttons"]:read() & 0x10) ~= 0 then
  -- button 1 pressed
end
if (manager:machine():ioport().ports[":joystick_buttons"]:read() & 0x20) ~= 0 then
  -- button 2 pressed
end



The joystick axes come in under the names "joystick_1_x" and "joystick_1_y"

Looking at apple2e.cpp we have:
Code
static INPUT_PORTS_START( apple2_joystick )
	PORT_START("joystick_1_x")      /* Joystick 1 X Axis */
	PORT_BIT( 0xff, 0x80, IPT_AD_STICK_X) PORT_NAME("P1 Joystick X")
	PORT_SENSITIVITY(JOYSTICK_SENSITIVITY)
	PORT_KEYDELTA(JOYSTICK_DELTA)
	PORT_CENTERDELTA(JOYSTICK_AUTOCENTER)
	PORT_MINMAX(0,0xff) PORT_PLAYER(1)
	PORT_CODE_DEC(KEYCODE_4_PAD)    PORT_CODE_INC(KEYCODE_6_PAD)
	PORT_CODE_DEC(JOYCODE_X_LEFT_SWITCH)    PORT_CODE_INC(JOYCODE_X_RIGHT_SWITCH)

	PORT_START("joystick_1_y")      /* Joystick 1 Y Axis */
	PORT_BIT( 0xff, 0x80, IPT_AD_STICK_Y) PORT_NAME("P1 Joystick Y")
	PORT_SENSITIVITY(JOYSTICK_SENSITIVITY)
	PORT_KEYDELTA(JOYSTICK_DELTA)
	PORT_CENTERDELTA(JOYSTICK_AUTOCENTER)
	PORT_MINMAX(0,0xff) PORT_PLAYER(1)
	PORT_CODE_DEC(KEYCODE_8_PAD)    PORT_CODE_INC(KEYCODE_2_PAD)
	PORT_CODE_DEC(JOYCODE_Y_UP_SWITCH)      PORT_CODE_INC(JOYCODE_Y_DOWN_SWITCH)


and in lua we can read it with:

Code
print(manager:machine():ioport().ports[":joystick_1_x"]:read())
128
print(manager:machine():ioport().ports[":joystick_1_y"]:read())
128


Note that to get the input events for the joystick movement and buttons, the apple2e window must be selected.

So if you do a print(manager:machine():ioport().ports[":joystick_buttons"]:read()) from the lua console you will get zero unless you select the apple2e window, hold the joystick button(s), click on the lua console window and then do your print statement.

What's kind of interesting is that with the focus taken away from the window, the joystick and buttons will center or release but won't move away from center.

#111231 - 11/05/17 06:11 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Jan 2012
Posts: 688
crazyc Offline
Senior Member
crazyc  Offline
Senior Member

Joined: Jan 2012
Posts: 688
Note if you want to set the input port value you have to use field:set_value() not port:write().

#111232 - 11/06/17 01:16 AM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: crazyc]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
Cool, field:set_value seems to work for buttons.

Code
[MAME]> function printt(a) local i,j; for i,j in pairs(a) do print(i,j) end end
[MAME]> printt(manager:machine():ioport().ports[":joystick_buttons"].fields)
P1 Button 2	sol.ioport_field*: 0x55c6ff3a0d28
P2 Button 1	sol.ioport_field*: 0x55c6ff3a0d68
P1 Button 1	sol.ioport_field*: 0x55c6ff3a0ce8
[MAME]>  print(manager:machine():ioport().ports[":joystick_buttons"]:read())
0
[MAME]> manager:machine():ioport().ports[":joystick_buttons"].fields["P1 Button 2"]:set_value(1)
[MAME]> print(manager:machine():ioport().ports[":joystick_buttons"]:read())
32
[MAME]> manager:machine():ioport().ports[":joystick_buttons"].fields["P1 Button 2"]:set_value(0)
[MAME]>  print(manager:machine():ioport().ports[":joystick_buttons"]:read())
0


I thought I'd try it for a joystick axis value but it doesn't seem to have any effect. I removed the bindings to the second joystick too.

Code
manager:machine():ioport().ports[":joystick_2_y"].fields["P2 Joystick Y"]:set_value(0)
print(manager:machine():ioport().ports[":joystick_2_y"]:read())
128

Last edited by Golden Child; 11/06/17 01:42 AM.
#111235 - 11/06/17 11:12 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: rfka01]  
Joined: Jan 2012
Posts: 688
crazyc Offline
Senior Member
crazyc  Offline
Senior Member

Joined: Jan 2012
Posts: 688
Unfortunately analog fields are only read directly from the source, there isn't currently any way to override it.

#111236 - 11/07/17 08:55 AM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: Golden Child]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
I thought I'd see if I can have the arcade board's AY-3-8912 make some beeps.

But I need to have some delays or it doesn't work. Without delays everything happens all at once... so let's fiddle some more with coroutines.

The advantage of this is that we can call a delay() function.

So for example if you want

Code
for i = 1,60 do
  sound(7,24)
  settonevol(0,175,15)
  delay(2)  -- delays for 2 frames
  settonevol(0,175,0)
  delay(2)
end


then you call:

Code
add_func_string([[local i; for i=1,30 do sound(7,24); settonevol(0,175,8); delay(2); settonevol(0,175,0); delay(2); end ]])


and what's cool is that you can enter little tests from the command line quite easily with add_func_string.

Code

-- ===========================================================================
-- FRAME DISPATCHER

dispatch_list={}

function frame_dispatcher()
for index,my_func in pairs(dispatch_list) do  my_func() end
end


function dispatch_list_remove(a_func)
for my_index,my_func in pairs(dispatch_list) do if my_func == a_func then table.remove(dispatch_list,my_index) end end
end

function print_dispatch_list() for my_index,my_func in pairs(dispatch_list) do print(my_func) end end

print("type cld() and hit enter to stop a runaway dispatch")

if already_registered_frame_dispatcher == nil then
   emu.register_frame(frame_dispatcher);
   already_registered_frame_dispatcher = 1
end

function cld()
dispatch_list = {}
end


-- ===========================================================================
-- COROUTINE DISPATCHER

coroutine_frame_list = { }

function coroutine_frame_dispatch()
local i,thread
  for i,thread in pairs(coroutine_frame_list) do coroutine.resume(thread) end
  for i = #coroutine_frame_list,1,-1 do if coroutine.status(coroutine_frame_list[i]) == "dead" then table.remove(coroutine_frame_list,i) end end
end

function delay(frames)
  local f
  for f = 1,frames do coroutine.yield() end
end

function add_func_exec(myfunc)
local newthread
  newthread = coroutine.create(myfunc)
  table.insert(coroutine_frame_list,newthread)
end

function add_func_string(func_string)
local newfunc
  newfunc = assert(loadstring(func_string))
  if newfunc ~= nil then add_func_exec(newfunc) end
end 




function addco()
-- once you clear your dispatch list, you must add the coroutine_frame_dispatch
-- to get the coroutine_dispatch to work
table.insert(dispatch_list,coroutine_frame_dispatch)
end


cld()
addco()


function lobyte(x)
 return x & 255
end
function hibyte(x)
  return (x & (255<<8))>>8
end

function checkrange(x,lo,hi)
if not(x >= lo and x <= hi) then print("checkrange failed ",x,lo,hi); return false 
else return true; end
end


aystr = ":sl7:ssprite:ssprite_ay"
aystr = ":sl4:arcbd:arcbd_ay"

function sound(regnum,value)
emu.item(manager:machine().devices[aystr].items["0/m_regs"]):write(regnum,value)
end



function settone(chan,tone)
  if checkrange(chan,0,2) then
    regnum = chan*2  
    sound(regnum,lobyte(tone))
    sound(regnum+1,hibyte(tone))
  end
end

function setvol(chan,vol)
  if checkrange(chan,0,2) then
    regnum = chan+8  
    sound(regnum,vol)
  end
end

function settonevol(chan,tone,vol)
  settone(chan,tone)
  setvol(chan,vol)
end

-- two different ways to add a function, pass a function to add_func_exec
-- or pass add_func_string a string and if you use double brackets you don't have to escape the quotes

add_func_exec(function () local i; for i = 1,10 do print("yoyo",i);delay(5);end end)

add_func_string("local i; for i=1,15 do print(\"hello\",i);delay(5); end")


-- sound(7,24) turns on sound ABC and turns off the noise channels

add_func_string([[local d; local i; for d = 1,4 do print("delay="..d) for i=1,30 do sound(7,24); settonevol(0,175,8); delay(d); settonevol(0,175,0); delay(d); end end ]])




Last edited by Golden Child; 11/07/17 09:06 AM.
#111260 - 11/11/17 01:04 PM Re: 8bit Apples - Apple I, II, /// and the 16 bit GS [Re: Golden Child]  
Joined: Feb 2014
Posts: 94
Golden Child Offline
Member
Golden Child  Offline
Member

Joined: Feb 2014
Posts: 94
I wanted to see if I could reproduce the apple 2 beep sound with the AY-3-8912. It's supposed to be around 1000hz, but that doesn't sound quite right if I'm using the apple2e driver as a reference.

Reading some Synetix SuperSprite documentation (Synetix SuperSprite Owners Manual.pdf page 40 of 266) it says that I just have to divide 63920.438 by the desired pitch.

Tone Period =1,022,727 / 16 X desired pitch
= 63,920.438 / desired pitch

so let's make a little function to calculate the tone:

Code
function calctone(freq)
return math.floor (63920.438 / freq)
end



then I can make something that sounds pretty close to the CTRL+G bell.

I came up with around 930 hz just by listening to the tone and hunting for a number that was close.

Code
add_func_string([[for i=0,0 do sound(7,24);settonevol(0,calctone (930),15); delay(6); settonevol(0,0,0); delay(1); end print("done")]])



but how close is that actually?

I fired up mame with the debugger and set a watchpoint on $c030 with

Code
wpset c030,1,r 


and then typed g in the debug window.

Once the boot beep hit c030 I went to the lua console and typed:

Code
a = emu.time()

then hit g again in the debugger, and then got the time at that point:

Code
b = emu.time()


so how long did that take?

Code
print(b-a)

0.00053435114503789


so let's convert that to hertz:

Code
print(1/(b-a))
1871.4285714295


oh but wait, it should be half that since we've only counted half a tone cycle

Code
print(1/(b-a)/2)
935.71428571477


which I got pretty darn close to, 930 vs 936. Not bad for someone who's tone deaf.

Now I've got a beep that is pretty much identical.



Code
add_func_string([[for i=0,0 do sound(7,24);settonevol(0,calctone (936),15); delay(6); settonevol(0,0,0); delay(1); end print("done")]])

Last edited by Golden Child; 11/11/17 01:12 PM.
Page 1 of 12 1 2 3 11 12

Who's Online Now
2 registered members (Edstrom, 1 invisible), 15 guests, and 3 spiders.
Key: Admin, Global Mod, Mod
Shout Box
Forum Statistics
Forums9
Topics8,435
Posts109,387
Members4,764
Most Online225
May 26th, 2014
Powered by UBB.threads™ PHP Forum Software 7.6.0
Page Time: 0.096s Queries: 14 (0.013s) Memory: 6.1450 MB (Peak: 7.2774 MB) Zlib enabled. Server Time: 2017-11-18 12:16:53 UTC