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: cnp.lib
Overview
The cnp.lib is a core part of the C64 OS network stack. Loading and unloading the cnp.lib and binding it to the network hardware driver is work that is performed automatically by the network.lib. The cnp.lib implements the socket API and the Commodore Network Protocol (CNP) which is a protocol for dividing a data-stream into a series of checksummed and socket-addressed packets. Packet acknowledgement allows for resending corrupt packets (in either direction) and controlling the rate of transmission on a per-socket basis.
Sockets can also have their incoming data stream temporarily paused and resumed, allowing the Application additional time to write data out to disk, or even allowing an Application to be frozen into the REU with Fast App Switching. The new foreground Application can then access the network with its own sockets, and when the original Application is thawed from the REU again, it can resume the data flow of its paused socket; a data transfer that was paused midstream can resume as though it were never interrupted.
The Commodore Network Protocol was built for C64 OS and to work hand-in-hand with C64 OS's Fast App Switching abilities.
Name | network.lib |
---|---|
code | cn |
size | 6 pages |
Link | Yes |
Unlink | Yes |
Emits Memory Warnings | No |
Related libraries
Socket Overview
Each Fast App Switching bank may have a maximum of 8 sockets open at a time. And there can be up to 32 Fast App Switching banks. 32 times 8 allows for 256 sockets open at a time. Packets are associated with a socket by a single identifying byte, this is referred to as the port number or the socket ID. The port number is a combination of the Fast App Switching bank number shifted left 3 times to occupy the upper 5 bits, OR'd with the index of the socket in the open sockets table, which then occupy the lower 3 bits.
Each instance of cnp.lib maintains its own open sockets table with 8 available slots. Whenever a socket is opened, a pointer to the socket is inserted into an available slot and it remains there until the socket is closed.
A socket, fundamentally, is a structure that groups together status flags and a status callback, with checksums and buffers for receiving and transmitting data. When transmitting data, a checksum is computed as data is written into the socket's outgoing buffer. A chunk of data up to 255 bytes in length is then dispatched to the CNP server in the form of a packet. The packet encapsulates the data, with the checksum and datasize information, and the socket ID whence this data originates.
When a packet is received, its port number or socket ID is used to direct the packet data into the correct socket's receiving buffer. The checksum is validated, and then the owner of the socket is notified by a call to the socket's status callback. The process that owns this socket may then proceed by reading the data from the socket's receive buffer.
Sockets and packets serve both to interleave data from different processes, but also to function as flow control. An individual socket may be temporarily paused while the Application that owns it is switched into the background. And while data for one socket is being processed, data can arrive at the same time for a different socket. Each socket has its own transmit and receive buffers and its own flow control.
CNP Socket Structure
Constant | Value | Size | Notes |
---|---|---|---|
csk_name | 0 | 2 | Endpoint string pointer, "hostname:port" or "IPaddress:port" |
csk_stat | 2 | 2 | Status callback |
csk_flgs | 4 | 1 | Status flags |
csk_tsiz | 5 | 1 | Tx Data Size |
csk_tsum | 6 | 1 | Tx Data Checksum |
csk_tbuf | 7 | 1 | Tx Data Buffer (page number) |
csk_rsiz | 8 | 1 | Rx Data Size |
csk_rsum | 9 | 1 | Rx Data Checksum |
csk_rbuf | 10 | 1 | Rx Data Buffer (page number) |
CNP Socket Status Flags (csk_flgs)
Constant | Value | Notes |
---|---|---|
csf_opng | %00000001 | Opening |
csf_clng | %00000010 | Closing |
csf_txng | %00000100 | Transmitting |
csf_open | %10000000 | Socket is open |
CNP Socket State Change Notifications
When the callback pointed to by csk_stat
is called, one of the following
socket notification messages is passed in the accumulator.
Constant | Value | Notes |
---|---|---|
csc_open | 0 | Socket Opened |
csc_fail | 1 | Socket Unable to Open |
csc_clos | 2 | Socket Closed |
csc_time | 3 | Socket Timed out |
csc_data | 4 | Socket Has Data to Read |
csc_tclr | 5 | Socket Clear to Transmit |
Packet Overview
Packets are designed to be as minimalist as possible. This makes processing them fast and simple. Transmission overhead is also minimized by making the ratio of header to payload small.
Packet headers have a variable size, which is defined by the packet type. Headers may be from 1 to 4 bytes, and payload data may be from 0 to 255 bytes. A full data packet has an overhead of 1.5%
Notes about TCP/IP + Ethernet overhead
In the worst case scenario, when transmitting a single data byte in a TCP packet, wrapped in an IP packet, wrapped in an ethernet packet, has 54 bytes of headers for 1 byte of payload. Over 98% of the bytes the computer has to send over the hardware are overhead.
In the best case scenario, ethernet may limit the transmission unit to 1500 bytes. That's 54 bytes of headers, leaving 1460 bytes for data. This is considered to be very efficient, with just 3.6% overhead.
Notes about CNP overhead
In the worst case scenario, when transmitting a single data byte in a CNP data packet, there are 4 header bytes. This is 80% overhead in the worst case scenario.
In the best case scenario, a data packet may transmit 255 bytes of data with 4 header bytes. This is less than 1.6% overhead.
After the CNP packet is transferred to the network hardware device, it still ends up getting wrapped in a TCP packet, and an IP packet and an Ethernet packet (or a Wifi packet which is bigger than an Ethernet packet.) However, the speed bottleneck is with the 1MHz CPU and the hardware transport layer, like RS-232, moving the data from memory into the network hardware device.
CNP packets are much more efficient for the Commodore 64 by reducing header sizes from 54 bytes to just 4 bytes, while maintaining support for multiple sockets, checksums, resends, etc.
CNP Packet Structure
Constant | Value | Size | Notes |
---|---|---|---|
cp_type | 0 | 1 | Packet Type |
cp_port | 1 | 1 | Port Number (i.e., Socket ID) |
cp_dsiz | 2 | 1 | Data Size (payload size, without the header.) |
cp_csum | 3 | 1 | XOR data checksum |
The first byte of the packet is the packet's type. Since different types of packet have different total sizes, this allows for some portions of the header to be omitted.
CNP Packet Types
Constant | Value | Header Size | Data Size | Notes |
---|---|---|---|---|
pt_alive | "-" | "+" | 1 | 0 | CNP Keep Alive |
pt_serv | "s" | 4 | 1-255 | CNP Service Packet |
pt_open | "o" | 4 | 1-255 | Socket Open Request |
pt_data | "d" | 4 | 1-255 | Data Carrier |
pt_close | "c" | 2 | 0 | Socket Close Request |
pt_time | "t" | 2 | 0 | Socket Timed Out |
pt_ack | "a" | 2 | 0 | Acknowledgement |
pt_nak | "n" | 2 | 0 | Negative Acknowledgement |
pt_pause | "p" | 2 | 0 | Socket Pause/Acknowledgement |
pt_resum | "r" | 2 | 0 | Socket Resume Request |
Library Routines
- CNP Session Management
- Socket Management
- Socket Transmission
- Socket Receiving
CNP Session Management
Link and Unload
In practice, you should never need to load the cnp.lib (or unload it) manually. Loading and unloading of the cnp.lib is handled automatically by the network.lib.
When cnp.lib is linked, it fetches the current Fast App Switching bank, shifts it left 3 times and preserves this as the App bank mask for this instance of cnp.lib. When packets are received from the server, the port's upper 5 bits are compared against the current App bank mask. If they do not match, then this packet is destined for an Application that is running from a different Fast App Switching bank. Such packets are ignored.
When packets are being prepared for transmission, the packet's port number is dynamically composed by OR'ing together the socket's table index with the current App bank mask.
Two KERNAL interval timers are queued and remain queued for as long as the cnp.lib is in memory. These are the CNP server keep alive and the packet timeout timer. These timers are paused, reset, and resumed at various points during network activity, but they are always queued. Thus, in any App bank where networking is used, two of the 10 total timers for that App bank are permanently occupied.
When the network.lib is unloaded, it automatically unloads the cnp.lib. When the cnp.lib is unloaded the two KERNAL timers are canceled and dequeued.
Bind to the Network Hardware Driver (bindnhd_)
Purpose | Bind the cnp.lib to the current network hardware driver. |
---|---|
Jump offset | $06 |
Communications registers | None |
Stack requirements | 2 |
Zero page usage | None |
Registers affected | A |
Input parameters | None |
Output parameters | None |
Description: This routine is called automatically by the network.lib
whenever the network hardware driver is changed. The page address of the network
hardware driver is stored in the workspace memory address ndrvpg
.
When this routine is called, the page number for the network hardware driver is read from workspace memory and written into key low-level routines in the cnp.lib for handling network data input and output.
CNP Session Begin (sessbgn_)
Purpose | Establish a connection to a CNP server |
---|---|
Jump offset | $09 |
Communications registers | A, X, Y |
Stack requirements | 6 |
Zero page usage | $a9, $aa |
Registers affected | A, X, Y |
Input parameters | RegPtr → CNP auth structure |
Output parameters |
C ← Set on error A ← 0 = ns_cpup already set A ← 1 = No carrier |
Description: This routine is called by network.lib after it opens a TCP/IP socket to a CNP server via a call to the network hardware driver. This routine begins the CNP session and cnp.lib takes ownership of the network hardware driver's TCP/IP socket.
The cnp.lib calls sethand
on the network hardware driver, passing itself
as the handler for the driver's online data mode. This means that all data received
by the network hardware driver, if the the network hardware is online (i.e., has a
TCP/IP socket open,) is sent to the cnp.lib for processing.
The call to the network hardware driver's sethand
returns status
information about whether it is online. If it's offline, this routine returns with
the carry set, indicating an error, and the accumulator set to 1, indicating that the
CNP session cannot be started because the network hardware is offline. This could
happen, for example, if the CNP server dropped the connection before the cnp.lib
had an chance to authenticate.
If the connection is still open, the keep alive timer is resumed. If the network
status flag, ns_cpup
is set, that is because the network was already
brought up, and the session was already begun by the cnp.lib in a different App
bank, or by something in this App bank which subsequently unloaded the network.lib.
In this case, the authentication credentials don't need to be sent. This
cnp.lib has been assigned as the data handler for the network hardware driver's
online data traffic. It returns with the carry set, to indicate that it did not
transmit the authentication credentials. But the accumulator is set to 0, which
indicates that this is not an error, and that the CNP session is already up.
Otherwise, it uses the RegPtr to the CNP auth structure. From this, it gets two pointers, the first to the CNP username, the second to the CNP password. It sends the username and password translated from PETSCII to ASCII, ending each with a carriage return. Clears the carry and returns, to indicate that the authentication credentials were sent.
Sending the credentials is asynchronous. This routine only sends the credentials to the network hardware driver and returns, it does not verify that the credentials were accepted. If the credentials are not accepted, the CNP server will drop the connection, at which time, the network.lib will reclaim ownership of the network hardware driver's data handlers, and the process of joining a CNP server can be attempted again.
Below is an example of a valid CNP authentication structure. A RegPtr to
cnpauth
could be passed to the call to sessbgn
. In
practice, you will not need to do this, because the network.lib does it for you.
cnp_user .null "username" cnp_pass .null "password" cnpauth ;Authentication Structure .word cnp_user .word cnp_pass
CNP Session End (sessend_)
Purpose | Request to end a CNP session |
---|---|
Jump offset | $0c |
Communications registers | Carry |
Stack requirements | 4+ |
Zero page usage | None |
Registers affected | A, X, Y |
Input parameters |
C → Clear = Send end-session service message C → Set = Notification that the TCP/IP socket is closed |
Output parameters | None |
Description: This routine is used both to instigate closing a CNP session and also to notify the cnp.lib that the session has already ended because the network hardware driver's TCP/IP socket was closed.
If the network hardware driver loses its TCP/IP socket connection, the network.lib
takes over control of the driver's data handlers and it calls sessend
with the carry set. At this point, cnp.lib undergoes a
session closing procedure. It pauses the keep alive timer. It loops over all open
sockets, deallocates their transmit and receive buffers, flags them as closed, and
removes them from its open sockets table. Individual sockets do not have their
status callback called when this happens, however the network.lib sends a general
mc_ntwrk
status message to inform the Application and/or Utility that
the operating system has gone offline. This message can be used to know, implicitly,
that all sockets have been closed.
sessend
can be called with the carry clear to tell the cnp.lib to end the
CNP server session. This is typically handled by using the Network Utility and
clicking the Stop button under the CNP tab. To end the session a service-type
packet is sent, with an "endsession" command in the payload.
The service packet is sent asynchronously. This routine returns immediately with no output parameters. The CNP server receives the message, closes the TCP/IP socket, and that then triggers the other function of this routine, as described above.
Socket Management
Open a CNP Socket (opencnps_)
Purpose | Open a CNP socket connection |
---|---|
Jump offset | $0f |
Communications registers | Carry, X, Y |
Stack requirements | 4 |
Zero page usage | $a9,$aa |
Registers affected | A, X, Y |
Input parameters | RegPtr → CNP socket structure |
Output parameters |
C ← Set on error. Either the cnp.lib is offline or there is no free socket slot. |
Description: This routine is used to open a CNP socket. Call the routine by passing a RegPtr to a CNP socket structure. If the cnp.lib is offline or if there are no available slots in the open sockets table, then the carry is returned set, to indicate a general error and failure to open the socket.
The pointer to the socket structure is inserted into a free slot in the open sockets
table. The socket's status flag csf_opng
is set to indicate that the
socket is in the process of opening. A pt_open
type packet is sent, the
payload is the null-terminated string pointed to by the socket structure at the
csk_name
offset. This can be an "ip:port" or a "domain:port", it is
interpreted by the TCP/IP networking in the CNP server which uses this string to
open the remote TCP/IP socket to which this CNP socket bridges.
The pt_open
type packet is sent asynchronously, and this routine
returns with the carry clear to indicate that the socket is in the process of
opening.
At some point in the future, if the socket opens successfully, its csf_opng
status flag is cleared and its csf_open
flag is set. The socket's status
change callback is called with the status csc_open
.
If the socket failed to open, the csf_opng
status flag is cleared, the
socket's status change callback is called with the status csc_fail
and
the socket is automatically removed from the cnp.lib's open sockets table.
Close a CNP socket (closecnps_)
Purpose | Close a CNP socket connection |
---|---|
Jump offset | $12 |
Communications registers | Carry, X, Y |
Stack requirements | 4+ |
Zero page usage | - |
Registers affected | A, X, Y |
Input parameters | RegPtr → CNP socket structure |
Output parameters |
C ← Clear if the socket close is underway C ← Set if the cnp.lib is offline, the socket is closed. |
Description: This routine is used to close a CNP socket that is currently open. Call this routine by passing a RegPtr to the CNP socket to close.
If the cnp.lib is already offline, a csc_clos
message is sent immediately
to the socket's status callback. And then this routine returns with the carry set.
Otherwise, a pt_close
type packet is sent with the port number of this
socket. This is sent asynchronously. The csf_clng
status flag is set on
the socket to indicate that it is in the process of closing. This routine returns
with the carry clear to indicate that the close packet has been sent.
At some point in the future, the socket will close. The csf_open
status
flag is cleared and the socket's status change callback is called with the status
csc_clos
. The socket is automatically removed from the cnp.lib's open
sockets table.
Socket Transmission
Transmitting data on a socket follows a similar pattern to writing data to a file on disk. To write data to a file on disk, the file must previously have been opened. Similarly, to transmit data on a socket the socket must previous have been opened.
To write data to an open file, a sequence of steps is required. First chkout
is called for the logical file number, this prepares the file to be written to, then
a series of chrout
calls write individual bytes to the file. Finally,
clrchn
is used to indicate that the write session is complete and to
prepare the bus for a different operation, such as reading or writing from/to a
different file.
Similarly, to write data to an open socket, a sequence of steps is required. First cnpsout is called with a pointer to the socket structure. This prepares the cnp.lib for a write session to that socket. Then a series of cnpsput calls write individual bytes to the socket. Finally, a call to cnpsclr ends the write session.
The main difference in the procedures of writing to a file and writing to a socket is that you can write an unlimited amount of data to a file in a single session. Writing data to a socket is limited to filling up a single packet; up to 255 bytes. Each call to cnpsput returns with the carry clear if the socket can accept more data or set if the packet is full. Calling cnpsclr sends the packet, with the datasize and checksum configured in the header.
Prepare a socket for transmission (cnpsout_)
Purpose | Prepare a socket for transmission |
---|---|
Jump offset | $15 |
Communications registers | Carry, A, X, Y |
Stack requirements | 2+ |
Zero page usage | - |
Registers affected | A, X, Y |
Input parameters | RegPtr → CNP socket pointer |
Output parameters |
None Raises exceptions. |
Description: This routine is used to prepare a previously opened socket for data to be transmitted. Call this routine with a RegPtr to the CNP socket structure.
This routine can only be called if a write session is not already in progress. Any
current write session must be completed by a call to cnpsclr
before calling this routine again. If cnpsout
is called a second time,
before cnpsclr is called, an exception is raised.
Memory buffers for sockets are managed automatically. If this socket does not have an allocated transmission buffer one is allocated and assigned automatically. This routine returns with no output parameters.
Write a byte to transmit on a socket (cnpsput_)
Purpose | Write a byte to a socket that's been prepared by cnpsout |
---|---|
Jump offset | $18 |
Communications registers | Carry, A |
Stack requirements | 2 |
Zero page usage | $a9, $aa |
Registers affected | A, X |
Input parameters | A → byte to transmit |
Output parameters |
C ← Clear = packet can take more data C ← Set = current packet is full |
Description: This routine is used to write a byte to a socket for transmitting. The socket has to be open and it must be prepared for the write session by calling cnpsout on it first.
Load the byte to be transmitted into the accumulator and call this routine. The carry is returned indicating whether this packet can take more data. If the carry is clear, you can continue to call this routine. If the packet is full and you continue to write more bytes this session, there is no error and no exception raised, but the upload datastream will be corrupted.
The Y register is unaffected by this routine, allowing you to use it as a loop index. After the packet is full, or if you have no more data to transmit at this time, call cnpsclr to end this write session and send this packet.
End a socket write session (cnpsclr_)
Purpose | End a socket write session and allow another to be started |
---|---|
Jump offset | $1b |
Communications registers | None |
Stack requirements | 4+ |
Zero page usage | $a9, $aa |
Registers affected | A, X, Y |
Input parameters | None |
Output parameters |
None Raises exceptions |
Description: This routine is used to end a socket write session. The session starts with cnpsout, then a series of cnpsput, and then ends with this routine.
If cnpsclr
is called but cnpsout has not previously
been called, an exception is raised. Also, if cnpsout is called
and then cnpsclr
is called but no bytes were output using
cnpsout, an exception is raised. If you have a reason why the
write session must or may be started and ended with no bytes transmitted, wrap the
call to cnpsclr
in a try/catch.
This routine returns nothing. The packet is sent asynchronously by passing the packet data to the network hardware driver for transmission.
While a socket is transmitting a packet its csf_txng
status flag is
set. You cannot transmit another packet on this socket until the one being transmitted
is acknowledged. Without any involvement from your Application, the CNP Server and the
cnp.lib may negotiate resending the current packet. The cnp.lib holds a copy of the
current packet in the socket's transmit buffer until it receives the acknowledgement.
You do not need to poll the socket for its readiness to send more data. When the
sent packet is acknowledged, the csf_txng
status flag is cleared and
the socket's status callback is called with a csc_tclr
, socket clear
to transmit. Upon receiving this message you can immediately start a new socket
write session.
Socket Receiving
Receiving data on a socket follows a similar pattern to reading data from a file on disk. To read data from a file on disk, the file must previously have been opened. Similarly, to receive data on a socket the socket must previous have been opened. The analogy is not perfect; a file is opened either for read or for write. When a socket is opened, it is always bi-directional.
To read data from an open file, a sequence of steps is required. First chkin
is called for the logical file number, this prepares the file to be read from, then
a series of chrin
calls read individual bytes from the file. Finally,
clrchn
is called to indicate that the read session is complete and to
prepare the bus for a different operation.
Similarly, to read data from an open socket, a sequence of steps
is required. First cnpsin is called with a pointer to the
socket structure. This prepares the cnp.lib for a read session from that socket.
Then a series of cnpsget calls read individual bytes from
the socket. Finally, a call to cnpsack ends the read session.
The main difference is that you can read an unlimited amount of data from a file,
all the way to the end of the file, in a single session. Reading data from a socket
is limited to the content of a single packet; up to 255 bytes. Each call
to cnpsget returns the
byte read in the accumulator and the carry indicates if there is more data. If the
carry is clear, there are more bytes to be read from the packet. If the carry is
set, then this call to cnpsget has given you the last byte.
This is analogous to the status
byte indicating EOF
after
reading the last byte from a file.
Calling cnpsack sends an acknowledge response packet. You must read all bytes from the packet in a single session. If you only need a few bytes from the packet, you can abandon the rest of the packet's data by calling cnpsack prematurely. But you cannot perform multiple read sessions from the same packet. As soon as the acknowledgement is sent the CNP server will send the next packet, which overwrites the current packet in the socket's receive buffer.
Starting in C64 OS v1.08, a socket may also be paused and resumed later. Pausing
the socket tells the CNP server to stop sending data to this socket and to hold the
data buffered in the CNP Server. If you are receiving data, you can start the read
session with cnpsin, read all the data with a series of
call to cnpsget, and then call cnpspas.
The pt_pause
packet type acknowledges receipt of the last packet and
also pauses the flow. Calling cnpsres tells the CNP server
to resume sending data. This can be used to interrupt a long download that's in
progress in an Application. You can then leave that Application by Fast App Switching
back home, go into a different Application and even use network sockets in the new
App. When you return to the original App, it thaws from the REU, sends the resume
packet, and the download carries on right where it left off.
Prepare a socket for receiving data (cnpsin_)
Purpose | Prepare a socket for receiving |
---|---|
Jump offset | $1e |
Communications registers | X, Y |
Stack requirements | 2+ |
Zero page usage | $a9, $aa |
Registers affected | A, X, Y |
Input parameters | RegPtr → CNP socket pointer |
Output parameters |
None Raises exceptions. |
Description: This routine is used to prepare a previously opened socket for data to be received. Call this routine with a RegPtr to the CNP socket structure.
This routine can only be called on a socket that is open. If the socket is not open
an exception is raised. Additionally, this routine should only be called in response
to a csc_data
status message. The socket's status change callback is
called with csc_data
when this socket has data that is ready to be
read, i.e., when it has received a complete packet and that packet has passed the
checksum.
Memory buffers for sockets are managed automatically. When a packet begins to be received on a socket, if the socket does not have an allocated receive buffer, one is allocated automatically. Then this routine returns with no output parameters.
Read a byte received on a socket (cnpsget_)
Purpose | Read a byte from a socket that's been prepared by cnpsin |
---|---|
Jump offset | $21 |
Communications registers | Carry, A |
Stack requirements | 2 |
Zero page usage | None |
Registers affected | A, X |
Input parameters | None |
Output parameters |
A ← byte read from the socket C ← Set = the last data byte in the packet |
Description: This routine is used to receive a byte from a socket. The socket has to be open and it must be prepared for the read session by calling cnpsin on it first.
The byte read from the socket is returned in the accumulator. The carry is used to
indicate if more data is available for read. If the carry is returned set, then the byte
in the accumulator is the last byte in the packet. After the last byte has been read,
you should not call cnpsget
again. Doing so will not cause a crash but
the data returned is undefined.
The Y register is unaffected by this routine, allowing you to use it as a loop index. You must read all the data from the current packet that you want to read in a single session. Typically this will be to the end, but you can stop reading data from the packet prematurely if the remainder of the data is not needed. When the read session is complete, you will either call cnpsack to acknowledge receipt of this packet and signal readiness to receive the next packet, or call cnpspas to acknowledge receipt of this packet but tell the CNP server to wait before sending the next packet.
End a socket read session (cnpsack_)
Purpose | End a socket read session, acknowledge the packet and permit the next one. |
---|---|
Jump offset | $24 |
Communications registers | None |
Stack requirements | 4+ |
Zero page usage | None |
Registers affected | A, X, Y |
Input parameters | None |
Output parameters | None |
Description: This routine is used to end a socket read session. The session starts with cnpsin, then a series of cnpsget, and then ends with this routine.
This routine returns nothing. The pt_ack
packet is sent asynchronously.
Unlike the csf_txng
status flag, there is no equivalent flag for
receiving data. You do not poll the socket waiting for new data to be available
to read. When a new packet has been received, data is ready to be read from the socket.
The socket's status change callback is called with the csc_data
message.
After calling cnpsack
, you are signalling to the CNP server the socket's
readiness to receive more data. And you then wait for the socket status change callback
to be called with csc_data
.
Pause and Resume Socket
This part of the specification is new in v1.08. This part of the spec is not 100% stable yet. How these work may be revised in the next version of C64 OS.
End a socket read session and pause flow (cnpspas_)
Purpose | End a socket read session, acknowledge the packet and pause flow. |
---|---|
Jump offset | $27 |
Communications registers | None |
Stack requirements | 4+ |
Zero page usage | None |
Registers affected | A, X, Y |
Input parameters | None |
Output parameters | None |
Description: This routine is used, much like
cnpsack to end a socket read session. This routine
acknowledges receipt of the previous packet, preparing the CNP server to send the
next packet, but tells it to wait for a pt_resum
packet before sending
the next packet.
This routine returns nothing. The pt_pause
packet is sent asynchronously.
Typically cnpspas
is used instead of cnpsack in
two situations: to give your Application time to write previously received data out
to disk, or to allow your Application to go into the background (with Fast App
Switching) without losing any data that still needs to be sent.
Pause and resume are like two halves of a cnpsack. The call
to cnpspas
acknowledges that the packet was successfully received,
but the CNP server will not send the next packet until you call
cnpsres.
Signal that a socket is ready to receive more data (cnpsres_)
Purpose | Signal that a socket is ready to receive more data |
---|---|
Jump offset | $2a |
Communications registers | X, Y |
Stack requirements | 4+ |
Zero page usage | None |
Registers affected | A, X, Y |
Input parameters | None |
Output parameters | None |
Description: This routine is used to signal to the CNP server that the socket that was previously paused is ready to receive data again.
This routine returns nothing. The pt_resum
packet is sent asynchronously.
This routine should only be called after previously calling
cnpspas. After calling cnpsres
, the socket
is in exactly the same state as if you had just called cnpsack.
There is no guarantee that an other packet may arrive or when, but the socket is
ready again to receive new packets.
Reading from and writing to other sockets is possible between
cnpspas and cnpsres
, but only in a different
App bank. The reason is because, in this App bank, after calling cnpspas
the read session is still underway. The read session is not fully completed until
the cnpsres
. Therefore, you cannot start a new read session, as this
changes the cnp.lib's internal pointers.
You can, however, acknowedge and pause the socket, and then Fast App Switch to a
different App. The socket's read session, and the cnp.lib's internal pointers are
all still configured in this App bank. The cnp.lib running in a different App bank
can access sockets there. When you return to this App bank, you must then call
cnpsres
to resume this socket, but it contextual to all the pointers
already configured for this socket in the cnp.lib in this App bank.
Previous Section: Library Reference
Next Chapter: Using Toolkit
Table of Contents
This document is subject to revision updates.
Last modified: Jul 03, 2025