mirror of
https://github.com/felipecsl/6502Android.git
synced 2024-06-08 06:29:32 +00:00
Fix a few bugs
This commit is contained in:
parent
053d7b267d
commit
25cfd99dd2
|
@ -5,22 +5,22 @@ import android.emu6502.instructions.Opcodes
|
||||||
import java.util.regex.Pattern
|
import java.util.regex.Pattern
|
||||||
import kotlin.text.Regex
|
import kotlin.text.Regex
|
||||||
|
|
||||||
class Assembler(private var labels: Labels,
|
class Assembler(private var labels: Labels, private var memory: Memory,
|
||||||
private var memory: Memory,
|
|
||||||
private var symbols: Symbols) {
|
private var symbols: Symbols) {
|
||||||
|
|
||||||
private var defaultCodePC = 0
|
var codeLen = 0
|
||||||
private var codeLen = 0
|
val BOOTSTRAP_ADDRESS = 0x600
|
||||||
private var codeAssembledOK = false
|
var defaultCodePC = BOOTSTRAP_ADDRESS
|
||||||
private var BOOTSTRAP_ADDRESS = 0x600
|
|
||||||
|
|
||||||
fun assembleCode(lines: List<String>): Boolean {
|
fun assembleCode(lines: List<String>) {
|
||||||
lines.forEach { line ->
|
lines.forEachIndexed { i, line ->
|
||||||
if (!assembleLine(line)) {
|
if (!assembleLine(line)) {
|
||||||
return false
|
val str = line.replace("<", "<").replace(">", ">")
|
||||||
|
throw RuntimeException("**Syntax error line " + (i + 1) + ": " + str + "**")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
// set a null byte at the end of the code
|
||||||
|
memory.set(defaultCodePC, 0x00)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun assembleLine(line: String): Boolean {
|
private fun assembleLine(line: String): Boolean {
|
||||||
|
@ -48,11 +48,11 @@ class Assembler(private var labels: Labels,
|
||||||
|
|
||||||
command = command.toUpperCase()
|
command = command.toUpperCase()
|
||||||
|
|
||||||
if (input.matches("^\\*\\s*=\\s*\$?[0-9a-f]*$".toRegex())) {
|
if (input.matches("^\\*\\s*=\\s*\\$?[0-9a-f]*$".toRegex())) {
|
||||||
// equ spotted
|
// equ spotted
|
||||||
param = input.replace("^\\s*\\*\\s*=\\s*".toRegex(), "")
|
param = input.replace("^\\s*\\*\\s*=\\s*".toRegex(), "")
|
||||||
if (param[0].equals("$")) {
|
if (param[0].equals("$")) {
|
||||||
param = param.replace("^\$".toRegex(), "")
|
param = param.replace("^\\$".toRegex(), "")
|
||||||
addr = Integer.parseInt(param, 16)
|
addr = Integer.parseInt(param, 16)
|
||||||
} else {
|
} else {
|
||||||
addr = Integer.parseInt(param, 10)
|
addr = Integer.parseInt(param, 10)
|
||||||
|
@ -132,7 +132,7 @@ class Assembler(private var labels: Labels,
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkAbsolute(param: String, opcode: Int): Boolean {
|
private fun checkAbsolute(param: String, opcode: Int): Boolean {
|
||||||
if (checkWordOperand(param, opcode, "^([\\w\$]+)$")) {
|
if (checkWordOperand(param, opcode, "^([\\w\\$]+)$")) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,28 +199,28 @@ class Assembler(private var labels: Labels,
|
||||||
if (opcode == 0xff) {
|
if (opcode == 0xff) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return checkByteOperand(param, opcode, "^\\(([\\w\$]+)\\),Y$")
|
return checkByteOperand(param, opcode, "^\\(([\\w\\$]+)\\),Y$")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkIndirectX(param: String, opcode: Int): Boolean {
|
private fun checkIndirectX(param: String, opcode: Int): Boolean {
|
||||||
if (opcode == 0xff) {
|
if (opcode == 0xff) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return checkByteOperand(param, opcode, "^\\(([\\w\$]+)\\),X$")
|
return checkByteOperand(param, opcode, "^\\(([\\w\\$]+)\\),X$")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkIndirect(param: String, opcode: Int): Boolean {
|
private fun checkIndirect(param: String, opcode: Int): Boolean {
|
||||||
if (opcode == 0xff) {
|
if (opcode == 0xff) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return checkWordOperand(param, opcode, "^\\(([\\w\$]+)\\)$")
|
return checkWordOperand(param, opcode, "^\\(([\\w\\$]+)\\)$")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkAbsoluteY(param: String, opcode: Int): Boolean {
|
private fun checkAbsoluteY(param: String, opcode: Int): Boolean {
|
||||||
if (opcode == 0xff) {
|
if (opcode == 0xff) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return checkWordOperand(param, opcode, "^([\\w\$]+),Y$") ||
|
return checkWordOperand(param, opcode, "^([\\w\\$]+),Y$") ||
|
||||||
checkLabel(param, opcode, "^\\w+,Y$".toRegex())
|
checkLabel(param, opcode, "^\\w+,Y$".toRegex())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,7 +228,7 @@ class Assembler(private var labels: Labels,
|
||||||
if (opcode == 0xff) {
|
if (opcode == 0xff) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return checkWordOperand(param, opcode, "^([\\w\$]+),X$") ||
|
return checkWordOperand(param, opcode, "^([\\w\\$]+),X$") ||
|
||||||
checkLabel(param, opcode, "^\\w+,X$".toRegex())
|
checkLabel(param, opcode, "^\\w+,X$".toRegex())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,14 +236,14 @@ class Assembler(private var labels: Labels,
|
||||||
if (opcode == 0xff) {
|
if (opcode == 0xff) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return checkByteOperand(param, opcode, "^([\\w\$]+),Y")
|
return checkByteOperand(param, opcode, "^([\\w\\$]+),Y")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkZeroPageX(param: String, opcode: Int): Boolean {
|
private fun checkZeroPageX(param: String, opcode: Int): Boolean {
|
||||||
if (opcode == 0xff) {
|
if (opcode == 0xff) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return checkByteOperand(param, opcode, "^([\\w\$]+),X")
|
return checkByteOperand(param, opcode, "^([\\w\\$]+),X")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkZeroPage(param: String, opcode: Int): Boolean {
|
private fun checkZeroPage(param: String, opcode: Int): Boolean {
|
||||||
|
@ -257,7 +257,7 @@ class Assembler(private var labels: Labels,
|
||||||
if (opcode == 0xff) {
|
if (opcode == 0xff) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if (checkByteOperand(param, opcode, "^#([\\w\$]+)$")) {
|
if (checkByteOperand(param, opcode, "^#([\\w\\$]+)$")) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,13 +300,13 @@ class Assembler(private var labels: Labels,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is it a hexadecimal operand?
|
// Is it a hexadecimal operand?
|
||||||
var pattern = Pattern.compile("^\$([0-9a-f]{1,2})$")
|
var pattern = Pattern.compile("^\\$([0-9a-f]{1,2})$", Pattern.CASE_INSENSITIVE)
|
||||||
var matcher = pattern.matcher(parameter)
|
var matcher = pattern.matcher(parameter)
|
||||||
if (matcher.find()) {
|
if (matcher.find()) {
|
||||||
value = Integer.parseInt(matcher.group(1), 16)
|
value = Integer.parseInt(matcher.group(1), 16)
|
||||||
} else {
|
} else {
|
||||||
// Is it a decimal operand?
|
// Is it a decimal operand?
|
||||||
pattern = Pattern.compile("^([0-9]{1,3})$")
|
pattern = Pattern.compile("^([0-9]{1,3})$", Pattern.CASE_INSENSITIVE)
|
||||||
matcher = pattern.matcher(parameter)
|
matcher = pattern.matcher(parameter)
|
||||||
if (matcher.find()) {
|
if (matcher.find()) {
|
||||||
value = Integer.parseInt(matcher.group(1), 10)
|
value = Integer.parseInt(matcher.group(1), 10)
|
||||||
|
@ -332,13 +332,13 @@ class Assembler(private var labels: Labels,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is it a hexadecimal operand?
|
// Is it a hexadecimal operand?
|
||||||
var pattern = Pattern.compile("^\$([0-9a-f]{3,4})$")
|
var pattern = Pattern.compile("^\\$([0-9a-f]{3,4})$", Pattern.CASE_INSENSITIVE)
|
||||||
var matcher = pattern.matcher(parameter)
|
var matcher = pattern.matcher(parameter)
|
||||||
if (matcher.find()) {
|
if (matcher.find()) {
|
||||||
value = Integer.parseInt(matcher.group(1), 16)
|
value = Integer.parseInt(matcher.group(1), 16)
|
||||||
} else {
|
} else {
|
||||||
// Is it a decimal operand?
|
// Is it a decimal operand?
|
||||||
pattern = Pattern.compile("^([0-9]{1,5})$")
|
pattern = Pattern.compile("^([0-9]{1,5})$", Pattern.CASE_INSENSITIVE)
|
||||||
matcher = pattern.matcher(parameter)
|
matcher = pattern.matcher(parameter)
|
||||||
if (matcher.find()) {
|
if (matcher.find()) {
|
||||||
value = Integer.parseInt(matcher.group(1), 10)
|
value = Integer.parseInt(matcher.group(1), 10)
|
||||||
|
|
|
@ -90,7 +90,7 @@ class CPU(private val memory: Memory) {
|
||||||
|
|
||||||
if (PC == 0 || !isRunning) {
|
if (PC == 0 || !isRunning) {
|
||||||
stop()
|
stop()
|
||||||
Log.i(TAG, "Program end at PC=$" + (PC - 1))
|
Log.i(TAG, "Program end at PC=$" + (PC - 1).toHexString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ class CPU(private val memory: Memory) {
|
||||||
val function = target.method
|
val function = target.method
|
||||||
target.operation.function()
|
target.operation.function()
|
||||||
} else {
|
} else {
|
||||||
Log.e(TAG, "Address $" + PC + " - unknown opcode")
|
Log.e(TAG, "Address $" + PC.toHexString() + " - unknown opcode " + instruction.toHexString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,4 +137,8 @@ class CPU(private val memory: Memory) {
|
||||||
fun popWord(): Int {
|
fun popWord(): Int {
|
||||||
return popByte() + popByte().shl(8)
|
return popByte() + popByte().shl(8)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Int.toHexString(): String {
|
||||||
|
return Integer.toHexString(this)
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -37,7 +37,10 @@ public class MainActivity : AppCompatActivity() {
|
||||||
|
|
||||||
fabRun.setOnClickListener {
|
fabRun.setOnClickListener {
|
||||||
emulator.assembler.assembleCode(txtInstructions.getText().toString().splitBy("\n"))
|
emulator.assembler.assembleCode(txtInstructions.getText().toString().splitBy("\n"))
|
||||||
Toast.makeText(fabRun.getContext(), "Code assembled", Toast.LENGTH_SHORT).show()
|
Toast.makeText(fabRun.getContext(),
|
||||||
|
"Code assembled successfully, " + emulator.assembler.codeLen + " bytes.",
|
||||||
|
Toast.LENGTH_SHORT).show()
|
||||||
|
emulator.cpu.execute()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user