disbrowser/src/jvmMain/kotlin/com/smallhacker/disbrowser/Service.kt

93 lines
3.5 KiB
Kotlin
Raw Normal View History

2019-01-11 03:19:08 +00:00
package com.smallhacker.disbrowser
import com.smallhacker.disbrowser.asm.*
import com.smallhacker.disbrowser.disassembler.Disassembler
2019-01-20 10:11:30 +00:00
import com.smallhacker.disbrowser.game.Game
import com.smallhacker.disbrowser.memory.SnesAddress
import com.smallhacker.disbrowser.memory.address
import com.smallhacker.disbrowser.memory.getWord
import com.smallhacker.util.VagueNumber
import com.smallhacker.util.toUInt24
2019-01-11 03:19:08 +00:00
import kotlin.reflect.KMutableProperty1
private val RESET_VECTOR_LOCATION = address(0x00_FFFC)
2019-01-14 02:03:16 +00:00
private val UPDATE_MUTEX = Any()
2019-01-11 03:19:08 +00:00
2019-01-13 03:38:59 +00:00
private val VECTORS = listOf(
address(0x00_FFE4) to "COP",
address(0x00_FFE6) to "BRK",
address(0x00_FFE8) to "ABORT",
address(0x00_FFEA) to "NMI",
address(0x00_FFEC) to "RESET",
address(0x00_FFEE) to "IRQ",
address(0x00_FFF4) to "COP (e)",
address(0x00_FFF6) to "BRK (e)",
address(0x00_FFF8) to "ABORT (e)",
address(0x00_FFFA) to "NMI (e)",
address(0x00_FFFC) to "RES (e)",
address(0x00_FFFE) to "IRQBRK (e)"
)
2019-01-11 03:19:08 +00:00
object Service {
fun showDisassemblyFromReset(game: Game): HtmlNode? {
val resetVector = game.memory.getWord(RESET_VECTOR_LOCATION)
2019-01-12 02:16:50 +00:00
val fullResetVector = resetVector!!.toUInt24()
val initialAddress = SnesAddress(fullResetVector)
2019-01-11 03:19:08 +00:00
val flags = VagueNumber(0x30u)
return showDisassembly(game, initialAddress, flags)
2019-01-11 03:19:08 +00:00
}
2019-01-18 21:19:30 +00:00
fun showDisassembly(game: Game, initialAddress: SnesAddress, flags: VagueNumber, global: Boolean = false): HtmlNode? {
val initialState = State(memory = game.memory, address = initialAddress, flags = flags, gameData = game.gameData)
2019-01-18 21:19:30 +00:00
val disassembly = Disassembler.disassemble(initialState, game.gameData, global)
2019-01-11 03:19:08 +00:00
return print(disassembly, game)
2019-01-11 03:19:08 +00:00
}
private fun print(disassembly: Disassembly, game: Game): HtmlNode {
2019-01-11 03:19:08 +00:00
val grid = Grid()
disassembly.forEach {
grid.add(it, game, disassembly)
2019-01-11 03:19:08 +00:00
}
disassembly.asSequence()
2019-01-14 05:23:19 +00:00
.mapNotNull {ins ->
ins.linkedState
2019-01-11 03:19:08 +00:00
?.let { link ->
2019-01-14 05:23:19 +00:00
ins.sortedAddress to link.address
2019-01-11 03:19:08 +00:00
}
}
.sortedBy { it.first distanceTo it.second }
.forEach { grid.arrow(it.first, it.second) }
2019-01-13 03:38:59 +00:00
return grid.output()
2019-01-11 03:19:08 +00:00
}
fun updateMetadata(game: Game, address: SnesAddress, field: KMutableProperty1<MetadataLine, String?>, value: String) {
2019-01-14 02:03:16 +00:00
synchronized(UPDATE_MUTEX) {
if (value.isEmpty()) {
if (address in game.gameData) {
doUpdateMetadata(game, address, field, null)
}
} else {
doUpdateMetadata(game, address, field, value)
2019-01-11 03:19:08 +00:00
}
}
}
private fun doUpdateMetadata(game: Game, address: SnesAddress, field: KMutableProperty1<MetadataLine, String?>, value: String?) {
val line = game.gameData.getOrCreate(address)
2019-01-11 05:09:12 +00:00
field.set(line, value)
game.saveGameData()
2019-01-11 05:09:12 +00:00
}
fun getVectors(game: Game) = VECTORS.asSequence()
2019-01-13 03:38:59 +00:00
.map { (vectorLocation: SnesAddress, name: String ) ->
val codeLocation = SnesAddress(game.memory.getWord(vectorLocation)!!.toUInt24())
val label = game.gameData[codeLocation]?.label
2019-01-13 03:38:59 +00:00
?: codeLocation.toFormattedString()
Vector(vectorLocation, codeLocation, name, label)
}
2019-01-11 03:19:08 +00:00
}
2019-01-13 03:38:59 +00:00
data class Vector(val vectorLocation: SnesAddress, val codeLocation: SnesAddress, val name: String, val label: String)