Skip to content

Commit

Permalink
m1n1.fw.afk: Fix r/w block stride for 13.5
Browse files Browse the repository at this point in the history
DCP doesn't use the r/w functions, but considering the hardcoded
AOP/IOP, I should probably inherit this

Signed-off-by: Eileen Yoon <[email protected]>
  • Loading branch information
eiln committed Jan 19, 2024
1 parent ca85722 commit f7ffcc1
Showing 1 changed file with 34 additions and 24 deletions.
58 changes: 34 additions & 24 deletions proxyclient/m1n1/fw/afk/rbep.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
# SPDX-License-Identifier: MIT

import struct
from construct import *

from ..common import *
from ...utils import *
from ..asc.base import *

class AFKError(Exception):
pass

class AFKEPMessage(Register64):
TYPE = 63, 48
Expand Down Expand Up @@ -50,19 +52,24 @@ class AFKEP_Shutdown(AFKEPMessage):
class AFKEP_Shutdown_Ack(AFKEPMessage):
TYPE = 63, 48, Constant(0xc1)


class AFKError(Exception):
pass
# TODO no one else but AOP uses AFKRingBuf right?
AFKRingBufItem = Struct(
"magic" / PaddedString(4, "utf8"),
"size" / Int32ul,
"unk1" / Int32ul,
"unk2" / Int32ul,
)

class AFKRingBuf(Reloadable):
BLOCK_SIZE = 0x40
BLOCK_COUNT = 3

def __init__(self, ep, base, size):
self.ep = ep
self.base = base

bs, unk = struct.unpack("<II", self.read_buf(0, 8))
assert (bs + 3 * self.BLOCK_SIZE) == size
assert (bs + self.BLOCK_COUNT * self.BLOCK_SIZE * 2) == size
self.bufsize = bs
self.rptr = 0
self.wptr = 0
Expand All @@ -72,7 +79,7 @@ def read_buf(self, off, size):

def write_buf(self, off, data):
return self.ep.iface.writemem(self.base + off, data)

def get_rptr(self):
return self.ep.asc.p.read32(self.base + self.BLOCK_SIZE)

Expand All @@ -88,45 +95,48 @@ def update_wptr(self, rptr):
def read(self):
self.wptr = self.get_wptr()

while self.wptr != self.rptr:
hdr = self.read_buf(3 * self.BLOCK_SIZE + self.rptr, 16)
self.rptr += 16
magic, size = struct.unpack("<4sI", hdr[:8])
assert magic in [b"IOP ", b"AOP "]
if size > (self.bufsize - self.rptr):
hdr = self.read_buf(3 * self.BLOCK_SIZE, 16)
self.rptr = 16
magic, size = struct.unpack("<4sI", hdr[:8])
assert magic in [b"IOP ", b"AOP "]

payload = self.read_buf(3 * self.BLOCK_SIZE + self.rptr, size)
self.rptr = (align_up(self.rptr + size, self.BLOCK_SIZE)) % self.bufsize
stride = self.BLOCK_COUNT * self.BLOCK_SIZE * 2
while self.wptr != self.rptr or (self.rptr == 0 and self.wptr == 0):
hdr = self.read_buf(stride + self.rptr, AFKRingBufItem.sizeof())
item = AFKRingBufItem.parse(hdr)
if item.magic not in ["IOP ", "AOP "]: break
self.rptr += AFKRingBufItem.sizeof()

if (item.size > (self.bufsize - self.rptr)):
hdr = self.read_buf(stride, AFKRingBufItem.sizeof())
item = AFKRingBufItem.parse(hdr)
self.rptr = AFKRingBufItem.sizeof()
assert magic in ["IOP ", "AOP "]

payload = self.read_buf(stride + self.rptr, item.size)
self.rptr = (align_up(self.rptr + item.size, self.BLOCK_SIZE)) % self.bufsize
self.update_rptr(self.rptr)
yield hdr[8:] + payload
self.wptr = self.get_wptr()

self.update_rptr(self.rptr)

def write(self, data):
stride = self.BLOCK_COUNT * self.BLOCK_SIZE * 2
hdr2, data = data[:8], data[8:]
self.rptr = self.get_rptr()

if self.wptr < self.rptr and self.wptr + 0x10 >= self.rptr:
raise AFKError("Ring buffer is full")

hdr = struct.pack("<4sI", b"IOP ", len(data)) + hdr2
self.write_buf(3 * self.BLOCK_SIZE + self.wptr, hdr)
self.write_buf(stride + self.wptr, hdr)

if len(data) > (self.bufsize - self.wptr - 16):
if self.rptr < 0x10:
raise AFKError("Ring buffer is full")
self.write_buf(3 * self.BLOCK_SIZE, hdr)
self.write_buf(stride, hdr)
self.wptr = 0

if self.wptr < self.rptr and self.wptr + 0x10 + len(data) >= self.rptr:
raise AFKError("Ring buffer is full")

self.write_buf(3 * self.BLOCK_SIZE + self.wptr + 0x10, data)
self.write_buf(stride + self.wptr + 0x10, data)
self.wptr = align_up(self.wptr + 0x10 + len(data), self.BLOCK_SIZE) % self.bufsize

self.update_wptr(self.wptr)
Expand Down Expand Up @@ -219,7 +229,7 @@ def Recv(self, msg):

def handle_ipc(self, data):
pass

def send_ipc(self, data):
wptr = self.txq.write(data)
self.send(AFKEP_Send(WPTR = wptr))

0 comments on commit f7ffcc1

Please sign in to comment.