← back to dsdmsa__PsOldRemotePlay

Function bodies 388 total

All specs Real LLM only Function bodies
MainActivity class · kotlin · L28-L171 (144 LOC)
app/ps2client/src/androidMain/kotlin/com/my/psremoteplay/app/ps2client/MainActivity.kt
class MainActivity : ComponentActivity() {

    private var viewModel: Ps2ClientViewModel? = null
    private var controllerState = ControllerState()

    override fun onCreate(savedInstanceState: Bundle?) {
        enableEdgeToEdge()
        super.onCreate(savedInstanceState)

        requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
        window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)

        WindowCompat.setDecorFitsSystemWindows(window, false)
        WindowInsetsControllerCompat(window, window.decorView).apply {
            hide(WindowInsetsCompat.Type.systemBars())
            systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
        }

        setContent {
            val deps = remember { AndroidPs2ClientDependencies(StreamingPreset.H264_HW) }
            val vm = viewModel { Ps2ClientViewModel(deps) }
            viewModel = vm

            LaunchedEffect(Unit) {
                vm.effects.collectL
MainActivity class · kotlin · L15-L43 (29 LOC)
app/ps3/src/androidMain/kotlin/com/my/psremoteplay/app/ps3/MainActivity.kt
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        enableEdgeToEdge()
        super.onCreate(savedInstanceState)

        setContent {
            val deps = remember { AndroidPs3Dependencies() }
            val viewModel = viewModel { Ps3ViewModel(deps) }

            LaunchedEffect(Unit) {
                viewModel.effects.collectLatest { effect ->
                    when (effect) {
                        is Ps3Effect.CopyToClipboard -> {
                            val clipboard = getSystemService(CLIPBOARD_SERVICE) as android.content.ClipboardManager
                            clipboard.setPrimaryClip(android.content.ClipData.newPlainText("logs", effect.text))
                        }
                        is Ps3Effect.ShowMessage -> {
                            android.widget.Toast.makeText(this@MainActivity, effect.message, android.widget.Toast.LENGTH_SHORT).show()
                        }
                    }
    
AndroidControllerInput class · kotlin · L16-L50 (35 LOC)
composeApp/src/androidMain/kotlin/com/my/psoldremoteplay/AndroidControllerInput.kt
class AndroidControllerInput(private val logger: PremoLogger) : ControllerInputSender {
    private var socket: Socket? = null
    private var isConnected = false

    override suspend fun connect(ps3Ip: String, sessionId: String, authToken: String) = withContext(Dispatchers.IO) {
        try {
            socket = Socket(ps3Ip, 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)
        }
    }

    override suspend fun disconnect() = withCont
AndroidPremoCrypto class · kotlin · L10-L26 (17 LOC)
composeApp/src/androidMain/kotlin/com/my/psoldremoteplay/AndroidPremoCrypto.kt
object AndroidPremoCrypto : PremoCrypto {
    override fun aesEncrypt(data: ByteArray, key: ByteArray, iv: ByteArray): ByteArray {
        val cipher = Cipher.getInstance("AES/CBC/NoPadding")
        cipher.init(Cipher.ENCRYPT_MODE, SecretKeySpec(key, "AES"), IvParameterSpec(iv))
        return cipher.doFinal(data)
    }

    override fun aesDecrypt(data: ByteArray, key: ByteArray, iv: ByteArray): ByteArray {
        val cipher = Cipher.getInstance("AES/CBC/NoPadding")
        cipher.init(Cipher.DECRYPT_MODE, SecretKeySpec(key, "AES"), IvParameterSpec(iv))
        return cipher.doFinal(data)
    }

    override fun base64Encode(data: ByteArray): String = Base64.getEncoder().encodeToString(data)
    override fun base64Decode(data: String): ByteArray = Base64.getDecoder().decode(data)
    override fun randomBytes(count: Int): ByteArray = ByteArray(count).also { SecureRandom().nextBytes(it) }
}
AndroidPremoSession class · kotlin · L9-L227 (219 LOC)
composeApp/src/androidMain/kotlin/com/my/psoldremoteplay/AndroidPremoSession.kt
class AndroidPremoSession(private val crypto: PremoCrypto, private val logger: PremoLogger) : 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()

         
AndroidPs3Discoverer class · kotlin · L11-L115 (105 LOC)
composeApp/src/androidMain/kotlin/com/my/psoldremoteplay/AndroidPs3Discoverer.kt
class AndroidPs3Discoverer(private val logger: PremoLogger) : 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)
            sock
AndroidVideoRenderer class · kotlin · L17-L49 (33 LOC)
composeApp/src/androidMain/kotlin/com/my/psoldremoteplay/AndroidVideoRenderer.kt
class AndroidVideoRenderer(private val logger: PremoLogger) : VideoRenderer {
    private val _currentFrame = MutableStateFlow<ImageBitmap?>(null)
    override val currentFrame: StateFlow<ImageBitmap?> = _currentFrame.asStateFlow()

    private var packetCount = 0

    override suspend fun start() = withContext(Dispatchers.IO) {
        logger.log("VIDEO", "[ANDROID] Video renderer initialized")
    }

    override suspend fun onStreamPacket(header: ByteArray, payload: ByteArray, isEncrypted: Boolean) =
        withContext(Dispatchers.IO) {
            val magic = header[1].toInt() and 0xFF
            packetCount++

            when (magic) {
                0xFF, 0xFE -> {
                    if (packetCount % 30 == 0) {
                        logger.log("VIDEO", "[ANDROID] H.264 frame ${packetCount}: ${payload.size} bytes")
                    }
                    // TODO: Queue to MediaCodec decoder
                }
                0xFD -> logger.log("VIDEO", "[ANDROID] Flush si
If a scraper extracted this row, it came from Repobility (https://repobility.com)
AndroidDependencies class · kotlin · L10-L30 (21 LOC)
composeApp/src/androidMain/kotlin/com/my/psoldremoteplay/di/AndroidDependencies.kt
class AndroidDependencies : PlatformDependencies {
    override val logger: PremoLogger = object : PremoLogger {
        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)
        }
    }

    override val crypto: PremoCrypto = AndroidPremoCrypto
    override val discoverer: Ps3Discoverer = AndroidPs3Discoverer(logger)
    override val sessionHandler: PremoSessionHandler = AndroidPremoSession(crypto, logger)
    override val registration: PremoRegistration = StubRegistration()
    override val videoDecoder: VideoDecoder = StubVideoDecoder()
    override val audioDecoder: AudioDecoder = StubAudioDecoder()
    override val videoRenderer: VideoRenderer = AndroidVideoRenderer(logger)
    override val audioRenderer: AudioRenderer = StubAudioRenderer(logger)
    override val upscaleFilter: UpscaleFilter 
MainActivity class · kotlin · L15-L44 (30 LOC)
composeApp/src/androidMain/kotlin/com/my/psoldremoteplay/MainActivity.kt
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        enableEdgeToEdge()
        super.onCreate(savedInstanceState)

        setContent {
            // ViewModel survives configuration changes (rotation) with this factory pattern
            val deps = remember { AndroidDependencies() }
            val viewModel = viewModel { RemotePlayViewModel(deps) }

            LaunchedEffect(Unit) {
                viewModel.effects.collectLatest { effect ->
                    when (effect) {
                        is RemotePlayEffect.CopyToClipboard -> {
                            val clipboard = getSystemService(CLIPBOARD_SERVICE) as android.content.ClipboardManager
                            clipboard.setPrimaryClip(android.content.ClipData.newPlainText("logs", effect.text))
                        }
                        is RemotePlayEffect.ShowMessage -> {
                            android.widget.Toast.makeText(this@MainActivity,
AndroidPlatform class · kotlin · L5-L7 (3 LOC)
composeApp/src/androidMain/kotlin/com/my/psoldremoteplay/Platform.android.kt
class AndroidPlatform : Platform {
    override val name: String = "Android ${Build.VERSION.SDK_INT}"
}
RemotePlayViewModel class · kotlin · L12-L389 (378 LOC)
composeApp/src/commonMain/kotlin/com/my/psoldremoteplay/presentation/RemotePlayViewModel.kt
class RemotePlayViewModel(private val deps: PlatformDependencies) : ViewModel() {

    private val _state = MutableStateFlow(RemotePlayState())
    val state: StateFlow<RemotePlayState> = _state.asStateFlow()

    private val _effects = Channel<RemotePlayEffect>(Channel.BUFFERED)
    val effects: Flow<RemotePlayEffect> = _effects.receiveAsFlow()

    private val logger = object : PremoLogger {
        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)
            deps.logger.error(tag, message, throwable)
        }
    }

    fun onIntent(intent: RemotePlayIntent) {
        when (intent) {
            is RemotePlayIntent.UpdateIp -> updateState { copy(p
Companion class · kotlin · L380-L388 (9 LOC)
composeApp/src/commonMain/kotlin/com/my/psoldremoteplay/presentation/RemotePlayViewModel.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
        }
    }
ControllerButtons class · kotlin · L13-L31 (19 LOC)
composeApp/src/commonMain/kotlin/com/my/psoldremoteplay/protocol/ControllerInput.kt
object ControllerButtons {
    const val CROSS = 0x0001
    const val CIRCLE = 0x0002
    const val SQUARE = 0x0004
    const val TRIANGLE = 0x0008
    const val L1 = 0x0010
    const val R1 = 0x0020
    const val L2 = 0x0040
    const val R2 = 0x0080
    const val SELECT = 0x0100
    const val START = 0x0200
    const val L3 = 0x0400
    const val R3 = 0x0800
    const val UP = 0x1000
    const val DOWN = 0x2000
    const val LEFT = 0x4000
    const val RIGHT = 0x8000
    const val PS = 0x10000
}
PadProtocol class · kotlin · L13-L72 (60 LOC)
composeApp/src/commonMain/kotlin/com/my/psoldremoteplay/protocol/PadProtocol.kt
object PadProtocol {
    /**
     * Build a single 128-byte pad packet from ControllerState.
     */
    fun buildPadPacket(state: ControllerState): ByteArray {
        val packet = ByteArray(128)

        // Magic constant
        packet[0x00] = 0x74

        // Left analog stick (center = 0x80, range 0x00-0xFF)
        packet[0x04] = (0x80 + (state.leftStickX * 127)).roundToInt().toByte()
        packet[0x05] = (0x80 + (state.leftStickY * 127)).roundToInt().toByte()

        // Right analog stick
        packet[0x08] = (0x80 + (state.rightStickX * 127)).roundToInt().toByte()
        packet[0x09] = (0x80 + (state.rightStickY * 127)).roundToInt().toByte()

        // Buttons — two bytes: high byte + low byte
        // High byte [0x05]: L2/R2/L1/R1/Triangle/Circle/Cross/Square
        // Low byte  [0x07]: Select/L3/R3/Start/Up/Right/Down/Left
        packet[0x05] = buildButtonByte(state.buttons, listOf(
            ControllerButtons.SQUARE,
            ControllerButtons.CROSS,
        
PremoConstants class · kotlin · L3-L87 (85 LOC)
composeApp/src/commonMain/kotlin/com/my/psoldremoteplay/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

    // UDP discovery
    val SRCH_PACKET = byteArrayOf(0x53, 0x52, 0x43, 0x48) // "SRCH"
    val RESP_MAGIC = byteArrayOf(0x52, 0x45, 0x53, 0x50)   // "RESP"

    // Static session keys (same for ALL PS3s — from Open-RP + Ghidra confirmation)
    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 =
Repobility · code-quality intelligence platform · https://repobility.com
StubVideoDecoder class · kotlin · L12-L17 (6 LOC)
composeApp/src/commonMain/kotlin/com/my/psoldremoteplay/protocol/StubDecoders.kt
class StubVideoDecoder : VideoDecoder {
    override suspend fun start(width: Int, height: Int, codecName: String) {}
    override suspend fun decode(nalData: ByteArray): VideoFrame? = null
    override suspend fun flush() {}
    override suspend fun stop() {}
}
StubAudioDecoder class · kotlin · L22-L27 (6 LOC)
composeApp/src/commonMain/kotlin/com/my/psoldremoteplay/protocol/StubDecoders.kt
class StubAudioDecoder : AudioDecoder {
    override suspend fun start(sampleRate: Int, channels: Int, codecName: String) {}
    override suspend fun decode(data: ByteArray): AudioBuffer? = null
    override suspend fun flush() {}
    override suspend fun stop() {}
}
StubRegistration class · kotlin · L9-L25 (17 LOC)
composeApp/src/commonMain/kotlin/com/my/psoldremoteplay/protocol/StubImplementations.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 encryption not yet solved. " +
                "Use HEN PS3 with pre-extracted keys or wait for community breakthrough."
            )
        )
    }
}
StubControllerInput class · kotlin · L27-L31 (5 LOC)
composeApp/src/commonMain/kotlin/com/my/psoldremoteplay/protocol/StubImplementations.kt
class StubControllerInput : ControllerInputSender {
    override suspend fun connect(ps3Ip: String, sessionId: String, authToken: String) {}
    override suspend fun sendState(state: ControllerState) {}
    override suspend fun disconnect() {}
}
LoggingVideoRenderer class · kotlin · L33-L54 (22 LOC)
composeApp/src/commonMain/kotlin/com/my/psoldremoteplay/protocol/StubImplementations.kt
class LoggingVideoRenderer(private val logger: PremoLogger) : VideoRenderer {
    private var packetCount = 0
    private val _currentFrame = MutableStateFlow<ImageBitmap?>(null)
    override val currentFrame: StateFlow<ImageBitmap?> = _currentFrame.asStateFlow()

    override suspend fun start() {
        logger.log("VIDEO", "Video renderer started")
    }

    override suspend fun onStreamPacket(header: ByteArray, payload: ByteArray, isEncrypted: Boolean) {
        packetCount++
        if (packetCount % 30 == 0) {
            logger.log("VIDEO", "Received $packetCount packets, last payload: ${payload.size} bytes")
        }
    }

    override suspend fun stop() {
        logger.log("VIDEO", "Video renderer stopped ($packetCount total packets)")
        packetCount = 0
        _currentFrame.value = null
    }
}
StubAudioRenderer class · kotlin · L56-L68 (13 LOC)
composeApp/src/commonMain/kotlin/com/my/psoldremoteplay/protocol/StubImplementations.kt
class StubAudioRenderer(private val logger: PremoLogger) : AudioRenderer {
    override suspend fun start() {
        logger.log("AUDIO", "Audio renderer started")
    }

    override suspend fun onAudioBuffer(buffer: AudioBuffer) {
        logger.log("AUDIO", "Audio buffer: ${buffer.samples.size} bytes @ ${buffer.sampleRate}Hz")
    }

    override suspend fun stop() {
        logger.log("AUDIO", "Audio renderer stopped")
    }
}
PassthroughUpscaler class · kotlin · L8-L10 (3 LOC)
composeApp/src/commonMain/kotlin/com/my/psoldremoteplay/protocol/upscale/PassthroughUpscaler.kt
class PassthroughUpscaler : UpscaleFilter {
    override suspend fun process(frame: VideoFrame): VideoFrame = frame
}
DesktopDependencies class · kotlin · L10-L31 (22 LOC)
composeApp/src/desktopMain/kotlin/com/my/psoldremoteplay/di/DesktopDependencies.kt
class DesktopDependencies : PlatformDependencies {
    override val logger: PremoLogger = object : PremoLogger {
        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)
        }
    }

    override val crypto: PremoCrypto = JvmPremoCrypto
    override val discoverer: Ps3Discoverer = JvmPs3Discoverer(logger)
    override val sessionHandler: PremoSessionHandler = JvmPremoSession(crypto, logger)
    override val registration: PremoRegistration = JvmPremoRegistration(crypto, logger)
    override val videoDecoder: VideoDecoder = StubVideoDecoder()
    override val audioDecoder: AudioDecoder = StubAudioDecoder()
    override val videoRenderer: VideoRenderer = JvmVideoRenderer(logger)
    override val audioRenderer: AudioRenderer = StubAudioRenderer(logger)
Repobility (the analyzer behind this table) · https://repobility.com
JvmControllerInput class · kotlin · L19-L54 (36 LOC)
composeApp/src/desktopMain/kotlin/com/my/psoldremoteplay/JvmControllerInput.kt
class JvmControllerInput(private val logger: PremoLogger) : ControllerInputSender {
    private var socket: Socket? = null
    private var isConnected = false

    override suspend fun connect(ps3Ip: String, sessionId: String, authToken: String) = withContext(Dispatchers.IO) {
        try {
            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()},${state.leftStickY.toInt()})")
            // TODO
JvmPremoCrypto class · kotlin · L10-L26 (17 LOC)
composeApp/src/desktopMain/kotlin/com/my/psoldremoteplay/JvmPremoCrypto.kt
object JvmPremoCrypto : PremoCrypto {
    override fun aesEncrypt(data: ByteArray, key: ByteArray, iv: ByteArray): ByteArray {
        val cipher = Cipher.getInstance("AES/CBC/NoPadding")
        cipher.init(Cipher.ENCRYPT_MODE, SecretKeySpec(key, "AES"), IvParameterSpec(iv))
        return cipher.doFinal(data)
    }

    override fun aesDecrypt(data: ByteArray, key: ByteArray, iv: ByteArray): ByteArray {
        val cipher = Cipher.getInstance("AES/CBC/NoPadding")
        cipher.init(Cipher.DECRYPT_MODE, SecretKeySpec(key, "AES"), IvParameterSpec(iv))
        return cipher.doFinal(data)
    }

    override fun base64Encode(data: ByteArray): String = Base64.getEncoder().encodeToString(data)
    override fun base64Decode(data: String): ByteArray = Base64.getDecoder().decode(data)
    override fun randomBytes(count: Int): ByteArray = ByteArray(count).also { SecureRandom().nextBytes(it) }
}
JvmPremoRegistration class · kotlin · L19-L89 (71 LOC)
composeApp/src/desktopMain/kotlin/com/my/psoldremoteplay/JvmPremoRegistration.kt
class JvmPremoRegistration(private val crypto: PremoCrypto, private val logger: PremoLogger) : 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", "   Re
JvmPremoSession class · kotlin · L10-L279 (270 LOC)
composeApp/src/desktopMain/kotlin/com/my/psoldremoteplay/JvmPremoSession.kt
class JvmPremoSession(private val crypto: PremoCrypto, private val logger: PremoLogger) : 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
JvmPs3Discoverer class · kotlin · L11-L161 (151 LOC)
composeApp/src/desktopMain/kotlin/com/my/psoldremoteplay/JvmPs3Discoverer.kt
class JvmPs3Discoverer(private val logger: PremoLogger) : 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.sen
JvmVideoRenderer class · kotlin · L17-L49 (33 LOC)
composeApp/src/desktopMain/kotlin/com/my/psoldremoteplay/JvmVideoRenderer.kt
class JvmVideoRenderer(private val logger: PremoLogger) : VideoRenderer {
    private val _currentFrame = MutableStateFlow<androidx.compose.ui.graphics.ImageBitmap?>(null)
    override val currentFrame: StateFlow<androidx.compose.ui.graphics.ImageBitmap?> = _currentFrame.asStateFlow()

    private var packetCount = 0

    override suspend fun start() = withContext(Dispatchers.IO) {
        logger.log("VIDEO", "[DESKTOP] Video renderer initialized")
    }

    override suspend fun onStreamPacket(header: ByteArray, payload: ByteArray, isEncrypted: Boolean) =
        withContext(Dispatchers.IO) {
            val magic = header[1].toInt() and 0xFF
            packetCount++

            when (magic) {
                0xFF, 0xFE -> {
                    if (packetCount % 30 == 0) {
                        logger.log("VIDEO", "[DESKTOP] H.264 frame ${packetCount}: ${payload.size} bytes")
                    }
                    // TODO: Decode H.264 NAL data and update _currentFrame
        
KeyboardController class · kotlin · L25-L100 (76 LOC)
composeApp/src/desktopMain/kotlin/com/my/psoldremoteplay/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.contains
DesktopPlatform class · kotlin · L3-L5 (3 LOC)
composeApp/src/desktopMain/kotlin/com/my/psoldremoteplay/Platform.desktop.kt
class DesktopPlatform : Platform {
    override val name: String = "Desktop JVM ${System.getProperty("java.version")}"
}
Open data scored by Repobility · https://repobility.com
PhoneTypePS4FormulaStrategy class · kotlin · L15-L262 (248 LOC)
composeApp/src/desktopMain/kotlin/com/my/psoldremoteplay/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: PremoCrypto,
        logger: PremoLogger
    ): 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
PCTypePS4FormulaStrategy class · kotlin · L275-L465 (191 LOC)
composeApp/src/desktopMain/kotlin/com/my/psoldremoteplay/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: PremoCrypto,
        logger: PremoLogger
    ): 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")
            }

      
PSPTypePS4FormulaStrategy class · kotlin · L476-L652 (177 LOC)
composeApp/src/desktopMain/kotlin/com/my/psoldremoteplay/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: PremoCrypto,
        logger: PremoLogger
    ): 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 
PhoneTypeBELonglongStrategy class · kotlin · L659-L676 (18 LOC)
composeApp/src/desktopMain/kotlin/com/my/psoldremoteplay/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: PremoCrypto,
        logger: PremoLogger
    ): RegistrationAttempt = withContext(Dispatchers.IO) {
        logger.log("REGIST", "▶ $name (disabled)")
        RegistrationAttempt(name, false, error = "Disabled - already tested and failed")
    }
}
PhoneTypeLELonglongStrategy class · kotlin · L683-L700 (18 LOC)
composeApp/src/desktopMain/kotlin/com/my/psoldremoteplay/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: PremoCrypto,
        logger: PremoLogger
    ): RegistrationAttempt = withContext(Dispatchers.IO) {
        logger.log("REGIST", "▶ $name (disabled)")
        RegistrationAttempt(name, false, error = "Disabled - already tested and failed")
    }
}
RegistrationStrategies class · kotlin · L58-L123 (66 LOC)
composeApp/src/desktopMain/kotlin/com/my/psoldremoteplay/RegistrationStrategy.kt
object RegistrationStrategies {

    /**
     * Strategy 2: Phone Type (1) with PS4 Formula
     * IV Context: PIN as 4-byte BE uint + 4 zeros
     * STATUS: TESTED - FAILED (403 Forbidden)
     *
     * Hypothesis: PS4 registration uses similar pattern, worth testing
     * Result: Does not match PS3 registration encryption
     */
    val phoneTypePS4Formula = PhoneTypePS4FormulaStrategy()

    /**
     * Strategy 3: PC Type (2) with PS4 Formula
     * IV Context: PIN as 4-byte BE uint + 4 zeros
     * Key Material: PIN as 4-byte BE + 12 zeros (PIN-derived)
     * STATUS: NEW - From VAIO DLL Analysis
     *
     * Insight: VRPSDK.dll analysis shows PC type uses PIN-derived key material,
     * unlike Phone type which uses random material. Different body structure.
     *
     * Reference: research/pupps3/ghidra_findings/22_VAIO_DLL_ANALYSIS.md page 312
     */
    val pcTypePS4Formula = PCTypePS4FormulaStrategy()

    /**
     * Strategy 4: Phone Type with 8-Byte BE Longlong
     * I
IosDependencies class · kotlin · L14-L69 (56 LOC)
composeApp/src/iosMain/kotlin/com/my/psoldremoteplay/di/IosDependencies.kt
class IosDependencies : PlatformDependencies {
    override val logger: PremoLogger = object : PremoLogger {
        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)
        }
    }

    override val crypto: PremoCrypto = object : PremoCrypto {
        override fun aesEncrypt(data: ByteArray, key: ByteArray, iv: ByteArray): ByteArray {
            error("iOS crypto not implemented yet")
        }
        override fun aesDecrypt(data: ByteArray, key: ByteArray, iv: ByteArray): ByteArray {
            error("iOS crypto not implemented yet")
        }
        override fun base64Encode(data: ByteArray): String {
            error("iOS crypto not implemented yet")
        }
        override fun base64Decode(data: String): ByteArray {
            error("iOS 
IOSPlatform class · kotlin · L5-L7 (3 LOC)
composeApp/src/iosMain/kotlin/com/my/psoldremoteplay/Platform.ios.kt
class IOSPlatform: Platform {
    override val name: String = UIDevice.currentDevice.systemName() + " " + UIDevice.currentDevice.systemVersion
}
If a scraper extracted this row, it came from Repobility (https://repobility.com)
StubAudioDecoder class · kotlin · L6-L11 (6 LOC)
core/audio/src/commonMain/kotlin/com/my/psremoteplay/core/audio/stubs/StubAudioDecoder.kt
class StubAudioDecoder : AudioDecoder {
    override suspend fun start(sampleRate: Int, channels: Int, codecName: String) {}
    override suspend fun decode(data: ByteArray): AudioBuffer? = null
    override suspend fun flush() {}
    override suspend fun stop() {}
}
StubAudioRenderer class · kotlin · L7-L19 (13 LOC)
core/audio/src/commonMain/kotlin/com/my/psremoteplay/core/audio/stubs/StubAudioRenderer.kt
class StubAudioRenderer(private val logger: Logger) : AudioRenderer {
    override suspend fun start() {
        logger.log("AUDIO", "Audio renderer started")
    }

    override suspend fun onAudioBuffer(buffer: AudioBuffer) {
        logger.log("AUDIO", "Audio buffer: ${buffer.samples.size} bytes @ ${buffer.sampleRate}Hz")
    }

    override suspend fun stop() {
        logger.log("AUDIO", "Audio renderer stopped")
    }
}
ControllerButtons class · kotlin · L13-L31 (19 LOC)
core/model/src/commonMain/kotlin/com/my/psremoteplay/core/model/input/ControllerState.kt
object ControllerButtons {
    const val CROSS = 0x0001
    const val CIRCLE = 0x0002
    const val SQUARE = 0x0004
    const val TRIANGLE = 0x0008
    const val L1 = 0x0010
    const val R1 = 0x0020
    const val L2 = 0x0040
    const val R2 = 0x0080
    const val SELECT = 0x0100
    const val START = 0x0200
    const val L3 = 0x0400
    const val R3 = 0x0800
    const val UP = 0x1000
    const val DOWN = 0x2000
    const val LEFT = 0x4000
    const val RIGHT = 0x8000
    const val PS = 0x10000
}
StubControllerInput class · kotlin · L3-L7 (5 LOC)
core/model/src/commonMain/kotlin/com/my/psremoteplay/core/model/input/StubControllerInput.kt
class StubControllerInput : ControllerInputSender {
    override suspend fun connect(params: Map<String, String>) {}
    override suspend fun sendState(state: ControllerState) {}
    override suspend fun disconnect() {}
}
PassthroughUpscaler class · kotlin · L5-L7 (3 LOC)
core/upscale/src/commonMain/kotlin/com/my/psremoteplay/core/upscale/PassthroughUpscaler.kt
class PassthroughUpscaler : UpscaleFilter {
    override suspend fun process(frame: VideoFrame): VideoFrame = frame
}
AndroidVideoRenderer class · kotlin · L13-L53 (41 LOC)
core/video/src/androidMain/kotlin/com/my/psremoteplay/core/video/AndroidVideoRenderer.kt
class AndroidVideoRenderer(private val logger: Logger) : VideoRenderer {
    private val _currentFrame = MutableStateFlow<ImageBitmap?>(null)
    override val currentFrame: StateFlow<ImageBitmap?> = _currentFrame.asStateFlow()

    private var packetCount = 0

    override suspend fun start() {
        logger.log("VIDEO", "[ANDROID] Video renderer initialized")
    }

    override suspend fun onStreamPacket(header: ByteArray, payload: ByteArray, isEncrypted: Boolean) =
        withContext(Dispatchers.IO) {
            packetCount++

            // Detect JPEG data (SOI marker: 0xFF 0xD8)
            if (payload.size >= 2 &&
                payload[0] == 0xFF.toByte() &&
                payload[1] == 0xD8.toByte()
            ) {
                try {
                    val bitmap = BitmapFactory.decodeByteArray(payload, 0, payload.size)
                    if (bitmap != null) {
                        _currentFrame.value = bitmap.asImageBitmap()
                    }
                }
LoggingVideoRenderer class · kotlin · L10-L31 (22 LOC)
core/video/src/commonMain/kotlin/com/my/psremoteplay/core/video/stubs/LoggingVideoRenderer.kt
class LoggingVideoRenderer(private val logger: Logger) : VideoRenderer {
    private var packetCount = 0
    private val _currentFrame = MutableStateFlow<ImageBitmap?>(null)
    override val currentFrame: StateFlow<ImageBitmap?> = _currentFrame.asStateFlow()

    override suspend fun start() {
        logger.log("VIDEO", "Video renderer started")
    }

    override suspend fun onStreamPacket(header: ByteArray, payload: ByteArray, isEncrypted: Boolean) {
        packetCount++
        if (packetCount % 30 == 0) {
            logger.log("VIDEO", "Received $packetCount packets, last payload: ${payload.size} bytes")
        }
    }

    override suspend fun stop() {
        logger.log("VIDEO", "Video renderer stopped ($packetCount total packets)")
        packetCount = 0
        _currentFrame.value = null
    }
}
StubVideoDecoder class · kotlin · L6-L11 (6 LOC)
core/video/src/commonMain/kotlin/com/my/psremoteplay/core/video/stubs/StubVideoDecoder.kt
class StubVideoDecoder : VideoDecoder {
    override suspend fun start(width: Int, height: Int, codecName: String) {}
    override suspend fun decode(nalData: ByteArray): VideoFrame? = null
    override suspend fun flush() {}
    override suspend fun stop() {}
}
Repobility · code-quality intelligence platform · https://repobility.com
JvmVideoRenderer class · kotlin · L13-L52 (40 LOC)
core/video/src/desktopMain/kotlin/com/my/psremoteplay/core/video/JvmVideoRenderer.kt
class JvmVideoRenderer(private val logger: Logger) : VideoRenderer {
    private val _currentFrame = MutableStateFlow<ImageBitmap?>(null)
    override val currentFrame: StateFlow<ImageBitmap?> = _currentFrame.asStateFlow()

    private var packetCount = 0

    override suspend fun start() = withContext(Dispatchers.IO) {
        logger.log("VIDEO", "[DESKTOP] Video renderer initialized")
    }

    override suspend fun onStreamPacket(header: ByteArray, payload: ByteArray, isEncrypted: Boolean) =
        withContext(Dispatchers.IO) {
            packetCount++

            // Detect JPEG data (SOI marker: 0xFF 0xD8)
            if (payload.size >= 2 &&
                payload[0] == 0xFF.toByte() &&
                payload[1] == 0xD8.toByte()
            ) {
                try {
                    val skiaImage = SkiaImage.makeFromEncoded(payload)
                    _currentFrame.value = skiaImage.toComposeImageBitmap()
                } catch (e: Exception) {
                    if (pa
NalUnitProtocol class · kotlin · L12-L86 (75 LOC)
feature/ps2/protocol/src/commonMain/kotlin/com/my/psremoteplay/feature/ps2/protocol/NalUnitProtocol.kt
object NalUnitProtocol {
    const val HEADER_SIZE = 9

    const val FLAG_KEYFRAME: Int = 0x01
    const val FLAG_SPS: Int = 0x02
    const val FLAG_PPS: Int = 0x04

    private const val NAL_TYPE_IDR = 5
    private const val NAL_TYPE_SPS = 7
    private const val NAL_TYPE_PPS = 8

    fun wrapNalUnit(nalUnit: ByteArray, sequenceNumber: Int, timestampMs: Long): ByteArray {
        val flags = detectFlags(nalUnit)
        val packet = ByteArray(HEADER_SIZE + nalUnit.size)

        packet[0] = (sequenceNumber ushr 24 and 0xFF).toByte()
        packet[1] = (sequenceNumber ushr 16 and 0xFF).toByte()
        packet[2] = (sequenceNumber ushr 8 and 0xFF).toByte()
        packet[3] = (sequenceNumber and 0xFF).toByte()

        val ts = timestampMs.toInt()
        packet[4] = (ts ushr 24 and 0xFF).toByte()
        packet[5] = (ts ushr 16 and 0xFF).toByte()
        packet[6] = (ts ushr 8 and 0xFF).toByte()
        packet[7] = (ts and 0xFF).toByte()

        packet[8] = flags.toByte()

        
Ps2Protocol class · kotlin · L5-L105 (101 LOC)
feature/ps2/protocol/src/commonMain/kotlin/com/my/psremoteplay/feature/ps2/protocol/Ps2Protocol.kt
object Ps2Protocol {

    const val DEFAULT_PORT = 9295

    // Message types
    const val VIDEO_FRAME: Byte = 0x01
    const val CONTROLLER_STATE: Byte = 0x03
    const val SERVER_INFO: Byte = 0x10
    const val STREAM_STATS: Byte = 0x04
    const val CLIENT_HELLO: Byte = 0x20

    const val CONTROLLER_PAYLOAD_SIZE = 14

    /**
     * Builds a wire frame: 4-byte BE length (type + payload size) + type byte + payload.
     */
    fun buildFrame(type: Byte, payload: ByteArray): ByteArray {
        val frameLength = 1 + payload.size // type + payload
        val frame = ByteArray(4 + frameLength)
        // 4-byte big-endian length
        frame[0] = (frameLength shr 24 and 0xFF).toByte()
        frame[1] = (frameLength shr 16 and 0xFF).toByte()
        frame[2] = (frameLength shr 8 and 0xFF).toByte()
        frame[3] = (frameLength and 0xFF).toByte()
        // type
        frame[4] = type
        // payload
        payload.copyInto(frame, destinationOffset = 5)
        return frame
  
page 1 / 8next ›