Skip to content

FujiNetWIFI/adam-smartbasic-1x-with-fujinet

Repository files navigation

SmartBASIC 1.x — FujiNet Commands

A manual for the FujiNet network statements added to SmartBASIC 1.x R21 (built from the Rev-20 source) for the Coleco Adam. These commands let BASIC programs talk directly to a FujiNet peripheral — fetching web pages, calling JSON APIs, browsing TNFS file servers, and loading/saving programs over the network — without any PRINT CHR$(4) plumbing.

New to the internals or building the binary? See FUJINET.md for the implementation, hook points, and build notes. Runnable examples are in NFUJI.BAS.


Contents


Quick start

Fetch a web page and print it to the screen:

10 NOPEN 1,"N:HTTP://WWW.GNU.ORG/LICENSES/GPL-3.0.TXT",4,0
20 NSTATUS 1,BW,CONN,ERR
30 IF BW=0 AND CONN=0 THEN 80
40 IF BW=0 THEN 20
50 L=BW : IF L>255 THEN L=255
60 NREAD 1,A$,L : PRINT A$;
70 GOTO 20
80 NCLOSE 1

That is the whole pattern: open a channel, poll status for bytes waiting, read them, and close when the host disconnects.


Concepts

Channels and device numbers

The connection commands (NOPEN, NCLOSE, NSTATUS, NREAD, NWRITE, NJSONPARSE, NJSONQUERY) take a device number (a "channel") as their first argument. The number 1..15 selects an EOS character device:

First argument EOS device Common name
1 9 N1:
2 10 N2:
15 23 N15:

In short, device = argument + 8. Channels 1 and 2 are the ones most firmware builds expose; treat each channel as one independent connection. Passing 0 or a value above 15 raises an Illegal Quantity error.

The filesystem and program commands (NCD, NDIR, NMKDIR, NRMDIR, NDEL, NLOAD, NSAVE) take no device number — they are one-shot operations that always use channel 1 (N1:, EOS device 9). Because the firmware runs them through that device, they displace whatever connection was open on channel 1; use channel 2+ for connections you want to keep across filesystem operations.

Device specifications (URLs)

Where a command takes a path or URL, it is a FujiNet devicespec string that begins with the network prefix N: and a protocol:

N:PROTO://[HOST][:PORT]/PATH...

Examples:

N:HTTP://WWW.GNU.ORG/LICENSES/GPL-3.0.TXT
N:HTTPS://API.EXAMPLE.COM/V1/STATUS
N:TCP://192.168.1.5:9000/
N:TNFS://TMA-3/GAMES/

Supported protocols depend on your FujiNet firmware, but typically include HTTP, HTTPS, TCP, UDP, TNFS, FTP, and SSH. A trailing / usually denotes a directory.

Open modes

NOPEN's third argument selects how the connection is opened:

Mode Meaning
4 Read (e.g. HTTP GET)
8 Write (e.g. HTTP PUT)
12 Read/write
13 POST

Translation modes

NOPEN's fourth argument controls end-of-line translation between the host and the Adam:

Trans Meaning
0 None (raw bytes)
1 CR
2 LF
3 CR/LF
4 PETSCII

Use 0 for binary data; use 1 or 3 for text you intend to PRINT.

The status / read loop

FujiNet streams data asynchronously, so you don't read a fixed length — you ask how much is waiting and read that. NSTATUS returns three values:

  • bytes waiting — how many bytes are ready to read right now;
  • connected1 while the resource is still open, 0 at end of stream;
  • error — the device's own status/error code (1 is the FujiNet "OK").

The canonical loop is: poll NSTATUS; if bytes are waiting, NREAD them; stop when connected is 0 and nothing is waiting. See Quick start.

String length limit

SmartBASIC strings hold at most 255 bytes, so NREAD, NWRITE, and NJSONQUERY move at most 255 bytes per call. For larger transfers, loop (read a chunk, process it, read again).


Command reference

Notation: d is a device number (1..15); $ suffixes mark string variables/expressions; other arguments are numeric.

Connection commands

NOPEN d, url$, mode, trans

Open a connection on channel d to the resource named by url$, using the given open mode and translation mode.

NOPEN 1,"N:HTTP://WWW.GNU.ORG/LICENSES/GPL-3.0.TXT",4,0

Opening a new resource on a channel replaces whatever was open there.

NCLOSE d

Close the connection on channel d. Always close channels you open.

NCLOSE 1

NSTATUS d, bw, conn, err

Query channel d and store three results into the numeric variables you name:

  • bw — bytes waiting (0–65535);
  • conn — connected flag (1 = still open, 0 = finished);
  • err — device error/status code.
NSTATUS 1,BW,CONN,ERR
IF ERR>1 THEN PRINT "DEVICE ERROR ";ERR

If bw can exceed 32767, store it in an integer variable (e.g. BW%); a plain floating-point variable would show large values as negative.

NREAD d, buf$, len

Read up to len bytes (max 255) from channel d into the string variable buf$. buf$ is set to exactly the bytes actually read, which may be fewer than len.

L=BW : IF L>255 THEN L=255
NREAD 1,A$,L
PRINT A$;

NWRITE d, buf$, len

Write len bytes from buf$ to channel d. If len is larger than the length of buf$, only LEN(buf$) bytes are sent.

P$="HELLO FUJINET"
NWRITE 1,P$,LEN(P$)

JSON commands

NJSONPARSE d

Tell channel d to parse the response body it has received as JSON. Call this once after the data has arrived, before issuing queries.

NJSONPARSE 1

NJSONPARSE also switches the channel into the firmware's JSON mode (a requirement for reading query results). After it, NREAD on that channel returns JSON query values rather than the raw body; issue a fresh NOPEN if you want raw reads again.

NJSONQUERY d, query$, a$

Run the JSONPath/pointer query$ against the parsed JSON on channel d and put the result text into the string variable a$ (up to 255 bytes).

NJSONQUERY 1,"/0/content",C$
PRINT C$

Filesystem commands

These operate on the file server addressed by the devicespec (e.g. a TNFS host). They take no device number — each is a one-shot operation on channel 1 (see Channels and device numbers).

NCD path$

Set the current N: directory (prefix).

NCD "N:TNFS://TMA-3/GAMES"

NDIR path$

Open the directory named by path$ and print its listing to the screen, then close it. Self-contained — no read loop needed.

NDIR "N:TNFS://TMA-3"

NMKDIR path$

Create the directory named by path$.

NMKDIR "N:TNFS://TMA-3/NEWDIR"

NRMDIR path$

Remove the directory named by path$ (it must be empty).

NRMDIR "N:TNFS://TMA-3/OLDDIR"

NDEL path$

Delete the file named by path$.

NDEL "N:TNFS://TMA-3/OLDFILE"

Program commands

These transfer a BASIC program as an ASCII listing (the same text you'd see from LIST), so they interoperate with other tools and editors. Like the filesystem commands they take no device number and always use channel 1.

Experimental. Use NLOAD/NSAVE from immediate mode (like LOAD/SAVE), not from inside a running program — NLOAD rewrites program memory as it reads. Validate these two on real hardware before relying on them.

NSAVE path$

Write the current program to path$ as an ASCII listing.

NSAVE "N:TNFS://TMA-3/MYPROG.BAS"

NLOAD path$

Read an ASCII program listing from path$ and enter it line by line (numbered lines are added to the program; blank lines are ignored).

NLOAD "N:TNFS://TMA-3/MYPROG.BAS"

Recipes

HTTP GET to the screen

10 NOPEN 1,"N:HTTP://WWW.GNU.ORG/LICENSES/GPL-3.0.TXT",4,0
20 NSTATUS 1,BW,CONN,ERR
30 IF BW=0 AND CONN=0 THEN 80
40 IF BW=0 THEN 20
50 L=BW : IF L>255 THEN L=255
60 NREAD 1,A$,L : PRINT A$;
70 GOTO 20
80 NCLOSE 1

Read a JSON API field

10 NOPEN 1,"N:HTTPS://FUJINET.ONLINE/FUJINET.JSON",4,0
20 NJSONPARSE 1
30 NJSONQUERY 1,"/0/content",C$
40 PRINT C$
50 NCLOSE 1

Send data over TCP

10 NOPEN 1,"N:TCP://192.168.1.5:9000/",12,0
20 M$="HELLO FUJINET" : NWRITE 1,M$,LEN(M$)
30 NSTATUS 1,BW,CONN,ERR
40 IF BW=0 THEN 30
50 L=BW : IF L>255 THEN L=255
60 NREAD 1,R$,L : PRINT R$;
70 NCLOSE 1

Browse and manage a TNFS host

10 NCD "N:TNFS://TMA-3"
20 NDIR "N:TNFS://TMA-3"
30 NMKDIR "N:TNFS://TMA-3/NEWDIR"
40 NDEL "N:TNFS://TMA-3/OLDFILE"
50 NRMDIR "N:TNFS://TMA-3/NEWDIR"

Save and reload a program over the network

] NSAVE "N:TNFS://TMA-3/MYPROG.BAS"
] NEW
] NLOAD "N:TNFS://TMA-3/MYPROG.BAS"
] RUN

Errors and troubleshooting

Argument errors are reported as ordinary BASIC errors:

Error Cause
Illegal Quantity Device number outside 1..15, a numeric argument outside 0..255, or the selected network device is not present on AdamNet (e.g. no FujiNet attached)
Type Mismatch A string was given where a number was expected (or vice versa), e.g. a non-string in a url$/buf$ slot

Network and device errors are not raised as BASIC errors. A failed open, read, or write does not stop your program — instead, the condition shows up in NSTATUS's err value (and a read simply returns no bytes). Always check NSTATUS when something doesn't behave:

NSTATUS 1,BW,CONN,ERR
PRINT "WAITING=";BW;" CONNECTED=";CONN;" ERR=";ERR

err = 1 is the FujiNet "OK" status. Other common values include end-of-file and protocol-specific codes; consult your firmware's documentation.

Nothing happens / hangs: make sure the FujiNet is powered and on AdamNet, that the channel number matches an available network device (usually 1 or 2), and that your devicespec begins with N: and a supported protocol.


Limitations

  • 255 bytes per transfer for NREAD/NWRITE/NJSONQUERY (loop for more). Larger bursts from the device are buffered internally (up to 1024 bytes per packet) and served to successive NREADs, so nothing is lost.
  • NREAD blocks until the device has something to send — poll NSTATUS and only read when bytes-waiting is nonzero.
  • NSTATUS bytes-waiting above 32767 should use an integer (%) variable.
  • NDIR opens the path as a directory (open mode 6, the firmware's DIRECTORY access mode) and drains it to the screen before closing.
  • NLOAD/NSAVE are experimental (they reuse the interpreter's LIST and line-entry paths) and are intended for immediate mode. NLOAD accepts CR, LF, or CR/LF line endings.
  • The command bytes (including , * + ! for the filesystem ops and 0xFC for JSON channel mode) are confirmed against the current FujiNet firmware's lib/device/adamnet/network.cpp.

Quick reference

Commands

Command Form Summary
NOPEN d, url$, mode, trans Open a connection
NCLOSE d Close a connection
NSTATUS d, bw, conn, err Bytes waiting / connected / error
NREAD d, buf$, len Read ≤ len bytes into buf$
NWRITE d, buf$, len Write min(len, LEN(buf$)) bytes
NJSONPARSE d Parse the response as JSON
NJSONQUERY d, query$, a$ JSONPath query → a$
NCD path$ Set the N: directory (channel 1)
NDIR path$ Print a directory listing (channel 1)
NMKDIR path$ Make a directory (channel 1)
NRMDIR path$ Remove an empty directory (channel 1)
NDEL path$ Delete a file (channel 1)
NLOAD path$ Load an ASCII program listing (channel 1)
NSAVE path$ Save the program as ASCII (channel 1)

Open modes: 4 read · 8 write · 12 read/write · 13 POST Translation: 0 none · 1 CR · 2 LF · 3 CR/LF · 4 PETSCII Device: channel argument n → EOS device n + 8 (1→9, 2→10, …); the no-argument commands always use channel 1 (device 9)


Installation

The commands are built into the SmartBASIC 1.x binary assembled from SmartBASIC 1.x Rev-20_SB1X20Y.ASM. Run make to assemble it with z88dk's z80asm and package it into a bootable EOS DDP image (SmartBASIC 1.x Rev-20_SB1X20Y.ddp) — boot that in an emulator or write it to media for real hardware. See FUJINET.md for build details, the three hook points, and the validation procedure.


FujiNet commands © 2026. SmartBASIC 1.x © 1991, 1997 Richard F. Drushel, released for the ADAM community. Built on the FujiNet fujinet-lib protocol and the EOS C bindings. GPL v3, see the source headers.

About

SmartBasic 1.x with FujiNet Commands Added.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages