Full Code of marioballano/emudore for AI

master 5d98f4447409 cached
42 files
1013.4 KB
256.8k tokens
21 symbols
1 requests
Download .txt
Showing preview only (1,044K chars total). Download the full file or copy to clipboard to get everything.
Repository: marioballano/emudore
Branch: master
Commit: 5d98f4447409
Files: 42
Total size: 1013.4 KB

Directory structure:
gitextract_1yla08f4/

├── CMakeLists.txt
├── LICENSE
├── Makefile
├── README.md
├── assets/
│   ├── bas/
│   │   ├── 10print.bas
│   │   ├── bitmap.bas
│   │   ├── bouncing.bas
│   │   └── lowercase.bas
│   ├── prg/
│   │   └── monopole.prg
│   ├── roms/
│   │   └── README.md
│   └── tests/
│       ├── 6502_functional_test.a65
│       ├── 6502_functional_test.lst
│       └── README.md
├── cmake/
│   ├── FindSDL2.cmake
│   ├── FindSDL2_image.cmake
│   ├── FindSDL2_net.cmake
│   ├── FindSDL2_ttf.cmake
│   └── README.md
├── doc/
│   ├── .gitignore
│   └── doxygen.conf
├── res/
│   └── emudore.rc
└── src/
    ├── c64.cpp
    ├── c64.h
    ├── cia1.cpp
    ├── cia1.h
    ├── cia2.cpp
    ├── cia2.h
    ├── cpu.cpp
    ├── cpu.h
    ├── debugger.cpp
    ├── debugger.h
    ├── io.cpp
    ├── io.h
    ├── loader.cpp
    ├── loader.h
    ├── main.cpp
    ├── memory.cpp
    ├── memory.h
    ├── sid.h
    ├── util.h
    ├── vic.cpp
    └── vic.h

================================================
FILE CONTENTS
================================================

================================================
FILE: CMakeLists.txt
================================================
cmake_minimum_required (VERSION 2.8)
project(emudore)
set(SRC_FILES "src/c64.cpp"
              "src/cpu.cpp"
              "src/memory.cpp"
              "src/cia1.cpp"
              "src/cia2.cpp"
              "src/vic.cpp"
              "src/io.cpp"
              "src/loader.cpp"
              "src/main.cpp")
# GCC and Clang
if (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall")
  set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Wall")
# C++11
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
endif()
# r2 debugging support, for now only available on Linux 
# and OSX Debug builds, if you want it enabled on release 
# mode just remove the second part of the expression
if(CMAKE_BUILD_TYPE MATCHES "Debug" AND
  (CMAKE_SYSTEM_NAME MATCHES "Linux" OR CMAKE_SYSTEM_NAME MATCHES "Darwin"))
  add_definitions(-DDEBUGGER_SUPPORT)
  set(SRC_FILES ${SRC_FILES} "src/debugger.cpp")
endif()         
# MSVC, using pre-built binaries downloaded from:
# https://www.libsdl.org/download-2.0.php
if (MSVC)
  set(SDL2_PATH "C:\\SDL2")
  set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
  set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
  add_executable (emudore ${SRC_FILES} res/emudore.rc)
  set_target_properties(emudore PROPERTIES LINK_FLAGS_DEBUG "/SUBSYSTEM:WINDOWS")
  set_target_properties(emudore PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS")
else()
  add_executable (emudore ${SRC_FILES})
endif()
# JavaScript and WebAssembly builds with emscripten
if(CMAKE_SYSTEM_NAME MATCHES "Emscripten")
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -O2 -s USE_SDL=2 -s DISABLE_EXCEPTION_CATCHING=0 --preload-file assets/roms/")
  if(WASM)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s WASM=1")
  endif()
endif()
# SDL2 
# Cmake 2.8 does not provide scripts to find SDL2, adding 
# them to the cmake module path and here for convenience
if(NOT CMAKE_SYSTEM_NAME MATCHES "Emscripten")
  list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
  find_package(SDL2 REQUIRED)
  include_directories(${SDL2_INCLUDE_DIR})
endif()
# link
target_link_libraries(emudore ${SDL2_LIBRARY})
# copy assets to build directory 
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_directory
${CMAKE_SOURCE_DIR}/assets/ ${CMAKE_BINARY_DIR}/assets/)


================================================
FILE: LICENSE
================================================
                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "{}"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright {yyyy} {name of copyright owner}

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.


================================================
FILE: Makefile
================================================
release:
	rm -rf build/*
	cd build;cmake -DCMAKE_BUILD_TYPE=Release ..
	cd build;make
debug:
	rm -rf build/*
	cd build;cmake -DCMAKE_BUILD_TYPE=Debug ..
	cd build;make
js:
	rm -rf build/*
	cd build;cmake -DCMAKE_TOOLCHAIN_FILE=~/emsdk/emscripten/incoming/cmake/Modules/Platform/Emscripten.cmake -DCMAKE_BUILD_TYPE=Release ..
	cd build;make
wasm:
	rm -rf build/*
	cd build;cmake -DCMAKE_TOOLCHAIN_FILE=~/emsdk/emscripten/incoming/cmake/Modules/Platform/Emscripten.cmake -DWASM=1 -DCMAKE_BUILD_TYPE=Release ..
	cd build;make


================================================
FILE: README.md
================================================
# emudore, a Commodore 64 emulator

![basic](/pics/basic.gif "basic")

# What's this?

emudore is a [Commodore 64 emulator](https://en.wikipedia.org/wiki/Commodore_64), 
fully written from the scratch and built on the top of the following technologies:

 * [C++11](https://en.wikipedia.org/wiki/C%2B%2B11)
 * [SDL2](https://www.libsdl.org/download-2.0.php)

emudore builds and runs on Linux, Windows (Visual Studio), OSX and even runs in
your browser thanks to Emscriptem, it should theoretically work on any platform 
supported by SDL2 provided a C++11 compiler is available.

# JavaScript and WebAssembly builds

If you wish to play a bit around without having to go through the hassle of 
compiling it you can try the web build:

* [emudore (boot into CBM BASIC)](http://marioballano.github.io/emudorejs/)
* [emudore (load Monopole PRG)](http://marioballano.github.io/emudorejs/?load=samples/monopole.prg)

A [WebAssembly](https://en.wikipedia.org/wiki/WebAssembly) build of emudore is also available, 
please note that a browser with WebAssembly support is required to run these demos:

* [emudore (boot into CBM BASIC)](http://marioballano.github.io/emudorewa/)
* [emudore (load Monopole PRG)](http://marioballano.github.io/emudorewa/?load=samples/monopole.prg)

# Why am I writing another C64 emulator?

Long story short: to learn a bit more about computer architecture, graphics, 
C++, etc..  while having some fun!

The Commodore 64 is regarded as one of the most epic 8-bit computers, it was actually 
the first computer I ever laid hands on - thanks to my dad :) - and it seemed like a 
sound choice to write an emulator for.

# Does this even work?

Well, yeah, mostly... 

The BASIC ROM runs just fine, and most simple programs run without issues, however, many 
of the more advanced games written in ML do not yet play well due to unimplemented hardware 
features, writing an emulator is a tough task and after all my goal wasn't to write a full 
perfect emulator but to learn in the process of making a simple one, here follow some facts 
you might be interested in knowing about emudore's implementation:

**emulation is instruction-exact**

That's right, on every emulation cycle a single instruction is fetched and interpreted, 
the number of CPU cycles the instruction has taken to execute is used to synchronize the 
rest of the chips in a C64 board. 

Unfortunately, this is not the best approach, other emulators are able to execute a single 
instruction over multiple iterations of their emulation loop and mimic more accurately 
the behaviour of the real hardware, however, this is an easier approach to implement 
and does not impede the emulation from being relatively accurate.

**illegal opcodes not supported yet**

As many other architectures the MOS 6510 features a number of undocumented opcodes,
most of these are thought to be unintended and usually perform a mix of other opcodes 
operations:

[NMOS 6510 Unintended Opcodes - PDF](http://csdb.dk/getinternalfile.php/135165/NoMoreSecrets-NMOS6510UnintendedOpcodes-20142412.pdf)

Nevertheless, some of these unintended opcodes have proven to be useful and are often
used in games and demos, emudore will need to support these in the future if we ever 
intend to emulate serious games and demos.

**single-threaded**

emudore has been written as a single-threaded program, everything (including graphics) is 
handled within the same thread, again, this approach has possibly some drawbacks, especially 
in terms of performance, but it greatly simplifies the architecture: things like 
synchronization of the mainboard chips become easier to implement.

**hardware acceleration and vertical refresh sync**

The screen is refreshed once at the end of every frame, when the video raster reaches the 
last visible scanline, this way we're not constantly writing to the host video memory.

Also, to speed things up a bit I implemented hardware acceleration, we use an accelerated 
renderer and streaming textures, unfortunately, we need to keep the rendered video frame 
within emudore's memory and upload the texture to the GPU on every frame, direct pixel-access
is not doable straight on the GPU memory.

I also implemented vertical refresh synchronization, at the end of every frame we check 
whether we are ahead of time compared to a real C64 computer, if that's the case we sleep 
for a bit and wake up at the point a real C64 would have finished rendering the frame, this
effectively locks the screen refresh down to ~50Hz (PAL).

There are two main benefits of implementing vsync: it helps with performance since GPU 
operations are costly and after all we don't want to run at the limit of fps our GPU can 
handle; also, and more importantly, by doing this we emulate the speed of the real C64 
computer synce the CPU and other chips are synchronized and run within the same thread, if 
we are on a fast computer visual effects won't look accelerated and games become playable :) 

**VIC-II chip**

The vic-ii is a relatively complex chip, my implementation is not yet complete whatsoever,
and certain features are more than likely still buggy, for now four out of the five official 
graphic modes are supported:

 * standard character mode 
 * multicolor character mode 
 * standard bitmap mode 
 * multicolor bitmap mode

Smooth scrolling, sprites and raster interrupts have also been implemented and badlines
are also emulated.

Some things that are left to implement include: sprite double height/width mode, sprite 
collision interrupts, etc.

A simple approach was taken to emulate the raster beam drawing, pixels drawn to the 
screen surface are computed at the end of each scan line, this might result in 
certain graphic effects being badly emulated, bear in mind that timing is of the essence 
in the c64, well-versed programmers master and exploit it to put together amazing
effects that otherwise wouldn't be feasible.

**beware**

Due to some of the aforementioned facts, expect things to fail, don't even dream
the emulation is going to be pixel-exact, certain effects are likely to get badly 
emulated, specially if you're running things like a demo.

# Are you bleedin' serious radare2 is supported?

Indeed, for now it's only suppported on Linux and OSX (debug) builds, you can grab 
a fresh copy of radare from [github](https://github.com/radare/radare2)

Then fire the emulator up and connect with radare:

    r2 -w -a 6502 rap://localhost:9999//

For now radare can just read and modify memory, further support might be coming
down the line once [this feature](https://github.com/radare/radare2/issues/4173) 
gets implemented in radare.

Some pictures of radare in action:

![r2mem](/pics/r2_mem.png "r2mem") 
![r2dis](/pics/r2_dis.png "r2dis")

I hope this feature will come in useful to retrodev reverse engineers :)

# So now .. what?

There are many features of the currently emulated chips that I haven't implemented 
yet, time permitting my plan is to keep working and learning about other aspects of
the C64 technology, also, at some stage I'd love to get the time to work on:

  * Sound support: [SID](https://en.wikipedia.org/wiki/MOS_Technology_SID)
  * Floppy drive support: [VIC-1541](https://en.wikipedia.org/wiki/Commodore_1541)

# Alright, enough of your jibba-jabba, how do I run this?

If you are running a Linux Debian-based distro:

    sudo apt-get install g++ cmake libsdl2-dev

Then simply compile and run:

    make release
    cd build
    ./emudore

# What C64 programs can I load into this?

For the time being emudore can load PRGs, you can test: 

    ./emudore assets/prg/monopole.prg

emudore can also type BASIC listings for you (special keys not supported yet):

    ./emudore assets/bas/10print.bas 
    (then type RUN at the emulator window)

# Got some more screenshots?

Sure.. 

![parallax](/pics/parallax.png "parallax") ![mario](/pics/mario.png "mario") ![pacman](/pics/pacman.png "pacman") 
![hitmen](/pics/hitmen.png "hitmen") ![montezuma](/pics/montezuma.png "montezuma") ![ghostbusters](/pics/ghostbusters.png "ghostbusters") 


# References

If you are interested in computer archeology, and particularly in the C64, among
others, the following resources came in handy to develop (and get inspiration) while 
developing emudore:

 * [The C64 Wiki](http://www.c64-wiki.com/)
 * [Programming the Commodore 64: The Definitive Guide](http://www.amazon.co.uk/Programming-Commodore-64-Definitive-Guide/dp/0874550815/)
 * [Commodore: A Company on the Edge (book)](http://www.amazon.co.uk/Commodore-Company-Edge-Brian-Bagnall/dp/0973864966/)
 * [The Ultimate Commodore 64 Talk](https://www.youtube.com/watch?v=ZsRRCnque2E)
 * [Behind the scenes of a C64 demo](https://www.youtube.com/watch?v=So-m4NUzKLw)
 * [Dustlayer's blog](http://dustlayer.com/blog/)
 * [The MOS 6567/6569 video controller (VIC-II) and its application in the Commodore 64](http://www.zimmers.net/cbmpics/cbm/c64/vic-ii.txt)

# Forks 

Some people have forked emudore and experimented with it, some notable forks include:

* [Chris Frantz's C64 and NES emulator](https://github.com/cfrantz/emudore)
* [Scott Hutter's bare metal x86-64 emulator](https://github.com/xlar54/emudore64)

# License

I don't think anybody will ever dare to use this for an actual useful purpose, but just in case, 
the project is licensed under the [Apache 2.0 license](http://www.apache.org/licenses/LICENSE-2.0)


================================================
FILE: assets/bas/10print.bas
================================================
REM source: http://10print.org/
10 PRINT CHR$(205.5+RND(1)); : GOTO 10


================================================
FILE: assets/bas/bitmap.bas
================================================
10 POKE 53272,PEEK(53272)OR8:POKE 53265,PEEK(53265)OR32
20 FORI=8192TO16191 STEP 8
30 POKEI,240:POKEI+1,240:POKEI+2,240:POKEI+3,240
40 POKEI+4,15:POKEI+5,15:POKEI+6,15:POKEI+7,15
50 NEXT
60 FORI=1024TO2034:POKEI,251:NEXT
70 GOTO 70


================================================
FILE: assets/bas/bouncing.bas
================================================
REM source: http://www.lemon64.com/manual/
NEW
10 POKE 53281,1: PRINT"*"
20 POKE 53280,7: POKE 53281,6
30 X = 1 : Y = 1
40 DX = 1 : DY = 1
50 POKE 1024 + X + 40 * Y, 81
60 FOR T = 1 TO 10 : NEXT
70 POKE 1024 + X + 40 * Y, 32
80 X = X + DX
90 IF X <= 0 OR X >= 39 THEN DX = -DX
100 Y = Y + DY
110 IF Y <= 0 OR Y >= 24 THEN DY = -DY
120 GOTO 50


================================================
FILE: assets/bas/lowercase.bas
================================================
REM SWITCH TO LOWERCASE MODE
POKE 53272,23 


================================================
FILE: assets/roms/README.md
================================================
The following files have been downloaded from: 

ftp://www.zimmers.net/pub/cbm/firmware/computers/c64/

Please, bear in mind that these files might be subject to other licenses
than emudore's

# kernal.901227-03.bin

  This 8-kilobyte 2364 ROM is the third and essentially last revision of 
  the Commodore 64 KERNAL. It is the most widely spread version.

# basic.901226-01.bin

  Commodore 64 BASIC V2. The first and essentially only revision, located at 
  $A000-$BFFF. In the 64GS system firmware, the 30 unused bytes at $BF53-$BF70 
  are filled with $00 instead of $AA. In the Commodore 65 firmware, these bytes 
  are filled with $FF.

# characters.901225-01.bin

  The character generator ROM.


================================================
FILE: assets/tests/6502_functional_test.a65
================================================
;
; 6 5 0 2   F U N C T I O N A L   T E S T
;
; Copyright (C) 2012-2015  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
; 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 General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program.  If not, see <http://www.gnu.org/licenses/>.


; This program is designed to test all opcodes of a 6502 emulator using all
; addressing modes with focus on propper setting of the processor status
; register bits.
; 
; version 21-oct-2015
; contact info at http://2m5.de or email K@2m5.de
;
; assembled with AS65 from http://www.kingswood-consulting.co.uk/assemblers/
; command line switches: -l -m -s2 -w -h0
;                         |  |  |   |  no page headers in listing
;                         |  |  |   wide listing (133 char/col)
;                         |  |  write intel hex file instead of binary
;                         |  expand macros in listing
;                         generate pass2 listing
;
; No IO - should be run from a monitor with access to registers.
; To run load intel hex image with a load command, than alter PC to 400 hex
; (code_segment) and enter a go command.
; Loop on program counter determines error or successful completion of test.
; Check listing for relevant traps (jump/branch *).
; Please note that in early tests some instructions will have to be used before
; they are actually tested!
;
; RESET, NMI or IRQ should not occur and will be trapped if vectors are enabled.
; Tests documented behavior of the original NMOS 6502 only! No unofficial
; opcodes. Additional opcodes of newer versions of the CPU (65C02, 65816) will
; not be tested. Decimal ops will only be tested with valid BCD operands and
; N V Z flags will be ignored.
;
; Debugging hints:
;     Most of the code is written sequentially. if you hit a trap, check the
;   immediately preceeding code for the instruction to be tested. Results are
;   tested first, flags are checked second by pushing them onto the stack and
;   pulling them to the accumulator after the result was checked. The "real"
;   flags are no longer valid for the tested instruction at this time!
;     If the tested instruction was indexed, the relevant index (X or Y) must
;   also be checked. Opposed to the flags, X and Y registers are still valid.
;
; versions:
;   28-jul-2012  1st version distributed for testing
;   29-jul-2012  fixed references to location 0, now #0
;                added license - GPLv3
;   30-jul-2012  added configuration options
;   01-aug-2012  added trap macro to allow user to change error handling
;   01-dec-2012  fixed trap in branch field must be a branch
;   02-mar-2013  fixed PLA flags not tested
;   19-jul-2013  allowed ROM vectors to be loaded when load_data_direct = 0
;                added test sequence check to detect if tests jump their fence
;   23-jul-2013  added RAM integrity check option
;   16-aug-2013  added error report to standard output option
;   13-dec-2014  added binary/decimal opcode table switch test
;   14-dec-2014  improved relative address test
;   23-aug-2015  added option to disable self modifying tests
;   24-aug-2015  all self modifying immediate opcodes now execute in data RAM
;                added small branch offset pretest
;   21-oct-2015  added option to disable decimal mode ADC & SBC tests


; C O N F I G U R A T I O N

;ROM_vectors writable (0=no, 1=yes)
;if ROM vectors can not be used interrupts will not be trapped
;as a consequence BRK can not be tested but will be emulated to test RTI
ROM_vectors = 1

;load_data_direct (0=move from code segment, 1=load directly)
;loading directly is preferred but may not be supported by your platform
;0 produces only consecutive object code, 1 is not suitable for a binary image
load_data_direct = 0

;I_flag behavior (0=force enabled, 1=force disabled, 2=prohibit change, 3=allow
;change) 2 requires extra code and is not recommended. SEI & CLI can only be
;tested if you allow changing the interrupt status (I_flag = 3)
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
;                                add 2 if I_flag = 2
zero_page = $a  

;data_segment memory start address, $6A (106) 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
;                                   add 2.5 kB if I_flag = 2
code_segment = $400  

;self modifying code may be disabled to allow running in ROM
;0=part of the code is self modifying and must reside in RAM
;1=tests disabled: branch range
disable_selfmod = 0

;report errors through I/O channel (0=use standard self trap loops, 1=include
;report.i65 as I/O channel, add 3.5 kB)
report = 0

;RAM integrity test option. Checks for undesired RAM writes.
;set lowest non RAM or RAM mirror address page (-1=disable, 0=64k, $40=16k)
;leave disabled if a monitor, OS or background interrupt is allowed to alter RAM
ram_top = -1

;disable test decimal mode ADC & SBC, 0=enable, 1=disable,
;2=disable including decimal flag in processor status
disable_decimal = 0

        noopt       ;do not take shortcuts

;macros for error & success traps to allow user modification
;example:
;trap    macro
;        jsr my_error_handler
;        endm
;trap_eq macro
;        bne skip\?
;        trap           ;failed equal (zero)
;skip\?
;        endm
;
; my_error_handler should pop the calling address from the stack and report it.
; putting larger portions of code (more than 3 bytes) inside the trap macro
; may lead to branch range problems for some tests.
    if report = 0
trap    macro
        jmp *           ;failed anyway
        endm
trap_eq macro
        beq *           ;failed equal (zero)
        endm
trap_ne macro
        bne *           ;failed not equal (non zero)
        endm
trap_cs macro
        bcs *           ;failed carry set
        endm
trap_cc macro
        bcc *           ;failed carry clear
        endm
trap_mi macro
        bmi *           ;failed minus (bit 7 set)
        endm
trap_pl macro
        bpl *           ;failed plus (bit 7 clear)
        endm
trap_vs macro
        bvs *           ;failed overflow set
        endm
trap_vc macro
        bvc *           ;failed overflow clear
        endm
; please observe that during the test the stack gets invalidated
; therefore a RTS inside the success macro is not possible
success macro
        jmp *           ;test passed, no errors
        endm
    endif
    if report = 1
trap    macro
        jsr report_error
        endm
trap_eq macro
        bne skip\?
        trap           ;failed equal (zero)
skip\?
        endm
trap_ne macro
        beq skip\?
        trap            ;failed not equal (non zero)
skip\?
        endm
trap_cs macro
        bcc skip\?
        trap            ;failed carry set
skip\?
        endm
trap_cc macro
        bcs skip\?
        trap            ;failed carry clear
skip\?
        endm
trap_mi macro
        bpl skip\?
        trap            ;failed minus (bit 7 set)
skip\?
        endm
trap_pl macro
        bmi skip\?
        trap            ;failed plus (bit 7 clear)
skip\?
        endm
trap_vs macro
        bvc skip\?
        trap            ;failed overflow set
skip\?
        endm
trap_vc macro
        bvs skip\?
        trap            ;failed overflow clear
skip\?
        endm
; please observe that during the test the stack gets invalidated
; therefore a RTS inside the success macro is not possible
success macro
        jsr report_success
        endm
    endif


carry   equ %00000001   ;flag bits in status
zero    equ %00000010
intdis  equ %00000100
decmode equ %00001000
break   equ %00010000
reserv  equ %00100000
overfl  equ %01000000
minus   equ %10000000

fc      equ carry
fz      equ zero
fzc     equ carry+zero
fv      equ overfl
fvz     equ overfl+zero
fn      equ minus
fnc     equ minus+carry
fnz     equ minus+zero
fnzc    equ minus+zero+carry
fnv     equ minus+overfl

fao     equ break+reserv    ;bits always on after PHP, BRK
fai     equ fao+intdis      ;+ forced interrupt disable
faod    equ fao+decmode     ;+ ignore decimal
faid    equ fai+decmode     ;+ ignore decimal
m8      equ $ff             ;8 bit mask
m8i     equ $ff&~intdis     ;8 bit mask - interrupt disable

;macros to allow masking of status bits.
;masking test of decimal bit
;masking of interrupt enable/disable on load and compare
;masking of always on bits after PHP or BRK (unused & break) on compare
    if disable_decimal < 2
        if I_flag = 0
load_flag   macro
            lda #\1&m8i         ;force enable interrupts (mask I)
            endm
cmp_flag    macro
            cmp #(\1|fao)&m8i   ;I_flag is always enabled + always on bits
            endm
eor_flag    macro
            eor #(\1&m8i|fao)   ;mask I, invert expected flags + always on bits
            endm
        endif
        if I_flag = 1
load_flag   macro
            lda #\1|intdis      ;force disable interrupts
            endm
cmp_flag    macro
            cmp #(\1|fai)&m8    ;I_flag is always disabled + always on bits
            endm
eor_flag    macro
            eor #(\1|fai)       ;invert expected flags + always on bits + I
            endm
        endif
        if I_flag = 2
load_flag   macro
            lda #\1
            ora flag_I_on       ;restore I-flag
            and flag_I_off
            endm
cmp_flag    macro
            eor flag_I_on       ;I_flag is never changed
            cmp #(\1|fao)&m8i   ;expected flags + always on bits, mask I
            endm
eor_flag    macro
            eor flag_I_on       ;I_flag is never changed
            eor #(\1&m8i|fao)   ;mask I, invert expected flags + always on bits
            endm
        endif
        if I_flag = 3
load_flag   macro
            lda #\1             ;allow test to change I-flag (no mask)
            endm
cmp_flag    macro
            cmp #(\1|fao)&m8    ;expected flags + always on bits
            endm
eor_flag    macro
            eor #\1|fao         ;invert expected flags + always on bits
            endm
        endif
    else
        if I_flag = 0
load_flag   macro
            lda #\1&m8i         ;force enable interrupts (mask I)
            endm
cmp_flag    macro
            ora #decmode        ;ignore decimal mode bit
            cmp #(\1|faod)&m8i  ;I_flag is always enabled + always on bits
            endm
eor_flag    macro
            ora #decmode        ;ignore decimal mode bit
            eor #(\1&m8i|faod)  ;mask I, invert expected flags + always on bits
            endm
        endif
        if I_flag = 1
load_flag   macro
            lda #\1|intdis      ;force disable interrupts
            endm
cmp_flag    macro
            ora #decmode        ;ignore decimal mode bit
            cmp #(\1|faid)&m8   ;I_flag is always disabled + always on bits
            endm
eor_flag    macro
            ora #decmode        ;ignore decimal mode bit
            eor #(\1|faid)      ;invert expected flags + always on bits + I
            endm
        endif
        if I_flag = 2
load_flag   macro
            lda #\1
            ora flag_I_on       ;restore I-flag
            and flag_I_off
            endm
cmp_flag    macro
            eor flag_I_on       ;I_flag is never changed
            ora #decmode        ;ignore decimal mode bit
            cmp #(\1|faod)&m8i  ;expected flags + always on bits, mask I
            endm
eor_flag    macro
            eor flag_I_on       ;I_flag is never changed
            ora #decmode        ;ignore decimal mode bit
            eor #(\1&m8i|faod)  ;mask I, invert expected flags + always on bits
            endm
        endif
        if I_flag = 3
load_flag   macro
            lda #\1             ;allow test to change I-flag (no mask)
            endm
cmp_flag    macro
            ora #decmode        ;ignore decimal mode bit
            cmp #(\1|faod)&m8   ;expected flags + always on bits
            endm
eor_flag    macro
            ora #decmode        ;ignore decimal mode bit
            eor #\1|faod        ;invert expected flags + always on bits
            endm
        endif
    endif

;macros to set (register|memory|zeropage) & status
set_stat    macro       ;setting flags in the processor status register
            load_flag \1
            pha         ;use stack to load status
            plp
            endm

set_a       macro       ;precharging accu & status
            load_flag \2
            pha         ;use stack to load status
            lda #\1     ;precharge accu
            plp
            endm

set_x       macro       ;precharging index & status
            load_flag \2
            pha         ;use stack to load status
            ldx #\1     ;precharge index x
            plp
            endm

set_y       macro       ;precharging index & status
            load_flag \2
            pha         ;use stack to load status
            ldy #\1     ;precharge index y
            plp
            endm

set_ax      macro       ;precharging indexed accu & immediate status
            load_flag \2
            pha         ;use stack to load status
            lda \1,x    ;precharge accu
            plp
            endm

set_ay      macro       ;precharging indexed accu & immediate status
            load_flag \2
            pha         ;use stack to load status
            lda \1,y    ;precharge accu
            plp
            endm

set_z       macro       ;precharging indexed zp & immediate status
            load_flag \2
            pha         ;use stack to load status
            lda \1,x    ;load to zeropage
            sta zpt
            plp
            endm

set_zx      macro       ;precharging zp,x & immediate status
            load_flag \2
            pha         ;use stack to load status
            lda \1,x    ;load to indexed zeropage
            sta zpt,x
            plp
            endm

set_abs     macro       ;precharging indexed memory & immediate status
            load_flag \2
            pha         ;use stack to load status
            lda \1,x    ;load to memory
            sta abst
            plp
            endm

set_absx    macro       ;precharging abs,x & immediate status
            load_flag \2
            pha         ;use stack to load status
            lda \1,x    ;load to indexed memory
            sta abst,x
            plp
            endm

;macros to test (register|memory|zeropage) & status & (mask)
tst_stat    macro       ;testing flags in the processor status register
            php         ;save status
            pla         ;use stack to retrieve status
            pha
            cmp_flag \1
            trap_ne
            plp         ;restore status
            endm
            
tst_a       macro       ;testing result in accu & flags
            php         ;save flags
            cmp #\1     ;test result
            trap_ne
            pla         ;load status
            pha
            cmp_flag \2
            trap_ne
            plp         ;restore status
            endm

tst_x       macro       ;testing result in x index & flags
            php         ;save flags
            cpx #\1     ;test result
            trap_ne
            pla         ;load status
            pha
            cmp_flag \2
            trap_ne
            plp         ;restore status
            endm

tst_y       macro       ;testing result in y index & flags
            php         ;save flags
            cpy #\1     ;test result
            trap_ne
            pla         ;load status
            pha
            cmp_flag \2
            trap_ne
            plp         ;restore status
            endm

tst_ax      macro       ;indexed testing result in accu & flags
            php         ;save flags
            cmp \1,x    ;test result
            trap_ne
            pla         ;load status
            eor_flag \3
            cmp \2,x    ;test flags
            trap_ne     ;
            endm

tst_ay      macro       ;indexed testing result in accu & flags
            php         ;save flags
            cmp \1,y    ;test result
            trap_ne     ;
            pla         ;load status
            eor_flag \3
            cmp \2,y    ;test flags
            trap_ne
            endm
        
tst_z       macro       ;indexed testing result in zp & flags
            php         ;save flags
            lda zpt
            cmp \1,x    ;test result
            trap_ne
            pla         ;load status
            eor_flag \3
            cmp \2,x    ;test flags
            trap_ne
            endm

tst_zx      macro       ;testing result in zp,x & flags
            php         ;save flags
            lda zpt,x
            cmp \1,x    ;test result
            trap_ne
            pla         ;load status
            eor_flag \3
            cmp \2,x    ;test flags
            trap_ne
            endm

tst_abs     macro       ;indexed testing result in memory & flags
            php         ;save flags
            lda abst
            cmp \1,x    ;test result
            trap_ne
            pla         ;load status
            eor_flag \3
            cmp \2,x    ;test flags
            trap_ne
            endm

tst_absx    macro       ;testing result in abs,x & flags
            php         ;save flags
            lda abst,x
            cmp \1,x    ;test result
            trap_ne
            pla         ;load status
            eor_flag \3
            cmp \2,x    ;test flags
            trap_ne
            endm
            
; RAM integrity test
;   verifies that none of the previous tests has altered RAM outside of the
;   designated write areas.
;   uses zpt word as indirect pointer, zpt+2 word as checksum
        if ram_top > -1
check_ram   macro 
            cld
            lda #0
            sta zpt         ;set low byte of indirect pointer
            sta zpt+3       ;checksum high byte
          if disable_selfmod = 0
            sta range_adr   ;reset self modifying code
          endif
            clc
            ldx #zp_bss-zero_page ;zeropage - write test area
ccs3\?      adc zero_page,x
            bcc ccs2\?
            inc zpt+3       ;carry to high byte
            clc
ccs2\?      inx
            bne ccs3\?
            ldx #hi(abs1)   ;set high byte of indirect pointer
            stx zpt+1
            ldy #lo(abs1)   ;data after write & execute test area
ccs5\?      adc (zpt),y
            bcc ccs4\?
            inc zpt+3       ;carry to high byte
            clc
ccs4\?      iny
            bne ccs5\?
            inx             ;advance RAM high address
            stx zpt+1
            cpx #ram_top
            bne ccs5\?
            sta zpt+2       ;checksum low is
            cmp ram_chksm   ;checksum low expected
            trap_ne         ;checksum mismatch
            lda zpt+3       ;checksum high is
            cmp ram_chksm+1 ;checksum high expected
            trap_ne         ;checksum mismatch
            endm            
        else
check_ram   macro
            ;RAM check disabled - RAM size not set
            endm
        endif

next_test   macro           ;make sure, tests don't jump the fence
            lda test_case   ;previous test
            cmp #test_num
            trap_ne         ;test is out of sequence
test_num = test_num + 1
            lda #test_num   ;*** next tests' number
            sta test_case
            ;check_ram       ;uncomment to find altered RAM after each test
            endm

    if load_data_direct = 1
        data
    else
        bss                 ;uninitialized segment, copy of data at end of code!
    endif
        org zero_page
;break test interrupt save
irq_a   ds  1               ;a register
irq_x   ds  1               ;x register
    if I_flag = 2
;masking for I bit in status
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
;add/subtract operand generation and result/flag prediction
adfc    ds  1               ;carry flag before op
ad1     ds  1               ;operand 1 - accumulator
ad2     ds  1               ;operand 2 - memory / immediate
adrl    ds  1               ;expected result bits 0-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
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
zpOR    db  0,$1f,$71,$80   ;test pattern for OR
zpAN    db  $0f,$ff,$7f,$80 ;test pattern for AND
zpEO    db  $ff,$0f,$8f,$8f ;test pattern for EOR
;indirect addressing pointers
ind1    dw  abs1            ;indirect pointer to pattern in absolute memory
        dw  abs1+1
        dw  abs1+2
        dw  abs1+3
        dw  abs7f
inw1    dw  abs1-$f8        ;indirect pointer for wrap-test pattern
indt    dw  abst            ;indirect pointer to store area in absolute memory
        dw  abst+1
        dw  abst+2
        dw  abst+3
inwt    dw  abst-$f8        ;indirect pointer for wrap-test store
indAN   dw  absAN           ;indirect pointer to AND pattern in absolute memory
        dw  absAN+1
        dw  absAN+2
        dw  absAN+3
indEO   dw  absEO           ;indirect pointer to EOR pattern in absolute memory
        dw  absEO+1
        dw  absEO+2
        dw  absEO+3
indOR   dw  absOR           ;indirect pointer to OR pattern in absolute memory
        dw  absOR+1
        dw  absOR+2
        dw  absOR+3
;add/subtract indirect pointers
adi2    dw  ada2            ;indirect pointer to operand 2 in absolute memory
sbi2    dw  sba2            ;indirect pointer to complemented operand 2 (SBC)
adiy2   dw  ada2-$ff        ;with offset for indirect indexed
sbiy2   dw  sba2-$ff
zp_bss_end
   
        org data_segment
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
ada2    ds  1               ;operand 2
sba2    ds  1               ;operand 2 complemented for subtract
        ds  3               ;fill remaining bytes
data_bss
    if load_data_direct = 1
ex_andi and #0              ;execute immediate opcodes
        rts
ex_eori eor #0              ;execute immediate opcodes
        rts
ex_orai ora #0              ;execute immediate opcodes
        rts
ex_adci adc #0              ;execute immediate opcodes
        rts
ex_sbci sbc #0              ;execute immediate opcodes
        rts
    else
ex_andi ds  3
ex_eori ds  3
ex_orai ds  3
ex_adci ds  3
ex_sbci ds  3
    endif
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
;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
;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
;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
;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
;logical results
absrlo  db  0,$ff,$7f,$80
absflo  db  fz,fn,0,fn
data_bss_end


        code
        org code_segment
start   cld
        ldx #$ff
        txs
        lda #0          ;*** test 0 = initialize
        sta test_case
test_num = 0

;stop interrupts before initializing BSS
    if I_flag = 1
        sei
    endif
    
;initialize I/O for report channel
    if report = 1
        jsr report_init
    endif
    
;pretest small branch offset
        ldx #5
        jmp psb_test
psb_bwok
        ldy #5
        bne psb_forw
        trap        ;branch should be taken
        dey         ;forward landing zone
        dey
        dey
        dey
        dey
psb_forw
        dey
        dey
        dey
        dey
        dey
        beq psb_fwok
        trap        ;forward offset

        dex         ;backward landing zone
        dex
        dex
        dex
        dex
psb_back
        dex
        dex
        dex
        dex
        dex
        beq psb_bwok
        trap        ;backward offset
psb_test
        bne psb_back
        trap        ;branch should be taken
psb_fwok
        
;initialize BSS segment
    if load_data_direct != 1
        ldx #zp_end-zp_init-1
ld_zp   lda zp_init,x
        sta zp_bss,x
        dex
        bpl ld_zp
        ldx #data_end-data_init-1
ld_data lda data_init,x
        sta data_bss,x
        dex
        bpl ld_data
      if ROM_vectors = 1
        ldx #5
ld_vect lda vec_init,x
        sta vec_bss,x
        dex
        bpl ld_vect
      endif
    endif

;retain status of interrupt flag
    if I_flag = 2
        php
        pla
        and #4          ;isolate flag
        sta flag_I_on   ;or mask
        eor #lo(~4)     ;reverse
        sta flag_I_off  ;and mask
    endif
        
;generate checksum for RAM integrity test
    if ram_top > -1
        lda #0 
        sta zpt         ;set low byte of indirect pointer
        sta ram_chksm+1 ;checksum high byte
      if disable_selfmod = 0
        sta range_adr   ;reset self modifying code
      endif
        clc
        ldx #zp_bss-zero_page ;zeropage - write test area
gcs3    adc zero_page,x
        bcc gcs2
        inc ram_chksm+1 ;carry to high byte
        clc
gcs2    inx
        bne gcs3
        ldx #hi(abs1)   ;set high byte of indirect pointer
        stx zpt+1
        ldy #lo(abs1)   ;data after write & execute test area
gcs5    adc (zpt),y
        bcc gcs4
        inc ram_chksm+1 ;carry to high byte
        clc
gcs4    iny
        bne gcs5
        inx             ;advance RAM high address
        stx zpt+1
        cpx #ram_top
        bne gcs5
        sta ram_chksm   ;checksum complete
    endif
        next_test            

    if disable_selfmod = 0
;testing relative addressing with BEQ
        ldy #$fe        ;testing maximum range, not -1/-2 (invalid/self adr)
range_loop
        dey             ;next relative address
        tya
        tax             ;precharge count to end of loop
        bpl range_fw    ;calculate relative address
        clc             ;avoid branch self or to relative address of branch
        adc #2
        nop             ;offset landing zone - tolerate +/-5 offset to branch
        nop
        nop
        nop
        nop
range_fw
        nop
        nop
        nop
        nop
        nop
        eor #$7f        ;complement except sign
        sta range_adr   ;load into test target
        lda #0          ;should set zero flag in status register
        jmp range_op
        
        dex             ; offset landing zone - backward branch too far
        dex
        dex
        dex
        dex
        ;relative address target field with branch under test in the middle
        dex             ;-128 - max backward
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex             ;-120
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex             ;-110
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex             ;-100
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex             ;-90
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex             ;-80
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex             ;-70
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex             ;-60
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex             ;-50
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex             ;-40
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex             ;-30
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex             ;-20
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex             ;-10
        dex
        dex
        dex
        dex
        dex
        dex
        dex             ;-3
range_op                ;test target with zero flag=0, z=1 if previous dex
range_adr   = *+1       ;modifiable relative address
        beq *+64        ;+64 if called without modification
        dex             ;+0
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex             ;+10
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex             ;+20
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex             ;+30
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex             ;+40
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex             ;+50
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex             ;+60
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex             ;+70
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex             ;+80
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex             ;+90
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex             ;+100
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex             ;+110
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex
        dex             ;+120
        dex
        dex
        dex
        dex
        dex
        dex
        nop             ;offset landing zone - forward branch too far
        nop
        nop
        nop
        nop
        beq range_ok    ;+127 - max forward
        trap            ; bad range
        nop             ;offset landing zone - tolerate +/-5 offset to branch
        nop
        nop
        nop
        nop
range_ok
        nop
        nop
        nop
        nop
        nop
        cpy #0
        beq range_end   
        jmp range_loop
range_end               ;range test successful
    endif
        next_test

;partial test BNE & CMP, CPX, CPY immediate
        cpy #1          ;testing BNE true
        bne test_bne
        trap 
test_bne
        lda #0 
        cmp #0          ;test compare immediate 
        trap_ne
        trap_cc
        trap_mi
        cmp #1
        trap_eq 
        trap_cs
        trap_pl
        tax 
        cpx #0          ;test compare x immediate
        trap_ne
        trap_cc
        trap_mi
        cpx #1
        trap_eq 
        trap_cs
        trap_pl
        tay 
        cpy #0          ;test compare y immediate
        trap_ne
        trap_cc
        trap_mi
        cpy #1
        trap_eq 
        trap_cs
        trap_pl
        next_test
;testing stack operations PHA PHP PLA PLP
            
        ldx #$ff        ;initialize stack
        txs
        lda #$55
        pha
        lda #$aa
        pha
        cmp $1fe        ;on stack ?
        trap_ne
        tsx
        txa             ;overwrite accu
        cmp #$fd        ;sp decremented?
        trap_ne
        pla
        cmp #$aa        ;successful retreived from stack?
        trap_ne
        pla
        cmp #$55
        trap_ne
        cmp $1ff        ;remains on stack?
        trap_ne
        tsx
        cpx #$ff        ;sp incremented?
        trap_ne
        next_test

;testing branch decisions BPL BMI BVC BVS BCC BCS BNE BEQ
        set_stat $ff    ;all on
        bpl nbr1        ;branches should not be taken
        bvc nbr2
        bcc nbr3
        bne nbr4
        bmi br1         ;branches should be taken
        trap 
br1     bvs br2
        trap 
br2     bcs br3
        trap 
br3     beq br4
        trap 
nbr1
        trap            ;previous bpl taken 
nbr2
        trap            ;previous bvc taken
nbr3
        trap            ;previous bcc taken
nbr4
        trap            ;previous bne taken
br4     php
        tsx
        cpx #$fe        ;sp after php?
        trap_ne
        pla
        cmp_flag $ff    ;returned all flags on?
        trap_ne
        tsx
        cpx #$ff        ;sp after php?
        trap_ne
        set_stat 0      ;all off
        bmi nbr11       ;branches should not be taken
        bvs nbr12
        bcs nbr13
        beq nbr14
        bpl br11        ;branches should be taken
        trap 
br11    bvc br12
        trap 
br12    bcc br13
        trap 
br13    bne br14
        trap 
nbr11
        trap            ;previous bmi taken 
nbr12
        trap            ;previous bvs taken 
nbr13
        trap            ;previous bcs taken 
nbr14
        trap            ;previous beq taken 
br14    php
        pla
        cmp_flag 0      ;flags off except break (pushed by sw) + reserved?
        trap_ne
        ;crosscheck flags
        set_stat zero
        bne brzs1
        beq brzs2
brzs1
        trap            ;branch zero/non zero
brzs2   bcs brzs3
        bcc brzs4
brzs3
        trap            ;branch carry/no carry
brzs4   bmi brzs5
        bpl brzs6
brzs5
        trap            ;branch minus/plus
brzs6   bvs brzs7
        bvc brzs8
brzs7
        trap            ;branch overflow/no overflow
brzs8
        set_stat carry
        beq brcs1
        bne brcs2
brcs1
        trap            ;branch zero/non zero
brcs2   bcc brcs3
        bcs brcs4
brcs3
        trap            ;branch carry/no carry
brcs4   bmi brcs5
        bpl brcs6
brcs5
        trap            ;branch minus/plus
brcs6   bvs brcs7
        bvc brcs8
brcs7
        trap            ;branch overflow/no overflow

brcs8
        set_stat minus
        beq brmi1
        bne brmi2
brmi1
        trap            ;branch zero/non zero
brmi2   bcs brmi3
        bcc brmi4
brmi3
        trap            ;branch carry/no carry
brmi4   bpl brmi5
        bmi brmi6
brmi5
        trap            ;branch minus/plus
brmi6   bvs brmi7
        bvc brmi8
brmi7
        trap            ;branch overflow/no overflow
brmi8
        set_stat overfl
        beq brvs1
        bne brvs2
brvs1
        trap            ;branch zero/non zero
brvs2   bcs brvs3
        bcc brvs4
brvs3
        trap            ;branch carry/no carry
brvs4   bmi brvs5
        bpl brvs6
brvs5
        trap            ;branch minus/plus
brvs6   bvc brvs7
        bvs brvs8
brvs7
        trap            ;branch overflow/no overflow
brvs8
        set_stat $ff-zero
        beq brzc1
        bne brzc2
brzc1
        trap            ;branch zero/non zero
brzc2   bcc brzc3
        bcs brzc4
brzc3
        trap            ;branch carry/no carry
brzc4   bpl brzc5
        bmi brzc6
brzc5
        trap            ;branch minus/plus
brzc6   bvc brzc7
        bvs brzc8
brzc7
        trap            ;branch overflow/no overflow
brzc8
        set_stat $ff-carry
        bne brcc1
        beq brcc2
brcc1
        trap            ;branch zero/non zero
brcc2   bcs brcc3
        bcc brcc4
brcc3
        trap            ;branch carry/no carry
brcc4   bpl brcc5
        bmi brcc6
brcc5
        trap            ;branch minus/plus
brcc6   bvc brcc7
        bvs brcc8
brcc7
        trap            ;branch overflow/no overflow
brcc8
        set_stat $ff-minus
        bne brpl1
        beq brpl2
brpl1
        trap            ;branch zero/non zero
brpl2   bcc brpl3
        bcs brpl4
brpl3
        trap            ;branch carry/no carry
brpl4   bmi brpl5
        bpl brpl6
brpl5
        trap            ;branch minus/plus
brpl6   bvc brpl7
        bvs brpl8
brpl7
        trap            ;branch overflow/no overflow
brpl8
        set_stat $ff-overfl
        bne brvc1
        beq brvc2
brvc1
        trap            ;branch zero/non zero
brvc2   bcc brvc3
        bcs brvc4
brvc3
        trap            ;branch carry/no carry
brvc4   bpl brvc5
        bmi brvc6
brvc5
        trap            ;branch minus/plus
brvc6   bvs brvc7
        bvc brvc8
brvc7
        trap            ;branch overflow/no overflow
brvc8
        next_test

; test PHA does not alter flags or accumulator but PLA does
        ldx #$55        ;x & y protected
        ldy #$aa
        set_a 1,$ff     ;push
        pha
        tst_a 1,$ff
        set_a 0,0
        pha
        tst_a 0,0
        set_a $ff,$ff
        pha
        tst_a $ff,$ff
        set_a 1,0
        pha
        tst_a 1,0
        set_a 0,$ff
        pha
        tst_a 0,$ff
        set_a $ff,0
        pha
        tst_a $ff,0
        set_a 0,$ff     ;pull
        pla
        tst_a $ff,$ff-zero
        set_a $ff,0
        pla
        tst_a 0,zero
        set_a $fe,$ff
        pla
        tst_a 1,$ff-zero-minus
        set_a 0,0
        pla
        tst_a $ff,minus
        set_a $ff,$ff
        pla
        tst_a 0,$ff-minus
        set_a $fe,0
        pla
        tst_a 1,0
        cpx #$55        ;x & y unchanged?
        trap_ne
        cpy #$aa
        trap_ne
        next_test
 
; partial pretest EOR #
        set_a $3c,0
        eor #$c3
        tst_a $ff,fn
        set_a $c3,0
        eor #$c3
        tst_a 0,fz
        next_test

; PC modifying instructions except branches (NOP, JMP, JSR, RTS, BRK, RTI)
; testing NOP
        ldx #$24
        ldy #$42
        set_a $18,0
        nop
        tst_a $18,0
        cpx #$24
        trap_ne
        cpy #$42
        trap_ne
        ldx #$db
        ldy #$bd
        set_a $e7,$ff
        nop
        tst_a $e7,$ff
        cpx #$db
        trap_ne
        cpy #$bd
        trap_ne
        next_test
        
; jump absolute
        set_stat $0
        lda #'F'
        ldx #'A'
        ldy #'R'        ;N=0, V=0, Z=0, C=0
        jmp test_far
        nop
        nop
        trap_ne         ;runover protection
        inx
        inx
far_ret 
        trap_eq         ;returned flags OK?
        trap_pl
        trap_cc
        trap_vc
        cmp #('F'^$aa)  ;returned registers OK?
        trap_ne
        cpx #('A'+1)
        trap_ne
        cpy #('R'-3)
        trap_ne
        dex
        iny
        iny
        iny
        eor #$aa        ;N=0, V=1, Z=0, C=1
        jmp test_near
        nop
        nop
        trap_ne         ;runover protection
        inx
        inx
test_near
        trap_eq         ;passed flags OK?
        trap_mi
        trap_cc
        trap_vc
        cmp #'F'        ;passed registers OK?
        trap_ne
        cpx #'A'
        trap_ne
        cpy #'R'
        trap_ne
        next_test
        
; jump indirect
        set_stat 0
        lda #'I'
        ldx #'N'
        ldy #'D'        ;N=0, V=0, Z=0, C=0
        jmp (ptr_tst_ind)
        nop
        trap_ne         ;runover protection
        dey
        dey
ind_ret 
        php             ;either SP or Y count will fail, if we do not hit
        dey
        dey
        dey
        plp
        trap_eq         ;returned flags OK?
        trap_pl
        trap_cc
        trap_vc
        cmp #('I'^$aa)  ;returned registers OK?
        trap_ne
        cpx #('N'+1)
        trap_ne
        cpy #('D'-6)
        trap_ne
        tsx             ;SP check
        cpx #$ff
        trap_ne
        next_test

; jump subroutine & return from subroutine
        set_stat 0
        lda #'J'
        ldx #'S'
        ldy #'R'        ;N=0, V=0, Z=0, C=0
        jsr test_jsr
jsr_ret = *-1           ;last address of jsr = return address
        php             ;either SP or Y count will fail, if we do not hit
        dey
        dey
        dey
        plp
        trap_eq         ;returned flags OK?
        trap_pl
        trap_cc
        trap_vc
        cmp #('J'^$aa)  ;returned registers OK?
        trap_ne
        cpx #('S'+1)
        trap_ne
        cpy #('R'-6)
        trap_ne
        tsx             ;sp?
        cpx #$ff
        trap_ne
        next_test

; break & return from interrupt
    if ROM_vectors = 1
        set_stat 0
        lda #'B'
        ldx #'R'
        ldy #'K'        ;N=0, V=0, Z=0, C=0
        brk
    else
        lda #hi brk_ret ;emulated break
        pha
        lda #lo brk_ret
        pha
        lda #fao        ;set break & unused on stack
        pha
        set_stat intdis
        lda #'B'
        ldx #'R'
        ldy #'K'        ;N=0, V=0, Z=0, C=0
        jmp irq_trap
    endif
        dey             ;should not be executed
brk_ret                 ;address of break return
        php             ;either SP or Y count will fail, if we do not hit
        dey
        dey
        dey
        cmp #('B'^$aa)  ;returned registers OK?
        trap_ne
        cpx #('R'+1)
        trap_ne
        cpy #('K'-6)
        trap_ne
        pla             ;returned flags OK (unchanged)?
        cmp_flag 0
        trap_ne
        tsx             ;sp?
        cpx #$ff
        trap_ne
        next_test
 
; test set and clear flags CLC CLI CLD CLV SEC SEI SED
        set_stat $ff
        clc
        tst_stat $ff-carry
        sec
        tst_stat $ff
    if I_flag = 3
        cli
        tst_stat $ff-intdis
        sei
        tst_stat $ff
    endif
        cld
        tst_stat $ff-decmode
        sed
        tst_stat $ff
        clv
        tst_stat $ff-overfl
        set_stat 0
        tst_stat 0
        sec
        tst_stat carry
        clc
        tst_stat 0  
    if I_flag = 3
        sei
        tst_stat intdis
        cli
        tst_stat 0
    endif  
        sed
        tst_stat decmode
        cld
        tst_stat 0  
        set_stat overfl
        tst_stat overfl
        clv
        tst_stat 0
        next_test
; testing index register increment/decrement and transfer
; INX INY DEX DEY TAX TXA TAY TYA 
        ldx #$fe
        set_stat $ff
        inx             ;ff
        tst_x $ff,$ff-zero
        inx             ;00
        tst_x 0,$ff-minus
        inx             ;01
        tst_x 1,$ff-minus-zero
        dex             ;00
        tst_x 0,$ff-minus
        dex             ;ff
        tst_x $ff,$ff-zero
        dex             ;fe
        set_stat 0
        inx             ;ff
        tst_x $ff,minus
        inx             ;00
        tst_x 0,zero
        inx             ;01
        tst_x 1,0
        dex             ;00
        tst_x 0,zero
        dex             ;ff
        tst_x $ff,minus

        ldy #$fe
        set_stat $ff
        iny             ;ff
        tst_y $ff,$ff-zero
        iny             ;00
        tst_y 0,$ff-minus
        iny             ;01
        tst_y 1,$ff-minus-zero
        dey             ;00
        tst_y 0,$ff-minus
        dey             ;ff
        tst_y $ff,$ff-zero
        dey             ;fe
        set_stat 0
        iny             ;ff
        tst_y $ff,0+minus
        iny             ;00
        tst_y 0,zero
        iny             ;01
        tst_y 1,0
        dey             ;00
        tst_y 0,zero
        dey             ;ff
        tst_y $ff,minus
                
        ldx #$ff
        set_stat $ff
        txa
        tst_a $ff,$ff-zero
        php
        inx             ;00
        plp
        txa
        tst_a 0,$ff-minus
        php
        inx             ;01
        plp
        txa
        tst_a 1,$ff-minus-zero
        set_stat 0
        txa
        tst_a 1,0
        php
        dex             ;00
        plp
        txa
        tst_a 0,zero
        php
        dex             ;ff
        plp
        txa
        tst_a $ff,minus
                        
        ldy #$ff
        set_stat $ff
        tya
        tst_a $ff,$ff-zero
        php
        iny             ;00
        plp
        tya
        tst_a 0,$ff-minus
        php
        iny             ;01
        plp
        tya
        tst_a 1,$ff-minus-zero
        set_stat 0
        tya
        tst_a 1,0
        php
        dey             ;00
        plp
        tya
        tst_a 0,zero
        php
        dey             ;ff
        plp
        tya
        tst_a $ff,minus

        load_flag $ff
        pha
        ldx #$ff        ;ff
        txa
        plp             
        tay
        tst_y $ff,$ff-zero
        php
        inx             ;00
        txa
        plp
        tay
        tst_y 0,$ff-minus
        php
        inx             ;01
        txa
        plp
        tay
        tst_y 1,$ff-minus-zero
        load_flag 0
        pha
        lda #0
        txa
        plp
        tay
        tst_y 1,0
        php
        dex             ;00
        txa
        plp
        tay
        tst_y 0,zero
        php
        dex             ;ff
        txa
        plp
        tay
        tst_y $ff,minus


        load_flag $ff
        pha
        ldy #$ff        ;ff
        tya
        plp
        tax
        tst_x $ff,$ff-zero
        php
        iny             ;00
        tya
        plp
        tax
        tst_x 0,$ff-minus
        php
        iny             ;01
        tya
        plp
        tax
        tst_x 1,$ff-minus-zero
        load_flag 0
        pha
        lda #0          ;preset status
        tya
        plp
        tax
        tst_x 1,0
        php
        dey             ;00
        tya
        plp
        tax
        tst_x 0,zero
        php
        dey             ;ff
        tya
        plp
        tax
        tst_x $ff,minus
        next_test
     
;TSX sets NZ - TXS does not
;  This section also tests for proper stack wrap around.
        ldx #1          ;01
        set_stat $ff
        txs
        php
        lda $101
        cmp_flag $ff
        trap_ne
        set_stat 0
        txs
        php
        lda $101
        cmp_flag 0
        trap_ne
        dex             ;00
        set_stat $ff
        txs
        php
        lda $100
        cmp_flag $ff
        trap_ne
        set_stat 0
        txs
        php
        lda $100
        cmp_flag 0
        trap_ne
        dex             ;ff
        set_stat $ff
        txs
        php
        lda $1ff
        cmp_flag $ff
        trap_ne
        set_stat 0
        txs
        php
        lda $1ff
        cmp_flag 0
        
        ldx #1
        txs             ;sp=01
        set_stat $ff
        tsx             ;clears Z, N
        php             ;sp=00
        cpx #1
        trap_ne
        lda $101
        cmp_flag $ff-minus-zero
        trap_ne
        set_stat $ff
        tsx             ;clears N, sets Z
        php             ;sp=ff
        cpx #0
        trap_ne
        lda $100
        cmp_flag $ff-minus
        trap_ne
        set_stat $ff
        tsx             ;clears N, sets Z
        php             ;sp=fe
        cpx #$ff
        trap_ne
        lda $1ff
        cmp_flag $ff-zero
        trap_ne
        
        ldx #1
        txs             ;sp=01
        set_stat 0
        tsx             ;clears Z, N
        php             ;sp=00
        cpx #1
        trap_ne
        lda $101
        cmp_flag 0
        trap_ne
        set_stat 0
        tsx             ;clears N, sets Z
        php             ;sp=ff
        cpx #0
        trap_ne
        lda $100
        cmp_flag zero
        trap_ne
        set_stat 0
        tsx             ;clears N, sets Z
        php             ;sp=fe
        cpx #$ff
        trap_ne
        lda $1ff
        cmp_flag minus
        trap_ne
        pla             ;sp=ff
        next_test
        
; testing index register load & store LDY LDX STY STX all addressing modes
; LDX / STX - zp,y / abs,y
        ldy #3
tldx    
        set_stat 0
        ldx zp1,y
        php         ;test stores do not alter flags
        txa
        eor #$c3
        plp
        sta abst,y
        php         ;flags after load/store sequence
        eor #$c3
        cmp abs1,y  ;test result
        trap_ne
        pla         ;load status
        eor_flag 0
        cmp fLDx,y  ;test flags
        trap_ne
        dey
        bpl tldx                  

        ldy #3
tldx1   
        set_stat $ff
        ldx zp1,y
        php         ;test stores do not alter flags
        txa
        eor #$c3
        plp
        sta abst,y
        php         ;flags after load/store sequence
        eor #$c3
        cmp abs1,y  ;test result
        trap_ne
        pla         ;load status
        eor_flag lo~fnz ;mask bits not altered
        cmp fLDx,y  ;test flags
        trap_ne
        dey
        bpl tldx1                  

        ldy #3
tldx2   
        set_stat 0
        ldx abs1,y
        php         ;test stores do not alter flags
        txa
        eor #$c3
        tax
        plp
        stx zpt,y
        php         ;flags after load/store sequence
        eor #$c3
        cmp zp1,y   ;test result
        trap_ne
        pla         ;load status
        eor_flag 0
        cmp fLDx,y  ;test flags
        trap_ne
        dey
        bpl tldx2                  

        ldy #3
tldx3   
        set_stat $ff
        ldx abs1,y
        php         ;test stores do not alter flags
        txa
        eor #$c3
        tax
        plp
        stx zpt,y
        php         ;flags after load/store sequence
        eor #$c3
        cmp zp1,y   ;test result
        trap_ne
        pla         ;load status
        eor_flag lo~fnz ;mask bits not altered
        cmp fLDx,y  ;test flags
        trap_ne
        dey
        bpl tldx3
        
        ldy #3      ;testing store result
        ldx #0
tstx    lda zpt,y
        eor #$c3
        cmp zp1,y
        trap_ne     ;store to zp data
        stx zpt,y   ;clear                
        lda abst,y
        eor #$c3
        cmp abs1,y
        trap_ne     ;store to abs data
        txa
        sta abst,y  ;clear                
        dey
        bpl tstx
        next_test
        
; indexed wraparound test (only zp should wrap)
        ldy #3+$fa
tldx4   ldx zp1-$fa&$ff,y   ;wrap on indexed zp
        txa
        sta abst-$fa,y      ;no STX abs,y!
        dey
        cpy #$fa
        bcs tldx4                  
        ldy #3+$fa
tldx5   ldx abs1-$fa,y      ;no wrap on indexed abs
        stx zpt-$fa&$ff,y
        dey
        cpy #$fa
        bcs tldx5                  
        ldy #3      ;testing wraparound result
        ldx #0
tstx1   lda zpt,y
        cmp zp1,y
        trap_ne     ;store to zp data
        stx zpt,y   ;clear                
        lda abst,y
        cmp abs1,y
        trap_ne     ;store to abs data
        txa
        sta abst,y  ;clear                
        dey
        bpl tstx1
        next_test
        
; LDY / STY - zp,x / abs,x
        ldx #3
tldy    
        set_stat 0
        ldy zp1,x
        php         ;test stores do not alter flags
        tya
        eor #$c3
        plp
        sta abst,x
        php         ;flags after load/store sequence
        eor #$c3
        cmp abs1,x  ;test result
        trap_ne
        pla         ;load status
        eor_flag 0
        cmp fLDx,x  ;test flags
        trap_ne
        dex
        bpl tldy                  

        ldx #3
tldy1   
        set_stat $ff
        ldy zp1,x
        php         ;test stores do not alter flags
        tya
        eor #$c3
        plp
        sta abst,x
        php         ;flags after load/store sequence
        eor #$c3
        cmp abs1,x  ;test result
        trap_ne
        pla         ;load status
        eor_flag lo~fnz ;mask bits not altered
        cmp fLDx,x  ;test flags
        trap_ne
        dex
        bpl tldy1                  

        ldx #3
tldy2   
        set_stat 0
        ldy abs1,x
        php         ;test stores do not alter flags
        tya
        eor #$c3
        tay
        plp
        sty zpt,x
        php         ;flags after load/store sequence
        eor #$c3
        cmp zp1,x   ;test result
        trap_ne
        pla         ;load status
        eor_flag 0
        cmp fLDx,x  ;test flags
        trap_ne
        dex
        bpl tldy2                  

        ldx #3
tldy3
        set_stat $ff
        ldy abs1,x
        php         ;test stores do not alter flags
        tya
        eor #$c3
        tay
        plp
        sty zpt,x
        php         ;flags after load/store sequence
        eor #$c3
        cmp zp1,x   ;test result
        trap_ne
        pla         ;load status
        eor_flag lo~fnz ;mask bits not altered
        cmp fLDx,x  ;test flags
        trap_ne
        dex
        bpl tldy3

        ldx #3      ;testing store result
        ldy #0
tsty    lda zpt,x
        eor #$c3
        cmp zp1,x
        trap_ne     ;store to zp,x data
        sty zpt,x   ;clear                
        lda abst,x
        eor #$c3
        cmp abs1,x
        trap_ne     ;store to abs,x data
        txa
        sta abst,x  ;clear                
        dex
        bpl tsty
        next_test

; indexed wraparound test (only zp should wrap)
        ldx #3+$fa
tldy4   ldy zp1-$fa&$ff,x   ;wrap on indexed zp
        tya
        sta abst-$fa,x      ;no STX abs,x!
        dex
        cpx #$fa
        bcs tldy4                  
        ldx #3+$fa
tldy5   ldy abs1-$fa,x      ;no wrap on indexed abs
        sty zpt-$fa&$ff,x
        dex
        cpx #$fa
        bcs tldy5                  
        ldx #3      ;testing wraparound result
        ldy #0
tsty1   lda zpt,x
        cmp zp1,x
        trap_ne     ;store to zp,x data
        sty zpt,x   ;clear                
        lda abst,x
        cmp abs1,x
        trap_ne     ;store to abs,x data
        txa
        sta abst,x  ;clear                
        dex
        bpl tsty1
        next_test

; LDX / STX - zp / abs / #
        set_stat 0  
        ldx zp1
        php         ;test stores do not alter flags
        txa
        eor #$c3
        tax
        plp
        stx abst
        php         ;flags after load/store sequence
        eor #$c3
        tax
        cpx #$c3    ;test result
        trap_ne
        pla         ;load status
        eor_flag 0
        cmp fLDx    ;test flags
        trap_ne
        set_stat 0
        ldx zp1+1
        php         ;test stores do not alter flags
        txa
        eor #$c3
        tax
        plp
        stx abst+1
        php         ;flags after load/store sequence
        eor #$c3
        tax
        cpx #$82    ;test result
        trap_ne
        pla         ;load status
        eor_flag 0
        cmp fLDx+1  ;test flags
        trap_ne
        set_stat 0
        ldx zp1+2
        php         ;test stores do not alter flags
        txa
        eor #$c3
        tax
        plp
        stx abst+2
        php         ;flags after load/store sequence
        eor #$c3
        tax
        cpx #$41    ;test result
        trap_ne
        pla         ;load status
        eor_flag 0
        cmp fLDx+2  ;test flags
        trap_ne
        set_stat 0
        ldx zp1+3
        php         ;test stores do not alter flags
        txa
        eor #$c3
        tax
        plp
        stx abst+3
        php         ;flags after load/store sequence
        eor #$c3
        tax
        cpx #0      ;test result
        trap_ne
        pla         ;load status
        eor_flag 0
        cmp fLDx+3  ;test flags
        trap_ne

        set_stat $ff
        ldx zp1  
        php         ;test stores do not alter flags
        txa
        eor #$c3
        tax
        plp
        stx abst  
        php         ;flags after load/store sequence
        eor #$c3
        tax
        cpx #$c3    ;test result
        trap_ne     ;
        pla         ;load status
        eor_flag lo~fnz ;mask bits not altered
        cmp fLDx    ;test flags
        trap_ne
        set_stat $ff
        ldx zp1+1
        php         ;test stores do not alter flags
        txa
        eor #$c3
        tax
        plp
        stx abst+1
        php         ;flags after load/store sequence
        eor #$c3
        tax
        cpx #$82    ;test result
        trap_ne
        pla         ;load status
        eor_flag lo~fnz ;mask bits not altered
        cmp fLDx+1  ;test flags
        trap_ne
        set_stat $ff
        ldx zp1+2
        php         ;test stores do not alter flags
        txa
        eor #$c3
        tax
        plp
        stx abst+2
        php         ;flags after load/store sequence
        eor #$c3
        tax
        cpx #$41    ;test result
        trap_ne     ;
        pla         ;load status
        eor_flag lo~fnz ;mask bits not altered
        cmp fLDx+2  ;test flags
        trap_ne
        set_stat $ff
        ldx zp1+3
        php         ;test stores do not alter flags
        txa
        eor #$c3
        tax
        plp
        stx abst+3
        php         ;flags after load/store sequence
        eor #$c3
        tax
        cpx #0      ;test result
        trap_ne
        pla         ;load status
        eor_flag lo~fnz ;mask bits not altered
        cmp fLDx+3  ;test flags
        trap_ne

        set_stat 0
        ldx abs1  
        php         ;test stores do not alter flags
        txa
        eor #$c3
        tax
        plp
        stx zpt  
        php         ;flags after load/store sequence
        eor #$c3
        cmp zp1     ;test result
        trap_ne
        pla         ;load status
        eor_flag 0
        cmp fLDx    ;test flags
        trap_ne
        set_stat 0
        ldx abs1+1
        php         ;test stores do not alter flags
        txa
        eor #$c3
        tax
        plp
        stx zpt+1
        php         ;flags after load/store sequence
        eor #$c3
        cmp zp1+1   ;test result
        trap_ne
        pla         ;load status
        eor_flag 0
        cmp fLDx+1  ;test flags
        trap_ne
        set_stat 0
        ldx abs1+2
        php         ;test stores do not alter flags
        txa
        eor #$c3
        tax
        plp
        stx zpt+2
        php         ;flags after load/store sequence
        eor #$c3
        cmp zp1+2   ;test result
        trap_ne
        pla         ;load status
        eor_flag 0
        cmp fLDx+2  ;test flags
        trap_ne
        set_stat 0
        ldx abs1+3
        php         ;test stores do not alter flags
        txa
        eor #$c3
        tax
        plp
        stx zpt+3
        php         ;flags after load/store sequence
        eor #$c3
        cmp zp1+3   ;test result
        trap_ne
        pla         ;load status
        eor_flag 0
        cmp fLDx+3  ;test flags
        trap_ne

        set_stat $ff
        ldx abs1  
        php         ;test stores do not alter flags
        txa
        eor #$c3
        tax
        plp
        stx zpt  
        php         ;flags after load/store sequence
        eor #$c3
        tax
        cpx zp1     ;test result
        trap_ne
        pla         ;load status
        eor_flag lo~fnz ;mask bits not altered
        cmp fLDx    ;test flags
        trap_ne
        set_stat $ff
        ldx abs1+1
        php         ;test stores do not alter flags
        txa
        eor #$c3
        tax
        plp
        stx zpt+1
        php         ;flags after load/store sequence
        eor #$c3
        tax
        cpx zp1+1   ;test result
        trap_ne
        pla         ;load status
        eor_flag lo~fnz ;mask bits not altered
        cmp fLDx+1  ;test flags
        trap_ne
        set_stat $ff
        ldx abs1+2
        php         ;test stores do not alter flags
        txa
        eor #$c3
        tax
        plp
        stx zpt+2
        php         ;flags after load/store sequence
        eor #$c3
        tax
        cpx zp1+2   ;test result
        trap_ne
        pla         ;load status
        eor_flag lo~fnz ;mask bits not altered
        cmp fLDx+2  ;test flags
        trap_ne
        set_stat $ff
        ldx abs1+3
        php         ;test stores do not alter flags
        txa
        eor #$c3
        tax
        plp
        stx zpt+3
        php         ;flags after load/store sequence
        eor #$c3
        tax
        cpx zp1+3   ;test result
        trap_ne
        pla         ;load status
        eor_flag lo~fnz ;mask bits not altered
        cmp fLDx+3  ;test flags
        trap_ne

        set_stat 0  
        ldx #$c3
        php
        cpx abs1    ;test result
        trap_ne
        pla         ;load status
        eor_flag 0
        cmp fLDx    ;test flags
        trap_ne
        set_stat 0
        ldx #$82
        php
        cpx abs1+1  ;test result
        trap_ne
        pla         ;load status
        eor_flag 0
        cmp fLDx+1  ;test flags
        trap_ne
        set_stat 0
        ldx #$41
        php
        cpx abs1+2  ;test result
        trap_ne
        pla         ;load status
        eor_flag 0
        cmp fLDx+2  ;test flags
        trap_ne
        set_stat 0
        ldx #0
        php
        cpx abs1+3  ;test result
        trap_ne
        pla         ;load status
        eor_flag 0
        cmp fLDx+3  ;test flags
        trap_ne

        set_stat $ff
        ldx #$c3  
        php
        cpx abs1    ;test result
        trap_ne
        pla         ;load status
        eor_flag lo~fnz ;mask bits not altered
        cmp fLDx    ;test flags
        trap_ne
        set_stat $ff
        ldx #$82
        php
        cpx abs1+1  ;test result
        trap_ne
        pla         ;load status
        eor_flag lo~fnz ;mask bits not altered
        cmp fLDx+1  ;test flags
        trap_ne
        set_stat $ff
        ldx #$41
        php
        cpx abs1+2  ;test result
        trap_ne
        pla         ;load status
        eor_flag lo~fnz ;mask bits not altered
        cmp fLDx+2  ;test flags
        trap_ne
        set_stat $ff
        ldx #0
        php
        cpx abs1+3  ;test result
        trap_ne
        pla         ;load status
        eor_flag lo~fnz ;mask bits not altered
        cmp fLDx+3  ;test flags
        trap_ne

        ldx #0
        lda zpt  
        eor #$c3
        cmp zp1  
        trap_ne     ;store to zp data
        stx zpt     ;clear                
        lda abst  
        eor #$c3
        cmp abs1  
        trap_ne     ;store to abs data
        stx abst    ;clear                
        lda zpt+1
        eor #$c3
        cmp zp1+1
        trap_ne     ;store to zp data
        stx zpt+1   ;clear                
        lda abst+1
        eor #$c3
        cmp abs1+1
        trap_ne     ;store to abs data
        stx abst+1  ;clear                
        lda zpt+2
        eor #$c3
        cmp zp1+2
        trap_ne     ;store to zp data
        stx zpt+2   ;clear                
        lda abst+2
        eor #$c3
        cmp abs1+2
        trap_ne     ;store to abs data
        stx abst+2  ;clear                
        lda zpt+3
        eor #$c3
        cmp zp1+3
        trap_ne     ;store to zp data
        stx zpt+3   ;clear                
        lda abst+3
        eor #$c3
        cmp abs1+3
        trap_ne     ;store to abs data
        stx abst+3  ;clear                
        next_test

; LDY / STY - zp / abs / #
        set_stat 0
        ldy zp1  
        php         ;test stores do not alter flags
        tya
        eor #$c3
        tay
        plp
        sty abst  
        php         ;flags after load/store sequence
        eor #$c3
        tay
        cpy #$c3    ;test result
        trap_ne
        pla         ;load status
        eor_flag 0
        cmp fLDx    ;test flags
        trap_ne
        set_stat 0
        ldy zp1+1
        php         ;test stores do not alter flags
        tya
        eor #$c3
        tay
        plp
        sty abst+1
        php         ;flags after load/store sequence
        eor #$c3
        tay
        cpy #$82    ;test result
        trap_ne
        pla         ;load status
        eor_flag 0
        cmp fLDx+1  ;test flags
        trap_ne
        set_stat 0
        ldy zp1+2
        php         ;test stores do not alter flags
        tya
        eor #$c3
        tay
        plp
        sty abst+2
        php         ;flags after load/store sequence
        eor #$c3
        tay
        cpy #$41    ;test result
        trap_ne
        pla         ;load status
        eor_flag 0
        cmp fLDx+2  ;test flags
        trap_ne
        set_stat 0
        ldy zp1+3
        php         ;test stores do not alter flags
        tya
        eor #$c3
        tay
        plp
        sty abst+3
        php         ;flags after load/store sequence
        eor #$c3
        tay
        cpy #0      ;test result
        trap_ne
        pla         ;load status
        eor_flag 0
        cmp fLDx+3  ;test flags
        trap_ne

        set_stat $ff
        ldy zp1  
        php         ;test stores do not alter flags
        tya
        eor #$c3
        tay
        plp
        sty abst  
        php         ;flags after load/store sequence
        eor #$c3
        tay
        cpy #$c3    ;test result
        trap_ne
        pla         ;load status
        eor_flag lo~fnz ;mask bits not altered
        cmp fLDx    ;test flags
        trap_ne
        set_stat $ff
        ldy zp1+1
        php         ;test stores do not alter flags
        tya
        eor #$c3
        tay
        plp
        sty abst+1
        php         ;flags after load/store sequence
        eor #$c3
        tay
        cpy #$82   ;test result
        trap_ne
        pla         ;load status
        eor_flag lo~fnz ;mask bits not altered
        cmp fLDx+1  ;test flags
        trap_ne
        set_stat $ff
        ldy zp1+2
        php         ;test stores do not alter flags
        tya
        eor #$c3
        tay
        plp
        sty abst+2
        php         ;flags after load/store sequence
        eor #$c3
        tay
        cpy #$41    ;test result
        trap_ne
        pla         ;load status
        eor_flag lo~fnz ;mask bits not altered
        cmp fLDx+2  ;test flags
        trap_ne
        set_stat $ff
        ldy zp1+3
        php         ;test stores do not alter flags
        tya
        eor #$c3
        tay
        plp
        sty abst+3
        php         ;flags after load/store sequence
        eor #$c3
        tay
        cpy #0      ;test result
        trap_ne
        pla         ;load status
        eor_flag lo~fnz ;mask bits not altered
        cmp fLDx+3  ;test flags
        trap_ne
        
        set_stat 0
        ldy abs1  
        php         ;test stores do not alter flags
        tya
        eor #$c3
        tay
        plp
        sty zpt  
        php         ;flags after load/store sequence
        eor #$c3
        tay
        cpy zp1     ;test result
        trap_ne
        pla         ;load status
        eor_flag 0
        cmp fLDx    ;test flags
        trap_ne
        set_stat 0
        ldy abs1+1
        php         ;test stores do not alter flags
        tya
        eor #$c3
        tay
        plp
        sty zpt+1
        php         ;flags after load/store sequence
        eor #$c3
        tay
        cpy zp1+1   ;test result
        trap_ne
        pla         ;load status
        eor_flag 0
        cmp fLDx+1  ;test flags
        trap_ne
        set_stat 0
        ldy abs1+2
        php         ;test stores do not alter flags
        tya
        eor #$c3
        tay
        plp
        sty zpt+2
        php         ;flags after load/store sequence
        eor #$c3
        tay
        cpy zp1+2   ;test result
        trap_ne
        pla         ;load status
        eor_flag 0
        cmp fLDx+2  ;test flags
        trap_ne
        set_stat 0
        ldy abs1+3
        php         ;test stores do not alter flags
        tya
        eor #$c3
        tay
        plp
        sty zpt+3
        php         ;flags after load/store sequence
        eor #$c3
        tay
        cpy zp1+3   ;test result
        trap_ne
        pla         ;load status
        eor_flag 0
        cmp fLDx+3  ;test flags
        trap_ne

        set_stat $ff
        ldy abs1  
        php         ;test stores do not alter flags
        tya
        eor #$c3
        tay
        plp
        sty zpt  
        php         ;flags after load/store sequence
        eor #$c3
        tay
        cmp zp1     ;test result
        trap_ne
        pla         ;load status
        eor_flag lo~fnz ;mask bits not altered
        cmp fLDx    ;test flags
        trap_ne
        set_stat $ff
        ldy abs1+1
        php         ;test stores do not alter flags
        tya
        eor #$c3
        tay
        plp
        sty zpt+1
        php         ;flags after load/store sequence
        eor #$c3
        tay
        cmp zp1+1   ;test result
        trap_ne
        pla         ;load status
        eor_flag lo~fnz ;mask bits not altered
        cmp fLDx+1  ;test flags
        trap_ne
        set_stat $ff
        ldy abs1+2
        php         ;test stores do not alter flags
        tya
        eor #$c3
        tay
        plp
        sty zpt+2
        php         ;flags after load/store sequence
        eor #$c3
        tay
        cmp zp1+2   ;test result
        trap_ne
        pla         ;load status
        eor_flag lo~fnz ;mask bits not altered
        cmp fLDx+2  ;test flags
        trap_ne
        set_stat $ff
        ldy abs1+3
        php         ;test stores do not alter flags
        tya
        eor #$c3
        tay
        plp
        sty zpt+3
        php         ;flags after load/store sequence
        eor #$c3
        tay
        cmp zp1+3   ;test result
        trap_ne
        pla         ;load status
        eor_flag lo~fnz ;mask bits not altered
        cmp fLDx+3  ;test flags
        trap_ne


        set_stat 0
        ldy #$c3  
        php
        cpy abs1    ;test result
        trap_ne
        pla         ;load status
        eor_flag 0
        cmp fLDx    ;test flags
        trap_ne
        set_stat 0
        ldy #$82
        php
        cpy abs1+1  ;test result
        trap_ne
        pla         ;load status
        eor_flag 0
        cmp fLDx+1  ;test flags
        trap_ne
        set_stat 0
        ldy #$41
        php
        cpy abs1+2  ;test result
        trap_ne
        pla         ;load status
        eor_flag 0
        cmp fLDx+2  ;test flags
        trap_ne
        set_stat 0
        ldy #0
        php
        cpy abs1+3  ;test result
        trap_ne
        pla         ;load status
        eor_flag 0
        cmp fLDx+3  ;test flags
        trap_ne

        set_stat $ff
        ldy #$c3  
        php
        cpy abs1    ;test result
        trap_ne
        pla         ;load status
        eor_flag lo~fnz ;mask bits not altered
        cmp fLDx    ;test flags
        trap_ne
        set_stat $ff
        ldy #$82
        php
        cpy abs1+1  ;test result
        trap_ne
        pla         ;load status
        eor_flag lo~fnz ;mask bits not altered
        cmp fLDx+1  ;test flags
        trap_ne
        set_stat $ff
        ldy #$41
        php
        cpy abs1+2   ;test result
        trap_ne
        pla         ;load status
        eor_flag lo~fnz ;mask bits not altered
        cmp fLDx+2  ;test flags
        trap_ne
        set_stat $ff
        ldy #0
        php
        cpy abs1+3  ;test result
        trap_ne
        pla         ;load status
        eor_flag lo~fnz ;mask bits not altered
        cmp fLDx+3  ;test flags
        trap_ne
        
        ldy #0
        lda zpt  
        eor #$c3
        cmp zp1  
        trap_ne     ;store to zp   data
        sty zpt     ;clear                
        lda abst  
        eor #$c3
        cmp abs1  
        trap_ne     ;store to abs   data
        sty abst    ;clear                
        lda zpt+1
        eor #$c3
        cmp zp1+1
        trap_ne     ;store to zp+1 data
        sty zpt+1   ;clear                
        lda abst+1
        eor #$c3
        cmp abs1+1
        trap_ne     ;store to abs+1 data
        sty abst+1  ;clear                
        lda zpt+2
        eor #$c3
        cmp zp1+2
        trap_ne     ;store to zp+2 data
        sty zpt+2   ;clear                
        lda abst+2
        eor #$c3
        cmp abs1+2
        trap_ne     ;store to abs+2 data
        sty abst+2  ;clear                
        lda zpt+3
        eor #$c3
        cmp zp1+3
        trap_ne     ;store to zp+3 data
        sty zpt+3   ;clear                
        lda abst+3
        eor #$c3
        cmp abs1+3
        trap_ne     ;store to abs+3 data
        sty abst+3  ;clear                
        next_test

; testing load / store accumulator LDA / STA all addressing modes
; LDA / STA - zp,x / abs,x
        ldx #3
tldax    
        set_stat 0
        lda zp1,x
        php         ;test stores do not alter flags
        eor #$c3
        plp
        sta abst,x
        php         ;flags after load/store sequence
        eor #$c3
        cmp abs1,x  ;test result
        trap_ne
        pla         ;load status
        eor_flag 0
        cmp fLDx,x  ;test flags
        trap_ne
        dex
        bpl tldax                  

        ldx #3
tldax1   
        set_stat $ff
        lda zp1,x
        php         ;test stores do not alter flags
        eor #$c3
        plp
        sta abst,x
        php         ;flags after load/store sequence
        eor #$c3
        cmp abs1,x   ;test result
        trap_ne
        pla         ;load status
        eor_flag lo~fnz ;mask bits not altered
        cmp fLDx,x  ;test flags
        trap_ne
        dex
        bpl tldax1                  

        ldx #3
tldax2   
        set_stat 0
        lda abs1,x
        php         ;test stores do not alter flags
        eor #$c3
        plp
        sta zpt,x
        php         ;flags after load/store sequence
        eor #$c3
        cmp zp1,x   ;test result
        trap_ne
        pla         ;load status
        eor_flag 0
        cmp fLDx,x  ;test flags
        trap_ne
        dex
        bpl tldax2                  

        ldx #3
tldax3
        set_stat $ff
        lda abs1,x
        php         ;test stores do not alter flags
        eor #$c3
        plp
        sta zpt,x
        php         ;flags after load/store sequence
        eor #$c3
        cmp zp1,x   ;test result
        trap_ne
        pla         ;load status
        eor_flag lo~fnz ;mask bits not altered
        cmp fLDx,x  ;test flags
        trap_ne
        dex
        bpl tldax3

        ldx #3      ;testing store result
        ldy #0
tstax   lda zpt,x
        eor #$c3
        cmp zp1,x
        trap_ne     ;store to zp,x data
        sty zpt,x   ;clear                
        lda abst,x
        eor #$c3
        cmp abs1,x
        trap_ne     ;store to abs,x data
        txa
        sta abst,x  ;clear                
        dex
        bpl tstax
        next_test

; LDA / STA - (zp),y / abs,y / (zp,x)
        ldy #3
tlday    
        set_stat 0
        lda (ind1),y
        php         ;test stores do not alter flags
        eor #$c3
        plp
        sta abst,y
        php         ;flags after load/store sequence
        eor #$c3
        cmp abs1,y  ;test result
        trap_ne
        pla         ;load status
        eor_flag 0
        cmp fLDx,y  ;test flags
        trap_ne
        dey
        bpl tlday                  

        ldy #3
tlday1   
        set_stat $ff
        lda (ind1),y
        php         ;test stores do not alter flags
        eor #$c3
        plp
        sta abst,y
        php         ;flags after load/store sequence
        eor #$c3
        cmp abs1,y  ;test result
        trap_ne
        pla         ;load status
        eor_flag lo~fnz ;mask bits not altered
        cmp fLDx,y  ;test flags
        trap_ne
        dey
        bpl tlday1                  

        ldy #3      ;testing store result
        ldx #0
tstay   lda abst,y
        eor #$c3
        cmp abs1,y
        trap_ne     ;store to abs data
        txa
        sta abst,y  ;clear                
        dey
        bpl tstay

        ldy #3
tlday2   
        set_stat 0
        lda abs1,y
        php         ;test stores do not alter flags
        eor #$c3
        plp
        sta (indt),y
        php         ;flags after load/store sequence
        eor #$c3
        cmp (ind1),y    ;test result
        trap_ne
        pla         ;load status
        eor_flag 0
        cmp fLDx,y  ;test flags
        trap_ne
        dey
        bpl tlday2                  

        ldy #3
tlday3   
        set_stat $ff
        lda abs1,y
        php         ;test stores do not alter flags
        eor #$c3
        plp
        sta (indt),y
        php         ;flags after load/store sequence
        eor #$c3
        cmp (ind1),y   ;test result
        trap_ne
        pla         ;load status
        eor_flag lo~fnz ;mask bits not altered
        cmp fLDx,y  ;test flags
        trap_ne
        dey
        bpl tlday3
        
        ldy #3      ;testing store result
        ldx #0
tstay1  lda abst,y
        eor #$c3
        cmp abs1,y
        trap_ne     ;store to abs data
        txa
        sta abst,y  ;clear                
        dey
        bpl tstay1
        
        ldx #6
        ldy #3
tldax4   
        set_stat 0
        lda (ind1,x)
        php         ;test stores do not alter flags
        eor #$c3
        plp
        sta (indt,x)
        php         ;flags after load/store sequence
        eor #$c3
        cmp abs1,y  ;test result
        trap_ne
        pla         ;load status
        eor_flag 0
        cmp fLDx,y  ;test flags
        trap_ne
        dex
        dex
        dey
        bpl tldax4                  

        ldx #6
        ldy #3
tldax5
        set_stat $ff
        lda (ind1,x)
        php         ;test stores do not alter flags
        eor #$c3
        plp
        sta (indt,x)
        php         ;flags after load/store sequence
        eor #$c3
        cmp abs1,y  ;test result
        trap_ne
        pla         ;load status
        eor_flag lo~fnz ;mask bits not altered
        cmp fLDx,y  ;test flags
        trap_ne
        dex
        dex
        dey
        bpl tldax5

        ldy #3      ;testing store result
        ldx #0
tstay2  lda abst,y
        eor #$c3
        cmp abs1,y
        trap_ne     ;store to abs data
        txa
        sta abst,y  ;clear                
        dey
        bpl tstay2
        next_test

; indexed wraparound test (only zp should wrap)
        ldx #3+$fa
tldax6  lda zp1-$fa&$ff,x   ;wrap on indexed zp
        sta abst-$fa,x      ;no STX abs,x!
        dex
        cpx #$fa
        bcs tldax6                  
        ldx #3+$fa
tldax7  lda abs1-$fa,x      ;no wrap on indexed abs
        sta zpt-$fa&$ff,x
        dex
        cpx #$fa
        bcs tldax7
                          
        ldx #3      ;testing wraparound result
        ldy #0
tstax1  lda zpt,x
        cmp zp1,x
        trap_ne     ;store to zp,x data
        sty zpt,x   ;clear                
        lda abst,x
        cmp abs1,x
        trap_ne     ;store to abs,x data
        txa
        sta abst,x  ;clear                
        dex
        bpl tstax1

        ldy #3+$f8
        ldx #6+$f8
tlday4  lda (ind1-$f8&$ff,x) ;wrap on indexed zp indirect
        sta abst-$f8,y
        dex
        dex
        dey
        cpy #$f8
        bcs tlday4
        ldy #3      ;testing wraparound result
        ldx #0
tstay4  lda abst,y
        cmp abs1,y
        trap_ne     ;store to abs data
        txa
        sta abst,y  ;clear                
        dey
        bpl tstay4
        
        ldy #3+$f8
tlday5  lda abs1-$f8,y  ;no wrap on indexed abs
        sta (inwt),y
        dey
        cpy #$f8
        bcs tlday5                  
        ldy #3      ;testing wraparound result
        ldx #0
tstay5  lda abst,y
        cmp abs1,y
        trap_ne     ;store to abs data
        txa
        sta abst,y  ;clear                
        dey
        bpl tstay5

        ldy #3+$f8
        ldx #6+$f8
tlday6  lda (inw1),y    ;no wrap on zp indirect indexed 
        sta (indt-$f8&$ff,x)
        dex
        dex
        dey
        cpy #$f8
        bcs tlday6
        ldy #3      ;testing wraparound result
        ldx #0
tstay6  lda abst,y
        cmp abs1,y
        trap_ne     ;store to abs data
        txa
        sta abst,y  ;clear                
        dey
        bpl tstay6
        next_test

; LDA / STA - zp / abs / #
        set_stat 0  
        lda zp1
        php         ;test stores do not alter flags
        eor #$c3
        plp
        sta abst
        php         ;flags after load/store sequence
        eor #$c3
        cmp #$c3    ;test result
        trap_ne
        pla         ;load status
        eor_flag 0
        cmp fLDx    ;test flags
        trap_ne
        set_stat 0
        lda zp1+1
        php         ;test stores do not alter flags
        eor #$c3
        plp
        sta abst+1
        php         ;flags after load/store sequence
        eor #$c3
        cmp #$82    ;test result
        trap_ne
        pla         ;load status
        eor_flag 0
        cmp fLDx+1  ;test flags
        trap_ne
        set_stat 0
        lda zp1+2
        php         ;test stores do not alter flags
        eor #$c3
        plp
        sta abst+2
        php         ;flags after load/store sequence
        eor #$c3
        cmp #$41    ;test result
        trap_ne
        pla         ;load status
        eor_flag 0
        cmp fLDx+2  ;test flags
        trap_ne
        set_stat 0
        lda zp1+3
        php         ;test stores do not alter flags
        eor #$c3
        plp
        sta abst+3
        php         ;flags after load/store sequence
        eor #$c3
        cmp #0      ;test result
        trap_ne
        pla         ;load status
        eor_flag 0
        cmp fLDx+3  ;test flags
        trap_ne
        set_stat $ff
        lda zp1  
        php         ;test stores do not alter flags
        eor #$c3
        plp
        sta abst  
        php         ;flags after load/store sequence
        eor #$c3
        cmp #$c3    ;test result
        trap_ne
        pla         ;load status
        eor_flag lo~fnz ;mask bits not altered
        cmp fLDx    ;test flags
        trap_ne
        set_stat $ff
        lda zp1+1
        php         ;test stores do not alter flags
        eor #$c3
        plp
        sta abst+1
        php         ;flags after load/store sequence
        eor #$c3
        cmp #$82    ;test result
        trap_ne
        pla         ;load status
        eor_flag lo~fnz ;mask bits not altered
        cmp fLDx+1  ;test flags
        trap_ne
        set_stat $ff
        lda zp1+2
        php         ;test stores do not alter flags
        eor #$c3
        plp
        sta abst+2
        php         ;flags after load/store sequence
        eor #$c3
        cmp #$41    ;test result
        trap_ne
        pla         ;load status
        eor_flag lo~fnz ;mask bits not altered
        cmp fLDx+2  ;test flags
        trap_ne
        set_stat $ff
        lda zp1+3
        php         ;test stores do not alter flags
        eor #$c3
        plp
        sta abst+3
        php         ;flags after load/store sequence
        eor #$c3
        cmp #0      ;test result
        trap_ne
        pla         ;load status
        eor_flag lo~fnz ;mask bits not altered
        cmp fLDx+3  ;test flags
        trap_ne
        set_stat 0
        lda abs1  
        php         ;test stores do not alter flags
        eor #$c3
        plp
        sta zpt  
        php         ;flags after load/store sequence
        eor #$c3
        cmp zp1     ;test result
        trap_ne
        pla         ;load status
        eor_flag 0
        cmp fLDx    ;test flags
        trap_ne
        set_stat 0
        lda abs1+1
        php         ;test stores do not alter flags
        eor #$c3
        plp
        sta zpt+1
        php         ;flags after load/store sequence
        eor #$c3
        cmp zp1+1   ;test result
        trap_ne
        pla         ;load status
        eor_flag 0
        cmp fLDx+1  ;test flags
        trap_ne
        set_stat 0
        lda abs1+2
        php         ;test stores do not alter flags
        eor #$c3
        plp
        sta zpt+2
        php         ;flags after load/store sequence
        eor #$c3
        cmp zp1+2   ;test result
        trap_ne
        pla         ;load status
        eor_flag 0
        cmp fLDx+2  ;test flags
        trap_ne
        set_stat 0
        lda abs1+3
        php         ;test stores do not alter flags
        eor #$c3
        plp
        sta zpt+3
        php         ;flags after load/store sequence
        eor #$c3
        cmp zp1+3   ;test result
        trap_ne
        pla         ;load status
        eor_flag 0
        cmp fLDx+3  ;test flags
        trap_ne
        set_stat $ff
        lda abs1  
        php         ;test stores do not alter flags
        eor #$c3
        plp
        sta zpt  
        php         ;flags after load/store sequence
        eor #$c3
        cmp zp1     ;test result
        trap_ne
        pla         ;load status
        eor_flag lo~fnz ;mask bits not altered
        cmp fLDx    ;test flags
        trap_ne
        set_stat $ff
        lda abs1+1
        php         ;test stores do not alter flags
        eor #$c3
        plp
        sta zpt+1
        php         ;flags after load/store sequence
        eor #$c3
        cmp zp1+1   ;test result
        trap_ne
        pla         ;load status
        eor_flag lo~fnz ;mask bits not altered
        cmp fLDx+1  ;test flags
        trap_ne
        set_stat $ff
        lda abs1+2
        php         ;test stores do not alter flags
        eor #$c3
        plp
        sta zpt+2
        php         ;flags after load/store sequence
        eor #$c3
        cmp zp1+2   ;test result
        trap_ne
        pla         ;load status
        eor_flag lo~fnz ;mask bits not altered
        cmp fLDx+2  ;test flags
        trap_ne
        set_stat $ff
        lda abs1+3
        php         ;test stores do not alter flags
        eor #$c3
        plp
        sta zpt+3
        php         ;flags after load/store sequence
        eor #$c3
        cmp zp1+3   ;test result
        trap_ne
        pla         ;load status
        eor_flag lo~fnz ;mask bits not altered
        cmp fLDx+3  ;test flags
        trap_ne
        set_stat 0  
        lda #$c3
        php
        cmp abs1    ;test result
        trap_ne
        pla         ;load status
        eor_flag 0
        cmp fLDx    ;test flags
        trap_ne
        set_stat 0
        lda #$82
        php
        cmp abs1+1  ;test result
        trap_ne
        pla         ;load status
        eor_flag 0
        cmp fLDx+1  ;test flags
        trap_ne
        set_stat 0
        lda #$41
        php
        cmp abs1+2  ;test result
        trap_ne
        pla         ;load status
        eor_flag 0
        cmp fLDx+2  ;test flags
        trap_ne
        set_stat 0
        lda #0
        php
        cmp abs1+3  ;test result
        trap_ne
        pla         ;load status
        eor_flag 0
        cmp fLDx+3  ;test flags
        trap_ne

        set_stat $ff
        lda #$c3  
        php
        cmp abs1    ;test result
        trap_ne
        pla         ;load status
        eor_flag lo~fnz ;mask bits not altered
        cmp fLDx    ;test flags
        trap_ne
        set_stat $ff
        lda #$82
        php
        cmp abs1+1  ;test result
        trap_ne
        pla         ;load status
        eor_flag lo~fnz ;mask bits not altered
        cmp fLDx+1  ;test flags
        trap_ne
        set_stat $ff
        lda #$41
        php
        cmp abs1+2  ;test result
        trap_ne
        pla         ;load status
        eor_flag lo~fnz ;mask bits not altered
        cmp fLDx+2  ;test flags
        trap_ne
        set_stat $ff
        lda #0
        php
        cmp abs1+3  ;test result
        trap_ne
        pla         ;load status
        eor_flag lo~fnz ;mask bits not altered
        cmp fLDx+3  ;test flags
        trap_ne

        ldx #0
        lda zpt  
        eor #$c3
        cmp zp1  
        trap_ne     ;store to zp data
        stx zpt     ;clear                
        lda abst  
        eor #$c3
        cmp abs1  
        trap_ne     ;store to abs data
        stx abst    ;clear                
        lda zpt+1
        eor #$c3
        cmp zp1+1
        trap_ne     ;store to zp data
        stx zpt+1   ;clear                
        lda abst+1
        eor #$c3
        cmp abs1+1
        trap_ne     ;store to abs data
        stx abst+1  ;clear                
        lda zpt+2
        eor #$c3
        cmp zp1+2
        trap_ne     ;store to zp data
        stx zpt+2   ;clear                
        lda abst+2
        eor #$c3
        cmp abs1+2
        trap_ne     ;store to abs data
        stx abst+2  ;clear                
        lda zpt+3
        eor #$c3
        cmp zp1+3
        trap_ne     ;store to zp data
        stx zpt+3   ;clear                
        lda abst+3
        eor #$c3
        cmp abs1+3
        trap_ne     ;store to abs data
        stx abst+3  ;clear                
        next_test

; testing bit test & compares BIT CPX CPY CMP all addressing modes
; BIT - zp / abs
        set_a $ff,0
        bit zp1+3   ;00 - should set Z / clear  NV
        tst_a $ff,fz 
        set_a 1,0
        bit zp1+2   ;41 - should set V (M6) / clear NZ
        tst_a 1,fv
        set_a 1,0
        bit zp1+1   ;82 - should set N (M7) & Z / clear V
        tst_a 1,fnz
        set_a 1,0
        bit zp1     ;c3 - should set N (M7) & V (M6) / clear Z
        tst_a 1,fnv
        
        set_a $ff,$ff
        bit zp1+3   ;00 - should set Z / clear  NV
        tst_a $ff,~fnv 
        set_a 1,$ff
        bit zp1+2   ;41 - should set V (M6) / clear NZ
        tst_a 1,~fnz
        set_a 1,$ff
        bit zp1+1   ;82 - should set N (M7) & Z / clear V
        tst_a 1,~fv
        set_a 1,$ff
        bit zp1     ;c3 - should set N (M7) & V (M6) / clear Z
        tst_a 1,~fz
        
        set_a $ff,0
        bit abs1+3  ;00 - should set Z / clear  NV
        tst_a $ff,fz 
        set_a 1,0
        bit abs1+2  ;41 - should set V (M6) / clear NZ
        tst_a 1,fv
        set_a 1,0
        bit abs1+1  ;82 - should set N (M7) & Z / clear V
        tst_a 1,fnz
        set_a 1,0
        bit abs1    ;c3 - should set N (M7) & V (M6) / clear Z
        tst_a 1,fnv
        
        set_a $ff,$ff
        bit abs1+3  ;00 - should set Z / clear  NV
        tst_a $ff,~fnv 
        set_a 1,$ff
        bit abs1+2  ;41 - should set V (M6) / clear NZ
        tst_a 1,~fnz
        set_a 1,$ff
        bit abs1+1  ;82 - should set N (M7) & Z / clear V
        tst_a 1,~fv
        set_a 1,$ff
        bit abs1    ;c3 - should set N (M7) & V (M6) / clear Z
        tst_a 1,~fz
        next_test
        
; CPX - zp / abs / #         
        set_x $80,0
        cpx zp7f
        tst_stat fc
        dex
        cpx zp7f
        tst_stat fzc
        dex
        cpx zp7f
        tst_x $7e,fn
        set_x $80,$ff
        cpx zp7f
        tst_stat ~fnz
        dex
        cpx zp7f
        tst_stat ~fn
        dex
        cpx zp7f
        tst_x $7e,~fzc

        set_x $80,0
        cpx abs7f
        tst_stat fc
        dex
        cpx abs7f
        tst_stat fzc
        dex
        cpx abs7f
        tst_x $7e,fn
        set_x $80,$ff
        cpx abs7f
        tst_stat ~fnz
        dex
        cpx abs7f
        tst_stat ~fn
        dex
        cpx abs7f
        tst_x $7e,~fzc

        set_x $80,0
        cpx #$7f
        tst_stat fc
        dex
        cpx #$7f
        tst_stat fzc
        dex
        cpx #$7f
        tst_x $7e,fn
        set_x $80,$ff
        cpx #$7f
        tst_stat ~fnz
        dex
        cpx #$7f
        tst_stat ~fn
        dex
        cpx #$7f
        tst_x $7e,~fzc
        next_test

; CPY - zp / abs / #         
        set_y $80,0
        cpy zp7f
        tst_stat fc
        dey
        cpy zp7f
        tst_stat fzc
        dey
        cpy zp7f
        tst_y $7e,fn
        set_y $80,$ff
        cpy zp7f
        tst_stat ~fnz
        dey
        cpy zp7f
        tst_stat ~fn
        dey
        cpy zp7f
        tst_y $7e,~fzc

        set_y $80,0
        cpy abs7f
        tst_stat fc
        dey
        cpy abs7f
        tst_stat fzc
        dey
        cpy abs7f
        tst_y $7e,fn
        set_y $80,$ff
        cpy abs7f
        tst_stat ~fnz
        dey
        cpy abs7f
        tst_stat ~fn
        dey
        cpy abs7f
        tst_y $7e,~fzc

        set_y $80,0
        cpy #$7f
        tst_stat fc
        dey
        cpy #$7f
        tst_stat fzc
        dey
        cpy #$7f
        tst_y $7e,fn
        set_y $80,$ff
        cpy #$7f
        tst_stat ~fnz
        dey
        cpy #$7f
        tst_stat ~fn
        dey
        cpy #$7f
        tst_y $7e,~fzc
        next_test

; CMP - zp / abs / #         
        set_a $80,0
        cmp zp7f
        tst_a $80,fc
        set_a $7f,0
        cmp zp7f
        tst_a $7f,fzc
        set_a $7e,0
        cmp zp7f
        tst_a $7e,fn
        set_a $80,$ff
        cmp zp7f
        tst_a $80,~fnz
        set_a $7f,$ff
        cmp zp7f
        tst_a $7f,~fn
        set_a $7e,$ff
        cmp zp7f
        tst_a $7e,~fzc

        set_a $80,0
        cmp abs7f
        tst_a $80,fc
        set_a $7f,0
        cmp abs7f
        tst_a $7f,fzc
        set_a $7e,0
        cmp abs7f
        tst_a $7e,fn
        set_a $80,$ff
        cmp abs7f
        tst_a $80,~fnz
        set_a $7f,$ff
        cmp abs7f
        tst_a $7f,~fn
        set_a $7e,$ff
        cmp abs7f
        tst_a $7e,~fzc

        set_a $80,0
        cmp #$7f
        tst_a $80,fc
        set_a $7f,0
        cmp #$7f
        tst_a $7f,fzc
        set_a $7e,0
        cmp #$7f
        tst_a $7e,fn
        set_a $80,$ff
        cmp #$7f
        tst_a $80,~fnz
        set_a $7f,$ff
        cmp #$7f
        tst_a $7f,~fn
        set_a $7e,$ff
        cmp #$7f
        tst_a $7e,~fzc

        ldx #4          ;with indexing by X
        set_a $80,0
        cmp zp1,x
        tst_a $80,fc
        set_a $7f,0
        cmp zp1,x
        tst_a $7f,fzc
        set_a $7e,0
        cmp zp1,x
        tst_a $7e,fn
        set_a $80,$ff
        cmp zp1,x
        tst_a $80,~fnz
        set_a $7f,$ff
        cmp zp1,x
        tst_a $7f,~fn
        set_a $7e,$ff
        cmp zp1,x
        tst_a $7e,~fzc

        set_a $80,0
        cmp abs1,x
        tst_a $80,fc
        set_a $7f,0
        cmp abs1,x
        tst_a $7f,fzc
        set_a $7e,0
        cmp abs1,x
        tst_a $7e,fn
        set_a $80,$ff
        cmp abs1,x
        tst_a $80,~fnz
        set_a $7f,$ff
        cmp abs1,x
        tst_a $7f,~fn
        set_a $7e,$ff
        cmp abs1,x
        tst_a $7e,~fzc

        ldy #4          ;with indexing by Y
        ldx #8          ;with indexed indirect
        set_a $80,0
        cmp abs1,y
        tst_a $80,fc
        set_a $7f,0
        cmp abs1,y
        tst_a $7f,fzc
        set_a $7e,0
        cmp abs1,y
        tst_a $7e,fn
        set_a $80,$ff
        cmp abs1,y
        tst_a $80,~fnz
        set_a $7f,$ff
        cmp abs1,y
        tst_a $7f,~fn
        set_a $7e,$ff
        cmp abs1,y
        tst_a $7e,~fzc

        set_a $80,0
        cmp (ind1,x)
        tst_a $80,fc
        set_a $7f,0
        cmp (ind1,x)
        tst_a $7f,fzc
        set_a $7e,0
        cmp (ind1,x)
        tst_a $7e,fn
        set_a $80,$ff
        cmp (ind1,x)
        tst_a $80,~fnz
        set_a $7f,$ff
        cmp (ind1,x)
        tst_a $7f,~fn
        set_a $7e,$ff
        cmp (ind1,x)
        tst_a $7e,~fzc

        set_a $80,0
        cmp (ind1),y
        tst_a $80,fc
        set_a $7f,0
        cmp (ind1),y
        tst_a $7f,fzc
        set_a $7e,0
        cmp (ind1),y
        tst_a $7e,fn
        set_a $80,$ff
        cmp (ind1),y
        tst_a $80,~fnz
        set_a $7f,$ff
        cmp (ind1),y
        tst_a $7f,~fn
        set_a $7e,$ff
        cmp (ind1),y
        tst_a $7e,~fzc
        next_test

; testing shifts - ASL LSR ROL ROR all addressing modes
; shifts - accumulator
        ldx #3
tasl
        set_ax zp1,0
        asl a
        tst_ax rASL,fASL,0
        dex
        bpl tasl
        ldx #3
tasl1
        set_ax zp1,$ff
        asl a
        tst_ax rASL,fASL,$ff-fnzc
        dex
        bpl tasl1

        ldx #3
tlsr
        set_ax zp1,0
        lsr a
        tst_ax rLSR,fLSR,0
        dex
        bpl tlsr
        ldx #3
tlsr1
        set_ax zp1,$ff
        lsr a
        tst_ax rLSR,fLSR,$ff-fnzc
        dex
        bpl tlsr1

        ldx #3
trol
        set_ax zp1,0
        rol a
        tst_ax rROL,fROL,0
        dex
        bpl trol
        ldx #3
trol1
        set_ax zp1,$ff-fc
        rol a
        tst_ax rROL,fROL,$ff-fnzc
        dex
        bpl trol1

        ldx #3
trolc
        set_ax zp1,fc
        rol a
        tst_ax rROLc,fROLc,0
        dex
        bpl trolc
        ldx #3
trolc1
        set_ax zp1,$ff
        rol a
        tst_ax rROLc,fROLc,$ff-fnzc
        dex
        bpl trolc1

        ldx #3
tror
        set_ax zp1,0
        ror a
        tst_ax rROR,fROR,0
        dex
        bpl tror
        ldx #3
tror1
        set_ax zp1,$ff-fc
        ror a
        tst_ax rROR,fROR,$ff-fnzc
        dex
        bpl tror1

        ldx #3
trorc
        set_ax zp1,fc
        ror a
        tst_ax rRORc,fRORc,0
        dex
        bpl trorc
        ldx #3
trorc1
        set_ax zp1,$ff
        ror a
        tst_ax rRORc,fRORc,$ff-fnzc
        dex
        bpl trorc1
        next_test

; shifts - zeropage
        ldx #3
tasl2
        set_z zp1,0
        asl zpt
        tst_z rASL,fASL,0
        dex
        bpl tasl2
        ldx #3
tasl3
        set_z zp1,$ff
        asl zpt
        tst_z rASL,fASL,$ff-fnzc
        dex
        bpl tasl3

        ldx #3
tlsr2
        set_z zp1,0
        lsr zpt
        tst_z rLSR,fLSR,0
        dex
        bpl tlsr2
        ldx #3
tlsr3
        set_z zp1,$ff
        lsr zpt
        tst_z rLSR,fLSR,$ff-fnzc
        dex
        bpl tlsr3

        ldx #3
trol2
        set_z zp1,0
        rol zpt
        tst_z rROL,fROL,0
        dex
        bpl trol2
        ldx #3
trol3
        set_z zp1,$ff-fc
        rol zpt
        tst_z rROL,fROL,$ff-fnzc
        dex
        bpl trol3

        ldx #3
trolc2
        set_z zp1,fc
        rol zpt
        tst_z rROLc,fROLc,0
        dex
        bpl trolc2
        ldx #3
trolc3
        set_z zp1,$ff
        rol zpt
        tst_z rROLc,fROLc,$ff-fnzc
        dex
        bpl trolc3

        ldx #3
tror2
        set_z zp1,0
        ror zpt
        tst_z rROR,fROR,0
        dex
        bpl tror2
        ldx #3
tror3
        set_z zp1,$ff-fc
        ror zpt
        tst_z rROR,fROR,$ff-fnzc
        dex
        bpl tror3

        ldx #3
trorc2
        set_z zp1,fc
        ror zpt
        tst_z rRORc,fRORc,0
        dex
        bpl trorc2
        ldx #3
trorc3
        set_z zp1,$ff
        ror zpt
        tst_z rRORc,fRORc,$ff-fnzc
        dex
        bpl trorc3
        next_test

; shifts - absolute
        ldx #3
tasl4
        set_abs zp1,0
        asl abst
        tst_abs rASL,fASL,0
        dex
        bpl tasl4
        ldx #3
tasl5
        set_abs zp1,$ff
        asl abst
        tst_abs rASL,fASL,$ff-fnzc
        dex
        bpl tasl5

        ldx #3
tlsr4
        set_abs zp1,0
        lsr abst
        tst_abs rLSR,fLSR,0
        dex
        bpl tlsr4
        ldx #3
tlsr5
        set_abs zp1,$ff
        lsr abst
        tst_abs rLSR,fLSR,$ff-fnzc
        dex
        bpl tlsr5

        ldx #3
trol4
        set_abs zp1,0
        rol abst
        tst_abs rROL,fROL,0
        dex
        bpl trol4
        ldx #3
trol5
        set_abs zp1,$ff-fc
        rol abst
        tst_abs rROL,fROL,$ff-fnzc
        dex
        bpl trol5

        ldx #3
trolc4
        set_abs zp1,fc
        rol abst
        tst_abs rROLc,fROLc,0
        dex
        bpl trolc4
        ldx #3
trolc5
        set_abs zp1,$ff
        rol abst
        tst_abs rROLc,fROLc,$ff-fnzc
        dex
        bpl trolc5

        ldx #3
tror4
        set_abs zp1,0
        ror abst
        tst_abs rROR,fROR,0
        dex
        bpl tror4
        ldx #3
tror5
        set_abs zp1,$ff-fc
        ror abst
        tst_abs rROR,fROR,$ff-fnzc
        dex
        bpl tror5

        ldx #3
trorc4
        set_abs zp1,fc
        ror abst
        tst_abs rRORc,fRORc,0
        dex
        bpl trorc4
        ldx #3
trorc5
        set_abs zp1,$ff
        ror abst
        tst_abs rRORc,fRORc,$ff-fnzc
        dex
        bpl trorc5
        next_test

; shifts - zp indexed
        ldx #3
tasl6
        set_zx zp1,0
        asl zpt,x
        tst_zx rASL,fASL,0
        dex
        bpl tasl6
        ldx #3
tasl7
        set_zx zp1,$ff
        asl zpt,x
        tst_zx rASL,fASL,$ff-fnzc
        dex
        bpl tasl7

        ldx #3
tlsr6
        set_zx zp1,0
        lsr zpt,x
        tst_zx rLSR,fLSR,0
        dex
        bpl tlsr6
        ldx #3
tlsr7
        set_zx zp1,$ff
        lsr zpt,x
        tst_zx rLSR,fLSR,$ff-fnzc
        dex
        bpl tlsr7

        ldx #3
trol6
        set_zx zp1,0
        rol zpt,x
        tst_zx rROL,fROL,0
        dex
        bpl trol6
        ldx #3
trol7
        set_zx zp1,$ff-fc
        rol zpt,x
        tst_zx rROL,fROL,$ff-fnzc
        dex
        bpl trol7

        ldx #3
trolc6
        set_zx zp1,fc
        rol zpt,x
        tst_zx rROLc,fROLc,0
        dex
        bpl trolc6
        ldx #3
trolc7
        set_zx zp1,$ff
        rol zpt,x
        tst_zx rROLc,fROLc,$ff-fnzc
        dex
        bpl trolc7

        ldx #3
tror6
        set_zx zp1,0
        ror zpt,x
        tst_zx rROR,fROR,0
        dex
        bpl tror6
        ldx #3
tror7
        set_zx zp1,$ff-fc
        ror zpt,x
        tst_zx rROR,fROR,$ff-fnzc
        dex
        bpl tror7

        ldx #3
trorc6
        set_zx zp1,fc
        ror zpt,x
        tst_zx rRORc,fRORc,0
        dex
        bpl trorc6
        ldx #3
trorc7
        set_zx zp1,$ff
        ror zpt,x
        tst_zx rRORc,fRORc,$ff-fnzc
        dex
        bpl trorc7
        next_test
        
; shifts - abs indexed
        ldx #3
tasl8
        set_absx zp1,0
        asl abst,x
        tst_absx rASL,fASL,0
        dex
        bpl tasl8
        ldx #3
tasl9
        set_absx zp1,$ff
        asl abst,x
        tst_absx rASL,fASL,$ff-fnzc
        dex
        bpl tasl9

        ldx #3
tlsr8
        set_absx zp1,0
        lsr abst,x
        tst_absx rLSR,fLSR,0
        dex
        bpl tlsr8
        ldx #3
tlsr9
        set_absx zp1,$ff
        lsr abst,x
        tst_absx rLSR,fLSR,$ff-fnzc
        dex
        bpl tlsr9

        ldx #3
trol8
        set_absx zp1,0
        rol abst,x
        tst_absx rROL,fROL,0
        dex
        bpl trol8
        ldx #3
trol9
        set_absx zp1,$ff-fc
        rol abst,x
        tst_absx rROL,fROL,$ff-fnzc
        dex
        bpl trol9

        ldx #3
trolc8
        set_absx zp1,fc
        rol abst,x
        tst_absx rROLc,fROLc,0
        dex
        bpl trolc8
        ldx #3
trolc9
        set_absx zp1,$ff
        rol abst,x
        tst_absx rROLc,fROLc,$ff-fnzc
        dex
        bpl trolc9

        ldx #3
tror8
        set_absx zp1,0
        ror abst,x
        tst_absx rROR,fROR,0
        dex
        bpl tror8
        ldx #3
tror9
        set_absx zp1,$ff-fc
        ror abst,x
        tst_absx rROR,fROR,$ff-fnzc
        dex
        bpl tror9

        ldx #3
trorc8
        set_absx zp1,fc
        ror abst,x
        tst_absx rRORc,fRORc,0
        dex
        bpl trorc8
        ldx #3
trorc9
        set_absx zp1,$ff
        ror abst,x
        tst_absx rRORc,fRORc,$ff-fnzc
        dex
        bpl trorc9
        next_test

; testing memory increment/decrement - INC DEC all addressing modes
; zeropage
        ldx #0
        lda #$7e
        sta zpt
tinc    
        set_stat 0
        inc zpt
        tst_z rINC,fINC,0
        inx
        cpx #2
        bne tinc1
        lda #$fe
        sta zpt
tinc1   cpx #5
        bne tinc
        dex
        inc zpt
tdec    
        set_stat 0
        dec zpt
        tst_z rINC,fINC,0
        dex
        bmi tdec1
        cpx #1
        bne tdec
        lda #$81
        sta zpt
        bne tdec
tdec1
        ldx #0
        lda #$7e
        sta zpt
tinc10    
        set_stat $ff
        inc zpt
        tst_z rINC,fINC,$ff-fnz
        inx
        cpx #2
        bne tinc11
        lda #$fe
        sta zpt
tinc11  cpx #5
        bne tinc10
        dex
        inc zpt
tdec10    
        set_stat $ff
        dec zpt
        tst_z rINC,fINC,$ff-fnz
        dex
        bmi tdec11
        cpx #1
        bne tdec10
        lda #$81
        sta zpt
        bne tdec10
tdec11
        next_test

; absolute memory
        ldx #0
        lda #$7e
        sta abst
tinc2    
        set_stat 0
        inc abst
        tst_abs rINC,fINC,0
        inx
        cpx #2
        bne tinc3
        lda #$fe
        sta abst
tinc3   cpx #5
        bne tinc2
        dex
        inc abst
tdec2    
        set_stat 0
        dec abst
        tst_abs rINC,fINC,0
        dex
        bmi tdec3
        cpx #1
        bne tdec2
        lda #$81
        sta abst
        bne tdec2
tdec3
        ldx #0
        lda #$7e
        sta abst
tinc12    
        set_stat $ff
        inc abst
        tst_abs rINC,fINC,$ff-fnz
        inx
        cpx #2
        bne tinc13
        lda #$fe
        sta abst
tinc13   cpx #5
        bne tinc12
        dex
        inc abst
tdec12    
        set_stat $ff
        dec abst
        tst_abs rINC,fINC,$ff-fnz
        dex
        bmi tdec13
        cpx #1
        bne tdec12
        lda #$81
        sta abst
        bne tdec12
tdec13
        next_test

; zeropage indexed
        ldx #0
        lda #$7e
tinc4   sta zpt,x
        set_stat 0
        inc zpt,x
        tst_zx rINC,fINC,0
        lda zpt,x
        inx
        cpx #2
        bne tinc5
        lda #$fe
tinc5   cpx #5
        bne tinc4
        dex
        lda #2
tdec4   sta zpt,x 
        set_stat 0
        dec zpt,x
        tst_zx rINC,fINC,0
        lda zpt,x
        dex
        bmi tdec5
        cpx #1
        bne tdec4
        lda #$81
        bne tdec4
tdec5
        ldx #0
        lda #$7e
tinc14  sta zpt,x
        set_stat $ff
        inc zpt,x
        tst_zx rINC,fINC,$ff-fnz
        lda zpt,x
        inx
        cpx #2
        bne tinc15
        lda #$fe
tinc15  cpx #5
        bne tinc14
        dex
        lda #2
tdec14  sta zpt,x 
        set_stat $ff
        dec zpt,x
        tst_zx rINC,fINC,$ff-fnz
        lda zpt,x
        dex
        bmi tdec15
        cpx #1
        bne tdec14
        lda #$81
        bne tdec14
tdec15
        next_test

; memory indexed
        ldx #0
        lda #$7e
tinc6   sta abst,x
        set_stat 0
        inc abst,x
        tst_absx rINC,fINC,0
        lda abst,x
        inx
        cpx #2
        bne tinc7
        lda #$fe
tinc7   cpx #5
        bne tinc6
        dex
        lda #2
tdec6   sta abst,x 
        set_stat 0
        dec abst,x
        tst_absx rINC,fINC,0
        lda abst,x
        dex
        bmi tdec7
        cpx #1
        bne tdec6
        lda #$81
        bne tdec6
tdec7
        ldx #0
        lda #$7e
tinc16  sta abst,x
        set_stat $ff
        inc abst,x
        tst_absx rINC,fINC,$ff-fnz
        lda abst,x
        inx
        cpx #2
        bne tinc17
        lda #$fe
tinc17  cpx #5
        bne tinc16
        dex
        lda #2
tdec16  sta abst,x 
        set_stat $ff
        dec abst,x
        tst_absx rINC,fINC,$ff-fnz
        lda abst,x
        dex
        bmi tdec17
        cpx #1
        bne tdec16
        lda #$81
        bne tdec16
tdec17
        next_test

; testing logical instructions - AND EOR ORA all addressing modes
; AND
        ldx #3          ;immediate
tand    lda zpAN,x
        sta ex_andi+1   ;set AND # operand
        set_ax  absANa,0
        jsr ex_andi     ;execute AND # in RAM
        tst_ax  absrlo,absflo,0
        dex
        bpl tand
        ldx #3
tand1   lda zpAN,x
        sta ex_andi+1   ;set AND # operand
        set_ax  absANa,$ff
        jsr ex_andi     ;execute AND # in RAM
        tst_ax  absrlo,absflo,$ff-fnz
        dex
        bpl tand1
    
        ldx #3      ;zp
tand2   lda zpAN,x
        sta zpt
        set_ax  absANa,0
        and zpt
        tst_ax  absrlo,absflo,0
        dex
        bpl tand2
        ldx #3
tand3   lda zpAN,x
        sta zpt
        set_ax  absANa,$ff
        and zpt
        tst_ax  absrlo,absflo,$ff-fnz
        dex
        bpl tand3

        ldx #3      ;abs
tand4   lda zpAN,x
        sta abst
        set_ax  absANa,0
        and abst
        tst_ax  absrlo,absflo,0
        dex
        bpl tand4
        ldx #3
tand5   lda zpAN,x
        sta abst
        set_ax  absANa,$ff
        and abst
        tst_ax  absrlo,absflo,$ff-fnz
        dex
        bpl tand6

        ldx #3      ;zp,x
tand6
        set_ax  absANa,0
        and zpAN,x
        tst_ax  absrlo,absflo,0
        dex
        bpl tand6
        ldx #3
tand7
        set_ax  absANa,$ff
        and zpAN,x
        tst_ax  absrlo,absflo,$ff-fnz
        dex
        bpl tand7

        ldx #3      ;abs,x
tand8
        set_ax  absANa,0
        and absAN,x
        tst_ax  absrlo,absflo,0
        dex
        bpl tand8
        ldx #3
tand9
        set_ax  absANa,$ff
        and absAN,x
        tst_ax  absrlo,absflo,$ff-fnz
        dex
        bpl tand9

        ldy #3      ;abs,y
tand10
        set_ay  absANa,0
        and absAN,y
        tst_ay  absrlo,absflo,0
        dey
        bpl tand10
        ldy #3
tand11
        set_ay  absANa,$ff
        and absAN,y
        tst_ay  absrlo,absflo,$ff-fnz
        dey
        bpl tand11

        ldx #6      ;(zp,x)
        ldy #3
tand12
        set_ay  absANa,0
        and (indAN,x)
        tst_ay  absrlo,absflo,0
        dex
        dex
        dey
        bpl tand12
        ldx #6
        ldy #3
tand13
        set_ay  absANa,$ff
        and (indAN,x)
        tst_ay  absrlo,absflo,$ff-fnz
        dex
        dex
        dey
        bpl tand13

        ldy #3      ;(zp),y
tand14
        set_ay  absANa,0
        and (indAN),y
        tst_ay  absrlo,absflo,0
        dey
        bpl tand14
        ldy #3
tand15
        set_ay  absANa,$ff
        and (indAN),y
        tst_ay  absrlo,absflo,$ff-fnz
        dey
        bpl tand15
        next_test

; EOR
        ldx #3          ;immediate - self modifying code
teor    lda zpEO,x
        sta ex_eori+1   ;set EOR # operand
        set_ax  absEOa,0
        jsr ex_eori     ;execute EOR # in RAM
        tst_ax  absrlo,absflo,0
        dex
        bpl teor
        ldx #3
teor1   lda zpEO,x
        sta ex_eori+1   ;set EOR # operand
        set_ax  absEOa,$ff
        jsr ex_eori     ;execute EOR # in RAM
        tst_ax  absrlo,absflo,$ff-fnz
        dex
        bpl teor1
    
        ldx #3      ;zp
teor2    lda zpEO,x
        sta zpt
        set_ax  absEOa,0
        eor zpt
        tst_ax  absrlo,absflo,0
        dex
        bpl teor2
        ldx #3
teor3   lda zpEO,x
        sta zpt
        set_ax  absEOa,$ff
        eor zpt
        tst_ax  absrlo,absflo,$ff-fnz
        dex
        bpl teor3

        ldx #3      ;abs
teor4   lda zpEO,x
        sta abst
        set_ax  absEOa,0
        eor abst
        tst_ax  absrlo,absflo,0
        dex
        bpl teor4
        ldx #3
teor5   lda zpEO,x
        sta abst
        set_ax  absEOa,$ff
        eor abst
        tst_ax  absrlo,absflo,$ff-fnz
        dex
        bpl teor6

        ldx #3      ;zp,x
teor6
        set_ax  absEOa,0
        eor zpEO,x
        tst_ax  absrlo,absflo,0
        dex
        bpl teor6
        ldx #3
teor7
        set_ax  absEOa,$ff
        eor zpEO,x
        tst_ax  absrlo,absflo,$ff-fnz
        dex
        bpl teor7

        ldx #3      ;abs,x
teor8
        set_ax  absEOa,0
        eor absEO,x
        tst_ax  absrlo,absflo,0
        dex
        bpl teor8
        ldx #3
teor9
        set_ax  absEOa,$ff
        eor absEO,x
        tst_ax  absrlo,absflo,$ff-fnz
        dex
        bpl teor9

        ldy #3      ;abs,y
teor10
        set_ay  absEOa,0
        eor absEO,y
        tst_ay  absrlo,absflo,0
        dey
        bpl teor10
        ldy #3
teor11
        set_ay  absEOa,$ff
        eor absEO,y
        tst_ay  absrlo,absflo,$ff-fnz
        dey
        bpl teor11

        ldx #6      ;(zp,x)
        ldy #3
teor12
        set_ay  absEOa,0
        eor (indEO,x)
        tst_ay  absrlo,absflo,0
        dex
        dex
        dey
        bpl teor12
        ldx #6
        ldy #3
teor13
        set_ay  absEOa,$ff
        eor (indEO,x)
        tst_ay  absrlo,absflo,$ff-fnz
        dex
        dex
        dey
        bpl teor13

        ldy #3      ;(zp),y
teor14
        set_ay  absEOa,0
        eor (indEO),y
        tst_ay  absrlo,absflo,0
        dey
        bpl teor14
        ldy #3
teor15
        set_ay  absEOa,$ff
        eor (indEO),y
        tst_ay  absrlo,absflo,$ff-fnz
        dey
        bpl teor15
        next_test

; OR
        ldx #3          ;immediate - self modifying code
tora    lda zpOR,x
        sta ex_orai+1   ;set ORA # operand
        set_ax  absORa,0
        jsr ex_orai     ;execute ORA # in RAM
        tst_ax  absrlo,absflo,0
        dex
        bpl tora
        ldx #3
tora1   lda zpOR,x
        sta ex_orai+1   ;set ORA # operand
        set_ax  absORa,$ff
        jsr ex_orai     ;execute ORA # in RAM
        tst_ax  absrlo,absflo,$ff-fnz
        dex
        bpl tora1
    
        ldx #3      ;zp
tora2   lda zpOR,x
        sta zpt
        set_ax  absORa,0
        ora zpt
        tst_ax  absrlo,absflo,0
        dex
        bpl tora2
        ldx #3
tora3   lda zpOR,x
        sta zpt
        set_ax  absORa,$ff
        ora zpt
        tst_ax  absrlo,absflo,$ff-fnz
        dex
        bpl tora3

        ldx #3      ;abs
tora4   lda zpOR,x
        sta abst
        set_ax  absORa,0
        ora abst
        tst_ax  absrlo,absflo,0
        dex
        bpl tora4
        ldx #3
tora5   lda zpOR,x
        sta abst
        set_ax  absORa,$ff
        ora abst
        tst_ax  absrlo,absflo,$ff-fnz
        dex
        bpl tora6

        ldx #3      ;zp,x
tora6
        set_ax  absORa,0
        ora zpOR,x
        tst_ax  absrlo,absflo,0
        dex
        bpl tora6
        ldx #3
tora7
        set_ax  absORa,$ff
        ora zpOR,x
        tst_ax  absrlo,absflo,$ff-fnz
        dex
        bpl tora7

        ldx #3      ;abs,x
tora8
        set_ax  absORa,0
        ora absOR,x
        tst_ax  absrlo,absflo,0
        dex
        bpl tora8
        ldx #3
tora9
        set_ax  absORa,$ff
        ora absOR,x
        tst_ax  absrlo,absflo,$ff-fnz
        dex
        bpl tora9

        ldy #3      ;abs,y
tora10
        set_ay  absORa,0
        ora absOR,y
        tst_ay  absrlo,absflo,0
        dey
        bpl tora10
        ldy #3
tora11
        set_ay  absORa,$ff
        ora absOR,y
        tst_ay  absrlo,absflo,$ff-fnz
        dey
        bpl tora11

        ldx #6      ;(zp,x)
        ldy #3
tora12
        set_ay  absORa,0
        ora (indOR,x)
        tst_ay  absrlo,absflo,0
        dex
        dex
        dey
        bpl tora12
        ldx #6
        ldy #3
tora13
        set_ay  absORa,$ff
        ora (indOR,x)
        tst_ay  absrlo,absflo,$ff-fnz
        dex
        dex
        dey
        bpl tora13

        ldy #3      ;(zp),y
tora14
        set_ay  absORa,0
        ora (indOR),y
        tst_ay  absrlo,absflo,0
        dey
        bpl tora14
        ldy #3
tora15
        set_ay  absORa,$ff
        ora (indOR),y
        tst_ay  absrlo,absflo,$ff-fnz
        dey
        bpl tora15
    if I_flag = 3
        cli
    endif                
        next_test

; full binary add/subtract test
; iterates through all combinations of operands and carry input
; uses increments/decrements to predict result & result flags
        cld
        ldx #ad2        ;for indexed test
        ldy #$ff        ;max range
        lda #0          ;start with adding zeroes & no carry
        sta adfc        ;carry in - for diag
        sta ad1         ;operand 1 - accumulator
        sta ad2         ;operand 2 - memory or immediate
        sta ada2        ;non zp
        sta adrl        ;expected result bits 0-7
        sta adrh        ;expected result bit 8 (carry out)
        lda #$ff        ;complemented operand 2 for subtract
        sta sb2
        sta sba2        ;non zp
        lda #2          ;expected Z-flag
        sta adrf
tadd    clc             ;test with carry clear
        jsr chkadd
        inc adfc        ;now with carry
        inc adrl        ;result +1
        php             ;save N & Z from low result
        php
        pla             ;accu holds expected flags
        and #$82        ;mask N & Z
        plp
        bne tadd1
        inc adrh        ;result bit 8 - carry
tadd1   ora adrh        ;merge C to expected flags
        sta adrf        ;save expected flags except overflow
        sec             ;test with carry set
        jsr chkadd
        dec adfc        ;same for operand +1 but no carry
        inc ad1
        bne tadd        ;iterate op1
        lda #0          ;preset result to op2 when op1 = 0
        sta adrh
        inc ada2
        inc ad2
        php             ;save NZ as operand 2 becomes the new result
        pla
        and #$82        ;mask N00000Z0
        sta adrf        ;no need to check carry as we are adding to 0
        dec sb2         ;complement subtract operand 2
        dec sba2
        lda ad2         
        sta adrl
        bne tadd        ;iterate op2
    if disable_decimal < 1
        next_test

; decimal add/subtract test
; *** WARNING - tests documented behavior only! ***
;   only valid BCD operands are tested, N V Z flags are ignored
; iterates through all valid combinations of operands and carry input
; uses increments/decrements to predict result & carry flag
        sed 
        ldx #ad2        ;for indexed test
        ldy #$ff        ;max range
        lda #$99        ;start with adding 99 to 99 with carry
        sta ad1         ;operand 1 - accumulator
        sta ad2         ;operand 2 - memory or immediate
        sta ada2        ;non zp
        sta adrl        ;expected result bits 0-7
        lda #1          ;set carry in & out
        sta adfc        ;carry in - for diag
        sta adrh        ;expected result bit 8 (carry out)
        lda #0          ;complemented operand 2 for subtract
        sta sb2
        sta sba2        ;non zp
tdad    sec             ;test with carry set
        jsr chkdad
        dec adfc        ;now with carry clear
        lda adrl        ;decimal adjust result
        bne tdad1       ;skip clear carry & preset result 99 (9A-1)
        dec adrh
        lda #$99
        sta adrl
        bne tdad3
tdad1   and #$f         ;lower nibble mask
        bne tdad2       ;no decimal adjust needed
        dec adrl        ;decimal adjust (?0-6)
        dec adrl
        dec adrl
        dec adrl
        dec adrl
        dec adrl
tdad2   dec adrl        ;result -1
tdad3   clc             ;test with carry clear
        jsr chkdad
        inc adfc        ;same for operand -1 but with carry
        lda ad1         ;decimal adjust operand 1
        beq tdad5       ;iterate operand 2
        and #$f         ;lower nibble mask
        bne tdad4       ;skip decimal adjust
        dec ad1         ;decimal adjust (?0-6)
        dec ad1
        dec ad1
        dec ad1
        dec ad1
        dec ad1
tdad4   dec ad1         ;operand 1 -1
        jmp tdad        ;iterate op1

tdad5   lda #$99        ;precharge op1 max
        sta ad1
        lda ad2         ;decimal adjust operand 2
        beq tdad7       ;end of iteration
        and #$f         ;lower nibble mask
        bne tdad6       ;skip decimal adjust
        dec ad2         ;decimal adjust (?0-6)
        dec ad2
        dec ad2
        dec ad2
        dec ad2
        dec ad2
        inc sb2         ;complemented decimal adjust for subtract (?9+6)
        inc sb2
        inc sb2
        inc sb2
        inc sb2
        inc sb2
tdad6   dec ad2         ;operand 2 -1
        inc sb2         ;complemented operand for subtract
        lda sb2
        sta sba2        ;copy as non zp operand
        lda ad2
        sta ada2        ;copy as non zp operand
        sta adrl        ;new result since op1+carry=00+carry +op2=op2
        inc adrh        ;result carry
        bne tdad        ;iterate op2
tdad7
        next_test

; decimal/binary switch test
; tests CLD, SED, PLP, RTI to properly switch between decimal & binary opcode
;   tables
        clc
        cld
        php
        lda #$55
        adc #$55
        cmp #$aa
        trap_ne         ;expected binary result after cld
        clc
        sed
        php
        lda #$55
        adc #$55
        cmp #$10
        trap_ne         ;expected decimal result after sed
        cld
        plp
        lda #$55
        adc #$55
        cmp #$10
        trap_ne         ;expected decimal result after plp D=1
        plp
        lda #$55
        adc #$55
        cmp #$aa
        trap_ne         ;expected binary result after plp D=0
        clc
        lda #hi bin_rti_ret ;emulated interrupt for rti
        pha
        lda #lo bin_rti_ret
        pha
        php
        sed
        lda #hi dec_rti_ret ;emulated interrupt for rti
        pha
        lda #lo dec_rti_ret
        pha
        php
        cld
        rti
dec_rti_ret
        lda #$55
        adc #$55
        cmp #$10
        trap_ne         ;expected decimal result after rti D=1
        rti
bin_rti_ret        
        lda #$55
        adc #$55
        cmp #$aa
        trap_ne         ;expected binary result after rti D=0
    endif
    
        lda test_case
        cmp #test_num
        trap_ne         ;previous test is out of sequence
        lda #$f0        ;mark opcode testing complete
        sta test_case
        
; final RAM integrity test
;   verifies that none of the previous tests has altered RAM outside of the
;   designated write areas.
        check_ram
; *** DEBUG INFO ***
; to debug checksum errors uncomment check_ram in the next_test macro to
; narrow down the responsible opcode.
; may give false errors when monitor, OS or other background activity is
; allowed during previous tests.


; S U C C E S S ************************************************
; -------------       
        success         ;if you get here everything went well
; -------------       
; S U C C E S S ************************************************
        jmp start       ;run again      

    if disable_decimal < 1
; core subroutine of the decimal add/subtract test
; *** WARNING - tests documented behavior only! ***
;   only valid BCD operands are tested, N V Z flags are ignored
; iterates through all valid combinations of operands and carry input
; uses increments/decrements to predict result & carry flag
chkdad
; decimal ADC / SBC zp
        php             ;save carry for subtract
        lda ad1
        adc ad2         ;perform add
        php          
        cmp adrl        ;check result
        trap_ne         ;bad result
        pla             ;check flags
        and #1          ;mask carry
        cmp adrh
        trap_ne         ;bad carry
        plp
        php             ;save carry for next add
        lda ad1
        sbc sb2         ;perform subtract
        php          
        cmp adrl        ;check result
        trap_ne         ;bad result
        pla             ;check flags
        and #1          ;mask carry
        cmp adrh
        trap_ne         ;bad flags
        plp
; decimal ADC / SBC abs
        php             ;save carry for subtract
        lda ad1
        adc ada2        ;perform add
        php          
        cmp adrl        ;check result
        trap_ne         ;bad result
        pla             ;check flags
        and #1          ;mask carry
        cmp adrh
        trap_ne         ;bad carry
        plp
        php             ;save carry for next add
        lda ad1
        sbc sba2        ;perform subtract
        php          
        cmp adrl        ;check result
        trap_ne         ;bad result
        pla             ;check flags
        and #1          ;mask carry
        cmp adrh
        trap_ne         ;bad carry
        plp
; decimal ADC / SBC #
        php             ;save carry for subtract
        lda ad2
        sta ex_adci+1   ;set ADC # operand
        lda ad1
        jsr ex_adci     ;execute ADC # in RAM
        php          
        cmp adrl        ;check result
        trap_ne         ;bad result
        pla             ;check flags
        and #1          ;mask carry
        cmp adrh
        trap_ne         ;bad carry
        plp
        php             ;save carry for next add
        lda sb2
        sta ex_sbci+1   ;set SBC # operand
        lda ad1
        jsr ex_sbci     ;execute SBC # in RAM
        php          
        cmp adrl        ;check result
        trap_ne         ;bad result
        pla             ;check flags
        and #1          ;mask carry
        cmp adrh
        trap_ne         ;bad carry
        plp
; decimal ADC / SBC zp,x
        php             ;save carry for subtract
        lda ad1
        adc 0,x         ;perform add
        php          
        cmp adrl        ;check result
        trap_ne         ;bad result
        pla             ;check flags
        and #1          ;mask carry
        cmp adrh
        trap_ne         ;bad carry
        plp
        php             ;save carry for next add
        lda ad1
        sbc sb2-ad2,x   ;perform subtract
        php          
        cmp adrl        ;check result
        trap_ne         ;bad result
        pla             ;check flags
        and #1          ;mask carry
        cmp adrh
        trap_ne         ;bad carry
        plp
; decimal ADC / SBC abs,x
        php             ;save carry for subtract
        lda ad1
        adc ada2-ad2,x  ;perform add
        php          
        cmp adrl        ;check result
        trap_ne         ;bad result
        pla             ;check flags
        and #1          ;mask carry
        cmp adrh
        trap_ne         ;bad carry
        plp
        php             ;save carry for next add
        lda ad1
        sbc sba2-ad2,x  ;perform subtract
        php          
        cmp adrl        ;check result
        trap_ne         ;bad result
        pla             ;check flags
        and #1          ;mask carry
        cmp adrh
        trap_ne         ;bad carry
        plp
; decimal ADC / SBC abs,y
        php             ;save carry for subtract
        lda ad1
        adc ada2-$ff,y  ;perform add
        php          
        cmp adrl        ;check result
        trap_ne         ;bad result
        pla             ;check flags
        and #1          ;mask carry
        cmp adrh
        trap_ne         ;bad carry
        plp
        php             ;save carry for next add
        lda ad1
        sbc sba2-$ff,y  ;perform subtract
        php          
        cmp adrl        ;check result
        trap_ne         ;bad result
        pla             ;check flags
        and #1          ;mask carry
        cmp adrh
        trap_ne         ;bad carry
        plp
; decimal ADC / SBC (zp,x)
        php             ;save carry for subtract
        lda ad1
        adc (lo adi2-ad2,x) ;perform add
        php          
        cmp adrl        ;check result
        trap_ne         ;bad result
        pla             ;check flags
        and #1          ;mask carry
        cmp adrh
        trap_ne         ;bad carry
        plp
        php             ;save carry for next add
        lda ad1
        sbc (lo sbi2-ad2,x) ;perform subtract
        php          
        cmp adrl        ;check result
        trap_ne         ;bad result
        pla             ;check flags
        and #1          ;mask carry
        cmp adrh
        trap_ne         ;bad carry
        plp
; decimal ADC / SBC (abs),y
        php             ;save carry for subtract
        lda ad1
        adc (adiy2),y   ;perform add
        php          
        cmp adrl        ;check result
        trap_ne         ;bad result
        pla             ;check flags
        and #1          ;mask carry
        cmp adrh
        trap_ne         ;bad carry
        plp
        php             ;save carry for next add
        lda ad1
        sbc (sbiy2),y   ;perform subtract
        php          
        cmp adrl        ;check result
        trap_ne         ;bad result
        pla             ;check flags
        and #1          ;mask carry
        cmp adrh
        trap_ne         ;bad carry
        plp
        rts
    endif

; core subroutine of the full binary add/subtract test
; iterates through all combinations of operands and carry input
; uses increments/decrements to predict result & result flags
chkadd  lda adrf        ;add V-flag if overflow
        and #$83        ;keep N-----ZC / clear V
        pha
        lda ad1         ;test sign unequal between operands
        eor ad2
        bmi ckad1       ;no overflow possible - operands have different sign
        lda ad1         ;test sign equal between operands and result
        eor adrl
        bpl ckad1       ;no overflow occured - operand and result have same sign
        pla
        ora #$40        ;set V
        pha
ckad1   pla
        sta adrf        ;save expected flags
; binary ADC / SBC zp
        php             ;save carry for subtract
        lda ad1
        adc ad2         ;perform add
        php          
        cmp adrl        ;check result
        trap_ne         ;bad result
        pla             ;check flags
        and #$c3        ;mask NV----ZC
        cmp adrf
        trap_ne         ;bad flags
        plp
        php             ;save carry for next add
        lda ad1
        sbc sb2         ;perform subtract
        php          
        cmp adrl        ;check result
        trap_ne         ;bad result
        pla             ;check flags
        and #$c3        ;mask NV----ZC
        cmp adrf
        trap_ne         ;bad flags
        plp
; binary ADC / SBC abs
        php             ;save carry for subtract
        lda ad1
        adc ada2        ;perform add
        php          
        cmp adrl        ;check result
        trap_ne         ;bad result
        pla             ;check flags
        and #$c3        ;mask NV----ZC
        cmp adrf
        trap_ne         ;bad flags
        plp
        php             ;save carry for next add
        lda ad1
        sbc sba2        ;perform subtract
        php          
        cmp adrl        ;check result
        trap_ne         ;bad result
        pla             ;check flags
        and #$c3        ;mask NV----ZC
        cmp adrf
        trap_ne         ;bad flags
        plp
; binary ADC / SBC #
        php             ;save carry for subtract
        lda ad2
        sta ex_adci+1   ;set ADC # operand
        lda ad1
        jsr ex_adci     ;execute ADC # in RAM
        php          
        cmp adrl        ;check result
        trap_ne         ;bad result
        pla             ;check flags
        and #$c3        ;mask NV----ZC
        cmp adrf
        trap_ne         ;bad flags
        plp
        php             ;save carry for next add
        lda sb2
        sta ex_sbci+1   ;set SBC # operand
        lda ad1
        jsr ex_sbci     ;execute SBC # in RAM
        php          
        cmp adrl        ;check result
        trap_ne         ;bad result
        pla             ;check flags
        and #$c3        ;mask NV----ZC
        cmp adrf
        trap_ne         ;bad flags
        plp
; binary ADC / SBC zp,x
        php             ;save carry for subtract
        lda ad1
        adc 0,x         ;perform add
        php          
        cmp adrl        ;check result
        trap_ne         ;bad result
        pla             ;check flags
        and #$c3        ;mask NV----ZC
        cmp adrf
        trap_ne         ;bad flags
        plp
        php             ;save carry for next add
        lda ad1
        sbc sb2-ad2,x   ;perform subtract
        php          
        cmp adrl        ;check result
        trap_ne         ;bad result
        pla             ;check flags
        and #$c3        ;mask NV----ZC
        cmp adrf
        trap_ne         ;bad flags
        plp
; binary ADC / SBC abs,x
        php             ;save carry for subtract
        lda ad1
        adc ada2-ad2,x  ;perform add
        php          
        cmp adrl        ;check result
        trap_ne         ;bad result
        pla             ;check flags
        and #$c3        ;mask NV----ZC
        cmp adrf
        trap_ne         ;bad flags
        plp
        php             ;save carry for next add
        lda ad1
        sbc sba2-ad2,x  ;perform subtract
        php          
        cmp adrl        ;check result
        trap_ne         ;bad result
        pla             ;check flags
        and #$c3        ;mask NV----ZC
        cmp adrf
        trap_ne         ;bad flags
        plp
; binary ADC / SBC abs,y
        php             ;save carry for subtract
        lda ad1
        adc ada2-$ff,y  ;perform add
        php          
        cmp adrl        ;check result
        trap_ne         ;bad result
        pla             ;check flags
        and #$c3        ;mask NV----ZC
        cmp adrf
        trap_ne         ;bad flags
        plp
        php             ;save carry for next add
        lda ad1
        sbc sba2-$ff,y  ;perform subtract
        php          
        cmp adrl        ;check result
        trap_ne         ;bad result
        pla             ;check flags
        and #$c3        ;mask NV----ZC
        cmp adrf
        trap_ne         ;bad flags
        plp
; binary ADC / SBC (zp,x)
        php             ;save carry for subtract
        lda ad1
        adc (lo adi2-ad2,x) ;perform add
        php          
        cmp adrl        ;check result
        trap_ne         ;bad result
        pla             ;check flags
        and #$c3        ;mask NV----ZC
        cmp adrf
        trap_ne         ;bad flags
        plp
        php             ;save carry for next add
        lda ad1
        sbc (lo sbi2-ad2,x) ;perform subtract
        php          
        cmp adrl        ;check result
        trap_ne         ;bad result
        pla             ;check flags
        and #$c3        ;mask NV----ZC
        cmp adrf
        trap_ne         ;bad flags
        plp
; binary ADC / SBC (abs),y
        php             ;save carry for subtract
        lda ad1
        adc (adiy2),y   ;perform add
        php          
        cmp adrl        ;check result
        trap_ne         ;bad result
        pla             ;check flags
        and #$c3        ;mask NV----ZC
        cmp adrf
        trap_ne         ;bad flags
        plp
        php             ;save carry for next add
        lda ad1
        sbc (sbiy2),y   ;perform subtract
        php          
        cmp adrl        ;check result
        trap_ne         ;bad result
        pla             ;check flags
        and #$c3        ;mask NV----ZC
        cmp adrf
        trap_ne         ;bad flags
        plp
        rts

; target for the jump absolute test
        dey
        dey
test_far
        php             ;either SP or Y count will fail, if we do not hit
        dey
        dey
        dey
        plp
        trap_cs         ;flags loaded?
        trap_vs
        trap_mi
        trap_eq 
        cmp #'F'        ;registers loaded?
        trap_ne
        cpx #'A'
        trap_ne        
        cpy #('R'-3)
        trap_ne
        pha             ;save a,x
        txa
        pha
        tsx
        cpx #$fd        ;check SP
        trap_ne
        pla             ;restore x
        tax
        set_stat $ff
        pla             ;restore a
        inx             ;return registers with modifications
        eor #$aa        ;N=1, V=1, Z=0, C=1
        jmp far_ret
        
; target for the jump indirect test
        align
ptr_tst_ind dw test_ind
ptr_ind_ret dw ind_ret
        trap            ;runover protection
        dey
        dey
test_ind
        php             ;either SP or Y count will fail, if we do not hit
        dey
        dey
        dey
        plp
        trap_cs         ;flags loaded?
        trap_vs
        trap_mi
        trap_eq 
        cmp #'I'        ;registers loaded?
        trap_ne
        cpx #'N'
        trap_ne        
        cpy #('D'-3)
        trap_ne
        pha             ;save a,x
        txa
        pha
        tsx
        cpx #$fd        ;check SP
        trap_ne
        pla             ;restore x
        tax
        set_stat $ff
        pla             ;restore a
        inx             ;return registers with modifications
        eor #$aa        ;N=1, V=1, Z=0, C=1
        jmp (ptr_ind_ret)
        trap            ;runover protection

; target for the jump subroutine test
        dey
        dey
test_jsr
        php             ;either SP or Y count will fail, if we do not hit
        dey
        dey
        dey
        plp
        trap_cs         ;flags loaded?
        trap_vs
        trap_mi
        trap_eq 
        cmp #'J'        ;registers loaded?
        trap_ne
        cpx #'S'
        trap_ne        
        cpy #('R'-3)
        trap_ne
        pha             ;save a,x
        txa
        pha       
        tsx             ;sp -4? (return addr,a,x)
        cpx #$fb
        trap_ne
        lda $1ff        ;propper return on stack
        cmp #hi(jsr_ret)
        trap_ne
        lda $1fe
        cmp #lo(jsr_ret)
        trap_ne
        set_stat $ff
        pla             ;pull x,a
        tax
        pla
        inx             ;return registers with modifications
        eor #$aa        ;N=1, V=1, Z=0, C=1
        rts
        trap            ;runover protection
        
;trap in case of unexpected IRQ, NMI, BRK, RESET - BRK test target
nmi_trap
        trap            ;check stack for conditions at NMI
res_trap
        trap            ;unexpected RESET
        
        dey
        dey
irq_trap                ;BRK test or unextpected BRK or IRQ
        php             ;either SP or Y count will fail, if we do not hit
        dey
        dey
        dey
        ;next 4 traps could be caused by unexpected BRK or IRQ
        ;check stack for BREAK and originating location
        ;possible jump/branch into weeds (uninitialized space)
        cmp #'B'        ;registers loaded?
        trap_ne
        cpx #'R'
        trap_ne        
        cpy #('K'-3)
        trap_ne
        sta irq_a       ;save registers during break test
        stx irq_x
        tsx             ;test break on stack
        lda $102,x
        cmp_flag 0      ;break test should have B=1
        trap_ne         ; - no break flag on stack
        pla
        cmp #fai        ;should have added interrupt disable
        trap_ne
        tsx
        cpx #$fc        ;sp -3? (return addr, flags)
        trap_ne
        lda $1ff        ;propper return on stack
        cmp #hi(brk_ret)
        trap_ne
        lda $1fe
        cmp #lo(brk_ret)
        trap_ne
        set_stat $ff
        ldx irq_x
        inx             ;return registers with modifications
        lda irq_a
        eor #$aa        ;N=1, V=1, Z=0, C=1 but original flags should be restored
        rti
        trap            ;runover protection
        
    if report = 1
        include "report.i65"
    endif
        
;copy of data to initialize BSS segment
    if load_data_direct != 1
zp_init
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
zpOR_   db  0,$1f,$71,$80   ;test pattern for OR
zpAN_   db  $0f,$ff,$7f,$80 ;test pattern for AND
zpEO_   db  $ff,$0f,$8f,$8f ;test pattern for EOR
;indirect addressing pointers
ind1_   dw  abs1            ;indirect pointer to pattern in absolute memory
        dw  abs1+1
        dw  abs1+2
        dw  abs1+3
        dw  abs7f
inw1_   dw  abs1-$f8        ;indirect pointer for wrap-test pattern
indt_   dw  abst            ;indirect pointer to store area in absolute memory
        dw  abst+1
        dw  abst+2
        dw  abst+3
inwt_   dw  abst-$f8        ;indirect pointer for wrap-test store
indAN_  dw  absAN           ;indirect pointer to AND pattern in absolute memory
        dw  absAN+1
        dw  absAN+2
        dw  absAN+3
indEO_  dw  absEO           ;indirect pointer to EOR pattern in absolute memory
        dw  absEO+1
        dw  absEO+2
        dw  absEO+3
indOR_  dw  absOR           ;indirect pointer to OR pattern in absolute memory
        dw  absOR+1
        dw  absOR+2
        dw  absOR+3
;add/subtract indirect pointers
adi2_   dw  ada2            ;indirect pointer to operand 2 in absolute memory
sbi2_   dw  sba2            ;indirect pointer to complemented operand 2 (SBC)
adiy2_  dw  ada2-$ff        ;with offset for indirect indexed
sbiy2_  dw  sba2-$ff
zp_end
    if (zp_end - zp_init) != (zp_bss_end - zp_bss)   
        ;force assembler error if size is different   
        ERROR ERROR ERROR   ;mismatch between bss and zeropage data
    endif 
data_init
ex_and_ and #0              ;execute immediate opcodes
        rts
ex_eor_ eor #0              ;execute immediate opcodes
        rts
ex_ora_ ora #0              ;execute immediate opcodes
        rts
ex_adc_ adc #0              ;execute immediate opcodes
        rts
ex_sbc_ sbc #0              ;execute immediate opcodes
        rts
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
;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
;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
;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
;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
;logical results
absrlo_ db  0,$ff,$7f,$80
absflo_ db  fz,fn,0,fn
data_end
    if (data_end - data_init) != (data_bss_end - data_bss)
        ;force assembler error if size is different   
        ERROR ERROR ERROR   ;mismatch between bss and data
    endif 

vec_init
        dw  nmi_trap
        dw  res_trap
        dw  irq_trap
vec_bss equ $fffa
    endif                   ;end of RAM init data
    
    if (load_data_direct = 1) & (ROM_vectors = 1)  
        org $fffa       ;vectors
        dw  nmi_trap
        dw  res_trap
        dw  irq_trap
    endif

        end start
            


================================================
FILE: assets/tests/6502_functional_test.lst
================================================
AS65 Assembler for R6502 [1.42].  Copyright 1994-2007, Frank A. Kingswood                                                Page    1
---------------------------------------------------- 6502_functional_test.a65 ----------------------------------------------------

6010 lines read, no errors in pass 1.
                        ;
                        ; 6 5 0 2   F U N C T I O N A L   T E S T
                        ;
                        ; Copyright (C) 2012-2015  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
                        ; 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 General Public License for more details.
                        ;
                        ; You should have received a copy of the GNU General Public License
                        ; along with this program.  If not, see <http://www.gnu.org/licenses/>.
                        
                        
                        ; This program is designed to test all opcodes of a 6502 emulator using all
                        ; addressing modes with focus on propper setting of the processor status
                        ; register bits.
                        ; 
                        ; version 21-oct-2015
                        ; contact info at http://2m5.de or email K@2m5.de
                        ;
                        ; assembled with AS65 from http://www.kingswood-consulting.co.uk/assemblers/
                        ; command line switches: -l -m -s2 -w -h0
                        ;                         |  |  |   |  no page headers in listing
                        ;                         |  |  |   wide listing (133 char/col)
                        ;                         |  |  write intel hex file instead of binary
                        ;                         |  expand macros in listing
                        ;                         generate pass2 listing
                        ;
                        ; No IO - should be run from a monitor with access to registers.
                        ; To run load intel hex image with a load command, than alter PC to 400 hex
                        ; (code_segment) and enter a go command.
                        ; Loop on program counter determines error or successful completion of test.
                        ; Check listing for relevant traps (jump/branch *).
                        ; Please note that in early tests some instructions will have to be used before
                        ; they are actually tested!
                        ;
                        ; RESET, NMI or IRQ should not occur and will be trapped if vectors are enabled.
                        ; Tests documented behavior of the original NMOS 6502 only! No unofficial
                        ; opcodes. Additional opcodes of newer versions of the CPU (65C02, 65816) will
                        ; not be tested. Decimal ops will only be tested with valid BCD operands and
                        ; N V Z flags will be ignored.
                        ;
                        ; Debugging hints:
                        ;     Most of the code is written sequentially. if you hit a trap, check the
                        ;   immediately preceeding code for the instruction to be tested. Results are
                        ;   tested first, flags are checked second by pushing them onto the stack and
                        ;   pulling them to the accumulator after the result was checked. The "real"
                        ;   flags are no longer valid for the tested instruction at this time!
                        ;     If the tested instruction was indexed, the relevant index (X or Y) must
                        ;   also be checked. Opposed to the flags, X and Y registers are still valid.
                        ;
                        ; versions:
                        ;   28-jul-2012  1st version distributed for testing
                        ;   29-jul-2012  fixed references to location 0, now #0
                        ;                added license - GPLv3
                        ;   30-jul-2012  added configuration options
                        ;   01-aug-2012  added trap macro to allow user to change error handling
                        ;   01-dec-2012  fixed trap in branch field must be a branch
                        ;   02-mar-2013  fixed PLA flags not tested
                        ;   19-jul-2013  allowed ROM vectors to be loaded when load_data_direct = 0
                        ;                added test sequence check to detect if tests jump their fence
                        ;   23-jul-2013  added RAM integrity check option
                        ;   16-aug-2013  added error report to standard output option
                        ;   13-dec-2014  added binary/decimal opcode table switch test
                        ;   14-dec-2014  improved relative address test
                        ;   23-aug-2015  added option to disable self modifying tests
                        ;   24-aug-2015  all self modifying immediate opcodes now execute in data RAM
                        ;                added small branch offset pretest
                        ;   21-oct-2015  added option to disable decimal mode ADC & SBC tests
                        
                        
                        ; C O N F I G U R A T I O N
                        
                        ;ROM_vectors writable (0=no, 1=yes)
                        ;if ROM vectors can not be used interrupts will not be trapped
                        ;as a consequence BRK can not be tested but will be emulated to test RTI
0001 =                  ROM_vectors = 1
                        
                        ;load_data_direct (0=move from code segment, 1=load directly)
                        ;loading directly is preferred but may not be supported by your platform
                        ;0 produces only consecutive object code, 1 is not suitable for a binary image
0000 =                  load_data_direct = 0
                        
                        ;I_flag behavior (0=force enabled, 1=force disabled, 2=prohibit change, 3=allow
                        ;change) 2 requires extra code and is not recommended. SEI & CLI can only be
                        ;tested if you allow changing the interrupt status (I_flag = 3)
0003 =                  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
                        ;                                add 2 if I_flag = 2
000a =                  zero_page = $a  
                        
                        ;data_segment memory start address, $6A (106) consecutive Bytes required
0200 =                  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
                        ;                                   add 2.5 kB if I_flag = 2
0400 =                  code_segment = $400  
                        
                        ;self modifying code may be disabled to allow running in ROM
                        ;0=part of the code is self modifying and must reside in RAM
                        ;1=tests disabled: branch range
0000 =                  disable_selfmod = 0
                        
                        ;report errors through I/O channel (0=use standard self trap loops, 1=include
                        ;report.i65 as I/O channel, add 3.5 kB)
0000 =                  report = 0
                        
                        ;RAM integrity test option. Checks for undesired RAM writes.
                        ;set lowest non RAM or RAM mirror address page (-1=disable, 0=64k, $40=16k)
                        ;leave disabled if a monitor, OS or background interrupt is allowed to alter RAM
ffff =                  ram_top = -1
                        
                        ;disable test decimal mode ADC & SBC, 0=enable, 1=disable,
                        ;2=disable including decimal flag in processor status
0000 =                  disable_decimal = 0
                        
                                noopt       ;do not take shortcuts
                        
                        ;macros for error & success traps to allow user modification
                        ;example:
                        ;trap    macro
                        ;        jsr my_error_handler
                        ;        endm
                        ;trap_eq macro
                        ;        bne skip\?
                        ;        trap           ;failed equal (zero)
                        ;skip\?
                        ;        endm
                        ;
                        ; my_error_handler should pop the calling address from the stack and report it.
                        ; putting larger portions of code (more than 3 bytes) inside the trap macro
                        ; may lead to branch range problems for some tests.
                            if report = 0
                        trap    macro
                                jmp *           ;failed anyway
                                endm
                        trap_eq macro
                                beq *           ;failed equal (zero)
                                endm
                        trap_ne macro
                                bne *           ;failed not equal (non zero)
                                endm
                        trap_cs macro
                                bcs *           ;failed carry set
                                endm
                        trap_cc macro
                                bcc *           ;failed carry clear
                                endm
                        trap_mi macro
                                bmi *           ;failed minus (bit 7 set)
                                endm
                        trap_pl macro
                                bpl *           ;failed plus (bit 7 clear)
                                endm
                        trap_vs macro
                                bvs *           ;failed overflow set
                                endm
                        trap_vc macro
                                bvc *           ;failed overflow clear
                                endm
                        ; please observe that during the test the stack gets invalidated
                        ; therefore a RTS inside the success macro is not possible
                        success macro
                                jmp *           ;test passed, no errors
                                endm
                            endif
                            if report = 1
                        trap    macro
                                jsr report_error
                                endm
                        trap_eq macro
                                bne skip\?
                                trap           ;failed equal (zero)
                        skip\?
                                endm
                        trap_ne macro
                                beq skip\?
                                trap            ;failed not equal (non zero)
                        skip\?
                                endm
                        trap_cs macro
                                bcc skip\?
                                trap            ;failed carry set
                        skip\?
                                endm
                        trap_cc macro
                                bcs skip\?
                                trap            ;failed carry clear
                        skip\?
                                endm
                        trap_mi macro
                                bpl skip\?
                                trap            ;failed minus (bit 7 set)
                        skip\?
                                endm
                        trap_pl macro
                                bmi skip\?
                                trap            ;failed plus (bit 7 clear)
                        skip\?
                                endm
                        trap_vs macro
                                bvc skip\?
                                trap            ;failed overflow set
                        skip\?
                                endm
                        trap_vc macro
                                bvs skip\?
                                trap            ;failed overflow clear
                        skip\?
                                endm
                        ; please observe that during the test the stack gets invalidated
                        ; therefore a RTS inside the success macro is not possible
                        success macro
                                jsr report_success
                                endm
                            endif
                        
                        
0001 =                  carry   equ %00000001   ;flag bits in status
0002 =                  zero    equ %00000010
0004 =                  intdis  equ %00000100
0008 =                  decmode equ %00001000
0010 =                  break   equ %00010000
0020 =                  reserv  equ %00100000
0040 =                  overfl  equ %01000000
0080 =                  minus   equ %10000000
                        
0001 =                  fc      equ carry
0002 =                  fz      equ zero
0003 =                  fzc     equ carry+zero
0040 =                  fv      equ overfl
0042 =                  fvz     equ overfl+zero
0080 =                  fn      equ minus
0081 =                  fnc     equ minus+carry
0082 =                  fnz     equ minus+zero
0083 =                  fnzc    equ minus+zero+carry
00c0 =                  fnv     equ minus+overfl
                        
0030 =                  fao     equ break+reserv    ;bits always on after PHP, BRK
0034 =                  fai     equ fao+intdis      ;+ forced interrupt disable
0038 =                  faod    equ fao+decmode     ;+ ignore decimal
003c =                  faid    equ fai+decmode     ;+ ignore decimal
00ff =                  m8      equ $ff             ;8 bit mask
00fb =                  m8i     equ $ff&~intdis     ;8 bit mask - interrupt disable
                        
                        ;macros to allow masking of status bits.
                        ;masking test of decimal bit
                        ;masking of interrupt enable/disable on load and compare
                        ;masking of always on bits after PHP or BRK (unused & break) on compare
                            if disable_decimal < 2
                                if I_flag = 0
                        load_flag   macro
                                    lda #\1&m8i         ;force enable interrupts (mask I)
                                    endm
                        cmp_flag    macro
                                    cmp #(\1|fao)&m8i   ;I_flag is always enabled + always on bits
                                    endm
                        eor_flag    macro
                                    eor #(\1&m8i|fao)   ;mask I, invert expected flags + always on bits
                                    endm
                                endif
                                if I_flag = 1
                        load_flag   macro
                                    lda #\1|intdis      ;force disable interrupts
                                    endm
                        cmp_flag    macro
                                    cmp #(\1|fai)&m8    ;I_flag is always disabled + always on bits
                                    endm
                        eor_flag    macro
                                    eor #(\1|fai)       ;invert expected flags + always on bits + I
                                    endm
                                endif
                                if I_flag = 2
                        load_flag   macro
                                    lda #\1
                                    ora flag_I_on       ;restore I-flag
                                    and flag_I_off
                                    endm
                        cmp_flag    macro
                                    eor flag_I_on       ;I_flag is never changed
                                    cmp #(\1|fao)&m8i   ;expected flags + always on bits, mask I
                                    endm
                        eor_flag    macro
                                    eor flag_I_on       ;I_flag is never changed
                                    eor #(\1&m8i|fao)   ;mask I, invert expected flags + always on bits
                                    endm
                                endif
                                if I_flag = 3
                        load_flag   macro
                                    lda #\1             ;allow test to change I-flag (no mask)
                                    endm
                        cmp_flag    macro
                                    cmp #(\1|fao)&m8    ;expected flags + always on bits
                                    endm
                        eor_flag    macro
                                    eor #\1|fao         ;invert expected flags + always on bits
                                    endm
                                endif
                            else
                                if I_flag = 0
                        load_flag   macro
                                    lda #\1&m8i         ;force enable interrupts (mask I)
                                    endm
                        cmp_flag    macro
                                    ora #decmode        ;ignore decimal mode bit
                                    cmp #(\1|faod)&m8i  ;I_flag is always enabled + always on bits
                                    endm
                        eor_flag    macro
                                    ora #decmode        ;ignore decimal mode bit
                                    eor #(\1&m8i|faod)  ;mask I, invert expected flags + always on bits
                                    endm
                                endif
                                if I_flag = 1
                        load_flag   macro
                                    lda #\1|intdis      ;force disable interrupts
                                    endm
                        cmp_flag    macro
                                    ora #decmode        ;ignore decimal mode bit
                                    cmp #(\1|faid)&m8   ;I_flag is always disabled + always on bits
                                    endm
                        eor_flag    macro
                                    ora #decmode        ;ignore decimal mode bit
                                    eor #(\1|faid)      ;invert expected flags + always on bits + I
                                    endm
                                endif
                                if I_flag = 2
                        load_flag   macro
                                    lda #\1
                                    ora flag_I_on       ;restore I-flag
                                    and flag_I_off
                                    endm
                        cmp_flag    macro
                                    eor flag_I_on       ;I_flag is never changed
                                    ora #decmode        ;ignore decimal mode bit
                                    cmp #(\1|faod)&m8i  ;expected flags + always on bits, mask I
                                    endm
                        eor_flag    macro
                                    eor flag_I_on       ;I_flag is never changed
                                    ora #decmode        ;ignore decimal mode bit
                                    eor #(\1&m8i|faod)  ;mask I, invert expected flags + always on bits
                                    endm
                                endif
                                if I_flag = 3
                        load_flag   macro
                                    lda #\1             ;allow test to change I-flag (no mask)
                                    endm
                        cmp_flag    macro
                                    ora #decmode        ;ignore decimal mode bit
                                    cmp #(\1|faod)&m8   ;expected flags + always on bits
                                    endm
                        eor_flag    macro
                                    ora #decmode        ;ignore decimal mode bit
                                    eor #\1|faod        ;invert expected flags + always on bits
                                    endm
                                endif
                            endif
                        
                        ;macros to set (register|memory|zeropage) & status
                        set_stat    macro       ;setting flags in the processor status register
                                    load_flag \1
                                    pha         ;use stack to load status
                                    plp
                                    endm
                        
                        set_a       macro       ;precharging accu & status
                                    load_flag \2
                                    pha         ;use stack to load status
                                    lda #\1     ;precharge accu
                                    plp
                                    endm
                        
                        set_x       macro       ;precharging index & status
                                    load_flag \2
                                    pha         ;use stack to load status
                                    ldx #\1     ;precharge index x
                                    plp
                                    endm
                        
                        set_y       macro       ;precharging index & status
                                    load_flag \2
                                    pha         ;use stack to load status
                                    ldy #\1     ;precharge index y
                                    plp
                                    endm
                        
                        set_ax      macro       ;precharging indexed accu & immediate status
                                    load_flag \2
                                    pha         ;use stack to load status
                                    lda \1,x    ;precharge accu
                                    plp
                                    endm
                        
                        set_ay      macro       ;precharging indexed accu & immediate status
                                    load_flag \2
                                    pha         ;use stack to load status
                                    lda \1,y    ;precharge accu
                                    plp
                                    endm
                        
                        set_z       macro       ;precharging indexed zp & immediate status
                                    load_flag \2
                                    pha         ;use stack to load status
                                    lda \1,x    ;load to zeropage
                                    sta zpt
                                    plp
                                    endm
                        
                        set_zx      macro       ;precharging zp,x & immediate status
                                    load_flag \2
                                    pha         ;use stack to load status
                                    lda \1,x    ;load to indexed zeropage
                                    sta zpt,x
                                    plp
                                    endm
                        
                        set_abs     macro       ;precharging indexed memory & immediate status
                                    load_flag \2
                                    pha         ;use stack to load status
                                    lda \1,x    ;load to memory
                                    sta abst
                                    plp
                                    endm
                        
                        set_absx    macro       ;precharging abs,x & immediate status
                                    load_flag \2
                                    pha         ;use stack to load status
                                    lda \1,x    ;load to indexed memory
                                    sta abst,x
                                    plp
                                    endm
                        
                        ;macros to test (register|memory|zeropage) & status & (mask)
                        tst_stat    macro       ;testing flags in the processor status register
                                    php         ;save status
                                    pla         ;use stack to retrieve status
                                    pha
                                    cmp_flag \1
                                    trap_ne
                                    plp         ;restore status
                                    endm
                                    
                        tst_a       macro       ;testing result in accu & flags
                                    php         ;save flags
                                    cmp #\1     ;test result
                                    trap_ne
                                    pla         ;load status
                                    pha
                                    cmp_flag \2
                                    trap_ne
                                    plp         ;restore status
                                    endm
                        
                        tst_x       macro       ;testing result in x index & flags
                                    php         ;save flags
                                    cpx #\1     ;test result
                                    trap_ne
                                    pla         ;load status
                                    pha
                                    cmp_flag \2
                                    trap_ne
                                    plp         ;restore status
                                    endm
                        
                        tst_y       macro       ;testing result in y index & flags
                                    php         ;save flags
                                    cpy #\1     ;test result
                                    trap_ne
                                    pla         ;load status
                                    pha
                                    cmp_flag \2
                                    trap_ne
                                    plp         ;restore status
                                    endm
                        
                        tst_ax      macro       ;indexed testing result in accu & flags
                                    php         ;save flags
                                    cmp \1,x    ;test result
                                    trap_ne
                                    pla         ;load status
                                    eor_flag \3
                                    cmp \2,x    ;test flags
                                    trap_ne     ;
                                    endm
                        
                        tst_ay      macro       ;indexed testing result in accu & flags
                                    php         ;save flags
                                    cmp \1,y    ;test result
Download .txt
gitextract_1yla08f4/

├── CMakeLists.txt
├── LICENSE
├── Makefile
├── README.md
├── assets/
│   ├── bas/
│   │   ├── 10print.bas
│   │   ├── bitmap.bas
│   │   ├── bouncing.bas
│   │   └── lowercase.bas
│   ├── prg/
│   │   └── monopole.prg
│   ├── roms/
│   │   └── README.md
│   └── tests/
│       ├── 6502_functional_test.a65
│       ├── 6502_functional_test.lst
│       └── README.md
├── cmake/
│   ├── FindSDL2.cmake
│   ├── FindSDL2_image.cmake
│   ├── FindSDL2_net.cmake
│   ├── FindSDL2_ttf.cmake
│   └── README.md
├── doc/
│   ├── .gitignore
│   └── doxygen.conf
├── res/
│   └── emudore.rc
└── src/
    ├── c64.cpp
    ├── c64.h
    ├── cia1.cpp
    ├── cia1.h
    ├── cia2.cpp
    ├── cia2.h
    ├── cpu.cpp
    ├── cpu.h
    ├── debugger.cpp
    ├── debugger.h
    ├── io.cpp
    ├── io.h
    ├── loader.cpp
    ├── loader.h
    ├── main.cpp
    ├── memory.cpp
    ├── memory.h
    ├── sid.h
    ├── util.h
    ├── vic.cpp
    └── vic.h
Download .txt
SYMBOL INDEX (21 symbols across 12 files)

FILE: src/c64.h
  function class (line 41) | class C64

FILE: src/cia1.h
  function class (line 29) | class Cia1

FILE: src/cia2.h
  function class (line 29) | class Cia2

FILE: src/cpu.h
  function class (line 27) | class Cpu

FILE: src/debugger.cpp
  type sockaddr_in (line 38) | struct sockaddr_in
  type sockaddr (line 58) | struct sockaddr
  type sockaddr_in (line 156) | struct sockaddr_in
  type sockaddr (line 159) | struct sockaddr

FILE: src/debugger.h
  function class (line 34) | class Debugger

FILE: src/io.h
  function class (line 40) | class IO
  function screen_update_pixel (line 89) | inline void IO::screen_update_pixel(int x, int y, int color)

FILE: src/loader.h
  function class (line 27) | class Loader

FILE: src/main.cpp
  function loader_cb (line 32) | bool loader_cb()
  function emscripten_loader_cb (line 39) | bool emscripten_loader_cb()
  function load_file (line 46) | void load_file(const char *file)
  function wget_cb (line 63) | void wget_cb(const char *f)
  function emscripten_loop (line 69) | void emscripten_loop()
  function main (line 74) | int main(int argc, char **argv)

FILE: src/memory.h
  function class (line 50) | class Memory

FILE: src/sid.h
  function class (line 26) | class Sid

FILE: src/vic.h
  function class (line 33) | class Vic
Condensed preview — 42 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,067K chars).
[
  {
    "path": "CMakeLists.txt",
    "chars": 2357,
    "preview": "cmake_minimum_required (VERSION 2.8)\nproject(emudore)\nset(SRC_FILES \"src/c64.cpp\"\n              \"src/cpu.cpp\"\n          "
  },
  {
    "path": "LICENSE",
    "chars": 11357,
    "preview": "                                 Apache License\n                           Version 2.0, January 2004\n                   "
  },
  {
    "path": "Makefile",
    "chars": 523,
    "preview": "release:\n\trm -rf build/*\n\tcd build;cmake -DCMAKE_BUILD_TYPE=Release ..\n\tcd build;make\ndebug:\n\trm -rf build/*\n\tcd build;c"
  },
  {
    "path": "README.md",
    "chars": 9404,
    "preview": "# emudore, a Commodore 64 emulator\n\n![basic](/pics/basic.gif \"basic\")\n\n# What's this?\n\nemudore is a [Commodore 64 emulat"
  },
  {
    "path": "assets/bas/10print.bas",
    "chars": 71,
    "preview": "REM source: http://10print.org/\n10 PRINT CHR$(205.5+RND(1)); : GOTO 10\n"
  },
  {
    "path": "assets/bas/bitmap.bas",
    "chars": 232,
    "preview": "10 POKE 53272,PEEK(53272)OR8:POKE 53265,PEEK(53265)OR32\n20 FORI=8192TO16191 STEP 8\n30 POKEI,240:POKEI+1,240:POKEI+2,240:"
  },
  {
    "path": "assets/bas/bouncing.bas",
    "chars": 343,
    "preview": "REM source: http://www.lemon64.com/manual/\nNEW\n10 POKE 53281,1: PRINT\"*\"\n20 POKE 53280,7: POKE 53281,6\n30 X = 1 : Y = 1\n"
  },
  {
    "path": "assets/bas/lowercase.bas",
    "chars": 44,
    "preview": "REM SWITCH TO LOWERCASE MODE\nPOKE 53272,23 \n"
  },
  {
    "path": "assets/roms/README.md",
    "chars": 702,
    "preview": "The following files have been downloaded from: \n\nftp://www.zimmers.net/pub/cbm/firmware/computers/c64/\n\nPlease, bear in "
  },
  {
    "path": "assets/tests/6502_functional_test.a65",
    "chars": 144710,
    "preview": ";\n; 6 5 0 2   F U N C T I O N A L   T E S T\n;\n; Copyright (C) 2012-2015  Klaus Dormann\n;\n; This program is free software"
  },
  {
    "path": "assets/tests/6502_functional_test.lst",
    "chars": 721434,
    "preview": "AS65 Assembler for R6502 [1.42].  Copyright 1994-2007, Frank A. Kingswood                                               "
  },
  {
    "path": "assets/tests/README.md",
    "chars": 359,
    "preview": "These are Klaus Dormann 6502 functional tests, also available at:\n\nhttps://github.com/Klaus2m5/6502_65C02_functional_tes"
  },
  {
    "path": "cmake/FindSDL2.cmake",
    "chars": 6193,
    "preview": "\n# This module defines\n# SDL2_LIBRARY, the name of the library to link against\n# SDL2_FOUND, if false, do not try to lin"
  },
  {
    "path": "cmake/FindSDL2_image.cmake",
    "chars": 3864,
    "preview": "# Locate SDL_image library\n#\n# This module defines:\n#\n# ::\n#\n#   SDL_IMAGE_LIBRARIES, the name of the library to link ag"
  },
  {
    "path": "cmake/FindSDL2_net.cmake",
    "chars": 3200,
    "preview": "# - Find SDL2_net library and headers\n# \n# Find module for SDL_net 2.0 (http://www.libsdl.org/projects/SDL_net/).\n# It d"
  },
  {
    "path": "cmake/FindSDL2_ttf.cmake",
    "chars": 3728,
    "preview": "# Locate SDL_image library\n#\n# This module defines:\n#\n# ::\n#\n#   SDL_TTF_LIBRARIES, the name of the library to link agai"
  },
  {
    "path": "cmake/README.md",
    "chars": 82,
    "preview": "These have been downloaded from:\n\nhttps://github.com/tcbrindle/sdl2-cmake-scripts\n"
  },
  {
    "path": "doc/.gitignore",
    "chars": 6,
    "preview": "html/\n"
  },
  {
    "path": "doc/doxygen.conf",
    "chars": 11621,
    "preview": "\n#---------------------------------------------------------------------------\n# Project related configuration options\n#-"
  },
  {
    "path": "res/emudore.rc",
    "chars": 62,
    "preview": "IDI_ICON1               ICON    DISCARDABLE     \"emudore.ico\"\n"
  },
  {
    "path": "src/c64.cpp",
    "chars": 2976,
    "preview": "/*\n * emudore, Commodore 64 emulator\n * Copyright (c) 2016, Mario Ballano <mballano@gmail.com>\n *\n * Licensed under the "
  },
  {
    "path": "src/c64.h",
    "chars": 1538,
    "preview": "/*\n * emudore, Commodore 64 emulator\n * Copyright (c) 2016, Mario Ballano <mballano@gmail.com>\n *\n * Licensed under the "
  },
  {
    "path": "src/cia1.cpp",
    "chars": 6141,
    "preview": "/*\n * emudore, Commodore 64 emulator\n * Copyright (c) 2016, Mario Ballano <mballano@gmail.com>\n *\n * Licensed under the "
  },
  {
    "path": "src/cia1.h",
    "chars": 1888,
    "preview": "/*\n * emudore, Commodore 64 emulator\n * Copyright (c) 2016, Mario Ballano <mballano@gmail.com>\n *\n * Licensed under the "
  },
  {
    "path": "src/cia2.cpp",
    "chars": 6262,
    "preview": "/*\n * emudore, Commodore 64 emulator\n * Copyright (c) 2016, Mario Ballano <mballano@gmail.com>\n *\n * Licensed under the "
  },
  {
    "path": "src/cia2.h",
    "chars": 1902,
    "preview": "/*\n * emudore, Commodore 64 emulator\n * Copyright (c) 2016, Mario Ballano <mballano@gmail.com>\n *\n * Licensed under the "
  },
  {
    "path": "src/cpu.cpp",
    "chars": 23708,
    "preview": "/*\n * emudore, Commodore 64 emulator\n * Copyright (c) 2016, Mario Ballano <mballano@gmail.com>\n *\n * Licensed under the "
  },
  {
    "path": "src/cpu.h",
    "chars": 5444,
    "preview": "/*\n * emudore, Commodore 64 emulator\n * Copyright (c) 2016, Mario Ballano <mballano@gmail.com>\n *\n * Licensed under the "
  },
  {
    "path": "src/debugger.cpp",
    "chars": 6140,
    "preview": "/*\n * emudore, Commodore 64 emulator\n * Copyright (c) 2016, Mario Ballano <mballano@gmail.com>\n *\n * Licensed under the "
  },
  {
    "path": "src/debugger.h",
    "chars": 1689,
    "preview": "/*\n * emudore, Commodore 64 emulator\n * Copyright (c) 2016, Mario Ballano <mballano@gmail.com>\n *\n * Licensed under the "
  },
  {
    "path": "src/io.cpp",
    "chars": 12648,
    "preview": "/*\n * emudore, Commodore 64 emulator\n * Copyright (c) 2016, Mario Ballano <mballano@gmail.com>\n *\n * Licensed under the "
  },
  {
    "path": "src/io.h",
    "chars": 2599,
    "preview": "/*\n * emudore, Commodore 64 emulator\n * Copyright (c) 2016, Mario Ballano <mballano@gmail.com>\n *\n * Licensed under the "
  },
  {
    "path": "src/loader.cpp",
    "chars": 2641,
    "preview": "/*\n * emudore, Commodore 64 emulator\n * Copyright (c) 2016, Mario Ballano <mballano@gmail.com>\n *\n * Licensed under the "
  },
  {
    "path": "src/loader.h",
    "chars": 1480,
    "preview": "/*\n * emudore, Commodore 64 emulator\n * Copyright (c) 2016, Mario Ballano <mballano@gmail.com>\n *\n * Licensed under the "
  },
  {
    "path": "src/main.cpp",
    "chars": 2172,
    "preview": "/*\n * emudore, Commodore 64 emulator\n * Copyright (c) 2016, Mario Ballano <mballano@gmail.com>\n *\n * Licensed under the "
  },
  {
    "path": "src/memory.cpp",
    "chars": 7457,
    "preview": "/*\n * emudore, Commodore 64 emulator\n * Copyright (c) 2016, Mario Ballano <mballano@gmail.com>\n *\n * Licensed under the "
  },
  {
    "path": "src/memory.h",
    "chars": 4480,
    "preview": "/*\n * emudore, Commodore 64 emulator\n * Copyright (c) 2016, Mario Ballano <mballano@gmail.com>\n *\n * Licensed under the "
  },
  {
    "path": "src/sid.h",
    "chars": 857,
    "preview": "/*\n * emudore, Commodore 64 emulator\n * Copyright (c) 2016, Mario Ballano <mballano@gmail.com>\n *\n * Licensed under the "
  },
  {
    "path": "src/util.h",
    "chars": 1465,
    "preview": "/*\n * emudore, Commodore 64 emulator\n * Copyright (c) 2016, Mario Ballano <mballano@gmail.com>\n *\n * Licensed under the "
  },
  {
    "path": "src/vic.cpp",
    "chars": 19167,
    "preview": "/*\n * emudore, Commodore 64 emulator\n * Copyright (c) 2016, Mario Ballano <mballano@gmail.com>\n *\n * Licensed under the "
  },
  {
    "path": "src/vic.h",
    "chars": 4750,
    "preview": "/*\n * emudore, Commodore 64 emulator\n * Copyright (c) 2016, Mario Ballano <mballano@gmail.com>\n *\n * Licensed under the "
  }
]

// ... and 1 more files (download for full content)

About this extraction

This page contains the full source code of the marioballano/emudore GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 42 files (1013.4 KB), approximately 256.8k tokens, and a symbol index with 21 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!