This commit is contained in:
Smallhacker 2019-01-11 11:35:35 -05:00
parent 32f3cdabff
commit 9881bf9e0b
17 changed files with 277 additions and 116 deletions

View File

@ -1,39 +1,155 @@
{
"008000" : {
"label" : "ResetVector"
},
"008034" : {
"label" : "MainGameLoop"
},
"0080b5" : {
"label" : "JumpToGameMode"
},
"0080c6" : {
"flags" : [ {
"flagType" : "JmpIndirectLongInterleavedTable",
"start" : "008061",
"entries" : 28
} ]
},
"00841e" : {
"label" : "ClearOam",
"comment" : "Test3"
},
"00879c" : {
"flags" : [ {
"flagType" : "NonReturningRoutine"
} ]
},
"0287d0" : {
"flags" : [ {
"flagType" : "JslTableRoutine",
"entries" : 4
} ]
},
"0cc115" : {
"flags" : [ {
"flagType" : "JslTableRoutine",
"entries" : 12
} ]
"code" : {
"008000" : {
"label" : "ResetVector"
},
"00801b" : {
"comment" : "\\ Turn off emulation mode"
},
"00801c" : {
"comment" : "/"
},
"00801f" : {
"comment" : "\\ Set direct page"
},
"008022" : {
"comment" : "/"
},
"008023" : {
"comment" : "\\ Set stack position"
},
"008026" : {
"comment" : "/"
},
"008034" : {
"label" : "MainGameLoop",
"comment" : "Wait for NMI"
},
"00805d" : {
"comment" : "Clear NMI flag"
},
"0080b5" : {
"label" : "JumpToGameMode",
"comment" : "Y = Current game mode"
},
"0080b7" : {
"comment" : "\\ Load routine low byte"
},
"0080ba" : {
"comment" : "/"
},
"0080bc" : {
"comment" : "\\ Load routine mid byte"
},
"0080bf" : {
"comment" : "/"
},
"0080c1" : {
"comment" : "\\ Load routine high byte"
},
"0080c4" : {
"comment" : "/"
},
"0080c6" : {
"flags" : [ {
"flagType" : "JmpIndirectLongInterleavedTable",
"start" : "008061",
"entries" : 28
} ]
},
"00841e" : {
"label" : "ClearOam",
"comment" : "Test3"
},
"00879c" : {
"comment" : "Preserve Y value for later",
"flags" : [ {
"flagType" : "NonReturningRoutine"
} ]
},
"00879e" : {
"comment" : "Y = Ret.Bank"
},
"00879f" : {
"comment" : "$02 = Ret.Bank"
},
"0087a3" : {
"comment" : "\\"
},
"0087a6" : {
"comment" : "|"
},
"0087a8" : {
"comment" : "| Y = In.A * 3"
},
"0087a9" : {
"comment" : "|"
},
"0087ab" : {
"comment" : "/"
},
"0087ac" : {
"comment" : "\\ $03-$04 = Ret.Offset"
},
"0087ad" : {
"comment" : "/"
},
"0087af" : {
"comment" : "Increase Y to compensate for Ret being off by one"
},
"0087b0" : {
"comment" : "\\"
},
"0087b2" : {
"comment" : "|"
},
"0087b4" : {
"comment" : "| Load target pointer into $00-03 (last byte unused)"
},
"0087b5" : {
"comment" : "|"
},
"0087b7" : {
"comment" : "/"
},
"0087bb" : {
"comment" : "Restore initial Y value"
},
"0087bd" : {
"comment" : "Jump to pointer"
},
"008901" : {
"comment" : "\\"
},
"008903" : {
"comment" : "|"
},
"008905" : {
"comment" : "| Write #$19:8000 to $00"
},
"008907" : {
"comment" : "|"
},
"008909" : {
"comment" : "|"
},
"00890b" : {
"comment" : "/"
},
"0287d0" : {
"flags" : [ {
"flagType" : "JslTableRoutine",
"entries" : 4
} ]
},
"029ee3" : {
"label" : "GM_TriforceRoom"
},
"0cc115" : {
"flags" : [ {
"flagType" : "JslTableRoutine",
"entries" : 12
} ]
}
}
}

View File

@ -9,13 +9,13 @@ class Grid {
private val content = HashMap<Pair<Int, Int>, HtmlNode?>()
private val cellClasses = HashMap<Pair<Int, Int>, String>()
private val addresses = HashMap<Address, Int>()
private val addresses = HashMap<SnesAddress, Int>()
private val rowClasses = HashMap<Int, String>()
private val rowId = HashMap<Int, String>()
private var height = 0
private var nextAddress: Address? = null
private var nextAddress: SnesAddress? = null
fun arrow(from: Address, to: Address) {
fun arrow(from: SnesAddress, to: SnesAddress) {
val yStart = addresses[from]
val yEnd = addresses[to]
if (yStart == null || yEnd == null) {
@ -60,7 +60,7 @@ class Grid {
}
fun add(ins: CodeUnit, metadata: Metadata, disassembly: Disassembly) {
val insMetadata = ins.address ?.let { metadata[it] }
val insMetadata = ins.address?.let { metadata[it] }
val actualAddress = ins.address
val presentedAddress = ins.presentedAddress
@ -80,7 +80,7 @@ class Grid {
text(ins.bytesToString()),
editableField(presentedAddress, "label", insMetadata?.label),
fragment {
text(ins.printOpcodeAndSuffix())
opcodeNode(ins)
text(" ")
var operands = ins.printOperands()
@ -111,7 +111,19 @@ class Grid {
}
}
private fun editableField(address: Address, type: String, value: String?): HtmlNode {
private fun HtmlArea.opcodeNode(ins: CodeUnit) {
val alt = ins.printAlternativeOpcodeAndSuffix()
if (alt == null) {
text(ins.printOpcodeAndSuffix())
} else {
span {
text(ins.printOpcodeAndSuffix())
}.attr("title", alt).addClass("opcode-info")
}
}
private fun editableField(address: SnesAddress, type: String, value: String?): HtmlNode {
return input(value = value ?: "")
.addClass("field-$type")
.addClass("field-editable")
@ -124,7 +136,7 @@ class Grid {
add(y, null, null, null, null, text("..."), null, null)
}
private fun add(y: Int, address: Address?,
private fun add(y: Int, address: SnesAddress?,
cAddress: HtmlNode?,
cBytes: HtmlNode?,
cLabel: HtmlNode?,

View File

@ -99,6 +99,8 @@ fun body(inner: InnerHtml = {}) = parent("body", inner)
fun HtmlArea.body(inner: InnerHtml = {}) = com.smallhacker.disbrowser.body(inner).appendTo(parent)
fun div(inner: InnerHtml = {}) = parent("div", inner)
fun HtmlArea.div(inner: InnerHtml = {}) = com.smallhacker.disbrowser.div(inner).appendTo(parent)
fun span(inner: InnerHtml = {}) = parent("span", inner)
fun HtmlArea.span(inner: InnerHtml = {}) = com.smallhacker.disbrowser.span(inner).appendTo(parent)
fun table(inner: InnerHtml = {}) = parent("table", inner)
fun HtmlArea.table(inner: InnerHtml = {}) = com.smallhacker.disbrowser.table(inner).appendTo(parent)
fun tr(inner: InnerHtml = {}) = parent("tr", inner)

View File

@ -23,12 +23,12 @@ object Service {
fun showDisassemblyFromReset(): HtmlNode? {
val resetVectorLocation = RESET_VECTOR_LOCATION
val initialAddress = Address(romData.value.getWord(resetVectorLocation.pc).toUInt24())
val initialAddress = SnesAddress(romData.value.getWord(resetVectorLocation.pc).toUInt24())
val flags = VagueNumber(0x30u)
return showDisassembly(initialAddress, flags)
}
fun showDisassembly(initialAddress: Address, flags: VagueNumber): HtmlNode? {
fun showDisassembly(initialAddress: SnesAddress, flags: VagueNumber): HtmlNode? {
val rom = romData.value
val initialState = State(data = rom, address = initialAddress, flags = flags)
@ -66,7 +66,7 @@ object Service {
}
}
fun updateMetadata(address: Address, field: KMutableProperty1<MetadataLine, String?>, value: String) {
fun updateMetadata(address: SnesAddress, field: KMutableProperty1<MetadataLine, String?>, value: String) {
if (value.isEmpty()) {
if (address in metadata) {
doUpdateMetadata(address, field, null)
@ -76,7 +76,7 @@ object Service {
}
}
private fun doUpdateMetadata(address: Address, field: KMutableProperty1<MetadataLine, String?>, value: String?) {
private fun doUpdateMetadata(address: SnesAddress, field: KMutableProperty1<MetadataLine, String?>, value: String?) {
val line = metadata.getOrCreate(address)
field.set(line, value)

View File

@ -3,7 +3,7 @@ package com.smallhacker.disbrowser.asm
class Disassembly(lines: List<CodeUnit>) : Iterable<CodeUnit> {
override fun iterator() = lineList.iterator() as Iterator<CodeUnit>
private val knownAddresses = HashSet<Address>()
private val knownAddresses = HashSet<SnesAddress>()
private val lineList = ArrayList<CodeUnit>()
init {
@ -16,5 +16,5 @@ class Disassembly(lines: List<CodeUnit>) : Iterable<CodeUnit> {
}
}
operator fun contains(address: Address) = address in knownAddresses
operator fun contains(address: SnesAddress) = address in knownAddresses
}

View File

@ -3,10 +3,10 @@ package com.smallhacker.disbrowser.asm
import com.smallhacker.disbrowser.util.*
interface CodeUnit {
val address: Address?
val relativeAddress: Address
val presentedAddress: Address
val nextPresentedAddress: Address
val address: SnesAddress?
val relativeAddress: SnesAddress
val presentedAddress: SnesAddress
val nextPresentedAddress: SnesAddress
val linkedState: State?
val preState: State?
@ -22,6 +22,11 @@ interface CodeUnit {
val suffix = lengthSuffix ?: ""
return "$mnemonic$suffix"
}
fun printAlternativeOpcodeAndSuffix(): String? {
val mnemonic = opcode.mnemonic.alternativeName ?: return null
val suffix = lengthSuffix ?: ""
return "$mnemonic$suffix"
}
fun printOperands() = opcode.mode.print(this)
fun bytesToString(): String {
@ -58,22 +63,22 @@ interface CodeUnit {
class DataBlock(
override val opcode: Opcode,
override val bytes: RomData,
override val presentedAddress: Address,
override val relativeAddress: Address,
override val presentedAddress: SnesAddress,
override val relativeAddress: SnesAddress,
override val linkedState: State?
) : CodeUnit {
override val nextPresentedAddress: Address
override val nextPresentedAddress: SnesAddress
get() = presentedAddress + operandLength.toInt()
override val operandLength get() = bytes.size
override val address: Address? = null
override val address: SnesAddress? = null
override val preState: State? = null
override val postState: State? = null
override val lengthSuffix: String? = null
}
class Instruction(override val bytes: RomData, override val opcode: Opcode, override val preState: State) : CodeUnit {
override val address: Address get() = preState.address
override val address: SnesAddress get() = preState.address
override val relativeAddress get() = address
override val presentedAddress get() = address
override val nextPresentedAddress get() = postState.address
@ -105,18 +110,18 @@ class Instruction(override val bytes: RomData, override val opcode: Opcode, over
override val operandLength
get() = opcode.mode.operandLength(preState)
private fun link(): Address? {
private fun link(): SnesAddress? {
if (!opcode.link) {
return null
}
return when (opcode.mode) {
Mode.ABSOLUTE -> relativeAddress.withinBank(word)
Mode.ABSOLUTE_LONG -> Address(long)
Mode.ABSOLUTE_LONG -> SnesAddress(long)
Mode.RELATIVE -> relativeAddress + 2 + signedByte.toInt()
Mode.RELATIVE_LONG -> relativeAddress + 3 + signedWord.toInt()
Mode.DATA_WORD -> relativeAddress.withinBank(word)
Mode.DATA_LONG -> Address(long)
Mode.DATA_LONG -> SnesAddress(long)
else -> null
}
}

View File

@ -7,36 +7,34 @@ import com.smallhacker.disbrowser.util.toUInt24
import java.util.*
class Metadata {
private val lines: MutableMap<Address, MetadataLine>
@JsonProperty
private val code: TreeMap<SnesAddress, MetadataLine>
constructor() {
this.lines = HashMap()
this.code = TreeMap()
}
@JsonCreator
private constructor(@JsonProperty lines: Map<Address, MetadataLine>) {
this.lines = HashMap(lines)
private constructor(@JsonProperty code: Map<SnesAddress, MetadataLine>) {
this.code = TreeMap(code)
}
@JsonValue
private fun serialize() = TreeMap(lines)
operator fun set(address: Address, line: MetadataLine?): Metadata {
operator fun set(address: SnesAddress, line: MetadataLine?): Metadata {
if (line == null) {
lines.remove(address)
code.remove(address)
} else {
lines[address] = line
code[address] = line
}
return this
}
operator fun get(address: Address): MetadataLine? {
return lines[address]
operator fun get(address: SnesAddress): MetadataLine? {
return code[address]
}
operator fun contains(address: Address) = lines[address] != null
operator fun contains(address: SnesAddress) = code[address] != null
fun getOrCreate(address: Address): MetadataLine {
fun getOrCreate(address: SnesAddress): MetadataLine {
val line = this[address]
if (line != null) {
return line
@ -60,17 +58,17 @@ object NonReturningRoutine : InstructionFlag {
}
class JmpIndirectLongInterleavedTable @JsonCreator constructor(
@field:JsonProperty @JsonProperty private val start: Address,
@field:JsonProperty @JsonProperty private val start: SnesAddress,
@field:JsonProperty @JsonProperty private val entries: Int
) : InstructionFlag {
private val uEntries get() = entries.toUInt()
fun readTable(data: RomData): Sequence<Address> {
fun readTable(data: RomData): Sequence<SnesAddress> {
return (0u until uEntries)
.asSequence()
.map { it + start.pc }
.map { pc -> joinBytes(data[pc], data[pc + uEntries], data[pc + uEntries + uEntries]).toUInt24() }
.map { Address(it) }
.map { SnesAddress(it) }
}
fun generateCode(jumpInstruction: Instruction): Sequence<DataBlock> {
@ -92,7 +90,7 @@ class JmpIndirectLongInterleavedTable @JsonCreator constructor(
jumpInstruction.postState.address + offset.toInt(),
jumpInstruction.relativeAddress,
jumpInstruction.opcode.mutate(jumpInstruction)
.mutateAddress { Address(target) }
.mutateAddress { SnesAddress(target) }
.withOrigin(jumpInstruction)
)
// Instruction(
@ -110,13 +108,13 @@ class JslTableRoutine @JsonCreator constructor(
@field:JsonProperty @JsonProperty private val entries: Int
) : InstructionFlag {
fun readTable(postJsr: State): Sequence<Address> {
fun readTable(postJsr: State): Sequence<SnesAddress> {
val data = postJsr.data
return (0u until entries.toUInt())
.asSequence()
.map { postJsr.address.pc + (it * 3u) }
.map { pc -> joinBytes(data[pc], data[pc + 1u], data[pc + 2u]).toUInt24() }
.map { Address(it) }
.map { SnesAddress(it) }
}
override fun toString() = "JslTableRoutine($entries)"

View File

@ -8,8 +8,9 @@ data class MetadataLine(
var label: String? = null,
var comment: String? = null,
var preComment: String? = null,
var length: Int? = null,
val flags: MutableList<InstructionFlag> = ArrayList()
) {
@JsonIgnore
fun isEmpty() = (label == null) && (comment == null) && (preComment == null) && (flags.isEmpty())
fun isEmpty() = (label == null) && (comment == null) && (preComment == null) && (length == 0) && (flags.isEmpty())
}

View File

@ -0,0 +1,13 @@
package com.smallhacker.disbrowser.asm
import com.fasterxml.jackson.annotation.JsonIgnore
import com.fasterxml.jackson.annotation.JsonInclude
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
data class MetadataRam(
var label: String? = null,
var length: Int?
) {
@JsonIgnore
fun isEmpty() = (label == null) && (length == null)
}

View File

@ -1,7 +1,7 @@
package com.smallhacker.disbrowser.asm
enum class Mnemonic(private val nameOverride: String? = null) {
ADC, AND, ASL, BCC, BCS, BEQ, BIT, BMI, BNE, BPL, BRA,
enum class Mnemonic(private val nameOverride: String? = null, val alternativeName: String? = null) {
ADC, AND, ASL, BCC(alternativeName = "BLT"), BCS(alternativeName = "BGE"), BEQ, BIT, BMI, BNE, BPL, BRA,
BRK, BRL, BVC, BVS, CLC, CLD, CLI, CLV, CMP, COP, CPX,
CPY, DEC, DEX, DEY, EOR, INC, INX, INY, JMP, JML, JSL,
JSR, LDA, LDX, LDY, LSR, MVN, MVP, NOP, ORA, PEA, PEI,
@ -11,7 +11,7 @@ enum class Mnemonic(private val nameOverride: String? = null) {
TCS, TDC, TRB, TSB, TSC, TSX, TXA, TXS, TXY, TYA, TYX,
WAI, WDM, XBA, XCE,
DB(".db"), DW(".dw"), DL(".dl");
DB(nameOverride = ".db"), DW(nameOverride = ".dw"), DL(nameOverride = ".dl");
val displayName get() = nameOverride ?: name
}

View File

@ -1,25 +1,25 @@
package com.smallhacker.disbrowser.asm
class Segment (val start: Address, val end: SegmentEnd, val instructions: List<Instruction>)
class Segment (val start: SnesAddress, val end: SegmentEnd, val instructions: List<Instruction>)
class SegmentEnd(val address: Address, val local: List<State> = emptyList(), val remote: List<State> = emptyList(), val returnAddress: Address? = null, val returning: Boolean = false)
class SegmentEnd(val address: SnesAddress, val local: List<State> = emptyList(), val remote: List<State> = emptyList(), val returnAddress: SnesAddress? = null, val returning: Boolean = false)
fun stoppingSegmentEnd(address: Address)
fun stoppingSegmentEnd(address: SnesAddress)
= SegmentEnd(address)
fun branchingSegmentEnd(address: Address, continueState: State, branchState: State)
fun branchingSegmentEnd(address: SnesAddress, continueState: State, branchState: State)
= SegmentEnd(address, local = listOf(continueState, branchState))
fun alwaysBranchingSegmentEnd(address: Address, branchState: State)
fun alwaysBranchingSegmentEnd(address: SnesAddress, branchState: State)
= SegmentEnd(address, local = listOf(branchState))
fun jumpSegmentEnd(address: Address, targetState: State)
fun jumpSegmentEnd(address: SnesAddress, targetState: State)
= SegmentEnd(address, remote = listOf(targetState))
fun subroutineSegmentEnd(address: Address, targetState: State, returnAddress: Address)
fun subroutineSegmentEnd(address: SnesAddress, targetState: State, returnAddress: SnesAddress)
= SegmentEnd(address, remote = listOf(targetState), returnAddress = returnAddress)
fun returnSegmentEnd(address: Address)
fun returnSegmentEnd(address: SnesAddress)
= SegmentEnd(address, returning = true)
fun continuationSegmentEnd(state: State)

View File

@ -1,19 +1,16 @@
package com.smallhacker.disbrowser.asm
import com.fasterxml.jackson.annotation.JsonCreator
import com.fasterxml.jackson.annotation.JsonIgnore
import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.annotation.JsonValue
import com.smallhacker.disbrowser.util.UInt24
import com.smallhacker.disbrowser.util.toUInt24
import com.smallhacker.disbrowser.util.tryParseInt
data class Address(val value: UInt24) : Comparable<Address> {
val rom = (value and 0x8000u).toUInt() == 0u
data class SnesAddress(val value: UInt24) : Comparable<SnesAddress> {
val pc = snesToPc(value)
operator fun plus(offset: Int) = Address(value + offset)
operator fun minus(offset: Int) = Address(value - offset)
operator fun plus(offset: Int) = SnesAddress(value + offset)
operator fun minus(offset: Int) = SnesAddress(value - offset)
operator fun inc() = plus(1)
operator fun dec() = minus(1)
@ -22,21 +19,21 @@ data class Address(val value: UInt24) : Comparable<Address> {
@JsonValue
fun toSimpleString(): String = String.format("%06x", value.toInt())
fun withinBank(value: UShort): Address = Address((this.value and 0xFF_0000u) or value.toUInt24())
fun withinBank(value: UShort): SnesAddress = SnesAddress((this.value and 0xFF_0000u) or value.toUInt24())
override fun compareTo(other: Address) = value.toUInt().compareTo(other.value.toUInt())
override fun compareTo(other: SnesAddress) = value.toUInt().compareTo(other.value.toUInt())
infix fun distanceTo(other: Address) = Math.abs(value.toInt() - other.value.toInt()).toUInt()
infix fun distanceTo(other: SnesAddress) = Math.abs(value.toInt() - other.value.toInt()).toUInt()
companion object {
@JvmStatic
@JsonCreator
fun parse(address: String): Address? = tryParseInt(address, 16)
?.let { Address(it.toUInt24()) }
fun parse(address: String): SnesAddress? = tryParseInt(address, 16)
?.let { SnesAddress(it.toUInt24()) }
}
}
fun address(snesAddress: Int) = Address(snesAddress.toUInt24())
fun address(snesAddress: Int) = SnesAddress(snesAddress.toUInt24())
private fun snesToPc(value: UInt24): UInt {
// TODO: This is incredibly oversimplified. Anything that isn't a small LoROM will crash and burn

View File

@ -2,10 +2,14 @@ package com.smallhacker.disbrowser.asm
import com.smallhacker.disbrowser.ImmStack
import com.smallhacker.disbrowser.immStack
import com.smallhacker.disbrowser.util.toUInt24
data class State(val origin: Instruction? = null, val data: RomData, val address: Address, val flags: VagueNumber = VagueNumber(), val stack: ImmStack<VagueNumber> = immStack()) {
data class State(val origin: Instruction? = null, val data: RomData, val address: SnesAddress, val flags: VagueNumber = VagueNumber(), val stack: ImmStack<VagueNumber> = immStack()) {
val m: Boolean? get() = flags.getBoolean(0x20u)
val x: Boolean? get() = flags.getBoolean(0x10u)
val db: UByte? get() = pb // TODO
val dp: UShort? get() = 0x7e00u // TODO
val pb: UByte get() = (address.value shr 16).toUByte()
val mWidth: UInt? get() = toWidth(m)
val xWidth: UInt? get() = toWidth(x)
@ -16,7 +20,7 @@ data class State(val origin: Instruction? = null, val data: RomData, val address
private fun withFlags(flags: VagueNumber) = copy(flags = flags)
fun mutateAddress(mutator: (Address) -> Address) = copy(address = mutator(address))
fun mutateAddress(mutator: (SnesAddress) -> SnesAddress) = copy(address = mutator(address))
fun withOrigin(instruction: Instruction?) = copy(origin = instruction)
fun push(value: UInt) = push(VagueNumber(value))
@ -52,6 +56,16 @@ data class State(val origin: Instruction? = null, val data: RomData, val address
return "A:${printSize(m)} XY:${printSize(x)} S:" + stackToString()
}
fun resolve(directPage: UByte) = dp?.let { dp ->
val ptr = (dp.toUInt24() shl 8) or (directPage.toUInt24())
SnesAddress(ptr)
}
fun resolve(absolute: UShort)= db?.let { db ->
val ptr = (db.toUInt24() shl 16) or (absolute.toUInt24())
SnesAddress(ptr)
}
private fun stackToString(): String {
return stack.reversed().asSequence()
.map { stackByteToString(it) }

View File

@ -6,7 +6,7 @@ import kotlin.collections.ArrayList
object Disassembler {
fun disassemble(initialState: State, metadata: Metadata, global: Boolean): Disassembly {
val seen = HashSet<Address>()
val seen = HashSet<SnesAddress>()
val queue = ArrayDeque<State>()
fun tryAdd(state: State) {
@ -79,7 +79,7 @@ object Disassembler {
}
fun disassembleSegments(initialState: State): List<Segment> {
val mapping = HashMap<Address, Segment>()
val mapping = HashMap<SnesAddress, Segment>()
val queue = ArrayDeque<State>()
val segments = ArrayList<Segment>()
@ -119,12 +119,12 @@ object Disassembler {
return segments
}
fun disassembleSegment(initialState: State, mapping: MutableMap<Address, Segment>): Segment {
fun disassembleSegment(initialState: State, mapping: MutableMap<SnesAddress, Segment>): Segment {
val instructions = ArrayList<Instruction>()
var lastState = initialState
val queue = ArrayDeque<State>()
val seen = HashSet<Address>()
val seen = HashSet<SnesAddress>()
fun finalize(segment: Segment): Segment {
instructions.forEach {

View File

@ -2,7 +2,7 @@ package com.smallhacker.disbrowser.resource
import com.smallhacker.disbrowser.HtmlNode
import com.smallhacker.disbrowser.Service
import com.smallhacker.disbrowser.asm.Address
import com.smallhacker.disbrowser.asm.SnesAddress
import com.smallhacker.disbrowser.asm.VagueNumber
import java.nio.charset.StandardCharsets
import javax.ws.rs.GET
@ -30,7 +30,7 @@ class DisassemblyResource {
@Produces(MediaType.TEXT_HTML)
fun getIt(@PathParam("address") address: String, @PathParam("state") state: String): Response {
return handle {
Address.parse(address)?.let {
SnesAddress.parse(address)?.let {
val flags = parseState(state)
Service.showDisassembly(it, flags)
}

View File

@ -1,7 +1,7 @@
package com.smallhacker.disbrowser.resource
import com.smallhacker.disbrowser.Service
import com.smallhacker.disbrowser.asm.Address
import com.smallhacker.disbrowser.asm.SnesAddress
import com.smallhacker.disbrowser.asm.MetadataLine
import javax.ws.rs.Consumes
import javax.ws.rs.POST
@ -16,7 +16,7 @@ class RestResource {
@Path("{address}/{field}")
@Consumes(MediaType.TEXT_PLAIN)
fun getIt(@PathParam("address") address: String, @PathParam("field") fieldName: String, body: String): Response {
val parsedAddress = Address.parse(address) ?: return Response.status(400).build()
val parsedAddress = SnesAddress.parse(address) ?: return Response.status(400).build()
val field = when (fieldName) {
"preComment" -> MetadataLine::preComment
"comment" -> MetadataLine::comment

View File

@ -99,9 +99,12 @@ tr.line-active {
border: none;
background: none;
padding: 0;
width: 100%;
}
.field-comment {
width: 500px;
}
.opcode-info{
text-decoration: green underline dotted;
}