mirror of
https://github.com/irmen/ksim65.git
synced 2024-06-01 21:41:31 +00:00
Compare commits
70 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
3f28ef6cad | ||
|
0fda62370e | ||
|
6812ab4b09 | ||
|
67c70abb41 | ||
|
5cc3f8fddd | ||
|
87c7aad49a | ||
|
1ca771840b | ||
|
b17b72b6b5 | ||
|
61bb920776 | ||
|
6c73852b5e | ||
|
6dc433417d | ||
|
f8b3213b41 | ||
|
b2b4b0ab83 | ||
|
1cbb006577 | ||
|
b8691db38e | ||
|
d1d433c3a6 | ||
|
3925c80258 | ||
|
c2d6954327 | ||
|
0670a85f88 | ||
|
7522d3cb3b | ||
|
99942748f9 | ||
|
323098f645 | ||
|
d9f1a76c47 | ||
|
95733df9af | ||
|
ec9b80433f | ||
|
cd00191dcf | ||
|
31962d083f | ||
|
1e27e5bae4 | ||
|
5667c00d85 | ||
|
35cbe4e3ca | ||
|
99d8f5cd97 | ||
|
be8716c4a4 | ||
|
deaf79fcc2 | ||
|
c619ddabf1 | ||
|
d5f533c300 | ||
|
62e2f1663a | ||
|
57e9bacef9 | ||
|
2ad73432f6 | ||
|
1123ddf482 | ||
|
08880c5d77 | ||
|
3888b142d2 | ||
|
a8874fd05a | ||
|
5d9c54eaf6 | ||
|
ffbd5050d6 | ||
|
0dd97ba41c | ||
|
f3f1abab88 | ||
|
cc1fb9716b | ||
|
6db5e792d6 | ||
|
606a587bb5 | ||
|
3f86d5185e | ||
|
c327c59c8b | ||
|
30351b44ba | ||
|
f61242a17b | ||
|
d940b9d136 | ||
|
30b164bb6d | ||
|
de60698349 | ||
|
7f3dd9c95d | ||
|
b7ebf6c922 | ||
|
7fb8feb676 | ||
|
b3334a23b9 | ||
|
8b84a7c653 | ||
|
43b2bec5da | ||
|
81ae12b809 | ||
|
b4a6709646 | ||
|
92e0c13c70 | ||
|
5deeb50c49 | ||
|
9cba058fd7 | ||
|
5ef6965c82 | ||
|
050c1d4478 | ||
|
8850638f11 |
|
@ -12,6 +12,9 @@
|
|||
<MarkdownNavigatorCodeStyleSettings>
|
||||
<option name="RIGHT_MARGIN" value="80" />
|
||||
</MarkdownNavigatorCodeStyleSettings>
|
||||
<codeStyleSettings language="Markdown">
|
||||
<option name="RIGHT_MARGIN" value="80" />
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="kotlin">
|
||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||
<option name="KEEP_LINE_BREAKS" value="false" />
|
||||
|
|
6
.idea/compiler.xml
Normal file
6
.idea/compiler.xml
Normal file
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<bytecodeTargetLevel target="11" />
|
||||
</component>
|
||||
</project>
|
|
@ -15,8 +15,6 @@
|
|||
<option value="$PROJECT_DIR$" />
|
||||
</set>
|
||||
</option>
|
||||
<option name="useAutoImport" value="true" />
|
||||
<option name="useQualifiedModuleNames" value="true" />
|
||||
</GradleProjectSettings>
|
||||
</option>
|
||||
</component>
|
||||
|
|
|
@ -26,5 +26,10 @@
|
|||
<option name="name" value="maven" />
|
||||
<option name="url" value="https://jitpack.io" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="MavenRepo" />
|
||||
<option name="name" value="MavenRepo" />
|
||||
<option name="url" value="https://repo.maven.apache.org/maven2/" />
|
||||
</remote-repository>
|
||||
</component>
|
||||
</project>
|
6
.idea/kotlinc.xml
Normal file
6
.idea/kotlinc.xml
Normal file
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="KotlinJpsPluginSettings">
|
||||
<option name="version" value="1.9.10" />
|
||||
</component>
|
||||
</project>
|
|
@ -1,2 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4" />
|
|
@ -12,7 +12,7 @@
|
|||
<component name="MarkdownProjectSettings">
|
||||
<PreviewSettings splitEditorLayout="SPLIT" splitEditorPreview="PREVIEW" useGrayscaleRendering="false" zoomFactor="1.0" maxImageWidth="0" synchronizePreviewPosition="true" highlightPreviewType="LINE" highlightFadeOut="5" highlightOnTyping="true" synchronizeSourcePosition="true" verticallyAlignSourceAndPreviewSyncPosition="true" showSearchHighlightsInPreview="true" showSelectionInPreview="true" lastLayoutSetsDefault="false">
|
||||
<PanelProvider>
|
||||
<provider providerId="com.vladsch.idea.multimarkdown.editor.swing.html.panel" providerName="Default - Swing" />
|
||||
<provider providerId="com.vladsch.md.nav.editor.javafx.html.panel" providerName="JavaFX WebView" />
|
||||
</PanelProvider>
|
||||
</PreviewSettings>
|
||||
<ParserSettings gitHubSyntaxChange="false" correctedInvalidSettings="false" emojiShortcuts="1" emojiImages="0">
|
||||
|
@ -36,7 +36,7 @@
|
|||
</ParserSettings>
|
||||
<HtmlSettings headerTopEnabled="false" headerBottomEnabled="false" bodyTopEnabled="false" bodyBottomEnabled="false" addPageHeader="false" imageUriSerials="false" addDocTypeHtml="true" noParaTags="false" plantUmlConversion="0">
|
||||
<GeneratorProvider>
|
||||
<provider providerId="com.vladsch.idea.multimarkdown.editor.text.html.generator" providerName="Unmodified HTML Generator" />
|
||||
<provider providerId="com.vladsch.md.nav.editor.javafx.html.generator" providerName="JavaFx HTML Generator" />
|
||||
</GeneratorProvider>
|
||||
<headerTop />
|
||||
<headerBottom />
|
||||
|
@ -45,9 +45,11 @@
|
|||
</HtmlSettings>
|
||||
<CssSettings previewScheme="UI_SCHEME" cssUri="" isCssUriEnabled="false" isCssUriSerial="true" isCssTextEnabled="false" isDynamicPageWidth="true">
|
||||
<StylesheetProvider>
|
||||
<provider providerId="com.vladsch.idea.multimarkdown.editor.text.html.css" providerName="No Stylesheet" />
|
||||
<provider providerId="com.vladsch.md.nav.editor.javafx.html.css" providerName="Default JavaFx Stylesheet" />
|
||||
</StylesheetProvider>
|
||||
<ScriptProviders />
|
||||
<ScriptProviders>
|
||||
<provider providerId="com.vladsch.md.nav.editor.hljs.html.script" providerName="HighlightJS Script" />
|
||||
</ScriptProviders>
|
||||
<cssText />
|
||||
<cssUriHistory />
|
||||
</CssSettings>
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="FrameworkDetectionExcludesConfiguration">
|
||||
<file type="web" url="file://$PROJECT_DIR$" />
|
||||
</component>
|
||||
<component name="JavaScriptSettings">
|
||||
<option name="languageLevel" value="ES6" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" project-jdk-name="openjdk-11" project-jdk-type="JavaSDK" />
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="openjdk-11" project-jdk-type="JavaSDK" />
|
||||
</project>
|
10
.travis.yml
10
.travis.yml
|
@ -1,10 +0,0 @@
|
|||
language: java
|
||||
sudo: false
|
||||
# jdk: openjdk8
|
||||
# dist: xenial
|
||||
|
||||
before_install:
|
||||
- chmod +x gradlew
|
||||
|
||||
script:
|
||||
- gradle test
|
76
README.md
76
README.md
|
@ -1,34 +1,49 @@
|
|||
[![saythanks](https://img.shields.io/badge/say-thanks-ff69b4.svg)](https://saythanks.io/to/irmen)
|
||||
[![Build Status](https://travis-ci.org/irmen/ksim65.svg?branch=master)](https://travis-ci.org/irmen/ksim65)
|
||||
|
||||
# KSim65 - Kotlin/JVM 6502/65C02 microprocessor simulator
|
||||
|
||||
*Written by Irmen de Jong (irmen@razorvine.net)*
|
||||
|
||||
*Software license: MIT, see file LICENSE*
|
||||
|
||||
|
||||
![6502](https://upload.wikimedia.org/wikipedia/commons/thumb/4/43/KL_MOS_6502.jpg/320px-KL_MOS_6502.jpg)
|
||||
|
||||
This is a Kotlin/JVM library that simulates the 8-bit 6502 and 65C02 microprocessors,
|
||||
which became very popular in the the early 1980's.
|
||||
which became very popular in the the early 1980's.
|
||||
|
||||
Properties of this simulator:
|
||||
|
||||
- Written in Kotlin. It is low-level code, but hopefully still readable :-)
|
||||
- Designed to simulate various hardware components (bus, cpu, memory, i/o controllers)
|
||||
- IRQ and NMI simulation
|
||||
- Aims to simulate correct instruction cycle timing, but is not 100% cycle exact for simplicity
|
||||
- Aims to implements all 6502 and 65c02 instructions, including the 'illegal' 6502 instructions (not yet done)
|
||||
- correct BCD mode for adc/sbc instructions on both cpu types
|
||||
- written in Kotlin. It is low-level code, but hopefully still readable :-)
|
||||
- simulates various hardware components (bus, cpu, memory, i/o controllers)
|
||||
- IRQ and NMI
|
||||
- instruction cycle times are simulated (however the *internal* cpu behavior is not cycle-exact for simplicity reasons)
|
||||
- has all 6502 and 65c02 instructions, including many of the 'illegal' 6502 instructions (goal is 100% eventually)
|
||||
- correct BCD mode for adc/sbc instructions on both cpu types
|
||||
- passes several extensive unit test suites that verify instruction and cpu flags behavior
|
||||
- provide a few virtual example machines, one of which is a Commodore-64
|
||||
- simple debugging machine monitor, which basic disassembler and assembler functions
|
||||
- provide a few virtual example machines, one of which is a fairly capable Commodore-64
|
||||
|
||||
|
||||
## Documentation
|
||||
|
||||
Still to be written. For now, use the source ;-)
|
||||
|
||||
## Using it as a library in your own project
|
||||
|
||||
**TODO move to another repository for published packages.**
|
||||
|
||||
You can simply add it as a dependency to your project.
|
||||
For Maven:
|
||||
|
||||
<dependency>
|
||||
<groupId>net.razorvine</groupId>
|
||||
<artifactId>ksim65</artifactId>
|
||||
<version>1.10</version>
|
||||
<type>pom</type>
|
||||
</dependency>
|
||||
|
||||
For Gradle:
|
||||
|
||||
implementation 'net.razorvine:ksim65:1.10'
|
||||
|
||||
Update the version as required.
|
||||
|
||||
|
||||
## Virtual machine examples
|
||||
|
||||
|
@ -45,3 +60,36 @@ various timers and IRQs. It's not cycle perfect, and the video display is drawn
|
|||
so raster splits/rasterbars are impossible. But many other things work fine.
|
||||
|
||||
![C64 emulation](c64.png)
|
||||
|
||||
|
||||
### License information
|
||||
|
||||
Ksim65 itself is licensed under the MIT software license, see file LICENSE.
|
||||
|
||||
It includes the 'Spleen' bitmap font (https://github.com/fcambus/spleen),
|
||||
which has the following license (BSD):
|
||||
|
||||
Copyright (c) 2018-2020, Frederic Cambus
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import org.jetbrains.dokka.gradle.DokkaTask
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
import java.util.*
|
||||
import kotlin.math.max
|
||||
|
@ -6,32 +5,39 @@ import kotlin.math.max
|
|||
|
||||
plugins {
|
||||
// Apply the Kotlin JVM plugin to add support for Kotlin on the JVM.
|
||||
kotlin("jvm") version "1.3.61"
|
||||
kotlin("jvm") version "1.9.10"
|
||||
`maven-publish`
|
||||
application
|
||||
id("org.jetbrains.dokka") version "0.10.0"
|
||||
id("com.jfrog.bintray") version "1.8.4"
|
||||
java
|
||||
}
|
||||
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_11
|
||||
targetCompatibility = JavaVersion.VERSION_11
|
||||
}
|
||||
|
||||
|
||||
allprojects {
|
||||
val versionProps = Properties().also {
|
||||
it.load(File("$projectDir/src/main/resources/version.properties").inputStream())
|
||||
}
|
||||
version = versionProps["version"] as String
|
||||
group = "net.razorvine"
|
||||
base.archivesBaseName = "ksim65"
|
||||
// base.archivesBaseName = "ksim65"
|
||||
|
||||
repositories {
|
||||
// Use jcenter for resolving dependencies.
|
||||
// You can declare any Maven/Ivy/file repository here.
|
||||
mavenLocal()
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
maven("https://jitpack.io")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
dependencies {
|
||||
// Align versions of all Kotlin components
|
||||
implementation(platform("org.jetbrains.kotlin:kotlin-bom"))
|
||||
implementation("org.jetbrains.kotlin:kotlin-reflect")
|
||||
|
||||
// Use the Kotlin JDK 8 standard library.
|
||||
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
|
||||
|
||||
|
@ -40,11 +46,11 @@ dependencies {
|
|||
|
||||
// Use the Kotlin JUnit5 integration.
|
||||
testImplementation("org.jetbrains.kotlin:kotlin-test-junit5")
|
||||
testImplementation("org.junit.jupiter:junit-jupiter-api:5.4.0")
|
||||
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.4.0")
|
||||
testImplementation("org.junit.jupiter:junit-jupiter-api:5.10.0")
|
||||
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
||||
|
||||
subprojects.forEach {
|
||||
archives(it)
|
||||
implementation(it)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -61,35 +67,27 @@ tasks {
|
|||
}
|
||||
|
||||
withType<KotlinCompile> {
|
||||
kotlinOptions.jvmTarget = "1.8"
|
||||
}
|
||||
|
||||
named<DokkaTask>("dokka") {
|
||||
outputFormat = "html"
|
||||
outputDirectory = "$buildDir/kdoc"
|
||||
configuration {
|
||||
skipEmptyPackages = true
|
||||
}
|
||||
kotlinOptions.jvmTarget = "11"
|
||||
}
|
||||
}
|
||||
|
||||
val c64emuScript by tasks.registering(CreateStartScripts::class) {
|
||||
outputDir = File(project.buildDir, "bin")
|
||||
outputDir = project.layout.buildDirectory.dir("bin").get().asFile
|
||||
applicationName = "c64emu"
|
||||
mainClassName = "razorvine.c64emu.C64MainKt"
|
||||
mainClass.set("razorvine.c64emu.C64MainKt")
|
||||
classpath = project.tasks["jar"].outputs.files+project.configurations.runtimeClasspath.get()
|
||||
}
|
||||
|
||||
val ehbasicScript by tasks.registering(CreateStartScripts::class) {
|
||||
outputDir = File(project.buildDir, "bin")
|
||||
outputDir = project.layout.buildDirectory.dir("bin").get().asFile
|
||||
applicationName = "ehbasic"
|
||||
mainClassName = "razorvine.examplemachines.EhBasicMainKt"
|
||||
mainClass.set("razorvine.examplemachines.EhBasicMainKt")
|
||||
classpath = project.tasks["jar"].outputs.files+project.configurations.runtimeClasspath.get()
|
||||
}
|
||||
|
||||
application {
|
||||
applicationName = "ksim65vm"
|
||||
mainClassName = "razorvine.examplemachines.MachineMainKt"
|
||||
mainClass.set("razorvine.examplemachines.MachineMainKt")
|
||||
applicationDistribution.into("bin") {
|
||||
from(c64emuScript, ehbasicScript)
|
||||
fileMode = 493
|
||||
|
@ -102,12 +100,6 @@ val sourcesJar by tasks.registering(Jar::class) {
|
|||
from(sourceSets.main.get().allSource)
|
||||
}
|
||||
|
||||
val dokkaDocs by tasks.registering(Jar::class) {
|
||||
dependsOn("dokka")
|
||||
archiveClassifier.set("kdoc")
|
||||
from(fileTree(File(project.buildDir, "kdoc")))
|
||||
}
|
||||
|
||||
publishing {
|
||||
repositories {
|
||||
mavenLocal()
|
||||
|
@ -116,23 +108,6 @@ publishing {
|
|||
register("mavenJava", MavenPublication::class) {
|
||||
from(components["java"])
|
||||
artifact(sourcesJar.get())
|
||||
artifact(dokkaDocs.get())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bintray {
|
||||
user = System.getenv("BINTRAY_USER")
|
||||
key = System.getenv("BINTRAY_KEY")
|
||||
|
||||
setPublications(* publishing.publications.names.toTypedArray())
|
||||
// setConfigurations("archives")
|
||||
pkg = PackageConfig().also {
|
||||
it.name = "ksim65"
|
||||
it.repo = "maven"
|
||||
it.setLicenses("MIT")
|
||||
it.vcsUrl = "https://github.com/irmen/ksim65.git"
|
||||
it.setLabels("6502", "retro", "emulation", "c64")
|
||||
it.githubRepo = it.vcsUrl
|
||||
}
|
||||
}
|
||||
|
|
BIN
c64.png
BIN
c64.png
Binary file not shown.
Before Width: | Height: | Size: 192 KiB After Width: | Height: | Size: 237 KiB |
BIN
c64testprgs/atlantis.prg
Normal file
BIN
c64testprgs/atlantis.prg
Normal file
Binary file not shown.
BIN
c64testprgs/inaloop.prg
Normal file
BIN
c64testprgs/inaloop.prg
Normal file
Binary file not shown.
BIN
c64testprgs/joytest.prg
Normal file
BIN
c64testprgs/joytest.prg
Normal file
Binary file not shown.
BIN
free-c64-roms/basic
Normal file
BIN
free-c64-roms/basic
Normal file
Binary file not shown.
BIN
free-c64-roms/chargen
Normal file
BIN
free-c64-roms/chargen
Normal file
Binary file not shown.
BIN
free-c64-roms/kernal
Normal file
BIN
free-c64-roms/kernal
Normal file
Binary file not shown.
24
free-c64-roms/readme.txt
Normal file
24
free-c64-roms/readme.txt
Normal file
|
@ -0,0 +1,24 @@
|
|||
Free/open source roms for the C64
|
||||
|
||||
See https://github.com/MEGA65/open-roms
|
||||
|
||||
The following copyright notices apply to the entirety of this package,
|
||||
including each source file, unless otherwise noted in each file or directory.
|
||||
|
||||
Copyright Paul Gardner-Stephen, 2019.
|
||||
Copyright Roman Standzikowski (FeralChil64), 2019-2020.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
kotlin.code.style=official
|
||||
org.gradle.caching=true
|
||||
org.gradle.console=rich
|
||||
org.gradle.parallel=true
|
||||
org.gradle.daemon=true
|
||||
kotlin.code.style=official
|
||||
|
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,5 +1,5 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
|
269
gradlew
vendored
269
gradlew
vendored
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env sh
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright 2015 the original author or authors.
|
||||
# Copyright © 2015-2021 the original authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -17,78 +17,113 @@
|
|||
#
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
#
|
||||
# Gradle start up script for POSIX generated by Gradle.
|
||||
#
|
||||
# Important for running:
|
||||
#
|
||||
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||
# noncompliant, but you have some other compliant shell such as ksh or
|
||||
# bash, then to run this script, type that shell name before the whole
|
||||
# command line, like:
|
||||
#
|
||||
# ksh Gradle
|
||||
#
|
||||
# Busybox and similar reduced shells will NOT work, because this script
|
||||
# requires all of these POSIX shell features:
|
||||
# * functions;
|
||||
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||
# * compound commands having a testable exit status, especially «case»;
|
||||
# * various built-in commands including «command», «set», and «ulimit».
|
||||
#
|
||||
# Important for patching:
|
||||
#
|
||||
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||
#
|
||||
# The "traditional" practice of packing multiple parameters into a
|
||||
# space-separated string is a well documented source of bugs and security
|
||||
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||
# options in "$@", and eventually passing that to Java.
|
||||
#
|
||||
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||
# see the in-line comments for details.
|
||||
#
|
||||
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
app_path=$0
|
||||
|
||||
# Need this for daisy-chained symlinks.
|
||||
while
|
||||
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||
[ -h "$app_path" ]
|
||||
do
|
||||
ls=$( ls -ld "$app_path" )
|
||||
link=${ls#*' -> '}
|
||||
case $link in #(
|
||||
/*) app_path=$link ;; #(
|
||||
*) app_path=$APP_HOME$link ;;
|
||||
esac
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
APP_BASE_NAME=${0##*/}
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
MAX_FD=maximum
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
} >&2
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
} >&2
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
case "$( uname )" in #(
|
||||
CYGWIN* ) cygwin=true ;; #(
|
||||
Darwin* ) darwin=true ;; #(
|
||||
MSYS* | MINGW* ) msys=true ;; #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
JAVACMD=$JAVA_HOME/bin/java
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
@ -97,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the
|
|||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
JAVACMD=java
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
|
@ -105,79 +140,95 @@ location of your Java installation."
|
|||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=`expr $i + 1`
|
||||
done
|
||||
case $i in
|
||||
0) set -- ;;
|
||||
1) set -- "$args0" ;;
|
||||
2) set -- "$args0" "$args1" ;;
|
||||
3) set -- "$args0" "$args1" "$args2" ;;
|
||||
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
case $MAX_FD in #(
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=`save "$@"`
|
||||
# Collect all arguments for the java command, stacking in reverse order:
|
||||
# * args from the command line
|
||||
# * the main class name
|
||||
# * -classpath
|
||||
# * -D...appname settings
|
||||
# * --module-path (only if needed)
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if "$cygwin" || "$msys" ; then
|
||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||
|
||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
for arg do
|
||||
if
|
||||
case $arg in #(
|
||||
-*) false ;; # don't mess with options #(
|
||||
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||
[ -e "$t" ] ;; #(
|
||||
*) false ;;
|
||||
esac
|
||||
then
|
||||
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||
fi
|
||||
# Roll the args list around exactly as many times as the number of
|
||||
# args, so each arg winds up back in the position where it started, but
|
||||
# possibly modified.
|
||||
#
|
||||
# NB: a `for` loop captures its iteration list before it begins, so
|
||||
# changing the positional parameters here affects neither the number of
|
||||
# iterations, nor the values presented in `arg`.
|
||||
shift # remove old arg
|
||||
set -- "$@" "$arg" # push replacement arg
|
||||
done
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command;
|
||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
||||
# shell script including quotes and variable substitutions, so put them in
|
||||
# double quotes to make sure that they get re-expanded; and
|
||||
# * put everything else in single quotes, so that it's not re-expanded.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
"$@"
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
#
|
||||
# In Bash we could simply go:
|
||||
#
|
||||
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||
# set -- "${ARGS[@]}" "$@"
|
||||
#
|
||||
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||
# character that might be a shell metacharacter, then use eval to reverse
|
||||
# that process (while maintaining the separation between arguments), and wrap
|
||||
# the whole thing up as a single "set" statement.
|
||||
#
|
||||
# This will of course break if any of these variables contains a newline or
|
||||
# an unmatched quote.
|
||||
#
|
||||
|
||||
eval "set -- $(
|
||||
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||
xargs -n1 |
|
||||
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||
tr '\n' ' '
|
||||
)" '"$@"'
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
|
|
25
gradlew.bat
vendored
25
gradlew.bat
vendored
|
@ -29,6 +29,9 @@ if "%DIRNAME%" == "" set DIRNAME=.
|
|||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
|
@ -37,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
|
|||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
if "%ERRORLEVEL%" == "0" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
@ -51,7 +54,7 @@ goto fail
|
|||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
|
@ -61,28 +64,14 @@ echo location of your Java installation.
|
|||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windows variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
|
|
48
src/main/kotlin/razorvine/c64emu/Bus6510.kt
Normal file
48
src/main/kotlin/razorvine/c64emu/Bus6510.kt
Normal file
|
@ -0,0 +1,48 @@
|
|||
package razorvine.c64emu
|
||||
|
||||
import razorvine.ksim65.components.Address
|
||||
import razorvine.ksim65.components.Rom
|
||||
import razorvine.ksim65.components.UByte
|
||||
|
||||
/**
|
||||
* The C64's bus is a bit peculiar:
|
||||
* appearance of RAM or ROM in certain address ranges can be dynamically controlled
|
||||
* via the 6510's IO port register in $00/$01, "bank switching".
|
||||
* More info here https://www.c64-wiki.com/wiki/Bank_Switching
|
||||
*
|
||||
* Note: we don't implement the expansion port's _EXROM and _GAME lines that are used
|
||||
* for mapping in cartridge ROMs into the address space.
|
||||
*/
|
||||
class Bus6510(private val ioPort: CpuIoPort,
|
||||
private val chargen: Rom,
|
||||
private val basic: Rom,
|
||||
private val kernal: Rom): razorvine.ksim65.Bus() {
|
||||
|
||||
override fun read(address: Address): UByte {
|
||||
return when(address) {
|
||||
in 0x0000..0x9fff -> super.read(address) // always RAM
|
||||
in 0xa000..0xbfff -> {
|
||||
// BASIC or RAM
|
||||
if(ioPort.loram && ioPort.hiram)
|
||||
basic[address - 0xa000]
|
||||
else
|
||||
super.read(address)
|
||||
}
|
||||
in 0xc000..0xcfff -> super.read(address) // always RAM
|
||||
in 0xd000..0xdfff -> {
|
||||
// IO or CHAR ROM
|
||||
if(ioPort.charen)
|
||||
super.read(address)
|
||||
else
|
||||
chargen[address - 0xd000]
|
||||
}
|
||||
else -> {
|
||||
// 0xe000..0xffff, KERNAL or RAM
|
||||
if(ioPort.hiram)
|
||||
kernal[address - 0xe000]
|
||||
else
|
||||
super.read(address)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,12 +9,20 @@ import java.awt.event.KeyEvent
|
|||
/**
|
||||
* Minimal simulation of the MOS 6526 CIA chip.
|
||||
* Depending on what CIA it is (1 or 2), some registers do different things on the C64.
|
||||
* This implementation provides a working keyboard matrix, TOD clock, and the essentials of the timer A and B.
|
||||
* This implementation provides a working keyboard matrix, joystick in port#2 (cia 1),
|
||||
* time of day clock, and the essentials of the timer A and B.
|
||||
*/
|
||||
class Cia(val number: Int, startAddress: Address, endAddress: Address, val cpu: Cpu6502) : MemMappedComponent(startAddress, endAddress) {
|
||||
private var ramBuffer = Array<UByte>(endAddress-startAddress+1) { 0 }
|
||||
private var regPRA = 0xff
|
||||
|
||||
// joystick in port 2 configuration (only works on cia#1)
|
||||
private var joy2up = false
|
||||
private var joy2down = false
|
||||
private var joy2left = false
|
||||
private var joy2right = false
|
||||
private var joy2fire = false
|
||||
|
||||
class TimeOfDay {
|
||||
private var updatedAt = 0L
|
||||
private var startedAt = 0L
|
||||
|
@ -52,6 +60,8 @@ class Cia(val number: Int, startAddress: Address, endAddress: Address, val cpu:
|
|||
if (updatedAt != latchedTime) {
|
||||
updatedAt = latchedTime
|
||||
var elapsedSeconds = (latchedTime.toDouble()-startedAt)/1000.0+userStartTime
|
||||
if(elapsedSeconds>60*3600)
|
||||
elapsedSeconds=0.0 // TOD counds max 60 hours
|
||||
hours = (elapsedSeconds/3600).toInt()
|
||||
elapsedSeconds -= hours*3600
|
||||
minutes = (elapsedSeconds/60).toInt()
|
||||
|
@ -84,7 +94,7 @@ class Cia(val number: Int, startAddress: Address, endAddress: Address, val cpu:
|
|||
totalCycles++
|
||||
|
||||
if (totalCycles%20000 == 0) {
|
||||
// TOD resolution is 0.1 second, no need to update it in every cycle
|
||||
// TOD resolution is 0.1 second, no need to update it in every bus cycle
|
||||
tod.update()
|
||||
}
|
||||
|
||||
|
@ -92,8 +102,8 @@ class Cia(val number: Int, startAddress: Address, endAddress: Address, val cpu:
|
|||
// timer A is enabled, assume system cycles counting for now
|
||||
timerAactual--
|
||||
if (timerAactual == 0 && timerAinterruptEnabled) {
|
||||
if (number == 1) cpu.irq()
|
||||
else if (number == 2) cpu.nmi()
|
||||
if (number == 1) cpu.irqAsserted = true
|
||||
else if (number == 2) cpu.nmiAsserted = true
|
||||
}
|
||||
if (timerAactual < 0) timerAactual = if (ramBuffer[0x0e].toInt() and 0b00001000 != 0) 0 else timerAset
|
||||
}
|
||||
|
@ -108,8 +118,8 @@ class Cia(val number: Int, startAddress: Address, endAddress: Address, val cpu:
|
|||
timerBactual--
|
||||
}
|
||||
if (timerBactual == 0 && timerBinterruptEnabled) {
|
||||
if (number == 1) cpu.irq()
|
||||
else if (number == 2) cpu.nmi()
|
||||
if (number == 1) cpu.irqAsserted = true
|
||||
else if (number == 2) cpu.nmiAsserted = true
|
||||
}
|
||||
if (timerBactual < 0) timerBactual = if (regCRB and 0b00001000 != 0) 0 else timerBset
|
||||
}
|
||||
|
@ -123,9 +133,14 @@ class Cia(val number: Int, startAddress: Address, endAddress: Address, val cpu:
|
|||
timerAset = 0
|
||||
timerBactual = 0
|
||||
timerBset = 0
|
||||
joy2up = false
|
||||
joy2down = false
|
||||
joy2left = false
|
||||
joy2right = false
|
||||
joy2fire = false
|
||||
}
|
||||
|
||||
override fun get(address: Address): UByte {
|
||||
override operator fun get(offset: Int): UByte {
|
||||
fun scanColumn(vararg keys: HostKeyPress): UByte {
|
||||
var bits = 0b10000000
|
||||
var presses = 0
|
||||
|
@ -136,72 +151,86 @@ class Cia(val number: Int, startAddress: Address, endAddress: Address, val cpu:
|
|||
return (presses.inv() and 255).toShort()
|
||||
}
|
||||
|
||||
val register = (address-startAddress) and 15
|
||||
if (number == 1 && register == 0x01) {
|
||||
// register 1 on CIA#1 is the keyboard data port
|
||||
// if bit is cleared in PRA, contains keys pressed in that column of the matrix
|
||||
return when (regPRA) {
|
||||
0b00000000 -> {
|
||||
// check if any keys are pressed at all (by checking all columns at once)
|
||||
if (hostKeyPresses.isEmpty()) 0xff.toShort() else 0x00.toShort()
|
||||
}
|
||||
0b11111110 -> {
|
||||
// read column 0
|
||||
scanColumn(HostKeyPress(KeyEvent.VK_DOWN), HostKeyPress(KeyEvent.VK_F5), HostKeyPress(KeyEvent.VK_F3),
|
||||
HostKeyPress(KeyEvent.VK_F1), HostKeyPress(KeyEvent.VK_F7), HostKeyPress(KeyEvent.VK_RIGHT),
|
||||
HostKeyPress(KeyEvent.VK_ENTER), HostKeyPress(KeyEvent.VK_BACK_SPACE))
|
||||
}
|
||||
0b11111101 -> {
|
||||
// read column 1
|
||||
scanColumn(HostKeyPress(KeyEvent.VK_SHIFT), // left shift
|
||||
HostKeyPress(KeyEvent.VK_E), HostKeyPress(KeyEvent.VK_S), HostKeyPress(KeyEvent.VK_Z),
|
||||
HostKeyPress(KeyEvent.VK_4), HostKeyPress(KeyEvent.VK_A), HostKeyPress(KeyEvent.VK_W),
|
||||
HostKeyPress(KeyEvent.VK_3))
|
||||
}
|
||||
0b11111011 -> {
|
||||
// read column 2
|
||||
scanColumn(HostKeyPress(KeyEvent.VK_X), HostKeyPress(KeyEvent.VK_T), HostKeyPress(KeyEvent.VK_F),
|
||||
HostKeyPress(KeyEvent.VK_C), HostKeyPress(KeyEvent.VK_6), HostKeyPress(KeyEvent.VK_D),
|
||||
HostKeyPress(KeyEvent.VK_R), HostKeyPress(KeyEvent.VK_5))
|
||||
}
|
||||
0b11110111 -> {
|
||||
// read column 3
|
||||
scanColumn(HostKeyPress(KeyEvent.VK_V), HostKeyPress(KeyEvent.VK_U), HostKeyPress(KeyEvent.VK_H),
|
||||
HostKeyPress(KeyEvent.VK_B), HostKeyPress(KeyEvent.VK_8), HostKeyPress(KeyEvent.VK_G),
|
||||
HostKeyPress(KeyEvent.VK_Y), HostKeyPress(KeyEvent.VK_7))
|
||||
}
|
||||
0b11101111 -> {
|
||||
// read column 4
|
||||
scanColumn(HostKeyPress(KeyEvent.VK_N), HostKeyPress(KeyEvent.VK_O), HostKeyPress(KeyEvent.VK_K),
|
||||
HostKeyPress(KeyEvent.VK_M), HostKeyPress(KeyEvent.VK_0), HostKeyPress(KeyEvent.VK_J),
|
||||
HostKeyPress(KeyEvent.VK_I), HostKeyPress(KeyEvent.VK_9))
|
||||
}
|
||||
0b11011111 -> {
|
||||
// read column 5
|
||||
scanColumn(HostKeyPress(KeyEvent.VK_COMMA), HostKeyPress(KeyEvent.VK_AT), HostKeyPress(KeyEvent.VK_COLON),
|
||||
HostKeyPress(KeyEvent.VK_PERIOD), HostKeyPress(KeyEvent.VK_MINUS), HostKeyPress(KeyEvent.VK_L),
|
||||
HostKeyPress(KeyEvent.VK_P), HostKeyPress(KeyEvent.VK_PLUS))
|
||||
}
|
||||
0b10111111 -> {
|
||||
// read column 6
|
||||
scanColumn(HostKeyPress(KeyEvent.VK_SLASH), HostKeyPress(KeyEvent.VK_CIRCUMFLEX), HostKeyPress(KeyEvent.VK_EQUALS),
|
||||
HostKeyPress(KeyEvent.VK_SHIFT, rightSide = true), // right shift
|
||||
HostKeyPress(KeyEvent.VK_HOME), HostKeyPress(KeyEvent.VK_SEMICOLON), HostKeyPress(KeyEvent.VK_ASTERISK),
|
||||
HostKeyPress(KeyEvent.VK_DEAD_TILDE) // pound sign
|
||||
)
|
||||
}
|
||||
0b01111111 -> {
|
||||
// read column 7
|
||||
scanColumn(HostKeyPress(KeyEvent.VK_ESCAPE), HostKeyPress(KeyEvent.VK_Q), HostKeyPress(KeyEvent.VK_ALT),
|
||||
HostKeyPress(KeyEvent.VK_SPACE), HostKeyPress(KeyEvent.VK_2), HostKeyPress(KeyEvent.VK_CONTROL),
|
||||
HostKeyPress(KeyEvent.VK_BACK_QUOTE), HostKeyPress(KeyEvent.VK_1))
|
||||
}
|
||||
else -> {
|
||||
// invalid column selection
|
||||
0xff
|
||||
val register = offset and 15
|
||||
|
||||
if(number==1) {
|
||||
// first CIA has keyboard matrix
|
||||
if(register==0x00) {
|
||||
// reading $dc00 is joystick in port #2
|
||||
return (0b01100000
|
||||
or (if(joy2up) 0 else 0b00000001)
|
||||
or (if(joy2down) 0 else 0b00000010)
|
||||
or (if(joy2left) 0 else 0b00000100)
|
||||
or (if(joy2right) 0 else 0b00001000)
|
||||
or (if(joy2fire) 0 else 0b00010000)).toShort()
|
||||
} else if(register==0x01) {
|
||||
// register 1 on CIA#1 is the keyboard data port (and joystick #1...)
|
||||
// if bit is cleared in PRA, contains keys pressed in that column of the matrix
|
||||
// NOTE: we do not emulate a joystick in port #1 as this conflicts with the keyboard.
|
||||
// just use the joystick in port #2 for now...
|
||||
return when (regPRA) {
|
||||
0b00000000 -> {
|
||||
// check if any keys are pressed at all (by checking all columns at once)
|
||||
if (hostKeyPresses.isEmpty()) 0xff.toShort() else 0x00.toShort()
|
||||
}
|
||||
0b11111110 -> {
|
||||
// read column 0
|
||||
scanColumn(HostKeyPress(KeyEvent.VK_DOWN), HostKeyPress(KeyEvent.VK_F5), HostKeyPress(KeyEvent.VK_F3),
|
||||
HostKeyPress(KeyEvent.VK_F1), HostKeyPress(KeyEvent.VK_F7), HostKeyPress(KeyEvent.VK_RIGHT),
|
||||
HostKeyPress(KeyEvent.VK_ENTER), HostKeyPress(KeyEvent.VK_BACK_SPACE))
|
||||
}
|
||||
0b11111101 -> {
|
||||
// read column 1
|
||||
scanColumn(HostKeyPress(KeyEvent.VK_SHIFT), // left shift
|
||||
HostKeyPress(KeyEvent.VK_E), HostKeyPress(KeyEvent.VK_S), HostKeyPress(KeyEvent.VK_Z),
|
||||
HostKeyPress(KeyEvent.VK_4), HostKeyPress(KeyEvent.VK_A), HostKeyPress(KeyEvent.VK_W),
|
||||
HostKeyPress(KeyEvent.VK_3))
|
||||
}
|
||||
0b11111011 -> {
|
||||
// read column 2
|
||||
scanColumn(HostKeyPress(KeyEvent.VK_X), HostKeyPress(KeyEvent.VK_T), HostKeyPress(KeyEvent.VK_F),
|
||||
HostKeyPress(KeyEvent.VK_C), HostKeyPress(KeyEvent.VK_6), HostKeyPress(KeyEvent.VK_D),
|
||||
HostKeyPress(KeyEvent.VK_R), HostKeyPress(KeyEvent.VK_5))
|
||||
}
|
||||
0b11110111 -> {
|
||||
// read column 3
|
||||
scanColumn(HostKeyPress(KeyEvent.VK_V), HostKeyPress(KeyEvent.VK_U), HostKeyPress(KeyEvent.VK_H),
|
||||
HostKeyPress(KeyEvent.VK_B), HostKeyPress(KeyEvent.VK_8), HostKeyPress(KeyEvent.VK_G),
|
||||
HostKeyPress(KeyEvent.VK_Y), HostKeyPress(KeyEvent.VK_7))
|
||||
}
|
||||
0b11101111 -> {
|
||||
// read column 4
|
||||
scanColumn(HostKeyPress(KeyEvent.VK_N), HostKeyPress(KeyEvent.VK_O), HostKeyPress(KeyEvent.VK_K),
|
||||
HostKeyPress(KeyEvent.VK_M), HostKeyPress(KeyEvent.VK_0), HostKeyPress(KeyEvent.VK_J),
|
||||
HostKeyPress(KeyEvent.VK_I), HostKeyPress(KeyEvent.VK_9))
|
||||
}
|
||||
0b11011111 -> {
|
||||
// read column 5
|
||||
scanColumn(HostKeyPress(KeyEvent.VK_COMMA), HostKeyPress(KeyEvent.VK_AT), HostKeyPress(KeyEvent.VK_COLON),
|
||||
HostKeyPress(KeyEvent.VK_PERIOD), HostKeyPress(KeyEvent.VK_MINUS), HostKeyPress(KeyEvent.VK_L),
|
||||
HostKeyPress(KeyEvent.VK_P), HostKeyPress(KeyEvent.VK_PLUS))
|
||||
}
|
||||
0b10111111 -> {
|
||||
// read column 6
|
||||
scanColumn(HostKeyPress(KeyEvent.VK_SLASH), HostKeyPress(KeyEvent.VK_CIRCUMFLEX), HostKeyPress(KeyEvent.VK_EQUALS),
|
||||
HostKeyPress(KeyEvent.VK_SHIFT, rightSide = true), // right shift
|
||||
HostKeyPress(KeyEvent.VK_HOME), HostKeyPress(KeyEvent.VK_SEMICOLON), HostKeyPress(KeyEvent.VK_ASTERISK),
|
||||
HostKeyPress(KeyEvent.VK_DEAD_TILDE) // pound sign
|
||||
)
|
||||
}
|
||||
0b01111111 -> {
|
||||
// read column 7
|
||||
scanColumn(HostKeyPress(KeyEvent.VK_ESCAPE), HostKeyPress(KeyEvent.VK_Q), HostKeyPress(KeyEvent.VK_ALT),
|
||||
HostKeyPress(KeyEvent.VK_SPACE), HostKeyPress(KeyEvent.VK_2), HostKeyPress(KeyEvent.VK_CONTROL),
|
||||
HostKeyPress(KeyEvent.VK_BACK_QUOTE), HostKeyPress(KeyEvent.VK_1))
|
||||
}
|
||||
else -> {
|
||||
// invalid column selection
|
||||
0xff
|
||||
}
|
||||
}
|
||||
}
|
||||
} else ramBuffer[register]
|
||||
}
|
||||
|
||||
return when (register) {
|
||||
0x04 -> (timerAactual and 0xff).toShort()
|
||||
|
@ -222,21 +251,8 @@ class Cia(val number: Int, startAddress: Address, endAddress: Address, val cpu:
|
|||
}
|
||||
}
|
||||
|
||||
private fun toBCD(data: Int): UByte {
|
||||
val tens = data/10
|
||||
val ones = data-tens*10
|
||||
return ((tens shl 4) or ones).toShort()
|
||||
}
|
||||
|
||||
private fun fromBCD(bcd: UByte): Int {
|
||||
val ibcd = bcd.toInt()
|
||||
val tens = ibcd ushr 4
|
||||
val ones = ibcd and 0x0f
|
||||
return tens*10+ones
|
||||
}
|
||||
|
||||
override fun set(address: Address, data: UByte) {
|
||||
val register = (address-startAddress) and 15
|
||||
override operator fun set(offset: Int, data: UByte) {
|
||||
val register = offset and 15
|
||||
if (number == 1 && register == 0x00) {
|
||||
// PRA data port A (select keyboard matrix column)
|
||||
regPRA = data.toInt()
|
||||
|
@ -294,6 +310,19 @@ class Cia(val number: Int, startAddress: Address, endAddress: Address, val cpu:
|
|||
}
|
||||
}
|
||||
|
||||
private fun toBCD(data: Int): UByte {
|
||||
val tens = data/10
|
||||
val ones = data-tens*10
|
||||
return ((tens shl 4) or ones).toShort()
|
||||
}
|
||||
|
||||
private fun fromBCD(bcd: UByte): Int {
|
||||
val ibcd = bcd.toInt()
|
||||
val tens = ibcd ushr 4
|
||||
val ones = ibcd and 0x0f
|
||||
return tens*10+ones
|
||||
}
|
||||
|
||||
fun hostKeyPressed(event: KeyEvent) {
|
||||
val rightSide = event.keyLocation == KeyEvent.KEY_LOCATION_RIGHT
|
||||
val numpad = event.keyLocation == KeyEvent.KEY_LOCATION_NUMPAD
|
||||
|
@ -372,4 +401,15 @@ class Cia(val number: Int, startAddress: Address, endAddress: Address, val cpu:
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun setJoystick2(up: Boolean, down: Boolean, left: Boolean, right: Boolean, fire: Boolean) {
|
||||
if(number!=1)
|
||||
throw NotImplementedError("joystick port 2 is connected to cia#1")
|
||||
|
||||
joy2up = up
|
||||
joy2down = down
|
||||
joy2left = left
|
||||
joy2right = right
|
||||
joy2fire = fire
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,45 +1,56 @@
|
|||
package razorvine.c64emu
|
||||
|
||||
import razorvine.ksim65.Cpu6502
|
||||
import razorvine.ksim65.components.Address
|
||||
import razorvine.ksim65.components.MemMappedComponent
|
||||
import razorvine.ksim65.components.UByte
|
||||
|
||||
/**
|
||||
* The 6510's IO port located at $00/$01
|
||||
* Controlling the memory layout, and cassette port (not processed at all).
|
||||
* TODO: actually mapping the roms in and out of the address space. This requires some MMU type logic in the Bus class.
|
||||
* TODO: there are a few functional tests that still fail. Is this not implemented correctly yet?
|
||||
*/
|
||||
class CpuIoPort(val cpu: Cpu6502) : MemMappedComponent(0x0000, 0x0001) {
|
||||
class CpuIoPort : MemMappedComponent(0x0000, 0x0001) {
|
||||
|
||||
private var dataDirections: Int = 0
|
||||
private var ioPort: Int = 0
|
||||
private var loram: Boolean = false // Bit 0: LORAM signal. Selects ROM or RAM at 40960 ($A000). 1=BASIC, 0=RAM
|
||||
private var hiram: Boolean = false // Bit 1: HIRAM signal. Selects ROM or RAM at 57344 ($E000). 1=Kernal, 0=RAM
|
||||
private var charen: Boolean = false // Bit 2: CHAREN signal. Selects character ROM or I/O devices. 1=I/O, 0=ROM
|
||||
|
||||
var loram: Boolean = false // Bit 0: LORAM signal. Selects ROM or RAM at 40960 ($A000). 1=BASIC, 0=RAM
|
||||
private set
|
||||
var hiram: Boolean = false // Bit 1: HIRAM signal. Selects ROM or RAM at 57344 ($E000). 1=Kernal, 0=RAM
|
||||
private set
|
||||
var charen: Boolean = false // Bit 2: CHAREN signal. Selects character ROM or I/O devices. 1=I/O, 0=ROM
|
||||
private set
|
||||
|
||||
override fun clock() { }
|
||||
override fun reset() { }
|
||||
override fun reset() {
|
||||
dataDirections = 0xef
|
||||
ioPort = 0x37
|
||||
determineRoms()
|
||||
}
|
||||
|
||||
override fun get(address: Address): UByte {
|
||||
return if(address==0) dataDirections.toShort() else {
|
||||
(ioPort or dataDirections.inv() and 0b00111111).toShort()
|
||||
override operator fun get(offset: Int): UByte {
|
||||
return if(offset==0) {
|
||||
dataDirections.toShort()
|
||||
} else {
|
||||
if(dataDirections and 0b00100000 == 0)
|
||||
(ioPort and 0b11011111).toShort() // bit 5 is low when input
|
||||
else
|
||||
ioPort.toShort()
|
||||
}
|
||||
}
|
||||
|
||||
override fun set(address: Address, data: UByte) {
|
||||
if(address==0) {
|
||||
override operator fun set(offset: Int, data: UByte) {
|
||||
if(offset==0) {
|
||||
dataDirections = data.toInt()
|
||||
determineRoms()
|
||||
} else {
|
||||
ioPort = data.toInt()
|
||||
ioPort = (ioPort and dataDirections.inv()) or (data.toInt() and dataDirections)
|
||||
determineRoms()
|
||||
}
|
||||
}
|
||||
|
||||
private fun determineRoms() {
|
||||
if (dataDirections and 0b00000001 != 0) loram = ioPort and 0b00000001 != 0
|
||||
if (dataDirections and 0b00000010 != 0) hiram = ioPort and 0b00000010 != 0
|
||||
if (dataDirections and 0b00000100 != 0) charen = ioPort and 0b00000100 != 0
|
||||
loram = ioPort and 0b00000001 != 0
|
||||
hiram = ioPort and 0b00000010 != 0
|
||||
charen = ioPort and 0b00000100 != 0
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package razorvine.c64emu
|
|||
|
||||
import razorvine.ksim65.Cpu6502
|
||||
import razorvine.ksim65.components.MemoryComponent
|
||||
import razorvine.ksim65.components.Rom
|
||||
import razorvine.ksim65.components.UByte
|
||||
import java.awt.Color
|
||||
import java.awt.KeyboardFocusManager
|
||||
|
@ -52,14 +53,14 @@ object ScreenDefs {
|
|||
val colorPalette = Palette()
|
||||
}
|
||||
|
||||
class MainC64Window(title: String, chargenData: ByteArray, val ram: MemoryComponent, val cpu: Cpu6502, val keypressCia: Cia) :
|
||||
class MainC64Window(title: String, chargen: Rom, val ram: MemoryComponent, val cpu: Cpu6502, private val keypressCia: Cia) :
|
||||
JFrame(title), KeyListener {
|
||||
init {
|
||||
defaultCloseOperation = EXIT_ON_CLOSE
|
||||
isResizable = false
|
||||
isFocusable = true
|
||||
|
||||
add(Screen(chargenData, ram))
|
||||
add(Screen(chargen, ram))
|
||||
addKeyListener(this)
|
||||
pack()
|
||||
setLocationRelativeTo(null)
|
||||
|
@ -81,16 +82,50 @@ class MainC64Window(title: String, chargenData: ByteArray, val ram: MemoryCompon
|
|||
// keyboard events:
|
||||
override fun keyTyped(event: KeyEvent) {}
|
||||
|
||||
private var joy2up = false
|
||||
private var joy2down = false
|
||||
private var joy2left = false
|
||||
private var joy2right = false
|
||||
private var joy2fire = false
|
||||
|
||||
override fun keyPressed(event: KeyEvent) {
|
||||
// '\' is mapped as RESTORE, this causes a NMI on the cpu
|
||||
if (event.keyChar == '\\') {
|
||||
cpu.nmi()
|
||||
cpu.nmiAsserted = true
|
||||
} else {
|
||||
if(event.keyLocation==KeyEvent.KEY_LOCATION_NUMPAD) {
|
||||
// numpad is joystick #2
|
||||
if (event.keyChar in "789") joy2up = true
|
||||
if (event.keyChar in "123") joy2down = true
|
||||
if (event.keyChar in "741") joy2left = true
|
||||
if (event.keyChar in "963") joy2right = true
|
||||
if (event.keyChar in "05\n") joy2fire = true
|
||||
keypressCia.setJoystick2(joy2up, joy2down, joy2left, joy2right, joy2fire)
|
||||
} else {
|
||||
keypressCia.hostKeyPressed(event)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun keyReleased(event: KeyEvent) {
|
||||
if(event.keyLocation==KeyEvent.KEY_LOCATION_NUMPAD) {
|
||||
// numpad is joystick #2
|
||||
if (event.keyChar in "789") joy2up = false
|
||||
if (event.keyChar in "123") joy2down = false
|
||||
if (event.keyChar in "741") joy2left = false
|
||||
if (event.keyChar in "963") joy2right = false
|
||||
if (event.keyChar in "05\n") joy2fire = false
|
||||
keypressCia.setJoystick2(joy2up, joy2down, joy2left, joy2right, joy2fire)
|
||||
} else {
|
||||
keypressCia.hostKeyPressed(event)
|
||||
}
|
||||
}
|
||||
|
||||
override fun keyReleased(event: KeyEvent) {
|
||||
keypressCia.hostKeyPressed(event)
|
||||
fun reset() {
|
||||
joy2up = false
|
||||
joy2down = false
|
||||
joy2left = false
|
||||
joy2right = false
|
||||
joy2fire = false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package razorvine.c64emu
|
|||
|
||||
import razorvine.ksim65.components.Address
|
||||
import razorvine.ksim65.components.MemoryComponent
|
||||
import razorvine.ksim65.components.Rom
|
||||
import razorvine.ksim65.components.UByte
|
||||
import java.awt.*
|
||||
import java.awt.image.BufferedImage
|
||||
|
@ -12,9 +13,10 @@ import javax.swing.JPanel
|
|||
* The rendering logic of the screen of the C64.
|
||||
* It supports: Character mode,
|
||||
* High res bitmap mode (320*200), Multicolor bitmap mode (160*200).
|
||||
* TODO: Custom charsets from RAM. Multicolor character mode. Extended background color mode.
|
||||
* TODO: Multicolor character mode. Extended background color mode.
|
||||
* TODO: Horizontal smooth scrolling (+38 col mode). Vertical smooth scrolling (+24 row mode).
|
||||
*/
|
||||
internal class Screen(private val chargenData: ByteArray, val ram: MemoryComponent) : JPanel() {
|
||||
internal class Screen(private val chargen: Rom, val ram: MemoryComponent) : JPanel() {
|
||||
|
||||
private val fullscreenImage: BufferedImage
|
||||
private val fullscreenG2d: Graphics2D
|
||||
|
@ -43,7 +45,7 @@ internal class Screen(private val chargenData: ByteArray, val ram: MemoryCompone
|
|||
val offset = if (shifted) 256*8 else 0
|
||||
for (char in 0..255) {
|
||||
for (line in 0..7) {
|
||||
val charbyte = chargenData[offset+char*8+line].toInt()
|
||||
val charbyte = chargen[offset+char*8+line].toInt()
|
||||
for (x in 0..7) {
|
||||
if (charbyte and (0b10000000 ushr x) != 0) chars[char].setRGB(x, line, 0xffffff)
|
||||
}
|
||||
|
@ -108,7 +110,7 @@ internal class Screen(private val chargenData: ByteArray, val ram: MemoryCompone
|
|||
}
|
||||
|
||||
private fun renderSprites(vicBank: Address) {
|
||||
// TODO sprite-background priorities
|
||||
// TODO sprite-background priorities, collisions
|
||||
// TODO multicolor sprites
|
||||
val spriteImage = fullscreenG2d.deviceConfiguration.createCompatibleImage(24, 21, Transparency.TRANSLUCENT)
|
||||
val spriteGfx = spriteImage.graphics
|
||||
|
@ -140,30 +142,23 @@ internal class Screen(private val chargenData: ByteArray, val ram: MemoryCompone
|
|||
val color = ScreenDefs.colorPalette[ram[0xd027+sprite]].rgb
|
||||
for (i in spritePixels.indices step 8) {
|
||||
val bits = sprdata[i/8].toInt()
|
||||
if (bits and 0b10000000 != 0) spritePixels[i] = color
|
||||
if (bits and 0b01000000 != 0) spritePixels[i+1] = color
|
||||
if (bits and 0b00100000 != 0) spritePixels[i+2] = color
|
||||
if (bits and 0b00010000 != 0) spritePixels[i+3] = color
|
||||
if (bits and 0b00001000 != 0) spritePixels[i+4] = color
|
||||
if (bits and 0b00000100 != 0) spritePixels[i+5] = color
|
||||
if (bits and 0b00000010 != 0) spritePixels[i+6] = color
|
||||
if (bits and 0b00000001 != 0) spritePixels[i+7] = color
|
||||
bits2Pixels(bits, spritePixels, i, color)
|
||||
}
|
||||
}
|
||||
|
||||
private fun renderCharacterMode(vicBank: Address, vicVMCSB: Int, multiColorMode: Boolean) {
|
||||
if (multiColorMode) {
|
||||
TODO("multicolor character mode")
|
||||
} else {
|
||||
// normal character mode
|
||||
val screenAddress = vicBank+(vicVMCSB ushr 4) shl 10
|
||||
val charsetAddress = (vicVMCSB and 0b00001110) shl 10
|
||||
for (y in 0 until ScreenDefs.SCREEN_HEIGHT_CHARS) {
|
||||
for (x in 0 until ScreenDefs.SCREEN_WIDTH_CHARS) {
|
||||
val char = ram[screenAddress+x+y*ScreenDefs.SCREEN_WIDTH_CHARS].toInt()
|
||||
val color = ram[0xd800+x+y*ScreenDefs.SCREEN_WIDTH_CHARS].toInt() // colors always at $d800
|
||||
drawColoredChar(x, y, char, color, vicBank+charsetAddress)
|
||||
}
|
||||
// TODO multicolor character mode, for now, falls back to normal char mode
|
||||
}
|
||||
|
||||
// normal character mode
|
||||
val screenAddress = vicBank+((vicVMCSB ushr 4) shl 10)
|
||||
val charsetAddress = (vicVMCSB and 0b00001110) shl 10
|
||||
for (y in 0 until ScreenDefs.SCREEN_HEIGHT_CHARS) {
|
||||
for (x in 0 until ScreenDefs.SCREEN_WIDTH_CHARS) {
|
||||
val char = ram[screenAddress+x+y*ScreenDefs.SCREEN_WIDTH_CHARS].toInt()
|
||||
val color = ram[0xd800+x+y*ScreenDefs.SCREEN_WIDTH_CHARS].toInt() // colors always at $d800
|
||||
drawColoredChar(x, y, char, color, vicBank+charsetAddress)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -237,31 +232,44 @@ internal class Screen(private val chargenData: ByteArray, val ram: MemoryCompone
|
|||
// and lies within the same 16K VIC bank as the screen character memory.
|
||||
when (charsetAddr) {
|
||||
0x1000, 0x1800, 0x9000, 0x9800 -> {
|
||||
val charImage = getCharImage(char, color, charsetAddr and 0x0800 != 0)
|
||||
val charImage = getCharFromROM(char, color, charsetAddr and 0x0800 != 0)
|
||||
fullscreenG2d.drawImage(charImage, x*8+ScreenDefs.BORDER_SIZE, y*8+ScreenDefs.BORDER_SIZE, null)
|
||||
}
|
||||
else -> {
|
||||
// TODO: currently custom charsets taken from RAM aren't supported yet (need to read the char pixels)
|
||||
fullscreenG2d.drawImage(placeholderUserCharacter, x*8+ScreenDefs.BORDER_SIZE, y*8+ScreenDefs.BORDER_SIZE, null)
|
||||
val charImg = getCharFromRAM(char, color, charsetAddr)
|
||||
fullscreenG2d.drawImage(charImg, x*8+ScreenDefs.BORDER_SIZE, y*8+ScreenDefs.BORDER_SIZE, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: temporary placeholder for user-defined charset
|
||||
private val placeholderUserCharacter: BufferedImage by lazy {
|
||||
val img = fullscreenG2d.deviceConfiguration.createCompatibleImage(8, 8, BufferedImage.BITMASK)
|
||||
with(img.graphics) {
|
||||
color = Color.DARK_GRAY
|
||||
fillRect(0, 0, 8, 8)
|
||||
private val userCharacter = fullscreenG2d.deviceConfiguration.createCompatibleImage(8, 8, BufferedImage.BITMASK)
|
||||
|
||||
private fun getCharFromRAM(char: Int, color: Int, charsetAddr: Address): BufferedImage {
|
||||
val chardefBytes = ram.getBlock(charsetAddr+char*8, 8)
|
||||
val charPixels = (userCharacter.raster.dataBuffer as DataBufferInt).data
|
||||
val rgb = ScreenDefs.colorPalette[color].rgb
|
||||
val gfx = userCharacter.graphics
|
||||
gfx.color = ScreenDefs.colorPalette[ram[0xd021]]
|
||||
gfx.fillRect(0, 0, 8, 8)
|
||||
for (y in 0..7) {
|
||||
val bits = chardefBytes[y].toInt()
|
||||
bits2Pixels(bits, charPixels, y*8, rgb)
|
||||
}
|
||||
for (x in 0..7) {
|
||||
img.setRGB(x, x, Color.RED.rgb)
|
||||
img.setRGB(7-x, x, Color.RED.rgb)
|
||||
}
|
||||
img
|
||||
return userCharacter
|
||||
}
|
||||
|
||||
private fun getCharImage(char: Int, color: Int, shifted: Boolean): BufferedImage {
|
||||
private fun bits2Pixels(bits: Int, bitmap: IntArray, yoffset: Int, colorRgb: Int) {
|
||||
if (bits and 0b10000000 != 0) bitmap[yoffset] = colorRgb
|
||||
if (bits and 0b01000000 != 0) bitmap[yoffset+1] = colorRgb
|
||||
if (bits and 0b00100000 != 0) bitmap[yoffset+2] = colorRgb
|
||||
if (bits and 0b00010000 != 0) bitmap[yoffset+3] = colorRgb
|
||||
if (bits and 0b00001000 != 0) bitmap[yoffset+4] = colorRgb
|
||||
if (bits and 0b00000100 != 0) bitmap[yoffset+5] = colorRgb
|
||||
if (bits and 0b00000010 != 0) bitmap[yoffset+6] = colorRgb
|
||||
if (bits and 0b00000001 != 0) bitmap[yoffset+7] = colorRgb
|
||||
}
|
||||
|
||||
private fun getCharFromROM(char: Int, color: Int, shifted: Boolean): BufferedImage {
|
||||
val key = Triple(char, color, shifted)
|
||||
|
||||
fun makeCachedImage(): BufferedImage {
|
||||
|
|
|
@ -38,7 +38,7 @@ class VicII(startAddress: Address, endAddress: Address, val cpu: Cpu6502) : MemM
|
|||
interruptStatusRegisterD019 = if (currentRasterLine == rasterIrqLine) {
|
||||
// signal that current raster line is equal to the desired IRQ raster line
|
||||
// schedule an IRQ as well if the raster interrupt is enabled
|
||||
if ((ramBuffer[0x1a].toInt() and 1) != 0) cpu.irq()
|
||||
if ((ramBuffer[0x1a].toInt() and 1) != 0) cpu.irqAsserted = true
|
||||
interruptStatusRegisterD019 or 0b10000001
|
||||
} else interruptStatusRegisterD019 and 0b11111110
|
||||
}
|
||||
|
@ -50,8 +50,8 @@ class VicII(startAddress: Address, endAddress: Address, val cpu: Cpu6502) : MemM
|
|||
interruptStatusRegisterD019 = 0
|
||||
}
|
||||
|
||||
override fun get(address: Address): UByte {
|
||||
return when (val register = (address-startAddress) and 63) {
|
||||
override operator fun get(offset: Int): UByte {
|
||||
return when (val register = offset and 63) {
|
||||
0x11 -> (0b00011011 or ((currentRasterLine and 0b100000000) ushr 1)).toShort()
|
||||
0x12 -> {
|
||||
(currentRasterLine and 255).toShort()
|
||||
|
@ -61,8 +61,8 @@ class VicII(startAddress: Address, endAddress: Address, val cpu: Cpu6502) : MemM
|
|||
}
|
||||
}
|
||||
|
||||
override fun set(address: Address, data: UByte) {
|
||||
val register = (address-startAddress) and 63
|
||||
override operator fun set(offset: Int, data: UByte) {
|
||||
val register = offset and 63
|
||||
ramBuffer[register] = data
|
||||
when (register) {
|
||||
0x11 -> {
|
||||
|
|
|
@ -25,23 +25,37 @@ import kotlin.concurrent.scheduleAtFixedRate
|
|||
*/
|
||||
class C64Machine(title: String) : IVirtualMachine {
|
||||
private val romsPath = determineRomPath()
|
||||
private val chargenData = romsPath.resolve("chargen").toFile().readBytes()
|
||||
private val basicData = romsPath.resolve("basic").toFile().readBytes()
|
||||
private val kernalData = romsPath.resolve("kernal").toFile().readBytes()
|
||||
|
||||
override val bus = Bus()
|
||||
private val chargenRom = Rom(0xd000, 0xdfff).also {
|
||||
val chargenData = romsPath.resolve("chargen").toFile().readBytes()
|
||||
it.load(chargenData)
|
||||
}
|
||||
private val basicRom = Rom(0xa000, 0xbfff).also {
|
||||
val basicData = romsPath.resolve("basic").toFile().readBytes()
|
||||
it.load(basicData)
|
||||
}
|
||||
private val kernalRom = Rom(0xe000, 0xffff).also {
|
||||
val kernalData = romsPath.resolve("kernal").toFile().readBytes()
|
||||
it.load(kernalData)
|
||||
}
|
||||
|
||||
val cpuIoPort = CpuIoPort()
|
||||
|
||||
// This bus contains "mmu" logic to control the memory bank switching controlled by the 6510's io port in $00/$01.
|
||||
// Therefore we provide it the various roms directly and not "connect" these to the bus in the default way.
|
||||
override val bus = Bus6510(cpuIoPort, chargenRom, basicRom, kernalRom)
|
||||
override val cpu = Cpu6502()
|
||||
|
||||
// the C64 has 64KB of RAM. Some of it may be banked out and replaced by ROM.
|
||||
val ram = Ram(0x0000, 0xffff)
|
||||
|
||||
val vic = VicII(0xd000, 0xd3ff, cpu)
|
||||
val cia1 = Cia(1, 0xdc00, 0xdcff, cpu)
|
||||
val cia2 = Cia(2, 0xdd00, 0xddff, cpu)
|
||||
val basicRom = Rom(0xa000, 0xbfff).also { it.load(basicData) }
|
||||
val kernalRom = Rom(0xe000, 0xffff).also { it.load(kernalData) }
|
||||
val cpuIoPort = CpuIoPort(cpu)
|
||||
|
||||
private val monitor = Monitor(bus, cpu)
|
||||
private val debugWindow = DebugWindow(this)
|
||||
private val hostDisplay = MainC64Window(title, chargenData, ram, cpu, cia1)
|
||||
private val hostDisplay = MainC64Window(title, chargenRom, ram, cpu, cia1)
|
||||
private var paused = false
|
||||
|
||||
init {
|
||||
|
@ -49,13 +63,11 @@ class C64Machine(title: String) : IVirtualMachine {
|
|||
cpu.addBreakpoint(0xffd8, ::breakpointKernelSave) // intercept SAVE subroutine in the kernal
|
||||
cpu.breakpointForBRK = ::breakpointBRK
|
||||
|
||||
bus += basicRom
|
||||
bus += kernalRom
|
||||
bus += vic
|
||||
bus += cia1
|
||||
bus += cia2
|
||||
bus += cpuIoPort
|
||||
bus += ram
|
||||
bus += ram // note: the ROMs are mapped depending on the cpu's io port
|
||||
bus += cpu
|
||||
bus.reset()
|
||||
|
||||
|
@ -75,7 +87,7 @@ class C64Machine(title: String) : IVirtualMachine {
|
|||
val txttab = ram[0x2b]+256*ram[0x2c] // basic load address ($0801 usually)
|
||||
val fnaddr = ram[0xbb]+256*ram[0xbc] // file name address
|
||||
return if (fnlen > 0) {
|
||||
val filename = (0 until fnlen).map { ram[fnaddr+it].toChar() }.joinToString("")
|
||||
val filename = (0 until fnlen).map { ram[fnaddr+it].toInt().toChar() }.joinToString("")
|
||||
val loadEndAddress = searchAndLoadFile(filename, fa, sa, txttab)
|
||||
if (loadEndAddress != null) {
|
||||
ram[0x90] = 0 // status OK
|
||||
|
@ -96,7 +108,7 @@ class C64Machine(title: String) : IVirtualMachine {
|
|||
val fromAddr = ram[cpu.regA]+256*ram[cpu.regA+1]
|
||||
val endAddr = cpu.regX+256*cpu.regY
|
||||
val data = (fromAddr..endAddr).map { ram[it].toByte() }.toByteArray()
|
||||
var filename = (0 until fnlen).map { ram[fnaddr+it].toChar() }.joinToString("").toLowerCase()
|
||||
var filename = (0 until fnlen).map { ram[fnaddr+it].toInt().toChar() }.joinToString("").lowercase()
|
||||
if (!filename.endsWith(".prg")) filename += ".prg"
|
||||
File(filename).outputStream().use {
|
||||
it.write(fromAddr and 0xff)
|
||||
|
@ -121,13 +133,13 @@ class C64Machine(title: String) : IVirtualMachine {
|
|||
"$" -> {
|
||||
// load the directory
|
||||
val files = File(".").listFiles(FileFilter { it.isFile })!!.associate {
|
||||
val name = it.nameWithoutExtension.toUpperCase()
|
||||
val ext = it.extension.toUpperCase()
|
||||
val name = it.nameWithoutExtension.uppercase()
|
||||
val ext = it.extension.uppercase()
|
||||
val fileAndSize = Pair(it, it.length())
|
||||
if (name.isEmpty()) Pair(".$ext", "") to fileAndSize
|
||||
else Pair(name, ext) to fileAndSize
|
||||
}
|
||||
val dirname = File(".").canonicalPath.substringAfterLast(File.separator).toUpperCase()
|
||||
val dirname = File(".").canonicalPath.substringAfterLast(File.separator).uppercase()
|
||||
val dirlisting = makeDirListing(dirname, files, basicLoadAddress)
|
||||
ram.load(dirlisting, basicLoadAddress)
|
||||
return basicLoadAddress+dirlisting.size-1
|
||||
|
@ -135,7 +147,7 @@ class C64Machine(title: String) : IVirtualMachine {
|
|||
else -> {
|
||||
fun findHostFile(filename: String): String? {
|
||||
val file = File(".").listFiles(FileFilter { it.isFile })?.firstOrNull {
|
||||
it.name.toUpperCase() == filename
|
||||
it.name.uppercase() == filename
|
||||
}
|
||||
return file?.name
|
||||
}
|
||||
|
@ -167,7 +179,7 @@ class C64Machine(title: String) : IVirtualMachine {
|
|||
listing.add((address ushr 8).toShort())
|
||||
listing.add((lineNumber and 0xff).toShort())
|
||||
listing.add((lineNumber ushr 8).toShort())
|
||||
listing.addAll(line.map { it.toShort() })
|
||||
listing.addAll(line.map { it.code.toShort() })
|
||||
listing.add(0)
|
||||
}
|
||||
addLine(0, "\u0012\"${dirname.take(16).padEnd(16)}\" 00 2A")
|
||||
|
@ -186,24 +198,6 @@ class C64Machine(title: String) : IVirtualMachine {
|
|||
return listing.toTypedArray()
|
||||
}
|
||||
|
||||
private fun determineRomPath(): Path {
|
||||
val candidates = listOf("./roms", "~/roms/c64", "~/roms", "~/.vice/C64")
|
||||
candidates.forEach {
|
||||
val path = Paths.get(expandUser(it))
|
||||
if (path.toFile().isDirectory) return path
|
||||
}
|
||||
throw FileNotFoundException("no roms directory found, tried: $candidates")
|
||||
}
|
||||
|
||||
private fun expandUser(path: String): String {
|
||||
return when {
|
||||
path.startsWith("~/") -> System.getProperty("user.home")+path.substring(1)
|
||||
path.startsWith("~"+File.separatorChar) -> System.getProperty("user.home")+path.substring(1)
|
||||
path.startsWith("~") -> throw UnsupportedOperationException("home dir expansion not implemented for other users")
|
||||
else -> path
|
||||
}
|
||||
}
|
||||
|
||||
override fun loadFileInRam(file: File, loadAddress: Address?) {
|
||||
if (file.extension == "prg" && (loadAddress == null || loadAddress == 0x0801)) ram.loadPrg(file.inputStream(), null)
|
||||
else ram.load(file.readBytes(), loadAddress!!)
|
||||
|
@ -222,6 +216,11 @@ class C64Machine(title: String) : IVirtualMachine {
|
|||
while (cpu.instrCycles > 0) bus.clock()
|
||||
}
|
||||
|
||||
override fun reset() {
|
||||
bus.reset()
|
||||
hostDisplay.reset()
|
||||
}
|
||||
|
||||
override fun executeMonitorCommand(command: String) = monitor.command(command)
|
||||
|
||||
fun start() {
|
||||
|
@ -229,11 +228,15 @@ class C64Machine(title: String) : IVirtualMachine {
|
|||
debugWindow.updateCpu(cpu, bus)
|
||||
}.start()
|
||||
|
||||
// we synchronise cpu cycles to the vertical blank of the Vic chip
|
||||
// this should result in ~1 Mhz cpu speed
|
||||
val timer = java.util.Timer("cpu-cycle", true)
|
||||
timer.scheduleAtFixedRate(0, 1000L/VicII.framerate) {
|
||||
// if(cpu.isLooping) {
|
||||
// // cpu is jump looping, could do some sleeping here perhaps
|
||||
// // but should still consider irqs occurring in the meantime...
|
||||
// }
|
||||
if (!paused) {
|
||||
// we synchronise cpu cycles to the vertical blank of the Vic chip
|
||||
// this should result in ~1 Mhz cpu speed
|
||||
try {
|
||||
while (vic.vsync) step()
|
||||
while (!vic.vsync) step()
|
||||
|
@ -252,6 +255,26 @@ class C64Machine(title: String) : IVirtualMachine {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
fun determineRomPath(): Path {
|
||||
val candidates = listOf("./roms", "~/roms/c64", "~/roms", "~/.vice/C64", "/usr/lib/vice/C64")
|
||||
candidates.forEach {
|
||||
val path = Paths.get(expandUser(it))
|
||||
if (path.toFile().isDirectory) return path
|
||||
}
|
||||
throw FileNotFoundException("no roms directory found, tried: $candidates")
|
||||
}
|
||||
|
||||
fun expandUser(path: String): String {
|
||||
return when {
|
||||
path.startsWith("~/") -> System.getProperty("user.home")+path.substring(1)
|
||||
path.startsWith("~"+File.separatorChar) -> System.getProperty("user.home")+path.substring(1)
|
||||
path.startsWith("~") -> throw UnsupportedOperationException("home dir expansion not implemented for other users")
|
||||
else -> path
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun main() {
|
||||
val machine = C64Machine("virtual Commodore-64 - using KSim65 v${Version.version}")
|
||||
machine.start()
|
||||
|
|
|
@ -44,6 +44,7 @@ class DebugWindow(private val vm: IVirtualMachine) : JFrame("Debugger - ksim65 v
|
|||
it.disabledTextColor = Color.DARK_GRAY
|
||||
it.font = Font(Font.MONOSPACED, Font.PLAIN, 12)
|
||||
}
|
||||
private val disassembler = Disassembler(vm.cpu)
|
||||
|
||||
init {
|
||||
contentPane.layout = GridBagLayout()
|
||||
|
@ -53,8 +54,6 @@ class DebugWindow(private val vm: IVirtualMachine) : JFrame("Debugger - ksim65 v
|
|||
val gc = GridBagConstraints()
|
||||
gc.insets = Insets(2, 2, 2, 2)
|
||||
gc.anchor = GridBagConstraints.EAST
|
||||
gc.gridx = 0
|
||||
gc.gridy = 0
|
||||
val cyclesLb = JLabel("cycles")
|
||||
val speedKhzLb = JLabel("speed (kHz)")
|
||||
val regAlb = JLabel("A")
|
||||
|
@ -64,13 +63,25 @@ class DebugWindow(private val vm: IVirtualMachine) : JFrame("Debugger - ksim65 v
|
|||
val regPClb = JLabel("PC")
|
||||
val regPlb = JLabel("Status")
|
||||
val disassemLb = JLabel("Instruction")
|
||||
listOf(cyclesLb, speedKhzLb, regAlb, regXlb, regYlb, regSPlb, regPClb, disassemLb, regPlb).forEach {
|
||||
cpuPanel.add(it, gc)
|
||||
gc.gridy++
|
||||
}
|
||||
cpuPanel.add(cyclesLb, gc.update(gridx=0, gridy=0))
|
||||
cpuPanel.add(speedKhzLb, gc.update(gridx=5, gridy=0))
|
||||
cpuPanel.add(regAlb, gc.update(gridx=0, gridy=1))
|
||||
cpuPanel.add(regXlb, gc.update(gridx=2, gridy=1))
|
||||
cpuPanel.add(regYlb, gc.update(gridx=4, gridy=1))
|
||||
cpuPanel.add(regPClb, gc.update(gridx=0, gridy=2))
|
||||
cpuPanel.add(regSPlb, gc.update(gridx=2, gridy=2))
|
||||
cpuPanel.add(regPlb, gc.update(gridx=0, gridy=3))
|
||||
cpuPanel.add(disassemLb, gc.update(gridx=0, gridy=4))
|
||||
gc.anchor = GridBagConstraints.WEST
|
||||
gc.gridx = 1
|
||||
gc.gridy = 0
|
||||
cpuPanel.add(cyclesTf, gc.update(gridx=1, gridy=0, gridwidth = 3))
|
||||
cpuPanel.add(speedKhzTf, gc.update(gridx=6, gridy=0))
|
||||
cpuPanel.add(regAtf, gc.update(gridx=1, gridy=1))
|
||||
cpuPanel.add(regXtf, gc.update(gridx=3, gridy=1))
|
||||
cpuPanel.add(regYtf, gc.update(gridx=5, gridy=1))
|
||||
cpuPanel.add(regPCtf, gc.update(gridx=1, gridy=2))
|
||||
cpuPanel.add(regSPtf, gc.update(gridx=3, gridy=2))
|
||||
cpuPanel.add(regPtf, gc.update(gridx=1, gridy=3, gridwidth=2))
|
||||
cpuPanel.add(disassemTf, gc.update(gridx=1, gridy=4, gridwidth=5))
|
||||
listOf(cyclesTf, speedKhzTf, regAtf, regXtf, regYtf, regSPtf, regPCtf, disassemTf, regPtf).forEach {
|
||||
it.font = Font(Font.MONOSPACED, Font.PLAIN, 14)
|
||||
it.disabledTextColor = Color.DARK_GRAY
|
||||
|
@ -81,8 +92,6 @@ class DebugWindow(private val vm: IVirtualMachine) : JFrame("Debugger - ksim65 v
|
|||
it.border = BorderFactory.createCompoundBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY),
|
||||
BorderFactory.createEmptyBorder(2, 2, 2, 2))
|
||||
}
|
||||
cpuPanel.add(it, gc)
|
||||
gc.gridy++
|
||||
}
|
||||
|
||||
val buttonPanel = JPanel(FlowLayout())
|
||||
|
@ -115,7 +124,7 @@ class DebugWindow(private val vm: IVirtualMachine) : JFrame("Debugger - ksim65 v
|
|||
val monitorPanel = JPanel()
|
||||
monitorPanel.layout = BoxLayout(monitorPanel, BoxLayout.Y_AXIS)
|
||||
monitorPanel.border = BorderFactory.createTitledBorder("Built-in Monitor")
|
||||
val output = JTextArea(6, 80)
|
||||
val output = JTextArea(10, 80)
|
||||
output.font = Font(Font.MONOSPACED, Font.PLAIN, 14)
|
||||
output.isEditable = false
|
||||
val outputScroll = JScrollPane(output)
|
||||
|
@ -173,6 +182,7 @@ class DebugWindow(private val vm: IVirtualMachine) : JFrame("Debugger - ksim65 v
|
|||
|
||||
}
|
||||
"reset" -> {
|
||||
vm.reset()
|
||||
vm.bus.reset()
|
||||
updateCpu(vm.cpu, vm.bus)
|
||||
}
|
||||
|
@ -190,8 +200,8 @@ class DebugWindow(private val vm: IVirtualMachine) : JFrame("Debugger - ksim65 v
|
|||
pauseBt.actionCommand = "pause"
|
||||
pauseBt.text = "Pause"
|
||||
}
|
||||
"irq" -> vm.cpu.irq()
|
||||
"nmi" -> vm.cpu.nmi()
|
||||
"irq" -> vm.cpu.irqAsserted = true
|
||||
"nmi" -> vm.cpu.nmiAsserted = true
|
||||
"quit" -> {
|
||||
dispatchEvent(WindowEvent(this, WindowEvent.WINDOW_CLOSING))
|
||||
}
|
||||
|
@ -207,8 +217,11 @@ class DebugWindow(private val vm: IVirtualMachine) : JFrame("Debugger - ksim65 v
|
|||
regPtf.text = "NV-BDIZC\n"+state.P.asInt().toString(2).padStart(8, '0')
|
||||
regPCtf.text = hexW(state.PC)
|
||||
regSPtf.text = hexB(state.SP)
|
||||
val memory = bus.memoryComponentFor(state.PC)
|
||||
disassemTf.text = cpu.disassembleOneInstruction(memory.data, state.PC, memory.startAddress).first.substringAfter(' ').trim()
|
||||
|
||||
val memory = listOf(bus[state.PC], bus[state.PC+1], bus[state.PC+2]).toTypedArray()
|
||||
|
||||
val disassem = disassembler.disassembleOneInstruction(memory, 0, state.PC).first.substringAfter(' ').trim()
|
||||
disassemTf.text = disassem
|
||||
|
||||
if (zeropageTf.isVisible || stackpageTf.isVisible) {
|
||||
val pages = vm.getZeroAndStackPages()
|
||||
|
@ -231,3 +244,13 @@ class DebugWindow(private val vm: IVirtualMachine) : JFrame("Debugger - ksim65 v
|
|||
speedKhzTf.text = "%.1f".format(cpu.averageSpeedKhzSinceReset)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun GridBagConstraints.update(gridx: Int, gridy: Int, gridwidth: Int?=null): GridBagConstraints {
|
||||
val gc = this.clone() as GridBagConstraints
|
||||
gc.gridx = gridx
|
||||
gc.gridy = gridy
|
||||
if(gridwidth!=null)
|
||||
gc.gridwidth=gridwidth
|
||||
return gc
|
||||
}
|
||||
|
|
|
@ -1,57 +1,27 @@
|
|||
package razorvine.examplemachines
|
||||
|
||||
import razorvine.fonts.PsfFont
|
||||
import razorvine.ksim65.*
|
||||
import java.awt.*
|
||||
import java.awt.event.*
|
||||
import java.awt.image.BufferedImage
|
||||
import java.util.*
|
||||
import javax.imageio.ImageIO
|
||||
import javax.swing.*
|
||||
import javax.swing.event.MouseInputListener
|
||||
|
||||
|
||||
/**
|
||||
* Define a monochrome screen that can display 640x480 pixels
|
||||
* and/or 80x30 characters (these are 8x16 pixels).
|
||||
* Define a monochrome screen that can display 80x30 charaacters
|
||||
* (usually equivalent to 640x480 pixels, but depends on the font size)
|
||||
*/
|
||||
object ScreenDefs {
|
||||
const val SCREEN_WIDTH_CHARS = 80
|
||||
const val SCREEN_HEIGHT_CHARS = 30
|
||||
const val SCREEN_WIDTH = SCREEN_WIDTH_CHARS*8
|
||||
const val SCREEN_HEIGHT = SCREEN_HEIGHT_CHARS*16
|
||||
const val PIXEL_SCALING = 1.5
|
||||
const val COLUMNS = 80
|
||||
const val ROWS = 30
|
||||
const val BORDER_SIZE = 32
|
||||
|
||||
val BG_COLOR = Color(0, 10, 20)
|
||||
val FG_COLOR = Color(200, 255, 230)
|
||||
val BORDER_COLOR = Color(20, 30, 40)
|
||||
val Characters = loadCharacters()
|
||||
|
||||
private fun loadCharacters(): Array<BufferedImage> {
|
||||
val img = ImageIO.read(javaClass.getResourceAsStream("/charset/unscii8x16.png"))
|
||||
val charactersImage = BufferedImage(img.width, img.height, BufferedImage.TYPE_INT_ARGB)
|
||||
charactersImage.createGraphics().drawImage(img, 0, 0, null)
|
||||
|
||||
val black = Color(0, 0, 0).rgb
|
||||
val foreground = FG_COLOR.rgb
|
||||
val nopixel = Color(0, 0, 0, 0).rgb
|
||||
for (y in 0 until charactersImage.height) {
|
||||
for (x in 0 until charactersImage.width) {
|
||||
val col = charactersImage.getRGB(x, y)
|
||||
if (col == black) charactersImage.setRGB(x, y, nopixel)
|
||||
else charactersImage.setRGB(x, y, foreground)
|
||||
}
|
||||
}
|
||||
|
||||
val numColumns = charactersImage.width/8
|
||||
val charImages = (0..255).map {
|
||||
val charX = it%numColumns
|
||||
val charY = it/numColumns
|
||||
charactersImage.getSubimage(charX*8, charY*16, 8, 16)
|
||||
}
|
||||
|
||||
return charImages.toTypedArray()
|
||||
}
|
||||
}
|
||||
|
||||
private class BitmapScreenPanel : JPanel() {
|
||||
|
@ -61,15 +31,21 @@ private class BitmapScreenPanel : JPanel() {
|
|||
private var cursorX: Int = 0
|
||||
private var cursorY: Int = 0
|
||||
private var cursorState: Boolean = false
|
||||
private val screenFont = PsfFont("spleen-12x24") // nice fonts: sun12x22, iso01-12x22, ter-124b, spleen-12x24, default8x16
|
||||
private val pixelScaling: Double = if(screenFont.width <= 8) 1.5 else 1.0
|
||||
private val screenFontImage: BufferedImage
|
||||
|
||||
init {
|
||||
println("SCREENFONT WIDTH: ${screenFont.width}")
|
||||
|
||||
val ge = GraphicsEnvironment.getLocalGraphicsEnvironment()
|
||||
val gd = ge.defaultScreenDevice.defaultConfiguration
|
||||
image = gd.createCompatibleImage(ScreenDefs.SCREEN_WIDTH, ScreenDefs.SCREEN_HEIGHT, Transparency.OPAQUE)
|
||||
image = gd.createCompatibleImage(ScreenDefs.COLUMNS*screenFont.width, ScreenDefs.ROWS*screenFont.height, Transparency.OPAQUE)
|
||||
g2d = image.graphics as Graphics2D
|
||||
screenFontImage = screenFont.convertToImage(g2d, ScreenDefs.FG_COLOR)
|
||||
|
||||
val size = Dimension((image.width*ScreenDefs.PIXEL_SCALING).toInt(),
|
||||
(image.height*ScreenDefs.PIXEL_SCALING).toInt())
|
||||
val size = Dimension((image.width*pixelScaling).toInt(),
|
||||
(image.height*pixelScaling).toInt())
|
||||
minimumSize = size
|
||||
maximumSize = size
|
||||
preferredSize = size
|
||||
|
@ -82,13 +58,13 @@ private class BitmapScreenPanel : JPanel() {
|
|||
override fun paint(graphics: Graphics) {
|
||||
val g2d = graphics as Graphics2D
|
||||
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR)
|
||||
g2d.drawImage(image, 0, 0, (image.width*ScreenDefs.PIXEL_SCALING).toInt(),
|
||||
(image.height*ScreenDefs.PIXEL_SCALING).toInt(), null)
|
||||
g2d.drawImage(image, 0, 0, (image.width*pixelScaling).toInt(),
|
||||
(image.height*pixelScaling).toInt(), null)
|
||||
if (cursorState) {
|
||||
val scx = (cursorX*ScreenDefs.PIXEL_SCALING*8).toInt()
|
||||
val scy = (cursorY*ScreenDefs.PIXEL_SCALING*16).toInt()
|
||||
val scw = (8*ScreenDefs.PIXEL_SCALING).toInt()
|
||||
val sch = (16*ScreenDefs.PIXEL_SCALING).toInt()
|
||||
val scx = (cursorX*pixelScaling*screenFont.width).toInt()
|
||||
val scy = (cursorY*pixelScaling*screenFont.height).toInt()
|
||||
val scw = (screenFont.width*pixelScaling).toInt()
|
||||
val sch = (screenFont.height*pixelScaling).toInt()
|
||||
g2d.setXORMode(Color.CYAN)
|
||||
g2d.fillRect(scx, scy, scw, sch)
|
||||
g2d.setPaintMode()
|
||||
|
@ -98,7 +74,7 @@ private class BitmapScreenPanel : JPanel() {
|
|||
|
||||
fun clearScreen() {
|
||||
g2d.background = ScreenDefs.BG_COLOR
|
||||
g2d.clearRect(0, 0, ScreenDefs.SCREEN_WIDTH, ScreenDefs.SCREEN_HEIGHT)
|
||||
g2d.clearRect(0, 0, ScreenDefs.COLUMNS*screenFont.width, ScreenDefs.ROWS*screenFont.height)
|
||||
cursorPos(0, 0)
|
||||
}
|
||||
|
||||
|
@ -110,20 +86,26 @@ private class BitmapScreenPanel : JPanel() {
|
|||
fun getPixel(x: Int, y: Int) = image.getRGB(x, y) != ScreenDefs.BG_COLOR.rgb
|
||||
|
||||
fun setChar(x: Int, y: Int, character: Char) {
|
||||
g2d.clearRect(8*x, 16*y, 8, 16)
|
||||
val coloredImage = ScreenDefs.Characters[character.toInt()]
|
||||
g2d.drawImage(coloredImage, 8*x, 16*y, null)
|
||||
val charnum = character.code
|
||||
val cx = charnum % (screenFontImage.width/screenFont.width)
|
||||
val cy = charnum / (screenFontImage.width/screenFont.width)
|
||||
g2d.clearRect(x*screenFont.width, y*screenFont.height, screenFont.width, screenFont.height)
|
||||
g2d.drawImage(screenFontImage, x*screenFont.width, y*screenFont.height, (x+1)*screenFont.width,
|
||||
(y+1)*screenFont.height, cx*screenFont.width, cy*screenFont.height,
|
||||
(cx+1)*screenFont.width, (cy+1)*screenFont.height, null)
|
||||
}
|
||||
|
||||
fun scrollUp() {
|
||||
g2d.copyArea(0, 16, ScreenDefs.SCREEN_WIDTH, ScreenDefs.SCREEN_HEIGHT-16, 0, -16)
|
||||
g2d.copyArea(0, screenFont.height,
|
||||
ScreenDefs.COLUMNS*screenFont.width, (ScreenDefs.ROWS-1)*screenFont.height,
|
||||
0, -screenFont.height)
|
||||
g2d.background = ScreenDefs.BG_COLOR
|
||||
g2d.clearRect(0, ScreenDefs.SCREEN_HEIGHT-16, ScreenDefs.SCREEN_WIDTH, 16)
|
||||
g2d.clearRect(0, (ScreenDefs.ROWS-1)*screenFont.height, ScreenDefs.COLUMNS*screenFont.width, screenFont.height)
|
||||
}
|
||||
|
||||
fun mousePixelPosition(): Point? {
|
||||
val pos = mousePosition ?: return null
|
||||
return Point((pos.x/ScreenDefs.PIXEL_SCALING).toInt(), (pos.y/ScreenDefs.PIXEL_SCALING).toInt())
|
||||
return Point((pos.x/pixelScaling).toInt(), (pos.y/pixelScaling).toInt())
|
||||
}
|
||||
|
||||
fun cursorPos(x: Int, y: Int) {
|
||||
|
@ -242,4 +224,8 @@ class MainWindow(title: String) : JFrame(title), KeyListener, MouseInputListener
|
|||
else keyboardBuffer.pop()
|
||||
}
|
||||
|
||||
fun reset() {
|
||||
// when the reset button is pressed
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ class EhBasicMachine(title: String) {
|
|||
val rom = Rom(0xc000, 0xffff).also { it.load(javaClass.getResourceAsStream("/ehbasic_C000.bin").readBytes()) }
|
||||
|
||||
private val hostDisplay = MainWindow(title)
|
||||
private val display = Display(0xd000, 0xd00a, hostDisplay, ScreenDefs.SCREEN_WIDTH_CHARS, ScreenDefs.SCREEN_HEIGHT_CHARS)
|
||||
private val display = Display(0xd000, 0xd00a, hostDisplay, ScreenDefs.COLUMNS, ScreenDefs.ROWS)
|
||||
private val keyboard = Keyboard(0xd400, 0xd400, hostDisplay)
|
||||
private var paused = false
|
||||
|
||||
|
@ -53,7 +53,7 @@ class EhBasicMachine(title: String) {
|
|||
Thread.sleep(200)
|
||||
} else {
|
||||
try {
|
||||
repeat(400) { step() }
|
||||
repeat(500) { step() }
|
||||
} catch (rx: RuntimeException) {
|
||||
JOptionPane.showMessageDialog(hostDisplay, "Run time error: $rx", "Error during execution", JOptionPane.ERROR_MESSAGE)
|
||||
break
|
||||
|
@ -61,7 +61,7 @@ class EhBasicMachine(title: String) {
|
|||
JOptionPane.showMessageDialog(hostDisplay, "Run time error: $ex", "Error during execution", JOptionPane.ERROR_MESSAGE)
|
||||
break
|
||||
}
|
||||
Thread.sleep(1)
|
||||
Thread.sleep(2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ class VirtualMachine(title: String) : IVirtualMachine {
|
|||
private val monitor = Monitor(bus, cpu)
|
||||
private val debugWindow = DebugWindow(this)
|
||||
private val hostDisplay = MainWindow(title)
|
||||
private val display = Display(0xd000, 0xd00a, hostDisplay, ScreenDefs.SCREEN_WIDTH_CHARS, ScreenDefs.SCREEN_HEIGHT_CHARS)
|
||||
private val display = Display(0xd000, 0xd00a, hostDisplay, ScreenDefs.COLUMNS, ScreenDefs.ROWS)
|
||||
private val mouse = Mouse(0xd300, 0xd305, hostDisplay)
|
||||
private val keyboard = Keyboard(0xd400, 0xd400, hostDisplay)
|
||||
private var paused = false
|
||||
|
@ -65,6 +65,11 @@ class VirtualMachine(title: String) : IVirtualMachine {
|
|||
while (cpu.instrCycles > 0) bus.clock()
|
||||
}
|
||||
|
||||
override fun reset() {
|
||||
bus.reset()
|
||||
hostDisplay.reset()
|
||||
}
|
||||
|
||||
override fun executeMonitorCommand(command: String) = monitor.command(command)
|
||||
|
||||
fun start() {
|
||||
|
@ -79,7 +84,7 @@ class VirtualMachine(title: String) : IVirtualMachine {
|
|||
Thread.sleep(200)
|
||||
} else {
|
||||
try {
|
||||
repeat(400) { step() }
|
||||
repeat(500) { step() }
|
||||
} catch (rx: RuntimeException) {
|
||||
JOptionPane.showMessageDialog(hostDisplay, "Run time error: $rx", "Error during execution", JOptionPane.ERROR_MESSAGE)
|
||||
break
|
||||
|
@ -87,7 +92,7 @@ class VirtualMachine(title: String) : IVirtualMachine {
|
|||
JOptionPane.showMessageDialog(hostDisplay, "Run time error: $ex", "Error during execution", JOptionPane.ERROR_MESSAGE)
|
||||
break
|
||||
}
|
||||
Thread.sleep(1)
|
||||
Thread.sleep(10)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
138
src/main/kotlin/razorvine/fonts/PsfFont.kt
Normal file
138
src/main/kotlin/razorvine/fonts/PsfFont.kt
Normal file
|
@ -0,0 +1,138 @@
|
|||
package razorvine.fonts
|
||||
|
||||
import java.awt.Color
|
||||
import java.awt.Graphics2D
|
||||
import java.awt.Transparency
|
||||
import java.awt.image.BufferedImage
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.io.IOException
|
||||
import java.util.zip.GZIPInputStream
|
||||
|
||||
|
||||
class PsfFont(name: String) {
|
||||
|
||||
// font format info: https://www.win.tue.nl/~aeb/linux/kbd/font-formats-1.html
|
||||
|
||||
val numChars: Int
|
||||
val bytesPerChar: Int
|
||||
val height: Int
|
||||
val width: Int
|
||||
private val hasUnicodeTable: Boolean
|
||||
private val rawBitmaps: List<ByteArray>
|
||||
|
||||
init {
|
||||
val data: ByteArray
|
||||
val fontsDirectory = "/usr/share/kbd/consolefonts"
|
||||
var stream = javaClass.getResourceAsStream("/charset/$name.psfu.gz") ?:
|
||||
javaClass.getResourceAsStream("/charset/$name.psf.gz") ?:
|
||||
(if(File("$fontsDirectory/$name.psfu.gz").exists()) FileInputStream("$fontsDirectory/$name.psfu.gz") else null ) ?:
|
||||
(if(File("$fontsDirectory/$name.psf.gz").exists()) FileInputStream("$fontsDirectory/$name.psf.gz") else null ) ?:
|
||||
(if(File("$fontsDirectory/$name.fnt.gz").exists()) FileInputStream("$fontsDirectory/$name.fnt.gz") else null )
|
||||
if(stream==null) {
|
||||
stream = javaClass.getResourceAsStream("/charset/$name.psfu") ?:
|
||||
javaClass.getResourceAsStream("/charset/$name.psf") ?:
|
||||
(if(File("$fontsDirectory/$name.psfu").exists()) FileInputStream("$fontsDirectory/$name.psfu") else null ) ?:
|
||||
(if(File("$fontsDirectory/$name.psf").exists()) FileInputStream("$fontsDirectory/$name.psf") else null ) ?:
|
||||
(if(File("$fontsDirectory/$name.fnt").exists()) FileInputStream("$fontsDirectory/$name.fnt") else null ) ?:
|
||||
throw IOException("no such font: $name")
|
||||
data = stream.readBytes()
|
||||
} else {
|
||||
GZIPInputStream(stream).use { data = it.readBytes() }
|
||||
}
|
||||
stream.close()
|
||||
|
||||
if (data[0] == 0x36.toByte() && data[1] == 0x04.toByte()) {
|
||||
// continue reading PSF1 font
|
||||
val mode = data[2].toInt()
|
||||
numChars = if (mode and 1 != 0) 512 else 256
|
||||
bytesPerChar = data[3].toInt()
|
||||
hasUnicodeTable = mode and 2 != 0
|
||||
height = bytesPerChar
|
||||
width = 8
|
||||
rawBitmaps = (0..numChars).map {
|
||||
data.sliceArray(3+it*bytesPerChar..3+(it+1)*bytesPerChar)
|
||||
}
|
||||
// ignore unicode table for now: val table = stream.readAllBytes()
|
||||
} else {
|
||||
if (data[0] == 0x72.toByte() && data[1] == 0xb5.toByte() && data[2] == 0x4a.toByte() && data[3] == 0x86.toByte()) {
|
||||
// continue reading PSF2 font
|
||||
// skip the version val version = makeInt(data, 4)
|
||||
val headersize = makeInt(data, 8)
|
||||
val flags = makeInt(data, 12)
|
||||
hasUnicodeTable = flags and 1 != 0
|
||||
numChars = makeInt(data, 16)
|
||||
bytesPerChar = makeInt(data, 20)
|
||||
height = makeInt(data, 24)
|
||||
width = makeInt(data, 28)
|
||||
rawBitmaps = (0..numChars).map {
|
||||
data.sliceArray(headersize+it*bytesPerChar..headersize+(it+1)*bytesPerChar)
|
||||
}
|
||||
} else {
|
||||
hasUnicodeTable = false
|
||||
numChars = 0
|
||||
bytesPerChar = 0
|
||||
height = 0
|
||||
width = 0
|
||||
rawBitmaps = emptyList()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun convertToImage(gfx: Graphics2D, textColor: Color): BufferedImage {
|
||||
// create a single image with all the characters in a vertical column from top to bottom.
|
||||
val bitmap = gfx.deviceConfiguration.createCompatibleImage((width+7) and 0b11111000, height*numChars, Transparency.BITMASK)
|
||||
val bytesHoriz = (width+7)/8
|
||||
val color = textColor.rgb
|
||||
val nopixel = Color(0, 0, 0, 0).rgb
|
||||
for (char in 0 until numChars) {
|
||||
for (b in 0 until bytesPerChar) {
|
||||
val c = rawBitmaps[char][b].toInt()
|
||||
val ix = 8*(b%bytesHoriz)
|
||||
val iy = b/bytesHoriz+char*height
|
||||
bitmap.setRGB(ix, iy, if (c and 0b10000000 != 0) color else nopixel)
|
||||
bitmap.setRGB(ix+1, iy, if (c and 0b01000000 != 0) color else nopixel)
|
||||
bitmap.setRGB(ix+2, iy, if (c and 0b00100000 != 0) color else nopixel)
|
||||
bitmap.setRGB(ix+3, iy, if (c and 0b00010000 != 0) color else nopixel)
|
||||
bitmap.setRGB(ix+4, iy, if (c and 0b00001000 != 0) color else nopixel)
|
||||
bitmap.setRGB(ix+5, iy, if (c and 0b00000100 != 0) color else nopixel)
|
||||
bitmap.setRGB(ix+6, iy, if (c and 0b00000010 != 0) color else nopixel)
|
||||
bitmap.setRGB(ix+7, iy, if (c and 0b00000001 != 0) color else nopixel)
|
||||
}
|
||||
}
|
||||
return bitmap
|
||||
}
|
||||
|
||||
private fun makeInt(bytes: ByteArray, offset: Int) =
|
||||
makeInt(bytes[offset], bytes[offset+1], bytes[offset+2], bytes[offset+3])
|
||||
private fun makeInt(b0: Byte, b1: Byte, b2: Byte, b3: Byte) =
|
||||
b0.toInt() or (b1.toInt() shl 8) or (b2.toInt() shl 16) or (b3.toInt() shl 24)
|
||||
}
|
||||
|
||||
|
||||
|
||||
// private fun loadFallbackCharacters(): Array<BufferedImage> {
|
||||
// val img = ImageIO.read(javaClass.getResourceAsStream("/charset/unscii8x16.png"))
|
||||
// val charactersImage = BufferedImage(img.width, img.height, BufferedImage.TYPE_INT_ARGB)
|
||||
// charactersImage.createGraphics().drawImage(img, 0, 0, null)
|
||||
//
|
||||
// val black = Color(0, 0, 0).rgb
|
||||
// val foreground = FG_COLOR.rgb
|
||||
// val nopixel = Color(0, 0, 0, 0).rgb
|
||||
// for (y in 0 until charactersImage.height) {
|
||||
// for (x in 0 until charactersImage.width) {
|
||||
// val col = charactersImage.getRGB(x, y)
|
||||
// if (col == black) charactersImage.setRGB(x, y, nopixel)
|
||||
// else charactersImage.setRGB(x, y, foreground)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// val numColumns = charactersImage.width/8
|
||||
// val charImages = (0..255).map {
|
||||
// val charX = it%numColumns
|
||||
// val charY = it/numColumns
|
||||
// charactersImage.getSubimage(charX*8, charY*16, 8, 16)
|
||||
// }
|
||||
//
|
||||
// return charImages.toTypedArray()
|
||||
// }
|
237
src/main/kotlin/razorvine/ksim65/Assembler.kt
Normal file
237
src/main/kotlin/razorvine/ksim65/Assembler.kt
Normal file
|
@ -0,0 +1,237 @@
|
|||
package razorvine.ksim65
|
||||
|
||||
import razorvine.ksim65.components.Address
|
||||
import razorvine.ksim65.components.MemMappedComponent
|
||||
|
||||
|
||||
class Assembler(cpu: Cpu6502, val memory: MemMappedComponent, initialStartAddress: Address? = null) {
|
||||
|
||||
companion object {
|
||||
fun parseRelativeToPC(relative: String, currentAddress: Int): Int {
|
||||
val rest = relative.substring(1).trim()
|
||||
if(rest.isNotEmpty()) {
|
||||
return when(rest[0]) {
|
||||
'-' -> currentAddress-parseNumber(rest.substring(1))
|
||||
'+' -> currentAddress+parseNumber(rest.substring(1))
|
||||
else -> throw NumberFormatException("invalid address syntax")
|
||||
}
|
||||
}
|
||||
return currentAddress
|
||||
}
|
||||
|
||||
fun parseNumber(number: String, decimalFirst: Boolean = false): Int {
|
||||
val num = number.trim()
|
||||
if (num.isBlank()) return 0
|
||||
if (decimalFirst && num[0].isDigit()) return num.toInt(10)
|
||||
return when (num[0]) {
|
||||
'$' -> num.substring(1).trimStart().toInt(16)
|
||||
'#' -> num.substring(1).trimStart().toInt(10)
|
||||
'%' -> num.substring(1).trimStart().toInt(2)
|
||||
else -> num.toInt(16)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private var startAddress = initialStartAddress ?: 0
|
||||
private var assembledSize = 0
|
||||
|
||||
private val instructions by lazy {
|
||||
val instr = cpu.instructions.withIndex().associate {
|
||||
Pair(it.value.mnemonic, it.value.mode) to it.index
|
||||
}.toMutableMap()
|
||||
instr[Pair("nop", Cpu6502.AddrMode.Imp)] = 0xea
|
||||
instr.toMap()
|
||||
}
|
||||
|
||||
class Result(val success: Boolean, val error: String, val startAddress: Address, val numBytes: Int)
|
||||
|
||||
fun assemble(lines: Iterable<String>): Result {
|
||||
for(line in lines) {
|
||||
val result = assemble(line)
|
||||
if(!result.success)
|
||||
return result
|
||||
assembledSize += result.numBytes
|
||||
}
|
||||
return Result(true, "", startAddress, assembledSize)
|
||||
}
|
||||
|
||||
fun assemble(line: String): Result {
|
||||
|
||||
/*
|
||||
The command is a line of the form:
|
||||
|
||||
"<address> <instruction> [<arguments>]"
|
||||
" <instruction> [<arguments>]"
|
||||
"* = <address>"
|
||||
*/
|
||||
|
||||
var args = line.trim().split(' ')
|
||||
if(args.isEmpty() || args.size == 1 && args[0] == "")
|
||||
return Result(true, "", startAddress, 0)
|
||||
if(args[0].startsWith("*=") && args.size==1) {
|
||||
startAddress = parseNumber(args[0].substring(2))
|
||||
return Result(true, "", startAddress, 0)
|
||||
}
|
||||
else if(args[0] == "*" && args[1] == "=") {
|
||||
startAddress = parseNumber(args[2])
|
||||
return Result(true, "", startAddress, 0)
|
||||
} else {
|
||||
// line with an instruction, may be preceded by a 4 or 5 char address
|
||||
if(args[0].length == 4 || args[0].length==5) {
|
||||
if(args.size!=2 && args.size !=3)
|
||||
return Result(false, "syntax error", startAddress, 0)
|
||||
startAddress = parseNumber(args[0])
|
||||
args = args.drop(1)
|
||||
}
|
||||
}
|
||||
|
||||
val instructionSize: Int
|
||||
val mnemonic = args[0].lowercase().trim()
|
||||
when (args.size) {
|
||||
1 -> {
|
||||
// implied or acc
|
||||
instructionSize = 1
|
||||
var instruction = instructions[Pair(mnemonic, Cpu6502.AddrMode.Imp)]
|
||||
if (instruction == null) instruction = instructions[Pair(mnemonic, Cpu6502.AddrMode.Acc)]
|
||||
if (instruction == null) return Result(false, "invalid instruction", this.startAddress, 0)
|
||||
memory[startAddress+assembledSize] = instruction.toShort()
|
||||
}
|
||||
2 -> {
|
||||
val arg = args[1]
|
||||
when {
|
||||
arg.startsWith('#') -> {
|
||||
// immediate
|
||||
val instruction = instructions[Pair(mnemonic, Cpu6502.AddrMode.Imm)] ?: return Result(false, "invalid instruction",
|
||||
this.startAddress, 0)
|
||||
memory[startAddress+assembledSize] = instruction.toShort()
|
||||
memory[startAddress+assembledSize+1] = parseNumber(arg.substring(1), decimalFirst = true).toShort()
|
||||
instructionSize = 2
|
||||
}
|
||||
arg.startsWith("(") && arg.endsWith(",x)") -> {
|
||||
// indirect X
|
||||
val indAddress = try {
|
||||
parseNumber(arg.substring(1, arg.length-3))
|
||||
} catch (x: NumberFormatException) {
|
||||
return Result(false, "invalid instruction", this.startAddress, 0)
|
||||
}
|
||||
val instruction = instructions[Pair(mnemonic, Cpu6502.AddrMode.IzX)] ?: return Result(false, "invalid instruction",
|
||||
this.startAddress, 0)
|
||||
memory[startAddress+assembledSize] = instruction.toShort()
|
||||
memory[startAddress+assembledSize+1] = indAddress.toShort()
|
||||
instructionSize = 2
|
||||
}
|
||||
arg.startsWith("(") && arg.endsWith("),y") -> {
|
||||
// indirect Y
|
||||
val indAddress = try {
|
||||
parseNumber(arg.substring(1, arg.length-3))
|
||||
} catch (x: NumberFormatException) {
|
||||
return Result(false, "invalid instruction", this.startAddress, 0)
|
||||
}
|
||||
val instruction = instructions[Pair(mnemonic, Cpu6502.AddrMode.IzY)] ?: return Result(false, "invalid instruction",
|
||||
this.startAddress, 0)
|
||||
memory[startAddress+assembledSize] = instruction.toShort()
|
||||
memory[startAddress+assembledSize+1] = indAddress.toShort()
|
||||
instructionSize = 2
|
||||
}
|
||||
arg.endsWith(",x") -> {
|
||||
// indexed X or zpIndexed X
|
||||
val indAddress = try {
|
||||
parseNumber(arg.substring(1, arg.length-2))
|
||||
} catch (x: NumberFormatException) {
|
||||
return Result(false, "invalid instruction", this.startAddress, 0)
|
||||
}
|
||||
instructionSize = if (indAddress <= 255) {
|
||||
val instruction = instructions[Pair(mnemonic, Cpu6502.AddrMode.ZpX)] ?: return Result(false, "invalid instruction",
|
||||
this.startAddress, 0)
|
||||
memory[startAddress+assembledSize] = instruction.toShort()
|
||||
memory[startAddress+assembledSize+1] = indAddress.toShort()
|
||||
2
|
||||
} else {
|
||||
val instruction = instructions[Pair(mnemonic, Cpu6502.AddrMode.AbsX)] ?: return Result(false, "invalid instruction",
|
||||
this.startAddress, 0)
|
||||
memory[startAddress+assembledSize] = instruction.toShort()
|
||||
memory[startAddress+assembledSize+1] = (indAddress and 255).toShort()
|
||||
memory[startAddress+assembledSize+2] = (indAddress ushr 8).toShort()
|
||||
3
|
||||
}
|
||||
}
|
||||
arg.endsWith(",y") -> {
|
||||
// indexed Y or zpIndexed Y
|
||||
val indAddress = try {
|
||||
parseNumber(arg.substring(1, arg.length-2))
|
||||
} catch (x: NumberFormatException) {
|
||||
return Result(false, "invalid instruction", this.startAddress, 0)
|
||||
}
|
||||
instructionSize = if (indAddress <= 255) {
|
||||
val instruction = instructions[Pair(mnemonic, Cpu6502.AddrMode.ZpY)] ?: return Result(false, "invalid instruction",
|
||||
this.startAddress, 0)
|
||||
memory[startAddress+assembledSize] = instruction.toShort()
|
||||
memory[startAddress+assembledSize+1] = indAddress.toShort()
|
||||
2
|
||||
} else {
|
||||
val instruction = instructions[Pair(mnemonic, Cpu6502.AddrMode.AbsY)] ?: return Result(false, "invalid instruction",
|
||||
this.startAddress, 0)
|
||||
memory[startAddress+assembledSize] = instruction.toShort()
|
||||
memory[startAddress+assembledSize+1] = (indAddress and 255).toShort()
|
||||
memory[startAddress+assembledSize+2] = (indAddress ushr 8).toShort()
|
||||
3
|
||||
}
|
||||
}
|
||||
arg.endsWith(")") -> {
|
||||
// indirect (jmp)
|
||||
val indAddress = try {
|
||||
parseNumber(arg.substring(1, arg.length-1))
|
||||
} catch (x: NumberFormatException) {
|
||||
return Result(false, "invalid instruction", this.startAddress, 0)
|
||||
}
|
||||
val instruction = instructions[Pair(mnemonic, Cpu6502.AddrMode.Ind)]
|
||||
?: return Result(false, "invalid instruction", this.startAddress, 0)
|
||||
memory[startAddress+assembledSize] = instruction.toShort()
|
||||
memory[startAddress+assembledSize+1] = (indAddress and 255).toShort()
|
||||
memory[startAddress+assembledSize+2] = (indAddress ushr 8).toShort()
|
||||
instructionSize = 3
|
||||
}
|
||||
else -> {
|
||||
val instr = instructions[Pair(mnemonic, Cpu6502.AddrMode.Rel)]
|
||||
if (instr != null) {
|
||||
// relative address
|
||||
val rel = try {
|
||||
parseRelativeToPC(arg, startAddress)
|
||||
} catch (x: NumberFormatException) {
|
||||
return Result(false, "invalid numeral", this.startAddress, 0)
|
||||
}
|
||||
memory[startAddress+assembledSize] = instr.toShort()
|
||||
memory[startAddress+assembledSize+1] = (rel-startAddress-2 and 255).toShort()
|
||||
instructionSize = 2
|
||||
} else {
|
||||
// absolute or absZp
|
||||
val absAddress = try {
|
||||
if(arg.startsWith('*')) parseRelativeToPC(arg, startAddress) else parseNumber(arg)
|
||||
} catch (x: NumberFormatException) {
|
||||
return Result(false, "invalid numeral", this.startAddress, 0)
|
||||
}
|
||||
val zpInstruction = instructions[Pair(mnemonic, Cpu6502.AddrMode.Zp)]
|
||||
instructionSize = if (absAddress <= 255 && zpInstruction != null) {
|
||||
memory[startAddress+assembledSize] = zpInstruction.toShort()
|
||||
memory[startAddress+assembledSize+1] = absAddress.toShort()
|
||||
2
|
||||
} else {
|
||||
val absInstr = instructions[Pair(mnemonic, Cpu6502.AddrMode.Abs)] ?: return Result(false, "invalid instruction",
|
||||
this.startAddress, 0)
|
||||
memory[startAddress+assembledSize] = absInstr.toShort()
|
||||
memory[startAddress+assembledSize+1] = (absAddress and 255).toShort()
|
||||
memory[startAddress+assembledSize+2] = (absAddress ushr 8).toShort()
|
||||
3
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else ->
|
||||
return Result(false, "syntax error", this.startAddress, 0)
|
||||
}
|
||||
|
||||
return Result(true, "", this.startAddress, instructionSize)
|
||||
}
|
||||
}
|
|
@ -12,7 +12,7 @@ import razorvine.ksim65.components.*
|
|||
* NOTE: currently the bus address mapping is STATIC: there is no possibility for Bank-switching.
|
||||
* (such as what the C-64 has; the ability to swap ROMs in and out of the address space).
|
||||
*/
|
||||
class Bus {
|
||||
open class Bus {
|
||||
|
||||
private val allComponents = mutableListOf<BusComponent>()
|
||||
private val memComponents = mutableListOf<MemMappedComponent>()
|
||||
|
@ -42,10 +42,10 @@ class Bus {
|
|||
* The first registered memory mapped component that listens to that address, will respond.
|
||||
* If no component is available, some CPUs generate a BUS ERROR but we return 0xff instead.
|
||||
*/
|
||||
fun read(address: Address): UByte {
|
||||
open fun read(address: Address): UByte {
|
||||
memComponents.forEach {
|
||||
if (address >= it.startAddress && address <= it.endAddress) {
|
||||
val data = it[address]
|
||||
val data = it[address - it.startAddress]
|
||||
require(data in 0..255) { "data at address $address must be a byte 0..255, but is $data" }
|
||||
return data
|
||||
}
|
||||
|
@ -57,13 +57,15 @@ class Bus {
|
|||
* Write a data byte to the given address.
|
||||
* All memory mapped components that are mapped to the address, will receive the data.
|
||||
*/
|
||||
fun write(address: Address, data: UByte) {
|
||||
open fun write(address: Address, data: UByte) {
|
||||
require(data in 0..255) { "data written to address $address must be a byte 0..255" }
|
||||
memComponents.forEach {
|
||||
if (address >= it.startAddress && address <= it.endAddress) it[address] = data
|
||||
if (address >= it.startAddress && address <= it.endAddress)
|
||||
it[address-it.startAddress] = data
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun memoryComponentFor(address: Address) =
|
||||
memComponents.first { it is MemoryComponent && address >= it.startAddress && address <= it.endAddress } as MemoryComponent
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -17,20 +17,20 @@ class Cpu65C02 : Cpu6502() {
|
|||
|
||||
/**
|
||||
* Process once clock cycle in the cpu
|
||||
* Use this if goal is cycle-perfect emulation.
|
||||
* Use this if you need cycle-perfect instruction timing simulation.
|
||||
*/
|
||||
override fun clock() {
|
||||
when (waiting) {
|
||||
Wait.Normal -> super.clock()
|
||||
Wait.Waiting -> {
|
||||
if (pendingInterrupt != null) {
|
||||
if (nmiAsserted || irqAsserted) {
|
||||
// continue execution after hardware interrupt
|
||||
waiting = Wait.Normal
|
||||
instrCycles = 1
|
||||
}
|
||||
}
|
||||
Wait.Stopped -> {
|
||||
if (pendingInterrupt != null) {
|
||||
if (nmiAsserted || irqAsserted) {
|
||||
// jump to reset vector after hardware interrupt
|
||||
regPC = readWord(RESET_vector)
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ class Cpu65C02 : Cpu6502() {
|
|||
|
||||
/**
|
||||
* Execute one single complete instruction.
|
||||
* Use this when the goal is emulation performance and not a cycle perfect system.
|
||||
* Use this when you don't care about clock cycle instruction timing simulation.
|
||||
*/
|
||||
override fun step() {
|
||||
totalCycles += instrCycles
|
||||
|
@ -103,7 +103,7 @@ class Cpu65C02 : Cpu6502() {
|
|||
}
|
||||
|
||||
override fun dispatchOpcode(opcode: Int): Boolean {
|
||||
when (opcode) {
|
||||
return when (opcode) {
|
||||
0x00 -> iBrk()
|
||||
0x01 -> iOra()
|
||||
0x02 -> iNop()
|
||||
|
@ -360,9 +360,8 @@ class Cpu65C02 : Cpu6502() {
|
|||
0xfd -> iSbc()
|
||||
0xfe -> iInc()
|
||||
0xff -> iBbs7()
|
||||
else -> { /* can't occur */ }
|
||||
else -> false /* can't occur */
|
||||
}
|
||||
return false // TODO determine if instructions can cause extra clock cycle
|
||||
}
|
||||
|
||||
// opcode list: http://www.oxyron.de/html/opcodesc02.html
|
||||
|
@ -624,33 +623,36 @@ class Cpu65C02 : Cpu6502() {
|
|||
/* fe */ Instruction("inc", AddrMode.AbsX, 7),
|
||||
/* ff */ Instruction("bbs7", AddrMode.Zpr, 5)).toTypedArray()
|
||||
|
||||
override fun iBrk() {
|
||||
// handle BRK ('software interrupt') or a real hardware IRQ
|
||||
val nmi = pendingInterrupt == Interrupt.NMI
|
||||
if (pendingInterrupt != null) {
|
||||
pushStackAddr(regPC-1)
|
||||
} else {
|
||||
regPC++
|
||||
pushStackAddr(regPC)
|
||||
}
|
||||
regP.B = pendingInterrupt == null
|
||||
override fun iBrk(): Boolean {
|
||||
// handle BRK ('software interrupt')
|
||||
regPC++
|
||||
pushStackAddr(regPC)
|
||||
regP.B = true
|
||||
pushStack(regP)
|
||||
regP.I = true // interrupts are now disabled
|
||||
regP.D = false // this is different from NMOS 6502
|
||||
regPC = readWord(if (nmi) NMI_vector else IRQ_vector)
|
||||
pendingInterrupt = null
|
||||
regPC = readWord(IRQ_vector)
|
||||
|
||||
// TODO prevent NMI from triggering immediately after IRQ/BRK... how does that work exactly?
|
||||
return false
|
||||
}
|
||||
|
||||
override fun iBit() {
|
||||
override fun handleInterrupt() {
|
||||
super.handleInterrupt()
|
||||
regP.D = false // this is different from NMOS 6502
|
||||
}
|
||||
|
||||
override fun iBit(): Boolean {
|
||||
val data = getFetched()
|
||||
regP.Z = (regA and data) == 0
|
||||
if (currentInstruction.mode != AddrMode.Imm) {
|
||||
regP.V = (data and 0b01000000) != 0
|
||||
regP.N = (data and 0b10000000) != 0
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun iAdc() {
|
||||
override fun iAdc(): Boolean {
|
||||
val value = getFetched()
|
||||
if (regP.D) {
|
||||
// BCD add
|
||||
|
@ -679,13 +681,14 @@ class Cpu65C02 : Cpu6502() {
|
|||
regP.C = tmp > 0xff
|
||||
regA = tmp and 0xff
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun iSbc() {
|
||||
override fun iSbc(operandOverride: Int?): Boolean {
|
||||
// see http://www.6502.org/tutorials/decimal_mode.html
|
||||
// and https://sourceforge.net/p/vice-emu/code/HEAD/tree/trunk/vice/src/65c02core.c#l1205
|
||||
// (the implementation below is based on the code used by Vice)
|
||||
val value = getFetched()
|
||||
val value = operandOverride ?: getFetched()
|
||||
var tmp = (regA-value-if (regP.C) 0 else 1) and 0xffff
|
||||
regP.V = (regA xor tmp) and (regA xor value) and 0b10000000 != 0
|
||||
if (regP.D) {
|
||||
|
@ -697,230 +700,323 @@ class Cpu65C02 : Cpu6502() {
|
|||
regP.Z = (tmp and 0xff) == 0
|
||||
regP.N = (tmp and 0b10000000) != 0
|
||||
regA = tmp and 0xff
|
||||
return false
|
||||
}
|
||||
|
||||
override fun iDec() {
|
||||
if (currentInstruction.mode == AddrMode.Acc) {
|
||||
override fun iDec(): Boolean {
|
||||
return if (currentInstruction.mode == AddrMode.Acc) {
|
||||
regA = (regA-1) and 0xff
|
||||
regP.Z = regA == 0
|
||||
regP.N = (regA and 0b10000000) != 0
|
||||
false
|
||||
} else super.iDec()
|
||||
}
|
||||
|
||||
override fun iInc() {
|
||||
if (currentInstruction.mode == AddrMode.Acc) {
|
||||
override fun iInc(): Boolean {
|
||||
return if (currentInstruction.mode == AddrMode.Acc) {
|
||||
regA = (regA+1) and 0xff
|
||||
regP.Z = regA == 0
|
||||
regP.N = (regA and 0b10000000) != 0
|
||||
false
|
||||
} else super.iInc()
|
||||
}
|
||||
|
||||
private fun iBra() {
|
||||
private fun iBra(): Boolean {
|
||||
// unconditional branch
|
||||
regPC = fetchedAddress
|
||||
return false
|
||||
}
|
||||
|
||||
private fun iTrb() {
|
||||
private fun iTrb(): Boolean {
|
||||
val data = getFetched()
|
||||
regP.Z = data and regA == 0
|
||||
write(fetchedAddress, data and regA.inv())
|
||||
return false
|
||||
}
|
||||
|
||||
private fun iTsb() {
|
||||
private fun iTsb(): Boolean {
|
||||
val data = getFetched()
|
||||
regP.Z = data and regA == 0
|
||||
write(fetchedAddress, data or regA)
|
||||
return false
|
||||
}
|
||||
|
||||
private fun iStz() {
|
||||
private fun iStz(): Boolean {
|
||||
write(fetchedAddress, 0)
|
||||
return false
|
||||
}
|
||||
|
||||
private fun iWai() {
|
||||
private fun iWai(): Boolean {
|
||||
waiting = Wait.Waiting
|
||||
return false
|
||||
}
|
||||
|
||||
private fun iStp() {
|
||||
private fun iStp(): Boolean {
|
||||
waiting = Wait.Stopped
|
||||
return false
|
||||
}
|
||||
|
||||
private fun iPhx() {
|
||||
private fun iPhx(): Boolean {
|
||||
pushStack(regX)
|
||||
return false
|
||||
}
|
||||
|
||||
private fun iPlx() {
|
||||
private fun iPlx(): Boolean {
|
||||
regX = popStack()
|
||||
regP.Z = regX == 0
|
||||
regP.N = (regX and 0b10000000) != 0
|
||||
return false
|
||||
}
|
||||
|
||||
private fun iPhy() {
|
||||
private fun iPhy(): Boolean {
|
||||
pushStack(regY)
|
||||
return false
|
||||
}
|
||||
|
||||
private fun iPly() {
|
||||
private fun iPly(): Boolean {
|
||||
regY = popStack()
|
||||
regP.Z = regY == 0
|
||||
regP.N = (regY and 0b10000000) != 0
|
||||
return false
|
||||
}
|
||||
|
||||
private fun iBbr0() {
|
||||
private fun iBbr0(): Boolean {
|
||||
val data = getFetched()
|
||||
if (data and 1 == 0) regPC = fetchedAddressZpr
|
||||
if (data and 1 == 0) {
|
||||
regPC = fetchedAddressZpr
|
||||
instrCycles++
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun iBbr1() {
|
||||
private fun iBbr1(): Boolean {
|
||||
val data = getFetched()
|
||||
if (data and 2 == 0) regPC = fetchedAddressZpr
|
||||
if (data and 2 == 0) {
|
||||
regPC = fetchedAddressZpr
|
||||
instrCycles++
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun iBbr2() {
|
||||
private fun iBbr2(): Boolean {
|
||||
val data = getFetched()
|
||||
if (data and 4 == 0) regPC = fetchedAddressZpr
|
||||
if (data and 4 == 0) {
|
||||
regPC = fetchedAddressZpr
|
||||
instrCycles++
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun iBbr3() {
|
||||
private fun iBbr3(): Boolean {
|
||||
val data = getFetched()
|
||||
if (data and 8 == 0) regPC = fetchedAddressZpr
|
||||
if (data and 8 == 0) {
|
||||
regPC = fetchedAddressZpr
|
||||
instrCycles++
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun iBbr4() {
|
||||
private fun iBbr4(): Boolean {
|
||||
val data = getFetched()
|
||||
if (data and 16 == 0) regPC = fetchedAddressZpr
|
||||
if (data and 16 == 0) {
|
||||
regPC = fetchedAddressZpr
|
||||
instrCycles++
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun iBbr5() {
|
||||
private fun iBbr5(): Boolean {
|
||||
val data = getFetched()
|
||||
if (data and 32 == 0) regPC = fetchedAddressZpr
|
||||
if (data and 32 == 0) {
|
||||
regPC = fetchedAddressZpr
|
||||
instrCycles++
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun iBbr6() {
|
||||
private fun iBbr6(): Boolean {
|
||||
val data = getFetched()
|
||||
if (data and 64 == 0) regPC = fetchedAddressZpr
|
||||
if (data and 64 == 0) {
|
||||
regPC = fetchedAddressZpr
|
||||
instrCycles++
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun iBbr7() {
|
||||
private fun iBbr7(): Boolean {
|
||||
val data = getFetched()
|
||||
if (data and 128 == 0) regPC = fetchedAddressZpr
|
||||
if (data and 128 == 0) {
|
||||
regPC = fetchedAddressZpr
|
||||
instrCycles++
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun iBbs0() {
|
||||
private fun iBbs0(): Boolean {
|
||||
val data = getFetched()
|
||||
if (data and 1 != 0) regPC = fetchedAddressZpr
|
||||
if (data and 1 != 0) {
|
||||
regPC = fetchedAddressZpr
|
||||
instrCycles++
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun iBbs1() {
|
||||
private fun iBbs1(): Boolean {
|
||||
val data = getFetched()
|
||||
if (data and 2 != 0) regPC = fetchedAddressZpr
|
||||
if (data and 2 != 0) {
|
||||
regPC = fetchedAddressZpr
|
||||
instrCycles++
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun iBbs2() {
|
||||
private fun iBbs2(): Boolean {
|
||||
val data = getFetched()
|
||||
if (data and 4 != 0) regPC = fetchedAddressZpr
|
||||
if (data and 4 != 0) {
|
||||
regPC = fetchedAddressZpr
|
||||
instrCycles++
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun iBbs3() {
|
||||
private fun iBbs3(): Boolean {
|
||||
val data = getFetched()
|
||||
if (data and 8 != 0) regPC = fetchedAddressZpr
|
||||
if (data and 8 != 0) {
|
||||
regPC = fetchedAddressZpr
|
||||
instrCycles++
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun iBbs4() {
|
||||
private fun iBbs4(): Boolean {
|
||||
val data = getFetched()
|
||||
if (data and 16 != 0) regPC = fetchedAddressZpr
|
||||
if (data and 16 != 0) {
|
||||
regPC = fetchedAddressZpr
|
||||
instrCycles++
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun iBbs5() {
|
||||
private fun iBbs5(): Boolean {
|
||||
val data = getFetched()
|
||||
if (data and 32 != 0) regPC = fetchedAddressZpr
|
||||
if (data and 32 != 0) {
|
||||
regPC = fetchedAddressZpr
|
||||
instrCycles++
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun iBbs6() {
|
||||
private fun iBbs6(): Boolean {
|
||||
val data = getFetched()
|
||||
if (data and 64 != 0) regPC = fetchedAddressZpr
|
||||
if (data and 64 != 0) {
|
||||
regPC = fetchedAddressZpr
|
||||
instrCycles++
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun iBbs7() {
|
||||
private fun iBbs7(): Boolean {
|
||||
val data = getFetched()
|
||||
if (data and 128 != 0) regPC = fetchedAddressZpr
|
||||
if (data and 128 != 0) {
|
||||
regPC = fetchedAddressZpr
|
||||
instrCycles++
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun iSmb0() {
|
||||
private fun iSmb0(): Boolean {
|
||||
val data = getFetched()
|
||||
write(fetchedAddress, data or 1)
|
||||
return false
|
||||
}
|
||||
|
||||
private fun iSmb1() {
|
||||
private fun iSmb1(): Boolean {
|
||||
val data = getFetched()
|
||||
write(fetchedAddress, data or 2)
|
||||
return false
|
||||
}
|
||||
|
||||
private fun iSmb2() {
|
||||
private fun iSmb2(): Boolean {
|
||||
val data = getFetched()
|
||||
write(fetchedAddress, data or 4)
|
||||
return false
|
||||
}
|
||||
|
||||
private fun iSmb3() {
|
||||
private fun iSmb3(): Boolean {
|
||||
val data = getFetched()
|
||||
write(fetchedAddress, data or 8)
|
||||
return false
|
||||
}
|
||||
|
||||
private fun iSmb4() {
|
||||
private fun iSmb4(): Boolean {
|
||||
val data = getFetched()
|
||||
write(fetchedAddress, data or 16)
|
||||
return false
|
||||
}
|
||||
|
||||
private fun iSmb5() {
|
||||
private fun iSmb5(): Boolean {
|
||||
val data = getFetched()
|
||||
write(fetchedAddress, data or 32)
|
||||
return false
|
||||
}
|
||||
|
||||
private fun iSmb6() {
|
||||
private fun iSmb6(): Boolean {
|
||||
val data = getFetched()
|
||||
write(fetchedAddress, data or 64)
|
||||
return false
|
||||
}
|
||||
|
||||
private fun iSmb7() {
|
||||
private fun iSmb7(): Boolean {
|
||||
val data = getFetched()
|
||||
write(fetchedAddress, data or 128)
|
||||
return false
|
||||
}
|
||||
|
||||
private fun iRmb0() {
|
||||
private fun iRmb0(): Boolean {
|
||||
val data = getFetched()
|
||||
write(fetchedAddress, data and 0b11111110)
|
||||
return false
|
||||
}
|
||||
|
||||
private fun iRmb1() {
|
||||
private fun iRmb1(): Boolean {
|
||||
val data = getFetched()
|
||||
write(fetchedAddress, data and 0b11111101)
|
||||
return false
|
||||
}
|
||||
|
||||
private fun iRmb2() {
|
||||
private fun iRmb2(): Boolean {
|
||||
val data = getFetched()
|
||||
write(fetchedAddress, data and 0b11111011)
|
||||
return false
|
||||
}
|
||||
|
||||
private fun iRmb3() {
|
||||
private fun iRmb3(): Boolean {
|
||||
val data = getFetched()
|
||||
write(fetchedAddress, data and 0b11110111)
|
||||
return false
|
||||
}
|
||||
|
||||
private fun iRmb4() {
|
||||
private fun iRmb4(): Boolean {
|
||||
val data = getFetched()
|
||||
write(fetchedAddress, data and 0b11101111)
|
||||
return false
|
||||
}
|
||||
|
||||
private fun iRmb5() {
|
||||
private fun iRmb5(): Boolean {
|
||||
val data = getFetched()
|
||||
write(fetchedAddress, data and 0b11011111)
|
||||
return false
|
||||
}
|
||||
|
||||
private fun iRmb6() {
|
||||
private fun iRmb6(): Boolean {
|
||||
val data = getFetched()
|
||||
write(fetchedAddress, data and 0b10111111)
|
||||
return false
|
||||
}
|
||||
|
||||
private fun iRmb7() {
|
||||
private fun iRmb7(): Boolean {
|
||||
val data = getFetched()
|
||||
write(fetchedAddress, data and 0b01111111)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
|
110
src/main/kotlin/razorvine/ksim65/Disassembler.kt
Normal file
110
src/main/kotlin/razorvine/ksim65/Disassembler.kt
Normal file
|
@ -0,0 +1,110 @@
|
|||
package razorvine.ksim65
|
||||
|
||||
import razorvine.ksim65.components.Address
|
||||
import razorvine.ksim65.components.UByte
|
||||
|
||||
|
||||
class Disassembler(cpu: Cpu6502) {
|
||||
|
||||
private val instructions = cpu.instructions
|
||||
|
||||
fun disassemble(memory: Array<UByte>, range: IntRange, baseAddress: Address): Pair<List<String>, Address> {
|
||||
var offset = range.first
|
||||
val result = mutableListOf<String>()
|
||||
while (offset <= range.last) {
|
||||
val dis = disassembleOneInstruction(memory, offset, baseAddress)
|
||||
result.add(dis.first)
|
||||
offset += dis.second
|
||||
}
|
||||
return Pair(result, offset+baseAddress)
|
||||
}
|
||||
|
||||
fun disassembleOneInstruction(memory: Array<UByte>, offset: Int, baseAddress: Address): Pair<String, Int> {
|
||||
val spacing1 = " "
|
||||
val spacing2 = " "
|
||||
val spacing3 = " "
|
||||
val byte = memory[offset]
|
||||
val line = "\$${hexW(offset+baseAddress)} ${hexB(byte)} "
|
||||
val opcode = instructions[byte.toInt()]
|
||||
return when (opcode.mode) {
|
||||
Cpu6502.AddrMode.Acc -> {
|
||||
Pair(line+"$spacing1 ${opcode.mnemonic} a", 1)
|
||||
}
|
||||
Cpu6502.AddrMode.Imp -> {
|
||||
Pair(line+"$spacing1 ${opcode.mnemonic}", 1)
|
||||
}
|
||||
Cpu6502.AddrMode.Imm -> {
|
||||
val value = memory[offset+1]
|
||||
Pair(line+"${hexB(value)} $spacing2 ${opcode.mnemonic} #\$${hexB(value)}", 2)
|
||||
}
|
||||
Cpu6502.AddrMode.Zp -> {
|
||||
val zpAddr = memory[offset+1]
|
||||
Pair(line+"${hexB(zpAddr)} $spacing2 ${opcode.mnemonic} \$${hexB(zpAddr)}", 2)
|
||||
}
|
||||
Cpu6502.AddrMode.Zpr -> {
|
||||
// addressing mode used by the 65C02, put here for convenience rather than the subclass
|
||||
val zpAddr = memory[offset+1]
|
||||
val rel = memory[offset+2]
|
||||
val target = (if (rel <= 0x7f) offset+3+rel+baseAddress else offset+3-(256-rel)+baseAddress) and 0xffff
|
||||
Pair(line+"${hexB(zpAddr)} ${hexB(rel)} $spacing3 ${opcode.mnemonic} \$${hexB(zpAddr)}, \$${hexW(target, true)}", 3)
|
||||
}
|
||||
Cpu6502.AddrMode.Izp -> {
|
||||
// addressing mode used by the 65C02, put here for convenience rather than the subclass
|
||||
val zpAddr = memory[offset+1]
|
||||
Pair(line+"${hexB(zpAddr)} $spacing2 ${opcode.mnemonic} \$(${hexB(zpAddr)})", 2)
|
||||
}
|
||||
Cpu6502.AddrMode.IaX -> {
|
||||
// addressing mode used by the 65C02, put here for convenience rather than the subclass
|
||||
val lo = memory[offset+1]
|
||||
val hi = memory[offset+2]
|
||||
val absAddr = lo.toInt() or (hi.toInt() shl 8)
|
||||
Pair(line+"${hexB(lo)} ${hexB(hi)} $spacing3 ${opcode.mnemonic} \$(${hexW(absAddr)},x)", 3)
|
||||
}
|
||||
Cpu6502.AddrMode.ZpX -> {
|
||||
val zpAddr = memory[offset+1]
|
||||
Pair(line+"${hexB(zpAddr)} $spacing2 ${opcode.mnemonic} \$${hexB(zpAddr)},x", 2)
|
||||
}
|
||||
Cpu6502.AddrMode.ZpY -> {
|
||||
val zpAddr = memory[offset+1]
|
||||
Pair(line+"${hexB(zpAddr)} $spacing2 ${opcode.mnemonic} \$${hexB(zpAddr)},y", 2)
|
||||
}
|
||||
Cpu6502.AddrMode.Rel -> {
|
||||
val rel = memory[offset+1]
|
||||
val target = (if (rel <= 0x7f) offset+2+rel+baseAddress else offset+2-(256-rel)+baseAddress) and 0xffff
|
||||
Pair(line+"${hexB(rel)} $spacing2 ${opcode.mnemonic} \$${hexW(target, true)}", 2)
|
||||
}
|
||||
Cpu6502.AddrMode.Abs -> {
|
||||
val lo = memory[offset+1]
|
||||
val hi = memory[offset+2]
|
||||
val absAddr = lo.toInt() or (hi.toInt() shl 8)
|
||||
Pair(line+"${hexB(lo)} ${hexB(hi)} $spacing3 ${opcode.mnemonic} \$${hexW(absAddr)}", 3)
|
||||
}
|
||||
Cpu6502.AddrMode.AbsX -> {
|
||||
val lo = memory[offset+1]
|
||||
val hi = memory[offset+2]
|
||||
val absAddr = lo.toInt() or (hi.toInt() shl 8)
|
||||
Pair(line+"${hexB(lo)} ${hexB(hi)} $spacing3 ${opcode.mnemonic} \$${hexW(absAddr)},x", 3)
|
||||
}
|
||||
Cpu6502.AddrMode.AbsY -> {
|
||||
val lo = memory[offset+1]
|
||||
val hi = memory[offset+2]
|
||||
val absAddr = lo.toInt() or (hi.toInt() shl 8)
|
||||
Pair(line+"${hexB(lo)} ${hexB(hi)} $spacing3 ${opcode.mnemonic} \$${hexW(absAddr)},y", 3)
|
||||
}
|
||||
Cpu6502.AddrMode.Ind -> {
|
||||
val lo = memory[offset+1]
|
||||
val hi = memory[offset+2]
|
||||
val indirectAddr = lo.toInt() or (hi.toInt() shl 8)
|
||||
Pair(line+"${hexB(lo)} ${hexB(hi)} $spacing3 ${opcode.mnemonic} (\$${hexW(indirectAddr)})", 3)
|
||||
}
|
||||
Cpu6502.AddrMode.IzX -> {
|
||||
val zpAddr = memory[offset+1]
|
||||
Pair(line+"${hexB(zpAddr)} $spacing2 ${opcode.mnemonic} (\$${hexB(zpAddr)},x)", 2)
|
||||
}
|
||||
Cpu6502.AddrMode.IzY -> {
|
||||
val zpAddr = memory[offset+1]
|
||||
Pair(line+"${hexB(zpAddr)} $spacing2 ${opcode.mnemonic} (\$${hexB(zpAddr)}),y", 2)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@ import java.io.File
|
|||
interface IVirtualMachine {
|
||||
fun step()
|
||||
fun pause(paused: Boolean)
|
||||
fun reset()
|
||||
fun getZeroAndStackPages(): Array<UByte>
|
||||
fun loadFileInRam(file: File, loadAddress: Address?)
|
||||
|
||||
|
|
|
@ -1,14 +1,10 @@
|
|||
package razorvine.ksim65
|
||||
|
||||
import kotlin.math.max
|
||||
|
||||
class Monitor(val bus: Bus, val cpu: Cpu6502) {
|
||||
|
||||
private val instructions by lazy {
|
||||
val instr = cpu.instructions.withIndex().associate {
|
||||
Pair(it.value.mnemonic, it.value.mode) to it.index
|
||||
}.toMutableMap()
|
||||
instr[Pair("nop", Cpu6502.AddrMode.Imp)] = 0xea
|
||||
instr.toMap()
|
||||
}
|
||||
private val disassembler = Disassembler(cpu)
|
||||
|
||||
fun command(command: String): IVirtualMachine.MonitorCmdResult {
|
||||
if (command.isEmpty()) return IVirtualMachine.MonitorCmdResult("", "", false)
|
||||
|
@ -22,9 +18,9 @@ class Monitor(val bus: Bus, val cpu: Cpu6502) {
|
|||
val parts = command.substring(1).trim().split(' ')
|
||||
if (parts.size != 3) IVirtualMachine.MonitorCmdResult("?syntax error", command, false)
|
||||
else {
|
||||
val start = parseNumber(parts[0])
|
||||
val end = parseNumber(parts[1])
|
||||
val value = parseNumber(parts[2]).toShort()
|
||||
val start = Assembler.parseNumber(parts[0])
|
||||
val end = Assembler.parseNumber(parts[1])
|
||||
val value = Assembler.parseNumber(parts[2]).toShort()
|
||||
for (addr in start..end) {
|
||||
bus.write(addr, value)
|
||||
}
|
||||
|
@ -33,12 +29,12 @@ class Monitor(val bus: Bus, val cpu: Cpu6502) {
|
|||
}
|
||||
'm' -> {
|
||||
val addresses = command.substring(1).trim().split(' ')
|
||||
val start = parseNumber(addresses[0])
|
||||
val end = if (addresses.size > 1) parseNumber(addresses[1]) else start+1
|
||||
val start = Assembler.parseNumber(addresses[0])
|
||||
val end = if (addresses.size > 1) Assembler.parseNumber(addresses[1]) else start+1
|
||||
val result = mutableListOf<String>()
|
||||
for (addr in start until end step 16) {
|
||||
result.add("m$${hexW(addr)} "+(0..15).joinToString(" ") { hexB(bus.read(addr+it)) }+" "+(0..15).joinToString("") {
|
||||
val chr = bus.read(addr+it).toChar()
|
||||
val chr = bus.read(addr+it).toInt().toChar()
|
||||
if (chr.isLetterOrDigit()) chr.toString()
|
||||
else "."
|
||||
})
|
||||
|
@ -47,19 +43,19 @@ class Monitor(val bus: Bus, val cpu: Cpu6502) {
|
|||
}
|
||||
'p' -> {
|
||||
val numbers = command.substring(1).trim().split(' ')
|
||||
val address = parseNumber(numbers[0])
|
||||
val values = numbers.drop(1).map { parseNumber(it) }
|
||||
val address = Assembler.parseNumber(numbers[0])
|
||||
val values = numbers.drop(1).map { Assembler.parseNumber(it) }
|
||||
values.forEachIndexed { index, i -> bus.write(address+index, i.toShort()) }
|
||||
IVirtualMachine.MonitorCmdResult("ok", "", true)
|
||||
}
|
||||
'i' -> {
|
||||
val addresses = command.substring(1).trim().split(' ')
|
||||
val start = parseNumber(addresses[0])
|
||||
val end = if (addresses.size > 1) parseNumber(addresses[1]) else start+1
|
||||
val start = Assembler.parseNumber(addresses[0])
|
||||
val end = if (addresses.size > 1) Assembler.parseNumber(addresses[1]) else start+1
|
||||
val result = mutableListOf<String>()
|
||||
for (addr in start until end step 64) {
|
||||
result.add("i$${hexW(addr)} "+(0..63).joinToString("") {
|
||||
val chr = bus.read(addr+it).toChar()
|
||||
val chr = bus.read(addr+it).toInt().toChar()
|
||||
if (chr.isLetterOrDigit()) chr.toString()
|
||||
else "."
|
||||
})
|
||||
|
@ -67,34 +63,44 @@ class Monitor(val bus: Bus, val cpu: Cpu6502) {
|
|||
IVirtualMachine.MonitorCmdResult(result.joinToString("\n"), "", true)
|
||||
}
|
||||
'$' -> {
|
||||
val number = parseNumber(command)
|
||||
val number = Assembler.parseNumber(command)
|
||||
val output = "$${hexW(number)} #$number %${number.toString(2)}"
|
||||
IVirtualMachine.MonitorCmdResult(output, "", true)
|
||||
}
|
||||
'#' -> {
|
||||
val number = parseNumber(command)
|
||||
val number = Assembler.parseNumber(command)
|
||||
val output = "$${hexW(number)} #$number %${number.toString(2)}"
|
||||
IVirtualMachine.MonitorCmdResult(output, "", true)
|
||||
}
|
||||
'%' -> {
|
||||
val number = parseNumber(command)
|
||||
val number = Assembler.parseNumber(command)
|
||||
val output = "$${hexW(number)} #$number %${number.toString(2)}"
|
||||
IVirtualMachine.MonitorCmdResult(output, "", true)
|
||||
}
|
||||
'g' -> {
|
||||
val address = parseNumber(command.substring(1))
|
||||
val address = Assembler.parseNumber(command.substring(1))
|
||||
cpu.regPC = address
|
||||
IVirtualMachine.MonitorCmdResult("", "", true)
|
||||
}
|
||||
'a' -> {
|
||||
val parts = command.substring(1).trim().split(' ')
|
||||
assemble(command, parts)
|
||||
val address = if(parts.size>=2) Assembler.parseNumber(parts[0]) else 0
|
||||
val assembler = Assembler(cpu, bus.memoryComponentFor(address), address)
|
||||
val result = assembler.assemble(command.substring(1).trimStart())
|
||||
if(result.success) {
|
||||
val memory = (result.startAddress..result.startAddress+result.numBytes).map { bus[it] }.toTypedArray()
|
||||
val d = disassembler.disassembleOneInstruction(memory, 0, result.startAddress)
|
||||
IVirtualMachine.MonitorCmdResult(d.first, "a$${hexW(result.startAddress+result.numBytes)} ", false)
|
||||
}
|
||||
else
|
||||
IVirtualMachine.MonitorCmdResult(result.error, command, false)
|
||||
}
|
||||
'd' -> {
|
||||
val addresses = command.substring(1).trim().split(' ')
|
||||
val start = parseNumber(addresses[0])
|
||||
val end = if (addresses.size > 1) parseNumber(addresses[1]) else start
|
||||
val disassem = cpu.disassemble(bus.memoryComponentFor(start), start, end)
|
||||
val start = Assembler.parseNumber(addresses[0])
|
||||
val end = if (addresses.size > 1) Assembler.parseNumber(addresses[1]) else start
|
||||
val memory = (start .. max(0xffff, end+3)).map {bus[it]}.toTypedArray()
|
||||
val disassem = disassembler.disassemble(memory, 0 .. end-start, start)
|
||||
IVirtualMachine.MonitorCmdResult(disassem.first.joinToString("\n") { "d$it" }, "d$${hexW(disassem.second)}", false)
|
||||
}
|
||||
else -> {
|
||||
|
@ -102,153 +108,4 @@ class Monitor(val bus: Bus, val cpu: Cpu6502) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun assemble(command: String, parts: List<String>): IVirtualMachine.MonitorCmdResult {
|
||||
if (parts.size < 2) return IVirtualMachine.MonitorCmdResult("done", "", false)
|
||||
|
||||
val address = parseNumber(parts[0])
|
||||
val mnemonic = parts[1].toLowerCase()
|
||||
when (parts.size) {
|
||||
2 -> {
|
||||
// implied or acc
|
||||
var instruction = instructions[Pair(mnemonic, Cpu6502.AddrMode.Imp)]
|
||||
if (instruction == null) instruction = instructions[Pair(mnemonic, Cpu6502.AddrMode.Acc)]
|
||||
if (instruction == null) return IVirtualMachine.MonitorCmdResult("?invalid instruction", command, false)
|
||||
bus.write(address, instruction.toShort())
|
||||
}
|
||||
3 -> {
|
||||
val arg = parts[2]
|
||||
when {
|
||||
arg.startsWith('#') -> {
|
||||
// immediate
|
||||
val instruction = instructions[Pair(mnemonic, Cpu6502.AddrMode.Imm)] ?: return IVirtualMachine.MonitorCmdResult("?invalid instruction", command, false)
|
||||
bus.write(address, instruction.toShort())
|
||||
bus.write(address+1, parseNumber(arg.substring(1), true).toShort())
|
||||
}
|
||||
arg.startsWith("(") && arg.endsWith(",x)") -> {
|
||||
// indirect X
|
||||
val indAddress = try {
|
||||
parseNumber(arg.substring(1, arg.length-3))
|
||||
} catch (x: NumberFormatException) {
|
||||
return IVirtualMachine.MonitorCmdResult("?invalid instruction", command, false)
|
||||
}
|
||||
val instruction = instructions[Pair(mnemonic, Cpu6502.AddrMode.IzX)] ?: return IVirtualMachine.MonitorCmdResult("?invalid instruction", command, false)
|
||||
bus.write(address, instruction.toShort())
|
||||
bus.write(address+1, indAddress.toShort())
|
||||
}
|
||||
arg.startsWith("(") && arg.endsWith("),y") -> {
|
||||
// indirect Y
|
||||
val indAddress = try {
|
||||
parseNumber(arg.substring(1, arg.length-3))
|
||||
} catch (x: NumberFormatException) {
|
||||
return IVirtualMachine.MonitorCmdResult("?invalid instruction", command, false)
|
||||
}
|
||||
val instruction = instructions[Pair(mnemonic, Cpu6502.AddrMode.IzY)] ?: return IVirtualMachine.MonitorCmdResult("?invalid instruction", command, false)
|
||||
bus.write(address, instruction.toShort())
|
||||
bus.write(address+1, indAddress.toShort())
|
||||
}
|
||||
arg.endsWith(",x") -> {
|
||||
// indexed X or zpIndexed X
|
||||
val indAddress = try {
|
||||
parseNumber(arg.substring(1, arg.length-2))
|
||||
} catch (x: NumberFormatException) {
|
||||
return IVirtualMachine.MonitorCmdResult("?invalid instruction", command, false)
|
||||
}
|
||||
if (indAddress <= 255) {
|
||||
val instruction = instructions[Pair(mnemonic, Cpu6502.AddrMode.ZpX)] ?: return IVirtualMachine.MonitorCmdResult(
|
||||
"?invalid instruction", command, false)
|
||||
bus.write(address, instruction.toShort())
|
||||
bus.write(address+1, indAddress.toShort())
|
||||
} else {
|
||||
val instruction =
|
||||
instructions[Pair(mnemonic, Cpu6502.AddrMode.AbsX)] ?: return IVirtualMachine.MonitorCmdResult("?invalid instruction", command, false)
|
||||
bus.write(address, instruction.toShort())
|
||||
bus.write(address+1, (indAddress and 255).toShort())
|
||||
bus.write(address+2, (indAddress ushr 8).toShort())
|
||||
}
|
||||
}
|
||||
arg.endsWith(",y") -> {
|
||||
// indexed Y or zpIndexed Y
|
||||
val indAddress = try {
|
||||
parseNumber(arg.substring(1, arg.length-2))
|
||||
} catch (x: NumberFormatException) {
|
||||
return IVirtualMachine.MonitorCmdResult("?invalid instruction", command, false)
|
||||
}
|
||||
if (indAddress <= 255) {
|
||||
val instruction = instructions[Pair(mnemonic, Cpu6502.AddrMode.ZpY)] ?: return IVirtualMachine.MonitorCmdResult(
|
||||
"?invalid instruction", command, false)
|
||||
bus.write(address, instruction.toShort())
|
||||
bus.write(address+1, indAddress.toShort())
|
||||
} else {
|
||||
val instruction =
|
||||
instructions[Pair(mnemonic, Cpu6502.AddrMode.AbsY)] ?: return IVirtualMachine.MonitorCmdResult("?invalid instruction", command, false)
|
||||
bus.write(address, instruction.toShort())
|
||||
bus.write(address+1, (indAddress and 255).toShort())
|
||||
bus.write(address+2, (indAddress ushr 8).toShort())
|
||||
}
|
||||
}
|
||||
arg.endsWith(")") -> {
|
||||
// indirect (jmp)
|
||||
val indAddress = try {
|
||||
parseNumber(arg.substring(1, arg.length-1))
|
||||
} catch (x: NumberFormatException) {
|
||||
return IVirtualMachine.MonitorCmdResult("?invalid instruction", command, false)
|
||||
}
|
||||
val instruction = instructions[Pair(mnemonic, Cpu6502.AddrMode.Ind)] ?: return IVirtualMachine.MonitorCmdResult("?invalid instruction", command, false)
|
||||
bus.write(address, instruction.toShort())
|
||||
bus.write(address+1, (indAddress and 255).toShort())
|
||||
bus.write(address+2, (indAddress ushr 8).toShort())
|
||||
}
|
||||
else -> {
|
||||
val instr = instructions[Pair(mnemonic, Cpu6502.AddrMode.Rel)]
|
||||
if (instr != null) {
|
||||
// relative address
|
||||
val rel = try {
|
||||
parseNumber(arg)
|
||||
} catch (x: NumberFormatException) {
|
||||
return IVirtualMachine.MonitorCmdResult("?invalid instruction", command, false)
|
||||
}
|
||||
bus.write(address, instr.toShort())
|
||||
bus.write(address+1, (rel-address-2 and 255).toShort())
|
||||
} else {
|
||||
// absolute or absZp
|
||||
val absAddress = try {
|
||||
parseNumber(arg)
|
||||
} catch (x: NumberFormatException) {
|
||||
return IVirtualMachine.MonitorCmdResult("?invalid instruction", command, false)
|
||||
}
|
||||
if (absAddress <= 255) {
|
||||
val absInstr = instructions[Pair(mnemonic, Cpu6502.AddrMode.Zp)] ?: return IVirtualMachine.MonitorCmdResult(
|
||||
"?invalid instruction", command, false)
|
||||
bus.write(address, absInstr.toShort())
|
||||
bus.write(address+1, absAddress.toShort())
|
||||
} else {
|
||||
val absInstr =
|
||||
instructions[Pair(mnemonic, Cpu6502.AddrMode.Abs)] ?: return IVirtualMachine.MonitorCmdResult("?invalid instruction", command, false)
|
||||
bus.write(address, absInstr.toShort())
|
||||
bus.write(address+1, (absAddress and 255).toShort())
|
||||
bus.write(address+2, (absAddress ushr 8).toShort())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> return IVirtualMachine.MonitorCmdResult("?syntax error", command, false)
|
||||
}
|
||||
|
||||
val disassem = cpu.disassemble(bus.memoryComponentFor(address), address, address)
|
||||
return IVirtualMachine.MonitorCmdResult(disassem.first.single(), "a$${hexW(disassem.second)} ", false)
|
||||
}
|
||||
|
||||
private fun parseNumber(number: String, decimalFirst: Boolean = false): Int {
|
||||
val num = number.trim()
|
||||
if (num.isBlank()) return 0
|
||||
if (decimalFirst && num[0].isDigit()) return num.toInt(10)
|
||||
return when (num[0]) {
|
||||
'$' -> num.substring(1).trimStart().toInt(16)
|
||||
'#' -> num.substring(1).trimStart().toInt(10)
|
||||
'%' -> num.substring(1).trimStart().toInt(2)
|
||||
else -> num.toInt(16)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,20 +2,16 @@ package razorvine.ksim65
|
|||
|
||||
import razorvine.ksim65.components.Address
|
||||
|
||||
fun hexW(number: Address, allowSingleByte: Boolean = false): String {
|
||||
val msb = number ushr 8
|
||||
val lsb = number and 0xff
|
||||
return if (msb == 0 && allowSingleByte) hexB(lsb)
|
||||
else hexB(msb)+hexB(lsb)
|
||||
}
|
||||
fun hexW(number: Int, allowSingleByte: Boolean = false) =
|
||||
if(allowSingleByte && (number and 0xff00 == 0)) {
|
||||
number.toString(16).padStart(2, '0')
|
||||
} else {
|
||||
number.toString(16).padStart(4, '0')
|
||||
}
|
||||
|
||||
fun hexB(number: Short): String = hexB(number.toInt())
|
||||
|
||||
fun hexB(number: Int): String {
|
||||
val hexdigits = "0123456789abcdef"
|
||||
val loNibble = number and 15
|
||||
val hiNibble = number ushr 4
|
||||
return hexdigits[hiNibble].toString()+hexdigits[loNibble]
|
||||
}
|
||||
fun hexB(number: Int) = number.toString(16).padStart(2, '0')
|
||||
|
||||
fun hexB(number: Short) = hexB(number.toInt())
|
||||
|
||||
typealias BreakpointHandler = (cpu: Cpu6502, pc: Address) -> Cpu6502.BreakpointResultAction
|
||||
|
|
|
@ -28,8 +28,8 @@ abstract class BusComponent {
|
|||
* Most I/O components fall into this category.
|
||||
*/
|
||||
abstract class MemMappedComponent(val startAddress: Address, val endAddress: Address) : BusComponent() {
|
||||
abstract operator fun get(address: Address): UByte
|
||||
abstract operator fun set(address: Address, data: UByte)
|
||||
abstract operator fun get(offset: Int): UByte
|
||||
abstract operator fun set(offset: Int, data: UByte)
|
||||
|
||||
init {
|
||||
require(endAddress >= startAddress)
|
||||
|
@ -39,13 +39,13 @@ abstract class MemMappedComponent(val startAddress: Address, val endAddress: Add
|
|||
fun hexDump(from: Address, to: Address, charmapper: ((Short) -> Char)? = null) {
|
||||
(from..to).chunked(16).forEach {
|
||||
print("\$${it.first().toString(16).padStart(4, '0')} ")
|
||||
val bytes = it.map { address -> get(address) }
|
||||
val bytes = it.map { address -> get(address - startAddress) }
|
||||
bytes.forEach { byte ->
|
||||
print(byte.toString(16).padStart(2, '0')+" ")
|
||||
}
|
||||
print(" ")
|
||||
val chars = if (charmapper != null) bytes.map { b -> charmapper(b) }
|
||||
else bytes.map { b -> if (b in 32..255) b.toChar() else '.' }
|
||||
else bytes.map { b -> if (b in 32..255) b.toInt().toChar() else '.' }
|
||||
println(chars.joinToString(""))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ class Display(startAddress: Address, endAddress: Address, private val host: IHos
|
|||
}
|
||||
|
||||
override fun reset() {
|
||||
charMatrix.forEach { it.fill(' '.toShort()) }
|
||||
charMatrix.forEach { it.fill(' '.code.toShort()) }
|
||||
cursorX = 0
|
||||
cursorY = 0
|
||||
charposX = 0
|
||||
|
@ -62,8 +62,8 @@ class Display(startAddress: Address, endAddress: Address, private val host: IHos
|
|||
host.clearScreen()
|
||||
}
|
||||
|
||||
override operator fun get(address: Address): UByte {
|
||||
return when (address-startAddress) {
|
||||
override operator fun get(offset: Int): UByte {
|
||||
return when (offset) {
|
||||
0x00 -> charposX.toShort()
|
||||
0x01 -> charposY.toShort()
|
||||
0x02 -> {
|
||||
|
@ -87,14 +87,14 @@ class Display(startAddress: Address, endAddress: Address, private val host: IHos
|
|||
}
|
||||
}
|
||||
|
||||
override operator fun set(address: Address, data: UByte) {
|
||||
when (address-startAddress) {
|
||||
override operator fun set(offset: Int, data: UByte) {
|
||||
when (offset) {
|
||||
0x00 -> charposX = data.toInt()
|
||||
0x01 -> charposY = data.toInt()
|
||||
0x02 -> {
|
||||
if (charposY in 0 until charHeight && charposX in 0 until charWidth) {
|
||||
charMatrix[charposY][charposX] = data
|
||||
host.setChar(charposX, charposY, data.toChar())
|
||||
host.setChar(charposX, charposY, data.toInt().toChar())
|
||||
}
|
||||
}
|
||||
0x03 -> pixelX = (pixelX and 0xff00) or data.toInt()
|
||||
|
@ -102,7 +102,7 @@ class Display(startAddress: Address, endAddress: Address, private val host: IHos
|
|||
0x05 -> pixelY = (pixelY and 0xff00) or data.toInt()
|
||||
0x06 -> pixelY = (pixelY and 0x00ff) or (data.toInt() shl 8)
|
||||
0x07 -> {
|
||||
if (pixelX in 0 until ScreenDefs.SCREEN_WIDTH && pixelY in 0 until ScreenDefs.SCREEN_HEIGHT) {
|
||||
if (pixelX in 0 until ScreenDefs.COLUMNS*charWidth && pixelY in 0 until ScreenDefs.ROWS*charHeight) {
|
||||
if (data == 0.toShort()) host.clearPixel(pixelX, pixelY)
|
||||
else host.setPixel(pixelX, pixelY)
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ class Display(startAddress: Address, endAddress: Address, private val host: IHos
|
|||
cursorX = charWidth-1
|
||||
}
|
||||
}
|
||||
charMatrix[cursorY][cursorX] = ' '.toShort()
|
||||
charMatrix[cursorY][cursorX] = ' '.code.toShort()
|
||||
host.setChar(cursorX, cursorY, ' ')
|
||||
}
|
||||
0x09 -> {
|
||||
|
@ -142,7 +142,7 @@ class Display(startAddress: Address, endAddress: Address, private val host: IHos
|
|||
else -> {
|
||||
// set character on screen
|
||||
charMatrix[cursorY][cursorX] = data
|
||||
host.setChar(cursorX, cursorY, data.toChar())
|
||||
host.setChar(cursorX, cursorY, data.toInt().toChar())
|
||||
cursorX++
|
||||
if (cursorX >= charWidth) {
|
||||
cursorX = 0
|
||||
|
@ -164,7 +164,7 @@ class Display(startAddress: Address, endAddress: Address, private val host: IHos
|
|||
charMatrix[y+1].copyInto(charMatrix[y])
|
||||
}
|
||||
for (x in 0 until charWidth) {
|
||||
charMatrix[charHeight-1][x] = ' '.toShort()
|
||||
charMatrix[charHeight-1][x] = ' '.code.toShort()
|
||||
}
|
||||
cursorY--
|
||||
host.scrollUp()
|
||||
|
|
|
@ -23,13 +23,12 @@ class Keyboard(startAddress: Address, endAddress: Address, private val host: IHo
|
|||
override fun clock() {}
|
||||
override fun reset() {}
|
||||
|
||||
override operator fun get(address: Address): UByte {
|
||||
return when (address-startAddress) {
|
||||
0x00 -> host.keyboard()?.toShort() ?: 0
|
||||
override operator fun get(offset: Int): UByte {
|
||||
return when (offset) {
|
||||
0x00 -> host.keyboard()?.code?.toShort() ?: 0
|
||||
else -> 0xff
|
||||
}
|
||||
}
|
||||
|
||||
override operator fun set(address: Address, data: UByte) { /* read-only device */
|
||||
}
|
||||
override operator fun set(offset: Int, data: UByte) { /* read-only device */ }
|
||||
}
|
||||
|
|
|
@ -25,8 +25,8 @@ class Mouse(startAddress: Address, endAddress: Address, private val host: IHostI
|
|||
|
||||
private var mouse = host.mouse()
|
||||
|
||||
override operator fun get(address: Address): UByte {
|
||||
return when (address-startAddress) {
|
||||
override operator fun get(offset: Int): UByte {
|
||||
return when (offset) {
|
||||
0x00 -> (mouse.x and 0xff).toShort()
|
||||
0x01 -> (mouse.x ushr 8).toShort()
|
||||
0x02 -> (mouse.y and 0xff).toShort()
|
||||
|
@ -41,7 +41,7 @@ class Mouse(startAddress: Address, endAddress: Address, private val host: IHostI
|
|||
}
|
||||
}
|
||||
|
||||
override operator fun set(address: Address, data: UByte) {
|
||||
if (address-startAddress == 0x05) mouse = host.mouse()
|
||||
override operator fun set(offset: Int, data: UByte) {
|
||||
if (offset == 0x05) mouse = host.mouse()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,16 +18,16 @@ class ParallelPort(startAddress: Address, endAddress: Address) : MemMappedCompon
|
|||
override fun clock() {}
|
||||
override fun reset() {}
|
||||
|
||||
override operator fun get(address: Address): UByte {
|
||||
return if (address == startAddress) dataByte
|
||||
override operator fun get(offset: Int): UByte {
|
||||
return if (offset == 0) dataByte
|
||||
else 0xff
|
||||
}
|
||||
|
||||
override operator fun set(address: Address, data: UByte) {
|
||||
if (address == startAddress) dataByte = data
|
||||
else if (address == endAddress) {
|
||||
override operator fun set(offset: Int, data: UByte) {
|
||||
if (offset == 0) dataByte = data
|
||||
else if (offset == 1) {
|
||||
if ((data.toInt() and 1) == 1) {
|
||||
val char = dataByte.toChar()
|
||||
val char = dataByte.toInt().toChar()
|
||||
println("PARALLEL WRITE: '$char'")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,10 +10,10 @@ import java.io.InputStream
|
|||
class Ram(startAddress: Address, endAddress: Address) : MemoryComponent(startAddress, endAddress) {
|
||||
override val data = Array<UByte>(endAddress-startAddress+1) { 0 }
|
||||
|
||||
override operator fun get(address: Address): UByte = data[address-startAddress]
|
||||
override operator fun get(offset: Int): UByte = data[offset]
|
||||
|
||||
override operator fun set(address: Address, data: UByte) {
|
||||
this.data[address-startAddress] = data
|
||||
override operator fun set(offset: Int, data: UByte) {
|
||||
this.data[offset] = data
|
||||
}
|
||||
|
||||
override fun clock() {}
|
||||
|
|
|
@ -34,8 +34,8 @@ class RealTimeClock(startAddress: Address, endAddress: Address) : MemMappedCompo
|
|||
/* never reset */
|
||||
}
|
||||
|
||||
override operator fun get(address: Address): UByte {
|
||||
return when (address-startAddress) {
|
||||
override operator fun get(offset: Int): UByte {
|
||||
return when (offset) {
|
||||
0x00 -> {
|
||||
val year = LocalDate.now().year
|
||||
(year and 255).toShort()
|
||||
|
@ -61,7 +61,5 @@ class RealTimeClock(startAddress: Address, endAddress: Address) : MemMappedCompo
|
|||
}
|
||||
}
|
||||
|
||||
override operator fun set(address: Address, data: UByte) {
|
||||
/* real time clock can't be set */
|
||||
}
|
||||
override operator fun set(offset: Int, data: UByte) { /* real time clock can't be set */ }
|
||||
}
|
||||
|
|
|
@ -6,15 +6,14 @@ import java.io.File
|
|||
* A ROM chip (read-only memory).
|
||||
*/
|
||||
class Rom(startAddress: Address, endAddress: Address, initialData: Array<UByte>? = null) : MemoryComponent(startAddress, endAddress) {
|
||||
override val data: Array<UByte> = initialData?.copyOf() ?: Array<UByte>(endAddress-startAddress+1) { 0 }
|
||||
override val data: Array<UByte> = initialData?.copyOf() ?: Array(endAddress-startAddress+1) { 0 }
|
||||
|
||||
init {
|
||||
require(endAddress-startAddress+1 == data.size) { "rom address range doesn't match size of data bytes" }
|
||||
}
|
||||
|
||||
override operator fun get(address: Address): UByte = data[address-startAddress]
|
||||
override operator fun set(address: Address, data: UByte) { /* read-only */
|
||||
}
|
||||
override operator fun get(offset: Int): UByte = data[offset]
|
||||
override operator fun set(offset: Int, data: UByte) { /* read-only */ }
|
||||
|
||||
override fun clock() {}
|
||||
override fun reset() {}
|
||||
|
@ -27,12 +26,7 @@ class Rom(startAddress: Address, endAddress: Address, initialData: Array<UByte>?
|
|||
load(bytes)
|
||||
}
|
||||
|
||||
fun load(data: Array<UByte>) = data.forEachIndexed { index, byte ->
|
||||
this.data[index] = byte
|
||||
}
|
||||
fun load(data: Array<UByte>) = data.copyInto(this.data)
|
||||
|
||||
fun load(data: ByteArray) = data.forEachIndexed { index, byte ->
|
||||
this.data[index] = if (byte >= 0) byte.toShort()
|
||||
else (256+byte).toShort()
|
||||
}
|
||||
fun load(data: ByteArray) = data.map { (it.toInt() and 255).toShort() }.toTypedArray().copyInto(this.data)
|
||||
}
|
||||
|
|
|
@ -33,8 +33,8 @@ class Timer(startAddress: Address, endAddress: Address, val cpu: Cpu6502) : MemM
|
|||
if (enabled && interval > 0) {
|
||||
counter++
|
||||
if (counter == interval) {
|
||||
if (nmi) cpu.nmi()
|
||||
else cpu.irq()
|
||||
if (nmi) cpu.nmiAsserted = true
|
||||
else cpu.irqAsserted = true
|
||||
counter = 0
|
||||
}
|
||||
}
|
||||
|
@ -47,8 +47,8 @@ class Timer(startAddress: Address, endAddress: Address, val cpu: Cpu6502) : MemM
|
|||
nmi = false
|
||||
}
|
||||
|
||||
override operator fun get(address: Address): UByte {
|
||||
return when (address-startAddress) {
|
||||
override operator fun get(offset: Int): UByte {
|
||||
return when (offset) {
|
||||
0x00 -> {
|
||||
var data = 0
|
||||
if (enabled) data = data or 0b00000001
|
||||
|
@ -62,8 +62,8 @@ class Timer(startAddress: Address, endAddress: Address, val cpu: Cpu6502) : MemM
|
|||
}
|
||||
}
|
||||
|
||||
override operator fun set(address: Address, data: UByte) {
|
||||
when (address-startAddress) {
|
||||
override operator fun set(offset: Int, data: UByte) {
|
||||
when (offset) {
|
||||
0x00 -> {
|
||||
val i = data.toInt()
|
||||
enabled = (i and 0b00000001) != 0
|
||||
|
|
BIN
src/main/resources/charset/spleen-12x24.psfu.gz
Normal file
BIN
src/main/resources/charset/spleen-12x24.psfu.gz
Normal file
Binary file not shown.
BIN
src/main/resources/charset/spleen-16x32.psfu.gz
Normal file
BIN
src/main/resources/charset/spleen-16x32.psfu.gz
Normal file
Binary file not shown.
BIN
src/main/resources/charset/spleen-8x16.psfu.gz
Normal file
BIN
src/main/resources/charset/spleen-8x16.psfu.gz
Normal file
Binary file not shown.
24
src/main/resources/charset/spleen-LICENSE
Normal file
24
src/main/resources/charset/spleen-LICENSE
Normal file
|
@ -0,0 +1,24 @@
|
|||
Copyright (c) 2018-2020, Frederic Cambus
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
Binary file not shown.
Before Width: | Height: | Size: 1.5 KiB |
|
@ -1 +1 @@
|
|||
version=1.5
|
||||
version=1.10
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
SCREEN_WIDTH=640
|
||||
|
||||
* = $1000
|
||||
irq_timer_cycles = 10000 ; every time this number of cycles passed, an IRQ occurs
|
||||
|
||||
start
|
||||
sei
|
||||
|
@ -20,11 +21,11 @@ start
|
|||
sta IRQVEC
|
||||
lda #>irq
|
||||
sta IRQVEC+1
|
||||
lda #<2000
|
||||
sta TIMER+1 ; every 2000 clock cycles an irq
|
||||
lda #>2000
|
||||
lda #<irq_timer_cycles
|
||||
sta TIMER+1
|
||||
lda #>irq_timer_cycles
|
||||
sta TIMER+2
|
||||
lda #0
|
||||
lda #irq_timer_cycles >> 16
|
||||
sta TIMER+3
|
||||
lda #1
|
||||
sta TIMER+0
|
||||
|
@ -40,7 +41,7 @@ start
|
|||
jsr print
|
||||
jmp +
|
||||
|
||||
_title1 .text "**** COMMODORE 64 BASIC V2 ****", 10, 10, " 64K RAM SYSTEM 38911 BASIC BYTES FREE", 10, 10, "READY.",10,0
|
||||
_title1 .text "**** COMMODORE 64 BASIC V9 ****", 10, 10, " 64K RAM SYSTEM 98765 BASIC BYTES FREE", 10, 10, "READY.",10,0
|
||||
_text2 .text 10,"Nah, only joking, this is not a weird C-64.",10,"This is a working fantasy 8-bit 6502 machine though!",10
|
||||
.text "Type some stuff on the keyboard, use the mouse (with Left button/Right button)", 10, "to draw/erase pixels.",10,10,0
|
||||
_text3 .text "Mouse drawing and keyboard scanning: done in main program loop.",10
|
||||
|
@ -92,6 +93,7 @@ irq
|
|||
pha
|
||||
tya
|
||||
pha
|
||||
|
||||
; we don't check for BRK flag because we're lazy
|
||||
lda DISPLAY+0
|
||||
pha
|
||||
|
@ -104,6 +106,7 @@ irq
|
|||
lda #<_time_msg
|
||||
ldy #>_time_msg
|
||||
jsr textout
|
||||
|
||||
; read the clock now
|
||||
; YEAR
|
||||
lda RTC+0
|
||||
|
@ -112,6 +115,7 @@ irq
|
|||
lda #<DecTenThousands
|
||||
ldy #>DecTenThousands
|
||||
jsr textout
|
||||
|
||||
lda #'-'
|
||||
sta DISPLAY+2
|
||||
inc DISPLAY+0
|
||||
|
@ -130,6 +134,7 @@ irq
|
|||
lda #<DecTens
|
||||
ldy #>DecTens
|
||||
jsr textout
|
||||
|
||||
lda #'/'
|
||||
sta DISPLAY+2
|
||||
inc DISPLAY+0
|
||||
|
@ -157,6 +162,7 @@ irq
|
|||
lda #<DecTens
|
||||
ldy #>DecTens
|
||||
jsr textout
|
||||
|
||||
lda #'.'
|
||||
sta DISPLAY+2
|
||||
inc DISPLAY+0
|
||||
|
@ -184,7 +190,7 @@ _time_msg .text "The current date and time is: ",0
|
|||
|
||||
|
||||
; ----- routines
|
||||
delay ldx #50
|
||||
delay ldx #100
|
||||
- ldy #0
|
||||
- nop
|
||||
dey
|
||||
|
|
Binary file not shown.
|
@ -34,7 +34,8 @@ chk_z = 0 ; check zero flag
|
|||
chk_c = 1 ; check carry flag
|
||||
|
||||
end_of_test macro
|
||||
db $db ;execute 65C02 stop instruction
|
||||
brk
|
||||
; db $db ;execute 65C02 stop instruction
|
||||
endm
|
||||
|
||||
bss
|
||||
|
@ -117,14 +118,14 @@ NEXT2 inc N2 ; [6] see text
|
|||
bpl LOOP1 ; loop through both values of the carry flag
|
||||
lda #0 ; test passed, so store 0 in ERROR
|
||||
sta ERROR
|
||||
DONE
|
||||
DONE
|
||||
end_of_test
|
||||
|
||||
|
||||
; Calculate the actual decimal mode accumulator and flags, the accumulator
|
||||
; and flag results when N1 is added to N2 using binary arithmetic, the
|
||||
; predicted accumulator result, the predicted carry flag, and the predicted
|
||||
; V flag
|
||||
;
|
||||
; V flag
|
||||
;
|
||||
ADD sed ; decimal mode
|
||||
cpy #1 ; set carry if Y = 1, clear carry if Y = 0
|
||||
lda N1
|
||||
|
@ -138,7 +139,7 @@ ADD sed ; decimal mode
|
|||
lda N1
|
||||
adc N2
|
||||
sta HA ; accumulator result of N1+N2 using binary arithmetic
|
||||
|
||||
|
||||
php
|
||||
pla
|
||||
sta HNVZC ; flags result of N1+N2 using binary arithmetic
|
||||
|
@ -153,10 +154,10 @@ ADD sed ; decimal mode
|
|||
and #$0F
|
||||
sec
|
||||
A1 ora N1H
|
||||
;
|
||||
;
|
||||
; if N1L + N2L < $0A, then add N2 & $F0
|
||||
; if N1L + N2L >= $0A, then add (N2 & $F0) + $0F + 1 (carry is set)
|
||||
;
|
||||
;
|
||||
adc N2H,x
|
||||
php
|
||||
bcs A2
|
||||
|
@ -169,16 +170,16 @@ A3 sta AR ; predicted accumulator result
|
|||
pla
|
||||
sta CF ; predicted carry result
|
||||
pla
|
||||
;
|
||||
;
|
||||
; note that all 8 bits of the P register are stored in VF
|
||||
;
|
||||
;
|
||||
sta VF ; predicted V flags
|
||||
rts
|
||||
|
||||
|
||||
; Calculate the actual decimal mode accumulator and flags, and the
|
||||
; accumulator and flag results when N2 is subtracted from N1 using binary
|
||||
; arithmetic
|
||||
;
|
||||
;
|
||||
SUB sed ; decimal mode
|
||||
cpy #1 ; set carry if Y = 1, clear carry if Y = 0
|
||||
lda N1
|
||||
|
@ -192,15 +193,15 @@ SUB sed ; decimal mode
|
|||
lda N1
|
||||
sbc N2
|
||||
sta HA ; accumulator result of N1-N2 using binary arithmetic
|
||||
|
||||
|
||||
php
|
||||
pla
|
||||
sta HNVZC ; flags result of N1-N2 using binary arithmetic
|
||||
rts
|
||||
|
||||
|
||||
if cputype != 1
|
||||
; Calculate the predicted SBC accumulator result for the 6502 and 65816
|
||||
;
|
||||
;
|
||||
SUB1 cpy #1 ; set carry if Y = 1, clear carry if Y = 0
|
||||
lda N1L
|
||||
sbc N2L
|
||||
|
@ -211,17 +212,17 @@ SUB1 cpy #1 ; set carry if Y = 1, clear carry if Y = 0
|
|||
and #$0F
|
||||
clc
|
||||
S11 ora N1H
|
||||
;
|
||||
;
|
||||
; if N1L - N2L >= 0, then subtract N2 & $F0
|
||||
; if N1L - N2L < 0, then subtract (N2 & $F0) + $0F + 1 (carry is clear)
|
||||
;
|
||||
;
|
||||
sbc N2H,x
|
||||
bcs S12
|
||||
sbc #$5F ; subtract $60 (carry is clear)
|
||||
S12 sta AR
|
||||
rts
|
||||
endif
|
||||
|
||||
|
||||
if cputype = 1
|
||||
; Calculate the predicted SBC accumulator result for the 6502 and 65C02
|
||||
;
|
||||
|
@ -234,10 +235,10 @@ SUB2 cpy #1 ; set carry if Y = 1, clear carry if Y = 0
|
|||
and #$0F
|
||||
clc
|
||||
S21 ora N1H
|
||||
;
|
||||
;
|
||||
; if N1L - N2L >= 0, then subtract N2 & $F0
|
||||
; if N1L - N2L < 0, then subtract (N2 & $F0) + $0F + 1 (carry is clear)
|
||||
;
|
||||
;
|
||||
sbc N2H,x
|
||||
bcs S22
|
||||
sbc #$5F ; subtract $60 (carry is clear)
|
||||
|
@ -247,14 +248,14 @@ S22 cpx #0
|
|||
S23 sta AR ; predicted accumulator result
|
||||
rts
|
||||
endif
|
||||
|
||||
|
||||
; Compare accumulator actual results to predicted results
|
||||
;
|
||||
; Return:
|
||||
;
|
||||
; Return:
|
||||
; Z flag = 1 (BEQ branch) if same
|
||||
; Z flag = 0 (BNE branch) if different
|
||||
;
|
||||
COMPARE
|
||||
;
|
||||
COMPARE
|
||||
if chk_a = 1
|
||||
lda DA
|
||||
cmp AR
|
||||
|
@ -284,22 +285,22 @@ COMPARE
|
|||
and #1 ; mask off C flag
|
||||
endif
|
||||
C1 rts
|
||||
|
||||
|
||||
; These routines store the predicted values for ADC and SBC for the 6502,
|
||||
; 65C02, and 65816 in AR, CF, NF, VF, and ZF
|
||||
|
||||
if cputype = 0
|
||||
|
||||
A6502 lda VF ; 6502
|
||||
;
|
||||
;
|
||||
; since all 8 bits of the P register were stored in VF, bit 7 of VF contains
|
||||
; the N flag for NF
|
||||
;
|
||||
;
|
||||
sta NF
|
||||
lda HNVZC
|
||||
sta ZF
|
||||
rts
|
||||
|
||||
|
||||
S6502 jsr SUB1
|
||||
lda HNVZC
|
||||
sta NF
|
||||
|
@ -317,7 +318,7 @@ A6502 lda AR ; 65C02
|
|||
sta NF
|
||||
sta ZF
|
||||
rts
|
||||
|
||||
|
||||
S6502 jsr SUB2
|
||||
lda AR
|
||||
php
|
||||
|
@ -330,7 +331,7 @@ S6502 jsr SUB2
|
|||
rts
|
||||
|
||||
endif
|
||||
if cputype = 2
|
||||
if cputype = 2
|
||||
|
||||
A6502 lda AR ; 65C816
|
||||
php
|
||||
|
@ -338,7 +339,7 @@ A6502 lda AR ; 65C816
|
|||
sta NF
|
||||
sta ZF
|
||||
rts
|
||||
|
||||
|
||||
S6502 jsr SUB1
|
||||
lda AR
|
||||
php
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
;
|
||||
; 6 5 0 2 F U N C T I O N A L T E S T
|
||||
;
|
||||
; Copyright (C) 2012-2015 Klaus Dormann
|
||||
; Copyright (C) 2012-2020 Klaus Dormann
|
||||
;
|
||||
; This program is free software: you can redistribute it and/or modify
|
||||
; it under the terms of the GNU General Public License as published by
|
||||
|
@ -21,10 +21,11 @@
|
|||
; addressing modes with focus on propper setting of the processor status
|
||||
; register bits.
|
||||
;
|
||||
; version 04-dec-2017
|
||||
; version 05-jan-2020
|
||||
; contact info at http://2m5.de or email K@2m5.de
|
||||
;
|
||||
; assembled with AS65 from http://www.kingswood-consulting.co.uk/assemblers/
|
||||
; assembled with AS65 written by Frank A. Kingswood
|
||||
; The assembler as65_142.zip can be obtained from my GitHub repository
|
||||
; command line switches: -l -m -s2 -w -h0
|
||||
; | | | | no page headers in listing
|
||||
; | | | wide listing (133 char/col)
|
||||
|
@ -76,7 +77,8 @@
|
|||
; 04-dec-2017 fixed BRK only tested with interrupts enabled
|
||||
; added option to skip the remainder of a failing test
|
||||
; in report.i65
|
||||
|
||||
; 05-jan-2020 fixed shifts not testing zero result and flag when last 1-bit
|
||||
; is shifted out
|
||||
|
||||
; C O N F I G U R A T I O N
|
||||
|
||||
|
@ -96,17 +98,17 @@ load_data_direct = 1
|
|||
I_flag = 3
|
||||
|
||||
;configure memory - try to stay away from memory used by the system
|
||||
;zero_page memory start address, $50 (80) consecutive Bytes required
|
||||
;zero_page memory start address, $52 (82) consecutive Bytes required
|
||||
; add 2 if I_flag = 2
|
||||
zero_page = $a
|
||||
zero_page = $0
|
||||
|
||||
;data_segment memory start address, $6A (106) consecutive Bytes required
|
||||
;data_segment memory start address, $7B (123) consecutive Bytes required
|
||||
data_segment = $200
|
||||
if (data_segment & $ff) != 0
|
||||
ERROR ERROR ERROR low byte of data_segment MUST be $00 !!
|
||||
endif
|
||||
|
||||
;code_segment memory start address, 13kB of consecutive space required
|
||||
;code_segment memory start address, 13.1kB of consecutive space required
|
||||
; add 2.5 kB if I_flag = 2
|
||||
code_segment = $400
|
||||
|
||||
|
@ -621,7 +623,7 @@ irq_x ds 1 ;x register
|
|||
flag_I_on ds 1 ;or mask to load flags
|
||||
flag_I_off ds 1 ;and mask to load flags
|
||||
endif
|
||||
zpt ;5 bytes store/modify test area
|
||||
zpt ;6 bytes store/modify test area
|
||||
;add/subtract operand generation and result/flag prediction
|
||||
adfc ds 1 ;carry flag before op
|
||||
ad1 ds 1 ;operand 1 - accumulator
|
||||
|
@ -631,6 +633,7 @@ adrh ds 1 ;expected result bit 8 (carry)
|
|||
adrf ds 1 ;expected flags NV0000ZC (only binary mode)
|
||||
sb2 ds 1 ;operand 2 complemented for subtract
|
||||
zp_bss
|
||||
zps db $80,1 ;additional shift pattern to test zero result & flag
|
||||
zp1 db $c3,$82,$41,0 ;test patterns for LDx BIT ROL ROR ASL LSR
|
||||
zp7f db $7f ;test pattern for compare
|
||||
;logical zeropage operands
|
||||
|
@ -672,10 +675,10 @@ zp_bss_end
|
|||
test_case ds 1 ;current test number
|
||||
ram_chksm ds 2 ;checksum for RAM integrity test
|
||||
;add/subtract operand copy - abs tests write area
|
||||
abst ;5 bytes store/modify test area
|
||||
abst ;6 bytes store/modify test area
|
||||
ada2 ds 1 ;operand 2
|
||||
sba2 ds 1 ;operand 2 complemented for subtract
|
||||
ds 3 ;fill remaining bytes
|
||||
ds 4 ;fill remaining bytes
|
||||
data_bss
|
||||
if load_data_direct = 1
|
||||
ex_andi and #0 ;execute immediate opcodes
|
||||
|
@ -695,34 +698,35 @@ ex_orai ds 3
|
|||
ex_adci ds 3
|
||||
ex_sbci ds 3
|
||||
endif
|
||||
;zps db $80,1 ;additional shift patterns test zero result & flag
|
||||
abs1 db $c3,$82,$41,0 ;test patterns for LDx BIT ROL ROR ASL LSR
|
||||
abs7f db $7f ;test pattern for compare
|
||||
;loads
|
||||
fLDx db fn,fn,0,fz ;expected flags for load
|
||||
fLDx db fn,fn,0,fz ;expected flags for load
|
||||
;shifts
|
||||
rASL ;expected result ASL & ROL -carry
|
||||
rROL db $86,$04,$82,0 ; "
|
||||
rROLc db $87,$05,$83,1 ;expected result ROL +carry
|
||||
rLSR ;expected result LSR & ROR -carry
|
||||
rROR db $61,$41,$20,0 ; "
|
||||
rRORc db $e1,$c1,$a0,$80 ;expected result ROR +carry
|
||||
fASL ;expected flags for shifts
|
||||
fROL db fnc,fc,fn,fz ;no carry in
|
||||
fROLc db fnc,fc,fn,0 ;carry in
|
||||
fLSR
|
||||
fROR db fc,0,fc,fz ;no carry in
|
||||
fRORc db fnc,fn,fnc,fn ;carry in
|
||||
rASL ;expected result ASL & ROL -carry
|
||||
rROL db 0,2,$86,$04,$82,0
|
||||
rROLc db 1,3,$87,$05,$83,1 ;expected result ROL +carry
|
||||
rLSR ;expected result LSR & ROR -carry
|
||||
rROR db $40,0,$61,$41,$20,0
|
||||
rRORc db $c0,$80,$e1,$c1,$a0,$80 ;expected result ROR +carry
|
||||
fASL ;expected flags for shifts
|
||||
fROL db fzc,0,fnc,fc,fn,fz ;no carry in
|
||||
fROLc db fc,0,fnc,fc,fn,0 ;carry in
|
||||
fLSR
|
||||
fROR db 0,fzc,fc,0,fc,fz ;no carry in
|
||||
fRORc db fn,fnc,fnc,fn,fnc,fn ;carry in
|
||||
;increments (decrements)
|
||||
rINC db $7f,$80,$ff,0,1 ;expected result for INC/DEC
|
||||
fINC db 0,fn,fn,fz,0 ;expected flags for INC/DEC
|
||||
rINC db $7f,$80,$ff,0,1 ;expected result for INC/DEC
|
||||
fINC db 0,fn,fn,fz,0 ;expected flags for INC/DEC
|
||||
;logical memory operand
|
||||
absOR db 0,$1f,$71,$80 ;test pattern for OR
|
||||
absAN db $0f,$ff,$7f,$80 ;test pattern for AND
|
||||
absEO db $ff,$0f,$8f,$8f ;test pattern for EOR
|
||||
absOR db 0,$1f,$71,$80 ;test pattern for OR
|
||||
absAN db $0f,$ff,$7f,$80 ;test pattern for AND
|
||||
absEO db $ff,$0f,$8f,$8f ;test pattern for EOR
|
||||
;logical accu operand
|
||||
absORa db 0,$f1,$1f,0 ;test pattern for OR
|
||||
absANa db $f0,$ff,$ff,$ff ;test pattern for AND
|
||||
absEOa db $ff,$f0,$f0,$0f ;test pattern for EOR
|
||||
absORa db 0,$f1,$1f,0 ;test pattern for OR
|
||||
absANa db $f0,$ff,$ff,$ff ;test pattern for AND
|
||||
absEOa db $ff,$f0,$f0,$0f ;test pattern for EOR
|
||||
;logical results
|
||||
absrlo db 0,$ff,$7f,$80
|
||||
absflo db fz,fn,0,fn
|
||||
|
@ -4070,91 +4074,91 @@ tstay6 lda abst,y
|
|||
|
||||
; testing shifts - ASL LSR ROL ROR all addressing modes
|
||||
; shifts - accumulator
|
||||
ldx #3
|
||||
ldx #5
|
||||
tasl
|
||||
set_ax zp1,0
|
||||
set_ax zps,0
|
||||
asl a
|
||||
tst_ax rASL,fASL,0
|
||||
dex
|
||||
bpl tasl
|
||||
ldx #3
|
||||
ldx #5
|
||||
tasl1
|
||||
set_ax zp1,$ff
|
||||
set_ax zps,$ff
|
||||
asl a
|
||||
tst_ax rASL,fASL,$ff-fnzc
|
||||
dex
|
||||
bpl tasl1
|
||||
|
||||
ldx #3
|
||||
ldx #5
|
||||
tlsr
|
||||
set_ax zp1,0
|
||||
set_ax zps,0
|
||||
lsr a
|
||||
tst_ax rLSR,fLSR,0
|
||||
dex
|
||||
bpl tlsr
|
||||
ldx #3
|
||||
ldx #5
|
||||
tlsr1
|
||||
set_ax zp1,$ff
|
||||
set_ax zps,$ff
|
||||
lsr a
|
||||
tst_ax rLSR,fLSR,$ff-fnzc
|
||||
dex
|
||||
bpl tlsr1
|
||||
|
||||
ldx #3
|
||||
ldx #5
|
||||
trol
|
||||
set_ax zp1,0
|
||||
set_ax zps,0
|
||||
rol a
|
||||
tst_ax rROL,fROL,0
|
||||
dex
|
||||
bpl trol
|
||||
ldx #3
|
||||
ldx #5
|
||||
trol1
|
||||
set_ax zp1,$ff-fc
|
||||
set_ax zps,$ff-fc
|
||||
rol a
|
||||
tst_ax rROL,fROL,$ff-fnzc
|
||||
dex
|
||||
bpl trol1
|
||||
|
||||
ldx #3
|
||||
ldx #5
|
||||
trolc
|
||||
set_ax zp1,fc
|
||||
set_ax zps,fc
|
||||
rol a
|
||||
tst_ax rROLc,fROLc,0
|
||||
dex
|
||||
bpl trolc
|
||||
ldx #3
|
||||
ldx #5
|
||||
trolc1
|
||||
set_ax zp1,$ff
|
||||
set_ax zps,$ff
|
||||
rol a
|
||||
tst_ax rROLc,fROLc,$ff-fnzc
|
||||
dex
|
||||
bpl trolc1
|
||||
|
||||
ldx #3
|
||||
ldx #5
|
||||
tror
|
||||
set_ax zp1,0
|
||||
set_ax zps,0
|
||||
ror a
|
||||
tst_ax rROR,fROR,0
|
||||
dex
|
||||
bpl tror
|
||||
ldx #3
|
||||
ldx #5
|
||||
tror1
|
||||
set_ax zp1,$ff-fc
|
||||
set_ax zps,$ff-fc
|
||||
ror a
|
||||
tst_ax rROR,fROR,$ff-fnzc
|
||||
dex
|
||||
bpl tror1
|
||||
|
||||
ldx #3
|
||||
ldx #5
|
||||
trorc
|
||||
set_ax zp1,fc
|
||||
set_ax zps,fc
|
||||
ror a
|
||||
tst_ax rRORc,fRORc,0
|
||||
dex
|
||||
bpl trorc
|
||||
ldx #3
|
||||
ldx #5
|
||||
trorc1
|
||||
set_ax zp1,$ff
|
||||
set_ax zps,$ff
|
||||
ror a
|
||||
tst_ax rRORc,fRORc,$ff-fnzc
|
||||
dex
|
||||
|
@ -4162,91 +4166,91 @@ trorc1
|
|||
next_test
|
||||
|
||||
; shifts - zeropage
|
||||
ldx #3
|
||||
ldx #5
|
||||
tasl2
|
||||
set_z zp1,0
|
||||
set_z zps,0
|
||||
asl zpt
|
||||
tst_z rASL,fASL,0
|
||||
dex
|
||||
bpl tasl2
|
||||
ldx #3
|
||||
ldx #5
|
||||
tasl3
|
||||
set_z zp1,$ff
|
||||
set_z zps,$ff
|
||||
asl zpt
|
||||
tst_z rASL,fASL,$ff-fnzc
|
||||
dex
|
||||
bpl tasl3
|
||||
|
||||
ldx #3
|
||||
ldx #5
|
||||
tlsr2
|
||||
set_z zp1,0
|
||||
set_z zps,0
|
||||
lsr zpt
|
||||
tst_z rLSR,fLSR,0
|
||||
dex
|
||||
bpl tlsr2
|
||||
ldx #3
|
||||
ldx #5
|
||||
tlsr3
|
||||
set_z zp1,$ff
|
||||
set_z zps,$ff
|
||||
lsr zpt
|
||||
tst_z rLSR,fLSR,$ff-fnzc
|
||||
dex
|
||||
bpl tlsr3
|
||||
|
||||
ldx #3
|
||||
ldx #5
|
||||
trol2
|
||||
set_z zp1,0
|
||||
set_z zps,0
|
||||
rol zpt
|
||||
tst_z rROL,fROL,0
|
||||
dex
|
||||
bpl trol2
|
||||
ldx #3
|
||||
ldx #5
|
||||
trol3
|
||||
set_z zp1,$ff-fc
|
||||
set_z zps,$ff-fc
|
||||
rol zpt
|
||||
tst_z rROL,fROL,$ff-fnzc
|
||||
dex
|
||||
bpl trol3
|
||||
|
||||
ldx #3
|
||||
ldx #5
|
||||
trolc2
|
||||
set_z zp1,fc
|
||||
set_z zps,fc
|
||||
rol zpt
|
||||
tst_z rROLc,fROLc,0
|
||||
dex
|
||||
bpl trolc2
|
||||
ldx #3
|
||||
ldx #5
|
||||
trolc3
|
||||
set_z zp1,$ff
|
||||
set_z zps,$ff
|
||||
rol zpt
|
||||
tst_z rROLc,fROLc,$ff-fnzc
|
||||
dex
|
||||
bpl trolc3
|
||||
|
||||
ldx #3
|
||||
ldx #5
|
||||
tror2
|
||||
set_z zp1,0
|
||||
set_z zps,0
|
||||
ror zpt
|
||||
tst_z rROR,fROR,0
|
||||
dex
|
||||
bpl tror2
|
||||
ldx #3
|
||||
ldx #5
|
||||
tror3
|
||||
set_z zp1,$ff-fc
|
||||
set_z zps,$ff-fc
|
||||
ror zpt
|
||||
tst_z rROR,fROR,$ff-fnzc
|
||||
dex
|
||||
bpl tror3
|
||||
|
||||
ldx #3
|
||||
ldx #5
|
||||
trorc2
|
||||
set_z zp1,fc
|
||||
set_z zps,fc
|
||||
ror zpt
|
||||
tst_z rRORc,fRORc,0
|
||||
dex
|
||||
bpl trorc2
|
||||
ldx #3
|
||||
ldx #5
|
||||
trorc3
|
||||
set_z zp1,$ff
|
||||
set_z zps,$ff
|
||||
ror zpt
|
||||
tst_z rRORc,fRORc,$ff-fnzc
|
||||
dex
|
||||
|
@ -4254,91 +4258,91 @@ trorc3
|
|||
next_test
|
||||
|
||||
; shifts - absolute
|
||||
ldx #3
|
||||
ldx #5
|
||||
tasl4
|
||||
set_abs zp1,0
|
||||
set_abs zps,0
|
||||
asl abst
|
||||
tst_abs rASL,fASL,0
|
||||
dex
|
||||
bpl tasl4
|
||||
ldx #3
|
||||
ldx #5
|
||||
tasl5
|
||||
set_abs zp1,$ff
|
||||
set_abs zps,$ff
|
||||
asl abst
|
||||
tst_abs rASL,fASL,$ff-fnzc
|
||||
dex
|
||||
bpl tasl5
|
||||
|
||||
ldx #3
|
||||
ldx #5
|
||||
tlsr4
|
||||
set_abs zp1,0
|
||||
set_abs zps,0
|
||||
lsr abst
|
||||
tst_abs rLSR,fLSR,0
|
||||
dex
|
||||
bpl tlsr4
|
||||
ldx #3
|
||||
ldx #5
|
||||
tlsr5
|
||||
set_abs zp1,$ff
|
||||
set_abs zps,$ff
|
||||
lsr abst
|
||||
tst_abs rLSR,fLSR,$ff-fnzc
|
||||
dex
|
||||
bpl tlsr5
|
||||
|
||||
ldx #3
|
||||
ldx #5
|
||||
trol4
|
||||
set_abs zp1,0
|
||||
set_abs zps,0
|
||||
rol abst
|
||||
tst_abs rROL,fROL,0
|
||||
dex
|
||||
bpl trol4
|
||||
ldx #3
|
||||
ldx #5
|
||||
trol5
|
||||
set_abs zp1,$ff-fc
|
||||
set_abs zps,$ff-fc
|
||||
rol abst
|
||||
tst_abs rROL,fROL,$ff-fnzc
|
||||
dex
|
||||
bpl trol5
|
||||
|
||||
ldx #3
|
||||
ldx #5
|
||||
trolc4
|
||||
set_abs zp1,fc
|
||||
set_abs zps,fc
|
||||
rol abst
|
||||
tst_abs rROLc,fROLc,0
|
||||
dex
|
||||
bpl trolc4
|
||||
ldx #3
|
||||
ldx #5
|
||||
trolc5
|
||||
set_abs zp1,$ff
|
||||
set_abs zps,$ff
|
||||
rol abst
|
||||
tst_abs rROLc,fROLc,$ff-fnzc
|
||||
dex
|
||||
bpl trolc5
|
||||
|
||||
ldx #3
|
||||
ldx #5
|
||||
tror4
|
||||
set_abs zp1,0
|
||||
set_abs zps,0
|
||||
ror abst
|
||||
tst_abs rROR,fROR,0
|
||||
dex
|
||||
bpl tror4
|
||||
ldx #3
|
||||
ldx #5
|
||||
tror5
|
||||
set_abs zp1,$ff-fc
|
||||
set_abs zps,$ff-fc
|
||||
ror abst
|
||||
tst_abs rROR,fROR,$ff-fnzc
|
||||
dex
|
||||
bpl tror5
|
||||
|
||||
ldx #3
|
||||
ldx #5
|
||||
trorc4
|
||||
set_abs zp1,fc
|
||||
set_abs zps,fc
|
||||
ror abst
|
||||
tst_abs rRORc,fRORc,0
|
||||
dex
|
||||
bpl trorc4
|
||||
ldx #3
|
||||
ldx #5
|
||||
trorc5
|
||||
set_abs zp1,$ff
|
||||
set_abs zps,$ff
|
||||
ror abst
|
||||
tst_abs rRORc,fRORc,$ff-fnzc
|
||||
dex
|
||||
|
@ -4346,91 +4350,91 @@ trorc5
|
|||
next_test
|
||||
|
||||
; shifts - zp indexed
|
||||
ldx #3
|
||||
ldx #5
|
||||
tasl6
|
||||
set_zx zp1,0
|
||||
set_zx zps,0
|
||||
asl zpt,x
|
||||
tst_zx rASL,fASL,0
|
||||
dex
|
||||
bpl tasl6
|
||||
ldx #3
|
||||
ldx #5
|
||||
tasl7
|
||||
set_zx zp1,$ff
|
||||
set_zx zps,$ff
|
||||
asl zpt,x
|
||||
tst_zx rASL,fASL,$ff-fnzc
|
||||
dex
|
||||
bpl tasl7
|
||||
|
||||
ldx #3
|
||||
ldx #5
|
||||
tlsr6
|
||||
set_zx zp1,0
|
||||
set_zx zps,0
|
||||
lsr zpt,x
|
||||
tst_zx rLSR,fLSR,0
|
||||
dex
|
||||
bpl tlsr6
|
||||
ldx #3
|
||||
ldx #5
|
||||
tlsr7
|
||||
set_zx zp1,$ff
|
||||
set_zx zps,$ff
|
||||
lsr zpt,x
|
||||
tst_zx rLSR,fLSR,$ff-fnzc
|
||||
dex
|
||||
bpl tlsr7
|
||||
|
||||
ldx #3
|
||||
ldx #5
|
||||
trol6
|
||||
set_zx zp1,0
|
||||
set_zx zps,0
|
||||
rol zpt,x
|
||||
tst_zx rROL,fROL,0
|
||||
dex
|
||||
bpl trol6
|
||||
ldx #3
|
||||
ldx #5
|
||||
trol7
|
||||
set_zx zp1,$ff-fc
|
||||
set_zx zps,$ff-fc
|
||||
rol zpt,x
|
||||
tst_zx rROL,fROL,$ff-fnzc
|
||||
dex
|
||||
bpl trol7
|
||||
|
||||
ldx #3
|
||||
ldx #5
|
||||
trolc6
|
||||
set_zx zp1,fc
|
||||
set_zx zps,fc
|
||||
rol zpt,x
|
||||
tst_zx rROLc,fROLc,0
|
||||
dex
|
||||
bpl trolc6
|
||||
ldx #3
|
||||
ldx #5
|
||||
trolc7
|
||||
set_zx zp1,$ff
|
||||
set_zx zps,$ff
|
||||
rol zpt,x
|
||||
tst_zx rROLc,fROLc,$ff-fnzc
|
||||
dex
|
||||
bpl trolc7
|
||||
|
||||
ldx #3
|
||||
ldx #5
|
||||
tror6
|
||||
set_zx zp1,0
|
||||
set_zx zps,0
|
||||
ror zpt,x
|
||||
tst_zx rROR,fROR,0
|
||||
dex
|
||||
bpl tror6
|
||||
ldx #3
|
||||
ldx #5
|
||||
tror7
|
||||
set_zx zp1,$ff-fc
|
||||
set_zx zps,$ff-fc
|
||||
ror zpt,x
|
||||
tst_zx rROR,fROR,$ff-fnzc
|
||||
dex
|
||||
bpl tror7
|
||||
|
||||
ldx #3
|
||||
ldx #5
|
||||
trorc6
|
||||
set_zx zp1,fc
|
||||
set_zx zps,fc
|
||||
ror zpt,x
|
||||
tst_zx rRORc,fRORc,0
|
||||
dex
|
||||
bpl trorc6
|
||||
ldx #3
|
||||
ldx #5
|
||||
trorc7
|
||||
set_zx zp1,$ff
|
||||
set_zx zps,$ff
|
||||
ror zpt,x
|
||||
tst_zx rRORc,fRORc,$ff-fnzc
|
||||
dex
|
||||
|
@ -4438,91 +4442,91 @@ trorc7
|
|||
next_test
|
||||
|
||||
; shifts - abs indexed
|
||||
ldx #3
|
||||
ldx #5
|
||||
tasl8
|
||||
set_absx zp1,0
|
||||
set_absx zps,0
|
||||
asl abst,x
|
||||
tst_absx rASL,fASL,0
|
||||
dex
|
||||
bpl tasl8
|
||||
ldx #3
|
||||
ldx #5
|
||||
tasl9
|
||||
set_absx zp1,$ff
|
||||
set_absx zps,$ff
|
||||
asl abst,x
|
||||
tst_absx rASL,fASL,$ff-fnzc
|
||||
dex
|
||||
bpl tasl9
|
||||
|
||||
ldx #3
|
||||
ldx #5
|
||||
tlsr8
|
||||
set_absx zp1,0
|
||||
set_absx zps,0
|
||||
lsr abst,x
|
||||
tst_absx rLSR,fLSR,0
|
||||
dex
|
||||
bpl tlsr8
|
||||
ldx #3
|
||||
ldx #5
|
||||
tlsr9
|
||||
set_absx zp1,$ff
|
||||
set_absx zps,$ff
|
||||
lsr abst,x
|
||||
tst_absx rLSR,fLSR,$ff-fnzc
|
||||
dex
|
||||
bpl tlsr9
|
||||
|
||||
ldx #3
|
||||
ldx #5
|
||||
trol8
|
||||
set_absx zp1,0
|
||||
set_absx zps,0
|
||||
rol abst,x
|
||||
tst_absx rROL,fROL,0
|
||||
dex
|
||||
bpl trol8
|
||||
ldx #3
|
||||
ldx #5
|
||||
trol9
|
||||
set_absx zp1,$ff-fc
|
||||
set_absx zps,$ff-fc
|
||||
rol abst,x
|
||||
tst_absx rROL,fROL,$ff-fnzc
|
||||
dex
|
||||
bpl trol9
|
||||
|
||||
ldx #3
|
||||
ldx #5
|
||||
trolc8
|
||||
set_absx zp1,fc
|
||||
set_absx zps,fc
|
||||
rol abst,x
|
||||
tst_absx rROLc,fROLc,0
|
||||
dex
|
||||
bpl trolc8
|
||||
ldx #3
|
||||
ldx #5
|
||||
trolc9
|
||||
set_absx zp1,$ff
|
||||
set_absx zps,$ff
|
||||
rol abst,x
|
||||
tst_absx rROLc,fROLc,$ff-fnzc
|
||||
dex
|
||||
bpl trolc9
|
||||
|
||||
ldx #3
|
||||
ldx #5
|
||||
tror8
|
||||
set_absx zp1,0
|
||||
set_absx zps,0
|
||||
ror abst,x
|
||||
tst_absx rROR,fROR,0
|
||||
dex
|
||||
bpl tror8
|
||||
ldx #3
|
||||
ldx #5
|
||||
tror9
|
||||
set_absx zp1,$ff-fc
|
||||
set_absx zps,$ff-fc
|
||||
ror abst,x
|
||||
tst_absx rROR,fROR,$ff-fnzc
|
||||
dex
|
||||
bpl tror9
|
||||
|
||||
ldx #3
|
||||
ldx #5
|
||||
trorc8
|
||||
set_absx zp1,fc
|
||||
set_absx zps,fc
|
||||
ror abst,x
|
||||
tst_absx rRORc,fRORc,0
|
||||
dex
|
||||
bpl trorc8
|
||||
ldx #3
|
||||
ldx #5
|
||||
trorc9
|
||||
set_absx zp1,$ff
|
||||
set_absx zps,$ff
|
||||
ror abst,x
|
||||
tst_absx rRORc,fRORc,$ff-fnzc
|
||||
dex
|
||||
|
@ -5997,6 +6001,7 @@ break2 ;BRK pass 2
|
|||
;copy of data to initialize BSS segment
|
||||
if load_data_direct != 1
|
||||
zp_init
|
||||
zps_ db $80,1 ;additional shift pattern to test zero result & flag
|
||||
zp1_ db $c3,$82,$41,0 ;test patterns for LDx BIT ROL ROR ASL LSR
|
||||
zp7f_ db $7f ;test pattern for compare
|
||||
;logical zeropage operands
|
||||
|
@ -6048,34 +6053,35 @@ ex_adc_ adc #0 ;execute immediate opcodes
|
|||
rts
|
||||
ex_sbc_ sbc #0 ;execute immediate opcodes
|
||||
rts
|
||||
;zps db $80,1 ;additional shift patterns test zero result & flag
|
||||
abs1_ db $c3,$82,$41,0 ;test patterns for LDx BIT ROL ROR ASL LSR
|
||||
abs7f_ db $7f ;test pattern for compare
|
||||
;loads
|
||||
fLDx_ db fn,fn,0,fz ;expected flags for load
|
||||
fLDx_ db fn,fn,0,fz ;expected flags for load
|
||||
;shifts
|
||||
rASL_ ;expected result ASL & ROL -carry
|
||||
rROL_ db $86,$04,$82,0 ; "
|
||||
rROLc_ db $87,$05,$83,1 ;expected result ROL +carry
|
||||
rLSR_ ;expected result LSR & ROR -carry
|
||||
rROR_ db $61,$41,$20,0 ; "
|
||||
rRORc_ db $e1,$c1,$a0,$80 ;expected result ROR +carry
|
||||
fASL_ ;expected flags for shifts
|
||||
fROL_ db fnc,fc,fn,fz ;no carry in
|
||||
fROLc_ db fnc,fc,fn,0 ;carry in
|
||||
rASL_ ;expected result ASL & ROL -carry
|
||||
rROL_ db 0,2,$86,$04,$82,0
|
||||
rROLc_ db 1,3,$87,$05,$83,1 ;expected result ROL +carry
|
||||
rLSR_ ;expected result LSR & ROR -carry
|
||||
rROR_ db $40,0,$61,$41,$20,0
|
||||
rRORc_ db $c0,$80,$e1,$c1,$a0,$80 ;expected result ROR +carry
|
||||
fASL_ ;expected flags for shifts
|
||||
fROL_ db fzc,0,fnc,fc,fn,fz ;no carry in
|
||||
fROLc_ db fc,0,fnc,fc,fn,0 ;carry in
|
||||
fLSR_
|
||||
fROR_ db fc,0,fc,fz ;no carry in
|
||||
fRORc_ db fnc,fn,fnc,fn ;carry in
|
||||
fROR_ db 0,fzc,fc,0,fc,fz ;no carry in
|
||||
fRORc_ db fn,fnc,fnc,fn,fnc,fn ;carry in
|
||||
;increments (decrements)
|
||||
rINC_ db $7f,$80,$ff,0,1 ;expected result for INC/DEC
|
||||
fINC_ db 0,fn,fn,fz,0 ;expected flags for INC/DEC
|
||||
rINC_ db $7f,$80,$ff,0,1 ;expected result for INC/DEC
|
||||
fINC_ db 0,fn,fn,fz,0 ;expected flags for INC/DEC
|
||||
;logical memory operand
|
||||
absOR_ db 0,$1f,$71,$80 ;test pattern for OR
|
||||
absAN_ db $0f,$ff,$7f,$80 ;test pattern for AND
|
||||
absEO_ db $ff,$0f,$8f,$8f ;test pattern for EOR
|
||||
absOR_ db 0,$1f,$71,$80 ;test pattern for OR
|
||||
absAN_ db $0f,$ff,$7f,$80 ;test pattern for AND
|
||||
absEO_ db $ff,$0f,$8f,$8f ;test pattern for EOR
|
||||
;logical accu operand
|
||||
absORa_ db 0,$f1,$1f,0 ;test pattern for OR
|
||||
absANa_ db $f0,$ff,$ff,$ff ;test pattern for AND
|
||||
absEOa_ db $ff,$f0,$f0,$0f ;test pattern for EOR
|
||||
absORa_ db 0,$f1,$1f,0 ;test pattern for OR
|
||||
absANa_ db $f0,$ff,$ff,$ff ;test pattern for AND
|
||||
absEOa_ db $ff,$f0,$f0,$0f ;test pattern for EOR
|
||||
;logical results
|
||||
absrlo_ db 0,$ff,$7f,$80
|
||||
absflo_ db fz,fn,0,fn
|
||||
|
@ -6100,4 +6106,4 @@ vec_bss equ $fffa
|
|||
endif
|
||||
|
||||
end start
|
||||
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
; This program is designed to test IRQ and NMI of a 6502 emulator. It requires
|
||||
; an internal or external feedback register to the IRQ & NMI inputs
|
||||
;
|
||||
;
|
||||
; version 15-aug-2014
|
||||
; contact info at http://2m5.de or email K@2m5.de
|
||||
;
|
||||
|
@ -83,10 +83,10 @@ D_clear = 0 ;0 = not cleared (NMOS), 1 = cleared (CMOS)
|
|||
|
||||
;configure memory - try to stay away from memory used by the system
|
||||
;zero_page memory start address, 6 consecutive Bytes required
|
||||
zero_page = $a
|
||||
zero_page = $0
|
||||
|
||||
;data_segment memory start address, 4 consecutive Bytes required
|
||||
data_segment = $200
|
||||
data_segment = $200
|
||||
|
||||
;code_segment memory start address
|
||||
code_segment = $400
|
||||
|
@ -205,7 +205,7 @@ zp_bss
|
|||
;fixed stack locations
|
||||
lst_f equ $1fe ;last flags before interrupt
|
||||
lst_a equ $1ff ;last accumulator before interrupt
|
||||
|
||||
|
||||
org data_segment
|
||||
;concurrent NMI, IRQ & BRK test result
|
||||
nmi_count ds 1 ;lowest number handled first, $ff = never
|
||||
|
@ -222,7 +222,7 @@ start cld
|
|||
sta I_src
|
||||
ldx #$ff
|
||||
txs
|
||||
|
||||
|
||||
;initialize I/O for report channel
|
||||
if report = 1
|
||||
jsr report_init
|
||||
|
@ -263,7 +263,7 @@ I_clr macro ibit ;ibit = interrupt bit
|
|||
and #I_filter
|
||||
ora #(1<<IRQ_bit)
|
||||
sta I_ddr
|
||||
endif
|
||||
endif
|
||||
else ;open collector, 0 -> I_DDR or I_port to force interrupt
|
||||
if I_ddr != 0 ;with DDR
|
||||
I_set macro ibit ;ibit = interrupt bit
|
||||
|
@ -278,7 +278,7 @@ I_set macro ibit ;ibit = interrupt bit
|
|||
I_clr macro ibit ;ibit = interrupt bit
|
||||
lda I_ddr ;turn off interrupt by bit
|
||||
and #I_filter-(1<<ibit)
|
||||
sta I_ddr
|
||||
sta I_ddr
|
||||
endm
|
||||
I_clr IRQ_bit ;turn off IRQ
|
||||
lda I_port ;precharge IRQ
|
||||
|
@ -329,7 +329,7 @@ I_clr macro ibit ;ibit = interrupt bit
|
|||
and #I_filter
|
||||
ora #(1<<IRQ_bit|1<<NMI_bit)
|
||||
sta I_ddr
|
||||
endif
|
||||
endif
|
||||
else ;open collector, 0 -> I_DDR or I_port to force interrupt
|
||||
if I_ddr != 0 ;with DDR
|
||||
I_set macro ibit ;ibit = interrupt bit
|
||||
|
@ -348,7 +348,7 @@ I_set macro ibit ;ibit = interrupt bit
|
|||
I_clr macro ibit ;ibit = interrupt bit
|
||||
lda I_ddr ;turn off interrupt by bit
|
||||
and #I_filter-(1<<ibit)
|
||||
sta I_ddr
|
||||
sta I_ddr
|
||||
endm
|
||||
I_clr IRQ_bit ;turn off IRQ & NMI
|
||||
I_clr NMI_bit
|
||||
|
@ -379,7 +379,7 @@ I_clr macro ibit ;ibit = interrupt bit
|
|||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
; IRQ integrity test
|
||||
; test for clear flags seen in IRQ vector
|
||||
lda #2 ;set expected interrupt source IRQ
|
||||
|
@ -633,7 +633,7 @@ I_clr macro ibit ;ibit = interrupt bit
|
|||
ldx #0
|
||||
lda #0
|
||||
sta I_src
|
||||
push_stat intdis
|
||||
push_stat intdis
|
||||
I_set IRQ_bit ;IRQ pending
|
||||
inx
|
||||
inx
|
||||
|
@ -657,7 +657,7 @@ I_clr macro ibit ;ibit = interrupt bit
|
|||
sta nmi_count
|
||||
sta irq_count
|
||||
sta brk_count
|
||||
push_stat 0
|
||||
push_stat 0
|
||||
I_set IRQ_bit ;trigger IRQ
|
||||
else
|
||||
; NMI integrity test
|
||||
|
@ -782,7 +782,7 @@ I_clr macro ibit ;ibit = interrupt bit
|
|||
ldx #0
|
||||
lda #4 ;set expected interrupt NMI only
|
||||
sta I_src
|
||||
push_stat intdis
|
||||
push_stat intdis
|
||||
I_set 8 ;both interrupts pending
|
||||
inx
|
||||
inx
|
||||
|
@ -825,21 +825,21 @@ I_clr macro ibit ;ibit = interrupt bit
|
|||
;may fail due to a bug on a real NMOS 6502 - NMI could mask BRK
|
||||
trap_ne ;lost an interrupt
|
||||
|
||||
; S U C C E S S ************************************************
|
||||
; -------------
|
||||
; S U C C E S S ************************************************
|
||||
; -------------
|
||||
success ;if you get here everything went well
|
||||
; -------------
|
||||
; S U C C E S S ************************************************
|
||||
; -------------
|
||||
; S U C C E S S ************************************************
|
||||
; check data_segment +0 to +2 for sequence of concurrent interrupts
|
||||
; e.g. 0x200 = NMI, 0x201 = IRQ, 0x202 = BRK, lower values = earlier
|
||||
jmp start ;run again
|
||||
jmp start ;run again
|
||||
|
||||
; manual tests for the WAI opcode of the 65c02
|
||||
|
||||
wai macro
|
||||
wai macro
|
||||
db $cb ;WAI opcode
|
||||
endm
|
||||
|
||||
|
||||
; requires single step operation, report = 0
|
||||
; set PC to the 1st instruction of the test
|
||||
; step to the WAI opcode, then manually tie the IRQ input low
|
||||
|
@ -860,7 +860,7 @@ wai macro
|
|||
trap_ne ;skipped opcodes!
|
||||
|
||||
success
|
||||
|
||||
|
||||
; WAI with interrupts enabled
|
||||
ldx #$ff
|
||||
txs
|
||||
|
@ -878,13 +878,13 @@ wai macro
|
|||
trap_ne ;skipped opcodes!
|
||||
|
||||
success
|
||||
|
||||
|
||||
; manual test for the STP opcode of the 65c02
|
||||
|
||||
stp macro
|
||||
stp macro
|
||||
db $db ;STP opcode
|
||||
endm
|
||||
|
||||
|
||||
; set PC to the 1st instruction of the test, then run
|
||||
nop
|
||||
nop
|
||||
|
@ -916,7 +916,7 @@ nmi_trap
|
|||
pha
|
||||
sta nmi_f
|
||||
lda I_src ;NMI expected?
|
||||
and #4
|
||||
and #4
|
||||
trap_eq ;unexpexted NMI - check stack for conditions
|
||||
pla ;test I-flag was set
|
||||
pha
|
||||
|
@ -925,7 +925,7 @@ nmi_trap
|
|||
pla ;return with other flags reversed
|
||||
eor #m8-fai-decmode
|
||||
pha
|
||||
tsx
|
||||
tsx
|
||||
lda $102,x ;test break on stack
|
||||
and #break
|
||||
trap_ne ;unexpected B-flag! - this may fail on a real 6502
|
||||
|
@ -933,7 +933,7 @@ nmi_trap
|
|||
lda I_src ;mark expected NMI has occured
|
||||
and #$ff-4
|
||||
sta I_src
|
||||
I_clr NMI_bit
|
||||
I_clr NMI_bit
|
||||
ldx nmi_x
|
||||
inx
|
||||
stx nmi_count
|
||||
|
@ -944,7 +944,7 @@ nmi_trap
|
|||
|
||||
res_trap
|
||||
trap ;unexpected RESET
|
||||
|
||||
|
||||
dey
|
||||
dey
|
||||
irq_trap ;BRK & IRQ test
|
||||
|
@ -958,7 +958,7 @@ irq_trap ;BRK & IRQ test
|
|||
pha
|
||||
sta irq_f
|
||||
lda I_src ;IRQ expected?
|
||||
and #3
|
||||
and #3
|
||||
trap_eq ;unexpexted IRQ/BRK - check stack for conditions
|
||||
pla ;test I-flag was set
|
||||
pha
|
||||
|
@ -966,26 +966,26 @@ irq_trap ;BRK & IRQ test
|
|||
trap_eq ;I-flag not set
|
||||
pla ;return with other flags reversed
|
||||
eor #m8-fai-decmode
|
||||
pha
|
||||
pha
|
||||
tsx
|
||||
lda $102,x ;test break on stack
|
||||
and #break
|
||||
bne brk_trap
|
||||
|
||||
|
||||
lda I_src ;IRQ expected?
|
||||
and #2
|
||||
and #2
|
||||
trap_eq ;unexpexted IRQ - check stack for conditions
|
||||
lda I_src ;mark expected IRQ has occured
|
||||
and #$ff-2
|
||||
sta I_src
|
||||
I_clr IRQ_bit
|
||||
I_clr IRQ_bit
|
||||
ldx irq_x
|
||||
inx
|
||||
stx irq_count
|
||||
lda #'Q' ;mark (IR)Q
|
||||
plp ;should be reversed by rti
|
||||
rti
|
||||
|
||||
|
||||
brk_trap
|
||||
lda I_src ;break expected?
|
||||
and #1
|
||||
|
@ -995,18 +995,18 @@ brk_trap
|
|||
sta I_src
|
||||
ldx irq_x
|
||||
inx
|
||||
stx brk_count
|
||||
stx brk_count
|
||||
lda irq_a
|
||||
lda #'K' ;mark (BR)K
|
||||
plp ;should be reversed by rti
|
||||
rti
|
||||
|
||||
|
||||
if report = 1
|
||||
rep_int = 1
|
||||
include "report.i65"
|
||||
endif
|
||||
|
||||
|
||||
|
||||
;system vectors
|
||||
if (load_data_direct = 1)
|
||||
org $fffa
|
||||
|
@ -1020,7 +1020,6 @@ vec_bss equ $fffa
|
|||
dw res_trap
|
||||
dw irq_trap
|
||||
endif
|
||||
|
||||
|
||||
end start
|
||||
|
||||
|
||||
|
||||
|
|
356
src/test/kotlin/6502_functional_tests/65C02_decimal_test.a65
Normal file
356
src/test/kotlin/6502_functional_tests/65C02_decimal_test.a65
Normal file
|
@ -0,0 +1,356 @@
|
|||
; Verify decimal mode behavior
|
||||
; Written by Bruce Clark. This code is public domain.
|
||||
; see http://www.6502.org/tutorials/decimal_mode.html
|
||||
;
|
||||
; Returns:
|
||||
; ERROR = 0 if the test passed
|
||||
; ERROR = 1 if the test failed
|
||||
; modify the code at the DONE label for desired program end
|
||||
;
|
||||
; This routine requires 17 bytes of RAM -- 1 byte each for:
|
||||
; AR, CF, DA, DNVZC, ERROR, HA, HNVZC, N1, N1H, N1L, N2, N2L, NF, VF, and ZF
|
||||
; and 2 bytes for N2H
|
||||
;
|
||||
; Variables:
|
||||
; N1 and N2 are the two numbers to be added or subtracted
|
||||
; N1H, N1L, N2H, and N2L are the upper 4 bits and lower 4 bits of N1 and N2
|
||||
; DA and DNVZC are the actual accumulator and flag results in decimal mode
|
||||
; HA and HNVZC are the accumulator and flag results when N1 and N2 are
|
||||
; added or subtracted using binary arithmetic
|
||||
; AR, NF, VF, ZF, and CF are the predicted decimal mode accumulator and
|
||||
; flag results, calculated using binary arithmetic
|
||||
;
|
||||
; This program takes approximately 1 minute at 1 MHz (a few seconds more on
|
||||
; a 65C02 than a 6502 or 65816)
|
||||
;
|
||||
|
||||
; Configuration:
|
||||
cputype = 1 ; 0 = 6502, 1 = 65C02, 2 = 65C816
|
||||
vld_bcd = 0 ; 0 = allow invalid bcd, 1 = valid bcd only
|
||||
chk_a = 1 ; check accumulator
|
||||
chk_n = 0 ; check sign (negative) flag
|
||||
chk_v = 0 ; check overflow flag
|
||||
chk_z = 0 ; check zero flag
|
||||
chk_c = 1 ; check carry flag
|
||||
|
||||
end_of_test macro
|
||||
brk
|
||||
; db $db ;execute 65C02 stop instruction
|
||||
endm
|
||||
|
||||
bss
|
||||
org 0
|
||||
; operands - register Y = carry in
|
||||
N1 ds 1
|
||||
N2 ds 1
|
||||
; binary result
|
||||
HA ds 1
|
||||
HNVZC ds 1
|
||||
;04
|
||||
; decimal result
|
||||
DA ds 1
|
||||
DNVZC ds 1
|
||||
; predicted results
|
||||
AR ds 1
|
||||
NF ds 1
|
||||
;08
|
||||
VF ds 1
|
||||
ZF ds 1
|
||||
CF ds 1
|
||||
ERROR ds 1
|
||||
;0C
|
||||
; workspace
|
||||
N1L ds 1
|
||||
N1H ds 1
|
||||
N2L ds 1
|
||||
N2H ds 2
|
||||
|
||||
code
|
||||
org $200
|
||||
TEST ldy #1 ; initialize Y (used to loop through carry flag values)
|
||||
sty ERROR ; store 1 in ERROR until the test passes
|
||||
lda #0 ; initialize N1 and N2
|
||||
sta N1
|
||||
sta N2
|
||||
LOOP1 lda N2 ; N2L = N2 & $0F
|
||||
and #$0F ; [1] see text
|
||||
if vld_bcd = 1
|
||||
cmp #$0a
|
||||
bcs NEXT2
|
||||
endif
|
||||
sta N2L
|
||||
lda N2 ; N2H = N2 & $F0
|
||||
and #$F0 ; [2] see text
|
||||
if vld_bcd = 1
|
||||
cmp #$a0
|
||||
bcs NEXT2
|
||||
endif
|
||||
sta N2H
|
||||
ora #$0F ; N2H+1 = (N2 & $F0) + $0F
|
||||
sta N2H+1
|
||||
LOOP2 lda N1 ; N1L = N1 & $0F
|
||||
and #$0F ; [3] see text
|
||||
if vld_bcd = 1
|
||||
cmp #$0a
|
||||
bcs NEXT1
|
||||
endif
|
||||
sta N1L
|
||||
lda N1 ; N1H = N1 & $F0
|
||||
and #$F0 ; [4] see text
|
||||
if vld_bcd = 1
|
||||
cmp #$a0
|
||||
bcs NEXT1
|
||||
endif
|
||||
sta N1H
|
||||
jsr ADD
|
||||
jsr A6502
|
||||
jsr COMPARE
|
||||
bne DONE
|
||||
jsr SUB
|
||||
jsr S6502
|
||||
jsr COMPARE
|
||||
bne DONE
|
||||
NEXT1 inc N1 ; [5] see text
|
||||
bne LOOP2 ; loop through all 256 values of N1
|
||||
NEXT2 inc N2 ; [6] see text
|
||||
bne LOOP1 ; loop through all 256 values of N2
|
||||
dey
|
||||
bpl LOOP1 ; loop through both values of the carry flag
|
||||
lda #0 ; test passed, so store 0 in ERROR
|
||||
sta ERROR
|
||||
DONE
|
||||
end_of_test
|
||||
|
||||
; Calculate the actual decimal mode accumulator and flags, the accumulator
|
||||
; and flag results when N1 is added to N2 using binary arithmetic, the
|
||||
; predicted accumulator result, the predicted carry flag, and the predicted
|
||||
; V flag
|
||||
;
|
||||
ADD sed ; decimal mode
|
||||
cpy #1 ; set carry if Y = 1, clear carry if Y = 0
|
||||
lda N1
|
||||
adc N2
|
||||
sta DA ; actual accumulator result in decimal mode
|
||||
php
|
||||
pla
|
||||
sta DNVZC ; actual flags result in decimal mode
|
||||
cld ; binary mode
|
||||
cpy #1 ; set carry if Y = 1, clear carry if Y = 0
|
||||
lda N1
|
||||
adc N2
|
||||
sta HA ; accumulator result of N1+N2 using binary arithmetic
|
||||
|
||||
php
|
||||
pla
|
||||
sta HNVZC ; flags result of N1+N2 using binary arithmetic
|
||||
cpy #1
|
||||
lda N1L
|
||||
adc N2L
|
||||
cmp #$0A
|
||||
ldx #0
|
||||
bcc A1
|
||||
inx
|
||||
adc #5 ; add 6 (carry is set)
|
||||
and #$0F
|
||||
sec
|
||||
A1 ora N1H
|
||||
;
|
||||
; if N1L + N2L < $0A, then add N2 & $F0
|
||||
; if N1L + N2L >= $0A, then add (N2 & $F0) + $0F + 1 (carry is set)
|
||||
;
|
||||
adc N2H,x
|
||||
php
|
||||
bcs A2
|
||||
cmp #$A0
|
||||
bcc A3
|
||||
A2 adc #$5F ; add $60 (carry is set)
|
||||
sec
|
||||
A3 sta AR ; predicted accumulator result
|
||||
php
|
||||
pla
|
||||
sta CF ; predicted carry result
|
||||
pla
|
||||
;
|
||||
; note that all 8 bits of the P register are stored in VF
|
||||
;
|
||||
sta VF ; predicted V flags
|
||||
rts
|
||||
|
||||
; Calculate the actual decimal mode accumulator and flags, and the
|
||||
; accumulator and flag results when N2 is subtracted from N1 using binary
|
||||
; arithmetic
|
||||
;
|
||||
SUB sed ; decimal mode
|
||||
cpy #1 ; set carry if Y = 1, clear carry if Y = 0
|
||||
lda N1
|
||||
sbc N2
|
||||
sta DA ; actual accumulator result in decimal mode
|
||||
php
|
||||
pla
|
||||
sta DNVZC ; actual flags result in decimal mode
|
||||
cld ; binary mode
|
||||
cpy #1 ; set carry if Y = 1, clear carry if Y = 0
|
||||
lda N1
|
||||
sbc N2
|
||||
sta HA ; accumulator result of N1-N2 using binary arithmetic
|
||||
|
||||
php
|
||||
pla
|
||||
sta HNVZC ; flags result of N1-N2 using binary arithmetic
|
||||
rts
|
||||
|
||||
if cputype != 1
|
||||
; Calculate the predicted SBC accumulator result for the 6502 and 65816
|
||||
;
|
||||
SUB1 cpy #1 ; set carry if Y = 1, clear carry if Y = 0
|
||||
lda N1L
|
||||
sbc N2L
|
||||
ldx #0
|
||||
bcs S11
|
||||
inx
|
||||
sbc #5 ; subtract 6 (carry is clear)
|
||||
and #$0F
|
||||
clc
|
||||
S11 ora N1H
|
||||
;
|
||||
; if N1L - N2L >= 0, then subtract N2 & $F0
|
||||
; if N1L - N2L < 0, then subtract (N2 & $F0) + $0F + 1 (carry is clear)
|
||||
;
|
||||
sbc N2H,x
|
||||
bcs S12
|
||||
sbc #$5F ; subtract $60 (carry is clear)
|
||||
S12 sta AR
|
||||
rts
|
||||
endif
|
||||
|
||||
if cputype = 1
|
||||
; Calculate the predicted SBC accumulator result for the 6502 and 65C02
|
||||
;
|
||||
SUB2 cpy #1 ; set carry if Y = 1, clear carry if Y = 0
|
||||
lda N1L
|
||||
sbc N2L
|
||||
ldx #0
|
||||
bcs S21
|
||||
inx
|
||||
and #$0F
|
||||
clc
|
||||
S21 ora N1H
|
||||
;
|
||||
; if N1L - N2L >= 0, then subtract N2 & $F0
|
||||
; if N1L - N2L < 0, then subtract (N2 & $F0) + $0F + 1 (carry is clear)
|
||||
;
|
||||
sbc N2H,x
|
||||
bcs S22
|
||||
sbc #$5F ; subtract $60 (carry is clear)
|
||||
S22 cpx #0
|
||||
beq S23
|
||||
sbc #6
|
||||
S23 sta AR ; predicted accumulator result
|
||||
rts
|
||||
endif
|
||||
|
||||
; Compare accumulator actual results to predicted results
|
||||
;
|
||||
; Return:
|
||||
; Z flag = 1 (BEQ branch) if same
|
||||
; Z flag = 0 (BNE branch) if different
|
||||
;
|
||||
COMPARE
|
||||
if chk_a = 1
|
||||
lda DA
|
||||
cmp AR
|
||||
bne C1
|
||||
endif
|
||||
if chk_n = 1
|
||||
lda DNVZC ; [7] see text
|
||||
eor NF
|
||||
and #$80 ; mask off N flag
|
||||
bne C1
|
||||
endif
|
||||
if chk_v = 1
|
||||
lda DNVZC ; [8] see text
|
||||
eor VF
|
||||
and #$40 ; mask off V flag
|
||||
bne C1 ; [9] see text
|
||||
endif
|
||||
if chk_z = 1
|
||||
lda DNVZC
|
||||
eor ZF ; mask off Z flag
|
||||
and #2
|
||||
bne C1 ; [10] see text
|
||||
endif
|
||||
if chk_c = 1
|
||||
lda DNVZC
|
||||
eor CF
|
||||
and #1 ; mask off C flag
|
||||
endif
|
||||
C1 rts
|
||||
|
||||
; These routines store the predicted values for ADC and SBC for the 6502,
|
||||
; 65C02, and 65816 in AR, CF, NF, VF, and ZF
|
||||
|
||||
if cputype = 0
|
||||
|
||||
A6502 lda VF ; 6502
|
||||
;
|
||||
; since all 8 bits of the P register were stored in VF, bit 7 of VF contains
|
||||
; the N flag for NF
|
||||
;
|
||||
sta NF
|
||||
lda HNVZC
|
||||
sta ZF
|
||||
rts
|
||||
|
||||
S6502 jsr SUB1
|
||||
lda HNVZC
|
||||
sta NF
|
||||
sta VF
|
||||
sta ZF
|
||||
sta CF
|
||||
rts
|
||||
|
||||
endif
|
||||
if cputype = 1
|
||||
|
||||
A6502 lda AR ; 65C02
|
||||
php
|
||||
pla
|
||||
sta NF
|
||||
sta ZF
|
||||
rts
|
||||
|
||||
S6502 jsr SUB2
|
||||
lda AR
|
||||
php
|
||||
pla
|
||||
sta NF
|
||||
sta ZF
|
||||
lda HNVZC
|
||||
sta VF
|
||||
sta CF
|
||||
rts
|
||||
|
||||
endif
|
||||
if cputype = 2
|
||||
|
||||
A6502 lda AR ; 65C816
|
||||
php
|
||||
pla
|
||||
sta NF
|
||||
sta ZF
|
||||
rts
|
||||
|
||||
S6502 jsr SUB1
|
||||
lda AR
|
||||
php
|
||||
pla
|
||||
sta NF
|
||||
sta ZF
|
||||
lda HNVZC
|
||||
sta VF
|
||||
sta CF
|
||||
rts
|
||||
|
||||
endif
|
||||
|
||||
end TEST
|
BIN
src/test/kotlin/6502_functional_tests/as65_142.zip
Normal file
BIN
src/test/kotlin/6502_functional_tests/as65_142.zip
Normal file
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,369 @@
|
|||
AS65 Assembler for R6502 [1.42]. Copyright 1994-2007, Frank A. Kingswood Page 1
|
||||
----------------------------------------------------- 6502_decimal_test.a65 ------------------------------------------------------
|
||||
|
||||
356 lines read, no errors in pass 1.
|
||||
; Verify decimal mode behavior
|
||||
; Written by Bruce Clark. This code is public domain.
|
||||
; see http://www.6502.org/tutorials/decimal_mode.html
|
||||
;
|
||||
; Returns:
|
||||
; ERROR = 0 if the test passed
|
||||
; ERROR = 1 if the test failed
|
||||
; modify the code at the DONE label for desired program end
|
||||
;
|
||||
; This routine requires 17 bytes of RAM -- 1 byte each for:
|
||||
; AR, CF, DA, DNVZC, ERROR, HA, HNVZC, N1, N1H, N1L, N2, N2L, NF, VF, and ZF
|
||||
; and 2 bytes for N2H
|
||||
;
|
||||
; Variables:
|
||||
; N1 and N2 are the two numbers to be added or subtracted
|
||||
; N1H, N1L, N2H, and N2L are the upper 4 bits and lower 4 bits of N1 and N2
|
||||
; DA and DNVZC are the actual accumulator and flag results in decimal mode
|
||||
; HA and HNVZC are the accumulator and flag results when N1 and N2 are
|
||||
; added or subtracted using binary arithmetic
|
||||
; AR, NF, VF, ZF, and CF are the predicted decimal mode accumulator and
|
||||
; flag results, calculated using binary arithmetic
|
||||
;
|
||||
; This program takes approximately 1 minute at 1 MHz (a few seconds more on
|
||||
; a 65C02 than a 6502 or 65816)
|
||||
;
|
||||
|
||||
; Configuration:
|
||||
0000 = cputype = 0 ; 0 = 6502, 1 = 65C02, 2 = 65C816
|
||||
0000 = vld_bcd = 0 ; 0 = allow invalid bcd, 1 = valid bcd only
|
||||
0001 = chk_a = 1 ; check accumulator
|
||||
0000 = chk_n = 0 ; check sign (negative) flag
|
||||
0000 = chk_v = 0 ; check overflow flag
|
||||
0000 = chk_z = 0 ; check zero flag
|
||||
0001 = chk_c = 1 ; check carry flag
|
||||
|
||||
end_of_test macro
|
||||
brk
|
||||
; db $db ;execute 65C02 stop instruction
|
||||
endm
|
||||
|
||||
bss
|
||||
0000 = org 0
|
||||
; operands - register Y = carry in
|
||||
0000 = N1 ds 1
|
||||
0001 = N2 ds 1
|
||||
; binary result
|
||||
0002 = HA ds 1
|
||||
0003 = HNVZC ds 1
|
||||
;04
|
||||
; decimal result
|
||||
0004 = DA ds 1
|
||||
0005 = DNVZC ds 1
|
||||
; predicted results
|
||||
0006 = AR ds 1
|
||||
0007 = NF ds 1
|
||||
;08
|
||||
0008 = VF ds 1
|
||||
0009 = ZF ds 1
|
||||
000a = CF ds 1
|
||||
000b = ERROR ds 1
|
||||
;0C
|
||||
; workspace
|
||||
000c = N1L ds 1
|
||||
000d = N1H ds 1
|
||||
000e = N2L ds 1
|
||||
000f = N2H ds 2
|
||||
|
||||
code
|
||||
0200 = org $200
|
||||
0200 : a001 TEST ldy #1 ; initialize Y (used to loop through carry flag values)
|
||||
0202 : 840b sty ERROR ; store 1 in ERROR until the test passes
|
||||
0204 : a900 lda #0 ; initialize N1 and N2
|
||||
0206 : 8500 sta N1
|
||||
0208 : 8501 sta N2
|
||||
020a : a501 LOOP1 lda N2 ; N2L = N2 & $0F
|
||||
020c : 290f and #$0F ; [1] see text
|
||||
if vld_bcd = 1
|
||||
cmp #$0a
|
||||
bcs NEXT2
|
||||
endif
|
||||
020e : 850e sta N2L
|
||||
0210 : a501 lda N2 ; N2H = N2 & $F0
|
||||
0212 : 29f0 and #$F0 ; [2] see text
|
||||
if vld_bcd = 1
|
||||
cmp #$a0
|
||||
bcs NEXT2
|
||||
endif
|
||||
0214 : 850f sta N2H
|
||||
0216 : 090f ora #$0F ; N2H+1 = (N2 & $F0) + $0F
|
||||
0218 : 8510 sta N2H+1
|
||||
021a : a500 LOOP2 lda N1 ; N1L = N1 & $0F
|
||||
021c : 290f and #$0F ; [3] see text
|
||||
if vld_bcd = 1
|
||||
cmp #$0a
|
||||
bcs NEXT1
|
||||
endif
|
||||
021e : 850c sta N1L
|
||||
0220 : a500 lda N1 ; N1H = N1 & $F0
|
||||
0222 : 29f0 and #$F0 ; [4] see text
|
||||
if vld_bcd = 1
|
||||
cmp #$a0
|
||||
bcs NEXT1
|
||||
endif
|
||||
0224 : 850d sta N1H
|
||||
0226 : 204c02 jsr ADD
|
||||
0229 : 20d302 jsr A6502
|
||||
022c : 20c602 jsr COMPARE
|
||||
022f : d01a bne DONE
|
||||
0231 : 209002 jsr SUB
|
||||
0234 : 20dc02 jsr S6502
|
||||
0237 : 20c602 jsr COMPARE
|
||||
023a : d00f bne DONE
|
||||
023c : e600 NEXT1 inc N1 ; [5] see text
|
||||
023e : d0da bne LOOP2 ; loop through all 256 values of N1
|
||||
0240 : e601 NEXT2 inc N2 ; [6] see text
|
||||
0242 : d0c6 bne LOOP1 ; loop through all 256 values of N2
|
||||
0244 : 88 dey
|
||||
0245 : 10c3 bpl LOOP1 ; loop through both values of the carry flag
|
||||
0247 : a900 lda #0 ; test passed, so store 0 in ERROR
|
||||
0249 : 850b sta ERROR
|
||||
024b : DONE
|
||||
end_of_test
|
||||
024b : 00 > brk
|
||||
> ; db $db ;execute 65C02 stop instruction
|
||||
|
||||
|
||||
; Calculate the actual decimal mode accumulator and flags, the accumulator
|
||||
; and flag results when N1 is added to N2 using binary arithmetic, the
|
||||
; predicted accumulator result, the predicted carry flag, and the predicted
|
||||
; V flag
|
||||
;
|
||||
024c : f8 ADD sed ; decimal mode
|
||||
024d : c001 cpy #1 ; set carry if Y = 1, clear carry if Y = 0
|
||||
024f : a500 lda N1
|
||||
0251 : 6501 adc N2
|
||||
0253 : 8504 sta DA ; actual accumulator result in decimal mode
|
||||
0255 : 08 php
|
||||
0256 : 68 pla
|
||||
0257 : 8505 sta DNVZC ; actual flags result in decimal mode
|
||||
0259 : d8 cld ; binary mode
|
||||
025a : c001 cpy #1 ; set carry if Y = 1, clear carry if Y = 0
|
||||
025c : a500 lda N1
|
||||
025e : 6501 adc N2
|
||||
0260 : 8502 sta HA ; accumulator result of N1+N2 using binary arithmetic
|
||||
|
||||
0262 : 08 php
|
||||
0263 : 68 pla
|
||||
0264 : 8503 sta HNVZC ; flags result of N1+N2 using binary arithmetic
|
||||
0266 : c001 cpy #1
|
||||
0268 : a50c lda N1L
|
||||
026a : 650e adc N2L
|
||||
026c : c90a cmp #$0A
|
||||
026e : a200 ldx #0
|
||||
0270 : 9006 bcc A1
|
||||
0272 : e8 inx
|
||||
0273 : 6905 adc #5 ; add 6 (carry is set)
|
||||
0275 : 290f and #$0F
|
||||
0277 : 38 sec
|
||||
0278 : 050d A1 ora N1H
|
||||
;
|
||||
; if N1L + N2L < $0A, then add N2 & $F0
|
||||
; if N1L + N2L >= $0A, then add (N2 & $F0) + $0F + 1 (carry is set)
|
||||
;
|
||||
027a : 750f adc N2H,x
|
||||
027c : 08 php
|
||||
027d : b004 bcs A2
|
||||
027f : c9a0 cmp #$A0
|
||||
0281 : 9003 bcc A3
|
||||
0283 : 695f A2 adc #$5F ; add $60 (carry is set)
|
||||
0285 : 38 sec
|
||||
0286 : 8506 A3 sta AR ; predicted accumulator result
|
||||
0288 : 08 php
|
||||
0289 : 68 pla
|
||||
028a : 850a sta CF ; predicted carry result
|
||||
028c : 68 pla
|
||||
;
|
||||
; note that all 8 bits of the P register are stored in VF
|
||||
;
|
||||
028d : 8508 sta VF ; predicted V flags
|
||||
028f : 60 rts
|
||||
|
||||
; Calculate the actual decimal mode accumulator and flags, and the
|
||||
; accumulator and flag results when N2 is subtracted from N1 using binary
|
||||
; arithmetic
|
||||
;
|
||||
0290 : f8 SUB sed ; decimal mode
|
||||
0291 : c001 cpy #1 ; set carry if Y = 1, clear carry if Y = 0
|
||||
0293 : a500 lda N1
|
||||
0295 : e501 sbc N2
|
||||
0297 : 8504 sta DA ; actual accumulator result in decimal mode
|
||||
0299 : 08 php
|
||||
029a : 68 pla
|
||||
029b : 8505 sta DNVZC ; actual flags result in decimal mode
|
||||
029d : d8 cld ; binary mode
|
||||
029e : c001 cpy #1 ; set carry if Y = 1, clear carry if Y = 0
|
||||
02a0 : a500 lda N1
|
||||
02a2 : e501 sbc N2
|
||||
02a4 : 8502 sta HA ; accumulator result of N1-N2 using binary arithmetic
|
||||
|
||||
02a6 : 08 php
|
||||
02a7 : 68 pla
|
||||
02a8 : 8503 sta HNVZC ; flags result of N1-N2 using binary arithmetic
|
||||
02aa : 60 rts
|
||||
|
||||
if cputype != 1
|
||||
; Calculate the predicted SBC accumulator result for the 6502 and 65816
|
||||
;
|
||||
02ab : c001 SUB1 cpy #1 ; set carry if Y = 1, clear carry if Y = 0
|
||||
02ad : a50c lda N1L
|
||||
02af : e50e sbc N2L
|
||||
02b1 : a200 ldx #0
|
||||
02b3 : b006 bcs S11
|
||||
02b5 : e8 inx
|
||||
02b6 : e905 sbc #5 ; subtract 6 (carry is clear)
|
||||
02b8 : 290f and #$0F
|
||||
02ba : 18 clc
|
||||
02bb : 050d S11 ora N1H
|
||||
;
|
||||
; if N1L - N2L >= 0, then subtract N2 & $F0
|
||||
; if N1L - N2L < 0, then subtract (N2 & $F0) + $0F + 1 (carry is clear)
|
||||
;
|
||||
02bd : f50f sbc N2H,x
|
||||
02bf : b002 bcs S12
|
||||
02c1 : e95f sbc #$5F ; subtract $60 (carry is clear)
|
||||
02c3 : 8506 S12 sta AR
|
||||
02c5 : 60 rts
|
||||
endif
|
||||
|
||||
if cputype = 1
|
||||
; Calculate the predicted SBC accumulator result for the 6502 and 65C02
|
||||
;
|
||||
SUB2 cpy #1 ; set carry if Y = 1, clear carry if Y = 0
|
||||
lda N1L
|
||||
sbc N2L
|
||||
ldx #0
|
||||
bcs S21
|
||||
inx
|
||||
and #$0F
|
||||
clc
|
||||
S21 ora N1H
|
||||
;
|
||||
; if N1L - N2L >= 0, then subtract N2 & $F0
|
||||
; if N1L - N2L < 0, then subtract (N2 & $F0) + $0F + 1 (carry is clear)
|
||||
;
|
||||
sbc N2H,x
|
||||
bcs S22
|
||||
sbc #$5F ; subtract $60 (carry is clear)
|
||||
S22 cpx #0
|
||||
beq S23
|
||||
sbc #6
|
||||
S23 sta AR ; predicted accumulator result
|
||||
rts
|
||||
endif
|
||||
|
||||
; Compare accumulator actual results to predicted results
|
||||
;
|
||||
; Return:
|
||||
; Z flag = 1 (BEQ branch) if same
|
||||
; Z flag = 0 (BNE branch) if different
|
||||
;
|
||||
02c6 : COMPARE
|
||||
if chk_a = 1
|
||||
02c6 : a504 lda DA
|
||||
02c8 : c506 cmp AR
|
||||
02ca : d006 bne C1
|
||||
endif
|
||||
if chk_n = 1
|
||||
lda DNVZC ; [7] see text
|
||||
eor NF
|
||||
and #$80 ; mask off N flag
|
||||
bne C1
|
||||
endif
|
||||
if chk_v = 1
|
||||
lda DNVZC ; [8] see text
|
||||
eor VF
|
||||
and #$40 ; mask off V flag
|
||||
bne C1 ; [9] see text
|
||||
endif
|
||||
if chk_z = 1
|
||||
lda DNVZC
|
||||
eor ZF ; mask off Z flag
|
||||
and #2
|
||||
bne C1 ; [10] see text
|
||||
endif
|
||||
if chk_c = 1
|
||||
02cc : a505 lda DNVZC
|
||||
02ce : 450a eor CF
|
||||
02d0 : 2901 and #1 ; mask off C flag
|
||||
endif
|
||||
02d2 : 60 C1 rts
|
||||
|
||||
; These routines store the predicted values for ADC and SBC for the 6502,
|
||||
; 65C02, and 65816 in AR, CF, NF, VF, and ZF
|
||||
|
||||
if cputype = 0
|
||||
|
||||
02d3 : a508 A6502 lda VF ; 6502
|
||||
;
|
||||
; since all 8 bits of the P register were stored in VF, bit 7 of VF contains
|
||||
; the N flag for NF
|
||||
;
|
||||
02d5 : 8507 sta NF
|
||||
02d7 : a503 lda HNVZC
|
||||
02d9 : 8509 sta ZF
|
||||
02db : 60 rts
|
||||
|
||||
02dc : 20ab02 S6502 jsr SUB1
|
||||
02df : a503 lda HNVZC
|
||||
02e1 : 8507 sta NF
|
||||
02e3 : 8508 sta VF
|
||||
02e5 : 8509 sta ZF
|
||||
02e7 : 850a sta CF
|
||||
02e9 : 60 rts
|
||||
|
||||
endif
|
||||
if cputype = 1
|
||||
|
||||
A6502 lda AR ; 65C02
|
||||
php
|
||||
pla
|
||||
sta NF
|
||||
sta ZF
|
||||
rts
|
||||
|
||||
S6502 jsr SUB2
|
||||
lda AR
|
||||
php
|
||||
pla
|
||||
sta NF
|
||||
sta ZF
|
||||
lda HNVZC
|
||||
sta VF
|
||||
sta CF
|
||||
rts
|
||||
|
||||
endif
|
||||
if cputype = 2
|
||||
|
||||
A6502 lda AR ; 65C816
|
||||
php
|
||||
pla
|
||||
sta NF
|
||||
sta ZF
|
||||
rts
|
||||
|
||||
S6502 jsr SUB1
|
||||
lda AR
|
||||
php
|
||||
pla
|
||||
sta NF
|
||||
sta ZF
|
||||
lda HNVZC
|
||||
sta VF
|
||||
sta CF
|
||||
rts
|
||||
|
||||
endif
|
||||
|
||||
02dc = end TEST
|
||||
|
||||
No errors in pass 2.
|
||||
Wrote binary from address $0200 through $02e9.
|
||||
Total size 234 bytes.
|
||||
Program start address is at $0200 (512).
|
||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
@ -0,0 +1,369 @@
|
|||
AS65 Assembler for R6502 [1.42]. Copyright 1994-2007, Frank A. Kingswood Page 1
|
||||
----------------------------------------------------- 65C02_decimal_test.a65 -----------------------------------------------------
|
||||
|
||||
356 lines read, no errors in pass 1.
|
||||
; Verify decimal mode behavior
|
||||
; Written by Bruce Clark. This code is public domain.
|
||||
; see http://www.6502.org/tutorials/decimal_mode.html
|
||||
;
|
||||
; Returns:
|
||||
; ERROR = 0 if the test passed
|
||||
; ERROR = 1 if the test failed
|
||||
; modify the code at the DONE label for desired program end
|
||||
;
|
||||
; This routine requires 17 bytes of RAM -- 1 byte each for:
|
||||
; AR, CF, DA, DNVZC, ERROR, HA, HNVZC, N1, N1H, N1L, N2, N2L, NF, VF, and ZF
|
||||
; and 2 bytes for N2H
|
||||
;
|
||||
; Variables:
|
||||
; N1 and N2 are the two numbers to be added or subtracted
|
||||
; N1H, N1L, N2H, and N2L are the upper 4 bits and lower 4 bits of N1 and N2
|
||||
; DA and DNVZC are the actual accumulator and flag results in decimal mode
|
||||
; HA and HNVZC are the accumulator and flag results when N1 and N2 are
|
||||
; added or subtracted using binary arithmetic
|
||||
; AR, NF, VF, ZF, and CF are the predicted decimal mode accumulator and
|
||||
; flag results, calculated using binary arithmetic
|
||||
;
|
||||
; This program takes approximately 1 minute at 1 MHz (a few seconds more on
|
||||
; a 65C02 than a 6502 or 65816)
|
||||
;
|
||||
|
||||
; Configuration:
|
||||
0001 = cputype = 1 ; 0 = 6502, 1 = 65C02, 2 = 65C816
|
||||
0000 = vld_bcd = 0 ; 0 = allow invalid bcd, 1 = valid bcd only
|
||||
0001 = chk_a = 1 ; check accumulator
|
||||
0000 = chk_n = 0 ; check sign (negative) flag
|
||||
0000 = chk_v = 0 ; check overflow flag
|
||||
0000 = chk_z = 0 ; check zero flag
|
||||
0001 = chk_c = 1 ; check carry flag
|
||||
|
||||
end_of_test macro
|
||||
brk
|
||||
; db $db ;execute 65C02 stop instruction
|
||||
endm
|
||||
|
||||
bss
|
||||
0000 = org 0
|
||||
; operands - register Y = carry in
|
||||
0000 = N1 ds 1
|
||||
0001 = N2 ds 1
|
||||
; binary result
|
||||
0002 = HA ds 1
|
||||
0003 = HNVZC ds 1
|
||||
;04
|
||||
; decimal result
|
||||
0004 = DA ds 1
|
||||
0005 = DNVZC ds 1
|
||||
; predicted results
|
||||
0006 = AR ds 1
|
||||
0007 = NF ds 1
|
||||
;08
|
||||
0008 = VF ds 1
|
||||
0009 = ZF ds 1
|
||||
000a = CF ds 1
|
||||
000b = ERROR ds 1
|
||||
;0C
|
||||
; workspace
|
||||
000c = N1L ds 1
|
||||
000d = N1H ds 1
|
||||
000e = N2L ds 1
|
||||
000f = N2H ds 2
|
||||
|
||||
code
|
||||
0200 = org $200
|
||||
0200 : a001 TEST ldy #1 ; initialize Y (used to loop through carry flag values)
|
||||
0202 : 840b sty ERROR ; store 1 in ERROR until the test passes
|
||||
0204 : a900 lda #0 ; initialize N1 and N2
|
||||
0206 : 8500 sta N1
|
||||
0208 : 8501 sta N2
|
||||
020a : a501 LOOP1 lda N2 ; N2L = N2 & $0F
|
||||
020c : 290f and #$0F ; [1] see text
|
||||
if vld_bcd = 1
|
||||
cmp #$0a
|
||||
bcs NEXT2
|
||||
endif
|
||||
020e : 850e sta N2L
|
||||
0210 : a501 lda N2 ; N2H = N2 & $F0
|
||||
0212 : 29f0 and #$F0 ; [2] see text
|
||||
if vld_bcd = 1
|
||||
cmp #$a0
|
||||
bcs NEXT2
|
||||
endif
|
||||
0214 : 850f sta N2H
|
||||
0216 : 090f ora #$0F ; N2H+1 = (N2 & $F0) + $0F
|
||||
0218 : 8510 sta N2H+1
|
||||
021a : a500 LOOP2 lda N1 ; N1L = N1 & $0F
|
||||
021c : 290f and #$0F ; [3] see text
|
||||
if vld_bcd = 1
|
||||
cmp #$0a
|
||||
bcs NEXT1
|
||||
endif
|
||||
021e : 850c sta N1L
|
||||
0220 : a500 lda N1 ; N1H = N1 & $F0
|
||||
0222 : 29f0 and #$F0 ; [4] see text
|
||||
if vld_bcd = 1
|
||||
cmp #$a0
|
||||
bcs NEXT1
|
||||
endif
|
||||
0224 : 850d sta N1H
|
||||
0226 : 204c02 jsr ADD
|
||||
0229 : 20d702 jsr A6502
|
||||
022c : 20ca02 jsr COMPARE
|
||||
022f : d01a bne DONE
|
||||
0231 : 209002 jsr SUB
|
||||
0234 : 20e002 jsr S6502
|
||||
0237 : 20ca02 jsr COMPARE
|
||||
023a : d00f bne DONE
|
||||
023c : e600 NEXT1 inc N1 ; [5] see text
|
||||
023e : d0da bne LOOP2 ; loop through all 256 values of N1
|
||||
0240 : e601 NEXT2 inc N2 ; [6] see text
|
||||
0242 : d0c6 bne LOOP1 ; loop through all 256 values of N2
|
||||
0244 : 88 dey
|
||||
0245 : 10c3 bpl LOOP1 ; loop through both values of the carry flag
|
||||
0247 : a900 lda #0 ; test passed, so store 0 in ERROR
|
||||
0249 : 850b sta ERROR
|
||||
024b : DONE
|
||||
end_of_test
|
||||
024b : 00 > brk
|
||||
> ; db $db ;execute 65C02 stop instruction
|
||||
|
||||
|
||||
; Calculate the actual decimal mode accumulator and flags, the accumulator
|
||||
; and flag results when N1 is added to N2 using binary arithmetic, the
|
||||
; predicted accumulator result, the predicted carry flag, and the predicted
|
||||
; V flag
|
||||
;
|
||||
024c : f8 ADD sed ; decimal mode
|
||||
024d : c001 cpy #1 ; set carry if Y = 1, clear carry if Y = 0
|
||||
024f : a500 lda N1
|
||||
0251 : 6501 adc N2
|
||||
0253 : 8504 sta DA ; actual accumulator result in decimal mode
|
||||
0255 : 08 php
|
||||
0256 : 68 pla
|
||||
0257 : 8505 sta DNVZC ; actual flags result in decimal mode
|
||||
0259 : d8 cld ; binary mode
|
||||
025a : c001 cpy #1 ; set carry if Y = 1, clear carry if Y = 0
|
||||
025c : a500 lda N1
|
||||
025e : 6501 adc N2
|
||||
0260 : 8502 sta HA ; accumulator result of N1+N2 using binary arithmetic
|
||||
|
||||
0262 : 08 php
|
||||
0263 : 68 pla
|
||||
0264 : 8503 sta HNVZC ; flags result of N1+N2 using binary arithmetic
|
||||
0266 : c001 cpy #1
|
||||
0268 : a50c lda N1L
|
||||
026a : 650e adc N2L
|
||||
026c : c90a cmp #$0A
|
||||
026e : a200 ldx #0
|
||||
0270 : 9006 bcc A1
|
||||
0272 : e8 inx
|
||||
0273 : 6905 adc #5 ; add 6 (carry is set)
|
||||
0275 : 290f and #$0F
|
||||
0277 : 38 sec
|
||||
0278 : 050d A1 ora N1H
|
||||
;
|
||||
; if N1L + N2L < $0A, then add N2 & $F0
|
||||
; if N1L + N2L >= $0A, then add (N2 & $F0) + $0F + 1 (carry is set)
|
||||
;
|
||||
027a : 750f adc N2H,x
|
||||
027c : 08 php
|
||||
027d : b004 bcs A2
|
||||
027f : c9a0 cmp #$A0
|
||||
0281 : 9003 bcc A3
|
||||
0283 : 695f A2 adc #$5F ; add $60 (carry is set)
|
||||
0285 : 38 sec
|
||||
0286 : 8506 A3 sta AR ; predicted accumulator result
|
||||
0288 : 08 php
|
||||
0289 : 68 pla
|
||||
028a : 850a sta CF ; predicted carry result
|
||||
028c : 68 pla
|
||||
;
|
||||
; note that all 8 bits of the P register are stored in VF
|
||||
;
|
||||
028d : 8508 sta VF ; predicted V flags
|
||||
028f : 60 rts
|
||||
|
||||
; Calculate the actual decimal mode accumulator and flags, and the
|
||||
; accumulator and flag results when N2 is subtracted from N1 using binary
|
||||
; arithmetic
|
||||
;
|
||||
0290 : f8 SUB sed ; decimal mode
|
||||
0291 : c001 cpy #1 ; set carry if Y = 1, clear carry if Y = 0
|
||||
0293 : a500 lda N1
|
||||
0295 : e501 sbc N2
|
||||
0297 : 8504 sta DA ; actual accumulator result in decimal mode
|
||||
0299 : 08 php
|
||||
029a : 68 pla
|
||||
029b : 8505 sta DNVZC ; actual flags result in decimal mode
|
||||
029d : d8 cld ; binary mode
|
||||
029e : c001 cpy #1 ; set carry if Y = 1, clear carry if Y = 0
|
||||
02a0 : a500 lda N1
|
||||
02a2 : e501 sbc N2
|
||||
02a4 : 8502 sta HA ; accumulator result of N1-N2 using binary arithmetic
|
||||
|
||||
02a6 : 08 php
|
||||
02a7 : 68 pla
|
||||
02a8 : 8503 sta HNVZC ; flags result of N1-N2 using binary arithmetic
|
||||
02aa : 60 rts
|
||||
|
||||
if cputype != 1
|
||||
; Calculate the predicted SBC accumulator result for the 6502 and 65816
|
||||
;
|
||||
SUB1 cpy #1 ; set carry if Y = 1, clear carry if Y = 0
|
||||
lda N1L
|
||||
sbc N2L
|
||||
ldx #0
|
||||
bcs S11
|
||||
inx
|
||||
sbc #5 ; subtract 6 (carry is clear)
|
||||
and #$0F
|
||||
clc
|
||||
S11 ora N1H
|
||||
;
|
||||
; if N1L - N2L >= 0, then subtract N2 & $F0
|
||||
; if N1L - N2L < 0, then subtract (N2 & $F0) + $0F + 1 (carry is clear)
|
||||
;
|
||||
sbc N2H,x
|
||||
bcs S12
|
||||
sbc #$5F ; subtract $60 (carry is clear)
|
||||
S12 sta AR
|
||||
rts
|
||||
endif
|
||||
|
||||
if cputype = 1
|
||||
; Calculate the predicted SBC accumulator result for the 6502 and 65C02
|
||||
;
|
||||
02ab : c001 SUB2 cpy #1 ; set carry if Y = 1, clear carry if Y = 0
|
||||
02ad : a50c lda N1L
|
||||
02af : e50e sbc N2L
|
||||
02b1 : a200 ldx #0
|
||||
02b3 : b004 bcs S21
|
||||
02b5 : e8 inx
|
||||
02b6 : 290f and #$0F
|
||||
02b8 : 18 clc
|
||||
02b9 : 050d S21 ora N1H
|
||||
;
|
||||
; if N1L - N2L >= 0, then subtract N2 & $F0
|
||||
; if N1L - N2L < 0, then subtract (N2 & $F0) + $0F + 1 (carry is clear)
|
||||
;
|
||||
02bb : f50f sbc N2H,x
|
||||
02bd : b002 bcs S22
|
||||
02bf : e95f sbc #$5F ; subtract $60 (carry is clear)
|
||||
02c1 : e000 S22 cpx #0
|
||||
02c3 : f002 beq S23
|
||||
02c5 : e906 sbc #6
|
||||
02c7 : 8506 S23 sta AR ; predicted accumulator result
|
||||
02c9 : 60 rts
|
||||
endif
|
||||
|
||||
; Compare accumulator actual results to predicted results
|
||||
;
|
||||
; Return:
|
||||
; Z flag = 1 (BEQ branch) if same
|
||||
; Z flag = 0 (BNE branch) if different
|
||||
;
|
||||
02ca : COMPARE
|
||||
if chk_a = 1
|
||||
02ca : a504 lda DA
|
||||
02cc : c506 cmp AR
|
||||
02ce : d006 bne C1
|
||||
endif
|
||||
if chk_n = 1
|
||||
lda DNVZC ; [7] see text
|
||||
eor NF
|
||||
and #$80 ; mask off N flag
|
||||
bne C1
|
||||
endif
|
||||
if chk_v = 1
|
||||
lda DNVZC ; [8] see text
|
||||
eor VF
|
||||
and #$40 ; mask off V flag
|
||||
bne C1 ; [9] see text
|
||||
endif
|
||||
if chk_z = 1
|
||||
lda DNVZC
|
||||
eor ZF ; mask off Z flag
|
||||
and #2
|
||||
bne C1 ; [10] see text
|
||||
endif
|
||||
if chk_c = 1
|
||||
02d0 : a505 lda DNVZC
|
||||
02d2 : 450a eor CF
|
||||
02d4 : 2901 and #1 ; mask off C flag
|
||||
endif
|
||||
02d6 : 60 C1 rts
|
||||
|
||||
; These routines store the predicted values for ADC and SBC for the 6502,
|
||||
; 65C02, and 65816 in AR, CF, NF, VF, and ZF
|
||||
|
||||
if cputype = 0
|
||||
|
||||
A6502 lda VF ; 6502
|
||||
;
|
||||
; since all 8 bits of the P register were stored in VF, bit 7 of VF contains
|
||||
; the N flag for NF
|
||||
;
|
||||
sta NF
|
||||
lda HNVZC
|
||||
sta ZF
|
||||
rts
|
||||
|
||||
S6502 jsr SUB1
|
||||
lda HNVZC
|
||||
sta NF
|
||||
sta VF
|
||||
sta ZF
|
||||
sta CF
|
||||
rts
|
||||
|
||||
endif
|
||||
if cputype = 1
|
||||
|
||||
02d7 : a506 A6502 lda AR ; 65C02
|
||||
02d9 : 08 php
|
||||
02da : 68 pla
|
||||
02db : 8507 sta NF
|
||||
02dd : 8509 sta ZF
|
||||
02df : 60 rts
|
||||
|
||||
02e0 : 20ab02 S6502 jsr SUB2
|
||||
02e3 : a506 lda AR
|
||||
02e5 : 08 php
|
||||
02e6 : 68 pla
|
||||
02e7 : 8507 sta NF
|
||||
02e9 : 8509 sta ZF
|
||||
02eb : a503 lda HNVZC
|
||||
02ed : 8508 sta VF
|
||||
02ef : 850a sta CF
|
||||
02f1 : 60 rts
|
||||
|
||||
endif
|
||||
if cputype = 2
|
||||
|
||||
A6502 lda AR ; 65C816
|
||||
php
|
||||
pla
|
||||
sta NF
|
||||
sta ZF
|
||||
rts
|
||||
|
||||
S6502 jsr SUB1
|
||||
lda AR
|
||||
php
|
||||
pla
|
||||
sta NF
|
||||
sta ZF
|
||||
lda HNVZC
|
||||
sta VF
|
||||
sta CF
|
||||
rts
|
||||
|
||||
endif
|
||||
|
||||
02e0 = end TEST
|
||||
|
||||
No errors in pass 2.
|
||||
Wrote binary from address $0200 through $02f1.
|
||||
Total size 242 bytes.
|
||||
Program start address is at $0200 (512).
|
||||
|
|
@ -10,14 +10,18 @@ The 6502_interrupt_test.a65 is a simple test to check the interrupt system
|
|||
of both processors. A feedback register is required to inject IRQ and NMI
|
||||
requests.
|
||||
|
||||
The 6502_decimal_test.a65 is Bruce Clark's code to accurately test decimal mode
|
||||
of the various 6502 cores (6502, 65c02 & 65816 in 8-bit mode) with added
|
||||
configuration options (invalid bcd or not, which flags to ignore).
|
||||
|
||||
Detailed information about how to configure, assemble and run the tests is
|
||||
included in each source file.
|
||||
|
||||
The tests have primarily been written to test my own ATMega16 6502 emulator
|
||||
project. You can find it here: http://2m5.de/6502_Emu/index.htm
|
||||
The assembler used is no longer available on the author's website. as65_142.zip
|
||||
is now included in this repository.
|
||||
|
||||
A discussion about the tests can be found here:
|
||||
http://forum.6502.org/viewtopic.php?f=2&t=2241
|
||||
And no, I will not switch to another assembler. However, GitHub user amb5l has
|
||||
a CA65 compatible version in his repository.
|
||||
|
||||
Good luck debugging your emulator, simulator, fpga core, discrete
|
||||
logic implementation or whatever you have!
|
||||
|
|
426
src/test/kotlin/6502testsuite/source/adca.asm
Normal file
426
src/test/kotlin/6502testsuite/source/adca.asm
Normal file
|
@ -0,0 +1,426 @@
|
|||
*= $0801
|
||||
|
||||
.byte $4c,$16,$08,$00,$97,$32
|
||||
.byte $2c,$30,$3a,$9e,$32,$30
|
||||
.byte $37,$30,$00,$00,$00,$a9
|
||||
.byte $01,$85,$02
|
||||
|
||||
jsr print
|
||||
.byte 13
|
||||
.text "(up)adca"
|
||||
.byte 0
|
||||
|
||||
lda #%00011011
|
||||
sta db
|
||||
lda #%11000110
|
||||
sta ab
|
||||
lda #%10110001
|
||||
sta xb
|
||||
lda #%01101100
|
||||
sta yb
|
||||
lda #0
|
||||
sta pb
|
||||
tsx
|
||||
stx sb
|
||||
|
||||
lda #0
|
||||
sta db
|
||||
sta ab
|
||||
|
||||
next lda pb
|
||||
and #%00001000
|
||||
bne decmode
|
||||
lda db
|
||||
sta da
|
||||
sta dr
|
||||
sta cmd0+1
|
||||
and #$7f
|
||||
sta cmd1+1
|
||||
clc
|
||||
lda pb
|
||||
and #1
|
||||
beq noc
|
||||
sec
|
||||
noc php
|
||||
lda ab
|
||||
cmd0 adc #0
|
||||
sta ar
|
||||
lda pb
|
||||
ora #%00110000
|
||||
and #%00111100
|
||||
bcc noc1
|
||||
ora #1
|
||||
noc1 tax
|
||||
lda ab
|
||||
and #$7f
|
||||
plp
|
||||
cmd1 adc #0
|
||||
bmi neg
|
||||
txa
|
||||
and #1
|
||||
beq cont
|
||||
set txa
|
||||
ora #%01000000
|
||||
tax
|
||||
jmp cont
|
||||
neg txa
|
||||
and #1
|
||||
beq set
|
||||
cont lda ar
|
||||
cmp #0
|
||||
bne nozero
|
||||
txa
|
||||
ora #%00000010
|
||||
tax
|
||||
nozero lda ar
|
||||
bpl noneg
|
||||
txa
|
||||
ora #%10000000
|
||||
tax
|
||||
noneg stx pr
|
||||
jmp deccont
|
||||
|
||||
decmode
|
||||
.block
|
||||
lda db
|
||||
sta da
|
||||
sta dr
|
||||
and #$0f
|
||||
sta l0+1
|
||||
lda pb
|
||||
ora #%00110000
|
||||
and #%00111100
|
||||
tax
|
||||
lda pb
|
||||
lsr a
|
||||
lda ab
|
||||
and #$0f
|
||||
l0 adc #0
|
||||
ldy #$00
|
||||
cmp #$0a
|
||||
bcc l1
|
||||
sec
|
||||
sbc #$0a
|
||||
and #$0f
|
||||
ldy #$08
|
||||
l1 sta ar
|
||||
sty l2+1
|
||||
sty l3+1
|
||||
lda db
|
||||
and #$f0
|
||||
ora l3+1
|
||||
sta l3+1
|
||||
lda ab
|
||||
and #$f0
|
||||
l2 ora #0
|
||||
clc
|
||||
l3 adc #0
|
||||
php
|
||||
bcs l4
|
||||
cmp #$a0
|
||||
bcc l5
|
||||
l4 sec
|
||||
sbc #$a0
|
||||
inx
|
||||
l5 ora ar
|
||||
sta ar
|
||||
plp
|
||||
bvc nov
|
||||
php
|
||||
txa
|
||||
ora #%01000000
|
||||
tax
|
||||
plp
|
||||
nov bpl non
|
||||
txa
|
||||
ora #%10000000
|
||||
tax
|
||||
non lda pb
|
||||
lsr a
|
||||
lda ab
|
||||
adc db
|
||||
bne noz
|
||||
txa
|
||||
ora #%00000010
|
||||
tax
|
||||
noz stx pr
|
||||
.bend
|
||||
|
||||
deccont lda xb
|
||||
sta xr
|
||||
|
||||
lda yb
|
||||
sta yr
|
||||
|
||||
lda sb
|
||||
sta sr
|
||||
|
||||
ldx sb
|
||||
txs
|
||||
lda pb
|
||||
pha
|
||||
lda ab
|
||||
ldx xb
|
||||
ldy yb
|
||||
plp
|
||||
|
||||
cmd adc da
|
||||
|
||||
php
|
||||
cld
|
||||
sta aa
|
||||
stx xa
|
||||
sty ya
|
||||
pla
|
||||
sta pa
|
||||
tsx
|
||||
stx sa
|
||||
jsr check
|
||||
|
||||
clc
|
||||
lda db
|
||||
adc #17
|
||||
sta db
|
||||
bcc jmpnext
|
||||
lda #0
|
||||
sta db
|
||||
clc
|
||||
lda ab
|
||||
adc #17
|
||||
sta ab
|
||||
bcc jmpnext
|
||||
lda #0
|
||||
sta ab
|
||||
inc pb
|
||||
beq nonext
|
||||
jmpnext jmp next
|
||||
nonext
|
||||
|
||||
jsr print
|
||||
.text " - ok"
|
||||
.byte 13,0
|
||||
lda 2
|
||||
beq load
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
jmp $8000
|
||||
|
||||
load jsr print
|
||||
name .text "adcax"
|
||||
namelen = *-name
|
||||
.byte 0
|
||||
lda #0
|
||||
sta $0a
|
||||
sta $b9
|
||||
lda #namelen
|
||||
sta $b7
|
||||
lda #<name
|
||||
sta $bb
|
||||
lda #>name
|
||||
sta $bc
|
||||
pla
|
||||
pla
|
||||
jmp $e16f
|
||||
|
||||
db .byte 0
|
||||
ab .byte 0
|
||||
xb .byte 0
|
||||
yb .byte 0
|
||||
pb .byte 0
|
||||
sb .byte 0
|
||||
da .byte 0
|
||||
aa .byte 0
|
||||
xa .byte 0
|
||||
ya .byte 0
|
||||
pa .byte 0
|
||||
sa .byte 0
|
||||
dr .byte 0
|
||||
ar .byte 0
|
||||
xr .byte 0
|
||||
yr .byte 0
|
||||
pr .byte 0
|
||||
sr .byte 0
|
||||
|
||||
check
|
||||
.block
|
||||
lda da
|
||||
cmp dr
|
||||
bne error
|
||||
lda aa
|
||||
cmp ar
|
||||
bne error
|
||||
lda xa
|
||||
cmp xr
|
||||
bne error
|
||||
lda ya
|
||||
cmp yr
|
||||
bne error
|
||||
lda pa
|
||||
cmp pr
|
||||
bne error
|
||||
lda sa
|
||||
cmp sr
|
||||
bne error
|
||||
rts
|
||||
|
||||
error jsr print
|
||||
.byte 13
|
||||
.null "before "
|
||||
ldx #<db
|
||||
ldy #>db
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "after "
|
||||
ldx #<da
|
||||
ldy #>da
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "right "
|
||||
ldx #<dr
|
||||
ldy #>dr
|
||||
jsr showregs
|
||||
lda #13
|
||||
jsr $ffd2
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
cmp #3
|
||||
beq stop
|
||||
rts
|
||||
stop lda 2
|
||||
beq basic
|
||||
jmp $8000
|
||||
basic jmp ($a002)
|
||||
|
||||
showregs stx 172
|
||||
sty 173
|
||||
ldy #0
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
ldx #"n"
|
||||
asl a
|
||||
bcc ok7
|
||||
ldx #"N"
|
||||
ok7 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"v"
|
||||
asl a
|
||||
bcc ok6
|
||||
ldx #"V"
|
||||
ok6 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"0"
|
||||
asl a
|
||||
bcc ok5
|
||||
ldx #"1"
|
||||
ok5 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"b"
|
||||
asl a
|
||||
bcc ok4
|
||||
ldx #"B"
|
||||
ok4 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"d"
|
||||
asl a
|
||||
bcc ok3
|
||||
ldx #"D"
|
||||
ok3 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"i"
|
||||
asl a
|
||||
bcc ok2
|
||||
ldx #"I"
|
||||
ok2 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"z"
|
||||
asl a
|
||||
bcc ok1
|
||||
ldx #"Z"
|
||||
ok1 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"c"
|
||||
asl a
|
||||
bcc ok0
|
||||
ldx #"C"
|
||||
ok0 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
.bend
|
||||
hexb pha
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
jsr hexn
|
||||
pla
|
||||
and #$0f
|
||||
hexn ora #$30
|
||||
cmp #$3a
|
||||
bcc hexn0
|
||||
adc #6
|
||||
hexn0 jmp $ffd2
|
||||
|
||||
print pla
|
||||
.block
|
||||
sta print0+1
|
||||
pla
|
||||
sta print0+2
|
||||
ldx #1
|
||||
print0 lda !*,x
|
||||
beq print1
|
||||
jsr $ffd2
|
||||
inx
|
||||
bne print0
|
||||
print1 sec
|
||||
txa
|
||||
adc print0+1
|
||||
sta print2+1
|
||||
lda #0
|
||||
adc print0+2
|
||||
sta print2+2
|
||||
print2 jmp !*
|
||||
.bend
|
||||
|
||||
|
435
src/test/kotlin/6502testsuite/source/adcax.asm
Normal file
435
src/test/kotlin/6502testsuite/source/adcax.asm
Normal file
|
@ -0,0 +1,435 @@
|
|||
*= $0801
|
||||
|
||||
.byte $4c,$16,$08,$00,$97,$32
|
||||
.byte $2c,$30,$3a,$9e,$32,$30
|
||||
.byte $37,$30,$00,$00,$00,$a9
|
||||
.byte $01,$85,$02
|
||||
|
||||
jsr print
|
||||
.byte 13
|
||||
.text "(up)adcax"
|
||||
.byte 0
|
||||
|
||||
lda #%00011011
|
||||
sta db
|
||||
lda #%11000110
|
||||
sta ab
|
||||
lda #%10110001
|
||||
sta xb
|
||||
lda #%01101100
|
||||
sta yb
|
||||
lda #0
|
||||
sta pb
|
||||
tsx
|
||||
stx sb
|
||||
|
||||
lda #0
|
||||
sta db
|
||||
sta ab
|
||||
sta xb
|
||||
|
||||
next lda pb
|
||||
and #%00001000
|
||||
bne decmode
|
||||
lda db
|
||||
sta da
|
||||
sta dr
|
||||
sta cmd0+1
|
||||
and #$7f
|
||||
sta cmd1+1
|
||||
clc
|
||||
lda pb
|
||||
and #1
|
||||
beq noc
|
||||
sec
|
||||
noc php
|
||||
lda ab
|
||||
cmd0 adc #0
|
||||
sta ar
|
||||
lda pb
|
||||
ora #%00110000
|
||||
and #%00111100
|
||||
bcc noc1
|
||||
ora #1
|
||||
noc1 tax
|
||||
lda ab
|
||||
and #$7f
|
||||
plp
|
||||
cmd1 adc #0
|
||||
bmi neg
|
||||
txa
|
||||
and #1
|
||||
beq cont
|
||||
set txa
|
||||
ora #%01000000
|
||||
tax
|
||||
jmp cont
|
||||
neg txa
|
||||
and #1
|
||||
beq set
|
||||
cont lda ar
|
||||
cmp #0
|
||||
bne nozero
|
||||
txa
|
||||
ora #%00000010
|
||||
tax
|
||||
nozero lda ar
|
||||
bpl noneg
|
||||
txa
|
||||
ora #%10000000
|
||||
tax
|
||||
noneg stx pr
|
||||
jmp deccont
|
||||
|
||||
decmode
|
||||
.block
|
||||
lda db
|
||||
sta da
|
||||
sta dr
|
||||
and #$0f
|
||||
sta l0+1
|
||||
lda pb
|
||||
ora #%00110000
|
||||
and #%00111100
|
||||
tax
|
||||
lda pb
|
||||
lsr a
|
||||
lda ab
|
||||
and #$0f
|
||||
l0 adc #0
|
||||
ldy #$00
|
||||
cmp #$0a
|
||||
bcc l1
|
||||
sec
|
||||
sbc #$0a
|
||||
and #$0f
|
||||
ldy #$08
|
||||
l1 sta ar
|
||||
sty l2+1
|
||||
sty l3+1
|
||||
lda db
|
||||
and #$f0
|
||||
ora l3+1
|
||||
sta l3+1
|
||||
lda ab
|
||||
and #$f0
|
||||
l2 ora #0
|
||||
clc
|
||||
l3 adc #0
|
||||
php
|
||||
bcs l4
|
||||
cmp #$a0
|
||||
bcc l5
|
||||
l4 sec
|
||||
sbc #$a0
|
||||
inx
|
||||
l5 ora ar
|
||||
sta ar
|
||||
plp
|
||||
bvc nov
|
||||
php
|
||||
txa
|
||||
ora #%01000000
|
||||
tax
|
||||
plp
|
||||
nov bpl non
|
||||
txa
|
||||
ora #%10000000
|
||||
tax
|
||||
non lda pb
|
||||
lsr a
|
||||
lda ab
|
||||
adc db
|
||||
bne noz
|
||||
txa
|
||||
ora #%00000010
|
||||
tax
|
||||
noz stx pr
|
||||
.bend
|
||||
|
||||
deccont lda xb
|
||||
sta xr
|
||||
|
||||
lda yb
|
||||
sta yr
|
||||
|
||||
lda sb
|
||||
sta sr
|
||||
|
||||
ldx sb
|
||||
txs
|
||||
lda pb
|
||||
pha
|
||||
lda ab
|
||||
ldx xb
|
||||
ldy yb
|
||||
plp
|
||||
|
||||
cmd adc da,x
|
||||
|
||||
php
|
||||
cld
|
||||
sta aa
|
||||
stx xa
|
||||
sty ya
|
||||
pla
|
||||
sta pa
|
||||
tsx
|
||||
stx sa
|
||||
jsr check
|
||||
|
||||
inc cmd+1
|
||||
bne noinc
|
||||
inc cmd+2
|
||||
noinc lda xb
|
||||
bne nodec
|
||||
dec cmd+2
|
||||
nodec dec xb
|
||||
|
||||
clc
|
||||
lda db
|
||||
adc #17
|
||||
sta db
|
||||
bcc jmpnext
|
||||
lda #0
|
||||
sta db
|
||||
clc
|
||||
lda ab
|
||||
adc #17
|
||||
sta ab
|
||||
bcc jmpnext
|
||||
lda #0
|
||||
sta ab
|
||||
inc pb
|
||||
beq nonext
|
||||
jmpnext jmp next
|
||||
nonext
|
||||
|
||||
jsr print
|
||||
.text " - ok"
|
||||
.byte 13,0
|
||||
lda 2
|
||||
beq load
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
jmp $8000
|
||||
|
||||
load jsr print
|
||||
name .text "adcay"
|
||||
namelen = *-name
|
||||
.byte 0
|
||||
lda #0
|
||||
sta $0a
|
||||
sta $b9
|
||||
lda #namelen
|
||||
sta $b7
|
||||
lda #<name
|
||||
sta $bb
|
||||
lda #>name
|
||||
sta $bc
|
||||
pla
|
||||
pla
|
||||
jmp $e16f
|
||||
|
||||
db .byte 0
|
||||
ab .byte 0
|
||||
xb .byte 0
|
||||
yb .byte 0
|
||||
pb .byte 0
|
||||
sb .byte 0
|
||||
da .byte 0
|
||||
aa .byte 0
|
||||
xa .byte 0
|
||||
ya .byte 0
|
||||
pa .byte 0
|
||||
sa .byte 0
|
||||
dr .byte 0
|
||||
ar .byte 0
|
||||
xr .byte 0
|
||||
yr .byte 0
|
||||
pr .byte 0
|
||||
sr .byte 0
|
||||
|
||||
check
|
||||
.block
|
||||
lda da
|
||||
cmp dr
|
||||
bne error
|
||||
lda aa
|
||||
cmp ar
|
||||
bne error
|
||||
lda xa
|
||||
cmp xr
|
||||
bne error
|
||||
lda ya
|
||||
cmp yr
|
||||
bne error
|
||||
lda pa
|
||||
cmp pr
|
||||
bne error
|
||||
lda sa
|
||||
cmp sr
|
||||
bne error
|
||||
rts
|
||||
|
||||
error jsr print
|
||||
.byte 13
|
||||
.null "before "
|
||||
ldx #<db
|
||||
ldy #>db
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "after "
|
||||
ldx #<da
|
||||
ldy #>da
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "right "
|
||||
ldx #<dr
|
||||
ldy #>dr
|
||||
jsr showregs
|
||||
lda #13
|
||||
jsr $ffd2
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
cmp #3
|
||||
beq stop
|
||||
rts
|
||||
stop lda 2
|
||||
beq basic
|
||||
jmp $8000
|
||||
basic jmp ($a002)
|
||||
|
||||
showregs stx 172
|
||||
sty 173
|
||||
ldy #0
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
ldx #"n"
|
||||
asl a
|
||||
bcc ok7
|
||||
ldx #"N"
|
||||
ok7 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"v"
|
||||
asl a
|
||||
bcc ok6
|
||||
ldx #"V"
|
||||
ok6 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"0"
|
||||
asl a
|
||||
bcc ok5
|
||||
ldx #"1"
|
||||
ok5 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"b"
|
||||
asl a
|
||||
bcc ok4
|
||||
ldx #"B"
|
||||
ok4 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"d"
|
||||
asl a
|
||||
bcc ok3
|
||||
ldx #"D"
|
||||
ok3 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"i"
|
||||
asl a
|
||||
bcc ok2
|
||||
ldx #"I"
|
||||
ok2 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"z"
|
||||
asl a
|
||||
bcc ok1
|
||||
ldx #"Z"
|
||||
ok1 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"c"
|
||||
asl a
|
||||
bcc ok0
|
||||
ldx #"C"
|
||||
ok0 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
.bend
|
||||
hexb pha
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
jsr hexn
|
||||
pla
|
||||
and #$0f
|
||||
hexn ora #$30
|
||||
cmp #$3a
|
||||
bcc hexn0
|
||||
adc #6
|
||||
hexn0 jmp $ffd2
|
||||
|
||||
print pla
|
||||
.block
|
||||
sta print0+1
|
||||
pla
|
||||
sta print0+2
|
||||
ldx #1
|
||||
print0 lda !*,x
|
||||
beq print1
|
||||
jsr $ffd2
|
||||
inx
|
||||
bne print0
|
||||
print1 sec
|
||||
txa
|
||||
adc print0+1
|
||||
sta print2+1
|
||||
lda #0
|
||||
adc print0+2
|
||||
sta print2+2
|
||||
print2 jmp !*
|
||||
.bend
|
||||
|
||||
|
435
src/test/kotlin/6502testsuite/source/adcay.asm
Normal file
435
src/test/kotlin/6502testsuite/source/adcay.asm
Normal file
|
@ -0,0 +1,435 @@
|
|||
*= $0801
|
||||
|
||||
.byte $4c,$16,$08,$00,$97,$32
|
||||
.byte $2c,$30,$3a,$9e,$32,$30
|
||||
.byte $37,$30,$00,$00,$00,$a9
|
||||
.byte $01,$85,$02
|
||||
|
||||
jsr print
|
||||
.byte 13
|
||||
.text "(up)adcay"
|
||||
.byte 0
|
||||
|
||||
lda #%00011011
|
||||
sta db
|
||||
lda #%11000110
|
||||
sta ab
|
||||
lda #%10110001
|
||||
sta xb
|
||||
lda #%01101100
|
||||
sta yb
|
||||
lda #0
|
||||
sta pb
|
||||
tsx
|
||||
stx sb
|
||||
|
||||
lda #0
|
||||
sta db
|
||||
sta ab
|
||||
sta yb
|
||||
|
||||
next lda pb
|
||||
and #%00001000
|
||||
bne decmode
|
||||
lda db
|
||||
sta da
|
||||
sta dr
|
||||
sta cmd0+1
|
||||
and #$7f
|
||||
sta cmd1+1
|
||||
clc
|
||||
lda pb
|
||||
and #1
|
||||
beq noc
|
||||
sec
|
||||
noc php
|
||||
lda ab
|
||||
cmd0 adc #0
|
||||
sta ar
|
||||
lda pb
|
||||
ora #%00110000
|
||||
and #%00111100
|
||||
bcc noc1
|
||||
ora #1
|
||||
noc1 tax
|
||||
lda ab
|
||||
and #$7f
|
||||
plp
|
||||
cmd1 adc #0
|
||||
bmi neg
|
||||
txa
|
||||
and #1
|
||||
beq cont
|
||||
set txa
|
||||
ora #%01000000
|
||||
tax
|
||||
jmp cont
|
||||
neg txa
|
||||
and #1
|
||||
beq set
|
||||
cont lda ar
|
||||
cmp #0
|
||||
bne nozero
|
||||
txa
|
||||
ora #%00000010
|
||||
tax
|
||||
nozero lda ar
|
||||
bpl noneg
|
||||
txa
|
||||
ora #%10000000
|
||||
tax
|
||||
noneg stx pr
|
||||
jmp deccont
|
||||
|
||||
decmode
|
||||
.block
|
||||
lda db
|
||||
sta da
|
||||
sta dr
|
||||
and #$0f
|
||||
sta l0+1
|
||||
lda pb
|
||||
ora #%00110000
|
||||
and #%00111100
|
||||
tax
|
||||
lda pb
|
||||
lsr a
|
||||
lda ab
|
||||
and #$0f
|
||||
l0 adc #0
|
||||
ldy #$00
|
||||
cmp #$0a
|
||||
bcc l1
|
||||
sec
|
||||
sbc #$0a
|
||||
and #$0f
|
||||
ldy #$08
|
||||
l1 sta ar
|
||||
sty l2+1
|
||||
sty l3+1
|
||||
lda db
|
||||
and #$f0
|
||||
ora l3+1
|
||||
sta l3+1
|
||||
lda ab
|
||||
and #$f0
|
||||
l2 ora #0
|
||||
clc
|
||||
l3 adc #0
|
||||
php
|
||||
bcs l4
|
||||
cmp #$a0
|
||||
bcc l5
|
||||
l4 sec
|
||||
sbc #$a0
|
||||
inx
|
||||
l5 ora ar
|
||||
sta ar
|
||||
plp
|
||||
bvc nov
|
||||
php
|
||||
txa
|
||||
ora #%01000000
|
||||
tax
|
||||
plp
|
||||
nov bpl non
|
||||
txa
|
||||
ora #%10000000
|
||||
tax
|
||||
non lda pb
|
||||
lsr a
|
||||
lda ab
|
||||
adc db
|
||||
bne noz
|
||||
txa
|
||||
ora #%00000010
|
||||
tax
|
||||
noz stx pr
|
||||
.bend
|
||||
|
||||
deccont lda xb
|
||||
sta xr
|
||||
|
||||
lda yb
|
||||
sta yr
|
||||
|
||||
lda sb
|
||||
sta sr
|
||||
|
||||
ldx sb
|
||||
txs
|
||||
lda pb
|
||||
pha
|
||||
lda ab
|
||||
ldx xb
|
||||
ldy yb
|
||||
plp
|
||||
|
||||
cmd adc da,y
|
||||
|
||||
php
|
||||
cld
|
||||
sta aa
|
||||
stx xa
|
||||
sty ya
|
||||
pla
|
||||
sta pa
|
||||
tsx
|
||||
stx sa
|
||||
jsr check
|
||||
|
||||
inc cmd+1
|
||||
bne noinc
|
||||
inc cmd+2
|
||||
noinc lda yb
|
||||
bne nodec
|
||||
dec cmd+2
|
||||
nodec dec yb
|
||||
|
||||
clc
|
||||
lda db
|
||||
adc #17
|
||||
sta db
|
||||
bcc jmpnext
|
||||
lda #0
|
||||
sta db
|
||||
clc
|
||||
lda ab
|
||||
adc #17
|
||||
sta ab
|
||||
bcc jmpnext
|
||||
lda #0
|
||||
sta ab
|
||||
inc pb
|
||||
beq nonext
|
||||
jmpnext jmp next
|
||||
nonext
|
||||
|
||||
jsr print
|
||||
.text " - ok"
|
||||
.byte 13,0
|
||||
lda 2
|
||||
beq load
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
jmp $8000
|
||||
|
||||
load jsr print
|
||||
name .text "adcix"
|
||||
namelen = *-name
|
||||
.byte 0
|
||||
lda #0
|
||||
sta $0a
|
||||
sta $b9
|
||||
lda #namelen
|
||||
sta $b7
|
||||
lda #<name
|
||||
sta $bb
|
||||
lda #>name
|
||||
sta $bc
|
||||
pla
|
||||
pla
|
||||
jmp $e16f
|
||||
|
||||
db .byte 0
|
||||
ab .byte 0
|
||||
xb .byte 0
|
||||
yb .byte 0
|
||||
pb .byte 0
|
||||
sb .byte 0
|
||||
da .byte 0
|
||||
aa .byte 0
|
||||
xa .byte 0
|
||||
ya .byte 0
|
||||
pa .byte 0
|
||||
sa .byte 0
|
||||
dr .byte 0
|
||||
ar .byte 0
|
||||
xr .byte 0
|
||||
yr .byte 0
|
||||
pr .byte 0
|
||||
sr .byte 0
|
||||
|
||||
check
|
||||
.block
|
||||
lda da
|
||||
cmp dr
|
||||
bne error
|
||||
lda aa
|
||||
cmp ar
|
||||
bne error
|
||||
lda xa
|
||||
cmp xr
|
||||
bne error
|
||||
lda ya
|
||||
cmp yr
|
||||
bne error
|
||||
lda pa
|
||||
cmp pr
|
||||
bne error
|
||||
lda sa
|
||||
cmp sr
|
||||
bne error
|
||||
rts
|
||||
|
||||
error jsr print
|
||||
.byte 13
|
||||
.null "before "
|
||||
ldx #<db
|
||||
ldy #>db
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "after "
|
||||
ldx #<da
|
||||
ldy #>da
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "right "
|
||||
ldx #<dr
|
||||
ldy #>dr
|
||||
jsr showregs
|
||||
lda #13
|
||||
jsr $ffd2
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
cmp #3
|
||||
beq stop
|
||||
rts
|
||||
stop lda 2
|
||||
beq basic
|
||||
jmp $8000
|
||||
basic jmp ($a002)
|
||||
|
||||
showregs stx 172
|
||||
sty 173
|
||||
ldy #0
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
ldx #"n"
|
||||
asl a
|
||||
bcc ok7
|
||||
ldx #"N"
|
||||
ok7 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"v"
|
||||
asl a
|
||||
bcc ok6
|
||||
ldx #"V"
|
||||
ok6 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"0"
|
||||
asl a
|
||||
bcc ok5
|
||||
ldx #"1"
|
||||
ok5 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"b"
|
||||
asl a
|
||||
bcc ok4
|
||||
ldx #"B"
|
||||
ok4 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"d"
|
||||
asl a
|
||||
bcc ok3
|
||||
ldx #"D"
|
||||
ok3 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"i"
|
||||
asl a
|
||||
bcc ok2
|
||||
ldx #"I"
|
||||
ok2 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"z"
|
||||
asl a
|
||||
bcc ok1
|
||||
ldx #"Z"
|
||||
ok1 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"c"
|
||||
asl a
|
||||
bcc ok0
|
||||
ldx #"C"
|
||||
ok0 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
.bend
|
||||
hexb pha
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
jsr hexn
|
||||
pla
|
||||
and #$0f
|
||||
hexn ora #$30
|
||||
cmp #$3a
|
||||
bcc hexn0
|
||||
adc #6
|
||||
hexn0 jmp $ffd2
|
||||
|
||||
print pla
|
||||
.block
|
||||
sta print0+1
|
||||
pla
|
||||
sta print0+2
|
||||
ldx #1
|
||||
print0 lda !*,x
|
||||
beq print1
|
||||
jsr $ffd2
|
||||
inx
|
||||
bne print0
|
||||
print1 sec
|
||||
txa
|
||||
adc print0+1
|
||||
sta print2+1
|
||||
lda #0
|
||||
adc print0+2
|
||||
sta print2+2
|
||||
print2 jmp !*
|
||||
.bend
|
||||
|
||||
|
428
src/test/kotlin/6502testsuite/source/adcb.asm
Normal file
428
src/test/kotlin/6502testsuite/source/adcb.asm
Normal file
|
@ -0,0 +1,428 @@
|
|||
*= $0801
|
||||
|
||||
.byte $4c,$16,$08,$00,$97,$32
|
||||
.byte $2c,$30,$3a,$9e,$32,$30
|
||||
.byte $37,$30,$00,$00,$00,$a9
|
||||
.byte $01,$85,$02
|
||||
|
||||
jsr print
|
||||
.byte 13
|
||||
.text "(up)adcb"
|
||||
.byte 0
|
||||
|
||||
lda #%00011011
|
||||
sta db
|
||||
lda #%11000110
|
||||
sta ab
|
||||
lda #%10110001
|
||||
sta xb
|
||||
lda #%01101100
|
||||
sta yb
|
||||
lda #0
|
||||
sta pb
|
||||
tsx
|
||||
stx sb
|
||||
|
||||
lda #0
|
||||
sta db
|
||||
sta ab
|
||||
|
||||
next lda pb
|
||||
and #%00001000
|
||||
bne decmode
|
||||
lda db
|
||||
sta da
|
||||
sta dr
|
||||
sta cmd+1
|
||||
sta cmd0+1
|
||||
and #$7f
|
||||
sta cmd1+1
|
||||
clc
|
||||
lda pb
|
||||
and #1
|
||||
beq noc
|
||||
sec
|
||||
noc php
|
||||
lda ab
|
||||
cmd0 adc #0
|
||||
sta ar
|
||||
lda pb
|
||||
ora #%00110000
|
||||
and #%00111100
|
||||
bcc noc1
|
||||
ora #1
|
||||
noc1 tax
|
||||
lda ab
|
||||
and #$7f
|
||||
plp
|
||||
cmd1 adc #0
|
||||
bmi neg
|
||||
txa
|
||||
and #1
|
||||
beq cont
|
||||
set txa
|
||||
ora #%01000000
|
||||
tax
|
||||
jmp cont
|
||||
neg txa
|
||||
and #1
|
||||
beq set
|
||||
cont lda ar
|
||||
cmp #0
|
||||
bne nozero
|
||||
txa
|
||||
ora #%00000010
|
||||
tax
|
||||
nozero lda ar
|
||||
bpl noneg
|
||||
txa
|
||||
ora #%10000000
|
||||
tax
|
||||
noneg stx pr
|
||||
jmp deccont
|
||||
|
||||
decmode
|
||||
.block
|
||||
lda db
|
||||
sta da
|
||||
sta dr
|
||||
sta cmd+1
|
||||
and #$0f
|
||||
sta l0+1
|
||||
lda pb
|
||||
ora #%00110000
|
||||
and #%00111100
|
||||
tax
|
||||
lda pb
|
||||
lsr a
|
||||
lda ab
|
||||
and #$0f
|
||||
l0 adc #0
|
||||
ldy #$00
|
||||
cmp #$0a
|
||||
bcc l1
|
||||
sec
|
||||
sbc #$0a
|
||||
and #$0f
|
||||
ldy #$08
|
||||
l1 sta ar
|
||||
sty l2+1
|
||||
sty l3+1
|
||||
lda db
|
||||
and #$f0
|
||||
ora l3+1
|
||||
sta l3+1
|
||||
lda ab
|
||||
and #$f0
|
||||
l2 ora #0
|
||||
clc
|
||||
l3 adc #0
|
||||
php
|
||||
bcs l4
|
||||
cmp #$a0
|
||||
bcc l5
|
||||
l4 sec
|
||||
sbc #$a0
|
||||
inx
|
||||
l5 ora ar
|
||||
sta ar
|
||||
plp
|
||||
bvc nov
|
||||
php
|
||||
txa
|
||||
ora #%01000000
|
||||
tax
|
||||
plp
|
||||
nov bpl non
|
||||
txa
|
||||
ora #%10000000
|
||||
tax
|
||||
non lda pb
|
||||
lsr a
|
||||
lda ab
|
||||
adc db
|
||||
bne noz
|
||||
txa
|
||||
ora #%00000010
|
||||
tax
|
||||
noz stx pr
|
||||
.bend
|
||||
|
||||
deccont lda xb
|
||||
sta xr
|
||||
|
||||
lda yb
|
||||
sta yr
|
||||
|
||||
lda sb
|
||||
sta sr
|
||||
|
||||
ldx sb
|
||||
txs
|
||||
lda pb
|
||||
pha
|
||||
lda ab
|
||||
ldx xb
|
||||
ldy yb
|
||||
plp
|
||||
|
||||
cmd adc #0
|
||||
|
||||
php
|
||||
cld
|
||||
sta aa
|
||||
stx xa
|
||||
sty ya
|
||||
pla
|
||||
sta pa
|
||||
tsx
|
||||
stx sa
|
||||
jsr check
|
||||
|
||||
clc
|
||||
lda db
|
||||
adc #17
|
||||
sta db
|
||||
bcc jmpnext
|
||||
lda #0
|
||||
sta db
|
||||
clc
|
||||
lda ab
|
||||
adc #17
|
||||
sta ab
|
||||
bcc jmpnext
|
||||
lda #0
|
||||
sta ab
|
||||
inc pb
|
||||
beq nonext
|
||||
jmpnext jmp next
|
||||
nonext
|
||||
|
||||
jsr print
|
||||
.text " - ok"
|
||||
.byte 13,0
|
||||
lda 2
|
||||
beq load
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
jmp $8000
|
||||
|
||||
load jsr print
|
||||
name .text "adcz"
|
||||
namelen = *-name
|
||||
.byte 0
|
||||
lda #0
|
||||
sta $0a
|
||||
sta $b9
|
||||
lda #namelen
|
||||
sta $b7
|
||||
lda #<name
|
||||
sta $bb
|
||||
lda #>name
|
||||
sta $bc
|
||||
pla
|
||||
pla
|
||||
jmp $e16f
|
||||
|
||||
db .byte 0
|
||||
ab .byte 0
|
||||
xb .byte 0
|
||||
yb .byte 0
|
||||
pb .byte 0
|
||||
sb .byte 0
|
||||
da .byte 0
|
||||
aa .byte 0
|
||||
xa .byte 0
|
||||
ya .byte 0
|
||||
pa .byte 0
|
||||
sa .byte 0
|
||||
dr .byte 0
|
||||
ar .byte 0
|
||||
xr .byte 0
|
||||
yr .byte 0
|
||||
pr .byte 0
|
||||
sr .byte 0
|
||||
|
||||
check
|
||||
.block
|
||||
lda da
|
||||
cmp dr
|
||||
bne error
|
||||
lda aa
|
||||
cmp ar
|
||||
bne error
|
||||
lda xa
|
||||
cmp xr
|
||||
bne error
|
||||
lda ya
|
||||
cmp yr
|
||||
bne error
|
||||
lda pa
|
||||
cmp pr
|
||||
bne error
|
||||
lda sa
|
||||
cmp sr
|
||||
bne error
|
||||
rts
|
||||
|
||||
error jsr print
|
||||
.byte 13
|
||||
.null "before "
|
||||
ldx #<db
|
||||
ldy #>db
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "after "
|
||||
ldx #<da
|
||||
ldy #>da
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "right "
|
||||
ldx #<dr
|
||||
ldy #>dr
|
||||
jsr showregs
|
||||
lda #13
|
||||
jsr $ffd2
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
cmp #3
|
||||
beq stop
|
||||
rts
|
||||
stop lda 2
|
||||
beq basic
|
||||
jmp $8000
|
||||
basic jmp ($a002)
|
||||
|
||||
showregs stx 172
|
||||
sty 173
|
||||
ldy #0
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
ldx #"n"
|
||||
asl a
|
||||
bcc ok7
|
||||
ldx #"N"
|
||||
ok7 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"v"
|
||||
asl a
|
||||
bcc ok6
|
||||
ldx #"V"
|
||||
ok6 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"0"
|
||||
asl a
|
||||
bcc ok5
|
||||
ldx #"1"
|
||||
ok5 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"b"
|
||||
asl a
|
||||
bcc ok4
|
||||
ldx #"B"
|
||||
ok4 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"d"
|
||||
asl a
|
||||
bcc ok3
|
||||
ldx #"D"
|
||||
ok3 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"i"
|
||||
asl a
|
||||
bcc ok2
|
||||
ldx #"I"
|
||||
ok2 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"z"
|
||||
asl a
|
||||
bcc ok1
|
||||
ldx #"Z"
|
||||
ok1 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"c"
|
||||
asl a
|
||||
bcc ok0
|
||||
ldx #"C"
|
||||
ok0 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
.bend
|
||||
hexb pha
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
jsr hexn
|
||||
pla
|
||||
and #$0f
|
||||
hexn ora #$30
|
||||
cmp #$3a
|
||||
bcc hexn0
|
||||
adc #6
|
||||
hexn0 jmp $ffd2
|
||||
|
||||
print pla
|
||||
.block
|
||||
sta print0+1
|
||||
pla
|
||||
sta print0+2
|
||||
ldx #1
|
||||
print0 lda !*,x
|
||||
beq print1
|
||||
jsr $ffd2
|
||||
inx
|
||||
bne print0
|
||||
print1 sec
|
||||
txa
|
||||
adc print0+1
|
||||
sta print2+1
|
||||
lda #0
|
||||
adc print0+2
|
||||
sta print2+2
|
||||
print2 jmp !*
|
||||
.bend
|
||||
|
||||
|
434
src/test/kotlin/6502testsuite/source/adcix.asm
Normal file
434
src/test/kotlin/6502testsuite/source/adcix.asm
Normal file
|
@ -0,0 +1,434 @@
|
|||
*= $0801
|
||||
|
||||
.byte $4c,$16,$08,$00,$97,$32
|
||||
.byte $2c,$30,$3a,$9e,$32,$30
|
||||
.byte $37,$30,$00,$00,$00,$a9
|
||||
.byte $01,$85,$02
|
||||
|
||||
jsr print
|
||||
.byte 13
|
||||
.text "(up)adcix"
|
||||
.byte 0
|
||||
|
||||
lda #%00011011
|
||||
sta db
|
||||
lda #%11000110
|
||||
sta ab
|
||||
lda #%10110001
|
||||
sta xb
|
||||
lda #%01101100
|
||||
sta yb
|
||||
lda #0
|
||||
sta pb
|
||||
tsx
|
||||
stx sb
|
||||
|
||||
lda #0
|
||||
sta db
|
||||
sta ab
|
||||
sta xb
|
||||
lda #<da
|
||||
sta 172
|
||||
lda #>da
|
||||
sta 173
|
||||
|
||||
next lda pb
|
||||
and #%00001000
|
||||
bne decmode
|
||||
lda db
|
||||
sta da
|
||||
sta dr
|
||||
sta cmd0+1
|
||||
and #$7f
|
||||
sta cmd1+1
|
||||
clc
|
||||
lda pb
|
||||
and #1
|
||||
beq noc
|
||||
sec
|
||||
noc php
|
||||
lda ab
|
||||
cmd0 adc #0
|
||||
sta ar
|
||||
lda pb
|
||||
ora #%00110000
|
||||
and #%00111100
|
||||
bcc noc1
|
||||
ora #1
|
||||
noc1 tax
|
||||
lda ab
|
||||
and #$7f
|
||||
plp
|
||||
cmd1 adc #0
|
||||
bmi neg
|
||||
txa
|
||||
and #1
|
||||
beq cont
|
||||
set txa
|
||||
ora #%01000000
|
||||
tax
|
||||
jmp cont
|
||||
neg txa
|
||||
and #1
|
||||
beq set
|
||||
cont lda ar
|
||||
cmp #0
|
||||
bne nozero
|
||||
txa
|
||||
ora #%00000010
|
||||
tax
|
||||
nozero lda ar
|
||||
bpl noneg
|
||||
txa
|
||||
ora #%10000000
|
||||
tax
|
||||
noneg stx pr
|
||||
jmp deccont
|
||||
|
||||
decmode
|
||||
.block
|
||||
lda db
|
||||
sta da
|
||||
sta dr
|
||||
and #$0f
|
||||
sta l0+1
|
||||
lda pb
|
||||
ora #%00110000
|
||||
and #%00111100
|
||||
tax
|
||||
lda pb
|
||||
lsr a
|
||||
lda ab
|
||||
and #$0f
|
||||
l0 adc #0
|
||||
ldy #$00
|
||||
cmp #$0a
|
||||
bcc l1
|
||||
sec
|
||||
sbc #$0a
|
||||
and #$0f
|
||||
ldy #$08
|
||||
l1 sta ar
|
||||
sty l2+1
|
||||
sty l3+1
|
||||
lda db
|
||||
and #$f0
|
||||
ora l3+1
|
||||
sta l3+1
|
||||
lda ab
|
||||
and #$f0
|
||||
l2 ora #0
|
||||
clc
|
||||
l3 adc #0
|
||||
php
|
||||
bcs l4
|
||||
cmp #$a0
|
||||
bcc l5
|
||||
l4 sec
|
||||
sbc #$a0
|
||||
inx
|
||||
l5 ora ar
|
||||
sta ar
|
||||
plp
|
||||
bvc nov
|
||||
php
|
||||
txa
|
||||
ora #%01000000
|
||||
tax
|
||||
plp
|
||||
nov bpl non
|
||||
txa
|
||||
ora #%10000000
|
||||
tax
|
||||
non lda pb
|
||||
lsr a
|
||||
lda ab
|
||||
adc db
|
||||
bne noz
|
||||
txa
|
||||
ora #%00000010
|
||||
tax
|
||||
noz stx pr
|
||||
.bend
|
||||
|
||||
deccont lda xb
|
||||
sta xr
|
||||
|
||||
lda yb
|
||||
sta yr
|
||||
|
||||
lda sb
|
||||
sta sr
|
||||
|
||||
ldx sb
|
||||
txs
|
||||
lda pb
|
||||
pha
|
||||
lda ab
|
||||
ldx xb
|
||||
ldy yb
|
||||
plp
|
||||
|
||||
cmd adc (172,x)
|
||||
|
||||
php
|
||||
cld
|
||||
sta aa
|
||||
stx xa
|
||||
sty ya
|
||||
pla
|
||||
sta pa
|
||||
tsx
|
||||
stx sa
|
||||
jsr check
|
||||
|
||||
inc cmd+1
|
||||
dec xb
|
||||
|
||||
clc
|
||||
lda db
|
||||
adc #17
|
||||
sta db
|
||||
bcc jmpnext
|
||||
lda #0
|
||||
sta db
|
||||
clc
|
||||
lda ab
|
||||
adc #17
|
||||
sta ab
|
||||
bcc jmpnext
|
||||
lda #0
|
||||
sta ab
|
||||
inc pb
|
||||
beq nonext
|
||||
jmpnext jmp next
|
||||
nonext
|
||||
|
||||
jsr print
|
||||
.text " - ok"
|
||||
.byte 13,0
|
||||
lda 2
|
||||
beq load
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
jmp $8000
|
||||
|
||||
load jsr print
|
||||
name .text "adciy"
|
||||
namelen = *-name
|
||||
.byte 0
|
||||
lda #0
|
||||
sta $0a
|
||||
sta $b9
|
||||
lda #namelen
|
||||
sta $b7
|
||||
lda #<name
|
||||
sta $bb
|
||||
lda #>name
|
||||
sta $bc
|
||||
pla
|
||||
pla
|
||||
jmp $e16f
|
||||
|
||||
db .byte 0
|
||||
ab .byte 0
|
||||
xb .byte 0
|
||||
yb .byte 0
|
||||
pb .byte 0
|
||||
sb .byte 0
|
||||
da .byte 0
|
||||
aa .byte 0
|
||||
xa .byte 0
|
||||
ya .byte 0
|
||||
pa .byte 0
|
||||
sa .byte 0
|
||||
dr .byte 0
|
||||
ar .byte 0
|
||||
xr .byte 0
|
||||
yr .byte 0
|
||||
pr .byte 0
|
||||
sr .byte 0
|
||||
|
||||
check
|
||||
.block
|
||||
lda da
|
||||
cmp dr
|
||||
bne error
|
||||
lda aa
|
||||
cmp ar
|
||||
bne error
|
||||
lda xa
|
||||
cmp xr
|
||||
bne error
|
||||
lda ya
|
||||
cmp yr
|
||||
bne error
|
||||
lda pa
|
||||
cmp pr
|
||||
bne error
|
||||
lda sa
|
||||
cmp sr
|
||||
bne error
|
||||
rts
|
||||
|
||||
error jsr print
|
||||
.byte 13
|
||||
.null "before "
|
||||
ldx #<db
|
||||
ldy #>db
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "after "
|
||||
ldx #<da
|
||||
ldy #>da
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "right "
|
||||
ldx #<dr
|
||||
ldy #>dr
|
||||
jsr showregs
|
||||
lda #13
|
||||
jsr $ffd2
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
cmp #3
|
||||
beq stop
|
||||
rts
|
||||
stop lda 2
|
||||
beq basic
|
||||
jmp $8000
|
||||
basic jmp ($a002)
|
||||
|
||||
showregs stx 172
|
||||
sty 173
|
||||
ldy #0
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
ldx #"n"
|
||||
asl a
|
||||
bcc ok7
|
||||
ldx #"N"
|
||||
ok7 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"v"
|
||||
asl a
|
||||
bcc ok6
|
||||
ldx #"V"
|
||||
ok6 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"0"
|
||||
asl a
|
||||
bcc ok5
|
||||
ldx #"1"
|
||||
ok5 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"b"
|
||||
asl a
|
||||
bcc ok4
|
||||
ldx #"B"
|
||||
ok4 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"d"
|
||||
asl a
|
||||
bcc ok3
|
||||
ldx #"D"
|
||||
ok3 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"i"
|
||||
asl a
|
||||
bcc ok2
|
||||
ldx #"I"
|
||||
ok2 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"z"
|
||||
asl a
|
||||
bcc ok1
|
||||
ldx #"Z"
|
||||
ok1 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"c"
|
||||
asl a
|
||||
bcc ok0
|
||||
ldx #"C"
|
||||
ok0 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
.bend
|
||||
hexb pha
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
jsr hexn
|
||||
pla
|
||||
and #$0f
|
||||
hexn ora #$30
|
||||
cmp #$3a
|
||||
bcc hexn0
|
||||
adc #6
|
||||
hexn0 jmp $ffd2
|
||||
|
||||
print pla
|
||||
.block
|
||||
sta print0+1
|
||||
pla
|
||||
sta print0+2
|
||||
ldx #1
|
||||
print0 lda !*,x
|
||||
beq print1
|
||||
jsr $ffd2
|
||||
inx
|
||||
bne print0
|
||||
print1 sec
|
||||
txa
|
||||
adc print0+1
|
||||
sta print2+1
|
||||
lda #0
|
||||
adc print0+2
|
||||
sta print2+2
|
||||
print2 jmp !*
|
||||
.bend
|
||||
|
||||
|
439
src/test/kotlin/6502testsuite/source/adciy.asm
Normal file
439
src/test/kotlin/6502testsuite/source/adciy.asm
Normal file
|
@ -0,0 +1,439 @@
|
|||
*= $0801
|
||||
|
||||
.byte $4c,$16,$08,$00,$97,$32
|
||||
.byte $2c,$30,$3a,$9e,$32,$30
|
||||
.byte $37,$30,$00,$00,$00,$a9
|
||||
.byte $01,$85,$02
|
||||
|
||||
jsr print
|
||||
.byte 13
|
||||
.text "(up)adciy"
|
||||
.byte 0
|
||||
|
||||
lda #%00011011
|
||||
sta db
|
||||
lda #%11000110
|
||||
sta ab
|
||||
lda #%10110001
|
||||
sta xb
|
||||
lda #%01101100
|
||||
sta yb
|
||||
lda #0
|
||||
sta pb
|
||||
tsx
|
||||
stx sb
|
||||
|
||||
lda #0
|
||||
sta db
|
||||
sta ab
|
||||
sta yb
|
||||
lda #<da
|
||||
sta 172
|
||||
lda #>da
|
||||
sta 173
|
||||
|
||||
next lda pb
|
||||
and #%00001000
|
||||
bne decmode
|
||||
lda db
|
||||
sta da
|
||||
sta dr
|
||||
sta cmd0+1
|
||||
and #$7f
|
||||
sta cmd1+1
|
||||
clc
|
||||
lda pb
|
||||
and #1
|
||||
beq noc
|
||||
sec
|
||||
noc php
|
||||
lda ab
|
||||
cmd0 adc #0
|
||||
sta ar
|
||||
lda pb
|
||||
ora #%00110000
|
||||
and #%00111100
|
||||
bcc noc1
|
||||
ora #1
|
||||
noc1 tax
|
||||
lda ab
|
||||
and #$7f
|
||||
plp
|
||||
cmd1 adc #0
|
||||
bmi neg
|
||||
txa
|
||||
and #1
|
||||
beq cont
|
||||
set txa
|
||||
ora #%01000000
|
||||
tax
|
||||
jmp cont
|
||||
neg txa
|
||||
and #1
|
||||
beq set
|
||||
cont lda ar
|
||||
cmp #0
|
||||
bne nozero
|
||||
txa
|
||||
ora #%00000010
|
||||
tax
|
||||
nozero lda ar
|
||||
bpl noneg
|
||||
txa
|
||||
ora #%10000000
|
||||
tax
|
||||
noneg stx pr
|
||||
jmp deccont
|
||||
|
||||
decmode
|
||||
.block
|
||||
lda db
|
||||
sta da
|
||||
sta dr
|
||||
and #$0f
|
||||
sta l0+1
|
||||
lda pb
|
||||
ora #%00110000
|
||||
and #%00111100
|
||||
tax
|
||||
lda pb
|
||||
lsr a
|
||||
lda ab
|
||||
and #$0f
|
||||
l0 adc #0
|
||||
ldy #$00
|
||||
cmp #$0a
|
||||
bcc l1
|
||||
sec
|
||||
sbc #$0a
|
||||
and #$0f
|
||||
ldy #$08
|
||||
l1 sta ar
|
||||
sty l2+1
|
||||
sty l3+1
|
||||
lda db
|
||||
and #$f0
|
||||
ora l3+1
|
||||
sta l3+1
|
||||
lda ab
|
||||
and #$f0
|
||||
l2 ora #0
|
||||
clc
|
||||
l3 adc #0
|
||||
php
|
||||
bcs l4
|
||||
cmp #$a0
|
||||
bcc l5
|
||||
l4 sec
|
||||
sbc #$a0
|
||||
inx
|
||||
l5 ora ar
|
||||
sta ar
|
||||
plp
|
||||
bvc nov
|
||||
php
|
||||
txa
|
||||
ora #%01000000
|
||||
tax
|
||||
plp
|
||||
nov bpl non
|
||||
txa
|
||||
ora #%10000000
|
||||
tax
|
||||
non lda pb
|
||||
lsr a
|
||||
lda ab
|
||||
adc db
|
||||
bne noz
|
||||
txa
|
||||
ora #%00000010
|
||||
tax
|
||||
noz stx pr
|
||||
.bend
|
||||
|
||||
deccont lda xb
|
||||
sta xr
|
||||
|
||||
lda yb
|
||||
sta yr
|
||||
|
||||
lda sb
|
||||
sta sr
|
||||
|
||||
ldx sb
|
||||
txs
|
||||
lda pb
|
||||
pha
|
||||
lda ab
|
||||
ldx xb
|
||||
ldy yb
|
||||
plp
|
||||
|
||||
cmd adc (172),y
|
||||
|
||||
php
|
||||
cld
|
||||
sta aa
|
||||
stx xa
|
||||
sty ya
|
||||
pla
|
||||
sta pa
|
||||
tsx
|
||||
stx sa
|
||||
jsr check
|
||||
|
||||
inc 172
|
||||
bne noinc
|
||||
inc 173
|
||||
noinc lda yb
|
||||
bne nodec
|
||||
dec 173
|
||||
nodec dec yb
|
||||
|
||||
clc
|
||||
lda db
|
||||
adc #17
|
||||
sta db
|
||||
bcc jmpnext
|
||||
lda #0
|
||||
sta db
|
||||
clc
|
||||
lda ab
|
||||
adc #17
|
||||
sta ab
|
||||
bcc jmpnext
|
||||
lda #0
|
||||
sta ab
|
||||
inc pb
|
||||
beq nonext
|
||||
jmpnext jmp next
|
||||
nonext
|
||||
|
||||
jsr print
|
||||
.text " - ok"
|
||||
.byte 13,0
|
||||
lda 2
|
||||
beq load
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
jmp $8000
|
||||
|
||||
load jsr print
|
||||
name .text "sbcb"
|
||||
namelen = *-name
|
||||
.byte 0
|
||||
lda #0
|
||||
sta $0a
|
||||
sta $b9
|
||||
lda #namelen
|
||||
sta $b7
|
||||
lda #<name
|
||||
sta $bb
|
||||
lda #>name
|
||||
sta $bc
|
||||
pla
|
||||
pla
|
||||
jmp $e16f
|
||||
|
||||
db .byte 0
|
||||
ab .byte 0
|
||||
xb .byte 0
|
||||
yb .byte 0
|
||||
pb .byte 0
|
||||
sb .byte 0
|
||||
da .byte 0
|
||||
aa .byte 0
|
||||
xa .byte 0
|
||||
ya .byte 0
|
||||
pa .byte 0
|
||||
sa .byte 0
|
||||
dr .byte 0
|
||||
ar .byte 0
|
||||
xr .byte 0
|
||||
yr .byte 0
|
||||
pr .byte 0
|
||||
sr .byte 0
|
||||
|
||||
check
|
||||
.block
|
||||
lda da
|
||||
cmp dr
|
||||
bne error
|
||||
lda aa
|
||||
cmp ar
|
||||
bne error
|
||||
lda xa
|
||||
cmp xr
|
||||
bne error
|
||||
lda ya
|
||||
cmp yr
|
||||
bne error
|
||||
lda pa
|
||||
cmp pr
|
||||
bne error
|
||||
lda sa
|
||||
cmp sr
|
||||
bne error
|
||||
rts
|
||||
|
||||
error jsr print
|
||||
.byte 13
|
||||
.null "before "
|
||||
ldx #<db
|
||||
ldy #>db
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "after "
|
||||
ldx #<da
|
||||
ldy #>da
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "right "
|
||||
ldx #<dr
|
||||
ldy #>dr
|
||||
jsr showregs
|
||||
lda #13
|
||||
jsr $ffd2
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
cmp #3
|
||||
beq stop
|
||||
rts
|
||||
stop lda 2
|
||||
beq basic
|
||||
jmp $8000
|
||||
basic jmp ($a002)
|
||||
|
||||
showregs stx 172
|
||||
sty 173
|
||||
ldy #0
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
ldx #"n"
|
||||
asl a
|
||||
bcc ok7
|
||||
ldx #"N"
|
||||
ok7 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"v"
|
||||
asl a
|
||||
bcc ok6
|
||||
ldx #"V"
|
||||
ok6 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"0"
|
||||
asl a
|
||||
bcc ok5
|
||||
ldx #"1"
|
||||
ok5 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"b"
|
||||
asl a
|
||||
bcc ok4
|
||||
ldx #"B"
|
||||
ok4 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"d"
|
||||
asl a
|
||||
bcc ok3
|
||||
ldx #"D"
|
||||
ok3 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"i"
|
||||
asl a
|
||||
bcc ok2
|
||||
ldx #"I"
|
||||
ok2 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"z"
|
||||
asl a
|
||||
bcc ok1
|
||||
ldx #"Z"
|
||||
ok1 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"c"
|
||||
asl a
|
||||
bcc ok0
|
||||
ldx #"C"
|
||||
ok0 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
.bend
|
||||
hexb pha
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
jsr hexn
|
||||
pla
|
||||
and #$0f
|
||||
hexn ora #$30
|
||||
cmp #$3a
|
||||
bcc hexn0
|
||||
adc #6
|
||||
hexn0 jmp $ffd2
|
||||
|
||||
print pla
|
||||
.block
|
||||
sta print0+1
|
||||
pla
|
||||
sta print0+2
|
||||
ldx #1
|
||||
print0 lda !*,x
|
||||
beq print1
|
||||
jsr $ffd2
|
||||
inx
|
||||
bne print0
|
||||
print1 sec
|
||||
txa
|
||||
adc print0+1
|
||||
sta print2+1
|
||||
lda #0
|
||||
adc print0+2
|
||||
sta print2+2
|
||||
print2 jmp !*
|
||||
.bend
|
||||
|
||||
|
428
src/test/kotlin/6502testsuite/source/adcz.asm
Normal file
428
src/test/kotlin/6502testsuite/source/adcz.asm
Normal file
|
@ -0,0 +1,428 @@
|
|||
*= $0801
|
||||
|
||||
.byte $4c,$16,$08,$00,$97,$32
|
||||
.byte $2c,$30,$3a,$9e,$32,$30
|
||||
.byte $37,$30,$00,$00,$00,$a9
|
||||
.byte $01,$85,$02
|
||||
|
||||
jsr print
|
||||
.byte 13
|
||||
.text "(up)adcz"
|
||||
.byte 0
|
||||
|
||||
lda #%00011011
|
||||
sta db
|
||||
lda #%11000110
|
||||
sta ab
|
||||
lda #%10110001
|
||||
sta xb
|
||||
lda #%01101100
|
||||
sta yb
|
||||
lda #0
|
||||
sta pb
|
||||
tsx
|
||||
stx sb
|
||||
|
||||
lda #0
|
||||
sta db
|
||||
sta ab
|
||||
|
||||
next lda pb
|
||||
and #%00001000
|
||||
bne decmode
|
||||
lda db
|
||||
sta 172
|
||||
sta dr
|
||||
sta cmd0+1
|
||||
and #$7f
|
||||
sta cmd1+1
|
||||
clc
|
||||
lda pb
|
||||
and #1
|
||||
beq noc
|
||||
sec
|
||||
noc php
|
||||
lda ab
|
||||
cmd0 adc #0
|
||||
sta ar
|
||||
lda pb
|
||||
ora #%00110000
|
||||
and #%00111100
|
||||
bcc noc1
|
||||
ora #1
|
||||
noc1 tax
|
||||
lda ab
|
||||
and #$7f
|
||||
plp
|
||||
cmd1 adc #0
|
||||
bmi neg
|
||||
txa
|
||||
and #1
|
||||
beq cont
|
||||
set txa
|
||||
ora #%01000000
|
||||
tax
|
||||
jmp cont
|
||||
neg txa
|
||||
and #1
|
||||
beq set
|
||||
cont lda ar
|
||||
cmp #0
|
||||
bne nozero
|
||||
txa
|
||||
ora #%00000010
|
||||
tax
|
||||
nozero lda ar
|
||||
bpl noneg
|
||||
txa
|
||||
ora #%10000000
|
||||
tax
|
||||
noneg stx pr
|
||||
jmp deccont
|
||||
|
||||
decmode
|
||||
.block
|
||||
lda db
|
||||
sta 172
|
||||
sta dr
|
||||
and #$0f
|
||||
sta l0+1
|
||||
lda pb
|
||||
ora #%00110000
|
||||
and #%00111100
|
||||
tax
|
||||
lda pb
|
||||
lsr a
|
||||
lda ab
|
||||
and #$0f
|
||||
l0 adc #0
|
||||
ldy #$00
|
||||
cmp #$0a
|
||||
bcc l1
|
||||
sec
|
||||
sbc #$0a
|
||||
and #$0f
|
||||
ldy #$08
|
||||
l1 sta ar
|
||||
sty l2+1
|
||||
sty l3+1
|
||||
lda db
|
||||
and #$f0
|
||||
ora l3+1
|
||||
sta l3+1
|
||||
lda ab
|
||||
and #$f0
|
||||
l2 ora #0
|
||||
clc
|
||||
l3 adc #0
|
||||
php
|
||||
bcs l4
|
||||
cmp #$a0
|
||||
bcc l5
|
||||
l4 sec
|
||||
sbc #$a0
|
||||
inx
|
||||
l5 ora ar
|
||||
sta ar
|
||||
plp
|
||||
bvc nov
|
||||
php
|
||||
txa
|
||||
ora #%01000000
|
||||
tax
|
||||
plp
|
||||
nov bpl non
|
||||
txa
|
||||
ora #%10000000
|
||||
tax
|
||||
non lda pb
|
||||
lsr a
|
||||
lda ab
|
||||
adc db
|
||||
bne noz
|
||||
txa
|
||||
ora #%00000010
|
||||
tax
|
||||
noz stx pr
|
||||
.bend
|
||||
|
||||
deccont lda xb
|
||||
sta xr
|
||||
|
||||
lda yb
|
||||
sta yr
|
||||
|
||||
lda sb
|
||||
sta sr
|
||||
|
||||
ldx sb
|
||||
txs
|
||||
lda pb
|
||||
pha
|
||||
lda ab
|
||||
ldx xb
|
||||
ldy yb
|
||||
plp
|
||||
|
||||
cmd adc 172
|
||||
|
||||
php
|
||||
cld
|
||||
sta aa
|
||||
stx xa
|
||||
sty ya
|
||||
pla
|
||||
sta pa
|
||||
tsx
|
||||
stx sa
|
||||
lda 172
|
||||
sta da
|
||||
jsr check
|
||||
|
||||
clc
|
||||
lda db
|
||||
adc #17
|
||||
sta db
|
||||
bcc jmpnext
|
||||
lda #0
|
||||
sta db
|
||||
clc
|
||||
lda ab
|
||||
adc #17
|
||||
sta ab
|
||||
bcc jmpnext
|
||||
lda #0
|
||||
sta ab
|
||||
inc pb
|
||||
beq nonext
|
||||
jmpnext jmp next
|
||||
nonext
|
||||
|
||||
jsr print
|
||||
.text " - ok"
|
||||
.byte 13,0
|
||||
lda 2
|
||||
beq load
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
jmp $8000
|
||||
|
||||
load jsr print
|
||||
name .text "adczx"
|
||||
namelen = *-name
|
||||
.byte 0
|
||||
lda #0
|
||||
sta $0a
|
||||
sta $b9
|
||||
lda #namelen
|
||||
sta $b7
|
||||
lda #<name
|
||||
sta $bb
|
||||
lda #>name
|
||||
sta $bc
|
||||
pla
|
||||
pla
|
||||
jmp $e16f
|
||||
|
||||
db .byte 0
|
||||
ab .byte 0
|
||||
xb .byte 0
|
||||
yb .byte 0
|
||||
pb .byte 0
|
||||
sb .byte 0
|
||||
da .byte 0
|
||||
aa .byte 0
|
||||
xa .byte 0
|
||||
ya .byte 0
|
||||
pa .byte 0
|
||||
sa .byte 0
|
||||
dr .byte 0
|
||||
ar .byte 0
|
||||
xr .byte 0
|
||||
yr .byte 0
|
||||
pr .byte 0
|
||||
sr .byte 0
|
||||
|
||||
check
|
||||
.block
|
||||
lda da
|
||||
cmp dr
|
||||
bne error
|
||||
lda aa
|
||||
cmp ar
|
||||
bne error
|
||||
lda xa
|
||||
cmp xr
|
||||
bne error
|
||||
lda ya
|
||||
cmp yr
|
||||
bne error
|
||||
lda pa
|
||||
cmp pr
|
||||
bne error
|
||||
lda sa
|
||||
cmp sr
|
||||
bne error
|
||||
rts
|
||||
|
||||
error jsr print
|
||||
.byte 13
|
||||
.null "before "
|
||||
ldx #<db
|
||||
ldy #>db
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "after "
|
||||
ldx #<da
|
||||
ldy #>da
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "right "
|
||||
ldx #<dr
|
||||
ldy #>dr
|
||||
jsr showregs
|
||||
lda #13
|
||||
jsr $ffd2
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
cmp #3
|
||||
beq stop
|
||||
rts
|
||||
stop lda 2
|
||||
beq basic
|
||||
jmp $8000
|
||||
basic jmp ($a002)
|
||||
|
||||
showregs stx 172
|
||||
sty 173
|
||||
ldy #0
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
ldx #"n"
|
||||
asl a
|
||||
bcc ok7
|
||||
ldx #"N"
|
||||
ok7 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"v"
|
||||
asl a
|
||||
bcc ok6
|
||||
ldx #"V"
|
||||
ok6 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"0"
|
||||
asl a
|
||||
bcc ok5
|
||||
ldx #"1"
|
||||
ok5 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"b"
|
||||
asl a
|
||||
bcc ok4
|
||||
ldx #"B"
|
||||
ok4 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"d"
|
||||
asl a
|
||||
bcc ok3
|
||||
ldx #"D"
|
||||
ok3 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"i"
|
||||
asl a
|
||||
bcc ok2
|
||||
ldx #"I"
|
||||
ok2 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"z"
|
||||
asl a
|
||||
bcc ok1
|
||||
ldx #"Z"
|
||||
ok1 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"c"
|
||||
asl a
|
||||
bcc ok0
|
||||
ldx #"C"
|
||||
ok0 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
.bend
|
||||
hexb pha
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
jsr hexn
|
||||
pla
|
||||
and #$0f
|
||||
hexn ora #$30
|
||||
cmp #$3a
|
||||
bcc hexn0
|
||||
adc #6
|
||||
hexn0 jmp $ffd2
|
||||
|
||||
print pla
|
||||
.block
|
||||
sta print0+1
|
||||
pla
|
||||
sta print0+2
|
||||
ldx #1
|
||||
print0 lda !*,x
|
||||
beq print1
|
||||
jsr $ffd2
|
||||
inx
|
||||
bne print0
|
||||
print1 sec
|
||||
txa
|
||||
adc print0+1
|
||||
sta print2+1
|
||||
lda #0
|
||||
adc print0+2
|
||||
sta print2+2
|
||||
print2 jmp !*
|
||||
.bend
|
||||
|
||||
|
432
src/test/kotlin/6502testsuite/source/adczx.asm
Normal file
432
src/test/kotlin/6502testsuite/source/adczx.asm
Normal file
|
@ -0,0 +1,432 @@
|
|||
*= $0801
|
||||
|
||||
.byte $4c,$16,$08,$00,$97,$32
|
||||
.byte $2c,$30,$3a,$9e,$32,$30
|
||||
.byte $37,$30,$00,$00,$00,$a9
|
||||
.byte $01,$85,$02
|
||||
|
||||
jsr print
|
||||
.byte 13
|
||||
.text "(up)adczx"
|
||||
.byte 0
|
||||
|
||||
lda #%00011011
|
||||
sta db
|
||||
lda #%11000110
|
||||
sta ab
|
||||
lda #%10110001
|
||||
sta xb
|
||||
lda #%01101100
|
||||
sta yb
|
||||
lda #0
|
||||
sta pb
|
||||
tsx
|
||||
stx sb
|
||||
|
||||
lda #0
|
||||
sta db
|
||||
sta ab
|
||||
sta xb
|
||||
|
||||
next lda pb
|
||||
and #%00001000
|
||||
bne decmode
|
||||
lda db
|
||||
sta 172
|
||||
sta dr
|
||||
sta cmd0+1
|
||||
and #$7f
|
||||
sta cmd1+1
|
||||
clc
|
||||
lda pb
|
||||
and #1
|
||||
beq noc
|
||||
sec
|
||||
noc php
|
||||
lda ab
|
||||
cmd0 adc #0
|
||||
sta ar
|
||||
lda pb
|
||||
ora #%00110000
|
||||
and #%00111100
|
||||
bcc noc1
|
||||
ora #1
|
||||
noc1 tax
|
||||
lda ab
|
||||
and #$7f
|
||||
plp
|
||||
cmd1 adc #0
|
||||
bmi neg
|
||||
txa
|
||||
and #1
|
||||
beq cont
|
||||
set txa
|
||||
ora #%01000000
|
||||
tax
|
||||
jmp cont
|
||||
neg txa
|
||||
and #1
|
||||
beq set
|
||||
cont lda ar
|
||||
cmp #0
|
||||
bne nozero
|
||||
txa
|
||||
ora #%00000010
|
||||
tax
|
||||
nozero lda ar
|
||||
bpl noneg
|
||||
txa
|
||||
ora #%10000000
|
||||
tax
|
||||
noneg stx pr
|
||||
jmp deccont
|
||||
|
||||
decmode
|
||||
.block
|
||||
lda db
|
||||
sta 172
|
||||
sta dr
|
||||
and #$0f
|
||||
sta l0+1
|
||||
lda pb
|
||||
ora #%00110000
|
||||
and #%00111100
|
||||
tax
|
||||
lda pb
|
||||
lsr a
|
||||
lda ab
|
||||
and #$0f
|
||||
l0 adc #0
|
||||
ldy #$00
|
||||
cmp #$0a
|
||||
bcc l1
|
||||
sec
|
||||
sbc #$0a
|
||||
and #$0f
|
||||
ldy #$08
|
||||
l1 sta ar
|
||||
sty l2+1
|
||||
sty l3+1
|
||||
lda db
|
||||
and #$f0
|
||||
ora l3+1
|
||||
sta l3+1
|
||||
lda ab
|
||||
and #$f0
|
||||
l2 ora #0
|
||||
clc
|
||||
l3 adc #0
|
||||
php
|
||||
bcs l4
|
||||
cmp #$a0
|
||||
bcc l5
|
||||
l4 sec
|
||||
sbc #$a0
|
||||
inx
|
||||
l5 ora ar
|
||||
sta ar
|
||||
plp
|
||||
bvc nov
|
||||
php
|
||||
txa
|
||||
ora #%01000000
|
||||
tax
|
||||
plp
|
||||
nov bpl non
|
||||
txa
|
||||
ora #%10000000
|
||||
tax
|
||||
non lda pb
|
||||
lsr a
|
||||
lda ab
|
||||
adc db
|
||||
bne noz
|
||||
txa
|
||||
ora #%00000010
|
||||
tax
|
||||
noz stx pr
|
||||
.bend
|
||||
|
||||
deccont lda xb
|
||||
sta xr
|
||||
|
||||
lda yb
|
||||
sta yr
|
||||
|
||||
lda sb
|
||||
sta sr
|
||||
|
||||
ldx sb
|
||||
txs
|
||||
lda pb
|
||||
pha
|
||||
lda ab
|
||||
ldx xb
|
||||
ldy yb
|
||||
plp
|
||||
|
||||
cmd adc 172,x
|
||||
|
||||
php
|
||||
cld
|
||||
sta aa
|
||||
stx xa
|
||||
sty ya
|
||||
pla
|
||||
sta pa
|
||||
tsx
|
||||
stx sa
|
||||
lda 172
|
||||
sta da
|
||||
jsr check
|
||||
|
||||
inc cmd+1
|
||||
dec xb
|
||||
|
||||
clc
|
||||
lda db
|
||||
adc #17
|
||||
sta db
|
||||
bcc jmpnext
|
||||
lda #0
|
||||
sta db
|
||||
clc
|
||||
lda ab
|
||||
adc #17
|
||||
sta ab
|
||||
bcc jmpnext
|
||||
lda #0
|
||||
sta ab
|
||||
inc pb
|
||||
beq nonext
|
||||
jmpnext jmp next
|
||||
nonext
|
||||
|
||||
jsr print
|
||||
.text " - ok"
|
||||
.byte 13,0
|
||||
lda 2
|
||||
beq load
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
jmp $8000
|
||||
|
||||
load jsr print
|
||||
name .text "adca"
|
||||
namelen = *-name
|
||||
.byte 0
|
||||
lda #0
|
||||
sta $0a
|
||||
sta $b9
|
||||
lda #namelen
|
||||
sta $b7
|
||||
lda #<name
|
||||
sta $bb
|
||||
lda #>name
|
||||
sta $bc
|
||||
pla
|
||||
pla
|
||||
jmp $e16f
|
||||
|
||||
db .byte 0
|
||||
ab .byte 0
|
||||
xb .byte 0
|
||||
yb .byte 0
|
||||
pb .byte 0
|
||||
sb .byte 0
|
||||
da .byte 0
|
||||
aa .byte 0
|
||||
xa .byte 0
|
||||
ya .byte 0
|
||||
pa .byte 0
|
||||
sa .byte 0
|
||||
dr .byte 0
|
||||
ar .byte 0
|
||||
xr .byte 0
|
||||
yr .byte 0
|
||||
pr .byte 0
|
||||
sr .byte 0
|
||||
|
||||
check
|
||||
.block
|
||||
lda da
|
||||
cmp dr
|
||||
bne error
|
||||
lda aa
|
||||
cmp ar
|
||||
bne error
|
||||
lda xa
|
||||
cmp xr
|
||||
bne error
|
||||
lda ya
|
||||
cmp yr
|
||||
bne error
|
||||
lda pa
|
||||
cmp pr
|
||||
bne error
|
||||
lda sa
|
||||
cmp sr
|
||||
bne error
|
||||
rts
|
||||
|
||||
error jsr print
|
||||
.byte 13
|
||||
.null "before "
|
||||
ldx #<db
|
||||
ldy #>db
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "after "
|
||||
ldx #<da
|
||||
ldy #>da
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "right "
|
||||
ldx #<dr
|
||||
ldy #>dr
|
||||
jsr showregs
|
||||
lda #13
|
||||
jsr $ffd2
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
cmp #3
|
||||
beq stop
|
||||
rts
|
||||
stop lda 2
|
||||
beq basic
|
||||
jmp $8000
|
||||
basic jmp ($a002)
|
||||
|
||||
showregs stx 172
|
||||
sty 173
|
||||
ldy #0
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
ldx #"n"
|
||||
asl a
|
||||
bcc ok7
|
||||
ldx #"N"
|
||||
ok7 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"v"
|
||||
asl a
|
||||
bcc ok6
|
||||
ldx #"V"
|
||||
ok6 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"0"
|
||||
asl a
|
||||
bcc ok5
|
||||
ldx #"1"
|
||||
ok5 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"b"
|
||||
asl a
|
||||
bcc ok4
|
||||
ldx #"B"
|
||||
ok4 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"d"
|
||||
asl a
|
||||
bcc ok3
|
||||
ldx #"D"
|
||||
ok3 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"i"
|
||||
asl a
|
||||
bcc ok2
|
||||
ldx #"I"
|
||||
ok2 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"z"
|
||||
asl a
|
||||
bcc ok1
|
||||
ldx #"Z"
|
||||
ok1 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"c"
|
||||
asl a
|
||||
bcc ok0
|
||||
ldx #"C"
|
||||
ok0 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
.bend
|
||||
hexb pha
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
jsr hexn
|
||||
pla
|
||||
and #$0f
|
||||
hexn ora #$30
|
||||
cmp #$3a
|
||||
bcc hexn0
|
||||
adc #6
|
||||
hexn0 jmp $ffd2
|
||||
|
||||
print pla
|
||||
.block
|
||||
sta print0+1
|
||||
pla
|
||||
sta print0+2
|
||||
ldx #1
|
||||
print0 lda !*,x
|
||||
beq print1
|
||||
jsr $ffd2
|
||||
inx
|
||||
bne print0
|
||||
print1 sec
|
||||
txa
|
||||
adc print0+1
|
||||
sta print2+1
|
||||
lda #0
|
||||
adc print0+2
|
||||
sta print2+2
|
||||
print2 jmp !*
|
||||
.bend
|
||||
|
||||
|
327
src/test/kotlin/6502testsuite/source/alrb.asm
Normal file
327
src/test/kotlin/6502testsuite/source/alrb.asm
Normal file
|
@ -0,0 +1,327 @@
|
|||
*= $0801
|
||||
|
||||
.byte $4c,$16,$08,$00,$97,$32
|
||||
.byte $2c,$30,$3a,$9e,$32,$30
|
||||
.byte $37,$30,$00,$00,$00,$a9
|
||||
.byte $01,$85,$02
|
||||
|
||||
jsr print
|
||||
.byte 13
|
||||
.text "(up)alrb"
|
||||
.byte 0
|
||||
|
||||
lda #%00011011
|
||||
sta db
|
||||
lda #%11000110
|
||||
sta ab
|
||||
lda #%10110001
|
||||
sta xb
|
||||
lda #%01101100
|
||||
sta yb
|
||||
lda #0
|
||||
sta pb
|
||||
tsx
|
||||
stx sb
|
||||
|
||||
lda #0
|
||||
sta db
|
||||
sta ab
|
||||
|
||||
next lda db
|
||||
sta da
|
||||
sta dr
|
||||
sta cmd+1
|
||||
|
||||
lda pb
|
||||
pha
|
||||
plp
|
||||
|
||||
lda ab
|
||||
and db
|
||||
lsr a
|
||||
sta ar
|
||||
|
||||
php
|
||||
pla
|
||||
sta pr
|
||||
|
||||
lda xb
|
||||
sta xr
|
||||
|
||||
lda yb
|
||||
sta yr
|
||||
|
||||
|
||||
lda sb
|
||||
sta sr
|
||||
|
||||
ldx sb
|
||||
txs
|
||||
lda pb
|
||||
pha
|
||||
lda ab
|
||||
ldx xb
|
||||
ldy yb
|
||||
plp
|
||||
|
||||
cmd .byte $4b
|
||||
.byte 0
|
||||
|
||||
php
|
||||
cld
|
||||
sta aa
|
||||
stx xa
|
||||
sty ya
|
||||
pla
|
||||
sta pa
|
||||
tsx
|
||||
stx sa
|
||||
jsr check
|
||||
|
||||
clc
|
||||
lda db
|
||||
adc #17
|
||||
sta db
|
||||
bcc jmpnext
|
||||
lda #0
|
||||
sta db
|
||||
clc
|
||||
lda ab
|
||||
adc #17
|
||||
sta ab
|
||||
bcc jmpnext
|
||||
lda #0
|
||||
sta ab
|
||||
inc pb
|
||||
beq nonext
|
||||
jmpnext jmp next
|
||||
nonext
|
||||
|
||||
jsr print
|
||||
.text " - ok"
|
||||
.byte 13,0
|
||||
lda 2
|
||||
beq load
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
jmp $8000
|
||||
|
||||
load jsr print
|
||||
name .text "arrb"
|
||||
namelen = *-name
|
||||
.byte 0
|
||||
lda #0
|
||||
sta $0a
|
||||
sta $b9
|
||||
lda #namelen
|
||||
sta $b7
|
||||
lda #<name
|
||||
sta $bb
|
||||
lda #>name
|
||||
sta $bc
|
||||
pla
|
||||
pla
|
||||
jmp $e16f
|
||||
|
||||
db .byte 0
|
||||
ab .byte 0
|
||||
xb .byte 0
|
||||
yb .byte 0
|
||||
pb .byte 0
|
||||
sb .byte 0
|
||||
da .byte 0
|
||||
aa .byte 0
|
||||
xa .byte 0
|
||||
ya .byte 0
|
||||
pa .byte 0
|
||||
sa .byte 0
|
||||
dr .byte 0
|
||||
ar .byte 0
|
||||
xr .byte 0
|
||||
yr .byte 0
|
||||
pr .byte 0
|
||||
sr .byte 0
|
||||
|
||||
check
|
||||
.block
|
||||
lda da
|
||||
cmp dr
|
||||
bne error
|
||||
lda aa
|
||||
cmp ar
|
||||
bne error
|
||||
lda xa
|
||||
cmp xr
|
||||
bne error
|
||||
lda ya
|
||||
cmp yr
|
||||
bne error
|
||||
lda pa
|
||||
cmp pr
|
||||
bne error
|
||||
lda sa
|
||||
cmp sr
|
||||
bne error
|
||||
rts
|
||||
|
||||
error jsr print
|
||||
.byte 13
|
||||
.null "before "
|
||||
ldx #<db
|
||||
ldy #>db
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "after "
|
||||
ldx #<da
|
||||
ldy #>da
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "right "
|
||||
ldx #<dr
|
||||
ldy #>dr
|
||||
jsr showregs
|
||||
lda #13
|
||||
jsr $ffd2
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
cmp #3
|
||||
beq stop
|
||||
rts
|
||||
stop lda 2
|
||||
beq basic
|
||||
jmp $8000
|
||||
basic jmp ($a002)
|
||||
|
||||
showregs stx 172
|
||||
sty 173
|
||||
ldy #0
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
ldx #"n"
|
||||
asl a
|
||||
bcc ok7
|
||||
ldx #"N"
|
||||
ok7 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"v"
|
||||
asl a
|
||||
bcc ok6
|
||||
ldx #"V"
|
||||
ok6 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"0"
|
||||
asl a
|
||||
bcc ok5
|
||||
ldx #"1"
|
||||
ok5 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"b"
|
||||
asl a
|
||||
bcc ok4
|
||||
ldx #"B"
|
||||
ok4 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"d"
|
||||
asl a
|
||||
bcc ok3
|
||||
ldx #"D"
|
||||
ok3 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"i"
|
||||
asl a
|
||||
bcc ok2
|
||||
ldx #"I"
|
||||
ok2 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"z"
|
||||
asl a
|
||||
bcc ok1
|
||||
ldx #"Z"
|
||||
ok1 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"c"
|
||||
asl a
|
||||
bcc ok0
|
||||
ldx #"C"
|
||||
ok0 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
.bend
|
||||
hexb pha
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
jsr hexn
|
||||
pla
|
||||
and #$0f
|
||||
hexn ora #$30
|
||||
cmp #$3a
|
||||
bcc hexn0
|
||||
adc #6
|
||||
hexn0 jmp $ffd2
|
||||
|
||||
print pla
|
||||
.block
|
||||
sta print0+1
|
||||
pla
|
||||
sta print0+2
|
||||
ldx #1
|
||||
print0 lda !*,x
|
||||
beq print1
|
||||
jsr $ffd2
|
||||
inx
|
||||
bne print0
|
||||
print1 sec
|
||||
txa
|
||||
adc print0+1
|
||||
sta print2+1
|
||||
lda #0
|
||||
adc print0+2
|
||||
sta print2+2
|
||||
print2 jmp !*
|
||||
.bend
|
||||
|
||||
|
346
src/test/kotlin/6502testsuite/source/ancb.asm
Normal file
346
src/test/kotlin/6502testsuite/source/ancb.asm
Normal file
|
@ -0,0 +1,346 @@
|
|||
*= $0801
|
||||
|
||||
.byte $4c,$16,$08,$00,$97,$32
|
||||
.byte $2c,$30,$3a,$9e,$32,$30
|
||||
.byte $37,$30,$00,$00,$00,$a9
|
||||
.byte $01,$85,$02
|
||||
|
||||
jsr print
|
||||
.byte 13
|
||||
.text "(up)ancb"
|
||||
.byte 0
|
||||
|
||||
lda #%00011011
|
||||
sta db
|
||||
lda #%11000110
|
||||
sta ab
|
||||
lda #%10110001
|
||||
sta xb
|
||||
lda #%01101100
|
||||
sta yb
|
||||
lda #0
|
||||
sta pb
|
||||
tsx
|
||||
stx sb
|
||||
|
||||
lda #0
|
||||
sta db
|
||||
sta ab
|
||||
lda #$0b
|
||||
sta cmd
|
||||
|
||||
next lda db
|
||||
sta da
|
||||
sta dr
|
||||
sta cmd+1
|
||||
eor #$ff
|
||||
sta cmdr+1
|
||||
|
||||
lda ab
|
||||
eor #$ff
|
||||
cmdr ora #0
|
||||
eor #$ff
|
||||
sta ar
|
||||
|
||||
lda xb
|
||||
sta xr
|
||||
|
||||
lda yb
|
||||
sta yr
|
||||
|
||||
lda pb
|
||||
ora #%00110000
|
||||
and #%01111100
|
||||
tax
|
||||
lda ar
|
||||
cmp #0
|
||||
bne nozero
|
||||
txa
|
||||
ora #%00000010
|
||||
tax
|
||||
nozero lda ar
|
||||
bpl noneg
|
||||
txa
|
||||
ora #%10000001
|
||||
tax
|
||||
noneg stx pr
|
||||
|
||||
lda sb
|
||||
sta sr
|
||||
|
||||
ldx sb
|
||||
txs
|
||||
lda pb
|
||||
pha
|
||||
lda ab
|
||||
ldx xb
|
||||
ldy yb
|
||||
plp
|
||||
|
||||
cmd .byte 0
|
||||
.byte 0
|
||||
|
||||
php
|
||||
cld
|
||||
sta aa
|
||||
stx xa
|
||||
sty ya
|
||||
pla
|
||||
sta pa
|
||||
tsx
|
||||
stx sa
|
||||
jsr check
|
||||
|
||||
clc
|
||||
lda db
|
||||
adc #17
|
||||
sta db
|
||||
bcc jmpnext
|
||||
lda #0
|
||||
sta db
|
||||
clc
|
||||
lda ab
|
||||
adc #17
|
||||
sta ab
|
||||
bcc jmpnext
|
||||
lda #0
|
||||
sta ab
|
||||
inc pb
|
||||
beq nonext
|
||||
jmpnext jmp next
|
||||
nonext
|
||||
lda #$2b
|
||||
cmp cmd
|
||||
beq end
|
||||
sta cmd
|
||||
jmp next
|
||||
end
|
||||
|
||||
jsr print
|
||||
.text " - ok"
|
||||
.byte 13,0
|
||||
lda 2
|
||||
beq load
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
jmp $8000
|
||||
|
||||
load jsr print
|
||||
name .text "lasay"
|
||||
namelen = *-name
|
||||
.byte 0
|
||||
lda #0
|
||||
sta $0a
|
||||
sta $b9
|
||||
lda #namelen
|
||||
sta $b7
|
||||
lda #<name
|
||||
sta $bb
|
||||
lda #>name
|
||||
sta $bc
|
||||
pla
|
||||
pla
|
||||
jmp $e16f
|
||||
|
||||
db .byte 0
|
||||
ab .byte 0
|
||||
xb .byte 0
|
||||
yb .byte 0
|
||||
pb .byte 0
|
||||
sb .byte 0
|
||||
da .byte 0
|
||||
aa .byte 0
|
||||
xa .byte 0
|
||||
ya .byte 0
|
||||
pa .byte 0
|
||||
sa .byte 0
|
||||
dr .byte 0
|
||||
ar .byte 0
|
||||
xr .byte 0
|
||||
yr .byte 0
|
||||
pr .byte 0
|
||||
sr .byte 0
|
||||
|
||||
check
|
||||
.block
|
||||
lda da
|
||||
cmp dr
|
||||
bne error
|
||||
lda aa
|
||||
cmp ar
|
||||
bne error
|
||||
lda xa
|
||||
cmp xr
|
||||
bne error
|
||||
lda ya
|
||||
cmp yr
|
||||
bne error
|
||||
lda pa
|
||||
cmp pr
|
||||
bne error
|
||||
lda sa
|
||||
cmp sr
|
||||
bne error
|
||||
rts
|
||||
|
||||
error jsr print
|
||||
.byte 13
|
||||
.null "before "
|
||||
ldx #<db
|
||||
ldy #>db
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "after "
|
||||
ldx #<da
|
||||
ldy #>da
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "right "
|
||||
ldx #<dr
|
||||
ldy #>dr
|
||||
jsr showregs
|
||||
lda #13
|
||||
jsr $ffd2
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
cmp #3
|
||||
beq stop
|
||||
rts
|
||||
stop lda 2
|
||||
beq basic
|
||||
jmp $8000
|
||||
basic jmp ($a002)
|
||||
|
||||
showregs stx 172
|
||||
sty 173
|
||||
ldy #0
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
ldx #"n"
|
||||
asl a
|
||||
bcc ok7
|
||||
ldx #"N"
|
||||
ok7 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"v"
|
||||
asl a
|
||||
bcc ok6
|
||||
ldx #"V"
|
||||
ok6 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"0"
|
||||
asl a
|
||||
bcc ok5
|
||||
ldx #"1"
|
||||
ok5 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"b"
|
||||
asl a
|
||||
bcc ok4
|
||||
ldx #"B"
|
||||
ok4 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"d"
|
||||
asl a
|
||||
bcc ok3
|
||||
ldx #"D"
|
||||
ok3 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"i"
|
||||
asl a
|
||||
bcc ok2
|
||||
ldx #"I"
|
||||
ok2 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"z"
|
||||
asl a
|
||||
bcc ok1
|
||||
ldx #"Z"
|
||||
ok1 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"c"
|
||||
asl a
|
||||
bcc ok0
|
||||
ldx #"C"
|
||||
ok0 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
.bend
|
||||
hexb pha
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
jsr hexn
|
||||
pla
|
||||
and #$0f
|
||||
hexn ora #$30
|
||||
cmp #$3a
|
||||
bcc hexn0
|
||||
adc #6
|
||||
hexn0 jmp $ffd2
|
||||
|
||||
print pla
|
||||
.block
|
||||
sta print0+1
|
||||
pla
|
||||
sta print0+2
|
||||
ldx #1
|
||||
print0 lda !*,x
|
||||
beq print1
|
||||
jsr $ffd2
|
||||
inx
|
||||
bne print0
|
||||
print1 sec
|
||||
txa
|
||||
adc print0+1
|
||||
sta print2+1
|
||||
lda #0
|
||||
adc print0+2
|
||||
sta print2+2
|
||||
print2 jmp !*
|
||||
.bend
|
||||
|
||||
|
336
src/test/kotlin/6502testsuite/source/anda.asm
Normal file
336
src/test/kotlin/6502testsuite/source/anda.asm
Normal file
|
@ -0,0 +1,336 @@
|
|||
*= $0801
|
||||
|
||||
.byte $4c,$16,$08,$00,$97,$32
|
||||
.byte $2c,$30,$3a,$9e,$32,$30
|
||||
.byte $37,$30,$00,$00,$00,$a9
|
||||
.byte $01,$85,$02
|
||||
|
||||
jsr print
|
||||
.byte 13
|
||||
.text "(up)anda"
|
||||
.byte 0
|
||||
|
||||
lda #%00011011
|
||||
sta db
|
||||
lda #%11000110
|
||||
sta ab
|
||||
lda #%10110001
|
||||
sta xb
|
||||
lda #%01101100
|
||||
sta yb
|
||||
lda #0
|
||||
sta pb
|
||||
tsx
|
||||
stx sb
|
||||
|
||||
lda #0
|
||||
sta db
|
||||
sta ab
|
||||
|
||||
next lda db
|
||||
sta da
|
||||
sta dr
|
||||
eor #$ff
|
||||
sta cmdr+1
|
||||
|
||||
lda ab
|
||||
eor #$ff
|
||||
cmdr ora #0
|
||||
eor #$ff
|
||||
sta ar
|
||||
|
||||
lda xb
|
||||
sta xr
|
||||
|
||||
lda yb
|
||||
sta yr
|
||||
|
||||
lda pb
|
||||
ora #%00110000
|
||||
and #%01111101
|
||||
tax
|
||||
lda ar
|
||||
cmp #0
|
||||
bne nozero
|
||||
txa
|
||||
ora #%00000010
|
||||
tax
|
||||
nozero lda ar
|
||||
bpl noneg
|
||||
txa
|
||||
ora #%10000000
|
||||
tax
|
||||
noneg stx pr
|
||||
|
||||
lda sb
|
||||
sta sr
|
||||
|
||||
ldx sb
|
||||
txs
|
||||
lda pb
|
||||
pha
|
||||
lda ab
|
||||
ldx xb
|
||||
ldy yb
|
||||
plp
|
||||
|
||||
cmd and da
|
||||
|
||||
php
|
||||
cld
|
||||
sta aa
|
||||
stx xa
|
||||
sty ya
|
||||
pla
|
||||
sta pa
|
||||
tsx
|
||||
stx sa
|
||||
jsr check
|
||||
|
||||
clc
|
||||
lda db
|
||||
adc #17
|
||||
sta db
|
||||
bcc jmpnext
|
||||
lda #0
|
||||
sta db
|
||||
clc
|
||||
lda ab
|
||||
adc #17
|
||||
sta ab
|
||||
bcc jmpnext
|
||||
lda #0
|
||||
sta ab
|
||||
inc pb
|
||||
beq nonext
|
||||
jmpnext jmp next
|
||||
nonext
|
||||
|
||||
jsr print
|
||||
.text " - ok"
|
||||
.byte 13,0
|
||||
lda 2
|
||||
beq load
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
jmp $8000
|
||||
|
||||
load jsr print
|
||||
name .text "andax"
|
||||
namelen = *-name
|
||||
.byte 0
|
||||
lda #0
|
||||
sta $0a
|
||||
sta $b9
|
||||
lda #namelen
|
||||
sta $b7
|
||||
lda #<name
|
||||
sta $bb
|
||||
lda #>name
|
||||
sta $bc
|
||||
pla
|
||||
pla
|
||||
jmp $e16f
|
||||
|
||||
db .byte 0
|
||||
ab .byte 0
|
||||
xb .byte 0
|
||||
yb .byte 0
|
||||
pb .byte 0
|
||||
sb .byte 0
|
||||
da .byte 0
|
||||
aa .byte 0
|
||||
xa .byte 0
|
||||
ya .byte 0
|
||||
pa .byte 0
|
||||
sa .byte 0
|
||||
dr .byte 0
|
||||
ar .byte 0
|
||||
xr .byte 0
|
||||
yr .byte 0
|
||||
pr .byte 0
|
||||
sr .byte 0
|
||||
|
||||
check
|
||||
.block
|
||||
lda da
|
||||
cmp dr
|
||||
bne error
|
||||
lda aa
|
||||
cmp ar
|
||||
bne error
|
||||
lda xa
|
||||
cmp xr
|
||||
bne error
|
||||
lda ya
|
||||
cmp yr
|
||||
bne error
|
||||
lda pa
|
||||
cmp pr
|
||||
bne error
|
||||
lda sa
|
||||
cmp sr
|
||||
bne error
|
||||
rts
|
||||
|
||||
error jsr print
|
||||
.byte 13
|
||||
.null "before "
|
||||
ldx #<db
|
||||
ldy #>db
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "after "
|
||||
ldx #<da
|
||||
ldy #>da
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "right "
|
||||
ldx #<dr
|
||||
ldy #>dr
|
||||
jsr showregs
|
||||
lda #13
|
||||
jsr $ffd2
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
cmp #3
|
||||
beq stop
|
||||
rts
|
||||
stop lda 2
|
||||
beq basic
|
||||
jmp $8000
|
||||
basic jmp ($a002)
|
||||
|
||||
showregs stx 172
|
||||
sty 173
|
||||
ldy #0
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
ldx #"n"
|
||||
asl a
|
||||
bcc ok7
|
||||
ldx #"N"
|
||||
ok7 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"v"
|
||||
asl a
|
||||
bcc ok6
|
||||
ldx #"V"
|
||||
ok6 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"0"
|
||||
asl a
|
||||
bcc ok5
|
||||
ldx #"1"
|
||||
ok5 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"b"
|
||||
asl a
|
||||
bcc ok4
|
||||
ldx #"B"
|
||||
ok4 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"d"
|
||||
asl a
|
||||
bcc ok3
|
||||
ldx #"D"
|
||||
ok3 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"i"
|
||||
asl a
|
||||
bcc ok2
|
||||
ldx #"I"
|
||||
ok2 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"z"
|
||||
asl a
|
||||
bcc ok1
|
||||
ldx #"Z"
|
||||
ok1 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"c"
|
||||
asl a
|
||||
bcc ok0
|
||||
ldx #"C"
|
||||
ok0 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
.bend
|
||||
hexb pha
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
jsr hexn
|
||||
pla
|
||||
and #$0f
|
||||
hexn ora #$30
|
||||
cmp #$3a
|
||||
bcc hexn0
|
||||
adc #6
|
||||
hexn0 jmp $ffd2
|
||||
|
||||
print pla
|
||||
.block
|
||||
sta print0+1
|
||||
pla
|
||||
sta print0+2
|
||||
ldx #1
|
||||
print0 lda !*,x
|
||||
beq print1
|
||||
jsr $ffd2
|
||||
inx
|
||||
bne print0
|
||||
print1 sec
|
||||
txa
|
||||
adc print0+1
|
||||
sta print2+1
|
||||
lda #0
|
||||
adc print0+2
|
||||
sta print2+2
|
||||
print2 jmp !*
|
||||
.bend
|
||||
|
||||
|
345
src/test/kotlin/6502testsuite/source/andax.asm
Normal file
345
src/test/kotlin/6502testsuite/source/andax.asm
Normal file
|
@ -0,0 +1,345 @@
|
|||
*= $0801
|
||||
|
||||
.byte $4c,$16,$08,$00,$97,$32
|
||||
.byte $2c,$30,$3a,$9e,$32,$30
|
||||
.byte $37,$30,$00,$00,$00,$a9
|
||||
.byte $01,$85,$02
|
||||
|
||||
jsr print
|
||||
.byte 13
|
||||
.text "(up)andax"
|
||||
.byte 0
|
||||
|
||||
lda #%00011011
|
||||
sta db
|
||||
lda #%11000110
|
||||
sta ab
|
||||
lda #%10110001
|
||||
sta xb
|
||||
lda #%01101100
|
||||
sta yb
|
||||
lda #0
|
||||
sta pb
|
||||
tsx
|
||||
stx sb
|
||||
|
||||
lda #0
|
||||
sta db
|
||||
sta ab
|
||||
sta xb
|
||||
|
||||
next lda db
|
||||
sta da
|
||||
sta dr
|
||||
eor #$ff
|
||||
sta cmdr+1
|
||||
|
||||
lda ab
|
||||
eor #$ff
|
||||
cmdr ora #0
|
||||
eor #$ff
|
||||
sta ar
|
||||
|
||||
lda xb
|
||||
sta xr
|
||||
|
||||
lda yb
|
||||
sta yr
|
||||
|
||||
lda pb
|
||||
ora #%00110000
|
||||
and #%01111101
|
||||
tax
|
||||
lda ar
|
||||
cmp #0
|
||||
bne nozero
|
||||
txa
|
||||
ora #%00000010
|
||||
tax
|
||||
nozero lda ar
|
||||
bpl noneg
|
||||
txa
|
||||
ora #%10000000
|
||||
tax
|
||||
noneg stx pr
|
||||
|
||||
lda sb
|
||||
sta sr
|
||||
|
||||
ldx sb
|
||||
txs
|
||||
lda pb
|
||||
pha
|
||||
lda ab
|
||||
ldx xb
|
||||
ldy yb
|
||||
plp
|
||||
|
||||
cmd and da,x
|
||||
|
||||
php
|
||||
cld
|
||||
sta aa
|
||||
stx xa
|
||||
sty ya
|
||||
pla
|
||||
sta pa
|
||||
tsx
|
||||
stx sa
|
||||
jsr check
|
||||
|
||||
inc cmd+1
|
||||
bne noinc
|
||||
inc cmd+2
|
||||
noinc lda xb
|
||||
bne nodec
|
||||
dec cmd+2
|
||||
nodec dec xb
|
||||
|
||||
clc
|
||||
lda db
|
||||
adc #17
|
||||
sta db
|
||||
bcc jmpnext
|
||||
lda #0
|
||||
sta db
|
||||
clc
|
||||
lda ab
|
||||
adc #17
|
||||
sta ab
|
||||
bcc jmpnext
|
||||
lda #0
|
||||
sta ab
|
||||
inc pb
|
||||
beq nonext
|
||||
jmpnext jmp next
|
||||
nonext
|
||||
|
||||
jsr print
|
||||
.text " - ok"
|
||||
.byte 13,0
|
||||
lda 2
|
||||
beq load
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
jmp $8000
|
||||
|
||||
load jsr print
|
||||
name .text "anday"
|
||||
namelen = *-name
|
||||
.byte 0
|
||||
lda #0
|
||||
sta $0a
|
||||
sta $b9
|
||||
lda #namelen
|
||||
sta $b7
|
||||
lda #<name
|
||||
sta $bb
|
||||
lda #>name
|
||||
sta $bc
|
||||
pla
|
||||
pla
|
||||
jmp $e16f
|
||||
|
||||
db .byte 0
|
||||
ab .byte 0
|
||||
xb .byte 0
|
||||
yb .byte 0
|
||||
pb .byte 0
|
||||
sb .byte 0
|
||||
da .byte 0
|
||||
aa .byte 0
|
||||
xa .byte 0
|
||||
ya .byte 0
|
||||
pa .byte 0
|
||||
sa .byte 0
|
||||
dr .byte 0
|
||||
ar .byte 0
|
||||
xr .byte 0
|
||||
yr .byte 0
|
||||
pr .byte 0
|
||||
sr .byte 0
|
||||
|
||||
check
|
||||
.block
|
||||
lda da
|
||||
cmp dr
|
||||
bne error
|
||||
lda aa
|
||||
cmp ar
|
||||
bne error
|
||||
lda xa
|
||||
cmp xr
|
||||
bne error
|
||||
lda ya
|
||||
cmp yr
|
||||
bne error
|
||||
lda pa
|
||||
cmp pr
|
||||
bne error
|
||||
lda sa
|
||||
cmp sr
|
||||
bne error
|
||||
rts
|
||||
|
||||
error jsr print
|
||||
.byte 13
|
||||
.null "before "
|
||||
ldx #<db
|
||||
ldy #>db
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "after "
|
||||
ldx #<da
|
||||
ldy #>da
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "right "
|
||||
ldx #<dr
|
||||
ldy #>dr
|
||||
jsr showregs
|
||||
lda #13
|
||||
jsr $ffd2
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
cmp #3
|
||||
beq stop
|
||||
rts
|
||||
stop lda 2
|
||||
beq basic
|
||||
jmp $8000
|
||||
basic jmp ($a002)
|
||||
|
||||
showregs stx 172
|
||||
sty 173
|
||||
ldy #0
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
ldx #"n"
|
||||
asl a
|
||||
bcc ok7
|
||||
ldx #"N"
|
||||
ok7 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"v"
|
||||
asl a
|
||||
bcc ok6
|
||||
ldx #"V"
|
||||
ok6 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"0"
|
||||
asl a
|
||||
bcc ok5
|
||||
ldx #"1"
|
||||
ok5 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"b"
|
||||
asl a
|
||||
bcc ok4
|
||||
ldx #"B"
|
||||
ok4 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"d"
|
||||
asl a
|
||||
bcc ok3
|
||||
ldx #"D"
|
||||
ok3 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"i"
|
||||
asl a
|
||||
bcc ok2
|
||||
ldx #"I"
|
||||
ok2 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"z"
|
||||
asl a
|
||||
bcc ok1
|
||||
ldx #"Z"
|
||||
ok1 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"c"
|
||||
asl a
|
||||
bcc ok0
|
||||
ldx #"C"
|
||||
ok0 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
.bend
|
||||
hexb pha
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
jsr hexn
|
||||
pla
|
||||
and #$0f
|
||||
hexn ora #$30
|
||||
cmp #$3a
|
||||
bcc hexn0
|
||||
adc #6
|
||||
hexn0 jmp $ffd2
|
||||
|
||||
print pla
|
||||
.block
|
||||
sta print0+1
|
||||
pla
|
||||
sta print0+2
|
||||
ldx #1
|
||||
print0 lda !*,x
|
||||
beq print1
|
||||
jsr $ffd2
|
||||
inx
|
||||
bne print0
|
||||
print1 sec
|
||||
txa
|
||||
adc print0+1
|
||||
sta print2+1
|
||||
lda #0
|
||||
adc print0+2
|
||||
sta print2+2
|
||||
print2 jmp !*
|
||||
.bend
|
||||
|
||||
|
345
src/test/kotlin/6502testsuite/source/anday.asm
Normal file
345
src/test/kotlin/6502testsuite/source/anday.asm
Normal file
|
@ -0,0 +1,345 @@
|
|||
*= $0801
|
||||
|
||||
.byte $4c,$16,$08,$00,$97,$32
|
||||
.byte $2c,$30,$3a,$9e,$32,$30
|
||||
.byte $37,$30,$00,$00,$00,$a9
|
||||
.byte $01,$85,$02
|
||||
|
||||
jsr print
|
||||
.byte 13
|
||||
.text "(up)anday"
|
||||
.byte 0
|
||||
|
||||
lda #%00011011
|
||||
sta db
|
||||
lda #%11000110
|
||||
sta ab
|
||||
lda #%10110001
|
||||
sta xb
|
||||
lda #%01101100
|
||||
sta yb
|
||||
lda #0
|
||||
sta pb
|
||||
tsx
|
||||
stx sb
|
||||
|
||||
lda #0
|
||||
sta db
|
||||
sta ab
|
||||
sta yb
|
||||
|
||||
next lda db
|
||||
sta da
|
||||
sta dr
|
||||
eor #$ff
|
||||
sta cmdr+1
|
||||
|
||||
lda ab
|
||||
eor #$ff
|
||||
cmdr ora #0
|
||||
eor #$ff
|
||||
sta ar
|
||||
|
||||
lda xb
|
||||
sta xr
|
||||
|
||||
lda yb
|
||||
sta yr
|
||||
|
||||
lda pb
|
||||
ora #%00110000
|
||||
and #%01111101
|
||||
tax
|
||||
lda ar
|
||||
cmp #0
|
||||
bne nozero
|
||||
txa
|
||||
ora #%00000010
|
||||
tax
|
||||
nozero lda ar
|
||||
bpl noneg
|
||||
txa
|
||||
ora #%10000000
|
||||
tax
|
||||
noneg stx pr
|
||||
|
||||
lda sb
|
||||
sta sr
|
||||
|
||||
ldx sb
|
||||
txs
|
||||
lda pb
|
||||
pha
|
||||
lda ab
|
||||
ldx xb
|
||||
ldy yb
|
||||
plp
|
||||
|
||||
cmd and da,y
|
||||
|
||||
php
|
||||
cld
|
||||
sta aa
|
||||
stx xa
|
||||
sty ya
|
||||
pla
|
||||
sta pa
|
||||
tsx
|
||||
stx sa
|
||||
jsr check
|
||||
|
||||
inc cmd+1
|
||||
bne noinc
|
||||
inc cmd+2
|
||||
noinc lda yb
|
||||
bne nodec
|
||||
dec cmd+2
|
||||
nodec dec yb
|
||||
|
||||
clc
|
||||
lda db
|
||||
adc #17
|
||||
sta db
|
||||
bcc jmpnext
|
||||
lda #0
|
||||
sta db
|
||||
clc
|
||||
lda ab
|
||||
adc #17
|
||||
sta ab
|
||||
bcc jmpnext
|
||||
lda #0
|
||||
sta ab
|
||||
inc pb
|
||||
beq nonext
|
||||
jmpnext jmp next
|
||||
nonext
|
||||
|
||||
jsr print
|
||||
.text " - ok"
|
||||
.byte 13,0
|
||||
lda 2
|
||||
beq load
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
jmp $8000
|
||||
|
||||
load jsr print
|
||||
name .text "andix"
|
||||
namelen = *-name
|
||||
.byte 0
|
||||
lda #0
|
||||
sta $0a
|
||||
sta $b9
|
||||
lda #namelen
|
||||
sta $b7
|
||||
lda #<name
|
||||
sta $bb
|
||||
lda #>name
|
||||
sta $bc
|
||||
pla
|
||||
pla
|
||||
jmp $e16f
|
||||
|
||||
db .byte 0
|
||||
ab .byte 0
|
||||
xb .byte 0
|
||||
yb .byte 0
|
||||
pb .byte 0
|
||||
sb .byte 0
|
||||
da .byte 0
|
||||
aa .byte 0
|
||||
xa .byte 0
|
||||
ya .byte 0
|
||||
pa .byte 0
|
||||
sa .byte 0
|
||||
dr .byte 0
|
||||
ar .byte 0
|
||||
xr .byte 0
|
||||
yr .byte 0
|
||||
pr .byte 0
|
||||
sr .byte 0
|
||||
|
||||
check
|
||||
.block
|
||||
lda da
|
||||
cmp dr
|
||||
bne error
|
||||
lda aa
|
||||
cmp ar
|
||||
bne error
|
||||
lda xa
|
||||
cmp xr
|
||||
bne error
|
||||
lda ya
|
||||
cmp yr
|
||||
bne error
|
||||
lda pa
|
||||
cmp pr
|
||||
bne error
|
||||
lda sa
|
||||
cmp sr
|
||||
bne error
|
||||
rts
|
||||
|
||||
error jsr print
|
||||
.byte 13
|
||||
.null "before "
|
||||
ldx #<db
|
||||
ldy #>db
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "after "
|
||||
ldx #<da
|
||||
ldy #>da
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "right "
|
||||
ldx #<dr
|
||||
ldy #>dr
|
||||
jsr showregs
|
||||
lda #13
|
||||
jsr $ffd2
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
cmp #3
|
||||
beq stop
|
||||
rts
|
||||
stop lda 2
|
||||
beq basic
|
||||
jmp $8000
|
||||
basic jmp ($a002)
|
||||
|
||||
showregs stx 172
|
||||
sty 173
|
||||
ldy #0
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
ldx #"n"
|
||||
asl a
|
||||
bcc ok7
|
||||
ldx #"N"
|
||||
ok7 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"v"
|
||||
asl a
|
||||
bcc ok6
|
||||
ldx #"V"
|
||||
ok6 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"0"
|
||||
asl a
|
||||
bcc ok5
|
||||
ldx #"1"
|
||||
ok5 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"b"
|
||||
asl a
|
||||
bcc ok4
|
||||
ldx #"B"
|
||||
ok4 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"d"
|
||||
asl a
|
||||
bcc ok3
|
||||
ldx #"D"
|
||||
ok3 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"i"
|
||||
asl a
|
||||
bcc ok2
|
||||
ldx #"I"
|
||||
ok2 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"z"
|
||||
asl a
|
||||
bcc ok1
|
||||
ldx #"Z"
|
||||
ok1 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"c"
|
||||
asl a
|
||||
bcc ok0
|
||||
ldx #"C"
|
||||
ok0 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
.bend
|
||||
hexb pha
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
jsr hexn
|
||||
pla
|
||||
and #$0f
|
||||
hexn ora #$30
|
||||
cmp #$3a
|
||||
bcc hexn0
|
||||
adc #6
|
||||
hexn0 jmp $ffd2
|
||||
|
||||
print pla
|
||||
.block
|
||||
sta print0+1
|
||||
pla
|
||||
sta print0+2
|
||||
ldx #1
|
||||
print0 lda !*,x
|
||||
beq print1
|
||||
jsr $ffd2
|
||||
inx
|
||||
bne print0
|
||||
print1 sec
|
||||
txa
|
||||
adc print0+1
|
||||
sta print2+1
|
||||
lda #0
|
||||
adc print0+2
|
||||
sta print2+2
|
||||
print2 jmp !*
|
||||
.bend
|
||||
|
||||
|
337
src/test/kotlin/6502testsuite/source/andb.asm
Normal file
337
src/test/kotlin/6502testsuite/source/andb.asm
Normal file
|
@ -0,0 +1,337 @@
|
|||
*= $0801
|
||||
|
||||
.byte $4c,$16,$08,$00,$97,$32
|
||||
.byte $2c,$30,$3a,$9e,$32,$30
|
||||
.byte $37,$30,$00,$00,$00,$a9
|
||||
.byte $01,$85,$02
|
||||
|
||||
jsr print
|
||||
.byte 13
|
||||
.text "(up)andb"
|
||||
.byte 0
|
||||
|
||||
lda #%00011011
|
||||
sta db
|
||||
lda #%11000110
|
||||
sta ab
|
||||
lda #%10110001
|
||||
sta xb
|
||||
lda #%01101100
|
||||
sta yb
|
||||
lda #0
|
||||
sta pb
|
||||
tsx
|
||||
stx sb
|
||||
|
||||
lda #0
|
||||
sta db
|
||||
sta ab
|
||||
|
||||
next lda db
|
||||
sta da
|
||||
sta dr
|
||||
sta cmd+1
|
||||
eor #$ff
|
||||
sta cmdr+1
|
||||
|
||||
lda ab
|
||||
eor #$ff
|
||||
cmdr ora #0
|
||||
eor #$ff
|
||||
sta ar
|
||||
|
||||
lda xb
|
||||
sta xr
|
||||
|
||||
lda yb
|
||||
sta yr
|
||||
|
||||
lda pb
|
||||
ora #%00110000
|
||||
and #%01111101
|
||||
tax
|
||||
lda ar
|
||||
cmp #0
|
||||
bne nozero
|
||||
txa
|
||||
ora #%00000010
|
||||
tax
|
||||
nozero lda ar
|
||||
bpl noneg
|
||||
txa
|
||||
ora #%10000000
|
||||
tax
|
||||
noneg stx pr
|
||||
|
||||
lda sb
|
||||
sta sr
|
||||
|
||||
ldx sb
|
||||
txs
|
||||
lda pb
|
||||
pha
|
||||
lda ab
|
||||
ldx xb
|
||||
ldy yb
|
||||
plp
|
||||
|
||||
cmd and #0
|
||||
|
||||
php
|
||||
cld
|
||||
sta aa
|
||||
stx xa
|
||||
sty ya
|
||||
pla
|
||||
sta pa
|
||||
tsx
|
||||
stx sa
|
||||
jsr check
|
||||
|
||||
clc
|
||||
lda db
|
||||
adc #17
|
||||
sta db
|
||||
bcc jmpnext
|
||||
lda #0
|
||||
sta db
|
||||
clc
|
||||
lda ab
|
||||
adc #17
|
||||
sta ab
|
||||
bcc jmpnext
|
||||
lda #0
|
||||
sta ab
|
||||
inc pb
|
||||
beq nonext
|
||||
jmpnext jmp next
|
||||
nonext
|
||||
|
||||
jsr print
|
||||
.text " - ok"
|
||||
.byte 13,0
|
||||
lda 2
|
||||
beq load
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
jmp $8000
|
||||
|
||||
load jsr print
|
||||
name .text "andz"
|
||||
namelen = *-name
|
||||
.byte 0
|
||||
lda #0
|
||||
sta $0a
|
||||
sta $b9
|
||||
lda #namelen
|
||||
sta $b7
|
||||
lda #<name
|
||||
sta $bb
|
||||
lda #>name
|
||||
sta $bc
|
||||
pla
|
||||
pla
|
||||
jmp $e16f
|
||||
|
||||
db .byte 0
|
||||
ab .byte 0
|
||||
xb .byte 0
|
||||
yb .byte 0
|
||||
pb .byte 0
|
||||
sb .byte 0
|
||||
da .byte 0
|
||||
aa .byte 0
|
||||
xa .byte 0
|
||||
ya .byte 0
|
||||
pa .byte 0
|
||||
sa .byte 0
|
||||
dr .byte 0
|
||||
ar .byte 0
|
||||
xr .byte 0
|
||||
yr .byte 0
|
||||
pr .byte 0
|
||||
sr .byte 0
|
||||
|
||||
check
|
||||
.block
|
||||
lda da
|
||||
cmp dr
|
||||
bne error
|
||||
lda aa
|
||||
cmp ar
|
||||
bne error
|
||||
lda xa
|
||||
cmp xr
|
||||
bne error
|
||||
lda ya
|
||||
cmp yr
|
||||
bne error
|
||||
lda pa
|
||||
cmp pr
|
||||
bne error
|
||||
lda sa
|
||||
cmp sr
|
||||
bne error
|
||||
rts
|
||||
|
||||
error jsr print
|
||||
.byte 13
|
||||
.null "before "
|
||||
ldx #<db
|
||||
ldy #>db
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "after "
|
||||
ldx #<da
|
||||
ldy #>da
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "right "
|
||||
ldx #<dr
|
||||
ldy #>dr
|
||||
jsr showregs
|
||||
lda #13
|
||||
jsr $ffd2
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
cmp #3
|
||||
beq stop
|
||||
rts
|
||||
stop lda 2
|
||||
beq basic
|
||||
jmp $8000
|
||||
basic jmp ($a002)
|
||||
|
||||
showregs stx 172
|
||||
sty 173
|
||||
ldy #0
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
ldx #"n"
|
||||
asl a
|
||||
bcc ok7
|
||||
ldx #"N"
|
||||
ok7 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"v"
|
||||
asl a
|
||||
bcc ok6
|
||||
ldx #"V"
|
||||
ok6 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"0"
|
||||
asl a
|
||||
bcc ok5
|
||||
ldx #"1"
|
||||
ok5 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"b"
|
||||
asl a
|
||||
bcc ok4
|
||||
ldx #"B"
|
||||
ok4 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"d"
|
||||
asl a
|
||||
bcc ok3
|
||||
ldx #"D"
|
||||
ok3 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"i"
|
||||
asl a
|
||||
bcc ok2
|
||||
ldx #"I"
|
||||
ok2 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"z"
|
||||
asl a
|
||||
bcc ok1
|
||||
ldx #"Z"
|
||||
ok1 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"c"
|
||||
asl a
|
||||
bcc ok0
|
||||
ldx #"C"
|
||||
ok0 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
.bend
|
||||
hexb pha
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
jsr hexn
|
||||
pla
|
||||
and #$0f
|
||||
hexn ora #$30
|
||||
cmp #$3a
|
||||
bcc hexn0
|
||||
adc #6
|
||||
hexn0 jmp $ffd2
|
||||
|
||||
print pla
|
||||
.block
|
||||
sta print0+1
|
||||
pla
|
||||
sta print0+2
|
||||
ldx #1
|
||||
print0 lda !*,x
|
||||
beq print1
|
||||
jsr $ffd2
|
||||
inx
|
||||
bne print0
|
||||
print1 sec
|
||||
txa
|
||||
adc print0+1
|
||||
sta print2+1
|
||||
lda #0
|
||||
adc print0+2
|
||||
sta print2+2
|
||||
print2 jmp !*
|
||||
.bend
|
||||
|
||||
|
344
src/test/kotlin/6502testsuite/source/andix.asm
Normal file
344
src/test/kotlin/6502testsuite/source/andix.asm
Normal file
|
@ -0,0 +1,344 @@
|
|||
*= $0801
|
||||
|
||||
.byte $4c,$16,$08,$00,$97,$32
|
||||
.byte $2c,$30,$3a,$9e,$32,$30
|
||||
.byte $37,$30,$00,$00,$00,$a9
|
||||
.byte $01,$85,$02
|
||||
|
||||
jsr print
|
||||
.byte 13
|
||||
.text "(up)andix"
|
||||
.byte 0
|
||||
|
||||
lda #%00011011
|
||||
sta db
|
||||
lda #%11000110
|
||||
sta ab
|
||||
lda #%10110001
|
||||
sta xb
|
||||
lda #%01101100
|
||||
sta yb
|
||||
lda #0
|
||||
sta pb
|
||||
tsx
|
||||
stx sb
|
||||
|
||||
lda #0
|
||||
sta db
|
||||
sta ab
|
||||
sta xb
|
||||
lda #<da
|
||||
sta 172
|
||||
lda #>da
|
||||
sta 173
|
||||
|
||||
next lda db
|
||||
sta da
|
||||
sta dr
|
||||
eor #$ff
|
||||
sta cmdr+1
|
||||
|
||||
lda ab
|
||||
eor #$ff
|
||||
cmdr ora #0
|
||||
eor #$ff
|
||||
sta ar
|
||||
|
||||
lda xb
|
||||
sta xr
|
||||
|
||||
lda yb
|
||||
sta yr
|
||||
|
||||
lda pb
|
||||
ora #%00110000
|
||||
and #%01111101
|
||||
tax
|
||||
lda ar
|
||||
cmp #0
|
||||
bne nozero
|
||||
txa
|
||||
ora #%00000010
|
||||
tax
|
||||
nozero lda ar
|
||||
bpl noneg
|
||||
txa
|
||||
ora #%10000000
|
||||
tax
|
||||
noneg stx pr
|
||||
|
||||
lda sb
|
||||
sta sr
|
||||
|
||||
ldx sb
|
||||
txs
|
||||
lda pb
|
||||
pha
|
||||
lda ab
|
||||
ldx xb
|
||||
ldy yb
|
||||
plp
|
||||
|
||||
cmd and (172,x)
|
||||
|
||||
php
|
||||
cld
|
||||
sta aa
|
||||
stx xa
|
||||
sty ya
|
||||
pla
|
||||
sta pa
|
||||
tsx
|
||||
stx sa
|
||||
jsr check
|
||||
|
||||
inc cmd+1
|
||||
dec xb
|
||||
|
||||
clc
|
||||
lda db
|
||||
adc #17
|
||||
sta db
|
||||
bcc jmpnext
|
||||
lda #0
|
||||
sta db
|
||||
clc
|
||||
lda ab
|
||||
adc #17
|
||||
sta ab
|
||||
bcc jmpnext
|
||||
lda #0
|
||||
sta ab
|
||||
inc pb
|
||||
beq nonext
|
||||
jmpnext jmp next
|
||||
nonext
|
||||
|
||||
jsr print
|
||||
.text " - ok"
|
||||
.byte 13,0
|
||||
lda 2
|
||||
beq load
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
jmp $8000
|
||||
|
||||
load jsr print
|
||||
name .text "andiy"
|
||||
namelen = *-name
|
||||
.byte 0
|
||||
lda #0
|
||||
sta $0a
|
||||
sta $b9
|
||||
lda #namelen
|
||||
sta $b7
|
||||
lda #<name
|
||||
sta $bb
|
||||
lda #>name
|
||||
sta $bc
|
||||
pla
|
||||
pla
|
||||
jmp $e16f
|
||||
|
||||
db .byte 0
|
||||
ab .byte 0
|
||||
xb .byte 0
|
||||
yb .byte 0
|
||||
pb .byte 0
|
||||
sb .byte 0
|
||||
da .byte 0
|
||||
aa .byte 0
|
||||
xa .byte 0
|
||||
ya .byte 0
|
||||
pa .byte 0
|
||||
sa .byte 0
|
||||
dr .byte 0
|
||||
ar .byte 0
|
||||
xr .byte 0
|
||||
yr .byte 0
|
||||
pr .byte 0
|
||||
sr .byte 0
|
||||
|
||||
check
|
||||
.block
|
||||
lda da
|
||||
cmp dr
|
||||
bne error
|
||||
lda aa
|
||||
cmp ar
|
||||
bne error
|
||||
lda xa
|
||||
cmp xr
|
||||
bne error
|
||||
lda ya
|
||||
cmp yr
|
||||
bne error
|
||||
lda pa
|
||||
cmp pr
|
||||
bne error
|
||||
lda sa
|
||||
cmp sr
|
||||
bne error
|
||||
rts
|
||||
|
||||
error jsr print
|
||||
.byte 13
|
||||
.null "before "
|
||||
ldx #<db
|
||||
ldy #>db
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "after "
|
||||
ldx #<da
|
||||
ldy #>da
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "right "
|
||||
ldx #<dr
|
||||
ldy #>dr
|
||||
jsr showregs
|
||||
lda #13
|
||||
jsr $ffd2
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
cmp #3
|
||||
beq stop
|
||||
rts
|
||||
stop lda 2
|
||||
beq basic
|
||||
jmp $8000
|
||||
basic jmp ($a002)
|
||||
|
||||
showregs stx 172
|
||||
sty 173
|
||||
ldy #0
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
ldx #"n"
|
||||
asl a
|
||||
bcc ok7
|
||||
ldx #"N"
|
||||
ok7 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"v"
|
||||
asl a
|
||||
bcc ok6
|
||||
ldx #"V"
|
||||
ok6 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"0"
|
||||
asl a
|
||||
bcc ok5
|
||||
ldx #"1"
|
||||
ok5 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"b"
|
||||
asl a
|
||||
bcc ok4
|
||||
ldx #"B"
|
||||
ok4 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"d"
|
||||
asl a
|
||||
bcc ok3
|
||||
ldx #"D"
|
||||
ok3 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"i"
|
||||
asl a
|
||||
bcc ok2
|
||||
ldx #"I"
|
||||
ok2 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"z"
|
||||
asl a
|
||||
bcc ok1
|
||||
ldx #"Z"
|
||||
ok1 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"c"
|
||||
asl a
|
||||
bcc ok0
|
||||
ldx #"C"
|
||||
ok0 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
.bend
|
||||
hexb pha
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
jsr hexn
|
||||
pla
|
||||
and #$0f
|
||||
hexn ora #$30
|
||||
cmp #$3a
|
||||
bcc hexn0
|
||||
adc #6
|
||||
hexn0 jmp $ffd2
|
||||
|
||||
print pla
|
||||
.block
|
||||
sta print0+1
|
||||
pla
|
||||
sta print0+2
|
||||
ldx #1
|
||||
print0 lda !*,x
|
||||
beq print1
|
||||
jsr $ffd2
|
||||
inx
|
||||
bne print0
|
||||
print1 sec
|
||||
txa
|
||||
adc print0+1
|
||||
sta print2+1
|
||||
lda #0
|
||||
adc print0+2
|
||||
sta print2+2
|
||||
print2 jmp !*
|
||||
.bend
|
||||
|
||||
|
349
src/test/kotlin/6502testsuite/source/andiy.asm
Normal file
349
src/test/kotlin/6502testsuite/source/andiy.asm
Normal file
|
@ -0,0 +1,349 @@
|
|||
*= $0801
|
||||
|
||||
.byte $4c,$16,$08,$00,$97,$32
|
||||
.byte $2c,$30,$3a,$9e,$32,$30
|
||||
.byte $37,$30,$00,$00,$00,$a9
|
||||
.byte $01,$85,$02
|
||||
|
||||
jsr print
|
||||
.byte 13
|
||||
.text "(up)andiy"
|
||||
.byte 0
|
||||
|
||||
lda #%00011011
|
||||
sta db
|
||||
lda #%11000110
|
||||
sta ab
|
||||
lda #%10110001
|
||||
sta xb
|
||||
lda #%01101100
|
||||
sta yb
|
||||
lda #0
|
||||
sta pb
|
||||
tsx
|
||||
stx sb
|
||||
|
||||
lda #0
|
||||
sta db
|
||||
sta ab
|
||||
sta yb
|
||||
lda #<da
|
||||
sta 172
|
||||
lda #>da
|
||||
sta 173
|
||||
|
||||
next lda db
|
||||
sta da
|
||||
sta dr
|
||||
eor #$ff
|
||||
sta cmdr+1
|
||||
|
||||
lda ab
|
||||
eor #$ff
|
||||
cmdr ora #0
|
||||
eor #$ff
|
||||
sta ar
|
||||
|
||||
lda xb
|
||||
sta xr
|
||||
|
||||
lda yb
|
||||
sta yr
|
||||
|
||||
lda pb
|
||||
ora #%00110000
|
||||
and #%01111101
|
||||
tax
|
||||
lda ar
|
||||
cmp #0
|
||||
bne nozero
|
||||
txa
|
||||
ora #%00000010
|
||||
tax
|
||||
nozero lda ar
|
||||
bpl noneg
|
||||
txa
|
||||
ora #%10000000
|
||||
tax
|
||||
noneg stx pr
|
||||
|
||||
lda sb
|
||||
sta sr
|
||||
|
||||
ldx sb
|
||||
txs
|
||||
lda pb
|
||||
pha
|
||||
lda ab
|
||||
ldx xb
|
||||
ldy yb
|
||||
plp
|
||||
|
||||
cmd and (172),y
|
||||
|
||||
php
|
||||
cld
|
||||
sta aa
|
||||
stx xa
|
||||
sty ya
|
||||
pla
|
||||
sta pa
|
||||
tsx
|
||||
stx sa
|
||||
jsr check
|
||||
|
||||
inc 172
|
||||
bne noinc
|
||||
inc 173
|
||||
noinc lda yb
|
||||
bne nodec
|
||||
dec 173
|
||||
nodec dec yb
|
||||
|
||||
clc
|
||||
lda db
|
||||
adc #17
|
||||
sta db
|
||||
bcc jmpnext
|
||||
lda #0
|
||||
sta db
|
||||
clc
|
||||
lda ab
|
||||
adc #17
|
||||
sta ab
|
||||
bcc jmpnext
|
||||
lda #0
|
||||
sta ab
|
||||
inc pb
|
||||
beq nonext
|
||||
jmpnext jmp next
|
||||
nonext
|
||||
|
||||
jsr print
|
||||
.text " - ok"
|
||||
.byte 13,0
|
||||
lda 2
|
||||
beq load
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
jmp $8000
|
||||
|
||||
load jsr print
|
||||
name .text "orab"
|
||||
namelen = *-name
|
||||
.byte 0
|
||||
lda #0
|
||||
sta $0a
|
||||
sta $b9
|
||||
lda #namelen
|
||||
sta $b7
|
||||
lda #<name
|
||||
sta $bb
|
||||
lda #>name
|
||||
sta $bc
|
||||
pla
|
||||
pla
|
||||
jmp $e16f
|
||||
|
||||
db .byte 0
|
||||
ab .byte 0
|
||||
xb .byte 0
|
||||
yb .byte 0
|
||||
pb .byte 0
|
||||
sb .byte 0
|
||||
da .byte 0
|
||||
aa .byte 0
|
||||
xa .byte 0
|
||||
ya .byte 0
|
||||
pa .byte 0
|
||||
sa .byte 0
|
||||
dr .byte 0
|
||||
ar .byte 0
|
||||
xr .byte 0
|
||||
yr .byte 0
|
||||
pr .byte 0
|
||||
sr .byte 0
|
||||
|
||||
check
|
||||
.block
|
||||
lda da
|
||||
cmp dr
|
||||
bne error
|
||||
lda aa
|
||||
cmp ar
|
||||
bne error
|
||||
lda xa
|
||||
cmp xr
|
||||
bne error
|
||||
lda ya
|
||||
cmp yr
|
||||
bne error
|
||||
lda pa
|
||||
cmp pr
|
||||
bne error
|
||||
lda sa
|
||||
cmp sr
|
||||
bne error
|
||||
rts
|
||||
|
||||
error jsr print
|
||||
.byte 13
|
||||
.null "before "
|
||||
ldx #<db
|
||||
ldy #>db
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "after "
|
||||
ldx #<da
|
||||
ldy #>da
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "right "
|
||||
ldx #<dr
|
||||
ldy #>dr
|
||||
jsr showregs
|
||||
lda #13
|
||||
jsr $ffd2
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
cmp #3
|
||||
beq stop
|
||||
rts
|
||||
stop lda 2
|
||||
beq basic
|
||||
jmp $8000
|
||||
basic jmp ($a002)
|
||||
|
||||
showregs stx 172
|
||||
sty 173
|
||||
ldy #0
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
ldx #"n"
|
||||
asl a
|
||||
bcc ok7
|
||||
ldx #"N"
|
||||
ok7 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"v"
|
||||
asl a
|
||||
bcc ok6
|
||||
ldx #"V"
|
||||
ok6 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"0"
|
||||
asl a
|
||||
bcc ok5
|
||||
ldx #"1"
|
||||
ok5 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"b"
|
||||
asl a
|
||||
bcc ok4
|
||||
ldx #"B"
|
||||
ok4 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"d"
|
||||
asl a
|
||||
bcc ok3
|
||||
ldx #"D"
|
||||
ok3 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"i"
|
||||
asl a
|
||||
bcc ok2
|
||||
ldx #"I"
|
||||
ok2 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"z"
|
||||
asl a
|
||||
bcc ok1
|
||||
ldx #"Z"
|
||||
ok1 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"c"
|
||||
asl a
|
||||
bcc ok0
|
||||
ldx #"C"
|
||||
ok0 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
.bend
|
||||
hexb pha
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
jsr hexn
|
||||
pla
|
||||
and #$0f
|
||||
hexn ora #$30
|
||||
cmp #$3a
|
||||
bcc hexn0
|
||||
adc #6
|
||||
hexn0 jmp $ffd2
|
||||
|
||||
print pla
|
||||
.block
|
||||
sta print0+1
|
||||
pla
|
||||
sta print0+2
|
||||
ldx #1
|
||||
print0 lda !*,x
|
||||
beq print1
|
||||
jsr $ffd2
|
||||
inx
|
||||
bne print0
|
||||
print1 sec
|
||||
txa
|
||||
adc print0+1
|
||||
sta print2+1
|
||||
lda #0
|
||||
adc print0+2
|
||||
sta print2+2
|
||||
print2 jmp !*
|
||||
.bend
|
||||
|
||||
|
338
src/test/kotlin/6502testsuite/source/andz.asm
Normal file
338
src/test/kotlin/6502testsuite/source/andz.asm
Normal file
|
@ -0,0 +1,338 @@
|
|||
*= $0801
|
||||
|
||||
.byte $4c,$16,$08,$00,$97,$32
|
||||
.byte $2c,$30,$3a,$9e,$32,$30
|
||||
.byte $37,$30,$00,$00,$00,$a9
|
||||
.byte $01,$85,$02
|
||||
|
||||
jsr print
|
||||
.byte 13
|
||||
.text "(up)andz"
|
||||
.byte 0
|
||||
|
||||
lda #%00011011
|
||||
sta db
|
||||
lda #%11000110
|
||||
sta ab
|
||||
lda #%10110001
|
||||
sta xb
|
||||
lda #%01101100
|
||||
sta yb
|
||||
lda #0
|
||||
sta pb
|
||||
tsx
|
||||
stx sb
|
||||
|
||||
lda #0
|
||||
sta db
|
||||
sta ab
|
||||
|
||||
next lda db
|
||||
sta 172
|
||||
sta dr
|
||||
eor #$ff
|
||||
sta cmdr+1
|
||||
|
||||
lda ab
|
||||
eor #$ff
|
||||
cmdr ora #0
|
||||
eor #$ff
|
||||
sta ar
|
||||
|
||||
lda xb
|
||||
sta xr
|
||||
|
||||
lda yb
|
||||
sta yr
|
||||
|
||||
lda pb
|
||||
ora #%00110000
|
||||
and #%01111101
|
||||
tax
|
||||
lda ar
|
||||
cmp #0
|
||||
bne nozero
|
||||
txa
|
||||
ora #%00000010
|
||||
tax
|
||||
nozero lda ar
|
||||
bpl noneg
|
||||
txa
|
||||
ora #%10000000
|
||||
tax
|
||||
noneg stx pr
|
||||
|
||||
lda sb
|
||||
sta sr
|
||||
|
||||
ldx sb
|
||||
txs
|
||||
lda pb
|
||||
pha
|
||||
lda ab
|
||||
ldx xb
|
||||
ldy yb
|
||||
plp
|
||||
|
||||
cmd and 172
|
||||
|
||||
php
|
||||
cld
|
||||
sta aa
|
||||
stx xa
|
||||
sty ya
|
||||
pla
|
||||
sta pa
|
||||
tsx
|
||||
stx sa
|
||||
lda 172
|
||||
sta da
|
||||
jsr check
|
||||
|
||||
clc
|
||||
lda db
|
||||
adc #17
|
||||
sta db
|
||||
bcc jmpnext
|
||||
lda #0
|
||||
sta db
|
||||
clc
|
||||
lda ab
|
||||
adc #17
|
||||
sta ab
|
||||
bcc jmpnext
|
||||
lda #0
|
||||
sta ab
|
||||
inc pb
|
||||
beq nonext
|
||||
jmpnext jmp next
|
||||
nonext
|
||||
|
||||
jsr print
|
||||
.text " - ok"
|
||||
.byte 13,0
|
||||
lda 2
|
||||
beq load
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
jmp $8000
|
||||
|
||||
load jsr print
|
||||
name .text "andzx"
|
||||
namelen = *-name
|
||||
.byte 0
|
||||
lda #0
|
||||
sta $0a
|
||||
sta $b9
|
||||
lda #namelen
|
||||
sta $b7
|
||||
lda #<name
|
||||
sta $bb
|
||||
lda #>name
|
||||
sta $bc
|
||||
pla
|
||||
pla
|
||||
jmp $e16f
|
||||
|
||||
db .byte 0
|
||||
ab .byte 0
|
||||
xb .byte 0
|
||||
yb .byte 0
|
||||
pb .byte 0
|
||||
sb .byte 0
|
||||
da .byte 0
|
||||
aa .byte 0
|
||||
xa .byte 0
|
||||
ya .byte 0
|
||||
pa .byte 0
|
||||
sa .byte 0
|
||||
dr .byte 0
|
||||
ar .byte 0
|
||||
xr .byte 0
|
||||
yr .byte 0
|
||||
pr .byte 0
|
||||
sr .byte 0
|
||||
|
||||
check
|
||||
.block
|
||||
lda da
|
||||
cmp dr
|
||||
bne error
|
||||
lda aa
|
||||
cmp ar
|
||||
bne error
|
||||
lda xa
|
||||
cmp xr
|
||||
bne error
|
||||
lda ya
|
||||
cmp yr
|
||||
bne error
|
||||
lda pa
|
||||
cmp pr
|
||||
bne error
|
||||
lda sa
|
||||
cmp sr
|
||||
bne error
|
||||
rts
|
||||
|
||||
error jsr print
|
||||
.byte 13
|
||||
.null "before "
|
||||
ldx #<db
|
||||
ldy #>db
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "after "
|
||||
ldx #<da
|
||||
ldy #>da
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "right "
|
||||
ldx #<dr
|
||||
ldy #>dr
|
||||
jsr showregs
|
||||
lda #13
|
||||
jsr $ffd2
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
cmp #3
|
||||
beq stop
|
||||
rts
|
||||
stop lda 2
|
||||
beq basic
|
||||
jmp $8000
|
||||
basic jmp ($a002)
|
||||
|
||||
showregs stx 172
|
||||
sty 173
|
||||
ldy #0
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
ldx #"n"
|
||||
asl a
|
||||
bcc ok7
|
||||
ldx #"N"
|
||||
ok7 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"v"
|
||||
asl a
|
||||
bcc ok6
|
||||
ldx #"V"
|
||||
ok6 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"0"
|
||||
asl a
|
||||
bcc ok5
|
||||
ldx #"1"
|
||||
ok5 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"b"
|
||||
asl a
|
||||
bcc ok4
|
||||
ldx #"B"
|
||||
ok4 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"d"
|
||||
asl a
|
||||
bcc ok3
|
||||
ldx #"D"
|
||||
ok3 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"i"
|
||||
asl a
|
||||
bcc ok2
|
||||
ldx #"I"
|
||||
ok2 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"z"
|
||||
asl a
|
||||
bcc ok1
|
||||
ldx #"Z"
|
||||
ok1 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"c"
|
||||
asl a
|
||||
bcc ok0
|
||||
ldx #"C"
|
||||
ok0 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
.bend
|
||||
hexb pha
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
jsr hexn
|
||||
pla
|
||||
and #$0f
|
||||
hexn ora #$30
|
||||
cmp #$3a
|
||||
bcc hexn0
|
||||
adc #6
|
||||
hexn0 jmp $ffd2
|
||||
|
||||
print pla
|
||||
.block
|
||||
sta print0+1
|
||||
pla
|
||||
sta print0+2
|
||||
ldx #1
|
||||
print0 lda !*,x
|
||||
beq print1
|
||||
jsr $ffd2
|
||||
inx
|
||||
bne print0
|
||||
print1 sec
|
||||
txa
|
||||
adc print0+1
|
||||
sta print2+1
|
||||
lda #0
|
||||
adc print0+2
|
||||
sta print2+2
|
||||
print2 jmp !*
|
||||
.bend
|
||||
|
||||
|
342
src/test/kotlin/6502testsuite/source/andzx.asm
Normal file
342
src/test/kotlin/6502testsuite/source/andzx.asm
Normal file
|
@ -0,0 +1,342 @@
|
|||
*= $0801
|
||||
|
||||
.byte $4c,$16,$08,$00,$97,$32
|
||||
.byte $2c,$30,$3a,$9e,$32,$30
|
||||
.byte $37,$30,$00,$00,$00,$a9
|
||||
.byte $01,$85,$02
|
||||
|
||||
jsr print
|
||||
.byte 13
|
||||
.text "(up)andzx"
|
||||
.byte 0
|
||||
|
||||
lda #%00011011
|
||||
sta db
|
||||
lda #%11000110
|
||||
sta ab
|
||||
lda #%10110001
|
||||
sta xb
|
||||
lda #%01101100
|
||||
sta yb
|
||||
lda #0
|
||||
sta pb
|
||||
tsx
|
||||
stx sb
|
||||
|
||||
lda #0
|
||||
sta db
|
||||
sta ab
|
||||
sta xb
|
||||
|
||||
next lda db
|
||||
sta 172
|
||||
sta dr
|
||||
eor #$ff
|
||||
sta cmdr+1
|
||||
|
||||
lda ab
|
||||
eor #$ff
|
||||
cmdr ora #0
|
||||
eor #$ff
|
||||
sta ar
|
||||
|
||||
lda xb
|
||||
sta xr
|
||||
|
||||
lda yb
|
||||
sta yr
|
||||
|
||||
lda pb
|
||||
ora #%00110000
|
||||
and #%01111101
|
||||
tax
|
||||
lda ar
|
||||
cmp #0
|
||||
bne nozero
|
||||
txa
|
||||
ora #%00000010
|
||||
tax
|
||||
nozero lda ar
|
||||
bpl noneg
|
||||
txa
|
||||
ora #%10000000
|
||||
tax
|
||||
noneg stx pr
|
||||
|
||||
lda sb
|
||||
sta sr
|
||||
|
||||
ldx sb
|
||||
txs
|
||||
lda pb
|
||||
pha
|
||||
lda ab
|
||||
ldx xb
|
||||
ldy yb
|
||||
plp
|
||||
|
||||
cmd and 172,x
|
||||
|
||||
php
|
||||
cld
|
||||
sta aa
|
||||
stx xa
|
||||
sty ya
|
||||
pla
|
||||
sta pa
|
||||
tsx
|
||||
stx sa
|
||||
lda 172
|
||||
sta da
|
||||
jsr check
|
||||
|
||||
inc cmd+1
|
||||
dec xb
|
||||
|
||||
clc
|
||||
lda db
|
||||
adc #17
|
||||
sta db
|
||||
bcc jmpnext
|
||||
lda #0
|
||||
sta db
|
||||
clc
|
||||
lda ab
|
||||
adc #17
|
||||
sta ab
|
||||
bcc jmpnext
|
||||
lda #0
|
||||
sta ab
|
||||
inc pb
|
||||
beq nonext
|
||||
jmpnext jmp next
|
||||
nonext
|
||||
|
||||
jsr print
|
||||
.text " - ok"
|
||||
.byte 13,0
|
||||
lda 2
|
||||
beq load
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
jmp $8000
|
||||
|
||||
load jsr print
|
||||
name .text "anda"
|
||||
namelen = *-name
|
||||
.byte 0
|
||||
lda #0
|
||||
sta $0a
|
||||
sta $b9
|
||||
lda #namelen
|
||||
sta $b7
|
||||
lda #<name
|
||||
sta $bb
|
||||
lda #>name
|
||||
sta $bc
|
||||
pla
|
||||
pla
|
||||
jmp $e16f
|
||||
|
||||
db .byte 0
|
||||
ab .byte 0
|
||||
xb .byte 0
|
||||
yb .byte 0
|
||||
pb .byte 0
|
||||
sb .byte 0
|
||||
da .byte 0
|
||||
aa .byte 0
|
||||
xa .byte 0
|
||||
ya .byte 0
|
||||
pa .byte 0
|
||||
sa .byte 0
|
||||
dr .byte 0
|
||||
ar .byte 0
|
||||
xr .byte 0
|
||||
yr .byte 0
|
||||
pr .byte 0
|
||||
sr .byte 0
|
||||
|
||||
check
|
||||
.block
|
||||
lda da
|
||||
cmp dr
|
||||
bne error
|
||||
lda aa
|
||||
cmp ar
|
||||
bne error
|
||||
lda xa
|
||||
cmp xr
|
||||
bne error
|
||||
lda ya
|
||||
cmp yr
|
||||
bne error
|
||||
lda pa
|
||||
cmp pr
|
||||
bne error
|
||||
lda sa
|
||||
cmp sr
|
||||
bne error
|
||||
rts
|
||||
|
||||
error jsr print
|
||||
.byte 13
|
||||
.null "before "
|
||||
ldx #<db
|
||||
ldy #>db
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "after "
|
||||
ldx #<da
|
||||
ldy #>da
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "right "
|
||||
ldx #<dr
|
||||
ldy #>dr
|
||||
jsr showregs
|
||||
lda #13
|
||||
jsr $ffd2
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
cmp #3
|
||||
beq stop
|
||||
rts
|
||||
stop lda 2
|
||||
beq basic
|
||||
jmp $8000
|
||||
basic jmp ($a002)
|
||||
|
||||
showregs stx 172
|
||||
sty 173
|
||||
ldy #0
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
ldx #"n"
|
||||
asl a
|
||||
bcc ok7
|
||||
ldx #"N"
|
||||
ok7 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"v"
|
||||
asl a
|
||||
bcc ok6
|
||||
ldx #"V"
|
||||
ok6 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"0"
|
||||
asl a
|
||||
bcc ok5
|
||||
ldx #"1"
|
||||
ok5 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"b"
|
||||
asl a
|
||||
bcc ok4
|
||||
ldx #"B"
|
||||
ok4 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"d"
|
||||
asl a
|
||||
bcc ok3
|
||||
ldx #"D"
|
||||
ok3 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"i"
|
||||
asl a
|
||||
bcc ok2
|
||||
ldx #"I"
|
||||
ok2 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"z"
|
||||
asl a
|
||||
bcc ok1
|
||||
ldx #"Z"
|
||||
ok1 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"c"
|
||||
asl a
|
||||
bcc ok0
|
||||
ldx #"C"
|
||||
ok0 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
.bend
|
||||
hexb pha
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
jsr hexn
|
||||
pla
|
||||
and #$0f
|
||||
hexn ora #$30
|
||||
cmp #$3a
|
||||
bcc hexn0
|
||||
adc #6
|
||||
hexn0 jmp $ffd2
|
||||
|
||||
print pla
|
||||
.block
|
||||
sta print0+1
|
||||
pla
|
||||
sta print0+2
|
||||
ldx #1
|
||||
print0 lda !*,x
|
||||
beq print1
|
||||
jsr $ffd2
|
||||
inx
|
||||
bne print0
|
||||
print1 sec
|
||||
txa
|
||||
adc print0+1
|
||||
sta print2+1
|
||||
lda #0
|
||||
adc print0+2
|
||||
sta print2+2
|
||||
print2 jmp !*
|
||||
.bend
|
||||
|
||||
|
341
src/test/kotlin/6502testsuite/source/aneb.asm
Normal file
341
src/test/kotlin/6502testsuite/source/aneb.asm
Normal file
|
@ -0,0 +1,341 @@
|
|||
*= $0801
|
||||
|
||||
.byte $4c,$16,$08,$00,$97,$32
|
||||
.byte $2c,$30,$3a,$9e,$32,$30
|
||||
.byte $37,$30,$00,$00,$00,$a9
|
||||
.byte $01,$85,$02
|
||||
|
||||
jsr print
|
||||
.byte 13
|
||||
.text "(up)aneb"
|
||||
.byte 0
|
||||
|
||||
lda #%00011011
|
||||
sta db
|
||||
lda #%11000110
|
||||
sta ab
|
||||
lda #%10110001
|
||||
sta xb
|
||||
lda #%01101100
|
||||
sta yb
|
||||
lda #0
|
||||
sta pb
|
||||
tsx
|
||||
stx sb
|
||||
|
||||
lda #0
|
||||
sta db
|
||||
sta xb
|
||||
|
||||
next lda db
|
||||
sta da
|
||||
sta dr
|
||||
sta cmd+1
|
||||
|
||||
lda ab
|
||||
ora #$ee
|
||||
and xb
|
||||
and db
|
||||
sta ar
|
||||
|
||||
lda xb
|
||||
sta xr
|
||||
|
||||
lda yb
|
||||
sta yr
|
||||
|
||||
lda pb
|
||||
ora #%00110000
|
||||
and #%01111101
|
||||
ldx ar
|
||||
bne nozero
|
||||
ora #%00000010
|
||||
nozero
|
||||
ldx ar
|
||||
bpl nominus
|
||||
ora #%10000000
|
||||
nominus
|
||||
sta pr
|
||||
|
||||
lda sb
|
||||
sta sr
|
||||
|
||||
waitborder
|
||||
lda $d011
|
||||
bmi border
|
||||
lda $d012
|
||||
cmp #40
|
||||
bcs waitborder
|
||||
border
|
||||
|
||||
ldx sb
|
||||
txs
|
||||
lda pb
|
||||
pha
|
||||
lda ab
|
||||
ldx xb
|
||||
ldy yb
|
||||
plp
|
||||
|
||||
cmd .byte $8b
|
||||
.byte 0
|
||||
|
||||
php
|
||||
cld
|
||||
sta aa
|
||||
stx xa
|
||||
sty ya
|
||||
pla
|
||||
sta pa
|
||||
tsx
|
||||
stx sa
|
||||
jsr check
|
||||
|
||||
inc ab
|
||||
clc
|
||||
lda db
|
||||
adc #17
|
||||
sta db
|
||||
bcc jmpnext
|
||||
lda #0
|
||||
sta db
|
||||
clc
|
||||
lda xb
|
||||
adc #17
|
||||
sta xb
|
||||
bcc jmpnext
|
||||
lda #0
|
||||
sta xb
|
||||
inc pb
|
||||
beq nonext
|
||||
jmpnext jmp next
|
||||
nonext
|
||||
|
||||
jsr print
|
||||
.text " - ok"
|
||||
.byte 13,0
|
||||
lda 2
|
||||
beq load
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
jmp $8000
|
||||
|
||||
load jsr print
|
||||
name .text "lxab"
|
||||
namelen = *-name
|
||||
.byte 0
|
||||
lda #0
|
||||
sta $0a
|
||||
sta $b9
|
||||
lda #namelen
|
||||
sta $b7
|
||||
lda #<name
|
||||
sta $bb
|
||||
lda #>name
|
||||
sta $bc
|
||||
pla
|
||||
pla
|
||||
jmp $e16f
|
||||
|
||||
db .byte 0
|
||||
ab .byte 0
|
||||
xb .byte 0
|
||||
yb .byte 0
|
||||
pb .byte 0
|
||||
sb .byte 0
|
||||
da .byte 0
|
||||
aa .byte 0
|
||||
xa .byte 0
|
||||
ya .byte 0
|
||||
pa .byte 0
|
||||
sa .byte 0
|
||||
dr .byte 0
|
||||
ar .byte 0
|
||||
xr .byte 0
|
||||
yr .byte 0
|
||||
pr .byte 0
|
||||
sr .byte 0
|
||||
|
||||
check
|
||||
.block
|
||||
lda da
|
||||
cmp dr
|
||||
bne error
|
||||
lda aa
|
||||
cmp ar
|
||||
bne error
|
||||
lda xa
|
||||
cmp xr
|
||||
bne error
|
||||
lda ya
|
||||
cmp yr
|
||||
bne error
|
||||
lda pa
|
||||
cmp pr
|
||||
bne error
|
||||
lda sa
|
||||
cmp sr
|
||||
bne error
|
||||
rts
|
||||
|
||||
error jsr print
|
||||
.byte 13
|
||||
.null "before "
|
||||
ldx #<db
|
||||
ldy #>db
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "after "
|
||||
ldx #<da
|
||||
ldy #>da
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "right "
|
||||
ldx #<dr
|
||||
ldy #>dr
|
||||
jsr showregs
|
||||
lda #13
|
||||
jsr $ffd2
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
cmp #3
|
||||
beq stop
|
||||
rts
|
||||
stop lda 2
|
||||
beq basic
|
||||
jmp $8000
|
||||
basic jmp ($a002)
|
||||
|
||||
showregs stx 172
|
||||
sty 173
|
||||
ldy #0
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
ldx #"n"
|
||||
asl a
|
||||
bcc ok7
|
||||
ldx #"N"
|
||||
ok7 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"v"
|
||||
asl a
|
||||
bcc ok6
|
||||
ldx #"V"
|
||||
ok6 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"0"
|
||||
asl a
|
||||
bcc ok5
|
||||
ldx #"1"
|
||||
ok5 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"b"
|
||||
asl a
|
||||
bcc ok4
|
||||
ldx #"B"
|
||||
ok4 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"d"
|
||||
asl a
|
||||
bcc ok3
|
||||
ldx #"D"
|
||||
ok3 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"i"
|
||||
asl a
|
||||
bcc ok2
|
||||
ldx #"I"
|
||||
ok2 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"z"
|
||||
asl a
|
||||
bcc ok1
|
||||
ldx #"Z"
|
||||
ok1 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"c"
|
||||
asl a
|
||||
bcc ok0
|
||||
ldx #"C"
|
||||
ok0 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
.bend
|
||||
hexb pha
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
jsr hexn
|
||||
pla
|
||||
and #$0f
|
||||
hexn ora #$30
|
||||
cmp #$3a
|
||||
bcc hexn0
|
||||
adc #6
|
||||
hexn0 jmp $ffd2
|
||||
|
||||
print pla
|
||||
.block
|
||||
sta print0+1
|
||||
pla
|
||||
sta print0+2
|
||||
ldx #1
|
||||
print0 lda !*,x
|
||||
beq print1
|
||||
jsr $ffd2
|
||||
inx
|
||||
bne print0
|
||||
print1 sec
|
||||
txa
|
||||
adc print0+1
|
||||
sta print2+1
|
||||
lda #0
|
||||
adc print0+2
|
||||
sta print2+2
|
||||
print2 jmp !*
|
||||
.bend
|
||||
|
||||
|
409
src/test/kotlin/6502testsuite/source/arrb.asm
Normal file
409
src/test/kotlin/6502testsuite/source/arrb.asm
Normal file
|
@ -0,0 +1,409 @@
|
|||
*= $0801
|
||||
|
||||
.byte $4c,$16,$08,$00,$97,$32
|
||||
.byte $2c,$30,$3a,$9e,$32,$30
|
||||
.byte $37,$30,$00,$00,$00,$a9
|
||||
.byte $01,$85,$02
|
||||
|
||||
jsr print
|
||||
.byte 13
|
||||
.text "(up)arrb"
|
||||
.byte 0
|
||||
|
||||
lda #%00011011
|
||||
sta db
|
||||
lda #%11000110
|
||||
sta ab
|
||||
lda #%10110001
|
||||
sta xb
|
||||
lda #%01101100
|
||||
sta yb
|
||||
lda #0
|
||||
sta pb
|
||||
tsx
|
||||
stx sb
|
||||
|
||||
lda #0
|
||||
sta db
|
||||
sta ab
|
||||
|
||||
next lda db
|
||||
sta da
|
||||
sta dr
|
||||
sta cmd+1
|
||||
|
||||
lda #%00001000
|
||||
bit pb
|
||||
bne decimal
|
||||
|
||||
lda pb
|
||||
lsr a
|
||||
lda ab
|
||||
and db
|
||||
ror a
|
||||
sta ar
|
||||
|
||||
lda pb
|
||||
ora #%00110000
|
||||
and #%00111100
|
||||
ldx ar
|
||||
bne nozero
|
||||
ora #%00000010
|
||||
nozero
|
||||
ldx ar
|
||||
bpl nominus
|
||||
ora #%10000000
|
||||
nominus
|
||||
tax
|
||||
lda ar
|
||||
and #%01000000
|
||||
beq nocarry
|
||||
inx
|
||||
nocarry
|
||||
lda ar
|
||||
and #%01100000
|
||||
beq noover
|
||||
cmp #%01100000
|
||||
beq noover
|
||||
txa
|
||||
ora #%01000000
|
||||
tax
|
||||
noover
|
||||
stx pr
|
||||
jmp nodecimal
|
||||
|
||||
decimal
|
||||
lda pb
|
||||
lsr a
|
||||
lda ab
|
||||
and db
|
||||
sta aa
|
||||
ror a
|
||||
sta ar
|
||||
|
||||
lda pb
|
||||
ora #%00110000
|
||||
and #%00111100
|
||||
ldx ar
|
||||
bne dnozero
|
||||
ora #%00000010
|
||||
dnozero
|
||||
ldx ar
|
||||
bpl dnominus
|
||||
ora #%10000000
|
||||
dnominus
|
||||
tax
|
||||
lda ar
|
||||
eor aa
|
||||
and #%01000000
|
||||
beq dnoover
|
||||
txa
|
||||
ora #%01000000
|
||||
tax
|
||||
dnoover
|
||||
lda aa
|
||||
and #$0f
|
||||
cmp #$05
|
||||
bcc noadjustlow
|
||||
lda ar
|
||||
and #$f0
|
||||
sta andlow+1
|
||||
lda ar
|
||||
clc
|
||||
adc #$06
|
||||
and #$0f
|
||||
andlow ora #$11
|
||||
sta ar
|
||||
noadjustlow
|
||||
lda aa
|
||||
and #$f0
|
||||
cmp #$50
|
||||
bcc noadjusthigh
|
||||
inx
|
||||
lda ar
|
||||
clc
|
||||
adc #$60
|
||||
sta ar
|
||||
noadjusthigh
|
||||
stx pr
|
||||
|
||||
nodecimal
|
||||
lda xb
|
||||
sta xr
|
||||
|
||||
lda yb
|
||||
sta yr
|
||||
|
||||
lda sb
|
||||
sta sr
|
||||
|
||||
ldx sb
|
||||
txs
|
||||
lda pb
|
||||
pha
|
||||
lda ab
|
||||
ldx xb
|
||||
ldy yb
|
||||
plp
|
||||
|
||||
cmd .byte $6b
|
||||
.byte 0
|
||||
|
||||
php
|
||||
cld
|
||||
sta aa
|
||||
stx xa
|
||||
sty ya
|
||||
pla
|
||||
sta pa
|
||||
tsx
|
||||
stx sa
|
||||
jsr check
|
||||
|
||||
clc
|
||||
lda db
|
||||
adc #17
|
||||
sta db
|
||||
bcc jmpnext
|
||||
lda #0
|
||||
sta db
|
||||
clc
|
||||
lda ab
|
||||
adc #17
|
||||
sta ab
|
||||
bcc jmpnext
|
||||
lda #0
|
||||
sta ab
|
||||
inc pb
|
||||
beq nonext
|
||||
jmpnext jmp next
|
||||
nonext
|
||||
|
||||
jsr print
|
||||
.text " - ok"
|
||||
.byte 13,0
|
||||
lda 2
|
||||
beq load
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
jmp $8000
|
||||
|
||||
load jsr print
|
||||
name .text "aneb"
|
||||
namelen = *-name
|
||||
.byte 0
|
||||
lda #0
|
||||
sta $0a
|
||||
sta $b9
|
||||
lda #namelen
|
||||
sta $b7
|
||||
lda #<name
|
||||
sta $bb
|
||||
lda #>name
|
||||
sta $bc
|
||||
pla
|
||||
pla
|
||||
jmp $e16f
|
||||
|
||||
db .byte 0
|
||||
ab .byte 0
|
||||
xb .byte 0
|
||||
yb .byte 0
|
||||
pb .byte 0
|
||||
sb .byte 0
|
||||
da .byte 0
|
||||
aa .byte 0
|
||||
xa .byte 0
|
||||
ya .byte 0
|
||||
pa .byte 0
|
||||
sa .byte 0
|
||||
dr .byte 0
|
||||
ar .byte 0
|
||||
xr .byte 0
|
||||
yr .byte 0
|
||||
pr .byte 0
|
||||
sr .byte 0
|
||||
|
||||
check
|
||||
.block
|
||||
lda da
|
||||
cmp dr
|
||||
bne error
|
||||
lda aa
|
||||
cmp ar
|
||||
bne error
|
||||
lda xa
|
||||
cmp xr
|
||||
bne error
|
||||
lda ya
|
||||
cmp yr
|
||||
bne error
|
||||
lda pa
|
||||
cmp pr
|
||||
bne error
|
||||
lda sa
|
||||
cmp sr
|
||||
bne error
|
||||
rts
|
||||
|
||||
error jsr print
|
||||
.byte 13
|
||||
.null "before "
|
||||
ldx #<db
|
||||
ldy #>db
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "after "
|
||||
ldx #<da
|
||||
ldy #>da
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "right "
|
||||
ldx #<dr
|
||||
ldy #>dr
|
||||
jsr showregs
|
||||
lda #13
|
||||
jsr $ffd2
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
cmp #3
|
||||
beq stop
|
||||
rts
|
||||
stop lda 2
|
||||
beq basic
|
||||
jmp $8000
|
||||
basic jmp ($a002)
|
||||
|
||||
showregs stx 172
|
||||
sty 173
|
||||
ldy #0
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
ldx #"n"
|
||||
asl a
|
||||
bcc ok7
|
||||
ldx #"N"
|
||||
ok7 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"v"
|
||||
asl a
|
||||
bcc ok6
|
||||
ldx #"V"
|
||||
ok6 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"0"
|
||||
asl a
|
||||
bcc ok5
|
||||
ldx #"1"
|
||||
ok5 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"b"
|
||||
asl a
|
||||
bcc ok4
|
||||
ldx #"B"
|
||||
ok4 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"d"
|
||||
asl a
|
||||
bcc ok3
|
||||
ldx #"D"
|
||||
ok3 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"i"
|
||||
asl a
|
||||
bcc ok2
|
||||
ldx #"I"
|
||||
ok2 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"z"
|
||||
asl a
|
||||
bcc ok1
|
||||
ldx #"Z"
|
||||
ok1 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"c"
|
||||
asl a
|
||||
bcc ok0
|
||||
ldx #"C"
|
||||
ok0 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
.bend
|
||||
hexb pha
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
jsr hexn
|
||||
pla
|
||||
and #$0f
|
||||
hexn ora #$30
|
||||
cmp #$3a
|
||||
bcc hexn0
|
||||
adc #6
|
||||
hexn0 jmp $ffd2
|
||||
|
||||
print pla
|
||||
.block
|
||||
sta print0+1
|
||||
pla
|
||||
sta print0+2
|
||||
ldx #1
|
||||
print0 lda !*,x
|
||||
beq print1
|
||||
jsr $ffd2
|
||||
inx
|
||||
bne print0
|
||||
print1 sec
|
||||
txa
|
||||
adc print0+1
|
||||
sta print2+1
|
||||
lda #0
|
||||
adc print0+2
|
||||
sta print2+2
|
||||
print2 jmp !*
|
||||
.bend
|
||||
|
||||
|
325
src/test/kotlin/6502testsuite/source/asla.asm
Normal file
325
src/test/kotlin/6502testsuite/source/asla.asm
Normal file
|
@ -0,0 +1,325 @@
|
|||
*= $0801
|
||||
|
||||
.byte $4c,$16,$08,$00,$97,$32
|
||||
.byte $2c,$30,$3a,$9e,$32,$30
|
||||
.byte $37,$30,$00,$00,$00,$a9
|
||||
.byte $01,$85,$02
|
||||
|
||||
jsr print
|
||||
.byte 13
|
||||
.text "(up)asla"
|
||||
.byte 0
|
||||
|
||||
lda #%00011011
|
||||
sta db
|
||||
lda #%11000110
|
||||
sta ab
|
||||
lda #%10110001
|
||||
sta xb
|
||||
lda #%01101100
|
||||
sta yb
|
||||
lda #0
|
||||
sta pb
|
||||
tsx
|
||||
stx sb
|
||||
|
||||
lda #0
|
||||
sta db
|
||||
|
||||
next lda db
|
||||
sta da
|
||||
sta dr
|
||||
asl dr
|
||||
|
||||
lda ab
|
||||
sta ar
|
||||
|
||||
lda xb
|
||||
sta xr
|
||||
|
||||
lda yb
|
||||
sta yr
|
||||
|
||||
lda pb
|
||||
ora #%00110000
|
||||
and #%01111100
|
||||
tax
|
||||
lda dr
|
||||
cmp #0
|
||||
bne nozero
|
||||
txa
|
||||
ora #%00000010
|
||||
tax
|
||||
lda dr
|
||||
nozero asl a
|
||||
bcc noneg
|
||||
txa
|
||||
ora #%10000000
|
||||
tax
|
||||
noneg lda db
|
||||
bpl nocarry
|
||||
txa
|
||||
ora #%00000001
|
||||
tax
|
||||
nocarry stx pr
|
||||
|
||||
lda sb
|
||||
sta sr
|
||||
|
||||
ldx sb
|
||||
txs
|
||||
lda pb
|
||||
pha
|
||||
lda ab
|
||||
ldx xb
|
||||
ldy yb
|
||||
plp
|
||||
|
||||
cmd asl da
|
||||
|
||||
php
|
||||
cld
|
||||
sta aa
|
||||
stx xa
|
||||
sty ya
|
||||
pla
|
||||
sta pa
|
||||
tsx
|
||||
stx sa
|
||||
jsr check
|
||||
|
||||
inc db
|
||||
bne jmpnext
|
||||
inc pb
|
||||
beq nonext
|
||||
jmpnext jmp next
|
||||
nonext
|
||||
|
||||
jsr print
|
||||
.text " - ok"
|
||||
.byte 13,0
|
||||
lda 2
|
||||
beq load
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
jmp $8000
|
||||
|
||||
load jsr print
|
||||
name .text "aslax"
|
||||
namelen = *-name
|
||||
.byte 0
|
||||
lda #0
|
||||
sta $0a
|
||||
sta $b9
|
||||
lda #namelen
|
||||
sta $b7
|
||||
lda #<name
|
||||
sta $bb
|
||||
lda #>name
|
||||
sta $bc
|
||||
pla
|
||||
pla
|
||||
jmp $e16f
|
||||
|
||||
db .byte 0
|
||||
ab .byte 0
|
||||
xb .byte 0
|
||||
yb .byte 0
|
||||
pb .byte 0
|
||||
sb .byte 0
|
||||
da .byte 0
|
||||
aa .byte 0
|
||||
xa .byte 0
|
||||
ya .byte 0
|
||||
pa .byte 0
|
||||
sa .byte 0
|
||||
dr .byte 0
|
||||
ar .byte 0
|
||||
xr .byte 0
|
||||
yr .byte 0
|
||||
pr .byte 0
|
||||
sr .byte 0
|
||||
|
||||
check
|
||||
.block
|
||||
lda da
|
||||
cmp dr
|
||||
bne error
|
||||
lda aa
|
||||
cmp ar
|
||||
bne error
|
||||
lda xa
|
||||
cmp xr
|
||||
bne error
|
||||
lda ya
|
||||
cmp yr
|
||||
bne error
|
||||
lda pa
|
||||
cmp pr
|
||||
bne error
|
||||
lda sa
|
||||
cmp sr
|
||||
bne error
|
||||
rts
|
||||
|
||||
error jsr print
|
||||
.byte 13
|
||||
.null "before "
|
||||
ldx #<db
|
||||
ldy #>db
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "after "
|
||||
ldx #<da
|
||||
ldy #>da
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "right "
|
||||
ldx #<dr
|
||||
ldy #>dr
|
||||
jsr showregs
|
||||
lda #13
|
||||
jsr $ffd2
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
cmp #3
|
||||
beq stop
|
||||
rts
|
||||
stop lda 2
|
||||
beq basic
|
||||
jmp $8000
|
||||
basic jmp ($a002)
|
||||
|
||||
showregs stx 172
|
||||
sty 173
|
||||
ldy #0
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
ldx #"n"
|
||||
asl a
|
||||
bcc ok7
|
||||
ldx #"N"
|
||||
ok7 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"v"
|
||||
asl a
|
||||
bcc ok6
|
||||
ldx #"V"
|
||||
ok6 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"0"
|
||||
asl a
|
||||
bcc ok5
|
||||
ldx #"1"
|
||||
ok5 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"b"
|
||||
asl a
|
||||
bcc ok4
|
||||
ldx #"B"
|
||||
ok4 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"d"
|
||||
asl a
|
||||
bcc ok3
|
||||
ldx #"D"
|
||||
ok3 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"i"
|
||||
asl a
|
||||
bcc ok2
|
||||
ldx #"I"
|
||||
ok2 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"z"
|
||||
asl a
|
||||
bcc ok1
|
||||
ldx #"Z"
|
||||
ok1 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"c"
|
||||
asl a
|
||||
bcc ok0
|
||||
ldx #"C"
|
||||
ok0 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
.bend
|
||||
hexb pha
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
jsr hexn
|
||||
pla
|
||||
and #$0f
|
||||
hexn ora #$30
|
||||
cmp #$3a
|
||||
bcc hexn0
|
||||
adc #6
|
||||
hexn0 jmp $ffd2
|
||||
|
||||
print pla
|
||||
.block
|
||||
sta print0+1
|
||||
pla
|
||||
sta print0+2
|
||||
ldx #1
|
||||
print0 lda !*,x
|
||||
beq print1
|
||||
jsr $ffd2
|
||||
inx
|
||||
bne print0
|
||||
print1 sec
|
||||
txa
|
||||
adc print0+1
|
||||
sta print2+1
|
||||
lda #0
|
||||
adc print0+2
|
||||
sta print2+2
|
||||
print2 jmp !*
|
||||
.bend
|
||||
|
||||
|
334
src/test/kotlin/6502testsuite/source/aslax.asm
Normal file
334
src/test/kotlin/6502testsuite/source/aslax.asm
Normal file
|
@ -0,0 +1,334 @@
|
|||
*= $0801
|
||||
|
||||
.byte $4c,$16,$08,$00,$97,$32
|
||||
.byte $2c,$30,$3a,$9e,$32,$30
|
||||
.byte $37,$30,$00,$00,$00,$a9
|
||||
.byte $01,$85,$02
|
||||
|
||||
jsr print
|
||||
.byte 13
|
||||
.text "(up)aslax"
|
||||
.byte 0
|
||||
|
||||
lda #%00011011
|
||||
sta db
|
||||
lda #%11000110
|
||||
sta ab
|
||||
lda #%10110001
|
||||
sta xb
|
||||
lda #%01101100
|
||||
sta yb
|
||||
lda #0
|
||||
sta pb
|
||||
tsx
|
||||
stx sb
|
||||
|
||||
lda #0
|
||||
sta db
|
||||
sta xb
|
||||
|
||||
next lda db
|
||||
sta da
|
||||
sta dr
|
||||
asl dr
|
||||
|
||||
lda ab
|
||||
sta ar
|
||||
|
||||
lda xb
|
||||
sta xr
|
||||
|
||||
lda yb
|
||||
sta yr
|
||||
|
||||
lda pb
|
||||
ora #%00110000
|
||||
and #%01111100
|
||||
tax
|
||||
lda dr
|
||||
cmp #0
|
||||
bne nozero
|
||||
txa
|
||||
ora #%00000010
|
||||
tax
|
||||
lda dr
|
||||
nozero asl a
|
||||
bcc noneg
|
||||
txa
|
||||
ora #%10000000
|
||||
tax
|
||||
noneg lda db
|
||||
bpl nocarry
|
||||
txa
|
||||
ora #%00000001
|
||||
tax
|
||||
nocarry stx pr
|
||||
|
||||
lda sb
|
||||
sta sr
|
||||
|
||||
ldx sb
|
||||
txs
|
||||
lda pb
|
||||
pha
|
||||
lda ab
|
||||
ldx xb
|
||||
ldy yb
|
||||
plp
|
||||
|
||||
cmd asl da,x
|
||||
|
||||
php
|
||||
cld
|
||||
sta aa
|
||||
stx xa
|
||||
sty ya
|
||||
pla
|
||||
sta pa
|
||||
tsx
|
||||
stx sa
|
||||
jsr check
|
||||
|
||||
inc cmd+1
|
||||
bne noinc
|
||||
inc cmd+2
|
||||
noinc lda xb
|
||||
bne nodec
|
||||
dec cmd+2
|
||||
nodec dec xb
|
||||
|
||||
inc db
|
||||
bne jmpnext
|
||||
inc pb
|
||||
beq nonext
|
||||
jmpnext jmp next
|
||||
nonext
|
||||
|
||||
jsr print
|
||||
.text " - ok"
|
||||
.byte 13,0
|
||||
lda 2
|
||||
beq load
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
jmp $8000
|
||||
|
||||
load jsr print
|
||||
name .text "lsrn"
|
||||
namelen = *-name
|
||||
.byte 0
|
||||
lda #0
|
||||
sta $0a
|
||||
sta $b9
|
||||
lda #namelen
|
||||
sta $b7
|
||||
lda #<name
|
||||
sta $bb
|
||||
lda #>name
|
||||
sta $bc
|
||||
pla
|
||||
pla
|
||||
jmp $e16f
|
||||
|
||||
db .byte 0
|
||||
ab .byte 0
|
||||
xb .byte 0
|
||||
yb .byte 0
|
||||
pb .byte 0
|
||||
sb .byte 0
|
||||
da .byte 0
|
||||
aa .byte 0
|
||||
xa .byte 0
|
||||
ya .byte 0
|
||||
pa .byte 0
|
||||
sa .byte 0
|
||||
dr .byte 0
|
||||
ar .byte 0
|
||||
xr .byte 0
|
||||
yr .byte 0
|
||||
pr .byte 0
|
||||
sr .byte 0
|
||||
|
||||
check
|
||||
.block
|
||||
lda da
|
||||
cmp dr
|
||||
bne error
|
||||
lda aa
|
||||
cmp ar
|
||||
bne error
|
||||
lda xa
|
||||
cmp xr
|
||||
bne error
|
||||
lda ya
|
||||
cmp yr
|
||||
bne error
|
||||
lda pa
|
||||
cmp pr
|
||||
bne error
|
||||
lda sa
|
||||
cmp sr
|
||||
bne error
|
||||
rts
|
||||
|
||||
error jsr print
|
||||
.byte 13
|
||||
.null "before "
|
||||
ldx #<db
|
||||
ldy #>db
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "after "
|
||||
ldx #<da
|
||||
ldy #>da
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "right "
|
||||
ldx #<dr
|
||||
ldy #>dr
|
||||
jsr showregs
|
||||
lda #13
|
||||
jsr $ffd2
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
cmp #3
|
||||
beq stop
|
||||
rts
|
||||
stop lda 2
|
||||
beq basic
|
||||
jmp $8000
|
||||
basic jmp ($a002)
|
||||
|
||||
showregs stx 172
|
||||
sty 173
|
||||
ldy #0
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
ldx #"n"
|
||||
asl a
|
||||
bcc ok7
|
||||
ldx #"N"
|
||||
ok7 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"v"
|
||||
asl a
|
||||
bcc ok6
|
||||
ldx #"V"
|
||||
ok6 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"0"
|
||||
asl a
|
||||
bcc ok5
|
||||
ldx #"1"
|
||||
ok5 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"b"
|
||||
asl a
|
||||
bcc ok4
|
||||
ldx #"B"
|
||||
ok4 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"d"
|
||||
asl a
|
||||
bcc ok3
|
||||
ldx #"D"
|
||||
ok3 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"i"
|
||||
asl a
|
||||
bcc ok2
|
||||
ldx #"I"
|
||||
ok2 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"z"
|
||||
asl a
|
||||
bcc ok1
|
||||
ldx #"Z"
|
||||
ok1 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"c"
|
||||
asl a
|
||||
bcc ok0
|
||||
ldx #"C"
|
||||
ok0 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
.bend
|
||||
hexb pha
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
jsr hexn
|
||||
pla
|
||||
and #$0f
|
||||
hexn ora #$30
|
||||
cmp #$3a
|
||||
bcc hexn0
|
||||
adc #6
|
||||
hexn0 jmp $ffd2
|
||||
|
||||
print pla
|
||||
.block
|
||||
sta print0+1
|
||||
pla
|
||||
sta print0+2
|
||||
ldx #1
|
||||
print0 lda !*,x
|
||||
beq print1
|
||||
jsr $ffd2
|
||||
inx
|
||||
bne print0
|
||||
print1 sec
|
||||
txa
|
||||
adc print0+1
|
||||
sta print2+1
|
||||
lda #0
|
||||
adc print0+2
|
||||
sta print2+2
|
||||
print2 jmp !*
|
||||
.bend
|
||||
|
||||
|
326
src/test/kotlin/6502testsuite/source/asln.asm
Normal file
326
src/test/kotlin/6502testsuite/source/asln.asm
Normal file
|
@ -0,0 +1,326 @@
|
|||
*= $0801
|
||||
|
||||
.byte $4c,$16,$08,$00,$97,$32
|
||||
.byte $2c,$30,$3a,$9e,$32,$30
|
||||
.byte $37,$30,$00,$00,$00,$a9
|
||||
.byte $01,$85,$02
|
||||
|
||||
jsr print
|
||||
.byte 13
|
||||
.text "(up)asln"
|
||||
.byte 0
|
||||
|
||||
lda #%00011011
|
||||
sta db
|
||||
lda #%11000110
|
||||
sta ab
|
||||
lda #%10110001
|
||||
sta xb
|
||||
lda #%01101100
|
||||
sta yb
|
||||
lda #0
|
||||
sta pb
|
||||
tsx
|
||||
stx sb
|
||||
|
||||
lda #0
|
||||
sta ab
|
||||
|
||||
next lda db
|
||||
sta da
|
||||
sta dr
|
||||
|
||||
lda ab
|
||||
sta aa
|
||||
sta ar
|
||||
asl ar
|
||||
|
||||
lda xb
|
||||
sta xr
|
||||
|
||||
lda yb
|
||||
sta yr
|
||||
|
||||
lda pb
|
||||
ora #%00110000
|
||||
and #%01111100
|
||||
tax
|
||||
lda ar
|
||||
cmp #0
|
||||
bne nozero
|
||||
txa
|
||||
ora #%00000010
|
||||
tax
|
||||
lda ar
|
||||
nozero asl a
|
||||
bcc noneg
|
||||
txa
|
||||
ora #%10000000
|
||||
tax
|
||||
noneg lda ab
|
||||
bpl nocarry
|
||||
txa
|
||||
ora #%00000001
|
||||
tax
|
||||
nocarry stx pr
|
||||
|
||||
lda sb
|
||||
sta sr
|
||||
|
||||
ldx sb
|
||||
txs
|
||||
lda pb
|
||||
pha
|
||||
lda ab
|
||||
ldx xb
|
||||
ldy yb
|
||||
plp
|
||||
|
||||
cmd asl a
|
||||
|
||||
php
|
||||
cld
|
||||
sta aa
|
||||
stx xa
|
||||
sty ya
|
||||
pla
|
||||
sta pa
|
||||
tsx
|
||||
stx sa
|
||||
jsr check
|
||||
|
||||
inc ab
|
||||
bne jmpnext
|
||||
inc pb
|
||||
beq nonext
|
||||
jmpnext jmp next
|
||||
nonext
|
||||
|
||||
jsr print
|
||||
.text " - ok"
|
||||
.byte 13,0
|
||||
lda 2
|
||||
beq load
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
jmp $8000
|
||||
|
||||
load jsr print
|
||||
name .text "aslz"
|
||||
namelen = *-name
|
||||
.byte 0
|
||||
lda #0
|
||||
sta $0a
|
||||
sta $b9
|
||||
lda #namelen
|
||||
sta $b7
|
||||
lda #<name
|
||||
sta $bb
|
||||
lda #>name
|
||||
sta $bc
|
||||
pla
|
||||
pla
|
||||
jmp $e16f
|
||||
|
||||
db .byte 0
|
||||
ab .byte 0
|
||||
xb .byte 0
|
||||
yb .byte 0
|
||||
pb .byte 0
|
||||
sb .byte 0
|
||||
da .byte 0
|
||||
aa .byte 0
|
||||
xa .byte 0
|
||||
ya .byte 0
|
||||
pa .byte 0
|
||||
sa .byte 0
|
||||
dr .byte 0
|
||||
ar .byte 0
|
||||
xr .byte 0
|
||||
yr .byte 0
|
||||
pr .byte 0
|
||||
sr .byte 0
|
||||
|
||||
check
|
||||
.block
|
||||
lda da
|
||||
cmp dr
|
||||
bne error
|
||||
lda aa
|
||||
cmp ar
|
||||
bne error
|
||||
lda xa
|
||||
cmp xr
|
||||
bne error
|
||||
lda ya
|
||||
cmp yr
|
||||
bne error
|
||||
lda pa
|
||||
cmp pr
|
||||
bne error
|
||||
lda sa
|
||||
cmp sr
|
||||
bne error
|
||||
rts
|
||||
|
||||
error jsr print
|
||||
.byte 13
|
||||
.null "before "
|
||||
ldx #<db
|
||||
ldy #>db
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "after "
|
||||
ldx #<da
|
||||
ldy #>da
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "right "
|
||||
ldx #<dr
|
||||
ldy #>dr
|
||||
jsr showregs
|
||||
lda #13
|
||||
jsr $ffd2
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
cmp #3
|
||||
beq stop
|
||||
rts
|
||||
stop lda 2
|
||||
beq basic
|
||||
jmp $8000
|
||||
basic jmp ($a002)
|
||||
|
||||
showregs stx 172
|
||||
sty 173
|
||||
ldy #0
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
ldx #"n"
|
||||
asl a
|
||||
bcc ok7
|
||||
ldx #"N"
|
||||
ok7 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"v"
|
||||
asl a
|
||||
bcc ok6
|
||||
ldx #"V"
|
||||
ok6 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"0"
|
||||
asl a
|
||||
bcc ok5
|
||||
ldx #"1"
|
||||
ok5 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"b"
|
||||
asl a
|
||||
bcc ok4
|
||||
ldx #"B"
|
||||
ok4 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"d"
|
||||
asl a
|
||||
bcc ok3
|
||||
ldx #"D"
|
||||
ok3 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"i"
|
||||
asl a
|
||||
bcc ok2
|
||||
ldx #"I"
|
||||
ok2 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"z"
|
||||
asl a
|
||||
bcc ok1
|
||||
ldx #"Z"
|
||||
ok1 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"c"
|
||||
asl a
|
||||
bcc ok0
|
||||
ldx #"C"
|
||||
ok0 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
.bend
|
||||
hexb pha
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
jsr hexn
|
||||
pla
|
||||
and #$0f
|
||||
hexn ora #$30
|
||||
cmp #$3a
|
||||
bcc hexn0
|
||||
adc #6
|
||||
hexn0 jmp $ffd2
|
||||
|
||||
print pla
|
||||
.block
|
||||
sta print0+1
|
||||
pla
|
||||
sta print0+2
|
||||
ldx #1
|
||||
print0 lda !*,x
|
||||
beq print1
|
||||
jsr $ffd2
|
||||
inx
|
||||
bne print0
|
||||
print1 sec
|
||||
txa
|
||||
adc print0+1
|
||||
sta print2+1
|
||||
lda #0
|
||||
adc print0+2
|
||||
sta print2+2
|
||||
print2 jmp !*
|
||||
.bend
|
||||
|
||||
|
327
src/test/kotlin/6502testsuite/source/aslz.asm
Normal file
327
src/test/kotlin/6502testsuite/source/aslz.asm
Normal file
|
@ -0,0 +1,327 @@
|
|||
*= $0801
|
||||
|
||||
.byte $4c,$16,$08,$00,$97,$32
|
||||
.byte $2c,$30,$3a,$9e,$32,$30
|
||||
.byte $37,$30,$00,$00,$00,$a9
|
||||
.byte $01,$85,$02
|
||||
|
||||
jsr print
|
||||
.byte 13
|
||||
.text "(up)aslz"
|
||||
.byte 0
|
||||
|
||||
lda #%00011011
|
||||
sta db
|
||||
lda #%11000110
|
||||
sta ab
|
||||
lda #%10110001
|
||||
sta xb
|
||||
lda #%01101100
|
||||
sta yb
|
||||
lda #0
|
||||
sta pb
|
||||
tsx
|
||||
stx sb
|
||||
|
||||
lda #0
|
||||
sta db
|
||||
|
||||
next lda db
|
||||
sta 172
|
||||
sta dr
|
||||
asl dr
|
||||
|
||||
lda ab
|
||||
sta ar
|
||||
|
||||
lda xb
|
||||
sta xr
|
||||
|
||||
lda yb
|
||||
sta yr
|
||||
|
||||
lda pb
|
||||
ora #%00110000
|
||||
and #%01111100
|
||||
tax
|
||||
lda dr
|
||||
cmp #0
|
||||
bne nozero
|
||||
txa
|
||||
ora #%00000010
|
||||
tax
|
||||
lda dr
|
||||
nozero asl a
|
||||
bcc noneg
|
||||
txa
|
||||
ora #%10000000
|
||||
tax
|
||||
noneg lda db
|
||||
bpl nocarry
|
||||
txa
|
||||
ora #%00000001
|
||||
tax
|
||||
nocarry stx pr
|
||||
|
||||
lda sb
|
||||
sta sr
|
||||
|
||||
ldx sb
|
||||
txs
|
||||
lda pb
|
||||
pha
|
||||
lda ab
|
||||
ldx xb
|
||||
ldy yb
|
||||
plp
|
||||
|
||||
cmd asl 172
|
||||
|
||||
php
|
||||
cld
|
||||
sta aa
|
||||
stx xa
|
||||
sty ya
|
||||
pla
|
||||
sta pa
|
||||
tsx
|
||||
stx sa
|
||||
lda 172
|
||||
sta da
|
||||
jsr check
|
||||
|
||||
inc db
|
||||
bne jmpnext
|
||||
inc pb
|
||||
beq nonext
|
||||
jmpnext jmp next
|
||||
nonext
|
||||
|
||||
jsr print
|
||||
.text " - ok"
|
||||
.byte 13,0
|
||||
lda 2
|
||||
beq load
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
jmp $8000
|
||||
|
||||
load jsr print
|
||||
name .text "aslzx"
|
||||
namelen = *-name
|
||||
.byte 0
|
||||
lda #0
|
||||
sta $0a
|
||||
sta $b9
|
||||
lda #namelen
|
||||
sta $b7
|
||||
lda #<name
|
||||
sta $bb
|
||||
lda #>name
|
||||
sta $bc
|
||||
pla
|
||||
pla
|
||||
jmp $e16f
|
||||
|
||||
db .byte 0
|
||||
ab .byte 0
|
||||
xb .byte 0
|
||||
yb .byte 0
|
||||
pb .byte 0
|
||||
sb .byte 0
|
||||
da .byte 0
|
||||
aa .byte 0
|
||||
xa .byte 0
|
||||
ya .byte 0
|
||||
pa .byte 0
|
||||
sa .byte 0
|
||||
dr .byte 0
|
||||
ar .byte 0
|
||||
xr .byte 0
|
||||
yr .byte 0
|
||||
pr .byte 0
|
||||
sr .byte 0
|
||||
|
||||
check
|
||||
.block
|
||||
lda da
|
||||
cmp dr
|
||||
bne error
|
||||
lda aa
|
||||
cmp ar
|
||||
bne error
|
||||
lda xa
|
||||
cmp xr
|
||||
bne error
|
||||
lda ya
|
||||
cmp yr
|
||||
bne error
|
||||
lda pa
|
||||
cmp pr
|
||||
bne error
|
||||
lda sa
|
||||
cmp sr
|
||||
bne error
|
||||
rts
|
||||
|
||||
error jsr print
|
||||
.byte 13
|
||||
.null "before "
|
||||
ldx #<db
|
||||
ldy #>db
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "after "
|
||||
ldx #<da
|
||||
ldy #>da
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "right "
|
||||
ldx #<dr
|
||||
ldy #>dr
|
||||
jsr showregs
|
||||
lda #13
|
||||
jsr $ffd2
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
cmp #3
|
||||
beq stop
|
||||
rts
|
||||
stop lda 2
|
||||
beq basic
|
||||
jmp $8000
|
||||
basic jmp ($a002)
|
||||
|
||||
showregs stx 172
|
||||
sty 173
|
||||
ldy #0
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
ldx #"n"
|
||||
asl a
|
||||
bcc ok7
|
||||
ldx #"N"
|
||||
ok7 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"v"
|
||||
asl a
|
||||
bcc ok6
|
||||
ldx #"V"
|
||||
ok6 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"0"
|
||||
asl a
|
||||
bcc ok5
|
||||
ldx #"1"
|
||||
ok5 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"b"
|
||||
asl a
|
||||
bcc ok4
|
||||
ldx #"B"
|
||||
ok4 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"d"
|
||||
asl a
|
||||
bcc ok3
|
||||
ldx #"D"
|
||||
ok3 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"i"
|
||||
asl a
|
||||
bcc ok2
|
||||
ldx #"I"
|
||||
ok2 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"z"
|
||||
asl a
|
||||
bcc ok1
|
||||
ldx #"Z"
|
||||
ok1 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"c"
|
||||
asl a
|
||||
bcc ok0
|
||||
ldx #"C"
|
||||
ok0 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
.bend
|
||||
hexb pha
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
jsr hexn
|
||||
pla
|
||||
and #$0f
|
||||
hexn ora #$30
|
||||
cmp #$3a
|
||||
bcc hexn0
|
||||
adc #6
|
||||
hexn0 jmp $ffd2
|
||||
|
||||
print pla
|
||||
.block
|
||||
sta print0+1
|
||||
pla
|
||||
sta print0+2
|
||||
ldx #1
|
||||
print0 lda !*,x
|
||||
beq print1
|
||||
jsr $ffd2
|
||||
inx
|
||||
bne print0
|
||||
print1 sec
|
||||
txa
|
||||
adc print0+1
|
||||
sta print2+1
|
||||
lda #0
|
||||
adc print0+2
|
||||
sta print2+2
|
||||
print2 jmp !*
|
||||
.bend
|
||||
|
||||
|
331
src/test/kotlin/6502testsuite/source/aslzx.asm
Normal file
331
src/test/kotlin/6502testsuite/source/aslzx.asm
Normal file
|
@ -0,0 +1,331 @@
|
|||
*= $0801
|
||||
|
||||
.byte $4c,$16,$08,$00,$97,$32
|
||||
.byte $2c,$30,$3a,$9e,$32,$30
|
||||
.byte $37,$30,$00,$00,$00,$a9
|
||||
.byte $01,$85,$02
|
||||
|
||||
jsr print
|
||||
.byte 13
|
||||
.text "(up)aslzx"
|
||||
.byte 0
|
||||
|
||||
lda #%00011011
|
||||
sta db
|
||||
lda #%11000110
|
||||
sta ab
|
||||
lda #%10110001
|
||||
sta xb
|
||||
lda #%01101100
|
||||
sta yb
|
||||
lda #0
|
||||
sta pb
|
||||
tsx
|
||||
stx sb
|
||||
|
||||
lda #0
|
||||
sta db
|
||||
sta xb
|
||||
|
||||
next lda db
|
||||
sta 172
|
||||
sta dr
|
||||
asl dr
|
||||
|
||||
lda ab
|
||||
sta ar
|
||||
|
||||
lda xb
|
||||
sta xr
|
||||
|
||||
lda yb
|
||||
sta yr
|
||||
|
||||
lda pb
|
||||
ora #%00110000
|
||||
and #%01111100
|
||||
tax
|
||||
lda dr
|
||||
cmp #0
|
||||
bne nozero
|
||||
txa
|
||||
ora #%00000010
|
||||
tax
|
||||
lda dr
|
||||
nozero asl a
|
||||
bcc noneg
|
||||
txa
|
||||
ora #%10000000
|
||||
tax
|
||||
noneg lda db
|
||||
bpl nocarry
|
||||
txa
|
||||
ora #%00000001
|
||||
tax
|
||||
nocarry stx pr
|
||||
|
||||
lda sb
|
||||
sta sr
|
||||
|
||||
ldx sb
|
||||
txs
|
||||
lda pb
|
||||
pha
|
||||
lda ab
|
||||
ldx xb
|
||||
ldy yb
|
||||
plp
|
||||
|
||||
cmd asl 172,x
|
||||
|
||||
php
|
||||
cld
|
||||
sta aa
|
||||
stx xa
|
||||
sty ya
|
||||
pla
|
||||
sta pa
|
||||
tsx
|
||||
stx sa
|
||||
lda 172
|
||||
sta da
|
||||
jsr check
|
||||
|
||||
inc cmd+1
|
||||
dec xb
|
||||
|
||||
inc db
|
||||
bne jmpnext
|
||||
inc pb
|
||||
beq nonext
|
||||
jmpnext jmp next
|
||||
nonext
|
||||
|
||||
jsr print
|
||||
.text " - ok"
|
||||
.byte 13,0
|
||||
lda 2
|
||||
beq load
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
jmp $8000
|
||||
|
||||
load jsr print
|
||||
name .text "asla"
|
||||
namelen = *-name
|
||||
.byte 0
|
||||
lda #0
|
||||
sta $0a
|
||||
sta $b9
|
||||
lda #namelen
|
||||
sta $b7
|
||||
lda #<name
|
||||
sta $bb
|
||||
lda #>name
|
||||
sta $bc
|
||||
pla
|
||||
pla
|
||||
jmp $e16f
|
||||
|
||||
db .byte 0
|
||||
ab .byte 0
|
||||
xb .byte 0
|
||||
yb .byte 0
|
||||
pb .byte 0
|
||||
sb .byte 0
|
||||
da .byte 0
|
||||
aa .byte 0
|
||||
xa .byte 0
|
||||
ya .byte 0
|
||||
pa .byte 0
|
||||
sa .byte 0
|
||||
dr .byte 0
|
||||
ar .byte 0
|
||||
xr .byte 0
|
||||
yr .byte 0
|
||||
pr .byte 0
|
||||
sr .byte 0
|
||||
|
||||
check
|
||||
.block
|
||||
lda da
|
||||
cmp dr
|
||||
bne error
|
||||
lda aa
|
||||
cmp ar
|
||||
bne error
|
||||
lda xa
|
||||
cmp xr
|
||||
bne error
|
||||
lda ya
|
||||
cmp yr
|
||||
bne error
|
||||
lda pa
|
||||
cmp pr
|
||||
bne error
|
||||
lda sa
|
||||
cmp sr
|
||||
bne error
|
||||
rts
|
||||
|
||||
error jsr print
|
||||
.byte 13
|
||||
.null "before "
|
||||
ldx #<db
|
||||
ldy #>db
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "after "
|
||||
ldx #<da
|
||||
ldy #>da
|
||||
jsr showregs
|
||||
jsr print
|
||||
.byte 13
|
||||
.null "right "
|
||||
ldx #<dr
|
||||
ldy #>dr
|
||||
jsr showregs
|
||||
lda #13
|
||||
jsr $ffd2
|
||||
wait jsr $ffe4
|
||||
beq wait
|
||||
cmp #3
|
||||
beq stop
|
||||
rts
|
||||
stop lda 2
|
||||
beq basic
|
||||
jmp $8000
|
||||
basic jmp ($a002)
|
||||
|
||||
showregs stx 172
|
||||
sty 173
|
||||
ldy #0
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
jsr hexb
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
ldx #"n"
|
||||
asl a
|
||||
bcc ok7
|
||||
ldx #"N"
|
||||
ok7 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"v"
|
||||
asl a
|
||||
bcc ok6
|
||||
ldx #"V"
|
||||
ok6 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"0"
|
||||
asl a
|
||||
bcc ok5
|
||||
ldx #"1"
|
||||
ok5 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"b"
|
||||
asl a
|
||||
bcc ok4
|
||||
ldx #"B"
|
||||
ok4 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"d"
|
||||
asl a
|
||||
bcc ok3
|
||||
ldx #"D"
|
||||
ok3 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"i"
|
||||
asl a
|
||||
bcc ok2
|
||||
ldx #"I"
|
||||
ok2 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"z"
|
||||
asl a
|
||||
bcc ok1
|
||||
ldx #"Z"
|
||||
ok1 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
ldx #"c"
|
||||
asl a
|
||||
bcc ok0
|
||||
ldx #"C"
|
||||
ok0 pha
|
||||
txa
|
||||
jsr $ffd2
|
||||
pla
|
||||
lda #32
|
||||
jsr $ffd2
|
||||
iny
|
||||
lda (172),y
|
||||
.bend
|
||||
hexb pha
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
lsr a
|
||||
jsr hexn
|
||||
pla
|
||||
and #$0f
|
||||
hexn ora #$30
|
||||
cmp #$3a
|
||||
bcc hexn0
|
||||
adc #6
|
||||
hexn0 jmp $ffd2
|
||||
|
||||
print pla
|
||||
.block
|
||||
sta print0+1
|
||||
pla
|
||||
sta print0+2
|
||||
ldx #1
|
||||
print0 lda !*,x
|
||||
beq print1
|
||||
jsr $ffd2
|
||||
inx
|
||||
bne print0
|
||||
print1 sec
|
||||
txa
|
||||
adc print0+1
|
||||
sta print2+1
|
||||
lda #0
|
||||
adc print0+2
|
||||
sta print2+2
|
||||
print2 jmp !*
|
||||
.bend
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user