disbrowser/src/jvmMain/kotlin/com/smallhacker/disbrowser/resource/DisassemblyResource.kt

149 lines
4.8 KiB
Kotlin
Raw Normal View History

2019-01-11 03:19:08 +00:00
package com.smallhacker.disbrowser.resource
2019-01-13 03:38:59 +00:00
import com.smallhacker.disbrowser.*
2019-01-20 10:11:30 +00:00
import com.smallhacker.util.VagueNumber
import com.smallhacker.disbrowser.game.getGameSource
2019-01-20 10:11:30 +00:00
import com.smallhacker.disbrowser.memory.SnesAddress
2019-01-11 05:09:12 +00:00
import java.nio.charset.StandardCharsets
2019-01-11 03:19:08 +00:00
import javax.ws.rs.GET
import javax.ws.rs.Path
import javax.ws.rs.PathParam
import javax.ws.rs.Produces
import javax.ws.rs.core.Configuration
import javax.ws.rs.core.Context
2019-01-11 03:19:08 +00:00
import javax.ws.rs.core.MediaType
import javax.ws.rs.core.Response
@Path("/{game}")
2019-01-11 03:19:08 +00:00
class DisassemblyResource {
@Context
private lateinit var config: Configuration
private val games by lazy { config.getGameSource() }
2019-01-11 03:19:08 +00:00
@GET
@Produces(MediaType.TEXT_HTML)
fun getIt(@PathParam("game") gameName: String) = handle {
games.getGame(gameName)?.let { game ->
htmlFragment {
table {
Service.getVectors(game).forEach {
tr {
td { text(it.name) }
td { text("(" + it.vectorLocation.toFormattedString() + ")") }
td {
a {
text(it.label)
}.attr("href", "/${game.id}/${it.codeLocation.toSimpleString()}/MX")
}
td { text("(" + it.codeLocation.toFormattedString() + ")") }
}
2019-01-13 03:38:59 +00:00
}
}.addClass("vector-table")
}
}
2019-01-11 03:19:08 +00:00
}
@GET
@Path("{address}")
@Produces(MediaType.TEXT_HTML)
fun getIt(
@PathParam("game") gameName: String,
@PathParam("address") address: String
) = getIt(gameName, address, "")
2019-01-11 03:19:08 +00:00
@GET
@Path("{address}/{state}")
@Produces(MediaType.TEXT_HTML)
fun getIt(
@PathParam("game") gameName: String,
@PathParam("address") address: String,
@PathParam("state") state: String
): Response {
2019-01-11 03:19:08 +00:00
return handle {
games.getGame(gameName)?.let { game ->
SnesAddress.parse(address)?.let {
val flags = parseState(state)
Service.showDisassembly(game, it, flags)
}
2019-01-11 03:19:08 +00:00
}
}
}
2019-01-18 21:19:30 +00:00
@GET
@Path("global/{address}")
@Produces(MediaType.TEXT_HTML)
fun getItGlobal(
@PathParam("game") gameName: String,
@PathParam("address") address: String
) = getItGlobal(gameName, address, "")
@GET
@Path("global/{address}/{state}")
@Produces(MediaType.TEXT_HTML)
fun getItGlobal(
@PathParam("game") gameName: String,
@PathParam("address") address: String,
@PathParam("state") state: String
): Response {
return handle {
games.getGame(gameName)?.let { game ->
SnesAddress.parse(address)?.let {
val flags = parseState(state)
Service.showDisassembly(game, it, flags, true)
}
}
}
}
2019-01-11 03:19:08 +00:00
private fun handle(runner: () -> HtmlNode?): Response {
try {
2019-01-13 03:38:59 +00:00
val output = runner()
?: return Response.status(404).build()
val html =
2019-01-19 22:13:41 +00:00
htmlFragment {
html {
head {
title { text("Disassembly Browser") }
link.attr("rel", "stylesheet").attr("href", "/resources/style.css")
meta.attr("charset", "UTF-8")
}
body {
main {
output.appendTo(parent)
}
2019-01-19 22:13:41 +00:00
aside.addClass("sidebar") {
button.attr("id", "btn-dark-mode") {
text("Dark Mode")
}
}
2019-01-19 22:13:41 +00:00
script.attr("src", "/resources/disbrowser.js")
}
}
2019-01-19 22:13:41 +00:00
}
2019-01-11 03:19:08 +00:00
2019-01-13 03:38:59 +00:00
return Response.ok(html.toString().toByteArray(StandardCharsets.UTF_8))
.encoding("UTF-8")
.build()
2019-01-15 05:54:54 +00:00
} catch (e: Throwable) {
2019-01-11 03:19:08 +00:00
e.printStackTrace()
throw e
}
}
private fun parseState(state: String): VagueNumber {
var flags = VagueNumber()
flags = parseFlag(state, flags, 'M', 'm', 0x20u)
flags = parseFlag(state, flags, 'X', 'x', 0x10u)
return flags
}
private fun parseFlag(state: String, flags: VagueNumber, set: Char, clear: Char, mask: UInt): VagueNumber = when {
state.contains(set) -> flags.withBits(mask)
state.contains(clear) -> flags.withoutBits(mask)
else -> flags
}
}