package devices import ( "encoding/binary" "fmt" "log" "go.bug.st/serial" ) const ( MAX_DATA_SIZE = 512 ) type N64 interface { Start() error Close() error SendData(data []byte) error ReceiveData() ([]byte, error) } type EverDrive struct { PortName string port serial.Port running bool } func (e *EverDrive) Start() error { mode := &serial.Mode{ BaudRate: 9600, DataBits: 8, Parity: serial.NoParity, // Changed from EvenParity StopBits: serial.OneStopBit, // Changed from TwoStopBits } port, err := serial.Open(e.PortName, mode) if err != nil { return err } e.port = port e.running = true return nil } func (e *EverDrive) Close() error { return nil } func (e *EverDrive) SendData(data []byte) error { if !e.running { return fmt.Errorf("N64 is not running") } // --- 1. CONSTRUCT THE UNFLOADER PACKET --- // Header (4 Bytes) packet := []byte{'D', 'M', 'A', '@'} // Data Type (1 Byte) // using 0x01 (DataTypeText) is fine, or define your own. packet = append(packet, 0x01) // Size (3 Bytes, Big Endian) // This tells usb.c how many REAL bytes of payload to expect. lengthBuf := make([]byte, 4) binary.BigEndian.PutUint32(lengthBuf, uint32(len(data))) packet = append(packet, lengthBuf[1:]...) // Skip first byte, append last 3 // Payload (The Coin) packet = append(packet, data...) // PAYLOAD ALIGNMENT (Crucial per usb.c line 640) // len = ALIGN(usb_datasize, 2); // If we send 1 byte (odd), usb.c will read 2 bytes. // We must provide that padding byte or it will eat the 'C' of the footer. if len(data)%2 != 0 { packet = append(packet, 0x00) } // Footer (4 Bytes) packet = append(packet, 'C', 'M', 'P', 'H') // --- 2. HARDWARE PADDING (The Fix) --- // The EverDrive needs a 512-byte transfer to wake up. // We pad the rest of the buffer with zeros. // The N64 will read the packet above, then fail 'DMA@' checks // on the zeros until the buffer is empty. This is expected behavior. blockSize := 512 totalLen := len(packet) if totalLen < blockSize { padding := make([]byte, blockSize-totalLen) packet = append(packet, padding...) } // Write exactly 512 bytes _, err := e.port.Write(packet) if err != nil { log.Printf("❌ N64 Write Error: %v", err) return err } log.Printf("📤 Sent Packet (Payload: %v | Total Wire: %d)", data, len(packet)) return nil } func (e *EverDrive) ReceiveData() ([]byte, error) { if !e.running { return nil, fmt.Errorf("N64 is not running") } data := make([]byte, MAX_DATA_SIZE) _, err := e.port.Read(data) if err != nil { log.Printf("❌ N64 Read Error: %v", err) return nil, err } log.Printf("📥 Received %s from N64", data) return data, nil } func NewEverDrive(portName string) *EverDrive { return &EverDrive{PortName: portName} }