RAPID 10
Items
Webdav server running on Firmware (Jaime)
- using duck to load files from PC via webdav right into FN SD card
- [11:02 PM]Thom Cherryhomes: @here To compliment the WebDAV server support for SD, there is now an mDNS advertisement for a _webdav service, which points to /dav, giving us auto mounting on Linux (plus windows and osx support)
Yahtzee Game from EricCarr
- Fujitzee came together and works for Atari on Aug 6th
- Multi player games with Thom, Eric, Ben, Andy testing
- Lobby server is already showing games – Blog post – Fujizee Review
First release of FN-Lib (4.4.0) that contains support for C64 (fenrock)
- First release of C64 network library (json tests/mastodon/httpbin all working, net-read has some issues) Released so it can be tested more thoroughly.
AppleII DISKII “flux” images write support (fozztexx)
- fozztexx forked the firmware and has been working on enabling write for DISKII flux images (WOZ).
- You can follow him on masto- @fozztexx
First Firmware builds on ESP32-S3 board! (@gennaro and @me)
Firmware Release! v1.4.0 released for Atari, Apple, ADAM and Coco
- Coco added to the list of official releases
Script to scaffold out a FN app (for cc65, fn-lib) (fenrock)
- Fenrock added a scaffolding script to the fujinet-build-tools repo
- it will create a start app with all the right folders, makefiles and basic structure to build an app for fujinet in C
Bouncy Demo Released
- A demo of the very first iterations of the Bouncy system were shown by fenrock running on two Ataris
Cool Videos
- https://www.youtube.com/watch?v=dxxvLEw3aa4
- TPUG Meeting – June 2024 – ft. Jaime Idolpx – Latest Meatloaf Developments – Commodore IEC Device
- Play Yahtzee: https://youtu.be/AHDgpuEzopc
DNS fixed for FN
BobC: Thanks a lot for finding the commit where mdns was removed! I haven’t dealt with GitHub much so I wasn’t sure how to search for something. Thom did say it sounded like an mdns problem. Anyway, after flashing yesterday’s daily, I’m able to use http://fujinet.local/ again.
Fujitzee Released
Mock up
Lobby Supports Fujitzee
C64 FujiNet Liberation
fenrock: ok, I’ve hooked up the setting the channel mode to protocol/json in firmware (adding the command “chmode”), which calls the set_channel_mode function, and I’ve got fujinet-lib calling it correctly, so I present the first fujinet-lib based chuck norris quote
CC65 and APPLEII ENH
fenrock: We are straying into “why did cc65 choose to make apple2 target like they did” territory. I think @Oliver Schmidt may have to answer your specific question about 80col on II+. He did the cater port, I was just answering why I thought there isn’t an apple2 target for that application.
Oliver Schmidt: A Videx 80 col. card is considered an add-on. cc65 targets never make use of add-ons. If one would start doing so, one would end up with hundreds of targets.
Cater is in one aspect different than other cc65 programs: It doesn’t use the CONIO layer for output, which is available in both 40 and 80 col. Rather its assembly code directly writes to the video RAM. That code is only available for 80 col. – and with 80 col. I mean here the 80 col. of the //e, not Videx 80 col. Therefore Cater is (totally independent from good or bad cc65 decisions) a //e-only program.
fenrock: Ah, thanks Oliver, I hadn’t realized that.
Oliver Schmidt: As discussed: The cc65 apple2 target actively converts lowercase chars to uppercase chars on output – both via STDIO and CONIO.
There are definitively machines that can’t run programs built for the apple2enh target but have lowercase output capabilities. Even if there weren’t, one can still say that one wants to have lowercase output if the current machine has it.
Anyhow, the cc65 decisions were made the way they were made and we can’t turn back time. I’m willing to extend cc65. But then every program making use of that extension will fail to link on everything but the cc65 git HEAD with some undefined external symbol. If you are willing and able to deal with that, then – and only then – I’ll look into that cc65 extension.
fenrock: For me this is fine, and a great addition for fujinet apps going forward:
I don’t use cc65 from releases, but from source, and this can be part of our guide to building C apps using fujinet-lib. Any application we publish that requires latest cc65 from source would be clearly labelled in the README. Any application built and pushed to “official” tnfs servers (which is a loose term and coincides with the new tnfs channel) would be built with an up to date cc65 too, so would work on the target machines without them having to do anything. So I see no issue in this extension, and am very happy/thankful at the offer to do the changes.
It won’t help cater though, to address @ppuskari ’s point on II+ without the 80col card of the //e
Oliver Schmidt: Yeah, the Videx 80 col. card is a completely different thing with a completely different memory layout and different
Okay, then let me check how to do that best. I’ll report here on the result…
Apple II Multiple Network Devices
July 30
3:40 AM]fenrock: Looking for some help from those who understand the Apple2 SmartPort better than I do.
In firmware for IWM at the moment, we have a single SP device named “NETWORK” that acts as the device for doing network traffic.
I want to make the A2 support multiple network interfaces, e.g. N1:, N2:, etc
There’s already an array of devices in the FN for network, but it only uses 1. However I want to go a different route.
The question I have is, can a single NETWORK SP device handle multiple network sub-devices, or do we have to have lots of SP devices?
I’ve refactored locally the IEC (c64) network class to hold a MAP(INT, NetworkData), where NetworkData is all the usual stuff like receiveBuffer, transmitBuffer, deviceSpec, protocol, json etc. (It’s part of my grand scheme to rewrite Network protocols from scratch)
On the 64, the channel you open (e.g. OPEN 16,…) picks the correct NetworkData class from the map.
I’m trying to refactor A2 to do the same, but before I go too far, I’m wondering if it’s possible to use 1 SP device in this way, or if there are limitations. I can’t see why it would though as it’s just a device receiving and sending traffic.
As long as when the NETWORK device is being used, we can identify which “channel” or sub-device is being used, it will pick out the correct receive/transmit/json/protocol, I think it should work. There’s no caching or other fancy stuff going on.
I can identify a channel (or device id, but that’s an overloaded term) from the “Nx:” in the open, but I think I may still need to send that ID down to the device as we’re not always sending the Nx: in a read/write operation.
I may have to somehow squeeze that ID into the data sent to SP. Maybe it’s just another byte in the payload
Any thoughts?
fenrock
Say hello to 2 different N devices reading from different URLs. On apple2 hardware. After the first one gets its data, it closes, and the 2nd one continues to be able to read, as it hasn’t closed yet. So yup, apple2 supporting multiple network devices is working. This is working over a single “NETWORK” device in fujinet, using sub-device ids to separate which http client is reading/parsing json etc. And because it’s a map and uses a byte for the sub-device id as the key into the map, it can in theory support up to 255 network devices (fujinet-lib only parses Nx: at the moment so 1–9, but I’ll change that). I want to do a bit more testing, e.g. ensuring resources are freed up on close, but it’s looking good. (edited)
Each network client takes about 10k of memory per open connection:
10:48:46.862 > [lib/http/fnHttpClient.cpp:37] ~fnHttpClient(): free low heap: 25567 … 10:48:46.904 > [lib/http/fnHttpClient.cpp:37] ~fnHttpClient(): free low heap: 35047 … 10:48:46.946 > [lib/http/fnHttpClient.cpp:37] ~fnHttpClient(): free low heap: 44499 … 10:48:46.989 > [lib/http/fnHttpClient.cpp:37] ~fnHttpClient(): free low heap: 53923 … 10:48:47.033 > [lib/http/fnHttpClient.cpp:37] ~fnHttpClient(): free low heap: 63363
i.e. using 5 connections.
I ran a test that does following 100 times in a tight loop: opens 5 connections/reads from them all / closes them all. So effectively 500 open/read/close cycles, and the memory was completely stable. I can’t see most apps opening more than 2 realistically, 5 is more than I need, but it’s a good data point
More Updates:
Summary of changes I’ve made today (for future RAPIDs etc):
- AppleWin updated for sending network-unit id
- AppleWinLinux has this change, and also pulled down latest changes from upstream linux port
- fujinet-lib v4.5.0 released to support apple2 multiple-network ids
- fujinet-firmware updated with new NetworkData encapsulation of protocol/json/strings for a network connection. This is implemented on IEC (c64) and IWM (apple2) targets. I haven’t ported it to atari etc yet. See https://github.com/FujiNetWIFI/fujinet-firmware/blob/master/lib/network-protocol/network_data.h which supports multiple network units for those platforms
The NetworkData class takes many of the fields out of the Network classes, so they can be encapsulated into a context and saved into a Map so that multiple networks can be quickly found and used from host to FN.
DISK II Write Support
Spent most of yesterday convincing #FujiNet to let me set a Disk II slot as writable and stop signaling disk is write protected. DOS 3.3 tries to save, but obviously it doesn’t work yet. 😉 Can see #AppleII switch /WRREQ from read mode to write mode and see it send data which flips on ones instead of pulse on ones.
I was surprised that DOS 3.3 got hung during the save, I thought it would merrily write without noticing that no sectors were actually updating.
RetroComputing #VintageComputing
FN Firmware builds on S3
July 31
Discord user Gennaro Tortone has been pushing the bring-up for the 2600 FujiNet, which will use a S3 and Pico together for the 2600. Gennaro has pushed S3 builds but it was user @me that popped in and completed the work and got the mainline FW to build on a S3 board.
me: @Gennaro Tortone i cannot build S3 version [2:44 PM]me: i get "error: implicit declaration of function 'btsnd_hcic_ble_sync_sem_init'; did you mean 'btsnd_hcic_ble_set_phy'? [-Werror=implicit-function-declaration] " [2:44 PM]me: just downloading actual github repo [2:45 PM]me: With these changes on platform.io [2:45 PM]me: [env:esp32s3] platform = espressif32@${fujinet.esp32_platform_version} board = fujinet-esp32s3 [2:45 PM]me: and building esp32s3 [2:45 PM]me: any clue? [3:28 PM]mozzwald: you'll need to disable BlueTooth in sdkconfig.esp32s3 [3:30 PM]me: ok, i thought it was done on repo. TNX!! ]Gennaro Tortone: now ESP32-S3 changes are merged in fujinet-firmware [3:43 PM]Gennaro Tortone: you can use the following commands: [3:44 PM]Gennaro Tortone: ./build.sh -s fujinet-atari-esp32-s3-wroom-1-n16r8 4:18 PM]Gennaro Tortone: ok [4:18 PM]me: It's building.... [4:19 PM]me: but i dont unders [5:55 PM]me: Ok, Ok... i know.... i must be sleeping.... [5:56 PM]me: ... but you know guys how goes that .... [5:56 PM]me: removed first / from data Path on platformio.ini and FS builded, flashed and : [5:56 PM]me: 23:54:34.368 > 23:54:34.368 > --~--~--~-- 23:54:34.368 > FujiNet v1.3 2024-04-26 06:08:28 (ATARI) Started @ 45 23:54:34.368 > Starting heap: 8553136 23:54:34.368 > [src/main.cpp:135] main_setup(): Heap: 205811 23:54:34.368 > 23:54:34.368 > Detected Hardware Version: 1.0 23:54:34.368 > Button A Disabled 23:54:34.368 > Button B Disabled 23:54:34.368 > Button C (Safe Reset) Disabled 23:54:34.368 > LittleFS mounted. 23:54:34.368 > E (250) sdmmc_sd: sdmmc_init_sd_if_cond: send_if_cond (1) returned 0x108 23:54:34.368 > E (250) vfs_fat_sdmmc: sdmmc_card_init failed (0x108). 23:54:34.368 > SD mount failed with code #264, "ESP_ERR_INVALID_RESPONSE" 23:54:34.368 > fnConfig::load 23:54:34.368 > Load fnconfig.ini from flash 23:54:34.368 > fnConfig::load read 601 bytes from config file 23:54:34.368 > Reading wifi section 23:54:34.368 > FLASH Config Storage: Enabled 23:54:34.368 > fnConfig::load read 601 bytes from FLASH config file 23:54:34.368 > disk UNMOUNT 23:54:34.368 > FileSystemLittleFS::filehandler_open /autorun.atr rb 23:54:34.368 > new FileHandlerLocal 23:54:34.368 > disk MOUNT 23:54:34.368 > ATR MOUNT 23:54:34.368 > FileHandlerLocal::seek 23:54:34.368 > FileHandlerLocal::read 23:54:34.368 > mounted ATR: paragraphs=5760, sect_size=128, sect_count=720, disk_size=0 23:54:34.368 > Creating a default printer using FS_LITTLEFS storage and type 1 23:54:34.368 > SIO SETUP 23:54:34.368 > Set HSIO baud from 19200 to 67431 (index 6), alt=68209 23:54:34.368 > Available heap: 8534384 23:54:34.368 > Setup complete @ 382 (337ms) 23:54:34.368 > [src/main.cpp:436] main_setup(): Low Heap: 187443 23:54:34.368 > 23:54:34.368 > WiFiManager::start() complete 23:54:34.368 > WIFI_EVENT_STA_START [6:00 PM]me: Thank you guys for the help!! [6:01 PM]me: Next stations : Conect it to Fpga Atari Core, connect an SD Card, C64 version.... [6:01 PM]me: good night
Template application
fenrock: I’ve add a template application to fujinet-build-tools and a script for generating a completely new applicaiton that fully builds, and contains makefiles, tools, and the subdirectory breakdown to show how to use target specific code (i.e. “apple2”, “atari” etc subdirs) with README files all over the place.
Please have a go, feedback / MRs welcome for small issues.
There need to be things like picoboot.bin sorted I think, but it’s 99.999% useable as is.
./create-app sample-app ../
cd ../sample-app
make
you can init this for git
git init .
will create “../sample-app/” folder with entire project structure, and the app name “sample-app”
See docs at https://github.com/FujiNetWIFI/fujinet-build-tools/
GitHub
Bouncy
A Q and A session between an Apple2 dev and fenrock
Edited for Clarity and consistency
Q: What is Bouncy exactly? I’ve looked at your recent Bouncy test. I am – once more – afraid that I don’t understand the scenario / use case, but it seems interesting.
A: fenrock: Thanks! The use case / setup is:
* It's just a big demo of cross platform fujinet-lib (network) data reading
* there is a world with body objects in it, of various sizes, 1x1, 2x2, 3x3, 5x5
* each body has a direction, speed, and mass
* they bounce around in the world off each other, and currently wrap at the edges - but I will make that configurable to bounce instead off the world boundary edges instead of wrapping to the other side of the world
* the code for the world is a Kotlin application with a rest controller and endpoints for clients to connect, and get the body objects within their viewport
When a client registers it causes the world total size to grow, so 2 clients don’t overlap.
Clients simply register, download the shapes of objects, then have a main loop to get all the bodies in their viewport.
The server sends very small amount of data, just shape ids and their x,y coordinates translated to the client’s screen size (which the client sends as part of the registration).
Clients are completely free to interpret the shape data how they want, it’s sent as NxN chars (eg 25 chars for 5×5 body) which the client can paint how they want, I used atascii chars for Atari, but graphical blocks and colours are equally good and would look super cool as shapes move across screens
The client is incredibly dumb, all it has to do is paint the shapes at the coordinates it is given. All physics, bouncing, etc is done by the server, it was way too much for the client to handle, so there’s a central service that runs the simulation, clients just constantly ask for what they can see, and the server calculates for each body every client that can see any part of the object (including partial views due to overlap), which gives the illusion of them passing between screens, obviously
Q: What made you want to create this demo?
A: fenrock: The idea behind bouncy-world was something we discussed at VCFE, we were looking at the “rock paper scissors” graphical demo for the c64 (see https://csdb.dk/release/?id=231377 – it’s a graphical screen with icons that bounce around).
I’d been trying to think of a demo we could do between different FujiNets at the show (they are usually lined up in a row on the desk).
I’d previously seen many many years ago a bird flying between 2 BBC archimedes machines that were plugged together to communicate where the “bird” was, and I thought a multi-client asteroids type application would be a good demo, where things would move between the screens like the birds did in the bbc demo.
It could be written in fujinet-lib as a cross platform application. JeffP was very keen to see something like this for a VCF show.
So a couple of months ago, I started writing the server side. I had originally thought it to be client to client driven, but very quickly realized that would be a nightmare to write, so went with a central controller model, a single simulation (which I’ve written plenty of over last couple of years), with clients acting as visual portals into the simulated world.
So that’s the background for it all. We wanted stuff to show off at VCF.
Q: Thanks for the comprehensive background. You write “download the shapes of objects” and then “clients are completely free to interpret the shape data how they want”. Does that mean you have some machine-independent “shape description language”? Maybe SVG?
A: Ha, it’s just ascii chars, that pseudo represent what I’m trying to convey:
I add the shapes to the server like this:
shapes.addAll(listOf(
createShape(4.8f, fromString(
“”“
| ┬┬
|└┤├┼┤
| ┼ ┼
|┌┤ ├┤
| ┼┴┴
”“”.trimMargin()
)
),
but the fromString method converts them to simple ascii here: https://github.com/markjfisher/bounce-world/blob/master/src/main/kotlin/data/ShapeCreator.kt#L16
e.g.
‘┌’ -> ‘r’.code
‘┐’ -> ‘)’.code
‘└’ -> ‘L’.code
‘┘’ -> ‘!’.code
‘┤’ -> ‘J’.code
‘├’ -> ‘t’.code
The “display” routines in the host are simple character prints at the moment, but it could do gfx instead.
for (i = 0; i < width; ++i) {
y = startY + i;
firstXInRow = false; // Reset for each row
// Only proceed if the row is within the vertical screen bounds
if (y >= 0 && y < SCREEN_HEIGHT) {
for (j = 0; j < width; ++j) {
x = startX + j;
// Check if the current character is within the horizontal screen bounds
if (x >= 0 && x < SCREEN_WIDTH) {
if (!firstXInRow) {
firstXInRow = true; // Found the first x position in this row within bounds
gotoxy(x, y);
}
cputc(data[i * width + j]); // Print and move to the next position
} else if (firstXInRow) {
// If we were printing characters and have now gone out of bounds, break
break;
}
}
}
}
you can see it’s just getting to the right row/column, then printing the chars with cputc() But graphics blocks are possible too.