Function bodies 388 total
FrameReader class · kotlin · L113-L179 (67 LOC)feature/ps2/protocol/src/commonMain/kotlin/com/my/psremoteplay/feature/ps2/protocol/Ps2Protocol.kt
class FrameReader {
private var buffer = ByteArray(4096)
private var writePos = 0
/**
* Feed raw bytes into the reader.
*/
fun feed(data: ByteArray, offset: Int = 0, length: Int = data.size) {
ensureCapacity(writePos + length)
data.copyInto(buffer, destinationOffset = writePos, startIndex = offset, endIndex = offset + length)
writePos += length
}
/**
* Returns the next complete frame as (type, payload), or null if not enough data yet.
*/
fun poll(): Pair<Byte, ByteArray>? {
if (writePos < 4) return null
val frameLength = ((buffer[0].toInt() and 0xFF) shl 24) or
((buffer[1].toInt() and 0xFF) shl 16) or
((buffer[2].toInt() and 0xFF) shl 8) or
(buffer[3].toInt() and 0xFF)
if (frameLength <= 0 || frameLength > MAX_FRAME_SIZE) {
compact(4)
return null
}
val totalNeeded = 4 + frameLength // header + body
Companion class · kotlin · L176-L178 (3 LOC)feature/ps2/protocol/src/commonMain/kotlin/com/my/psremoteplay/feature/ps2/protocol/Ps2Protocol.kt
private companion object {
const val MAX_FRAME_SIZE = 10 * 1024 * 1024 // 10MB
}Companion class · kotlin · L32-L51 (20 LOC)feature/ps2/protocol/src/commonMain/kotlin/com/my/psremoteplay/feature/ps2/protocol/StreamStats.kt
companion object {
const val PAYLOAD_SIZE = 24
fun decode(data: ByteArray): StreamStats {
require(data.size >= PAYLOAD_SIZE)
fun readInt(offset: Int): Int =
((data[offset].toInt() and 0xFF) shl 24) or
((data[offset + 1].toInt() and 0xFF) shl 16) or
((data[offset + 2].toInt() and 0xFF) shl 8) or
(data[offset + 3].toInt() and 0xFF)
return StreamStats(
framesReceived = readInt(0).toLong(),
framesDecoded = readInt(4).toLong(),
framesDropped = readInt(8).toLong(),
avgDecodeMs = readInt(12).toLong(),
avgNetworkJitterMs = readInt(16).toLong(),
currentFps = readInt(20)
)
}
}AndroidMediaCodecClient class · kotlin · L32-L363 (332 LOC)feature/ps2/src/androidMain/kotlin/com/my/psremoteplay/feature/ps2/strategy/client/AndroidMediaCodecClient.kt
class AndroidMediaCodecClient(private val logger: Logger) : VideoStreamClient {
override val name = "H.264/MediaCodec"
override val usesSurfaceRendering = true
override val currentFrame: StateFlow<ImageBitmap?> = MutableStateFlow(null)
override val decodedFrameCount: Long get() = framesDecoded.get()
@Volatile private var receiving = false
private var socket: DatagramSocket? = null
private var receiverThread: Thread? = null
private var decoderThread: Thread? = null
private var decoder: MediaCodec? = null
@Volatile private var surface: Surface? = null
private val framesReceived = AtomicLong(0)
private val framesDecoded = AtomicLong(0)
private val framesDropped = AtomicLong(0)
private val totalDecodeNs = AtomicLong(0)
private val statsStartTime = AtomicLong(0)
private val decoderLock = Any()
private val nalQueue = ConcurrentLinkedQueue<ByteArray>()
@Volatile private var spsData: ByteArray? = null
@Volatile prCompanion class · kotlin · L351-L362 (12 LOC)feature/ps2/src/androidMain/kotlin/com/my/psremoteplay/feature/ps2/strategy/client/AndroidMediaCodecClient.kt
companion object {
private const val NAL_TYPE_IDR = 5
private const val NAL_TYPE_SPS = 7
private const val NAL_TYPE_PPS = 8
private val VENDOR_LOW_LATENCY_KEYS = listOf(
"vendor.low-latency.enable",
"vendor.hisi-video-dec-low-latency-mode",
"vendor.rtc-ext-dec-low-latency.enable",
"vdec-lowlatency"
)
}NalAccumulator class · kotlin · L369-L421 (53 LOC)feature/ps2/src/androidMain/kotlin/com/my/psremoteplay/feature/ps2/strategy/client/AndroidMediaCodecClient.kt
private class NalAccumulator {
private var buffer = ByteArray(262144)
private var writePos = 0
private var scanPos = 4
companion object {
private const val MAX_BUFFER_SIZE = 4 * 1024 * 1024 // 4MB cap
}
fun feed(data: ByteArray, offset: Int, length: Int) {
ensureCapacity(writePos + length)
data.copyInto(buffer, writePos, offset, offset + length)
writePos += length
}
fun poll(): ByteArray? {
var i = scanPos
while (i + 3 < writePos) {
if (buffer[i] == 0.toByte() && buffer[i + 1] == 0.toByte() &&
buffer[i + 2] == 0.toByte() && buffer[i + 3] == 1.toByte()
) {
if (i > 0) {
val nalUnit = buffer.copyOfRange(0, i)
val remaining = writePos - i
buffer.copyInto(buffer, 0, i, writePos)
writePos = remaining
scanPos = 4
return nalUnit
Companion class · kotlin · L374-L376 (3 LOC)feature/ps2/src/androidMain/kotlin/com/my/psremoteplay/feature/ps2/strategy/client/AndroidMediaCodecClient.kt
companion object {
private const val MAX_BUFFER_SIZE = 4 * 1024 * 1024 // 4MB cap
}Same scanner, your repo: https://repobility.com — Repobility
AndroidUdpJpegClient class · kotlin · L19-L89 (71 LOC)feature/ps2/src/androidMain/kotlin/com/my/psremoteplay/feature/ps2/strategy/client/AndroidUdpJpegClient.kt
class AndroidUdpJpegClient(private val logger: Logger) : VideoStreamClient {
override val name = "MJPEG/UDP"
private val _currentFrame = MutableStateFlow<ImageBitmap?>(null)
override val currentFrame: StateFlow<ImageBitmap?> = _currentFrame.asStateFlow()
@Volatile private var receiving = false
private var socket: DatagramSocket? = null
private var readerThread: Thread? = null
override fun start(serverIp: String, config: StreamConfig): Boolean {
return try {
val s = DatagramSocket(config.videoPort)
s.soTimeout = 5000
socket = s
receiving = true
readerThread = Thread {
val buf = ByteArray(65536)
var frameCount = 0L
var totalDecodeMs = 0L
val startTime = System.currentTimeMillis()
try {
while (receiving) {
val packet = DatagramPacket(buf, buf.size)
Companion class · kotlin · L389-L563 (175 LOC)feature/ps2/src/androidMain/kotlin/com/my/psremoteplay/feature/ps2/ui/FsrRenderer.kt
companion object {
private const val VERTEX_SRC = """
#version 300 es
layout(location = 0) in vec2 aPosition;
layout(location = 1) in vec2 aTexCoord;
out vec2 vTexCoord;
void main() {
gl_Position = vec4(aPosition, 0.0, 1.0);
vTexCoord = aTexCoord;
}
"""
/** Simple OES → screen blit with SurfaceTexture transform */
private const val BLIT_OES_FRAG = """
#version 300 es
#extension GL_OES_EGL_image_external_essl3 : require
precision mediump float;
uniform samplerExternalOES uTex;
uniform mat4 uSTMatrix;
in vec2 vTexCoord;
out vec4 fragColor;
void main() {
vec2 tc = (uSTMatrix * vec4(vTexCoord, 0.0, 1.0)).xy;
fragColor = texture(uTex, tc);
}
"""
/**
* FSR EASU — Edge-Adaptive Spatial Upscaling.
*
* 12-tap directional Lanczos filter that detects edge orientation
* and elongates the filter kernel along edges to preserve sharpness.
*/
private const val EASU_FRAG = """
#version 300 es
precPs2ClientViewModel class · kotlin · L17-L170 (154 LOC)feature/ps2/src/commonMain/kotlin/com/my/psremoteplay/feature/ps2/presentation/Ps2ClientViewModel.kt
class Ps2ClientViewModel(private val deps: Ps2ClientDependencies) : ViewModel() {
private val _state = MutableStateFlow(Ps2ClientState())
val state: StateFlow<Ps2ClientState> = _state.asStateFlow()
/** Video frames from the active strategy */
val currentFrame: StateFlow<ImageBitmap?> = deps.videoStreamClient.currentFrame
private val _effects = Channel<Ps2ClientEffect>(Channel.BUFFERED)
val effects: Flow<Ps2ClientEffect> = _effects.receiveAsFlow()
private var streamingJob: Job? = null
private var inputCount = 0L
private val logger = object : Logger {
override fun log(tag: String, message: String) {
addLog(tag, message, isError = false)
deps.logger.log(tag, message)
}
override fun error(tag: String, message: String, throwable: Throwable?) {
val errMsg = "$message${throwable?.let { "\n ${it::class.simpleName}: ${it.message}" } ?: ""}"
addLog(tag, errMsg, isError = true)
Ps2ServerViewModel class · kotlin · L14-L218 (205 LOC)feature/ps2/src/commonMain/kotlin/com/my/psremoteplay/feature/ps2/presentation/Ps2ServerViewModel.kt
class Ps2ServerViewModel(private val deps: Ps2ServerDependencies) : ViewModel() {
private val _state = MutableStateFlow(Ps2ServerState())
val state: StateFlow<Ps2ServerState> = _state.asStateFlow()
private val _effects = Channel<Ps2ServerEffect>(Channel.BUFFERED)
val effects: Flow<Ps2ServerEffect> = _effects.receiveAsFlow()
init {
// Hook into deps logger so ALL subsystem logs (FFmpeg, control server, etc.)
// appear in the UI log panel — not just ViewModel-level logs.
deps.installLogListener { tag, message, isError ->
addLog(tag, message, isError)
}
}
private val logger = object : Logger {
override fun log(tag: String, message: String) {
// deps.logger already forwards to addLog via the listener above
deps.logger.log(tag, message)
}
override fun error(tag: String, message: String, throwable: Throwable?) {
deps.logger.error(tag, message, throwable)
ButtonToKeyMap class · kotlin · L6-L39 (34 LOC)feature/ps2/src/desktopMain/kotlin/com/my/psremoteplay/feature/ps2/platform/ButtonToKeyMap.kt
object ButtonToKeyMap {
/**
* Maps PS2 controller buttons to keyboard keys matching PCSX2 v2.x defaults.
* PCSX2 uses: Z=Cross, X=Circle, A=Square, S=Triangle, Enter=Start, Backspace=Select.
*/
val mapping: Map<Int, Int> = mapOf(
ControllerButtons.CROSS to KeyEvent.VK_Z,
ControllerButtons.CIRCLE to KeyEvent.VK_X,
ControllerButtons.SQUARE to KeyEvent.VK_A,
ControllerButtons.TRIANGLE to KeyEvent.VK_S,
ControllerButtons.UP to KeyEvent.VK_UP,
ControllerButtons.DOWN to KeyEvent.VK_DOWN,
ControllerButtons.LEFT to KeyEvent.VK_LEFT,
ControllerButtons.RIGHT to KeyEvent.VK_RIGHT,
ControllerButtons.START to KeyEvent.VK_ENTER,
ControllerButtons.SELECT to KeyEvent.VK_BACK_SPACE,
ControllerButtons.L1 to KeyEvent.VK_Q,
ControllerButtons.R1 to KeyEvent.VK_E,
ControllerButtons.L2 to KeyEvent.VK_1,
ControllerButtons.R2 FfmpegCapture class · kotlin · L13-L89 (77 LOC)feature/ps2/src/desktopMain/kotlin/com/my/psremoteplay/feature/ps2/platform/FfmpegCapture.kt
class FfmpegCapture(private val logger: Logger) {
private var captureThread: Thread? = null
@Volatile private var capturing = false
/**
* Start screen capture using Java Robot API.
* Captures the screen at ~30fps and encodes each frame as JPEG.
* @param screenIndex unused (captures primary screen)
*/
fun start(screenIndex: String = "1", onJpegFrame: (ByteArray) -> Unit) {
if (capturing) {
logger.log("CAPTURE", "Already capturing")
return
}
capturing = true
captureThread = Thread {
try {
val robot = Robot()
val screenSize = Toolkit.getDefaultToolkit().screenSize
val captureRect = Rectangle(screenSize)
val targetWidth = 640
val targetHeight = 448
val frameIntervalMs = 33L // ~30fps
// Set up JPEG writer with quality control
val jpegWriter = ImageIO.getImageJavaCvVideoStreamer class · kotlin · L17-L111 (95 LOC)feature/ps2/src/desktopMain/kotlin/com/my/psremoteplay/feature/ps2/platform/JavaCvVideoStreamer.kt
class JavaCvVideoStreamer(private val logger: Logger) {
@Volatile private var streaming = false
private var streamThread: Thread? = null
fun start(rtpPort: Int) {
if (streaming) return
streaming = true
streamThread = Thread {
var recorder: FFmpegFrameRecorder? = null
try {
val robot = Robot()
val screenSize = Toolkit.getDefaultToolkit().screenSize
val captureRect = Rectangle(screenSize)
val converter = Java2DFrameConverter()
val width = 640
val height = 448
val fps = 30.0
// RTP output URL — client connects to this
val rtpUrl = "rtp://0.0.0.0:$rtpPort"
recorder = FFmpegFrameRecorder(rtpUrl, width, height).apply {
format = "rtp"
videoCodec = avcodec.AV_CODEC_ID_H264
frameRate = fps
videoKeyInjector class · kotlin · L18-L180 (163 LOC)feature/ps2/src/desktopMain/kotlin/com/my/psremoteplay/feature/ps2/platform/KeyInjector.kt
class KeyInjector(private val logger: Logger) {
private var process: Process? = null
private var writer: OutputStreamWriter? = null
private val pressedKeys = mutableSetOf<Int>()
private var keyPressCount = 0L
init {
startHelper()
}
/** Set the target PID and activate the app so it receives CGEvents. */
fun setTargetPid(pid: Long) {
sendCommand("P $pid")
logger.log("INPUT", "keyinject targeting PID $pid")
// Ensure PCSX2 stays in front — re-activate after a short delay
// (PCSX2 may take a moment to create its window)
Thread {
Thread.sleep(3000)
sendCommand("F")
logger.log("INPUT", "Re-activated PCSX2 window")
}.apply { isDaemon = true; start() }
}
fun pressKey(keyCode: Int) {
val cgKey = awtToCGKeyCode(keyCode)
if (cgKey < 0) return
synchronized(pressedKeys) {
if (!pressedKeys.add(cgKey)) return
}
senMethodology: Repobility · https://repobility.com/research/state-of-ai-code-2026/
Pcsx2Launcher class · kotlin · L5-L48 (44 LOC)feature/ps2/src/desktopMain/kotlin/com/my/psremoteplay/feature/ps2/platform/Pcsx2Launcher.kt
class Pcsx2Launcher(private val logger: Logger) {
private var process: Process? = null
fun launch(pcsx2Path: String, gamePath: String): Boolean {
if (process?.isAlive == true) {
logger.log("PCSX2", "Already running")
return true
}
return try {
logger.log("PCSX2", "Launching: $pcsx2Path")
logger.log("PCSX2", "Game: $gamePath")
val pb = ProcessBuilder(pcsx2Path, "-batch", gamePath)
pb.redirectErrorStream(true)
process = pb.start()
// Read output in background thread to prevent blocking
Thread {
process?.inputStream?.bufferedReader()?.forEachLine {
logger.log("PCSX2", it)
}
}.apply { isDaemon = true; start() }
logger.log("PCSX2", "Process started (PID: ${process?.pid()})")
true
} catch (e: Exception) {
logger.error("PCSX2", "Failed to launch: $Ps2ControlServer class · kotlin · L17-L173 (157 LOC)feature/ps2/src/desktopMain/kotlin/com/my/psremoteplay/feature/ps2/platform/Ps2ControlServer.kt
class Ps2ControlServer(private val logger: Logger) {
private var serverSocket: ServerSocket? = null
private var acceptThread: Thread? = null
@Volatile private var running = false
private val clients = CopyOnWriteArrayList<ClientConnection>()
private val clientThreads = CopyOnWriteArrayList<Thread>()
private var inputHandler: ((ControllerState) -> Unit)? = null
private var statsHandler: ((StreamStats) -> Unit)? = null
private var controllerInputCount = 0L
private class ClientConnection(val socket: Socket, val output: OutputStream)
fun start(port: Int) {
if (running) return
running = true
try {
serverSocket = ServerSocket(port).apply { soTimeout = 2000 }
logger.log("CONTROL", "Control server listening on port $port")
acceptThread = Thread {
while (running) {
try {
val clientSocket = serverSocket?.accept() ?: break
Ps2StreamingServer class · kotlin · L11-L152 (142 LOC)feature/ps2/src/desktopMain/kotlin/com/my/psremoteplay/feature/ps2/platform/Ps2StreamingServer.kt
class Ps2StreamingServer(private val logger: Logger) {
private var serverSocket: ServerSocket? = null
private var acceptThread: Thread? = null
@Volatile private var running = false
private val clients = CopyOnWriteArrayList<ClientConnection>()
private var inputHandler: ((ControllerState) -> Unit)? = null
private class ClientConnection(val socket: Socket, val output: OutputStream)
fun start(port: Int = Ps2Protocol.DEFAULT_PORT) {
if (running) return
running = true
try {
serverSocket = ServerSocket(port)
logger.log("SERVER", "Listening on port $port")
acceptThread = Thread {
while (running) {
try {
val clientSocket = serverSocket?.accept() ?: break
logger.log("SERVER", "Client connected: ${clientSocket.remoteSocketAddress}")
val connection = ClientConnection(clientSocket, clientSocket.getOutJavaCvMpegTsClient class · kotlin · L21-L85 (65 LOC)feature/ps2/src/desktopMain/kotlin/com/my/psremoteplay/feature/ps2/strategy/client/JavaCvMpegTsClient.kt
class JavaCvMpegTsClient(private val logger: Logger) : VideoStreamClient {
override val name = "H.264/MPEG-TS"
private val _currentFrame = MutableStateFlow<ImageBitmap?>(null)
override val currentFrame: StateFlow<ImageBitmap?> = _currentFrame.asStateFlow()
@Volatile private var receiving = false
private var readerThread: Thread? = null
override fun start(serverIp: String, config: StreamConfig): Boolean {
return try {
receiving = true
readerThread = Thread {
var grabber: FFmpegFrameGrabber? = null
try {
val converter = Java2DFrameConverter()
val udpUrl = "udp://$serverIp:${config.videoPort}"
grabber = FFmpegFrameGrabber(udpUrl).apply {
format = "mpegts"
setOption("fflags", "nobuffer")
setOption("flags", "low_delay")
setOption("analyzedurationJavaCvRtpClient class · kotlin · L21-L86 (66 LOC)feature/ps2/src/desktopMain/kotlin/com/my/psremoteplay/feature/ps2/strategy/client/JavaCvRtpClient.kt
class JavaCvRtpClient(private val logger: Logger) : VideoStreamClient {
override val name = "H.264/RTP"
private val _currentFrame = MutableStateFlow<ImageBitmap?>(null)
override val currentFrame: StateFlow<ImageBitmap?> = _currentFrame.asStateFlow()
@Volatile private var receiving = false
private var readerThread: Thread? = null
override fun start(serverIp: String, config: StreamConfig): Boolean {
return try {
receiving = true
readerThread = Thread {
var grabber: FFmpegFrameGrabber? = null
try {
val converter = Java2DFrameConverter()
val rtpUrl = "rtp://$serverIp:${config.videoPort}"
grabber = FFmpegFrameGrabber(rtpUrl).apply {
format = "rtp"
setOption("fflags", "nobuffer")
setOption("flags", "low_delay")
setOption("analyzeduration", "100000TcpJpegClient class · kotlin · L19-L77 (59 LOC)feature/ps2/src/desktopMain/kotlin/com/my/psremoteplay/feature/ps2/strategy/client/TcpJpegClient.kt
class TcpJpegClient(private val logger: Logger) : VideoStreamClient {
override val name = "MJPEG/TCP"
private val _currentFrame = MutableStateFlow<ImageBitmap?>(null)
override val currentFrame: StateFlow<ImageBitmap?> = _currentFrame.asStateFlow()
@Volatile private var receiving = false
private var socket: Socket? = null
private var readerThread: Thread? = null
override fun start(serverIp: String, config: StreamConfig): Boolean {
return try {
val s = Socket(serverIp, config.videoPort)
socket = s
receiving = true
readerThread = Thread {
try {
val input = DataInputStream(s.getInputStream())
while (receiving && !s.isClosed) {
val length = input.readInt()
if (length <= 0) continue
val type = input.readByte()
val payloadSize = length - 1
UdpJpegClient class · kotlin · L19-L86 (68 LOC)feature/ps2/src/desktopMain/kotlin/com/my/psremoteplay/feature/ps2/strategy/client/UdpJpegClient.kt
class UdpJpegClient(private val logger: Logger) : VideoStreamClient {
override val name = "MJPEG/UDP"
private val _currentFrame = MutableStateFlow<ImageBitmap?>(null)
override val currentFrame: StateFlow<ImageBitmap?> = _currentFrame.asStateFlow()
@Volatile private var receiving = false
private var socket: DatagramSocket? = null
private var readerThread: Thread? = null
override fun start(serverIp: String, config: StreamConfig): Boolean {
return try {
val s = DatagramSocket(config.videoPort)
s.soTimeout = 5000
socket = s
receiving = true
readerThread = Thread {
val buf = ByteArray(65536)
var frameCount = 0L
var totalDecodeMs = 0L
val startTime = System.currentTimeMillis()
try {
while (receiving) {
val packet = DatagramPacket(buf, buf.size)
tryFfmpegH264UdpServer class · kotlin · L17-L114 (98 LOC)feature/ps2/src/desktopMain/kotlin/com/my/psremoteplay/feature/ps2/strategy/server/FfmpegH264UdpServer.kt
class FfmpegH264UdpServer(private val logger: Logger) : VideoStreamServer {
override val name = "H.264/NAL-UDP"
@Volatile private var streaming = false
private var process: Process? = null
private var logThread: Thread? = null
override fun start(config: StreamConfig) {
if (streaming) return
streaming = true
val os = System.getProperty("os.name").lowercase()
val captureArgs = buildCaptureArgs(os, config)
if (captureArgs == null) {
logger.error(name, "Unsupported OS: $os")
streaming = false
return
}
val encodeArgs = buildEncodeArgs(config)
val udpUrl = "udp://${config.targetIp}:${config.videoPort}?pkt_size=32768"
val cmd = listOf("ffmpeg", "-y") + captureArgs + encodeArgs + listOf(
"-f", "h264",
udpUrl
)
try {
logger.log(name, "Starting FFmpeg (libx264)")
logger.log(name, "CMD: ${cmd.joinToStrRepobility · severity-and-effort ranking · https://repobility.com
FfmpegMpegTsServer class · kotlin · L12-L99 (88 LOC)feature/ps2/src/desktopMain/kotlin/com/my/psremoteplay/feature/ps2/strategy/server/FfmpegMpegTsServer.kt
class FfmpegMpegTsServer(private val logger: Logger) : VideoStreamServer {
override val name = "H.264/MPEG-TS"
@Volatile private var streaming = false
private var process: Process? = null
private var logThread: Thread? = null
override fun start(config: StreamConfig) {
if (streaming) return
streaming = true
val udpUrl = "udp://0.0.0.0:${config.videoPort}?pkt_size=1316"
// Detect platform for capture input
val os = System.getProperty("os.name").lowercase()
val captureArgs = when {
os.contains("mac") -> listOf(
"-f", "avfoundation",
"-framerate", config.fps.toString(),
"-capture_cursor", "0",
"-i", "1:none"
)
os.contains("linux") -> listOf(
"-f", "x11grab",
"-framerate", config.fps.toString(),
"-video_size", "${Toolkit.screenSize.width}x${Toolkit.screenSize.height}",
Toolkit class · kotlin · L95-L98 (4 LOC)feature/ps2/src/desktopMain/kotlin/com/my/psremoteplay/feature/ps2/strategy/server/FfmpegMpegTsServer.kt
private object Toolkit {
val screenSize: java.awt.Dimension
get() = java.awt.Toolkit.getDefaultToolkit().screenSize
}JavaCvRtpServer class · kotlin · L20-L89 (70 LOC)feature/ps2/src/desktopMain/kotlin/com/my/psremoteplay/feature/ps2/strategy/server/JavaCvRtpServer.kt
class JavaCvRtpServer(private val logger: Logger) : VideoStreamServer {
override val name = "H.264/RTP"
@Volatile private var streaming = false
private var streamThread: Thread? = null
override fun start(config: StreamConfig) {
if (streaming) return
streaming = true
streamThread = Thread {
var recorder: FFmpegFrameRecorder? = null
try {
val robot = Robot()
val screenSize = Toolkit.getDefaultToolkit().screenSize
val captureRect = Rectangle(screenSize)
val converter = Java2DFrameConverter()
val rtpUrl = "rtp://0.0.0.0:${config.videoPort}"
recorder = FFmpegFrameRecorder(rtpUrl, config.width, config.height).apply {
format = "rtp"
videoCodec = avcodec.AV_CODEC_ID_H264
frameRate = config.fps.toDouble()
videoBitrate = config.bitrate
RobotJpegTcpServer class · kotlin · L24-L117 (94 LOC)feature/ps2/src/desktopMain/kotlin/com/my/psremoteplay/feature/ps2/strategy/server/RobotJpegTcpServer.kt
class RobotJpegTcpServer(private val logger: Logger) : VideoStreamServer {
override val name = "MJPEG/TCP"
@Volatile private var streaming = false
private var captureThread: Thread? = null
private var serverSocket: ServerSocket? = null
private var acceptThread: Thread? = null
private val clients = CopyOnWriteArrayList<OutputStream>()
override fun start(config: StreamConfig) {
if (streaming) return
streaming = true
// Start TCP server
serverSocket = ServerSocket(config.videoPort)
acceptThread = Thread {
while (streaming) {
try {
val socket = serverSocket?.accept() ?: break
logger.log(name, "Client connected: ${socket.remoteSocketAddress}")
clients.add(socket.getOutputStream())
} catch (e: Exception) {
if (streaming) logger.error(name, "Accept error: ${e.message}")
}
}RobotJpegUdpServer class · kotlin · L22-L163 (142 LOC)feature/ps2/src/desktopMain/kotlin/com/my/psremoteplay/feature/ps2/strategy/server/RobotJpegUdpServer.kt
class RobotJpegUdpServer(private val logger: Logger) : VideoStreamServer {
override val name = "MJPEG/UDP"
@Volatile private var streaming = false
private var captureThread: Thread? = null
private var socket: DatagramSocket? = null
private lateinit var targetAddress: InetAddress
override fun start(config: StreamConfig) {
if (streaming) return
streaming = true
targetAddress = InetAddress.getByName(config.targetIp)
socket = DatagramSocket().apply { broadcast = true }
logger.log(name, "Sending video to ${config.targetIp}:${config.videoPort}")
captureThread = Thread {
try {
val robot = Robot()
val jpegWriter = ImageIO.getImageWritersByFormatName("jpeg").next()
val jpegParams = jpegWriter.defaultWriteParam.apply {
compressionMode = ImageWriteParam.MODE_EXPLICIT
compressionQuality = 0.6f
}
ScreenCaptureKitServer class · kotlin · L18-L131 (114 LOC)feature/ps2/src/desktopMain/kotlin/com/my/psremoteplay/feature/ps2/strategy/server/ScreenCaptureKitServer.kt
class ScreenCaptureKitServer(private val logger: Logger) : VideoStreamServer {
override val name = "H.264/NAL-UDP"
@Volatile private var streaming = false
private var process: Process? = null
private var logThread: Thread? = null
override fun start(config: StreamConfig) {
if (streaming) return
streaming = true
val binary = ensureBinary()
if (binary == null) {
logger.error(name, "Failed to prepare screencap binary (macOS only)")
streaming = false
return
}
val cmd = listOf(
binary,
"--target", config.targetIp,
"--port", config.videoPort.toString(),
"--width", config.width.toString(),
"--height", config.height.toString(),
"--fps", config.fps.toString(),
"--bitrate", config.bitrate.toString(),
"--keyframe", config.keyframeInterval.toString(),
"--app", "PCSX2"
)
IosPs2ClientDependencies class · kotlin · L23-L62 (40 LOC)feature/ps2/src/iosMain/kotlin/com/my/psremoteplay/feature/ps2/di/IosPs2ClientDependencies.kt
class IosPs2ClientDependencies : Ps2ClientDependencies {
private val _logger: Logger = object : Logger {
override fun log(tag: String, message: String) { println("[$tag] $message") }
override fun error(tag: String, message: String, throwable: Throwable?) {
println("[$tag] ERROR: $message${throwable?.let { " - ${it.message}" } ?: ""}")
}
}
override val streaming: StreamingDependencies = object : StreamingDependencies {
override val crypto: Crypto = object : Crypto {
override fun aesEncrypt(data: ByteArray, key: ByteArray, iv: ByteArray): ByteArray = error("Not implemented")
override fun aesDecrypt(data: ByteArray, key: ByteArray, iv: ByteArray): ByteArray = error("Not implemented")
override fun base64Encode(data: ByteArray): String = error("Not implemented")
override fun base64Decode(data: String): ByteArray = error("Not implemented")
override fun randomBytes(count: Int):AndroidPs3Dependencies class · kotlin · L26-L53 (28 LOC)feature/ps3/src/androidMain/kotlin/com/my/psremoteplay/feature/ps3/di/AndroidPs3Dependencies.kt
class AndroidPs3Dependencies : Ps3Dependencies {
private val logger: Logger = object : Logger {
override fun log(tag: String, message: String) {
android.util.Log.d(tag, message)
}
override fun error(tag: String, message: String, throwable: Throwable?) {
android.util.Log.e(tag, message, throwable)
}
}
private val crypto: Crypto = JvmCrypto
override val streaming: StreamingDependencies = object : StreamingDependencies {
override val crypto: Crypto = [email protected]
override val videoDecoder: VideoDecoder = StubVideoDecoder()
override val audioDecoder: AudioDecoder = StubAudioDecoder()
override val videoRenderer: VideoRenderer = LoggingVideoRenderer([email protected])
override val audioRenderer: AudioRenderer = StubAudioRenderer([email protected])
override val upscaleFilter: UpscaleFilter = PassthroughUpscaler()
Want this analysis on your repo? https://repobility.com/scan/
AndroidControllerInput class · kotlin · L16-L51 (36 LOC)feature/ps3/src/androidMain/kotlin/com/my/psremoteplay/feature/ps3/platform/AndroidControllerInput.kt
class AndroidControllerInput(private val logger: Logger) : ControllerInputSender {
private var socket: Socket? = null
private var isConnected = false
override suspend fun connect(params: Map<String, String>) = withContext(Dispatchers.IO) {
try {
val ip = params["ip"] ?: error("Missing 'ip' in params")
socket = Socket(ip, PremoConstants.PORT)
isConnected = true
logger.log("PAD", "[ANDROID] Controller connected")
} catch (e: Exception) {
logger.error("PAD", "[ANDROID] Connection failed", e)
isConnected = false
}
}
override suspend fun sendState(state: ControllerState) = withContext(Dispatchers.IO) {
if (!isConnected) return@withContext
try {
PadProtocol.buildPadPacket(state)
// TODO: Queue to batch, send when full
} catch (e: Exception) {
logger.error("PAD", "[ANDROID] Send error", e)
}
}
overridAndroidPremoSession class · kotlin · L11-L229 (219 LOC)feature/ps3/src/androidMain/kotlin/com/my/psremoteplay/feature/ps3/platform/AndroidPremoSession.kt
class AndroidPremoSession(private val crypto: Crypto, private val logger: Logger) : PremoSessionHandler {
private var socket: Socket? = null
override suspend fun createSession(ps3Ip: String, config: SessionConfig): Result<SessionResponse> =
withContext(Dispatchers.IO) {
try {
val sock = Socket(ps3Ip, PremoConstants.PORT)
val request = buildSessionRequest(config, crypto)
logger.log("SESSION", "Sending session request to $ps3Ip:${PremoConstants.PORT}")
sock.getOutputStream().write(request.toByteArray(Charsets.US_ASCII))
sock.getOutputStream().flush()
val responseBytes = ByteArray(4096)
val n = sock.getInputStream().read(responseBytes)
val responseText = if (n > 0) String(responseBytes, 0, n, Charsets.US_ASCII) else ""
logger.log("SESSION", "Response:\n$responseText")
sock.close()
valAndroidPs3Discoverer class · kotlin · L11-L115 (105 LOC)feature/ps3/src/androidMain/kotlin/com/my/psremoteplay/feature/ps3/platform/AndroidPs3Discoverer.kt
class AndroidPs3Discoverer(private val logger: Logger) : Ps3Discoverer {
override suspend fun discover(timeoutMs: Int): Ps3Info? = withContext(Dispatchers.IO) {
discoverViaBroadcast(timeoutMs)
?: discoverViaSubnet(timeoutMs)
}
override suspend fun discoverDirect(ip: String, timeoutMs: Int): Ps3Info? = withContext(Dispatchers.IO) {
val udpResult = try {
logger.log("DISCOVERY", "Trying UDP SRCH to $ip:${PremoConstants.PORT}...")
sendSrchTo(InetAddress.getByName(ip), timeoutMs)
} catch (e: Exception) {
logger.log("DISCOVERY", "UDP SRCH failed: ${e.message}")
null
}
if (udpResult != null) return@withContext udpResult
return@withContext try {
logger.log("DISCOVERY", "Trying TCP connection to $ip:${PremoConstants.PORT}...")
val socket = Socket()
socket.connect(InetSocketAddress(ip, PremoConstants.PORT), timeoutMs)
socket.clStubRegistration class · kotlin · L6-L17 (12 LOC)feature/ps3/src/androidMain/kotlin/com/my/psremoteplay/feature/ps3/platform/StubRegistration.kt
class StubRegistration : PremoRegistration {
override suspend fun register(
ps3Ip: String,
pin: String,
deviceId: ByteArray,
deviceMac: ByteArray,
deviceName: String,
platformType: Int
): Result<RegistrationResult> {
return Result.failure(UnsupportedOperationException("Registration not available on Android"))
}
}Ps3ViewModel class · kotlin · L18-L280 (263 LOC)feature/ps3/src/commonMain/kotlin/com/my/psremoteplay/feature/ps3/presentation/Ps3ViewModel.kt
class Ps3ViewModel(private val deps: Ps3Dependencies) : ViewModel() {
private val _state = MutableStateFlow(Ps3State())
val state: StateFlow<Ps3State> = _state.asStateFlow()
private val _effects = Channel<Ps3Effect>(Channel.BUFFERED)
val effects: Flow<Ps3Effect> = _effects.receiveAsFlow()
private val logger = object : Logger {
override fun log(tag: String, message: String) {
addLog(tag, message, isError = false)
deps.streaming.logger.log(tag, message)
}
override fun error(tag: String, message: String, throwable: Throwable?) {
val errMsg = "$message${throwable?.let { "\n ${it::class.simpleName}: ${it.message}" } ?: ""}"
addLog(tag, errMsg, isError = true)
deps.streaming.logger.error(tag, message, throwable)
}
}
fun onIntent(intent: Ps3Intent) {
when (intent) {
is Ps3Intent.UpdateIp -> updateState { copy(ps3Ip = cleanIp(intent.ip)) }
Companion class · kotlin · L271-L279 (9 LOC)feature/ps3/src/commonMain/kotlin/com/my/psremoteplay/feature/ps3/presentation/Ps3ViewModel.kt
companion object {
fun cleanIp(raw: String): String {
var ip = raw.trim()
ip = ip.removePrefix("http://").removePrefix("https://")
ip = ip.trimEnd('/')
ip = ip.split(":").first()
return ip
}
}PadProtocol class · kotlin · L7-L45 (39 LOC)feature/ps3/src/commonMain/kotlin/com/my/psremoteplay/feature/ps3/protocol/PadProtocol.kt
object PadProtocol {
fun buildPadPacket(state: ControllerState): ByteArray {
val packet = ByteArray(128)
packet[0x00] = 0x74
packet[0x04] = (0x80 + (state.leftStickX * 127)).roundToInt().toByte()
packet[0x05] = (0x80 + (state.leftStickY * 127)).roundToInt().toByte()
packet[0x08] = (0x80 + (state.rightStickX * 127)).roundToInt().toByte()
packet[0x09] = (0x80 + (state.rightStickY * 127)).roundToInt().toByte()
packet[0x05] = buildButtonByte(state.buttons, listOf(
ControllerButtons.SQUARE, ControllerButtons.CROSS,
ControllerButtons.CIRCLE, ControllerButtons.TRIANGLE,
ControllerButtons.R1, ControllerButtons.L1,
ControllerButtons.R2, ControllerButtons.L2
)).toByte()
packet[0x07] = buildButtonByte(state.buttons, listOf(
ControllerButtons.LEFT, ControllerButtons.DOWN,
ControllerButtons.RIGHT, ControllerButtons.UP,
ControllerButtons.STPremoConstants class · kotlin · L3-L83 (81 LOC)feature/ps3/src/commonMain/kotlin/com/my/psremoteplay/feature/ps3/protocol/PremoConstants.kt
object PremoConstants {
const val PORT = 9293
const val PREMO_VERSION_MAJOR = 0
const val PREMO_VERSION_MINOR = 3
const val USER_AGENT = "premo/1.0.0 libhttp/1.0.0"
const val FRAME_WIDTH = 480
const val FRAME_HEIGHT = 272
val SRCH_PACKET = byteArrayOf(0x53, 0x52, 0x43, 0x48)
val RESP_MAGIC = byteArrayOf(0x52, 0x45, 0x53, 0x50)
val SKEY0 = byteArrayOf(
0xD1.toByte(), 0xB2.toByte(), 0x12, 0xEB.toByte(),
0x73, 0x86.toByte(), 0x6C, 0x7B,
0x12, 0xA7.toByte(), 0x5E, 0x0C,
0x04, 0xC6.toByte(), 0xB8.toByte(), 0x91.toByte()
)
val SKEY1 = byteArrayOf(
0x1F, 0xD5.toByte(), 0xB9.toByte(), 0xFA.toByte(),
0x71, 0xB8.toByte(), 0x96.toByte(), 0x81.toByte(),
0xB2.toByte(), 0x87.toByte(), 0x92.toByte(), 0xE2.toByte(),
0x6F, 0x38, 0xC3.toByte(), 0x6F
)
val SKEY2 = byteArrayOf(
0x65, 0x2D, 0x8C.toByte(), 0x90.toByte(),
0xDE.toByte(), 0x87.toByte(), 0x17, 0xCF.toByte(),
Same scanner, your repo: https://repobility.com — Repobility
DesktopPs3Dependencies class · kotlin · L22-L50 (29 LOC)feature/ps3/src/desktopMain/kotlin/com/my/psremoteplay/feature/ps3/di/DesktopPs3Dependencies.kt
class DesktopPs3Dependencies : Ps3Dependencies {
private val logger: Logger = object : Logger {
override fun log(tag: String, message: String) {
println("[$tag] $message")
}
override fun error(tag: String, message: String, throwable: Throwable?) {
System.err.println("[ERROR:$tag] $message")
throwable?.printStackTrace(System.err)
}
}
private val crypto: Crypto = JvmCrypto
override val streaming: StreamingDependencies = object : StreamingDependencies {
override val crypto: Crypto = [email protected]
override val videoDecoder: VideoDecoder = StubVideoDecoder()
override val audioDecoder: AudioDecoder = StubAudioDecoder()
override val videoRenderer: VideoRenderer = JvmVideoRenderer([email protected])
override val audioRenderer: AudioRenderer = StubAudioRenderer([email protected])
override val upscaleFilter: JvmControllerInput class · kotlin · L18-L54 (37 LOC)feature/ps3/src/desktopMain/kotlin/com/my/psremoteplay/feature/ps3/platform/JvmControllerInput.kt
class JvmControllerInput(private val logger: Logger) : ControllerInputSender {
private var socket: Socket? = null
private var isConnected = false
override suspend fun connect(params: Map<String, String>) = withContext(Dispatchers.IO) {
try {
val ps3Ip = params["ip"] ?: error("Missing 'ip' parameter")
socket = Socket(ps3Ip, PremoConstants.PORT)
isConnected = true
logger.log("PAD", "[DESKTOP] Controller connected to $ps3Ip")
} catch (e: Exception) {
logger.error("PAD", "[DESKTOP] Controller connection failed", e)
isConnected = false
}
}
override suspend fun sendState(state: ControllerState) = withContext(Dispatchers.IO) {
if (!isConnected) return@withContext
try {
val packet = PadProtocol.buildPadPacket(state)
logger.log("PAD", "[DESKTOP] Pad state: buttons=${"%05X".format(state.buttons)}, sticks=(${state.leftStickX.toInt()},${stateJvmPremoRegistration class · kotlin · L22-L92 (71 LOC)feature/ps3/src/desktopMain/kotlin/com/my/psremoteplay/feature/ps3/platform/JvmPremoRegistration.kt
class JvmPremoRegistration(private val crypto: Crypto, private val logger: Logger) : PremoRegistration {
override suspend fun register(
ps3Ip: String,
pin: String,
deviceId: ByteArray,
deviceMac: ByteArray,
deviceName: String,
platformType: Int
): Result<RegistrationResult> = withContext(Dispatchers.IO) {
try {
logger.log("REGIST", "=== REGISTRATION STRATEGY ORCHESTRATOR ===")
logger.log("REGIST", "PS3: $ps3Ip, PIN: $pin")
logger.log("REGIST", "Testing ${RegistrationStrategies.allStrategies.count { it.isEnabled }} enabled strategies...")
logger.log("REGIST", "")
val attempts = mutableListOf<RegistrationAttempt>()
for (strategy in RegistrationStrategies.allStrategies) {
if (!strategy.isEnabled) {
logger.log("REGIST", "⊘ SKIPPED: ${strategy.name} (disabled)")
logger.log("REGIST", " Reason: ${stJvmPremoSession class · kotlin · L12-L281 (270 LOC)feature/ps3/src/desktopMain/kotlin/com/my/psremoteplay/feature/ps3/platform/JvmPremoSession.kt
class JvmPremoSession(private val crypto: Crypto, private val logger: Logger) : PremoSessionHandler {
private var socket: Socket? = null
override suspend fun createSession(ps3Ip: String, config: SessionConfig): Result<SessionResponse> =
withContext(Dispatchers.IO) {
try {
val sock = Socket(ps3Ip, PremoConstants.PORT)
val out = sock.getOutputStream()
val inp = sock.getInputStream()
val request = buildSessionRequest(config, crypto)
logger.log("SESSION", "Sending session request to $ps3Ip:${PremoConstants.PORT}")
logger.log("SESSION", request)
out.write(request.toByteArray(Charsets.US_ASCII))
out.flush()
val responseBytes = readHttpResponse(inp)
val responseText = String(responseBytes, Charsets.US_ASCII)
logger.log("SESSION", "Response:\n$responseText")
sock.close()
JvmPs3Discoverer class · kotlin · L11-L161 (151 LOC)feature/ps3/src/desktopMain/kotlin/com/my/psremoteplay/feature/ps3/platform/JvmPs3Discoverer.kt
class JvmPs3Discoverer(private val logger: Logger) : Ps3Discoverer {
override suspend fun discover(timeoutMs: Int): Ps3Info? = withContext(Dispatchers.IO) {
// Try broadcast first, then directed if we have a subnet
discoverViaBroadcast(timeoutMs)
?: discoverViaSubnet(timeoutMs)
}
private fun discoverViaBroadcast(timeoutMs: Int): Ps3Info? {
return try {
logger.log("DISCOVERY", "Trying 255.255.255.255 broadcast on port ${PremoConstants.PORT}...")
val socket = DatagramSocket()
socket.broadcast = true
socket.soTimeout = timeoutMs
val srch = PremoConstants.SRCH_PACKET
val broadcastAddr = InetAddress.getByName("255.255.255.255")
val sendPacket = DatagramPacket(srch, srch.size, broadcastAddr, PremoConstants.PORT)
logger.log("DISCOVERY", "Sending SRCH packet (${srch.size} bytes) to 255.255.255.255:${PremoConstants.PORT}")
socket.send(senKeyboardController class · kotlin · L24-L99 (76 LOC)feature/ps3/src/desktopMain/kotlin/com/my/psremoteplay/feature/ps3/platform/KeyboardController.kt
object KeyboardController {
private var currentState = ControllerState()
private val pressedKeys = mutableSetOf<Key>()
fun handleKeyDown(event: KeyEvent): ControllerState? {
// Note: KeyEvent in Compose uses nativeKeyCode, need to map to Key objects
// For now, this is a placeholder that returns null
return null
}
fun handleKeyUp(event: KeyEvent): ControllerState? {
// Note: KeyEvent in Compose uses nativeKeyCode, need to map to Key objects
// For now, this is a placeholder that returns null
return null
}
private fun updateState(): ControllerState? {
var newState = ControllerState()
// D-Pad (arrow keys)
if (pressedKeys.contains(Key.DirectionUp)) newState = newState.copy(buttons = newState.buttons or ControllerButtons.UP)
if (pressedKeys.contains(Key.DirectionDown)) newState = newState.copy(buttons = newState.buttons or ControllerButtons.DOWN)
if (pressedKeys.containsPhoneTypePS4FormulaStrategy class · kotlin · L18-L265 (248 LOC)feature/ps3/src/desktopMain/kotlin/com/my/psremoteplay/feature/ps3/platform/RegistrationStrategyImpl.kt
class PhoneTypePS4FormulaStrategy : RegistrationStrategy {
override val name = "Phone Type PS4 Formula"
override val description = "Phone Type (1) with PIN as 4-byte BE + 4 zeros"
override val isEnabled = false // Already tested and failed
override suspend fun attemptRegistration(
ps3Ip: String,
pin: String,
deviceId: ByteArray,
deviceMac: ByteArray,
deviceName: String,
crypto: Crypto,
logger: Logger
): RegistrationAttempt = withContext(Dispatchers.IO) {
simpleRegisterAttempt(ps3Ip, pin, deviceId, deviceMac, deviceName, 1, false, crypto, logger, name)
}
private fun deriveKeyPhone(keyMaterial: ByteArray): ByteArray {
val key = ByteArray(16)
for (i in 0..15) {
key[i] = (((keyMaterial[i].toInt() and 0xFF) - i - 0x28) xor (PremoConstants.REG_XOR_PHONE[i].toInt() and 0xFF)).toByte()
}
return key
}
private fun deriveIvPhone(contextBytes: ByteArraPCTypePS4FormulaStrategy class · kotlin · L278-L468 (191 LOC)feature/ps3/src/desktopMain/kotlin/com/my/psremoteplay/feature/ps3/platform/RegistrationStrategyImpl.kt
class PCTypePS4FormulaStrategy : RegistrationStrategy {
override val name = "PC Type PS4 Formula"
override val description = "PC Type (2) with PIN-derived key material (4-byte BE + 12 zeros) and 480-byte body prefix"
override val isEnabled = true // HIGH PRIORITY - new approach
override suspend fun attemptRegistration(
ps3Ip: String,
pin: String,
deviceId: ByteArray,
deviceMac: ByteArray,
deviceName: String,
crypto: Crypto,
logger: Logger
): RegistrationAttempt = withContext(Dispatchers.IO) {
try {
logger.log("REGIST", "▶ $name")
val bodyText = buildString {
append("Client-Type: VITA\r\n")
append("Client-Id: ${deviceId.joinToString("") { "%02x".format(it) }}\r\n")
append("Client-Mac: ${deviceMac.joinToString("") { "%02x".format(it) }}\r\n")
append("Client-Nickname: $deviceName\r\n")
}
val Methodology: Repobility · https://repobility.com/research/state-of-ai-code-2026/
PSPTypePS4FormulaStrategy class · kotlin · L479-L655 (177 LOC)feature/ps3/src/desktopMain/kotlin/com/my/psremoteplay/feature/ps3/platform/RegistrationStrategyImpl.kt
class PSPTypePS4FormulaStrategy : RegistrationStrategy {
override val name = "PSP Type PS4 Formula"
override val description = "PSP Type (0) with PIN as 4-byte BE + 4 zeros"
override val isEnabled = true // NEW - Never tested yet
override suspend fun attemptRegistration(
ps3Ip: String,
pin: String,
deviceId: ByteArray,
deviceMac: ByteArray,
deviceName: String,
crypto: Crypto,
logger: Logger
): RegistrationAttempt = withContext(Dispatchers.IO) {
try {
logger.log("REGIST", "▶ $name")
val bodyText = buildString {
append("Client-Type: Phone\r\n") // PSP type uses "Phone" client type
append("Client-Id: ${deviceId.joinToString("") { "%02x".format(it) }}\r\n")
append("Client-Mac: ${deviceMac.joinToString("") { "%02x".format(it) }}\r\n")
append("Client-Nickname: $deviceName\r\n")
}
val keyMateriaPhoneTypeBELonglongStrategy class · kotlin · L662-L679 (18 LOC)feature/ps3/src/desktopMain/kotlin/com/my/psremoteplay/feature/ps3/platform/RegistrationStrategyImpl.kt
class PhoneTypeBELonglongStrategy : RegistrationStrategy {
override val name = "Phone Type BE Longlong"
override val description = "Phone Type (1) with PIN as 8-byte BE longlong"
override val isEnabled = false
override suspend fun attemptRegistration(
ps3Ip: String,
pin: String,
deviceId: ByteArray,
deviceMac: ByteArray,
deviceName: String,
crypto: Crypto,
logger: Logger
): RegistrationAttempt = withContext(Dispatchers.IO) {
logger.log("REGIST", "▶ $name (disabled)")
RegistrationAttempt(name, false, error = "Disabled - already tested and failed")
}
}PhoneTypeLELonglongStrategy class · kotlin · L686-L703 (18 LOC)feature/ps3/src/desktopMain/kotlin/com/my/psremoteplay/feature/ps3/platform/RegistrationStrategyImpl.kt
class PhoneTypeLELonglongStrategy : RegistrationStrategy {
override val name = "Phone Type LE Longlong"
override val description = "Phone Type (1) with PIN as 8-byte LE longlong"
override val isEnabled = false
override suspend fun attemptRegistration(
ps3Ip: String,
pin: String,
deviceId: ByteArray,
deviceMac: ByteArray,
deviceName: String,
crypto: Crypto,
logger: Logger
): RegistrationAttempt = withContext(Dispatchers.IO) {
logger.log("REGIST", "▶ $name (disabled)")
RegistrationAttempt(name, false, error = "Disabled - already tested and failed")
}
}