Home Page

8bit Apples - Apple I, II, /// and the 16 bit GS

Posted By: rfka01

8bit Apples - Apple I, II, /// and the 16 bit GS - 11/29/16 08:27 PM

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
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and GS - 11/29/16 08:35 PM

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
Posted By: rfka01

Re: 8bit Apples - Apple I, II, /// and GS - 11/29/16 08:42 PM

noted and reflected in the edited title smile
Posted By: robcfg

Re: 8bit Apples - Apple I, II, /// and GS - 11/29/16 09:04 PM

I'm after a friend of mine to dump a german IIe.

Will be telling you when I achieve it.
Posted By: rfka01

Re: 8bit Apples - Apple I, II, /// and GS - 11/29/16 09:16 PM

@robcfg
A quick search shows the ROMs for a German IIe are available.
Posted By: robcfg

Re: 8bit Apples - Apple I, II, /// and GS - 11/29/16 10:53 PM

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.
Posted By: rfka01

Re: 8bit Apples - Apple I, II, /// and GS - 11/29/16 11:02 PM

True dat smile
Posted By: rfka01

Re: 8bit Apples - Apple I, II, /// and GS - 03/02/17 06:30 PM

This thread

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

has links to Ramfast SCSI ROMs.
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and GS - 03/02/17 07:18 PM

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
Posted By: rfka01

Konan David Jr II - 05/01/17 06:19 PM

Konan David Jr II

I bought this as an Apple II winchester controller, looks like it was used in the SyMBfile hardiskks among others.

Konan David Jr II Winchester controller

http://quartdepomme.fr/quartdepomme.../Symbiotic_%26_Hard_drive_ICE_10_Mb.html

http://bitsavers.informatik.uni-stuttgart.de/pdf/konan/Konan_David_Junior_II_Reference_Aug83.pdf

http://www.computinghistory.org.uk/det/19277/Symbfile-Hard-Disk-for-Apple-II/
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and GS - 05/11/17 01:25 PM

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.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and GS - 05/14/17 10:32 AM

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]
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and GS - 05/14/17 04:10 PM

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.
Posted By: rfka01

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/21/17 05:50 PM

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.
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/21/17 06:25 PM

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.
Posted By: peter ferrie

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/23/17 11:50 PM

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.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/24/17 06:38 PM

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]
Posted By: peter ferrie

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/24/17 10:51 PM

It's likely to be same issue, but caused by another switch access which I overlooked.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/25/17 01:38 AM

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
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/25/17 01:38 PM

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.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/25/17 03:27 PM

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
Posted By: peter ferrie

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/25/17 06:55 PM

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.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/26/17 12:35 PM

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]
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/27/17 11:55 AM

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]
Posted By: peter ferrie

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/01/17 02:01 AM

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.
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/01/17 12:14 PM

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).
Posted By: rfka01

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/01/17 05:52 PM

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
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/06/17 08:12 AM

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:

Posted By: Vas Crabb

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/06/17 08:23 AM

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.
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/06/17 12:09 PM

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.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/06/17 03:49 PM

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.
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/06/17 04:23 PM

2.67 i5 should be fine. Do you have some background process that's using a lot of CPU?
Posted By: anikom15

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/06/17 04:37 PM

I know if I don't plug in my laptop, CPU governing kills performance on Windows.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/06/17 05:07 PM

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.

Posted By: Vas Crabb

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/07/17 09:31 AM

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.
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/07/17 12:58 PM

-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.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/07/17 04:25 PM

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)
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/11/17 10:01 AM

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]
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/11/17 12:13 PM

Yes, that's known. It'll get fixed whenever we end up doing correct NTSC decoding in-line.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/12/17 01:57 AM

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.
Posted By: Pernod

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/12/17 02:02 AM

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.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/12/17 04:03 AM

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
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/12/17 02:15 PM

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.
Posted By: peter ferrie

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/12/17 11:47 PM

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.
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/12/17 11:54 PM

Great, thanks Peter!
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/14/17 07:50 PM

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.
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/14/17 08:47 PM

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.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/14/17 10:54 PM

Thanks for your help, RB. I am sure enjoying playing with the apple2e driver, especially now with no pops 8-)
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/23/17 08:33 PM

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?
Posted By: seanriddle

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/23/17 10:30 PM

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.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/24/17 01:22 AM

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.

Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/24/17 01:03 PM

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?
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/24/17 02:08 PM

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.
Posted By: Vas Crabb

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/24/17 02:31 PM

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.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/24/17 03:53 PM

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.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/24/17 06:08 PM

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)
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/25/17 12:00 AM

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
Posted By: Vas Crabb

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/25/17 01:54 AM

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.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/26/17 12:33 PM

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                                         
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/26/17 10:33 PM

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")


Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/26/17 11:55 PM

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
Posted By: crazyc

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/27/17 12:13 AM

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.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/27/17 03:29 PM

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
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/27/17 03:37 PM

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.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/27/17 05:01 PM

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

Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/27/17 07:47 PM

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)
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/28/17 05:19 PM

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
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/28/17 06:21 PM

That's really awesome. I'm glad to see someone combining MAME capabilities in unexpected-to-us ways smile
Posted By: Vas Crabb

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/29/17 09:59 AM

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
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/29/17 04:03 PM

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);");

Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/29/17 07:13 PM

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


Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/30/17 10:13 PM

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)
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 10/02/17 07:51 AM

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

Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 10/02/17 12:34 PM

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.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 10/02/17 12:59 PM

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.
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 10/02/17 02:55 PM

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.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 10/03/17 02:02 PM

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.
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 10/03/17 02:35 PM

Oh, I'd *love* to see a dump of that thing.
Posted By: Al Kossow

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 10/03/17 03:21 PM

"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.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 10/03/17 04:38 PM

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.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 10/04/17 11:56 AM

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.
Posted By: Vas Crabb

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 10/04/17 01:38 PM

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.
Posted By: Just Desserts

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 10/04/17 01:42 PM

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.
Posted By: Vas Crabb

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 10/04/17 02:11 PM

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.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 10/04/17 05:31 PM

Thanks Vas,

I just gave it a try and the missing characters type properly now in a paste. Yay!
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 10/09/17 11:58 AM

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);

}

Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 10/09/17 01:16 PM

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.
Posted By: Haze

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 10/09/17 01:31 PM

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.


Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 10/09/17 01:43 PM

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.
Posted By: Vas Crabb

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 10/10/17 02:09 AM

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.
Posted By: Vas Crabb

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 10/10/17 02:20 AM

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.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 10/10/17 12:48 PM

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.
Posted By: Justin

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 10/10/17 04:24 PM

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.
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 10/10/17 05:59 PM

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.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 10/12/17 12:25 PM

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")
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 10/12/17 02:28 PM

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.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 10/12/17 05:01 PM

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.
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 10/12/17 06:12 PM

That's an idea as well - put a whole line into the buffer, adjust the buffer position accordingly, and send an Enter keypress.
Posted By: crazyc

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 10/12/17 11:02 PM

It's an Applesoft TAS!
Posted By: rfka01

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 10/15/17 08:12 PM

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.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 10/17/17 06:06 PM

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.
Posted By: crazyc

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 10/17/17 06:17 PM

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).
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 10/18/17 03:41 AM

Thank you, crazyc! That's exactly what I was looking for. Beauty!
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 10/18/17 02:42 PM

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))

Posted By: crazyc

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 10/18/17 03:02 PM

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).
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 10/18/17 07:53 PM

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.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 10/19/17 08:17 AM

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
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 10/25/17 02:40 AM

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)
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 11/01/17 12:02 PM

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
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 11/05/17 04:58 PM

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.
Posted By: crazyc

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 11/05/17 06:11 PM

Note if you want to set the input port value you have to use field:set_value() not port:write().
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 11/06/17 01:16 AM

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
Posted By: crazyc

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 11/06/17 11:12 PM

Unfortunately analog fields are only read directly from the source, there isn't currently any way to override it.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 11/07/17 08:55 AM

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 ]])



Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 11/11/17 01:04 PM

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")]])
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 11/22/17 02:24 PM

One of the things I'm terrible at is counting cpu cycles.

So let's figure out how many cycles it takes to do the system beep, and while we're at it figure out what the cpu clock is.

How can we get the totalcycles?
./mame64 apple2e -plugin console -debug

Just ask the debugger to print the totalcycles.

Immediately after boot, if we ask the debugger for totalcycles we get:

Code
>print totalcycles
3


so how to get that value into a variable in lua?

Code
function getcycles() 
  dbg = manager:machine():debugger()
  dbg:command("print totalcycles") 
  lastline = dbg.consolelog[#dbg.consolelog] 
  cycles = tonumber(lastline,16) 
  return cycles
end


and a single line version to paste at the lua console:

Code
function getcycles() dbg = manager:machine():debugger() dbg:command("print totalcycles")   lastline = dbg.consolelog[#dbg.consolelog]   cycles = tonumber(lastline,16)   return cycles end

so let's set a watchpoint and then go:

Code
dbg = manager:machine():debugger()
dbg:command("wpset c030,1,rw")
dbg:command("g")


so we've hit the first click of the speaker so get the time and the cycles:

Code
a = emu.time(); cyclesa = getcycles()


so let's get the next click:

Code
dbg:command("g")
b = emu.time(); cyclesb = getcycles()

print(cyclesb-cyclesa)

546


and remember that it's a half cycle (since the c030 inverts the speaker) so we multiply by 2


and if we do a little math we can get the system clock:


Code
[MAME]> print(1/((b-a)/(cyclesb-cyclesa)))
1021800.0000005
[MAME]> print((cyclesb-cyclesa)*2)
1092
[MAME]> print(1021800/1092)
935.71428571429
[MAME]> 


and sure enough the cpu clock corresponds exactly to the source code that defines the cpu frequency

Code
static MACHINE_CONFIG_DERIVED( apple2ee, apple2e )
	MCFG_CPU_REPLACE("maincpu", M65C02, 1021800)        /* close to actual CPU frequency of 1.020484 MHz */
	MCFG_CPU_PROGRAM_MAP(apple2e_map)
MACHINE_CONFIG_END



One of the things that baffled me for a bit was why the system clock for the Atari 2600 would come up as not matching the source code exactly:


Code
MAME debugger version 0.191 (mame0191-183-g346a935839-dirty)
Currently targeting a2600 (Atari 2600 (NTSC))
[MAME]> function getcycles() dbg = manager:machine():debugger() dbg:command("print totalcycles")   lastline = dbg.consolelog[#dbg.consolelog]   cycles = tonumber(lastline,16)   return cycles end


[MAME]> a = emu.time(); acycles=getcycles()
[MAME]> 
3
[MAME]> dbg:command("step")
[MAME]> b = emu.time(); bcycles=getcycles()
[MAME]> 
5

print((bcycles-acycles)/(b-a))
1193181.0000007

print((bcycles-acycles)/(b-a)*3)
3579543.0000022

print(3579545/3)
1193181.6666667



so why doesn't 3579543 match up with 3579545? Finally I realized that there's some rounding taking place that converts (3579543/3) = 1193181.6666667 into 1193181.0 because the machines take an integer value for the frequency and that accounts for the discrepancy (bye bye fractional part).

Code

#define MASTER_CLOCK_NTSC   3579545

static MACHINE_CONFIG_START( a2600 )
	/* basic machine hardware */
	MCFG_CPU_ADD("maincpu", M6507, MASTER_CLOCK_NTSC / 3)
Posted By: crazyc

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 11/22/17 02:28 PM

dbg.consolelog:__len() == #dbg.consolelog
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 11/22/17 02:48 PM

Originally Posted by crazyc
dbg.consolelog:__len() == #dbg.consolelog


I didn't think anyone would see that. Post edited 8-)
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 11/22/17 02:59 PM

Are there any "bad" side-effects to enabling SOL_CHECK_ARGUMENTS in luaengine.h aside from performance reasons?

Code
#define SOL_CHECK_ARGUMENTS
#include "sol2/sol.hpp"


I inevitably type . instead of : and get a segfault.

For example:

Code
print((manager:machine():debugger().consolelog:__len()))
2


but if I change the : to a ., then kaboom.

Code
print((manager:machine():debugger().consolelog.__len()))
Segmentation fault (core dumped)

and if I uncomment #define SOL_CHECK_ARGUMENTS
it will gracefully give me an error.

Code
print((manager:machine():debugger().consolelog.__len()))
error: 	[string "print((manager:machine():debugger().consolelo..."]:1: stack index 1, expected userdata, received no value



according to:

https://github.com/ThePhD/sol2/issues/408

Quote

ThePhD commented on May 19

Please turn on the safety features. This will crash your code with a specific error message. You can turn on the most important safety feature by definining SOL_CHECK_ARGUMENTS either VIA command line or by putting it before every single <sol.hpp> include.

The segfault is intentional at this level. If you do not turn on safety features we assume that you are doing so for performance reasons and do not want the (small, but sometimes important to people) overhead, or because you expect certain kinds of type punning to happen (e.g., like the many type-puns the MAME engine does in order to fiddle with bits and mess with other low-level things).
Posted By: crazyc

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 11/22/17 03:06 PM

There shouldn't be any issues enabling that.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 11/22/17 03:22 PM

Originally Posted by crazyc
There shouldn't be any issues enabling that.


Cool. That was one of the things that would crash when I'd experiment.

Now I just have to remember not to try to copy with CTRL+C in the mame console. kaboom! Old habits die hard.


Interestingly, if I type CTRL+V (for paste) I see a ^V in the console, but it takes two deletes to remove it.

If I only delete once after hitting CTRL+V I get this "unexpected symbol" and I could not figure out why my command didn't work.

type print("hello") then CTRL+V and then delete once, the command line looks ok, but there's a bizarro character at the end.

This is with Ubuntu terminal console.

Code
print("hello")
error: 	[string "print("hello")"]:1: unexpected symbol near '<\127>'




I can edit the plugins/console/init.lua and add this line:

Code
local ln = require("linenoise")
ln_global = ln


so I can access the linenoise as the global variable ln_global and then I can save the history as:

Code
ln_global.savehistory("mysavehistoryln.txt")


and loading that into a text editor I can see that there's a strange 007F character at the end.


Is there an easy way of accessing the actual linenoise history entries, like a "history" command in bash, for example?

If I type ln_global. and then hit TAB to complete I get:

Code
ln_global.                                  

addcompletion
clearscreen
sethistorymaxlen
linenoise
lines
historysave
line
preload
loadhistory
savehistory
setcompletion
addhistory
refresh
historyadd
historysetmaxlen
historyload



But none of those seem to give me access to the actual history.


edit:
Hmmm, why not savehistory to /dev/stdout, that seems to work.

Code
ln_global.savehistory("/dev/stdout")

Posted By: crazyc

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 11/22/17 03:56 PM

The linenoise function char **linenoiseHistory(int *len) provides access to the history but it's not passed to lua in to lua-linenoise. If you can add it that'd be great, it shouldn't be hard to do.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 11/22/17 04:12 PM

Originally Posted by crazyc
The linenoise function char **linenoiseHistory(int *len) provides access to the history but it's not passed to lua in to lua-linenoise. If you can add it that'd be great, it shouldn't be hard to do.


sounds like an interesting idea, I'll give it a shot.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 11/22/17 10:41 PM


I took a stab at adding it to linenoise.c, this seems to work. Cool!

Code
static int l_gethistorytable(lua_State *L)
{
    int i,j;
    char ** phist;
    int lenhist = linenoiseHistoryGetMaxLen();

    phist = linenoiseHistory(&lenhist); 

    lua_newtable(L);
    i = 1;

    for (j=0; j<lenhist; j++){

        /* create result table */
        lua_pushnumber(L, i++);  /* push key */
        lua_pushstring(L, (char *)*(phist+j));  /* push value */
        lua_settable(L, -3);  /* adds key and value to table on top of stack */
      }
      return 1;  /* table is already on top */
}

luaL_Reg linenoise_funcs[] = {
    { "linenoise", l_linenoise },
    { "historyadd", l_historyadd },
    { "historysetmaxlen", l_historysetmaxlen },
    { "historysave", l_historysave },
    { "historyload", l_historyload },
    { "clearscreen", l_clearscreen },
    { "setcompletion", l_setcompletion},
    { "addcompletion", l_addcompletion },
    { "preload", l_preloadbuffer },
    { "refresh", l_refresh },

    /* Aliases for more consistent function names */
    { "addhistory", l_historyadd },
    { "sethistorymaxlen", l_historysetmaxlen },
    { "savehistory", l_historysave },
    { "loadhistory", l_historyload },

    { "line", l_linenoise },
    { "lines", l_lines },

    { "gethistory", l_gethistorytable},  // added function to gethistory
    { NULL, NULL }
};



I think you don't see the current command in the history list because it gets added after it gets executed.

Code
MAME debugger version 0.191 (mame0191-183-g346a935839-dirty)
Currently targeting a2600 (Atari 2600 (NTSC))
[MAME]> print(#ln_global.gethistory())
0
[MAME]> print(#ln_global.gethistory())
1
[MAME]> function printt(a) local i,j; for i,j in pairs(a) do print(i,j) end end

[MAME]> printt(ln_global.gethistory())
1	print(#ln_global.gethistory())
2	function printt(a) local i,j; for i,j in pairs(a) do print(i,j) end end

[MAME]> printt(ln_global.gethistory())
1	print(#ln_global.gethistory())
2	function printt(a) local i,j; for i,j in pairs(a) do print(i,j) end end
3	printt(ln_global.gethistory())
[MAME]> 
Posted By: Vas Crabb

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 11/23/17 05:23 AM

Originally Posted by Golden Child
Interestingly, if I type CTRL+V (for paste) I see a ^V in the console, but it takes two deletes to remove it.

If I only delete once after hitting CTRL+V I get this "unexpected symbol" and I could not figure out why my command didn't work.

type print("hello") then CTRL+V and then delete once, the command line looks ok, but there's a bizarro character at the end.

This is with Ubuntu terminal console.

Code
print("hello")
error: 	[string "print("hello")"]:1: unexpected symbol near '<\127>'



Ctrl-V means "interpret the next character literally", so Ctrl-V Ctrl-C will type a literal ETX character rather than sending SIGINT, Ctrl-V Delete will type a literal DEL rather than deleting the previous character, etc.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 11/23/17 08:21 AM

Originally Posted by Vas Crabb

Ctrl-V means "interpret the next character literally", so Ctrl-V Ctrl-C will type a literal ETX character rather than sending SIGINT, Ctrl-V Delete will type a literal DEL rather than deleting the previous character, etc.


Ohhhh, now that makes perfect sense. That explains why if I'd type Ctrl+v Return that I'd get a ^M or Ctrl+v left arrow I'd get ESC [ D. So that's why I'd get an 007F character from Ctrl+V DEL.

I guess that's a keystroke from VIM.

And sure enough, the code in 3rdparty/linenoise/linenoise.c is pretty straightforward.

Code
    case ctrl('V'):    /* ctrl-v */
            if (has_room(current, 3)) {
                /* Insert the ^V first */
                if (insert_char(current, current->pos, c)) {
                    refreshLine(current->prompt, current);
                    /* Now wait for the next char. Can insert anything except \0 */
                    c = fd_read(current);

                    /* Remove the ^V first */
                    remove_char(current, current->pos - 1);
                    if (c != -1) {
                        /* Insert the actual char */
                        insert_char(current, current->pos, c);
                    }
                    refreshLine(current->prompt, current);
                }
            }
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 11/23/17 09:29 AM

So while we're at it, why not do a historygetmaxlen too:

Code
static int l_gethistorytable(lua_State *L)
{
    int i,j;
    char ** phist;
    int lenhist = linenoiseHistoryGetMaxLen();

    phist = linenoiseHistory(&lenhist); 

    lua_newtable(L); /* put a table on the stack */
    i = 1;

    for (j=0; j<lenhist; j++){
        /* create result table */
        lua_pushnumber(L, i++);  /* push key */
        lua_pushstring(L, phist[j]);  /* push value */
        lua_settable(L, -3);  /* adds key and value to table at position 3 from top of stack */
      }
      return 1;  /* table is already on top */
}


static int l_historygetmaxlen(lua_State *L)
{
      lua_pushinteger(L, linenoiseHistoryGetMaxLen());  /* push max len on stack */
      return 1;  /* number of items on stack */
}

luaL_Reg linenoise_funcs[] = {
    { "linenoise", l_linenoise },
    { "historyadd", l_historyadd },
    { "historysetmaxlen", l_historysetmaxlen },
    { "historysave", l_historysave },
    { "historyload", l_historyload },
    { "clearscreen", l_clearscreen },
    { "setcompletion", l_setcompletion},
    { "addcompletion", l_addcompletion },
    { "preload", l_preloadbuffer },
    { "refresh", l_refresh },

    /* Aliases for more consistent function names */
    { "addhistory", l_historyadd },
    { "sethistorymaxlen", l_historysetmaxlen },
    { "savehistory", l_historysave },
    { "loadhistory", l_historyload },

    { "line", l_linenoise },
    { "lines", l_lines },

    { "gethistory", l_gethistorytable},
    { "historygetmaxlen", l_historygetmaxlen},
    { NULL, NULL }
};




Code
MAME debugger version 0.191 (mame0191-183-g346a935839-dirty)
Currently targeting a2600 (Atari 2600 (NTSC))
[MAME]> print(ln_global.historygetmaxlen())
100
[MAME]> print(ln_global.historysetmaxlen(250))
true
[MAME]> print(ln_global.historygetmaxlen())
250
[MAME]> function printt(a) local i,j; for i,j in pairs(a) do print(i,j) end end
[MAME]> printt(ln_global.gethistory())
1	print(ln_global.historygetmaxlen())
2	print(ln_global.historysetmaxlen(250))
3	print(ln_global.historygetmaxlen())
4	function printt(a) local i,j; for i,j in pairs(a) do print(i,j) end end
[MAME]> 
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 11/24/17 09:29 AM

Ok, I thought I should clean the code up a little bit, and maybe add a couple of functions to return the history length ln.historylen() and to print the history ln.print() or ln.history().


3rdparty/lua-linenoise/linenoise.c
Code

static int l_gethistorytable(lua_State *L)
{
    int history_len;
    char ** history = linenoiseHistory(&history_len);

    lua_newtable(L); /* put a table on the stack */

    for (int i=0; i<history_len; i++){
        /* create result table */
        lua_pushnumber(L, i+1);  /* push key */
        lua_pushstring(L, history[i]);  /* push value */
        lua_settable(L, -3);  /* adds key and value to table at position 3 from top of stack */
      }
      return 1;  /* table is on top of stack */
}

static int l_historylen(lua_State *L)
{
     int history_len;
     char ** history = linenoiseHistory(&history_len);
     history = history;  // compiler warning about unused variable
     lua_pushinteger(L, history_len);
     return 1;
}

static int l_historygetmaxlen(lua_State *L)
{
      lua_pushinteger(L, linenoiseHistoryGetMaxLen());
      return 1;
}

static int l_historyprint(lua_State *L)
{
    int history_len;
    char ** history = linenoiseHistory(&history_len);

    printf("print history: %d entries\n",history_len);
    for (int i=0; i<history_len; i++){
       printf("%d %s\n",i+1,history[i]);
      }
    return handle_ln_ok(L);
}


luaL_Reg linenoise_funcs[] = {
    { "linenoise", l_linenoise },
    { "historyadd", l_historyadd },
    { "historysetmaxlen", l_historysetmaxlen },
    { "historysave", l_historysave },
    { "historyload", l_historyload },
    { "clearscreen", l_clearscreen },
    { "setcompletion", l_setcompletion},
    { "addcompletion", l_addcompletion },
    { "preload", l_preloadbuffer },
    { "refresh", l_refresh },

    /* Aliases for more consistent function names */
    { "addhistory", l_historyadd },
    { "sethistorymaxlen", l_historysetmaxlen },
    { "savehistory", l_historysave },
    { "loadhistory", l_historyload },

    { "line", l_linenoise },
    { "lines", l_lines },

    { "gethistorytable", l_gethistorytable},
    { "historygetmaxlen", l_historygetmaxlen},
    { "historylen", l_historylen},
    { "print", l_historyprint},
    { "history", l_historyprint},
    { NULL, NULL }
};


What's kind of interesting is that if you set the history to n, the maximum length is actually n-1.

So for ln.historysetmaxlen(5), the length of the history is actually a maximum of 4 entries.


And if you remove this line from plugins/console/init.lua it will default to a maximum length of 100.

Code
ln.historysetmaxlen(10)

since 3rdparty/linenoise/linenoise.c has this:
Code
#define LINENOISE_DEFAULT_HISTORY_MAX_LEN 100


And if you like to make ln a global variable ln for access you can do this in plugins/console/init.lua

Code
  
local ln = require("linenoise")
_G.ln = ln  -- make a global ln for console access
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 11/25/17 06:00 PM

I was curious how the CTRL+C worked in linenoise and whether it could be "caught".


One interesting side effect of enabling SOL_CHECK_ARGUMENTS in luaengine.h is in whether sol will throw an exception when it executes this in luaengine.cpp:

Code
auto ret = func();

if (ret.valid()) {
	const char *tmp = ret.get<const char *>();
        if (tmp != nullptr)
			ctx.result = tmp;
		else
			exit(0);
	}



So when you type a CTRL+C on the console, it will return a nil from linenoise, tmp will be null so it calls exit(0);

When you've got SOL_CHECK_ARGUMENTS enabled, it will throw a sol::error exception immediately when it executes the following line

Code
const char *tmp = ret.get<const char *>();


It drops out and never sees the following if (tmp != nullptr) statement.

I had to put a bunch of printfs around to figure out exactly where it was blowing up.

And you get this kind of exit.

Code
[MAME]> 
terminate called after throwing an instance of 'sol::error'
  what():  lua: error: stack index 2, expected string, received nil
Aborted (core dumped)


So if we insert a little try catch block, we can catch that sol::error on the get.
Code
if (ret.valid()) {

    printf("calling ret.get const char *\n");

    try{
       const char *tmp = ret.get<const char *>();

	if (tmp != nullptr)
		ctx.result = tmp;
	else
		exit(0);
	
 catch (const std::exception& e) {  
     printf("Caught Exception:\n"); std::cout << e.what() << std::endl;
          }
}
	
		


With the catch it will catch the sol::error and keep you in the console. Of course, it's so convenient to just hit CTRL+C to drop out of mame, but there are other ways, like manager:machine():exit()


Code
[MAME]> 
calling ret.get const char *
Caught exception:
lua: error: stack index 2, expected string, received nil
[MAME]> 
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 11/25/17 06:54 PM

Now that I've thought about for a bit, it's just getting a nil result from linenoise when you hit CTRL+C. The nil will cause the exception so why not look for that in plugins/console/init.lua:

The linenoise reading code:

Code
local scr = [[
local ln = require('linenoise')
ln.setcompletion(function(c, str, pos)
	status = str .. "\x01" .. tostring(pos)
	yield()
	ln.addcompletion(c, status:match("([^\x01]*)\x01(.*)"))
end)
return ln.linenoise('\x1b[1;36m[MAME]\x1b[0m> ')
]]



so instead of just returning the value from ln.linenoise, we'll check it for NIL and if so, convert it to the empty string.

Code
local scr = [[
local ln = require('linenoise')
ln.setcompletion(function(c, str, pos)
	status = str .. "\x01" .. tostring(pos)
	yield()
	ln.addcompletion(c, status:match("([^\x01]*)\x01(.*)"))
end)
local lnresult = ln.linenoise('\x1b[1;36m[MAME]\x1b[0m> ')
if lnresult == nil then print ("NIL result") lnresult = "" end
return lnresult
]]

Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 11/26/17 10:18 AM

Or how about ask the user if they'd like to exit.

If so, then pass a nil result through.

Code
local lnresult = ln.linenoise('\x1b[1;36m[MAME]\x1b[0m> ')
if (lnresult == nil) then 
  lnresult = "" 
  io.write("CTRL+C detected: are you sure you want to exit?") 
  if io.read() == "y" then lnresult = nil end 
end
return lnresult
]]
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 12/04/17 12:29 PM

So a couple of things I was trying to figure out,
1. how to print to another text console, and
2. how often register_periodic will call a routine.


So how to send lua print output to another text console.

I would get lots of output information that would mess up my command line, so why not send it to another window?

On ubuntu 17.10, you can launch an xterm with a command line like:
Code
xterm -e "tty;cat" &

So it executes the program tty which prints something like "/dev/pts/3" on the top line which is the pseudoterminal assigned to the terminal and then executes cat. The & is to run it in the background so you get your console back.

I tried it with "gnome-terminal -- tty;cat" but it didn't seem to work, giving me some kind of error.

I launch mame with this command line:

Code
./mame64 a2600 stampede -plugin console -debug -window  2>/dev/pts/3


so the 2> redirects stderr to my freshly created xterm at /dev/pts/3.

and any error messages from lua goes to stderr and I can also print stuff directly with

Code
io.stderr:write("This goes to stderr\n")




I was trying to figure out how often a routine registered to emu().register_periodic would get called:

Code
function testperiodic() if not stopprint then if cycles == nil then cycles = 1 end io.stderr:write(" cycles="..(cycles).."  "..os.date().."\n") if cycles then cycles=cycles+1 end end end

-- same function on multiple lines:

function testperiodic() 
  if not stopprint then 
    if cycles == nil then cycles = 1 end 
    io.stderr:write(" cycles="..(cycles).."  "..os.date().."\n") 
    if cycles then cycles=cycles+1 end 
  end 
end

emu.register_periodic(testperiodic)


-- and when you want to stop the printing, set stopprint to true
-- stopprint=true


and you get output like:
Code
 cycles=1  Mon 04 Dec 2017 04:05:44 PM EST
 cycles=2  Mon 04 Dec 2017 04:05:44 PM EST
 cycles=3  Mon 04 Dec 2017 04:05:44 PM EST
 cycles=4  Mon 04 Dec 2017 04:05:44 PM EST
 cycles=5  Mon 04 Dec 2017 04:05:44 PM EST
 cycles=6  Mon 04 Dec 2017 04:05:45 PM EST
 cycles=7  Mon 04 Dec 2017 04:05:45 PM EST
 cycles=8  Mon 04 Dec 2017 04:05:45 PM EST
 cycles=9  Mon 04 Dec 2017 04:05:45 PM EST
 cycles=10  Mon 04 Dec 2017 04:05:45 PM EST
 cycles=11  Mon 04 Dec 2017 04:05:45 PM EST
 cycles=12  Mon 04 Dec 2017 04:05:45 PM EST
 cycles=13  Mon 04 Dec 2017 04:05:45 PM EST
 cycles=14  Mon 04 Dec 2017 04:05:45 PM EST
 cycles=15  Mon 04 Dec 2017 04:05:45 PM EST
 cycles=16  Mon 04 Dec 2017 04:05:45 PM EST
 cycles=17  Mon 04 Dec 2017 04:05:45 PM EST
 cycles=18  Mon 04 Dec 2017 04:05:45 PM EST
 cycles=19  Mon 04 Dec 2017 04:05:45 PM EST
 cycles=20  Mon 04 Dec 2017 04:05:45 PM EST
 cycles=21  Mon 04 Dec 2017 04:05:45 PM EST
 cycles=22  Mon 04 Dec 2017 04:05:45 PM EST
 cycles=23  Mon 04 Dec 2017 04:05:45 PM EST
 cycles=24  Mon 04 Dec 2017 04:05:45 PM EST
 cycles=25  Mon 04 Dec 2017 04:05:46 PM EST


And it looks like you get around 20 cycles per second.

And if you want other terminal output windows, you can use io.open like so:
Code
[MAME]> out2 = io.open("/dev/pts/4","w")
[MAME]> print(out2)
file (0x56300b8219b0)
[MAME]> out2:write("hello wont be seen until newline")
[MAME]> out2:write("hello\n")
[MAME]> out2:write("wont see me until flush")
[MAME]> out2:flush()

Posted By: shattered

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 03/13/18 02:26 PM

Working on Apple disk support in SAMdisk -- this is a (probably cracked) Datasoft Conan disk. And it boots when converted into .DO image:

[Linked Image]

Code
[a140-023.scp]
35 Cyls Head 0:
cyl 32 head 0 sec 6: invalid gcr at 016 - A5 -> FF
cyl 32 head 0 sec 6: invalid gcr at 017 - 7B -> FF
cyl 32 head 0 sec 6: invalid gcr at 01E - 7F -> FF
cyl 32 head 0 sec 6: invalid gcr at 01F - D5 -> FF
cyl 32 head 0 sec 6: invalid gcr at 020 - 93 -> FF
cyl 32 head 0 sec 6: invalid gcr at 021 - A9 -> FF
250Kbps Apple, 16 sectors,  256 bytes/sector:
  0.0  5 6 7 8 9 10 11 12 13 14 15 0 1 2 3 4
  1.0  10 11 12 13 14 15 0 1 2 3 4 5 6 7 8 9
  2.0  14 15 0 1 2 3 4 5 6 7 8 9 10 11 12 13
  3.0  2 3 4 5 6 7 8 9 10 11 12 13 14 15 0 1
  4.0  7 8 9 10 11 12 13 14 15 0 1 2 3 4 5 6
  5.0  11 12 13 14 15 0 1 2 3 4 5 6 7 8 9 10
  6.0  0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
  7.0  4 5 6 7 8 9 10 11 12 13 14 15 0 1 2 3
  8.0  9 10 11 12 13 14 15 0 1 2 3 4 5 6 7 8
  9.0  13 14 15 0 1 2 3 4 5 6 7 8 9 10 11 12
 10.0  2 3 4 5 6 7 8 9 10 11 12 13 14 15 0 1
 11.0  6 7 8 9 10 11 12 13 14 15 0 1 2 3 4 5
 12.0  11 12 13 14 15 0 1 2 3 4 5 6 7 8 9 10
 13.0  15 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
 14.0  4 5 6 7 8 9 10 11 12 13 14 15 0 1 2 3
 15.0  8 9 10 11 12 13 14 15 0 1 2 3 4 5 6 7
 16.0  13 14 15 0 1 2 3 4 5 6 7 8 9 10 11 12
 17.0  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 0
 18.0  14 15 0 1 2 3 4 5 6 7 8 9 10 11 12 13
 19.0  2 3 4 5 6 7 8 9 10 11 12 13 14 15 0 1
 20.0  7 8 9 10 11 12 13 14 15 0 1 2 3 4 5 6
 21.0  11 12 13 14 15 0 1 2 3 4 5 6 7 8 9 10
 22.0  0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
 23.0  4 5 6 7 8 9 10 11 12 13 14 15 0 1 2 3
 24.0  9 10 11 12 13 14 15 0 1 2 3 4 5 6 7 8
 25.0  13 14 15 0 1 2 3 4 5 6 7 8 9 10 11 12
 26.0  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 0
 27.0  6 7 8 9 10 11 12 13 14 15 0 1 2 3 4 5
 28.0  11 12 13 14 15 0 1 2 3 4 5 6 7 8 9 10
 29.0  15 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
 30.0  3 4 5 6 7 8 9 10 11 12 13 14 15 0 1 2
 31.0  8 9 10 11 12 13 14 15 0 1 2 3 4 5 6 7
 32.0  12 13 14 15 0 1 2 3 4 5 6 7 8 9 10 11
 33.0  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 0
 34.0  5 6 7 8 9 10 11 12 13 14 15 0 1 2 3 4
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 03/13/18 02:44 PM

Very nice!
Posted By: robj

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/11/18 11:04 AM

Not to sure where to post this, but this seems like a good place.

One of the members of the Apple /// Facebook group, Madeleine, has noticed an issue in the Apple /// emulation when writing to floppy images. This was noticed when trying to use MAME to help speed up some A3 driver development. After a few operations writing to the disk, then some corruption happens and the disk image will not work anymore.

It is easily reproducable and looks like its been there for quite some time, the current 0.196 has it, and looks like back to 0.158, but 0.153 is ok.

You can test and reproduce with the following disk image:
http://www.apple3.org/Software/programming/basic/Apple3BusBasic.dsk

1. Boot the dsk image mounted as flop1
2. type 'load volumes' (read a basic program to save in)
3. repeat saving the same file many times 'save volumes1', 'save volumes2' ..etc
4. Error can occur after 1 or 2 times, or may take quite a bit more. Looks like you can get two things that happen when the write errors occur
- ?VOLUME NOT FOUND - then the disk directory blocks seem trashed, you can see this if you open up the dks image in ciderpress using the block viewer
- ?I/O ERROR - cannot save after this, but can do a CATALOG but this shows errors. Again, I think the directory sector is trashed some how.

I'm wondering if someone can have a look at why this might be happening?

/Robj
Posted By: Pernod

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/11/18 02:18 PM

Originally Posted by robj
It is easily reproducable and looks like its been there for quite some time, the current 0.196 has it, and looks like back to 0.158, but 0.153 is ok.

I don't think this is specific to the Apple or any particular format as I've also had BBC users reporting to me something similar. I have been able to replicate the issue myself with bbcb and a ssd format floppy and it seems to insert an extra byte after the first sector rendering the image corrupt. Haven't yet investigated further as it seems core floppy image related.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/23/18 03:26 AM

I was reading up on the Apple2 game subnodule at John Romero's website and thought I'd give it a spin in Mame's apple2e driver and it doesn't work.

./mame64 apple2e -flop1 subnodule.dsk

and it drops out to the monitor right after booting.

It's quite a good read.

http://rome.ro/subnodule/
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/23/18 11:49 AM

Yeah, the boot sector loads what appears to be invalid data and jumps to it, even if I switch to the old HLE disk controller. I'll take a more detailed look later today unless Peter Ferrie sees it first smile
Posted By: peter ferrie

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/23/18 07:32 PM

Maybe I need a notification subscription, because I saw this only by accident.
The sectors are ProDOS order (0, E, D, C...), not DOS order (0, 1, 2, 3...).
It works in AppleWin, for example, because they don't do the right thing.
It's not a bug, and not MAME's fault.
Reording the sectors will give you a good image. Do you need me to send one?
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/23/18 07:38 PM

I can add a heuristic to detect this disk. We already do for a bunch of them. Wasn't quite expecting the disk to be ProDOS order since it has a DOS 3.3-looking BOOT0, but you never know smile
Posted By: peter ferrie

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/23/18 08:54 PM

I was surprised, too. I have a dsk-ordered image which boots in MAME. Does either of you want to ask Romero if he's like to distribute that instead (and plug MAME over AppleWin at the same time? :-) ).
Posted By: peter ferrie

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/23/18 08:59 PM

Originally Posted by shattered
Working on Apple disk support in SAMdisk -- this is a (probably cracked) Datasoft Conan disk


Before Conan rides his horse across the bottom of the screen, does the uninterruptible music play? If not, then it's the crack from BITD.
If so, then it's likely to be 4am's crack. The original won't boot from any .dsk-style format.

Depending on your intention, you might want to use my 1-sided ProDOS-based version instead. It fixes the game-crashing bug in level 6.
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/23/18 11:55 PM

MAME top-of-tree boots Subnodule fine.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/24/18 04:41 PM

Yay it works!

Thanks Arbee!
Posted By: shattered

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/25/18 06:17 AM

Originally Posted by peter ferrie
Originally Posted by shattered
Working on Apple disk support in SAMdisk -- this is a (probably cracked) Datasoft Conan disk


Before Conan rides his horse across the bottom of the screen, does the uninterruptible music play? If not, then it's the crack from BITD.
If so, then it's likely to be 4am's crack. The original won't boot from any .dsk-style format.

Depending on your intention, you might want to use my 1-sided ProDOS-based version instead. It fixes the game-crashing bug in level 6.


It's not 4am crack - disk pile is too old for that. Speaking of disk piles, a group in Bulgaria dumped their copy-protected disk pile into a custom format (via http://forum.agatcomp.ru//viewtopic.php?id=158)
Quote

This is the output of a sampler running on 100 MHz clock. File is just stream of 16-bit words,
little endian. So each sample is with a resolution of 10 ns. No further structure.

Short Apple II program "scans" 36 tracks, including the quarter tracks in-between. Total should be
141. The board just captures (passively) the RD signal from the floppy drive. Each track is
scanned about 8 times. That's why the huge size.

Each sample denotes the width of a pulse (the time period between two pulses), so in a way:

- value about 400 (4 us) is bitstream "1"
- value about 800 (8 us) is bitstream "01"
- value about 1200 (12 us) is bitstream "001"


And samdisk can sort of read that now. One sample dump is normal dos 3.3 disk, another is (probably uncracked) Autoduel disk -- first track uses non-standard epilogues (AF 5x xx).
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/25/18 12:58 PM

With the .WOZ disk image support we can boot 13-sector disks by booting the DOS 3.3 master and BRUNing BOOT13. Here's DOS 3.2 running:

[Linked Image]
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/26/18 02:49 AM

You're bringing back memories of having to boot DOS BASICS 3.3 so I could run Microsoft Adventure. I think it was 13 sectors if I remember.
Posted By: shattered

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/28/18 06:45 PM

Originally Posted by shattered
Working on Apple disk support in SAMdisk


It's now merged.
Posted By: shattered

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 06/04/18 08:14 PM

Originally Posted by shattered

And samdisk can sort of read that now. One sample dump is normal dos 3.3 disk, another is (probably uncracked) Autoduel disk -- first track uses non-standard epilogues (AF 5x xx).


List of all dumps follows. Anything in there that might be undumped?


a_mind_forever_voyaging/dii.a_mind_forever_voyaging.1A
a_mind_forever_voyaging/dii.a_mind_forever_voyaging.1B
age_of_adventure/alt1/dii.age_of_adventure.1A
age_of_adventure/alt1/dii.age_of_adventure.1B
age_of_adventure/dii.ali_baba_and_the_40_thieves
age_of_adventure/dii.the_return_of_heracles
amnesia/dii.amnesia.1A
amnesia/dii.amnesia.1B
amnesia/dii.amnesia.2A
amnesia/dii.amnesia.2B
archon/dii.archon
archon_ii:_adept/dii.adept
arcticfox/dii.arcticfox
arkanoid/dii.arkanoid.raw
autoduel/dii.autoduel.1A
autoduel/dii.autoduel.1B
aztec/dii.aztec
balance_of_power/dii.balance_of_power
battletech/dii.battletech.1A
battletech/dii.battletech.1B
beyond_castle_wolfenstein/dii.beyond_castle_wolfenstein
beyond_zork/dii.beyond_zork.1A
beyond_zork/dii.beyond_zork.1B
bird's_eye_view/dii.bird's_eye_view
bubble_bobble/dii.bubble_bobble.1A
bubble_bobble/dii.bubble_bobble.1B
castle_wolfenstein/alt1/dii.castle_wolfenstein
castle_wolfenstein/dii.castle_wolfentstein
championship_baseball/dii.championship_baseball.1A
championship_baseball/dii.championship_baseball.1B
championship_golf/dii.championship_golf
championship_wrestling/dii.championship_wrestling.1A
championship_wrestling/dii.championship_wrestling.1B
clue_master_detective/dii.clue_master_detective
copy_ii_plus/dii.copy_v9.1A
copy_ii_plus/dii.copy_v9.1B
copy_ii_plus/dii.copy_1982-1987
copy_ii_plus/dii.copy_1985-1987
cosmic_balance_ii/dii.cosmic_balance2
dii.autoduel.1A
dii.merlin_dii
dii.merlin_dii.eim.dsk
dinosaurs_are_forever/dii.dinosaurs_are_forever
discover_your_child/dii.discover_your_child.1A
discover_your_child/dii.discover_your_child.1B
discover_your_child/dii.discover_your_child.2A
discover_your_child/dii.discover_your_child.2B
dive_bomber/dii.dive_bomber
dreadnoughts/dii.dreadnoughts__BAD
dunjonquest_-_hellfire_warrior/dii.hellfire_warrior
elite_gold_edition/alt1/dii.elite_gold_edition
elite_gold_edition/alt2/dii.elite_gold_edition
elite_gold_edition/dii.elite_gold_edition
final_conflict/dii.final_conflict
flight_simulator_ii/dii.flight_simulator_ii
gauntlet/dii.gauntlet.1A
gauntlet/dii.gauntlet.1B
gba_championship_basketball/dii.gba_championship_basketball
gemstone_healer/dii.gemstone_healer
gemstone_warrior/dii.gemstone_warrior
ghostbusters/dii.ghostbusters
hard_hat_mack/dii.hard_hat_mack
high_seas/dii.high_seas.1A
high_seas/dii.high_seas.2A
hitchhiker's_guide/dii.hitchhiker_128K.1A.raw
hitchhiker's_guide/dii.hitchhiker_128K.1B.raw
hitchhiker's_guide/dii.hitchhiker_48K.1A.raw
homework_writer/dii.homework_writer.1A
homework_writer/dii.homework_writer.1B
in_search_of_the_most_amazing_thing/dii.in_search_of_the_most_amazing_thing
infiltrator/dii.infiltrator.1A
infiltrator/dii.infiltrator.1B
karateka/alt1/dii.karateka.1A.raw
karateka/alt1/dii.karateka.1B.raw
karateka/dii.karateka.1A
karateka/dii.karateka.1A__again
karateka/dii.karateka.1B
karateka/dii.karateka.1B__again
king's_quest/dii.kq1.1A
king's_quest/dii.kq1.1B
king's_quest/dii.kq1.2A
king's_quest_ii/alt1/dii.kq2.1A
king's_quest_ii/alt1/dii.kq2.1B
king's_quest_ii/alt1/dii.kq2.2A
king's_quest_ii/alt1/dii.kq2.2B
king's_quest_ii/alt1/dii.kq2.3A
king's_quest_ii/dii.kq2.1A
king's_quest_ii/dii.kq2.1B
king's_quest_ii/dii.kq2.2A
king's_quest_ii/dii.kq2.2B
king's_quest_ii/dii.kq2.3A
king's_quest_iii/alt1/dii.kq3_v2.0A_i0.089.1A
king's_quest_iii/alt1/dii.kq3_v2.0A_i0.089.1B
king's_quest_iii/alt1/dii.kq3_v2.0A_i0.089.2A
king's_quest_iii/alt1/dii.kq3_v2.0A_i0.089.2B
king's_quest_iii/alt1/dii.kq3_v2.0A_i0.089.3A
king's_quest_iii/alt1/dii.kq3_v2.0A_i0.089.3B
king's_quest_iii/alt1/dii.kq3_v2.0A_i0.089.4A
king's_quest_iii/alt1/dii.kq3_v2.0A_i0.089.4B
king's_quest_iii/alt1/dii.kq3_v2.0A_i0.089.5A
king's_quest_iii/alt1/dii.kq3_v2.0A_i0.089.5B
king's_quest_iii/dii.kq3_v2.0A_i0.099.1A
king's_quest_iii/dii.kq3_v2.0A_i0.099.1B
king's_quest_iii/dii.kq3_v2.0A_i0.099.2A
king's_quest_iii/dii.kq3_v2.0A_i0.099.2B
king's_quest_iii/dii.kq3_v2.0A_i0.099.3A
king's_quest_iii/dii.kq3_v2.0A_i0.099.3B
king's_quest_iii/dii.kq3_v2.0A_i0.099.4A
king's_quest_iii/dii.kq3_v2.0A_i0.099.4B
king's_quest_iii/dii.kq3_v2.0A_i0.099.5A
king's_quest_iii/dii.kq3_v2.0A_i0.099.5B
king's_quest_iv/dii.kq4_v1.0W_i0.144.1A
king's_quest_iv/dii.kq4_v1.0W_i0.144.1B
king's_quest_iv/dii.kq4_v1.0W_i0.144.2A
king's_quest_iv/dii.kq4_v1.0W_i0.144.2B
king's_quest_iv/dii.kq4_v1.0W_i0.144.3A
king's_quest_iv/dii.kq4_v1.0W_i0.144.3B
king's_quest_iv/dii.kq4_v1.0W_i0.144.4A
king's_quest_iv/dii.kq4_v1.0W_i0.144.4B
king's_quest_iv/dii.kq4_v1.0W_i0.144.5A
king's_quest_iv/dii.kq4_v1.0W_i0.144.5B
king's_quest_iv/dii.kq4_v1.0W_i0.144.6A
king's_quest_iv/dii.kq4_v1.0W_i0.144.6B
king's_quest_iv/dii.kq4_v1.0W_i0.144.7A
king's_quest_iv/dii.kq4_v1.0W_i0.144.7B
king's_quest_iv/dii.kq4_v1.0W_i0.144.8A
king's_quest_iv/dii.kq4_v1.0W_i0.144.8B
kung-fu_master/dii.kung-fu_master
legacy_of_the_ancients/dii.legacy_of_the_ancients.1A
legacy_of_the_ancients/dii.legacy_of_the_ancients.1B
legacy_of_the_ancients/dii.legacy_of_the_ancients.2A
legacy_of_the_ancients/dii.legacy_of_the_ancients.2B
letters_for_you/dii.letters_for_you
mastertype/dii.mastertype.1A
mastertype/dii.mastertype.1B
math_and_me/dii.math_and_me.1A
math_and_me/dii.math_and_me.1B
math_word_problems/dii.math_word_problems
meet_the_presidents/dii.meet_the_presidents.1A
meet_the_presidents/dii.meet_the_presidents.2A
meet_the_presidents/dii.meet_the_presidents.3A
meet_the_presidents/dii.meet_the_presidents.4A
memory_castle/dii.4242_memory_castle
microzine/dii.microzine_24.1A
microzine/dii.microzine_33.1A
microzine/dii.microzine_24.1B
microzine/dii.microzine_33.1B
microzine/dii.microzine_33.2A
microzine/dii.microzine_33.2B
might_and_magic/dii.might_and_magic.1A
might_and_magic/dii.might_and_magic.1B
might_and_magic/dii.might_and_magic.2A
might_and_magic/dii.might_and_magic.2B
might_and_magic_ii/dii.might_and_magic2.1A
might_and_magic_ii/dii.might_and_magic2.1B
might_and_magic_ii/dii.might_and_magic2.2A
might_and_magic_ii/dii.might_and_magic2.2B
might_and_magic_ii/dii.might_and_magic2.3A
might_and_magic_ii/dii.might_and_magic2.3B
mines_of_titan/dii.mines_of_titan.1A
mines_of_titan/dii.mines_of_titan.1B
moebius/dii.moebius.1A
moebius/dii.moebius.1B
moebius/dii.moebius.2A
moebius/dii.moebius.2B
moonmist/dii.moonmist
murder_on_the_zinderneuf/alt1/dii.murder_on_the_zinderneuf
murder_on_the_zinderneuf/dii.murder_on_the_zinderneuf
mystery_master:_felony!/alt1/dii.felony
mystery_master:_felony!/dii.felony
objective:_kursk/dii.objective:_kursk
old_ironsides/dii.old_ironsides
phantasie/dii.phantasie.1A
phantasie/dii.phantasie.1B
phantasie_ii/dii.phantasie2.1A
phantasie_ii/dii.phantasie2.1B
phantasie_iii/dii.phantasie3.1A
phantasie_iii/dii.phantasie3.1B
pic.builder/dii.pic.builder
pinball_construction_set/dii.pinball_construction_set
planetfall/dii.planetfall
platoon/dii.platoon.1A
platoon/dii.platoon.1B
questron/alt1/dii.questron.1A
questron/alt1/dii.questron.1B
questron/alt1/dii.questron.2A
questron/dii.questron.1A
questron/dii.questron.1B
questron/dii.questron.2A
questron/dii.questron.2B
questron_ii/alt1/dii.questron2.1A
questron_ii/alt1/dii.questron2.1B
questron_ii/dii.questron2.1A
questron_ii/dii.questron2.1B
raven-7/dii.raven-7
reading_and_me/dii.reading_and_me__BAD
renegade/dii.renegade.1A
renegade/dii.renegade.1B
rings_of_zilfin/dii.rings_of_zilfin.1A
rings_of_zilfin/dii.rings_of_zilfin.2A
rings_of_zilfin/dii.rings_of_zilfin.2B
roadwar_europa/dii.roadwar_europa.1A
roadwar_europa/dii.roadwar_europa.1B
robot_odyssey_i/dii.robot_odyssey_i.1A
robot_odyssey_i/dii.robot_odyssey_i.1B
russia_the_great_war_in_the_east_1941-1945/dii.russia.1A
russia_the_great_war_in_the_east_1941-1945/dii.russia.1B
sargon_ii/alt1/dii.sargon2
sargon_ii/dii.sargon_ii
sea_dragon/alt1/dii.sea_dragon
sea_dragon/dii.sea_dragon
seastalker/dii.seastalker
shard_of_spring/dii.shard_of_spring.1A
shard_of_spring/dii.shard_of_spring.1B
skyfox/alt1/dii.skyfox
skyfox/dii.skyfox.raw
socorder/dii.socorder
socpix/dii.socpix
soko-ban/dii.soko-ban.1A
soko-ban/dii.soko-ban.1B
solo_flight/dii.solo_flight
space_quest/dii.sq1.1A
space_quest/dii.sq1.1B
space_quest/dii.sq1_v1.0Q_i0.071.2A
space_quest/dii.sq1_v1.0Q_i0.071.2B
space_quest/dii.sq1_v1.0Q_i0.071.3A
space_quest/dii.sq1_v1.0Q_i0.071.3B
space_quest/dii.sq1_v1.0Q_i0.071.4A
space_quest/dii.sq1_v1.0Q_i0.071.4B
space_quest_ii/dii.sq2_v2.0A.1A
space_quest_ii/dii.sq2_v2.0A.1B
space_quest_ii/dii.sq2_v2.0A.2A
space_quest_ii/dii.sq2_v2.0A.2B
space_quest_ii/dii.sq2_v2.0A.3A
space_quest_ii/dii.sq2_v2.0A.3B
space_quest_ii/dii.sq2_v2.0A.4A
space_quest_ii/dii.sq2_v2.0A.4B
spellbreaker/dii.spellbreaker
spy_vs_spy/dii.spy_vs_spy
spy_vs_spy/dii.spy_vs_spy_i_ii
strike_fleet/dii.strike_fleet.1A
strike_fleet/dii.strike_fleet.1B
summer_games/alt1/dii.summer_games.1A__BAD
summer_games/dii.summer_games.1A
summer_games/dii.summer_games.1B
sundog/dii.sundog.1A
sundog/dii.sundog.1B
super_mario_bros._print_world/dii.print_world.1A
super_mario_bros._print_world/dii.print_world.1B
tangled_tales/alt1/dii.tangled_tales.1A
tangled_tales/alt1/dii.tangled_tales.1B
tangled_tales/alt1/dii.tangled_tales.2A
tangled_tales/alt1/dii.tangled_tales.2B
tangled_tales/dii.tangled_tales.1A
tangled_tales/dii.tangled_tales.1B
tangled_tales/dii.tangled_tales.2A
tangled_tales/dii.tangled_tales.2B
tetris/dii.tetris.1A
tetris/dii.tetris.1B
tetris/dii.tetris.1A.ei
tetris/dii.tetris.1A.eim
the_adventures_of_sinbad/dii.the_adventures_of_sinbad.1A
the_adventures_of_sinbad/dii.the_adventures_of_sinbad.1B
the_chessmaster_2000/dii.the_chessmaster_2000.1A
the_chessmaster_2000/dii.the_chessmaster_2000.1B
the_computer_edition_of_scrabble_brand_crossword_game/dii.scrabble
the_halley_project:_a_mission_in_our_solar_system/dii.the_halley_project
the_mist/dii.the_mist
the_oregon_trail/dii.the_oregon_trail.1A
the_oregon_trail/dii.the_oregon_trail.1B
the_sporting_news:_baseball/dii.baseball.1A
the_sporting_news:_baseball/dii.baseball.1B
the_stickybear_abc/dii.stickybear_abc
thunderchopper/dii.thunderchopper
tomahawk/dii.tomahawk.1A
tomahawk/dii.tomahawk.1B
trinity/dii.trinity.1A
trinity/dii.trinity.1B
ultima_i_new/dii.ultima1_new
ultima_ii/dii.ultima2.1A
ultima_ii/dii.ultima2.1B
ultima_ii/dii.ultima2.2A
ultima_iii/dii.ultima3.1A
ultima_iii/dii.ultima3.1B
ultima_iv/dii.ultima4.1A
ultima_iv/dii.ultima4.1B
ultima_iv/dii.ultima4.2A
ultima_iv/dii.ultima4.2B
ultima_v/dii.ultima5.1A
ultima_v/dii.ultima5.1B
ultima_v/dii.ultima5.2A
ultima_v/dii.ultima5.2B
ultima_v/dii.ultima5.3A
ultima_v/dii.ultima5.3B
ultima_v/dii.ultima5.4A
ultima_v/dii.ultima5.4B
wheel_of_fortune/dii.wheel_of_fortune.1A
wheel_of_fortune_2nd_edition/dii.wheel_of_fortune.1A
wheel_of_fortune_2nd_edition/dii.wheel_of_fortune.1B
where_in_europe_is_carmen_sandiego/alt1/dii.carmen_europe.1A
where_in_europe_is_carmen_sandiego/alt1/dii.carmen_europe.1B
where_in_europe_is_carmen_sandiego/dii.carmen_europe.1A
where_in_europe_is_carmen_sandiego/dii.carmen_europe.1B
where_in_the_u.s.a._is_carmen_sandiego/alt1/dii.carmen_usa.1A
where_in_the_u.s.a._is_carmen_sandiego/alt1/dii.carmen_usa.1B
where_in_the_u.s.a._is_carmen_sandiego/alt1/dii.carmen_usa.2A
where_in_the_u.s.a._is_carmen_sandiego/alt2/dii.carmen_usa.1A
where_in_the_u.s.a._is_carmen_sandiego/alt2/dii.carmen_usa.1B
where_in_the_u.s.a._is_carmen_sandiego/alt2/dii.carmen_usa.2A
where_in_the_u.s.a._is_carmen_sandiego/dii.carmen_usa.1A
where_in_the_u.s.a._is_carmen_sandiego/dii.carmen_usa.1B
where_in_the_u.s.a._is_carmen_sandiego/dii.carmen_usa.2A
who_framed_roger_rabbit/alt1/dii.who_framed_roger_rabbit.1A
who_framed_roger_rabbit/alt1/dii.who_framed_roger_rabbit.1B
who_framed_roger_rabbit/alt1/dii.who_framed_roger_rabbit.2A
who_framed_roger_rabbit/alt1/dii.who_framed_roger_rabbit.2B
who_framed_roger_rabbit/dii.who_framed_roger_rabbit.1A
who_framed_roger_rabbit/dii.who_framed_roger_rabbit.1B
who_framed_roger_rabbit/dii.who_framed_roger_rabbit.2A
who_framed_roger_rabbit/dii.who_framed_roger_rabbit.2B
wilderness/dii.wilderness.1A
wilderness/dii.wilderness.1B
win,_lose_or_draw_junior/dii.win,_lose_or_draw_junior.1A
win,_lose_or_draw_junior/dii.win,_lose_or_draw_junior.1B
wings_of_fury/dii.wings_of_fury.1A
wings_of_fury/dii.wings_of_fury.1B
winter_games/dii.winter_games.1A
winter_games/dii.winter_games.1B
wishbringer/dii.wishbringer
wizardry/2_knight_of_diamonds/dii.knight.1A
wizardry/2_knight_of_diamonds/dii.knight.1B
wizardry/1_proving_grounds_of_the_mad_overlord/dii.overlord.1A
wizardry/1_proving_grounds_of_the_mad_overlord/dii.overlord.1B
wizardry/3_legacy_of_llylgamyn/alt1/dii.legacy_of_llylgamyn.boot
wizardry/3_legacy_of_llylgamyn/alt1/dii.legacy_of_llylgamyn.scenario
wizardry/3_legacy_of_llylgamyn/alt2/dii.legacy_of_llylgamyn.boot
wizardry/3_legacy_of_llylgamyn/alt2/dii.legacy_of_llylgamyn.scenario
wizardry/3_legacy_of_llylgamyn/dii.llylgamyn.1A
wizardry/3_legacy_of_llylgamyn/dii.llylgamyn.1B
zip_chip_utilities/dii.zip_chip.dos
zip_chip_utilities/dii.zip_chip.prodos
zork_i/dii.zork_i
zork_zero/dii.zork_zero.1A
zork_zero/dii.zork_zero.1B
zork_zero/dii.zork_zero.2A
zork_zero/dii.zork_zero.2B
zork_zero/dii.zork_zero.1A.unknown
zork_zero/dii.zork_zero.1B.unknown
Posted By: peter ferrie

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 06/05/18 06:17 AM

Oooh, exciting! Some of these have no dumps at all, some have only defaced versions.
Here are the ones that I would love to have:

balance_of_power/dii.balance_of_power
discover_your_child/dii.discover_your_child.1A
discover_your_child/dii.discover_your_child.1B
discover_your_child/dii.discover_your_child.2A
discover_your_child/dii.discover_your_child.2B
gemstone_healer/dii.gemstone_healer
high_seas/dii.high_seas.1A
high_seas/dii.high_seas.2A
infiltrator/dii.infiltrator.1A
infiltrator/dii.infiltrator.1B
legacy_of_the_ancients/dii.legacy_of_the_ancients.1A
legacy_of_the_ancients/dii.legacy_of_the_ancients.1B
legacy_of_the_ancients/dii.legacy_of_the_ancients.2A
legacy_of_the_ancients/dii.legacy_of_the_ancients.2B
math_and_me/dii.math_and_me.1A
math_and_me/dii.math_and_me.1B
phantasie/dii.phantasie.1A
phantasie/dii.phantasie.1B
phantasie_ii/dii.phantasie2.1A
phantasie_ii/dii.phantasie2.1B
phantasie_iii/dii.phantasie3.1A
phantasie_iii/dii.phantasie3.1B
pic.builder/dii.pic.builder
sea_dragon/alt1/dii.sea_dragon
sea_dragon/dii.sea_dragon
socorder/dii.socorder
socpix/dii.socpix
spy_vs_spy/dii.spy_vs_spy_i_ii
the_computer_edition_of_scrabble_brand_crossword_game/dii.scrabble
Posted By: shattered

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 06/05/18 07:36 PM

There no info attached to these images, some of them might be cracked/defaced already... Anyway, can upload all of these dumps to messftp (13 GB) or elsewhere.

dii.high_seas.1A looks original -- uses non-standard prologues (D4 AA 96) and epilogues (AF xx xx).
Posted By: shattered

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 06/07/18 10:16 PM

gemstone_healer looks like a regular DOS disk, boots and runs, and is newer version (1.4) than https://archive.org/details/390a_Gemstone_Healer_side_A (1.2)
Posted By: peter ferrie

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 06/08/18 01:14 AM

Then please add it to my list. :-)
Posted By: shattered

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 06/10/18 09:51 AM

Help, I'm having too much fun smile

[Linked Image]

(added code to samdisk to scan neighboring quarter tracks for valid sectors, regular dos 3.3 disks get copied in 1 pass)
Posted By: rfka01

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 06/12/18 06:36 PM

A guy on the German vintage computer forum is restoring his Basis 108 to working condition, which prompted me to do some quick searches for that machine.

ROMs can be found online at the Internet Archive.

There are at least two different keyboard controllers, M5L8048 marked ASCII and DEUTSCH.

ASCII keyboard controller

German keyboard controller

As those are soldered in, motivating people to dump them will probably be hard ...

At least the post in the German forum contains a high quality scan of the Basis mainboard schematics.
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 06/12/18 08:46 PM

Can you grab the higher-quality schematic and put it somewhere? That forum won't let non-members see the attachments, and I don't particularly want to sign up for a forum in a language I don't speak for one file smile
Posted By: rfka01

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 06/12/18 09:01 PM

Done ... I'll follow up with whatever is coming along ... maybe having the Basis 108 in MAME could motivate people to dump the keyboard ROMs as well.
Posted By: shattered

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 06/17/18 12:06 PM

Originally Posted by peter ferrie
Then please add it to my list. :-)


I've uploaded raw dumps in 'dii' format to messftp. Patch to samdisk is at https://github.com/shattered/samdisk/tree/diiwip -- it adds a new command 'diicopy', you have to use it with '--no-dups --force' option like so:

samdisk diicopy dii/wishbringer/dii.wishbringer --no-dups --force --verbose wishbringer.do
Posted By: peter ferrie

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 06/19/18 05:36 PM

Thanks, I will experiment with it.
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 07/21/18 12:16 AM

KansasFest 2018 brought us a new raster split demo, taken from an upcoming game-spoof called "Talbot Fantasy VII". This one's a bit unusual in that it uses the floating bus technique once to get in raster sync and then it relies on cycle-exactness for the rest of its run time. It features a 3-way screen split: text on top, 6-color hi-res in the middle, and 16-color lo-res for the Chocobo rider at the bottom. Get the .DSK at http://www.deater.net/weave/vmwprod/split_demo/

[Linked Image]
Posted By: Haze

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 07/21/18 04:13 AM

I still think it's worth software listing useful demos / test programs for future reference.
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 07/21/18 12:41 PM

Yeah, we'll get there, but the firehose just got turned on as far as booting protected originals too.
Posted By: rfka01

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 07/31/18 09:07 PM

I finally got hold of an ITT2020, the first licensed Apple II clone for the European market. It's marked "PALSOFT" and the ROM labels match the descriptions for that designation.
They patched some known problems with the original ROMs but introduced new compatibility problems by altering some memory addresses and increasing the A2's resolution to display colour on PAL monitors / TV sets.

[Linked Image]

Now how to read these ROMs ... I read they are 9316's, and the pinout is different to a regular 2716.

[Linked Image]

[Linked Image]

[Linked Image]
Posted By: shattered

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/01/18 07:28 PM

Originally Posted by peter ferrie
Thanks, I will experiment with it.


Anything interesting in there?
Posted By: Lord Nightmare

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/01/18 08:32 PM

All those roms are labeled as standard PAL applesoft 'PALsoft' roms EXCEPT the one at F8.
I think we need dumps of all of those, but it may be possible to dump all of them from software to a serial port, if the computer works and you have a super serial card and cable.

LN
Posted By: rfka01

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/01/18 09:40 PM

It may be some time, but I've ordered an adapter from Reactive Micro to read those ROMs. Apart from that, I'm hating myself for not being able to find that 25 pin gender changer adapter to run ADT on a //e but go ahead, rub it in grin
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/01/18 11:26 PM

LN: yeah, the 2020 has wider video for PAL and a 9th bit in the 2000-4000 range to back it up so there are definitely mods to at least the Monitor HGR routines. It's the only "true" PAL Apple II that was released until the GS.
Posted By: rfka01

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/03/18 10:02 PM

The character generator of an ITT2020 was dumped by a guy on the German vintage computer forum. He claims the dump came from a 2732 EPROM and contained a German and an US char set. My machine has a RO 2513 char ROM. Could someone please check if the dump is sane?

My ITT2020 is not operational atm, it seems to have memory problems as booting disks is hit and (mostly) miss. Even the original ITT2020 disk from the Asimov archive doesn't boot.
I have a functioning //e with disks and a SSC, so if there's a way to transplant the chargen ROM and read it out via the //e, I'm game.

Apart from the disks from Asimov, the char gen ROM and some documentation, the archive on the FTP and here contains ITT2020 cassette dumps that were posted by a guy on comp.sys.apple2 but seem to have disappeared since.
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/03/18 11:25 PM

Wiki claims the 2020 never officially got the 16-sector DOS 3.3 upgrade and only came with 3.2, but I would think that in real life plenty of them probably got the upgraded card and drives?
Posted By: rfka01

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/04/18 10:32 AM

Unfortunately I just got the machine without peripherals or disk (apart from that language card). After the quick run of the ITT2020 the Apple II clones started proliferating in Germany, so I imagine most ITT2020 users just grabbed a 16 sector controller and copied away happily.
Posted By: rfka01

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/05/18 12:16 PM

Looking at the apple2.cpp source, the original Apple II's character generator is marked "BAD DUMP"

I've put up an album on Imgur of an Apple II I have - is the chip we're looking for there? There's some kind of kludge, presumably to allow switching charsets.

https://imgur.com/a/KSPp9Li
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/05/18 02:04 PM

I actually expect that the original II's chargen will match the II Plus one; it's BAD DUMP mostly because it's worthwhile for historical reasons to check.

Yours appears to possibly have a lowercase mod, or maybe the second chip has special German characters? Dumping at least the RO-3-2513 would be useful to resolve the bad dump question, and both chips would be interesting if we wanted to emulate whatever mod you have there.
Posted By: rfka01

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/05/18 02:29 PM

Right, so I need a good way to dump the RO3-2513's from both the ITT2020 and the Apple II ...you're spot on for the lower case Generator - it's listed in the LS ADM-3 manual

https://www.manualslib.com/manual/1023524/Lear-Siegler-Adm-3.html?page=106
Posted By: Kaylee

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/10/18 05:17 AM

Sorry to bother you.

I've recently tried to run the apple2e driver from the terminal and got this "error"

Driver apple2e (file apple2.cpp): 7 errors, 0 warnings
Errors:
Street Electronics Echo Plus device 'sl1:echoiiplus': Required device ':sl1:echoiiplus:mockbd_ay2' not found
Street Electronics Echo Plus device 'sl2:echoiiplus': Required device ':sl2:echoiiplus:mockbd_ay2' not found
Street Electronics Echo Plus device 'sl3:echoiiplus': Required device ':sl3:echoiiplus:mockbd_ay2' not found
Street Electronics Echo Plus device 'sl4:echoiiplus': Required device ':sl4:echoiiplus:mockbd_ay2' not found
Street Electronics Echo Plus device 'sl5:echoiiplus': Required device ':sl5:echoiiplus:mockbd_ay2' not found
Street Electronics Echo Plus device 'sl6:echoiiplus': Required device ':sl6:echoiiplus:mockbd_ay2' not found
Street Electronics Echo Plus device 'sl7:echoiiplus': Required device ':sl7:echoiiplus:mockbd_ay2' not found

Required device ':sl1:echoiiplus:mockbd_ay2' not found
Ignoring MAME exception: Missing some required objects, unable to proceed
Fatal error: Missing some required objects, unable to proceed

any idea why?
Posted By: Just Desserts

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/10/18 06:07 AM

Originally Posted by Kaylee
any idea why?


Yeah, you're not synced up to the latest code.
Posted By: Anon01

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/19/18 12:44 AM

Hello all.

I made most of the Apple-1 .wav files quite some time ago for MESS. I'm here to post one more for the software list (if anyone is interested adding it).

I finished this way back in 2012 but never got around to submitting it.

Full Credit goes to Jeff Tranter for the hex dump. jefftranter.blogspot.com

Enhanced Basic 2.22

Screenshot
Enhanced Basic 2.22 .wav
ebasic.bin
EnhancedBASIC_hex.txt

Enhanced Basic 2.22 - load at 5000.78B0R enter at 7825R
(Note: Press Enter when prompted for "Memory size?".)

Load ebasic.bin in Mame debuger:

- bin file should be in Mame directory
- load ebasic.bin,5000
- type "go" in debugger without quotes
- x out of debugger
- type 7825R in Mame to run program

Thank you Robbbert for teaching me how to load .bin files.

Updated hex dump: Updated Enhanced Basic 2.22 hex dump
5000R runs the program (already in the dump at the end of the hex). Just copy and paste and hit enter when finished.
I'll make a .wav for this in the near future.

P.S. Sorry for all the edits.
Posted By: Anon01

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/21/18 01:30 PM

There has been no community interest in the files I posted. What that said they are no longer available for download.

Happy emulation devs.

Out.
Posted By: Just Desserts

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/21/18 02:28 PM

So basically, you didn't submit your files the correct way (code AT mamedev.org), you posted in a forum that is next to impossible to register on these days, you posted about a system that only a couple people on these forums have interest in, and then you waited only two days before pulling down the files in a huff, like some kind of toddler throwing a tantrum? God, the people in your life must hate you.
Posted By: Alegend45

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/21/18 02:33 PM

Yeah, I agree with JD, fuck that noise.
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/21/18 02:38 PM

Oh, geez. Anon01: look, things don't get added to MAME right away. There's one Apple developer, me (and that includes Apple I, II, ///, and Mac), and I have a near-infinite TODO list combined with major IRL stress. Stuff submitted as a turn-key patch to the software list XMLs is far more likely to go in quickly than stuff like this where I don't even understand what I'm supposed to do with it.
Posted By: Anon01

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/23/18 04:42 PM

Originally Posted by Just Desserts
So basically, you didn't submit your files the correct way (code AT mamedev.org), you posted in a forum that is next to impossible to register on these days, you posted about a system that only a couple people on these forums have interest in, and then you waited only two days before pulling down the files in a huff, like some kind of toddler throwing a tantrum? God, the people in your life must hate you.

So basically I was correct to remove my files since:

- I didn't submit my files the correct way.
- I posted in a forum that is next to impossible to register on these days.
- I posted about a system that only a couple people on these forums have interest in...

Originally Posted by Just Desserts
God, the people in your life must hate you.

The people in my life must... whaaa!? I remove some files, and you post how people in my life must HATE me?

>CRINGY<
Posted By: shattered

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/23/18 08:42 PM

You have overreacted, please calm down, get the files back online and be patient.
Posted By: Haze

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/25/18 01:14 PM

indeed, I think you overestimate how many people are actively working on the project, and how much time they have.

it is a little worrying, as I've stated elsewhere, as really we do need more people monitoring places for new dumps, resources etc. but as we don't sometimes things can be slow to process.

there are some dumps in other threads here that I have an interest in too, but haven't had time to look at (eg. the new dumps from BeckieRGB) doesn't mean nobody cares, just means everybody is busy working on something already
Posted By: rfka01

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/27/18 09:25 PM

Please join me all in a rousing chorus of "Oh when the bytes come marching in ..." Do not hate the vertical video, it allows me to show both the screen and the contraption that holds the chip grin

[Linked Image]

This is the MFA computer doing (almost) what it was designed for: Helping people find their way into computer land with very hands-on methods.

The machine was expanded with a second parallel output card to have enough outputs for the nine address lines of the 2513 chargen ROM. Going through all three bit row addresses for each six bit character address, I then read the incoming data and saved it to a file on the MFA, transferred it to the PC and converted it to the BIN format that is used by the equivalent character generator in the Apple 1 driver: each five bit word is expanded to an eight bit byte with the top three bits set to zero. You can see the bottom right LED flashing although there's no cable connected - I thought first that I had to toggle the Output Inhibit aka Chip Enable line for each row, but in the end it was enough to pull it to GND. Thank goodness there were no timings to be observed.

This archive contains the ITT2020's ROMs and character ROM, this one for my Apple ][ with its language card. There are comments in the Apple 2 driver that might be resolved by these dumps. This particular machine has a lowercase chargen mod, both ROMs are dumped.
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/28/18 12:19 AM

That's AWESOME! Great blinkenlights too smile
Posted By: Anon01

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/31/18 01:43 PM

Originally Posted by Just Desserts
God, the people in your life must hate you.

Someone said I overreacted (the hypocrisy) when I removed my files, and maybe that is true, but saying people in my life must hate me (nice way to use God btw) was inappropriate. Constructive criticism is one thing, but personal attacks are unacceptable.

I have many more dumps I would like to submit (maybe not the correct way), but unless this issue is resolved, my future contributions to Mame is over.

If this can not be resolved, so be it. It's up to you.
Posted By: Robbbert

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/31/18 03:23 PM

Well, first I've seen of this. I would be adding your contribution about now, except that the files are not available.

Quote
Thank you Robbbert for teaching me how to load .bin files.


Thanks.

Maybe you could send me a PM. Just remember it can take a few weeks sometimes to get an answer.
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/31/18 03:32 PM

Originally Posted by Anon01
I have many more dumps I would like to submit (maybe not the correct way), but unless this issue is resolved, my future contributions to Mame is over.

If this can not be resolved, so be it. It's up to you.


I don't understand what a "resolution" is here.
Posted By: Anon01

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/31/18 06:58 PM

Originally Posted by R. Belmont
Originally Posted by Anon01
I have many more dumps I would like to submit (maybe not the correct way), but unless this issue is resolved, my future contributions to Mame is over.

If this can not be resolved, so be it. It's up to you.


I don't understand what a "resolution" is here.

Just Desserts can answer that question.
Posted By: Anon01

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/31/18 07:20 PM

Originally Posted by Robbbert
Well, first I've seen of this. I would be adding your contribution about now, except that the files are not available.

Quote
Thank you Robbbert for teaching me how to load .bin files.


Thanks.

Maybe you could send me a PM. Just remember it can take a few weeks sometimes to get an answer.

Thanks for your willingness to help. I wish I had your leet programing / hacking skills. Always been a fan.
Posted By: Haze

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/01/18 12:56 AM

Originally Posted by Anon01
Originally Posted by R. Belmont
Originally Posted by Anon01
I have many more dumps I would like to submit (maybe not the correct way), but unless this issue is resolved, my future contributions to Mame is over.

If this can not be resolved, so be it. It's up to you.


I don't understand what a "resolution" is here.

Just Desserts can answer that question.


If you're trying to extract an apology out of Ryan you'll fail. You can either contribute if you think it has some value to the project, or not contribute, unfortunately those are the choices you have.
Posted By: Anon01

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/02/18 04:04 PM

Originally Posted by Haze
Originally Posted by Anon01
Originally Posted by R. Belmont
Originally Posted by Anon01
I have many more dumps I would like to submit (maybe not the correct way), but unless this issue is resolved, my future contributions to Mame is over.

If this can not be resolved, so be it. It's up to you.


I don't understand what a "resolution" is here.

Just Desserts can answer that question.


If you're trying to extract an apology out of Ryan you'll fail. You can either contribute if you think it has some value to the project, or not contribute, unfortunately those are the choices you have.

I see R Belmont had to edit your post due to 'further personal insults". Interesting.

On topic.

(1) My goal was to try and resolve this matter with Just Deserts.This is where I failed.

(2) Just Deserts is all grow up. He (or it she?) can speak for himself. If he is man enough to throw insults at me, then he should be man enough to address me directly on that matter.

(3) I set the terms here, not you. My terms were either to have this issue resolved with Just Deserts, and if it could not be resolved I would no longer contribute to Mame. The issue has not been resolved, therefore I will no longer contribute to Mame. No skin off my back. It's that simple.

I'm sure more toxic comments (that have not be edited) are coming my way, so I'll be on my way.

Adios...
Posted By: Darkstar

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/02/18 08:54 PM

Originally Posted by Anon01
I'll be on my way.

Adios...

That's probably for the best.... If you don't want to contribute anything, you're just wasting your and everyone else's time...

*sigh*... some people want to be handled like rockstars for contributing to MAME... meanwhile other people just upload everything they can to archive.org so that everyone can benefit...
Posted By: Haze

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/03/18 01:32 AM

Originally Posted by Anon01

I see R Belmont had to edit your post due to 'further personal insults". Interesting.

I'm sure more toxic comments (that have not be edited) are coming my way, so I'll be on my way.


He did, although they were more strategic, and directed at MG, not you, because I wanted to show that even other people here did not appreciate his initial response. I thought this reasoning would be understood, but clearly it was not and it got edited.

That said, Darkstar and most others have a point, you're showing yourself to have an equally bad attitude, those who care about contributing contribute, because they're doing it for the value it has to the documentation of our computing history which is why projects like MAME and archive.org were formed. If you want to punish every other person on the planet because you dislike how one person treated you then that I'm afraid is your problem.

I actively dislike a number of the team members because I feel that they're bad for the project, but since I have skills to write code, I write it, because who knows, I might get hit by a bus tomorrow, and in the end what I think of them matters a lot less than the value the project has to human history.

Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/03/18 02:59 AM

I edited it more because of the specific language than the point being made, which I thought was reasonably well preserved.

Now we need to get back to topic and I gotta download the stuff rfka01 made with that awesome blinkenlights dumping rig.
Posted By: rfka01

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/03/18 06:29 AM

@RB just to clarify: the blinkenlights rig (TM) was just used for the character generators, an adapter from Reactive Micro was used for the Apple II and ITT2020 ROMs.
Posted By: Anon01

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/04/18 02:38 AM

Originally Posted by Haze
That said, Darkstar and most others have a point, you're showing yourself to have an equally bad attitude, those who care about contributing contribute, because they're doing it for the value it has to the documentation of our computing history which is why projects like MAME and archive.org were formed. If you want to punish every other person on the planet because you dislike how one person treated you then that I'm afraid is your problem.

I actively dislike a number of the team members because I feel that they're bad for the project, but since I have skills to write code, I write it, because who knows, I might get hit by a bus tomorrow, and in the end what I think of them matters a lot less than the value the project has to human history.

I'll put together the most complete apple-1 software collection available (for the cassette interface), and give it to Mame when finished. I can't give a date, as this will take some time.
Posted By: rfka01

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/04/18 08:53 AM

Quote
I'll put together the most complete apple-1 software collection available (for the cassette interface), and give it to Mame when finished. I can't give a date, as this will take some time.


Thanks! That'll be a good opportunity to check out the Apple 1 - so far it was too bare metal for me.
Posted By: Anon01

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/04/18 03:54 PM

Originally Posted by rfka01
Quote
I'll put together the most complete apple-1 software collection available (for the cassette interface), and give it to Mame when finished. I can't give a date, as this will take some time.


Thanks! That'll be a good opportunity to check out the Apple 1 - so far it was too bare metal for me.

Don't get too excited. The Apple-1 'kit computer' had a very short life (April 11, 1976 - September 30, 1977), so the available software is rather sparse. Apart from "official" Apple-1 programs (from Apple Computer Co.) a good majority of the software came from enthusiasts. Homebrew software was common in this era as computers were mostly for hobbyists.

I plan to put together all the known software for the Apple-1. However, I'm not entirely confident I will be able to convert all the programs into a .wav format. I'll see what I can do for Mame.
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/04/18 05:36 PM

If you can stuff the programs onto a CFFA-for-Apple I harddisk image we could probably use that (and it would be more user-friendly than loading from tape).
Posted By: ICEknight

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/05/18 12:34 PM

Preserving the cassettes as 48000Hz-24bit-stereo FLAC/WAVs would be very appreciated, in any case.
Posted By: Anon01

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/06/18 06:44 PM

Originally Posted by R. Belmont
If you can stuff the programs onto a CFFA-for-Apple I harddisk image we could probably use that (and it would be more user-friendly than loading from tape).

I can certainly do that, but Mame doesn't add CFAA harddisk images to the software list is that correct?
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/06/18 06:51 PM

Let us worry about that smile
Posted By: Anon01

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/14/18 09:15 PM

Aside from software, I thought it would be a good idea to have artwork to go along with the Apple-1. Maybe it will get more people curious about this vintage machine.

I plan on submitting this for Mame / MESS artwork (yes I know this isn't the place to submit it). It's a vintage Sanyo VM4209 Video Computer Monitor. It's period correct, and was used for the Apple-1. I'll have two versions. One with a realistic reflective screen (made in Photoshop shown below), and one without.


Still a work in progress (death in details).
Vintage Sanyo VM4209 Video Computer Monitor
Posted By: Anon01

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 10/29/18 02:51 AM

Originally Posted by R. Belmont
If you can stuff the programs onto a CFFA-for-Apple I harddisk image we could probably use that (and it would be more user-friendly than loading from tape).

Here is that CFFA1 CHD Apple 1.7z link for the Apple 1. The Apple 1.7z contains the 'Ultimate Apple-1 Software Collection CHD', the 'Apple-1 Infocom CHD', 'WAV tape files', 'snaps', 'artpreview', and 'In-Game Artwork'.

The 'ultimate-(Apple-1).chd' contains the most extensive software collection for the Apple 1. lord_philip put most of this collection together with his ULTIMATE APPLE1 CFFA 3.5.po. His collection was missing some programs. I converted his po to a CHD, and added TREKII, WordCross, and Wari. Detailed instructions on how to use the CFFA1 is in the 7z.

I also made an Apple 1 Infocom CHD [ infocom-(Apple-1).chd ] so people can play vintage Infocom games (z-code version 3 only) on the Apple 1. I used this tutorial by ChristopherB.

Games on the Infocom CHD :

BALLYHOO.97
CUTTHROATS.23
DEADLINE.27
ENCHANT.29
HITCH.56 (Hitchhiker's Guide to the Galaxy)
HOLLYWOOD.37 (Hollywood Hijinx)
HOLLYWOOD.235
INFIDEL.22
LGOP.0 (Leather Goddesses of Phobos)
LGOP.50
LURK.203 (The Lurking Horror)
LURK.221
MOONMIST.9
PLANETFALL.20
PLANETFALL.37
PLUNDERED.26 (Plundered Hearts)
SEASTALKER.16
SORCERERR.15
SPELLBRK.63 (Spellbreaker)
SPELLBRK.87
STARCROSS.17
STATIONFALL.107
SUSPECT.14
SUSPENDED.8
WISHBRINGER.69
WITNESS.22 (The Witness)
ZORKI.20 (Zork I)
ZORKI.25
ZORKI.30
ZORKI.75
ZORKI.88
ZORKII.48 (Zork II)
ZorkIII.17 (Zork III)

Non Infocom games :

ADVENTURE (colossal cave adventure game)
CATSEYE
CURSES
GUSSDEATH
MOONGLOW

Note: The end number is the game version.
SPELLBRK.87 (.87 is the release / version number)

Here are some new WAV files for the software list. I found these programs here. I converted the aiff to WAV for MAME.

* Enhanced BASIC
load at 5000.78B0R enter at 7825R

* Huston Basic
load at E000.EFFFR300.035FR enter at 320R

"This version of Basic (Apple Basic) contains a check sum program to verify the load. This is probably the latest version of Basic based on it being the only one with the verify program and based on some apparent bug fixes that can be seen in comparisons with other Basics." Read more here

I have not been able to add Huston Basic to the CFFA CHD. At this time It's only available as a WAV.

* Monitor
load at 0800.0FFFR enter at 0F3DR

* Wari (Load Apple Basic first)
load at 4A.00FFR400.0FFFR enter at E2B3R

* WordCross (Load Apple Basic first)
load at 4A.00FFR300.0FFFR enter at E2B3R

Last but least I've included some extras in the Apple 1 7z.

In-game Artwork (Sanyo VM4209 Monitor)
http://oi66.tinypic.com/imp64g.jpg

It's far from perfect, and I'm just too lazy to improve it (right now).
Posted By: Lord Nightmare

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 10/29/18 05:07 AM

The Infocom CHD link doesn't seem to be correct(?)

LN
Posted By: Anon01

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 10/29/18 05:56 AM

Originally Posted by Lord Nightmare
The Infocom CHD link doesn't seem to be correct(?)

LN

The Infocom CHD is in the Apple 1.7z file. Is this link not working? I placed all the CHDs, WAVS, Artwork, etc in one file. Sorry for the confusion.
Posted By: Anon01

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 10/29/18 01:44 PM

Originally Posted by Lord Nightmare


LN

What is LN?
Posted By: Lord Nightmare

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 10/29/18 01:49 PM

Originally Posted by Anon01
Originally Posted by Lord Nightmare
The Infocom CHD link doesn't seem to be correct(?)

LN

The Infocom CHD is in the Apple 1.7z file. Is this link not working? I placed all the CHDs, WAVS, Artwork, etc in one file. Sorry for the confusion.


Sorry about that, I didn't see it in there. All is good.

LN is my 'signature', it is an abbreviated form of my nickname/handle.
Posted By: Anon01

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 10/29/18 02:03 PM

Originally Posted by Lord Nightmare
LN is my 'signature', it is an abbreviated form of my nickname/handle.

I thought so, but wanted to make sure. There's so many abbreviated slang on the net, especially forums.
Posted By: Anon01

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 10/29/18 10:07 PM

I just noticed a typo with the infocom games list. SORCERERR.15 should be SORCERER.15. The Infocom CHD has the correct spelling, but I had to fix the games list in the 7z file. This is the fixed version. Apple 1.7z
Posted By: Anon01

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 11/03/18 06:19 PM

Once again I made a mistake. ZorkII.48 had an incorrect data file (Infocom.dat) in the infocom chd. This new upload has the correct version. Apple 1.7z

I've also added all the known .z3 versions of Zork 1 in the updated chd. You can read more about these versions here.

They are :

ZORKI.20
ZORKI.23
ZORKI.25
ZORKI.26
ZORKI.28
ZORKI.30
ZORKI.75
ZORKI.76
ZORKI.88 is the last .z3 version. There was a 'Solid Gold Edition (.z5), but the infocom CFFA1 only supports z3.

Hopefully this is my last upload (cross fingers). If anyone notices a mistake please leave a message. Feel free to leave any message about my uploads.Good bad or whatever.

Thanks. smile

Off topic, THIS YouTube video shows a tutorial on how to install a Generic Bezel for MAME. How flattering because I made that plastic bezel. No that isn't me in the video.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 12/04/18 11:53 AM

Have you Apple II guys heard about the VidHD from the apple II wizard John Brooks?


It outputs 1080p video and has some interesting text mode abilities like HD text modes: 40x24, 80x24, 80x45, 120x67, 240x135.

A few tidbits from the discussion on google groups:

Quote

Yes, the mirroring was only to easily demo at kfest the equivalent number of 80x24 text pages usable in each extended text mode.

The normal mode stores text in aux mem at $2000-$9E90 (240x135 chars).


Quote
The feature set at launch will be aimed at displaying existing Apple II video modes via HDMI and also adding three high-resolution 1080p text modes:

1) 80 x 45 (24x24 font)
2) 120 x 67 (16x16 font)
3) 240 x 135 (8x8 font)


> Also, I gathered from the video that you were accessing some type of
control panel. How is that accessed?

The VidHD control panel is currently activated by pressing Ctrl-^ (Ctrl-6) in any app. VidHD watches the CPU bus for a read of Ctrl-^ from $C000. When this happens, VidHD pauses the CPU, takes over the bus, reads the keyboard, and runs the control panel UI.

From the control panel screen, when the user presses return (to accept changes), or esc (to cancel), VidHD restores the active AppleII video display and the AppleII CPU is released to continue running.





Quote

BTW: I stumbled on one other undocumented Apple //e mode while making VidHD, which I forgot to include in the slides:

1KB 4-color 280x48 mode!

You enable double-lores, but then disable 80 column mode. IE, lores graphics mode with AN3 on.

It's cool because it's partial hires in only 1KB.

And yes, VidHD includes this crazy 280x48 mode and 4-color hires too.

-JB
@JBrooksBSI


Google groups discussion about the VidHD:

https://groups.google.com/forum/#!msg/comp.sys.apple2/QzlPKoV9nzg/U0318aB_AAAJ

Youtube videos:

Kansas Fest 2018

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

Text Modes demo

https://www.youtube.com/watch?v=qmiIFyvbMn0&t=27s
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 12/04/18 12:35 PM

Yes, of course I have heard of it, I have two on order smile
Posted By: peter ferrie

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 12/04/18 10:49 PM

Yes, I was at KansasFest where it was demonstrated. :-)
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 12/06/18 11:45 AM

I should figure you guys know about the VidHd. Especially considering the text on the "Bitsy Bye" screen. smile

That's the coolest thing I've seen for a long time.

Reading up on the discussion around it, other Apple video boards were mentioned which got me searching on Apple II RGB cards.

I found some interesting pictures and video of a DigiCard IIe RGB board with a blue text screen that looked really interesting, where the inverse text color wasn't just inverse bits but different colors.

I'm guessing this is the Light Blue/DarkBlue/Orange/DarkBlue combination. It's a "Fingerprint Plus" screen.

This was a look I'd never seen before.

[Linked Image]

[Linked Image]

[Linked Image]


These pictures are from a cool webpage at

http://www.cvxmelody.net/AppleUsersGroupSydneyAppleIIDiskCollection.htm#IIECOLLECTION

Video at:

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

Manual at:

https://archive.org/details/DIGICARD64KExtended80ColumnRGBCardForAppleIIeInstructionManual
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 12/22/18 03:10 AM

I recently heard about a Apple II video RGB card that I had never heard of before: The Keyzone Spectragram.

This is actually pretty cool in that it you can remap the apple hi-res colors into different colors.


from Vintage Micro Music: https://www.flickr.com/photos/88521483@N03/15316640816/

[Linked Image]

https://www.flickr.com/photos/88521483@N03/15287208695/

[Linked Image]
[Linked Image]

Apple2000 Vol 2 No 5 October 1987
[Linked Image]
Posted By: robj

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 12/30/18 01:21 AM

I notice there has been an update to the Apple /// font uploading, thanks. I also noted the comment that its still not perfect..
I had a look and it seems the wrong address was mistakenly used for turning off char writing, it should be $C0DA, and not $C0DC. I had a quick try and it seems to work ok from what i can see when this is updated.
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 12/30/18 05:22 AM

Hi Rob,

I saw your csa2 post and did that update. Nice catch, changing it to $C0DA does improve Atomic Defense (the in-game status bar font is now correct).
Posted By: robj

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 01/01/19 12:03 AM

Thanks for updating it, the font loading does looks like its working well now.

One other thing I noticed with Atomic Defense is the speech is quite quick in emulation compared to the real thing. (sorry to keep banging on about this game.. :-) )

I did a quick bit of investigation with a logic analyser. When the Video display is on, the Apple3 downshifts to 1MHz for each scan line, and then upshifts back to 2MHz for the blanking period. I can see that this impacts the overall effective speed quite a bit. And can also see why they built the function in the console driver to be able to turn off the display when you wanted it to run faster for raw processing power. I did a quick hack to set the clock to 1.5Mhz, and then the speech sounds much more like on the real metal. When set like this though, Atomic defense does not seem to run well with the smooth scroll, so seems its needs this up/down clk speed emulated correctly when the display is on. I suppose the code is relying on 2Mhz clk to get as much done in the blanking time as possible.

One other observation is that the ram refresh also causes the downshift to occur, so the A3 never really gets the full 2Mhz speed :-(.

Some pics from my logic analyser if you are interested. CH1 is PH0 from the processor, CH2 is VBL, and CH3 is BL
https://www.dropbox.com/s/ny3it2dyevzl4ba/Apple3_clk.zip?dl=0
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 01/01/19 12:17 AM

No, feel free to keep going on about the game, it's pretty much the only really good test we have for the hardware :-)

It makes perfect sense to me that it has to run 1 MHz during active video because they're still using Woz's A2 video timings, I don't know why I didn't think of that earlier myself.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 01/09/19 03:40 AM

So I was playing Miner 2049er II recently and every time I'd start up it would ask me if I wanted the Apple Joystick or Joyport Atari Joystick. It got me to thinking and doing some reading I found an article that explains how the Sirius Joyport worked:

https://en.wikipedia.org/wiki/Sirius_Joyport

https://www.atarimagazines.com/cva/v1n1/joysticks.php

the original article on archive:

https://archive.org/details/Video_Arcade_Games_Vol_1_No_1_1983-09_Creative_Computing_US/page/n101

[Linked Image]


so I thought, gee, this looks easy all it does is change the annunciator #1 to on, and then you can read pushbuttons 0, 1 and 2 to get the firebutton, left, right. It sets ann #1 to off, and then you can get the firebutton, up and down.



It's too bad that atari joysticks of this era didn't have two buttons because theoretically there's an ability to have two fire buttons on the PB0 input.


What complicates things is that it does everything backwards from typical Apple conventions. When you press the fire button on an Apple Joystick, it sets PB0 to > 128. When you press the firebutton on the Sirius Joyport Atari Joystick, PB0 is < 128. The same goes for left/right and up/down, low = pressed.

And the biggest complication of all is that the Sirius Gameport is incompatible with the Apple 2e. After hooking it up, the apple2e driver wouldn't boot. It totally freaked me out, but then I figured out that it was holding PB0 high which is also open-apple and that goes into the self-test routine.

So what to do about that? My solution is to not engage PB0 or PB1 high until after a second of machine run time. That seems to work pretty well.

It actually reads it right away, within the first 1/1000 of a second.

from my debugging junk:

C000R READ M_AN1 FALSE pb1 MDJOY_READ VALUE RAW= ff INVERT= ffffff00 RETURN= 80
Machine Time:0.000956
pb0 MDJOY_READ VALUE RAW= ff INVERT= ffffff00 RETURN= 80
Machine Time:0.000962



Okay, so the actual code: It seems to work with Miner II, Miner 2049er, Berzap, Stellar 7. The controls are definitely "tighter" since it's digital and may actually run the game a little bit faster.


One of the things I ran into is that reading/writing c05a/c05b to set/clear the annunciator would get lost, so I added a bunch of printing messages and some extra code that is probably unnecessary. I have no idea what IOUDIS is.

I wanted to be able to switch between the regular joystick and the atari joystick on the fly so I made a configuration option, I didn't think bit 0x80 was being used.


diff against mame205_extract/mame/src/mame/drivers/apple2e.cpp

Code

220,221d219
< m_djoy_0_1(*this, "djoy_0_1"),
< m_djoy_b(*this, "djoy_b"),
265d262
< required_ioport m_djoy_0_1, m_djoy_b;
1387,1388d1383
< 
< 
1445,1451d1439
< 		case 0x5a: // AN1 off
< printf("IOUDIS = 1 GETTING HIT HERE EXECUTING 0X5A DOIO M_AN1 FALSE\n");
< 			m_an1 = false; break;
< 
< 		case 0x5b: // AN1 on
< printf("IOUDIS = 1 GETTING HIT HERE DOIO M_AN1 TRUE\n");
< 			m_an1 = true; break;
1571d1558
< printf("DOIO M_AN1 FALSE");
1575d1561
< printf("DOIO M_AN1 TRUE");
1616,1618d1601
< 
< int joyreturnvalue;
< 
1680,1689d1662
< 		case 0x5a: // AN1 off
< printf("IOUDIS %x\n",m_ioudis);
< printf("C000R READ M_AN1 FALSE");
< 			m_an1 = false; break;
< 
< 		case 0x5b: // AN1 on
< printf("IOUDIS %x\n",m_ioudis);
< printf("C000R READ M_AN1 TRUE");
< 			m_an1 = true; break;
< 
1699,1701c1672
< 		case 0x69:  
< 
< if (!(m_sysconfig->read() & 0x80))
---
> 		case 0x69:
1703,1709c1674
< else {
< //NEWSTUFF (just a text target to search for)
< joyreturnvalue=(~(m_djoy_b->read()) & 0x01) ? 0x0 : 0x80;
< printf("pb0 MDJOY_READ VALUE RAW= %x INVERT= %x  RETURN= %x \n",m_djoy_b->read(),~m_djoy_b->read(),joyreturnvalue);
< if (machine().time().as_double() < 5.0) printf("Machine Time:%lf\n",machine().time().as_double());
< if (machine().time().as_double() < 1.0) return 0; else return joyreturnvalue;
< }
---
> 
1712d1676
< if (!(m_sysconfig->read() & 0x80))
1714,1719d1677
< else {
< joyreturnvalue=((~(m_djoy_0_1->read())) & ((m_an1) ? 0x01 : 0x04)) ? 0x0 : 0x80;
< printf("pb1 MDJOY_READ VALUE RAW= %x INVERT= %x  RETURN= %x \n",m_djoy_0_1->read(),~m_djoy_0_1->read(),joyreturnvalue);
< if (machine().time().as_double() < 5.0) printf("Machine Time:%lf\n",machine().time().as_double());
< if (machine().time().as_double() < 1.0) return 0; else return joyreturnvalue;
< }
1723d1680
< if (!(m_sysconfig->read() & 0x80))
1725,1731d1681
< else {
< joyreturnvalue=((~(m_djoy_0_1->read())) & ((m_an1) ? 0x02 : 0x08)) ? 0x0 : 0x80;
< printf("pb2 MDJOY_READ VALUE RAW= %x INVERT= %x  RETURN= %x \n",m_djoy_0_1->read(),~m_djoy_0_1->read(),joyreturnvalue);
< 
< if (machine().time().as_double() < 5.0) printf("Machine Time:%lf\n",machine().time().as_double());
< if (machine().time().as_double() < 1.0) return 0; else return joyreturnvalue;
< }
1756,1757d1705
< //printf("DEFAULT DO-IO in c000R offset %x\n",offset);
< 
1888d1835
< if (offset==0x5a || offset==0x5b) printf("WRITE8 C000W DEFAULT %X\n",offset);
3145,3168d3091
< 
< static INPUT_PORTS_START( apple2_sirius_joyport )
<         PORT_START("djoy_0_1")
<         PORT_BIT(0x01, 0x01, IPT_JOYSTICK_UP)    PORT_CODE(KEYCODE_8_PAD) PORT_CODE(JOYCODE_Y_UP_SWITCH)    PORT_PLAYER(1)
<         PORT_BIT(0x02, 0x02, IPT_JOYSTICK_DOWN)  PORT_CODE(KEYCODE_2_PAD) PORT_CODE(JOYCODE_Y_DOWN_SWITCH)  PORT_PLAYER(1)
<         PORT_BIT(0x04, 0x04, IPT_JOYSTICK_LEFT)  PORT_CODE(KEYCODE_4_PAD) PORT_CODE(JOYCODE_X_LEFT_SWITCH)  PORT_PLAYER(1)
<         PORT_BIT(0x08, 0x08, IPT_JOYSTICK_RIGHT) PORT_CODE(KEYCODE_6_PAD) PORT_CODE(JOYCODE_X_RIGHT_SWITCH) PORT_PLAYER(1)
<         PORT_BIT(0x10, 0x10, IPT_JOYSTICK_UP)    PORT_CODE(KEYCODE_8_PAD) PORT_CODE(JOYCODE_Y_UP_SWITCH)    PORT_PLAYER(2)
<         PORT_BIT(0x20, 0x20, IPT_JOYSTICK_DOWN)  PORT_CODE(KEYCODE_2_PAD) PORT_CODE(JOYCODE_Y_DOWN_SWITCH)  PORT_PLAYER(2)
<         PORT_BIT(0x40, 0x40, IPT_JOYSTICK_LEFT)  PORT_CODE(KEYCODE_4_PAD) PORT_CODE(JOYCODE_X_LEFT_SWITCH)  PORT_PLAYER(2)
<         PORT_BIT(0x80, 0x80, IPT_JOYSTICK_RIGHT) PORT_CODE(KEYCODE_6_PAD) PORT_CODE(JOYCODE_X_RIGHT_SWITCH) PORT_PLAYER(2)
< 
<         PORT_START("djoy_b")
<         PORT_BIT(0x01, 0x01, IPT_BUTTON1) PORT_CODE(KEYCODE_0_PAD) PORT_CODE(JOYCODE_BUTTON1) PORT_PLAYER(1)
<         PORT_BIT(0x02, 0x02, IPT_BUTTON1) PORT_CODE(JOYCODE_BUTTON1) PORT_PLAYER(2)
<         PORT_BIT(0x04, 0x04, IPT_UNUSED)
<         PORT_BIT(0x08, 0x08, IPT_UNUSED)
<         PORT_BIT(0x10, 0x10, IPT_BUTTON2) PORT_CODE(KEYCODE_DEL_PAD) PORT_CODE(JOYCODE_BUTTON2) PORT_PLAYER(1)
<         PORT_BIT(0x20, 0x20, IPT_BUTTON2) PORT_CODE(JOYCODE_BUTTON2) PORT_PLAYER(2)
<         PORT_BIT(0x40, 0x40, IPT_UNUSED)
<         PORT_BIT(0x80, 0x80, IPT_UNUSED)
< INPUT_PORTS_END
< 
< 
3171d3093
<         PORT_INCLUDE( apple2_sirius_joyport )
3181,3183d3102
<         PORT_CONFNAME(0x80, 0x00, "Gameport type")
<         PORT_CONFSETTING(0x00, "Normal")
<         PORT_CONFSETTING(0X80, "Sirius Joyport (Atari Digital)")

Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 01/09/19 04:01 AM

IOUDIS is the other reason the Joyport can't work with the //e. That signal is used for other things in those machines (like enabling double-hi-res).

I'll add correct support for the II/II Plus sometime though.
Posted By: Vas Crabb

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 01/09/19 04:51 AM

Shouln't it be a slot device? Or is this actually a hardware mod? Or is it some kind of adapter you plug in the regular Apple II analog joystick/paddle port?
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 01/09/19 05:33 AM

[Linked Image]

The Sirius Joyport would plug into the 16 pin gameport socket in an Apple 2 and allow you to plug in two Atari 9 pin digital joysticks.

I just put in a hacky config thing so I could enable it/disable it, because if a program doesn't support the Joyport, you need to be able to switch back to the normal gameport behavior.
Posted By: Vas Crabb

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 01/09/19 05:59 AM

Yeah, it's just that "thing that plugs in" is usually supposed to be a slot device, potentially exposing more slots.
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 01/09/19 12:37 PM

Right, the joysticks should be converted to a slot device (which would also allow adding support for Woz's original Atari-clone paddles in addition to this). But I'm allergic to all the inexplicable and undocumented stuff people have slammed into a2bus since Vas originally made it nice and clean.

The Atari 9-pin situation is a giant mess in MAME because the 7800 guys decided to stop contributing to MAME when I asked if they'd help clean that situation up rather than make it worse.
Posted By: Spk

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 01/12/19 03:39 AM

Running Mame64 0.205 on Windows, I'm having a video problem with the Apple IIe and certain games like Rescue Raiders and Wings of Fury.

There are flickering horizontal lines all over the screen which are quite distracting. No matter what Mame video settings I change (bgfx, d3d, gdi, etc.) the lines persist.

I've tried running Mame on three different computers with Nvidia, AMD and Intel GPUs but it doesn't make any difference, the flickering lines are always there.
I also tried the Apple II+ and Apple IIc drivers and they both suffer the same problem. However, the Apple IIgs driver does not have any problems and looks fine.

I traced the start of the problem back to Mame 167. Mame 166 and prior versions look fine.

Anybody else seeing this?
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 01/14/19 02:42 PM

I noticed a little glitching running minr2049 under apple2p and apple2e but only on the startup screen. Gameplay seems to be fine.

./mame64 apple2p minr2049

it will do it while it scrolls up the title.

[Linked Image]
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 01/14/19 03:37 PM

The lines are a side effect of the imperfect screen-split support and will eventually go away.
Posted By: Spk

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 01/14/19 09:44 PM

Yes those are the same horizontal lines I'm seeing.

I don't see them on static 'no-motion' screens, but in my case, I do see them when there's horizontal scrolling or motion like in Rescue Raiders or Wings of Fury. They are present during both game-play and the intros.

So will they eventually go away when the machine warms up a little? grin
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 01/14/19 10:19 PM

I wanted to see if my Sirius Joyport hack would work with the apple2 driver and it seems to be a bit simpler:

Yes, it's hacky but it works.

I'm having a blast beating Stellar 7 again, this time with the Atari Joystick.

./mame64 apple2p stellar7 -speed 1.5

(it's a bit better a little faster I think, you may have to do -frameskip 4 to get it to actually go faster)


Code
$ cat diff_apple2sirius.cpp 
114a115,116
>                 m_djoy_0_1(*this, "djoy_0_1"),
>                 m_djoy_b(*this, "djoy_b"),
136a139
>         required_ioport m_djoy_0_1, m_djoy_b;
640a644
>              if (!(m_sysconfig->read() & 0x80)) // if not Sirius Joyport enabled
641a646,650
>              else {
>                     // Sirius Joyport return joystick button, active low so read is inverted before &,
>                     //  return 0x0 if pressed, 0x80 if not pressed
>                     return (~(m_djoy_b->read()) & 0x01) ? 0x0 : 0x80;
>                     }
644c653,659
< 		return (m_joybuttons->read() & 0x20) ? 0x80 : 0;
---
> 	if (!(m_sysconfig->read() & 0x80))  // if not Sirius Joyport enabled
> 	         return (m_joybuttons->read() & 0x20) ? 0x80 : 0;
>         else {
>                 // Sirius Joyport return Up (0x01) or Left (0x04) depending on Annunciator #1,
>                 //  active low so read is inverted before &, return 0x0 if pressed, 0x80 if not pressed
>                 return ((~(m_djoy_0_1->read())) & ((m_an1) ? 0x01 : 0x04)) ? 0x0 : 0x80;
>                }
646a662
>                if (!(m_sysconfig->read() & 0x80)) {  // if not Sirius Joyport enabled
652a669,675
>                }
> 
>                else {  
>                // Sirius Joyport return status of Down (0x02) or Right (0x08) depending on Annunciator #1,
>                //  active low so read is inverted before &, return 0x0 if pressed, 0x80 if not pressed
>                return ((~(m_djoy_0_1->read())) & ((m_an1) ? 0x02 : 0x08)) ? 0x0 : 0x80;
> }
1146a1170,1191
> static INPUT_PORTS_START( apple2_sirius_joyport )
>          PORT_START("djoy_0_1")
>          PORT_BIT(0x01, 0x01, IPT_JOYSTICK_UP)    PORT_CODE(KEYCODE_8_PAD) PORT_CODE(JOYCODE_Y_UP_SWITCH)    PORT_PLAYER(1)
>          PORT_BIT(0x02, 0x02, IPT_JOYSTICK_DOWN)  PORT_CODE(KEYCODE_2_PAD) PORT_CODE(JOYCODE_Y_DOWN_SWITCH)  PORT_PLAYER(1)
>          PORT_BIT(0x04, 0x04, IPT_JOYSTICK_LEFT)  PORT_CODE(KEYCODE_4_PAD) PORT_CODE(JOYCODE_X_LEFT_SWITCH)  PORT_PLAYER(1)
>          PORT_BIT(0x08, 0x08, IPT_JOYSTICK_RIGHT) PORT_CODE(KEYCODE_6_PAD) PORT_CODE(JOYCODE_X_RIGHT_SWITCH) PORT_PLAYER(1)
>          PORT_BIT(0x10, 0x10, IPT_JOYSTICK_UP)    PORT_CODE(KEYCODE_8_PAD) PORT_CODE(JOYCODE_Y_UP_SWITCH)    PORT_PLAYER(2)
>          PORT_BIT(0x20, 0x20, IPT_JOYSTICK_DOWN)  PORT_CODE(KEYCODE_2_PAD) PORT_CODE(JOYCODE_Y_DOWN_SWITCH)  PORT_PLAYER(2)
>          PORT_BIT(0x40, 0x40, IPT_JOYSTICK_LEFT)  PORT_CODE(KEYCODE_4_PAD) PORT_CODE(JOYCODE_X_LEFT_SWITCH)  PORT_PLAYER(2)
>          PORT_BIT(0x80, 0x80, IPT_JOYSTICK_RIGHT) PORT_CODE(KEYCODE_6_PAD) PORT_CODE(JOYCODE_X_RIGHT_SWITCH) PORT_PLAYER(2)
> 
>          PORT_START("djoy_b")
>          PORT_BIT(0x01, 0x01, IPT_BUTTON1) PORT_CODE(KEYCODE_LCONTROL) PORT_CODE(JOYCODE_BUTTON1) PORT_PLAYER(1)
>          PORT_BIT(0x02, 0x02, IPT_BUTTON1) PORT_CODE(JOYCODE_BUTTON1)  PORT_PLAYER(2)
>          PORT_BIT(0x04, 0x04, IPT_UNUSED)
>          PORT_BIT(0x08, 0x08, IPT_UNUSED)
>          PORT_BIT(0x10, 0x10, IPT_BUTTON2) PORT_CODE(KEYCODE_DEL_PAD) PORT_CODE(JOYCODE_BUTTON2) PORT_PLAYER(1)
>          PORT_BIT(0x20, 0x20, IPT_BUTTON2) PORT_CODE(JOYCODE_BUTTON2) PORT_PLAYER(2)
>          PORT_BIT(0x40, 0x40, IPT_UNUSED)
>          PORT_BIT(0x80, 0x80, IPT_UNUSED)
> INPUT_PORTS_END
> 
1147a1193
>         PORT_INCLUDE( apple2_sirius_joyport )
1161a1208,1212
> 
>         PORT_CONFNAME(0x80, 0x00, "Gameport type")
>         PORT_CONFSETTING(0x00, "Normal")
>         PORT_CONFSETTING(0X80, "Sirius Joyport (Atari Digital)")
> 
Posted By: robj

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 01/30/19 04:00 AM

I had a question regarding how MAME chooses the floppy format. I am using the apple3 emulation and trying to load a Prodos ordered disk image, but having issues. The disk is a modified atomic-defense disk but now in po format, so its not a prodos/sos disk as such.

Does MAME used the file extension or does it detect the sector ordering some other way? Is there a way to force using po ordering?
Posted By: AJR

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 01/30/19 05:00 AM

The MAME code the Apple .DSK formats supports both sector orders, but the algorithm it uses to identify images in this case doesn't look at sector orders. It seems that only a file having the .po extension will be detected as ProDOS format.
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 01/30/19 03:17 PM

Depends on the disk controller. wozfdc attempts to algorithmically identify the sector order by matching known boot sectors, and that's what the apple3 driver uses. On apple2/2p/2e the same applies. On the IIgs, and on earlier IIs if you use "-sl6 diskii", it does use the file extension to determine the sector order.

robj: is that disc image available someplace? I can add it to the heuristics.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 01/30/19 07:31 PM

More stupid fun,

I wanted to be able to click on the apple graphics screen and find out the x,y coordinates and the memory location.

It got tiring to save a screenshot, then load into gimp to figure out what the coordinates were. So why not have mame help me out.

If I execute this routine, it will give me the coordinates, draw a line and a box around it where I click on the screen.

Once I know the address then I can just set a watchpoint in the debugger.

[Linked Image]

which allowed me to set a watchpoint "wp 3106,1,w" and then once it hit that, do a "history" which led me to a routine around 7E46 and disassembling at 7E00 points me to the memory addresses at 81F8 to 81FA where the player score is stored.

[Linked Image]



Code


function rem(a) print(a) end
function remp(a,b,c,d) print(a,b,c,d) end
function rem(a) end
function float(f) return string.format("%6.2f",f) end
function hex(a) return string.format("0x%02x",a) end
function calc(line) return line % 8 * 1024 + math.floor(line / 64) * 40 + math.floor((line%64) / 8) * 128 +8192 end

emu.unpause() 

function findmouse() 
print("BEGIN") 
for i=1,50 do  
emu.wait(0.25) 
rem(manager:machine():uiinput():find_mouse()) 
x,y,button,target=manager:machine():uiinput():find_mouse()
if target==nil then print ("TARGET=nil") return 
else
if button then 
print("\nBUTTON PRESSED") 
manager:machine().screens[":screen"]:draw_line(0,0,x/target:width()*559,y/target:height()*191,0xffffffff)
boxsize=4
manager:machine().screens[":screen"]:draw_box(x/target:width()*559-boxsize*2,y/target:height()*191-boxsize,x/target:width()*559+boxsize*2,y/target:height()*191+boxsize,0x22ffffff,0xffff0000)
xsize=target:width() 
ysize=target:height() 
textx=math.min(math.floor(x/xsize*560+10),400)
texty=math.min(math.floor(y/ysize*192+10),160)
manager:machine().screens[":screen"]:draw_text(textx,texty,"x="..float(x/xsize*280).." y="..float(y/ysize*192).."\n addr="..hex(calc(math.floor(y/ysize*192))+math.floor(x/xsize*279/7)),0xffffffff,0xffff0000)
emu.pause() 
return 
end 
xsize=target:width() ysize=target:height() 
io.write("\rx="..float(x/xsize*279) ..", y="..float(y/ysize*191) .."  address="..hex(calc(math.floor(y/ysize*191))+math.floor(x/xsize*279/7)).."  ") 
rem("Should it be *191 or *192?")
end
end 
end 
findmouseco=coroutine.create(findmouse) coroutine.resume(findmouseco)



A couple of notes, if you have the debugger paused, it won't work because the emu.wait() won't get fired.

If the target is nil, just click on a couple of windows and try it again.

And you have to emu.unpause() to get everything moving again.


Now to figure out where the shield gauge routine is:
[Linked Image]
Posted By: peter ferrie

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 01/30/19 07:41 PM

You want to cheat in Stellar 7?
That's a cool script. Normally, I just set individual watch-points on the screen lines ($2000-2027, $2400-2427, $2800-2827, etc) to know when things are hit.
I don't think that I've needed pixel-level breakpoints so far.
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 01/30/19 09:38 PM

That's a very cool script!
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 01/31/19 02:59 AM

Hi Peter,

I don't really want to cheat so much as fully understand the code. Cheating in Stellar 7 would totally spoil the whole experience. 8-) I like the sense of panic when your shield is running out, and then you've got to go into stealth mode.

I've got a project where I want to completely disassemble Stellar 7's code and figure out what everything does. I'd like to try and rewrite it with better graphics, but playing exactly like the original.

It's such a work of art that I'm amazed to this day that such a great game could be done on the Apple 2.

Thanks for your compliment!
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 01/31/19 03:07 AM

Thanks, RB!

If you like that one, here's a "better version" that gets called by emu.register_frame_done() so it runs after every frame as an overlay.


Code
function rem(a) print(a) end
function remp(a,b,c,d) print(a,b,c,d) end
function rem(a) end
function float(f) return string.format("%6.2f",f) end
function hex(a) return string.format("0x%02x",a) end
function calc(line) return line % 8 * 1024 + math.floor(line / 64) * 40 + math.floor((line%64) / 8) * 128 +8192 end

function myframedispatcher() if myframedispatchlist ~= nil then for i,j in pairs(myframedispatchlist) do j() end end end


function draw_crosshairs()
x,y,button,target=manager:machine():uiinput():find_mouse()
if target==nil then print ("TARGET=nil") return end 
manager:machine().screens[":screen"]:draw_line(0,0,x/target:width()*559,y/target:height()*191,0xffffffff)
boxsize=4
manager:machine().screens[":screen"]:draw_box(x/target:width()*559-boxsize*2,y/target:height()*191-boxsize,x/target:width()*559+boxsize*2,y/target:height()*191+boxsize,0x22ffffff,0xffff0000)
xsize=target:width() 
ysize=target:height() 
textx=math.min(math.floor(x/xsize*560+10),400)
texty=math.min(math.floor(y/ysize*192+10),160)
manager:machine().screens[":screen"]:draw_text(textx,texty,"x="..float(x/xsize*280).." y="..float(y/ysize*192).."\n addr="..hex(calc(math.floor(y/ysize*192))+math.floor(x/xsize*279/7)),0xffffffff,0xffff0000)
if button then
  myframedispatchlist={}
end
end

myframedispatchlist={} table.insert(myframedispatchlist,draw_crosshairs)


if alreadyregisteredmyframedispatcher==nil then
  emu.register_frame_done(myframedispatcher)
  alreadyregisteredmyframedispatcher=true
end


function clrd() myframedispatchlist={} end


If you press the button, it will clear the dispatcher and won't draw the target anymore.

If it goes runaway, you can type "clrd()" and hit return to stop the function calls.


Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 01/31/19 09:03 AM

I added a memory lookup as well using mem:read_u8() and noticed that it doesn't account for which hi-res page is displayed, so let's look that up in an item called ":a2video/0/m_page2".


Code
function rem(a) print(a) end
function remp(a,b,c,d) print(a,b,c,d) end
function rem(a) end
function float(f) return string.format("%6.2f",f) end
function hex(a) return string.format("0x%02x",a) end
function calc(line,page) page=page or 0 return line % 8 * 1024 + math.floor(line / 64) * 40 + math.floor((line%64) / 8) * 128 + 8192*(page + 1) end

function iif(a,b,c) if a then return b else return c end end 
function bool10(a) return iif(a,1,0) end

function bin(x,numbits,gap) if x==nil then return nil end gap=gap or "_" numbits=numbits or 8 str="" for i=numbits-1,0,-1 do str=str..iif((x&(2^i))~=0,"1","0")..iif((i%8==0) and (i>0),gap,"") end return str end

function myframedispatcher() if myframedispatchlist ~= nil then for i,j in pairs(myframedispatchlist) do j() end end end

function get_page() return  emu.item(manager:machine().devices[":a2video"].items["0/m_page2"]):read(0) end

function draw_crosshairs()
x,y,button,target=manager:machine():uiinput():find_mouse()
if target==nil then print ("TARGET=nil") return end 
manager:machine().screens[":screen"]:draw_line(0,0,x/target:width()*559,y/target:height()*191,0xffffffff)
boxsize=4
manager:machine().screens[":screen"]:draw_box(x/target:width()*559-boxsize*2,y/target:height()*191-boxsize,x/target:width()*559+boxsize*2,y/target:height()*191+boxsize,0x22ffffff,0xffff0000)
xsize=target:width() 
ysize=target:height() 
textx=math.min(math.floor(x/xsize*560+10),400)
texty=math.min(math.floor(y/ysize*192+10),160)
cpu = manager:machine().devices[":maincpu"];mem = cpu.spaces["program"]
page=get_page()
screenaddr=calc(math.floor(y/ysize*192),get_page())+math.floor(x/xsize*279/7)
screenvalue=mem:read_u8(screenaddr)
manager:machine().screens[":screen"]:draw_text(textx,texty,"x="..float(x/xsize*280).." y="..float(y/ysize*192).."\naddr="..hex(screenaddr).."\nvideo page= "..page.."\nvalue="..hex(screenvalue).." "..bin(screenvalue),0xffffffff,0xffff0000)
if button then
  myframedispatchlist={}
end
end

myframedispatchlist={} table.insert(myframedispatchlist,draw_crosshairs)

if alreadyregisteredmyframedispatcher==nil then
  emu.register_frame_done(myframedispatcher)
  alreadyregisteredmyframedispatcher=true
end

function clrd() myframedispatchlist={} end


[Linked Image]
[Linked Image]

And you can flip the hi-res pages with the following command in the debugger:
b!c054=1 (for page 1)
b!c055=1 (for page 2)

or if you're adventurous:
emu.item(manager:machine().devices[":a2video"].items["0/m_page2"]):write(0,0) for page 1
emu.item(manager:machine().devices[":a2video"].items["0/m_page2"]):write(0,1) for page 2

So if I hover over the character A in the opening menu screen and work downward, I find that the bytes are 7c,44,44,7c,46,46,46
and if I do a search with "find 0,c000,7c,44,44,7c,46,46,46" it tells that it's found at 7A08, and further study finds the text font starting at 0x7900.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 01/31/19 02:38 PM

Ok, more silly fun. The hits keep coming!

I've added cross hairs that will show the byte boundaries and the line boundaries, and if you press the 1 or 2 keys you can switch hi-res pages.

Code
function rem(a) print(a) end
function remp(a,b,c,d) print(a,b,c,d) end
function rem(a) end
function float(f) return string.format("%6.2f",f) end
function hex(a) return string.format("0x%02x",a) end
function calc(line,page) page=page or 0 return line % 8 * 1024 + math.floor(line / 64) * 40 + math.floor((line%64) / 8) * 128 + 8192*(page + 1) end

function iif(a,b,c) if a then return b else return c end end 
function bool10(a) return iif(a,1,0) end

function bin(x,numbits,gap) if x==nil then return nil end gap=gap or "_" numbits=numbits or 8 str="" for i=numbits-1,0,-1 do str=str..iif((x&(2^i))~=0,"1","0")..iif((i%8==0) and (i>0),gap,"") end return str end

function myframedispatcher() if myframedispatchlist ~= nil then for i,j in pairs(myframedispatchlist) do j() end end end

function get_page()
page = emu.item(manager:machine().devices[":a2video"].items["0/m_page2"]):read(0)
return page
end

function iskeypressed(keycode) 
inp = manager:machine():input() return inp:code_pressed(inp:code_from_token(keycode))
end

function draw_crosshairs()
x,y,button,target=manager:machine():uiinput():find_mouse()
if target==nil then print ("TARGET=nil") return end 
manager:machine().screens[":screen"]:draw_line(0,0,x/target:width()*559,y/target:height()*191,0xffffffff)
boxsize=4
manager:machine().screens[":screen"]:draw_box(x/target:width()*559-boxsize*2,y/target:height()*191-boxsize,x/target:width()*559+boxsize*2,y/target:height()*191+boxsize,0x22ffffff,0xffff0000)
xsize=target:width() 
ysize=target:height() 
textx=math.min(math.floor(x/xsize*560+10),400)
texty=math.min(math.floor(y/ysize*192+10),160)
if texty>159 then texty=texty-40 end
x1=math.floor(x/xsize*279/7)*7*2
x2=(math.floor(x/xsize*279/7)+1)*7*2
y1=math.floor(y/ysize*191)
y2=math.floor(y/ysize*191)+1
manager:machine().screens[":screen"]:draw_box(x1,0,x2,y/target:height()*191,0x44ffff00,0xffff0000)
manager:machine().screens[":screen"]:draw_box(0,y1,x/xsize*559,y2,0x44ffff00,0xffff0000)
cpu = manager:machine().devices[":maincpu"];mem = cpu.spaces["program"]
page=get_page()
screenaddr=calc(math.floor(y/ysize*191),get_page())+math.floor(x/xsize*279/7)
screenvalue=mem:read_u8(screenaddr)
manager:machine().screens[":screen"]:draw_text(textx,texty,"x="..float(x/xsize*280).." y="..float(y/ysize*192).."\naddr="..hex(screenaddr).."\nvideo page= "..page.."\nvalue="..hex(screenvalue).." "..bin(screenvalue),0xffffffff,0xffff0000)
if button then
  myframedispatchlist={}
end
if     iskeypressed("KEYCODE_1") then   emu.item(manager:machine().devices[":a2video"].items["0/m_page2"]):write(0,0)
elseif iskeypressed("KEYCODE_2") then   emu.item(manager:machine().devices[":a2video"].items["0/m_page2"]):write(0,1)
end
end

myframedispatchlist={} table.insert(myframedispatchlist,draw_crosshairs)

if alreadyregisteredmyframedispatcher==nil then
  emu.register_frame_done(myframedispatcher)
  alreadyregisteredmyframedispatcher=true
end

function clrd() myframedispatchlist={} end


[Linked Image]
Posted By: robj

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 01/31/19 09:30 PM

R.Belmont, thanks for explaining, makes sense now why it wasn't working the way I expected. I did convert my sysutils1.3 dsk to po, and it also did not work, so had me confused a bit.

Looks like there are a couple of other A3 SOS boot sectors that it might be good to add in support for. One looks like an older Apple one, and one is used on the BOS operating system disks written by Bob Consorti. This second one looks like it supports the 512k ram option. Here is a link to the disk images for these:
https://www.dropbox.com/s/jp5wppqpab2ip2v/a3_boot_sector_disks.zip?dl=0

That disk image that did not work was just my attempt at putting atomic-defense back together from my disassembled source. The boot sector for it uses the block io inbuilt into the apple3 firmware, so it was easier to just use a prodos ordered disk to just add the code parts together to make an image. I don't think there is much point adding this one in at the moment, i'll just convert to dsk and work with that for now.

And still on Atomic-defense, I worked out why the text screen disappears during the game play on some machines. The Alpha Lock key is checked by the code! If the key is down, then the text displaying the score is kept at the top. If the key is released, then the code times 240 VBL periods (4 seconds) and then removes the text from the top. It Mame it works ok once you toggle it in the game, although Mame does not seem to carry in the current state of the capslock key into the emulator on startup.
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 01/31/19 09:46 PM

Cheers, thanks Rob smile
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 02/01/19 05:28 AM

I thought I'd try and see if I could create a memory viewer that writes into the hi-res graphics page #1.

It's kind of cool, you can see that Stellar 7's menus will "fight" over drawing into the hi-res page.

There's also a really neat effect where if you scroll into hi-res page #1 memory range that the bytes will shimmer and disappear.

Code
function float(f) return string.format("%6.2f",f) end
function hex(a) return string.format("0x%02x",a) end
function calc(line,page) page=page or 0 return line % 8 * 1024 + math.floor(line / 64) * 40 + math.floor((line%64) / 8) * 128 + 8192* (page + 1) end

function iif(a,b,c) if a then return b else return c end end 
function bool10(a) return iif(a,1,0) end

function bin(x,numbits,gap) if x==nil then return nil end gap=gap or "_" numbits=numbits or 8 str="" for i=numbits-1,0,-1 do str=str..iif((x&(2^i))~=0,"1","0")..iif((i%8==0) and (i>0),gap,"") end return str end

function myframedispatcher() if myframedispatchlist ~= nil then for i,j in pairs(myframedispatchlist) do j() end end end

function between(a,b,c) return (a >= b) and (a <= c) end

function memtovideo(start,stride)
cpu = manager:machine().devices[":maincpu"];mem = cpu.spaces["program"]
screenwidth=40
mempos=start
for i=0,screenwidth+stride,stride do
for j=0,191 do
for k=0,stride-1 do
      xpos=i+k
      ypos=j
      if between(xpos,0,screenwidth-1) and between(ypos,0,191) then
            memaddress=calc(ypos)+xpos
       if between(mempos,0,0xc000) then valuetowrite=mem:read_u8(mempos)
        else valuetowrite = iif(mempos%1==0,0xaa,0x55)
       end
-- iif evaluates all operands so this won't work since it does the mem:read_u8
-- valuetowrite=iif(between(mempos,0,0xc000),mem:read_u8(mempos),iif(mempos%1==0,0xaa,0x55))
            mem:write_u8(memaddress,valuetowrite)
      end
      mempos=mempos+1
end
end
end
end

function iskeypressed(keycode) 
inp = manager:machine():input() return inp:code_pressed(inp:code_from_token(keycode))
end

mempos0=0
memorystep=192
blockwidth=1

framecounter=0
keydelay=0

function memviewer()
if keydelay > 0 then keydelay=keydelay-1 end
framecounter=framecounter+1
if framecounter % 5 == 0 then 
   framecounter=0
   memtovideo(mempos0,blockwidth)   
if     iskeypressed("KEYCODE_1") then 
          mempos0=mempos0 - (iif(iskeypressed("KEYCODE_LSHIFT"),8*blockwidth,iif(iskeypressed("KEYCODE_LCONTROL"),1,memorystep*blockwidth)))
          mempos0=math.max(0,mempos0)
elseif iskeypressed("KEYCODE_2") then 
          mempos0=mempos0 + (iif(iskeypressed("KEYCODE_LSHIFT"),8*blockwidth,iif(iskeypressed("KEYCODE_LCONTROL"),1,memorystep*blockwidth)))
          mempos0=math.min(0xc0000,mempos0)
elseif iskeypressed("KEYCODE_BACKSPACE") then myframedispatchlist={} 
elseif iskeypressed("KEYCODE_3") and keydelay==0 then blockwidth=blockwidth-1 blockwidth=math.max(blockwidth,1)   keydelay=20
elseif iskeypressed("KEYCODE_4") and keydelay==0 then blockwidth=blockwidth+1 blockwidth=math.min(blockwidth,128) keydelay=20
end
end
manager:machine().screens[":screen"]:draw_text(350,0,"Address="..hex(mempos0).."  Blockwidth="..blockwidth.."\n\nPress 1,2 = move by column\nshift+1,2 = move by 8 * blocksize\nctrl+1,2 = move by 1\n3,4 = increase/decrease blockwidth\nBackspace = quit",0xffffffff,0xffff0000)
end

myframedispatchlist={} table.insert(myframedispatchlist,memviewer)

if alreadyregisteredmyframedispatcher==nil then
  emu.register_frame_done(myframedispatcher)
  alreadyregisteredmyframedispatcher=true
end

function clrd() myframedispatchlist={} end


Here you can see the start of the font:
[Linked Image]
And here's the raven graphic:
[Linked Image]
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 02/02/19 01:58 PM

Hi guys,

I was trying to set the monitor type "on the fly" in the apple2p driver from lua, and was having problems.

There's an ioport named ":a2_config" that controls the configuration of the "Composite monitor type" from 0=Color, 1=B+W, 2=Green, 3=Amber.

INPUT_PORTS_START( apple2_sysconfig )
PORT_START("a2_config")
PORT_CONFNAME(0x03, 0x00, "Composite monitor type")
PORT_CONFSETTING(0x00, "Color")
PORT_CONFSETTING(0x01, "B&W")
PORT_CONFSETTING(0x02, "Green")
PORT_CONFSETTING(0x03, "Amber")

PORT_CONFNAME(0x04, 0x04, "Shift key mod") // default to installed
PORT_CONFSETTING(0x00, "Not present")
PORT_CONFSETTING(0x04, "Installed")
INPUT_PORTS_END

I can set it with:

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

and I read it back with

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


but for some reason, when I read it, it doesn't seem to change it right away.

So let's see what happens if we set a value, and read it right back:

function portsetvalue(x)
manager:machine():ioport().ports[":a2_config"].fields["Composite monitor type"]:set_value(x) print(manager:machine():ioport().ports[":a2_config"]:read())
end

function portwrite(x,mask)
manager:machine():ioport().ports[":a2_config"]:write(x,mask)
print(manager:machine():ioport().ports[":a2_config"]:read())
end

[MAME]> portsetvalue(0)
6
[MAME]> portsetvalue(0)
6
[MAME]> portsetvalue(0)
6
[MAME]> portsetvalue(1)
6
[MAME]> portsetvalue(0)
7
[MAME]> portsetvalue(1)
7
[MAME]> portsetvalue(0)
4
[MAME]> portsetvalue(1)
4
[MAME]> portsetvalue(0)
5
[MAME]> portsetvalue(1)
5
[MAME]> portsetvalue(0)
6
[MAME]>

and what's weird is that it the port's read() value seems to lag where it changes to a value that I've set awhile back.

I can see the monitor type change at different points but it seems very disconnected from what I'm trying to write to the port. It seems to be sensitive to actually sending a different number to set_value.


Edit: I wrote a little function that will call setvalue(0) and setvalue(1) and have an emu:wait() in between.

What's strange is that it seems to cycle the values for the monitor type 0,1,2,3 and you can see the monitor type change, cycling through (color,b&w,green,amber) in the apple2 display which doesn't make sense to me.

Code

function co1() 
for i=1,20 do 
  print("cycle="..i) 
  manager:machine():ioport().ports[":a2_config"].fields["Composite monitor type"]:set_value(0)
  print("set_value(0)")
  print(":a2_config="..manager:machine():ioport().ports[":a2_config"]:read()) 
  emu.wait(60/60) 
  manager:machine():ioport().ports[":a2_config"].fields["Composite monitor type"]:set_value(1)
  print("set_value(1)")
  print(":a2_config="..manager:machine():ioport().ports[":a2_config"]:read()) 
emu.wait(30/60) 
end 
end

co1co = coroutine.create(co1)
coroutine.resume(co1co)



cycle=1
set_value(0)
:a2_config=5
set_value(1)
:a2_config=5
cycle=2
set_value(0)
:a2_config=6
set_value(1)
:a2_config=6
cycle=3
set_value(0)
:a2_config=7
set_value(1)
:a2_config=7
cycle=4
set_value(0)
:a2_config=4
set_value(1)
:a2_config=4
cycle=5
set_value(0)
:a2_config=5
set_value(1)
:a2_config=5
cycle=6
set_value(0)
:a2_config=6
set_value(1)
:a2_config=6
... repeats 7,4,5,6,7

Edit:

I think that the ioport values update every frame so if I wait a little bit, and set_value again, I could get it to cycle on purpose.

Code
function portsetvalue(x) 
print ("set_value="..x)
manager:machine():ioport().ports[":a2_config"].fields["Composite monitor type"]:set_value(x) print(manager:machine():ioport().ports[":a2_config"]:read()) 
end

function keepcyclingport(wanted)
print(wanted)
for i=0,30 do
if (manager:machine():ioport().ports[":a2_config"]:read() & 0x03) ~= wanted then
portsetvalue(0)
emu.wait(2/60)
portsetvalue(1)
emu.wait(2/60)
else
  return
end end end

keepco =coroutine.create(keepcyclingport) coroutine.resume(keepco,2)

keepco=coroutine.create(keepcyclingport)  coroutine.resume(keepco,0)



Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 02/02/19 06:44 PM

Right, I/O ports update at VBL time, so once a frame.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 02/02/19 11:22 PM

I thought I'd try the memviewer thing on Miner 2049er to see what's in memory. I had to pause the game, and then b!c054=1 in the debugger.

It's kind of cool to see how all the graphics were laid out in memory, with 7 copies of each graphic shifted by 1 pixel.

[Linked Image]
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 02/03/19 10:35 AM

Silly fun episode XI:

So I was perusing miner 2049er main memory looking for where it draws the words PLAYER 1 and PLAYER2 but I couldn't find it. I finally figured out it was loading the screens from disk.

How to view them? Why just rewrite my memory viewer to load the data from a .dsk file instead. Just read a .dsk file into a lua string and use that as the data source.

I just let the miner 2049er program crash, since it loads some of its code into the first hi-res page and then it won't be competing for the hi-res page 0. I set up the "9" key to re initialize graphics mode.

It's neat to scroll through the disk stepping by blocks of 256 bytes, when it comes across a hi-res screen it's like it's "tuning" into view like a television.

Code
function rem(a) print(a) end
function remp(a,b,c,d) print(a,b,c,d) end
function rem(a) end
function float(f) return string.format("%6.2f",f) end
function hex(a) return string.format("0x%02x",a) end
function calc(line,page) page=page or 0 return line % 8 * 1024 + math.floor(line / 64) * 40 + math.floor((line%64) / 8) * 128 + 8192* (page + 1) end

function iif(a,b,c) if a then return b else return c end end 
function bool10(a) return iif(a,1,0) end

function bin(x,numbits,gap) if x==nil then return nil end gap=gap or "_" numbits=numbits or 8 str="" for i=numbits-1,0,-1 do str=str..iif((x&(2^i))~=0,"1","0")..iif((i%8==0) and (i>0),gap,"") end return str end

function myframedispatcher() if myframedispatchlist ~= nil then for i,j in pairs(myframedispatchlist) do j() end end end

function between(a,b,c) return (a >= b) and (a <= c) end

disksize=143360

function disktovideointerleave(start)
if mydisk==nil then return end
cpu = manager:machine().devices[":maincpu"];mem = cpu.spaces["program"]
for i=0,screenwidth do
for j=0,191 do
xpos = i
ypos = j
      if between(xpos,0,screenwidth-1) and between(ypos,0,191) then
            memaddress=calc(ypos)+xpos
            mempos=start+(memaddress-8192)
       if between(mempos,0,disksize-1) then valuetowrite=mydisk:byte(mempos+1)
          else valuetowrite = iif(mempos%1==0,0xaa,0x55)
       end
       mem:write_u8(memaddress,valuetowrite)
      end
end
end
end


function disktovideo(start,stride)
if mydisk==nil then return end
cpu = manager:machine().devices[":maincpu"];mem = cpu.spaces["program"]
screenwidth=40
mempos=start
for i=0,screenwidth+stride,stride do
for j=0,191 do
for k=0,stride-1 do
      xpos=i+k
      ypos=j
      if between(xpos,0,screenwidth-1) and between(ypos,0,191) then
         memaddress=calc(ypos)+xpos
         if between(mempos,0,disksize-1) then valuetowrite=mydisk:byte(mempos+1)
            else valuetowrite = iif(mempos%1==0,0xaa,0x55)
         end
         mem:write_u8(memaddress,valuetowrite)
      end
      mempos=mempos+1
end
end
end
end


function setgfx()
cpu = manager:machine().devices[":maincpu"];mem = cpu.spaces["program"]
dummy=mem:read_u8(0xc050)  -- display graphics
dummy=mem:read_u8(0xc052)  -- full screen
dummy=mem:read_u8(0xc054)  -- page 1
dummy=mem:read_u8(0xc057)  -- hi res
end

function iskeypressed(keycode) 
inp = manager:machine():input() return inp:code_pressed(inp:code_from_token(keycode))
end

mempos0=0
memorystep=192
blockwidth=1

framecounter=0
keydelay=0
interleavemode=0

function diskviewer()
if keydelay > 0 then keydelay=keydelay-1 end
framecounter=framecounter+1
if framecounter % 5 == 0 then 
   framecounter=0
if interleavemode == 0 then disktovideo(mempos0,blockwidth) else disktovideointerleave(mempos0) end
if     iskeypressed("KEYCODE_1") then 
     if interleavemode == 0 then
          mempos0=mempos0 - (iif(iskeypressed("KEYCODE_LSHIFT"),8*blockwidth,iif(iskeypressed("KEYCODE_LCONTROL"),1,memorystep*blockwidth)))
     else
          mempos0=mempos0 - 256 mempos0 = math.floor(mempos0 / 256) * 256
     end
          mempos0=math.max(0,mempos0)
elseif iskeypressed("KEYCODE_2") then 
     if interleavemode == 0 then
          mempos0=mempos0 + (iif(iskeypressed("KEYCODE_LSHIFT"),8*blockwidth,iif(iskeypressed("KEYCODE_LCONTROL"),1,memorystep*blockwidth)))
     else
         mempos0=mempos0 + 256 mempos0 = math.floor(mempos0 / 256) * 256
     end
          mempos0=math.min(disksize-1,mempos0)
elseif iskeypressed("KEYCODE_BACKSPACE") then myframedispatchlist={} 
elseif iskeypressed("KEYCODE_3") and keydelay==0 then blockwidth=blockwidth-1 blockwidth=math.max(blockwidth,1)   keydelay=20
elseif iskeypressed("KEYCODE_4") and keydelay==0 then blockwidth=blockwidth+1 blockwidth=math.min(blockwidth,128) keydelay=20
elseif iskeypressed("KEYCODE_9") then setgfx()
elseif iskeypressed("KEYCODE_7") then interleavemode=0
elseif iskeypressed("KEYCODE_8") then interleavemode=1 
end
end
manager:machine().screens[":screen"]:draw_text(350,0,"Disk Viewer  File="..iif(diskname==nil,"NO DISK",diskname).."\nAddress="..hex(mempos0).."  Blockwidth="..blockwidth.."\n"..iif(interleavemode==0,"","Hi-res interleave mode\n").."\n\nPress 1,2 = move by column\nshift+1,2 = move by 8 * blocksize\nctrl+1,2 = move by 1\n3,4 = increase/decrease blockwidth\n7 = Hi res interleave mode off\n8= Hi res interleave mode on\n9= Reset Graphics mode\nBackspace = quit",0xffffffff,0xffff0000)
if mydisk==nil then manager:machine().screens[":screen"]:draw_text(0,0,"No Disk Loaded") end
end

myframedispatchlist={} table.insert(myframedispatchlist,diskviewer)

if alreadyregisteredmyframedispatcher==nil then
  emu.register_frame_done(myframedispatcher)
  alreadyregisteredmyframedispatcher=true
end

function clrd() myframedispatchlist={} end

function loaddisk(filename)
   myfile=assert(io.open(filename,"r"))
   mydisk = myfile:read("*all")
   myfile:close()
   diskname=filename
end

function viewdisk(filename)
  loaddisk(filename)
  myframedispatchlist={} table.insert(myframedispatchlist,diskviewer)
end

-- dofile("../../mame205_extract/mame/memviewer_diskviewer_lua.txt")
-- loaddisk("miner 2049er (1982)(micro fun)(clean crack).dsk")


[Linked Image]
Posted By: shattered

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 02/03/19 11:01 AM

Nice. Edit mode is the logical next step :-)
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 02/15/19 08:22 PM

Stupid fun with the Joystick Calibration value:

I was reading the apple2.cpp source and noticed that the calibration for the x and y axes is different.
The x has 12 msec and the y has 13 msec.

/src/mame/drivers/apple2.cpp:316: m_x_calibration = attotime::from_usec(12).as_double();
/src/mame/drivers/apple2.cpp:317: m_y_calibration = attotime::from_usec(13).as_double();


[Linked Image]

According to the Apple II reference manual, 3060 ms is how long it should take to read the joystick which sounds right: 12ms * 256 = 3072 ms.

If you divide 3060 ms/256 you get 11.953 ms.


My calibration "program" is just a little applesoft one-liner:

100 PRINT PDL(0),PDL(1): GOTO 100

This would report 142 at rest for the PDL(0) and 154 at rest for PDL(1).

[Linked Image]


What if I set both to 12 msec? Then I got 142 at rest for both axes.

I got to thinking, what's the minimum values that would give the "full range" and 128 at rest.


It appears to be around 10800 nsec (or 10.8 msec)

// precalculate joystick time constants
m_x_calibration = attotime::from_nsec(10800).as_double();
m_y_calibration = attotime::from_nsec(10700).as_double();


[Linked Image]

With 10800 nsec, I can get 0 to 255. With 10700 nsec, the range reported is from 0 to 253.

A value too small won't give you a wide enough range.


Just for fun, I thought I'd see how Stellar 7 plays under the IIgs, but I noticed that it doesn't read the joystick properly with the faster CPU speed. Stellar 7 doesn't have any kind of pre-game joystick calibration.

So if I set the calibration down to 6 msec in the IIGS driver, the joystick reads properly and it's playable at the faster IIgs speed. Now Stellar 7 is a fast action game! Whee!

Interestingly, Stellar 7 loads very slowly (or it feels very slow to load) under the IIgs. I wonder why? I thought it'd be faster all around or at least the same speed.
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 02/15/19 09:40 PM

Thanks, I'll adjust the values in the source to 10800 nsec so we get better joystick reading.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 02/16/19 12:06 PM

Hi guys,

I was trying to play serpentine and I noticed that it would hang. I tried every image I could find and it still would freeze.

So I fired up the debugger and it seems to cycle on a loop reading c060 which is the cassette input port. If I peek (49248) I always get a value of 0. Just to experiment, I changed it to return some random "noise" and it seems to run.

It must use it for some kind of random number generator. Clearly 0-127 is perhaps too much noise I'll see if a small value like 0-15 will work.

I just tried rand()%15 and it seems to work fine.

Yes! What a great game!

Code
READ8_MEMBER(apple2_state::flags_r)
{
	// Y output of 74LS251 at H14 read as D7
	switch (offset)
	{
	case 0: // cassette in
		return m_cassette->input() > 0.0 ? 0x80 : rand()%15;


Code
http://www.kreativekorp.com/miscpages/a2info/iomemory.shtml

Comp:  O = Apple II+  E = Apple IIe  C = Apple IIc  G = Apple IIgs
Act:   R = Read       W = Write      7 = Bit 7      V = Value


C060 49248 TAPEIN       OE    R7  Read Cassette Input
                          C   R7  Status of 80/40 Column Switch
           BUTN3           G  R7  Switch Input 3
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 02/16/19 12:25 PM

It needs to return the floating bus on bits other than 7, I'll fix that. Thanks for the great report!
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 02/16/19 08:33 PM

I've committed both of these fixes for all Apple II models. Thanks again!
Posted By: anoid

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 02/16/19 10:35 PM

Thanks for the recent fixes.

Would the joystick fixes have any impact to HERO (WOZ image), where the character will always drop dynamite (press down) when landing on the ground?

Any impact to the freeze in Joust (WOZ image) after a few seconds of play?

Thanks,

A-Noid
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 02/17/19 12:22 AM

This is the first I've heard of either of those things; please report that kind of stuff ASAP smile

Joust I thought might be a protection problem, but even the San Inc crack fails the same way so I'm not sure what's going on. Peter, any ideas?

HERO sounds like you have a button stuck?
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 02/17/19 01:14 AM

Joust was suffering from relying on uninitialized memory; I've added a preliminary fill pattern on power-up that makes it happy. I'll have to see exactly what AppleWin's doing for that these days.
Posted By: anoid

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 02/17/19 01:44 AM

Arbee,

Thanks for your quick fix and dedication. Much appreciated. I have been playing with WOZ images recently and hitting a bunch of games.

- HERO behaves the same on multiple machines including online at <a href="https://archive.org/details/wozaday_HERO">WOZ HERO</a>
- Hard Hat Mack will register multiple key presses for each jump, making it hard to play. You can press down to cancel the extra jump. I don't remember having to do that on the Apple II back in the day.
- Swashbuckler has frequent random graphics corruption (lines) during play. I've seen at least one other game that also had the same graphics corruption.

One other thing. Is there a way to cycle power for Apple II in MAME without restarting MAME? F3 does a soft reset and will reset to game menu or apple prompt. It would be nice to be able to power off / on the Apple within the emulator.

Thanks again... and no demands for fixes, just enthusiasm.

A-Noid
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 02/17/19 02:17 AM

Shift + F3 does a "hard reset", which completely tears down and restarts MAME and the emulated system, it's effectively like power cycling the Apple.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 02/17/19 03:45 AM

Hi Anoid,

I thought I'd give the HERO woz a spin and sure enough, it doesn't work properly, dropping dynamite every time you land (until you run out of dynamite, of course). According to the atari 2600 manual for hero, when you pull the stick down its supposed to put down some dynamite. So that must be what's happening.

When I was playing with the joystick calibration values, I would just put some different values in and with trial and error and much recompiling I came up with some good values. Waiting for the compile and link became intolerable. So then I thought, what if I could change the calibration "on the fly" while mame was running.

I thought a slider would be cool, but that would mean messing about in the sliders with ui.cpp.

WARNING: HORRIBLE HACK ALERT!

I did a terrible hack of luaengine.cpp and the apple2.cpp, a terrible terrible hack but it seems to work. (For proof of concept)


So I added m_x_calibration, and m_y_calibration to the save_item list:

Code
	save_item(NAME(m_an0));
	save_item(NAME(m_an1));
	save_item(NAME(m_an2));
	save_item(NAME(m_an3));
	save_item(NAME(m_anykeydown));
        save_item(NAME(m_x_calibration));
        save_item(NAME(m_y_calibration));



And then did a horrible hack of emu.item, adding readasdouble and writeasdouble:

Code

*
 * emu.item(item_index)
 * item.size - size of the raw data type
 * item.count - number of entries
 * item:read(offset) - read entry value by index
 * item:read_block(offset, count) - read a block of entry values as a string (byte addressing)
 * item:write(offset, value) - write entry value by index
 */

	emu.new_usertype<save_item>("item", sol::call_constructor, sol::initializers([this](save_item &item, int index) {
					if(!machine().save().indexed_item(index, item.base, item.size, item.count))
					{
						item.base = nullptr;
						item.size = 0;
						item.count= 0;
					}
				}),
			"size", sol::readonly(&save_item::size),
			"count", sol::readonly(&save_item::count),
			"read", [this](save_item &item, int offset) -> sol::object {
					uint64_t ret = 0;
					if(!item.base || (offset > item.count))
						return sol::make_object(sol(), sol::nil);
					switch(item.size)
					{
						case 1:
						default:
							ret = ((uint8_t *)item.base)[offset];
							break;
						case 2:
							ret = ((uint16_t *)item.base)[offset];
							break;
						case 4:
							ret = ((uint32_t *)item.base)[offset];
							break;
						case 8:
							ret = ((uint64_t *)item.base)[offset];
							break;
					}
					return sol::make_object(sol(), ret);
				},
			"readasdouble", [this](save_item &item, int offset) -> sol::object {
					uint64_t ret = 0;
                                        double retfloat = 0;					
					if(!item.base || (offset > item.count))
						return sol::make_object(sol(), sol::nil);
					switch(item.size)
					{
						case 1:
						default:
							ret = ((uint8_t *)item.base)[offset];
							break;
						case 2:
							ret = ((uint16_t *)item.base)[offset];
							break;
						case 4:
							ret = ((uint32_t *)item.base)[offset];
							break;
						case 8:
							ret = ((uint64_t *)item.base)[offset];
							break;
					}
                                        retfloat = (*(double *) &ret);                         // get the return value as a float
					return sol::make_object(sol(), retfloat);
				},	

			"read_block", [](save_item &item, int offset, sol::buffer *buff) {
					if(!item.base || ((offset + buff->get_len()) > (item.size * item.count)))
						buff->set_len(0);
					else
						memcpy(buff->get_ptr(), (uint8_t *)item.base + offset, buff->get_len());
					return buff;
				},
			"write", [](save_item &item, int offset, uint64_t value) {
					if(!item.base || (offset > item.count))
						return;
					switch(item.size)
					{
						case 1:
						default:
							((uint8_t *)item.base)[offset] = (uint8_t)value;
							break;
						case 2:
							((uint16_t *)item.base)[offset] = (uint16_t)value;
							break;
						case 4:
							((uint32_t *)item.base)[offset] = (uint32_t)value;
							break;
						case 8:
							((uint64_t *)item.base)[offset] = (uint64_t)value;
							break;
					}
				},
			"writeasdouble", [](save_item &item, int offset, double value) {
					if(!item.base || (offset > item.count))
						return;
					switch(item.size)
					{
						case 1:
						default:
							((uint8_t *)item.base)[offset] = (uint8_t)value;
							break;
						case 2:
							((uint16_t *)item.base)[offset] = (uint16_t)value;
							break;
						case 4:
							((uint32_t *)item.base)[offset] = (uint32_t)value;
							break;
						case 8:
							((double *)item.base)[offset] = value;        // write the double value
							break;
					}
				});





and I also made a new device method to return all of items in the item list: allitems

Why did I do that? Because the items in the apple2 state are inaccessible. I can see them in the Memory Window in the debugger, but not with lua.

If I execute this lua one-liner, my x and y calibration don't show up in the device list.

for devname,devdevice in pairs(manager:machine().devices) do print (devname,devdevice) for i,j in pairs(devdevice.items) do print(i,j) end end

But device.items[] iterates through the whole list, checking the devicetag to match, why not just make a variation called allitems that will just add them all.
So it you look below, it just has an if (1).

Code

/* machine.devices[device_tag]
 * device:name() - device long name
 * device:shortname() - device short name
 * device:tag() - device tree tag
 * device:owner() - device parent tag
 * device:debug() - debug interface, cpus only
 * device.spaces[] - device address spaces table
 * device.state[] - device state entries table
 * device.items[] - device save state items table (item name is key, item index is value)
 */

	sol().registry().new_usertype<device_t>("device", "new", sol::no_constructor,
			"name", &device_t::name,
			"shortname", &device_t::shortname,
			"tag", &device_t::tag,
			"owner", &device_t::owner,
			"debug", [this](device_t &dev) -> sol::object {
					if(!(dev.machine().debug_flags & DEBUG_FLAG_ENABLED) || !dynamic_cast<cpu_device *>(&dev)) // debugger not enabled or not cpu
						return sol::make_object(sol(), sol::nil);
					return sol::make_object(sol(), dev.debug());
				},
			"spaces", sol::property([this](device_t &dev) {
					device_memory_interface *memdev = dynamic_cast<device_memory_interface *>(&dev);
					sol::table sp_table = sol().create_table();
					if(!memdev)
						return sp_table;
					for(int sp = 0; sp < memdev->max_space_count(); ++sp)
					{
						if(memdev->has_space(sp))
							sp_table[memdev->space(sp).name()] = addr_space(memdev->space(sp), *memdev);
					}
					return sp_table;
				}),
			"state", sol::property([this](device_t &dev) {
					sol::table st_table = sol().create_table();
					if(!dynamic_cast<device_state_interface *>(&dev))
						return st_table;
					// XXX: refrain from exporting non-visible entries?
					for(auto &s : dev.state().state_entries())
						st_table[s->symbol()] = s.get();
					return st_table;
				}),
			"items", sol::property([this](device_t &dev) {
					sol::table table = sol().create_table();
					std::string tag = dev.tag();
					// 10000 is enough?
					for(int i = 0; i < 10000; i++)
					{
						std::string name;
						const char *item;
						unsigned int size, count;
						void *base;
						item = dev.machine().save().indexed_item(i, base, size, count);
						if(!item)
							break;
						name = &(strchr(item, '/')[1]);
						if(name.substr(0, name.find("/")) == tag)
						{
							name = name.substr(name.find("/") + 1, std::string::npos);
							table[name] = i;
						}
					}
					return table;
				}),

			"allitems", sol::property([this](device_t &dev) {
					sol::table table = sol().create_table();
					std::string tag = dev.tag();
					// 10000 is enough?
					for(int i = 0; i < 10000; i++)
					{
						std::string name;
						const char *item;
						unsigned int size, count;
						void *base;
						item = dev.machine().save().indexed_item(i, base, size, count);
						if(!item)
							break;
						name = &(strchr(item, '/')[1]);
					//if(name.substr(0, name.find("/")) == tag)
					if(1)
						{
							name = name.substr(name.find("/") + 1, std::string::npos);
							table[name] = i;
						}
					}
					return table;
				})

			);



so once that's done I can do this:

emu.item(manager:machine().devices[":maincpu"].allitems["0/m_y_calibration"]):writeasdouble(0,9800e-9)
emu.item(manager:machine().devices[":maincpu"].allitems["0/m_y_calibration"]):writeasdouble(0,9800e-9)


If you read it as an integer, it is nonsense.

print(emu.item(manager:machine().devices[":maincpu"].allitems["0/m_x_calibration"]):read(0))
4533201175231652948

You want to use my new function readasdouble:

print(emu.item(manager:machine().devices[":maincpu"].allitems["0/m_x_calibration"]):readasdouble(0))
1.2e-05


[MAME]> function printt(a) for i,j in pairs(a) do print(i,j) end end
[MAME]>
[MAME]> printt(manager:machine().devices[":maincpu"].allitems)
m_lastcoin 610
10/m_stored_vector 351
0/TMP 319
0/m_last_update_time.attoseconds 264
31/m_stored_vector 456
21/m_stored_vector 405
41/m_stored_vector 507
2E/m_curstate 442
1E/m_curstate 391
0/m_y_calibration 234
0/m_totalcycles 341
0/m_step_samples 308
... etc



Okay, so back to HERO:

Just trying some different values I can get the joystick to work properly and not drop the dynamite:


9800 nsec seems to work:

[MAME]> print(emu.item(manager:machine().devices[":maincpu"].allitems["0/m_x_calibration"]):writeasdouble(0,9800e-9))

[MAME]> print(emu.item(manager:machine().devices[":maincpu"].allitems["0/m_y_calibration"]):writeasdouble(0,9800e-9))


[MAME]> print(emu.item(manager:machine().devices[":maincpu"].allitems["0/m_x_calibration"]):readasdouble(0))
9.8e-06
[MAME]> print(emu.item(manager:machine().devices[":maincpu"].allitems["0/m_y_calibration"]):readasdouble(0))
9.8e-06


Actually, 10800 nsec works too (I forgot that I was using the old 12 msec values to start with)

print(emu.item(manager:machine().devices[":maincpu"].allitems["0/m_x_calibration"]):writeasdouble(0,10800e-9))
print(emu.item(manager:machine().devices[":maincpu"].allitems["0/m_y_calibration"]):writeasdouble(0,10800e-9))


Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 02/17/19 04:11 AM

Horrible hack part #2 - finding the optimum value for the Apple IIGS and Stellar 7 on fast cpu mode.

I added the m_x_calibration and m_y_calibration to the save item list in the apple2gs.cpp driver.


So I located the joystick read routine for Stellar 7 by putting a watchpoint on C064 (analog paddle 0 read)

[Linked Image]

then I put some breakpoints on every RTS from the read joystick subroutine that would print out the joystick return values:

wp c064,1,r

bp 7ca1,1,{printf "x=%02x y=%02x",x,y;g}
bp 7cb2,1,{printf "x=%02x y=%02x",x,y;g}
bp 7cc3,1,{printf "x=%02x y=%02x",x,y;g}

wpdis 1

[Linked Image]


then I could fine-tune my joystick calibration values with some lua commands in real time:

print(emu.item(manager:machine().devices[":maincpu"].allitems["0/m_x_calibration"]):writeasdouble(0,2500e-9)) -- maximum is 3E

print(emu.item(manager:machine().devices[":maincpu"].allitems["0/m_x_calibration"]):writeasdouble(0,4800e-9)) -- maximum is 7e, half 3c

print(emu.item(manager:machine().devices[":maincpu"].allitems["0/m_x_calibration"]):writeasdouble(0,5150e-9)) -- maximum is 7F, half is 40
print(emu.item(manager:machine().devices[":maincpu"].allitems["0/m_y_calibration"]):writeasdouble(0,5150e-9))


So it looks like the "perfect" calibration for Stellar 7 running in fast mode is 5150 nsec.

Posted By: anoid

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 02/17/19 05:03 AM

Golden Child,

Thanks for the information. I guess that the fix Arbee did earlier may actually fix the problem in HERO by changing to 10800 nsec.

I do remember manually centering the joysticks on the Apple II back in the day...

A-Noid
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 02/17/19 06:10 PM

Horrible hack part #3:

I wanted to see if I could create a function under the emu table that would give me all of the items:

Code
// New function emu["items"]

	emu["items"] = [this](){ 	sol::table table = sol().create_table();
					// 10000 is enough?
					for(int i = 0; i < 10000; i++)
					{
						std::string name;
						const char *item;
						unsigned int size, count;
						void *base;
						item = machine().save().indexed_item(i, base, size, count);
						if(!item) break;
						//name = &(strchr(item, '/')[1]);
						name = item;
						table[name] = i;
						
					}
					return table;
				};


Now I can do this:

Code
print(emu.item(emu.items()["Apple //e/:/0/m_y_calibration"]):readasdouble(0))
1.3e-05


If I uncomment the //name = &(strchr(item, '/')[1]); it will strip off the leading part up to the first / but I kind of like having the full name. It also matches the names that show up in the Debug: Memory View.


function printt(a) for i,j in pairs(a) do print(i,j) end end
function printto(a) local b={} for i,j in pairs(a) do b[j]=i end printt(b) end

[MAME]> printto(emu.items())
1 5.25" single density floppy drive/:sl6:diskiing:0:525/0/m_clock
2 5.25" single density floppy drive/:sl6:diskiing:0:525/0/m_clock_scale
...
142 Apple //e/:/0/m_x_calibration
143 Apple //e/:/0/m_xirq
144 Apple //e/:/0/m_xy
145 Apple //e/:/0/m_y0
146 Apple //e/:/0/m_y0edge
147 Apple //e/:/0/m_y1
148 Apple //e/:/0/m_y_calibration
149 Apple //e/:/0/m_yirq
...
828 timer/sound_manager::update/0/m_start.attoseconds
829 timer/sound_manager::update/0/m_start.seconds
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 02/17/19 07:48 PM

More hacking on luaengine:

why not just directly get the item?

If I create this function (it's horribly inefficient but proof of concept:) I can just go ahead and get an item directly from a string:
Code
      emu["getitem"] = [this](const char* itemname){ 	sol::table table = sol().create_table();
					// 10000 is enough?
					int index = -1;
					save_item return_item;
					if (!(itemname == 0))					
					for(int i = 0; i < 10000; i++)
					{
						std::string name;
						const char *item;
						unsigned int size, count;
						void *base;
						item = machine().save().indexed_item(i, base, size, count);
						if(!item) break;
						//name = &(strchr(item, '/')[1]);
						name = item;
						table[name] = i;
                                                if (itemname == name) index = i;						
					}
				if (index == -1 || !machine().save().indexed_item(index, return_item.base, return_item.size, return_item.count))	
					{	return_item.base = nullptr;
						return_item.size = 0;
						return_item.count= 0;
					};
					return return_item;
				};



Code
[MAME]> print(emu.item(emu.items()["Apple //e/:/0/m_y_calibration"]):readasdouble(0))
1.3e-05
[MAME]> print(emu.getitem("Apple //e/:/0/m_y_calibration"):readasdouble(0))
1.3e-05
[MAME]> print(emu.getitem("Apple //e/:/0/m_x_calibration"):readasdouble(0))
1.2e-05
[MAME]> print(emu.getitem("Apple misspelled"):readasdouble(0))
nil
[MAME]> print(emu.getitem("doesnt exist"):readasdouble(0))
nil
[MAME]> print(emu.getitem():readasdouble(0))
nil


Posted By: peter ferrie

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 02/17/19 11:51 PM

It's funny about Joust. I never tested it in MAME, apparently.
I've known about Serpentine for ages. I thought that I submitted the fix for it, but clearly not.
A couple of other games had the same requirement.
I think that Pooyan and Lady Tut also rely on uninitialised memory, but the effects aren't detrimental.

Yes, Hero is very sensitive to the joystick calibration.
Posted By: anoid

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 02/18/19 12:12 AM

A couple more...

Congo Bongo (WOZ) won't boot in MAME, but the crack works from the software list.

I've noticed longer delays in Drol (WOZ) when loading the 3rd level (snakes) and winning cut scene after 3rd level. Levels 1 and 2 seem to have load times similar to cracked version.

A-Noid
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 02/18/19 12:23 AM

Regarding load times, originals oftentimes will take longer because they're doing a protection check instead of just loading the data.

Peter: does Congo Bongo use weak bits?
Posted By: peter ferrie

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 02/18/19 12:25 AM

RB: yes, along with Bruce Lee and Mr. Do.
Posted By: peter ferrie

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 02/18/19 12:30 AM

Regarding Drol, those two sections are huge compared to the other two, and the protection is alternating quarter-track, so it's very slow to load.
Try our Lode Runner crack vs the original for extreme speed difference! :-)
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 02/23/19 01:24 PM

Here's a quality-of-life improvement for the 8-bit A2s: the disassembler now knows about Monitor ROM entry points, soft switches, and common zero-page locations. ProDOS MLI parsing is to come, as is full IIgs support for Toolbox and GS/OS calls and bank $E0/$E1 globals.

[Linked Image]
Posted By: peter ferrie

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 02/23/19 05:03 PM

That's awesome. I'm always forgetting the names of some of those.
By the way, $FADA is RGDSP1.
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 02/23/19 07:15 PM

$FADA wasn't in the lists I was using, but I'll add it.

The version going in also shows ProDOS 8 calls and lets you step over them cleanly.
Posted By: Carbon

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 02/23/19 08:08 PM

That's very cool. Out of curiosity, does this exist for other systems?
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 02/23/19 08:33 PM

There's a few others (the Mac, Palm, and TRS-80 Color Computers), and it's pretty easy to add more. The downside is that as it's currently implemented, it's pretty low-level; your hook has the same power and responsibility as the CPU core disassemblers, except you can pass any opcode you don't want back to the core to deal with. It's probably easiest to do for A-line traps on 680x0 systems, which is why 2 of the existing 3 are 680x0.
Posted By: Carbon

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 02/24/19 08:28 AM

A-Traps? Now, there's something that reminds me my active programming years. And now I think of Scott Knasters's Mac programming books ... 😊
Posted By: peter ferrie

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 02/25/19 04:49 AM

Originally Posted by R. Belmont
$FADA wasn't in the lists I was using, but I'll add it.


I have the original monitor ROM source. I can add more of the labels for the next version.
First, though, is to get II+ LC working properly. It's marked writable but writes are ignored until state is changed to read-only and then back to writable.
Posted By: peter ferrie

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 02/26/19 05:19 PM

RB, related to that, while I'm adding the missing labels from the monitor source, shall I change the zpage labels to their original names? e.g. CURSORHORZ -> CH, TXTWIDTH -> WNDWDTH...
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 02/26/19 05:34 PM

If you have canonical names for them, go ahead. I was working primarily off of http://www.kreativekorp.com/miscpages/a2info/zeropage.shtml which gives what they are but not the canonical names.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 03/03/19 12:45 AM

Some more silly fun:

I always thought that Altirra's enhanced text mode was pretty cool, so why not see if I could do a text overlay with lua?

Code

-- 80 column text overlay for Apple IIe

function calc(line,page) page=page or 0 return line % 8 * 1024 + math.floor(line / 64) * 40 + math.floor((line%64) / 8) * 128 + 8192* (page + 1) end

function iskeypressed(keycode) 
inp = manager:machine():input() return inp:code_pressed(inp:code_from_token(keycode))
end

function striphi(a) if type(a)=="number" then a=string.char(a) end local b="" for i=1,#a do b=b..string.char(string.byte(a,i)&0x7f) end return b end

mem=manager:machine().devices[":maincpu"].spaces["program"]
aux=emu.item(manager:machine().devices[":aux:ext80"].items["0/m_ram"])
scr=manager:machine().screens[":screen"]

function widthpct(c) if c==nil or c==string.char(0) then return 0 end return ((manager:ui():get_string_width(c,1.0)/manager:ui():get_string_width("A",1.0))) end
function widthoffset(c) if c==nil or c==string.char(0) then return 0 end return 3.5*(1-widthpct(c)) end


drawoverlay=true
keydelay=0

function print_80col()
for y=0,23 do for x=0,39 do offset=calc(y*8)-8192+x 
c1=striphi(aux:read(1024+offset)) c0=striphi(mem:read_u8(1024+offset))
io.write(c1..c0) end print() end
end

function draw_80col()
if keydelay > 0 then keydelay = keydelay - 1 end
if drawoverlay then 
scr:draw_box(0,0,559,279,0xff000000,0xffffffff)for y=0,23 do for x=0,39 do offset=calc(y*8)-8192+x 
c1=striphi(aux:read(1024+offset)) c0=striphi(mem:read_u8(1024+offset))
scr:draw_text((x*2+0)*7+widthoffset(c1),y*8,c1,0xffffffff,0xff000000) scr:draw_text((x*2+1)*7+widthoffset(c0),y*8,c0,0xffffffff,0xff000000) end end
end
if iskeypressed("KEYCODE_LSHIFT") and keydelay==0 then drawoverlay=not drawoverlay keydelay=20 end
end

draw80dispatchlist={draw_80col}

function draw80dispatch() for i,j in pairs(draw80dispatchlist) do j() end end

function drawon() draw80dispatchlist={draw_80col} end
function drawoff() draw80dispatchlist={} end

if not alreadyregistereddraw80 then
  emu.register_frame_done(draw80dispatch)
  alreadyregistereddraw80=true
end




With overlay:
[Linked Image]

Without overlay:
[Linked Image]


Just hit the shift key to toggle it on/off


It took me a while to figure out why it looks strange when it's scrolling in 80 columns. Reading with manager:machine().devices[":maincpu"].spaces["program"]:read_u8() gets the data from the auxiliary memory when the softswitches are set during the scroll.
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 03/03/19 01:55 AM

That's really cool! Apple II text display in modern fonts smile

For added perversion, use https://www.kreativekorp.com/software/fonts/apple2.shtml as the MAME UI font.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 03/03/19 12:24 PM

Here's a small improvement:

Using emu.item(manager:machine().devices[":ram"].items["0/m_pointer"]):read() will always get main memory so the scrolling is not as strange while the softswitches are getting hit.

Also we do inverse characters by flipping the foreground/background color so you can see the cursor.

Code

-- 80 column text overlay for Apple IIe

function calc(line,page) page=page or 0 return line % 8 * 1024 + math.floor(line / 64) * 40 + math.floor((line%64) / 8) * 128 + 8192* (page + 1) end

function iskeypressed(keycode) 
inp = manager:machine():input() return inp:code_pressed(inp:code_from_token(keycode))
end

function striphi(a) if type(a)=="number" then a=string.char(a) end local b="" for i=1,#a do b=b..string.char(string.byte(a,i)&0x7f) end return b end

mem=manager:machine().devices[":maincpu"].spaces["program"]              -- gets main or aux, depending on softswitches
aux=emu.item(manager:machine().devices[":aux:ext80"].items["0/m_ram"])   -- gets aux memory
scr=manager:machine().screens[":screen"]
main=emu.item(manager:machine().devices[":ram"].items["0/m_pointer"])  -- always gets main memory

function widthpct(c) if c==nil or c==string.char(0) then return 0 end return ((manager:ui():get_string_width(c,1.0)/manager:ui():get_string_width("A",1.0))) end
function widthoffset(c) if c==nil or c==string.char(0) then return 0 end return 3.5*(1-widthpct(c)) end


function between(a,b,c) return (a >= b) and (a <= c) end

function applecharfixinverse(c)
  if type(c)=="string" then c=string.byte(c) end
  if c == 0 then return string.char(32),false end -- looks terrible with @ signs at bootup
  if between(c,0,31) then return string.char(c+64),true
  elseif between (c,32,127) then return string.char(c), true
  elseif between (c,128,159) then return string.char(c-128+64), false
  elseif between (c,160,255) then return string.char(c-128), false
  else return 0, false
  end
end

drawoverlay=true
keydelay=0

function print_80col()
for y=0,23 do for x=0,39 do offset=calc(y*8)-8192+x 
c1=striphi(aux:read(1024+offset)) c0=striphi(mem:read_u8(1024+offset)) 
io.write(c1..c0) end print() end
end

function draw_80col()
if keydelay > 0 then keydelay = keydelay - 1 end
if drawoverlay then 
scr:draw_box(0,0,559,279,0xff000000,0xffffffff)for y=0,23 do for x=0,39 do offset=calc(y*8)-8192+x 
c1=aux:read(1024+offset)
c1,c1invert=applecharfixinverse(c1)
c0=main:read(1024+offset)
c0,c0invert=applecharfixinverse(c0)
fgcolor,bgcolor=0xffffffff,0xff000000
if c1invert then fgcolor,bgcolor=bgcolor,fgcolor end
scr:draw_text((x*2+0)*7+widthoffset(c1),y*8,c1,fgcolor,bgcolor) 
fgcolor,bgcolor=0xffffffff,0xff000000
if c0invert then fgcolor,bgcolor=bgcolor,fgcolor end
scr:draw_text((x*2+1)*7+widthoffset(c0),y*8,c0,fgcolor,bgcolor) end end
end
if iskeypressed("KEYCODE_LSHIFT") and keydelay==0 then drawoverlay=not drawoverlay keydelay=20 end
end

draw80dispatchlist={draw_80col}

function draw80dispatch() for i,j in pairs(draw80dispatchlist) do j() end end

function drawon() draw80dispatchlist={draw_80col} end
function drawoff() draw80dispatchlist={} end

if not alreadyregistereddraw80 then
  emu.register_frame_done(draw80dispatch)
  alreadyregistereddraw80=true
end




oops - I added a check for the 0 character since the aux card gets all 0's on bootup and it makes it hard to read.
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 03/03/19 09:29 PM

You could key off the m_80col variable in the a2video device to determine if 80 column video is enabled, and either drop to 40 or don't show the overlay.
Posted By: anoid

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 03/04/19 04:56 AM

Thanks to Golden Child and R. Belmont for fixing the Apple keyboard timings.... Can play HERO wonderfully with MAME 0.207.

A-Noid
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 03/04/19 02:35 PM

Hi guys,

Just wanted to share my latest lua project for fiddling with Apple disk images.

You can load a disk image into a global "mydisk" variable with:

loaddisk("stellar7.dsk")

then you can do

Code
catalog()
[MAME]> catalog()
(11,0f) 00  *B 003 LETTER                         TS List=(12,0f)
(11,0f) 01  *B 01a ROCK1                          TS List=(12,0c)
(11,0f) 02  *B 04f ROCK2                          TS List=(13,02)
(11,0f) 03  *B 007 ROCK3                          TS List=(18,03)
(11,0f) 04   B 022 TITLE                          TS List=(04,0f)
(11,0f) 05  *B 022 PANEL                          TS List=(1b,0a)
(11,0f) 06  *B 022 BRIEF                          TS List=(1d,08)
(11,0e) 00  *B 008 BRIEF.ST                       TS List=(1f,06)
(11,0e) 01  *B 019 PLAYGAME                       TS List=(20,0e)
(11,0e) 02  *B 00f BRIEFING                       TS List=(21,05)
(11,0e) 03  *B 00e LEV1                           TS List=(22,07)
(11,0e) 04  *B 00e LEV2                           TS List=(10,09)
(11,0e) 05  *B 00e LEV3                           TS List=(0f,0b)
(11,0e) 06  *B 00e LEV4                           TS List=(08,0f)
(11,0d) 00  *B 00e LEV5                           TS List=(0d,0f)
(11,0d) 01  *B 00e LEV6                           TS List=(07,0f)
(11,0d) 02  *B 00e LEV7                           TS List=(06,0f)
(11,0d) 03  *B 002 OBJ1                           TS List=(0b,05)
(11,0d) 04  *B 002 OBJ2                           TS List=(0b,03)
(11,0d) 05  *B 002 OBJ3                           TS List=(0b,01)
(11,0d) 06  *B 002 OBJ4                           TS List=(0a,0f)
(11,0c) 00  *B 002 OBJ5                           TS List=(0a,0d)
(11,0c) 01  *B 002 OBJ6                           TS List=(0a,0b)
(11,0c) 02  *B 002 OBJ7                           TS List=(0a,09)
(11,0c) 03  *B 003 DYN1                           TS List=(0a,07)
(11,0c) 04  *B 003 DYN2                           TS List=(0a,04)
(11,0c) 05  *B 003 DYN3                           TS List=(0a,01)
(11,0c) 06  *B 003 DYN4                           TS List=(09,0e)
(11,0b) 00  *B 003 DYN5                           TS List=(09,0b)
(11,0b) 01  *B 003 DYN6                           TS List=(09,08)
(11,0b) 02  *B 003 DYN7                           TS List=(09,05)
(11,0b) 03   B 002 HIGH                           TS List=(09,02)
(11,0b) 04   A 002 HELLO                          TS List=(19,0c)
(11,0b) 05   A 003 LEVELS VERTAUSCHEN             TS List=(1a,0f)
T=228 out of range

and if you want to load a file:
Code
[MAME]> a=getfileraw("LEVEL")
(11,0f) 00  *B 003 LETTER                         TS List=(12,0f)
...
(11,0b) 04   A 002 HELLO                          TS List=(19,0c)
(11,0b) 05   A 003 LEVELS VERTAUSCHEN             TS List=(1a,0f)
matched "LEVEL" with "LEVELS VERTAUSCHEN            "

You can do basic dumps
Code
[MAME]> basdump(a)
5   PRINT "LEVELS VERTAUSCHEN": PRINT 
10   PRINT 
15   INPUT "LEVEL1, LEVEL2 ZU TAUSCHEN ?";L1,L2
17   IF L1 = 0 OR L2 = 0 THEN 30
18  A$ = "UNLOCK":I = L1: GOSUB 100:I = L2: GOSUB 100
20  I = L1:A$ = "RENAME":J = 99: GOSUB 110:I = L2:J = L1: GOSUB 110:I = 99:J = L2: GOSUB 110
30  A$ = "LOCK":I = L1: GOSUB 100:I = L2: GOSUB 100
40   PRINT "FERTIG.": PRINT : RUN 
99   END 
100   PRINT A$"LEV"I: PRINT A$"OBJ"I: PRINT A$"DYN"I: RETURN 
110   PRINT A$"LEV"I",LEV"J: PRINT A$"OBJ"I",OBJ"J: PRINT A$"DYN"I",DYN"J: RETURN 

or hexdumps

Code
[MAME]> hexdump(a)
00   5c 01 1d 08 05 00 ba 22  |  4c 45 56 45 4c 53 20 56  |  \.....:"LEVELS V
10   45 52 54 41 55 53 43 48  |  45 4e 22 3a ba 00 23 08  |  ERTAUSCHEN"::.#.
20   0a 00 ba 00 4d 08 0f 00  |  84 22 4c 45 56 45 4c 31  |  ..:.M...."LEVEL1
30   2c 20 4c 45 56 45 4c 32  |  20 5a 55 20 54 41 55 53  |  , LEVEL2 ZU TAUS
40   43 48 45 4e 20 3f 22 3b  |  4c 31 2c 4c 32 00 5f 08  |  CHEN ?";L1,L2._.
50   11 00 ad 4c 31 d0 30 ce  |  4c 32 d0 30 c4 33 30 00  |  ..-L1P0NL2P0D30.
60   84 08 12 00 41 24 d0 22  |  04 55 4e 4c 4f 43 4b 22  |  ....A$P".UNLOCK"
70   3a 49 d0 4c 31 3a b0 31  |  30 30 3a 49 d0 4c 32 3a  |  :IPL1:0100:IPL2:
80   b0 31 30 30 00 c2 08 14  |  00 49 d0 4c 31 3a 41 24  |  0100.B...IPL1:A$
90   d0 22 04 52 45 4e 41 4d  |  45 22 3a 4a d0 39 39 3a  |  P".RENAME":JP99:
a0   b0 31 31 30 3a 49 d0 4c  |  32 3a 4a d0 4c 31 3a b0  |  0110:IPL2:JPL1:0
b0   31 31 30 3a 49 d0 39 39  |  3a 4a d0 4c 32 3a b0 31  |  110:IP99:JPL2:01
c0   31 30 00 e5 08 1e 00 41  |  24 d0 22 04 4c 4f 43 4b  |  10.e...A$P".LOCK
d0   22 3a 49 d0 4c 31 3a b0  |  31 30 30 3a 49 d0 4c 32  |  ":IPL1:0100:IPL2
e0   3a b0 31 30 30 00 f8 08  |  28 00 ba 22 46 45 52 54  |  :0100.x.(.:"FERT
f0   49 47 2e 22 3a ba 3a ac  |  00 fe 08 63 00 80 00 22  |  IG.":::,.~.c.�."
100   09 64 00 ba 41 24 22 4c  |  45 56 22 49 3a ba 41 24  |  .d.:A$"LEV"I::A$
110   22 4f 42 4a 22 49 3a ba  |  41 24 22 44 59 4e 22 49  |  "OBJ"I::A$"DYN"I
120   3a b1 00 5b 09 6e 00 ba  |  41 24 22 4c 45 56 22 49  |  :1.[.n.:A$"LEV"I
130   22 2c 4c 45 56 22 4a 3a  |  ba 41 24 22 4f 42 4a 22  |  ",LEV"J::A$"OBJ"
140   49 22 2c 4f 42 4a 22 4a  |  3a ba 41 24 22 44 59 4e  |  I",OBJ"J::A$"DYN
150   22 49 22 2c 44 59 4e 22  |  4a 3a b1 00 00 00 4c 00  |  "I",DYN"J:1...L.
160   00 00 00 00 00 00 00 00  |  00 00 00 00 00 00 00 00  |  ................
...
1f0   00 00 00 00 00 00 00 00  |  00 00 00 00 00 00 00 00  |  ................

DONE


You can get the track sector list

Code
[MAME]> printt(gettslist(0x12,0xf))
{{0x12 18, 0xe 14}, 
{0x12 18, 0xd 13}}

or you can do textdumps:

Code
[MAME]> a=getfile("LET")
(11,0f) 00  *B 003 LETTER                         TS List=(12,0f)
matched "LET" with "LETTER                        "
BLOAD ADDR=(01,09)  0901   DATA LENGTH=(26,01) DATA LENGTH=0126
LEN ORIG:	200
LEN AFTER:	126
[MAME]> textdump(a)
00                STELLAR 7.
38   .
39   YOU SHOULDN'T BE READING THIS, BUT IF.

You can load a picture file:
Code
bload("BRIEF",0x2000)
hgr()


and a neat-o function to print tables:
Code
 printt({"why","lisa",{"you're tearing me apart","oh hi","mark"}})
{"why", 
"lisa", 
{"you're tearing me apart", "oh hi", "mark"}}

printt(manager:machine().devices)
{":a2video" = sol.device_t*: 0x5585abc0fa28, 
":a2bus" = sol.device_t*: 0x5585abc09028, 
":sl6:diskiing:0:525" = sol.device_t*: 0x5585abc08de8, 
":sl4:mockingboard:mockbd_via2" = sol.device_t*: 0x5585abc09268, 
":r40bank" = sol.device_t*: 0x5585abc0f7a8, 
...
":r20bank" = sol.device_t*: 0x5585abc0fb68}


You can bload files:

Code
[MAME]> loaddisk("serpentine_bolocheat_pestpatrol.dsk")
[MAME]> bload("PEST")
(11,0f) 00   A 003 HELLO                          TS List=(05,0f)
(11,0f) 01  *T 002 SERPENTINE*                    TS List=(15,0a)
(11,0f) 02  *B 00a SERPENTINE 00-08               TS List=(15,08)
(11,0f) 03  *B 03a SERPENTINE 08-40               TS List=(16,0e)
(11,0f) 04  *B 052 SERPENTINE 40-90               TS List=(19,04)
(11,0f) 05  *B 02a SERPENTINE 90-B8               TS List=(1e,02)
(11,0f) 06  *B 00a SERPENTINE B8-C0               TS List=(21,08)
(11,0e) 00  *B 022 BOLOSCREEN                     TS List=(05,0c)
(11,0e) 01  *B 012 BOLO                           TS List=(03,0a)
(11,0e) 02  *B 060 BOLO.BINARY                    TS List=(02,08)
(11,0e) 03   A 007 BOLO-CHEATER                   TS List=(10,0c)
(11,0e) 04  *B 08c PEST PATROL                    TS List=(07,0f)
matched "PEST" with "PEST PATROL                   "
BLOAD ADDR=(fd,0c)  0cfd   DATA LENGTH=(03,89) DATA LENGTH=8903
LEN ORIG:	8a00
LEN AFTER:	8903


and you can bload a file and execute it like a brun but you have to stop the cpu first with stop() for synchronization reasons:

Code
[MAME]> stop()
[MAME]> bload("PEST",nil,nil,true)
(11,0f) 00   A 003 HELLO                          TS List=(05,0f)
(11,0f) 01  *T 002 SERPENTINE*                    TS List=(15,0a)
(11,0f) 02  *B 00a SERPENTINE 00-08               TS List=(15,08)
(11,0f) 03  *B 03a SERPENTINE 08-40               TS List=(16,0e)
(11,0f) 04  *B 052 SERPENTINE 40-90               TS List=(19,04)
(11,0f) 05  *B 02a SERPENTINE 90-B8               TS List=(1e,02)
(11,0f) 06  *B 00a SERPENTINE B8-C0               TS List=(21,08)
(11,0e) 00  *B 022 BOLOSCREEN                     TS List=(05,0c)
(11,0e) 01  *B 012 BOLO                           TS List=(03,0a)
(11,0e) 02  *B 060 BOLO.BINARY                    TS List=(02,08)
(11,0e) 03   A 007 BOLO-CHEATER                   TS List=(10,0c)
(11,0e) 04  *B 08c PEST PATROL                    TS List=(07,0f)
matched "PEST" with "PEST PATROL                   "
BLOAD ADDR=(fd,0c)  0cfd   DATA LENGTH=(03,89) DATA LENGTH=8903
LEN ORIG:	8a00
LEN AFTER:	8903
pc=cfd
g


It's a little too large to include in a forum post so you can find it at:

https://github.com/goldnchild/goldenchilds_apple2_lua_stuff/blob/master/diskimage_file.lua
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 03/04/19 04:31 PM

Good idea RB to check the m_80col to see if it is in 80 column mode.

Also if you want to see how drawing by rows works, just do a

drawbyrow(true)


Code

-- 80 column text overlay for Apple IIe

function calc(line,page) page=page or 0 return line % 8 * 1024 + math.floor(line / 64) * 40 + math.floor((line%64) / 8) * 128 + 8192* (page + 1) end

function iskeypressed(keycode) 
inp = manager:machine():input() return inp:code_pressed(inp:code_from_token(keycode))
end

function striphi(a) if type(a)=="number" then a=string.char(a) end local b="" for i=1,#a do b=b..string.char(string.byte(a,i)&0x7f) end return b end

mem=manager:machine().devices[":maincpu"].spaces["program"]  -- gets main or aux, depending on softswitches
aux=emu.item(manager:machine().devices[":aux:ext80"].items["0/m_ram"])   -- gets aux memory
scr=manager:machine().screens[":screen"]
main=emu.item(manager:machine().devices[":ram"].items["0/m_pointer"])  -- always gets main memory

function widthpct(c) 
  if c==nil or c==string.char(0) then return 0 end 
  return ((manager:ui():get_string_width(c,1.0)/manager:ui():get_string_width("A",1.0))) 
end
function widthoffset(c) if c==nil or c==string.char(0) then return 0 end return 3.5*(1-widthpct(c)) end
-- assume chars have width of 7 pixels, center offset=7*((1-widthpercentage)/2)=3.5*(1-widthpercentage)

precalcwidthoffsettable={}

function precalccharwidthoffset()
  for i=0,255 do precalcwidthoffsettable[i]=widthoffset(string.char(i)) end
end

precalccharwidthoffset()

function widthoffsetpre(c)  if c==nil or c==string.char(0) then return 0 else return precalcwidthoffsettable[string.byte(c)] end end

function between(a,b,c) return (a >= b) and (a <= c) end
-- 80 column text overlay for Apple IIe

function calc(line,page) page=page or 0 return line % 8 * 1024 + math.floor(line / 64) * 40 + math.floor((line%64) / 8) * 128 + 8192* (page + 1) end

function iskeypressed(keycode) 
inp = manager:machine():input() return inp:code_pressed(inp:code_from_token(keycode))
end

function striphi(a) if type(a)=="number" then a=string.char(a) end local b="" for i=1,#a do b=b..string.char(string.byte(a,i)&0x7f) end return b end

mem=manager:machine().devices[":maincpu"].spaces["program"]  -- gets main or aux, depending on softswitches
aux=emu.item(manager:machine().devices[":aux:ext80"].items["0/m_ram"])   -- gets aux memory
scr=manager:machine().screens[":screen"]
main=emu.item(manager:machine().devices[":ram"].items["0/m_pointer"])  -- always gets main memory

function widthpct(c) 
  if c==nil or c==string.char(0) then return 0 end 
  return ((manager:ui():get_string_width(c,1.0)/manager:ui():get_string_width("A",1.0))) 
end
function widthoffset(c) if c==nil or c==string.char(0) then return 0 end return 3.5*(1-widthpct(c)) end
-- assume chars have width of 7 pixels, center offset=7*((1-widthpercentage)/2)=3.5*(1-widthpercentage)

precalcwidthoffsettable={}

function precalccharwidthoffset()
  for i=0,255 do precalcwidthoffsettable[i]=widthoffset(string.char(i)) end
end

precalccharwidthoffset()

function widthoffsetpre(c)  if c==nil or c==string.char(0) then return 0 else return precalcwidthoffsettable[string.byte(c)] end end

function between(a,b,c) return (a >= b) and (a <= c) end

function applecharfixinverse(c)
  if type(c)=="string" then c=string.byte(c) end
  if between(c,0,31) then return string.char(c+64),true
  elseif between (c,32,127) then return string.char(c), true
  elseif between (c,128,159) then return string.char(c-128+64), false
  elseif between (c,160,255) then return string.char(c-128), false
  else return 0, false
  end
end

drawoverlay=true
keydelay=0

function print_80col()
for y=0,23 do for x=0,39 do offset=calc(y*8)-8192+x 
c1=striphi(aux:read(1024+offset)) c0=striphi(mem:read_u8(1024+offset)) 
io.write(c1..c0) end print() end
end

function interleavec1c0(c1row,c0row)
local outrow=""
for i=1,#c1row do
  outrow=outrow..applecharfixinverse(c1row:sub(i,i))..applecharfixinverse(c0row:sub(i,i))
end
return outrow
end

function draw_80colrow()
  if keydelay > 0 then keydelay = keydelay - 1 end
  local m_80col=emu.item(manager:machine().devices[":a2video"].items["0/m_80col"]):read(0)==1
  if drawoverlay then 
    scr:draw_box(0,0,559,279,0xff000000,0xffffffff)
    for y=0,23 do 
      offset=calc(y*8)-8192 
      c1row=aux:read_block(1024+offset,40)
      c0row=main:read_block(1024+offset,40)
      if m_80col then
        c0row=interleavec1c0(c1row,c0row)
      else
        c0row=interleavec1c0(string.rep(" ",40),c0row)
      end
      fgcolor,bgcolor=0xffffffff,0xff000000
      scr:draw_text(0,y*8,c0row,fgcolor,bgcolor) 
    end
  end
  if iskeypressed("KEYCODE_LSHIFT") and keydelay==0 then drawoverlay=not drawoverlay keydelay=20 end
end

m_80col_itemnum=-1

function draw_80col()
  if keydelay > 0 then keydelay = keydelay - 1 end
  -- might be a smidge faster if we didn't have to look up the itemnum for m_80col each time
  if m_80col_itemnum < 0 then m_80col_itemnum = manager:machine().devices[":a2video"].items["0/m_80col"] end
  local m_80col=emu.item(m_80col_itemnum):read(0)==1
  if drawoverlay then 
    scr:draw_box(0,0,559,279,0xff000000,0xffffffff)
    for y=0,23 do 
      offset=calc(y*8)-8192 
      c1row=aux:read_block(1024+offset,40)
      c0row=main:read_block(1024+offset,40)
      for x=0,39 do 
        c1=c1row:byte(x+1)
        c1,c1invert=applecharfixinverse(c1)
        c0=c0row:byte(x+1)
        c0,c0invert=applecharfixinverse(c0)
        fgcolor,bgcolor=0xffffffff,0xff000000
        if c1invert then fgcolor,bgcolor=bgcolor,fgcolor end
        --only draw the 80 columns if 80col is active
        if m_80col then
          scr:draw_text((x*2+0)*7+widthoffsetpre(c1),y*8,c1,fgcolor,bgcolor) 
        end
        fgcolor,bgcolor=0xffffffff,0xff000000
        if c0invert then fgcolor,bgcolor=bgcolor,fgcolor end
        scr:draw_text((x*2+1)*7+widthoffsetpre(c0),y*8,c0,fgcolor,bgcolor) 
      end 
    end
  end
  if iskeypressed("KEYCODE_LSHIFT") and keydelay==0 then drawoverlay=not drawoverlay keydelay=20 end
end

draw80dispatchlist={draw_80col}

function draw80dispatch() for i,j in pairs(draw80dispatchlist) do j() end end

function drawon() draw80dispatchlist={draw_80col} end
function drawoff() draw80dispatchlist={} end

-- Draw by rows by calling drawbyrow(true) or shut off with drawbyrow(false)
-- You end up losing the inverse chars and your ui font should be a monospace font
--  or it won't look right.  Also the fonts end up getting cropped at the right edge of the screen.
-- It's much faster since it can write out a whole 80 character row in one draw_text call
--  instead of 80 separate draw_text calls for each individual character.

function drawbyrow(a)
  if a==nil then a=true end
  if a==true then draw80dispatchlist={draw_80colrow} 
             else draw80dispatchlist={draw_80col}
  end
end

if not alreadyregistereddraw80 then
  emu.register_frame_done(draw80dispatch)
  alreadyregistereddraw80=true
end


Posted By: rfka01

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 03/05/19 08:30 AM

The "remote control" for the disk images is a great idea ... I might have to learn how to use the LUA console one day after all smile
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 03/14/19 05:08 PM

More silly fun: I always loved the different fonts and wanted to use the Beagle Bros fonts from Apple Mechanic which are shape tables. So I wrote a shape table interpreter. It's not fully complete in that it doesn't do scale and rot, but it can write the text to the screen.

Code

function iif(a,b,c) if a then return b else return c end end 
function bool10(a) return iif(a,1,0) end

function bin(x,numbits,gap) if x==nil then return nil end gap=gap or "_" numbits=numbits or 8 str="" for i=numbits-1,0,-1 do str=str..iif((x&(2^i))~=0,"1","0")..iif((i%8==0) and (i>0),gap,"") end return str end

function hex(a,digits,prefix) digits=digits or 2 prefix=prefix or "" if a==nil then return nil end return string.format(prefix.."%0"..digits.."x",a) end
function hexx(a,digits,prefix) prefix=prefix or "0x" return hex(a,digits,"0x") end
function hexpair(a,b) return "("..hex(a)..","..hex(b)..")" end

function max(a,b) if a>b then return a else return b end end 
function min(a,b) if a<b then return a else return b end end
function round(x) if x<0 then return math.floor(x-0.5) else return math.floor (x+0.5) end end

function calc(line,page) if line<0 then line = 0 end if line > 191 then line=191 end page=page or 0 return line % 8 * 1024 + math.floor(line / 64) * 40 + math.floor((line%64) / 8) * 128 + 8192* (page + 1) end

function calcyaddr(line,page) return calc(line,page) end

function plot(x,y,page) page=page or 0 x = max(0,x) x = min(x,279) y = max(0,y) y = min(y,191) mem=applemem() mem:write_u8(calcyaddr(y,page)+math.floor(x/7),mem:read_u8(calcyaddr(y,page)+math.floor(x/7))|(1<<(x%7))) end

function applemem() return manager:machine().devices[":maincpu"].spaces["program"] end

function getbits(a,lobit,hibit) local retval=0 for bit=lobit,hibit do retval=retval|((1<<bit)&a) end return retval end

function getbitsshift(a,lobit,hibit) return getbits(a,lobit,hibit)>>lobit end

stuck=nil
stuckmax=5000

function stuckcheck(stucklimit)
if stuck==nil then stuck =0 end
stuck=stuck+1
stucklimit=stucklimit or stuckmax
if stuck > stucklimit then print("STUCK hit loop "..stucklimit.."times") stuck=nil gonnamakeanerror() end
end

function getdrawcmd(a,cmdindex) return getbitsshift(a,cmdindex*3,cmdindex*3+2) end

function drawshapetable(a,shapenum,xpos,ypos)
local bytepos=2*shapenum+1
if printdebugshapetable then print("drawshapetable shapenum="..shapenum) end
if a:byte(1) < shapenum then 
   if  printdebugshapetable then print ("only have "..a:byte(1).." shapes!  shapenum="..shapenum) end 
   return xpos,ypos end
if printdebugshapetable then print(string.rep("-",80)) end
bytepos=a:byte(bytepos)+a:byte(bytepos+1)*256+1
stuck=nil
while true do
stuckcheck()  -- stop those pesky infinite loops while debugging things, an infinite loop will hang mame
local b=a:byte(bytepos)
local drawcmd={}
for i=0,2 do
  if b==0 or b==nil then return xpos,ypos end
  drawcmd[i+1]=getdrawcmd(b,i)
end
for i=0,2 do
  local dirbits=getbitsshift(drawcmd[i+1],0,1)
  local plotbit=getbitsshift(drawcmd[i+1],2,2)
  dirtable={{x=0,y=-1,dir="up"},{x=1,y=0,dir="right"},{x=0,y=1,dir="down"},{x=-1,y=0,dir="left"}}
  x,y,dir=dirtable[dirbits+1].x,dirtable[dirbits+1].y,dirtable[dirbits+1].dir
  local skip=false
  if i==1 and drawcmd[2]==0 and drawcmd[3]==0 then skip=true end -- if second and third are zero, ignore
  if i==2 and dirbits==0 then skip=true end -- 00 in last command (can't go up in final command)
  if printdebugshapetable then  print("bytepos="..hex(bytepos),"byte="..hex(b),"binary="..bin(b),i+1,bin(drawcmd[i+1],3),"PLOT="..plotbit,"DIR="..dirbits.."  "..dir.." "..iif(skip,"<SKIP>","")..iif(plotbit==1," plot","")) end
  if skip then break end
  newxpos,newypos=xpos+x,ypos+y
  if plotbit == 1 then plot(xpos,ypos) end --plot before moving
  xpos,ypos=newxpos,newypos
end
if printdebugshapetable then print(string.rep("=",80)) end
bytepos=bytepos+1
end -- while
end -- drawshapetable

-- we can just draw the character and ignore the return ypos if we don't want to draw shape #99 between characters

function drawshapetext(a,thisstr,x,y,spacing,xclip,height) for i=1,#thisstr do if thisstr:byte(i)==string.byte("\n") then if x~=0 then x,y=0,y+height end else x=drawshapetable(a,thisstr:byte(i)-32+1,x,y) x=x+spacing if x>xclip then x,y=0,y+height end end end return x,y end

-- Beagle Bros shape table fonts, draw shape #99 between characters to return to baseline and add space

function drawshapetext99(a,thisstr,x,y,spacing,xclip,height) for i=1,#thisstr do if thisstr:byte(i)==string.byte("\n") then if x ~= 0 then x,y=0,y+height end else x,y=drawshapetable(a,thisstr:byte(i)-32+1,x,y) x,y=drawshapetable(a,99,x,y) if x>xclip then x,y=0,y+height end end end return x,y end



printdebugshapetable = true


It's kinda neat to see how the shapes were put together:
Code
drawshapetable shapenum=99
--------------------------------------------------------------------------------
bytepos=10a5	byte=40	binary=01000000	1	000	PLOT=0	DIR=0  up 
bytepos=10a5	byte=40	binary=01000000	2	000	PLOT=0	DIR=0  up 
bytepos=10a5	byte=40	binary=01000000	3	001	PLOT=0	DIR=1  right 
================================================================================
...
bytepos=10ac	byte=08	binary=00001000	1	000	PLOT=0	DIR=0  up 
bytepos=10ac	byte=08	binary=00001000	2	001	PLOT=0	DIR=1  right 
bytepos=10ac	byte=08	binary=00001000	3	000	PLOT=0	DIR=0  up <SKIP>
================================================================================


[Linked Image]

Code
loaddisk("../../apple_mechanic_typefaces.dsk") hgr() hgrfull() hgrclr() a=getfile("]COMPUTE") drawshapetext99(a,"I'm gonna download and compile mame! ...and compile mame!\nI'm going to live like modern hardware doesn't exist! ...like it doesn't exist!\nI'm gonna fly like a 6502 in the night!\nFeel the artifacts on my eyes",0,0,0,260,18)


[Linked Image]
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 03/15/19 07:58 PM

I was always jealous of other computers where you could redefine the fonts, so why not see if I can create a custom font rom for the apple 2.

There's an article on reactivemicro where they mention some "custom" character sets like Pigfont and ReActiveText: https://wiki.reactivemicro.com/Apple_IIe_Enhancement_Kit

So let's see what's in the Apple 2 character roms, we can just load them into the hi-res screen.

The apple 2 char rom is "reversed".

No lowercase characters here!


[Linked Image]

So let's reverse it and shift it a little bit, that looks better.

[Linked Image]

and look at the 2e rom:

[Linked Image]

and the 2c rom: (hey look, it's the running man!)

[Linked Image]

It's kind of cool to see the bit patterns that make up the lo-res colors. I think I'm finally understanding how the 560 pixel double hi-res works, it's just the same bit patterns that make up the lo-res colors.

and what if we look at some non-native character sets loaded into Apple hi-res:

(I put the apple2 configuration into black and white mode)

Colecovision:

[Linked Image]

Atari 800:
[Linked Image]

C64:
[Linked Image]

The coleco adam, pet2001 and the cpc300 char roms look pretty good too.

Code
stuck=nil
stuckmax=5000
function stuckcheck(stucklimit)
if stuck==nil then stuck =0 end
stuck=stuck+1
stucklimit=stucklimit or stuckmax
if stuck > stucklimit then print("STUCK hit loop "..stucklimit.."times") stuck=nil error("I may be STUCK in an infinite loop.  I've fallen and I can't get up") end
end

function loadfile(filename) if filename==nil then print("NO FILENAME") return nil end local f=assert(io.open(filename,"r")) local a=f:read("*a") f:close() if a==nil then print("NO DATA") else print("Loadfile (\""..filename.."\") = "..#a.." bytes read.") end return a end

function revbits(a) local r=0 for i=0,7 do r=(r<<1)+a%2 a=a>>1 end return r end

function drawblockloop(looplist,dofunc,xwrap)
--reset stuck counter
stuck=nil
looplist=looplist or {"y",8,"x",1}
xwrap = xwrap or 40  -- wrap the x at 40 bytes across, since apple screen is 40 bytes across
-- from left to right, outer --> inner
-- need to track value of each loop index and what type is it, an "x" loop or a "y" loop
-- iterate from inner out, so iterate in reverse order for i=looplevelcount,1,-1 
-- xsize (of all inners multiplied) * currentlevel value
-- and same goes for ycoordinate
-- so initialize all levels of our loop
-- and start from innermost level
-- add 1, if greater than loop size, then revert to zero and propagate the add to the next outer level
-- go up a level, add 1, if greater than bump up to next, rinse, repeat
-- if all levels done then exit
loopstate={}
looplevelcount=0
for i = 1,#looplist,2 do
  looplevelcount=looplevelcount+1
  loopstate[looplevelcount]={}
  loopstate[looplevelcount].axis=looplist[i]
  loopstate[looplevelcount].size=looplist[i+1]
  loopstate[looplevelcount].value=0
end
print(looplevelcount)
printt(loopstate)
print("Size of block should be ")
blocksize=1
for i=looplevelcount,1,-1 do
   blocksize=blocksize*loopstate[i].size 
   io.write(loopstate[i].size.." * ")
end
print("1 = "..blocksize)
index=0
while true do
stuckcheck()
-- now compute the x value
local coord=0
blocksize=1
for i=looplevelcount,1,-1 do
  if loopstate[i].axis=="x" then coord=coord+blocksize*loopstate[i].value
                                 blocksize=blocksize*loopstate[i].size 
end
end
xcoord=coord
coord=0
blocksize=1
for i=looplevelcount,1,-1 do
  if loopstate[i].axis=="y" then coord=coord+blocksize*loopstate[i].value blocksize=blocksize*loopstate[i].size 
end
end
ycoord=coord
xfinal=xcoord%xwrap
yfinal=ycoord+blocksize*math.floor(xcoord/xwrap)
dofunc(xfinal,yfinal,index)
index=index+1
-- now add 1 to inner levels
for i=looplevelcount,1,-1 do
  loopstate[i].value = loopstate[i].value + 1
  if loopstate[i].value <= loopstate[i].size-1 then break end
  loopstate[i].value = 0  -- set to value and propagate up to next level
  if i==1 then return end-- we need to stop everything since we are done
end
end
end --drawblockloop

function applemem() return manager:machine().devices[":maincpu"].spaces["program"] end

function revstring(a) local b="" for i=1,#a do b=b..string.char(revbits(a:byte(i))) end return b end
function shiftstringleft(a,numbits) local b="" for i=1,#a do b=b..string.char((a:byte(i)<<numbits)&0xff) end return b end
function andstring(a,andvalue) local b="" for i=1,#a do b=b..string.char(a:byte(i)&andvalue) end return b end
function invertstring(a) local b="" for i=1,#a do b=b..string.char(255-a:byte(i)) end return b end


Code

-- to draw the coleco font, uses a loadstring(executestr)() to execute some text code

hgr() hgrfull() hgrclr() 
filename="../../CHARSETS/coleco/r72114a_8317.u2" 
a=loadfile(filename) 
executestr="a=revstring(a) a=shiftstringleft(a,0) a=andstring(a,0x7f)" 
loadstring(executestr)()
stuckmax=16384 
startfrom=4096+4+152*8
drawblockloop({"y",16,"x",32,"y",8},function(x,y,index) applemem():write_u8(calc(y)+x,(a:sub(startfrom)):byte(index+1)) end,32) 
drawshapetext(font,filename,0,140,1,270,8) drawshapetext(font,executestr.." a:sub("..startfrom..")",0,150,1,270,10)



And one interesting discovery, though completely trivial: In studying the colecovision font, there's an error in the lowercase x, it doesn't look right.


[Linked Image]

and going to the tms9918 manual pdf, there's a picture and hex, but clearly the hex doesn't match the picture.

It should be 00 88 50 20 50 88 00.

[Linked Image]

[Linked Image]
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 03/24/19 12:30 PM

I found another program that will render shape table fonts which is Executive Briefing System. It's actually pretty clever in that it "hides" the character width information in the shape table itself. The first two bytes I think are the height and the baseline, then it's a normal shape table, so we can just go a:sub(3) to skip past the first two characters of the a string.

The shape table has a byte to tell you the number of shapes, and the unused next byte is used to point to the offset of the width information.

[Linked Image][Linked Image]

According to the applesoft disassembly at http://www.txbobsc.com/scsc/scdocumentor/F5BA.html, F605- AA 1650 DRAW1 is the entry point, so putting a breakpoint at F605 told me that it was surely an applesoft shape table.



And now we can generate font samples automatically. Just get a filelist, iterate through the filelist, draw a sample, then wait 2/60 of a second and ask the debugger to take a snapshot.

Since we've got to use emu.wait this must be done with coroutines.

Code

function getebswidth(a,shapenum) return a:sub(1):byte(a:sub(1):byte(2)+shapenum+1) end

function drawshapetextebs(a,thisstr,x,y,spacing,xclip,height) for i=1,#thisstr do if thisstr:byte(i)==string.byte("\n") then if x~=0 then x,y=0,y+height end else
local c=thisstr:byte(i)  if c>=32 and c<=95 then c=c elseif c<32 then c=32 elseif c>=97 and c<=127 then c=c-97+1 else c=32 end 
 drawshapetable(a,c,x,y) x=x+getebswidth(a,c) if x>xclip then x,y=0,y+height end end end return x,y end

function getfilenamepart(s)
local curpos=1
repeat
local newpos=s:find("/",curpos,true)
if newpos then curpos = newpos+1 end  -- if you don't add the +1, keeps getting same match over and over for an infinite loop
until newpos == nil
return s:sub(curpos)
end

function trim2(s) return s:match "^%s*(.-)%s*$" end  -- from lua users wiki

disknamelist={""../../EXEC_BRIEF_SYS_hr.dsk","../../EXEC_BRIEF_SYS_FONTS_hr.dsk")

loaddisk("../../EXEC_BRIEF_SYS_hr.dsk") monospacefont=getfile("MONOSPACE.FONT")

co1=coroutine.create( function()
disknamelist={"../../EXEC_BRIEF_SYS_hr.dsk","../../EXEC_BRIEF_SYS_FONTS_hr.dsk"}
for d=1,#disknamelist do diskname=disknamelist[d] loaddisk(diskname)
filelist=cat()
for i=1,#filelist do print(filelist[i]) 
  if filelist[i]:find(".FONT",1,true) then 
  print("IT'S A FONT so let's render a sample!") 
  a=getfile(filelist[i])
  hgr() hgrfull() hgrclr() xpos=0 ypos=10 for i=1,95 do drawshapetable(a:sub(3),i,xpos,ypos) xpos=xpos+a:sub(3):byte(a:sub(3):byte(2)+i+1) print("width="..a:sub(3):byte(0xc2+i-1))  if xpos>250 or (((i+1) % 16) == 0) then xpos=0 ypos=ypos+20 end end
  drawshapetextebs(monospacefont:sub(3),getfilenamepart(diskname).."\n"..filelist[i],0,170,1,250,10)
  emu.wait(1/60+.01) 
  manager:machine():debugger():command("snap \"" .. sanefilename(getfilenamepart(diskname).."_"..trim2(filelist[i]))..".png\"")
end end end end) 
ok,error=coroutine.resume(co1)
print(ok,error)




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


coming soon: drawing Print Shop and Fontrix fonts
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 03/24/19 07:26 PM

Here's some routines to draw the print shop fonts (on the original disk)

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

Code

-- printshop_drawfont7.lua

function applemem() 
  if applememobject == nil then applememobject = manager:machine().devices[":maincpu"].spaces["program"] end
  return applememobject
end

function calc(line,page) if line<0 then line = 0 end if line > 191 then line=191 end page=page or 0 return line % 8 * 1024 + math.floor(line / 64) * 40 + math.floor((line%64) / 8) * 128 + 8192* (page + 1) end

function calcyaddr(line,page) return calc(line,page) end
function readswitch(a)
local cpu = manager:machine().devices[":maincpu"]  local mem = cpu.spaces["program"]
mem:read_u8(a)
end

function hgrfull(page)
page = page or 1
readswitch(0xC050) -- graphics
readswitch(0xC052) -- full screen
readswitch(0xC054+page-1) -- page 1
readswitch(0xC057) -- hi res
end

function hgr(page)
page = page or 1
readswitch(0xC050) -- graphics
readswitch(0xC053) -- full mixed
readswitch(0xC054+page-1) -- page 1
readswitch(0xC057) -- hi res
end

function textmode()
readswitch(0xC051) -- text
readswitch(0xC054) -- page 1
end

function text()
readswitch(0xC051) -- text
readswitch(0xC054) -- page 1
end

function hgrclr(page) 
local cpu = manager:machine().devices[":maincpu"]  local mem = cpu.spaces["program"]
for y=0,191 do for x=0,39 do mem:write_u8(calc(y)+x,0) end end end

function hgrwhite(page) for x=0,39 do for y=0,191 do applemem():write_u8(calcyaddr(y,page)+x,127) end end end

function getbits(a,lobit,hibit) local retval=0 for bit=lobit,hibit do retval=retval|((1<<bit)&a) end return retval end

function getbitsshift(a,lobit,hibit) return getbits(a,lobit,hibit)>>lobit end


function getfilenamepart(s)
local curpos=1
repeat
local newpos=s:find("/",curpos,true)
if newpos then curpos = newpos+1 end  -- if you don't add the +1, keeps getting same match, infinite loop
until newpos == nil
return s:sub(curpos)
end

function trim2(s) return s:match "^%s*(.-)%s*$" end  -- from lua users wiki

-- plot function, haven't got all the operations working yet but or,xor,store,and inverse seem to be ok

function plot(x,y,page,bit,operation) page=page or 0 x = math.max(0,x) x = math.min(x,279) y = math.max(0,y) y = math.min(y,191) mem=applemem() 
local memloc=calcyaddr(y,page)+math.floor(x/7)
local readval=mem:read_u8(memloc) local bitpos=x%7
local mask=~(1<<bitpos)
local invertmask=(1<<bitpos)
local bitshifted = bit<<bitpos 
local notbitshifted=(iif(bit==0,1,0) << bitpos)
if operation == nil or operation == "or" then mem:write_u8(memloc,readval | (bit<<bitpos)) 
elseif operation == "erase"     then mem:write_u8(memloc,readval & (bit<<bitpos)) 
elseif operation == "color"     then mem:write_u8(memloc,readval & (bit<<bitpos))  -- erase = color black
elseif operation == "xor"     then mem:write_u8(memloc,readval ~ (bit<<bitpos)) 
elseif operation == "store"   then mem:write_u8(memloc,(readval & mask) | bitshifted)
elseif operation == "inverse" then mem:write_u8(memloc,(readval & mask) | notbitshifted)
else error("PLOT OPERATION "..operation.." not recognized") end
end



function revbits(a) if a==nil then print("REV NIL") return nil end local r=0 for i=0,7 do r=(r<<1)+a%2 a=a>>1 end return r end

-- 0x3b = 59 so we can have 59 characters per font
-- 
-- byte offset  0x3b * 0 + c = width of character
-- byte offset  0x3b * 1 + c = height of character
-- byte offset  0x3b * 2 + c = offset of character data low byte
-- byte offset  0x3b * 3 + c = offset of character data high byte as well as some flags so AND it with 0x1f

-- fonts on the Print Shop disk are named F0 through F9, in a "hidden" directory (start at t,s=17,2)
-- fonts on Print Shop Companion have additional 12 bytes at the beginning, we're just interested
--   in drawing the bitmap so we can just "ignore" these 12 bytes by using a:sub(13) which means take
--    all the bytes to the end of the string starting at character position 13 (numbered from 1).

function getcharwidth(a,c)  return a:byte((0x3b*0)+c+1) end
function getcharheight(a,c) return a:byte((0x3b*1)+c+1) end
function getcharoffset(a,c) return a:byte((0x3b*2)+c+1)+(a:byte((0x3b*3)+c+1)&0x1f)*256 end

--if we draw as bytes then we lose the high bit of the byte and we are on byte boundaries so it looks strange
-- drawing as pixels the fonts look much better

function drawpsfont(a,c0,c1,offset,doprint,xpos,ypos,lineheight,bytesorpixels,drawmode)
-- draw font characters from c0 to c1
c0 = c0 or 0
c1 = c1 or 58
offset=offset or 0
xpos,ypos=xpos or 0,ypos or 0
for c=c0,c1 do 
if getcharwidth(a,c) < 128 then 
local charwidth=getcharwidth(a,c)
local charheight=getcharheight(a,c)
local charoffset=getcharoffset(a,c)
local charbytewidth=math.floor((charwidth-1)/8)+1
drawmode = drawmode or "or"
if doprint then print("char="..c,"width="..getcharwidth(a,c),"height="..getcharheight(a,c),"offset="..hex(getcharoffset(a,c)))  end
if charoffset>#a then print("INVALID CHAR OFFSET") 
else
if charheight~=0 then 
if c~=32 then
--drawblock loop by bytes
if bytesorpixels=="bytes" then
  drawblockloop({"y",charheight,"x",charbytewidth},function(x,y,index) applemem():write_u8(calc(y+ypos)+x+xpos,revbits(a:sub(getcharoffset(a,c)+1):byte(index+offset+1))) end,32)
--drawblock loop by pixels
else
  drawblockloop({"y",charheight,"x",charbytewidth},function(x,y,index) local bytetoplot=revbits((a:sub(charoffset+1):byte(index+offset+1))) local numpixels=math.min(8,charwidth-8*x) x=xpos+x*8 for i=0,numpixels-1 do plot(x+i,y+ypos,0,getbitsshift(bytetoplot,i,i),drawmode) end end,32)
end
else  -- draw the space
      -- leave space blank for now
end
-- draw the gap between characters
  if bytesorpixels~="bytes" then for y=0,charheight-1 do plot(xpos+charwidth,y+ypos,0,0,drawmode) end end
end
if bytesorpixels=="bytes" then xpos = xpos+charbytewidth  -- by bytes
                          else xpos = xpos+charwidth+1    -- by pixels
end
end
if bytesorpixels=="bytes" then if xpos>36  then xpos=0 ypos=ypos+lineheight end -- by bytes
                          else if xpos>240 then xpos=0 ypos=ypos+lineheight end -- by pixels
end
end
end
print("returning xpos="..xpos.." ypos="..ypos)
return xpos,ypos
end

function writepsfonttext(a,s,x,y,offset,charoffset,lineheight,drawmode) charoffset=charoffset or (65-33) for i=1,#s do x,y=drawpsfont(a,s:byte(i)-charoffset,s:byte(i)-charoffset,offset,false,x,y,lineheight,nil,drawmode) print(x) if x>255 then x=0 y=y+16 end end end

-- translate function for combo lower case/uppercase fonts

function translateps(c) -- c passed as a char number
local replacedchars=""
local translate0=             "!\"#$%&'()*+,-./0123456789:;<=>?"
local translate1=string.upper("!wmnop`rsqt,k.zjabcdefghivuxly?")
for i=1,#translate0 do
  if translate0:sub(i,i)~= translate1:sub(i,i) then replacedchars=replacedchars..translate0:sub(i,i)
end
end
print("REPLACED="..replacedchars)
if c>=string.byte("A") and c<=string.byte("Z") then  
  local cpos=string.find(translate1,string.char(c),1,true)
  if cpos==nil then c=string.byte(c) end
  c=string.byte(translate0:sub(cpos,cpos))
elseif c>=string.byte("a") and c<=string.byte("z") then c=c-32
elseif string.find(replacedchars,string.char(c),1,true)  then c=string.byte("!")
elseif c>128 or c<32 then c=string.byte(".")
elseif c>90 or c<32 then c=string.byte(".")
end
return c
end

--for i=string.byte("a"),string.byte("z") do c=string.char(i) print(c,translateps(c)) end

--[[

loaddisk("../../PrintShop.dsk")
catalog()
getcatalog(17,2,nil,true)

-- snippet to render font f1

hgrclr() filename="F1" filelist,t,s=getcatalog(17,2,filename,nil) a=getfilefromtslist(gettslist(t,s)) print(#a.." bytes") a=stripfileheaderandextra(a) hgrclr() drawpsfont(a,32,58,0,false,0,0,38,"pixels","xor") writepsfonttext(a,filename.." 32-58",0,160)

--]]


--[[
-- snippet will loop through the namelist and render each one, but not taking any snaps

namelist={"SYSTEM","RSVP","ALEXIA","NEWS","TECH","PARTY","BLOCK","TYPEWRITER","STENCIL"}
filelist={"F0","F1","F2","F3","F4","F5","F6","F7","F8"}loaddisk("../../Print_Shop_The_1984_Broderbund_a.dsk")hgr() hgrfull() hgrclr() for i=1,#filelist do filename=filelist[i] aafilelist,t,s=getcatalog(17,2,filename,nil) a=getfilefromtslist(gettslist(t,s)) print(#a.." bytes") a=stripfileheaderandextra(a) hgrclr() drawpsfont(a,1,58,0,false,0,0,38,"pixels","xor") writepsfonttext(a,filename.." "..namelist[i],0,160) 
end


-- this snippet will create snaps of all the fonts on the print shop disk


co1=coroutine.create( function()
namelist={"SYSTEM","RSVP","ALEXIA","NEWS","TECH","PARTY","BLOCK","TYPEWRITER","STENCIL"}
filelist={"F0","F1","F2","F3","F4","F5","F6","F7","F8"}
diskname="../../Print_Shop_The_1984_Broderbund_a.dsk"  -- has good f5 block font, bad  f1 rsvp
diskname="../../PrintShop.dsk"                         -- has bad  f5 block font, good f1 rsvp
loaddisk(diskname)hgr() hgrfull() hgrclr() for i=1,#filelist do filename=filelist[i] aafilelist,t,s=getcatalog(17,2,filename,nil) a=getfilefromtslist(gettslist(t,s)) print(#a.." bytes") a=stripfileheaderandextra(a) hgrclr() drawpsfont(a,iif(filename=="F1",32,1),58,0,false,0,0,iif(filename=="F1",38,32),"pixels","xor") writepsfonttext(a,filename.." "..namelist[i],0,160) 
emu.wait(2/60)
manager:machine():debugger():command("snap \"" .. sanefilename(getfilenamepart(diskname).."_"..trim2(filelist[i]).."_"..namelist[i])..".png\"")
end
end)
ok,error=coroutine.resume(co1)
print(ok,error)

--]]


A couple of things to note about the print shop disk, the catalog is truncated, so if you start at track 17, sector 2 you can see the rest of the files. Also font F1 or F5 is corrupted depending on the disk you use.

Now the PS Companion fonts seem to have 12 extra bytes at the beginning, so if you pass them as a:sub(13) instead of a those 12 bytes will be ignored.



Code
-- just a quick test on the PS Companion disk.
loaddisk("../../PrintShop.Companion.dsk") catalog()
filename="FONT.BALLOON" hgr() hgrclr() hgrwhite() a=getfile(filename) drawpsfont(a:sub(13),iif(filename=="BALLOON",32,1),58,0,false,0,0,32,"pixels","xor") writepsfonttext(a:sub(13),filename,0,140,0,nil,20,"xor")


[Linked Image]
Posted By: Lord Nightmare

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 03/24/19 07:52 PM

Golden Child: speaking of AppleII font stuff, is the "candy apple" Hershey font editor/renderer apple2 disk preserved anywhere?
The Applesoft basic listing and some of the binary and text contents are listed at https://www.govinfo.gov/content/pkg...C13-f5df264c560c0810c872edea211033cc.pdf which might be enough to re-create the disk from scratch, but I don't know of any surviving copies. Both authors of that paper have sadly passed away, so its unlikely I can get any information from that angle.

EDIT: some of the fonts on the Fontrix user group disks are traced by hand from some glyphs of the herhsey fonts with some manual adjustment, but none seem to be a direct 1:1 copy.

LN
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 03/25/19 11:42 AM

Hi LN, looking around at the "regular" places, I don't see any Hershey fonts. They're kind of interesting vector fonts, the only mention I could find was a company named Tangent 270 which sold a Hershey font product (google for "tangent 270 hershey fonts apple").

Code
SOFTWARE/ GRAPHICS TANGENT 270 P.O. Box 38587. DspL 9281 Denver, CO ... High quality characters based on Hershey's character repertory. 14 fonts including Roman Bold, English Gothic, Greek. 7 special ... 48K Apple II+. DOS 3.3.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 03/25/19 11:56 AM

Now to draw some Fontrix fonts:

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

I was able to get some files from Printrix to draw also, which has Times 25,30,40,50,70 and Helvetica 25,30,40,50,70.

Since the printrix disk was Prodos, I created a dos3.3 image in the file manager (I called it created_image.dsk and you can see the SET.HELVET25) and used COPY II+ to copy the files over so I could access them. (I haven't written routines to access Prodos disks yet -- coming soon after I can decipher Beyond Apple Prodos).



Code
function calc(line,page) if line<0 then line = 0 end if line > 191 then line=191 end page=page or 0 return line % 8 * 1024 + math.floor(line / 64) * 40 + math.floor((line%64) / 8) * 128 + 8192* (page + 1) end

function calcyaddr(line,page) return calc(line,page) end

function plot(x,y,page,bit,operation) page=page or 0 x = math.max(0,x) x = math.min(x,279) y = math.max(0,y) y = math.min(y,191) mem=applemem() 
local memloc=calcyaddr(y,page)+math.floor(x/7)
local readval=mem:read_u8(memloc) local bitpos=x%7
local mask=~(1<<bitpos)
local invertmask=(1<<bitpos)
local bitshifted = bit<<bitpos 
local notbitshifted=(iif(bit==0,1,0) << bitpos)
if operation == nil or operation == "or" then mem:write_u8(memloc,readval | (bit<<bitpos)) 
elseif operation == "erase"     then mem:write_u8(memloc,readval & (bit<<bitpos)) 
elseif operation == "color"     then mem:write_u8(memloc,readval & (bit<<bitpos))  -- erase = color black
elseif operation == "xor"     then mem:write_u8(memloc,readval ~ (bit<<bitpos)) 
elseif operation == "store"   then mem:write_u8(memloc,(readval & mask) | bitshifted)
elseif operation == "inverse" then mem:write_u8(memloc,(readval & mask) | notbitshifted)
else error("PLOT OPERATION "..operation.." not recognized") end
end

function applemem() return manager:machine().devices[":maincpu"].spaces["program"] end

function hgrwhite(page) for x=0,39 do for y=0,191 do applemem():write_u8(calcyaddr(y,page)+x,127) end end end

function getbits(a,lobit,hibit) if a==nil then print("getbits:NIL!") return 0 end local retval=0 for bit=lobit,hibit do retval=retval|((1<<bit)&a) end return retval end

function getbitsshift(a,lobit,hibit) if a==nil then print("getbitsshift:NIL!") return 0 end return getbits(a,lobit,hibit)>>lobit end



function getcharheightfontrix(a,c) return a:byte(0x14+1) end
function getcharwidthfontrix(a,c)  return a:byte((0xe2)+(c-1)+1) end

function getcharwidthfontrix(a,c)  if a:byte(0x12+1)==0 then return a:byte(0x13+1) else return a:byte((0xe2)+(c-1)+1) end end

function getcharoffsetfontrix(a,c) return a:byte((0x20)+(c-1)*2+1)+a:byte((0x21)+(c-1)*2+1)*256 end

function applemem() 
  if applememobject == nil then applememobject = manager:machine().devices[":maincpu"].spaces["program"] end
  return applememobject
end


-- subtle difference, between just catalog() and return catalog()
function cat(...) return catalog(...) end
function CAT(...) return catalog(...) end


--new version of drawfontrix font, with xpos coordinate is pixel, not byte
function drawfontrixfont2(a,c0,c1,offset,doprint,xpos,ypos,lineheight,drawmode)
-- draw font characters from c0 to c1
c0 = c0 or 0
c1 = c1 or 58
offset=offset or 0
--hgrclr() 
xpos,ypos=xpos or 0,ypos or 0
for c=c0,c1 do 
local charwidth=getcharwidthfontrix(a,c)
local charheight=getcharheightfontrix(a,c)
local charoffset=getcharoffsetfontrix(a,c)
local charbytewidth=math.floor((charwidth-1)/8)+1
if doprint then print("char="..c.."  "..string.char(c+31),"width="..charwidth,"height="..charheight,"offset="..hex(charoffset).." vpos="..getcharvposfontrix(a,c))
  end
if charoffset>#a then print("INVALID CHAR OFFSET") 
else
drawblockloop({"y",charheight,"x",charbytewidth},function(x,y,index) local bytetoplot=(a:sub(charoffset+1):byte(index+offset+1)) local numpixels=math.min(8,charwidth-8*x) x=xpos+x*8 for i=0,numpixels-1 do plot(x+i,y+ypos+getcharvposfontrix(a,c),0,getbitsshift(bytetoplot,i,i),drawmode) end end,32)
xpos=xpos+charwidth+2 -- pixels now
if xpos>250 then xpos=0 ypos=ypos+lineheight end  -- ypos=ypos+charheight+1 
end
end
print("returning xpos="..xpos.." ypos="..ypos)
return xpos,ypos
end

function writetextfontrix2(a,s,x,y,lineheight,drawmode) for i=1,#s do c=s:byte(i) c=c-32+1 x,y=drawfontrixfont2(a,c,c,0,nil,x,y,lineheight,drawmode) if x>250 then x=0 y=y+lineheight print(y) end end end


-- for the bigger fonts
function getcharheightfontrix(a,c) return a:byte(0x200+(c-2)+1) end

function getcharheightfontrix(a,c) if a:byte(1)==0x14 then return a:byte(0x200+(c-2)+1) else return a:byte(0x14+1) end end
function getcharvposfontrix(a,c) if a:byte(1)==0x14 then return a:byte(0x200+96*1-1+(c-2)+1) else return 0 end end

--[[


function getfilenamepart(s)
local curpos=1
repeat
local newpos=s:find("/",curpos,true)
if newpos then curpos = newpos+1 end  -- if you don't add the +1, keeps getting same match, infinite loop
until newpos == nil
return s:sub(curpos)
end

function trim2(s) return s:match "^%s*(.-)%s*$" end  -- from lua users wiki


loaddisk("../../fontrix.dsk") setascii=getfile("SET.ASCII BOLD")

co1=coroutine.create( function()
disknamelist={"../../fontrix.dsk","../../Font Paks 1 and 2.dsk","../../fontrixfontpak14.dsk","../../created_image.dsk"}
for d=1,#disknamelist do diskname=disknamelist[d] 
loaddisk(diskname)
filelist=cat()
for i=1,#filelist do print(filelist[i]) 
if filelist[i]:find("SET.",1,true) then 
print("IT'S A FONT so let's render a sample!") 
filename=filelist[i]
a=getfile(filelist[i])
 hgr() hgrfull() hgrclr() xpos=0 ypos=10
drawfontrixfont2(a,1,96,0,true,0,0,30) 
writetextfontrix2(setascii,diskname,0,170,20,"store")
writetextfontrix2(setascii,filename,0,180,20,"store")
emu.wait(1/60+.01) 
manager:machine():debugger():command("snap \"" .. sanefilename(getfilenamepart(diskname).."_"..trim2(filelist[i]))..".png\"")
end end
end
end) 
ok,error=coroutine.resume(co1)
print(ok,error)


--]]



I think the screen's too small for 50 point type.

[Linked Image][Linked Image]
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 03/27/19 02:49 PM

I was creating some blank apple 2 disk images to copy some Prodos files to Dos 3.3 with Copy II+ using mame's built in file manager and was getting some strange results, primarily because I was asking for filenames with .DSK in capitals as opposed to a lowercase .dsk extension.

What threw me off was that it would happily create the file and give it a zero size so I could see it in Ubuntu's file manager but it contained no data.

Only after a few tries did I see that there was a popup message at the bottom of the screen that said "Error: Unable to identify the image format".

So be careful when you leave your caps lock on, because it doesn't like .DSK, only .dsk.

[Linked Image]

Notice that the menu here doesn't have a default option:

[Linked Image]

and we get a popup error message: (which I didn't see the first couple of times I did this)

[Linked Image]


and when using lowercase .dsk extension the menu is slightly different with a bar separating the first option from the rest.

[Linked Image]
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 03/29/19 03:28 AM

With the Apple II SCSI card solidified, the next step was getting the CD-ROM drive to work. Didn't take much work, and here you see the IIgs Finder browsing a PlayStation game disc.

[Linked Image]
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 03/29/19 03:42 AM

MAME is now the first and only Apple IIgs emulator able to use the Golden Orchard CD-ROM .iso.

[Linked Image]

And, it can even boot from the CD-ROM:
[Linked Image]
Posted By: Duke

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 03/29/19 08:22 AM

That's awesome smile
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/02/19 01:59 PM

Something I've been fiddling with (and the emulation is probably horribly incorrect since I have no idea what I'm doing)

Bonus points if you know what this is:

[Linked Image]
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/04/19 12:06 PM

Getting closer...

[Linked Image] [Linked Image] [Linked Image]
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/07/19 11:35 AM

Got different intensities working from 0 to 7: (not that anybody ever used this, but I suppose it's more authentic 8-)

[Linked Image]
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/08/19 04:03 AM

Having some silly fun, 2 printers at the same time, in slots 1 and 2.

Zoom Grafix is awesome:

[Linked Image]

3x3 rotated:

[Linked Image]

It gets a bit slow, but skip 10/10 unthrottle with F10 makes it fly at 800%.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/08/19 06:05 AM

If you want to play with the silentype:

https://github.com/goldnchild/mame/commit/621d051f50803aa23fd4c17d84508ba19a22609e

You don't need to boot into DOS 3.3, just launch mame's apple2p driver with -sl1 silentype,hit reset, type PR#1 and you are sending data to the printer.

CTRL+Q will dump the hi-res screen.


Intensity is stored in 0xCF10:

POKE -12528,0 for intensity 0
POKE -12528,7 for intensity 7

or CALL -151 and then CF10:7 for example.

CTRL+T toggles screen echo

(if you enable screen echo, output is limited to 40 columns so if you LIST an applesoft program it won't be 80 columns wide)


And you can have multiple silentypes which is kind of fun: -sl1 silentype -sl2 silentype. PR#2 will send data to the printer in slot #2.

It will save each page to the snap directory under a silentype directory with a filename that includes the slot number like so:

silentype_slot2_page1.png

There's something really satisfying about watching the emulated printhead move back and forth.



I always felt bad when my silentype printer broke years ago due to a flimsy plastic printhead and a wrinkle in the paper.

I don't feel so bad now that I can run it in mame. 8-)
Posted By: peter ferrie

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/10/19 07:09 PM

Let me know if you want any help with the ProDOS support. I have code to read and write ProDOS disks without relying on ProDOS itself.
Posted By: Lord Nightmare

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/10/19 10:38 PM

That sounds like it could be useful in imagetool/floptool.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/10/19 10:59 PM

Hi Peter,

Sure, any help is appreciated. 8-) I got so interested in the silentype I haven't done much with the disk reading stuff for a while.

I've been studying the books Beneath Apple Prodos and Universal File Conversion.

The one thing that had me really stumped was the different sector orders between dos 3.3 and prodos.

[Linked Image]

So dos 3.3 logical sector 1 maps to prodos logical sector 0xE for example.

I came up with this function which seems to work (it's really useful to look at hexdumps).

Code
-- prodos order to dos order
function mappotodo(a) local map={0,14,13,12,11,10,9,8,7,6,5,4,3,2,1,15} return map[a+1] end
-- function has an interesting property: calling it twice results in inverting the function
-- mappotodo(maptptodo(i))  == i
--
-- example: to hexdump a track in normal dos order
-- for i=0,15 do hexdumpts(0,i) end
-- example: to hexdump the same track in prodos order 
-- for i=0,15 do hexdumpts(0,mappotodo(i)) end

Posted By: peter ferrie

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/11/19 07:53 PM

Hi Golden Child,
Yes, you have it mapped correctly, provided that the disk image is really in ProDOS ordering, of course. It's really physical order rather than DOS order, though.
DOS ordering is 0, 13, 11, 9, 7, 5, 3, 1, 14, 12, 10, 8, 6, 4, 2, 15.
The problem that we have is .dsk and .po aren't fixed in their format, so we might have DOS-ordered sectors in .po files, ProDOS-ordered sectors in .dsk files, physical ordering in both, etc.
Emulators tend to have heuristics to detect what's what, but as you might have seen with the latest release of Anti-M for the Apple II, MAME failed to boot it because the file format was wrong and the heuristic was defeated.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/13/19 08:35 PM

I think I'm very close to getting the Apple Graphics Tablet working...

You PR#4 then print some configuration strings, then IN#4 and INPUT the X,Y and STATUS. If you use

INPUT "";X$,Y$,Z$ you won't see a ? mark on the screen.

after you input the string, IN#0 to reset the input to the keyboard.


What input device can mame map to a tablet? I hooked up a joystick just for testing, just mapping the 0 to 255 values.


[Linked Image]

[Linked Image]

[Linked Image]
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/13/19 09:51 PM

GC: Your Silentype implementation is pretty good, but you can get the slot number in an A2 card by calling slotno(). For instance, the zipdrive/focus drive has the common setup of separate CnXX images in the ROM for each slot:

Code
uint8_t a2bus_zipdrivebase_device::read_cnxx(uint8_t offset)
{
	int const slotimg = slotno() * 0x100;

	// ROM contains CnXX images for each of slots 1-7 at 0x0 and 0x1000
	return m_rom[offset+slotimg+0x1000];
}
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/13/19 11:53 PM

Originally Posted by R. Belmont
GC: Your Silentype implementation is pretty good, but you can get the slot number in an A2 card by calling slotno(). For instance, the zipdrive/focus drive has the common setup of separate CnXX images in the ROM for each slot:

Code
uint8_t a2bus_zipdrivebase_device::read_cnxx(uint8_t offset)
{
	int const slotimg = slotno() * 0x100;

	// ROM contains CnXX images for each of slots 1-7 at 0x0 and 0x1000
	return m_rom[offset+slotimg+0x1000];
}



Hi RB:

Thanks! I knew there had to be an easier way to find out the slot number. I was getting ready to ask you for any suggestions/comments.


I've got to clean up a couple of bugs too:

Code
	    // clear paper to bottom from the current head position

	    // this doesn't make sense
	    // clear to the bottom
	    //m_bitmap.plot_box(m_ypos*7/4,3,PAPER_WIDTH-1,PAPER_HEIGHT-1,rgb_t::white());
           // I think it should be:
	    m_bitmap.plot_box(0,m_ypos*7/4+7,PAPER_WIDTH,PAPER_HEIGHT,rgb_t::white());



Hacking on mame is so darn addictive...
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/14/19 10:45 AM

Hi all,

I'm having some weird issues trying to get the mouse to work for a joystick input. I finally decided that I'd try to get a "real" mouse device hooked up, so I added some code for another mouse.

What's really strange is that once I added the additional mouse, the mouse control of the joystick all of a sudden started working. I added a PORT_CODE(MOUSECODE_X) to select the mouse axis x for the joystick, but it wouldn't work. I also couldn't map the Mouse axis in the mame control panel by hitting enter then moving the mouse horizontally back and forth for mouse axis x or vertically for mouse axis y. With the additional mouse, I can map mouse axis x or y in the control panel.

Another thing I noticed is that if you add the apple mouse card with "-sl4 mouse", you have to manually select the mouse x and y axis in the control panel. I think if there were a PORT_CODE(MOUSECODE_X) for the mouse x axis and a PORT_CODE(MOUSECODE_Y) for the y axis that it would automatically select that. I was using the mouse card with Print Magic and it works really nicely once you config the mouse x axis and y axis.





Code

// just copied mouse definitions from devices/bus/a2bus/mouse.cpp

#define MOUSE_BUTTON_TAG    "a2mse_button"
#define MOUSE_XAXIS_TAG     "a2mse_x"
#define MOUSE_YAXIS_TAG     "a2mse_y"

// joystick definitions from src/mame/drivers/apple2.cpp

#define JOYSTICK_DELTA          80
#define JOYSTICK_SENSITIVITY    50
#define JOYSTICK_AUTOCENTER     80

static INPUT_PORTS_START( apple2_joystick3 )
        PORT_START("joystick_3_x")      /* Joystick 1 X Axis */
        PORT_BIT( 0xff, 0x80, IPT_AD_STICK_X) PORT_NAME("P3 Joystick X")
        PORT_SENSITIVITY(JOYSTICK_SENSITIVITY)
        PORT_KEYDELTA(JOYSTICK_DELTA)
        PORT_CENTERDELTA(JOYSTICK_AUTOCENTER)
        PORT_MINMAX(0,0xff) PORT_PLAYER(3)
        PORT_CODE(MOUSECODE_X)
        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_3_y")      /* Joystick 1 Y Axis */
        PORT_BIT( 0xff, 0x80, IPT_AD_STICK_Y) PORT_NAME("P3 Joystick Y")
        PORT_SENSITIVITY(JOYSTICK_SENSITIVITY)
        PORT_KEYDELTA(JOYSTICK_DELTA)
        PORT_CENTERDELTA(JOYSTICK_AUTOCENTER)
        PORT_MINMAX(0,0xff) PORT_PLAYER(3)
        PORT_CODE(MOUSECODE_Y)
        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)

        PORT_START("joystick_3_buttons")
        PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON1)  PORT_PLAYER(3)            PORT_CODE(KEYCODE_0_PAD)    PORT_CODE(JOYCODE_BUTTON1)
        PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_BUTTON2)  PORT_PLAYER(3)            PORT_CODE(KEYCODE_ENTER_PAD)PORT_CODE(JOYCODE_BUTTON2)
INPUT_PORTS_END

static INPUT_PORTS_START( mouse )
        PORT_START(MOUSE_BUTTON_TAG) /* Mouse - button */
        PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("Mouse Button") PORT_CODE(MOUSECODE_BUTTON1)

        PORT_START(MOUSE_XAXIS_TAG) /* Mouse - X AXIS */
        PORT_BIT( 0xff, 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(40) PORT_KEYDELTA(0) PORT_PLAYER(1)

        PORT_START(MOUSE_YAXIS_TAG) /* Mouse - Y AXIS */
        PORT_BIT( 0xff, 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(40) PORT_KEYDELTA(0) PORT_PLAYER(1)
INPUT_PORTS_END


static INPUT_PORTS_START( gfxall )
    PORT_INCLUDE( mouse )
    PORT_INCLUDE(apple2_joystick3)
INPUT_PORTS_END

/***************************************************************************
    FUNCTION PROTOTYPES
***************************************************************************/


// missing the word const

ioport_constructor a2bus_agraphtablet_device::device_input_ports() const
{
    return INPUT_PORTS_NAME (gfxall );
//  can only return one INPUT_PORTS_NAME here, so we include them both in gfxall and return that
//    return INPUT_PORTS_NAME( apple2_joystick3 );
//    return INPUT_PORTS_NAME(mouse);

}



[Linked Image]

and now I can draw! (with a mouse)

[Linked Image]

Now I wonder how to handle that I can't see the tablet overlays to actually use the software... gonna have to try to make a layout. 8-)
Posted By: Haze

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/14/19 11:06 AM

might need work on the artwork system, I'm not sure there is a way to translate relative coordinates on a layout element into screen coordinates

(things like the Pico need something like this as you're meant to press locations on the book)
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/14/19 02:22 PM

I was thinking of something like this screenshot from OpenEmulator where you could click and draw on the "virtual tablet".

[Linked Image]
Posted By: robcfg

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/14/19 04:51 PM

I'd love to have this working for the Dragon with the Touchmaster Tablet!
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/14/19 05:33 PM

robcfg: if we can come up with a way to make this work in terms of the artwork system and everything, it should also be possible to adapt for other systems.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/14/19 07:38 PM

Just a little mockup in LibreOffice Draw

[Linked Image]

If I could hook up clickable buttons I could set the tablet to register its position in that location.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/14/19 08:42 PM

Some funny messages I saw when trying to run the Menu Alignment Program:

[Linked Image]
[Linked Image]
[Linked Image]
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/15/19 01:31 PM

Having some fun with Motter Tektura fonts and some logos that I found.

I managed to find a neat one with a fixed "s" character called Apple-motter.v1.dfont, but the y character looked funny so I used Verdana and scaled and stretched it.

[Linked Image]
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/16/19 06:07 PM

Ok if you want to try the Graphics Tablet,

https://github.com/goldnchild/mame/commit/d5a41eeb31daab5999c76f3656762a7a04bc2d7e


You'll need the rom:

ROM_LOAD( "341-0026-00.bin", 0x000000, 0x000800, CRC(3dda85de) SHA1(b025f03bb5a9316d4a50bca5503ad4825389518f))


It's pretty useful to "tune" the tablet by setting the min and max values it will return which can be done from the lua console or the mame debugger memory view window (Apple Graphics Tablet/:sl2:agraphtablet/ entries)


You can't have min less than 97 (0x61) or max greater than 2560 (0xa00). Values outside this range are considered "off scale" and you will be likely be eaten by a grue. (No, nothing bad will happen but it will act as though the pen is off the tablet).

Note also that you should use the control panel to remap the mouse buttons for the joystick 3 input (which is masquerading as our tablet) if you want to draw with the tablet disk.

Joystick Button 1 will make the tablet go "offscale" and joystick button 2 will act as "pen down".


The software's not really usable yet as clicking on the overlay buttons is impossible, but I managed to hit the color menu just clicking blindly.

[Linked Image]
Posted By: Pernod

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/16/19 06:52 PM

Originally Posted by robcfg
I'd love to have this working for the Dragon with the Touchmaster Tablet!

I looked into this a couple of years ago. When a practical solution exists for the artwork then I'll get back on it. The tablet overlays should ideally be associated with software, rather than artwork for a machine.
See
https://forums.bannister.org/ubbthreads.php?ubb=showflat&Number=109936#Post109936 for my previous attempt.
Posted By: robcfg

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/16/19 07:57 PM

Hmmm, how does the Vectrex driver manage the overlays per game?
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/16/19 08:49 PM

It seems like SVG_SCREEN would work for this, we just need the SVG renderer to cache the image instead of re-parsing it each frame.
Posted By: Haze

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/16/19 09:09 PM

Originally Posted by robcfg
Hmmm, how does the Vectrex driver manage the overlays per game?


badly last time I checked (everything in one layout file, switchable from the artwork menu)

but that might have been changed?
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/16/19 09:20 PM

Here's more silly fun: patch the rom while the driver's running:

I wanted to see if I could get the Apple Graphics Tablet to return values up to +9999, but the firmware doesn't actually allow that, topping out at 0xa00.

But if we patch the rom code, we can get it to return something larger:


In the rom there's a CMP #$0a (for a maximum counter value of 0xa00), so let's see if we can make it CMP #$0e (for 0xe00)


[Linked Image]


We can use the lua console:

Code
MAME]> print(manager:machine():memory().regions[":sl2:agraphtablet:agraphtablet_rom"]:read_u8(0x47a))
10
[MAME]> print(manager:machine():memory().regions[":sl2:agraphtablet:agraphtablet_rom"]:write_u8(0x47a,0xe0))

[MAME]> print(manager:machine():memory().regions[":sl2:agraphtablet:agraphtablet_rom"]:read_u8(0x47a))
224
[MAME]> emu.item(manager:machine().devices[":sl2:agraphtablet"].items["0/m_tabletmax"]):write(0,0xd05)




Or use the mame debugger memory window to set 0x47a to 0x0f:

[Linked Image]

and set the m_tabletmax to 0xd05

[Linked Image]

A little basic program with scale set to 1, "S1" in the initialization string.

Code
emu.keypost(''..
'      90 PR#2:PRINT"D,M1" : REM DEFAULT, MIXED MODE PAGE 1\n'..
'     100 PR#2:PRINT"P,X291,Y291,S1"\n'..
'     110 IN#2:INPUT "";X$,Y$,Z$:IN#0\n'..
'     120 VTAB 22:PRINT X$Y$Z$\n'..
'     125 POKE -16368,0\n'..
'     140 GOTO 110\n'..
'     RUN\n')





Oh yeah, +9999+9999!

The values seem to be multiplied by 3, so 0xd05 * 3 = 9999.

[Linked Image]


I can also "patch" the Apple 2 character graphics rom with the same idea:

Code
-- changing the @ sign 
-- just start the apple2p driver with the debugger and step until you get a text screen with @ signs:
-- you may need to step the debugger to get the screen to update

[MAME]> print(manager:machine():memory().regions[":gfx1"]:write_u8(0x0,0x01))
[MAME]> print(manager:machine():memory().regions[":gfx1"]:write_u8(0x1,0x02))
[MAME]> print(manager:machine():memory().regions[":gfx1"]:write_u8(0x2,0x04))
[MAME]> print(manager:machine():memory().regions[":gfx1"]:write_u8(0x3,0x08))


[Linked Image]


If you reset the driver with Shift+F3, your rom patching disappears.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/17/19 08:13 PM

I thought I'd try to see if I could get a "slider" adjuster working:

The PORT_ADJUSTER looked very promising but it was limited to 0 to 100. What if I did a define of my own that had a mask of 0xffff for 16 bits?

If I make my own PORT_ADJUSTER_16MASK macro based on the PORT_ADJUSTER macro in src/emu/ioport.h and change the mask, I can get 16 bits.

It seems to work but it says percent in the display.

So now I have an adjuster that goes from 97 to 2559 and I can hit ALT+LEFT or ALT+RIGHT arrow to go to each end of the full extent and CTRL+ARROWS to change the value faster.


Code
#define PORT_ADJUSTER_16MASK(_default, _name)					\
        configurer.field_alloc(IPT_ADJUSTER, (_default), 0xffff, (_name)); \
        configurer.field_set_min_max(0, 100);


static INPUT_PORTS_START( tablet_adjusters )
        PORT_START("Position Min") /*  */
        PORT_ADJUSTER_16MASK(97,"Tablet Position Min")
        PORT_MINMAX(97,2559)


        PORT_START("Position Max") /*  */
        PORT_ADJUSTER_16MASK(2559,"Tablet Position Max")
        PORT_MINMAX(97,2559)
//      PORT_BIT(0xffff, 0x00,  IPT_ADJUSTER)  // this didn't work
INPUT_PORTS_END

static INPUT_PORTS_START(gfxall)
    PORT_INCLUDE(mouse)
    PORT_INCLUDE(apple2_joystick3)
    PORT_INCLUDE(tablet_adjusters)
INPUT_PORTS_END


and I can read the adjusters with:

    m_tabletmin = ioport("Position Min")->read();
    m_tabletmax = ioport("Position Max")->read();
    
    printf("ioport adjusters %x %x\n",ioport("Position Min")->read(),ioport("Position Max")->read());



and with a little Applesoft program we can see the values change in realtime with the sliders:
2559 * 3 = 7677

Code
emu.keypost(''..
'     NEW\n'..
'      90 PR#2:PRINT"D,M1" : REM DEFAULT, MIXED MODE PAGE 1\n'..
'     100 PR#2:PRINT"P,X0,Y0,S1"\n'..
'     110 IN#2:INPUT "";X$,Y$,Z$:IN#0\n'..
'     120 VTAB 22:PRINT X$Y$Z$\n'..
'     125 POKE -16368,0\n'..
'     128 A=FRE(0) : REM APPLESOFT NEEDS GC OR HIRES PAGE GETS CLOBBERED\n'..   -- fre needs a parameter
'     140 GOTO 110\n'..
'     RUN\n')




[Linked Image]
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/18/19 01:00 AM

More dumb fun: Using cassettes with the apple2 driver:

I typed in a short little applesoft program but didn't load DOS, so how to save it?

Just create a cassette image with the file manager with a .wav suffix (it won't work otherwise), then go to tape control, record and type SAVE and return from the command line.

After it beeps twice, your program is saved. Make sure you're recording before you type SAVE or you'll miss some of the program.

To load your program, type LOAD and return then rewind and play your tape image.

The wav file gets large, like 4MB to save a 4K file, but it works!

Once you reboot and load DOS 3.3, just LOAD from your cassette image.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/18/19 01:10 PM

So you want to see bigger fonts in the debugger?

You could use the -debugger_font_size option from the command line or
change the option from the lua console. You won't see it unless you open a new dasm or memory window.

Code
[MAME]> function printt(a) for i,j in pairs(a) do print(i,j) end end
[MAME]> printt(manager:options().entries)

homepath	sol.core_options::entry*: 0x5603fbf64898
screen	sol.core_options::entry*: 0x5603fbf5d608
snapbilinear	sol.core_options::entry*: 0x5603fbf6fa28
gl_forcepow2texture	sol.core_options::entry*: 0x5603fbf361a8
volume	sol.core_options::entry*: 0x5603fbf6f1a8
... etc

[MAME]> print(manager:options().entries["debugger_font_size"]:description())
font size to use for debugger views

[MAME]> print(manager:options().entries["debugger_font_size"]:value())                -- 0.0 is the default
0.0
[MAME]> print(manager:options().entries["debugger_font_size"]:value(5.0))    -- font size for Tiny Elvis
[MAME]> print(manager:options().entries["debugger_font_size"]:value())
5.0
[MAME]> print(manager:options().entries["debugger_font_size"]:value(12.0))   -- mame's default seems to be about 12
[MAME]> print(manager:options().entries["debugger_font_size"]:value(13.0))
[MAME]> print(manager:options().entries["debugger_font_size"]:value(15.0))


[Linked Image]

Why not change the font too?

(monospace fonts are the best, memory views can get weird)

Code
MAME]> print(manager:options().entries["debugger_font"]:value())
auto
[MAME]> print(manager:options().entries["debugger_font"]:value("Verdana"))
[MAME]> print(manager:options().entries["debugger_font"]:value("NanumSquare Bold"))
[MAME]> print(manager:options().entries["debugger_font"]:value("Noto Mono"))




[Linked Image]
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/20/19 04:36 AM

I tried to make a layout file and struggled mightily.

If you want to see mame segfault, just put a stray < somewhere inside the layout file. That was fun to figure out.


I took a layout file from the snspell artwork at Mr. Do's and could not get the buttons to work. I tried and tried and tried, I put the flag MACHINE_CLICKABLE_ARTWORK in apple2p.cpp which didn't help.

COMP( 1979, apple2p, apple2, 0, apple2p, apple2p, apple2_state, empty_init, "Apple Computer", "Apple ][+", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK )


I could see the buttons but they didn't work.

I thought I was going to go insane!


And then I found the answer at http://www.mameworld.info/ubbthread...page=&view=&sb=5&o=&vc=1

Quote


So I noticed none of the buttons (clickable; move up/down when you press them) in this artwork file (mslug2) worked anymore. I look, and the neogeo driver was updated some time back.

I look some more, and I see that the controllers for neogeo are now bus devices.

...


> Because Neo Geo controllers are now bus devices, the input tags also need to be
> changed to edge:joy:JOY1 and edge:joy:JOY2. These tags appear in the -listxml output.


Ah... knew it would be something simple. I had simply changed them to JOY1 and JOY2.

That will help me with other thing, too.

Thank you!!! :cheers5:



So after changing INPUTTAG="joystick_3_buttons" to INPUTTAG="sl2:agraphtablet:joystick_3_buttons" they started working!!!


Sure enough, if you look at the ioports table it will be prefaced with sl2:agraphtablet:

Code
[MAME]> print(manager:machine():ioport().ports)
table: 0x555dcaf592b0
[MAME]> function printt(a) for i,j in pairs(a) do print(i,j) end end 
[MAME]> printt(manager:machine():ioport().ports)
:X6	sol.ioport_port*: 0x555dcaf5a5d8
:sl2:agraphtablet:joystick_3_buttons	sol.ioport_port*: 0x555dcaf5ac68
:sl2:agraphtablet:a2mse_y	sol.ioport_port*: 0x555dcaf5acd8
:X2	sol.ioport_port*: 0x555dcaf5a798
:joystick_2_x	sol.ioport_port*: 0x555dcaf5aa38
...
:sl2:agraphtablet:Position Max	sol.ioport_port*: 0x555dcaf5ae98
:reset_dip	sol.ioport_port*: 0x555dcaf5ab88
:sl2:agraphtablet:joystick_3_y	sol.ioport_port*: 0x555dcaf5af08
:X3	sol.ioport_port*: 0x555dcaf5a728
:joystick_2_y	sol.ioport_port*: 0x555dcaf5a9c8
:joystick_buttons	sol.ioport_port*: 0x555dcaf5a958



I don't know what was worse, struggling to get this working or watching Aquaman at the same time... 8-)

Baby steps...


Code
<!-- taken from snspell.lay and modified -->

<mamelayout version="2">
	<element name="shadow" defstate="0">
		<text string=" ">
			<bounds x="0" y="0" width="1" height="1" />
			<color red="0.0" green="0.0" blue="0.0" />
		</text>
			<disk state="0">
			<bounds x="0.07" y="0.07" width="0.86" height="0.86" />
			<color red="1.0" green="0.0" blue="0.0" />
		</disk>
		<disk state="1">
			<bounds x="0.07" y="0.07" width="0.86" height="0.86" />
			<color red="0.0" green="0.0" blue="0.0" />
		</disk>
	</element>
	<view name="Handheld_Artwork">
		   <screen index="0">
			<bounds x="0" y="0" width="5554" height="7842" />
		</screen> 

		<!-- Keypad	-->
		<!-- ABCDE -->
			<cpanel element="shadow" inputtag="sl2:agraphtablet:joystick_3_buttons" inputmask="0x10"><bounds y="4484" x="600" width="305" height="305"/><color alpha="0.85" /></cpanel>
			<cpanel element="shadow" inputtag="sl2:agraphtablet:joystick_3_buttons" inputmask="0x20"><bounds y="4484" x="1060" width="305" height="305"/><color alpha="0.85" /></cpanel>
	</view>
</mamelayout>



[Linked Image]
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/20/19 01:28 PM

Has anyone made an apple II layout that shows the disk drive LED status?

I was fiddling around and can see the status in the sl6:diskiing;wozfdc/0/external_io_select (0 for drive 1, 1 for drive 2) and the motor in sl6:diskiing;wozfdc/0/active (0 for off, 1 for on, 2 for getting ready to stop)

It should be theoretically possible to do a track LED display too like those indus GT drives.

[Linked Image]
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/21/19 09:41 AM

I wanted to see if I could control the ioports for the joystick and after much fiddling and adding some code to luaengine and ioports.h and ioports.cpp I think I've got it.

Yes, it's a bit of a hack, but it's pretty useful to be able to precisely control an anlog input.

So now I can draw spirals with the graphics tablet:

Code
function spiral()
for i=16384,16384+8192-1 do manager:machine().devices[":maincpu"].spaces["program"]:write_u8(i,0) end
for i=0,256*16,1 do 
x=math.cos(i/256.0*math.pi*2.0)*i/256.0*8.0*1024
y=math.sin(i/256.0*math.pi*2.0)*i/256.0*8.0*1024
ioports=manager:machine():ioport().ports ioports[":sl2:agraphtablet:joystick_3_x"].fields["P3 Joystick X"].live:set_analog_value(math.floor(x),math.floor(x),0)
ioports=manager:machine():ioport().ports ioports[":sl2:agraphtablet:joystick_3_y"].fields["P3 Joystick Y"].live:set_analog_value(math.floor(y),math.floor(y),0)
print (i,x,y,ioports[":sl2:agraphtablet:joystick_3_x"]:read(),ioports[":sl2:agraphtablet:joystick_3_y"]:read())
emu.wait(1/60+.001) 
print (i,x,y,ioports[":sl2:agraphtablet:joystick_3_x"]:read(),ioports[":sl2:agraphtablet:joystick_3_y"]:read())
end 
end
co1=coroutine.create(spiral) ok,err=coroutine.resume(co1) print(ok,err)



I wrote a function set_analog_value that just stuffs values into m_accum and m_previousvalue for the live ioport analog member. m_previousanalog doesn't seem to have any effect.

Code
       // live analog value tracking
        s32                 m_accum;                // accumulated value (including relative adjustments)
        s32                 m_previous;             // previous adjusted value
        s32                 m_previousanalog;       // previous analog value


In ioport.h

Code
struct ioport_field_live
{
        // construction/destruction
        ioport_field_live(ioport_field &field, analog_field *analog);

        void set_value(ioport_value newvalue) {value = newvalue;};
        void set_analog_value(s32 newaccumvalue, s32 newpreviousvalue, s32 newpreviousanalogvalue);




In ioport.cpp

Code
void ioport_field_live::set_analog_value(s32 newaccumvalue, s32 newpreviousvalue, s32 newpreviousanalogvalue)
   {analog->set_accum(newaccumvalue); analog->set_previous(newpreviousvalue); analog->set_previousanalog(newpreviousanalogvalue);}


Just added set_accum, set_previous and set_previousanalog to class analog field:

Code
// ======================> analog_field

// live analog field information
class analog_field
{
        friend class simple_list<analog_field>;
        friend class ioport_manager;
        friend void ioport_field::set_user_settings(const ioport_field::user_settings &settings);

public:
        // construction/destruction
        analog_field(ioport_field &field);

        // getters
        analog_field *next() const { return m_next; }
        ioport_manager &manager() const { return m_field.manager(); }
        ioport_field &field() const { return m_field; }
        s32 sensitivity() const { return m_sensitivity; }
        bool reverse() const { return m_reverse; }
        s32 delta() const { return m_delta; }
        s32 centerdelta() const { return m_centerdelta; }

        // readers
        void read(ioport_value &value);
        float crosshair_read();
        void frame_update(running_machine &machine);

        void set_accum(s32 newvalue){m_accum=newvalue;};
        void set_previous(s32 newvalue){m_previous=newvalue;};
        void set_previousanalog(s32 newvalue){m_previousanalog=newvalue;};



In luaengine.cpp

Code
/* field.live
 */

	sol().registry().new_usertype<ioport_field_live>("ioport_field_live", "new", sol::no_constructor,
                        "set_value", &ioport_field_live::set_value,
                        "set_analog_value", &ioport_field_live::set_analog_value,		
			"name", &ioport_field_live::name,
                        "value", &ioport_field_live::value);


It kinda looks like a fingerprint.


[Linked Image]
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/21/19 04:11 PM

One of the great mysteries to me was why calling write on an io port was ineffective.

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


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

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

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

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


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

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

This made no sense to me at all.

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

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



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


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

Adding a set_value function to the ioport_field_live in ioport.h

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

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


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

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


Now I can set the value directly:


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

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

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



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

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

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


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

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

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


[Linked Image]

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

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

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

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




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

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

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/21/19 11:43 PM

The write method on an I/O port isn't for setting the value of input fields. I/O ports can have output fields as well, with handlers supplied by a device. That's what write is for.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/22/19 03:30 AM

So why not get the tablet to do some turtlegraphics?

[Linked Image] [Linked Image]

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

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

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

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

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

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

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

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

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

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

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

doco(drawsquiral)

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

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

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

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


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



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

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/22/19 11:52 AM

I don't have a real graphics tablet to calibrate against, however there is calibration information on the various software disks available.

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

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

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

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


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

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


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

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

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

and we'll change those sliders to match:

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

[Linked Image]

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

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

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

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

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

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

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


and I can do my own Jackson Pollock.

[Linked Image]
Posted By: anoid

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/23/19 03:20 PM

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

4AM similar crack info

Video below is a playthrough of Adventureland for reference:

Playthrough of Adventureland

Thanks,

A-Noid
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/23/19 08:18 PM

Those don't have weak bits from what I've read of the protection, it's a deeper issue. Probably the same one that prevents us from implementing the weak bits. I'm gonna have to write my own damn floppy subsystem at this rate.
Posted By: anoid

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/23/19 09:46 PM

Thanks Arbee! Impossible Mission WOZ was released today and has it's own, but different difficulties.


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


A-Noid
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/24/19 10:48 AM

[Linked Image]

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

Launching mame with -override_artwork my_art_directory works pretty well.

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

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

Code
Segmentation fault (core dumped)

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

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/24/19 11:04 AM

You realise the format is documented, and we include a script that validates a lot of stuff in XML layouts, right?
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/24/19 11:20 AM

Hi Vas,

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

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

Error handling

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



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

Using complay.py

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

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

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




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

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


Posted By: peter ferrie

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/24/19 04:43 PM

Originally Posted by anoid
FYI - The latest WOZ disks for Adventureland and Pirate Adventure do not appear to work in MAME once you get to the actual game. Could this be
more weak bit issues from the copy protection?


No, the protection is a crafted track with timing bits, but not weak bits.
You'll have to be more specific about what's not working.
I just booted Adventureland in 0.209 and I can walk around and do stuff.
It's awfully slow to load. Perhaps you were not patient enough?
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/24/19 05:01 PM

Okay, let's see how to hook up the buttons to an input port:

I don't know what code to use, so I thought IPT_OUTPUT would work, and that allows me to click on the buttons.

Code
PORT_START("tablet_menu_buttons")
PORT_BIT( 0x1, IP_ACTIVE_HIGH, IPT_OUTPUT)
PORT_BIT( 0x2, IP_ACTIVE_HIGH, IPT_OUTPUT)
PORT_BIT( 0x4, IP_ACTIVE_HIGH, IPT_OUTPUT)
PORT_BIT( 0x8, IP_ACTIVE_HIGH, IPT_OUTPUT)
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OUTPUT)
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OUTPUT)
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OUTPUT)
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OUTPUT)
PORT_BIT( 0x100, IP_ACTIVE_HIGH, IPT_OUTPUT)
PORT_BIT( 0x200, IP_ACTIVE_HIGH, IPT_OUTPUT)
PORT_BIT( 0x400, IP_ACTIVE_HIGH, IPT_OUTPUT)
PORT_BIT( 0x800, IP_ACTIVE_HIGH, IPT_OUTPUT)
PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_OUTPUT)



I define an element for each menu button, from menu0 to menu21:

If I don't define a state option, it gets a state="0" by default and when I click on it it disappears.

Code
         <element name="menu0">
	  <rect>
	         <bounds x="0" y="0" width="1" height="1"/><color red="1.0" green="0.88" blue="0.42" alpha="1.0"/>
	    </rect>
	    <text string="RESET">
	         <bounds x="0" y=".37" width="1.0" height=".25"/><color red="0.0" green="0.0" blue="0.0" alpha="1.0"/>
	    </text>
	 </element>

	<element name="menu1">
	   <rect state="0"><bounds x="0" y="0" width="1" height="1"/><color red="1.0" green="0.88" blue="0.42" alpha="1.0"/></rect>
	   <rect state="1"><bounds x="0" y="0" width="1" height="1"/><color red="1.0" green="0.88" blue="0.42" alpha="0.5"/></rect>
	  <text string="CLEAR"><bounds x="0" y=".37" width="1.0" height=".25"/><color red="0.0" green="0.0" blue="0.0" alpha="1.0"/></text>
	  <text state="1" string="CLEAR"><bounds x="0" y=".37" width="1.0" height=".25"/><color red="1.0" green="1.0" blue="1.0" alpha="1.0"/></text>
	 </element>


So I've got 22 buttons, and I use one bit of the port for each button.

Code
                       <repeat count="22">
			<param name="menunum" start="0" increment="1"/>
			<param name="xpos" start="0" increment="255"/>
			<param name="maskbits" start="1" lshift="1"/>
			<cpanel element="menu~menunum~" inputtag="sl2:agraphtablet:tablet_menu_buttons" inputmask="~maskbits~"><bounds y="0" x="~xpos~" width="245" height="245"/></cpanel>
			</repeat>
			


and then I check the button status and if nonzero, find out which button and use that to set the values returned to the x and y axis so the software thinks the pen is over the button.

Code
	    if (m_tablet_menu_buttons->read())
		{
		int buttonstate=m_tablet_menu_buttons->read();
		for(int i=0;i<22;i++)
		    if (buttonstate & (1<<i))
			m_timervalue = (m_tabletmax-m_tabletmin)/255.0*(i*250.0/22+(250.0/22/2))+m_tabletmin;   // multiply by 250/22  and then offset by half of 250/22 so it's in the middle.
		}


and I can draw like it's 1980! (The graphics tablet software isn't quite DeluxePaint. 8-)

Anybody know where to find the Utopia Graphics System (mentioned at http://www.edibleapple.com/2009/11/23/the-first-apple-tablet-from-1979/ )

[Linked Image]
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/25/19 04:51 AM

Hi all,

I am trying to get some lua scripting going for a layout, and I can't get it to do anything.

Sticking a print("hello") statement doesn't even seem to work.


=====================

Ok, I think I've found the problem, for some reason I don't have the layout plugin activated.

With -plugin layout on the command line, I get some layout action. Yes!


But I can't print anything? And manager isn't available...


Let's look at init.lua in plugins/layout:

It redefines machine to be manager:machine()

so normal lua code that uses manager:machine() to access machine, just becomes machine.


Code
function layout.startplugin()
        local scripts = {}
        local function prepare_layout(script)
                local env = { machine = manager:machine(), pairs = pairs, ipairs = ipairs, emu = emu, print = print,
                                  table = { insert = table.insert, remove = table.remove } }



I added a few things, like emu and print, so now I can do this, a drive led that shows activity:
Code
<script>
  local layout = {}
  local function bool10(a) if a then return 1 else return 0 end end
  function layout.frame()
     --print("oh yeah")   -- it will print oh yeah for every frame if you uncomment it
     machine:outputs():set_value("drive1led",
     bool10(emu.item(machine.devices[":sl6:diskiing:wozfdc"].items["0/active"]):read(0)==1) &amp; 
     bool10(emu.item(machine.devices[":sl6:diskiing:wozfdc"].items["0/external_io_select"]):read(0) == 0))

     machine:outputs():set_value("drive2led",bool10(emu.item(machine.devices[":sl6:diskiing:wozfdc"].items["0/active"]):read(0)==1) &amp; 
     bool10 (emu.item(machine.devices[":sl6:diskiing:wozfdc"].items["0/external_io_select"]):read(0) == 1))
  end
  return layout,"apple2"
</script>


and also in my layout I've got:


Code
       <element name="driveled">
			<disk state="1">
			<bounds x="0.07" y="0.07" width="0.86" height="0.86" />
			<color red="1.0" green="0.0" blue="0.0" alpha="1.0" />
		</disk>
		<disk state="0">
			<bounds x="0.07" y="0.07" width="0.86" height="0.86" />
			<color red="0.0" green="0.0" blue="0.0" alpha="1.0"/>
		</disk>
	</element>


	<view name="Apple2Layout">
		   <bounds x="0" y="0" width="5800" height="4800"/>
		   <screen index="0">
			<bounds x="0" y="500" width="5600" height="3840" />
		</screen> 
		<cpanel element="driveled" name="drive1led"><bounds y="50" x="4400" width="50" height="50"/><color alpha="0.85" /></cpanel>
		<cpanel element="driveled" name="drive2led"><bounds y="50" x="4500" width="50" height="50"/><color alpha="0.85" /></cpanel>
       </view>


So in the upper right, I've got two drive LEDs that light up when the respective disk drive is active. Now all I need to do is activate those drive sounds again. 8-)

I was doing a catalog at the time the snapshot was taken so the drive 1 light was on.

[Linked Image]

I noticed that it flickers more than the apple disk drives would normally,
using this:

Code
bool10(emu.item(machine.devices[":sl6:diskiing:wozfdc"].items["0/active"]):read(0)>0)

instead of

bool10(emu.item(machine.devices[":sl6:diskiing:wozfdc"].items["0/active"]):read(0)==1)

keeps the light on until the motor stops.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/26/19 07:33 AM

More silly fun:

How to make those drive sounds again...


I add the .enable_sound(true) to the end of the line of FLOPPY_CONNECTOR in src/devices/bus/a2bus/a2diskiing.cpp

Code
void diskiing_device::device_add_mconfig(machine_config &config)
{
        DISKII_FDC(config, m_wozfdc, 1021800*2);
        for (auto &floppy : m_floppy)
                FLOPPY_CONNECTOR(config, floppy, a2_floppies, "525", diskiing_device::floppy_formats).enable_sound(true);
}



also turning up the slider control up to 2.0

and I didn't hear the seeks so I added a line to floppy_image_device::seek_phase_w in src/devices/imagedev/floppy.cpp

Code
void floppy_image_device::seek_phase_w(int phases)
{
 ...

        if(TRACE_STEP && (next_pos != cur_pos))
                logerror("track %d.%d\n", cyl, subcyl);
        if (m_make_sound) m_sound_out->step(cyl*5/tracks);   // added this line



It's not quite perfect sounding, but it's satisfying enough along with visible LEDs. 8-)

I also came up with a track display for my layout:
Code
	<element name="counter2digits">
	  <simplecounter maxstate="99" digits="2"><bounds y="0" x="0" width="1" height="1"/><color red="1.0" green="1.0" blue="1.0" alpha="0.85" /></simplecounter>
	</element>

and in my view:
Code
	<cpanel element="counter2digits" name="floppytrack1" ><bounds y="10" x="3000" width="700" height="200"/><color red="1.0" blue="0.0" green="0" alpha="1"/></cpanel>
	<cpanel element="counter2digits" name="floppytrack1sub" ><bounds y="10" x="3500" width="300" height="200"/><color red="1.0" blue="0.0" green="0" alpha="1"/></cpanel>

and for the script:
Code
  local layout = {}
  local function iif(a,b,c) if a then return b else return c end end
  function layout.frame()

   machine:outputs():set_value("floppytrack1",
     iif(
     (emu.item(machine.devices[":sl6:diskiing:wozfdc"].items["0/active"]):read(0)&gt;0),
     emu.item(machine.devices[":sl6:diskiing:0:525"].items["0/cyl"]):read(0),999)
     )
        
     machine:outputs():set_value("floppytrack1sub",
     iif(
     (emu.item(machine.devices[":sl6:diskiing:wozfdc"].items["0/active"]):read(0)>0),
     emu.item(machine.devices[":sl6:diskiing:0:525"].items["0/subcyl"]):read(0),999)
     )


writing 999 to a two digit counter makes it disappear, so the track display disappears when it's inactive.

I figured that red would look good: [Linked Image]

A floppy with sounds, leds and a track display. Awesome!
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/27/19 06:52 PM

More silly fun/experiments:

I came across a disk image for the computer eyes video digitizer (the very first one that hooked up to the gameport). I thought I'd load it up just to see if it'd do anything. Running a capture I saw that if you pressed the controller button, it would change the screen display. Cool!

[Linked Image]

Tapping the controller button as it captures: (kinda looks like a barcode)

[Linked Image]

So this is a 1 bit capture device, capturing 280x192 and it captures 1 bit for each scanline, scanning left to right across the screen.



Well, why not try to send the capture program some data? Gimp is pretty useful in that it can save data in a raw format. I'll create a little 280x192 rgba bitmap and export it as raw data. (gimp seems to want to add an alpha channel to the image)

We'll add some stuff to apple2.cpp:

Make a buffer to hold a picture:
Code
uint m_computereyescapturebuffer[192][280];  // [280][192] that is column major, we want [192][280]
int  m_cex, m_cey;


Give it a save_item so we can access it from lua:
Code
    save_item(NAME(m_computereyescapturebuffer));


Reset the position when we reset AN0.
Code
WRITE_LINE_MEMBER(apple2_state::an0_w)
{
m_cex=0;
m_cey=0;
printf("set cex,cey to zero AN0   %x\n",state);

 m_an0 = state;
}


Read a pixel from button 1 and increment the position:

Code
READ8_MEMBER(apple2_state::flags_r)
{
int old_m_cey=m_cey;
int old_m_cex=m_cex;
if ((m_cex==0) && (m_cey==0)) printf(" AN STATUS: %x %x %x %x\n",m_an0,m_an1,m_an2,m_an3);

        u8 uFloatingBus7 = read_floatingbus() & 0x7f;

        // Y output of 74LS251 at H14 read as D7
        switch (offset)
        {
        case 0: // cassette in (accidentally read at $C068 by ProDOS to attempt IIgs STATE register)
                return (m_cassette->input() > 0.0 ? 0x80 : 0) | uFloatingBus7;

        case 1:  // button 0

                return ((m_joybuttons->read() & 0x10) ? 0x80 : 0) | uFloatingBus7;

        case 2:  // button 1

m_cey=m_cey+1;
if(m_cey>191) {m_cey=0; m_cex=m_cex+1;}

return (m_computereyescapturebuffer[std::min(old_m_cey,191)][std::min(old_m_cex,279)]>(128*m_an2+64*m_an1+32*m_an3))? 0x80:0;

// capture threshold seems to be 128  *m_an2  +  64 * m_an1    + 32 * m_an3


and since the main machine's saveitems aren't accessible otherwise, we'll add a function to luaengine.cpp

Code
      emu["items"] = [this](){        sol::table table = sol().create_table();
                                        // 10000 is enough?
                                        for(int i = 0; i < 10000; i++)
                                        {
                                                std::string name;
                                                const char *item;
                                                unsigned int size, count;
                                                void *base;
                                                item = machine().save().indexed_item(i, base, size, count);
                                                if(!item) break;
                                                //name = &(strchr(item, '/')[1]);
                                                name = item;
                                                table[name] = i;                                             
                                        }
                                        return table;
                                };




Now we can load the file into a string:
Code
f=assert(io.open("rawmame_280x192.data"))
a=f:read("*a") f:close() print(#a) 

and then write it into our capture "buffer".
Code
quick = emu.items()["Apple ][+/:/0/m_computereyescapturebuffer"] print(quick)
for i=0,280*192-1 do emu.item(quick):write(i,a:byte(1+i*4)) end  -- just grab the red component to make it simple


It's a bit of a hack (yeah ok, it's a total hack), in that I'm not really getting the timing and sync right, I'm just incrementing the read position based on how many times it reads button 1, and resetting that position when it resets AN0.


I want to figure out how to capture a frame with v4l2 and load that up.


Mame logo:
[Linked Image]

original bitmaps:
[Linked Image]

8 level capture versus a 2 level capture:
[Linked Image][Linked Image]


The 8 bit guy has a video using a computer eyes on a c64 at https://www.youtube.com/watch?v=4vpKsteIzJs At the 6:55 mark you can see what's actually inside, it's pretty simple.

Digital Vision put up a webpage for the history of their products:

http://www.digital-vision-inc.com/productCEAppleII.htm
Posted By: Pernod

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/27/19 07:24 PM

There's a Video Digitiser for the BBC Micro I'd like to emulate at some point, but we don't yet support any kind of video input. Would implementing a bitmap_image_device be a suitable compromise to allow emulating such devices?

With a bitmap_image_device you'd be able to provide a bmp image for the emulated device to capture. Waste of time or worthwhile?
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/27/19 08:18 PM

A bitmap image device would be cool. libpng and libjpeg are available in MAME so you should be able to go nuts on input formats, within reason.
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/28/19 12:22 AM

The Digital Vision website indicates that the Apple II, C64, and Atari 800 versions are the same hardware with different connection methods (game port on A2 and Atari, user port on the Commodore) so we could potentially pull one of those "only in MAME" things if the software for all 3 can be found.
Posted By: robcfg

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/28/19 07:15 AM

Same goes for the Touchmaster Tablet which, according to the manual, can be connected to a BBC Micro, a C64, Vic-20, the ZX Spectrum and the Dragon.

I’ve only managed to see the Dragon version, though.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/28/19 11:41 AM

I found a c64 computereyes disk on the net (just search for "computereyes c64")
and thought I'd have a look.

It uses the userport and from the info at: https://www.c64-wiki.com/wiki/CIA the important addresses are $DD01 (read/write data) and $DD03 (sets io direction).

Making some hacky changes to c64.cpp:

Code
uint m_computereyescapturebuffer[200][320];  // resolution of c64 capture is 320x200
int  m_cex, m_cey;
int m_portb_write;


add the save item:

Code
 save_item(NAME(m_computereyescapturebuffer));


make some changes to the cia2:

Code
READ8_MEMBER( c64_state::cia2_pb_r )
{

int threshold = ((m_portb_write & (1<<2)) ? 128 : 0) +      // bit 2 = threshold bit 7
                ((m_portb_write & (1<<1)) ? 64  : 0) +      // bit 1 = threshold bit 6
                ((m_portb_write & (1<<0)) ? 32  : 0) ;      // bit 0 = threshold bit 5

//threshold = threshold;  // compiler keeps complaining about unused variables!!!
int valtoreturn = m_computereyescapturebuffer[std::min(m_cey,199)][std::min(m_cex,319)]>threshold ? 0x40:0;  // return capture in bit 6, sync is bit 7
//int valtoreturn = m_joy2->read_joy()&(1<<5) ? 0x40:0;  // return capture in bit 6, sync is bit 7, joystick button to set the capture bit

// find address of pc
std::string mycontext = machine().describe_context();
int myaddr = stoi(mycontext.substr(mycontext.find("(")+1,4),nullptr,16);
if (myaddr==0xc101) // only increment our position if we are reading $DD01 at address 0xc101 since we read $DD01 in multiple places
{
m_cey=m_cey+1;
if(m_cey>199) {m_cey=0; m_cex=m_cex+1;}
}

return valtoreturn;  
        return m_user_pb;
}

WRITE8_MEMBER( c64_state::cia2_pb_w )
{
        m_user->write_c((data>>0)&1);
        m_user->write_d((data>>1)&1);
        m_user->write_e((data>>2)&1);
        m_user->write_f((data>>3)&1);
        m_user->write_h((data>>4)&1);
        m_user->write_j((data>>5)&1);
        m_user->write_k((data>>6)&1);
        m_user->write_l((data>>7)&1);

printf("wrote %x to pb_w      m_user_pb=%x\n",data,m_user_pb);  // why doesn't m_user_pb == data?
if ((data&0xf) != (m_portb_write&0xf)) {printf("LOW NIBBLE CHANGED RESETTING m_cex,m_cey=0\n");m_cex=0;m_cey=0;}
m_portb_write=data;
}


and our pic must be 320x200 now, so I made a little file in Gimp to "capture"


Code
f=assert(io.open("c64raw.data"))
a=f:read("*a") f:close() print(#a) 
quick = emu.items()["Commodore 64 (NTSC)/:/0/m_computereyescapturebuffer"] print(quick)
for i=0,320*200-1 do emu.item(quick):write(i,a:byte(1+i*4)) end  -- just grab the red component to make it simple


The first thing I'd thought I'd try was to hook up the joystick 2 button and get it to return some values into bit 6 of the user port b at $dd01.

After that worked I tried to get a picture to load, but I noticed that it keeps reading from $dd01 in multiple locations since it gets the sync bit in bit 7,
so we only increment the position when we read at address $c101.

[Linked Image] Using the joystick 2 button: [Linked Image]
[Linked Image]
[Linked Image][Linked Image][Linked Image]

It gets a higher resolution 320x200 than the apple's 280x192 capture which is a slight improvement, but still black and white. Unfortunately, it blanks the screen while capturing (probably to avoid any cpu slowdown) so you can't see what's going on.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/28/19 03:28 PM

I'm on a roll now, let's see if we can get the atari 800 computer eyes to show something.

I found a file with v1.3 and v2.0 and the plain 800 driver wouldn't load it, but the 800xl driver would boot them properly.

So let's make some changes to atari400.cpp:

We'll add our capture buffer, plus a couple of functions to pass-through the pia read and write:

Code
uint m_computereyescapturebuffer[192][320];  // resolution of atari 800 capture is 320x192
int  m_cex, m_cey;
int m_portb_write;

uint8_t mypiaread_alt(offs_t offset){

int retval = m_pia->read_alt(offset);

if (offset==0) {

int threshold = ((m_portb_write & (1<<3)) ? 128 : 0) +      // bit 3 = threshold bit 7
                ((m_portb_write & (1<<2)) ? 64  : 0) +      // bit 2 = threshold bit 6
                ((m_portb_write & (1<<1)) ? 32  : 0) ;      // bit 1 = threshold bit 5

retval = m_computereyescapturebuffer[std::min(m_cey,191)][std::min(m_cex,319)]>threshold ? 0x40:0;  // return capture in bit 6, sync is bit 7

// find address of pc
std::string mycontext = machine().describe_context();
int myaddr = stoi(mycontext.substr(mycontext.find("(")+1,4),nullptr,16);
if (myaddr==0x1eb7) // only increment our position if we are reading $D300 at address 0xc101
{
  m_cey=m_cey+1;
  if(m_cey>191) {m_cey=0; m_cex=m_cex+1;}
}
}
//printf("read pia offset=%x return=%x\n",offset,retval);
return retval;
}


void   mypiawrite_alt(offs_t offset, uint8_t data) {

if (offset==0) {  // reset the counters on any port write
  m_cex=0;
  m_cey=0;
  printf("set cex,cey to zero pia write to D300 \n");
  m_portb_write = data;
}
;printf("write pia offset=%x  data=%x\n",offset,data); m_pia->write_alt(offset,data); }

};



put my pass through handlers into the memory map in place of the pia:
Code
void a400_state::a800xl_mem(address_map &map)
{
        map(0x0000, 0xcfff).rw(FUNC(a400_state::a800xl_low_r), FUNC(a400_state::a800xl_low_w));
        map(0xd000, 0xd0ff).rw(m_gtia, FUNC(gtia_device::read), FUNC(gtia_device::write));
        map(0xd100, 0xd1ff).noprw();
        map(0xd200, 0xd2ff).rw("pokey", FUNC(pokey_device::read), FUNC(pokey_device::write));
//      map(0xd300, 0xd3ff).rw(m_pia, FUNC(mypiaread_alt), FUNC(pia6821_device::write_alt));
// put in my pia functions
        map(0xd300, 0xd3ff).rw(FUNC(a400_state::mypiaread_alt), FUNC(a400_state::mypiawrite_alt));
        map(0xd400, 0xd4ff).rw(m_antic, FUNC(antic_device::read), FUNC(antic_device::write));
        map(0xd500, 0xd7ff).noprw();
        map(0xd800, 0xffff).rw(FUNC(a400_state::a800xl_high_r), FUNC(a400_state::a800xl_high_w));
}


add our save item to a800xl:
Code
MACHINE_START_MEMBER( a400_state, a800xl )
{
        m_mmu = 0xfd;
        m_ext_bank = 0x03;  // only used by a130xe
        setup_cart(m_cart);

        save_item(NAME(m_cart_disabled));
        save_item(NAME(m_cart_helper));
        save_item(NAME(m_last_offs));
        save_item(NAME(m_mmu));
        save_item(NAME(m_ext_bank));

 save_item(NAME(m_computereyescapturebuffer));

}



Making a picture in Gimp that's 320x192.

and our lua code to load the picture from a disk file:
Code
f=assert(io.open("ATARI800.data"))
a=f:read("*a") f:close() print(#a) 
quick = emu.items()["Atari 800XL (NTSC)/:/0/m_computereyescapturebuffer"] print(quick)
for i=0,320*200-1 do emu.item(quick):write(i,a:byte(1+i*4)) end  -- just grab the red component to make it simple


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


What's different about the Atari 800 is that you get two new options: High contrast and Low contrast which gives you a 4 level grayscale capture, which I like a little better than the dithering.

[Linked Image][Linked Image]
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/28/19 04:36 PM

Very, very cool!
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/29/19 01:51 PM

Thanks, RB!

I found a disk image of the ComputerEyes that would capture in Double hi-res, so I did some hacking on the apple2e driver to make it work:


I did run into a couple of interesting problems.

The ioudis was preventing the annunciators from getting modified.

In the function do_io the ioudis keeps the bottommost switch from getting reached due to a return.


Code
void apple2e_state::do_io(address_space &space, int offset, bool is_iic)
{
        if(machine().side_effects_disabled()) return;

        // Handle C058-C05F according to IOUDIS
        if ((offset & 0x58) == 0x58)
        {

          if (m_ioudis)
                {       printf("m_ioudis <> 0\n");
                        switch (offset)
                        {
                                case 0x5e:  // SETDHIRES
                                        m_screen->update_now();
                                        m_video->m_dhires = true;
                                        break;

                                case 0x5f:  // CLRDHIRES
                                        m_screen->update_now();
                                        m_video->m_dhires = false;
                                        break;
                        }
                }

                return;           // always hits return here
        }

      switch (offset)      // switch here never gets reached for cases 0x58-0x5f
        {
                case 0x20:
                        if (m_cassette)
                        {



so my hack code never gets reached.

Code
                case 0x58: // AN0 off
                         m_cex=0;
                         m_cey=0;
                         printf("set cex,cey to zero AN0 %x \n",0);
                        
                         m_an0 = false; break;


Everything's made right by copying the switch statement and putting the relevant parts into an else.

Code
               else
                        switch (offset)
                        {

               case 0x58: // AN0 off
                        m_an0 = false; break;

                case 0x59: // AN0 on
                        m_an0 = true; break;

                case 0x5a: // AN1 off
                        m_an1 = false; break;

                case 0x5b: // AN1 on
                        m_an1 = true; break;

                case 0x5c: // AN2 off
                        m_an2 = false; break;

                case 0x5d: // AN2 on
                        m_an2 = true; break;

                case 0x5e: // AN3 off
                        m_an3 = false; break;

                case 0x5f: // AN3 on
                        m_an3 = true; break;
                        }

                return;         



And I noticed that ioudis is 1 on bootup, so after setting ioudis to 0 manually with the debugger memory window, things started working. Yay!

The dithering is a bit better (no pun intended) at the higher resolution of 560x192.

[Linked Image][Linked Image]
b+w double hi-res [Linked Image] color double hi-res [Linked Image]
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/29/19 02:28 PM

Yeah, that return should be inside the if (m_ioudis) {} block, not just after it. Good catch!
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 04/30/19 02:45 PM

The Computereyes double hires capture program is really baffling to me because it never seems to touch the ioudis softswitches at C07E and C07F to turn ioudis off and on.

According to Jon Relay's page, C07E and C07F are the important switches.

Code
C07E 49278 IOUDISON      EC  W    Disable IOU
           RDIOUDIS      EC   R7  Status of IOU Disabling
C07F 49279 IOUDISOFF     EC  W    Enable IOU
           RDDHIRES      EC   R7  Status of Double HiRes


and ioudis is supposed to control access to the annunciators:

Code
C058 49240 CLRAN0       OE G WR   If IOUDIS off: Annunciator 0 Off
           DISXY          C  WR   If IOUDIS on: Mask X0/Y0 Move Interrupts
C059 49241 SETAN0       OE G WR   If IOUDIS off: Annunciator 0 On
           ENBXY          C  WR   If IOUDIS on: Allow X0/Y0 Move Interrupts
C05A 49242 CLRAN1       OE G WR   If IOUDIS off: Annunciator 1 Off
           DISVBL         C  WR   If IOUDIS on: Disable VBL Interrupts
C05B 49243 SETAN1       OE G WR   If IOUDIS off: Annunciator 1 On
           ENVBL          C  WR   If IOUDIS on: Enable VBL Interrupts
C05C 49244 CLRAN2       OE G WR   If IOUDIS off: Annunciator 2 Off
           X0EDGE         C  WR   If IOUDIS on: Interrupt on X0 Rising
C05D 49245 SETAN2       OE G WR   If IOUDIS off: Annunciator 2 On
           X0EDGE         C  WR   If IOUDIS on: Interrupt on X0 Falling
C05E 49246 CLRAN3       OE G WR   If IOUDIS off: Annunciator 3 Off
           Y0EDGE         C  WR   If IOUDIS on: Interrupt on Y0 Rising
           DHIRESON      ECG WR   In 80-Column Mode: Double Width Graphics
C05F 49247 SETAN3       OE G WR   If IOUDIS off: Annunciator 3 On
           Y0EDGE         C  WR   If IOUDIS on: Interrupt on Y0 Falling
           DHIRESOFF     ECG WR   In 80-Column Mode: Single Width Graphics


and according to the Apple IIe Technical reference manual, appendix F: frequently used tables,

Code
IOUDIS W $C07E On: disable IOU access for addresses $C058 to $C05F; enable access to DHIRES switch
IOUDIS W $C07F Off: enable IOU access for addresses $C058 to $C05F; disable access to DHIRES switch


and lower down on the page it says:

Code
 The firmware normally leaves IOUDIS on.


The thing is, I can't find anywhere that touches these softswitches:

Running the apple2e driver with digitalvision_computereyes_dhgr_v2.4.dsk (v2.4 which was found inside of digitalvision_computereyes.zip)
and another version in AIIComputerEyesDHR.DSK (v.1.0 of the capture program)

and setting a watchpoint in the debugger before the driver boots:

Code
wpset c07e,2,rw


and it never hits the watchpoint at all in the capture program.

So it must be still able to modify the Annunciators even with IOUDIS on?

Code
812A: AD 5E C0 lda DHIRESON
812D: 66 01    ror $01
812F: 90 03    bcc $8134
8131: AD 5F C0 lda DHIRESOFF
8134: AD 5A C0 lda CLRAN1
8137: 66 01    ror $01
8139: 90 03    bcc $813e
813B: AD 5B C0 lda SETAN1
813E: AD 5C C0 lda CLRAN2
8141: 66 01    ror $01
8143: 90 03    bcc $8148
8145: AD 5D C0 lda SETAN2
8148: AD 59 C0 lda SETAN0
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 05/02/19 03:11 AM

Let's see if we can capture a "real" picture from our webcam and get it to load:

Using v4l2 on ubuntu with my LifeCam VX-6000:

lsusb reports:
Bus 001 Device 014: ID 045e:00f4 Microsoft Corp. LifeCam VX-6000 (SN9C20x + OV9650)

Code
v4l2-ctl --device /dev/video0 --stream-mmap --stream-to=frame.jpg --stream-count=1 --set-fmt-video=width=640,height=480,pixelformat=JPEG

and then convert frame.jpg to a raw RGBA using imagemagick:

Code
convert -resize 280x192\! frame.jpg -size 280x192 -depth 8 -modulate 200,0 -brightness-contrast 0x50 RGBA:myframe.data


I had to put the exclamation mark after the resize or imagemagick would set it to the original aspect ratio and I'd get a 256x192 image instead of 280x192.

The modulate takes away all of the color and I thought I'd ramp up the contrast a bit:

and then load it into the buffer, though it's a good idea to do this once the computer has booted, since it treats the controller button 2 as one of the open apple keys
and it goes into a self test.

Code
f=assert(io.open("myframe.data"))
a=f:read("*a") f:close() print(#a) 
quick = emu.items()["Apple //e/:/0/m_computereyescapturebuffer"] print(quick)
for i=0,280*192-1 do emu.item(quick):write(i,a:byte(1+i*4)) end  -- just grab the red component to make it simple


Taking a picture of something handy nearby and then passing it to the Apple //e double-hi res capture program:

[Linked Image][Linked Image]


I also found a c64 computereyes capture program that will do greys (5 levels of grey though only 2 levels per 8x8 block)

computereyes32doodle-sb168180-Page-ZimmermanSet2.d64

It will do a LOW-CONT capture or a HIGH-CONT capture in addition to the regular B/W dithering.

But it puts its routines in a different location so my hacky code that checks the PC needs modifying, The accesses for $DD01 that are important use the BIT opcode so we'll look for a BIT opcode then. Hacky, but it seems to work.

Code
READ8_MEMBER( c64_state::cia2_pb_r )
{

int threshold = ((m_portb_write & (1<<2)) ? 128 : 0) +      // bit 2 = threshold bit 7
                ((m_portb_write & (1<<1)) ? 64  : 0) +      // bit 1 = threshold bit 6
                ((m_portb_write & (1<<0)) ? 32  : 0) ;      // bit 0 = threshold bit 5

int valtoreturn = m_computereyescapturebuffer[std::min(m_cey,199)][std::min(m_cex,319)]>threshold ? 0x40:0;  // return capture in bit 6, sync is bit 7
if (m_ram->pointer()[m_maincpu->pc()]==0x2c)  // 0x2c == BIT opcode, looking for BIT $DD01 
{
m_cey=m_cey+1;
if(m_cey>199) {m_cey=0; m_cex=m_cex+1;}
}

return valtoreturn;  


and we just convert it to 320x200 with imagemagick:
Code
convert -resize 320x200\! frame.jpg -size 320x200 -depth 8 -modulate 200,0 -brightness-contrast 0x50 RGBA:myframe.data

[Linked Image][Linked Image]

Posted By: rfka01

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 05/03/19 05:14 PM

Guy over at the German vintage computer forum uploaded an archive with Basis 108 disk images ... I've uploaded them to the FTP just in case.

https://forum.classic-computing.de/forum/index.php?thread/16546-disketten-sw-f%C3%BCr-basis-108/
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 05/03/19 06:14 PM

That's great! Original software for Apple II clones is a bit hard to find these days smile
Posted By: rfka01

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 05/03/19 07:21 PM

I'm not sure if they're original, but at least they're marked as being for the Basis 108.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 05/05/19 03:34 PM

Let's see if we can pretend to be a ComputerEyes 2 (the version which goes in a Apple II slot). They were kind enough to give out Big Mac assembly source code for the capture routines which made things so much easier to figure out what's happening. That's found on digitalvision_computereyes2_sourcecode.dsk.

The ComputerEyes 2 will capture at 280x192 black and white, and 140x192 with 8 levels of gray (or with false color, which is an interesting effect). It will capture a full frame in about 6 seconds. (Since we're cheating it goes faster because we're not actually syncing to a real signal)

It captures one pixel in each column moving from top to bottom, with the column captures moving from left to right across the screen.

So let's make a hack to see something on screen.

We'll put it in slot 1 which means that its i/o addresses are at C090,C091 and C092. I don't want to go to the trouble of making a proper device so we'll hack up the c080_r and the c080_w routine to intercept accesses to these addresses.


First, add a couple of variables:

Code
uint m_computereyescapturebuffer[192][280];  // [280][192] that is column major, we want [192][280]
int m_cex, m_cey;
int m_cer0,m_cer1,m_cer2;
int m_cethreshold_counter;


Code
READ8_MEMBER(apple2e_state::c080_r)
{

//  CER0 read bits
//  10 = sync
//  20 = test bit (used in detection), turned on by writing 80 to cer0
//  01 = capture data bit
// CER0 write bits
//  80 = test bit on (bit 7)
//  40 = monitor relay
//  0F = brightness  (guessing bits 0..3?)
// CER1 write bits
//  80 = interface on (bit 7)
//  0F = contrast (guessing bits 0..3?)

int retval=0;

        if (offset==0x10) // c090 SLOT 1
           {  if (m_cer0 & 0x80) {printf("cer0 returning 0x20\n");  return 0x20;}
              else

                  if ( ((m_maincpu->pc() >= 0x84f3) && (m_maincpu->pc()<= 0x8505)) ||
                       ((m_maincpu->pc() >= 0x85a1) && (m_maincpu->pc()<= 0x85b3)) ||
                       ((m_maincpu->pc() >= 0x82c5) && (m_maincpu->pc()<= 0x82c5)) )
                  {
                     retval = (m_computereyescapturebuffer[std::min(m_cey,191)][std::min(m_cex,279)]<((7-m_cethreshold_counter) * 0x20))? 0x01:0;  // data in bit 0 
                     printf("cer0 retval = %x   pc= %x  m_cethreshold_counter=%d  m_cex=%x m_cey=%x\n",retval,m_maincpu->pc(),m_cethreshold_counter,m_cex,m_cey);
                     m_cethreshold_counter += 1;
                     int thresholdlimit = 7;
                     if (m_maincpu->pc() == 0x82c5) thresholdlimit=1;
                     int totalrows=191;
                     if ((m_maincpu->pc() >= 0x84f3) && (m_maincpu->pc()<= 0x8505)) totalrows=192; 
                     if (m_cethreshold_counter >= thresholdlimit)
                        {m_cey += 1;
                        if (m_cey>totalrows){m_cex += 1; m_cey=0;}
                         }
                     m_cethreshold_counter %= thresholdlimit; 
                   }
                   else if (m_maincpu->pc() == 0x8270) {retval = 0x10; m_cex=0;m_cey=0;}   // sync, expects a 1 to proceed within 256 loop cycles or error
                   else if (m_maincpu->pc() == 0x827f) retval = 0x0;                       // sync, expects a 0 to proceed within 256 loop cycles or error
                     return retval;
             }
        else if ((offset==0x11)||(offset==0x12)) return 0;

        if(!machine().side_effects_disabled())
...


and we'll hack on c080_w for the writes:

Code

WRITE8_MEMBER(apple2e_state::c080_w)
{
        int slot;

        offset &= 0x7F;
        slot = offset / 0x10;

        if (offset==0x10) // c090 SLOT 1
           {  
             printf("write cer0  data=%x\n",data);
             m_cer0 = data;
             return;
             }
        else if (offset==0x11)
            {
              printf("write cer1  data=%x\n",data);
              m_cer1 = data;
              return;
            }
         else if (offset==0x12)
            {
              printf("write cer2  data=%x\n",data);
              m_cer2 = data;
//              m_cex = 0;
//              m_cey = 0;
              m_cethreshold_counter=0;
                return;
            }




One of the things that threw me for awhile was that the DHR grey captures 192 rows while the DHR false color captures 193 rows, which I have to take into account.


Then we'll get lua to execute v4l2-ctl to capture us a frame, convert it and preview it with eog (eye of gnome, Ubuntu's default image viewer). If the lua code wants to pause on launching eog, just have an eog window already open.

Note that I'm converting it to 140x192 twice, once for the data to load, and another to generate a preview so I can see what's actually being passed through:
(Yes I named it frame280.jpg, that's before I figured out it was actually a 140 pixel capture).

If you pass imagemagick convert the -append parameter it will "concatenate" jpegs together for my preview jpeg.

[Linked Image]

The commands broken into separate lines:

Code
v4l2-ctl --device /dev/video0 --stream-mmap --stream-to=frame.jpg --stream-count=1 --set-fmt-video=width=640,height=480,pixelformat=JPEG  --set-ctrl=brightness=175,contrast=255;
convert -resize 140x192\\! frame.jpg -modulate 200,0 -brightness-contrast 0x50 frame280.jpg;
convert -resize 140x192\\! frame.jpg -size 140x192 -depth 8 -modulate 200,0 -brightness-contrast 0x50 RGBA:myframe.data; 
convert -append frame.jpg frame280.jpg framepreview.jpg;
eog -w framepreview.jpg


Code
ret=os.execute("v4l2-ctl --device /dev/video0 --stream-mmap --stream-to=frame.jpg --stream-count=1 --set-fmt-video=width=640,height=480,pixelformat=JPEG  --set-ctrl=brightness=175,contrast=255;convert -resize 140x192\\! frame.jpg -modulate 200,0 -brightness-contrast 0x50 frame280.jpg;convert -resize 140x192\\! frame.jpg -size 140x192 -depth 8 -modulate 200,0 -brightness-contrast 0x50 RGBA:myframe.data; convert -append frame.jpg frame280.jpg framepreview.jpg;echo hello;eog -w framepreview.jpg;echo hello")  print(ret) 

f=assert(io.open("myframe.data")) a=f:read("*a") f:close() print(#a) quick = emu.items()["Apple //e/:/0/m_computereyescapturebuffer"] print(quick)
counter=0 for row=0,192-1 do for x=0,139 do emu.item(quick):write(row*280+x,a:byte(1+counter*4)) counter = counter + 1 end end





[Linked Image] [Linked Image]
Note the black and white capture is 280x192 (and I've loaded only a 140x192 bitmap, the right side is from a previous load of a 280x192 bitmap)
[Linked Image] [Linked Image]
DHR grey
[Linked Image] [Linked Image]
DHR False Color
[Linked Image] [Linked Image]


According to the Digital Vision website, there's supposed to be a 12-second scan mode in addition to the 6-second scan, but the version of the software that I was able to find only seems to do the single scan only. I can do 8 levels of gray, where the article says 64 levels of gray. Perhaps it adjusts the brightness and contrast slightly, then does another 6-second scan and averages the results.
Quote

ComputerEyes/2 was still a black-and-white slow-scan device requiring six seconds to capture an image, but all of the gray levels were captured at once, and there were 64 of them! This resulted in images of excellent quality (for the day). A 12-second scan mode was also provided that produced images with even higher resolution. ComputerEyes/2 replaced the original ComputerEyes, which was the company's first product to become obsolete!


http://www.digital-vision-inc.com/productCEAppleII2.htm
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 05/09/19 02:47 PM

More fun:

I thought I'd see if I could figure out the AlphaSyntauri keyboard:

[Linked Image]

Hacking on the apple2e driver, I think I've figured it out:

If I put the keyboard interface in slot 7, the i/o addresses would be c0f0-c0ff (c080+70 to c08f + 70) and it looks like it's actually pretty simple (though getting there was hard and exasperating, I don't know how you guys figure out the really hard stuff).

Using the AlphaSyntauri alphaplus software as my testing ground,
There are 61 keys for a 5 octave keyboard, 12 for each octave * 5 plus the start of one extra octave.

The lower 8 bytes (c0f0-c0f7) are the key off bits.
The upper 8 bytes (c0f8-c0ff) are the key on bits.

(corrected this - oops - need more sleep)

c0f0,c0f8 bit 0 = lowest octave c
c0f0,c0f8 bit 1 = + 8 half tones from c (c#,d,d#,e,f,f#,g,g#) g#
c0f0,c0f8 bit 2 = + 8 half tones (a,a#,b,c,c#,d,d#,e) e
c0f0,c0f8 bit 3 = + 24 half tones (f,f#,g,g#,a,a#,b,c) ( 2 octaves higher c)
c0f0,c0f8 bit 4 = + 32 half tones g#
c0f0,c0f8 bit 5 = + 40 half tones e
c0f0,c0f8 bit 6 = + 48 half tones ( 4 octaves higher c)
c0f0,c0f8 bit 7 = + 56 half tones
...

c0f1 - starts at c#, bits increment at +8 half tones
c0f2 - starts at d, bits increment at +8 half tones


and etc.

I haven't figured everything out yet, like how you can do velocity sensitive key testing? or how the pedals map into this, but it's a start.

According to an article I found:
Quote

Velocity sensing. Each key on the alphaSyntauri keyboard has two electrical contacts, one of which makes [contact] about one-third of the key-down travel, the other of which makes [contact] at the bottom. When a key is pressed, the following occurs:

The lower contact closes. A count register in the Apple II's memory which is assigned and maintained for each key is set to zero. No other action takes place.
The upper contact closes. The accumulated count value in the key's timing register is used to index into the velocity assignment table. Attack rate and attack target volume (envelope) of the oscillators are determined. (Note, both attack rate and attack volume are varied. Psychoacoustic research tells us that we perceive loudness to increase not only with absolute loudness increase, but also as a function of the rate of increase and the linearity of the curve.)
A new oscillator is assigned for the key which has been pressed.



I added a bunch more buttons to the apple joystick so now I have 16 buttons to map:

(I just don't have enough keys on the keyboard, I'm gonna have to figure out how to do multiple keyboards on Ubuntu)

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)
        PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_BUTTON2)  PORT_PLAYER(2)            PORT_CODE(JOYCODE_BUTTON2)
        PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON3)  PORT_PLAYER(1)            PORT_CODE(JOYCODE_BUTTON3)
        PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON4)  PORT_PLAYER(1)            PORT_CODE(JOYCODE_BUTTON4)
        PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON5)  PORT_PLAYER(1)            PORT_CODE(JOYCODE_BUTTON5)
        PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_BUTTON6)  PORT_PLAYER(1)            PORT_CODE(JOYCODE_BUTTON6)
        PORT_BIT( 0x20000, IP_ACTIVE_HIGH, IPT_BUTTON7)  PORT_PLAYER(1)         PORT_CODE(JOYCODE_BUTTON7)
        PORT_BIT( 0x100, IP_ACTIVE_HIGH, IPT_BUTTON8)  PORT_PLAYER(1)            PORT_CODE(JOYCODE_BUTTON8)
        PORT_BIT( 0x200, IP_ACTIVE_HIGH, IPT_BUTTON9)  PORT_PLAYER(1)            PORT_CODE(JOYCODE_BUTTON9)
        PORT_BIT( 0x400, IP_ACTIVE_HIGH, IPT_BUTTON10)  PORT_PLAYER(1)            PORT_CODE(JOYCODE_BUTTON10)
        PORT_BIT( 0x800, IP_ACTIVE_HIGH, IPT_BUTTON11)  PORT_PLAYER(1)            PORT_CODE(JOYCODE_BUTTON11)
        PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_BUTTON12)  PORT_PLAYER(1)            PORT_CODE(JOYCODE_BUTTON12)
        PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_BUTTON13)  PORT_PLAYER(1)            PORT_CODE(JOYCODE_BUTTON13)
        PORT_BIT( 0x4000, IP_ACTIVE_HIGH, IPT_BUTTON14)  PORT_PLAYER(1)            PORT_CODE(JOYCODE_BUTTON14)
        PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_BUTTON15)  PORT_PLAYER(1)            PORT_CODE(JOYCODE_BUTTON15)
        PORT_BIT( 0x10000, IP_ACTIVE_HIGH, IPT_BUTTON16)  PORT_PLAYER(1)            PORT_CODE(JOYCODE_BUTTON16)


and then mangled READ8_MEMBER(apple2e_state::c080_r) some more:

Code
if ((offset<=0x70) && (offset<=0x7f))  if (m_joybuttons->read() & 0x20000) printf("m_joybuttons = %x\n",m_joybuttons->read());
if ((offset>=0x70) && (offset<=0x70)) return ((m_joybuttons->read() & 0x10) ? 0xff : 0); 
else if ((offset==0x71)) return ((m_joybuttons->read() & 0x20) ? 0xff : 0);  
else if ((offset==0x72)) return ((m_joybuttons->read() & 0x40) ? 0xff : 0); 
else if ((offset==0x73)) return ((m_joybuttons->read() & 0x80) ? 0xff : 0); 
else if ((offset==0x74)) return ((m_joybuttons->read() & 0x01) ? 0xff : 0); 
else if ((offset==0x75)) return ((m_joybuttons->read() & 0x02) ? 0xff : 0); 

etc.



returning 0xff from c0f8
[Linked Image]

returning 0xff from c0fc

(hey I hit the high c! note that there are 5 octaves, 12 tones per octave, each bar is 3 lo-res pixels wide. Screen display has 5 rows, each with 12 bars, top most row has 13 bars)
[Linked Image]

returning 0xff from c0f8 to c0fe: (do you think I can be the organist for the movie Interstellar?)
[Linked Image]

and had to map all of the buttons in the ui:
(so many buttons to map, I didn't want the side effect of pressing keys on the emulated keyboard, the numeric pad came in handy)

[Linked Image]

What would be really awesome is to get a real midi keyboard and map that to an emulated AlphaSyntauri keyboard.
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 05/09/19 05:40 PM

Neat! Schematics of the keyboard interface and keyboard are on http://www.appleii-box.de/H212_0_AppleIIalphaSyntauriPage.htm smile
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 05/10/19 12:08 PM

I think I understand how it does the velocity sensitive aspect, there are two paired addresses for each set of keys

C0F0 and it's companion at +8 bytes C0F8 (and the rest, C0F1-C0F9, C0F2-C0FA etc)

and the lower address is the lower keyswitch, the upper address is the upper keyswitch.

If I map a controller button to an address and hit both buttons simultaneously, it will make it louder with the velocity piano.

Hitting the button for the upper address only (upper keyswitch) and releasing will turn it on and leave the sound on.

Hitting the button for the lower address only (lower keyswitch) and releasing will only shut the sound off, not turn it on.



Been thinking about how to read the midi controller, it looks like I can just open the midi device and start reading bytes. Now I've gotta find a usb midi interface, I know it's around here somewhere 8-)

https://ccrma.stanford.edu/~craig/articles/linuxmidi/input/section1.html
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 05/10/19 12:45 PM

MAME has a built-in MIDI framework using the PortMIDI library. Add a MIDI IN port to your card and parse the incoming 31500 bps serial data (look at the Apple II MIDI card for details).
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 05/10/19 02:55 PM

Thanks for the suggestion, RB. I found a PDF of the Passport MIDI that I'm going to study. It tells about the PTM and the ACIA (so many acronyms 8-)

Just for fun, I was curious how many times the AlphaSyn reads the keyboard per second.

Let's throw some code into READ8_MEMBER(apple2e_state::c080_r)

Code
static int readcounter[16];
static double lastinterval;

if (machine().time().as_double() > lastinterval) {
lastinterval=machine().time().as_double()+5.0;
printf("%f  : ",lastinterval);
for (int i=0;i<16;i++) {printf("%d=%3d ",i,readcounter[i]); readcounter[i]=0;} printf("\n");
}
if ((offset>=0x70) && (offset<=0x7f)) readcounter[offset-0x70]+=1;


which produces this output:
Code
306.151057  : 0=7634 1=7634 2=7634 3=7634 4=7634 5=7634 6=7634 7=7634 8=7633 9=7633 10=7633 11=7633 12=7633 13=7633 14=7633 15=7634 
311.151146  : 0=7623 1=7623 2=7623 3=7623 4=7623 5=7623 6=7623 7=7623 8=7624 9=7624 10=7624 11=7624 12=7624 13=7624 14=7624 15=7624 
316.151269  : 0=7634 1=7634 2=7634 3=7634 4=7634 5=7634 6=7634 7=7634 8=7634 9=7634 10=7634 11=7634 12=7634 13=7634 14=7634 15=7634 


It looks like about 7600 times per 5.0 second interval or 1520 times per second.

7600/5 = 1520

5.0 / 7600 = 0.00065789473 seconds per read which is 25x faster than checking it every 1/60 of a second.

so I think it could definitely detect how quickly the switches change for velocity sensing.
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 05/10/19 05:49 PM

See if you can figure out the timing range for minimum velocity to full velocity. I can handle emulating the keyboard card with a MIDI input then.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 05/10/19 07:23 PM

Hi RB, ok let's see if we can figure out the delay:

Making a saveitem of m_testdelay:

Code
static int mykeystate=0;
static double mykeysecondtimedown;

if ((m_joybuttons->read()&0x10) && (mykeystate==0))  // state 0 = key up
{             mykeystate=1;
              mykeysecondtimedown=machine().time().as_double()+(1.0/1520)*m_testdelay;
              printf("delay = %f\n",mykeysecondtimedown-machine().time().as_double());
}
else if (!(m_joybuttons->read()&0x10))  // button up, set keystate to 0
               mykeystate=0;

if ((offset==0x70)) // c0f0 slot 7
{           if ((mykeystate==1) && (machine().time().as_double() > mykeysecondtimedown))
                return 0xff;
           else
                return 0;
}
else if ((offset==0x78)) // c0f0 slot 7
if (mykeystate==1) return 0xff; else return 0;



Code
print (emu.item(emu:items()["Apple //e/:/0/m_testdelay"]):write(0,0))   -- loudest
print (emu.item(emu:items()["Apple //e/:/0/m_testdelay"]):write(0,12))   -- quietest



using 1/1520 as a reference I was able to see that it got the quietest on 12 * 1/1520 of delay. More than 12x didn't see to make a difference. So I'd say it goes from 0 delay to 12x.


12 = delay = 0.007895



I ran the Alphaplus software and pressed the 0 key for "Velocity Piano". The other instruments(1-9) don't seem to be velocity sensitive.


If you hit CTRL+T in AlphaPlus there are adjustments that can be made to the Velocity Sensitivity.

0 = most sensitive, 7 is least

(p.67 of the alphaplus tutorial manual)

[Linked Image]
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 05/10/19 10:08 PM

Ok, there's 61 keys, and 8 bytes with 8 bits each for 64 possible keys. So the pedals must be in the high bits of bytes 5, 6 or 7.

Testing it out, it looks like the sustain pedal is byte 6, bit 7 0x80 of address C0F6 (for slot 7). I don't think it worries about the pedals being velocity sensitive, just on or off.

The portamento pedal I couldn't hear the difference (it's supposed to sweep the pitch from one note to the other) but it must be the high bit of either byte 5 or 7.
Posted By: Spk

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 05/11/19 05:51 AM

I've been playing with Apple IIgs SCSI drives in MAME .209 and they work great. I can get both cd-roms and hard-drives mounted and functioning together. And I can boot from a cd-rom on its own.

But when I try to boot directly off a SCSI hard-drive with no cd-rom, the IIgs hangs for about 60 seconds before starting to boot, after which it's all good.

So this command works:

mame64 apple2gs -sl7 scsi -hard1 D:\Mame\software\apple2gs\SCSIHD.chd -sl7 scsi -cdrom1 D:\Mame\software\apple2gs\cd.iso

And so does this:

mame64 apple2gs -sl7 scsi -cdrom1 D:\Mame\software\apple2gs\cd.iso

But this results in a temporary hang:

mame64 apple2gs -sl7 scsi -hard1 D:\Mame\software\apple2gs\SCSIHD.chd

Is there a command to set the cd-rom to null when just using a SCSI hard-drive?
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 05/11/19 10:58 AM

Indeed there is! You can actually set the 6 SCSI IDs to any combination of hard disks and CD-ROMs like so. These are only valid after "-sl7 scsi" of course.

-sl7:scsi:scsibus:1 "" (no device)
-sl7:scsi:scsibus:1 harddisk
-sl7:scsi:scsibus:2 cdrom


By default, the hard disk is SCSI ID 6 and the CD-ROM is ID 1.

I'm also gonna investigate if there's some way to speed up the timeout without removing the CD-ROM drive.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 05/11/19 08:02 PM

I keep fiddling with it and I think that maybe the lower set of addresses (C0F0-C0F8) are the upper switches and the higher addresses are the lower switches (C0F8-C0FF).

I suppose it has to be one or the other, and I think that's correct. It would make sense as the bar on screen will appear on pressing the lower switch and disappear on releasing the upper switch.

It would be good to run a little test program on a real Syntauri keyboard that would read those addresses.

just something simple like:
100 S=7:PRINT PEEK(49280+S*16+0),PEEK(49280+S*16+8):GOTO 100 REM SLOT 7 = C0F0
and then press the lowest key on the keyboard slowly.

Here's a short little program, and if you push the key down slowly enough it should show you which io location changes first:

Code
100 S=7:IO=49280+S*16  :  REM 0XC080 + SLOT*16
110 U=PEEK(IO):D=PEEK(IO+8)
120 IF U<>U0 OR D<>D0 THEN PRINT U" "D
125 U0=U:D0=D
130 GOTO 110


[Linked Image]

So when a key goes down it first hits the upper switch, and then the lower switch, the time delay being a measure of how fast you're pressing the key down.

delay = 0.026316 very quiet
delay = 0.013158 quiet
delay = 0 loudest

It doesn't seem to have many gradations in between loud and quiet. I hooked up my Sidewinder Precision Pro's throttle wheel (closest thing I've got to a paddle controller) to the joystick 2 x axis and set my delay to:

mykeysecondtimedown=machine().time().as_double()+(1.0/1520/100)*m_joy2x->read()*10; // the joystick reads between 0-255

and I can't hear too much in between the loud and the soft.

Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 05/12/19 01:39 AM

Found a 1980 brochure for AlphaSyntauri on archive.org:
https://archive.org/details/TNM_alphaSyntauri_live_music_on_Apple_computer_-__20180131_0046

I think they mean from C to C not F to F.
Wikipedia says "The modern console specification recommended by the American Guild of Organists calls for manual keyboards with sixty-one notes (five octaves, from C to c′′′′)".

[Linked Image]

[Linked Image]
Posted By: Spk

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 05/12/19 07:21 AM

Thank you very much for the SCSI command info!

I got it working and proceded to try a drive-hooked-up IIgs.

Connected:
5.25 drive: BlankProdos.dsk
3.5 drive: PrintShopGS.2mg
SCSI cdrom: GO.iso
SCSI hardrive: SCSIHD.chd (not booted)
VULCAN.GOLD hardrive: VULCAN.chd (boot)
RAM-Drive: 4MB

Everything works nicely. What a machine!

[Linked Image]

Obviously the IIgs slots (nvram) must be set accordingly. In my case I went with: Slot2: Your card, Slot7: Your card, Boot: Scan, and set a RAM-Drive to 4MB

Example command:

D:\Mame>mame64 apple2gs -ramsize 8M -flop1 D:\Mame\software\apple2gs\BlankProdos.dsk -flop3 D:\Mame\software\apple2gs\PrintShopGS.2mg -sl2 scsi -sl2:scsi:scsibus:1 cdrom -cdrom1 D:\Mame\software\apple2gs\GO.iso -sl2 scsi -sl2:scsi:scsibus:6 harddisk -hard1 D:\Mame\software\apple2gs\SCSIHD.chd -sl7 vulcangold -hard2 D:\Mame\software\apple2gs\VULCAN.chd

Cheers
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 05/12/19 11:55 AM

I hardly ever use GR mode, but happened to end up in it after breaking out of Alphaplus, and noticed that if you print text that makes the screen scroll, it will make the screen vertically shift.

100 GR:FOR I=0 TO 39:R=RND(1)*16:COLOR=R:HLIN 0,39 AT I:NEXT
110 PRINT : GOTO 110

the screen will "wiggle". It's actually kind of a neat effect.

Interestingly, whenever it wiggles, it causes a partial screen update message to display if I turn on the frameskip osd with F11.

If you vary the frameskip, you can see the numbers change on the partial screen update message. If I set frameskip to 10/10 the partial screen update numbers slow down where you can actually read them.

Also, if you put an HGR in the above program, like 105 HGR the screen glitches show up. It's interesting that the CALL -912 routine at FC70 makes some hits to softswitches.

Printing text in the print statement shows that the text window part doesn't wiggle.

If I change line 110 to 110 CALL -912 : GOTO 110 it will do the same thing.



[Linked Image]
Putting them side by side, you can see the bars have shifted vertically:
[Linked Image][Linked Image]
adding "105 HGR" to the program:
[Linked Image]

The text part is solid, it doesn't wiggle at all:
[Linked Image]
Maybe that can give some clues as to what's happening.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 05/12/19 09:38 PM

I think I know why the GR screen wiggles when the screen scrolls.

The scroll routine hits softswitches c054 and c055 which causes partial updating to occur.

I put a little printf to show me what was happening:

In the apple2e_state:screen_update routine:
Code
       else    // lo-res
                {
                        if (m_video->m_mix)
                        {
                                if ((m_video->m_dhires) && (m_video->m_80col))
                                {
                                        m_video->dlores_update(screen, bitmap, cliprect, 0, 159);
                                }
                                else
                                {       if (m_joybuttons->read() & 0x40) printf("cliprect = top bot %d,%d, left rt %d,%d  wid ht  %d,%d\n",cliprect.top(),cliprect.bottom(),cliprect.left(),cliprect.right(),cliprect.width(),cliprect.height());
                                        m_video->lores_update(screen, bitmap, cliprect, 0, 159);
                                }



Code
cliprect = top bot 0,85, left rt 0,559  wid ht  560,86
cliprect = top bot 86,86, left rt 0,254  wid ht  255,1
getting to the switch  offset=54
cliprect = top bot 86,86, left rt 254,559  wid ht  306,1
cliprect = top bot 87,191, left rt 0,559  wid ht  560,105
cliprect = top bot 0,191, left rt 0,559  wid ht  560,192
getting to the switch  offset=55
cliprect = top bot 0,19, left rt 0,559  wid ht  560,20
cliprect = top bot 20,20, left rt 0,2  wid ht  3,1
getting to the switch  offset=54
cliprect = top bot 20,20, left rt 2,366  wid ht  365,1
cliprect = top bot 20,191, left rt 0,559  wid ht  560,172
cliprect = top bot 0,191, left rt 0,559  wid ht  560,192
getting to the switch  offset=55
getting to the switch  offset=54


and when it hits the softswitch, it triggers a partial update

Code
 
              case 0x54:  // set page 1
                        if (!m_video->m_80col)
                        {
                                m_screen->update_now();   // This must trigger the partial update
                        }
                        m_page2 = false;
                        m_video->m_page2 = false;
                        auxbank_update();
                        break;

                case 0x55:  // set page 2
                        if (!m_video->m_80col)
                        {
                                m_screen->update_now();
                        }
                        m_page2 = true;
                        m_video->m_page2 = true;
                        auxbank_update();
                        break;



without the switches being hit, it will do an update all at once:
Code
cliprect = top bot 0,191, left rt 0,559  wid ht  560,192
cliprect = top bot 0,191, left rt 0,559  wid ht  560,192
cliprect = top bot 0,191, left rt 0,559  wid ht  560,192
cliprect = top bot 0,191, left rt 0,559  wid ht  560,192
cliprect = top bot 0,191, left rt 0,559  wid ht  560,192
cliprect = top bot 0,191, left rt 0,559  wid ht  560,192


So I think what's happening is that it's coming into the lores_update with a non multiple of 8 as the top of the cliprect.

If we and the row with 0xf8 we can lock it to a multiple of 8 and set our starty to row % 8. That seems to fix the wiggle (just in my limited testing.)


Code
  beginrow = (std::max)(beginrow, cliprect.top());
        endrow = (std::min)(endrow, cliprect.bottom());

        if (!(m_sysconfig & 0x03))
        {
                for (row = beginrow; row <= endrow; row += 8)
                {
                        for (col = 0; col < 40; col++)
                        {
                                /* calculate adderss */      // adderss 8-)
                                address = start_address + ((((row/8) & 0x07) << 7) | (((row/8) & 0x18) * 5 + col));

                                /* perform the lookup */
                                code = m_ram_ptr[address];

                                int starty = row % 8;   // get the low three bits

                                /* and now draw */
                                for (y = starty; y < 4; y++)   // start from starty
                                {
                                        if ((row + y) <= endrow)
                                        {
                                                for (x = 0; x < 14; x++)
                                                {
                                                        bitmap.pix16((row & 0xf8) + y, col * 14 + x) = (code >> 0) & 0x0F;    // and the row with 0xf8
                                                }
                                        }
                                }
                                for (y = starty+4; y < 8; y++)  // start from starty + 4
                                {
                                        if ((row + y) <= endrow)
                                        {
                                                for (x = 0; x < 14; x++)
                                                {
                                                        bitmap.pix16((row & 0xf8) + y, col * 14 + x) = (code >> 4) & 0x0F;
                                                }
                                        }
                                }
                        }
                }
        }




That got me to thinking, maybe the hgr_update routine is getting a little confused with getting different cliprects coming in, this modification seems to solve most of the glitching (though I did see a little speckle now and then).

(I don't completely understand the routine, so my assumptions may be wrong)

Code
void a2_video_device::hgr_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int beginrow, int endrow)
...

      for (row = beginrow; row <= endrow; row++)
        {
                for (col = begincol; col < endcol; col++)
                {
                        offset = ((((row/8) & 0x07) << 7) | (((row/8) & 0x18) * 5 + col)) | ((row & 7) << 10);
                        vram_row[1+col] = vram[offset];
                }

//              p = &bitmap.pix16(row);
//              for (col = 0; col < 40; col++)

                for (col = begincol; col < endcol; col++)     // if we wanted to limit it to the cliprect start at begincol and end at endcol
                {
                p = &bitmap.pix16(row,col*14);  // update the p pointer for the start of our row and col


                        w =     (((uint32_t) vram_row[col+0] & 0x7f) <<  0)
                                |   (((uint32_t) vram_row[col+1] & 0x7f) <<  7)
                                |   (((uint32_t) vram_row[col+2] & 0x7f) << 14);


Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 05/12/19 11:17 PM

The understanding of the routine is that French Touch and Deater both switch video modes arbitrarily in their stuff. Text, then HGR, then GR, then text on the bottom in Deater's most well-known case; French Touch went with HGR on the left and GR on the right IIRC. It's not exactly emulating that case properly but it's closer than it used to be.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 05/13/19 02:17 AM

Wow, just got done looking at the http://www.appleii-box.de website's syntauri pages and they're amazing in the level of detail and completeness. Seriously amazing, I wish I knew how to read schematics well.

[Linked Image]


Some of the disk images are completely blank. They must share a common source with the Science Fiction Writer site.


hexdump -C ../../SUPERPLUS_from_APPLEBOX.dsk
00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00023000
hexdump -C ../../DEMOSNOTES_FROM_APPLEIIBOX.dsk
00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
hexdump -C ../../EXAMPLES_FROM_APPLEBOX.dsk
00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
hexdump -C ../../ALPHAPLUS_FROM_APPLEBOX.dsk
00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|


I also found a bunch of .NIB files on another site but that's not directly loadable in mame now, any suggestions on how to convert .nibs?
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 05/13/19 02:33 AM

Does CiderPress read .nibs? Otherwise you can -sl6 diskii to use the old HLE disk controller in MAME and run .nibs.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 05/13/19 02:37 AM

Thanks, RB, I'll give it a try. I didn't know you could use the old HLE controller. Cool! So many things to learn. 8-)


edit:
I'm beginning to think the .nib images that I found aren't any good as the HLE disk ii didn't like them. Neither did nib2dsk or ciderpress 3.01, or applewin or applepc. Can .nib files be in the wrong disk order?

(just to test my sanity, the HLE disk ii seemed to work fine as it booted Microsoft Decathlon.nib)
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 05/13/19 03:27 AM

mame apple2e -listslots shows all the connectable things going on.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 05/13/19 01:36 PM

-listslots is very useful. Man, that list is impressive. So many cool things to try.

aesms Applied Engineering Super Music Synthesizer
aevm80 Applied Engineering Viewmaster 80
alfam2 ALF MC1 / Apple Music II
ap16 IBS AP-16 80 column card
ap16alt IBS AP-16 80 column card (alt. version)
applicard PCPI Applicard
arcbd Third Millenium Engineering Arcade Board
cffa2 CFFA2000 Compact Flash (65C02 firmware, www.dreher.net)
cffa202 CFFA2000 Compact Flash (6502 firmware, www.dreher.net)
corvus Corvus Flat Cable interface
diskii Apple Disk II controller
diskiing Apple Disk II NG controller (16-sector)
diskiing13 Apple Disk II NG controller (13-sector)
dx1 Decillonix DX-1
echoii Street Electronics Echo II
echoiiplus Street Electronics Echo Plus
ezcgi E-Z Color Graphics Interface
ezcgi9938 E-Z Color Graphics Interface (TMS9938)
ezcgi9958 E-Z Color Graphics Interface (TMS9958)
mcms1 Mountain Computer Music System (card 1)
mcms2 Mountain Computer Music System (card 2)
memexp Apple II Memory Expansion Card
midi 6850 MIDI card
mockingboard Sweet Micro Systems Mockingboard
mouse Apple II Mouse Card
parallel Apple Parallel Interface Card
pcxport Applied Engineering PC Transporter
phasor Applied Engineering Phasor
ramfactor Applied Engineering RamFactor
sam Don't Ask Software S.A.M.
scsi Apple II SCSI Card
softcard Microsoft SoftCard
ssbapple Multitech Industrial SSB Apple speech card
ssc Apple Super Serial Card
ssprite Synetix SuperSprite
swyft IAI SwyftCard
thclock ThunderWare ThunderClock Plus
themill Stellation Two The Mill
tm2ho Applied Engineering TimeMaster H.O.
twarp Applied Engineering TransWarp
ultraterm Videx UltraTerm (original)
ultratermenh Videx UltraTerm (enhanced //e)
videoterm Videx VideoTerm
vtc1 unknown VideoTerm clone #1
vtc2 unknown VideoTerm clone #2
zipdrive Zip Technologies ZipDrive
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 05/13/19 02:27 PM

By default the II and II Plus have lang (Apple II 16K Languard Card) in slot 0, mockingboard in slot 4, and diskiing in slot 6.

The IIe has ext80 (Apple 64K Extended 80 Column Card) in the aux slot, mockingboard in slot 4, and diskiing in slot 6. The AE RamWorks III is also supported for the aux slot, for up to 1 meg usable by AppleWorks.

The memory-expandable IIc versions have a memory card installed and a Mockingboard 4C. -ramsize values above 128K populate the memory card.

All IIes and IIcs have a No-Slot Clock.
Posted By: peter ferrie

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 05/13/19 04:35 PM

.nibs can be oversized (36 tracks instead of 35).
Golden Child, if you want to share some with me, then I can try to work out what's wrong with them.
Normally, .nibs are 232960 bytes long, and can't be in the wrong sector order - they're just steams of track data.
Posted By: Spk

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 05/23/19 08:20 AM

Is it possible to set a specific ram size in KB for the Apple IIgs?

I realise the following will work;

>mame64 apple2gsr1 -ramsize 4M

and so will;

>mame64 apple2gsr1 -ramsize 4096K

But I would like to add a 4MB RAM card to a ROM01 IIgs which has 256K onboard by default.
So I believe that works out as 4096K + 256K = 4352K

But the following isn't accepted by MAME;

>mame64 apple2gsr1 -ramsize 4352K

or am I confused?

Cheers
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 05/23/19 11:59 AM

Sorry, yes, I didn't bother to compute all of the K values for ROM 01 and ROM 03, I just went to megabytes. I will add the more detailed values in the future.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 05/28/19 06:02 PM

I finally dug my Yamaha YPG-625 out and was surprised to see that it doesn't have a "real" midi port, just a USB port, so I hooked it up to see if it would do anything under Ubuntu. It came up as /dev/midi2 so I started up lua5.3 and was able to read raw midi data.
Code

a=io.open("/dev/midi2","r")
for j=1,32 do b=a:read(500) t=os.time() for i =1,#b do print (t,j,i,string.format("%x",b:byte(i))) end end

There's a whole bunch of MIDI System Real-Time Messages with 0xf8 and 0xfe so if I don't print those I can see the notes:

for j=1,32 do b=a:read(200) t=os.time() for i =1,#b do d=b:byte(i) if not ((d == 0xf8) or (d==0xfe)) then print (t,j,i,string.format("%x",b:byte(i))) end end end

1559056749	3	186	90
1559056749	3	187	3c
1559056749	3	188	53
1559056749	3	194	90
1559056749	3	195	3c
1559056749	3	196	0




So I thought I'd see if that passport midi would be able to use the keyboard:
Code
./mame64 apple2e -listmidi

MIDI input ports:
Midi Through Port-0 (default)
Portable Grand MIDI 1 

MIDI output ports:
Midi Through Port-0 (default)
Portable Grand MIDI 1 


./mame64 apple2e -sl2 midi -midiin  "Portable Grand MIDI 1" -verbose -flop1 ../../Passport\ designs\ -\ Master\ tracks\ v1.8.dsk 
./mame64 apple2e -sl2 midi -midiin  "Portable Grand MIDI 1" -verbose -flop1 ../../Passport\ designs\ -\ MIDI8\ plus\ v1.2.dsk 

and the software seems to work to record a few notes (first I have to set one of the tracks to REC) but then crashes...
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 05/30/19 03:15 AM

Running the Master Tracks software with the debugger shows that it's still reading the midi data but the program seems to stop updating the screen and responding to key strokes:

./mame64 apple2e -sl2 midi -verbose -flop1 ../../Passport\ designs\ -\ Master\ tracks\ v1.8.dsk -snapsize 560x384 -debug -midiin "Portable Grand MIDI 1" -midiout "Portable Grand MIDI 1"


I thought I'd see what registers were being read.

Code
wp c0a0,10,rw,1,{printf "pc=%x wpaddr=%x wpdata=%x a=%x",pc,wpaddr,wpdata,a; g}

Error in command: {printf "pc=%x wpaddr=%x wpdata=%x a=%x",pc,wpaddr,wpdata,a; g}

                  ^unknown command


So what was wrong with my wpset debugger command? An extra space at the end of the line... It says unknown command but doesn't tell you why exactly.



Master Tracks freezes up within just a few seconds, but hitting CTRL+F12 for reset brings it back, and if you set the track to play (F for format, then P for play) and space to start playback, it will play the first few notes it recorded before it froze up.

[Linked Image][Linked Image]


[Linked Image]


Are there any other midi programs for the Apple IIe?


Just for fun, I thought I'd type in the little Applesoft Demo program for the Passport Midi Card from the manual and fix some of the mistakes:


Code
emu.keypost([[
100 REM ------------------------------
110 REM - MIDI DATA PLAYBACK DEMO    -
120 REM -APPLESOFT BASIC-
130 REM -(C)1984 PASSPORT DESIGNS INC-
140 REM -ALL RIGHTS RESERVED-
150 REM --
160 REM - VERSIOM 1.19/6/84 -
170 REM -PROGRAMMER: BRUCE BETHKE-
200 REM -----------------------------
210 REM
220 GOSUB 2000: REM DRAW SCREEN
230 GOSUB 3000: REM DEFINE VARIABLES
235 GOTO 1000: REM BEGIN PLAYBACK
240 REM
250 REM
260 REM -----------------------------
270 REM -SUBROUTINES-
280 REM -----------------------------
290 REM
300 REM -- WAIT FOR ACIA TO CLEAR ---
310 FOR TIM = 1 TO 4: NEXT : RETURN
320 REM
330 REM
400 REM —- WAIT FOR NOTES DURATION -—
410 FOR TIM = 1 TO 4: NEXT : RETURN
420 REM
430 REM
500 REM ------TURN OFF OLD NOTE ------
510 POKE AD,OFFKY: GOSUB 310
520 POKE AD,OLDKY: GOSUB 310
530 POKE AD,VOFF: GOSUB 310
540 RETURN
550 REM
560 REM
600 REM ----- TURN ON NEW NOTE -----
610 POKE AD,KEYDN: GOSUB 310
620 POKE AD,NEXKY: GOSUB 310
630 POKE AD,VMAX: GOSUB 310
640 RETURN
650 REM
660 REM
1000 REM --------------------------
1010 REM -BEGIN PLAYBACK—
1020 REM --------------------------
1030 REM
1040 FOR N = 1 TO 24
1050 READ NEXKY
1060 NEXKY = NEXKY + T: REM TRANSPOSE
1070 GOSUB 510: REM TURN OFF PREVIOUS NOTE
1080 GOSUB 610: REM PLAY CURRENT NOTE
1090 GOSUB 410: REM WAIT ONE NOTE’S DURATION
1100 OLDKY = NEXKY: REM CURRENT NOTE BECOMES PREVIOUS NOTE
1110 NEXT N: REM GET NEXT NOTE
1120 REM
1130 REM ----------------------------
1140 REM - AT END OF DATA, TURN OFF -
1150 REM - LAST NOTE PLAYED-
1160 REM ----------------------------
1175 GOSUB 410
1180 POKE AD,OFFKY: GOSUB 310
1190 POKE AD,OLDKY: GOSUB 310
1195 POKE AD,VOFF: GOSUB 310
1197 REM
1200 REM ----------------------------
1210 REM - EXIT / TRANSPOSE PROMPT -
1220 REM ----------------------------
1240 VTAB 12: HTAB 10
1250 PRINT “CONTINUE (Y/N)";: INPUT A$
1260 IF (A$ = “Y” OR A$ = "y") THEN 1300
1270 HOME : END
1290 REM
1300 REM ---- CONTINUE PLAYBACK ---
1310 VTAB 14: HTAB 3
1320 PRINT “TRANSPOSE VALUE (+/- 0...36)”;: INPUT A$
1330 T = VAL (A$)
1340 IF (T > = — 36) AND (T < = 36) THEN 1400
1350 HOME : GOSUB 2000: GOTO 1310
1360 REM
1400 RESTORE : GOTO 1040
1410 REM =======================
1500 REM
1900 REM
2000 REM -------------------------
2010 REM -DRAW SCREEN-
2020 REM -------------------------
2040 HOME : PRINT CHR$ (7): REM BEEP!
2050 VTAB 1: HTAB 7: INVERSE
2060 PRINT “MIDI PLAYBACK DEMONSTRATION”
2070 NORMAL
2080 VTAB 3: HTAB 5: INVERSE
2090 PRINT “(C) 1984 PASSPORT DESIGNS, INC.”
2100 NORMAL
2110 VTAB 5: HTAB 5: PRINT”**********************************"
2120 RETURN
2130 REM
2140 REM
3000 REM --------------------------
3010 REM -DEFINE VARIABLES—
3020 REM --------------------------
3030 REM
3040 REM ACIA CONTROL AND DATA REGISTERS
3050 REM WITH MIDI CARD IN SLOT#2
3060 AC = 49320: REM ACIA CONTROL
3070 AD = 49321: REM ACIA DATA
3080 OFFKY = 128: REM KEY OFF STATUS BYTE
3090 KEYDN = 144: REM KEY ON STATUS BYTE
3100 VOFF = 0: REM KEY VELOCITY 0
3110 VMAX = 127: REM KEY VELOCITY = 127
3120 OLDKY = 0: REM “OLD” KEY ID NUMBER
3130 NEXKY = 0: REM “NEW” KEY ID NUMBER
3140 DUR = 50 : REM NOTE DURATION
3150 T = 0    : REM TRANSPOSITION VALUE
3160 A$ = ““  : REM INPUT STRING VARIABLE
3180 REM
3200 REM ----------------------------
3210 REM -RESET & CONFIGURE ACIA-
3220 REM ----------------------------
3230 REM
3240 POKE AC,19: POKE AC,17
3250 RETURN
3300 REM
3400 REM
4000 REM ----------------------------
4010 REM - KEY ID (NOTE) DATA TABLE -
4020 REM ----------------------------
4030 REM
4040 DATA 60,61,62,63,64,65
4050 DATA 66,67,68,69,70,71
4060 DATA 72,71,69,68,67,66
4070 DATA 65,64,63,62,61,60
4080 REM
4090 REM
]])
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 05/30/19 03:44 PM

In the comments for a2midi.c, it says that Yamaha's card is on of the apple 2 cards. "Apple II 6850 MIDI card, as made by Passport, Yamaha, and others."

So let's try the RittorMusic Midi/4 sequencer, which is supposed to work with the Yamaha Music Interface.

./mame64 apple2p -sl2 midi -verbose -flop1 ../../RittorMusic\ MIDI4\ Sequencer\ -\ Side\ 1.dsk -debug -midiout "Portable Grand MIDI 1" -midiin "Portable Grand MIDI 1"


This looks very familiar:

[Linked Image][Linked Image]

but it seems to hit different addresses to get the midi data, so it just freezes if you try to play or record.


Interestingly, with the Passport Midi Mastertracks, the midi card is accessed through interrupts, and you can watch the data getting put into memory at $800-8ff (circular buffer), even after the software has frozen up. It seems to store the song data at $3000.
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 05/30/19 05:46 PM

A lot of these programs are hardcoded in terms of what slot they want the MIDI card in.

What's the 6502 doing when the Passport software freezes? It's not any kind of total crash if it's still fielding interrupts.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 05/31/19 01:33 PM

I'm not sure exactly what the code is doing, but it looks like it stops getting some of the interrupts.

There's an interrupt routine at 2572 which will do a lda $c0a8 and if there isn't data to get it will do things like update the clock. When the clock freezes it must not be getting these interrupts, and once that happens then it only gets interrupts when a midi keyboard key is pressed, and the interrupt routine processes the key data instead.



./mame64 apple2p -sl2 midi -verbose -flop1 ../../Passport\ designs\ -\ Master\ tracks\ v1.8.dsk -debug -midiout "Portable Grand MIDI 1" -midiin "Portable Grand MIDI 1"

setting a breakpoint on the clock address "bp 96,1,w"

Code
history

2676: lda $96                            $96 is the lowest part of the clock, goes from 0-23 and then cycles back to 0
2674: inc $96
2671: sta $c0a8
266F: lda #$b1
266D: inc $04
266B: sta ($04), y
2669: lda #$f8
2667: sta $a0
2665: lda $a1
2662: sta $c0ae
2660: bne $26d6
265E: dec $a0
265C: bmi $26d6
265A: bit $af
264E: bpl $265a
264C: bit $88
2608: bmi $264c
2606: bit $92
2604: beq $264c
2602: cmp $00
2600: lda $08
25FE: ldy #$00
25FD: cli
25FA: lda $c0a4
25F7: lda $c0a1
257E: jmp $25f7             so it jumps to 25f7
257C: bmi $2581            no data to get
2579: lda $c0a8                    
2578: pha
2577: tya
2576: pha
2575: txa
2574: pha
2572: lda <ACC
BFFC: jmp ($03fe)              3FE points to 2572
BFFA: sta <ACC                   interrupt gets called here, FFFE vector points to BFFA



If I don't touch any of the keys, the clock will run fine. Then if I start playing a bunch of keys it stops the clock.

When the clock stops you can manually change location $96 and the screen will update, so the main display loop is running, but it isn't getting the constant interrupts that would make the clock update.

Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 05/31/19 02:33 PM

Hmm. I don't see anything obviously wrong with the card device (although it should use one of those newfangled input mergers for the two chips' IRQs instead of rolling its own). Might be a bug in the 6840.
Posted By: Just Desserts

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 05/31/19 03:07 PM

That wouldn't really shock me. The 6840 has issues with the Fairlight CMI IIx driver as well.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 05/31/19 05:57 PM

I thought I'd chuck some LOG statements into 6840ptm.cpp and uncomment #define VERBOSE 1


Code
void ptm6840_device::update_interrupts()
{
        int new_state = ((m_status_reg & TIMER1_IRQ) && (m_control_reg[0] & INTERRUPT_EN)) ||
                                        ((m_status_reg & TIMER2_IRQ) && (m_control_reg[1] & INTERRUPT_EN)) ||
                                        ((m_status_reg & TIMER3_IRQ) && (m_control_reg[2] & INTERRUPT_EN));

        LOG("UPDATEINTER newstate=%d time=%f %d\n",new_state, machine().time().as_double(), m_irq);

        if (new_state != m_irq)
        {
                m_irq = new_state;

                if (m_irq)
                {
                        m_status_reg |= ANY_IRQ;
                }
                else
                {
                        m_status_reg &= ~ANY_IRQ;
                }

                m_irq_cb(m_irq);

                LOG("INTERRUPTS AFTER M_IRQ_CB: m_irq_cb time=%f %d\n", machine().time().as_double(), m_irq);

        }
}


So after it loads up and starts recording there's interrupts being generated continuously,

Code

[:sl2:midi:midi_ptm] UPDATEINTER newstate=0 time=30.329903 0
[:sl2:midi:midi_ptm] 30.329903: **ptm6840 t1 output 0 **
[:sl2:midi:midi_ptm] Timer #1 internal clock freq 1021800.000000 
[:sl2:midi:midi_ptm] Timer #1 reload_count: clock = 1021800.000000  count = 332
[:sl2:midi:midi_ptm] Timer #1 reload_count: output = 0.000325
[:sl2:midi:midi_ptm] **ptm6840 t2 timeout**
[:sl2:midi:midi_ptm] UPDATEINTER newstate=1 time=30.330194 0
[:sl2:midi:midi_ptm] INTERRUPTS AFTER M_IRQ_CB: m_irq_cb time=30.330194 1
[:sl2:midi:midi_ptm] 30.330194: **ptm6840 t2 output 0 **
[:sl2:midi:midi_ptm] Timer #2 internal clock freq 1021800.000000 
[:sl2:midi:midi_ptm] Timer #2 reload_count: clock = 1021800.000000  count = 10624
[:sl2:midi:midi_ptm] Timer #2 reload_count: output = 0.010397
[:sl2:midi:midi_ptm] **ptm6840 t1 timeout**
[:sl2:midi:midi_ptm] UPDATEINTER[:sl2:midi:midi_ptm] Timer #1 reload_count: output = 0.000325
[:sl2:midi:midi_ptm] **ptm6840 t1 timeout** newstate=1 time=30.330228 1
[:sl2:midi:midi_ptm] 30.330228: **ptm6840 t1 output 1 **
[:sl2:midi:midi_ptm] Timer #1 internal clock freq 1021800.000000 
[:sl2:midi:midi_ptm] Timer #1 reload_count: clock = 1021800.000000  count = 332
[:sl2:midi:midi_ptm] Timer #1 reload_count: output = 0.000325
[:sl2:midi:midi_ptm] ':maincpu' (25F7): Status read = 0087
[:sl2:midi:midi_ptm] Timer #2 internal clock freq 1021800.000000 
[:sl2:midi:midi_ptm] Timer #2 read counter: 10574
[:sl2:midi:midi_ptm] UPDATEINTER newstate=0 time=30.330242 1
[:sl2:midi:midi_ptm] INTERRUPTS AFTER M_IRQ_CB: m_irq_cb time=30.330242 0
[:sl2:midi:midi_ptm] ':maincpu' (25FA): Counter 2 read = 0029
[:sl2:midi:midi_ptm] **ptm6840 t1 timeout**
[:sl2:midi:midi_ptm] UPDATEINTER newstate=0 time=30.330553 0
[:sl2:midi:midi_ptm] 30.330553: **ptm6840 t1 output 0 **
[:sl2:midi:midi_ptm] Timer #1 internal clock freq 1021800.000000 
[:sl2:midi:midi_ptm] Timer #1 reload_count: clock = 1021800.000000  count = 332
[:sl2:midi:midi_ptm] Timer #1 reload_count: output = 0.000325
[:sl2:midi:midi_ptm] **ptm6840 t1 timeout**


and then at some point, after typing a bunch of midi keys, it will stop generating interrupts.

Code
[:sl2:midi:midi_ptm] UPDATEINTER newstate=0 time=30.350698 0
[:sl2:midi:midi_ptm] 30.350698: **ptm6840 t1 output 0 **
[:sl2:midi:midi_ptm] Timer #1 internal clock freq 1021800.000000 
[:sl2:midi:midi_ptm] Timer #1 reload_count: clock = 1021800.000000  count = 332
[:sl2:midi:midi_ptm] Timer #1 reload_count: output = 0.000325
[:sl2:midi:midi_ptm] **ptm6840 t2 timeout**
[:sl2:midi:midi_ptm] UPDATEINTER newstate=1 time=30.350988 0

last interrupt gets generated here at 30.350988 and newstate seems to get stuck at 1 so it never toggles the 

[:sl2:midi:midi_ptm] INTERRUPTS AFTER M_IRQ_CB: m_irq_cb time=30.350988 1
[:sl2:midi:midi_ptm] 30.350988: **ptm6840 t2 output 0 **
[:sl2:midi:midi_ptm] Timer #2 internal clock freq 1021800.000000 
[:sl2:midi:midi_ptm] Timer #2 reload_count: clock = 1021800.000000  count = 10624
[:sl2:midi:midi_ptm] Timer #2 reload_count: output = 0.010397
[:sl2:midi:midi_ptm] **ptm6840 t1 timeout**
[:sl2:midi:midi_ptm] UPDATEINTER newstate=1 time=30.351023 1
[:sl2:midi:midi_ptm] 30.351023: **ptm6840 t1 output 1 **
[:sl2:midi:midi_ptm] Timer #1 internal clock freq 1021800.000000 
[:sl2:midi:midi_ptm] Timer #1 reload_count: clock = 1021800.000000  count = 332
[:sl2:midi:midi_ptm] Timer #1 reload_count: output = 0.000325
[:sl2:midi:midi_ptm] **ptm6840 t1 timeout**
[:sl2:midi:midi_ptm] UPDATEINTER newstate=1 time=30.351348 1


The last time it changes the Control registers in the log is at time=20.41 seconds, setting control reg #2 to d3 which does have interrupts enabled (bit 6).

Code
[:sl2:midi:midi_ptm] Timer #1 reload_count: output = 0.000101
[:sl2:midi:midi_ptm] Control register #2 selected
[:sl2:midi:midi_ptm] operation mode   = 010 continuous mode
[:sl2:midi:midi_ptm] value            = 00D3
[:sl2:midi:midi_ptm] t3divisor        = 1
[:sl2:midi:midi_ptm] **ptm6840 t1 timeout**
[:sl2:midi:midi_ptm] UPDATEINTER newstate=0 time=20.411291 0
[:sl2:midi:midi_ptm] 20.411291: **ptm6840 t1 output 0 **
[:sl2:midi:midi_ptm] Timer #1 internal clock freq 1021800.000000 
[:sl2:midi:midi_ptm] Timer #1 reload_count: clock = 1021800.000000  count = 103
[:sl2:midi:midi_ptm] Timer #1 reload_count: output = 0.000101
[:sl2:midi:midi_ptm] **ptm6840 t1 timeout**
[:sl2:midi:midi_ptm] UPDATEINTER newstate=0 time=20.411392 0
[:sl2:midi:midi_ptm] 20.411392: **ptm6840 t1 output 1 **
[:sl2:midi:midi_ptm] Timer #1 internal clock freq 1021800.000000 
[:sl2:midi:midi_ptm] Timer #1 reload_count: clock = 1021800.000000  count = 103
[:sl2:midi:midi_ptm] Timer #1 reload_count: output = 0.000101
[:sl2:midi:midi_ptm] msbbuf1 = 01
[:sl2:midi:midi_ptm] UPDATEINTER newstate=0 time=20.411446 0
[:sl2:midi:midi_ptm] ':maincpu' (23AB): Counter #1 latch = 014B
[:sl2:midi:midi_ptm] msbbuf2 = 29
[:sl2:midi:midi_ptm] UPDATEINTER newstate=0 time=20.411462 0
[:sl2:midi:midi_ptm] ':maincpu' (23B6): Counter #2 latch = 297F
[:sl2:midi:midi_ptm] Control register #1 selected
[:sl2:midi:midi_ptm] operation mode   = 010 continuous mode
[:sl2:midi:midi_ptm] value            = 0092
[:sl2:midi:midi_ptm] t3divisor        = 1
[:sl2:midi:midi_ptm] **ptm6840 t1 timeout**



Adding a line to print the status register it gets stuck at 87 and stays there:
Code
        LOG("UPDATEINTER newstate=%d time=%f %d\n",new_state, machine().time().as_double(), m_irq);
        LOG("UPDATEINTER time=%f statusreg=%x\n",machine().time().as_double(), m_status_reg);


[:sl2:midi:midi_ptm] UPDATEINTER time=23.440963 statusreg=5
[:sl2:midi:midi_ptm] 23.440963: **ptm6840 t1 output 1 **
[:sl2:midi:midi_ptm] Timer #1 internal clock freq 1021800.000000 
[:sl2:midi:midi_ptm] Timer #1 reload_count: clock = 1021800.000000  count = 332
[:sl2:midi:midi_ptm] Timer #1 reload_count: output = 0.000325
[:sl2:midi:midi_ptm] **ptm6840 t2 timeout**
[:sl2:midi:midi_ptm] UPDATEINTER newstate=1 time=23.440966 0
[:sl2:midi:midi_ptm] UPDATEINTER time=23.440966 statusreg=7
[:sl2:midi:midi_ptm] INTERRUPTS AFTER M_IRQ_CB: m_irq_cb time=23.440966 1
[:sl2:midi:midi_ptm] 23.440966: **ptm6840 t2 output 0 **
[:sl2:midi:midi_ptm] Timer #2 internal clock freq 1021800.000000 
[:sl2:midi:midi_ptm] Timer #2 reload_count: clock = 1021800.000000  count = 10624
[:sl2:midi:midi_ptm] Timer #2 reload_count: output = 0.010397
[:sl2:midi:midi_ptm] **ptm6840 t1 timeout**
[:sl2:midi:midi_ptm] UPDATEINTER newstate=1 time=23.441288 1
[:sl2:midi:midi_ptm] UPDATEINTER time=23.441288 statusreg=87
[:sl2:midi:midi_ptm] 23.441288: **ptm6840 t1 output 0 **
[:sl2:midi:midi_ptm] Timer #1 internal clock freq 1021800.000000 
[:sl2:midi:midi_ptm] Timer #1 reload_count: clock = 1021800.000000  count = 332
[:sl2:midi:midi_ptm] Timer #1 reload_count: output = 0.000325




edit:

and if I go into the Debug Memory View and locate the MC6840 PTM/:sl2:midi:midi_ptm/0/m_status_reg and after it gets stuck,
manually set the low nibble to 0, it gets unstuck.

I can then play a few more keys before it gets stuck again, and setting the low nibble to 0 gets it unstuck again.


Also, another way to unstick it is to set the MC6840 PTM/:sl2:midi:midi_ptm/0/m_irq to 0 (gets stuck on 1)



edit:

doing some hacky mangling of ptm6840_device:timeout() stops the freezing, but playback is erratic, going superfast at times 8-)

Code
void ptm6840_device::timeout(int idx)
{
        LOG("**ptm6840 t%d timeout**\n", idx + 1);
        LOG("TIMEOUT time=%f statusreg=%x\n",machine().time().as_double(), m_status_reg);

        // Set the interrupt flag
        m_status_reg |= (1 << idx);
        m_status_read_since_int &= ~(1 << idx);
        update_interrupts();
        m_status_reg &= ~(1 << idx);    //  if I clear the status reg bits here it seems to stop the freezing



edit:

also noticed that the routine for m_ptm_irq in src/devices/bus/a2midi.cpp had a copy paste typo:


Code
WRITE_LINE_MEMBER( a2bus_midi_device::ptm_irq_w )
{
        m_ptm_irq = state ? true : false;     // should be m_ptm_irq?  ( I suppose it doesn't make too much difference )

        if (m_acia_irq || m_ptm_irq)
        {
                raise_slot_irq();
        }
        else
        {
                lower_slot_irq();
        }
}
Posted By: Spk

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 06/01/19 08:47 AM

Hi RB

I've sent an apparent Apple IIe Vulcan ROM file to messdrivers. I found it on the Net. Not sure if it's real or useful. Just FYI in case the email was junked.

Cheers
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 06/01/19 11:41 AM

Hi Spk! I haven't received the email and it's not in my Spam folder so I'm not sure what's going on.
Posted By: Spk

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 06/01/19 09:18 PM

Mmm that is odd. I've resent. If it still doesn't go through I'll PM you a link
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 06/01/19 09:19 PM

Got the resend, thanks!
Posted By: Firehawke

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 06/01/19 10:01 PM

Just going to post a brief status report here on my Apple II softlist work:

I had completely misunderstood significant things about softlists, so some side work I'd been doing for 3.5" disks was not really necessary and was backed out before it went beyond initial testing. Other than the embarrassment, it's not a bad situation as it means the end result I'm working towards will be a lot cleaner.

Honestly, part of the problem is that I've only learned what I need to know about getting these right by trial and error. I've been refining my tools and processes as I go, but some of the early data my first-generation tools generated wasn't great and requires some hand-massaging before I merge it in. This slows the process because I'm double checking my work for each entry as I go-- I'm too deep in to just throw out the first pass work and start over.

Nevertheless, we're getting there.
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 06/01/19 11:25 PM

Sounds great. Keep up the good work!
Posted By: Vas Crabb

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 06/02/19 03:37 AM

Originally Posted by Firehawke
Just going to post a brief status report here on my Apple II softlist work:

You're doing great work, no-one's unhappy with the speed of progress. That's the way things go with these kinds of tools - you try and automate part of your workflow, find out where it's lacking, and tune it up. You don't know which parts will need tuning until you try to use it for real.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 06/02/19 02:33 PM

More silly fun:

You midi guys would know all of this stuff, but I just discovered the virtual midi piano keyboard (vmpk) and it's pretty cool if you don't have a real midi keyboard handy.

./mame64 apple2p -sl2 midi -verbose -flop1 ../../Passport\ designs\ -\ Master\ tracks\ v1.8.dsk -snapsize 560x384 -debug -midiout "VMPK Input" -midiin "VMPK Output" -log

I also installed fluidsynth for linux so I can get some midi sounds too.

Now I get a bunch more items when I listmidi:

Code
./mame64 apple2e -listmidi

MIDI input ports:
Midi Through Port-0 (default)
Portable Grand MIDI 1 
VMPK Output 

MIDI output ports:
Midi Through Port-0 (default)
Portable Grand MIDI 1 
Synth input port (20027:0) 
VMPK Input 
qjackctl 


./mame64 apple2p -sl2 midi -verbose -flop1 ../../Passport\ designs\ -\ Master\ tracks\ v1.8.dsk -snapsize 560x384 -debug -midiin "Virtual Keyboard" -log -midiout "Synth input port (20027:0)"

On ubuntu, just "sudo apt install vmpk fluidsynth" and get a soundfont2 from the net (I got the General User one)

[Linked Image]
Posted By: Firehawke

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 06/09/19 01:21 AM

[Linked Image]
This is a glaring omission that has now been corrected. I'll PR this addition tonight.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 06/23/19 11:51 AM

Hi Arbee,

I was looking at how mame hooks up to the midi with portmidi src/osd/modules/midi/portmidi.cpp and it seems that it doesn't pass the 1 byte messages through like F8 (timing clock).


Code

int osd_midi_device_pm::read(uint8_t *pOut)

...

                                case 0xf:   // system common
                                        switch (status & 0xf)
                                        {
                                                case 0: // System Exclusive
                                                {
                                                        *pOut++ = status;   // this should be OK: the shortest legal sysex is F0 tt dd F7, I believe
                                                        *pOut++ = (rx_evBuf[msg].message>>8) & 0xff;
                                                        *pOut++ = (rx_evBuf[msg].message>>16) & 0xff;
                                                        uint8_t last = *pOut++ = (rx_evBuf[msg].message>>24) & 0xff;
                                                        bytesOut += 4;
                                                        rx_sysex = (last != MIDI_EOX);
                                                        break;
                                                }

                                                case 7: // End of System Exclusive
                                                        *pOut++ = status;
                                                        bytesOut += 1;
                                                        rx_sysex = false;
                                                        break;

                                                case 2: // song pos
                                                case 3: // song select
                                                        *pOut++ = status;
                                                        *pOut++ = Pm_MessageData1(rx_evBuf[msg].message);
                                                        *pOut++ = Pm_MessageData2(rx_evBuf[msg].message);
                                                        bytesOut += 3;
                                                        break;

                                                default:    // all other defined Fx messages are 1 byte

                                                        *pOut++ = status;             // shouldn't we pass the 1 byte messages along?
                                                        bytesOut += 1;
                                                        break;
                                        }





Also if I read it correctly, 0xF3 (song select) should only supply 2 bytes (status + 1 data byte).


http://www.personal.kent.edu/~sbirch/Music_Production/MP-II/MIDI/midi_protocol.htm
http://www.personal.kent.edu/~sbirch/Music_Production/MP-II/MIDI/midi_system_common_messages.htm
http://www.personal.kent.edu/~sbirch/Music_Production/MP-II/MIDI/midi_system_real.htm
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 06/23/19 12:11 PM

Thanks! You missed a detail or two but it's fixed in GitHub top-of-tree now smile
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 06/23/19 05:24 PM

Originally Posted by R. Belmont
Thanks! You missed a detail or two but it's fixed in GitHub top-of-tree now smile



Thanks, RB! I always miss those details 8-)
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/04/19 11:12 AM

I think I've finally figured out why MasterTracks 1.8 was freezing after typing some midi keys, it's actually very subtle.

After setting up a new ubuntu system on a new laptop, I thought I'd download a fresh mame for experiments/mangling.

I totally forgot all about the typo in a2midi.cpp after a month or two of being busy with other stuff. (Yeah, I suppose I should read my own posts 8-)

(I mistakenly thought that this typo didn't make a difference)

https://github.com/mamedev/mame/blob/master/src/devices/bus/a2bus/a2midi.cpp

Code
WRITE_LINE_MEMBER( a2bus_midi_device::acia_irq_w )
{
	m_acia_irq = state ? true : false;

	if (m_acia_irq || m_ptm_irq)
	{
		raise_slot_irq();
	}
	else
	{
		lower_slot_irq();
	}
}

WRITE_LINE_MEMBER( a2bus_midi_device::ptm_irq_w )
{
	m_acia_irq = state ? true : false;                // should be m_ptm_irq

	if (m_acia_irq || m_ptm_irq)
	{
		raise_slot_irq();
	}
	else
	{
		lower_slot_irq();
	}
}



So how does the bug manifest itself?

You've got the 6840ptm and the 6850 acia both modifying the variable m_acia_irq.

The 6502 interrupt routine at $2572 (vector stored at $3FE/3FF) will first check the midi to see if there's data, if not the routine will check the timer and reset it by reading c0a1 and c0a4 which will clear the timer interrupt.

The problem comes in when you have midi data that comes in generating an IRQ while there's a timer IRQ as well. The 6840 routine update_interrupts() will only modify its IRQ variable on transitions from 0 to 1 or 1 to 0, so once it calls a2bus_midi_device::ptm_irq_w (true) and setting m_acia_irq to true it won't call it again.

But our interrupt routine processes the midi byte first, clearing the midi interrupt by reading $c0a9 and it calls a2bus_midi_device::acia_irq_w(false) which will set m_acia_irq to false.

This ends up dropping all interrupts for the timer so it will never update the clock.

It will keep processing the midi acia interrupts, but no timer processing will happen after this occurs.

I ended up disassembling a bunch of master tracks to figure out how it worked. I think I understand quite a bit more about the 6840 and the 6850 now. (the 6840 data sheet is really difficult to figure out)
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/05/19 01:43 PM

Some more dumb fun seeing if I can read midi data from the 6850 ACIA with lua. (with a midi card in slot 2 -sl2 midi)

If I keep polling 0xc0a8 every 1/31250*10 seconds (1 second divided by the midi clock times 10 bits) I should be able to see all of the data bytes since one byte will arrive at this interval.

It's useful to me to see just exactly how the device behaves.

We'll just read 18 bytes and then exit the coroutine.

Code

mem=manager:machine().devices[":maincpu"].spaces["program"]
mem:write_u8(0xc0a8,19)  -- acia master reset CR0=1, CR1=1
mem:write_u8(0xc0a8,17)  -- set divider to 16 CR0=1, CR1=0
co1 = function() for i=1,18 do 
  status=mem:read_u8(0xc0a8)
  while (status&1)==0 do 
     emu.wait(1/31250*10) 
     status=mem:read_u8(0xc0a8) 
  end 
  data=mem:read_u8(0xc0a9) 
  if (status&0x20)~=0 then print ("OVERRUN ") end 
  print(string.format("status=%x  data=%x",status,data)) 
  emu.wait(1/31250*10) 
end end
myco1=coroutine.create(co1) ok,errormsg=coroutine.resume(myco1)



and you get something like this as output:

Code
[MAME]> myco1=coroutine.create(co1) ok,errormsg=coroutine.resume(myco1)
status=3  data=45
OVERRUN 
status=23  data=45
[MAME]> status=3  data=90
status=3  data=49
status=3  data=44
status=3  data=90
status=3  data=49
status=3  data=0
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/05/19 01:54 PM

Neat. I've started working on creating a "picture" image device so we can emulate the ComputerEyes for real now that the gameio is a slot. (I already added the Sirius Joyport so you can get more precise control of a lot of classic A2 games that support it).
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/05/19 03:18 PM

Hi Arbee,

that sounds awesome! I gotta try the Joyport now. 8-)
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/06/19 05:07 AM

Hi Arbee,

I thought I'd give the sirius joyport a spin with my favorite game ever Stellar 7 and it was only letting me go left and right, but not up and down.

Diving into joyport.cpp it looks like we just need to swap an_0 with an_1 and vice versa, super simple fix.

an_0 selecting the player
and an_1 choosing which direction we're reading

Code
git diff
diff --git a/src/devices/bus/a2gameio/joyport.cpp b/src/devices/bus/a2gameio/joyport.cpp
index cfc8ef1246..9ed0579644 100644
--- a/src/devices/bus/a2gameio/joyport.cpp
+++ b/src/devices/bus/a2gameio/joyport.cpp
@@ -76,23 +76,23 @@ void apple2_joyport_device::device_start()
 
 READ_LINE_MEMBER(apple2_joyport_device::sw0_r)
 {
-       u8 port_read = m_an1 ? m_player2->read() : m_player1->read();
+       u8 port_read = m_an0 ? m_player2->read() : m_player1->read();
 
        return BIT(port_read, 4);
 }
 
 READ_LINE_MEMBER(apple2_joyport_device::sw1_r)
 {
-       u8 port_read = m_an1 ? m_player2->read() : m_player1->read();
+       u8 port_read = m_an0 ? m_player2->read() : m_player1->read();
 
-       return m_an0 ? BIT(port_read, 0) : BIT(port_read, 3);
+       return m_an1 ? BIT(port_read, 0) : BIT(port_read, 3);
 }
 
 READ_LINE_MEMBER(apple2_joyport_device::sw2_r)
 {
-       u8 port_read = m_an1 ? m_player2->read() : m_player1->read();
+       u8 port_read = m_an0 ? m_player2->read() : m_player1->read();
 
-       return m_an0 ? BIT(port_read, 2) : BIT(port_read, 1);
+       return m_an1 ? BIT(port_read, 2) : BIT(port_read, 1);
 }
 
 WRITE_LINE_MEMBER(apple2_joyport_device::an0_w)
(END)
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/08/19 09:51 AM

I thought I'd try to fiddle with the Apple /// and see how it does its silentype. Man, the Apple /// is really an alien experience to someone who has only known DOS 3.3 and Applesoft.

There's a disk image of Apple3_Diskware_SilentypeIIIDriver_681-0009-a.dsk which has a basic demo program.

Doing a directory of floppy 2 you have to type "CAT .D2" or once you know the disk name is SITYPE, you can type "CAT /SITYPE".

Then to set the prefix, use the business basic prompt to

PRINT PREFIX$
PREFIX$ = "/SITYPE/"
LOAD DEMO
LIST

(CTRL+numpad 7 will pause/unpause listing) (good old CTRL+S and Q doesn't work)

RUN

at which point it freezes.

[Linked Image from i.imgur.com]
[Linked Image from i.imgur.com]
[Linked Image from i.imgur.com]

Business basic is sure different, with all of these commands like INVOKE and PERFORM which will load assembly language modules and execute routines in the modules.

I'm guessing the actual silentype driver is in BIG.DRIVER and SMALL.DRIVER.

[Linked Image from i.imgur.com]

Somewhere there exists a Silentype Manual for the Silentype ///. (I could only find a picture of it on worthpoint)

[Linked Image from i.imgur.com]

edit:

I was trying to experiment with the graphic commands from the basic command line with

INVOKE "bgraf.inv"
PERFORM grafixmode(%0,%1)

and it would give ?SOS call error

INVOKE "bgraf.inv"
PERFORM gload."anyfilename"

would cause it to freeze up.

Trying the silentype demo program with only the OPEN #1,".silentype" gives a file not found error, so maybe the driver isn't there?

LOAD DEMO
DEL 80-5000
DEL 50-60

[Linked Image from i.imgur.com]
[Linked Image from i.imgur.com]


edit: ok, I was able to get some graphics operations working with Apple3BusBasic1.23.dsk
so how do you do a mixed text/graphics mode? It seems you have to switch back and forth with PERFORM grafixon and TEXT.
[Linked Image from i.imgur.com]
[Linked Image from i.imgur.com]
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/08/19 05:35 PM

Ok, I can do writing text to the screen and drawing lines in Business Basic.

The y coordinate is zero in the lower left.

emu.keypost doesn't work correctly, I get @ instead of ".

Code
emu.keypost([[
INVOKE "BGRAF.INV"
PERFORM GRAFIXMODE (%2,%1)  : REM 2 IS 560X192 B/W
PERFORM INITGRAFIX
PERFORM FILLCOLOR (%0)
PERFORM FILLPORT            : REM ERASE TO COLOR 0
PERFORM GRAFIXON
OPEN #1,".grafix"
FOR Y=0 TO 190 STEP 10
PERFORM MOVETO(%0,%0)
PERFORM LINETO(%320,%Y)
PRINT #1;"X,Y=(";EXFN%.XLOC:",";EXFN%.YLOC;")"
NEXT Y
]])


[Linked Image from i.imgur.com]
[Linked Image from i.imgur.com]
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/08/19 06:21 PM

Working with the Apple3BusBasic1.23.dsk and running the sample program VOLUMES there does appear to be a .SILENTYPE driver that wasn't there with the 1.1 disk.

[Linked Image from i.imgur.com]
[Linked Image from i.imgur.com]
[Linked Image from i.imgur.com]

Interestingly, it also lists .D1 through .D3 but not a .D4 volume.

For comparison, here's the v1.1 business basic VOLUMES output.

[Linked Image from i.imgur.com]
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/08/19 07:58 PM

SOS has a feature very much like vendor Unixes where you have to relink the kernel to add or remove device drivers. So you have to boot a disk where SOS.DRIVERS includes the .SILENTYPE driver or use the System Utilities to add it to the disk of your choice.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/08/19 10:53 PM

That explains it. I'm doing some reading of this article in the Sept 1982 BYTE where it says that you have to use the System Configuration Program to do this reconfiguration. I'm learning all kinds of interesting stuff.

https://archive.org/stream/byte-mag...ters_and_the_Disabled#page/n109/mode/2up

edit:

I fiddled with the SCP program and it seems pretty straightforward, you can change things like the number of drives in a system, and load driver files to generate a new system.

The only problem that I'm having now is that the floppy drives don't seem to write properly. The SCP can't format a freshly made image (getting an I/O error) and when I saved some basic files to a disk it seemed to clobber it and afterwards I couldn't even get a directory listing.
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/09/19 02:58 AM

Code
./mame64 apple2p -gameio compeyes -picture sun440.png 
bitmap is 1152 x 900


#Soon
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/09/19 04:02 AM

[Linked Image from rbelmont.mameworld.info]

Sooner than I thought, actually. I'll commit this tomorrow after I get some more testing on it.
Posted By: Duke

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/09/19 10:24 AM

Very cool!
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/10/19 12:11 AM

Originally Posted by Pernod
There's a Video Digitiser for the BBC Micro I'd like to emulate at some point, but we don't yet support any kind of video input. Would implementing a bitmap_image_device be a suitable compromise to allow emulating such devices?

With a bitmap_image_device you'd be able to provide a bmp image for the emulated device to capture. Waste of time or worthwhile?


Now you know: worthwhile smile
Posted By: Spk

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/10/19 01:13 AM

Hey RB, are there any plans to get a Transwarp GS working with the apple2gs?
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/10/19 02:07 AM

Spk: Yes, TransWarp GS support is planned.
Posted By: Pernod

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/10/19 02:20 AM

Originally Posted by R. Belmont
Originally Posted by Pernod
There's a Video Digitiser for the BBC Micro I'd like to emulate at some point, but we don't yet support any kind of video input. Would implementing a bitmap_image_device be a suitable compromise to allow emulating such devices?

With a bitmap_image_device you'd be able to provide a bmp image for the emulated device to capture. Waste of time or worthwhile?


Now you know: worthwhile smile

Thanks, I'm already looking at a couple of devices that will use this smile
Posted By: Pernod

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/10/19 10:53 AM

Originally Posted by R. Belmont
Code
./mame64 apple2p -gameio compeyes -picture sun440.png 
bitmap is 1152 x 900


I see you only do the conversion to m_a2_bitmap once in device_reset, so to scan multiple pictures you'd have to reset the machine between each picture. Is this an intentional limitation or an oversight?
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/10/19 10:57 AM

Intentional to make a first version quickly that works and can get any other interested devs started. The image device itself will at least leak memory if you try to hotload a different picture right now so it's not a great idea.

ETA: And now I've fixed both of those things.
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/10/19 11:23 AM

In double-hi-res with the 8-pass grayscale scan it doesn't do a half-bad job.

[Linked Image from rbelmont.mameworld.info]
[Linked Image from rbelmont.mameworld.info]
[Linked Image from rbelmont.mameworld.info]
[Linked Image from rbelmont.mameworld.info]
Posted By: rfka01

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/10/19 11:35 AM

Would it be possible to enable MAME to capture the input of a USB webcam from the host machine?
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/10/19 11:45 AM

Video input is planned but it'll require a lot of OSD-layer work. Since ComputerEyes is a slow scan device (it takes 6 seconds to do a full capture and you had to hold still for that time if you were using a video camera back in the day) "scanning" .PNGs seemed like a better solution.

When we emulate more capable stuff like the SGI Indy's live video input then having video in will be more useful.
Posted By: rfka01

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/10/19 04:59 PM

Ah, I wasn't thinking about live video ... my webcam has a still image button, but of course you couldn't know that smile

How about things like the hand scanners (e.g. Logitech Scanman)?
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/10/19 05:17 PM

AFAIK there's no consistent API for hand scanners, you might as well just scan to PNG.
Posted By: rfka01

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/10/19 05:28 PM

Somehow I'm leaving the most important information out of my sentences today: For the handscanners I meant of course as emulated devices within MAME. Sorry for the chaos!
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/10/19 06:09 PM

Oh, yeah, if they're dumped or whatever.
Posted By: Pernod

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/10/19 06:24 PM

Originally Posted by rfka01
For the handscanners I meant of course as emulated devices within MAME. Sorry for the chaos!

Of course, at the moment I'm looking at BeebScan which is a handheld scanner for the BBC. The same scanner was also used with the Archimedes, see http://chrisacorns.computinghistory.org.uk/32bit_UpgradesH2Z/WE_SCannerIF.html. The scanner is read-only and continually outputs a stream of bytes of the current line in view, when the button is pressed. As this is a generic scanner, used with many other machines at the time, it came with an interface board for the relevant micro.
Posted By: Darkstar

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/10/19 07:49 PM

Originally Posted by R. Belmont
AFAIK there's no consistent API for hand scanners, you might as well just scan to PNG.

On Windows there is WIA which can connect to scanners, digital cameras etc. I'm sure on Linux there is something similar (maybe SANE?).

I guess what rfka01 is asking is, would it be possible to add such support to the OSD layer for those kind of scanner devices?
Posted By: Olivier Galibert

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/10/19 07:53 PM

Originally Posted by Darkstar
I guess what rfka01 is asking is, would it be possible to add such support to the OSD layer for those kind of scanner devices?


Something something send PR
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/10/19 08:12 PM

Eh? I thought his clarification was that he was talking about emulating hand scanners using e.g. the picture image device, not actually supporting them for input.

I'd like to emulate the Cauzin Softstrip reader for giggles - we have enough old magazine scans to make it worthwhile.
Posted By: rfka01

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/10/19 08:49 PM

I mangled up two ideas in my posts before: One thing was taking snaps with a USB connected webcam instead of supplying PNG graphics to the emulated scanner. The other thing was emulating a hand scanner within MAME. Pernod and RB got it right.
Posted By: Darkstar

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/10/19 11:35 PM

Originally Posted by Olivier Galibert
Originally Posted by Darkstar
I guess what rfka01 is asking is, would it be possible to add such support to the OSD layer for those kind of scanner devices?

Something something send PR

Nah, I better leave that to someone who actually cares about that feature. I was just pointing out that there *is* an API for scanners, at least on Windows.

But I misunderstood rfka01 so it doesn't matter anyways ;-)
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/11/19 04:01 PM

More fiddling with the Apple /// driver: There's some major weirdness with Business Basic and using the mame debugger.

It seems that there's a strange interaction when the debugger is active. If I type in the simplest of basic programs:

100 GOTO 100
RUN

It will run fine with no debugger.

With the debugger active, it seems that the more debugger windows I open (I think at least a couple of memory windows) will cause the running program to either drop out to a command prompt or get a ?SYNTAX ERROR IN 100 error. Sometimes it takes a while for it to happen.

./mame64 apple3 -flop1 Apple3BusBasic1.23.dsk -console -window -debug
[Linked Image from i.imgur.com]
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/11/19 04:26 PM

That means some read-activated softswitch doesn't have a debugger guard on it, although everything in the /// should.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/11/19 08:10 PM

Hi RB,

I looked at apple3_memory_r and it looked like it guarded most things, perhaps it is getting confused with the fetching of the xbyte causing side effects by changing m_indir_bank?

(I probably don't know what I'm talking about since I'm new to apple 3 stuff)
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/11/19 08:45 PM

That's quite possible, I haven't looked at that code in a while smile
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/11/19 09:45 PM

Testing my theory, if I put a debugger guard for fetching the x byte the 100 GOTO 100 program seems to run without incident.
Code
                     if (!machine().side_effects_disabled())
                        // fetch the "X byte"
                        m_indir_bank = *apple3_bankaddr(~0, m_zpa ^ 0x0C00) & 0x8f;


The Apple /// is truly weird and wonderful.
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/11/19 11:22 PM

Yup. What's surprising is how much of it made it into the //e without anyone noticing.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/12/19 01:08 PM

So I happened to read an article today by Andy Hertzfeld on folklore.org and it got me thinking, maybe I should look at the 6522 VIA registers for silentype activity.

https://www.folklore.org/StoryView.py?project=Macintosh&story=Apple_II_Mouse_Card.txt

Quote

Bud Tribble had written the initial code to drive the mouse on the Macintosh, but I had to maintain it, so I was familiar with how it worked. I had used a 6522 chip the previous year, since the Apple III had one, which I had programmed to shift bits out to the Silentype thermal printer. I realized that all that was required to interface a mouse to the Apple III was to make a simple connector to route the appropriate signals to the proper pins.


so let's fire up Business Basic v1.23 and see what happens:

OPEN #1,".SILENTYPE"

The "D" 6522 via is mapped in at FFD0-FFDF. A is the shift register address, so let's watch $FFDA.

Code
wp ffda,1,w,1,{printf "f1=%x f2=%x",b@f1,b@f2}

f1=0 f2=6
Stopped at watchpoint 3 writing 00 to 0000FFDA (PC=4801)
Stopped at watchpoint 3 writing 06 to 0000FFDA (PC=480D)
f1=0 f2=C
Stopped at watchpoint 3 writing 00 to 0000FFDA (PC=4801)
Stopped at watchpoint 3 writing 0C to 0000FFDA (PC=480D)
f1=0 f2=9
Stopped at watchpoint 3 writing 00 to 0000FFDA (PC=4801)
Stopped at watchpoint 3 writing 09 to 0000FFDA (PC=480D)
f1=0 f2=3
Stopped at watchpoint 3 writing 00 to 0000FFDA (PC=4801)
Stopped at watchpoint 3 writing 03 to 0000FFDA (PC=480D)
f1=0 f2=6
f1=0 f2=C
f1=0 f2=9
f1=0 f2=3


Code
47F3: AD 5E C0 lda $c05e
47F6: AD DF FF lda $ffdf
47F9: 48       pha
47FA: 09 80    ora #$80         // set the clock to 1mhz
47FC: 8D DF FF sta $ffdf      // store into E environment register
47FF: A5 F1    lda $f1
4801: 8D DA FF sta $ffda     // store the first byte (from $F1) into FFDA
4804: AD DD FF lda $ffdd    // poll the IFR flags until the shift is done
4807: 29 04    and #$04
4809: F0 F9    beq $4804
480B: A5 F2    lda $f2
480D: 8D DA FF sta $ffda   // store the second byte (from $F2) into FFDA
4810: AD DD FF lda $ffdd   // poll the flags until shift is done
4813: 29 04    and #$04
4815: F0 F9    beq $4810
4817: AD 5B C0 lda $c05b     // this part must be to "clock" it into the silentype's internal registers
481A: AD 5F C0 lda $c05f
481D: EA       nop
481E: AD 5E C0 lda $c05e
4821: EA       nop
4822: AD 5A C0 lda $c05a
4825: 68       pla
4826: 8D DF FF sta $ffdf     // restore E register
4829: 60       rts

I edited a bunch of stuff out, but you can see the pattern 6,c,9,3,6,c,9,3 which is pretty clearly the horizontal stepper motor which is bits 0-3. It appears that it writes two bytes in succession to the shift register for the silentype.


Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/13/19 05:34 PM

It's showing some signs of life once I interpret the stepper motors and the left margin switch, and process the bits for the printhead.

OPEN #1,".SILENTYPE"
PRINT #1;"APPLE /// SILENTYPE"

Code


0xFFDA write data=00   m_shift_reg=0600
0xFFDA write data=03   m_shift_reg=0003
0xc05a read , clock in data written to ffda : 0003
silentype m_xpos=136 m_ypos=02         headbits=0000000   0
...............***..****..****..*.....*****................................***...***..*.....*****.*...*.*****.*...*.****..*****.................................
..............*...*.*...*.*...*.*.....*...............*.....*.....*.......*...*...*...*.....*.....*...*...*...*...*.*...*.*.....................................
..............*...*.*...*.*...*.*.....*..............*.....*.....*........*.......*...*.....*.....**..*...*...*...*.*...*.*.....................................
..............*...*.****..****..*.....****..........*.....*.....*..........***....*...*.....****..*.*.*...*....***..****..****..................................
..............*****.*.....*.....*.....*............*.....*.....*..............*...*...*.....*.....*..**...*.....*...*.....*.....................................
..............*...*.*.....*.....*.....*...........*.....*.....*...........*...*...*...*.....*.....*...*...*.....*...*.....*.....................................
..............*...*.*.....*.....*****.*****................................***...***..*****.*****.*...*...*.....*...*.....*****.................................
................................................................................................................................................................
0
0xFFDA write data=00   m_shift_reg=0000
0xFFDA write data=90   m_shift_reg=0090
0xc05a read , clock in data written to ffda : 0090
silentype m_xpos=131 m_ypos=08         headbits=0000000   0
....................*...............*.........**........*.......*......*..*......**.........................................................
....................*...............*........*..*.......*.................*.......*.........................................................
...............***..****...***...****..***...*.....****.*.**...**......*..*..*....*....*.*..*.**...***..****...****.*.**....................
..................*.*...*.*.....*...*.*...*.***...*...*.**..*...*......*..*.*.....*...*.*.*.**..*.*...*.*...*.*...*.**..*...................
...............****.*...*.*.....*...*.****...*.....****.*...*...*......*..**......*...*.*.*.*...*.*...*.****...****.*.......................
..............*...*.*...*.*.....*...*.*......*........*.*...*...*...*..*..*.*.....*...*.*.*.*...*.*...*.*.........*.*.......................
...............****.****...***...****..***...*.....***..*...*..***...**...*..*...***..*...*.*...*..***..*.........*.*.......................
............................................................................................................................................
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/13/19 05:36 PM

Very cool!
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/14/19 02:50 AM

The IIgs 1 MHz-side sync was stealing way too many cycles, which broke 3200 color picture displayers (these show 16 unique colors per scanline by racing the beam). It's better now.

[Linked Image from rbelmont.mameworld.info]
[Linked Image from rbelmont.mameworld.info]
[Linked Image from rbelmont.mameworld.info]
[Linked Image from rbelmont.mameworld.info]
[Linked Image from rbelmont.mameworld.info]
[Linked Image from rbelmont.mameworld.info]
[Linked Image from rbelmont.mameworld.info]
Posted By: Spk

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/14/19 03:06 AM

Awesome!

Reminds me of when I used 'Convert 3200' (Brutal Deluxe Software) to alter/enhance the images I'd scan in to my IIgs with a ThunderScan (https://www.computerhistory.org/collections/catalog/102673216).
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/14/19 09:08 AM

It's alive.....it's ALLLIVEEE!

To get the silentype demo to run I had to do some brain surgery because the BGRAF.INV on the silentype disk seems to crash.
so I changed line 50 to use the bgraf on the business basic v1.23 disk.

30 INVOKE "PSCREEN",".D1/BGRAF.INV"

and why not see the graphics too:

55 PERFORM GRAFIXON

[Linked Image from i.imgur.com]
[Linked Image from i.imgur.com]
[Linked Image from i.imgur.com]

There's (almost) no limit to what the Silentype /// can do! It's all up to you!

[Linked Image from i.imgur.com]
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/15/19 01:27 PM

I didn't want any "page breaks" in the output, so I set the paper length to 33 inches so now everything is on a single page.

[Linked Image from i.imgur.com]
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/15/19 04:20 PM

In the absence of the Silentype /// manual, I wanted to know how the different ESC codes worked since I couldn't get bidirectional printing to look right, sometimes it looks good and other times it looks bad.

I was able to find a table of the ESC codes along with a jump table of the routine address - 1.

ESC codes at $42F4 and Jump table is $4309

[Linked Image from i.imgur.com]

So far I've figured out that

ESC < is bidirectional printing
ESC > is unidirectional printing
ESC B is bold on
ESC b is bold off
ESC W [n] is wide width, takes a number that specifies the character width (numbers from 0 to 7, 8 acts like 0)
ESC w turns off wide width
ESC ? is remap the ESC key to character ie ESC ? | makes any occurence of | act like the ESC code
ESC = is reset the silentype to default settings
ESC . [n] is inter-character gap
ESC ^ [n] is line spacing (in 7/4 pixels, so ESC ^ 4 will feed the paper 7 pixels between lines, single line spacing is normally 6)
ESC H [chr$[n]] is move horizontally precisely [n] pixels so ESC H chr$(3) will move the printhead 3 pixels to the right.
ESC V [chr$[n]] is move vertically precisely [n] * (7/4) pixels so ESC V chr$(4) will move the printhead down exactly 7 pixels.

ESC F [n] is choose font 0,1,2 0=Normal, 1 = Compact, 2 = Roman (though they all seem identical, perhaps the "bigger" driver has the additional character sets)

ESC J [chr$([n])] is set Left Margin
ESK K [chr$([n])] is set Right Margin
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/20/19 03:43 PM

I figured out a couple of more escape codes:

ESC L [chr$([n])] is set the number of lines that a FF will generate (up to 15 I think)
ESC C is set right margin clipping on/off (text that goes further that the right margin will get clipped and not wrapped to the next line)
ESC c is turn clipping on/off

so the only ones I haven't figured out yet are ESC G and the ESC E/e pair.


I wanted to see the silentype printout close up, so I was playing with the copyrozbitmap function (took me awhile to figure out how the parameters work, all good fun.) I want to make it so I can zoom in/out and pan with a joystick.


[Linked Image from i.imgur.com]


edit:
Just on a whim, I thought the ESC G might do graphics, and since there's only 7 elements on the printhead, maybe it will use the codes from 128 to 255.

Yes! It works!

ESC G to go into graphics mode, then send it characters >= 128, bit data is in lower 7 bits. Graphics mode seems to be terminated by sending it the "H" character.

I remember back when I was using the silentype with my apple 2 how much I wanted to be able to send bit patterns to the printer. It's so easy with the Apple /// driver. 8-)

[Linked Image from i.imgur.com]

It's kind of cool that it will print the 7 pixels of bit data just as soon as you send it.

You can see the pixel pattern in the "staircase" in the lower right. Lowest bit is the bottommost pixel.

PRINT #1;CHR$(27)"G";
PRINT #1;CHR$(128+1);
PRINT #1;CHR$(128+2);
PRINT #1;CHR$(128+4);
PRINT #1;CHR$(128+8);
PRINT #1;CHR$(128+16);

[Linked Image from i.imgur.com]
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/21/19 02:47 PM

It appears that ESC E/e pair just turn on/off double spacing. For every CR, you get an extra CR. BOGO.

I guess I was expecting it to be more complicated than that 8-)

It would've been cool if they'd included a sample basic program that would show how every ESC code worked. I think I'll write one.

One last mystery to solve is why the bidirectional printing doesn't line up properly. Sometimes it does, and other times it doesn't.

I noticed that if I printed a line that was over 40 characters long that it would be off by one pixel printing characters on the return trip leftward. When it prints less than 40 characters, it lines up perfectly.

[Linked Image from i.imgur.com]
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/25/19 09:32 PM

ComputerEyes/2 was much more painful since it actually polls the composite sync and expects the true raster V position to be the V position of the capture (the horizontal position is handled internally by the hardware). But it gives nicer results, especially in double-hi-res greyscale:

[Linked Image from rbelmont.mameworld.info]

ETA: And a little MAMEception: here's a MAME screenshot from the IIgs driver used as source for a //e double-hi-res capture:

[Linked Image from rbelmont.mameworld.info]
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/27/19 08:17 AM

I think I found out why the silentype /// bidirectional printing is a little strange. There's a small stretch of code that does some addition on a two byte value, and curiously it adds an extra 1 when the low byte overflows.

You 6502 guys would be able to figure this out. Me, it takes forever. 8-) I had to keep looking at it over and over again to figure out what was happening because it's subtle.

[Linked Image from i.imgur.com]

It calls jsr $4ada which is just a lda #$05, rts. After that returns it clears the carry flag, adds $3e86 and pushes the flags on the stack. Then it adds $3ea2 which is the intercharacter gap, and stores it to $3e86. Then it adjusts $3e87 and increments it if the second addition had a carry flag set, then pulls the flags off the stack and increments $3e87 again if the first addition had the carry flag set.

Before it adds $3ea2 it doesn't clear the carry flag, so when that first addition of #$05 and $3e86 overflows it gets an additional +1.

If the line is 40 characters (starting at a horizontal position of 12 and each character being 5 pixels wide + 1 pixel gap you get an hpos of 6*40+12=252).
If the line is 41 characters the hpos crosses the 255 value and when it adds 6 to 252 it jumps from 252 to 259 with the addition of the carry flag.

So 259=0x103 instead of 258=0x102.

I wonder if this was actually deliberate as the stepper motors were inaccurate and that was empirically determined to compensate for that. Or it could just be a bug. Of course we're not emulating the mass and acceleration of the motors and printhead, but an idealized stepper motor which perfectly and instantaneously jumps from location to location.

So what if we try to patch it?

Code
< 4278: 08       php
< 4279: 6D A2 3E adc $3ea2
< 427C: 8D 86 3E sta $3e86
< 427F: 90 03    bcc $4284
< 4281: EE 87 3E inc $3e87
< 4284: 28       plp
< 4285: 90 03    bcc $428a
< 4287: EE 87 3E inc $3e87
---
> 4278: 90 03    bcc $427d
> 427A: EE 87 3E inc $3e87
> 427D: 18       clc
> 427E: 6D A2 3E adc $3ea2
> 4281: 8D 86 3E sta $3e86
> 4284: 90 03    bcc $4289
> 4286: EE 87 3E inc $3e87
> 4289: EA       nop


I can get the code in with one byte left over as a nop, and that seems to get the bidirectional lines to line up as expected.

Some other interesting bits from fiddling:

When the silentype is active, you can't read any of the joystick buttons or paddles. Closing the silentype device with CLOSE #1 will make them available again.

?PDL(0) will give you ?RESOURCE UNAVAILABLE ERROR.

[Linked Image from i.imgur.com]

3F4D seems to be the main driver entry so "bp 3f4d" will stop right on entry to the driver.

Executing a source command (eg "source debugcmd1.txt") from the debugger window will only work if the debugger is paused first. Otherwise, it seems to have no effect.

Executing a trace command with the apple /// must be done with the maincpu as an argument (ie 'trace mytrace1.txt,maincpu,,{tracelog "A=%02x X=%02x Y=%02x P=%02x PC=%02x >>> ",a,x,y,p,pc}' otherwise you end up with completely empty trace files.

The history command will blow up the apple3 debugger if you type "history ,5". You need to give it "history maincpu,5". Just plain old "history" works but you don't always want 200 history entries 8-)
Posted By: peter ferrie

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/27/19 06:13 PM

The first BCC could be +4 instead of +3, but otherwise the patch looks fine. Yes, it looks like a bug unless the bounds were known to only ever result in a single overflow.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/27/19 08:53 PM

Originally Posted by peter ferrie
The first BCC could be +4 instead of +3, but otherwise the patch looks fine. Yes, it looks like a bug unless the bounds were known to only ever result in a single overflow.


That's a good idea to save two cycles. Also I think the second BCC could be +4 too, skipping the NOP. 8-)
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/27/19 09:14 PM

I wanted to keypost some basic programs into the apple 3 driver but the emu.keypost("\"") wouldn't give me a proper quote.

It's a pretty easy fix, just change the PORT_CHAR to "@" for KEYCODE_2, because the \" is also on KEYCODE_QUOTE, so the keypost gets the first one while it searches, finding the 2 key instead of the quote key.

Code
diff --git a/src/mame/drivers/apple3.cpp b/src/mame/drivers/apple3.cpp
index ecaa1453d0..e429ecf878 100644
--- a/src/mame/drivers/apple3.cpp
+++ b/src/mame/drivers/apple3.cpp
@@ -215,7 +215,7 @@ static INPUT_PORTS_START( apple3 )
        PORT_START("X0")
        PORT_BIT(0x001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Esc")      PORT_CODE(KEYCODE_ESC)      PORT_CHAR(27)
        PORT_BIT(0x002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_1)      PORT_CHAR('1') PORT_CHAR('!')
-       PORT_BIT(0x004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_2)  PORT_CHAR('2') PORT_CHAR('\"')
+       PORT_BIT(0x004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_2)  PORT_CHAR('2') PORT_CHAR('@')
        PORT_BIT(0x008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_3)  PORT_CHAR('3') PORT_CHAR('#')
        PORT_BIT(0x010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_4)  PORT_CHAR('4') PORT_CHAR('$')
        PORT_BIT(0x020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_5)  PORT_CHAR('5') PORT_CHAR('%')


also I thought it'd be cool to have a emu.keydump() to help see the keys, a simple two line addition to luaengine.cpp:

Code
diff --git a/src/frontend/mame/luaengine.cpp b/src/frontend/mame/luaengine.cpp
index df730b7019..89bba51324 100644
--- a/src/frontend/mame/luaengine.cpp
+++ b/src/frontend/mame/luaengine.cpp
@@ -8,6 +8,7 @@
 
 ***************************************************************************/
 
+#include <iostream>
 #include <thread>
 #include <lua.hpp>
 #include "emu.h"
@@ -805,6 +806,7 @@ void lua_engine::initialize()
        emu["romname"] = [this](){ return machine().basename(); };
        emu["softname"] = [this]() { return machine().options().software_name(); };
        emu["keypost"] = [this](const char *keys){ machine().ioport().natkeyboard().post_utf8(keys); };
+       emu["keydump"] = [this](){ machine().ioport().natkeyboard().dump(std::cout); };
        emu["time"] = [this](){ return machine().time().as_double(); };
        emu["start"] = [this](const char *driver) {
                        int i = driver_list::find(driver);

Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/28/19 01:07 PM

I thought I'd check all of the emu.keypost characters and there's a few more misassignments.

6789 should be ^&*(


a little lua script to test:
Code
function iif(a,b,c) if a then return b else return c end end
for i=32,127 do emu.keypost(iif(i==32,"rem ","")..i.." "..string.char(i).." "..iif(i%10==0,"\nrem ","") ) io.write(i.." "..string.char(i).." "..iif(i%10==0,"\n","")) end emu.keypost("\n") print()


[Linked Image from i.imgur.com]

Code
diff --git a/src/mame/drivers/apple3.cpp b/src/mame/drivers/apple3.cpp
index ecaa1453d0..deedcef9e4 100644
--- a/src/mame/drivers/apple3.cpp
+++ b/src/mame/drivers/apple3.cpp
@@ -215,14 +215,14 @@ static INPUT_PORTS_START( apple3 )
        PORT_START("X0")
        PORT_BIT(0x001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Esc")      PORT_CODE(KEYCODE_ESC)      PORT_CHAR(27)
        PORT_BIT(0x002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_1)      PORT_CHAR('1') PORT_CHAR('!')
-       PORT_BIT(0x004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_2)  PORT_CHAR('2') PORT_CHAR('\"')
+       PORT_BIT(0x004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_2)  PORT_CHAR('2') PORT_CHAR('@')
        PORT_BIT(0x008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_3)  PORT_CHAR('3') PORT_CHAR('#')
        PORT_BIT(0x010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_4)  PORT_CHAR('4') PORT_CHAR('$')
        PORT_BIT(0x020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_5)  PORT_CHAR('5') PORT_CHAR('%')
-       PORT_BIT(0x040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_6)  PORT_CHAR('6') PORT_CHAR('&')
-       PORT_BIT(0x080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_7)  PORT_CHAR('7') PORT_CHAR('\'')
-       PORT_BIT(0x100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_8)  PORT_CHAR('8') PORT_CHAR('(')
-       PORT_BIT(0x200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_9)  PORT_CHAR('9') PORT_CHAR(')')
+       PORT_BIT(0x040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_6)  PORT_CHAR('6') PORT_CHAR('^')
+       PORT_BIT(0x080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_7)  PORT_CHAR('7') PORT_CHAR('&')
+       PORT_BIT(0x100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_8)  PORT_CHAR('8') PORT_CHAR('*')
+       PORT_BIT(0x200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_9)  PORT_CHAR('9') PORT_CHAR('(')
 
        PORT_START("X1")
        PORT_BIT(0x001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Tab")      PORT_CODE(KEYCODE_TAB)      PORT_CHAR(9)
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 08/29/19 03:38 AM

While we're at it, why don't we verify our keystrokes with what actually gets recognized by the computer?

First let's find out in memory where the screen memory actually is:

On the initial load of business basic, there's a directory listing. Let's choose something on screen that's recognizable: "VOLUMES.DOC".

Writing a little lua function to scan the memory, and then a few false starts: screen memory is split into two blocks one at 0x400 and 0x800 with every other character, so VOLUMES.DOC would be VLMSDC or OUE.O, and the high bit needs to be set.

Code
mem=emu.item(manager:machine().devices[":ram"].items["0/m_pointer"])

function scanmatch(byteseq,mem,start)  for addr = start,start+string.len(byteseq)-1 do if mem:read(addr)~=string.byte(byteseq,1+addr-start) then return false end  end return true end

function eachchar(s,func) ret="" for i=1,#s do ret=ret..string.char(func(string.byte(s,i))) end return ret end
function sethibit(achar) return achar | 0x80 end

function hex(a) return string.format("%02x",a) end

for i=0,0x40000 do if scanmatch(eachchar("VLMSDC",sethibit),mem,i) then print(hex(i)) end end


which tells us that the screen memory is at 0x38000 + 0x400 (for page 1) and 0x38000+0x800 (for page 2)

[MAME]> for i=0,0x40000 do if scanmatch(eachchar("VLMSDC",sethibit),mem,i) then print(hex(i)) end end
38b07
[MAME]> for i=0,0x40000 do if scanmatch(eachchar("OUE.O",sethibit),mem,i) then print(hex(i)) end end
38708


Knowing that we can write a little basic program to read a keystroke, print it in the upper left at hpos=1 and vpos =1 which would be address 0x38000+0x400 and we can read that to check against what we're sending:

Code
function myco() 
quitco=nil 
emu.keypost([[
new
90 home
100 get a$:HPOS=1:VPOS=1:? a$"  ASC="ASC(A$)"    "
105 for i = 1 to 300:next i
110 GOTO 100
run
]])
mem=emu.item(manager:machine().devices[":ram"].items["0/m_pointer"])
emu.wait(15) 
for i=32,126 do 
emu.keypost(string.char(i)) 
emu.wait(.5)
screenchar=mem:read(0x40000-0x8000+0x400) 
print("SENT: "..string.char(i).."   SCREEN:"..string.char(screenchar&0x7f)) 
if quitco then return end end end
co1=coroutine.create(myco) coroutine.resume(co1)


and the output looks like:

SENT: SCREEN:
SENT: ! SCREEN:!
SENT: " SCREEN:"
SENT: # SCREEN:#
SENT: $ SCREEN:$
SENT: % SCREEN:%
SENT: & SCREEN:&

Interestingly, afterward, typing CTRL+C to exit the basic program, you have to blind type "TEXT" and enter to get your normal screen back. I think that printing CHR$(3) does something strange to the console driver.

I initially wanted to use the basic KBD function but I couldn't get KBD to work. "PRINT KBD" would always give me zero. GET A$ works just fine. (edit: Oh I see how KBD works from the business basic vol 1 manual, you have to use ON KBD GOTO for KBD to get set properly)

The uppercase and lowercase characters seem to be reversed, there must be a reason for that, it'd be simple to flip the order of the PORT_CHAR to lowercase first, then uppercase character.


Let's also figure out how the addresses at a000 gets mapped into memory:

Code
function hextobytes(h) local a,b,c c="" h=string.upper(h)for i=1,string.len(h),2 do a=string.byte(h,i)-string.byte("0") if a>16 then a=a-7 end b=string.byte(h,i+1)-string.byte("0") if b>16 then b=b-7 end c=c..string.char(a*16+b) end return c end

for i=0,0x40000 do if scanmatch(hextobytes("4ce5a020ca"),mem,i) then print(hex(i)) end end

and it tells us that a000 gets mapped into 3a000.

[Linked Image from i.imgur.com]
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/01/19 11:31 PM

[Linked Image from i.imgur.com]
[Linked Image from i.imgur.com]
[Linked Image from i.imgur.com]

Now I can rotate and zoom it in and out with keyboard control, it's kinda hypnotic watching it do its thing.

If you see a line that's 66644464646464 it's because I mapped the keypad keys 4 and 6 to rotation and 5 and 2 to zoom.

There's no line draw function into a bitmap so I ripped one off of irobot's driver that works ok. That's how I draw the red rectangle that shows the printhead location.

I also learned that I can type PRINT#1"TEXT" instead of PRINT #1;"TEXT".

So if I have a line of basic code that is 5 PRINT#1"TEXT"

If I type RUN 5 from the immediate command line it closes the open file #1, but if I GOTO 5 or GOSUB 5 it doesn't close the open file.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/02/19 12:34 AM

Fun read:

https://archive.org/details/TNM_Computer_products_catalog_1980_-_Electronic_S_20180506_0144



There's a lot of neat apple ii hardware listed here.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/06/19 09:03 PM

I was trying to get Cyclod running with the sirius joyport, but for some reason I couldn't get it to select the joyport. Supposedly you enable the atari joystick with CTRL+SHIFT+P (which is actually CTRL+@). CTRL+P will enable the normal apple joystick.

Sirius freefall and snakebyte wants CTRL+SHIFT+P too:

https://archive.org/details/Cyclod/page/n1
https://archive.org/details/1982-sirius-freefall/page/n1
https://archive.org/details/sirius_snakebyte_manual/page/n1

This puzzled me because none of these seem to work. So let's start digging:

I looked at the code inside cyclod for reading the joyport and sure enough, it's got code that hits c05a and c05b
Code
>find 0,bfff,5a,c0
Found at 869D
Found at 882B
Found at 8CB5
[MAME]> 

>find 0,bfff,5b,c0
Found at 86BE
[MAME]> 

and there's a joyport reading routine at 8699, but why doesn't it get called?

let's watch what is actually reading from the keyboard and that leads us to the code where it reads the keyboard:

Code
wp c000,1,r,1,{printf "keyboard read: pc=%x wpaddr=%x  wpdata=%x ",pc,wpaddr,wpdata;g}

7398: AD 00 C0 lda KBD / 80STOREOFF
739B: 8D 27 70 sta $7027
739E: AD 10 C0 lda KBDSTRB
73A1: AD 5E 70 lda $705e
73A4: C9 01    cmp #$01
73A6: F0 06    beq $73ae
73A8: 20 99 86 jsr $8699


so our joyport routine will get called if there isn't a 1 in 705e


we can find these routines by looking for where 7027 and 705e get accessed:
Code
>find 0,bfff,5e,70
>find 0,bfff,27,70


8D7D: AD 27 70 lda $7027    keycode gets put here
8D80: C9 8B    cmp #$8b      8b = CTRL+K  keyboard
8D82: D0 09    bne $8d8d
8D84: A9 00    lda #$00        puts 00 in 705e
8D86: 8D 5E 70 sta $705e
8D89: 20 BC 82 jsr $82bc          calls some other stuff
8D8C: 60       rts
8D8D: C9 90    cmp #$90     90 = CTRL+P joystick
8D8F: D0 09    bne $8d9a
8D91: A9 01    lda #$01        puts 01 in 705e
8D93: 8D 5E 70 sta $705e
8D96: 20 84 7D jsr $7d84
8D99: 60       rts
8D9A: C9 80    cmp #$80      80 = CTRL+shift+p or CTRL+@
8D9C: D0 08    bne $8da6
8D9E: A9 02    lda #$02       puts 02 in 705e
8DA0: 8D 5E 70 sta $705e
8DA3: 20 E6 76 jsr $76e6
8DA6: 60       rts

very similar routines to those above reading CTRL+k,CTRL+P,CTRL+@
Code
8DA7: AD 27 70 lda $7027      
8DAA: C9 8B    cmp #$8b
8DAC: D0 06    bne $8db4
8DAE: A9 00    lda #$00
8DB0: 8D 5E 70 sta $705e
8DB3: 60       rts
8DB4: C9 90    cmp #$90
8DB6: D0 06    bne $8dbe
8DB8: A9 01    lda #$01
8DBA: 8D 5E 70 sta $705e
8DBD: 60       rts
8DBE: C9 80    cmp #$80
8DC0: D0 05    bne $8dc7
8DC2: A9 02    lda #$02
8DC4: 8D 5E 70 sta $705e
8DC7: 60       rts



so the code is there but it's looking for a keycode of 0x80, but we're not getting it.

Looking at the key table in src/mame/drivers/apple2.c we can fix the table to send a 0x00 code:

Code
static const uint8_t a2_key_remap[0x32][4] =
{
/*    norm shft ctrl both */
        { 0x33,0x23,0x33,0x23 },    /* 3 #     00     */
        { 0x34,0x24,0x34,0x24 },    /* 4 $     01     */
        { 0x35,0x25,0x35,0x25 },    /* 5 %     02     */
...
        { 0x55,0x55,0x15,0x15 },    /* u U     10     */
        { 0x49,0x49,0x09,0x09 },    /* i I     11     */
        { 0x4f,0x4f,0x0f,0x0f },    /* o O     12     */
        { 0x50,0x40,0x10,0x00 },    /* p P     13     */  //should be a 0x00 for a CTRL_SHIFT_P
        { 0x44,0x44,0x04,0x04 },    /* d D     14     */
        { 0x46,0x46,0x06,0x06 },    /* f F     15     */
        { 0x47,0x47,0x07,0x07 },    /* g G     16     */
        { 0x48,0x48,0x08,0x08 },    /* h H     17     */
        { 0x4a,0x4a,0x0a,0x0a },    /* j J   

but we still don't get an 0x80 code because of an if statement in ay3600_data_ready_w that checks to see if our translated character is zero:

commenting that out we now get the 0x80 code when we read $c000! Yay!

Code
WRITE_LINE_MEMBER(apple2_state::ay3600_data_ready_w)
{
        if (state == ASSERT_LINE)
        {
                int mod = 0;
                m_lastchar = m_ay3600->b_r();

                mod = (m_kbspecial->read() & 0x06) ? 0x01 : 0x00;
                mod |= (m_kbspecial->read() & 0x08) ? 0x02 : 0x00;

                m_transchar = a2_key_remap[m_lastchar&0x3f][mod];


//              if (m_transchar != 0)
                {
                        m_strobe = 0x80;
//          printf("new char = %04x (%02x)\n", m_lastchar&0x3f, m_transchar);
                }
        }
}
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/06/19 09:50 PM

Thanks! I'll fix that in mainline.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/06/19 10:23 PM

Thanks, RB! I've got some fixes for the sirius joyport that I'll submit a PR for once I've fixed up my git.

Here's the relevant bits (I think this is correct now:)

Code
READ_LINE_MEMBER(apple2_joyport_device::sw0_r)
{
        u8 port_read = m_an0 ? m_player2->read() : m_player1->read();
        return BIT(port_read, 4);
}

READ_LINE_MEMBER(apple2_joyport_device::sw1_r)
{
        u8 port_read = m_an0 ? m_player2->read() : m_player1->read();
        return m_an1 ? BIT(port_read, 0) : BIT(port_read, 3);
} // 0 is up 3 is left

READ_LINE_MEMBER(apple2_joyport_device::sw2_r)
{
        u8 port_read = m_an0 ? m_player2->read() : m_player1->read();
        return m_an1 ? BIT(port_read, 2) : BIT(port_read, 1);
}  // 2 is  down 1 is right





I did some reading at https://git-scm.com/book/en/v2 and I think I'm finally getting closer to understanding git.

It's hard to fathom, but there's no 2 player games I could find that really use the sirius joyport. I think there's a dearth in general of 2 player games on the apple 2, probably because very few people had more than 1 joystick. (I wonder how hard it would be to patch the karateka 2 player patch to use the joyport?)

The only game that really tested out the 2 player setting is boulderdash where it alternates between joystick 1 and 2.

Vindicators actually uses the second joystick, which is kinda different.

Most use the first joystick, like stellar 7.


There's a Computer Foosball game that uses the 4 paddle mode of the sirius joyport (you can hook up 2x2 paddle controllers and play with 2 teams of each paddle and button controlling one group of foosball flippers). I copied your joystick device and modified it to do the joyport with paddles, I called it joyportpaddle.
You hit Ctrl+R to reset then you can choose 1 / 2 / 4 player with the 1,2,and 4 keys. Once a game has started you can't change the number of players but you can type N or F for Normal/Fast. The 4 player mode says "requires JOYPORT." The ball tends to get stuck so you have to hit Ctrl+B to do another serve.

This is probably the only game that used the 4 paddle mode. (That would be good for a warlords type game).

[Linked Image from i.imgur.com]

[Linked Image from i.imgur.com]

Code
// This  should be m_joy_y
u8 apple2_joyportpaddle_device::pdl3_r()
{
        return m_joy_y[1]->read();
}

READ_LINE_MEMBER(apple2_joyportpaddle_device::sw0_r)
{
        return m_an0 ? BIT(m_buttons->read(), 6) : BIT(m_buttons->read(), 4);

// m_an0  true = bit 6  false = bit4 
// this makes sense for normal two player with a single paddle, 
//    we read bits 4 and 5 on switch 0 and 1
// For 4 paddles, we read bits 6 and 7 on switch 0 and 1 when m_an0 is true
}

READ_LINE_MEMBER(apple2_joyportpaddle_device::sw1_r)
{
        return m_an0 ? BIT(m_buttons->read(), 7) : BIT(m_buttons->read(), 5);
}

READ_LINE_MEMBER(apple2_joyportpaddle_device::sw2_r)
{
return 0;
}

READ_LINE_MEMBER(apple2_joyportpaddle_device::sw3_r)
{
return 0;
}

Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/07/19 01:54 PM

I thought I'd try all the games in the sirius collection as they'd be the ones most likely to have sirius joyport support.

So far I've found that bandits, hadron, buzzard bait, freefall work with the joyport.

Copts and robbers is a curious case. It has code to read the joyport, but it just doesn't work, moving the character only when the fire button is pressed and then backwards and diagonally to the upper left.

Copts and robbers is a loose clone of adventure, down to the use of a magnet and a block representing the player's character.

The manual doesn't mention the joyport. https://mocagh.org/miscgame/coptsrobbers.pdf

[Linked Image from i.imgur.com]

CTRL+shift+P activates the joyport, CTRL+K goes back to keyboard.

I looked and looked at the code at 1f40 and it just doesn't work because the joyport has buttons that are active low, hi bit set when pressed.


If we change the BMIs to BPLs and vice versa ($30 to $10) and ($10 to $30) then the routine behaves normally.

The first thing it does is to check the button and bmi to 1fbf if the button is pressed to return the value in $c4. This is clearly backwards and must be a BPL.

puts left button in $26
right in $27
up in $28
down in $29

when the routine exits, it has loaded the accumulator with the value of one of the following memory addresses (which basically mimics the keyboard actions):
Code
$c0 = c1 = A
$c1 = 95 = CTRL+U or right arrow
$c2 = da = Z
$c3 = 88 = CTRL+H or left arrow
$c4 = a0 = space

1F40: AD 61 C0 lda RDBTN0
1F43: 30 7A    bmi $1fbf
1F45: AD 5A C0 lda CLRAN1
1F48: AD 62 C0 lda BUTN1
1F4B: 85 26    sta <GBASL
1F4D: AD 63 C0 lda RD63
1F50: 85 27    sta <GBASH
1F52: AD 5B C0 lda SETAN1
1F55: AD 62 C0 lda BUTN1
1F58: 85 28    sta <BASL
1F5A: AD 63 C0 lda RD63
1F5D: 85 29    sta <BASH
1F5F: A5 26    lda <GBASL
1F61: 05 27    ora $27
1F63: 85 2A    sta $2a
1F65: A5 28    lda <BASL
1F67: 05 29    ora $29
1F69: 25 2A    and $2a
1F6B: 10 0A    bpl $1f77
1F6D: 24 FE    bit $fe
1F6F: 10 03    bpl $1f74
1F71: 4C 8B 1F jmp $1f8b
1F74: 4C 96 1F jmp $1f96
1F77: 20 8B 1F jsr $1f8b
1F7A: F0 01    beq $1f7d
1F7C: 60       rts
1F7D: 20 96 1F jsr $1f96
1F80: F0 01    beq $1f83
1F82: 60       rts
1F83: A9 00    lda #$00
1F85: 85 80    sta $80
1F87: AD 00 C0 lda KBD / 80STOREOFF
1F8A: 60       rts

if 26 (left) is pressed, go to 1faf  (load $c3)

1F8B: A5 26    lda <GBASL
1F8D: 30 20    bmi $1faf        

if 27 (right) is pressed go to 1fb3  (load $c1)

1F8F: A5 27    lda <GBASH
1F91: 30 20    bmi $1fb3
1F93: A9 00    lda #$00
1F95: 60       rts
1F96: A5 28    lda <BASL
1F98: 30 1D    bmi $1fb7
1F9A: A5 29    lda <BASH
1F9C: 30 1D    bmi $1fbb
1F9E: A9 00    lda #$00
1FA0: 60       rts
1FA1: 08       php
1FA2: A0 00    ldy #$00
1FA4: 84 FE    sty $fe
1FA6: 28       plp
1FA7: 60       rts
1FA8: 08       php
1FA9: A0 80    ldy #$80
1FAB: 84 FE    sty $fe
1FAD: 28       plp
1FAE: 60       rts

load the value into A and set/clear the diagonal flag in $fe on the way out

1FAF: A5 C3    lda $c3
1FB1: D0 EE    bne $1fa1          clear the diagonal flag
1FB3: A5 C1    lda $c1
1FB5: D0 EA    bne $1fa1
1FB7: A5 C0    lda $c0
1FB9: D0 ED    bne $1fa8          set the diagonal flag
1FBB: A5 C2    lda $c2
1FBD: D0 E9    bne $1fa8
1FBF: A5 C4    lda $c4
1FC1: 60       rts

 


So I after I flipped the bmi <-> bpl, the routine worked more normally, but diagonals weren't working so I had to flip the ora <-> and ($05 to $25) as well.

Code
< 1F43: 30 7A    bmi $1fbf
---
> 1F43: 10 7A    bpl $1fbf
14c14
< 1F61: 05 27    ora $27
---
> 1F61: 25 27    and $27
17,19c17,19
< 1F67: 05 29    ora $29
< 1F69: 25 2A    and $2a
< 1F6B: 10 0A    bpl $1f77
---
> 1F67: 25 29    and $29
> 1F69: 05 2A    ora $2a
> 1F6B: 30 0A    bmi $1f77
35c35
< 1F8D: 30 20    bmi $1faf
---
> 1F8D: 10 20    bpl $1faf
37c37
< 1F91: 30 20    bmi $1fb3
---
> 1F91: 10 20    bpl $1fb3
41c41
< 1F98: 30 1D    bmi $1fb7
---
> 1F98: 10 1D    bpl $1fb7
43c43
< 1F9C: 30 1D    bmi $1fbb
---
> 1F9C: 10 1D    bpl $1fbb


I wonder if this code is a vestige of an early version of the joyport when it may have had active high buttons, or a copy protection?

It's soooo much better with a joyport than the keyboard.

Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/07/19 02:25 PM

I was trying to figure out how some of the keystrokes can be generated and noticed some very small and subtle discrepancies in the keytable:

Somewhere in the copts and robbers code it was checking for a keycode of 0x9e and 0x9d which can only be generated by ctrl+shift+M = 0x9d and ctrl+shift+N = 0x9e

[Linked Image from i.imgur.com]


so according the manual m will generate

CD 8D DD 9D
and the manual has the columns in different order of ctrl shift so to match the key_remap table
it would be:
cd dd 8d 9d -> (removing the high bit)
4d 5d 0d 1d

{ 0x4d,0x4d,0x0d,0x0d }, /* m M 24 */


N is
CE 8E dE 9E
and reordering
ce de 8e 9e ->
4e 5e 0e 1e

I don't have real hardware to test against, so ymmv. This is from the apple ii reference manual, is the 2 plus any different?



static const uint8_t a2_key_remap[0x32][4] =
{
/* norm shft ctrl both */
{ 0x33,0x23,0x33,0x23 }, /* 3 # 00 */
{ 0x34,0x24,0x34,0x24 }, /* 4 $ 01 */
...
{ 0x08,0x08,0x08,0x08 }, /* Left 1c */
{ 0x15,0x15,0x15,0x15 }, /* Right 1d */
{ 0x5a,0x5a,0x1a,0x1a }, /* z Z 1e */
{ 0x58,0x58,0x18,0x18 }, /* x X 1f */
{ 0x43,0x43,0x03,0x03 }, /* c C 20 */
{ 0x56,0x56,0x16,0x16 }, /* v V 21 */
{ 0x42,0x42,0x02,0x02 }, /* b B 22 */
{ 0x4e,0x5e,0x0e,0x5e }, /* n N 23 */
{ 0x4d,0x4d,0x0d,0x0d }, /* m M 24 */


Interestingly they didn't do that with CTRL+SHIFT+L and CTRL+SHIFT+O to generate the unique codes of 9C and 9F, just with CTRL+M and CTRL+N.


Looking at the this, I wonder why they just didn't add some small modifications to this table so the apple 2 could type backslashes, both brackets and underscores directly from the keyboard with a CTRL+SHIFT. That would've been really useful as a bunch of codes can't be typed. $DB,DC, and DF are missing. CTRL+SHIFT could've given codes from E0 to FF. (I suppose they fixed all this with the 2e)

Just as an experiment I modified the table so I could type underscore with a CTRL+SHIFT+L and backslash with CTRL+SHIFT+O and it seemed to work fine with PRINT "_\".

Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/07/19 04:39 PM

Thanks for the additional fixes. The II and II Plus are completely identical aside from the ROMs.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/07/19 05:46 PM

some interesting interviews:

I could find a picture of the manual, but no actual manual for the Joyport.

https://66.media.tumblr.com/eddb73060bd78c26807b74d81bed0051/tumblr_pf5uvqpIJf1tg94xho1_500.jpg

http://www.gooddealgames.com/interviews/int_Keithen%20Hayenga.html

http://www.ataricompendium.com/archives/interviews/steve_woita/interview_steve_woita.html
Posted By: Happy

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/07/19 08:00 PM

Regarding the key matrix, Apple used the off the shelf MOS MM5740 AAE, which was designed to work with or mimic a Teletype ASR 33 type keyboard : http://www.bitsavers.org/communicat...pewriter_Sets_Technical_Manual_Sep74.pdf at page 99 you can see the keymapping. Although custom decoding could be ordered for the MOS MM5740, I don't expect Apple would have wanted to pay for it.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/08/19 01:03 PM

So that explains the keycoding, I found a MM5740 datasheet and one of the tables has:

CTRL+SHIFT+P makes NUL,
CTRL+SHIFT+M makes GS,
CTRL+SHIFT+N makes RS

I don't know why they duplicated lines in the datasheet, though for M and N where it doesn't have the different SHIFT+CTRL.

[Linked Image from i.imgur.com]

duplicate lines for P

[Linked Image from i.imgur.com]
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/08/19 01:28 PM

After using the apple 3 driver for awhile I became frustrated with the lack of auto-repeat on the keyboard. Retyping lines by hitting the right arrow key repeatedly 30 times is just something the dude cannot abide.

So let's scarf some code from the apple2 driver:

src/mame/includes/apple3.h

add a timer callback for ay3600_repeat
and a write line member for ay3600_ako_w (any key out)

Code
        DECLARE_READ_LINE_MEMBER(ay3600_shift_r);
        DECLARE_READ_LINE_MEMBER(ay3600_control_r);
        DECLARE_WRITE_LINE_MEMBER(ay3600_data_ready_w);
+       DECLARE_WRITE_LINE_MEMBER(ay3600_ako_w);
+       TIMER_DEVICE_CALLBACK_MEMBER(ay3600_repeat);
        virtual void device_post_load() override;



a couple of variables to hold the anykeydown state and repeat delay

Code
       uint16_t m_lastchar, m_strobe;
        uint8_t m_transchar;
        bool m_charwrt;
+bool m_anykeydown;
+int m_repeatdelay;
 


src/mame/drivers/apple3.cpp
Code
        m_ay3600->shift().set(FUNC(apple3_state::ay3600_shift_r));
        m_ay3600->control().set(FUNC(apple3_state::ay3600_control_r));
        m_ay3600->data_ready().set(FUNC(apple3_state::ay3600_data_ready_w));
+        m_ay3600->ako().set(FUNC(apple3_state::ay3600_ako_w));   // ako is anykey output
+        timer_device &timer(TIMER(config, "repttmr", 0));
+        timer.configure_periodic(timer_device::expired_delegate(FUNC(apple2e_state::ay3600_repeat), this), attotime::from_hz(15));
+


src/mame/machine/apple3.cpp

Code
+
+WRITE_LINE_MEMBER(apple3_state::ay3600_ako_w)
+{
+        m_anykeydown = (state == ASSERT_LINE) ? true : false;
+
+        if (m_anykeydown)
+        {
+                m_repeatdelay = 10;
+        }
+}
+
+TIMER_DEVICE_CALLBACK_MEMBER(apple3_state::ay3600_repeat)
+{
+        if (m_anykeydown)
+        {
+                if (m_repeatdelay)
+                {
+                        m_repeatdelay--;
+                }
+                else
+                {  
+                        m_strobe = 0x80;
+                        ay3600_data_ready_w(true);    // must set the ay3600_data_ready_w to TRUE
+                }
+        }
+}
+
+
+



After I copied the code from the apple2 driver it just didn't work. Finally I realized that I had to set the data_ready_line to true! Then I got my auto repeat working.

I know it isn't exact, but hey it works 8-) The dude can now go back to abiding.



Supposedly it's supposed to go faster if the solid apple key is held and the arrow keys do 2 speed stages or something:

https://www.wap.org/a3/a3library/a3beginninglll.html

"Every key is equipped with an automatic repeat. Holding down the key causes the letter or number to be repeated until the key is released. Some of the special character keys have a two speed repeat. The longer the pressure on the key, the faster the character is repeated. This is advantageous when moving the cursor and drawing lines or dots."

https://archive.org/details/Apple_3_Data_Sheet_A3/page/n3

"All keys have automatic repeat; Four directional-arrow keys with two-speed repeat"

https://archive.org/details/DTCA3DOC-012_review_apple_3_byte_1982-09/page/n5

[Linked Image from i.imgur.com]

Apple III Review - PCW - August 1980.pdf

[Linked Image from i.imgur.com]

edit:

Apparently the arrow keys are "double action" switches:

https://deskthority.net/viewtopic.php?t=17354

Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/08/19 05:14 PM

I was finally able to see the Silentype's font 1 and font 2. You have to use the BIG.DRIVER from the silentype disk and get that integrated into your SOS.DRIVER file. But the latest mame's got floppy corruption problems, every time I try to write a disk it seems to clobber it. Claudette Clobber...

So I thought, why not go back in time, and try an old mame version, I tried a few but was able to get 0178 to compile. Thank you NOWERROR=1! And that version seemed to be able to write the SOS.DRIVER to the floppy.

git checkout mame0178

I discovered the Apple3 "ready to run" hd setup and was able to integrate the BIG.DRIVER silentype driver into bosboot.dsk (after deleting APPLE2.INTERP because it was so full).

and typing

OPEN #1,".SILENTYPE"
FOR I=0 TO 2: PRINT #1 CHR$(27)"F"CHR$(I) " FONT "I:FOR J=32 TO 127 : PRINT #1 CHR$(J) : NEXT : PRINT #1 : NEXT

FONT 0 is the normal font (80 chars per line, 5 pixels + 1 pixel gap)
FONT 1 is the compact font (96 chars per line, 4 pixels + 1 pixel gap)
FONT 2 is the roman font(60 chars per line, 7 pixels + 1 gap)

[Linked Image from i.imgur.com]
3x size
[Linked Image from i.imgur.com]

[Linked Image from i.imgur.com]

Yay! I've been trying so long to get that to work!
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/09/19 09:32 AM

Since I read about the keyzone spectragram I've been trying to find any information and the only program that I could find that mentions it is Gazelle.

"Gazelle permits the online display of Viewdata frames in high-quality colour if you
have a IIGS and an analog RGB monitor. Viewdata frames can be displayed
offline in colour with a //e or //c double Hi-Res colour display. They may also be
viewed offline in colour on the //e by using a Keyzone Spectragram colour card
and RGB monitor."

If I run the gazelle communications program and put in a watchpoint for the c0f0-c0ff range (for slot 7) it gets hit at 4b17. (wp c0f0,f,rw)
Next thing it starts peeking at c0f2, so let's (find 0,bfff,f2,c0)

And we can find some code where it wants to write to c700 (which makes sense as the keyzone would sit in slot 7)

[Linked Image from i.imgur.com]
[Linked Image from i.imgur.com]

Knowing from an article that the keyzone has 8 bit color (2 bits blue, 3 bits for r and b) that these bit values seem to be initializing a color table.
If we take the upper 2 bits middle 3 and lower 3, this table translates to:

00 = 000
07 = 001
c0 = 100
C7 = 101
38 = 110
00 = 000
FF = 111
C7 = 101
00 = 000
00 = 000
00 = 000
FF = 111
00 = 000
3F = 011
F8 = 110
FF = 111

It looks like these would be 8 colors with each R G or B component set to 1 or 0, which would match the teletext colors, since that's what Gazelle was designed to view.

[Linked Image from i.imgur.com]
[Linked Image from i.imgur.com]
[Linked Image from i.imgur.com]
[Linked Image from i.imgur.com]

Left alt will bring up the menu.

If it finds a keyzone card it puts a nonzero value in 4aa5, if we set 4aa5=1 it will draw different bit patterns in the double hi-res space. Maybe the keyzone displays 140x192 without artifacts?

So it's most curious, just wish I could find a keyzone disk image/manual somewhere.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/09/19 11:40 AM

Here's a weird bug with regards to autorepeat and the User-initiated break:

Bring up the apple2e driver with the debugger active, hit the tilde/backtick key for a user-initiated break, keeping the focus on the apple2e window, then type a bunch of keys like asdf jkl;, then switch to the debugger window and give a go command and now your auto repeat will never stop repeating no matter what key you press except for the backtick. Offset $17 in the x_mask keeps getting stuck to $40, which you can see in the debugger memory window:

You can manually set the $40 to zero in the memory view, but it will get set right back to $40.

The only way to get it to stop repeating is to do another user initiated break which will unstick the key.

I using Ubuntu if that makes any difference?

[Linked Image from i.imgur.com]

emu.keypost("`") won't unstick the ` key.

Please release me, let me go...

Posted By: Lord Nightmare

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/09/19 03:35 PM

Regarding the original apple2 and apple2plus "two part" keyboard, it uses a GI AY-5-3600 custom mask 931 part (which does internal keycode->ascii translation), which has not been completely dumped or decapped yet. Someone at VCF-east I spoke to had done a partial table of it by hand and was planning to use an arduino or similar to dump the full table out of it. This mask 931 part uses the mask option where pins 1, 2 and 3 are internal oscillator, pin 4 is AKO and pin 5 is B10. (B10 is incorrectly called "BIO" on parts of the datasheet, it's an extra data output bit to the computer side).

The Apple IIe and IIc use the AY-5-3600-PRO part, which was a mask sold by GI which is well-documented on datasheets (intended to use an external EPROM for keycode->ascii translation, as apple did in this case), so we know what the mask contents are for every possible key combination. The AY-5-3600-PRO has pins 1, 2 and 3 masked for internal oscillator, pin 4 is LO/RO and pin 5 is AKO

LN
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/09/19 03:44 PM

GC: debugger keys also being visible to the emulation is a known, and very annoying, problem. It's not at all Linux specific. I think it's related to the emulation seeing keys you use while navigating the Tab menu.

LN: Known, we of course emulate the PRO part on the IIe and IIc and use Apple's own external layout PROM to translate the layout.
Posted By: Happy

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/09/19 05:16 PM

The MOS MM5740 is the chip in the original Datanetics keyboards used in Apple I and early Apple II models. The point being that the keyboard encodings were inherited from the Teletype ASR 33 (which is also tied to the origin of ASCII ) and only a few keys had any special function for Ctrl-Shift combinations.
Posted By: Lord Nightmare

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/09/19 07:09 PM

Found my notes: The guy at vcf east who was working on dumping the keyboard controller stuff was Eric Rangell: https://github.com/erangell/
He had a replica-1 apple1 clone at vcf, and had a "The Keyboard Company" 2-part keyboard for it which used a 331-0931-B // KR3600-070 // SMC // 8151 chip on it, which I'm 99% sure (due to sharing the "931" part number) is a second source of the ay-5-3600-931 (or, given the 'B', perhaps a minor bugfix of it) used on the later II and II+ and europlus, so running it connected to an apple1 is a bit of a hack? Then again the apple1 does want ascii input, so maybe it's really not a hack...

semi-offtopic: I'm curious if it is possible to use a common ay-5-3600-pro and an eprom on a tiny daughterboard to replace the very rare ay-5-3600-931/331-0931-B on the 2-part keyboard from the later II and the II+, if we had the 931 mask rom data (or just a digital truth table)... Obviously pin 5 from the pro has to be swapped in place of pin 4 from the 931, since the AKO (any key output) pin is used by the AppleII and the mask options moved it to a different pin. Do the appleII/II+ need the B10 output pin at all?

LN
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/09/19 07:41 PM

I would think it's possible, given that's effectively how our Apple II/II+ keyboard emulation work. Our AY-5-3600 emulation behaves like the PRO version, and the array Golden Child corrected acts as a translation PROM.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/10/19 04:48 AM

I was looking at the "remapping" table and it looks like the first 5 colors and the last 3 colors line up pretty well with the double hi-res graphics colors.

The gazelle software only seems to care about the 8 colors used for Videotex Viewdata. Maybe it doesn't use the other colors?

2 bits for blue, 3 for green, 3 for red

BGR
00 = 000 black
07 = 001 red
c0 = 100 blue
C7 = 101 b+r= magenta
38 = 010 green
00 = 000
FF = 111
C7 = 101
00 = 000
00 = 000
00 = 000
FF = 111
00 = 000
3F = 011 g+r = yellow
F8 = 110 b+g = cyan
FF = 111 white


I happened along a really cool spreadsheet regarding apple ii double-hi res and the 16 colors:

Apple II Video Display Theory

https://www.kreativekorp.com/software/fonts/apple2.shtml

https://docs.google.com/spreadsheets/d/1rKR6A_bVniSCtIP_rrv8QLWJdj4h6jEU1jJj0AebWwg/edit?usp=sharing
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/11/19 02:24 PM

Here's a rare piece of hardware: The HAL Labs gizmo, which is only supported by 2 games that I could find: Super Taxman and Vindicator, both by HAL Labs.

There's a picture on Atari Age forums:

[Linked Image from i.imgur.com]

https://atariage.com/forums/gallery/image/12734-gizmo/

There's a few more posts from Greg Autry on Atari Age:

https://atariage.com/forums/topic/216495-taxman/
https://atariage.com/forums/profile/41442-gautry/content/
Quote

gautry

Sorry I'm late to the thread. If anyone is still paying attention, I was the founder of HAL Labs. Brian Fitzgerald and I developed Taxman while in high school and as undergrads living in a trailer on campus at UC Irvine 1980-1981.

I take exception with any criticisms here. It was a nearly perfect copy of Pacman, far better than the other Apple clones and Atari produced versions for other platforms. Brian's bit mapping algorithms were way faster and far smoother (see Broderbund's Snoggle for instance) and the AI on our ghosts was damn good. We even replicated minor things like being able to pass through a ghost on rare occasions (1/255 collisions). Some people hate the keyboard controls, but the Apple's potentiometer based joystick, while great for flight simulators, was terrible for maze games which should be restricted to a four switch movement.
...
We were so frustrated by the Apple Joystick that we developed an adapter with encoding hardware to allow an Atari style 9pin arcade (4 switch) joystick to plug into the Apple II 16 pin DIP connector. Playing Taxman with a WICO joystick was actually really nice.

...
Unfortunately no. There was only one chip (7400 series) let me see if I can remember what it was or how to wire it. Essentially we sent signal out the enunciator port to the chip telling it which of the 4 inputs to accept as a button press at that moment. It was 30 years ago . . . Unfortunately the device I have is sealed with epoxy.


It could only work with software written for it and there wasn't much. Supertaxman and a really great game we did called Vindicator, which was a bit like Robotron. Really incredibly fast for the 1mhz 8 bit CPU. Our distribution died at that time as BIG organizations piled into the market with massive marketing budgets and very few people got to see it. A couple of other small game companies supported the device, but I don't recall which games.





From the code, it sets or clears the 3 annunciators an0,an1, and an2 to select one of the 5 atari joystick lines and reads the address c061 (button0) to get the bit. These seem to be active highs. Just an 8 to 1 mux. 74151 perhaps?

I copied joystick.h to gizmo.h and added a little bit:

Adding m_an2

Code
      // input ports
        required_ioport m_player1, m_player2;
        int m_an0, m_an1, m_an2;
        int gizmotable[8] = {1,3,2,0,4,5,5,5};  // right, left, down, up, fire, none, none, none

Copying joystick.cpp to gizmo.cpp and adding the gizmotable as a save item so I could change the values from the debug view in real time because I was having some trouble getting it just right.

Code

void apple2_gizmo_device::device_start()
{
        save_item(NAME(m_an0));
        save_item(NAME(m_an1));
        save_item(NAME(m_an2));
        save_item(NAME(gizmotable));
}



READ_LINE_MEMBER(apple2_gizmo_device::sw0_r)
{
/*      PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP )                 0 = up
        PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT )          1 = right
        PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN )         2 = down
        PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT )             3 = left
        PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 )                        4 = fire
*/

        return BIT(m_player1->read(),gizmotable[m_an0+m_an1*2+m_an2*4]) ^ 0x1;    // active high so we'll invert it
}


[Linked Image from i.imgur.com]

If you set the 4 to 6 in the gizmotable you get autofire in Vindicator, it's much easier.

Hit enter once to get the Gizmo.
[Linked Image from i.imgur.com]
There's a built in sprite editor, just hit esc on the control selection screen.
[Linked Image from i.imgur.com]
[Linked Image from i.imgur.com][Linked Image from i.imgur.com]

Vindicator is a Robotron clone that if it were a bit less manic it'd be a really good game. Your character moves too fast and can be hard to control. I'm going to try and patch it sometime to make it more playable.


In Super Taxman 2, just hit the space bar to start, it is set up already to use the Gizmo. The original taxman didn't have any support that I could find.

[Linked Image from i.imgur.com]
[Linked Image from i.imgur.com]
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/11/19 06:38 PM

I wanted to test out some two player games that used regular joysticks like Archon and One on One but there's an interesting problem, on these two games, they've put the firebutton for player to on input switch #1.

According to the documentation:
[Linked Image from i.imgur.com]
[Linked Image from i.imgur.com]
[Linked Image from i.imgur.com]
and scrg paddle adapple manual you just move a jumper wire.

What makes sense to me for the paddle adapple is:

S1C is switch 1 computer ---> S0B switch 0 socket B (player 2 on socket B)
S0C is switch 0 computer ----> S0A switch 0 socket A (player 1 on socket A)

[Linked Image from i.imgur.com]
[Linked Image from i.imgur.com]
[Linked Image from i.imgur.com]

It'd be neat to have the remappability functionality of the paddle adapple.

[Linked Image from i.imgur.com]


Pretty simple modification, just change sw1_r to look for BIT number 6 (player 2 button 0)

Code
u8 apple2_joystick_device::pdl0_r()
{
        return m_joy_x[0]->read();
}

u8 apple2_joystick_device::pdl1_r()
{
        return m_joy_y[0]->read();
}

u8 apple2_joystick_device::pdl2_r()
{
        return m_joy_x[1]->read();
}

u8 apple2_joystick_device::pdl3_r()
{
        return m_joy_y[1]->read();
}

READ_LINE_MEMBER(apple2_joystick_device::sw0_r)
{
        return BIT(m_buttons->read(), 4);
}

READ_LINE_MEMBER(apple2_joystick_device::sw1_r)
{
//      return BIT(m_buttons->read(), 5);   single player
        return BIT(m_buttons->read(), 6);   // two player, archon and 1 on 1 want joystick 2 button here
}

Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/13/19 04:44 AM

So I thought I'd see if HorizonV by Nasir would do the joyport thing, and it does but it's a little bit strange.

It will only ask you once what controller you are going to use, and if you don't type CTRL+SHIFT+P right at that moment you won't be able to switch to the joyport. But it isn't consistent about how it uses the ports. Note that it doesn't list the joyport as an option.

[Linked Image from i.imgur.com]

I think that it was written with using the switch in the Left Position where it completely ignores what the m_an0 is doing. Because it wants to turn an0 on and off which chooses the other joystick. So the fire button ends up on the other joystick from where the left/right and up/down is.

[Linked Image from i.imgur.com]

So why don't we try to reproduce that functionality with a little configuration option:
Code
        PORT_START("joyport_config")
        PORT_CONFNAME(0x03, 0x01, "Joyport Switch Setting")
        PORT_CONFSETTING(0x00, "Left (Joystick 1)")
        PORT_CONFSETTING(0x01, "Middle (2 Player - Both)")
        PORT_CONFSETTING(0x02, "Right (Joystick 2)")

        PORT_CONFNAME(0x0C, 0x04, "Atari Joystick / Paddle Switch")
        PORT_CONFSETTING(0x04, "Joystick")
        PORT_CONFSETTING(0x08, "4 Player Paddle")

add it to our device:
Code
apple2_joyport_device::apple2_joyport_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
        : device_t(mconfig, APPLE2_JOYPORT, tag, owner, clock)
        , device_a2gameio_interface(mconfig, *this)
        , m_player1(*this, "joystick_p1")
        , m_player2(*this, "joystick_p2")
        , m_joyport_config(*this, "joyport_config")
{
}


and add the required_ioport to our .h file:
Code
        // input ports
        required_ioport m_player1, m_player2;
        required_ioport m_joyport_config;



Code
READ_LINE_MEMBER(apple2_joyport_device::sw0_r)
{
        u8 port_read;
        if      ((m_joyport_config->read() & 0x03) == 0x00) port_read = m_player1->read();
        else if ((m_joyport_config->read() & 0x03) == 0x01) port_read = m_an0 ? m_player2->read() : m_player1->read();
        else if ((m_joyport_config->read() & 0x03) == 0x02) port_read = m_player2->read();
        return BIT(port_read, 4);
}


the other switches are pretty similar to this one:



and now you can just switch the port into left / middle (both) / right

[Linked Image from i.imgur.com]

And I reckon I could implement the Paddle Adapple functionality with a similar configuration option, one for each of the inputs, have a corresponding output and just select the one you want.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/13/19 04:10 PM

Taking some liberties with the apple2 remap table, so I can get underscore with CTRL+SHIFT+O, I can use the step by step disk. Sure I can catalog it, and use esc ijkm, space and arrow keys to load the characters into the input buffer, but where's the fun in that?

Just modify our remap table:

{ 0x4f,0x4f,0x0f,0x5f }, /* o O 12 */ // 5f will make underscore


I remember this introduction to Basic programming from back in the day.

Step-by-Step BASIC (all in one).dsk

[Linked Image from i.imgur.com]
[Linked Image from i.imgur.com]
[Linked Image from i.imgur.com]

It'd be nice to have the workbook, but it's pretty easy to figure out what they're going for.

There was a second one in the series: "Step by Step Two" by Program Design Inc.
[Linked Image from i.imgur.com]
Posted By: rfka01

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/15/19 04:51 PM

https://www.nightfallcrew.com/category/gallery/retro_computers_and_other_stuff/rushware/

Shame you don't do C64 Golden Child grin

That looks like a great little plotter.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/15/19 05:42 PM

Hi rfka01,

You've got me curious 8-).

The Super Sketch is pretty neat. According to this forum post there's an apple 2 version, but I haven't been able to find a disk image. It doesn't look like it'd be that hard to figure out.


https://atariage.com/forums/topic/275735-what-system-is-this-super-sketch-used/

The forum post said that there were a bunch of different versions:

TI - Cart / Coleco - Cart / Atari - long 9-pin / C64 - long 9-pin / Apple II - 9-pin

C64 Model G2100
Apple Model g2200?
Atari Model G2300
TI Model G2400
Coleco Model G2500
Posted By: rfka01

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/15/19 05:50 PM

Let's see if comp.sys.apple2 knows something ... just posted there smile
Posted By: rfka01

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/15/19 07:00 PM

I completely misunderstood that thing from the first photos! I thought the "tip" would be moved by motors and be some sort of plotter ... but it's a line tracing device smile

Ooops
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/15/19 07:19 PM

I thought it was a plotter also, and I couldn't figure out how they were getting such smooth curves from an 8-bit micro driving what looked like a toy.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/15/19 07:31 PM

In my quest to find games that supported the Joyport I came across Mating Zone, which supported the Wico Trackball. It had a trackball controller interface board that would go into one of the apple slots.

Does anyone know of anything else that supported the Wico Trackball?

Here's some pics from ebay:

[Linked Image from i.imgur.com]
[Linked Image from i.imgur.com]


It's got four 74LS191 4 bit counters so I think it can present itself with an X axis from 0-255 and Y from 0-255. I don't have hardware or a manual so I'm just guessing.

[Linked Image from i.imgur.com]

Hitting CTRL+I brings up the configuration screen:
(This game covers everything!)

[Linked Image from i.imgur.com]

Hitting the left arrow cycles the < through the options, hitting the right arrow cycles the > through the options.

A number key will set the slot or the button number for the last arrow that was moved.

Here I've got the wico set for slot 4 and button 1.

[Linked Image from i.imgur.com]

reading the trackball at 6b1c:

[Linked Image from i.imgur.com]

I don't understand why it would need to hit c0c2 c0c4 and c0c6?

The game only concerns itself with a single axis, I would assume that reading c0c1 would be the y axis.

reading the buttons at 6a40:
(read C0C6: bit 7 is button 1, bit 6 is button 2)

[Linked Image from i.imgur.com]

If I put watchpoints at c0c0,f,r,1 and then set the A register with a=c0;g and then use the keypad enter key (so it doesn't clear the command line) I can feed it some values.

[Linked Image from i.imgur.com]

It seems that the game only uses the upper 6 bits of the value returned, if I feed it a sequence of values like b0,b4,b8,bc,c0 we can see the character move to the right, feeding it descending values moves to the left.

[Linked Image from i.imgur.com]

[Linked Image from i.imgur.com]
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/15/19 08:04 PM

I didn't know the Wico trackball existed. Should be easy enough to hook up. That code indicates they won't accept values > 0xdc, and that's obviously to keep the character out of the score area on the right.

Apple paddle support too!
Posted By: robj

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/25/19 11:24 PM

I have one of these trackballs and have used it with my Apple ///. It took a bit to find the disk with the A3 Driver on it. It has quiet good integration with the console and simulates cursor key movement with the trackball. You can grab the driver from here if you are interested:
https://www.dropbox.com/s/c1dnzw3t97t8n3r/TRKBALL.DSK?dl=0

There is some nice info here on how to program for it:
http://www.txbobsc.com/aal/1983/aal8306.html
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/25/19 11:41 PM

Thanks Rob, that second article fills in a lot of important information that we would've had trouble reverse-engineering. Turns out to be quite a versatile interface.
Posted By: robj

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/26/19 03:31 AM

No problems, I was looking on here as i bumped into something and can't quite seem to work out whats going on.

I am playing with an Apple III driver that interfaces with the Prodos block mode card interface, i'm using the cffa2 card that Mame has for testing. It seems the card expansion rom for c800-cfff is being switched off for some reason.
If i run in debug mode, and set a breakpoint for the card entry point, then when it jumps to the expansion rom its just showing c800-cfff all containing ff. If i take a trace of the cpu, it seems to get further before it switches out. The disk boots ok on real HW with that combo. Any thoughts?

I can provide a link to my disk image if that helps. I'm using a recent Mame version.
Posted By: robj

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/26/19 04:27 AM

Ahh, seems like this is due to my harddisk image not being correct for this.

The hd image is different between using an A3 driver with the CFFA2 card and Apple2 Prodos using the CFFA2 card. The Apple3 one has partition info in the first block which seems to confuse the prodos block mode. When I make up a nice new hd image of two 32mb disks it at least boots ok now :-)
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/30/19 11:46 AM

Thanks, robj! That wico trackball information is really good!


======================

Here's something interesting I saw on ebay: A digital atari joystick interface from West side electronics, the DJI-100. According to the seller,

Quote


Apple II Digital Joystick

Interface Card - Blank PCB

West Side Electronics DJI-100

This is a blank PC Board that was used to make a Digital Joystick interface card for the Apple II. Technically it was used in a Corvus computer as part of a simulator built for a government agency. It attaches to a digital joystick such as the WICO #15-9714 through a 9-pin D connector. It provides an interrupt signal to the computer whenever the joystick is moved or one of the buttons is pressed. The computer can also read the state of the joystick at any time. Complete schematic is also included so you can build your own or use it as the starting point for another project.

NOTE: This item is the blank PCB and schematic only; photos of the partially built and prototype units are for reference only.


https://www.ebay.com/itm/West-Side-...ck-Interface-Card-Blank-PCB/193015994623

[Linked Image from i.imgur.com]
[Linked Image from i.imgur.com]

[Linked Image from i.imgur.com]

[Linked Image from i.imgur.com]

I wonder if the J.Mazur listed on the schematic is Jeff Mazur who made the cdrive.

https://apple2history.org/spotlight/mazur/
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 09/30/19 04:25 PM

Originally Posted by robj
Ahh, seems like this is due to my harddisk image not being correct for this.

The hd image is different between using an A3 driver with the CFFA2 card and Apple2 Prodos using the CFFA2 card. The Apple3 one has partition info in the first block which seems to confuse the prodos block mode. When I make up a nice new hd image of two 32mb disks it at least boots ok now :-)


That's interesting. Remember that SOS actually only allows 16 MB on a partition - it uses a signed int16 where ProDOS uses unsigned.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 10/01/19 09:37 AM

From an auction on ebay for the manual for Super Taxman 2 there's a description of the Gizmo and an order form ($15 back in 1982. pretty reasonable)

[Linked Image from i.imgur.com]
[Linked Image from i.imgur.com]
[Linked Image from i.imgur.com]
Posted By: robj

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 10/05/19 10:47 AM

Originally Posted by R. Belmont

That's interesting. Remember that SOS actually only allows 16 MB on a partition - it uses a signed int16 where ProDOS uses unsigned.

I'm playing with a SOS driver that hooks with a cards Prodos Block driver, so then the card needs to be configured as it would for an A2. It needs some work still as it sometime bumps into the character loading. I have to be careful of that 16mb limit, seems sos is ok with it, but the system utils and some of the programs are not. CFFA2 has the fixed 32mb sizes, so its not ideal, but we don't have many other choices in MAME.

It still seems a but odd with the rom select when running the -debug option. I'm not sure whats going on there. I have temporarily commented out the cfff disable to help me debug my code.
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 10/05/19 12:25 PM

Great. I've checked in a fix that should prevent the debugger from stomping most of the read-activated soft switches.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 11/01/19 05:34 PM

One of the things I had been lamenting was that the apple II+ keyboard couldn't type all of the characters. Turns out there was a cool device called the Videx Enhancer II that would do this, and in addition, also provide macro keys. There was also a function key strip that would plug into it called the Videx FunctionStrip.

This board would install in between the keyboard and the apple ii.

It had a 6502 processor on board with 1k of memory to monitor the apple 2 keyboard and pass the keystrokes along.

It's cool that there was great documentation providing full source code and schematics.

I wanted to look at the code and figured out by pausing the apple II driver, I could load the rom file into memory at $1800 and use the mame debugger to do the disassembly.

load "Videx Enhancer II ROM - 2716.BIN",1800

dasm "VidexEnhancer.txt",1800,800


The rom file doesn't exactly match up with the assembly listing given in the manual, but it's pretty close.

[Linked Image from i.imgur.com]

Quote

The following are some of the Enhancer ]['s features:
*Full ASCII keyboard (128 ASCII codes)
*The complete printable ASCII character set —including lower case — may be displayed
*User definable keys — with down loading from disc [section: 5.f]
*Type ahead buffer [section: 5.g]*Auto repeat [section: 5.a.3]
*Fast repeat [section: 5.a.3]
*Normal Apple ][ mode [section: 5.d]
*Typewriter like operation [section: 5.e]
*Shift—lock feature [section: 5.e.1]
*Control — Reset protection (section: 5.c.1]
*Simple installation [chapter two]
*Microprocessor controlled (6500 series)
*Self test diagnostics [section: 5.h]
*A 2716 EPROM is used for on board firmware

*Complete firmware listings [appendix Y]
*Complete schematic [appendix Z]

*Dvorak keyboard option


Your new keyboard Enhancer ][ utilizes a sophisticated microprocessor with its own RAM. Although the Enhancer ][ is more sophisticated than it’s predecessor, the Keyboard & Display Enhancer, it is significantly easier to install. The microprocessor extends the features of the Enhancer ][ beyond those of the original Keyboard & Display Enhancer with features such as user definable keys and a type ahead buffer. The caps lock, caps unlock, shift lock and control — reset features are preserved, thus supporting the normal Apple ][ keyboard as well as a typewriter like mode.


Ul—2716 EFROM (Enhancer ][ Firmware)
U2—6504 Microprocessor (6502 instruction set)
U3—2114 1K x 4 RAM
U4—2114 1K x 4 RAM
U5—74LS05Hex inverter, open collector
U6—74LS373Octal D latch
U7—74LS139Dual 2—4 line decoder
U8—74LS05Hex inverter, open collector
U9—74LS373Octal D latch
U10—74LS374Octal D flip—flop
Ull—Keyboard output
2N3904 — Reset logic
Posted By: Vas Crabb

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 11/02/19 12:50 AM

Why didn't you just use unidasm to disassemble the ROM?
Posted By: R. Belmont

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 11/02/19 02:41 AM

Because, and I might as well give out the secret: unidasm doesn't actually do anything, it just prints usage text no matter what arguments you give.

Or at least that's my experience.
Posted By: Vas Crabb

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 11/02/19 09:29 AM

Code
./build/mingw-gcc/bin/x64/Debug/unidasm.exe -arch m6805 -skip 0x100 -count 39 -basepc 0x100 roms/Tiger-Heli_with_MCU/68705brian.bin 
100: 9c        rsp
101: a6 ff     lda   #$FF
103: b7 04     sta   $04
105: b7 05     sta   $05
107: b7 01     sta   $01
109: b7 00     sta   $00
10b: a6 00     lda   #$00
10d: b7 06     sta   $06
10f: 15 01     bclr  2, $01
111: a6 73     lda   #$73
113: b7 00     sta   $00
115: 14 01     bset  2, $01
117: 9a        cli
118: 20 fe     bra   $118
11a: 9d        nop
11b: 9d        nop
11c: 9d        nop
11d: 9d        nop
11e: 9d        nop
11f: 9d        nop
120: cd 01 30  jsr   $0130
123: cd 01 50  jsr   $0150
126: 80        rti

Works just fine. As long as you give it a recognised -arch and a filename it will produce disassembly. The usage message tells you you need to give it -arch and a filename.
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 11/02/19 09:53 AM

I tried it and yes, you can get a disassembly with

./unidasm -arch m6502 -basepc 1800 "../../Videx Enhancer II ROM - 2716.BIN" -lower


There are slight differences where you've got the replacement of addresses with labels.


diff -b unidasmlowercase.txt videxlowercase.txt
216c216
< 1981: a4 a5 ldy $a5
---
> 1981: a4 a5 ldy <arg
955c955
< 1f45: 20 00 fa jsr $fa00
---
> 1f45: 20 00 fa jsr f8rom:mnemr
971c971
< 1f62: c5 d8 cmp $d8
---
> 1f62: c5 d8 cmp <errflg
Posted By: Golden Child

Re: 8bit Apples - Apple I, II, /// and the 16 bit GS - 11/03/19 11:11 PM

Thanks to quart de pomme I now have a Silentype 3 manual!!! Yes! I've been looking for this for so long and it answers a lot of questions about it such as how to vary the intensity of the thermal print as well as the meaning and subtleties of the ESC codes.

© 2019 Forums