Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CLAUDE.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -163,7 +163,8 @@ to the ip65 layout.

### UCI test scripts

Scripts under `tools/uci/` require a U64E at 192.168.1.81 and use
Scripts under `tools/uci/` require a U64E (default 192.168.1.81,
overridable via the `U64_HOST` environment variable) and use
`DeviceLock` + `enable_uci`/`disable_uci`:

- `boot_check.py` — verify UCI firmware detection and boot banner
Expand Down
21 changes: 21 additions & 0 deletions LICENSE
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 JC-000

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
19 changes: 12 additions & 7 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,11 +18,11 @@ An HTTPS client for the Commodore 64 in 6502 assembly. Implements TLS 1.3 over T
│ │ Record Layer │ Handshake Proto │ │ tls_record.asm, tls_handshake.asm
│ └──────┬───────┴────────┬─────────┘ │
│ │ │ │
│ ┌──────┴───────┐ ┌─────┴──────────┐
│ │ AEAD │ │ Key Schedule │ │ (crypto modules)
│ │ ChaCha20- │ │ HKDF-SHA256 │ │ hkdf.asm
│ │ Poly1305 │ │ ECDHE P-256 │ │
│ └──────────────┘ └────────────────┘ │
│ ┌──────┴───────┐ ┌─────┴─────────
│ │ AEAD │ │ Key Schedule │ │ (crypto modules)
│ │ ChaCha20- │ │ HKDF-SHA256 │ │ hkdf.asm
│ │ Poly1305 │ │ ECDHE P-256 │
│ └──────────────┘ └────────────────┘
├─────────────────────────────────────────┤
│ Network ABI (src/net_abi.inc) │ net_init / net_tcp_* / net_dns_*
├──────────────────────┬──────────────────┤
Expand DownExpand Up@@ -114,7 +114,12 @@ The Makefile automatically builds ip65 from the submodule into a flat binary blo

## Project Status

Current status (40 KB binary, 537 labels):
Current status:

- 38 KB binary (ip65 build), 1738 labels
- 38 KB binary (uci build), 1816 labels

Progress:

- [x] Project structure and build system
- [x] ip65 submodule integration — 6.8 KB binary blob at $2000 (TCP/UDP/DNS/DHCP/ARP + RR-Net CS8900a)
Expand DownExpand Up@@ -205,7 +210,7 @@ The setup script creates `br-c64` with `tap-c64-0`/`tap-c64-1`, assigns `10.0.65

### Ultimate 64 Elite Hardware Tests (UCI backend)

Scripts under `tools/uci/` drive a real Ultimate 64 Elite over the network (default `192.168.1.81`), exercising the **UCI backend only** (built with `make BACKEND=uci`). They DMA the PRG into RAM, run the boot, and snapshot UCI/TLS state on completion or timeout. These scripts do not run under VICE.
Scripts under `tools/uci/` drive a real Ultimate 64 Elite over the network (default `192.168.1.81`, overridable via the `U64_HOST` environment variable), exercising the **UCI backend only** (built with `make BACKEND=uci`). They DMA the PRG into RAM, run the boot, and snapshot UCI/TLS state on completion or timeout. These scripts do not run under VICE.

```bash
python3 tools/uci/boot_check.py # UCI firmware detection
Expand Down
41 changes: 24 additions & 17 deletions src/net/ip65/net.s
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,9 +10,15 @@
; The callback must NOT touch crypto state — it only copies received data
; into tcp_recv_buf (a ring buffer) for later processing by the TLS layer.
;
; The d973531 fix (clamp cb_remaining to 255 per callback invocation) is
; preserved verbatim. The ZP $02-$1B save/restore around every ip65 call
; is load-bearing — do not remove.
; The ZP $02-$1B save/restore around every ip65 call is load-bearing —
; do not remove.
;
; The former d973531 clamp (cb_remaining -> 255 bytes per callback) was
; a data-loss bug: ip65 ACKs the full tcp_inbound_data_length regardless
; of how many bytes the callback consumes, so any byte past #255 was
; silently dropped. TLS records larger than 255 B (e.g. a Certificate
; record) got corrupted. The callback now copies the full 16-bit length
; and advances the SMC source high-byte when the 8-bit X index wraps.

.include "constants.inc"
.include "ip65_symbols.inc"
Expand DownExpand Up@@ -316,8 +322,11 @@ net_recv_byte:
; SMC instructions below so we can read those ip65 variables using absolute
; addressing (no ZP indirection needed).
;
; d973531 fix (preserved): cb_remaining is clamped to 255 bytes per callback
; invocation so the 8-bit X index cannot wrap and re-read the inbound buffer.
; 16-bit copy: cb_remaining carries the full inbound length (up to 1460 B
; for a full MSS segment). The inner loop uses X as an 8-bit source index
; and the SMC source base (cb_copy_byte+1/+2). When X wraps 0->0 (256 B
; consumed) we advance the high byte of the SMC source so successive
; 256-byte windows of the inbound buffer are copied correctly.
; =============================================================================
net_tcp_recv_cb:
; --- Read inbound data length (16-bit) ---
Expand All@@ -340,17 +349,10 @@ cb_load_ptr_hi:
lda $ffff ; SMC: patched to addr of tcp_inbound_data_ptr+1
sta cb_copy_byte+2 ; patch high byte of LDA abs,x source

; Clamp cb_remaining to 255 bytes max per callback to prevent
; 8-bit X-index wrap which would re-read source byte 0 onwards
; and overwrite previously-copied ring bytes. (d973531)
lda cb_remaining+1
beq :+
lda #255
sta cb_remaining
lda #0
sta cb_remaining+1
:
; Copy loop: X = source index; ring store uses SMC on cb_store
; Copy loop: X = source index (wraps every 256 B; when it wraps
; we advance the high byte of the SMC source pointer so the next
; 256-byte window is read from the correct address). The ring
; store uses SMC on cb_store, repatched per byte.
ldx #0
cb_loop:
; Check 16-bit remaining count
Expand All@@ -359,7 +361,7 @@ cb_loop:
bne :+
jmp cb_done
:
; --- Overflow check: if ((tail+1) & $3FF) == head, ring is full ---
; --- Overflow check: if ((tail+1) & TCP_RECV_MASK) == head, ring is full ---
lda tcp_recv_tail+0
clc
adc #1
Expand DownExpand Up@@ -395,6 +397,11 @@ cb_copy_byte:
cb_store:
sta $ffff ; SMC: patched to tcp_recv_buf + tail
inx
bne cb_src_ok
; X wrapped $FF -> $00: advance SMC source high byte to read the
; next 256-byte window of the inbound buffer.
inc cb_copy_byte+2
cb_src_ok:

; tail = next (already computed above)
lda cb_next_lo
Expand Down
Loading