Removed dead code

This commit is contained in:
ml
2026-06-01 16:31:29 +02:00
parent d7adb56197
commit 724157aca3
8 changed files with 1 additions and 209 deletions
@@ -1,37 +0,0 @@
package de.ladkau.schwertundmagieonpebblecompanionapp
import android.graphics.Bitmap
import java.nio.ByteBuffer
class C64Engine {
// Native hooks representing underlying open-source emulator loops (e.g., Frodo Core)
external fun initEmulator(romPath: String): Boolean
external fun runFrame()
external fun getRawVideoBuffer(buffer: ByteBuffer) // Populates native 320x200 ARGB pixels
external fun injectNativeKey(keyCode: Int, isPressed: Boolean)
companion object {
init {
System.loadLibrary("frodoc64_core")
}
}
// Maps standard incoming string commands to traditional C64 matrix keycodes
fun handleWatchInput(command: String) {
val c64KeyCode = when (command) {
"1" -> 0x31 // C64 '1'
"2" -> 0x32 // C64 '2'
"3" -> 0x33 // C64 '3'
"Y" -> 0x59 // C64 'Y'
"N" -> 0x4E // C64 'N'
else -> return
}
// Simulates a clean hardware keypress cycle
Thread {
injectNativeKey(c64KeyCode, true)
Thread.sleep(100) // Hold down frame duration
injectNativeKey(c64KeyCode, false)
}.start()
}
}
@@ -1,74 +0,0 @@
package de.ladkau.schwertundmagieonpebblecompanionapp
import android.app.Service
import android.content.Context
import android.content.Intent
import android.os.IBinder
import com.getpebble.android.kit.PebbleKit
import com.getpebble.android.kit.PebbleKit.PebbleDataReceiver
import com.getpebble.android.kit.util.PebbleDictionary
import java.util.UUID
class EmulatorService : Service() {
private val PEBBLE_APP_UUID = UUID.fromString("6d616769-652d-c64p-ebbl-e57591684000")
private val KEY_COMMAND = 1
private lateinit var emulatorEngine: C64Engine
private lateinit var watchStreamer: PebbleStreamer
private var isRunning = false
private var pebbleDataReceiver: PebbleDataReceiver? = null
override fun onCreate() {
super.onCreate()
emulatorEngine = C64Engine()
watchStreamer = PebbleStreamer(this)
// Boot standard disk path containing Schwert und Magie Part 1
val romPath = filesDir.absolutePath + "/schwert_und_magie_1.d64"
emulatorEngine.initEmulator(romPath)
setupPebbleInputReceiver()
startEmulationLoop()
}
private fun setupPebbleInputReceiver() {
pebbleDataReceiver = object : PebbleDataReceiver(PEBBLE_APP_UUID) {
override fun receiveData(context: Context?, transactionId: Int, data: PebbleDictionary) {
// Read ASCII string parsed by watch selections
val command = data.getString(KEY_COMMAND)
if (command != null) {
emulatorEngine.handleWatchInput(command)
}
}
}
PebbleKit.registerReceivedDataHandler(this, pebbleDataReceiver)
}
private fun startEmulationLoop() {
isRunning = true
Thread {
val TargetFrameTimeMs = 33 // Aiming roughly around standard video refresh increments
while (isRunning) {
val startTime = System.currentTimeMillis()
emulatorEngine.runFrame()
watchStreamer.processAndStreamFrame(emulatorEngine)
val elapsed = System.currentTimeMillis() - startTime
if (elapsed < TargetFrameTimeMs) {
Thread.sleep(TargetFrameTimeMs - elapsed)
}
}
}.start()
}
override fun onDestroy() {
isRunning = false
super.onDestroy()
try {
unregisterReceiver(pebbleDataReceiver)
} catch (e: Exception) { /* Context safety cleanup */ }
}
override fun onBind(intent: Intent?): IBinder? = null
}
@@ -1,76 +0,0 @@
package de.ladkau.schwertundmagieonpebblecompanionapp
import android.content.Context
import android.graphics.Bitmap
import com.getpebble.android.kit.PebbleKit
import com.getpebble.android.kit.util.PebbleDictionary
import java.nio.ByteBuffer
import java.util.UUID
class PebbleStreamer(private val context: Context) {
// Matches the unique watch app configuration ID
private val PEBBLE_APP_UUID = UUID.fromString("6d616769-652d-c64p-ebbl-e57591684000")
private val KEY_FRAMEBUFFER = 0
private val c64Width = 320
private val c64Height = 200
private val targetWidth = 144
private val targetHeight = 168
private val rawVideoByteBuffer = ByteBuffer.allocateDirect(c64Width * c64Height * 4)
private val previousPackedFrame = ByteArray(3024) // Base baseline to identify delta frames
fun processAndStreamFrame(engine: C64Engine) {
rawVideoByteBuffer.clear()
engine.getRawVideoBuffer(rawVideoByteBuffer)
rawVideoByteBuffer.rewind()
// 1. Downsample raw output directly to 144x168 target matrix via threshold loop
val packedFrame = ByteArray(3024) // 144 * 168 / 8 bits
var byteIndex = 0
var bitCounter = 0
var currentByte = 0
// Calculate steps for nearest-neighbor scaling while stripping non-essential margins
val scaleX = c64Width.toFloat() / targetWidth.toFloat()
val scaleY = c64Height.toFloat() / targetHeight.toFloat()
for (y in 0 until targetHeight) {
val sourceY = (y * scaleY).toInt().coerceIn(0, c64Height - 1)
for (x in 0 until targetWidth) {
val sourceX = (x * scaleX).toInt().coerceIn(0, c64Width - 1)
// Read Pixel Integer (ARGB)
val pixelIdx = (sourceY * c64Width + sourceX) * 4
val r = rawVideoByteBuffer.get(pixelIdx + 1).toInt() and 0xFF
val g = rawVideoByteBuffer.get(pixelIdx + 2).toInt() and 0xFF
val b = rawVideoByteBuffer.get(pixelIdx + 3).toInt() and 0xFF
// Traditional relative luminance formula for 1-bit thresholding
val luminance = (0.299 * r + 0.587 * g + 0.114 * b)
val bit = if (luminance > 128) 1 else 0 // 1 = White background, 0 = Dark Text
// Pack bits securely into destination byte indices
currentByte = (currentByte shl 1) or bit
bitCounter++
if (bitCounter == 8) {
packedFrame[byteIndex++] = currentByte.toByte()
currentByte = 0
bitCounter = 0
}
}
}
// 2. Perform simple Dirty Frame Check to preserve BLE airwaves
if (packedFrame.contentEquals(previousPackedFrame)) {
return // Game screen is currently static; abort transfer
}
System.arraycopy(packedFrame, 0, previousPackedFrame, 0, packedFrame.size)
// 3. Dispatch the payload out to the connected Pebble Watch
val dict = PebbleDictionary()
dict.addBytes(KEY_FRAMEBUFFER, packedFrame)
PebbleKit.sendDataToPebble(context, PEBBLE_APP_UUID, dict)
}
}