package com.htmlism import cats.implicits._ import java.io.PrintWriter object MatchOpcodes { def paddedBinary(n: Int, width: Int) = String.format(s"%${width}s", Integer.toBinaryString(n)).replace(" ", "0") def main(args: Array[String]): Unit = write(args(0))(doStuff) def generatedOpcodes: Map[Int, (Instruction, AddressingMode)] = (0 to 255) .map(n => n -> toOpcode(n)) .collect { case (n, Some(x)) => (n, x) } .toMap // format: off def injectedOpcodesRelative: Map[Int, (Instruction, AddressingMode)] = Map( 0x10 -> BPL, 0x30 -> BMI, 0x50 -> BVC, 0x70 -> BVS, 0x90 -> BCC, 0xB0 -> BCS, 0xD0 -> BNE, 0xF0 -> BEQ, ).view.mapValues(x => x -> Relative).toMap def injectedOpcodesImplied: Map[Int, (Instruction, AddressingMode)] = Map( 0x00 -> BRK, 0x20 -> JSR, 0x40 -> RTI, 0x60 -> RTS, 0x08 -> PHP, 0x28 -> PLP, 0x48 -> PHA, 0x68 -> PLA, 0x88 -> DEY, 0xA8 -> TAY, 0xC8 -> INY, 0xE8 -> INX, 0x18 -> CLC, 0x38 -> SEC, 0x58 -> CLI, 0x78 -> SEI, 0x98 -> TYA, 0xB8 -> CLV, 0xD8 -> CLD, 0xF8 -> SED, 0x8A -> TXA, 0x9A -> TXS, 0xAA -> TAX, 0xBA -> TSX, 0xCA -> DEX, 0xEA -> NOP ).view.mapValues(x => x -> Implied).toMap // format: on def doStuff(out: PrintWriter): Unit = { val lookup = generatedOpcodes ++ injectedOpcodesImplied ++ injectedOpcodesRelative out.print("") // print headers out.print("") out.print("") out.print("") for (r <- Seq(0x00, 0x20, 0x40, 0x60, 0x80, 0xA0, 0xC0, 0xE0)) { out.print("") // left header out.print(s"") for (f <- fancyColumns) { val fullInt = r + f lookup.get(fullInt) match { case Some((ints, mode)) => val hex = f"$fullInt%2X" out.print( s"""""" ) case None => out.print(s"") } } out.print("") } out.print("
") val fancyColumns = for { c <- 0 to 3 b <- 0 to 7 } yield b * 4 + c for (f <- fancyColumns) out.print(s"${paddedBinary(f, 8)}
${paddedBinary(r, 3)}$ints $mode
$hex
UNDEF
") out.print("") // print headers out.print("") out.print("") out.print("") for (r <- wideRows) { out.print("") // left header out.print(s"") for (c <- wideColumns) { val fullInt = (r << 5) + c lookup.get(fullInt) match { case Some((ints, mode)) => val hex = f"$fullInt%2X" out.print( s"""""" ) case None => out.print(s"") } } out.print("") } out.print("
") for (c <- wideColumns) out.print(s"${paddedBinary(c, 5)}
${paddedBinary(r, 3)}$ints $mode
$hex
UNDEF
") quartile(out, 0, lookup) quartile(out, 1, lookup) quartile(out, 2, lookup) quartile(out, 3, lookup) } def quartile(out: PrintWriter, n: Int, lookup: Map[Int, (Instruction, AddressingMode)]) = { out.print(s"

${paddedBinary(n, 2)}

") out.print("") // print headers out.print("") out.print("") out.print("") for (r <- rows) { out.print("") // left header out.print(s"") for (c <- columns) { val fullInt = (r << (3 + 2)) + (c << 2) + n lookup.get(fullInt) match { case Some((ints, mode)) => val hex = f"$fullInt%2X" out.print( s"""""" ) case None => out.print(s"") } } out.print("") } out.print("
") val columns = for { y <- 0 to 1 x <- 0 to 1 z <- 0 to 1 } yield (z << 2) + (x << 1) + y val rows = 0 to 7 for (c <- columns) out.print(s"${paddedBinary(c, 3)}
${paddedBinary(r, 3)}$ints $mode
$hex
UNDEF
") } def wideColumns: Seq[Int] = for { cc <- 0 to 3 y <- 0 to 1 xx <- 0 to 3 } yield (xx << 3) + (y << 2) + cc def wideRows: Seq[Int] = 0 to 7 private def write(file: String)(f: PrintWriter => Unit) = { val out = new PrintWriter(file) f(out) out.close() } def toOpcode(n: Int): Option[(Instruction, AddressingMode)] = { val BitPattern = ThreeBits >> ThreeBits >> TwoBits n match { case BitPattern((aaa, bbb), cc) => cc match { case 0 => c00(aaa, bbb).some case 1 => c01(aaa, bbb).some case 2 => c10(aaa, bbb).some case 3 => None } } } def c01(aaa: Int, bbb: Int): (Instruction, AddressingMode) = { val instruction = Seq(ORA, AND, EOR, ADC, STA, LDA, CMP, SBC)(aaa) val addressingMode = Seq(IndirectX, ZeroPage, Immediate, Absolute, IndirectY, ZeroPageX, AbsoluteY, AbsoluteX)(bbb) instruction -> addressingMode } def c10(aaa: Int, bbb: Int): (Instruction, AddressingMode) = { val instruction = Seq(ASL, ROL, LSR, ROR, STX, LDX, DEC, INC)(aaa) val addressingMode = Seq(Immediate, ZeroPage, Accumulator, Absolute, NoMode, ZeroPageX, NoMode, AbsoluteX)(bbb) instruction -> addressingMode } def c00(aaa: Int, bbb: Int): (Instruction, AddressingMode) = { val instruction = Seq(NoInstruction, BIT, JMP, JMP, STY, LDY, CPY, CPX)(aaa) val addressingMode = Seq(Immediate, ZeroPage, NoMode, Absolute, NoMode, ZeroPageX, NoMode, AbsoluteX)(bbb) instruction -> addressingMode } }