Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

ADAM Programming Overview

Programming the FujiNet on the Coleco ADAM uses the AdamNet bus, the ADAM’s native peripheral communication network. When the ADAM powers on, it scans AdamNet and identifies connected devices. The FujiNet responds to this scan and can emulate multiple device types simultaneously.

Emulated Devices

The FujiNet can present itself as any of the following AdamNet devices:

DeviceDescription
FujiNetThe core FujiNet control device, providing real-time clock access and network protocol converters (HTTP, HTTPS, FTP, SMB, TELNET, JSON)
KeyboardStandard ADAM keyboard emulation (disabled in standard builds)
PrinterADAM printer emulation
Digital Data DriveEmulated tape drive (DDP) for loading and saving data
Floppy DriveEmulated floppy disk drive
Modem DeviceModem emulation for BBS and serial communication
Serial PortSerial port emulation
FujiNet CP/MCP/M operating system support

AdamNet Device IDs

Two device IDs are central to FujiNet programming on the ADAM:

Device IDNamePurpose
$0FFujiNet ControlSystem-level operations: WiFi management, host/device slots, clock, configuration
$09 - $0CNetwork (N:)Up to four network connections for protocol-based I/O

Programming Model

Programs communicate with FujiNet by writing command structures to the appropriate device ID using EOS (Elementary Operating System) calls, then reading the response. The basic pattern is:

  1. Build a command structure in memory
  2. Write it to the device using eos_write_character_device()
  3. Read the response using eos_read_character_device()
  4. Check for ACK ($80) to confirm success

Command Structure

Most commands use a structure beginning with a command byte, followed by command-specific parameters:

struct {
    unsigned char cmd;      // Command byte
    unsigned short mode;    // Mode flags (command-specific)
    unsigned char trans;    // Translation mode
    unsigned char url[256]; // URL or payload
} command;

Note: The command format for ADAM Network devices ($09-$0C) is identical to the Atari SIO command format for the corresponding N: device operations.

FujiNet Control Device ($0F)

The control device at ID $0F handles system-level operations. Key commands include:

CommandDescription
$D1Device enable status
$D2Get time
$D3Random number
$D4Disable device
$D5Enable device
$D6Set boot mode
$D7Mount all
$D8Copy file
$E2Set filename for device slot
$E8Get adapter config
$F2Read device slots
$F4Read host slots
$F5Close directory
$F6Read directory
$F7Open directory
$F8Mount device image
$F9Mount host
$FAGet WiFi status
$FBSet SSID and connect
$FCGet scan result
$FDScan networks
$FEGet SSID
$FFReset FujiNet

Example: Reading the Real-Time Clock

#include <stdio.h>
#include <conio.h>

#define FUJI_DEV 0x0F
#define ACK      0x80

typedef struct {
    unsigned char century;
    unsigned char year;
    unsigned char month;
    unsigned char day;
    unsigned char hour;
    unsigned char minute;
    unsigned char second;
} FUJI_TIME;

typedef struct {
    unsigned char cmd;
    unsigned short mode;
    unsigned char trans;
    unsigned char url[256];
} FUJI_CMD;

int io_time(FUJI_TIME *time)
{
    FUJI_CMD oc;
    unsigned char response[1024];

    oc.cmd = 0xD2; // Get Time

    if (eos_write_character_device(FUJI_DEV,
            (unsigned char *)&oc, sizeof(oc)) != ACK)
        return 1;

    if (eos_read_character_device(FUJI_DEV,
            response, sizeof(response)) != ACK)
        return 3;

    memcpy(time, response, sizeof(FUJI_TIME));
    return 0;
}

void main(void)
{
    FUJI_TIME ft;
    clrscr();
    io_time(&ft);
    printf("Date: %02u%02u-%02u-%02u\n",
        ft.century, ft.year, ft.month, ft.day);
    printf("Time: %02u:%02u:%02u\n",
        ft.hour, ft.minute, ft.second);
}

Network Device ($09)

The Network device supports the same command set as the Atari N: device. Commands are issued by writing a command structure to device $09, then reading the response.

CommandDescription
'O'Open a network URL
'C'Close the connection
'R'Read data
'W'Write data
'S'Get status (bytes waiting, connected state)
'P'Parse JSON
'Q'Query JSON element
'E'Get last error code
'H'Set hash type
$FCSet channel mode (e.g., JSON)
$FDSet login credentials
$FESet password

Example: Reading JSON Data from the Network

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <eos.h>

#define NET_DEV 0x09
#define CHANNEL_MODE_JSON 0x01
#define ACK 0x80

const char *url = "N:HTTPS://oldbytes.space/api/v1/timelines/public?limit=1";
char response[1024];

void main(void)
{
    unsigned char r;

    // Open command
    struct { unsigned char cmd; char mode; char trans; char url[256]; } OC;
    // Set Channel Mode command
    struct { unsigned char cmd; char mode; } SCM;
    // Query command
    struct { unsigned char cmd; char query[128]; } QC;

    OC.cmd = 'O';
    OC.mode = 12;     // Read/Write
    OC.trans = 3;     // CR/LF to CR
    strncpy(OC.url, url, 256);

    SCM.cmd = 0xFC;
    SCM.mode = CHANNEL_MODE_JSON;

    QC.cmd = 'Q';

    printf("JSON TEST PROGRAM\n\n");

    // Open the URL
    printf("OPENING URL:\n%s\n", url);
    if (eos_write_character_device(NET_DEV,
            (unsigned char *)&OC, sizeof(OC)) != ACK) {
        printf("ERROR OPENING.\n");
        return;
    }
    printf("OPENED.\n");

    // Switch to JSON mode
    printf("SETTING CHANNEL MODE TO JSON\n");
    if (eos_write_character_device(NET_DEV,
            (unsigned char *)&SCM, sizeof(SCM)) != ACK) {
        printf("ERROR.\n");
        return;
    }

    // Parse the JSON response
    printf("PARSING JSON.\n");
    if (eos_write_character_device(NET_DEV, "P", 1) != ACK) {
        printf("ERROR.\n");
        return;
    }

    // Query for display name
    strncpy(QC.query, "/0/account/display_name", 128);
    while (eos_write_character_device(NET_DEV,
            (unsigned char *)&QC, sizeof(QC)) < 0x80);
    while (eos_read_character_device(NET_DEV,
            response, 1024) < 0x80);
    printf("\nNAME: %s\n\n", response);

    // Query for content
    strncpy(QC.query, "/0/content", 128);
    while (eos_write_character_device(NET_DEV,
            (unsigned char *)&QC, sizeof(QC)) < 0x80);
    while (eos_read_character_device(NET_DEV,
            response, 1024) < 0x80);
    printf("\n%s\n\n", response);

    // Close connection
    printf("CLOSING.\n");
    eos_write_character_device(NET_DEV, "C", 1);
}

URL Format

Network URLs follow this format:

N:PROTO://[HOSTNAME][:PORT]/[PATH]

Where:

  • PROTO is the protocol (HTTP, HTTPS, TCP, UDP, FTP, TNFS, SMB, TELNET, etc.)
  • HOSTNAME is the destination host
  • PORT is the port number (optional for standard ports)
  • PATH is the resource path (optional)

Further Reading