The C64 OS Programmer's Guide is being written
This guide is being written and released and few chapters at a time. If a chapter seems to be empty, or if you click a chapter in the table of contents but it loads up Chapter 1, that's mostly likely because the chapter you've clicked doesn't exist yet.
Discussion of development topics are on-going about what to put in this guide. The discusssions are happening in the C64 OS Community Support Discord server, available to licensed C64 OS users.
C64 OS PROGRAMMER'S GUIDE
Library Reference: network.lib
Overview
The network.lib is a coordination library for managing the C64 OS network stack. Its primary job is to load the cnp.lib, which implements the the socket API and the Commodore Network Protocol (CNP). The network.lib loads and stores network settings, loads and configures the network hardware driver and connects the driver to the cnp.lib.
The Network Utility retrieves and modifies the network settings via the network.lib. But the Network Utility itself is responsible for saving the network settings to storage.
Name | network.lib |
---|---|
code | ne |
size | 5 pages |
Link | Yes |
Unlink | Yes |
Emits Memory Warnings | No |
Related libraries
Network Settings
Network settings are stored in network.t
in the system's settings directory
(//os/settings/).
The file consists of 10 lines ended by a carriage return ($0d). The first 3 lines are integers encoded as a single byte by shifting the value into a human-readable range of PETSCII. The last 7 lines are strings of PETSCII.
Line | Description | Type | Encoding | Length |
---|---|---|---|---|
0 | Driver page size | Int | PETSCII "0" ($32) added to it | 1 byte |
1 | Initial baud rate code | Int | PETSCII "a" ($41) added to it | 1 byte |
2 | Maximum baud rate code | Int | PETSCII "a" ($41) added to it | 1 byte |
3 | Network Hardware Driver filename | String | PETSCII | 1 to 16 characters |
4 | Wifi SSID | String | PETSCII | 1 to 32 characters |
5 | Wifi Password | String | PETSCII | 1 to 32 characters |
6 | CNP Host | String | PETSCII | 1 to 20 characters |
7 | CNP Port | String | PETSCII | 1 to 5 characters |
8 | CNP Username | String | PETSCII | 1 to 16 characters |
9 | CNP Password | String | PETSCII | 1 to 16 characters |
Network Status
The status of the network is persisted between Fast App Switching banks, even when the current App bank does not have the network stack loaded. Its bits can be checked to determine whether the operating system's network settings are configured or not, and whether the operating system is online or not. Being online means that the network hardware has an active connection to a CNP server.
The network.lib sends a network status message (mc_ntwrk
) to the Application, and
to the Utility if one is open, whenever any network status bit changes. Your Application can
listen for these messages to know when the operating system goes online or offline and respond
accordingly.
Constant | Value | Description |
---|---|---|
ns_nhcf | %00000001 | Network hardware driver loaded |
ns_nhsp | %00000010 | Network hardware initialized |
ns_trcf | %00000100 | Transport layer configured |
ns_trup | %00001000 | Transport layer connected |
ns_cpcf | %00010000 | CNP configured |
ns_cpup | %00100000 | CNP connected |
Description of how the network status bits are used and what they mean:
ns_nhcf
This bit is set when the network hardware driver has been specified, is loaded into memory, and the network hardware driver is able to communicate with the corresponding hardware. The test for the ability to communicate with the hardware is provided by the driver itself.
ns_nhsp
This bit is set when the hardware's speed and other parameters have been initialized. It's used internally by the driver to know when it needs to initialize the hardware and when that step can be skipped. This is used primarily when a modem connected via RS-232 needs to have its communications speed changed, and the driver has to adjust its own speed to match.
ns_trcf
The transport layer is the network hardware's internal ability to access the internet via TCP/IP. For example, if the modem connects to the internet by WiFi, the transport layer is the modem's connection to the wireless access point. If the modem uses ethernet, it is the modem's physical ethernet link and its ability to acquire an IP address.
C64 OS does not provide support for configuring the ethernet settings on those modems which use ethernet. They must either provide their own means of configuring the connection or use automatic resolution, such as DHCP, to acquire an IP address.
This bit is set when a Wifi SSID and Password have been provided by the user. If the driver does not have the ability to set the SSID and password of the hardware, these values have to be provided anyway, even if they are bogus. (This may change in a future version of C64 OS.)
ns_trup
This bit is set when the transport layer is connected. The driver is provided with the Wifi SSID and password and it can provide those to the network hardware device. The driver is responsible for reading information about the transport layer connection from the hardware, such as the SSID that the wifi modem is connected to, or in theory the IP-address, gateway or other information that the ethernet hardware has acquired for its transport layer. (Ethernet connections and reporting need improvement in C64 OS.)
ns_cpcf
This bit is set when the host, port and access credentials for a CNP server have been provided. OpCoders Inc. provides a CNP server to connect to, with a subscription to Network Proxy Services. Access credentials can be configured by logging into your account at c64os.com. The host and port are provided in the instructions on the same page.
Alternatively, the CNP server is open source. It can be downloaded, modified, and configured to run on different cloud infrastructure.
ns_cpup
This bit is set when the network hardware has an active connection open to a CNP server, has successfully authenticated, and the cnp.lib is able to communicate with the CNP server.
Networking and Fast App Switching
If the user switches to an App bank where the network stack is not loaded (neither the
network.lib, the cnp.lib nor the network hardware driver), only the ns_nhcf
bit goes low. This indicates that the network hardware driver is not loaded into memory.
Because all network hardware devices supported by C64 OS are smart network devices, they are able to internally maintain their own TCP/IP connection to the CNP server, even when the Commodore 64 does not have a network hardware driver active in memory for communicating with the hardware.
When Fast App Switching, the Switcher calls nhdpause
on the network hardware
driver before freezing the Application to the REU. This allows the driver to assert hardware
flow control which prevents the hardware from attempting to send data to the computer while
the computer doesn't have a driver that can handle the incoming data. When the Switcher
thaws an App from the REU, it forwards all of the network status bits to the new bank, except
for ns_nhcf
. If the new bank already has ns_nhcf
set, then the
driver is already available in this bank, and Switcher calls nhdresum
on the
driver. The driver unasserts hardware flow control and network data can resume being
processed.
The system status bar reports the operating system as online whenever the
ns_cpup
bit is set, regardless of whether the current App bank has the network
stack loaded in.
While the network stack is loaded in the current App bank, and the CNP server connection is established, a keep-alive message is sent periodically to maintain the CNP server connection. If you Fast App Switch to an App bank where the network stack is not loaded in, or if you drop to BASIC (where the network stack is never active), after some period of inactivity (typically 10 minutes), the CNP server will close the TCP/IP connection to the network hardware.
Whenever C64 OS is Fast Rebooted, or the user Fast App Switches back to a bank in which the
network stack is available, the network hardware driver notices that the carrier detect
signal (or its equivalent) is no longer asserted. This is communicated to the network.lib
which promptly lowers the ns_cpup
status bit and sends an mc_ntwrk
message. All open sockets are closed automatically when the CNP connection is lost.
The network.lib also automatically opens the Network Utility in response to going offline. The user should be able to click the "Start" button under the CNP tab to resume the CNP connection, bring the operating system back online, and continue normal network operations.
Library Routines
Link and Unload
When this library is linked to the KERNAL it automatically loads the
cnp.lib and binds itself to several routines provided by the
cnp.lib. Additionally, it sets the workspace variable cnplibpg
to the page
address where the cnp.lib was relocated.
;defined by //os/s/:network.s cnplibpg = $0244
It is critically important to use the slunload
flag when
unloading network.lib.
This will automatically unload any loaded network hardware driver and unloads the cnp.lib
and sets cnplibpg
back to 0.
Unloading the network.lib sends mc_ntwrk
network status messages.
Load Settings (loadset_)
Purpose | Load network settings. Optionally perform a full network boot. |
---|---|
Jump offset | $06 |
Communications registers | A, X, Y |
Stack requirements | 16+ |
Zero page usage | $1e, $1f (plus others used by cnp.lib, the NHD, the KERNAL file accesses, etc.) |
Registers affected | A, X, Y |
Input parameters |
C → Clear to load network settings only. C → Set to load settings and perform a full network boot. |
Output parameters |
C ← SET = An error occurred. |
Description: This routine loads and parses the values stored in the
network.t
settings file found in //os/settings/
. If the file does
not exist, the carry is returned set, indicating an error.
The network settings are loaded into statically allocated buffers inside the network.lib.
Upon loading the settings, the ns_trcf
and ns_cpcf
bits are set
if all of their corresponding fields have content.
If this routine is called with the carry clear, it only loads the settings and returns with the carry set if the settings file does not exist, or clear to indicate that the settings were successfully loaded in.
If this routine is called with the carry set, it first tries to load in the settings, and then if the settings were successfully loaded, it begins a long, complex, and asynchronous process of booting the network. If the full network boot option is specified, but there is an error loading the network settings, the Network Utility is automatically loaded so the user can see that the network is not configured, and is guided towards configuring it.
Similarly, if the network settings are configured, and the network boot process begins, if somewhere down the chain of asynchronous stages the network fails to boot, the Network Utility is opened. This allows the user to see how the network is currently configured and resolve any configuration issues. Opening the Network Utility guides the user towards what needs to be done and makes it easier to manually start the CNP connection and go online.
Because booting the network is multi-stage and each stage is asynchronous, this routine
returns before the network is actually booted. It is necessary for the Application to listen
for mc_ntwrk
messages to keep informed about changes to the network status.
Read a network setting (readset_)
Purpose | Read a network setting |
---|---|
Jump offset | $09 |
Communications registers | A, X, Y |
Stack requirements | 2 |
Zero page usage | None |
Registers affected | A, X, Y |
Input parameters | X → network setting index |
Output parameters | RegPtr → pointer to the network setting buffer |
Description: The network.lib stores the network settings in statically allocated buffers within its own memory space. This routine is used to request a pointer to the buffer inside network.lib which holds the requested settings data.
You will probably never be required to use this routine. This routine is used by the Network Utility to fetch the settings buffers from the network.lib, which it uses directly as the string buffers for the TKInput text fields. Thus, as the user interacts with the Network Utility, typing in a new Wifi SSID, for example, the TKInput is editing the data directly in the settings buffer provided by the network.lib.
The network.lib does not implement writing its settings to //os/settings/:network.t. The network settings are written by the Network Utility after it has changed them.
Network Settings Constants
This network settings constants correspond with the line numbers in the network.t settings file described above. Each of the string buffers is 1 byte longer than the maximum number of characters that can be held in that settings field. The extra byte allows the string buffer to hold a NULL terminating byte.
Buffer sizes and buffer overruns
If you do call readset
and use it to access the network settings buffers, it
is critically important that the buffers not be overrun.
It is safest to attach the buffer to a TKInput object and specify its maximum buffer size as listed below. TKInput is carefully designed to prevent the buffer from being overrun, while handling selections, insertions, copying, pasting and validation.
;defined in //os/s/:network.s
Constant | Value | Description | Buffer size |
---|---|---|---|
nhdpgsz | 0 | Network driver page size | 1 byte |
inibaud | 1 | Initial baud rate code | 1 byte |
maxbaud | 2 | Maximum baud rate code | 1 byte |
nhddrvr | 3 | Network hardware driver filename | 16 bytes |
wifinam | 4 | Wifi name (SSID) | 32 bytes |
wifipas | 5 | Wifi password | 32 bytes |
cnphost | 6 | CNP host | 20 bytes |
cnpport | 7 | CNP port | 5 bytes |
cnpuser | 8 | CNP username | 16 bytes |
cnppass | 9 | CNP password | 16 bytes |
Load Network Hardware Driver (loadnhd_)
Purpose | Load a network hardware |
---|---|
Jump offset | $0c |
Communications registers | Carry |
Stack requirements | 8+ |
Zero page usage | $1e, $1f |
Registers affected | A, X, Y |
Input parameters | None |
Output parameters | C ← Set on error |
Description: This routine is used to load a configured network hardware driver, and bind the network.lib and the cnp.lib to the new driver.
You will not typically ever call this routine manually. It's called by the Network Utility when it first starts up, and then again if you change the selected driver and save. This routine is called as part of the full network boot up.
The first thing it does is unload any currently loaded network hardware driver. Unloading a
network hardware driver consists of calling its unlink routine, allowing the driver to clean
itself up and to pause any data flow from the hardware. Then the memory the driver was loaded
into is freed, the workspace variable ndrvpg
is set to #0 (NULL) indicating that
no driver is loaded. And lastly it unsets the ns_nhcf
network status bit. The
mc_ntwrk
message is not sent at this time.
After unloading any previously loaded driver, it then checks to see if the settings specify
a driver to load. If there is no specified driver, then the mc_ntwrk
message
is sent and the carry is returned set, to indicate an error. The error is that this routine
is supposed to load a network driver, but it could not because one is not specified in the
network settings.
Otherwise, the new driver is loaded and relocated. The relocation address of the loaded
driver is set into the workspace variable ndrvpg
. If the specified driver file
fails to load or relocate, then any memory that was allocated for it is freed, ndrvpg
is set back to #0, the mc_ntwrk
message is sent out and the carry is returned
set, to indicate an error loading the driver.
If the specified driver succeeds in being loaded and relocated, then the jump table in the network.lib is updated with the relocated page address of the driver, to bind the library to the new driver. The network.lib's jump table to the network hardware driver consists of the following routines:
- nhdunlnk
- sethand
- dataget
- setrate
- ssidstat
- opensock
Initially, the driver's incoming data handlers are configured, by calling its
sethand
routine, so that its online and offline datastreams are both
handled by the network.lib. It then calls bindnhd
in the cnp.lib.
The cnp.lib binds itself to the new driver, and sets itself as the handler for the
online data stream.
After the new driver has been installed, it sets the ns_nhcf
network
status bit and the mc_ntwrk
message is sent.
For more information about these routines, see Chapter 7: Using Drivers → Network Hardware.
;defined in //os/s/:network.s ndrvpg = $0804
Configure the driver's baud rate (confbaud_)
Purpose | Configure the driver's communication speed |
---|---|
Jump offset | $0f |
Communications registers | Carry, A |
Stack requirements | 4+ |
Zero page usage | Whatever the driver uses |
Registers affected | A, X, Y |
Input parameters | None |
Output parameters |
C ← Set on error A ← Error code 0 = Carrier Detected 1 = Baud Match Test Failed |
Description: This routine is used to configure the driver's communications speed, to step the driver up from the hardware's default or initial speed to its preferred speed for C64 OS.
You will not typically ever call this routine manually. It's called by the Network Utility when it first starts up, and then again if you change the selected driver and save. This routine is called as part of the full network boot up.
The first thing it does is sets the driver only to the initial communications speed
of the hardware, but calling the driver's setrate
routine with the
carry clear.
A communications test is then run by the driver. If the test fails, this routine then attempts to the set the speed of the driver to the max. baud rate, to see if that matches the hardware. The final communications test is performed.
If the first communications test was successful, then it tells the driver to step the modem up. The driver does this by sending the command to the modem to set its new communications speed, and then the driver itself changes its communications speed. The final communications test is performed.
In either case, whether the initial communications test failed or succeeded, the
success or failure of the second communications test sets ns_nhsp
network
status bit and the mc_ntwrk
message is sent.
There is one exceptional case. If the hardware is already online, (i.e., a modem's
carrier detect signal is asserted) then the communications test can't be run. In this
case it is assumed that the hardware is online because of a previous instance of
C64 OS bringing it online, but then the OS losing its network status information,
for example, because of a reboot (without a fast reboot via the REU.) In this case,
the driver only is configured for the maximum baud rate, and the ns_nhsp
network status bit is set.
It is possible that the assumption is wrong. If the modem was taken online by some non-C64-OS telecommunications software, and the hardware's baud rate is not set to the maximum baud rate specified in the C64 OS network settings, then the driver will not be able to communicate with the hardware. In this case, the only way to make the two align is by forcing the modem to disconnect first. How this is accomplished depends on the hardware. Some modems have a reset button, some modems reset automatically when the computer is reset. The original telecommunications software could be used to tell the modem to disconnect, etc.
Connect the network hardware to a Wifi access point (joinwifi_)
Purpose | Connect the network hardware to a Wifi access point |
---|---|
Jump offset | $12 |
Communications registers | Carry, A, X, Y |
Stack requirements | 4+ |
Zero page usage | Whatever the driver uses |
Registers affected | A, X, Y |
Input parameters |
RegPtr → Next stage callback C → Clear = Read current SSID C → Set = Join SSID |
Output parameters |
When reading the SSIDC ← Always clearWhen joining an SSIDC ← Set on errorA ← Error code 0 = Carrier Detected 1 = SSID/Password not configured |
Description: This routine is used to read what SSID the network hardware is current connected to, and to tell the network hardware to join an SSID. The feedback from the modem is asynchronous, and flow continues when the callback routine is called.
You will not typically ever call this routine manually. It's called by the Network Utility when the user clicks the cycle button or the join button under the Wifi tab. This routine is also called as part of the full network boot up. The cycle button calls this routine to read the SSID, the join button calls this routine to join an SSID.
If the ns_trcf
network status bit is unset, this routine returns with
the carry set immediately, and the error code in the accumulator as 1, indicating
that it cannot proceed because the SSID and password fields are not configured.
The network.lib's response buffer is cleared and the ssidstat
routine
of the driver is called. Network.lib passes to ssidstat
a RegPtr to a
structure which holds pointers to the buffers for the SSID and password.
If the network hardware is already online, it returns with the carry set and the
accumulator is set to 0 indicating carrier is detected. In this case, the
ns_trup
network status bit is set, the mc_ntwrk
message
is sent. But this routine returns with the carry set, and the accumulator is set to
0. The callback will not be called, because no commands could be sent to the network
hardware.
If the call to ssidstat
returns with the carry set and the accumulator
is not 0, then some other error occurred. This routine returns both with the carry
set and with the accumulator holding the driver's error code. The callback will
not be called.
If ssidstat
returns with the carry clear, then the command to either
read or set the SSID was sent to the modem. The response will come later when the
callback is called.
The callback is called with the response code in the accumulator. If the response is
"0" (PETSCII "0", not integer $00) then the SSID was joined. The default callback
sets the ns_trup
network status bit and proceeds by calling
cnpsrvr. The default callback is used by the full network
boot process. Otherwise the Network Utility provides its own callback.
Connect or disconnect from the CNP server (cnpsrvr_)
Purpose | Join/Part from the CNP server |
---|---|
Jump offset | $15 |
Communications registers | Carry, A, X, Y |
Stack requirements | 5+ |
Zero page usage | Whatever the cnp.lib and driver uses |
Registers affected | A, X, Y |
Input parameters |
RegPtr → Next stage callback C → Clear = Join the CNP Server C → Set = Part from the CNP Server |
Output parameters |
C ← Set on error A ← Error code 0 = Carrier Detected 1 = CNP settings not configured |
Description: This routine is used to connect to or disconnect from the CNP server. Feedback from the connection attempt is asynchronous and flow continues when the callback routine is called.
When connecting, the driver is told to open a TCP/IP socket. When the socket opens, the callback from this routine must hand control of the socket over to the cnp.lib. That can be done by calling the cnpctrl routine. The cnp.lib takes over, sends the access credentials, and then continues to manage the socket.
You will not typically ever call this routine manually. It's called by the Network Utility when the user clicks the start or stop button under the CNP tab. This routine is also called as part of the full network boot up. The stop button calls this routine to terminate a CNP server connection, the start button calls this routine to open a connection to the CNP server and pass control over to the cnp.lib.
If the ns_cpcf
network status bit is unset, this routine returns with
the carry set immediately, and the error code in the accumulator as 1, indicating
that it cannot proceed because the CNP settings are not configured.
The network.lib's response buffer is cleared and the opensock
routine
of the network hardware driver is called. Network.lib passes to opensock
a RegPtr to a structure which holds pointers to the buffers for the CNP server's
host and port. The host can usually be either a domain name or an IP address.
If the network hardware is already online, it returns with the carry set. In this
case, the ns_cpup
network status bit is set, the mc_ntwrk
message is sent. This routine returns with the carry set and the accumulator set
to 0. The callback will not be called.
In the network hardware driver, the opensock
routine is used to open a
socket if the carry is passed in clear. It is also used to close a socket by passing
the carry in set. This is a TCP/IP socket, not a CNP socket. The network
hardware must support TCP/IP and offer functionality to open at least one TCP/IP
socket.
If the call to opensock
returns with the carry clear, the command was
sent to the modem. This routine also returns with the carry clear, but the response
from the network hardware driver comes later when the callback is called.
The callback is called with the response code in the accumulator. If the response is "1" (PETSCII "1", not integer $01) then the socket was opened. The default callback proceeds by calling cnpctrl. If the response code was not "1" then the default callback launches the Network Utility. The default callback is used by the full network boot process. Otherwise the Network Utility provides its own callback.
Pass control of the TCP/IP socket over to cnp.lib (cnpctrl_)
Purpose | Pass control to cnp.lib to authenticate |
---|---|
Jump offset | $18 |
Communications registers | Carry, X, Y |
Stack requirements | 4+ |
Zero page usage | Whatever the cnp.lib uses |
Registers affected | A, X, Y |
Input parameters |
C → Set = Allow network.lib to handle an auto-disconnect C → Clear = Specify a custom auto-disconnect callback RegPtr → custom auto-disconnect callback |
Output parameters | None |
Description: This routine is used to transfer control of a just-opened TCP/IP socket to the cnp.lib.
You will not typically ever call this routine manually. It's called by the Network Utility after the user clicked the start button under the CNP tab and then the network hardware driver successfully opened the TCP/IP socket. This routine is also called as part of the full network boot up.
There is a condition under which the TCP/IP socket to the CNP server may unexpectedly close. When this routine is called there are two options, one is to allow the network.lib to handle the disconnection. This option is used by the full network boot. The other option is to pass in the carry clear to specify a custom disconnect handler. The Network Utility specifies a custom disconnect handler. A pointer to the custom handler routine is passed in a RegPtr.
This routine calls sessbgn
(session begin) in the cnp.lib and passes a
RegPtr to a struct which holds pointers to the settings buffers for the CNP access
credentials, i.e., the username and password. The authentication attempt is synchronous,
even though sending the actual credentials and getting the response is asynchronous.
sessbgn
returns with the carry clear when the access credentials are
sent. At this point, before the access credentials are accepted or not, the
ns_cpup
network status bit is set and the mc_ntwrk
message
is sent.
sessbgn
returns with the carry set if the access credentials could not
be sent. The accumulator comes back 0 if the ns_cpup
bit is already
set. This is not really an error, it just means the access credentials didn't need
to be sent again, and the cnp.lib in this app bank has taken control over the
TCP/IP socket. The mc_ntwrk
message is sent so that the App or Utility
get notified that this app bank is online.
sessbgn
may also return with the carry set if the hardware driver
indicates that the carrier is not up. That is, if the TCP/IP socket is not open,
then the carry is set and the accumulator comes back as 1. If this happens, the
disconnect handler is is called immediately.
The default disconnect handler provided by network.lib reclaims the communications
over the TCP/IP socket from the cnp.lib. Even though the socket is now closed, in
order for cnp.lib to have control over the network hardware driver's online data
stream it has to have sessbgn
called again. It does this by calling
sessend
with the carry set on the cnp.lib. Then it clears the
ns_cpup
network status bit and sends the mc_ntwrk
message. Then it opens the Network Utility automatically so the user can deal with
the issue.
Incorrect access credentials
But what happens if the access credentials are not correct?
Because the access credentials are sent over the network, this is done asynchronously.
When everything is configured correctly the access credentials will be accepted.
Therefore, once sessbgn
returns with the carry clear, indicating that it
has sent the credentials, the network status changes and C64 OS goes online.
The access credentials are off course still buffered and being streamed up to the CNP server at the speed of the network hardware. If the access credentials are not accepted, for example, if they were typed in wrong or if the user changed them in their account settings at https://www.c64os.com/c64os/account/#cnpaccess
Previous Section: Library Reference
Next Chapter: Using Toolkit
Table of Contents
This document is subject to revision updates.
Last modified: Jun 13, 2025