RAPID 8 – Extended Cut

RAPID 8 for June 2024 is here. So much going on it’s starting to get hard to condense it down into these single pages.

See all the RAPIDS including 8 at: https://www.atariorbit.org/rapid/

Top hits:


  • M68k
    • Data Sent over Macintosh Floppy
  • COCO
    • CocoFest was held May 4/5 and there was a good showing of CocoFujiNet
    • Work is going on for a full cart-based solution using 2040 (no serial) by JeffP
    • Final rev of the ROM+Serial board by ChrisT
  • CBM
    • Recent code stability fixes pushed over from MeatLoaf into FN (Jamie)
    • Small fixes and FN-LIB exploration happening (Mark)
    • Five CardStud client is nearly done (EricC)
  • LEAKS: HTTP memory leak fixed! (TCH, PNP2048, Eric Carr)
    • at 7pm on May 13 Thom ran FN-PC thru valgrind, results showed where the leak was
    • Valgrind used to plug many memory leaks (Mark)
    • Switch to LittleFS reduced startup ready time for all platforms (SPIFFS)
    • with the littlefs change, it goes from cold start to service loop in 166ms.
  • Apple II
    • Netcat re-written for A2 (TCH)
    • lots of improvements, lowercase (on non-enh)
    • F-Tools for Apple2 (TCH)


  • CONFIG-NG .0.9.3 (Mark)

  • tnfs server TCP updates (Newton/TCH)

  • FN-LIB 4.1 – normalize appKeys across platforms (Mark)

  • GAMING: 5CS Arrives for Apple2 (Eric)

  • DSK (DiskCopy) Image support 68k (JeffP)

  • Nightly Builds available for supported Platforms (BenK)
  • GH nightly builds were implemented by BenK for all supported platforms
  • https://github.com/FujiNetWIFI/fujinet-firmware/releases/tag/nightly

  • New Web Flasher allows custom zip flashes (Moz)
  • https://fujinet.online/flasher/

  • Contiki update- follow relative links – need to use trailing slashes on URIs

Fn contiki rel link.

Contiki Browser working with Relative Links on Apple2 (And Atari)

Details and info from Discord


Mark Fisher

config-ng update! ( @jtsom / @Andy Diller ) There was a subtle bug in the wifi setup, where you could enter setup mode, but you couldn’t exit it. A bit like watching noobs typing vi Changes in this release:

  • fix wifi setup issue (wouldn’t affect anyone who is already connected to wifi)
  • reduced the amount of passing args around in cc65 style, so lots of function calls are a bit quicker as they write directly to the target functions values instead of via software stack
  • decreased screen drawing time! yes, the screen updates even faster now, as I’ve replaced the loop of adding 40 per line to using a table lookup. So now drawing strings on the screen is done in constant time instead of taking longer the further down the screen was being printed.
  • config-ng saves its state in appkeys! Currently the only saved value isn’t used, but now you’ll find a shiny new “fenrock” appkey on your SD (fe0c for fe(nr)0c(k) prefix). I’ll be adding colour selection similar to U1MB screen soon which will be saved to the key.

At the moment, colour changes take a few minutes before they kick in on the screen and disappear as soon as you hit a key. (that’s an attract joke folks) (edited)

TCP Support for TNFS

Newton: Yes, the UDP sessions are removed after 6h of inactivity, the TCP sessions are removed 6h after disconnecting. Yesterday we added keep-alive, so if only FujiNet is running, the UDP/TCP sessions are considered alive, even if idle.
Let's see where we can get with 1022 TCP clients, maybe that'd be enough. This will be only active TCP connections.

newton: Created 3 PRs, to bump the TCP connection count, to log metrics and to include timestamp in all logged messages:


fenrock: Hot on its heels, a breaking release. Sorry 3, you were short lived.
All functions now return success status instead of error status in some cases (appkey and hashing functions).
Note, only atari has implemented hashing functions.


GitHub Release Clear Berkelium · FujiNetWIFI/fujinet-lib [4.0.0] – 2024-05-06
This release brings breaking changes in the signature meanings of appkey and hashing functions.
In order to be consistent with other functions in the library, i’ve inverted…

fujinet-lib 4.1.0 information
This release is mostly about appkeys, but also I tidied up the apple2 bus functions, converting from ASM to C.

  • There are now specific libraries for apple2 and apple2enh, ensure you pull the right one down when building your targets.
  • I’ve updated fujinet-apps/fujinet-lib-examples/appkey which works for platforms apple2, apple2enh, and atari. The build in fujinet-lib-examples is a good example of building several apps using common build scripts, and has been updated to fetch the target specific version of the library as per point above
  • The 3 appkey functions in action are seen in iss-tracker/atari and appkey example app:
  fuji_set_appkey_details(CREATOR_ID, APP_ID, DEFAULT);
  if (!fuji_read_appkey(KEY_ID, &read_count, (uint8_t *) &key_data[0])) {
    return false;
  color0 = key_data[0];
  // etc.

  key_data[0] = color0;
  // etc.
  fuji_set_appkey_details(CREATOR_ID, APP_ID, DEFAULT);
  return fuji_write_appkey(KEY_ID, 4, (uint8_t *) &key_data[0]);

Firmware changes for apple2: 
I've made the firmware honor the size of data sent to FN and write only that many bytes. It was already doing this in atari, but apple was writing a fixed length of 64.

I've started work on allowing different keysizes, the default value is 64 as normal, but soon I'll complete support for larger size keys by changing the value in fuji_set_appkey_details. Use DEFAULT and you'll see no changes in how things work. 

N: vs F-Tools on Apple2

Oliver Schmidt: I believe to remember that you discussed this in detail on the Apple II Slack when you started the FujiApple bringup. Not surprisingly 😉 the situation has unfortunately not changed in the meantime: ProDOS has an external block interface, but no external file interface. The interface provider is never asked to open the file "abc", it is always asked to read block number 4711. Adding an external file interface to ProDOS was actually done with the Apple II Workstation card. But as ProDOS doesn't actually have the necessary interface, this was done by completely replacing ProDOS with something that provides the same API as ProDOS. 

This approach:
- Is pretty heavy handed.
- Offers only limited compatibility as programs tend to rely on ProDOS internals in one way or another.
- Doesn't work with Total Replay.

Recently I started a lengthy discussion on the Apple II Slack because I believe that Total Replay not actually using ProDOS hinders any further development regarding ProDOS. If someone would come up with a new/external file interface for ProDOS, Total Replay would be incompatible with it. Not a single person being part of the discussion did even see the problem. Basically Total Replay repeats the Disk II dilemma of forcing new stuff into backward compatibility to "wrong" interfaces. And in just the same way people were back then proud of their code directly accessing the Disk II card, now the Total Replay programmer is proud of his own code directly accessing ProDOS block drivers.

If one would be willing to life with all downsides mentioned above, one could conceptually clearly create an Apple II slot card that works along the lines of the Apple II Workstation card and that uses FN N devices as backend. The A2Pico would be - at least from my POV - be an ideal hardware platform to do so. Given that I have all this already thought through without having (started to) implement it, your assumption is true that I'm not going to do it.

 BTW: The missing ProDOS file interface is also the reason why Apple II emulators usually don't offer to access files in some directory on the host machine - as it is. common with Atari and CBM emulators.
 The closest thing to what one wants is from my POV what was recently added to Apple II-IO-RPi: A virtual disk image where the blocks aren't actually persisted but only on the fly generated at access based on the RPi file system.

Apple IIc Disk usage

Riding Pwnies: Also, re: drive slots in the //c. The Disk ][ drives are just not necessary. If I have a real diskette in the drive, it will always load whatever is in the real drive. If I don't, then whatever is in the Fujinet drive 1 becomes slot 6. This is confirmed in PRODOS and the ROM 4x menu
 At least in my case. Not sure what the behavior is in the original 16k ROM 255

SteveY: Original IIc, the internal drive boots and that's it. External is drive 2.
The disk port was not Smart either. No UniDisk 3.5" drive support.

Riding Pwnies: Can you even use Fujinet in that case?

Can you even use Fujinet in that case?
[11:25 PM]mozzwald: nope
[11:27 PM]SteveY: Well, with the SD card with disk images in read only mode, and not bootable, correct ?
[11:27 PM]SteveY: That would be a disk 2, for disk 2 of 2 virtual drive or data drive only.
[11:27 PM]SteveY: No network
[11:28 PM]mozzwald: you can use Disk II Drive 2 as Read Only on FujiNet and must mount disks via webui. That's it. nothing else would work

Writing FujiNet Games

Eric Carr:

Regarding using the server, it is a few steps:
Your game server POSTs  server details to the lobby api, containing the server endpoint, active players, etc
A player sees the server in the Lobby client and selects a server.
The Lobby client stores the endpoint into an App Key and starts you game client.
Your game client reads the app key to know where to go to start the game.

The App Key Name is in the form of 0001-01-[A unique key for your game]. 
You can register your key by editing here https://github.com/FujiNetWIFI/fujinet-firmware/wiki/SIO-Command-%24DC-Open-App-Key#lobby-client-app-key-ids

For instance, Lobby saves Https://5cardserver/?table=red to 0001-01-01 since 5 Card Stud registered 01.

If you claim 03, then you will expect to read the endpoint from appkey 0001-01-03 when your game client starts, to begin or continue the game happening at that endpoint.

An example POST your game server would send to fujinet.online:8080/server for a hypothetical Chess game with registered app key 03 is:

    "game": "Chess",
    "appkey": 3,
    "server": "Chess By James - Room 1",
    "region": "us",
    "serverurl": "https://chess.jamesor.com/?room=1",
    "status": "online",
    "maxplayers": 2,
    "curplayers": 1,
    "clients": [
            "platform": "atari",
            "url": "TNFS://server/atari/chess.xex"
            "platform": "apple2",
            "url": "TNFS://server/apple2/chess.po"

Whenever any state changes (player joins/leaves, server starts/stops), you post with new values (it's always an upsert).
Lobby Server doc here: http://fujinet.online:8080/docs 


Since the 8 bit client machines can sometimes freeze/need to be rebooted, it's important to be able to pick up where you left off. You could save the "key" details in an app key and retrieve it on app start to store in memory. An app key is a small file on the SD Card in the FujiNet, of (currently) up to 64 bytes. 

Any app key can be read by any program, so to avoid using other program's appkeys, each appkey name is composed of  [ 2 byte creator id prefix ] - [ app id ] - [ key id ].  The idea is, the creator ID points to who wrote the program using the app key, and the [app id] is your own number you assigned to your program, and [key id] to allow multiple keys to be associated with the same program.

For example, my creator ID is E41C (hex).  For the 5 Card Stud game's internal preferences I use these two app keys to store gamer preferences:
E41C-01-01 - Have they seen the help screen? Shown first run only
E41C-01-02 - What theme/color did they select? So, I can use that same theme the next time they start the game

You can register your own creator ID, so others do not use it, by editing the wiki here: https://github.com/FujiNetWIFI/fujinet-firmware/wiki/SIO-Command-%24DC-Open-App-Key#known-creator-ids-and-appids

The Lobby has a reserved creator ID 1 (0001). It stores the player name in 0001-01-00, which your game can read, or optionally set. 

DSK support in 68k

Jeff Piepmeier: Currently, DSK and DISKCOPY4.2 IMAGE files are treated as DCD if you mount them in slots 1-4. We should work on figuring out how to treat them as floppy if mounted in slot 5. That requires inserting sync and sector bits, and doing some weird byte interleaving i think?
The floppy disks have to be told to increment or decrement the head stepper motor. The motor runs a lead screw to which the head carriage is attached. It is SOP to drive the head arbitrarily and all the way to the stop upon power up. That's how the drive calibrates the head location. I think it might watch for the zero sector bit to go active.

Mac 68k FujiNet Driver

marciot: I might have missed the astronomical event of the decade, but at least I have some good news to share. I have successfully achieved bi-directional communications between MacOS and the Pico controller via the floppy port.
 I've only tested it over the emulated HD 20 device, but it should work with an emulated floppy device as well, as I built the protocol to use only sector tags and sector data.
It would be easy to implement and Eject message now that I have communications worked out.
I could even implement commands to control the keyboard/mouse so you can automate tasks, lol.

HTTP Memory Leak

Thom Cherryhomes: good god.
[7:18 PM]Eric Carr: I see it mgHttp allocating to load the CA that doesn't get released, but that wouldn't apply to the fnHttp
[7:19 PM]Eric Carr: PeoplesUrlParser::parseURL 14kb loss? 
[7:20 PM]pnp2084: Certainly iwmNetwork::read_channel_json() is missing a free(msg) after the second call of util_hexdump()
[7:21 PM]Thom Cherryhomes:
PeoplesUrlParser* PeoplesUrlParser::parseURL(const std::string &u) {
    PeoplesUrlParser *url = new PeoplesUrlParser;
    return url;
[7:23 PM]Thom Cherryhomes: i'm pulling away all calls to util_hexdump.
[7:23 PM]Thom Cherryhomes: in iwmnetwork
[7:25 PM]Eric Carr: I see one call without a free. EDIT: nm pnp2084 already found it 🙂 
[7:25 PM]Thom Cherryhomes: that function looks like no end of trouble, thanks for finding that @pnp2084
[7:29 PM]Thom Cherryhomes: @Eric Carr good job on the sounds. the apple speaker isn't the most hospitable output device. 🙂
[7:29 PM]pnp2084: All the 23 repeats of things...I'd suspect the HTTP_CLIENT_CLASS object client allocated by NetworkProtocolHTTP::mount() maybe isn't always deleted? I haven't looked at all the code, but  ~NetworkProtocolHTTP() doesn't delete client.  Also, ::mount() doesn't check if client is already allocated.
[7:33 PM]Eric Carr: That' what I'm seeing
[7:33 PM]Eric Carr: Well, the "ca" isn't deleted inside mgHttpClient (fujinet pc anyway - though that is low low priority compared to esp builds) 
[7:35 PM]pnp2084: Again, not following all the code, but I don't see anything that deletes the urlParser created by iwmNetwork::create_url_parser().  Could also get assigned on top of the existing one, that's harder to tell.
[7:37 PM]Thom Cherryhomes: we're doing a lot better now. I'm checking in changes.
[7:38 PM]Thom Cherryhomes: we're actually hovering at 63000 bytes
[7:39 PM]Thom Cherryhomes: sweet jesus, it's stable
[7:40 PM]Thom Cherryhomes: oh god i have tears in my eyes
[7:40 PM]Thom Cherryhomes: this leak had kicked my ass for a year straight

LittleFS switch from SPIFFS

it's alive!
[10:34 AM]fenrock:
15:33:10.440 > --~--~--~--
15:33:10.440 > FujiNet v1.3 2024-04-26 06:08:28 (ATARI) Started @ 6
15:33:10.441 > Starting heap: 4299688
15:33:10.441 > [src/main.cpp:135] main_setup(): Heap: 154383
15:33:10.443 >
15:33:10.466 > Detected Hardware Version: 1.6.1 and up
15:33:10.466 > Safe Reset button ENABLED on GPIO 14
15:33:10.495 > LittleFS mounted.
15:33:10.576 > SD mounted.
15:33:10.576 > fnConfig::load
15:33:10.576 > Load fnconfig.ini from SD
15:33:10.576 > fopen = /fnconfig.ini : ok
15:33:10.579 > fnConfig::load read 1006 bytes from config file
15:33:10.582 > Reading wifi section
15:33:10.587 > FLASH Config Storage: Enabled
15:33:10.591 > fnConfig::load read 1006 bytes from FLASH config file
15:33:10.591 > disk UNMOUNT
15:33:10.594 > FileSystemSDFAT::filehandler_open autorun-ng-img.atr rb
15:33:10.594 > fopen = autorun-ng-img.atr : ok
15:33:10.595 > new FileHandlerLocal
15:33:10.595 > disk MOUNT
15:33:10.595 > ATR MOUNT
15:33:10.596 > FileHandlerLocal::seek
15:33:10.596 > FileHandlerLocal::read
15:33:10.596 > mounted ATR: paragraphs=5760, sect_size=128, sect_count=720, disk_size=0
15:33:10.599 > Mounted Alternate CONFIG autorun-ng-img.atr

0 to mounted config in  0.159s 
[10:34 AM]DjayBee: 🎉
[10:34 AM]Thom Cherryhomes: that's just wonderful.
[10:35 AM]fenrock: @Andy Diller SOME HEADLINES FOR YOU RIGHT HERE
Many memory leaks vapourized
Startup time reduced massively
TNFS tcp working across all platforms
[10:35 AM]Thom Cherryhomes: so ok, big lesson with spiffs? every file increases startup time substantially.
[10:36 AM]Thom Cherryhomes: because from what I see in the spiffs initialization code, it treats the whole flash space as one big linear chonk of tape, and it builds the index when the filesystem is attached to vfs.
[10:36 AM]Thom Cherryhomes: which is oooof
[10:37 AM]Thom Cherryhomes: so now I feel compelled to mention, because he was the one who brought littlefs here: 

@jaime idolpx was right.

This commit made the change to littleFS the default:

3 AM]fenrock: @here
Anyone building fujinet-firmware from master and using build.sh will need to ensure they add the -f flag when they upload their firmware image to also update the filesystem.
This is only required to be done once, as we have changed the default to be LittleFS for faster start times.
This will change your flash file storage from SPIFFS to LITTLEFS.
# clean, build, upload filesystem and firmware:
./build.sh -cbfu

You do not need to keep adding -f it's a one time thing.

NetCat on A2

superbenk: Run netcat.po from apps.irata.online/Apple_II/FujiNet/ & try to go to N:TELNET://BBS.FOZZTEXX.COM/


[4:10 AM]Oliver Schmidt: I'm a bit lost... Is there any point in having a newly written program like i.e. netcat use the fn modem device? Or is the modem device only relevant for "old" programs that insist in sending AT cmds and receiving modem status reports. Or asking in other terms: Can the fn modem device talk any protocol "to the outside" that isn't also available via the protocol adapter that i.e. netcat uses? I hope that the question at least makes sense... 

[11:05 AM]Oliver Schmidt: @Thom Cherryhomes Maybe you can answer my question. Sorry if this is the wrong channel...
[11:07 AM]fenrock: I'm interested in this too, it'll help my understanding of what modem is supposed to be
[11:07 AM]Thom Cherryhomes: @Oliver Schmidt i'll try to answer this question, it's a bit weird on the apple2...

The modem device was meant for legacy comms programs. On the Atari, it maps to the R: device, and has an Atari 850 Interface emulation bundled with it.

On the apple2, it's a smartport device. And you know the issues there.
[11:07 AM]Thom Cherryhomes: the modem can't really be used in its intended use on the apple2.
[11:07 AM]Thom Cherryhomes: with the current hardware 
[11:08 AM]Thom Cherryhomes: We could potentially connect the protocol stack into the modem.
[11:10 AM]Thom Cherryhomes: short answer is netcat can connect to a whole lot more.
[11:11 AM]Oliver Schmidt: I understand the Apple2-Modem issue. I'm more wondering about the "outside view". So totally independent from the API a program uses: Can the modem give me some functionality I can't get via the protocol adapters? Currently it seems rather like the opposite: The protocol adapters allow for SSH while the modem doesn't allow for SSH. Maybe my question seems weird so yet another perspective: Would netcat gain any functionality by using the FN modem?
[11:11 AM]Thom Cherryhomes: no, it wouldn't.
[11:11 AM]Thom Cherryhomes: the modem really was meant for legacy comms stuff.
[11:11 AM]Oliver Schmidt: That's the answer to my question. Thanks 👍
[11:12 AM]Thom Cherryhomes: the modem is older than the network adapter.


[11:26 AM]Oliver Schmidt: So the the netcat as is stands can't do SSH as it doesn't have a way to ask the user for the credentials and call the commands in question, right?
[11:26 AM]fenrock: The SSH protocol could/should read the user/pass off ssh://user:pass@url for non key passwords, but means they are visible
[11:27 AM]Oliver Schmidt: Ah, so they can be both given as part of the URL as well as set via command?
[11:28 AM]fenrock: I would expect us to support that as it's the way basic Auth works in http.
[11:29 AM]fenrock: Need to check it though. The URL parser has lots of things in it, just a matter of hooking them together
[11:31 AM]Oliver Schmidt: As you sure expect I'm asking all this as I want to learn if I can take the way netcat interacts with fn-lib and replace the naive netcat screen / keybord I/O with my VT100 client. Or do I need to wait some more?
[11:32 AM]Thom Cherryhomes: you know my answer. 🙂
[11:40 AM]Oliver Schmidt: Sorry to disappoint you but actually I don't 🙁
[11:40 AM]Thom Cherryhomes: go fro it.

Nightly Automated Builds

Fn nightly builds.

superbenk: FYI, nightly firmware builds are happening now!  Every night a job will run attempting to build the current state of the master branch of the firmware repository to generate bleeding edge zip file builds that can be installed via the FujiNet Flasher tool.  These nightly builds will automatically be attached to this special pre-release in the repo where you can download them.   Absolutely NO guarantees on whether they will work properly as they are built nightly & will likely contain bugs from time to time.  Use at your own “risk” (you can always just flash back to a stable version if you want).


Wiki page with some more details: 

Categories: Uncategorized

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.