Inital Commit

This commit is contained in:
Gospodin Medvedev 2023-03-12 15:55:16 +01:00
commit fb9f811160
21 changed files with 4960 additions and 0 deletions

522
Cargo.lock generated Normal file
View File

@ -0,0 +1,522 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "autocfg"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bumpalo"
version = "3.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9df67f7bf9ef8498769f994239c45613ef0c5899415fb58e9add412d2c1a538"
[[package]]
name = "cfg-if"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "console_error_panic_hook"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8d976903543e0c48546a91908f21588a680a8c8f984df9a5d69feccb2b2a211"
dependencies = [
"cfg-if 0.1.10",
"wasm-bindgen",
]
[[package]]
name = "emulator"
version = "0.1.0"
dependencies = [
"console_error_panic_hook",
"lazy_static",
"log",
"once_cell",
"wasm-bindgen",
"wasm-bindgen-test",
"wasm-timer",
"wee_alloc",
]
[[package]]
name = "futures"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a12aa0eb539080d55c3f2d45a67c3b58b6b0773c1a3ca2dfec66d58c97fd66ca"
dependencies = [
"futures-channel",
"futures-core",
"futures-executor",
"futures-io",
"futures-sink",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-channel"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5da6ba8c3bb3c165d3c7319fc1cc8304facf1fb8db99c5de877183c08a273888"
dependencies = [
"futures-core",
"futures-sink",
]
[[package]]
name = "futures-core"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88d1c26957f23603395cd326b0ffe64124b818f4449552f960d815cfba83a53d"
[[package]]
name = "futures-executor"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45025be030969d763025784f7f355043dc6bc74093e4ecc5000ca4dc50d8745c"
dependencies = [
"futures-core",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-io"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "522de2a0fe3e380f1bc577ba0474108faf3f6b18321dbf60b3b9c39a75073377"
[[package]]
name = "futures-macro"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18e4a4b95cea4b4ccbcf1c5675ca7c4ee4e9e75eb79944d07defde18068f79bb"
dependencies = [
"autocfg",
"proc-macro-hack",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "futures-sink"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36ea153c13024fe480590b3e3d4cad89a0cfacecc24577b68f86c6ced9c2bc11"
[[package]]
name = "futures-task"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d3d00f4eddb73e498a54394f228cd55853bdf059259e8e7bc6e69d408892e99"
[[package]]
name = "futures-util"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36568465210a3a6ee45e1f165136d68671471a501e632e9a98d96872222b5481"
dependencies = [
"autocfg",
"futures-channel",
"futures-core",
"futures-io",
"futures-macro",
"futures-sink",
"futures-task",
"memchr",
"pin-project-lite",
"pin-utils",
"proc-macro-hack",
"proc-macro-nested",
"slab",
]
[[package]]
name = "instant"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "716d3d89f35ac6a34fd0eed635395f4c3b76fa889338a4632e5231a8684216bd"
dependencies = [
"cfg-if 1.0.0",
]
[[package]]
name = "js-sys"
version = "0.3.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7cc9ffccd38c451a86bf13657df244e9c3f37493cce8e5e21e940963777acc84"
dependencies = [
"wasm-bindgen",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7f823d141fe0a24df1e23b4af4e3c7ba9e5966ec514ea068c93024aa7deb765"
[[package]]
name = "lock_api"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109"
dependencies = [
"scopeguard",
]
[[package]]
name = "log"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
dependencies = [
"cfg-if 1.0.0",
]
[[package]]
name = "memchr"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
[[package]]
name = "memory_units"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3"
[[package]]
name = "once_cell"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56"
[[package]]
name = "parking_lot"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
dependencies = [
"instant",
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216"
dependencies = [
"cfg-if 1.0.0",
"instant",
"libc",
"redox_syscall",
"smallvec",
"winapi",
]
[[package]]
name = "pin-project-lite"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443"
[[package]]
name = "pin-utils"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "proc-macro-hack"
version = "0.5.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
[[package]]
name = "proc-macro-nested"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086"
[[package]]
name = "proc-macro2"
version = "1.0.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9f5105d4fdaab20335ca9565e106a5d9b82b6219b5ba735731124ac6711d23d"
dependencies = [
"unicode-xid",
]
[[package]]
name = "quote"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
dependencies = [
"proc-macro2",
]
[[package]]
name = "redox_syscall"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff"
dependencies = [
"bitflags",
]
[[package]]
name = "scoped-tls"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
[[package]]
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "sdl2"
version = "0.34.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "deecbc3fa9460acff5a1e563e05cb5f31bba0aa0c214bb49a43db8159176d54b"
dependencies = [
"bitflags",
"lazy_static",
"libc",
"sdl2-sys",
]
[[package]]
name = "sdl2-sys"
version = "0.34.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41a29aa21f175b5a41a6e26da572d5e5d1ee5660d35f9f9d0913e8a802098f74"
dependencies = [
"cfg-if 0.1.10",
"libc",
"version-compare",
]
[[package]]
name = "slab"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c307a32c1c5c437f38c7fd45d753050587732ba8628319fbdf12a7e289ccc590"
[[package]]
name = "smallvec"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309"
[[package]]
name = "space-invaders"
version = "0.1.0"
dependencies = [
"emulator",
"lazy_static",
"once_cell",
"sdl2",
]
[[package]]
name = "syn"
version = "1.0.76"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6f107db402c2c2055242dbf4d2af0e69197202e9faacbef9571bbe47f5a1b84"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "unicode-xid"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
[[package]]
name = "version-compare"
version = "0.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d63556a25bae6ea31b52e640d7c41d1ab27faba4ccb600013837a3d0b3994ca1"
[[package]]
name = "wasm-bindgen"
version = "0.2.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce"
dependencies = [
"cfg-if 1.0.0",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b"
dependencies = [
"bumpalo",
"lazy_static",
"log",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-futures"
version = "0.4.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e8d7523cb1f2a4c96c1317ca690031b714a51cc14e05f712446691f413f5d39"
dependencies = [
"cfg-if 1.0.0",
"js-sys",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab"
dependencies = [
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc"
[[package]]
name = "wasm-bindgen-test"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96f1aa7971fdf61ef0f353602102dbea75a56e225ed036c1e3740564b91e6b7e"
dependencies = [
"console_error_panic_hook",
"js-sys",
"scoped-tls",
"wasm-bindgen",
"wasm-bindgen-futures",
"wasm-bindgen-test-macro",
]
[[package]]
name = "wasm-bindgen-test-macro"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6006f79628dfeb96a86d4db51fbf1344cd7fd8408f06fc9aa3c84913a4789688"
dependencies = [
"proc-macro2",
"quote",
]
[[package]]
name = "wasm-timer"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be0ecb0db480561e9a7642b5d3e4187c128914e58aa84330b9493e3eb68c5e7f"
dependencies = [
"futures",
"js-sys",
"parking_lot",
"pin-utils",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
]
[[package]]
name = "web-sys"
version = "0.3.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38eb105f1c59d9eaa6b5cdc92b859d85b926e82cb2e0945cd0c9259faa6fe9fb"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "wee_alloc"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbb3b5a6b2bb17cb6ad44a2e68a43e8d2722c997da10e928665c72ec6c0a0b8e"
dependencies = [
"cfg-if 0.1.10",
"libc",
"memory_units",
"winapi",
]
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

16
Cargo.toml Normal file
View File

@ -0,0 +1,16 @@
[package]
name = "space-invaders"
version = "0.1.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[workspace]
members = [ "emulator"]
[dependencies]
once_cell = "1.8.0"
lazy_static = "1.4.0"
sdl2 = "0.34.5"
emulator = { path = "emulator" }

4
README.md Normal file
View File

@ -0,0 +1,4 @@
# space-invade.rs: Biterrfied edition
## I resized cells and changed colors.
![Screenshot](screenshot.png)
[Original source code](https://github.com/cbeust/space-invade.rs)

BIN
SDL2.lib Normal file

Binary file not shown.

33
emulator/Cargo.toml Normal file
View File

@ -0,0 +1,33 @@
[package]
name = "emulator"
version = "0.1.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
once_cell = "1.8.0"
lazy_static = "1.4.0"
log = "0.4"
wasm-bindgen = "0.2.63"
wasm-timer = "0.2.5"
# The `console_error_panic_hook` crate provides better debugging of panics by
# logging them with `console.error`. This is great for development, but requires
# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
# code size when deploying.
console_error_panic_hook = { version = "0.1.6", optional = true }
# `wee_alloc` is a tiny allocator for wasm that is only ~1K in code size
# compared to the default allocator's ~10K. It is slower than the default
# allocator, however.
#
# Unfortunately, `wee_alloc` requires nightly Rust when targeting wasm for now.
wee_alloc = { version = "0.4.5", optional = true }
[dev-dependencies]
wasm-bindgen-test = "0.3.13"
[profile.release]
# Tell `rustc` to optimize for small code size.
opt-level = "s"

811
emulator/cpudiag.asm Normal file
View File

@ -0,0 +1,811 @@
;***********************************************************************
; MICROCOSM ASSOCIATES 8080/8085 CPU DIAGNOSTIC VERSION 1.0 (C) 1980
;***********************************************************************
;
;DONATED TO THE "SIG/M" CP/M USER'S GROUP BY:
;KELLY SMITH, MICROCOSM ASSOCIATES
;3055 WACO AVENUE
;SIMI VALLEY, CALIFORNIA, 93065
;(805) 527-9321 (MODEM, CP/M-NET (TM))
;(805) 527-0518 (VERBAL)
;
;
;
;
;
;
ORG 00100H
;
;
;
JMP CPU ;JUMP TO 8080 CPU DIAGNOSTIC
;
;
;
DB 'MICROCOSM ASSOCIATES 8080/8085 CPU DIAGNOSTIC'
DB ' VERSION 1.0 (C) 1980'
;
;
;
BDOS EQU 00005H ;BDOS ENTRY TO CP/M
WBOOT EQU 00000H ;RE-ENTRY TO CP/M WARM BOOT
;
;
;
;MESSAGE OUTPUT ROUTINE
;
MSG: PUSH D ;EXILE D REG.
XCHG ;SWAP H&L REGS. TO D&E REGS.
MVI C,9 ;LET BDOS KNOW WE WANT TO SEND A MESSAGE
CALL BDOS
POP D ;BACK FROM EXILE
RET
;
;
;
;CHARACTER OUTPUT ROUTINE
;
PCHAR: MVI C,2
CALL BDOS
RET
;
;
;
BYTEO: PUSH PSW
CALL BYTO1
MOV E,A
CALL PCHAR
POP PSW
CALL BYTO2
MOV E,A
JMP PCHAR
BYTO1: RRC
RRC
RRC
RRC
BYTO2: ANI 0FH
CPI 0AH
JM BYTO3
ADI 7
BYTO3: ADI 30H
RET
;
;
;
;************************************************************
; MESSAGE TABLE FOR OPERATIONAL CPU TEST
;************************************************************
;
OKCPU: DB 0CH,0DH,0AH,' CPU IS OPERATIONAL$'
;
NGCPU: DB 0CH,0DH,0AH,' CPU HAS FAILED! ERROR EXIT=$'
;
;
;
;************************************************************
; 8080/8085 CPU TEST/DIAGNOSTIC
;************************************************************
;
;NOTE: (1) PROGRAM ASSUMES "CALL",AND "LXI SP" INSTRUCTIONS WORK!
;
; (2) INSTRUCTIONS NOT TESTED ARE "HLT","DI","EI","RIM","SIM",
; AND "RST 0" THRU "RST 7"
;
;
;
;TEST JUMP INSTRUCTIONS AND FLAGS
;
CPU: LXI SP,STACK ;SET THE STACK POINTER
ANI 0 ;INITIALIZE A REG. AND CLEAR ALL FLAGS
JZ J010 ;TEST "JZ"
CALL CPUER
J010: JNC J020 ;TEST "JNC"
CALL CPUER
J020: JPE J030 ;TEST "JPE"
CALL CPUER
J030: JP J040 ;TEST "JP"
CALL CPUER
J040: JNZ J050 ;TEST "JNZ"
JC J050 ;TEST "JC"
JPO J050 ;TEST "JPO"
JM J050 ;TEST "JM"
JMP J060 ;TEST "JMP" (IT'S A LITTLE LATE,BUT WHAT THE HELL!
J050: CALL CPUER
J060: ADI 6 ;A=6,C=0,P=1,S=0,Z=0
JNZ J070 ;TEST "JNZ"
CALL CPUER
J070: JC J080 ;TEST "JC"
JPO J080 ;TEST "JPO"
JP J090 ;TEST "JP"
J080: CALL CPUER
J090: ADI 070H ;A=76H,C=0,P=0,S=0,Z=0
JPO J100 ;TEST "JPO"
CALL CPUER
J100: JM J110 ;TEST "JM"
JZ J110 ;TEST "JZ"
JNC J120 ;TEST "JNC"
J110: CALL CPUER
J120: ADI 081H ;A=F7H,C=0,P=0,S=1,Z=0
JM J130 ;TEST "JM"
CALL CPUER
J130: JZ J140 ;TEST "JZ"
JC J140 ;TEST "JC"
JPO J150 ;TEST "JPO"
J140: CALL CPUER
J150: ADI 0FEH ;A=F5H,C=1,P=1,S=1,Z=0
JC J160 ;TEST "JC"
CALL CPUER
J160: JZ J170 ;TEST "JZ"
JPO J170 ;TEST "JPO"
JM AIMM ;TEST "JM"
J170: CALL CPUER
;
;
;
;TEST ACCUMULATOR IMMEDIATE INSTRUCTIONS
;
AIMM: CPI 0 ;A=F5H,C=0,Z=0
JC CPIE ;TEST "CPI" FOR RE-SET CARRY
JZ CPIE ;TEST "CPI" FOR RE-SET ZERO
CPI 0F5H ;A=F5H,C=0,Z=1
JC CPIE ;TEST "CPI" FOR RE-SET CARRY ("ADI")
JNZ CPIE ;TEST "CPI" FOR RE-SET ZERO
CPI 0FFH ;A=F5H,C=1,Z=0
JZ CPIE ;TEST "CPI" FOR RE-SET ZERO
JC ACII ;TEST "CPI" FOR SET CARRY
CPIE: CALL CPUER
ACII: ACI 00AH ;A=F5H+0AH+CARRY(1)=0,C=1
ACI 00AH ;A=0+0AH+CARRY(0)=0BH,C=0
CPI 00BH
JZ SUII ;TEST "ACI"
CALL CPUER
SUII: SUI 00CH ;A=FFH,C=0
SUI 00FH ;A=F0H,C=1
CPI 0F0H
JZ SBII ;TEST "SUI"
CALL CPUER
SBII: SBI 0F1H ;A=F0H-0F1H-CARRY(0)=FFH,C=1
SBI 00EH ;A=FFH-OEH-CARRY(1)=F0H,C=0
CPI 0F0H
JZ ANII ;TEST "SBI"
CALL CPUER
ANII: ANI 055H ;A=F0H<AND>55H=50H,C=0,P=1,S=0,Z=0
CPI 050H
JZ ORII ;TEST "ANI"
CALL CPUER
ORII: ORI 03AH ;A=50H<OR>3AH=7AH,C=0,P=0,S=0,Z=0
CPI 07AH
JZ XRII ;TEST "ORI"
CALL CPUER
XRII: XRI 00FH ;A=7AH<XOR>0FH=75H,C=0,P=0,S=0,Z=0
CPI 075H
JZ C010 ;TEST "XRI"
CALL CPUER
;
;
;
;TEST CALLS AND RETURNS
;
C010: ANI 000H ;A=0,C=0,P=1,S=0,Z=1
CC CPUER ;TEST "CC"
CPO CPUER ;TEST "CPO"
CM CPUER ;TEST "CM"
CNZ CPUER ;TEST "CNZ"
CPI 000H
JZ C020 ;A=0,C=0,P=0,S=0,Z=1
CALL CPUER
C020: SUI 077H ;A=89H,C=1,P=0,S=1,Z=0
CNC CPUER ;TEST "CNC"
CPE CPUER ;TEST "CPE"
CP CPUER ;TEST "CP"
CZ CPUER ;TEST "CZ"
CPI 089H
JZ C030 ;TEST FOR "CALLS" TAKING BRANCH
CALL CPUER
C030: ANI 0FFH ;SET FLAGS BACK!
CPO CPOI ;TEST "CPO"
CPI 0D9H
JZ MOVI ;TEST "CALL" SEQUENCE SUCCESS
CALL CPUER
CPOI: RPE ;TEST "RPE"
ADI 010H ;A=99H,C=0,P=0,S=1,Z=0
CPE CPEI ;TEST "CPE"
ADI 002H ;A=D9H,C=0,P=0,S=1,Z=0
RPO ;TEST "RPO"
CALL CPUER
CPEI: RPO ;TEST "RPO"
ADI 020H ;A=B9H,C=0,P=0,S=1,Z=0
CM CMI ;TEST "CM"
ADI 004H ;A=D7H,C=0,P=1,S=1,Z=0
RPE ;TEST "RPE"
CALL CPUER
CMI: RP ;TEST "RP"
ADI 080H ;A=39H,C=1,P=1,S=0,Z=0
CP TCPI ;TEST "CP"
ADI 080H ;A=D3H,C=0,P=0,S=1,Z=0
RM ;TEST "RM"
CALL CPUER
TCPI: RM ;TEST "RM"
ADI 040H ;A=79H,C=0,P=0,S=0,Z=0
CNC CNCI ;TEST "CNC"
ADI 040H ;A=53H,C=0,P=1,S=0,Z=0
RP ;TEST "RP"
CALL CPUER
CNCI: RC ;TEST "RC"
ADI 08FH ;A=08H,C=1,P=0,S=0,Z=0
CC CCI ;TEST "CC"
SUI 002H ;A=13H,C=0,P=0,S=0,Z=0
RNC ;TEST "RNC"
CALL CPUER
CCI: RNC ;TEST "RNC"
ADI 0F7H ;A=FFH,C=0,P=1,S=1,Z=0
CNZ CNZI ;TEST "CNZ"
ADI 0FEH ;A=15H,C=1,P=0,S=0,Z=0
RC ;TEST "RC"
CALL CPUER
CNZI: RZ ;TEST "RZ"
ADI 001H ;A=00H,C=1,P=1,S=0,Z=1
CZ CZI ;TEST "CZ"
ADI 0D0H ;A=17H,C=1,P=1,S=0,Z=0
RNZ ;TEST "RNZ"
CALL CPUER
CZI: RNZ ;TEST "RNZ"
ADI 047H ;A=47H,C=0,P=1,S=0,Z=0
CPI 047H ;A=47H,C=0,P=1,S=0,Z=1
RZ ;TEST "RZ"
CALL CPUER
;
;
;
;TEST "MOV","INR",AND "DCR" INSTRUCTIONS
;
MOVI: MVI A,077H
INR A
MOV B,A
INR B
MOV C,B
DCR C
MOV D,C
MOV E,D
MOV H,E
MOV L,H
MOV A,L ;TEST "MOV" A,L,H,E,D,C,B,A
DCR A
MOV C,A
MOV E,C
MOV L,E
MOV B,L
MOV D,B
MOV H,D
MOV A,H ;TEST "MOV" A,H,D,B,L,E,C,A
MOV D,A
INR D
MOV L,D
MOV C,L
INR C
MOV H,C
MOV B,H
DCR B
MOV E,B
MOV A,E ;TEST "MOV" A,E,B,H,C,L,D,A
MOV E,A
INR E
MOV B,E
MOV H,B
INR H
MOV C,H
MOV L,C
MOV D,L
DCR D
MOV A,D ;TEST "MOV" A,D,L,C,H,B,E,A
MOV H,A
DCR H
MOV D,H
MOV B,D
MOV L,B
INR L
MOV E,L
DCR E
MOV C,E
MOV A,C ;TEST "MOV" A,C,E,L,B,D,H,A
MOV L,A
DCR L
MOV H,L
MOV E,H
MOV D,E
MOV C,D
MOV B,C
MOV A,B
CPI 077H
CNZ CPUER ;TEST "MOV" A,B,C,D,E,H,L,A
;
;
;
;TEST ARITHMETIC AND LOGIC INSTRUCTIONS
;
XRA A
MVI B,001H
MVI C,003H
MVI D,007H
MVI E,00FH
MVI H,01FH
MVI L,03FH
ADD B
ADD C
ADD D
ADD E
ADD H
ADD L
ADD A
CPI 0F0H
CNZ CPUER ;TEST "ADD" B,C,D,E,H,L,A
SUB B
SUB C
SUB D
SUB E
SUB H
SUB L
CPI 078H
CNZ CPUER ;TEST "SUB" B,C,D,E,H,L
SUB A
CNZ CPUER ;TEST "SUB" A
MVI A,080H
ADD A
MVI B,001H
MVI C,002H
MVI D,003H
MVI E,004H
MVI H,005H
MVI L,006H
ADC B
MVI B,080H
ADD B
ADD B
ADC C
ADD B
ADD B
ADC D
ADD B
ADD B
ADC E
ADD B
ADD B
ADC H
ADD B
ADD B
ADC L
ADD B
ADD B
ADC A
CPI 037H
CNZ CPUER ;TEST "ADC" B,C,D,E,H,L,A
MVI A,080H
ADD A
MVI B,001H
SBB B
MVI B,0FFH
ADD B
SBB C
ADD B
SBB D
ADD B
SBB E
ADD B
SBB H
ADD B
SBB L
CPI 0E0H
CNZ CPUER ;TEST "SBB" B,C,D,E,H,L
MVI A,080H
ADD A
SBB A
CPI 0FFH
CNZ CPUER ;TEST "SBB" A
MVI A,0FFH
MVI B,0FEH
MVI C,0FCH
MVI D,0EFH
MVI E,07FH
MVI H,0F4H
MVI L,0BFH
ANA A
ANA C
ANA D
ANA E
ANA H
ANA L
ANA A
CPI 024H
CNZ CPUER ;TEST "ANA" B,C,D,E,H,L,A
XRA A
MVI B,001H
MVI C,002H
MVI D,004H
MVI E,008H
MVI H,010H
MVI L,020H
ORA B
ORA C
ORA D
ORA E
ORA H
ORA L
ORA A
CPI 03FH
CNZ CPUER ;TEST "ORA" B,C,D,E,H,L,A
MVI A,000H
MVI H,08FH
MVI L,04FH
XRA B
XRA C
XRA D
XRA E
XRA H
XRA L
CPI 0CFH
CNZ CPUER ;TEST "XRA" B,C,D,E,H,L
XRA A
CNZ CPUER ;TEST "XRA" A
MVI B,044H
MVI C,045H
MVI D,046H
MVI E,047H
MVI H,(TEMP0 / 0FFH) ;HIGH BYTE OF TEST MEMORY LOCATION
MVI L,(TEMP0 AND 0FFH) ;LOW BYTE OF TEST MEMORY LOCATION
MOV M,B
MVI B,000H
MOV B,M
MVI A,044H
CMP B
CNZ CPUER ;TEST "MOV" M,B AND B,M
MOV M,D
MVI D,000H
MOV D,M
MVI A,046H
CMP D
CNZ CPUER ;TEST "MOV" M,D AND D,M
MOV M,E
MVI E,000H
MOV E,M
MVI A,047H
CMP E
CNZ CPUER ;TEST "MOV" M,E AND E,M
MOV M,H
MVI H,(TEMP0 / 0FFH)
MVI L,(TEMP0 AND 0FFH)
MOV H,M
MVI A,(TEMP0 / 0FFH)
CMP H
CNZ CPUER ;TEST "MOV" M,H AND H,M
MOV M,L
MVI H,(TEMP0 / 0FFH)
MVI L,(TEMP0 AND 0FFH)
MOV L,M
MVI A,(TEMP0 AND 0FFH)
CMP L
CNZ CPUER ;TEST "MOV" M,L AND L,M
MVI H,(TEMP0 / 0FFH)
MVI L,(TEMP0 AND 0FFH)
MVI A,032H
MOV M,A
CMP M
CNZ CPUER ;TEST "MOV" M,A
ADD M
CPI 064H
CNZ CPUER ;TEST "ADD" M
XRA A
MOV A,M
CPI 032H
CNZ CPUER ;TEST "MOV" A,M
MVI H,(TEMP0 / 0FFH)
MVI L,(TEMP0 AND 0FFH)
MOV A,M
SUB M
CNZ CPUER ;TEST "SUB" M
MVI A,080H
ADD A
ADC M
CPI 033H
CNZ CPUER ;TEST "ADC" M
MVI A,080H
ADD A
SBB M
CPI 0CDH
CNZ CPUER ;TEST "SBB" M
ANA M
CNZ CPUER ;TEST "ANA" M
MVI A,025H
ORA M
CPI 037H
CNZ CPUER ;TEST "ORA" M
XRA M
CPI 005H
CNZ CPUER ;TEST "XRA" M
MVI M,055H
INR M
DCR M
ADD M
CPI 05AH
CNZ CPUER ;TEST "INR","DCR",AND "MVI" M
LXI B,12FFH
LXI D,12FFH
LXI H,12FFH
INX B
INX D
INX H
MVI A,013H
CMP B
CNZ CPUER ;TEST "LXI" AND "INX" B
CMP D
CNZ CPUER ;TEST "LXI" AND "INX" D
CMP H
CNZ CPUER ;TEST "LXI" AND "INX" H
MVI A,000H
CMP C
CNZ CPUER ;TEST "LXI" AND "INX" B
CMP E
CNZ CPUER ;TEST "LXI" AND "INX" D
CMP L
CNZ CPUER ;TEST "LXI" AND "INX" H
DCX B
DCX D
DCX H
MVI A,012H
CMP B
CNZ CPUER ;TEST "DCX" B
CMP D
CNZ CPUER ;TEST "DCX" D
CMP H
CNZ CPUER ;TEST "DCX" H
MVI A,0FFH
CMP C
CNZ CPUER ;TEST "DCX" B
CMP E
CNZ CPUER ;TEST "DCX" D
CMP L
CNZ CPUER ;TEST "DCX" H
STA TEMP0
XRA A
LDA TEMP0
CPI 0FFH
CNZ CPUER ;TEST "LDA" AND "STA"
LHLD TEMPP
SHLD TEMP0
LDA TEMPP
MOV B,A
LDA TEMP0
CMP B
CNZ CPUER ;TEST "LHLD" AND "SHLD"
LDA TEMPP+1
MOV B,A
LDA TEMP0+1
CMP B
CNZ CPUER ;TEST "LHLD" AND "SHLD"
MVI A,0AAH
STA TEMP0
MOV B,H
MOV C,L
XRA A
LDAX B
CPI 0AAH
CNZ CPUER ;TEST "LDAX" B
INR A
STAX B
LDA TEMP0
CPI 0ABH
CNZ CPUER ;TEST "STAX" B
MVI A,077H
STA TEMP0
LHLD TEMPP
LXI D,00000H
XCHG
XRA A
LDAX D
CPI 077H
CNZ CPUER ;TEST "LDAX" D AND "XCHG"
XRA A
ADD H
ADD L
CNZ CPUER ;TEST "XCHG"
MVI A,0CCH
STAX D
LDA TEMP0
CPI 0CCH
STAX D
LDA TEMP0
CPI 0CCH
CNZ CPUER ;TEST "STAX" D
LXI H,07777H
DAD H
MVI A,0EEH
CMP H
CNZ CPUER ;TEST "DAD" H
CMP L
CNZ CPUER ;TEST "DAD" H
LXI H,05555H
LXI B,0FFFFH
DAD B
MVI A,055H
CNC CPUER ;TEST "DAD" B
CMP H
CNZ CPUER ;TEST "DAD" B
MVI A,054H
CMP L
CNZ CPUER ;TEST "DAD" B
LXI H,0AAAAH
LXI D,03333H
DAD D
MVI A,0DDH
CMP H
CNZ CPUER ;TEST "DAD" D
CMP L
CNZ CPUER ;TEST "DAD" B
STC
CNC CPUER ;TEST "STC"
CMC
CC CPUER ;TEST "CMC
MVI A,0AAH
CMA
CPI 055H
CNZ CPUER ;TEST "CMA"
ORA A ;RE-SET AUXILIARY CARRY
DAA
CPI 055H
CNZ CPUER ;TEST "DAA"
MVI A,088H
ADD A
DAA
CPI 076H
CNZ CPUER ;TEST "DAA"
XRA A
MVI A,0AAH
DAA
CNC CPUER ;TEST "DAA"
CPI 010H
CNZ CPUER ;TEST "DAA"
XRA A
MVI A,09AH
DAA
CNC CPUER ;TEST "DAA"
CNZ CPUER ;TEST "DAA"
STC
MVI A,042H
RLC
CC CPUER ;TEST "RLC" FOR RE-SET CARRY
RLC
CNC CPUER ;TEST "RLC" FOR SET CARRY
CPI 009H
CNZ CPUER ;TEST "RLC" FOR ROTATION
RRC
CNC CPUER ;TEST "RRC" FOR SET CARRY
RRC
CPI 042H
CNZ CPUER ;TEST "RRC" FOR ROTATION
RAL
RAL
CNC CPUER ;TEST "RAL" FOR SET CARRY
CPI 008H
CNZ CPUER ;TEST "RAL" FOR ROTATION
RAR
RAR
CC CPUER ;TEST "RAR" FOR RE-SET CARRY
CPI 002H
CNZ CPUER ;TEST "RAR" FOR ROTATION
LXI B,01234H
LXI D,0AAAAH
LXI H,05555H
XRA A
PUSH B
PUSH D
PUSH H
PUSH PSW
LXI B,00000H
LXI D,00000H
LXI H,00000H
MVI A,0C0H
ADI 0F0H
POP PSW
POP H
POP D
POP B
CC CPUER ;TEST "PUSH PSW" AND "POP PSW"
CNZ CPUER ;TEST "PUSH PSW" AND "POP PSW"
CPO CPUER ;TEST "PUSH PSW" AND "POP PSW"
CM CPUER ;TEST "PUSH PSW" AND "POP PSW"
MVI A,012H
CMP B
CNZ CPUER ;TEST "PUSH B" AND "POP B"
MVI A,034H
CMP C
CNZ CPUER ;TEST "PUSH B" AND "POP B"
MVI A,0AAH
CMP D
CNZ CPUER ;TEST "PUSH D" AND "POP D"
CMP E
CNZ CPUER ;TEST "PUSH D" AND "POP D"
MVI A,055H
CMP H
CNZ CPUER ;TEST "PUSH H" AND "POP H"
CMP L
CNZ CPUER ;TEST "PUSH H" AND "POP H"
LXI H,00000H
DAD SP
SHLD SAVSTK ;SAVE THE "OLD" STACK-POINTER!
LXI SP,TEMP4
DCX SP
DCX SP
INX SP
DCX SP
MVI A,055H
STA TEMP2
CMA
STA TEMP3
POP B
CMP B
CNZ CPUER ;TEST "LXI","DAD","INX",AND "DCX" SP
CMA
CMP C
CNZ CPUER ;TEST "LXI","DAD","INX", AND "DCX" SP
LXI H,TEMP4
SPHL
LXI H,07733H
DCX SP
DCX SP
XTHL
LDA TEMP3
CPI 077H
CNZ CPUER ;TEST "SPHL" AND "XTHL"
LDA TEMP2
CPI 033H
CNZ CPUER ;TEST "SPHL" AND "XTHL"
MVI A,055H
CMP L
CNZ CPUER ;TEST "SPHL" AND "XTHL"
CMA
CMP H
CNZ CPUER ;TEST "SPHL" AND "XTHL"
LHLD SAVSTK ;RESTORE THE "OLD" STACK-POINTER
SPHL
LXI H,CPUOK
PCHL ;TEST "PCHL"
;
;
;
CPUER: LXI H,NGCPU ;OUTPUT "CPU HAS FAILED ERROR EXIT=" TO CONSOLE
CALL MSG
XTHL
MOV A,H
CALL BYTEO ;SHOW ERROR EXIT ADDRESS HIGH BYTE
MOV A,L
CALL BYTEO ;SHOW ERROR EXIT ADDRESS LOW BYTE
JMP WBOOT ;EXIT TO CP/M WARM BOOT
;
;
;
CPUOK: LXI H,OKCPU ;OUTPUT "CPU IS OPERATIONAL" TO CONSOLE
CALL MSG
JMP WBOOT ;EXIT TO CP/M WARM BOOT
;
;
;
TEMPP: DW TEMP0 ;POINTER USED TO TEST "LHLD","SHLD",
; AND "LDAX" INSTRUCTIONS
;
TEMP0: DS 1 ;TEMPORARY STORAGE FOR CPU TEST MEMORY LOCATIONS
TEMP1: DS 1 ;TEMPORARY STORAGE FOR CPU TEST MEMORY LOCATIONS
TEMP2 DS 1 ;TEMPORARY STORAGE FOR CPU TEST MEMORY LOCATIONS
TEMP3: DS 1 ;TEMPORARY STORAGE FOR CPU TEST MEMORY LOCATIONS
TEMP4: DS 1 ;TEMPORARY STORAGE FOR CPU TEST MEMORY LOCATIONS
SAVSTK: DS 2 ;TEMPORARY STACK-POINTER STORAGE LOCATION
;
;
;
STACK EQU TEMPP+256 ;DE-BUG STACK POINTER STORAGE AREA
;
;
;
END
;
;
;

BIN
emulator/cpudiag.bin Normal file

Binary file not shown.

981
emulator/cpudiag.lst Normal file
View File

@ -0,0 +1,981 @@
;***********************************************************************
; MICROCOSM ASSOCIATES 8080/8085 CPU DIAGNOSTIC VERSION 1.0 (C) 1980
;***********************************************************************
;
;DONATED TO THE "SIG/M" CP/M USER'S GROUP BY:
;KELLY SMITH, MICROCOSM ASSOCIATES
;3055 WACO AVENUE
;SIMI VALLEY, CALIFORNIA, 93065
;(805) 527-9321 (MODEM, CP/M-NET (TM))
;(805) 527-0518 (VERBAL)
;
;
;
;
;
;
ORG 00100H
;
;
;
0100 C3 AB 01 JMP CPU ;JUMP TO 8080 CPU DIAGNOSTIC
;
;
;
0103 4D 49 43 52 DB 'MICROCOSM ASSOCIATES 8080/8085 CPU DIAGNOSTIC'
. . .
012F 43
0130 20 56 45 52 DB ' VERSION 1.0 (C) 1980'
. . .
0144 30
;
;
;
BDOS EQU 00005H ;BDOS ENTRY TO CP/M
WBOOT EQU 00000H ;RE-ENTRY TO CP/M WARM BOOT
;
;
;
;MESSAGE OUTPUT ROUTINE
;
0145 D5 MSG: PUSH D ;EXILE D REG.
0146 EB XCHG ;SWAP H&L REGS. TO D&E REGS.
0147 0E 09 MVI C,9 ;LET BDOS KNOW WE WANT TO SEND A MESSAGE
0149 CD 05 00 CALL BDOS
014C D1 POP D ;BACK FROM EXILE
014D C9 RET
;
;
;
;CHARACTER OUTPUT ROUTINE
;
014E 0E 02 PCHAR: MVI C,2
0150 CD 05 00 CALL BDOS
0153 C9 RET
;
;
;
0154 F5 BYTEO: PUSH PSW
0155 CD 64 01 CALL BYTO1
0158 5F MOV E,A
0159 CD 4E 01 CALL PCHAR
015C F1 POP PSW
015D CD 68 01 CALL BYTO2
0160 5F MOV E,A
0161 C3 4E 01 JMP PCHAR
0164 0F BYTO1: RRC
0165 0F RRC
0166 0F RRC
0167 0F RRC
0168 E6 0F BYTO2: ANI 0FH
016A FE 0A CPI 0AH
016C FA 71 01 JM BYTO3
016F C6 07 ADI 7
0171 C6 30 BYTO3: ADI 30H
0173 C9 RET
;
;
;
;************************************************************
; MESSAGE TABLE FOR OPERATIONAL CPU TEST
;************************************************************
;
0174 0C 0D 0A 20 OKCPU: DB 0CH,0DH,0AH,' CPU IS OPERATIONAL$'
. . .
0188 41 4C 24
;
018B 0C 0D 0A 20 NGCPU: DB 0CH,0DH,0AH,' CPU HAS FAILED! ERROR EXIT=$'
. . .
01A7 49 54 3D 24
;
;
;
;************************************************************
; 8080/8085 CPU TEST/DIAGNOSTIC
;************************************************************
;
;NOTE: (1) PROGRAM ASSUMES "CALL",AND "LXI SP" INSTRUCTIONS WORK!
;
; (2) INSTRUCTIONS NOT TESTED ARE "HLT","DI","EI","RIM","SIM",
; AND "RST 0" THRU "RST 7"
;
;
;
;TEST JUMP INSTRUCTIONS AND FLAGS
;
01AB 31 AD 06 CPU: LXI SP,STACK ;SET THE STACK POINTER
01AE E6 00 ANI 0 ;INITIALIZE A REG. AND CLEAR ALL FLAGS
01B0 CA B6 01 JZ J010 ;TEST "JZ"
01B3 CD 89 06 CALL CPUER
01B6 D2 BC 01 J010: JNC J020 ;TEST "JNC"
01B9 CD 89 06 CALL CPUER
01BC EA C2 01 J020: JPE J030 ;TEST "JPE"
01BF CD 89 06 CALL CPUER
01C2 F2 C8 01 J030: JP J040 ;TEST "JP"
01C5 CD 89 06 CALL CPUER
01C8 C2 D7 01 J040: JNZ J050 ;TEST "JNZ"
01CB DA D7 01 JC J050 ;TEST "JC"
01CE E2 D7 01 JPO J050 ;TEST "JPO"
01D1 FA D7 01 JM J050 ;TEST "JM"
01D4 C3 DA 01 JMP J060 ;TEST "JMP" (IT'S A LITTLE LATE,BUT WHAT THE HELL!
01D7 CD 89 06 J050: CALL CPUER
01DA C6 06 J060: ADI 6 ;A=6,C=0,P=1,S=0,Z=0
01DC C2 E2 01 JNZ J070 ;TEST "JNZ"
01DF CD 89 06 CALL CPUER
01E2 DA EB 01 J070: JC J080 ;TEST "JC"
01E5 E2 EB 01 JPO J080 ;TEST "JPO"
01E8 F2 EE 01 JP J090 ;TEST "JP"
01EB CD 89 06 J080: CALL CPUER
01EE C6 70 J090: ADI 070H ;A=76H,C=0,P=0,S=0,Z=0
01F0 E2 F6 01 JPO J100 ;TEST "JPO"
01F3 CD 89 06 CALL CPUER
01F6 FA FF 01 J100: JM J110 ;TEST "JM"
01F9 CA FF 01 JZ J110 ;TEST "JZ"
01FC D2 02 02 JNC J120 ;TEST "JNC"
01FF CD 89 06 J110: CALL CPUER
0202 C6 81 J120: ADI 081H ;A=F7H,C=0,P=0,S=1,Z=0
0204 FA 0A 02 JM J130 ;TEST "JM"
0207 CD 89 06 CALL CPUER
020A CA 13 02 J130: JZ J140 ;TEST "JZ"
020D DA 13 02 JC J140 ;TEST "JC"
0210 E2 16 02 JPO J150 ;TEST "JPO"
0213 CD 89 06 J140: CALL CPUER
0216 C6 FE J150: ADI 0FEH ;A=F5H,C=1,P=1,S=1,Z=0
0218 DA 1E 02 JC J160 ;TEST "JC"
021B CD 89 06 CALL CPUER
021E CA 27 02 J160: JZ J170 ;TEST "JZ"
0221 E2 27 02 JPO J170 ;TEST "JPO"
0224 FA 2A 02 JM AIMM ;TEST "JM"
0227 CD 89 06 J170: CALL CPUER
;
;
;
;TEST ACCUMULATOR IMMEDIATE INSTRUCTIONS
;
022A FE 00 AIMM: CPI 0 ;A=F5H,C=0,Z=0
022C DA 42 02 JC CPIE ;TEST "CPI" FOR RE-SET CARRY
022F CA 42 02 JZ CPIE ;TEST "CPI" FOR RE-SET ZERO
0232 FE F5 CPI 0F5H ;A=F5H,C=0,Z=1
0234 DA 42 02 JC CPIE ;TEST "CPI" FOR RE-SET CARRY ("ADI")
0237 C2 42 02 JNZ CPIE ;TEST "CPI" FOR RE-SET ZERO
023A FE FF CPI 0FFH ;A=F5H,C=1,Z=0
023C CA 42 02 JZ CPIE ;TEST "CPI" FOR RE-SET ZERO
023F DA 45 02 JC ACII ;TEST "CPI" FOR SET CARRY
0242 CD 89 06 CPIE: CALL CPUER
0245 CE 0A ACII: ACI 00AH ;A=F5H+0AH+CARRY(1)=0,C=1
0247 CE 0A ACI 00AH ;A=0+0AH+CARRY(0)=0BH,C=0
0249 FE 0B CPI 00BH
024B CA 51 02 JZ SUII ;TEST "ACI"
024E CD 89 06 CALL CPUER
0251 D6 0C SUII: SUI 00CH ;A=FFH,C=0
0253 D6 0F SUI 00FH ;A=F0H,C=1
0255 FE F0 CPI 0F0H
0257 CA 5D 02 JZ SBII ;TEST "SUI"
025A CD 89 06 CALL CPUER
025D DE F1 SBII: SBI 0F1H ;A=F0H-0F1H-CARRY(0)=FFH,C=1
025F DE 0E SBI 00EH ;A=FFH-OEH-CARRY(1)=F0H,C=0
0261 FE F0 CPI 0F0H
0263 CA 69 02 JZ ANII ;TEST "SBI"
0266 CD 89 06 CALL CPUER
0269 E6 55 ANII: ANI 055H ;A=F0H55H=50H,C=0,P=1,S=0,Z=0
026B FE 50 CPI 050H
026D CA 73 02 JZ ORII ;TEST "ANI"
0270 CD 89 06 CALL CPUER
0273 F6 3A ORII: ORI 03AH ;A=50H3AH=7AH,C=0,P=0,S=0,Z=0
0275 FE 7A CPI 07AH
0277 CA 7D 02 JZ XRII ;TEST "ORI"
027A CD 89 06 CALL CPUER
027D EE 0F XRII: XRI 00FH ;A=7AH0FH=75H,C=0,P=0,S=0,Z=0
027F FE 75 CPI 075H
0281 CA 87 02 JZ C010 ;TEST "XRI"
0284 CD 89 06 CALL CPUER
;
;
;
;TEST CALLS AND RETURNS
;
0287 E6 00 C010: ANI 000H ;A=0,C=0,P=1,S=0,Z=1
0289 DC 89 06 CC CPUER ;TEST "CC"
028C E4 89 06 CPO CPUER ;TEST "CPO"
028F FC 89 06 CM CPUER ;TEST "CM"
0292 C4 89 06 CNZ CPUER ;TEST "CNZ"
0295 FE 00 CPI 000H
0297 CA 9D 02 JZ C020 ;A=0,C=0,P=0,S=0,Z=1
029A CD 89 06 CALL CPUER
029D D6 77 C020: SUI 077H ;A=89H,C=1,P=0,S=1,Z=0
029F D4 89 06 CNC CPUER ;TEST "CNC"
02A2 EC 89 06 CPE CPUER ;TEST "CPE"
02A5 F4 89 06 CP CPUER ;TEST "CP"
02A8 CC 89 06 CZ CPUER ;TEST "CZ"
02AB FE 89 CPI 089H
02AD CA B3 02 JZ C030 ;TEST FOR "CALLS" TAKING BRANCH
02B0 CD 89 06 CALL CPUER
02B3 E6 FF C030: ANI 0FFH ;SET FLAGS BACK!
02B5 E4 C0 02 CPO CPOI ;TEST "CPO"
02B8 FE D9 CPI 0D9H
02BA CA 1D 03 JZ MOVI ;TEST "CALL" SEQUENCE SUCCESS
02BD CD 89 06 CALL CPUER
02C0 E8 CPOI: RPE ;TEST "RPE"
02C1 C6 10 ADI 010H ;A=99H,C=0,P=0,S=1,Z=0
02C3 EC CC 02 CPE CPEI ;TEST "CPE"
02C6 C6 02 ADI 002H ;A=D9H,C=0,P=0,S=1,Z=0
02C8 E0 RPO ;TEST "RPO"
02C9 CD 89 06 CALL CPUER
02CC E0 CPEI: RPO ;TEST "RPO"
02CD C6 20 ADI 020H ;A=B9H,C=0,P=0,S=1,Z=0
02CF FC D8 02 CM CMI ;TEST "CM"
02D2 C6 04 ADI 004H ;A=D7H,C=0,P=1,S=1,Z=0
02D4 E8 RPE ;TEST "RPE"
02D5 CD 89 06 CALL CPUER
02D8 F0 CMI: RP ;TEST "RP"
02D9 C6 80 ADI 080H ;A=39H,C=1,P=1,S=0,Z=0
02DB F4 E4 02 CP TCPI ;TEST "CP"
02DE C6 80 ADI 080H ;A=D3H,C=0,P=0,S=1,Z=0
02E0 F8 RM ;TEST "RM"
02E1 CD 89 06 CALL CPUER
02E4 F8 TCPI: RM ;TEST "RM"
02E5 C6 40 ADI 040H ;A=79H,C=0,P=0,S=0,Z=0
02E7 D4 F0 02 CNC CNCI ;TEST "CNC"
02EA C6 40 ADI 040H ;A=53H,C=0,P=1,S=0,Z=0
02EC F0 RP ;TEST "RP"
02ED CD 89 06 CALL CPUER
02F0 D8 CNCI: RC ;TEST "RC"
02F1 C6 8F ADI 08FH ;A=08H,C=1,P=0,S=0,Z=0
02F3 DC FC 02 CC CCI ;TEST "CC"
02F6 D6 02 SUI 002H ;A=13H,C=0,P=0,S=0,Z=0
02F8 D0 RNC ;TEST "RNC"
02F9 CD 89 06 CALL CPUER
02FC D0 CCI: RNC ;TEST "RNC"
02FD C6 F7 ADI 0F7H ;A=FFH,C=0,P=1,S=1,Z=0
02FF C4 08 03 CNZ CNZI ;TEST "CNZ"
0302 C6 FE ADI 0FEH ;A=15H,C=1,P=0,S=0,Z=0
0304 D8 RC ;TEST "RC"
0305 CD 89 06 CALL CPUER
0308 C8 CNZI: RZ ;TEST "RZ"
0309 C6 01 ADI 001H ;A=00H,C=1,P=1,S=0,Z=1
030B CC 14 03 CZ CZI ;TEST "CZ"
030E C6 D0 ADI 0D0H ;A=17H,C=1,P=1,S=0,Z=0
0310 C0 RNZ ;TEST "RNZ"
0311 CD 89 06 CALL CPUER
0314 C0 CZI: RNZ ;TEST "RNZ"
0315 C6 47 ADI 047H ;A=47H,C=0,P=1,S=0,Z=0
0317 FE 47 CPI 047H ;A=47H,C=0,P=1,S=0,Z=1
0319 C8 RZ ;TEST "RZ"
031A CD 89 06 CALL CPUER
;
;
;
;TEST "MOV","INR",AND "DCR" INSTRUCTIONS
;
031D 3E 77 MOVI: MVI A,077H
031F 3C INR A
0320 47 MOV B,A
0321 04 INR B
0322 48 MOV C,B
0323 0D DCR C
0324 51 MOV D,C
0325 5A MOV E,D
0326 63 MOV H,E
0327 6C MOV L,H
0328 7D MOV A,L ;TEST "MOV" A,L,H,E,D,C,B,A
0329 3D DCR A
032A 4F MOV C,A
032B 59 MOV E,C
032C 6B MOV L,E
032D 45 MOV B,L
032E 50 MOV D,B
032F 62 MOV H,D
0330 7C MOV A,H ;TEST "MOV" A,H,D,B,L,E,C,A
0331 57 MOV D,A
0332 14 INR D
0333 6A MOV L,D
0334 4D MOV C,L
0335 0C INR C
0336 61 MOV H,C
0337 44 MOV B,H
0338 05 DCR B
0339 58 MOV E,B
033A 7B MOV A,E ;TEST "MOV" A,E,B,H,C,L,D,A
033B 5F MOV E,A
033C 1C INR E
033D 43 MOV B,E
033E 60 MOV H,B
033F 24 INR H
0340 4C MOV C,H
0341 69 MOV L,C
0342 55 MOV D,L
0343 15 DCR D
0344 7A MOV A,D ;TEST "MOV" A,D,L,C,H,B,E,A
0345 67 MOV H,A
0346 25 DCR H
0347 54 MOV D,H
0348 42 MOV B,D
0349 68 MOV L,B
034A 2C INR L
034B 5D MOV E,L
034C 1D DCR E
034D 4B MOV C,E
034E 79 MOV A,C ;TEST "MOV" A,C,E,L,B,D,H,A
034F 6F MOV L,A
0350 2D DCR L
0351 65 MOV H,L
0352 5C MOV E,H
0353 53 MOV D,E
0354 4A MOV C,D
0355 41 MOV B,C
0356 78 MOV A,B
0357 FE 77 CPI 077H
0359 C4 89 06 CNZ CPUER ;TEST "MOV" A,B,C,D,E,H,L,A
;
;
;
;TEST ARITHMETIC AND LOGIC INSTRUCTIONS
;
035C AF XRA A
035D 06 01 MVI B,001H
035F 0E 03 MVI C,003H
0361 16 07 MVI D,007H
0363 1E 0F MVI E,00FH
0365 26 1F MVI H,01FH
0367 2E 3F MVI L,03FH
0369 80 ADD B
036A 81 ADD C
036B 82 ADD D
036C 83 ADD E
036D 84 ADD H
036E 85 ADD L
036F 87 ADD A
0370 FE F0 CPI 0F0H
0372 C4 89 06 CNZ CPUER ;TEST "ADD" B,C,D,E,H,L,A
0375 90 SUB B
0376 91 SUB C
0377 92 SUB D
0378 93 SUB E
0379 94 SUB H
037A 95 SUB L
037B FE 78 CPI 078H
037D C4 89 06 CNZ CPUER ;TEST "SUB" B,C,D,E,H,L
0380 97 SUB A
0381 C4 89 06 CNZ CPUER ;TEST "SUB" A
0384 3E 80 MVI A,080H
0386 87 ADD A
0387 06 01 MVI B,001H
0389 0E 02 MVI C,002H
038B 16 03 MVI D,003H
038D 1E 04 MVI E,004H
038F 26 05 MVI H,005H
0391 2E 06 MVI L,006H
0393 88 ADC B
0394 06 80 MVI B,080H
0396 80 ADD B
0397 80 ADD B
0398 89 ADC C
0399 80 ADD B
039A 80 ADD B
039B 8A ADC D
039C 80 ADD B
039D 80 ADD B
039E 8B ADC E
039F 80 ADD B
03A0 80 ADD B
03A1 8C ADC H
03A2 80 ADD B
03A3 80 ADD B
03A4 8D ADC L
03A5 80 ADD B
03A6 80 ADD B
03A7 8F ADC A
03A8 FE 37 CPI 037H
03AA C4 89 06 CNZ CPUER ;TEST "ADC" B,C,D,E,H,L,A
03AD 3E 80 MVI A,080H
03AF 87 ADD A
03B0 06 01 MVI B,001H
03B2 98 SBB B
03B3 06 FF MVI B,0FFH
03B5 80 ADD B
03B6 99 SBB C
03B7 80 ADD B
03B8 9A SBB D
03B9 80 ADD B
03BA 9B SBB E
03BB 80 ADD B
03BC 9C SBB H
03BD 80 ADD B
03BE 9D SBB L
03BF FE E0 CPI 0E0H
03C1 C4 89 06 CNZ CPUER ;TEST "SBB" B,C,D,E,H,L
03C4 3E 80 MVI A,080H
03C6 87 ADD A
03C7 9F SBB A
03C8 FE FF CPI 0FFH
03CA C4 89 06 CNZ CPUER ;TEST "SBB" A
03CD 3E FF MVI A,0FFH
03CF 06 FE MVI B,0FEH
03D1 0E FC MVI C,0FCH
03D3 16 EF MVI D,0EFH
03D5 1E 7F MVI E,07FH
03D7 26 F4 MVI H,0F4H
03D9 2E BF MVI L,0BFH
03DB A7 ANA A
03DC A1 ANA C
03DD A2 ANA D
03DE A3 ANA E
03DF A4 ANA H
03E0 A5 ANA L
03E1 A7 ANA A
03E2 FE 24 CPI 024H
03E4 C4 89 06 CNZ CPUER ;TEST "ANA" B,C,D,E,H,L,A
03E7 AF XRA A
03E8 06 01 MVI B,001H
03EA 0E 02 MVI C,002H
03EC 16 04 MVI D,004H
03EE 1E 08 MVI E,008H
03F0 26 10 MVI H,010H
03F2 2E 20 MVI L,020H
03F4 B0 ORA B
03F5 B1 ORA C
03F6 B2 ORA D
03F7 B3 ORA E
03F8 B4 ORA H
03F9 B5 ORA L
03FA B7 ORA A
03FB FE 3F CPI 03FH
03FD C4 89 06 CNZ CPUER ;TEST "ORA" B,C,D,E,H,L,A
0400 3E 00 MVI A,000H
0402 26 8F MVI H,08FH
0404 2E 4F MVI L,04FH
0406 A8 XRA B
0407 A9 XRA C
0408 AA XRA D
0409 AB XRA E
040A AC XRA H
040B AD XRA L
040C FE CF CPI 0CFH
040E C4 89 06 CNZ CPUER ;TEST "XRA" B,C,D,E,H,L
0411 AF XRA A
0412 C4 89 06 CNZ CPUER ;TEST "XRA" A
0415 06 44 MVI B,044H
0417 0E 45 MVI C,045H
0419 16 46 MVI D,046H
041B 1E 47 MVI E,047H
041D 26 06 MVI H,(TEMP0 / 0FFH) ;HIGH BYTE OF TEST MEMORY LOCATION
041F 2E A6 MVI L,(TEMP0 AND 0FFH) ;LOW BYTE OF TEST MEMORY LOCATION
0421 70 MOV M,B
0422 06 00 MVI B,000H
0424 46 MOV B,M
0425 3E 44 MVI A,044H
0427 B8 CMP B
0428 C4 89 06 CNZ CPUER ;TEST "MOV" M,B AND B,M
042B 72 MOV M,D
042C 16 00 MVI D,000H
042E 56 MOV D,M
042F 3E 46 MVI A,046H
0431 BA CMP D
0432 C4 89 06 CNZ CPUER ;TEST "MOV" M,D AND D,M
0435 73 MOV M,E
0436 1E 00 MVI E,000H
0438 5E MOV E,M
0439 3E 47 MVI A,047H
043B BB CMP E
043C C4 89 06 CNZ CPUER ;TEST "MOV" M,E AND E,M
043F 74 MOV M,H
0440 26 06 MVI H,(TEMP0 / 0FFH)
0442 2E A6 MVI L,(TEMP0 AND 0FFH)
0444 66 MOV H,M
0445 3E 06 MVI A,(TEMP0 / 0FFH)
0447 BC CMP H
0448 C4 89 06 CNZ CPUER ;TEST "MOV" M,H AND H,M
044B 75 MOV M,L
044C 26 06 MVI H,(TEMP0 / 0FFH)
044E 2E A6 MVI L,(TEMP0 AND 0FFH)
0450 6E MOV L,M
0451 3E A6 MVI A,(TEMP0 AND 0FFH)
0453 BD CMP L
0454 C4 89 06 CNZ CPUER ;TEST "MOV" M,L AND L,M
0457 26 06 MVI H,(TEMP0 / 0FFH)
0459 2E A6 MVI L,(TEMP0 AND 0FFH)
045B 3E 32 MVI A,032H
045D 77 MOV M,A
045E BE CMP M
045F C4 89 06 CNZ CPUER ;TEST "MOV" M,A
0462 86 ADD M
0463 FE 64 CPI 064H
0465 C4 89 06 CNZ CPUER ;TEST "ADD" M
0468 AF XRA A
0469 7E MOV A,M
046A FE 32 CPI 032H
046C C4 89 06 CNZ CPUER ;TEST "MOV" A,M
046F 26 06 MVI H,(TEMP0 / 0FFH)
0471 2E A6 MVI L,(TEMP0 AND 0FFH)
0473 7E MOV A,M
0474 96 SUB M
0475 C4 89 06 CNZ CPUER ;TEST "SUB" M
0478 3E 80 MVI A,080H
047A 87 ADD A
047B 8E ADC M
047C FE 33 CPI 033H
047E C4 89 06 CNZ CPUER ;TEST "ADC" M
0481 3E 80 MVI A,080H
0483 87 ADD A
0484 9E SBB M
0485 FE CD CPI 0CDH
0487 C4 89 06 CNZ CPUER ;TEST "SBB" M
048A A6 ANA M
048B C4 89 06 CNZ CPUER ;TEST "ANA" M
048E 3E 25 MVI A,025H
0490 B6 ORA M
0491 FE 37 CPI 037H
0493 C4 89 06 CNZ CPUER ;TEST "ORA" M
0496 AE XRA M
0497 FE 05 CPI 005H
0499 C4 89 06 CNZ CPUER ;TEST "XRA" M
049C 36 55 MVI M,055H
049E 34 INR M
049F 35 DCR M
04A0 86 ADD M
04A1 FE 5A CPI 05AH
04A3 C4 89 06 CNZ CPUER ;TEST "INR","DCR",AND "MVI" M
04A6 01 FF 12 LXI B,12FFH
04A9 11 FF 12 LXI D,12FFH
04AC 21 FF 12 LXI H,12FFH
04AF 03 INX B
04B0 13 INX D
04B1 23 INX H
04B2 3E 13 MVI A,013H
04B4 B8 CMP B
04B5 C4 89 06 CNZ CPUER ;TEST "LXI" AND "INX" B
04B8 BA CMP D
04B9 C4 89 06 CNZ CPUER ;TEST "LXI" AND "INX" D
04BC BC CMP H
04BD C4 89 06 CNZ CPUER ;TEST "LXI" AND "INX" H
04C0 3E 00 MVI A,000H
04C2 B9 CMP C
04C3 C4 89 06 CNZ CPUER ;TEST "LXI" AND "INX" B
04C6 BB CMP E
04C7 C4 89 06 CNZ CPUER ;TEST "LXI" AND "INX" D
04CA BD CMP L
04CB C4 89 06 CNZ CPUER ;TEST "LXI" AND "INX" H
04CE 0B DCX B
04CF 1B DCX D
04D0 2B DCX H
04D1 3E 12 MVI A,012H
04D3 B8 CMP B
04D4 C4 89 06 CNZ CPUER ;TEST "DCX" B
04D7 BA CMP D
04D8 C4 89 06 CNZ CPUER ;TEST "DCX" D
04DB BC CMP H
04DC C4 89 06 CNZ CPUER ;TEST "DCX" H
04DF 3E FF MVI A,0FFH
04E1 B9 CMP C
04E2 C4 89 06 CNZ CPUER ;TEST "DCX" B
04E5 BB CMP E
04E6 C4 89 06 CNZ CPUER ;TEST "DCX" D
04E9 BD CMP L
04EA C4 89 06 CNZ CPUER ;TEST "DCX" H
04ED 32 A6 06 STA TEMP0
04F0 AF XRA A
04F1 3A A6 06 LDA TEMP0
04F4 FE FF CPI 0FFH
04F6 C4 89 06 CNZ CPUER ;TEST "LDA" AND "STA"
04F9 2A A4 06 LHLD TEMPP
04FC 22 A6 06 SHLD TEMP0
04FF 3A A4 06 LDA TEMPP
0502 47 MOV B,A
0503 3A A6 06 LDA TEMP0
0506 B8 CMP B
0507 C4 89 06 CNZ CPUER ;TEST "LHLD" AND "SHLD"
050A 3A A5 06 LDA TEMPP+1
050D 47 MOV B,A
050E 3A A7 06 LDA TEMP0+1
0511 B8 CMP B
0512 C4 89 06 CNZ CPUER ;TEST "LHLD" AND "SHLD"
0515 3E AA MVI A,0AAH
0517 32 A6 06 STA TEMP0
051A 44 MOV B,H
051B 4D MOV C,L
051C AF XRA A
051D 0A LDAX B
051E FE AA CPI 0AAH
0520 C4 89 06 CNZ CPUER ;TEST "LDAX" B
0523 3C INR A
0524 02 STAX B
0525 3A A6 06 LDA TEMP0
0528 FE AB CPI 0ABH
052A C4 89 06 CNZ CPUER ;TEST "STAX" B
052D 3E 77 MVI A,077H
052F 32 A6 06 STA TEMP0
0532 2A A4 06 LHLD TEMPP
0535 11 00 00 LXI D,00000H
0538 EB XCHG
0539 AF XRA A
053A 1A LDAX D
053B FE 77 CPI 077H
053D C4 89 06 CNZ CPUER ;TEST "LDAX" D AND "XCHG"
0540 AF XRA A
0541 84 ADD H
0542 85 ADD L
0543 C4 89 06 CNZ CPUER ;TEST "XCHG"
0546 3E CC MVI A,0CCH
0548 12 STAX D
0549 3A A6 06 LDA TEMP0
054C FE CC CPI 0CCH
054E 12 STAX D
054F 3A A6 06 LDA TEMP0
0552 FE CC CPI 0CCH
0554 C4 89 06 CNZ CPUER ;TEST "STAX" D
0557 21 77 77 LXI H,07777H
055A 29 DAD H
055B 3E EE MVI A,0EEH
055D BC CMP H
055E C4 89 06 CNZ CPUER ;TEST "DAD" H
0561 BD CMP L
0562 C4 89 06 CNZ CPUER ;TEST "DAD" H
0565 21 55 55 LXI H,05555H
0568 01 FF FF LXI B,0FFFFH
056B 09 DAD B
056C 3E 55 MVI A,055H
056E D4 89 06 CNC CPUER ;TEST "DAD" B
0571 BC CMP H
0572 C4 89 06 CNZ CPUER ;TEST "DAD" B
0575 3E 54 MVI A,054H
0577 BD CMP L
0578 C4 89 06 CNZ CPUER ;TEST "DAD" B
057B 21 AA AA LXI H,0AAAAH
057E 11 33 33 LXI D,03333H
0581 19 DAD D
0582 3E DD MVI A,0DDH
0584 BC CMP H
0585 C4 89 06 CNZ CPUER ;TEST "DAD" D
0588 BD CMP L
0589 C4 89 06 CNZ CPUER ;TEST "DAD" B
058C 37 STC
058D D4 89 06 CNC CPUER ;TEST "STC"
0590 3F CMC
0591 DC 89 06 CC CPUER ;TEST "CMC
0594 3E AA MVI A,0AAH
0596 2F CMA
0597 FE 55 CPI 055H
0599 C4 89 06 CNZ CPUER ;TEST "CMA"
059C B7 ORA A ;RE-SET AUXILIARY CARRY
059D 27 DAA
059E FE 55 CPI 055H
05A0 C4 89 06 CNZ CPUER ;TEST "DAA"
05A3 3E 88 MVI A,088H
05A5 87 ADD A
05A6 27 DAA
05A7 FE 76 CPI 076H
05A9 C4 89 06 CNZ CPUER ;TEST "DAA"
05AC AF XRA A
05AD 3E AA MVI A,0AAH
05AF 27 DAA
05B0 D4 89 06 CNC CPUER ;TEST "DAA"
05B3 FE 10 CPI 010H
05B5 C4 89 06 CNZ CPUER ;TEST "DAA"
05B8 AF XRA A
05B9 3E 9A MVI A,09AH
05BB 27 DAA
05BC D4 89 06 CNC CPUER ;TEST "DAA"
05BF C4 89 06 CNZ CPUER ;TEST "DAA"
05C2 37 STC
05C3 3E 42 MVI A,042H
05C5 07 RLC
05C6 DC 89 06 CC CPUER ;TEST "RLC" FOR RE-SET CARRY
05C9 07 RLC
05CA D4 89 06 CNC CPUER ;TEST "RLC" FOR SET CARRY
05CD FE 09 CPI 009H
05CF C4 89 06 CNZ CPUER ;TEST "RLC" FOR ROTATION
05D2 0F RRC
05D3 D4 89 06 CNC CPUER ;TEST "RRC" FOR SET CARRY
05D6 0F RRC
05D7 FE 42 CPI 042H
05D9 C4 89 06 CNZ CPUER ;TEST "RRC" FOR ROTATION
05DC 17 RAL
05DD 17 RAL
05DE D4 89 06 CNC CPUER ;TEST "RAL" FOR SET CARRY
05E1 FE 08 CPI 008H
05E3 C4 89 06 CNZ CPUER ;TEST "RAL" FOR ROTATION
05E6 1F RAR
05E7 1F RAR
05E8 DC 89 06 CC CPUER ;TEST "RAR" FOR RE-SET CARRY
05EB FE 02 CPI 002H
05ED C4 89 06 CNZ CPUER ;TEST "RAR" FOR ROTATION
05F0 01 34 12 LXI B,01234H
05F3 11 AA AA LXI D,0AAAAH
05F6 21 55 55 LXI H,05555H
05F9 AF XRA A
05FA C5 PUSH B
05FB D5 PUSH D
05FC E5 PUSH H
05FD F5 PUSH PSW
05FE 01 00 00 LXI B,00000H
0601 11 00 00 LXI D,00000H
0604 21 00 00 LXI H,00000H
0607 3E C0 MVI A,0C0H
0609 C6 F0 ADI 0F0H
060B F1 POP PSW
060C E1 POP H
060D D1 POP D
060E C1 POP B
060F DC 89 06 CC CPUER ;TEST "PUSH PSW" AND "POP PSW"
0612 C4 89 06 CNZ CPUER ;TEST "PUSH PSW" AND "POP PSW"
0615 E4 89 06 CPO CPUER ;TEST "PUSH PSW" AND "POP PSW"
0618 FC 89 06 CM CPUER ;TEST "PUSH PSW" AND "POP PSW"
061B 3E 12 MVI A,012H
061D B8 CMP B
061E C4 89 06 CNZ CPUER ;TEST "PUSH B" AND "POP B"
0621 3E 34 MVI A,034H
0623 B9 CMP C
0624 C4 89 06 CNZ CPUER ;TEST "PUSH B" AND "POP B"
0627 3E AA MVI A,0AAH
0629 BA CMP D
062A C4 89 06 CNZ CPUER ;TEST "PUSH D" AND "POP D"
062D BB CMP E
062E C4 89 06 CNZ CPUER ;TEST "PUSH D" AND "POP D"
0631 3E 55 MVI A,055H
0633 BC CMP H
0634 C4 89 06 CNZ CPUER ;TEST "PUSH H" AND "POP H"
0637 BD CMP L
0638 C4 89 06 CNZ CPUER ;TEST "PUSH H" AND "POP H"
063B 21 00 00 LXI H,00000H
063E 39 DAD SP
063F 22 AB 06 SHLD SAVSTK ;SAVE THE "OLD" STACK-POINTER!
0642 31 AA 06 LXI SP,TEMP4
0645 3B DCX SP
0646 3B DCX SP
0647 33 INX SP
0648 3B DCX SP
0649 3E 55 MVI A,055H
064B 32 A8 06 STA TEMP2
064E 2F CMA
064F 32 A9 06 STA TEMP3
0652 C1 POP B
0653 B8 CMP B
0654 C4 89 06 CNZ CPUER ;TEST "LXI","DAD","INX",AND "DCX" SP
0657 2F CMA
0658 B9 CMP C
0659 C4 89 06 CNZ CPUER ;TEST "LXI","DAD","INX", AND "DCX" SP
065C 21 AA 06 LXI H,TEMP4
065F F9 SPHL
0660 21 33 77 LXI H,07733H
0663 3B DCX SP
0664 3B DCX SP
0665 E3 XTHL
0666 3A A9 06 LDA TEMP3
0669 FE 77 CPI 077H
066B C4 89 06 CNZ CPUER ;TEST "SPHL" AND "XTHL"
066E 3A A8 06 LDA TEMP2
0671 FE 33 CPI 033H
0673 C4 89 06 CNZ CPUER ;TEST "SPHL" AND "XTHL"
0676 3E 55 MVI A,055H
0678 BD CMP L
0679 C4 89 06 CNZ CPUER ;TEST "SPHL" AND "XTHL"
067C 2F CMA
067D BC CMP H
067E C4 89 06 CNZ CPUER ;TEST "SPHL" AND "XTHL"
0681 2A AB 06 LHLD SAVSTK ;RESTORE THE "OLD" STACK-POINTER
0684 F9 SPHL
0685 21 9B 06 LXI H,CPUOK
0688 E9 PCHL ;TEST "PCHL"
;
;
;
0689 21 8B 01 CPUER: LXI H,NGCPU ;OUTPUT "CPU HAS FAILED ERROR EXIT=" TO CONSOLE
068C CD 45 01 CALL MSG
068F E3 XTHL
0690 7C MOV A,H
0691 CD 54 01 CALL BYTEO ;SHOW ERROR EXIT ADDRESS HIGH BYTE
0694 7D MOV A,L
0695 CD 54 01 CALL BYTEO ;SHOW ERROR EXIT ADDRESS LOW BYTE
0698 C3 00 00 JMP WBOOT ;EXIT TO CP/M WARM BOOT
;
;
;
069B 21 74 01 CPUOK: LXI H,OKCPU ;OUTPUT "CPU IS OPERATIONAL" TO CONSOLE
069E CD 45 01 CALL MSG
06A1 C3 00 00 JMP WBOOT ;EXIT TO CP/M WARM BOOT
;
;
;
06A4 A6 06 TEMPP: DW TEMP0 ;POINTER USED TO TEST "LHLD","SHLD",
; AND "LDAX" INSTRUCTIONS
;
06A6 00 TEMP0: DS 1 ;TEMPORARY STORAGE FOR CPU TEST MEMORY LOCATIONS
06A7 00 TEMP1: DS 1 ;TEMPORARY STORAGE FOR CPU TEST MEMORY LOCATIONS
06A8 00 TEMP2 DS 1 ;TEMPORARY STORAGE FOR CPU TEST MEMORY LOCATIONS
06A9 00 TEMP3: DS 1 ;TEMPORARY STORAGE FOR CPU TEST MEMORY LOCATIONS
06AA 00 TEMP4: DS 1 ;TEMPORARY STORAGE FOR CPU TEST MEMORY LOCATIONS
06AB 00 00 SAVSTK: DS 2 ;TEMPORARY STACK-POINTER STORAGE LOCATION
;
;
;
STACK EQU TEMPP+256 ;DE-BUG STACK POINTER STORAGE AREA
;
;
;
END
;
;
;
Labels:
acii 0245aimm 022Aanii 0269bdos 0005
byteo 0154byto1 0164byto2 0168byto3 0171
c010 0287c020 029Dc030 02B3cci 02FC
cmi 02D8cnci 02F0cnzi 0308cpei 02CC
cpie 0242cpoi 02C0cpu 01ABcpuer 0689
cpuok 069Bczi 0314end 06ADj010 01B6
j020 01BCj030 01C2j040 01C8j050 01D7
j060 01DAj070 01E2j080 01EBj090 01EE
j100 01F6j110 01FFj120 0202j130 020A
j140 0213j150 0216j160 021Ej170 0227
movi 031Dmsg 0145ngcpu 018Bokcpu 0174
orii 0273pchar 014Esavstk 06ABsbii 025D
stack 06ADsuii 0251tcpi 02E4temp0 06A6
temp1 06A7temp2 06A8temp3 06A9temp4 06AA
tempp 06A4wboot 0000xrii 027D
Memory dump:
0100: C3 AB 01 4D 49 43 52 4F-43 4F 53 4D 20 41 53 53 ...MICROCOSM.ASS
0110: 4F 43 49 41 54 45 53 20-38 30 38 30 2F 38 30 38 OCIATES.8080/808
0120: 35 20 43 50 55 20 44 49-41 47 4E 4F 53 54 49 43 5.CPU.DIAGNOSTIC
0130: 20 56 45 52 53 49 4F 4E-20 31 2E 30 20 28 43 29 .VERSION.1.0.(C)
0140: 20 31 39 38 30 D5 EB 0E-09 CD 05 00 D1 C9 0E 02 .1980...........
0150: CD 05 00 C9 F5 CD 64 01-5F CD 4E 01 F1 CD 68 01 ......d._.N...h.
0160: 5F C3 4E 01 0F 0F 0F 0F-E6 0F FE 0A FA 71 01 C6 _.N..........q..
0170: 07 C6 30 C9 0C 0D 0A 20-43 50 55 20 49 53 20 4F ..0.....CPU.IS.O
0180: 50 45 52 41 54 49 4F 4E-41 4C 24 0C 0D 0A 20 43 PERATIONAL$....C
0190: 50 55 20 48 41 53 20 46-41 49 4C 45 44 21 20 45 PU.HAS.FAILED!.E
01A0: 52 52 4F 52 20 45 58 49-54 3D 24 31 AD 06 E6 00 RROR.EXIT=$1....
01B0: CA B6 01 CD 89 06 D2 BC-01 CD 89 06 EA C2 01 CD ................
01C0: 89 06 F2 C8 01 CD 89 06-C2 D7 01 DA D7 01 E2 D7 ................
01D0: 01 FA D7 01 C3 DA 01 CD-89 06 C6 06 C2 E2 01 CD ................
01E0: 89 06 DA EB 01 E2 EB 01-F2 EE 01 CD 89 06 C6 70 ...............p
01F0: E2 F6 01 CD 89 06 FA FF-01 CA FF 01 D2 02 02 CD ................
0200: 89 06 C6 81 FA 0A 02 CD-89 06 CA 13 02 DA 13 02 ................
0210: E2 16 02 CD 89 06 C6 FE-DA 1E 02 CD 89 06 CA 27 ...............'
0220: 02 E2 27 02 FA 2A 02 CD-89 06 FE 00 DA 42 02 CA ..'..*.......B..
0230: 42 02 FE F5 DA 42 02 C2-42 02 FE FF CA 42 02 DA B....B..B....B..
0240: 45 02 CD 89 06 CE 0A CE-0A FE 0B CA 51 02 CD 89 E...........Q...
0250: 06 D6 0C D6 0F FE F0 CA-5D 02 CD 89 06 DE F1 DE ........].......
0260: 0E FE F0 CA 69 02 CD 89-06 E6 55 FE 50 CA 73 02 ....i.....U.P.s.
0270: CD 89 06 F6 3A FE 7A CA-7D 02 CD 89 06 EE 0F FE ....:.z.}.......
0280: 75 CA 87 02 CD 89 06 E6-00 DC 89 06 E4 89 06 FC u...............
0290: 89 06 C4 89 06 FE 00 CA-9D 02 CD 89 06 D6 77 D4 ..............w.
02A0: 89 06 EC 89 06 F4 89 06-CC 89 06 FE 89 CA B3 02 ................
02B0: CD 89 06 E6 FF E4 C0 02-FE D9 CA 1D 03 CD 89 06 ................
02C0: E8 C6 10 EC CC 02 C6 02-E0 CD 89 06 E0 C6 20 FC ................
02D0: D8 02 C6 04 E8 CD 89 06-F0 C6 80 F4 E4 02 C6 80 ................
02E0: F8 CD 89 06 F8 C6 40 D4-F0 02 C6 40 F0 CD 89 06 ......@....@....
02F0: D8 C6 8F DC FC 02 D6 02-D0 CD 89 06 D0 C6 F7 C4 ................
0300: 08 03 C6 FE D8 CD 89 06-C8 C6 01 CC 14 03 C6 D0 ................
0310: C0 CD 89 06 C0 C6 47 FE-47 C8 CD 89 06 3E 77 3C ......G.G....>w<
0320: 47 04 48 0D 51 5A 63 6C-7D 3D 4F 59 6B 45 50 62 G.H.QZcl}=OYkEPb
0330: 7C 57 14 6A 4D 0C 61 44-05 58 7B 5F 1C 43 60 24 |W.jM.aD.X{_.C`$
0340: 4C 69 55 15 7A 67 25 54-42 68 2C 5D 1D 4B 79 6F LiU.zg%TBh,].Kyo
0350: 2D 65 5C 53 4A 41 78 FE-77 C4 89 06 AF 06 01 0E -e\SJAx.w.......
0360: 03 16 07 1E 0F 26 1F 2E-3F 80 81 82 83 84 85 87 .....&..?.......
0370: FE F0 C4 89 06 90 91 92-93 94 95 FE 78 C4 89 06 ............x...
0380: 97 C4 89 06 3E 80 87 06-01 0E 02 16 03 1E 04 26 ....>..........&
0390: 05 2E 06 88 06 80 80 80-89 80 80 8A 80 80 8B 80 ................
03A0: 80 8C 80 80 8D 80 80 8F-FE 37 C4 89 06 3E 80 87 .........7...>..
03B0: 06 01 98 06 FF 80 99 80-9A 80 9B 80 9C 80 9D FE ................
03C0: E0 C4 89 06 3E 80 87 9F-FE FF C4 89 06 3E FF 06 ....>........>..
03D0: FE 0E FC 16 EF 1E 7F 26-F4 2E BF A7 A1 A2 A3 A4 .......&........
03E0: A5 A7 FE 24 C4 89 06 AF-06 01 0E 02 16 04 1E 08 ...$............
03F0: 26 10 2E 20 B0 B1 B2 B3-B4 B5 B7 FE 3F C4 89 06 &...........?...
0400: 3E 00 26 8F 2E 4F A8 A9-AA AB AC AD FE CF C4 89 >.&..O..........
0410: 06 AF C4 89 06 06 44 0E-45 16 46 1E 47 26 06 2E ......D.E.F.G&..
0420: A6 70 06 00 46 3E 44 B8-C4 89 06 72 16 00 56 3E .p..F>D....r..V>
0430: 46 BA C4 89 06 73 1E 00-5E 3E 47 BB C4 89 06 74 F....s..^>G....t
0440: 26 06 2E A6 66 3E 06 BC-C4 89 06 75 26 06 2E A6 &...f>.....u&...
0450: 6E 3E A6 BD C4 89 06 26-06 2E A6 3E 32 77 BE C4 n>.....&...>2w..
0460: 89 06 86 FE 64 C4 89 06-AF 7E FE 32 C4 89 06 26 ....d....~.2...&
0470: 06 2E A6 7E 96 C4 89 06-3E 80 87 8E FE 33 C4 89 ...~....>....3..
0480: 06 3E 80 87 9E FE CD C4-89 06 A6 C4 89 06 3E 25 .>............>%
0490: B6 FE 37 C4 89 06 AE FE-05 C4 89 06 36 55 34 35 ..7.........6U45
04A0: 86 FE 5A C4 89 06 01 FF-12 11 FF 12 21 FF 12 03 ..Z.........!...
04B0: 13 23 3E 13 B8 C4 89 06-BA C4 89 06 BC C4 89 06 .#>.............
04C0: 3E 00 B9 C4 89 06 BB C4-89 06 BD C4 89 06 0B 1B >...............
04D0: 2B 3E 12 B8 C4 89 06 BA-C4 89 06 BC C4 89 06 3E +>.............>
04E0: FF B9 C4 89 06 BB C4 89-06 BD C4 89 06 32 A6 06 .............2..
04F0: AF 3A A6 06 FE FF C4 89-06 2A A4 06 22 A6 06 3A .:.......*.."..:
0500: A4 06 47 3A A6 06 B8 C4-89 06 3A A5 06 47 3A A7 ..G:......:..G:.
0510: 06 B8 C4 89 06 3E AA 32-A6 06 44 4D AF 0A FE AA .....>.2..DM....
0520: C4 89 06 3C 02 3A A6 06-FE AB C4 89 06 3E 77 32 ...<.:.......>w2
0530: A6 06 2A A4 06 11 00 00-EB AF 1A FE 77 C4 89 06 ..*.........w...
0540: AF 84 85 C4 89 06 3E CC-12 3A A6 06 FE CC 12 3A ......>..:.....:
0550: A6 06 FE CC C4 89 06 21-77 77 29 3E EE BC C4 89 .......!ww)>....
0560: 06 BD C4 89 06 21 55 55-01 FF FF 09 3E 55 D4 89 .....!UU....>U..
0570: 06 BC C4 89 06 3E 54 BD-C4 89 06 21 AA AA 11 33 .....>T....!...3
0580: 33 19 3E DD BC C4 89 06-BD C4 89 06 37 D4 89 06 3.>.........7...
0590: 3F DC 89 06 3E AA 2F FE-55 C4 89 06 B7 27 FE 55 ?...>./.U....'.U
05A0: C4 89 06 3E 88 87 27 FE-76 C4 89 06 AF 3E AA 27 ...>..'.v....>.'
05B0: D4 89 06 FE 10 C4 89 06-AF 3E 9A 27 D4 89 06 C4 .........>.'....
05C0: 89 06 37 3E 42 07 DC 89-06 07 D4 89 06 FE 09 C4 ..7>B...........
05D0: 89 06 0F D4 89 06 0F FE-42 C4 89 06 17 17 D4 89 ........B.......
05E0: 06 FE 08 C4 89 06 1F 1F-DC 89 06 FE 02 C4 89 06 ................
05F0: 01 34 12 11 AA AA 21 55-55 AF C5 D5 E5 F5 01 00 .4....!UU.......
0600: 00 11 00 00 21 00 00 3E-C0 C6 F0 F1 E1 D1 C1 DC ....!..>........
0610: 89 06 C4 89 06 E4 89 06-FC 89 06 3E 12 B8 C4 89 ...........>....
0620: 06 3E 34 B9 C4 89 06 3E-AA BA C4 89 06 BB C4 89 .>4....>........
0630: 06 3E 55 BC C4 89 06 BD-C4 89 06 21 00 00 39 22 .>U........!..9"
0640: AB 06 31 AA 06 3B 3B 33-3B 3E 55 32 A8 06 2F 32 ..1..;;3;>U2../2
0650: A9 06 C1 B8 C4 89 06 2F-B9 C4 89 06 21 AA 06 F9 ......./....!...
0660: 21 33 77 3B 3B E3 3A A9-06 FE 77 C4 89 06 3A A8 !3w;;.:...w...:.
0670: 06 FE 33 C4 89 06 3E 55-BD C4 89 06 2F BC C4 89 ..3...>U..../...
0680: 06 2A AB 06 F9 21 9B 06-E9 21 8B 01 CD 45 01 E3 .*...!...!...E..
0690: 7C CD 54 01 7D CD 54 01-C3 00 00 21 74 01 CD 45 |.T.}.T....!t..E
06A0: 01 C3 00 00 A6 06 00 00-00 00 00 00 00 ................
Intel HEX:
cat >test.hex <<X
:20010000C3AB014D4943524F434F534D204153534F43494154455320383038302F383038F6
:20012000352043505520444941474E4F535449432056455253494F4E20312E3020284329D4
:200140002031393830D5EB0E09CD0500D1C90E02CD0500C9F5CD64015FCD4E01F1CD6801F6
:200160005FC34E010F0F0F0FE60FFE0AFA7101C607C630C90C0D0A20435055204953204F87
:200180005045524154494F4E414C240C0D0A2043505520484153204641494C4544212045DA
:2001A00052524F5220455849543D2431AD06E600CAB601CD8906D2BC01CD8906EAC201CD33
:2001C0008906F2C801CD8906C2D701DAD701E2D701FAD701C3DA01CD8906C606C2E201CD69
:2001E0008906DAEB01E2EB01F2EE01CD8906C670E2F601CD8906FAFF01CAFF01D20202CDCD
:200200008906C681FA0A02CD8906CA1302DA1302E21602CD8906C6FEDA1E02CD8906CA2777
:2002200002E22702FA2A02CD8906FE00DA4202CA4202FEF5DA4202C24202FEFFCA4202DA09
:200240004502CD8906CE0ACE0AFE0BCA5102CD8906D60CD60FFEF0CA5D02CD8906DEF1DEE2
:200260000EFEF0CA6902CD8906E655FE50CA7302CD8906F63AFE7ACA7D02CD8906EE0FFE85
:2002800075CA8702CD8906E600DC8906E48906FC8906C48906FE00CA9D02CD8906D677D4B4
:2002A0008906EC8906F48906CC8906FE89CAB302CD8906E6FFE4C002FED9CA1D03CD89064C
:2002C000E8C610ECCC02C602E0CD8906E0C620FCD802C604E8CD8906F0C680F4E402C680A2
:2002E000F8CD8906F8C640D4F002C640F0CD8906D8C68FDCFC02D602D0CD8906D0C6F7C438
:200300000803C6FED8CD8906C8C601CC1403C6D0C0CD8906C0C647FE47C8CD89063E773C8F
:200320004704480D515A636C7D3D4F596B4550627C57146A4D0C614405587B5F1C43602476
:200340004C6955157A67255442682C5D1D4B796F2D655C534A4178FE77C48906AF06010ED1
:200360000316071E0F261F2E3F80818283848587FEF0C48906909192939495FE78C489066F
:2003800097C489063E808706010E0216031E0426052E0688068080808980808A80808B8051
:2003A000808C80808D80808FFE37C489063E808706019806FF8099809A809B809C809DFE1F
:2003C000E0C489063E80879FFEFFC489063EFF06FE0EFC16EF1E7F26F42EBFA7A1A2A3A491
:2003E000A5A7FE24C48906AF06010E0216041E0826102E20B0B1B2B3B4B5B7FE3FC489063C
:200400003E00268F2E4FA8A9AAABACADFECFC48906AFC4890606440E4516461E4726062E93
:20042000A6700600463E44B8C48906721600563E46BAC48906731E005E3E47BBC489067468
:2004400026062EA6663E06BCC489067526062EA66E3EA6BDC4890626062EA63E3277BEC4A3
:20046000890686FE64C48906AF7EFE32C4890626062EA67E96C489063E80878EFE33C4894A
:20048000063E80879EFECDC48906A6C489063E25B6FE37C48906AEFE05C4890636553435C3
:2004A00086FE5AC4890601FF1211FF1221FF120313233E13B8C48906BAC48906BCC48906F4
:2004C0003E00B9C48906BBC48906BDC489060B1B2B3E12B8C48906BAC48906BCC489063EAE
:2004E000FFB9C48906BBC48906BDC4890632A606AF3AA606FEFFC489062AA40622A6063A34
:20050000A406473AA606B8C489063AA506473AA706B8C489063EAA32A606444DAF0AFEAA23
:20052000C489063C023AA606FEABC489063E7732A6062AA406110000EBAF1AFE77C4890654
:20054000AF8485C489063ECC123AA606FECC123AA606FECCC48906217777293EEEBCC48942
:2005600006BDC4890621555501FFFF093E55D48906BCC489063E54BDC4890621AAAA113332
:2005800033193EDDBCC48906BDC4890637D489063FDC89063EAA2FFE55C48906B727FE55A3
:2005A000C489063E888727FE76C48906AF3EAA27D48906FE10C48906AF3E9A27D48906C456
:2005C0008906373E4207DC890607D48906FE09C489060FD489060FFE42C489061717D48900
:2005E00006FE08C489061F1FDC8906FE02C4890601341211AAAA215555AFC5D5E5F5010005
:20060000001100002100003EC0C6F0F1E1D1C1DC8906C48906E48906FC89063E12B8C4897F
:20062000063E34B9C489063EAABAC48906BBC489063E55BCC48906BDC48906210000392205
:20064000AB0631AA063B3B333B3E5532A8062F32A906C1B8C489062FB9C4890621AA06F9D0
:200660002133773B3BE33AA906FE77C489063AA806FE33C489063E55BDC489062FBCC4895E
:20068000062AAB06F9219B06E9218B01CD4501E37CCD54017DCD5401C30000217401CD458A
:0D06A00001C30000A60600000000000000DD
:00000001FF
X
gobjcopy -I ihex test.hex -O binary test.com

1352
emulator/src/emulator.rs Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,81 @@
use crate::memory;
use crate::memory::GRAPHIC_MEMORY_SIZE;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub struct SharedState {
display: bool,
megahertz: f64,
in_1: u8,
in_2: u8,
is_paused: bool,
}
#[wasm_bindgen]
impl SharedState {
pub fn new() -> SharedState {
SharedState {
display: false,
megahertz: 2.0,
in_1: 8, // bit 3 is always 1
in_2: 0,
is_paused: false,
}
}
}
impl SharedState {
#[cfg(not(target_arch = "wasm32"))]
pub fn graphic_memory(&self) -> [u8; GRAPHIC_MEMORY_SIZE] {
let mut result: [u8; GRAPHIC_MEMORY_SIZE] = [0; GRAPHIC_MEMORY_SIZE];
let memory = memory::STATIC_MEMORY.read().unwrap();
result.clone_from_slice(&memory[0x2400..0x2400 + GRAPHIC_MEMORY_SIZE]);
result
}
fn set_vbl(&mut self, value: bool) {
self.display = value;
}
fn is_vbl(&self) -> bool { self.display }
pub fn set_megahertz(&mut self, mhz: f64) {
self.megahertz = mhz;
}
pub fn get_megahertz(&self) -> f64 {
self.megahertz
}
pub fn set_bit_in_1(&mut self, bit: u8, value: bool) {
let mask = 1 << bit;
if value {
self.in_1 |= mask;
} else {
self.in_1 &= ! mask;
}
}
pub fn get_in_1(&self) -> u8 {
self.in_1
}
pub fn set_bit_in_2(&mut self, bit: u8, value: bool) {
let mask = 1 << bit;
if value {
self.in_2 |= mask;
} else {
self.in_2 &= ! mask;
}
}
pub fn get_in_2(&self) -> u8 {
self.in_2
}
pub fn is_paused(&self) -> bool { self.is_paused }
pub fn pause(&mut self) { self.is_paused = true; }
pub fn unpause(&mut self) { self.is_paused = false; }
}

18
emulator/src/lib.rs Normal file
View File

@ -0,0 +1,18 @@
pub mod emulator;
pub mod memory;
pub mod state;
pub mod emulator_state;
pub mod opcodes;
mod test;
const VERBOSE: bool = false;
static mut VERBOSE_DISASSEMBLE: bool = false;
const VERBOSE_GRAPHIC: bool = true;
const VERBOSE_DISASSEMBLE_SECTION: bool = false;
const DISASSEMBLE_SECTION_START: usize = 0x1439;
const DISASSEMBLE_SECTION_END: usize = 0x1447;
// const DISASSEMBLE_SECTION_START: usize = 0x1439;
// const DISASSEMBLE_SECTION_END: usize = 0x1447;
const VERBOSE_MEMORY: bool = false;

89
emulator/src/memory.rs Normal file
View File

@ -0,0 +1,89 @@
use std::fs::File;
use std::io::Read;
use crate::state::State;
use crate::opcodes::Opcode;
use std::sync::{Mutex, RwLock};
use lazy_static::lazy_static;
use crate::emulator_state::SharedState;
const MEMORY_SIZE: usize = 0x10000;
pub const SCREEN_WIDTH: usize = 0x20; // 0x20 bytes (256 pixels)
pub const SCREEN_HEIGHT: usize = 0xe0;
pub const GRAPHIC_MEMORY_SIZE: usize = SCREEN_WIDTH * SCREEN_HEIGHT;
pub trait GraphicRenderer: Send {
fn draw(&mut self, x: u8, y: u8, value: u8);
fn color(&self, x: u8, y: u8) -> u8;
fn display(&self);
}
static _STATIC_MEMORY: [u8; MEMORY_SIZE] = [0; MEMORY_SIZE];
lazy_static! {
pub(crate) static ref STATIC_MEMORY: RwLock<[u8; MEMORY_SIZE]> = RwLock::new(_STATIC_MEMORY);
}
pub struct Memory {
pub verbose: bool,
}
impl Memory {
pub fn new() -> Self {
Memory {
verbose: false,
}
}
pub(crate) fn set_verbose(&mut self, v: bool) {
self.verbose = v;
}
pub fn read_file(&mut self, file_name: &str, start: usize) {
let mut file = File::open(file_name).expect("Couldn't open file");
let mut buffer = Vec::new();
file.read_to_end(&mut buffer).expect("Couldn't read file");
let mut state = State::default();
state.pc = start;
let mut i: usize = 0;
for byte in buffer {
self.write(i + state.pc, byte);
i += 1;
}
}
pub(crate) fn write(&mut self, address: usize, value: u8) {
STATIC_MEMORY.write().unwrap()[address] = value;
if self.verbose {
println!(" mem[{:04x}={:02X}]", address, value );
}
}
pub(crate) fn read(&self, i: usize) -> u8 {
STATIC_MEMORY.read().unwrap()[i]
}
pub(crate) fn read_word(&self, b0: u8, b1: u8) -> u8 {
STATIC_MEMORY.read().unwrap()[Memory::to_word(b0, b1)]
}
pub(crate) fn write_word(&mut self, b0: u8, b1: u8, value: u8) {
let address = Memory::to_word(b0, b1);
STATIC_MEMORY.write().unwrap()[address] = value;
}
pub(crate) fn disassemble(&self, opcode: &Opcode, pc: usize) -> (String, usize) {
let formatted_opcode = match opcode.size {
1 => opcode.display1(),
2 => opcode.display2(self.read(pc + 1)),
_ => opcode.display3(self.read(pc + 1), self.read(pc + 2)),
};
let result = format!("{:04x}: {}", pc, formatted_opcode);
(result, opcode.size)
}
pub(crate) fn to_word(b1: u8, b2: u8) -> usize {
return ((b2 as u16) << 8 | b1 as u16) as usize;
}
}

543
emulator/src/opcodes.rs Normal file
View File

@ -0,0 +1,543 @@
use std::collections::HashMap;
use crate::memory::Memory;
use lazy_static::lazy_static;
pub struct Opcode {
opcode: u8,
pub(crate) size: usize,
name: &'static str
}
impl Opcode {
fn new(opcode: u8, size: usize, name: &'static str) -> Opcode {
Opcode { opcode, size, name }
}
pub(crate) fn display1(&self) -> String {
let s = self.name;
format!("{:02x} {:14}", self.opcode, s)
}
pub(crate) fn display2(&self, byte1: u8) -> String {
let s = format!("{} {:02x}", self.name, byte1);
format!("{:02x} {:02x} {:14}", self.opcode, byte1, s)
}
pub(crate) fn display3(&self, byte1: u8, byte2: u8) -> String {
let s = format!("{} {:04x}", self.name, Memory::to_word(byte1, byte2));
format!("{:02x} {:02x} {:02x} {:14}", self.opcode, byte1, byte2, s)
}
}
pub const NOP: u8 = 0x00;
pub const LXI_B: u8 = 0x01;
pub const STAX_B: u8 = 0x02;
pub const INX_B: u8 = 0x03;
pub const INR_B: u8 = 0x04;
pub const DCR_B: u8 = 0x05;
pub const MVI_B: u8 = 0x06;
pub const RLC: u8 = 0x07;
pub const DAD_B: u8 = 0x09;
pub const LDAX_B: u8 = 0x0a;
pub const DCX_B: u8 = 0x0b;
pub const RRC: u8 = 0x0f;
pub const LXI_D: u8 = 0x11;
pub const STAX_D: u8 = 0x12;
pub const INX_D: u8 = 0x13;
pub const INR_C: u8 = 0x0c;
pub const DCR_C: u8 = 0x0d;
pub const MVI_C: u8 = 0x0e;
pub const INR_D: u8 = 0x14;
pub const DCR_D: u8 = 0x15;
pub const MVI_D: u8 = 0x16;
pub const RAL: u8 = 0x17;
pub const DAD_D: u8 = 0x19;
pub const LDAX_D: u8 = 0x1a;
pub const DCX_D: u8 = 0x1b;
pub const INR_E: u8 = 0x1c;
pub const DCR_E: u8 = 0x1d;
pub const MVI_E: u8 = 0x1e;
pub const RAR: u8 = 0x1f;
pub const LXI_H: u8 = 0x21;
pub const SHLD: u8 = 0x22;
pub const INX_H: u8 = 0x23;
pub const INR_H: u8 = 0x24;
pub const DCR_H: u8 = 0x25;
pub const MVI_H: u8 = 0x26;
pub const DAA: u8 = 0x27;
pub const DAD_H: u8 = 0x29;
pub const LHLD: u8 = 0x2a;
pub const DCX_H: u8 = 0x2b;
pub const INR_L: u8 = 0x2c;
pub const DCR_L: u8 = 0x2d;
pub const MVI_L: u8 = 0x2e;
pub const CMA: u8 = 0x2f;
pub const LXI_SP: u8 = 0x31;
pub const STA: u8 = 0x32;
pub const INX_SP: u8 = 0x33;
pub const INR_M: u8 = 0x34;
pub const DCR_M: u8 = 0x35;
pub const MVI_M: u8 = 0x36;
pub const STC: u8 = 0x37;
pub const DAD_SP: u8 = 0x39;
pub const LDA: u8 = 0x3a;
pub const DCX_SP: u8 = 0x3b;
pub const INR_A: u8 = 0x3c;
pub const DCR_A: u8 = 0x3d;
pub const MVI_A: u8 = 0x3e;
pub const CMC: u8 = 0x3f;
pub const MOV_B_B: u8 = 0x40;
pub const MOV_B_C: u8 = 0x41;
pub const MOV_B_D: u8 = 0x42;
pub const MOV_B_E: u8 = 0x43;
pub const MOV_B_H: u8 = 0x44;
pub const MOV_B_L: u8 = 0x45;
pub const MOV_B_M: u8 = 0x46;
pub const MOV_B_A: u8 = 0x47;
pub const MOV_C_B: u8 = 0x48;
pub const MOV_C_C: u8 = 0x49;
pub const MOV_C_D: u8 = 0x4a;
pub const MOV_C_E: u8 = 0x4b;
pub const MOV_C_H: u8 = 0x4c;
pub const MOV_C_L: u8 = 0x4d;
pub const MOV_C_M: u8 = 0x4e;
pub const MOV_C_A: u8 = 0x4f;
pub const MOV_D_B: u8 = 0x50;
pub const MOV_D_C: u8 = 0x51;
pub const MOV_D_D: u8 = 0x52;
pub const MOV_D_E: u8 = 0x53;
pub const MOV_D_H: u8 = 0x54;
pub const MOV_D_L: u8 = 0x55;
pub const MOV_D_M: u8 = 0x56;
pub const MOV_D_A: u8 = 0x57;
pub const MOV_E_B: u8 = 0x58;
pub const MOV_E_C: u8 = 0x59;
pub const MOV_E_D: u8 = 0x5a;
pub const MOV_E_E: u8 = 0x5b;
pub const MOV_E_H: u8 = 0x5c;
pub const MOV_E_L: u8 = 0x5d;
pub const MOV_E_M: u8 = 0x5e;
pub const MOV_E_A: u8 = 0x5f;
pub const MOV_H_B: u8 = 0x60;
pub const MOV_H_C: u8 = 0x61;
pub const MOV_H_D: u8 = 0x62;
pub const MOV_H_E: u8 = 0x63;
pub const MOV_H_H: u8 = 0x64;
pub const MOV_H_L: u8 = 0x65;
pub const MOV_H_M: u8 = 0x66;
pub const MOV_H_A: u8 = 0x67;
pub const MOV_L_B: u8 = 0x68;
pub const MOV_L_C: u8 = 0x69;
pub const MOV_L_D: u8 = 0x6a;
pub const MOV_L_E: u8 = 0x6b;
pub const MOV_L_H: u8 = 0x6c;
pub const MOV_L_L: u8 = 0x6d;
pub const MOV_L_M: u8 = 0x6e;
pub const MOV_L_A: u8 = 0x6f;
pub const MOV_M_B: u8 = 0x70;
pub const MOV_M_C: u8 = 0x71;
pub const MOV_M_D: u8 = 0x72;
pub const MOV_M_E: u8 = 0x73;
pub const MOV_M_H: u8 = 0x74;
pub const MOV_M_L: u8 = 0x75;
pub const MOV_M_A: u8 = 0x77;
pub const MOV_A_B: u8 = 0x78;
pub const MOV_A_C: u8 = 0x79;
pub const MOV_A_D: u8 = 0x7a;
pub const MOV_A_E: u8 = 0x7b;
pub const MOV_A_H: u8 = 0x7c;
pub const MOV_A_L: u8 = 0x7d;
pub const MOV_A_M: u8 = 0x7e;
pub const ADD_B: u8 = 0x80;
pub const ADD_C: u8 = 0x81;
pub const ADD_D: u8 = 0x82;
pub const ADD_E: u8 = 0x83;
pub const ADD_H: u8 = 0x84;
pub const ADD_L: u8 = 0x85;
pub const ADD_M: u8 = 0x86;
pub const ADD_A: u8 = 0x87;
pub const ADC_B: u8 = 0x88;
pub const ADC_C: u8 = 0x89;
pub const ADC_D: u8 = 0x8a;
pub const ADC_E: u8 = 0x8b;
pub const ADC_H: u8 = 0x8c;
pub const ADC_L: u8 = 0x8d;
pub const ADC_M: u8 = 0x8e;
pub const ADC_A: u8 = 0x8f;
pub const SUB_B: u8 = 0x90;
pub const SUB_C: u8 = 0x91;
pub const SUB_D: u8 = 0x92;
pub const SUB_E: u8 = 0x93;
pub const SUB_H: u8 = 0x94;
pub const SUB_L: u8 = 0x95;
pub const SUB_M: u8 = 0x96;
pub const SUB_A: u8 = 0x97;
pub const SBB_B: u8 = 0x98;
pub const SBB_C: u8 = 0x99;
pub const SBB_D: u8 = 0x9a;
pub const SBB_E: u8 = 0x9b;
pub const SBB_H: u8 = 0x9c;
pub const SBB_L: u8 = 0x9d;
pub const SBB_M: u8 = 0x9e;
pub const SBB_A: u8 = 0x9f;
pub const ORA_B: u8 = 0xb0;
pub const ORA_C: u8 = 0xb1;
pub const ORA_D: u8 = 0xb2;
pub const ORA_E: u8 = 0xb3;
pub const ORA_H: u8 = 0xb4;
pub const ORA_L: u8 = 0xb5;
pub const ORA_M: u8 = 0xb6;
pub const ORA_A: u8 = 0xb7;
pub const CMP_B: u8 = 0xb8;
pub const CMP_C: u8 = 0xb9;
pub const CMP_D: u8 = 0xba;
pub const CMP_E: u8 = 0xbb;
pub const CMP_H: u8 = 0xbc;
pub const CMP_L: u8 = 0xbd;
pub const CMP_M: u8 = 0xbe;
pub const CMP_A: u8 = 0xbf;
pub const ANA_B: u8 = 0xa0;
pub const ANA_C: u8 = 0xa1;
pub const ANA_D: u8 = 0xa2;
pub const ANA_E: u8 = 0xa3;
pub const ANA_H: u8 = 0xa4;
pub const ANA_L: u8 = 0xa5;
pub const ANA_M: u8 = 0xa6;
pub const ANA_A: u8 = 0xa7;
pub const XRA_B: u8 = 0xa8;
pub const XRA_C: u8 = 0xa9;
pub const XRA_D: u8 = 0xaa;
pub const XRA_E: u8 = 0xab;
pub const XRA_H: u8 = 0xac;
pub const XRA_L: u8 = 0xad;
pub const XRA_M: u8 = 0xae;
pub const XRA_A: u8 = 0xaf;
pub const RNZ: u8 = 0xc0;
pub const POP_B: u8 = 0xc1;
pub const JNZ: u8 = 0xc2;
pub const JMP: u8 = 0xc3;
pub const CNZ: u8 = 0xc4;
pub const PUSH_B: u8 = 0xc5;
pub const ADI: u8 = 0xc6;
pub const RZ: u8 = 0xc8;
pub const RET: u8 = 0xc9;
pub const JZ: u8 = 0xca;
pub const CZ: u8 = 0xcc;
pub const CALL: u8 = 0xcd;
pub const ACI: u8 = 0xce;
pub const RST_1: u8 = 0xcf;
pub const RNC: u8 = 0xd0;
pub const POP_D: u8 = 0xd1;
pub const JNC: u8 = 0xd2;
pub const OUT: u8 = 0xd3;
pub const CNC: u8 = 0xd4;
pub const PUSH_D: u8 = 0xd5;
pub const SUI: u8 = 0xd6;
pub const RST_2: u8 = 0xd7;
pub const RC: u8 = 0xd8;
pub const JC: u8 = 0xda;
pub const IN: u8 = 0xdb;
pub const CC: u8 = 0xdc;
pub const SBI: u8 = 0xde;
pub const RPO: u8 = 0xe0;
pub const POP_H: u8 = 0xe1;
pub const JPO: u8 = 0xe2;
pub const XTHL: u8 = 0xe3;
pub const CPO: u8 = 0xe4;
pub const PUSH_H: u8 = 0xe5;
pub const ANI: u8 = 0xe6;
pub const RPE: u8 = 0xe8;
pub const PCHL: u8 = 0xe9;
pub const JPE: u8 = 0xea;
pub const XCHG: u8 = 0xeb;
pub const CPE: u8 = 0xec;
pub const XRI: u8 = 0xee;
pub const RP: u8 = 0xf0;
pub const POP_PSW: u8 = 0xf1;
pub const JP: u8 = 0xf2;
pub const DI: u8 = 0xf3;
pub const CP: u8 = 0xf4;
pub const PUSH_PSW: u8 = 0xf5;
pub const ORI: u8 = 0xf6;
pub const RM: u8 = 0xf8;
pub const SPHL: u8 = 0xf9;
pub const JM: u8 = 0xfa;
pub const EI: u8 = 0xfb;
pub const CM: u8 = 0xfc;
pub const CPI: u8 = 0xfe;
pub const RST_7: u8 = 0xff;
fn init_opcodes() -> HashMap<u8, Opcode> {
// Opcode, size, disassembly name, cycles (appendix B of the ref manual)
let ops: Vec<(u8, usize, &str)> = vec![
(NOP, 1, "NOP"),
(LXI_B, 3, "LD BC,"),
(STAX_B, 1, "STA (BC)"),
(INX_B, 1, "INC (BC)"),
(INR_B, 1, "INR B"),
(DCR_B, 1, "DEC B"),
(MVI_B, 2, "LD B,"),
(RLC, 1, "RLC"),
(DAD_B, 1, "ADD HL,BC"),
(LDAX_B, 1, "LD A,(BC)"),
(DCX_B, 1, "DEC (BC)"),
(INR_C, 1, "INR C"),
(DCR_C, 1, "DEC C"),
(MVI_C, 2, "LD C,"),
(RRC, 1, "RRC"),
(LXI_D, 3, "LD DE,"),
(STAX_D, 1, "STA (DE)"),
(INX_D, 1, "INC (DE)"),
(INR_D, 1, "INR D"),
(DCR_D, 1, "DEC D"),
(MVI_D, 2, "LD D,"),
(RAL, 1, "RAL"),
(DAD_D, 1, "ADD HL,DE"),
(LDAX_D, 1, "LD A,(DE)"),
(DCX_D, 1, "DC (DE)"),
(INR_E, 1, "INR E"),
(DCR_E, 1, "DEC E"),
(MVI_E, 2, "LD E,"),
(RAR, 1, "RAR"),
(LXI_H, 3, "LD HL,"),
(SHLD, 3, "SHLD"),
(INX_H, 1, "INC (HL)"),
(INR_H, 1, "INR H"),
(DCR_H, 1, "DEC HL"),
(MVI_H, 2, "MOV H,"),
(DAA, 1, "DAA"),
(DAD_H, 1, "ADD HL,HL"),
(LHLD, 3, "LHLD"),
(DCX_H, 1, "DEC (HL)"),
(INR_L, 1, "INR L"),
(DCR_L, 1, "DEC L"),
(MVI_L, 2, "LD L,"),
(CMA, 1, "CMA"),
(LXI_SP, 3, "LD SP,"),
(STA, 3, "STA"),
(INX_SP, 1, "INC (SP)"),
(INR_M, 1, "INC (HL)"),
(DCR_M, 1, "DEC (HL)"),
(MVI_M, 2, "MV (HL),"),
(STC, 1, "STC"),
(DAD_SP, 1, "ADD HL,SP"),
(0x3a, 3, "LDA"),
(DCX_SP, 1, "DEC (SP)"),
(INR_A, 1, "INR A"),
(DCR_A, 1, "DEC A"),
(MVI_A, 2, "LD A,"),
(CMC, 1, "CMC"),
(MOV_B_C, 1, "MOV B,C"),
(MOV_B_D, 1, "MOV B,D"),
(MOV_B_E, 1, "MOV B,E"),
(MOV_B_H, 1, "MOV B,H"),
(MOV_B_L, 1, "MOV B,L"),
(MOV_B_M, 1, "MOV B,M"),
(MOV_B_A, 1, "MOV B,A"),
(MOV_C_B, 1, "MOV C,B"),
(MOV_C_C, 1, "MOV C,C"),
(MOV_C_D, 1, "MOV C,D"),
(MOV_C_E, 1, "MOV C,E"),
(MOV_C_H, 1, "MOV C,H"),
(MOV_C_L, 1, "MOV C,L"),
(MOV_C_M, 1, "MOV C,M"),
(MOV_C_A, 1, "MOV C,A"),
(MOV_D_B, 1, "MOV D,B"),
(MOV_D_C, 1, "MOV D,C"),
(MOV_D_D, 1, "MOV D,D"),
(MOV_D_E, 1, "MOV D,E"),
(MOV_D_H, 1, "MOV D,H"),
(MOV_D_L, 1, "MOV D,L"),
(MOV_D_M, 1, "MOV D,M"),
(MOV_D_A, 1, "MOV D,A"),
(MOV_E_B, 1, "MOV E,B"),
(MOV_E_C, 1, "MOV E,C"),
(MOV_E_D, 1, "MOV E,D"),
(MOV_E_E, 1, "MOV E,E"),
(MOV_E_H, 1, "MOV E,H"),
(MOV_E_L, 1, "MOV E,L"),
(MOV_E_M, 1, "MOV E,M"),
(MOV_E_A, 1, "MOV E,A"),
(MOV_H_B, 1, "MOV H,B"),
(MOV_H_C, 1, "MOV H,C"),
(MOV_H_D, 1, "MOV H,D"),
(MOV_H_E, 1, "MOV H,E"),
(MOV_H_H, 1, "MOV H,H"),
(MOV_H_L, 1, "MOV H,L"),
(MOV_H_M, 1, "MOV H,M"),
(MOV_H_A, 1, "MOV H,A"),
(MOV_L_B, 1, "MOV L,B"),
(MOV_L_C, 1, "MOV L,C"),
(MOV_L_D, 1, "MOV L,D"),
(MOV_L_E, 1, "MOV L,E"),
(MOV_L_H, 1, "MOV L,H"),
(MOV_L_L, 1, "MOV L,L"),
(MOV_L_M, 1, "MOV L,M"),
(MOV_L_A, 1, "MOV L,A"),
(MOV_M_B, 1, "LD (HL),B"),
(MOV_M_C, 1, "LD (HL),C"),
(MOV_M_D, 1, "LD (HL),D"),
(MOV_M_E, 1, "LD (HL),E"),
(MOV_M_H, 1, "LD (HL),H"),
(MOV_M_L, 1, "LD (HL),L"),
(MOV_M_A, 1, "LD (HL),A"),
(MOV_A_B, 1, "MOV A,B"),
(MOV_A_C, 1, "MOV A,C"),
(MOV_A_D, 1, "MOV A,D"),
(MOV_A_E, 1, "MOV A,E"),
(MOV_A_H, 1, "MOV A,H"),
(MOV_A_L, 1, "MOV A,L"),
(MOV_A_M, 1, "MOV A,(HL)"),
(ADD_B, 1, "ADD B"),
(ADD_C, 1, "ADD C"),
(ADD_D, 1, "ADD D"),
(ADD_E, 1, "ADD E"),
(ADD_H, 1, "ADD H"),
(ADD_L, 1, "ADD L"),
(ADD_M, 1, "ADD M"),
(ADD_A, 1, "ADD A"),
(ADC_B, 1, "ADC B"),
(ADC_C, 1, "ADC C"),
(ADC_D, 1, "ADC D"),
(ADC_E, 1, "ADC E"),
(ADC_H, 1, "ADC H"),
(ADC_L, 1, "ADC L"),
(ADC_M, 1, "ADC M"),
(ADC_A, 1, "ADC A"),
(SUB_B, 1, "SUB B"),
(SUB_C, 1, "SUB C"),
(SUB_D, 1, "SUB D"),
(SUB_E, 1, "SUB E"),
(SUB_H, 1, "SUB H"),
(SUB_L, 1, "SUB L"),
(SUB_M, 1, "SUB M"),
(SUB_A, 1, "SUB A"),
(SBB_B, 1, "SBB B"),
(SBB_C, 1, "SBB C"),
(SBB_D, 1, "SBB D"),
(SBB_E, 1, "SBB E"),
(SBB_H, 1, "SBB H"),
(SBB_L, 1, "SBB L"),
(SBB_M, 1, "SBB M"),
(SBB_A, 1, "SBB A"),
(ANA_B, 1, "AND B"),
(ANA_C, 1, "AND C"),
(ANA_D, 1, "AND D"),
(ANA_E, 1, "AND E"),
(ANA_H, 1, "AND H"),
(ANA_L, 1, "AND L"),
(ANA_M, 1, "AND M"),
(ANA_A, 1, "AND A"),
(ORA_B, 1, "ORA B"),
(ORA_C, 1, "ORA C"),
(ORA_D, 1, "ORA D"),
(ORA_E, 1, "ORA E"),
(ORA_H, 1, "ORA H"),
(ORA_L, 1, "ORA L"),
(ORA_M, 1, "ORA M"),
(ORA_A, 1, "ORA A"),
(CMP_B, 1, "CMP B"),
(CMP_C, 1, "CMP C"),
(CMP_D, 1, "CMP D"),
(CMP_E, 1, "CMP E"),
(CMP_H, 1, "CMP H"),
(CMP_L, 1, "CMP L"),
(CMP_M, 1, "CMP M"),
(CMP_A, 1, "CMP A"),
(XRA_B, 1, "XRA B"),
(XRA_C, 1, "XRA C"),
(XRA_D, 1, "XRA D"),
(XRA_E, 1, "XRA E"),
(XRA_H, 1, "XRA H"),
(XRA_L, 1, "XRA L"),
(XRA_M, 1, "XRA M"),
(XRA_A, 1, "XRA A"),
(RNZ, 1, "RNZ"),
(POP_B, 1, "POP BC"),
(JNZ, 3, "JNZ"),
(JMP, 3, "JMP"),
(CNZ, 3, "CNZ"),
(PUSH_B, 1, "PUSH BC"),
(ADI, 2, "ADI"),
(RZ, 1, "RZ"),
(RET, 1, "RET"),
(JZ, 3, "JZ"),
(CZ, 3, "CZ"),
(CALL, 3, "CALL"),
(ACI, 2, "ACI"),
(RNC, 1, "RNC"),
(POP_D, 1, "POP DE"),
(JNC, 3, "JNC"),
(OUT, 2, "OUT"),
(CNC, 3, "CNC"),
(PUSH_D, 1, "PUSH DE"),
(SUI, 2, "SUI"),
(RC, 1, "RC"),
(JC, 3, "JC"),
(IN, 2, "IN"),
(CC, 3, "CC"),
(SBI, 2, "SBI"),
(RPO, 1, "RPO"),
(POP_H, 1, "POP HL"),
(JPO, 3, "JPO"),
(XTHL, 1, "XTHL"),
(CPO, 3, "CPO"),
(PUSH_H, 1, "PUSH HL"),
(ANI, 2, "ANI"),
(RPE, 1, "RPE"),
(PCHL, 1, "PCHL"),
(JPE, 3, "JPE"),
(XCHG, 1, "EX DE,HL"),
(CPE, 3, "CPE"),
(XRI, 2, "XRI"),
(RP, 1, "RP"),
(POP_PSW, 1, "POP PSW"),
(JP, 3, "JP"),
(CP, 3, "CP"),
(PUSH_PSW, 1, "PUSH PSW"),
(ORI, 2, "ORI"),
(RM, 1, "RM"),
(SPHL, 1, "SPHL"),
(JM, 3, "JM"),
(CM, 3, "CM"),
(EI, 1, "EI"),
(DI, 1, "DI"),
(CPI, 2, "CPI"),
(RST_1, 2, "RST 1"),
(RST_2, 2, "RST 2"),
(RST_7, 2, "RST 7"),
];
let mut result: HashMap<u8, Opcode> = HashMap::new();
for op in ops {
if result.get(&op.0).is_some() {
panic!("REPEATED OPCODE {:02x}", op.0);
}
result.insert(op.0, Opcode::new(op.0, op.1, op.2));
}
result
}
lazy_static! {
pub(crate) static ref OPCODES: HashMap<u8, Opcode> = init_opcodes();
}
// fn insert(map: &mut HashMap<u8, Opcode>, opcode: u8, size: usize, name: &'static str) {
// map.insert(opcode, Opcode::new(opcode, size, name));
// }

186
emulator/src/state.rs Normal file
View File

@ -0,0 +1,186 @@
use crate::memory::Memory;
#[derive(Default)]
pub(crate) struct Psw {
pub a: u8,
pub sign: bool,
pub zero: bool,
pub auxiliary_carry: bool,
pub parity: bool,
pub carry: bool,
}
/*
* PSW is: A for the high byte and the flags for the low byte, in order,
* sign, zero, auxiliary carry, parity, carry:
*
* Bit: 7 6 5 4 3 2 1 0
* Flag: S Z 0 AC 0 P 1 C
*/
impl Psw {
pub(crate) fn to_u8(f: bool) -> u16 { if f { 1 } else { 0 } }
pub(crate) fn to_bool(v: u8) -> bool { if v == 0 { false } else { true }}
pub(crate) fn set_flags(&mut self, value: u8) {
self.sign = Psw::to_bool(value & (1 << 7));
self.zero = Psw::to_bool(value & (1 << 6));
self.auxiliary_carry = Psw::to_bool(value & (1 << 4));
self.parity = Psw::to_bool(value & (1 << 2));
self.carry = Psw::to_bool(value & 1);
}
pub(crate) fn value(&self) -> u16 {
(self.a as u16) << 8 |
Psw::to_u8(self.sign) << 7 |
Psw::to_u8(self.zero) << 6 |
Psw::to_u8(self.auxiliary_carry) << 4 |
Psw::to_u8(self.parity) << 2 |
1 << 1 |
Psw::to_u8(self.carry)
}
pub(crate) fn disassemble(&self) -> String {
format!("[C={} P={} S={} Z={}]",
Psw::to_u8(self.carry),
Psw::to_u8(self.parity),
Psw::to_u8(self.sign),
Psw::to_u8(self.zero))
}
}
#[derive(Default)]
pub(crate) struct State {
pub b: u8,
pub c: u8,
pub d: u8,
pub e: u8,
pub h: u8,
pub l: u8,
pub psw: Psw,
pub pc: usize,
pub sp: usize,
pub enable_interrupts: bool,
}
impl State {
pub(crate) fn new(pc: usize) -> State {
State {
pc,
.. Default::default()
}
}
pub fn m(&self) -> usize {
Memory::to_word(self.l, self.h)
}
pub fn disassemble(&self) -> String {
format!("a:{:02x} b:{:02x} c:{:02x} d:{:02x} e:{:02x} lh:{:04x} pc:{:04x} sp:{:04x} {}",
self.psw.a, self.b, self.c, self.d, self.e, ((self.h as u16) << 8) | self.l as u16,
self.pc, self.sp,
self.psw.disassemble())
}
pub fn set_logic_flags(&mut self, value: i16) {
self.psw.zero = value == 0;
self.psw.sign = 0x80 == (value & 0x80);
self.psw.parity = (value & 0xff).count_ones() % 2 == 0;
self.psw.carry = false;
// state.psw.auxiliary_carry = (state.psw.a < byte1);
}
pub fn set_arithmetic_flags(&mut self, value: i16) {
self.psw.zero = (value & 0xff) == 0;
self.psw.sign = 0x80 == (value & 0x80);
self.psw.parity = (value & 0xff).count_ones() % 2 == 0;
self.psw.carry = value < 0 || value > 0xff;
self.psw.auxiliary_carry = self.psw.carry;
}
pub fn jump_if_flag(&mut self, word: usize, flag: bool) -> bool {
if flag {
self.pc = word;
true
} else {
false
}
}
pub fn call(&mut self, memory: &mut Memory, target_pc: usize) {
let ret = self.pc + 3;
memory.write(self.sp - 1, ((ret >> 8) as u8) & 0xff);
memory.write(self.sp - 2, (ret & 0xff) as u8);
self.sp -= 2;
self.pc = target_pc;
}
pub fn ret(&mut self, memory: &Memory, flag: bool) -> bool {
if flag {
self.pc = Memory::to_word(memory.read(self.sp), memory.read(self.sp + 1));
self.sp += 2;
}
flag
}
pub fn dec(&mut self, n: u8) -> u8 {
let value = if n == 0 {
self.psw.carry = true;
self.psw.auxiliary_carry = true;
0xff
} else {
n - 1
};
self.set_arithmetic_flags(value as i16);
value
}
pub fn xra(&mut self, value: u8) -> u8 {
let value = self.psw.a ^ value;
self.set_arithmetic_flags(value as i16);
value
}
pub fn and(&mut self, value: u8) -> u8 {
let value = self.psw.a & value;
self.set_arithmetic_flags(value as i16);
value
}
pub fn or(&mut self, value: u8) -> u8 {
let value = self.psw.a | value;
self.set_arithmetic_flags(value as i16);
value
}
pub fn add(&mut self, value: u8, carry: u16) {
let value = self.psw.a as u16 + value as u16 + carry;
self.set_arithmetic_flags(value as i16);
self.psw.a = value as u8 & 0xff;
}
pub fn sub(&mut self, value: u8, carry: u16) {
let value = self.psw.a as i16 - value as i16 - carry as i16;
self.set_arithmetic_flags(value as i16);
self.psw.a = value as u8 & 0xff;
}
pub fn cmp(&mut self, n: u8) {
let value: i16 = self.psw.a as i16 - n as i16;
self.set_arithmetic_flags(value);
}
pub fn inr(&mut self, n: u8) -> u8 {
let value = if n == 0xff { 0 } else { n + 1 };
self.set_arithmetic_flags(value as i16);
value
}
pub fn add_hl(&mut self, b0: u8, b1: u8) {
let hl = Memory::to_word(self.l, self.h) as u32;
let v = Memory::to_word(b0, b1) as u32;
let result: u32 = hl + v;
self.psw.carry = result > 0xffff;
self.h = ((result & 0xff00) >> 8) as u8;
self.l = (result & 0xff) as u8;
}
}

30
emulator/src/test.rs Normal file
View File

@ -0,0 +1,30 @@
#[cfg(test)]
mod test {
use crate::memory::Memory;
use crate::emulator::{Emulator, StepResult, StepStatus};
#[test]
fn run_cpu_diag() {
let mut memory = Memory::new();
let start = 0x100;
memory.read_file("cpudiag.bin", start);
let mut computer = Emulator::new(Box::new(memory), start as usize);
let mut result = StepResult { status: StepStatus::Continue, cycles: 0 };
unsafe {
while result.status == StepStatus::Continue {
result = computer.step(true);
}
}
match result.status {
StepStatus::Success(s) => {
println!("Success: {}", s)
},
StepStatus::Failure(s) => {
panic!(s);
},
_ => {
println!("Something went wrong");
}
}
}
}

9
emulator/src/test2.rs Normal file
View File

@ -0,0 +1,9 @@
struct Foo {}
fn main() {
let foo = Foo{};
thread::spawn(move || {
println!("Here is foo {}", foo);
})
}

BIN
screenshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
space-invaders.rom Normal file

Binary file not shown.

76
src/emulator2.rs Normal file
View File

@ -0,0 +1,76 @@
const MEMORY_SIZE: usize = 260;
use lazy_static::lazy_static;
use std::sync::RwLock;
use std::sync::Mutex;
use std::time::Duration;
use std::thread;
use emulator::opcodes::STA;
use crate::log_time;
use once_cell::sync::Lazy;
struct State {
memory: Vec<u8>,
input_1: u8,
}
static SHARED_STATE: Lazy<RwLock<State>> = Lazy::new(|| {
RwLock::new(State {
memory: vec![0; MEMORY_SIZE],
input_1: 0,
})
});
trait Emulator {
fn run_one_frame(&self);
fn write_memory(&mut self, address: usize, value: u8);
fn memory(&self) -> Vec<u8>;
fn set_input_1(&mut self, value: u8);
fn input_1(&self) -> u8;
}
struct Runner{}
impl Emulator for Runner {
fn run_one_frame(&self) {
println!("Running one frame");
std::thread::sleep(Duration::from_millis(500));
}
fn write_memory(&mut self, address: usize, value: u8) {
SHARED_STATE.write().unwrap().memory[address] = value;
}
fn memory(&self) -> Vec<u8> {
SHARED_STATE.read().unwrap().memory.to_vec()
}
fn set_input_1(&mut self, value: u8) {
SHARED_STATE.write().unwrap().input_1 = value;
}
fn input_1(&self) -> u8 {
SHARED_STATE.read().unwrap().input_1
}
}
pub(crate) fn main() {
let mut e2 = Runner{};
let mut e3 = Runner{};
let t = thread::spawn(move || {
let mut i = 0;
loop {
e2.run_one_frame();
println!("Writing {}, input_1: {}", i, e2.input_1());
e2.write_memory(0, i);
i += 1;
}
});
loop {
let value = e3.memory()[0];
let s = format!("============= Memory: {:02x}", value);
e3.set_input_1(value);
log_time(&s);
thread::sleep(Duration::from_millis(500));
}
}

13
src/main.rs Normal file
View File

@ -0,0 +1,13 @@
use emulator::emulator_state::SharedState;
use std::time::{UNIX_EPOCH, SystemTime};
mod sdl2;
fn main() -> Result<(), String> {
sdl2::sdl2()
}
pub fn log_time(s: &str) {
println!("{} {}", SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis() % 100000, s);
}

196
src/sdl2.rs Normal file
View File

@ -0,0 +1,196 @@
use std::time::{Duration, SystemTime};
use sdl2::event::Event;
use sdl2::pixels::Color;
use sdl2::keyboard::Keycode;
use sdl2::rect::Rect;
use emulator::memory::Memory;
use std::thread;
use std::sync::Mutex;
use emulator::emulator::{Emulator, WIDTH, HEIGHT};
use emulator::emulator_state::SharedState;
// I replaced GREEN with blue color and WHITE with red color.
// I also made RECTANGLE_SIZE double of it's original value cuz window was too small in my opinion. -Biterr
const RECTANGLE_SIZE: u32 = 4;
const WHITE: Color = Color::RGB(128,0,0);
const BLACK: Color = Color::RGB(0, 0, 0);
const RED: Color = Color::RGB(255, 0, 0);
const GREEN: Color = Color::RGB(0, 0, 255);
pub fn sdl2() -> Result<(), String> {
let sdl_context = sdl2::init()?;
let video_subsystem = sdl_context.video()?;
let window = video_subsystem
.window("", WIDTH as u32 * RECTANGLE_SIZE, HEIGHT as u32 * RECTANGLE_SIZE)
.position_centered()
.resizable()
.build()
.map_err(|e| e.to_string())?;
let mut canvas = window.into_canvas().build().map_err(|e| e.to_string())?;
canvas.clear();
canvas.present();
//
// Spawn the game logic in a separate thread. This logic will communicate with the
// main thread (and therefore, the actual graphics on your screen) via the `SHARED_STATE`
// object returned by the start of the emilator.
//
let shared_state = Emulator::start_emulator();
// Hehe
println!("Recolorised and resized by Biterr");
canvas.clear();
canvas.present();
// Only update the title every one second or so
let mut last_title_update = SystemTime::now();
// Main game loop
let mut event_pump = sdl_context.event_pump()?;
'running: loop {
for event in event_pump.poll_iter() {
//
// Read the keyboard
//
match event {
Event::Quit { .. } | Event::KeyDown { keycode: Some(Keycode::Escape), .. }
=> break 'running,
// Pause / unpause ('p')
Event::KeyDown { keycode: Some(Keycode::P), .. } => {
let mut l = shared_state.lock().unwrap();
if l.is_paused() {
l.unpause();
} else {
l.pause();
}
},
// Insert coin
Event::KeyDown { keycode: Some(Keycode::C), .. } => {
shared_state.lock().unwrap().set_bit_in_1(0, true);
},
Event::KeyUp { keycode: Some(Keycode::C), .. } => {
shared_state.lock().unwrap().set_bit_in_1(0, false);
},
// Start 2 players
Event::KeyDown { keycode: Some(Keycode::Num2), .. } => {
shared_state.lock().unwrap().set_bit_in_1(1, true);
},
Event::KeyUp { keycode: Some(Keycode::Num2), .. } => {
shared_state.lock().unwrap().set_bit_in_1(1, false);
},
// Start 1 player
Event::KeyDown { keycode: Some(Keycode::Num1), .. } => {
shared_state.lock().unwrap().set_bit_in_1(2, true);
},
Event::KeyUp { keycode: Some(Keycode::Num1), .. } => {
shared_state.lock().unwrap().set_bit_in_1(2, false);
},
// Player 1 shot
Event::KeyDown { keycode: Some(Keycode::Space), .. } => {
if shared_state.lock().unwrap().is_paused() {
shared_state.lock().unwrap().unpause();
} else {
shared_state.lock().unwrap().set_bit_in_1(4, true);
}
},
Event::KeyUp { keycode: Some(Keycode::Space), .. } => {
shared_state.lock().unwrap().set_bit_in_1(4, false);
},
// Player 1 move left
Event::KeyDown { keycode: Some(Keycode::Left), .. } => {
shared_state.lock().unwrap().set_bit_in_1(5, true);
},
Event::KeyUp { keycode: Some(Keycode::Left), .. } => {
shared_state.lock().unwrap().set_bit_in_1(5, false);
},
// Player 1 move right
Event::KeyDown { keycode: Some(Keycode::Right), .. } => {
shared_state.lock().unwrap().set_bit_in_1(6, true);
},
Event::KeyUp { keycode: Some(Keycode::Right), .. } => {
shared_state.lock().unwrap().set_bit_in_1(6, false);
},
// Player 2 shot ('s')
Event::KeyDown { keycode: Some(Keycode::S), .. } => {
shared_state.lock().unwrap().set_bit_in_2(4, true);
},
Event::KeyUp { keycode: Some(Keycode::S), .. } => {
shared_state.lock().unwrap().set_bit_in_2(4, false);
},
// Player 2 move left ('a')
Event::KeyDown { keycode: Some(Keycode::A), .. } => {
shared_state.lock().unwrap().set_bit_in_2(5, true);
},
Event::KeyUp { keycode: Some(Keycode::A), .. } => {
shared_state.lock().unwrap().set_bit_in_2(5, false);
},
// Player 2 move right ('d')
Event::KeyDown { keycode: Some(Keycode::D), .. } => {
shared_state.lock().unwrap().set_bit_in_2(6, true);
},
Event::KeyUp { keycode: Some(Keycode::D), .. } => {
shared_state.lock().unwrap().set_bit_in_2(6, false);
},
// If the emulator is paused, any key will unpause it
Event::KeyDown { .. } => {
if shared_state.lock().unwrap().is_paused() {
shared_state.lock().unwrap().unpause();
}
}
_ => {
}
}
}
// ::std::thread::sleep(Duration::new(0, 1_000_000_000u32 / 30));
canvas.clear();
//
// Draw the graphic
// Simply map the listener's frame buffer (updated by the main logic in a separate thread)
// to the SDL canvas
//
let graphic_memory = shared_state.lock().unwrap().graphic_memory();
let mut i: usize = 0;
for ix in 0..WIDTH {
for iy in (0..HEIGHT).step_by(8) {
let mut byte = graphic_memory[i];
i += 1;
for b in 0..8 {
let x: i32 = ix as i32 * RECTANGLE_SIZE as i32;
let y: i32 = (HEIGHT as i32 - (iy as i32+ b)) * RECTANGLE_SIZE as i32;
let color = if byte & 1 == 0 { BLACK } else {
if iy > 200 && iy < 220 { RED }
else if iy < 80 { GREEN }
else { WHITE }
};
byte >>= 1;
canvas.set_draw_color(color);
canvas.fill_rect(Rect::new(x, y, RECTANGLE_SIZE as u32, RECTANGLE_SIZE as u32))
.unwrap();
}
}
}
if last_title_update.elapsed().unwrap().gt(&Duration::from_millis(1000)) {
let paused = if shared_state.lock().unwrap().is_paused() { " - Paused" } else { "" };
canvas.window_mut().set_title(
format!("Space Invaders in Rust - Hacked by Biterr - {:.2} Mhz{}",
shared_state.lock().unwrap().get_megahertz(),
paused)
.as_str()).unwrap();
last_title_update = SystemTime::now();
}
canvas.present();
}
Ok(())
}