diff --git a/src/protocol/client.ts b/src/protocol/client.ts index e200030..ddc3ef0 100644 --- a/src/protocol/client.ts +++ b/src/protocol/client.ts @@ -169,6 +169,7 @@ export class ViceClient { // Process complete packets // Response header: STX(1) + API(1) + bodyLength(4) + responseType(1) + errorCode(1) + requestId(1) = 9 bytes + // Then body of `bodyLength` bytes follows while (this.responseBuffer.length >= 9) { const stx = this.responseBuffer[0]; if (stx !== STX) { @@ -179,7 +180,7 @@ export class ViceClient { } const bodyLength = this.responseBuffer.readUInt32LE(2); - const totalLength = 6 + bodyLength; // Header prefix (6) + body (which includes type, error, reqId) + const totalLength = 9 + bodyLength; // Header (9) + body debugLog(`Packet: bodyLength=${bodyLength}, totalLength=${totalLength}, bufferLen=${this.responseBuffer.length}`); @@ -272,11 +273,11 @@ export class ViceClient { const requestId = this.nextRequestId(); // Build packet: STX(1) + API(1) + Length(4) + RequestID(1) + Command(1) + Body - // Length field includes: RequestID(1) + Command(1) + Body + // Length field is ONLY the command body, NOT including ReqID or Command const header = Buffer.alloc(8); header[0] = STX; header[1] = API_VERSION; - header.writeUInt32LE(body.length + 2, 2); // Body length includes request ID (1) and command (1) + header.writeUInt32LE(body.length, 2); // Just the command body length header[6] = requestId; header[7] = command; diff --git a/src/protocol/types.ts b/src/protocol/types.ts index 192ec47..5e2f5b8 100644 --- a/src/protocol/types.ts +++ b/src/protocol/types.ts @@ -2,42 +2,44 @@ // API Constants export const STX = 0x02; -export const API_VERSION = 0x02; +export const API_VERSION = 0x01; // VICE 3.x uses API v1 -// Command codes +// Command codes (per KB docs) export enum Command { // Memory operations MemoryGet = 0x01, MemorySet = 0x02, // Checkpoint (breakpoint/watchpoint) operations - CheckpointGet = 0x11, - CheckpointSet = 0x12, + CheckpointSet = 0x11, + CheckpointGet = 0x12, CheckpointDelete = 0x13, CheckpointList = 0x14, CheckpointToggle = 0x15, // Register operations - RegistersGet = 0x31, - RegistersSet = 0x32, + RegistersGet = 0x22, + RegistersSet = 0x23, // Execution control + Continue = 0x31, + Step = 0x32, + Reset = 0x43, + + // Dump/Undump (snapshots) Dump = 0x41, Undump = 0x42, - Reset = 0x43, // Resources ResourceGet = 0x51, ResourceSet = 0x52, - // Advanced execution - AdvanceInstructions = 0x71, - KeyboardFeed = 0x72, - Continue = 0x81, - Step = 0x82, + // Exit + Exit = 0x71, - // Quit - Quit = 0xbb, + // Advanced execution + KeyboardFeed = 0x72, + AdvanceInstructions = 0x73, // Display DisplayGet = 0x84, diff --git a/test-binary-protocol.js b/test-binary-protocol.js new file mode 100644 index 0000000..eb9517f --- /dev/null +++ b/test-binary-protocol.js @@ -0,0 +1,102 @@ +#!/usr/bin/env node +// Quick test script to verify VICE binary monitor protocol +// Run: node test-binary-protocol.js + +import { Socket } from 'net'; + +const HOST = '127.0.0.1'; +const PORT = 6502; + +const sock = new Socket(); +let buffer = Buffer.alloc(0); + +function parsePackets() { + while (buffer.length >= 9) { + const stx = buffer[0]; + if (stx !== 0x02) { + console.log(`Skipping non-STX byte: 0x${stx.toString(16)}`); + buffer = buffer.subarray(1); + continue; + } + + const apiVer = buffer[1]; + const bodyLength = buffer.readUInt32LE(2); + const totalLength = 9 + bodyLength; + + console.log(`\nPacket header: STX=0x${stx.toString(16)} API=0x${apiVer.toString(16)} bodyLen=${bodyLength} totalLen=${totalLength} bufLen=${buffer.length}`); + + if (buffer.length < totalLength) { + console.log(' Waiting for more data...'); + break; + } + + const respType = buffer[6]; + const errorCode = buffer[7]; + const reqId = buffer[8]; + const body = buffer.subarray(9, totalLength); + + console.log(` RespType: 0x${respType.toString(16)}`); + console.log(` Error: 0x${errorCode.toString(16)}`); + console.log(` ReqID: ${reqId} (0x${reqId.toString(16)})`); + console.log(` Body (${body.length} bytes): ${body.toString('hex')}`); + + // Interpret response type + const typeNames = { + 0x00: 'Invalid', + 0x01: 'OK', + 0x02: 'Object', + 0x11: 'Stopped', + 0x12: 'Resumed', + 0x31: 'MemoryGet', + 0x62: 'RegisterInfo', + 0x63: 'CheckpointHit', + }; + console.log(` Type name: ${typeNames[respType] || 'Unknown'}`); + + buffer = buffer.subarray(totalLength); + } +} + +sock.on('connect', () => { + console.log('Connected to VICE'); + + // Send a simple registers get command + const body = Buffer.from([0x00]); // memspace = main CPU + const header = Buffer.alloc(8); + header[0] = 0x02; // STX + header[1] = 0x01; // API version + header.writeUInt32LE(body.length, 2); // body length + header[6] = 0x01; // request ID + header[7] = 0x22; // RegistersGet command + + const packet = Buffer.concat([header, body]); + console.log('Sending packet:', packet.toString('hex')); + + sock.write(packet); + console.log('Packet sent, waiting for response...'); +}); + +sock.on('data', (data) => { + console.log(`\n--- Received ${data.length} bytes: ${data.toString('hex')}`); + buffer = Buffer.concat([buffer, data]); + parsePackets(); +}); + +sock.on('error', (err) => { + console.error('Socket error:', err.message); +}); + +sock.on('close', () => { + console.log('\nConnection closed'); + if (buffer.length > 0) { + console.log(`Remaining buffer: ${buffer.toString('hex')}`); + } +}); + +sock.on('timeout', () => { + console.log('Socket timeout'); + sock.end(); +}); + +sock.setTimeout(5000); +sock.connect(PORT, HOST);