First Commit

Uploading Current Source To Github
This commit is contained in:
Damian Peckett 2015-04-08 17:14:01 +10:00
parent 909e1ac9e2
commit 2798ae6d16
49 changed files with 5916 additions and 1 deletions

313
6502tests/test.c Normal file
View File

@ -0,0 +1,313 @@
/*
Bunch of unit tests I wrote during the development of the emulator.
These are very nasty and not really release worthy but someone might
find them useful!
Copyright (c) 2015, Damian Peckett <damian.peckett@gmail.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
//TEST Functions
#include "test/testAdc.c"
#include "test/testAnd.c"
#include "test/testAsl.c"
#include "test/testBcc.c"
#include "test/testBcs.c"
#include "test/testBeq.c"
#include "test/testBit.c"
#include "test/testBmi.c"
#include "test/testBne.c"
#include "test/testBpl.c"
#include "test/testBrk.c"
#include "test/testBvc.c"
#include "test/testBvs.c"
#include "test/testClear.c"
#include "test/testCmp.c"
#include "test/testCpx.c"
#include "test/testCpy.c"
#include "test/testDec.c"
#include "test/testEor.c"
#include "test/testInc.c"
#include "test/testJmp.c"
#include "test/testLd.c"
#include "test/testLsr.c"
#include "test/testOra.c"
#include "test/testPha.c"
#include "test/testPhp.c"
#include "test/testPla.c"
#include "test/testPlp.c"
#include "test/testRol.c"
#include "test/testRor.c"
#include "test/testRti.c"
#include "test/testRts.c"
#include "test/testSbc.c"
#include "test/testSet.c"
#include "test/testSta.c"
#include "test/testSt.c"
#include "test/testTransfer.c"
void testAdc() {
printf("testAdcImmediate: %d\r\n", testAdcImmediate());
printf("testAdcZeropage: %d\r\n", testAdcZeropage());
printf("testAdcZeropageX: %d\r\n", testAdcZeropageX());
printf("testAdcAbsolute: %d\r\n", testAdcAbsolute());
printf("testAdcAbsoluteX: %d\r\n", testAdcAbsoluteX());
printf("testAdcAbsoluteY: %d\r\n", testAdcAbsoluteY());
printf("testAdcIndirectX: %d\r\n", testAdcIndirectX());
printf("testAdcIndirectY: %d\r\n", testAdcIndirectY());
}
void testAnd() {
printf("testAndImmediate: %d\r\n", testAndImmediate());
printf("testAndZeropage: %d\r\n", testAndZeropage());
printf("testAndZeropageX: %d\r\n", testAndZeropageX());
printf("testAndAbsolute: %d\r\n", testAndAbsolute());
printf("testAndAbsoluteX: %d\r\n", testAndAbsoluteX());
printf("testAndAbsoluteY: %d\r\n", testAndAbsoluteY());
printf("testAndIndirectX: %d\r\n", testAndIndirectX());
printf("testAndIndirectY: %d\r\n", testAndIndirectY());
}
void testAsl() {
printf("testAslImplied: %d\r\n", testAslImplied());
printf("testAslZeropage: %d\r\n", testAslZeropage());
printf("testAslZeropageX: %d\r\n", testAslZeropageX());
printf("testAslAbsolute: %d\r\n", testAslAbsolute());
printf("testAslAbsoluteX: %d\r\n", testAslAbsoluteX());
}
void testBranches() {
printf("testBccImplied: %d\r\n", testBccImplied());
printf("testBcsImplied: %d\r\n", testBcsImplied());
printf("testBeqImplied: %d\r\n", testBeqImplied());
printf("testBmiImplied: %d\r\n", testBmiImplied());
printf("testBneImplied: %d\r\n", testBneImplied());
printf("testBplImplied: %d\r\n", testBplImplied());
printf("testBvcImplied: %d\r\n", testBvcImplied());
printf("testBvsImplied: %d\r\n", testBvsImplied());
}
void testBit() {
printf("testBitZeropage: %d\r\n", testBitZeropage());
printf("testBitAbsolute: %d\r\n", testBitAbsolute());
}
void testBrk() {
printf("testBrkImplied: %d\r\n", testBrkImplied());
}
void testClear() {
printf("testClcImplied: %d\r\n", testClcImplied());
printf("testCldImplied: %d\r\n", testCldImplied());
printf("testCliImplied: %d\r\n", testCliImplied());
printf("testClvImplied: %d\r\n", testClvImplied());
}
void testCompare() {
printf("testCmpImmediate: %d\r\n", testCmpImmediate());
printf("testCmpZeropage: %d\r\n", testCmpZeropage());
printf("testCmpZeropageX: %d\r\n", testCmpZeropageX());
printf("testCmpAbsolute: %d\r\n", testCmpAbsolute());
printf("testCmpAbsoluteX: %d\r\n", testCmpAbsoluteX());
printf("testCmpAbsoluteY: %d\r\n", testCmpAbsoluteY());
printf("testCmpIndirectX: %d\r\n", testCmpIndirectX());
printf("testCmpIndirectY: %d\r\n", testCmpIndirectY());
printf("testCpxImmediate: %d\r\n", testCpxImmediate());
printf("testCpxZeropage: %d\r\n", testCpxZeropage());
printf("testCpxAbsolute: %d\r\n", testCpxAbsolute());
printf("testCpyImmediate: %d\r\n", testCpyImmediate());
printf("testCpyZeropage: %d\r\n", testCpyZeropage());
printf("testCpyAbsolute: %d\r\n", testCpyAbsolute());
}
void testDec() {
printf("testDecZeropage: %d\r\n", testDecZeropage());
printf("testDecZeropageX: %d\r\n", testDecZeropageX());
printf("testDecAbsolute: %d\r\n", testDecAbsolute());
printf("testDexImplied: %d\r\n", testDexImplied());
printf("testDeyImplied: %d\r\n", testDeyImplied());
}
void testEor() {
printf("testEorImmediate: %d\r\n", testEorImmediate());
printf("testEorZeropage: %d\r\n", testEorZeropage());
printf("testEorZeropageX: %d\r\n", testEorZeropageX());
printf("testEorAbsolute: %d\r\n", testEorAbsolute());
printf("testEorAbsoluteX: %d\r\n", testEorAbsoluteX());
printf("testEorAbsoluteY: %d\r\n", testEorAbsoluteY());
printf("testEorIndirectX: %d\r\n", testEorIndirectX());
printf("testEorIndirectY: %d\r\n", testEorIndirectY());
}
void testInc() {
printf("testIncZeropage: %d\r\n", testIncZeropage());
printf("testIncZeropageX: %d\r\n", testIncZeropageX());
printf("testIncAbsolute: %d\r\n", testIncAbsolute());
printf("testInxImplied: %d\r\n", testInxImplied());
printf("testInyImplied: %d\r\n", testInyImplied());
}
void testJmp() {
printf("testJmpAbsolute: %d\r\n", testJmpAbsolute());
printf("testJmpIndirect: %d\r\n", testJmpIndirect());
printf("testJsrAbsolute: %d\r\n", testJsrAbsolute());
}
void testLoads() {
printf("testLdaImmediate: %d\r\n", testLdaImmediate());
printf("testLdaZeropage: %d\r\n", testLdaZeropage());
printf("testLdaZeropageX: %d\r\n", testLdaZeropageX());
printf("testLdaAbsolute: %d\r\n", testLdaAbsolute());
printf("testLdaAbsoluteX: %d\r\n", testLdaAbsoluteX());
printf("testLdaAbsoluteY: %d\r\n", testLdaAbsoluteY());
printf("testLdaIndirectX: %d\r\n", testJmpAbsolute());
printf("testLdaIndirectY: %d\r\n", testLdaIndirectY());
printf("testLdxImmediate: %d\r\n", testLdxImmediate());
printf("testLdxZeropage: %d\r\n", testLdxZeropage());
printf("testLdxZeropageY: %d\r\n", testLdxZeropageY());
printf("testLdxAbsolute: %d\r\n", testLdxAbsolute());
printf("testLdxAbsoluteY: %d\r\n", testLdxAbsoluteY());
printf("testLdyImmediate: %d\r\n", testLdyImmediate());
printf("testLdyZeropage: %d\r\n", testLdyZeropage());
printf("testLdyZeropageX: %d\r\n", testLdyZeropageX());
printf("testLdyAbsolute: %d\r\n", testLdyAbsolute());
printf("testLdyAbsoluteX: %d\r\n", testLdyAbsoluteX());
}
void testLsr() {
printf("testLsrImplied: %d\r\n", testLsrImplied());
printf("testLsrZeropage: %d\r\n", testLsrZeropage());
printf("testLdyZeropageX: %d\r\n", testLsrZeropageX());
printf("testLsrAbsolute: %d\r\n", testLsrAbsolute());
printf("testLsrAbsoluteX: %d\r\n", testLsrAbsoluteX());
}
void testOra() {
printf("testOraImmediate: %d\r\n", testOraImmediate());
printf("testOraZeropage: %d\r\n", testOraZeropage());
printf("testOraZeropageX: %d\r\n", testOraZeropageX());
printf("testOraAbsolute: %d\r\n", testOraAbsolute());
printf("testOraAbsoluteX: %d\r\n", testOraAbsoluteX());
printf("testOraAbsoluteY: %d\r\n", testOraAbsoluteY());
printf("testOraIndirectX: %d\r\n", testOraIndirectX());
printf("testOraIndirectY: %d\r\n", testOraIndirectY());
}
void testStack() {
printf("testPhaImplied: %d\r\n", testPhaImplied());
printf("testPhpImplied: %d\r\n", testPhpImplied());
printf("testPlaImplied: %d\r\n", testPlaImplied());
printf("testPlpImplied: %d\r\n", testPlpImplied());
}
void testRotate() {
printf("testRolImplied: %d\r\n", testRolImplied());
printf("testRolZeropage: %d\r\n", testRolZeropage());
printf("testRolZeropageX: %d\r\n", testRolZeropageX());
printf("testRolAbsolute: %d\r\n", testRolAbsolute());
printf("testRolAbsoluteX: %d\r\n", testRolAbsoluteX());
printf("testRorImplied: %d\r\n", testRorImplied());
printf("testRorZeropage: %d\r\n", testRorZeropage());
printf("testRorZeropageX: %d\r\n", testRorZeropageX());
printf("testRorAbsolute: %d\r\n", testRorAbsolute());
printf("testRorAbsoluteX: %d\r\n", testRorAbsoluteX());
}
void testReturn() {
printf("testRtiImplied: %d\r\n", testRtiImplied());
printf("testRtsImplied: %d\r\n", testRtsImplied());
}
void testSbc() {
printf("testSbcImmediate: %d\r\n", testSbcImmediate());
printf("testSbcZeropage: %d\r\n", testSbcZeropage());
printf("testSbcZeropageX: %d\r\n", testSbcZeropageX());
printf("testSbcAbsolute: %d\r\n", testSbcAbsolute());
printf("testSbcAbsoluteX: %d\r\n", testSbcAbsoluteX());
printf("testSbcAbsoluteY: %d\r\n", testSbcAbsoluteY());
printf("testSbcIndirectX: %d\r\n", testSbcIndirectX());
printf("testSbcIndirectY: %d\r\n", testSbcIndirectY());
}
void testSet() {
printf("testSecImplied: %d\r\n", testSecImplied());
printf("testSedImplied: %d\r\n", testSedImplied());
printf("testSeiImplied: %d\r\n", testSeiImplied());
}
void testSta() {
printf("testStaZeropage: %d\r\n", testStaZeropage());
printf("testStaZeropageX: %d\r\n", testStaZeropageX());
printf("testStaAbsolute: %d\r\n", testStaAbsolute());
printf("testStaAbsoluteX: %d\r\n", testStaAbsoluteX());
printf("testStaAbsoluteY: %d\r\n", testStaAbsoluteY());
printf("testStaIndirectX: %d\r\n", testStaIndirectX());
printf("testStaIndirectY: %d\r\n", testStaIndirectY());
}
void testStores() {
printf("testStxZeropage: %d\r\n", testStxZeropage());
printf("testStxZeropageY: %d\r\n", testStxZeropageY());
printf("testStxAbsolute: %d\r\n", testStxAbsolute());
printf("testStyZeropage: %d\r\n", testStyZeropage());
printf("testStyZeropageX: %d\r\n", testStyZeropageX());
printf("testStyAbsolute: %d\r\n", testStyAbsolute());
}
void testTransfer() {
printf("testTaxImplied: %d\r\n", testTaxImplied());
printf("testTayImplied: %d\r\n", testTayImplied());
printf("testTsxImplied: %d\r\n", testTsxImplied());
printf("testTxaImplied: %d\r\n", testTxaImplied());
printf("testTxsImplied: %d\r\n", testTxsImplied());
printf("testTyaImplied: %d\r\n", testTyaImplied());
}
int main() {
testAnd();
testAdc();
testAsl();
testBranches();
testBit();
testBrk();
testClear();
testCompare();
testDec();
testEor();
testInc();
testJmp();
testLoads();
testLsr();
testOra();
testStack();
testRotate();
testReturn();
testSbc();
testSet();
testSta();
testStores();
testTransfer();
return 0;
}

10
6502tests/test/test.iml Normal file
View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

503
6502tests/test/testAdc.c Normal file
View File

@ -0,0 +1,503 @@
int testAdcImmediate() {
//no carry
A = 0x00;
SR&=(~SR_CARRY);
ram[0] = 0x69;
ram[1] = 0x01;
instructions = 1; run();
if(!(A == 0x01 && !SR&SR_NEG && !SR&SR_ZERO && !SR&SR_CARRY && !SR&SR_OVER)) return -1;
//with carry
A = 0x00;
SR|=SR_CARRY;
ram[0] = 0x69;
ram[1] = 0x01;
instructions = 1; run();
if(!(A == 0x02 && !(SR&SR_NEG) && !(SR&SR_ZERO) && !(SR&SR_CARRY) && !(SR&SR_OVER))) return -2;
//negative result
A = 0xFE;
SR&=(~SR_CARRY);
ram[0] = 0x69;
ram[1] = 0xFE;
instructions = 1; run();
if(!(A == 0xFC && SR&SR_NEG && !(SR&SR_ZERO) && SR&SR_CARRY && !(SR&SR_OVER))) return -3;
//overflow result
A = 0x80;
SR&=(~SR_CARRY);
ram[0] = 0x69;
ram[1] = 0xFF;
instructions = 1; run();
if(!(A == 0x7F && !(SR&SR_NEG) && !(SR&SR_ZERO) && SR&SR_CARRY && SR&SR_OVER)) return -4;
//zero result
A = 0xFF; //-1
SR&=(~SR_CARRY);
ram[0] = 0x69;
ram[1] = 0x01; //+1
instructions = 1; run();
if(!(A == 0x00 && !(SR&SR_NEG) && SR&SR_ZERO && SR&SR_CARRY && !(SR&SR_OVER))) return -5;
//carry result
A = 0xF0; //+70
SR&=(~SR_CARRY);
ram[0] = 0x69;
ram[1] = 0xF0; //+70
instructions = 1; run();
if(!(A == 0xE0 && SR&SR_NEG && !(SR&SR_ZERO) && SR&SR_CARRY && !(SR&SR_OVER))) return -6;
return 0;
}
int testAdcZeropage() {
//no carry
A = 0x00;
SR &= (~SR_CARRY);
ram[0] = 0x65;
ram[1] = 0x02;
ram[2] = 0x01;
instructions = 1; run();
if(!(A == 0x01 && !(SR&SR_NEG) && !(SR&SR_ZERO) && !(SR&SR_CARRY) && !(SR&SR_OVER))) return -1;
//with carry
A = 0x00;
SR |= SR_CARRY;
ram[0] = 0x65;
ram[1] = 0x02;
ram[2] = 0x01;
instructions = 1; run();
if(!(A == 0x02 && !(SR&SR_NEG) && !(SR&SR_ZERO) && !(SR&SR_CARRY) && !(SR&SR_OVER))) return -2;
//negative result
A = 0xFE;
SR &= (~SR_CARRY);
ram[0] = 0x65;
ram[1] = 0x02;
ram[2] = 0xFE;
instructions = 1; run();
if(!(A == 0xFC && SR&SR_NEG && !(SR&SR_ZERO) && SR&SR_CARRY && !(SR&SR_OVER))) return -3;
//overflow result
A = 0x80;
SR &= (~SR_CARRY);
ram[0] = 0x65;
ram[1] = 0x02;
ram[2] = 0xFF;
instructions = 1; run();
if(!(A == 0x7F && !(SR&SR_NEG) && !(SR&SR_ZERO) && SR&SR_CARRY && SR&SR_OVER)) return -4;
//zero result
A = 0xFF; //-1
SR &= (~SR_CARRY);
ram[0] = 0x65;
ram[1] = 0x02;
ram[2] = 0x01; //+1
instructions = 1; run();
if(!(A == 0x00 && !(SR&SR_NEG) && SR&SR_ZERO && SR&SR_CARRY && !(SR&SR_OVER))) return -5;
//carry result
A = 0xF0; //+70
SR &= (~SR_CARRY);
ram[0] = 0x65;
ram[1] = 0x02;
ram[2] = 0xF0; //+70
instructions = 1; run();
if(!(A == 0xE0 && SR&SR_NEG && !(SR&SR_ZERO) && SR&SR_CARRY && !(SR&SR_OVER))) return -6;
return 0;
}
int testAdcZeropageX() {
X = 0x01; Y=0x00;
//no carry
A = 0x00;
SR &= (~SR_CARRY);
ram[0] = 0x75;
ram[1] = 0x02;
ram[3] = 0x01;
instructions = 1; run();
if(!(A == 0x01 && !(SR&SR_NEG) && !(SR&SR_ZERO) && !(SR&SR_CARRY) && !(SR&SR_OVER))) return -1;
//with carry
A = 0x00;
SR |= SR_CARRY;
ram[0] = 0x75;
ram[1] = 0x02;
ram[3] = 0x01;
instructions = 1; run();
if(!(A == 0x02 && !(SR&SR_NEG) && !(SR&SR_ZERO) && !(SR&SR_CARRY) && !(SR&SR_OVER))) return -2;
//negative result
A = 0xFE;
SR &= (~SR_CARRY);
ram[0] = 0x75;
ram[1] = 0x02;
ram[3] = 0xFE;
instructions = 1; run();
if(!(A == 0xFC && SR&SR_NEG && !(SR&SR_ZERO) && SR&SR_CARRY && !(SR&SR_OVER))) return -3;
//overflow result
A = 0x80;
SR &= (~SR_CARRY);
ram[0] = 0x75;
ram[1] = 0x02;
ram[3] = 0xFF;
instructions = 1; run();
if(!(A == 0x7F && !(SR&SR_NEG) && !(SR&SR_ZERO) && SR&SR_CARRY && SR&SR_OVER)) return -4;
//zero result
A = 0xFF; //-1
SR &= (~SR_CARRY);
ram[0] = 0x75;
ram[1] = 0x02;
ram[3] = 0x01; //+1
instructions = 1; run();
if(!(A == 0x00 && !(SR&SR_NEG) && SR&SR_ZERO && SR&SR_CARRY && !(SR&SR_OVER))) return -5;
//carry result
A = 0xF0; //+70
SR &= (~SR_CARRY);
ram[0] = 0x75;
ram[1] = 0x02;
ram[3] = 0xF0; //+70
instructions = 1; run();
if(!(A == 0xE0 && SR&SR_NEG && !(SR&SR_ZERO) && SR&SR_CARRY && !(SR&SR_OVER))) return -6;
return 0;
}
int testAdcAbsolute() {
//no carry
A = 0x00;
SR &= (~SR_CARRY);
ram[0] = 0x6D;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0x01;
instructions = 1; run();
if(!(A == 0x01 && !(SR&SR_NEG) && !(SR&SR_ZERO) && !(SR&SR_CARRY) && !(SR&SR_OVER))) return -1;
//with carry
A = 0x00;
SR |= SR_CARRY;
ram[0] = 0x6D;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0x01;
instructions = 1; run();
if(!(A == 0x02 && !(SR&SR_NEG) && !(SR&SR_ZERO) && !(SR&SR_CARRY) && !(SR&SR_OVER))) return -2;
//negative result
A = 0xFE;
SR &= (~SR_CARRY);
ram[0] = 0x6D;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0xFE;
instructions = 1; run();
if(!(A == 0xFC && SR&SR_NEG && !(SR&SR_ZERO) && SR&SR_CARRY && !(SR&SR_OVER))) return -3;
//overflow result
A = 0x80;
SR &= (~SR_CARRY);
ram[0] = 0x6D;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0xFF;
instructions = 1; run();
if(!(A == 0x7F && !(SR&SR_NEG) && !(SR&SR_ZERO) && SR&SR_CARRY && SR&SR_OVER)) return -4;
//zero result
A = 0xFF; //-1
SR &= (~SR_CARRY);
ram[0] = 0x6D;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0x01; //+1
instructions = 1; run();
if(!(A == 0x00 && !(SR&SR_NEG) && SR&SR_ZERO && SR&SR_CARRY && !(SR&SR_OVER))) return -5;
//carry result
A = 0xF0; //+70
SR &= (~SR_CARRY);
ram[0] = 0x6D;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0xF0; //+70
instructions = 1; run();
if(!(A == 0xE0 && SR&SR_NEG && !(SR&SR_ZERO) && SR&SR_CARRY && !(SR&SR_OVER))) return -6;
return 0;
}
int testAdcAbsoluteX() {
X = 0x01; Y = 0x00;
//no carry
A = 0x00;
SR &= (~SR_CARRY);
ram[0] = 0x7D;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x01;
instructions = 1; run();
if(!(A == 0x01 && !(SR&SR_NEG) && !(SR&SR_ZERO) && !(SR&SR_CARRY) && !(SR&SR_OVER))) return -1;
//with carry
A = 0x00;
SR |= SR_CARRY;
ram[0] = 0x7D;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x01;
instructions = 1; run();
if(!(A == 0x02 && !(SR&SR_NEG) && !(SR&SR_ZERO) && !(SR&SR_CARRY) && !(SR&SR_OVER))) return -2;
//negative result
A = 0xFE;
SR &= (~SR_CARRY);
ram[0] = 0x7D;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0xFE;
instructions = 1; run();
if(!(A == 0xFC && SR&SR_NEG && !(SR&SR_ZERO) && SR&SR_CARRY && !(SR&SR_OVER))) return -3;
//overflow result
A = 0x80;
SR &= (~SR_CARRY);
ram[0] = 0x7D;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0xFF;
instructions = 1; run();
if(!(A == 0x7F && !(SR&SR_NEG) && !(SR&SR_ZERO) && SR&SR_CARRY && SR&SR_OVER)) return -4;
//zero result
A = 0xFF; //-1
SR &= (~SR_CARRY);
ram[0] = 0x7D;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x01; //+1
instructions = 1; run();
if(!(A == 0x00 && !(SR&SR_NEG) && SR&SR_ZERO && SR&SR_CARRY && !(SR&SR_OVER))) return -5;
//carry result
A = 0xF0; //+70
SR &= (~SR_CARRY);
ram[0] = 0x7D;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0xF0; //+70
instructions = 1; run();
if(!(A == 0xE0 && SR&SR_NEG && !(SR&SR_ZERO) && SR&SR_CARRY && !(SR&SR_OVER))) return -6;
return 0;
}
int testAdcAbsoluteY() {
Y = 0x01; X = 0x00;
//no carry
A = 0x00;
SR &= (~SR_CARRY);
ram[0] = 0x79;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x01;
instructions = 1; run();
if(!(A == 0x01 && !(SR&SR_NEG) && !(SR&SR_ZERO) && !(SR&SR_CARRY) && !(SR&SR_OVER))) return -1;
//with carry
A = 0x00;
SR |= SR_CARRY;
ram[0] = 0x79;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x01;
instructions = 1; run();
if(!(A == 0x02 && !(SR&SR_NEG) && !(SR&SR_ZERO) && !(SR&SR_CARRY) && !(SR&SR_OVER))) return -2;
//negative result
A = 0xFE;
SR &= (~SR_CARRY);
ram[0] = 0x79;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0xFE;
instructions = 1; run();
if(!(A == 0xFC && SR&SR_NEG && !(SR&SR_ZERO) && SR&SR_CARRY && !(SR&SR_OVER))) return -3;
//overflow result
A = 0x80;
SR &= (~SR_CARRY);
ram[0] = 0x79;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0xFF;
instructions = 1; run();
if(!(A == 0x7F && !(SR&SR_NEG) && !(SR&SR_ZERO) && SR&SR_CARRY && SR&SR_OVER)) return -4;
//zero result
A = 0xFF; //-1
SR &= (~SR_CARRY);
ram[0] = 0x79;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x01; //+1
instructions = 1; run();
if(!(A == 0x00 && !(SR&SR_NEG) && SR&SR_ZERO && SR&SR_CARRY && !(SR&SR_OVER))) return -5;
//carry result
A = 0xF0; //+70
SR &= (~SR_CARRY);
ram[0] = 0x79;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0xF0; //+70
instructions = 1; run();
if(!(A == 0xE0 && SR&SR_NEG && !(SR&SR_ZERO) && SR&SR_CARRY && !(SR&SR_OVER))) return -6;
return 0;
}
int testAdcIndirectX() {
X = 0x01; Y = 0x00;
//no carry
A = 0x00;
SR &= (~SR_CARRY);
ram[0] = 0x61;
ram[1] = 0x02;
ram[2] = 0x02;
ram[3] = 0x01;
instructions = 1; run();
if(!(A == 0x01 && !(SR&SR_NEG) && !(SR&SR_ZERO) && !(SR&SR_CARRY) && !(SR&SR_OVER))) return -1;
//with carry
A = 0x00;
SR |= SR_CARRY;
ram[0] = 0x61;
ram[1] = 0x02;
ram[2] = 0x02;
ram[3] = 0x01;
instructions = 1; run();
if(!(A == 0x02 && !(SR&SR_NEG) && !(SR&SR_ZERO) && !(SR&SR_CARRY) && !(SR&SR_OVER))) return -2;
//negative result
A = 0xFE;
SR &= (~SR_CARRY);
ram[0] = 0x61;
ram[1] = 0x02;
ram[2] = 0x02;
ram[3] = 0xFE;
instructions = 1; run();
if(!(A == 0xFC && SR&SR_NEG && !(SR&SR_ZERO) && SR&SR_CARRY && !(SR&SR_OVER))) return -3;
//overflow result
A = 0x80;
SR &= (~SR_CARRY);
ram[0] = 0x61;
ram[1] = 0x02;
ram[2] = 0x02;
ram[3] = 0xFF;
instructions = 1; run();
if(!(A == 0x7F && !(SR&SR_NEG) && !(SR&SR_ZERO) && SR&SR_CARRY && SR&SR_OVER)) return -4;
//zero result
A = 0xFF; //-1
SR &= (~SR_CARRY);
ram[0] = 0x61;
ram[1] = 0x02;
ram[2] = 0x02;
ram[3] = 0x01; //+1
instructions = 1; run();
if(!(A == 0x00 && !(SR&SR_NEG) && SR&SR_ZERO && SR&SR_CARRY && !(SR&SR_OVER))) return -5;
//carry result
A = 0xF0; //+70
SR &= (~SR_CARRY);
ram[0] = 0x61;
ram[1] = 0x02;
ram[2] = 0x02;
ram[3] = 0xF0; //+70
instructions = 1; run();
if(!(A == 0xE0 && SR&SR_NEG && !(SR&SR_ZERO) && SR&SR_CARRY && !(SR&SR_OVER))) return -6;
return 0;
}
int testAdcIndirectY() {
Y = 0x01; X = 0x00;
//no carry
A = 0x00;
SR &= (~SR_CARRY);
ram[0] = 0x71;
ram[1] = 0x02;
ram[2] = 0x03;
ram[3] = 0x00;
ram[4] = 0x01;
instructions = 1; run();
if(!(A == 0x01 && !(SR&SR_NEG) && !(SR&SR_ZERO) && !(SR&SR_CARRY) && !(SR&SR_OVER))) return -1;
//with carry
A = 0x00;
SR |= SR_CARRY;
ram[0] = 0x71;
ram[1] = 0x02;
ram[2] = 0x03;
ram[3] = 0x00;
ram[4] = 0x01;
instructions = 1; run();
if(!(A == 0x02 && !(SR&SR_NEG) && !(SR&SR_ZERO) && !(SR&SR_CARRY) && !(SR&SR_OVER))) return -2;
//negative result
A = 0xFE;
SR &= (~SR_CARRY);
ram[0] = 0x71;
ram[1] = 0x02;
ram[2] = 0x03;
ram[3] = 0x00;
ram[4] = 0xFE;
instructions = 1; run();
if(!(A == 0xFC && SR&SR_NEG && !(SR&SR_ZERO) && SR&SR_CARRY && !(SR&SR_OVER))) return -3;
//overflow result
A = 0x80;
SR &= (~SR_CARRY);
ram[0] = 0x71;
ram[1] = 0x02;
ram[2] = 0x03;
ram[3] = 0x00;
ram[4] = 0xFF;
instructions = 1; run();
if(!(A == 0x7F && !(SR&SR_NEG) && !(SR&SR_ZERO) && SR&SR_CARRY && SR&SR_OVER)) return -4;
//zero result
A = 0xFF; //-1
SR &= (~SR_CARRY);
ram[0] = 0x71;
ram[1] = 0x02;
ram[2] = 0x03;
ram[3] = 0x00;
ram[4] = 0x01;
instructions = 1; run();
if(!(A == 0x00 && !(SR&SR_NEG) && SR&SR_ZERO && SR&SR_CARRY && !(SR&SR_OVER))) return -5;
//carry result
A = 0xF0; //+70
SR &= (~SR_CARRY);
ram[0] = 0x71;
ram[1] = 0x02;
ram[2] = 0x03;
ram[3] = 0x00;
ram[4] = 0xF0;
instructions = 1; run();
if(!(A == 0xE0 && SR&SR_NEG && !(SR&SR_ZERO) && SR&SR_CARRY && !(SR&SR_OVER))) return -6;
return 0;
}

174
6502tests/test/testAnd.c Normal file
View File

@ -0,0 +1,174 @@
int testAndImmediate() {
A = 0xFF;
//all high
ram[0] = 0x29;
ram[1] = 0xFF;
instructions = 1; run();
if(!(A == 0xFF && SR&SR_NEG && !(SR&SR_ZERO) && !(SR&SR_CARRY) && !(SR&SR_OVER))) return -1;
//all low
ram[0] = 0x29;
ram[1] = 0x00;
instructions = 1; run();
if(!(A == 0x00 && !(SR&SR_NEG) && SR&SR_ZERO && !(SR&SR_CARRY) && !(SR&SR_OVER))) return -2;
return 0;
}
int testAndZeropage() {
A = 0xFF;
//all high
ram[0] = 0x25;
ram[1] = 0x02;
ram[2] = 0xFF;
instructions = 1; run();
if(!(A == 0xFF && SR&SR_NEG && !(SR&SR_ZERO) && !(SR&SR_CARRY) && !(SR&SR_OVER))) return -1;
//all low
ram[0] = 0x25;
ram[1] = 0x02;
ram[2] = 0x00;
instructions = 1; run();
if(!(A == 0x00 && !(SR&SR_NEG) && SR&SR_ZERO && !(SR&SR_CARRY) && !(SR&SR_OVER))) return -2;
return 0;
}
int testAndZeropageX() {
X = 0x01; Y = 0x00;
A = 0xFF;
//all high
ram[0] = 0x35;
ram[1] = 0x01;
ram[2] = 0xFF;
instructions = 1; run();
if(!(A == 0xFF && SR&SR_NEG && !(SR&SR_ZERO) && !(SR&SR_CARRY) && !(SR&SR_OVER))) return -1;
//all low
ram[0] = 0x35;
ram[1] = 0x01;
ram[2] = 0x00;
instructions = 1; run();
if(!(A == 0x00 && !(SR&SR_NEG) && SR&SR_ZERO && !(SR&SR_CARRY) && !(SR&SR_OVER))) return -2;
return 0;
}
int testAndAbsolute() {
A = 0xFF;
//all high
ram[0] = 0x2D;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0xFF;
instructions = 1; run();
if(!(A == 0xFF && SR&SR_NEG && !(SR&SR_ZERO) && !(SR&SR_CARRY) && !(SR&SR_OVER))) return -1;
//all low
ram[0] = 0x2D;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0x00;
instructions = 1; run();
if(!(A == 0x00 && !(SR&SR_NEG) && SR&SR_ZERO && !(SR&SR_CARRY) && !(SR&SR_OVER))) return -2;
return 0;
}
int testAndAbsoluteX() {
A = 0xFF;
X = 0x01; Y = 0x00;
//all high
ram[0] = 0x3D;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0xFF;
instructions = 1; run();
if(!(A == 0xFF && SR&SR_NEG && !(SR&SR_ZERO) && !(SR&SR_CARRY) && !(SR&SR_OVER))) return -1;
//all low
ram[0] = 0x3D;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x00;
instructions = 1; run();
if(!(A == 0x00 && !(SR&SR_NEG) && SR&SR_ZERO && !(SR&SR_CARRY) && !(SR&SR_OVER))) return -2;
return 0;
}
int testAndAbsoluteY() {
A = 0xFF;
Y = 0x01; X = 0x00;
//all high
ram[0] = 0x39;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0xFF;
instructions = 1; run();
if(!(A == 0xFF && SR&SR_NEG && !(SR&SR_ZERO) && !(SR&SR_CARRY) && !(SR&SR_OVER))) return -1;
//all low
ram[0] = 0x39;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x00;
instructions = 1; run();
if(!(A == 0x00 && !(SR&SR_NEG) && SR&SR_ZERO && !(SR&SR_CARRY) && !(SR&SR_OVER))) return -2;
return 0;
}
int testAndIndirectX() {
A = 0xFF;
X = 0x01; Y = 0x00;
//all high
ram[0] = 0x21;
ram[1] = 0x02;
ram[2] = 0x02;
ram[3] = 0xFF;
instructions = 1; run();
if(!(A == 0xFF && SR&SR_NEG && !(SR&SR_ZERO) && !(SR&SR_CARRY) && !(SR&SR_OVER))) return -1;
//all low
ram[0] = 0x21;
ram[1] = 0x02;
ram[2] = 0x02;
ram[3] = 0x00;
instructions = 1; run();
if(!(A == 0x00 && !(SR&SR_NEG) && SR&SR_ZERO && !(SR&SR_CARRY) && !(SR&SR_OVER))) return -2;
return 0;
}
int testAndIndirectY() {
A = 0xFF;
Y = 0x01; X = 0x00;
//all high
ram[0] = 0x31;
ram[1] = 0x02;
ram[2] = 0x03;
ram[3] = 0x00;
ram[4] = 0xFF;
instructions = 1; run();
if(!(A == 0xFF && SR&SR_NEG && !(SR&SR_ZERO) && !(SR&SR_CARRY) && !(SR&SR_OVER))) return -1;
//all low
ram[0] = 0x31;
ram[1] = 0x02;
ram[2] = 0x03;
ram[3] = 0x00;
ram[4] = 0x00;
instructions = 1; run();
if(!(A == 0x00 && !(SR&SR_NEG) && SR&SR_ZERO && !(SR&SR_CARRY) && !(SR&SR_OVER))) return -2;
return 0;
}

131
6502tests/test/testAsl.c Normal file
View File

@ -0,0 +1,131 @@
int testAslImplied() {
//normal
A = 0x01;
ram[0] = 0x0A;
instructions = 1; run();
if(!(A == 0x02 && !(SR&SR_NEG) && !(SR&SR_ZERO) && !(SR&SR_CARRY) && !(SR&SR_OVER))) return -1;
//carry and zero
A = 0x80;
ram[0] = 0x0A;
instructions = 1; run();
if(!(A == 0x00 && !(SR&SR_NEG) && SR&SR_ZERO && SR&SR_CARRY && !(SR&SR_OVER))) return -2;
//carry and negative
A = 0xC0;
ram[0] = 0x0A;
instructions = 1; run();
if(!(A == 0x80 && SR&SR_NEG && !(SR&SR_ZERO) && SR&SR_CARRY && !(SR&SR_OVER))) return -3;
return 0;
}
int testAslZeropage() {
//normal
ram[0] = 0x06;
ram[1] = 0x02;
ram[2] = 0x01;
instructions = 1; run();
if(!(ram[2] == 0x02 && !(SR&SR_NEG) && !(SR&SR_ZERO) && !(SR&SR_CARRY) && !(SR&SR_OVER))) return -1;
//carry and zero
ram[0] = 0x06;
ram[1] = 0x02;
ram[2] = 0x80;
instructions = 1; run();
if(!(ram[2] == 0x00 && !(SR&SR_NEG) && SR&SR_ZERO && SR&SR_CARRY && !(SR&SR_OVER))) return -2;
//carry and negative
ram[0] = 0x06;
ram[1] = 0x02;
ram[2] = 0xC0;
instructions = 1; run();
if(!(ram[2] == 0x80 && SR&SR_NEG && !(SR&SR_ZERO) && SR&SR_CARRY && !(SR&SR_OVER))) return -3;
return 0;
}
int testAslZeropageX() {
X = 0x01; Y = 0x00;
//normal
ram[0] = 0x16;
ram[1] = 0x01;
ram[2] = 0x01;
instructions = 1; run();
if(!(ram[2] == 0x02 && !(SR&SR_NEG) && !(SR&SR_ZERO) && !(SR&SR_CARRY) && !(SR&SR_OVER))) return -1;
//carry and zero
ram[0] = 0x16;
ram[1] = 0x01;
ram[2] = 0x80;
instructions = 1; run();
if(!(ram[2] == 0x00 && !(SR&SR_NEG) && SR&SR_ZERO && SR&SR_CARRY && !(SR&SR_OVER))) return -2;
//carry and negative
ram[0] = 0x16;
ram[1] = 0x01;
ram[2] = 0xC0;
instructions = 1; run();
if(!(ram[2] == 0x80 && SR&SR_NEG && !(SR&SR_ZERO) && SR&SR_CARRY && !(SR&SR_OVER))) return -3;
return 0;
}
int testAslAbsolute() {
//normal
ram[0] = 0x0E;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0x01;
instructions = 1; run();
if(!(ram[3] == 0x02 && !(SR&SR_NEG) && !(SR&SR_ZERO) && !(SR&SR_CARRY) && !(SR&SR_OVER))) return -1;
//carry and zero
ram[0] = 0x0E;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0x80;
instructions = 1; run();
if(!(ram[3] == 0x00 && !(SR&SR_NEG) && SR&SR_ZERO && SR&SR_CARRY && !(SR&SR_OVER))) return -2;
//carry and negative
ram[0] = 0x0E;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0xC0;
instructions = 1; run();
if(!(ram[3] == 0x80 && SR&SR_NEG && !(SR&SR_ZERO) && SR&SR_CARRY && !(SR&SR_OVER))) return -3;
return 0;
}
int testAslAbsoluteX() {
X = 0x01; Y = 0x00;
//normal
ram[0] = 0x1E;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x01;
instructions = 1; run();
if(!(ram[3] == 0x02 && !(SR&SR_NEG) && !(SR&SR_ZERO) && !(SR&SR_CARRY) && !(SR&SR_OVER))) return -1;
//carry and zero
ram[0] = 0x1E;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x80;
instructions = 1; run();
if(!(ram[3] == 0x00 && !(SR&SR_NEG) && SR&SR_ZERO && SR&SR_CARRY && !(SR&SR_OVER))) return -2;
//carry and negative
ram[0] = 0x1E;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0xC0;
instructions = 1; run();
if(!(ram[3] == 0x80 && SR&SR_NEG && !(SR&SR_ZERO) && SR&SR_CARRY && !(SR&SR_OVER))) return -3;
return 0;
}

23
6502tests/test/testBcc.c Normal file
View File

@ -0,0 +1,23 @@
int testBccImplied() {
SR|=SR_CARRY;
SR&=(~SR_DEC);
ram[0] = 0x90;
ram[1] = 0x01;
ram[2] = 0x00;
ram[3] = 0xF8; //SED
instructions = 4;
run();
if((SR&SR_DEC) > 0) return -1;
SR&=(~SR_CARRY);
SR&=(~SR_DEC);
ram[0] = 0x90;
ram[1] = 0x01;
ram[2] = 0x00;
ram[3] = 0xF8;
instructions = 4;
run();
if((SR&SR_DEC) == 0) return -2;
return 0;
}

23
6502tests/test/testBcs.c Normal file
View File

@ -0,0 +1,23 @@
int testBcsImplied() {
SR|=SR_CARRY;
SR&=(~SR_DEC);
ram[0] = 0xB0;
ram[1] = 0x01;
ram[2] = 0x00;
ram[3] = 0xF8; //SED
instructions = 4;
run();
if((SR&SR_DEC) == 0) return -1;
SR&=(~SR_CARRY);
SR&=(~SR_DEC);
ram[0] = 0xB0;
ram[1] = 0x01;
ram[2] = 0x00;
ram[3] = 0xF8;
instructions = 4;
run();
if((SR&SR_DEC) > 0) return -2;
return 0;
}

22
6502tests/test/testBeq.c Normal file
View File

@ -0,0 +1,22 @@
int testBeqImplied() {
SR|=SR_ZERO;
SR&=(~SR_DEC);
ram[0] = 0xF0;
ram[1] = 0x01;
ram[2] = 0x00;
ram[3] = 0xF8; //SED
instructions = 4;
run();
if((SR&SR_DEC) == 0) return -1;
SR&=(~SR_ZERO);
SR&=(~SR_DEC);
ram[0] = 0xF0;
ram[1] = 0x01;
ram[2] = 0x00;
ram[3] = 0xF8;
instructions = 4; run();
if(SR&SR_DEC) return -2;
return 0;
}

45
6502tests/test/testBit.c Normal file
View File

@ -0,0 +1,45 @@
int testBitZeropage() {
//bits set
A = 0x00;
ram[0] = 0x24;
ram[1] = 0x02;
ram[2] = 0xFF;
instructions = 2;
run();
if(!(SR&SR_NEG && SR&SR_ZERO && SR&SR_OVER)) return -1;
//bits unset
A = 0x01;
ram[0] = 0x24;
ram[1] = 0x02;
ram[2] = 0x01;
instructions = 2;
run();
if(!(!(SR&SR_NEG) && !(SR&SR_ZERO) && !(SR&SR_OVER))) return -2;
return 0;
}
int testBitAbsolute() {
//bits set
A = 0x00;
ram[0] = 0x24;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0xFF;
instructions = 2;
run();
if(!(SR&SR_NEG && SR&SR_ZERO && !(SR&SR_CARRY) && SR&SR_OVER)) return -1;
//bits unset
A = 0x01;
ram[0] = 0x24;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0x01;
instructions = 2;
run();
if(!(!(SR&SR_NEG) && !(SR&SR_ZERO) && !(SR&SR_CARRY) && !(SR&SR_OVER))) return -2;
return 0;
}

21
6502tests/test/testBmi.c Normal file
View File

@ -0,0 +1,21 @@
int testBmiImplied() {
SR |= SR_NEG;
SR &= (~SR_DEC);
ram[0] = 0x30;
ram[1] = 0x01;
ram[2] = 0x00;
ram[3] = 0xF8; //SED
instructions = 4; run();
if(!(SR&SR_DEC)) return -1;
SR &= (~SR_NEG);
SR &= (~SR_DEC);
ram[0] = 0x30;
ram[1] = 0x01;
ram[2] = 0x00;
ram[3] = 0xF8;
instructions = 4; run();
if(SR&SR_DEC) return -2;
return 0;
}

21
6502tests/test/testBne.c Normal file
View File

@ -0,0 +1,21 @@
int testBneImplied() {
SR &= (~SR_ZERO);
SR &= (~SR_DEC);
ram[0] = 0xD0;
ram[1] = 0x01;
ram[2] = 0x00;
ram[3] = 0xF8; //SED
instructions = 4; run();
if(!(SR&SR_DEC)) return -1;
SR |= SR_ZERO;
SR &= (~SR_DEC);
ram[0] = 0xD0;
ram[1] = 0x01;
ram[2] = 0x00;
ram[3] = 0xF8;
instructions = 4; run();
if(SR&SR_DEC) return -2;
return 0;
}

21
6502tests/test/testBpl.c Normal file
View File

@ -0,0 +1,21 @@
int testBplImplied() {
SR |= SR_NEG;
SR &= (~SR_DEC);
ram[0] = 0x10;
ram[1] = 0x01;
ram[2] = 0x00;
ram[3] = 0xF8; //SED
instructions = 4; run();
if(SR&SR_DEC) return -1;
SR &= (~SR_NEG);
SR &= (~SR_DEC);
ram[0] = 0x10;
ram[1] = 0x01;
ram[2] = 0x00;
ram[3] = 0xF8;
instructions = 4; run();
if(!(SR&SR_DEC)) return -2;
return 0;
}

8
6502tests/test/testBrk.c Normal file
View File

@ -0,0 +1,8 @@
int testBrkImplied() {
SR &= (~SR_INT);
SP = 0xFF;
ram[0] = 0x00;
instructions = 4; run();
if(!(SR&SR_INT) || PC != (read8(0xFFFE)|((unsigned short)read8(0xFFFF)<<8)) || SP != 0xFC) return -1;
return 0;
}

21
6502tests/test/testBvc.c Normal file
View File

@ -0,0 +1,21 @@
int testBvcImplied() {
SR |= SR_OVER;
SR &= (~SR_DEC);
ram[0] = 0x50;
ram[1] = 0x01;
ram[2] = 0x00;
ram[3] = 0xF8; //SED
instructions = 4; run();
if(SR&SR_DEC) return -1;
SR &= (~SR_OVER);
SR &= (~SR_DEC);
ram[0] = 0x50;
ram[1] = 0x01;
ram[2] = 0x00;
ram[3] = 0xF8;
instructions = 4; run();
if(!(SR&SR_DEC)) return -2;
return 0;
}

21
6502tests/test/testBvs.c Normal file
View File

@ -0,0 +1,21 @@
int testBvsImplied() {
SR |= SR_OVER;
SR &= (~SR_DEC);
ram[0] = 0x70;
ram[1] = 0x01;
ram[2] = 0x00;
ram[3] = 0xF8; //SED
instructions = 4; run();
if(!(SR&SR_DEC)) return -1;
SR &= (~SR_OVER);
SR &= (~SR_DEC);
ram[0] = 0x70;
ram[1] = 0x01;
ram[2] = 0x00;
ram[3] = 0xF8;
instructions = 4; run();
if(SR&SR_DEC) return -2;
return 0;
}

View File

@ -0,0 +1,31 @@
int testClcImplied() {
SR |= SR_CARRY;
ram[0] = 0x18;
instructions = 1; run();
if(SR&SR_CARRY) return -1;
return 0;
}
int testCldImplied() {
SR |= SR_DEC;
ram[0] = 0xD8;
instructions = 1; run();
if(SR&SR_DEC) return -1;
return 0;
}
int testCliImplied() {
SR |= SR_INT;
ram[0] = 0x58;
instructions = 1; run();
if(SR&SR_INT) return -1;
return 0;
}
int testClvImplied() {
SR |= SR_OVER;
ram[0] = 0xB8;
instructions = 1; run();
if(SR&SR_OVER) return -1;
return 0;
}

320
6502tests/test/testCmp.c Normal file
View File

@ -0,0 +1,320 @@
int testCmpImmediate() {
//no difference
SR |= SR_ZERO;
SR |= SR_CARRY;
SR |= SR_NEG;
A = 0x10;
ram[0] = 0xC9;
ram[1] = 0x10;
instructions = 2; run();
if(!(!(SR&SR_NEG) && SR&SR_ZERO && SR&SR_CARRY)) return -1;
//less
SR |= SR_ZERO;
SR |= SR_CARRY;
SR |= SR_NEG;
A = 0x10;
ram[0] = 0xC9;
ram[1] = 0x04;
instructions = 2; run();
if(!(!(SR&SR_NEG) && !(SR&SR_ZERO) && SR&SR_CARRY)) return -2;
//more
SR |= SR_ZERO;
SR |= SR_CARRY;
SR |= SR_NEG;
A = 0x04;
ram[0] = 0xC9;
ram[1] = 0x10;
instructions = 2; run();
if(!(SR&SR_NEG && !(SR&SR_ZERO) && !(SR&SR_CARRY))) return -2;
return 0;
}
int testCmpZeropage() {
//no difference
SR |= SR_ZERO;
SR |= SR_CARRY;
SR |= SR_NEG;
A = 0x10;
ram[0] = 0xC5;
ram[1] = 0x02;
ram[2] = 0x10;
instructions = 2; run();
if(!(!(SR&SR_NEG) && SR&SR_ZERO && SR&SR_CARRY)) return -1;
//less
SR |= SR_ZERO;
SR |= SR_CARRY;
SR |= SR_NEG;
A = 0x10;
ram[0] = 0xC5;
ram[1] = 0x02;
ram[2] = 0x04;
instructions = 2; run();
if(!(!(SR&SR_NEG) && !(SR&SR_ZERO) && SR&SR_CARRY)) return -2;
//more
SR |= SR_ZERO;
SR |= SR_CARRY;
SR |= SR_NEG;
A = 0x04;
ram[0] = 0xC5;
ram[1] = 0x02;
ram[2] = 0x10;
instructions = 2; run();
if(!(SR&SR_NEG && !(SR&SR_ZERO) && !(SR&SR_CARRY))) return -2;
return 0;
}
int testCmpZeropageX() {
X = 0x01; Y = 0x00;
//no difference
SR |= SR_ZERO;
SR |= SR_CARRY;
SR |= SR_NEG;
A = 0x10;
ram[0] = 0xD5;
ram[1] = 0x01;
ram[2] = 0x10;
instructions = 2; run();
if(!(!(SR&SR_NEG) && SR&SR_ZERO && SR&SR_CARRY)) return -1;
//less
SR |= SR_ZERO;
SR |= SR_CARRY;
SR |= SR_NEG;
A = 0x10;
ram[0] = 0xD5;
ram[1] = 0x01;
ram[2] = 0x04;
instructions = 2; run();
if(!(!(SR&SR_NEG) && !(SR&SR_ZERO) && SR&SR_CARRY)) return -2;
//more
SR |= SR_ZERO;
SR |= SR_CARRY;
SR |= SR_NEG;
A = 0x04;
ram[0] = 0xD5;
ram[1] = 0x01;
ram[2] = 0x10;
instructions = 2; run();
if(!(SR&SR_NEG && !(SR&SR_ZERO) && !(SR&SR_CARRY))) return -2;
return 0;
}
int testCmpAbsolute() {
//no difference
SR |= SR_ZERO;
SR |= SR_CARRY;
SR |= SR_NEG;
A = 0x10;
ram[0] = 0xCD;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0x10;
instructions = 2; run();
if(!(!(SR&SR_NEG) && SR&SR_ZERO && SR&SR_CARRY)) return -1;
//less
SR |= SR_ZERO;
SR |= SR_CARRY;
SR |= SR_NEG;
A = 0x10;
ram[0] = 0xCD;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0x04;
instructions = 2; run();
if(!(!(SR&SR_NEG) && !(SR&SR_ZERO) && SR&SR_CARRY)) return -2;
//more
SR |= SR_ZERO;
SR |= SR_CARRY;
SR |= SR_NEG;
A = 0x04;
ram[0] = 0xCD;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0x10;
instructions = 2; run();
if(!(SR&SR_NEG && !(SR&SR_ZERO) && !(SR&SR_CARRY))) return -2;
return 0;
}
int testCmpAbsoluteX() {
X = 0x01; Y = 0x00;
//no difference
SR |= SR_ZERO;
SR |= SR_CARRY;
SR |= SR_NEG;
A = 0x10;
ram[0] = 0xDD;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x10;
instructions = 2; run();
if(!(!(SR&SR_NEG) && SR&SR_ZERO && SR&SR_CARRY)) return -1;
//less
SR |= SR_ZERO;
SR |= SR_CARRY;
SR |= SR_NEG;
A = 0x10;
ram[0] = 0xDD;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x04;
instructions = 2; run();
if(!(!(SR&SR_NEG) && !(SR&SR_ZERO) && SR&SR_CARRY)) return -2;
//more
SR |= SR_ZERO;
SR |= SR_CARRY;
SR |= SR_NEG;
A = 0x04;
ram[0] = 0xDD;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x10;
instructions = 2; run();
if(!(SR&SR_NEG && !(SR&SR_ZERO) && !(SR&SR_CARRY))) return -2;
return 0;
}
int testCmpAbsoluteY() {
Y = 0x01; X = 0x00;
//no difference
SR |= SR_ZERO;
SR |= SR_CARRY;
SR |= SR_NEG;
A = 0x10;
ram[0] = 0xD9;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x10;
instructions = 2; run();
if(!(!(SR&SR_NEG) && SR&SR_ZERO && SR&SR_CARRY)) return -1;
//less
SR |= SR_ZERO;
SR |= SR_CARRY;
SR |= SR_NEG;
A = 0x10;
ram[0] = 0xD9;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x04;
instructions = 2; run();
if(!(!(SR&SR_NEG) && !(SR&SR_ZERO) && SR&SR_CARRY)) return -2;
//more
SR |= SR_ZERO;
SR |= SR_CARRY;
SR |= SR_NEG;
A = 0x04;
ram[0] = 0xD9;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x10;
instructions = 2; run();
if(!(SR&SR_NEG && !(SR&SR_ZERO) && !(SR&SR_CARRY))) return -2;
return 0;
}
int testCmpIndirectX() {
X = 0x01; Y = 0x00;
//no difference
SR |= SR_ZERO;
SR |= SR_CARRY;
SR |= SR_NEG;
A = 0x10;
ram[0] = 0xC1;
ram[1] = 0x02;
ram[2] = 0x02;
ram[3] = 0x10;
instructions = 2; run();
if(!(!(SR&SR_NEG) && SR&SR_ZERO && SR&SR_CARRY)) return -1;
//less
SR |= SR_ZERO;
SR |= SR_CARRY;
SR |= SR_NEG;
A = 0x10;
ram[0] = 0xC1;
ram[1] = 0x02;
ram[2] = 0x02;
ram[3] = 0x04;
instructions = 2; run();
if(!(!(SR&SR_NEG) && !(SR&SR_ZERO) && SR&SR_CARRY)) return -2;
//more
SR |= SR_ZERO;
SR |= SR_CARRY;
SR |= SR_NEG;
A = 0x04;
ram[0] = 0xC1;
ram[1] = 0x02;
ram[2] = 0x02;
ram[3] = 0x10;
instructions = 2; run();
if(!(SR&SR_NEG && !(SR&SR_ZERO) && !(SR&SR_CARRY))) return -2;
return 0;
}
int testCmpIndirectY() {
Y = 0x01; X = 0x00;
//no difference
SR |= SR_ZERO;
SR |= SR_CARRY;
SR |= SR_NEG;
A = 0x10;
ram[0] = 0xD1;
ram[1] = 0x02;
ram[2] = 0x03;
ram[3] = 0x00;
ram[4] = 0x10;
instructions = 2; run();
if(!(!(SR&SR_NEG) && SR&SR_ZERO && SR&SR_CARRY)) return -1;
//less
SR |= SR_ZERO;
SR |= SR_CARRY;
SR |= SR_NEG;
A = 0x10;
ram[0] = 0xD1;
ram[1] = 0x02;
ram[2] = 0x03;
ram[3] = 0x00;
ram[4] = 0x04;
instructions = 2; run();
if(!(!(SR&SR_NEG) && !(SR&SR_ZERO) && SR&SR_CARRY)) return -2;
//more
SR |= SR_ZERO;
SR |= SR_CARRY;
SR |= SR_NEG;
A = 0x04;
ram[0] = 0xD1;
ram[1] = 0x02;
ram[2] = 0x03;
ram[3] = 0x00;
ram[4] = 0x10;
instructions = 2; run();
if(!(SR&SR_NEG && !(SR&SR_ZERO) && !(SR&SR_CARRY))) return -2;
return 0;
}

110
6502tests/test/testCpx.c Normal file
View File

@ -0,0 +1,110 @@
int testCpxImmediate() {
//no difference
SR |= SR_ZERO;
SR |= SR_CARRY;
SR |= SR_NEG;
X = 0x10;
ram[0] = 0xE0;
ram[1] = 0x10;
instructions = 2; run();
if(!(!(SR&SR_NEG) && SR&SR_ZERO && SR&SR_CARRY)) return -1;
//less
SR |= SR_ZERO;
SR |= SR_CARRY;
SR |= SR_NEG;
X = 0x10;
ram[0] = 0xE0;
ram[1] = 0x04;
instructions = 2; run();
if(!(!(SR&SR_NEG) && !(SR&SR_ZERO) && SR&SR_CARRY)) return -2;
//more
SR |= SR_ZERO;
SR |= SR_CARRY;
SR |= SR_NEG;
X = 0x04;
ram[0] = 0xE0;
ram[1] = 0x10;
instructions = 2; run();
if(!(SR&SR_NEG && !(SR&SR_ZERO) && !(SR&SR_CARRY))) return -2;
return 0;
}
int testCpxZeropage() {
//no difference
SR |= SR_ZERO;
SR |= SR_CARRY;
SR |= SR_NEG;
X = 0x10;
ram[0] = 0xE4;
ram[1] = 0x02;
ram[2] = 0x10;
instructions = 2; run();
if(!(!(SR&SR_NEG) && SR&SR_ZERO && SR&SR_CARRY)) return -1;
//less
SR |= SR_ZERO;
SR |= SR_CARRY;
SR |= SR_NEG;
X = 0x10;
ram[0] = 0xE4;
ram[1] = 0x02;
ram[2] = 0x04;
instructions = 2; run();
if(!(!(SR&SR_NEG) && !(SR&SR_ZERO) && SR&SR_CARRY)) return -2;
//more
SR |= SR_ZERO;
SR |= SR_CARRY;
SR |= SR_NEG;
X = 0x04;
ram[0] = 0xE4;
ram[1] = 0x02;
ram[2] = 0x10;
instructions = 2; run();
if(!(SR&SR_NEG && !(SR&SR_ZERO) && !(SR&SR_CARRY))) return -2;
return 0;
}
int testCpxAbsolute() {
//no difference
SR |= SR_ZERO;
SR |= SR_CARRY;
SR |= SR_NEG;
X = 0x10;
ram[0] = 0xEC;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0x10;
instructions = 2; run();
if(!(!(SR&SR_NEG) && SR&SR_ZERO && SR&SR_CARRY)) return -1;
//less
SR |= SR_ZERO;
SR |= SR_CARRY;
SR |= SR_NEG;
X = 0x10;
ram[0] = 0xEC;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0x04;
instructions = 2; run();
if(!(!(SR&SR_NEG) && !(SR&SR_ZERO) && SR&SR_CARRY)) return -2;
//more
SR |= SR_ZERO;
SR |= SR_CARRY;
SR |= SR_NEG;
X = 0x04;
ram[0] = 0xEC;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0x10;
instructions = 2; run();
if(!(SR&SR_NEG && !(SR&SR_ZERO) && !(SR&SR_CARRY))) return -2;
return 0;
}

110
6502tests/test/testCpy.c Normal file
View File

@ -0,0 +1,110 @@
int testCpyImmediate() {
//no difference
SR |= SR_ZERO;
SR |= SR_CARRY;
SR |= SR_NEG;
Y = 0x10;
ram[0] = 0xC0;
ram[1] = 0x10;
instructions = 2; run();
if(!(!(SR&SR_NEG) && SR&SR_ZERO && SR&SR_CARRY)) return -1;
//less
SR |= SR_ZERO;
SR |= SR_CARRY;
SR |= SR_NEG;
Y = 0x10;
ram[0] = 0xC0;
ram[1] = 0x04;
instructions = 2; run();
if(!(!(SR&SR_NEG) && !(SR&SR_ZERO) && SR&SR_CARRY)) return -2;
//more
SR |= SR_ZERO;
SR |= SR_CARRY;
SR |= SR_NEG;
Y = 0x04;
ram[0] = 0xC0;
ram[1] = 0x10;
instructions = 2; run();
if(!(SR&SR_NEG && !(SR&SR_ZERO) && !(SR&SR_CARRY))) return -3;
return 0;
}
int testCpyZeropage() {
//no difference
SR |= SR_ZERO;
SR |= SR_CARRY;
SR |= SR_NEG;
Y = 0x10;
ram[0] = 0xC4;
ram[1] = 0x02;
ram[2] = 0x10;
instructions = 2; run();
if(!(!(SR&SR_NEG) && SR&SR_ZERO && SR&SR_CARRY)) return -1;
//less
SR |= SR_ZERO;
SR |= SR_CARRY;
SR |= SR_NEG;
Y = 0x10;
ram[0] = 0xC4;
ram[1] = 0x02;
ram[2] = 0x04;
instructions = 2; run();
if(!(!(SR&SR_NEG) && !(SR&SR_ZERO) && SR&SR_CARRY)) return -2;
//more
SR |= SR_ZERO;
SR |= SR_CARRY;
SR |= SR_NEG;
Y = 0x04;
ram[0] = 0xC4;
ram[1] = 0x02;
ram[2] = 0x10;
instructions = 2; run();
if(!(SR&SR_NEG && !(SR&SR_ZERO) && !(SR&SR_CARRY))) return -3;
return 0;
}
int testCpyAbsolute() {
//no difference
SR |= SR_ZERO;
SR |= SR_CARRY;
SR |= SR_NEG;
Y = 0x10;
ram[0] = 0xCC;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0x10;
instructions = 2; run();
if(!(!(SR&SR_NEG) && SR&SR_ZERO && SR&SR_CARRY)) return -1;
//less
SR |= SR_ZERO;
SR |= SR_CARRY;
SR |= SR_NEG;
Y = 0x10;
ram[0] = 0xCC;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0x04;
instructions = 2; run();
if(!(!(SR&SR_NEG) && !(SR&SR_ZERO) && SR&SR_CARRY)) return -2;
//more
SR |= SR_ZERO;
SR |= SR_CARRY;
SR |= SR_NEG;
Y = 0x04;
ram[0] = 0xCC;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0x10;
instructions = 2; run();
if(!(SR&SR_NEG && !(SR&SR_ZERO) && !(SR&SR_CARRY))) return -3;
return 0;
}

105
6502tests/test/testDec.c Normal file
View File

@ -0,0 +1,105 @@
int testDecZeropage() {
ram[0] = 0xC6;
ram[1] = 0x02;
ram[2] = 0x01;
instructions = 1; run();
if(!(ram[2] == 0x00 && !(SR&SR_NEG) && SR&SR_ZERO)) return -1;
//wrap
ram[0] = 0xC6;
ram[1] = 0x02;
ram[2] = 0x00;
instructions = 1; run();
if(!(ram[2] == 0xFF && SR&SR_NEG && !(SR&SR_ZERO))) return -2;
return 0;
}
int testDecZeropageX() {
X = 0x01; Y = 0x00;
ram[0] = 0xD6;
ram[1] = 0x01;
ram[2] = 0x01;
instructions = 1; run();
if(!(ram[2] == 0x00 && !(SR&SR_NEG) && SR&SR_ZERO)) return -1;
//wrap
ram[0] = 0xD6;
ram[1] = 0x01;
ram[2] = 0x00;
instructions = 1; run();
if(!(ram[2] == 0xFF && SR&SR_NEG && !(SR&SR_ZERO))) return -2;
return 0;
}
int testDecAbsolute() {
ram[0] = 0xCE;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0x01;
instructions = 1; run();
if(!(ram[3] == 0x00 && !(SR&SR_NEG) && SR&SR_ZERO)) return -1;
//wrap
ram[0] = 0xCE;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0x00;
instructions = 1; run();
if(!(ram[3] == 0xFF && SR&SR_NEG && !(SR&SR_ZERO))) return -2;
return 0;
}
int testDecAbsoluteX() {
X = 0x01; Y = 0x00;
ram[0] = 0xDE;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x01;
instructions = 1; run();
if(!(ram[3] == 0x00 && !(SR&SR_NEG) && SR&SR_ZERO)) return -1;
//wrap
ram[0] = 0xDE;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x00;
instructions = 1; run();
if(!(ram[3] == 0xFF && SR&SR_NEG && !(SR&SR_ZERO))) return -2;
return 0;
}
int testDexImplied() {
X = 0x01;
ram[0] = 0xCA;
instructions = 1; run();
if(!(X == 0x00 && !(SR&SR_NEG) && SR&SR_ZERO)) return -1;
//wrap
X = 0x00;
ram[0] = 0xCA;
instructions = 1; run();
if(!(X == 0xFF && SR&SR_NEG && !(SR&SR_ZERO))) return -2;
return 0;
}
int testDeyImplied() {
Y = 0x01;
ram[0] = 0x88;
instructions = 1; run();
if(!(Y == 0x00 && !(SR&SR_NEG) && SR&SR_ZERO)) return -1;
//wrap
X = 0x00;
ram[0] = 0x88;
instructions = 1; run();
if(!(Y == 0xFF && SR&SR_NEG && !(SR&SR_ZERO))) return -2;
return 0;
}

89
6502tests/test/testEor.c Normal file
View File

@ -0,0 +1,89 @@
int testEorImmediate() {
A = 0xCE;
ram[0] = 0x49;
ram[1] = 0x20;
instructions = 1; run();
if(!(A == (0xCE^0x20) && !(SR&SR_ZERO) && SR&SR_NEG)) return -1;
return 0;
}
int testEorZeropage() {
A = 0xCE;
ram[0] = 0x45;
ram[1] = 0x02;
ram[2] = 0x20;
instructions = 1; run();
if(!(A == (0xCE^0x20) && !(SR&SR_ZERO) && SR&SR_NEG)) return -1;
return 0;
}
int testEorZeropageX() {
X = 0x01; Y = 0x00;
A = 0xCE;
ram[0] = 0x55;
ram[1] = 0x01;
ram[2] = 0x20;
instructions = 1; run();
if(!(A == (0xCE^0x20) && !(SR&SR_ZERO) && SR&SR_NEG)) return -1;
return 0;
}
int testEorAbsolute() {
A = 0xCE;
ram[0] = 0x4D;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0x20;
instructions = 1; run();
if(!(A == (0xCE^0x20) && !(SR&SR_ZERO) && SR&SR_NEG)) return -1;
return 0;
}
int testEorAbsoluteX() {
X = 0x01; Y = 0x00;
A = 0xCE;
ram[0] = 0x5D;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x20;
instructions = 1; run();
if(!(A == (0xCE^0x20) && !(SR&SR_ZERO) && SR&SR_NEG)) return -1;
return 0;
}
int testEorAbsoluteY() {
Y = 0x01; X = 0x00;
A = 0xCE;
ram[0] = 0x59;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x20;
instructions = 1; run();
if(!(A == (0xCE^0x20) && !(SR&SR_ZERO) && SR&SR_NEG)) return -1;
return 0;
}
int testEorIndirectX() {
X = 0x01; Y = 0x00;
A = 0xCE;
ram[0] = 0x41;
ram[1] = 0x02;
ram[2] = 0x02;
ram[3] = 0x20;
instructions = 1; run();
if(!(A == (0xCE^0x20) && !(SR&SR_ZERO) && SR&SR_NEG)) return -1;
return 0;
}
int testEorIndirectY() {
Y = 0x01; X = 0x00;
A = 0xCE;
ram[0] = 0x51;
ram[1] = 0x02;
ram[2] = 0x03;
ram[3] = 0x00;
ram[4] = 0x20;
instructions = 1; run();
if(!(A == (0xCE^0x20) && !(SR&SR_ZERO) && SR&SR_NEG)) return -1;
return 0;
}

105
6502tests/test/testInc.c Normal file
View File

@ -0,0 +1,105 @@
int testIncZeropage() {
ram[0] = 0xE6;
ram[1] = 0x02;
ram[2] = 0xFE;
instructions = 1; run();
if(!(ram[2] == 0xFF && SR&SR_NEG && !(SR&SR_ZERO))) return -1;
//wrap
ram[0] = 0xE6;
ram[1] = 0x02;
ram[2] = 0xFF;
instructions = 1; run();
if(!(ram[2] == 0x00 && !(SR&SR_NEG) && SR&SR_ZERO)) return -2;
return 0;
}
int testIncZeropageX() {
X = 0x01; Y = 0x00;
ram[0] = 0xF6;
ram[1] = 0x01;
ram[2] = 0xFE;
instructions = 1; run();
if(!(ram[2] == 0xFF && SR&SR_NEG && !(SR&SR_ZERO))) return -1;
//wrap
ram[0] = 0xF6;
ram[1] = 0x01;
ram[2] = 0xFF;
instructions = 1; run();
if(!(ram[2] == 0x00 && !(SR&SR_NEG) && SR&SR_ZERO)) return -2;
return 0;
}
int testIncAbsolute() {
ram[0] = 0xEE;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0xFE;
instructions = 1; run();
if(!(ram[3] == 0xFF && SR&SR_NEG && !(SR&SR_ZERO))) return -1;
//wrap
ram[0] = 0xEE;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0xFF;
instructions = 1; run();
if(!(ram[3] == 0x00 && !(SR&SR_NEG) && SR&SR_ZERO)) return -2;
return 0;
}
int testIncAbsoluteX() {
X = 0x01; Y = 0x00;
ram[0] = 0xFE;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0xFE;
instructions = 1; run();
if(!(ram[3] == 0x02 && SR&SR_NEG && !(SR&SR_ZERO))) return -1;
//wrap
ram[0] = 0xFE;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0xFF;
instructions = 1; run();
if(!(ram[3] == 0x00 && !(SR&SR_NEG) && SR&SR_ZERO)) return -2;
return 0;
}
int testInxImplied() {
X = 0xFE;
ram[0] = 0xE8;
instructions = 1; run();
if(!(X == 0xFF && SR&SR_NEG && !(SR&SR_ZERO))) return -1;
//wrap
X = 0xFF;
ram[0] = 0xE8;
instructions = 1; run();
if(!(X == 0x00 && !(SR&SR_NEG) && SR&SR_ZERO)) return -2;
return 0;
}
int testInyImplied() {
Y = 0xFE;
ram[0] = 0xC8;
instructions = 1; run();
if(!(Y == 0xFF && SR&SR_NEG && !(SR&SR_ZERO))) return -1;
//wrap
Y = 0xFF;
ram[0] = 0xC8;
instructions = 1; run();
if(!(Y == 0x00 && !(SR&SR_NEG) && SR&SR_ZERO)) return -2;
return 0;
}

37
6502tests/test/testJmp.c Normal file
View File

@ -0,0 +1,37 @@
int testJmpAbsolute() {
SR &= (~SR_DEC);
ram[0] = 0x4C;
ram[1] = 0x04;
ram[2] = 0x00;
ram[3] = 0x00;
ram[4] = 0xF8;
instructions = 5; run();
if(!(SR&SR_DEC)) return -1;
return 0;
}
int testJmpIndirect() {
SR &= (~SR_DEC);
ram[0] = 0x4C;
ram[1] = 0x04;
ram[2] = 0x00;
ram[3] = 0x00;
ram[4] = 0x06;
ram[5] = 0x00;
ram[6] = 0xF8;
instructions = 7; run();
if(!(SR&SR_DEC)) return -1;
return 0;
}
int testJsrAbsolute() {
SR &= (~SR_DEC);
ram[0] = 0x20;
ram[1] = 0x04;
ram[2] = 0x00;
ram[3] = 0x00;
ram[4] = 0xF8;
instructions = 5; run();
if(!(SR&SR_DEC && pull16() == 0x0002)) return -1;
return 0;
}

546
6502tests/test/testLd.c Normal file
View File

@ -0,0 +1,546 @@
int testLdaImmediate() {
//zero
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xA9;
ram[1] = 0x00;
instructions = 1; run();
if(!(A == 0x00 && SR&SR_ZERO && !(SR&SR_NEG))) return -1;
//normal
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xA9;
ram[1] = 0x20;
instructions = 1; run();
if(!(A == 0x20 && !(SR&SR_ZERO) && !(SR&SR_NEG))) return -2;
//negative
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xA9;
ram[1] = 0x80;
instructions = 1; run();
if(!(A == 0x80 && !(SR&SR_ZERO) && SR&SR_NEG)) return -3;
return 0;
}
int testLdaZeropage() {
//zero
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xA5;
ram[1] = 0x02;
ram[2] = 0x00;
instructions = 1; run();
if(!(A == 0x00 && SR&SR_ZERO && !(SR&SR_NEG))) return -1;
//normal
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xA5;
ram[1] = 0x02;
ram[2] = 0x20;
instructions = 1; run();
if(!(A == 0x20 && !(SR&SR_ZERO) && !(SR&SR_NEG))) return -2;
//negative
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xA5;
ram[1] = 0x02;
ram[2] = 0x80;
instructions = 1; run();
if(!(A == 0x80 && !(SR&SR_ZERO) && SR&SR_NEG)) return -3;
return 0;
}
int testLdaZeropageX() {
X = 0x01; Y = 0x00;
//zero
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xB5;
ram[1] = 0x01;
ram[2] = 0x00;
instructions = 1; run();
if(!(A == 0x00 && SR&SR_ZERO && !(SR&SR_NEG))) return -1;
//normal
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xB5;
ram[1] = 0x01;
ram[2] = 0x20;
instructions = 1; run();
if(!(A == 0x20 && !(SR&SR_ZERO) && !(SR&SR_NEG))) return -2;
//negative
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xB5;
ram[1] = 0x01;
ram[2] = 0x80;
instructions = 1; run();
if(!(A == 0x80 && !(SR&SR_ZERO) && SR&SR_NEG)) return -3;
return 0;
}
int testLdaAbsolute() {
//zero
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xAD;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0x00;
instructions = 1; run();
if(!(A == 0x00 && SR&SR_ZERO && !(SR&SR_NEG))) return -1;
//normal
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xAD;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0x20;
instructions = 1; run();
if(!(A == 0x20 && !(SR&SR_ZERO) && !(SR&SR_NEG))) return -2;
//negative
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xAD;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0x80;
instructions = 1; run();
if(!(A == 0x80 && !(SR&SR_ZERO) && SR&SR_NEG)) return -3;
return 0;
}
int testLdaAbsoluteX() {
X = 0x01; Y = 0x00;
//zero
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xBD;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x00;
instructions = 1; run();
if(!(A == 0x00 && SR&SR_ZERO && !(SR&SR_NEG))) return -1;
//normal
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xBD;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x20;
instructions = 1; run();
if(!(A == 0x20 && !(SR&SR_ZERO) && !(SR&SR_NEG))) return -2;
//negative
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xBD;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x80;
instructions = 1; run();
if(!(A == 0x80 && !(SR&SR_ZERO) && SR&SR_NEG)) return -3;
return 0;
}
int testLdaAbsoluteY() {
Y = 0x01; X = 0x00;
//zero
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xB9;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x00;
instructions = 1; run();
if(!(A == 0x00 && SR&SR_ZERO && !(SR&SR_NEG))) return -1;
//normal
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xB9;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x20;
instructions = 1; run();
if(!(A == 0x20 && !(SR&SR_ZERO) && !(SR&SR_NEG))) return -2;
//negative
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xB9;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x80;
instructions = 1; run();
if(!(A == 0x80 && !(SR&SR_ZERO) && SR&SR_NEG)) return -3;
return 0;
}
int testLdaIndirectX() {
X = 0x01; Y = 0x00;
//zero
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xA1;
ram[1] = 0x02;
ram[2] = 0x02;
ram[3] = 0x00;
instructions = 1; run();
if(!(A == 0x00 && SR&SR_ZERO && !(SR&SR_NEG))) return -1;
//normal
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xA1;
ram[1] = 0x02;
ram[2] = 0x02;
ram[3] = 0x20;
instructions = 1; run();
if(!(A == 0x20 && !(SR&SR_ZERO) && !(SR&SR_NEG))) return -2;
//negative
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xA1;
ram[1] = 0x02;
ram[2] = 0x02;
ram[3] = 0x80;
instructions = 1; run();
if(!(A == 0x80 && !(SR&SR_ZERO) && SR&SR_NEG)) return -3;
return 0;
}
int testLdaIndirectY() {
Y = 0x01; X = 0x00;
//zero
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xB1;
ram[1] = 0x02;
ram[2] = 0x03;
ram[3] = 0x00;
ram[4] = 0x00;
instructions = 1; run();
if(!(A == 0x00 && SR&SR_ZERO && !(SR&SR_NEG))) return -1;
//normal
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xB1;
ram[1] = 0x02;
ram[2] = 0x03;
ram[3] = 0x00;
ram[4] = 0x20;
instructions = 1; run();
if(!(A == 0x20 && !(SR&SR_ZERO) && !(SR&SR_NEG))) return -2;
//negative
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xB1;
ram[1] = 0x02;
ram[2] = 0x03;
ram[3] = 0x00;
ram[4] = 0x80;
instructions = 1; run();
if(!(A == 0x80 && !(SR&SR_ZERO) && SR&SR_NEG)) return -3;
return 0;
}
int testLdxImmediate() {
//zero
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xA2;
ram[1] = 0x00;
instructions = 1; run();
if(!(X == 0x00 && SR&SR_ZERO && !(SR&SR_NEG))) return -1;
//normal
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xA2;
ram[1] = 0x20;
instructions = 1; run();
if(!(X == 0x20 && !(SR&SR_ZERO) && !(SR&SR_NEG))) return -2;
//negative
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xA2;
ram[1] = 0x80;
instructions = 1; run();
if(!(X == 0x80 && !(SR&SR_ZERO) && SR&SR_NEG)) return -3;
return 0;
}
int testLdxZeropage() {
//zero
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xA6;
ram[1] = 0x02;
ram[2] = 0x00;
instructions = 1; run();
if(!(X == 0x00 && SR&SR_ZERO && !(SR&SR_NEG))) return -1;
//normal
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xA6;
ram[1] = 0x02;
ram[2] = 0x20;
instructions = 1; run();
if(!(X == 0x20 && !(SR&SR_ZERO) && !(SR&SR_NEG))) return -2;
//negative
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xA6;
ram[1] = 0x02;
ram[2] = 0x80;
instructions = 1; run();
if(!(X == 0x80 && !(SR&SR_ZERO) && SR&SR_NEG)) return -3;
return 0;
}
int testLdxZeropageY() {
Y = 0x01; X = 0x00;
//zero
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xB6;
ram[1] = 0x01;
ram[2] = 0x00;
instructions = 1; run();
if(!(X == 0x00 && SR&SR_ZERO && !(SR&SR_NEG))) return -1;
//normal
Y = 0x01;
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xB6;
ram[1] = 0x01;
ram[2] = 0x20;
instructions = 1; run();
if(!(X == 0x20 && !(SR&SR_ZERO) && !(SR&SR_NEG))) return -2;
//negative
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xB6;
ram[1] = 0x01;
ram[2] = 0x80;
instructions = 1; run();
if(!(X == 0x80 && !(SR&SR_ZERO) && SR&SR_NEG)) return -3;
return 0;
}
int testLdxAbsolute() {
//zero
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xAE;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0x00;
instructions = 1; run();
if(!(X == 0x00 && SR&SR_ZERO && !(SR&SR_NEG))) return -1;
//normal
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xAE;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0x20;
instructions = 1; run();
if(!(X == 0x20 && !(SR&SR_ZERO) && !(SR&SR_NEG))) return -2;
//negative
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xAE;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0x80;
instructions = 1; run();
if(!(X == 0x80 && !(SR&SR_ZERO) && SR&SR_NEG)) return -3;
return 0;
}
int testLdxAbsoluteY() {
Y = 0x01; X = 0x00;
//zero
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xBE;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x00;
instructions = 1; run();
if(!(X == 0x00 && SR&SR_ZERO && !(SR&SR_NEG))) return -1;
//normal
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xBE;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x20;
instructions = 1; run();
if(!(X == 0x20 && !(SR&SR_ZERO) && !(SR&SR_NEG))) return -2;
//negative
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xBE;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x80;
instructions = 1; run();
if(!(X == 0x80 && !(SR&SR_ZERO) && SR&SR_NEG)) return -3;
return 0;
}
int testLdyImmediate() {
//zero
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xA0;
ram[1] = 0x00;
instructions = 1; run();
if(!(Y == 0x00 && SR&SR_ZERO && !(SR&SR_NEG))) return -1;
//normal
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xA0;
ram[1] = 0x20;
instructions = 1; run();
if(!(Y == 0x20 && !(SR&SR_ZERO) && !(SR&SR_NEG))) return -2;
//negative
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xA0;
ram[1] = 0x80;
instructions = 1; run();
if(!(Y == 0x80 && !(SR&SR_ZERO) && SR&SR_NEG)) return -3;
return 0;
}
int testLdyZeropage() {
//zero
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xA4;
ram[1] = 0x02;
ram[2] = 0x00;
instructions = 1; run();
if(!(Y == 0x00 && SR&SR_ZERO && !(SR&SR_NEG))) return -1;
//normal
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xA4;
ram[1] = 0x02;
ram[2] = 0x20;
instructions = 1; run();
if(!(Y == 0x20 && !(SR&SR_ZERO) && !(SR&SR_NEG))) return -2;
//negative
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xA4;
ram[1] = 0x02;
ram[2] = 0x80;
instructions = 1; run();
if(!(Y == 0x80 && !(SR&SR_ZERO) && SR&SR_NEG)) return -3;
return 0;
}
int testLdyZeropageX() {
X = 0x01; Y = 0x00;
//zero
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xB4;
ram[1] = 0x01;
ram[2] = 0x00;
instructions = 1; run();
if(!(Y == 0x00 && SR&SR_ZERO && !(SR&SR_NEG))) return -1;
//normal
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xB4;
ram[1] = 0x01;
ram[2] = 0x20;
instructions = 1; run();
if(!(Y == 0x20 && !(SR&SR_ZERO) && !(SR&SR_NEG))) return -2;
//negative
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xB4;
ram[1] = 0x01;
ram[2] = 0x80;
instructions = 1; run();
if(!(Y == 0x80 && !(SR&SR_ZERO) && SR&SR_NEG)) return -3;
return 0;
}
int testLdyAbsolute() {
X = 0x01;
//zero
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xAC;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0x00;
instructions = 1; run();
if(!(Y == 0x00 && SR&SR_ZERO && !(SR&SR_NEG))) return -1;
//normal
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xAC;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0x20;
instructions = 1; run();
if(!(Y == 0x20 && !(SR&SR_ZERO) && !(SR&SR_NEG))) return -2;
//negative
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xAC;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0x80;
instructions = 1; run();
if(!(Y == 0x80 && !(SR&SR_ZERO) && SR&SR_NEG)) return -3;
return 0;
}
int testLdyAbsoluteX() {
X = 0x01; Y = 0x00;
//zero
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xBC;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x00;
instructions = 1; run();
if(!(Y == 0x00 && SR&SR_ZERO && !(SR&SR_NEG))) return -1;
//normal
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xBC;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x20;
instructions = 1; run();
if(!(Y == 0x20 && !(SR&SR_ZERO) && !(SR&SR_NEG))) return -2;
//negative
SR &= ~(SR_NEG|SR_ZERO);
ram[0] = 0xBC;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x80;
instructions = 1; run();
if(!(Y == 0x80 && !(SR&SR_ZERO) && SR&SR_NEG)) return -3;
return 0;
}

103
6502tests/test/testLsr.c Normal file
View File

@ -0,0 +1,103 @@
int testLsrImplied() {
SR &= (~SR_DEC);
SR &= (~SR_NEG);
//zero
SR |= SR_CARRY;
A = 0x01;
ram[0] = 0x4A;
instructions = 1; run();
if(!(A == 0x00 && SR&SR_ZERO && SR&SR_CARRY && !(SR&SR_NEG))) return -1;
//carry out
A = 0x80;
ram[0] = 0x4A;
instructions = 1; run();
if(!(A == 0x40 && !(SR&SR_ZERO) && !(SR&SR_CARRY) && !(SR&SR_NEG))) return -2;
return 0;
}
int testLsrZeropage() {
//zero
SR |= SR_CARRY;
ram[0] = 0x46;
ram[1] = 0x02;
ram[2] = 0x01;
instructions = 1; run();
if(!(ram[2] == 0x00 && SR&SR_ZERO && SR&SR_CARRY && !(SR&SR_NEG))) return -1;
//carry out
ram[0] = 0x46;
ram[1] = 0x02;
ram[2] = 0x80;
instructions = 1; run();
if(!(ram[2] == 0x40 && !(SR&SR_ZERO) && !(SR&SR_CARRY) && !(SR&SR_NEG))) return -2;
return 0;
}
int testLsrZeropageX() {
X = 0x01; Y = 0x00;
//zero
SR |= SR_CARRY;
ram[0] = 0x56;
ram[1] = 0x01;
ram[2] = 0x01;
instructions = 1; run();
if(!(ram[2] == 0x00 && SR&SR_ZERO && SR&SR_CARRY && !(SR&SR_NEG))) return -1;
//carry out
ram[0] = 0x56;
ram[1] = 0x01;
ram[2] = 0x80;
instructions = 1; run();
if(!(ram[2] == 0x40 && !(SR&SR_ZERO) && !(SR&SR_CARRY) && !(SR&SR_NEG))) return -2;
return 0;
}
int testLsrAbsolute() {
//zero
SR |= SR_CARRY;
ram[0] = 0x4E;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0x01;
instructions = 1; run();
if(!(ram[3] == 0x00 && SR&SR_ZERO && SR&SR_CARRY && !(SR&SR_NEG))) return -1;
//carry out
ram[0] = 0x4E;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0x80;
instructions = 1; run();
if(!(ram[3] == 0x40 && !(SR&SR_ZERO) && !(SR&SR_CARRY) && !(SR&SR_NEG))) return -2;
return 0;
}
int testLsrAbsoluteX() {
X = 0x01; Y = 0x00;
//zero
SR |= SR_CARRY;
ram[0] = 0x5E;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x01;
instructions = 1; run();
if(!(ram[3] == 0x00 && SR&SR_ZERO && SR&SR_CARRY && !(SR&SR_NEG))) return -1;
//carry out
ram[0] = 0x5E;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x80;
instructions = 1; run();
if(!(ram[3] == 0x40 && !(SR&SR_ZERO) && !(SR&SR_CARRY) && !(SR&SR_NEG))) return -2;
return 0;
}

178
6502tests/test/testOra.c Normal file
View File

@ -0,0 +1,178 @@
int testOraImmediate() {
//all set
A = 0xFF;
ram[0] = 0x09;
ram[1] = 0x0F;
instructions = 1; run();
if(!(A == 0xFF && SR&SR_NEG && !(SR&SR_ZERO))) return -1;
//zero
A = 0x00;
ram[0] = 0x09;
ram[1] = 0x00;
instructions = 1; run();
if(!(A == 0x00 && !(SR&SR_NEG) && SR&SR_ZERO)) return -2;
return 0;
}
int testOraZeropage() {
//all set
A = 0xFF;
ram[0] = 0x05;
ram[1] = 0x02;
ram[2] = 0x0F;
instructions = 1; run();
if(!(A == 0xFF && SR&SR_NEG && !(SR&SR_ZERO))) return -1;
//zero
A = 0x00;
ram[0] = 0x05;
ram[1] = 0x02;
ram[2] = 0x00;
instructions = 1; run();
if(!(A == 0x00 && !(SR&SR_NEG) && SR&SR_ZERO)) return -2;
return 0;
}
int testOraZeropageX() {
X = 0x01; Y = 0x00;
//all set
A = 0xFF;
ram[0] = 0x15;
ram[1] = 0x01;
ram[2] = 0x0F;
instructions = 1; run();
if(!(A == 0xFF && SR&SR_NEG && !(SR&SR_ZERO))) return -1;
//zero
A = 0x00;
ram[0] = 0x15;
ram[1] = 0x01;
ram[2] = 0x00;
instructions = 1; run();
if(!(A == 0x00 && !(SR&SR_NEG) && SR&SR_ZERO)) return -2;
return 0;
}
int testOraAbsolute() {
//all set
A = 0xFF;
ram[0] = 0x0D;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0x0F;
instructions = 1; run();
if(!(A == 0xFF && SR&SR_NEG && !(SR&SR_ZERO))) return -1;
//zero
A = 0x00;
ram[0] = 0x0D;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0x00;
instructions = 1; run();
if(!(A == 0x00 && !(SR&SR_NEG) && SR&SR_ZERO)) return -2;
return 0;
}
int testOraAbsoluteX() {
X = 0x01; Y = 0x00;
//all set
A = 0xFF;
ram[0] = 0x1D;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x0F;
instructions = 1; run();
if(!(A == 0xFF && SR&SR_NEG && !(SR&SR_ZERO))) return -1;
//zero
A = 0x00;
ram[0] = 0x1D;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x00;
instructions = 1; run();
if(!(A == 0x00 && !(SR&SR_NEG) && SR&SR_ZERO)) return -2;
return 0;
}
int testOraAbsoluteY() {
X = 0x00; Y = 0x01;
//all set
A = 0xFF;
ram[0] = 0x19;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x0F;
instructions = 1; run();
if(!(A == 0xFF && SR&SR_NEG && !(SR&SR_ZERO))) return -1;
//zero
A = 0x00;
ram[0] = 0x19;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x00;
instructions = 1; run();
if(!(A == 0x00 && !(SR&SR_NEG) && SR&SR_ZERO)) return -2;
return 0;
}
int testOraIndirectX() {
X = 0x01; Y = 0x00;
//all set
A = 0xFF;
ram[0] = 0x01;
ram[1] = 0x02;
ram[2] = 0x02;
ram[3] = 0x0F;
instructions = 1; run();
if(!(A == 0xFF && SR&SR_NEG && !(SR&SR_ZERO))) return -1;
//zero
A = 0x00;
ram[0] = 0x01;
ram[1] = 0x02;
ram[2] = 0x02;
ram[3] = 0x00;
instructions = 1; run();
if(!(A == 0x00 && !(SR&SR_NEG) && SR&SR_ZERO)) return -2;
return 0;
}
int testOraIndirectY() {
Y = 0x01; X = 0x00;
//all set
A = 0xFF;
ram[0] = 0x11;
ram[1] = 0x02;
ram[2] = 0x03;
ram[3] = 0x00;
ram[4] = 0x0F;
instructions = 1; run();
if(!(A == 0xFF && SR&SR_NEG && !(SR&SR_ZERO))) return -1;
//zero
A = 0x00;
ram[0] = 0x11;
ram[1] = 0x02;
ram[2] = 0x02;
ram[3] = 0x00;
instructions = 1; run();
if(!(A == 0x00 && !(SR&SR_NEG) && SR&SR_ZERO)) return -2;
return 0;
}

8
6502tests/test/testPha.c Normal file
View File

@ -0,0 +1,8 @@
int testPhaImplied() {
unsigned short beginSp = SP;
A = 0x23;
ram[0] = 0x48;
instructions = 1; run();
if(!((beginSp-SP) == 1 && pull8() == 0x23)) return -1;
return 0;
}

15
6502tests/test/testPhp.c Normal file
View File

@ -0,0 +1,15 @@
int testPhpImplied() {
//random pattern
SR |= SR_NEG; SR &= (~SR_OVER); SR |= SR_DEC; SR &= (~SR_INT); SR |= SR_ZERO; SR &= (~SR_CARRY);
ram[0] = 0x08;
instructions = 1; run();
if(!(pull8() == 0xBA)) return -1;
//all set
SR = 0xFF;
ram[0] = 0x08;
instructions = 1; run();
if(!(pull8() == 0xFF)) return -2;
return 0;
}

17
6502tests/test/testPla.c Normal file
View File

@ -0,0 +1,17 @@
int testPlaImplied() {
//no flags
A = 0x00;
push8(0x23);
ram[0] = 0x68;
instructions = 1; run();
if(!(A == 0x23 && !(SR&SR_ZERO) && !(SR&SR_NEG))) return -1;
//zero flag
A = 0x23;
push8(0x00);
ram[0] = 0x68;
instructions = 1; run();
if(!(A == 0x00 && SR&SR_ZERO && !(SR&SR_NEG))) return -1;
return 0;
}

8
6502tests/test/testPlp.c Normal file
View File

@ -0,0 +1,8 @@
int testPlpImplied() {
SR = 0x20;
push8(0xBA);
ram[0] = 0x28;
instructions = 1; run();
if(!(SR&SR_NEG && !(SR&SR_OVER) && SR&SR_DEC && !(SR&SR_INT) && SR&SR_ZERO && !(SR&SR_CARRY))) return -1;
return 0;
}

105
6502tests/test/testRol.c Normal file
View File

@ -0,0 +1,105 @@
int testRolImplied() {
//rotate in
A = 0x81;
SR |= SR_CARRY;
ram[0] = 0x2A;
instructions = 1; run();
if(!(A == 0x03 && !(SR&SR_ZERO) && !(SR&SR_NEG) && SR&SR_CARRY)) return -1;
//rotate out
A = 0x80;
SR &= (~SR_CARRY);
ram[0] = 0x2A;
instructions = 1; run();
if(!(A == 0x00 && SR&SR_ZERO && !(SR&SR_NEG) && SR&SR_CARRY)) return -2;
return 0;
}
int testRolZeropage() {
//rotate in
SR |= SR_CARRY;
ram[0] = 0x26;
ram[1] = 0x02;
ram[2] = 0x81;
instructions = 1; run();
if(!(ram[2] == 0x03 && !(SR&SR_ZERO) && !(SR&SR_NEG) && SR&SR_CARRY)) return -1;
//rotate out
SR &= (~SR_CARRY);
ram[0] = 0x26;
ram[1] = 0x02;
ram[2] = 0x80;
instructions = 1; run();
if(!(ram[2] == 0x00 && SR&SR_ZERO && !(SR&SR_NEG) && SR&SR_CARRY)) return -2;
return 0;
}
int testRolZeropageX() {
X = 0x01; Y = 0x00;
//rotate in
SR |= SR_CARRY;
ram[0] = 0x36;
ram[1] = 0x01;
ram[2] = 0x81;
instructions = 1; run();
if(!(ram[2] == 0x03 && !(SR&SR_ZERO) && !(SR&SR_NEG) && SR&SR_CARRY)) return -1;
//rotate out
SR &= (~SR_CARRY);
ram[0] = 0x36;
ram[1] = 0x01;
ram[2] = 0x80;
instructions = 1; run();
if(!(ram[2] == 0x00 && SR&SR_ZERO && !(SR&SR_NEG) && SR&SR_CARRY)) return -2;
return 0;
}
int testRolAbsolute() {
//rotate in
SR |= SR_CARRY;
ram[0] = 0x2E;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0x81;
instructions = 1; run();
if(!(ram[3] == 0x03 && !(SR&SR_ZERO) && !(SR&SR_NEG) && SR&SR_CARRY)) return -1;
//rotate out
SR &= (~SR_CARRY);
ram[0] = 0x2E;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0x80;
instructions = 1; run();
if(!(ram[3] == 0x00 && SR&SR_ZERO && !(SR&SR_NEG) && SR&SR_CARRY)) return -2;
return 0;
}
int testRolAbsoluteX() {
X = 0x01; Y = 0x00;
//rotate in
SR |= SR_CARRY;
ram[0] = 0x3E;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x81;
instructions = 1; run();
if(!(ram[3] == 0x03 && !(SR&SR_ZERO) && !(SR&SR_NEG) && SR&SR_CARRY)) return -1;
//rotate out
SR &= (~SR_CARRY);
ram[0] = 0x3E;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x80;
instructions = 1; run();
if(!(ram[3] == 0x00 && SR&SR_ZERO && !(SR&SR_NEG) && SR&SR_CARRY)) return -2;
return 0;
}

105
6502tests/test/testRor.c Normal file
View File

@ -0,0 +1,105 @@
int testRorImplied() {
//rotate in
A = 0x81;
SR |= SR_CARRY;
ram[0] = 0x6A;
instructions = 1; run();
if(!(A == 0xC0 && !(SR&SR_ZERO) && SR&SR_NEG && SR&SR_CARRY)) return -1;
//rotate out
A = 0x01;
SR &= (~SR_CARRY);
ram[0] = 0x6A;
instructions = 1; run();
if(!(A == 0x00 && SR&SR_ZERO && !(SR&SR_NEG) && SR&SR_CARRY)) return -2;
return 0;
}
int testRorZeropage() {
//rotate in
SR |= SR_CARRY;
ram[0] = 0x66;
ram[1] = 0x02;
ram[2] = 0x81;
instructions = 1; run();
if(!(ram[2] == 0xC0 && !(SR&SR_ZERO) && SR&SR_NEG && SR&SR_CARRY)) return -1;
//rotate out
SR &= (~SR_CARRY);
ram[0] = 0x66;
ram[1] = 0x02;
ram[2] = 0x01;
instructions = 1; run();
if(!(ram[2] == 0x00 && SR&SR_ZERO && !(SR&SR_NEG) && SR&SR_CARRY)) return -2;
return 0;
}
int testRorZeropageX() {
X = 0x01; Y = 0x00;
//rotate in
SR |= SR_CARRY;
ram[0] = 0x76;
ram[1] = 0x01;
ram[2] = 0x81;
instructions = 1; run();
if(!(ram[2] == 0xC0 && !(SR&SR_ZERO) && SR&SR_NEG && SR&SR_CARRY)) return -1;
//rotate out
SR &= (~SR_CARRY);
ram[0] = 0x76;
ram[1] = 0x01;
ram[2] = 0x01;
instructions = 1; run();
if(!(ram[2] == 0x00 && SR&SR_ZERO && !(SR&SR_NEG) && SR&SR_CARRY)) return -2;
return 0;
}
int testRorAbsolute() {
//rotate in
SR |= SR_CARRY;
ram[0] = 0x6E;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0x81;
instructions = 1; run();
if(!(ram[3] == 0xC0 && !(SR&SR_ZERO) && SR&SR_NEG && SR&SR_CARRY)) return -1;
//rotate out
SR &= (~SR_CARRY);
ram[0] = 0x6E;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0x01;
instructions = 1; run();
if(!(ram[3] == 0x00 && SR&SR_ZERO && !(SR&SR_NEG) && SR&SR_CARRY)) return -2;
return 0;
}
int testRorAbsoluteX() {
X = 0x01; Y = 0x00;
//rotate in
SR |= SR_CARRY;
ram[0] = 0x7E;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x81;
instructions = 1; run();
if(!(ram[3] == 0xC0 && !(SR&SR_ZERO) && SR&SR_NEG && SR&SR_CARRY)) return -1;
//rotate out
SR &= (~SR_CARRY);
ram[0] = 0x7E;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x01;
instructions = 1; run();
if(!(ram[3] == 0x00 && SR&SR_ZERO && !(SR&SR_NEG) && SR&SR_CARRY)) return -2;
return 0;
}

9
6502tests/test/testRti.c Normal file
View File

@ -0,0 +1,9 @@
int testRtiImplied() {
push8(0x00); //high byte pc
push8(0x02); // low byte pc
push8(0xBA); //SR
ram[0] = 0x40;
instructions = 1; run();
if(!(SR&SR_NEG && !(SR&SR_OVER) && SR&SR_DEC && !(SR&SR_INT) && SR&SR_ZERO && !(SR&SR_CARRY) && PC == 0x02)) return -1;
return 0;
}

8
6502tests/test/testRts.c Normal file
View File

@ -0,0 +1,8 @@
int testRtsImplied() {
push8(0x00); //high byte pc
push8(0x02); // low byte pc
ram[0] = 0x60;
instructions = 1; run();
if(!(PC == 0x03)) return -1;
return 0;
}

283
6502tests/test/testSbc.c Normal file
View File

@ -0,0 +1,283 @@
int testSbcImmediate() {
SR &= (~SR_DEC);
//no overflow
SR |= SR_CARRY;
A = 0x00;
ram[0] = 0xE9;
ram[1] = 0x01;
instructions = 1; run();
if(!(A == 0xFF && SR&SR_NEG && !(SR&SR_ZERO) && !(SR&SR_CARRY) && !(SR&SR_OVER))) return -1;
//overflow
SR |= SR_CARRY;
A = 0x7F;
ram[0] = 0xE9;
ram[1] = 0xFF;
instructions = 1; run();
if(!(A == 0x80 && SR&SR_NEG && !(SR&SR_ZERO) && !(SR&SR_CARRY) && SR&SR_OVER)) return -2;
//no borrow
SR &= (~SR_CARRY);
A = 0xC0;
ram[0] = 0xE9;
ram[1] = 0x40;
instructions = 1; run();
//overflow differs from 2nd sim ...
if(!(A == 0x7F && !(SR&SR_NEG) && !(SR&SR_ZERO) && SR&SR_CARRY && SR&SR_OVER)) return -3;
return 0;
}
int testSbcZeropage() {
//no overflow
SR |= SR_CARRY;
A = 0x00;
ram[0] = 0xE5;
ram[1] = 0x02;
ram[2] = 0x01;
instructions = 1; run();
if(!(A == 0xFF && SR&SR_NEG && !(SR&SR_ZERO) && !(SR&SR_CARRY) && !(SR&SR_OVER))) return -1;
//overflow
SR |= SR_CARRY;
A = 0x7F;
ram[0] = 0xE5;
ram[1] = 0x02;
ram[2] = 0xFF;
instructions = 1; run();
if(!(A == 0x80 && SR&SR_NEG && !(SR&SR_ZERO) && !(SR&SR_CARRY) && SR&SR_OVER)) return -2;
//no borrow
SR &= (~SR_CARRY);
A = 0xC0;
ram[0] = 0xE5;
ram[1] = 0x02;
ram[2] = 0x40;
instructions = 1; run();
//overflow differs from 2nd sim ...
if(!(A == 0x7F && !(SR&SR_NEG) && !(SR&SR_ZERO) && SR&SR_CARRY && SR&SR_OVER)) return -3;
return 0;
}
int testSbcZeropageX() {
X = 0x01; Y = 0x00;
//no overflow
SR |= SR_CARRY;
A = 0x00;
ram[0] = 0xF5;
ram[1] = 0x01;
ram[2] = 0x01;
instructions = 1; run();
if(!(A == 0xFF && SR&SR_NEG && !(SR&SR_ZERO) && !(SR&SR_CARRY) && !(SR&SR_OVER))) return -1;
//overflow
SR |= SR_CARRY;
A = 0x7F;
ram[0] = 0xF5;
ram[1] = 0x01;
ram[2] = 0xFF;
instructions = 1; run();
if(!(A == 0x80 && SR&SR_NEG && !(SR&SR_ZERO) && !(SR&SR_CARRY) && SR&SR_OVER)) return -2;
//no borrow
SR &= (~SR_CARRY);
A = 0xC0;
ram[0] = 0xF5;
ram[1] = 0x01;
ram[2] = 0x40;
instructions = 1; run();
//overflow differs from 2nd sim ...
if(!(A == 0x7F && !(SR&SR_NEG) && !(SR&SR_ZERO) && SR&SR_CARRY && SR&SR_OVER)) return -3;
return 0;
}
int testSbcAbsolute() {
//no overflow
SR |= SR_CARRY;
A = 0x00;
ram[0] = 0xED;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0x01;
instructions = 1; run();
if(!(A == 0xFF && SR&SR_NEG && !(SR&SR_ZERO) && !(SR&SR_CARRY) && !(SR&SR_OVER))) return -1;
//overflow
SR |= SR_CARRY;
A = 0x7F;
ram[0] = 0xED;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0xFF;
instructions = 1; run();
if(!(A == 0x80 && SR&SR_NEG && !(SR&SR_ZERO) && !(SR&SR_CARRY) && SR&SR_OVER)) return -2;
//no borrow
SR &= (~SR_CARRY);
A = 0xC0;
ram[0] = 0xED;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0x40;
instructions = 1; run();
//overflow differs from 2nd sim ...
if(!(A == 0x7F && !(SR&SR_NEG) && !(SR&SR_ZERO) && SR&SR_CARRY && SR&SR_OVER)) return -3;
return 0;
}
int testSbcAbsoluteX() {
X = 0x01; Y = 0x00;
//no overflow
SR |= SR_CARRY;
A = 0x00;
ram[0] = 0xFD;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x01;
instructions = 1; run();
if(!(A == 0xFF && SR&SR_NEG && !(SR&SR_ZERO) && !(SR&SR_CARRY) && !(SR&SR_OVER))) return -1;
//overflow
SR |= SR_CARRY;
A = 0x7F;
ram[0] = 0xFD;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0xFF;
instructions = 1; run();
if(!(A == 0x80 && SR&SR_NEG && !(SR&SR_ZERO) && !(SR&SR_CARRY) && SR&SR_OVER)) return -2;
//no borrow
SR &= (~SR_CARRY);
A = 0xC0;
ram[0] = 0xFD;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x40;
instructions = 1; run();
//overflow differs from 2nd sim ...
if(!(A == 0x7F && !(SR&SR_NEG) && !(SR&SR_ZERO) && SR&SR_CARRY && SR&SR_OVER)) return -3;
return 0;
}
int testSbcAbsoluteY() {
Y = 0x01; X = 0x00;
//no overflow
SR |= SR_CARRY;
A = 0x00;
ram[0] = 0xF9;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x01;
instructions = 1; run();
if(!(A == 0xFF && SR&SR_NEG && !(SR&SR_ZERO) && !(SR&SR_CARRY) && !(SR&SR_OVER))) return -1;
//overflow
SR |= SR_CARRY;
A = 0x7F;
ram[0] = 0xF9;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0xFF;
instructions = 1; run();
if(!(A == 0x80 && SR&SR_NEG && !(SR&SR_ZERO) && !(SR&SR_CARRY) && SR&SR_OVER)) return -2;
//no borrow
SR &= (~SR_CARRY);
A = 0xC0;
ram[0] = 0xF9;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x40;
instructions = 1; run();
//overflow differs from 2nd sim ...
if(!(A == 0x7F && !(SR&SR_NEG) && !(SR&SR_ZERO) && SR&SR_CARRY && SR&SR_OVER)) return -3;
return 0;
}
int testSbcIndirectX() {
X = 0x01; Y = 0x00;
//no overflow
SR |= SR_CARRY;
A = 0x00;
ram[0] = 0xE1;
ram[1] = 0x02;
ram[2] = 0x02;
ram[3] = 0x01;
instructions = 1; run();
if(!(A == 0xFF && SR&SR_NEG && !(SR&SR_ZERO) && !(SR&SR_CARRY) && !(SR&SR_OVER))) return -1;
//overflow
SR |= SR_CARRY;
A = 0x7F;
ram[0] = 0xE1;
ram[1] = 0x02;
ram[2] = 0x02;
ram[3] = 0xFF;
instructions = 1; run();
if(!(A == 0x80 && SR&SR_NEG && !(SR&SR_ZERO) && !(SR&SR_CARRY) && SR&SR_OVER)) return -2;
//no borrow
SR &= (~SR_CARRY);
A = 0xC0;
ram[0] = 0xE1;
ram[1] = 0x02;
ram[2] = 0x02;
ram[3] = 0x40;
instructions = 1; run();
//overflow differs from 2nd sim ...
if(!(A == 0x7F && !(SR&SR_NEG) && !(SR&SR_ZERO) && SR&SR_CARRY && SR&SR_OVER)) return -3;
return 0;
}
int testSbcIndirectY() {
Y = 0x01; X = 0x00;
//no overflow
SR |= SR_CARRY;
A = 0x00;
ram[0] = 0xF1;
ram[1] = 0x02;
ram[2] = 0x03;
ram[3] = 0x00;
ram[4] = 0x01;
instructions = 1; run();
if(!(A == 0xFF && SR&SR_NEG && !(SR&SR_ZERO) && !(SR&SR_CARRY) && !(SR&SR_OVER))) return -1;
//overflow
SR |= SR_CARRY;
A = 0x7F;
ram[0] = 0xF1;
ram[1] = 0x02;
ram[2] = 0x03;
ram[3] = 0x00;
ram[4] = 0xFF;
instructions = 1; run();
if(!(A == 0x80 && SR&SR_NEG && !(SR&SR_ZERO) && !(SR&SR_CARRY) && SR&SR_OVER)) return -2;
//no borrow
SR &= (~SR_CARRY);
A = 0xC0;
ram[0] = 0xF1;
ram[1] = 0x02;
ram[2] = 0x03;
ram[3] = 0x00;
ram[4] = 0x40;
instructions = 1; run();
//overflow differs from 2nd sim ...
if(!(A == 0x7F && !(SR&SR_NEG) && !(SR&SR_ZERO) && SR&SR_CARRY && SR&SR_OVER)) return -3;
return 0;
}

23
6502tests/test/testSet.c Normal file
View File

@ -0,0 +1,23 @@
int testSecImplied() {
SR &= (~SR_CARRY);
ram[0] = 0x38;
instructions = 1; run();
if(!(SR&SR_CARRY)) return -1;
return 0;
}
int testSedImplied() {
SR &= (~SR_DEC);
ram[0] = 0xF8;
instructions = 1; run();
if(!(SR&SR_DEC)) return -1;
return 0;
}
int testSeiImplied() {
SR &= (~SR_INT);
ram[0] = 0x78;
instructions = 1; run();
if(!(SR&SR_INT)) return -1;
return 0;
}

63
6502tests/test/testSt.c Normal file
View File

@ -0,0 +1,63 @@
int testStxZeropage() {
X = 0x23;
ram[0] = 0x86;
ram[1] = 0x02;
ram[2] = 0x00;
instructions = 1; run();
if(ram[2] != 0x23) return -1;
return 0;
}
int testStxZeropageY() {
Y = 0x01;
X = 0x23;
ram[0] = 0x96;
ram[1] = 0x01;
ram[2] = 0x00;
instructions = 1; run();
if(ram[2] != 0x23) return -1;
return 0;
}
int testStxAbsolute() {
X = 0x23;
ram[0] = 0x8E;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0x00;
instructions = 1; run();
if(ram[3] != 0x23) return -1;
return 0;
}
int testStyZeropage() {
Y = 0x23;
ram[0] = 0x84;
ram[1] = 0x02;
ram[2] = 0x00;
instructions = 1; run();
if(ram[2] != 0x23) return -1;
return 0;
}
int testStyZeropageX() {
X = 0x01;
Y = 0x23;
ram[0] = 0x94;
ram[1] = 0x01;
ram[2] = 0x00;
instructions = 1; run();
if(ram[2] != 0x23) return -1;
return 0;
}
int testStyAbsolute() {
Y = 0x23;
ram[0] = 0x8C;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0x00;
instructions = 1; run();
if(ram[3] != 0x23) return -1;
return 0;
}

80
6502tests/test/testSta.c Normal file
View File

@ -0,0 +1,80 @@
int testStaZeropage() {
A = 0x23;
ram[0] = 0x85;
ram[1] = 0x02;
ram[2] = 0x00;
instructions = 1; run();
if(ram[2] != 0x23) return -1;
return 0;
}
int testStaZeropageX() {
X = 0x01; Y = 0x00;
A = 0x23;
ram[0] = 0x95;
ram[1] = 0x01;
ram[2] = 0x00;
instructions = 1; run();
if(ram[2] != 0x23) return -1;
return 0;
}
int testStaAbsolute() {
A = 0x23;
ram[0] = 0x8D;
ram[1] = 0x03;
ram[2] = 0x00;
ram[3] = 0x00;
instructions = 1; run();
if(ram[3] != 0x23) return -1;
return 0;
}
int testStaAbsoluteX() {
X = 0x01; Y = 0x00;
A = 0x23;
ram[0] = 0x9D;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x00;
instructions = 1; run();
if(ram[3] != 0x23) return -1;
return 0;
}
int testStaAbsoluteY() {
Y = 0x01; X = 0x00;
A = 0x23;
ram[0] = 0x99;
ram[1] = 0x02;
ram[2] = 0x00;
ram[3] = 0x00;
instructions = 1; run();
if(ram[3] != 0x23) return -1;
return 0;
}
int testStaIndirectX() {
X = 0x01; Y = 0x00;
A = 0x23;
ram[0] = 0x81;
ram[1] = 0x02;
ram[2] = 0x02;
ram[3] = 0x00;
instructions = 1; run();
if(ram[3] != 0x23) return -1;
return 0;
}
int testStaIndirectY() {
Y = 0x01; X = 0x00;
A = 0x23;
ram[0] = 0x91;
ram[1] = 0x02;
ram[2] = 0x03;
ram[3] = 0x00;
ram[4] = 0x00;
instructions = 1; run();
if(ram[4] != 0x23) return -1;
return 0;
}

View File

@ -0,0 +1,79 @@
int testTaxImplied() {
//normal
X = 0; A = 0x23;
ram[0] = 0xAA;
instructions = 1; run();
if(!(X == 0x23 && !(SR&SR_NEG) && !(SR&SR_ZERO)))return -1;
//negative
X = 0; A = 0xFE;
ram[0] = 0xAA;
instructions = 1; run();
if(!(X == 0xFE && SR&SR_NEG && !(SR&SR_ZERO)))return -2;
return 0;
}
int testTayImplied() {
//normal
Y = 0; A = 0x23;
ram[0] = 0xA8;
instructions = 1; run();
if(!(Y == 0x23 && !(SR&SR_NEG) && !(SR&SR_ZERO)))return -1;
//negative
Y = 0; A = 0xFE;
ram[0] = 0xA8;
instructions = 1; run();
if(!(Y == 0xFE && SR&SR_NEG && !(SR&SR_ZERO)))return -2;
return 0;
}
int testTsxImplied() {
//normal
X = 0; SP = 0x23;
ram[0] = 0xBA;
instructions = 1; run();
if(!(X == 0x23 && !(SR&SR_NEG) && !(SR&SR_ZERO)))return -1;
//negative
X = 0; SP = 0xFE;
ram[0] = 0xBA;
instructions = 1; run();
if(!(X == 0xFE && SR&SR_NEG && !(SR&SR_ZERO)))return -2;
return 0;
}
int testTxaImplied() {
//normal
A = 0; X = 0x23;
ram[0] = 0x8A;
instructions = 1; run();
if(!(A == 0x23 && !(SR&SR_NEG) && !(SR&SR_ZERO)))return -1;
//negative
A = 0; X = 0xFE;
ram[0] = 0x8A;
instructions = 1; run();
if(!(A == 0xFE && SR&SR_NEG && !(SR&SR_ZERO)))return -2;
return 0;
}
int testTxsImplied() {
//normal
SR = SR_FIXED_BITS;
X = 0x00; SP = 0x00;
ram[0] = 0x9A;
instructions = 1; run();
if(!(SP == 0x23 && !(SR&SR_ZERO)))return -1;
return 0;
}
int testTyaImplied() {
//normal
A = 0; Y = 0x23;
ram[0] = 0x98;
instructions = 1; run();
if(!(A == 0x23 && !(SR&SR_NEG) && !(SR&SR_ZERO)))return -1;
//negative
A = 0; Y = 0xFE;
ram[0] = 0x98;
instructions = 1; run();
if(!(A == 0xFE && SR&SR_NEG && !(SR&SR_ZERO)))return -2;
return 0;
}

42
APPLEII/APPLEII.ino Normal file
View File

@ -0,0 +1,42 @@
/*
Copyright (c) 2015, Damian Peckett <damian.peckett@gmail.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
All firmware is property of Apple Computer and is recreated here for
historical purposes only.
*/
#include <avr/pgmspace.h>
void setup() {
Serial.begin(115200);
clearScreen();
speaker_begin();
cassette_begin();
keyboard_begin();
sei();
}
void loop() {
run();
}

168
APPLEII/cassette.ino Normal file
View File

@ -0,0 +1,168 @@
// Share speaker pin for output
#define CASSETTE_READ_PIN A5
#define SPEAKER_PIN 5
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
void cassette_header(unsigned short periods) {
// Header Tone
for(int i = 0; i < periods*128; ++i) {
digitalWrite(SPEAKER_PIN, HIGH);
delayMicroseconds(650);
digitalWrite(SPEAKER_PIN, LOW);
delayMicroseconds(650);
}
// Sync pulse, one half cycle at 2500hz and then 2000hz
// 2500 hz
digitalWrite(SPEAKER_PIN, HIGH);
delayMicroseconds(200);
// 2000 hz
digitalWrite(SPEAKER_PIN, LOW);
delayMicroseconds(250);
}
void cassette_write_byte(unsigned char val) {
// Shift it out, MSB first
digitalWrite(SPEAKER_PIN, HIGH);
delayMicroseconds((val&0x80) ? 500 : 250);
digitalWrite(SPEAKER_PIN, LOW);
delayMicroseconds((val&0x80) ? 500 : 250);
//bit 6
digitalWrite(SPEAKER_PIN, HIGH);
delayMicroseconds((val&0x40) ? 500 : 250);
digitalWrite(SPEAKER_PIN, LOW);
delayMicroseconds((val&0x40) ? 500 : 250);
//bit 5
digitalWrite(SPEAKER_PIN, HIGH);
delayMicroseconds((val&0x20) ? 500 : 250);
digitalWrite(SPEAKER_PIN, LOW);
delayMicroseconds((val&0x20) ? 500 : 250);
//bit 4
digitalWrite(SPEAKER_PIN, HIGH);
delayMicroseconds((val&0x10) ? 500 : 250);
digitalWrite(SPEAKER_PIN, LOW);
delayMicroseconds((val&0x10) ? 500 : 250);
//bit 3
digitalWrite(SPEAKER_PIN, HIGH);
delayMicroseconds((val&0x08) ? 500 : 250);
digitalWrite(SPEAKER_PIN, LOW);
delayMicroseconds((val&0x08) ? 500 : 250);
//bit 2
digitalWrite(SPEAKER_PIN, HIGH);
delayMicroseconds((val&0x04) ? 500 : 250);
digitalWrite(SPEAKER_PIN, LOW);
delayMicroseconds((val&0x04) ? 500 : 250);
//bit 1
digitalWrite(SPEAKER_PIN, HIGH);
delayMicroseconds((val&0x02) ? 500 : 250);
digitalWrite(SPEAKER_PIN, LOW);
delayMicroseconds((val&0x02) ? 500 : 250);
//bit 0
digitalWrite(SPEAKER_PIN, HIGH);
delayMicroseconds((val&0x01) ? 500 : 250);
digitalWrite(SPEAKER_PIN, LOW);
delayMicroseconds((val&0x01) ? 500 : 250);
}
void cassette_write_block(unsigned short A1, unsigned short A2) {
unsigned char checksum = 0xFF, val = 0;
for(unsigned short addr = A1; addr <= A2; ++addr) {
val = read8(addr);
cassette_write_byte(val);
checksum ^= val;
}
cassette_write_byte(checksum);
// High idle for a little while, make sure all bits cleared
digitalWrite(SPEAKER_PIN, HIGH);
delay(10);
digitalWrite(SPEAKER_PIN, LOW);
}
// Used to track center voltage
float cassette_center_voltage = 512;
// implement zero crossing detector
boolean cassette_read_state() {
static boolean zerocross_state = false;
// get value
short adc = (analogRead(CASSETTE_READ_PIN) - (short)cassette_center_voltage);
// bias drift correction
cassette_center_voltage += adc*0.05f;
// ~7mv hysteresis
if(zerocross_state && adc < -7) zerocross_state = false;
else if(!zerocross_state && adc > 7) zerocross_state = true;
return zerocross_state;
}
// figure out the duration of zero crossing
short cassette_read_transition() {
unsigned long start_time;
static boolean last = false;
boolean cur = last;
// loop until state transition
for(start_time = micros();cur == last;) cur = cassette_read_state();
// update transition tracking
last = cur;
//return duration of transition us
return micros() - start_time;
}
// Based loosely on steve wozniaks original algorithm
boolean cassette_read_block(unsigned short A1, unsigned short A2) {
short bitperiod;
unsigned char val, checksum = 0xFF, datachecksum = 0x00;
// Calibrate the zero crossing detector
for(short i = 0; i < 10000; ++i) cassette_read_state();
// find tape in edge
cassette_read_transition();
cassette_read_transition();
// Small delay to allow things to settle
delay(500);
//wait for sync bit, short zero
while(cassette_read_transition() > 300);
// skip second cycle of sync bit
cassette_read_transition();
// start reading data
for(unsigned short addr = A1; addr <= A2; ++addr) {
// zero our byte of memory
val = 0;
for(unsigned char i = 8; i != 0; --i) {
bitperiod = (cassette_read_transition() + cassette_read_transition()) / 2;
if(bitperiod > 300) val |= _BV(i-1);
}
// write byte to memory
write8(addr, val);
// update checksum
checksum ^= val;
}
// Read checksum
for(unsigned char i = 8; i != 0; --i) {
bitperiod = (cassette_read_transition() + cassette_read_transition()) / 2;
if(bitperiod > 300) datachecksum |= _BV(i-1);
}
//return whether the data passes error checking
return (datachecksum == checksum);
}
void cassette_begin() {
// ADC prescale, 77khz
sbi(ADCSRA,ADPS2);
cbi(ADCSRA,ADPS1);
cbi(ADCSRA,ADPS0);
// internal pullup on analog pin
digitalWrite(CASSETTE_READ_PIN, HIGH);
// use 1.1v internal analog reference
analogReference(INTERNAL);
}

528
APPLEII/cpu.ino Normal file
View File

@ -0,0 +1,528 @@
// μ6502 - Barebones 6502 Emulator By Damian Peckett
// dpeckett.com, <damian.peckett@gmail.com>
// Address Modes
#define AD_IMP 0x01
#define AD_A 0x02
#define AD_ABS 0x03
#define AD_ABSX 0x04
#define AD_ABSY 0x05
#define AD_IMM 0x06
#define AD_IND 0x07
#define AD_INDX 0x08
#define AD_INDY 0x09
#define AD_REL 0x0A
#define AD_ZPG 0x0B
#define AD_ZPGX 0x0C
#define AD_ZPGY 0x0D
// SR Flag Modes
#define FL_NONE 0x00
#define FL_Z 0x20
#define FL_ZN 0xA0
#define FL_ZNC 0xB0
#define FL_ZC 0x30
#define FL_ALL 0xF0
//Unimplemented ops
#define UNDF 0x00
//Other constants
#define SR_FIXED_BITS 0x20
#define SR_CARRY 0x01
#define SR_ZERO 0x02
#define SR_INT 0x04
#define SR_DEC 0x08
#define SR_BRK 0x10
#define SR_OVER 0x40
#define SR_NEG 0x80
//Stack pointer base address
#define STP_BASE 0x100
//high nibble SR flags, low nibble address mode
const unsigned char flags[] PROGMEM = {
AD_IMP, AD_INDX, UNDF, UNDF, UNDF, FL_ZN|AD_ZPG, FL_ZNC|AD_ZPG, UNDF, AD_IMP, FL_ZN|AD_IMM, FL_ZNC|AD_A, UNDF, UNDF, FL_ZN|AD_ABS, FL_ZNC|AD_ABS, UNDF,
AD_REL, FL_ZN|AD_INDY, UNDF, UNDF, UNDF, FL_ZN|AD_ZPGX, FL_ZNC|AD_ZPGX, UNDF, AD_IMP, FL_ZN|AD_ABSY, UNDF, UNDF, UNDF, FL_ZN|AD_ABSX, FL_ZNC|AD_ABSX, UNDF,
AD_ABS, FL_ZN|AD_INDX, UNDF, UNDF, FL_Z|AD_ZPG, FL_ZN|AD_ZPG, FL_ZNC|AD_ZPG, UNDF, AD_IMP, FL_ZN|AD_IMM, FL_ZNC|AD_A, UNDF, FL_Z|AD_ABS, FL_ZN|AD_ABS, FL_ZNC|AD_ABS, UNDF,
AD_REL, FL_ZN|AD_INDY, UNDF, UNDF, UNDF, FL_ZN|AD_ZPGX, FL_ZNC|AD_ZPGX, UNDF, AD_IMP, FL_ZN|AD_ABSY, UNDF, UNDF, UNDF, FL_ZN|AD_ABSX, FL_ZNC|AD_ABSX, UNDF,
AD_IMP, FL_ZN|AD_INDX, UNDF, UNDF, UNDF, FL_ZN|AD_ZPG, FL_ZNC|AD_ZPG, UNDF, AD_IMP, FL_ZN|AD_IMM, FL_ZNC|AD_A, UNDF, AD_ABS, FL_ZN|AD_ABS, FL_ZNC|AD_ABS, UNDF,
AD_REL, FL_ZN|AD_INDY, UNDF, UNDF, UNDF, FL_ZN|AD_ZPGX, FL_ZNC|AD_ZPGX, UNDF, AD_IMP, FL_ZN|AD_ABSY, UNDF, UNDF, UNDF, FL_ZN|AD_ABSX, FL_ZNC|AD_ABSX, UNDF,
AD_IMP, FL_ALL|AD_INDX, UNDF, UNDF, UNDF, FL_ALL|AD_ZPG, FL_ZNC|AD_ZPG, UNDF, FL_ZN|AD_IMP, FL_ALL|AD_IMM, FL_ZNC|AD_A,UNDF, AD_IND, FL_ALL|AD_ABS, FL_ZNC|AD_ABS, UNDF,
AD_REL, FL_ALL|AD_INDY, UNDF, UNDF, UNDF, FL_ALL|AD_ZPGX, FL_ZNC|AD_ZPGX, UNDF, AD_IMP, FL_ALL|AD_ABSY, UNDF, UNDF, UNDF, FL_ALL|AD_ABSX, FL_ZNC|AD_ABSX, UNDF,
UNDF, AD_INDX, UNDF, UNDF, AD_ZPG, AD_ZPG, AD_ZPG, UNDF, FL_ZN|AD_IMP, UNDF, FL_ZN|AD_IMP, UNDF, AD_ABS, AD_ABS, AD_ABS, UNDF,
AD_REL, AD_INDY, UNDF, UNDF, AD_ZPGX, AD_ZPGX, AD_ZPGY, UNDF, FL_ZN|AD_IMP, AD_ABSY, AD_IMP, UNDF, UNDF, AD_ABSX, UNDF, UNDF,
FL_ZN|AD_IMM, FL_ZN|AD_INDX, FL_ZN|AD_IMM, UNDF, FL_ZN|AD_ZPG, FL_ZN|AD_ZPG, FL_ZN|AD_ZPG, UNDF, FL_ZN|AD_IMP, FL_ZN|AD_IMM, FL_ZN|AD_IMP, UNDF, FL_ZN|AD_ABS, FL_ZN|AD_ABS, FL_ZN|AD_ABS, UNDF,
AD_REL, FL_ZN|AD_INDY, UNDF, UNDF, FL_ZN|AD_ZPGX, FL_ZN|AD_ZPGX, FL_ZN|AD_ZPGY, UNDF, AD_IMP, FL_ZN|AD_ABSY, FL_ZN|AD_IMP, UNDF, FL_ZN|AD_ABSX, FL_ZN|AD_ABSX, FL_ZN|AD_ABSY, UNDF,
FL_ZNC|AD_IMM, FL_ZNC|AD_INDX, UNDF, UNDF, FL_ZNC|AD_ZPG, FL_ZNC|AD_ZPG, FL_ZN|AD_ZPG, UNDF, FL_ZN|AD_IMP, FL_ZNC|AD_IMM, FL_ZN|AD_IMP, UNDF, FL_ZNC|AD_ABS, FL_ZNC|AD_ABS, FL_ZN|AD_ABS, UNDF,
AD_REL, FL_ZNC|AD_INDY, UNDF, UNDF, UNDF, FL_ZNC|AD_ZPGX, FL_ZN|AD_ZPGX, UNDF, AD_IMP, FL_ZNC|AD_ABSY, UNDF, UNDF, UNDF, FL_ZNC|AD_ABSX, FL_ZN|AD_ABSX, UNDF,
FL_ZNC|AD_IMM, FL_ALL|AD_INDX, UNDF, UNDF, FL_ZNC|AD_ZPG, FL_ALL|AD_ZPG, FL_ZN|AD_ZPG, UNDF, FL_ZN|AD_IMP, FL_ALL|AD_IMM, AD_IMP, UNDF, FL_ZNC|AD_ABS, FL_ALL|AD_ABS, FL_ZN|AD_ABS, UNDF,
AD_REL, FL_ALL|AD_INDY, UNDF, UNDF, UNDF, FL_ALL|AD_ZPGX, FL_ZN|AD_ZPGX, UNDF, AD_IMP, FL_ALL|AD_ABSY, UNDF, UNDF, UNDF, FL_ALL|AD_ABSX, FL_ZN|AD_ABSX, UNDF
};
// CPU registers
unsigned short PC;
unsigned char STP = 0xFD, A = 0x00, X = 0x00, Y = 0x00, SR = SR_FIXED_BITS;
//Execution variables
unsigned char opcode, opflags;
unsigned short argument_addr;
//Temporary variables for flag generation
unsigned char value8;
unsigned short value16, value16_2, result;
void setflags() {
// Mask out affected flags
switch(opflags&0xF0) {
case 0xA0: SR&=0x7D; break;
case 0xB0: SR&=0x7C; break;
case 0x30: SR&=0xFC; break;
case 0xF0: SR&=0x3C; break;
case 0x20: SR&=0xFD; break;
}
// Set various status flags
if(opflags&0x80) SR |= (result&0x0080); //negative
if(opflags&0x20) SR |= (((result&0xFF) == 0)?0x02:0); //zero
if(opflags&0x10) SR |= ((result&0xFF00)?0x01:0); //carry
if(opflags&0x40) SR |= ((result^((unsigned short)A))&(result^value16)&0x0080)>>1;
}
// Stack functions
void push16(unsigned short pushval) {
write8(STP_BASE + (STP--), (pushval>>8)&0xFF);
write8(STP_BASE + (STP--), pushval&0xFF);
}
void push8(unsigned char pushval) {
write8(STP_BASE + (STP--), pushval);
}
unsigned short pull16() {
value16 = read8(STP_BASE + (++STP)) | ((unsigned short)read8(STP_BASE + (++STP))<< 8);
return value16;
}
unsigned char pull8() {
return read8(STP_BASE + (++STP));
}
void run() {
// Load the reset vector
PC = read16(0xFFFC);
STP = 0xFD;
for(;;) {
// Routines for hooking apple ][ monitor routines
program_hooks(PC);
// Get opcode / addressing mode
opcode = read8(PC++);
opflags = pgm_read_byte_near(flags+opcode);
// Addressing modes
switch(opflags&0x0F) {
case AD_IMP: case AD_A: argument_addr = 0xFFFF; break;
case AD_ABS:
argument_addr = read16(PC);
PC += 2;
break;
case AD_ABSX:
argument_addr = read16(PC) + (unsigned short)X;
PC += 2;
break;
case AD_ABSY:
argument_addr = read16(PC) + (unsigned short)Y;
PC += 2;
break;
case AD_IMM:
argument_addr = PC++;
break;
case AD_IND:
argument_addr = read16(PC);
value16 = (argument_addr&0xFF00) | ((argument_addr+1)&0x00FF); // Page wrap
argument_addr = (unsigned short)read8(argument_addr) | ((unsigned short)read8(value16) << 8);
PC+=2;
break;
case AD_INDX:
argument_addr = ((unsigned short)read8(PC++) + (unsigned short)X)&0xFF;
value16 = (argument_addr&0xFF00) | ((argument_addr+1)&0x00FF); // Page wrap
argument_addr = (unsigned short)read8(argument_addr) | ((unsigned short)read8(value16) << 8);
break;
case AD_INDY:
argument_addr = (unsigned short)read8(PC++);
value16 = (argument_addr&0xFF00) | ((argument_addr+1)&0x00FF); // Page wrap
argument_addr = (unsigned short)read8(argument_addr) | ((unsigned short)read8(value16) << 8);
argument_addr += Y;
break;
case AD_REL:
argument_addr = (unsigned short)read8(PC++);
argument_addr |= ((argument_addr&0x80)?0xFF00:0);
break;
case AD_ZPG:
argument_addr = (unsigned short)read8(PC++);
break;
case AD_ZPGX:
argument_addr = ((unsigned short)read8(PC++) + (unsigned short)X)&0xFF;
break;
case AD_ZPGY:
argument_addr = ((unsigned short)read8(PC++) + (unsigned short)Y)&0xFF;
break;
}
//opcodes
switch(opcode) {
//ADC
case 0x69: case 0x65: case 0x75:
case 0x6D: case 0x7D: case 0x79:
case 0x61: case 0x71:
value16 = (unsigned short)read8(argument_addr);
result = (unsigned short)A + value16 + (unsigned short)(SR&SR_CARRY);
setflags();
A = result&0xFF;
break;
//AND
case 0x29: case 0x25: case 0x35:
case 0x2D: case 0x3D: case 0x39:
case 0x21: case 0x31:
result = A&read8(argument_addr);
A = result&0xFF;
setflags();
break;
//ASL A
case 0x0A:
value16 = (unsigned short)A;
result = value16<<1;
setflags();
A = result&0xFF;
break;
//ASL
case 0x06: case 0x16: case 0x0E:
case 0x1E:
value16 = read8(argument_addr);
result = value16<<1;
setflags();
write8(argument_addr, result&0xFF);
break;
//BCC
case 0x90:
if(!(SR&SR_CARRY)) PC += argument_addr;
break;
//BCS
case 0xB0:
if((SR&SR_CARRY)) PC += argument_addr;
break;
//BEQ
case 0xF0:
if((SR&SR_ZERO)) PC += argument_addr;
break;
//BNE
case 0xD0:
if(!(SR&SR_ZERO)) PC += argument_addr;
break;
//BIT
case 0x24: case 0x2C:
value8 = read8(argument_addr);
result = A & value8;
setflags();
SR = (SR&0x3F) | (value8&0xC0);
break;
//BMI
case 0x30:
if((SR&SR_NEG)) PC += argument_addr;
break;
//BPL
case 0x10:
if(!(SR&SR_NEG)) PC += argument_addr;
break;
//BRK
case 0x00:
PC++;
push16(PC);
push8(SR|SR_BRK);
SR|=SR_INT;
PC = read16(0xFFFE);
break;
//BVC
case 0x50:
if(!(SR&SR_OVER)) PC += argument_addr;
break;
//BVS
case 0x70:
if(SR&SR_OVER) PC += argument_addr;
break;
//CLC
case 0x18:
SR&=0xFE;
break;
//CLD
case 0xD8:
SR&=0xF7;
break;
//CLI
case 0x58:
SR&=0xFB;
break;
//CLV
case 0xB8:
SR&=0xBF;
break;
//CMP
case 0xC9: case 0xC5: case 0xD5:
case 0xCD: case 0xDD: case 0xD9:
case 0xC1: case 0xD1:
value16 = ((unsigned short)read8(argument_addr)) ^ 0x00FF;
result = (unsigned short)A + value16 + (unsigned short)1;
setflags();
break;
//CPX
case 0xE0: case 0xE4: case 0xEC:
value16 = ((unsigned short)read8(argument_addr)) ^ 0x00FF;
result = (unsigned short)X + value16 + (unsigned short)1;
setflags();
break;
//CPY
case 0xC0: case 0xC4: case 0xCC:
value16 = ((unsigned short)read8(argument_addr)) ^ 0x00FF;
result = (unsigned short)Y + value16 + (unsigned short)1;
setflags();
break;
//DEC
case 0xC6: case 0xD6: case 0xCE:
case 0xDE:
value16 = (unsigned short)read8(argument_addr);
result = value16 - 1;
setflags();
write8(argument_addr, result&0xFF);
break;
//DEX
case 0xCA:
result = --X;
setflags();
break;
//DEY
case 0x88:
result = --Y;
setflags();
break;
//EOR
case 0x49: case 0x45: case 0x55:
case 0x4D: case 0x5D: case 0x59:
case 0x41: case 0x51:
value8 = read8(argument_addr);
result = A^value8;
setflags();
A = result&0xFF;
break;
//INC
case 0xE6: case 0xF6: case 0xEE:
case 0xFE:
value16 = (unsigned short)read8(argument_addr);
result = value16 + 1;
setflags();
write8(argument_addr, result&0xFF);
break;
//INX
case 0xE8:
result = ++X;
setflags();
break;
//INY
case 0xC8:
result = ++Y;
setflags();
break;
//JMP
case 0x4C: case 0x6C:
PC = argument_addr;
break;
//JSR
case 0x20:
push16(PC-1);
PC = argument_addr;
break;
//LDA
case 0xA9: case 0xA5: case 0xB5:
case 0xAD: case 0xBD: case 0xB9:
case 0xA1: case 0xB1:
A = read8(argument_addr);
result = A;
setflags();
break;
//LDX
case 0xA2: case 0xA6: case 0xB6:
case 0xAE: case 0xBE:
X = read8(argument_addr);
result = X;
setflags();
break;
//LDY
case 0xA0: case 0xA4: case 0xB4:
case 0xAC: case 0xBC:
Y = read8(argument_addr);
result = Y;
setflags();
break;
//LSR A
case 0x4A:
value8 = A;
result = value8 >> 1;
result |= (value8&0x1)?0x8000:0;
setflags();
A = result&0xFF;
break;
//LSR
case 0x46: case 0x56: case 0x4E:
case 0x5E:
value8 = read8(argument_addr);
result = value8 >> 1;
result |= (value8&0x1)?0x8000:0;
setflags();
write8(argument_addr, result&0xFF);
break;
//NOP
case 0xEA:
break;
//ORA
case 0x09: case 0x05: case 0x15:
case 0x0D: case 0x1D: case 0x19:
case 0x01: case 0x11:
value8 = read8(argument_addr);
result = A | value8;
setflags();
A = result&0xFF;
break;
//PHA
case 0x48:
push8(A);
break;
//PHP
case 0x08:
push8(SR|SR_BRK);
break;
//PLA
case 0x68:
result = pull8();
setflags();
A = result;
break;
//PLP
case 0x28:
SR = pull8() | SR_FIXED_BITS;
break;
//ROL A
case 0x2A:
value16 = (unsigned short)A;
result = (value16 << 1) | (SR&SR_CARRY);
setflags();
A = result&0xFF;
break;
//ROL
case 0x26: case 0x36: case 0x2E:
case 0x3E:
value16 = (unsigned short)read8(argument_addr);
result = (value16 << 1) | (SR&SR_CARRY);
setflags();
write8(argument_addr, result&0xFF);
break;
//ROR A
case 0x6A:
value16 = (unsigned short)A;
result = (value16 >> 1) | ((SR&SR_CARRY) << 7);
result |= (value16&0x1)?0x8000:0;
setflags();
A = result&0xFF;
break;
//ROR
case 0x66: case 0x76: case 0x6E:
case 0x7E:
value16 = (unsigned short)read8(argument_addr);
result = (value16 >> 1) | ((SR&SR_CARRY) << 7);
result |= (value16&0x1)?0x8000:0;
setflags();
write8(argument_addr, result&0xFF);
break;
//RTI
case 0x40:
SR = pull8();
PC = pull16();
break;
//RTS
case 0x60:
PC = pull16() + 1;
break;
//SBC
case 0xE9: case 0xE5: case 0xF5:
case 0xED: case 0xFD: case 0xF9:
case 0xE1: case 0xF1:
value16 = ((unsigned short)read8(argument_addr)) ^ 0x00FF;
result = (unsigned short)A + value16 + (unsigned short)(SR&SR_CARRY);
setflags();
A = result&0xFF;
break;
//SEC
case 0x38:
SR |= SR_CARRY;
break;
//SED
case 0xF8:
SR |= SR_DEC;
break;
//SEI
case 0x78:
SR |= SR_INT;
break;
//STA
case 0x85: case 0x95: case 0x8D:
case 0x9D: case 0x99: case 0x81:
case 0x91:
write8(argument_addr, A);
break;
//STX
case 0x86: case 0x96: case 0x8E:
write8(argument_addr, X);
break;
//STY
case 0x84: case 0x94: case 0x8C:
write8(argument_addr, Y);
break;
//TAX
case 0xAA:
X = A;
result = A;
setflags();
break;
//TAY
case 0xA8:
Y = A;
result = A;
setflags();
break;
//TSX
case 0xBA:
X = STP;
result = STP;
setflags();
break;
//TXA
case 0x8A:
A = X;
result = X;
setflags();
break;
//TXS
case 0x9A:
STP = X;
result = X;
setflags();
break;
//TYA
case 0x98:
A = Y;
result = Y;
setflags();
break;
}
}
}

29
APPLEII/ghettovga.ino Normal file
View File

@ -0,0 +1,29 @@
void writeCharacter(unsigned char row, unsigned char col, unsigned char val) {
unsigned char buf[4] = {0xFD, 0, 0, 0};
buf[1] = col;
buf[2] = row;
buf[3] = val;
Serial.write(buf, 4);
}
unsigned char readCharacter(unsigned char row, unsigned char col) {
unsigned long transaction_begin;
unsigned char buf[4] = {0xFA, 0, 0};
buf[1] = col;
buf[2] = row;
Serial.write(buf, 3);
for(transaction_begin = millis(); !Serial.available(); millis() < (transaction_begin+50));
return Serial.read();
}
void clearScreen() {
unsigned char cmd = 0xFC;
Serial.write(&cmd, 1);
delay(20);
}
void screenScroll() {
unsigned char cmd = 0xFB;
Serial.write(&cmd, 1);
delay(20);
}

87
APPLEII/keyboard.ino Normal file
View File

@ -0,0 +1,87 @@
#include <avr/wdt.h>
#define KEYBD_DATA_PIN 4
const unsigned char scancode_to_apple[] PROGMEM = {
//$0 $1 $2 $3 $4 $5 $6 $7 $8 $9 $A $B $C $D $E $F
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //$00
0x00, 0x00, 0x00, 0x00, 0x00, 0xD1, 0xB1, 0x00, 0x00, 0x00, 0xDA, 0xD3, 0xC1, 0xD7, 0xB2, 0x00, //$10
0x00, 0xC3, 0xD8, 0xC4, 0xC5, 0xB4, 0xB3, 0x00, 0x00, 0xA0, 0xD6, 0xC6, 0xD4, 0xD2, 0xB5, 0x00, //$20
0x00, 0xCE, 0xC2, 0xC8, 0xC7, 0xD9, 0xB6, 0x00, 0x00, 0x00, 0xCD, 0xCA, 0xD5, 0xB7, 0xB8, 0x00, //$30
0x00, 0xAC, 0xCB, 0xC9, 0xCF, 0xB0, 0xB9, 0x00, 0x00, 0xAE, 0xAF, 0xCC, 0xBB, 0xD0, 0xAD, 0x00, //$40
0x00, 0x00, 0xA7, 0x00, 0x00, 0xBD, 0x00, 0x00, 0x00, 0x00, 0x8D, 0x00, 0x00, 0x00, 0x00, 0x00, //$50
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0xB1, 0x00, 0xB4, 0xB7, 0x00, 0x00, 0x00, //$60
0xB0, 0xAE, 0xB2, 0xB5, 0xB6, 0xB8, 0x9B, 0x00, 0x00, 0xAB, 0xB3, 0xAD, 0xAA, 0xB9, 0x00, 0x00, //$70
// High mirror, shift modified keys
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //$80 0
0x00, 0x00, 0x00, 0x00, 0x00, 0xD1, 0xA1, 0x00, 0x00, 0x00, 0xDA, 0xD3, 0xC1, 0xD7, 0xC0, 0x00, //$90 1
0x00, 0xC3, 0xD8, 0xC4, 0xC5, 0xA4, 0xA3, 0x00, 0x00, 0xA0, 0xD6, 0xC6, 0xD4, 0xD2, 0xA5, 0x00, //$A0 2
0x00, 0xCE, 0xC2, 0xC8, 0xC7, 0xD9, 0xDE, 0x00, 0x00, 0x00, 0xCD, 0xCA, 0xD5, 0xA6, 0xAA, 0x00, //$B0 3
0x00, 0xBC, 0xCB, 0xC9, 0xCF, 0xA9, 0xA8, 0x00, 0x00, 0xBE, 0xBF, 0xCC, 0xBA, 0xD0, 0xAD, 0x00, //$C0 4
0x00, 0x00, 0xA2, 0x00, 0x00, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x8D, 0x00, 0x00, 0x00, 0x00, 0x00, //$D0 5
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0xB1, 0x00, 0xB4, 0xB7, 0x00, 0x00, 0x00, //$E0 6
0xB0, 0xAE, 0xB2, 0xB5, 0xB6, 0xB8, 0x9B, 0x00, 0x00, 0xAB, 0xB3, 0xAD, 0xAA, 0xB9, 0x00, 0x00 //$F0 7
};
// keyboard scan buffer
unsigned short keyboard_data[3] = {0, 0, 0};
unsigned char keyboard_buf_indx = 0, keyboard_mbyte = 0;
boolean shift_enabled = false;
// In apple II scancode format
volatile unsigned char keymem = 0;
unsigned char keyboard_read() {
return keymem;
}
void keyboard_strobe() {
keymem&=0x7F;
}
// clock must be on digital 3
void keyboard_begin() {
pinMode(3, INPUT_PULLUP);
pinMode(KEYBD_DATA_PIN, INPUT_PULLUP);
attachInterrupt(1, keyboard_bit, FALLING);
}
void keyboard_bit() {
if(digitalRead(KEYBD_DATA_PIN))keyboard_data[2] |= _BV(keyboard_buf_indx);
else keyboard_data[2] &= ~(_BV(keyboard_buf_indx));
if(++keyboard_buf_indx == 11) {
// Ignore parity checks for now
keyboard_data[2] = (keyboard_data[2]>>1)&0xFF;
// extended keys
if(keyboard_data[2] == 0xF0 || keyboard_data[2] == 0xE0) keyboard_mbyte = 1;
else {
//decrement counter for multibyte commands
if(keyboard_mbyte) keyboard_mbyte--;
// multibyte command is finished / normal command, process it
if(!keyboard_mbyte) {
if(keyboard_data[1] != 0xF0 && keyboard_data[1] != 0xE0) {
//Standard keys
if(keyboard_data[2] == 0x12 || keyboard_data[2] == 0x59) shift_enabled = true; //shift modifiers
else keymem = pgm_read_byte_near(scancode_to_apple+keyboard_data[2]+((shift_enabled)?0x80:0x00));
} else if(keyboard_data[0] != 0xF0 && keyboard_data[1] == 0xE0) {
//Extended keys
if(keyboard_data[2] == 0x6B) keymem = 0x95; //back key
if(keyboard_data[2] == 0x74) keymem = 0x88; //forward key
// Power management keys, hardware reset
if(keyboard_data[2] == 0x37) {
// enable watchdog with min timeout
// wait until reset
wdt_enable(WDTO_15MS);
for(;;);
}
} else if(keyboard_data[1] == 0xF0 && (keyboard_data[2] == 0x12 || keyboard_data[2] == 0x59)) shift_enabled = false;
}
}
//shuffle buffer
keyboard_data[0] = keyboard_data[1];
keyboard_data[1] = keyboard_data[2];
keyboard_buf_indx = 0;
}
}

1077
APPLEII/memory.ino Normal file

File diff suppressed because it is too large Load Diff

29
APPLEII/monitor.ino Normal file
View File

@ -0,0 +1,29 @@
// Hook routines for the apple II monitor program
// Used to trick the apple code into working on this hardware
// Ideally should patch the ROM itself, will do in future.
void program_hooks(unsigned short addr) {
// hook screen scroll, monitor command
if(addr == 0xFC70) {
screenScroll();
PC = 0xFC95;
}
// hook cassette write commnand
else if (addr == 0xFECD || addr == 0xFECF) {
// Header length
cassette_header((addr==0xFECD)?64:A);
// Write Data Block
cassette_write_block(read16(0x3C), read16(0x3E));
// Emulate counter behaviour
write16(0x003C, read16(0x3E));
PC = 0xFEF5;
}
// hook cassette read command
else if (addr == 0xFEFD) {
// Read Data Block
boolean success = cassette_read_block(read16(0x3C), read16(0x3E));
// Emulate counter behaviour
write16(0x003C, read16(0x3E));
if(success) PC = 0xFF3A;
else PC = 0xFF2D;
}
}

41
APPLEII/screen.ino Normal file
View File

@ -0,0 +1,41 @@
// squash all the modes for this demo
unsigned char appleToGhettoVGA(unsigned char apple) {
if(apple >= 0xC0) return apple-0x40;
else return apple&0x7F;
}
// Squash into normal mode
unsigned char ghettoVGAToApple(unsigned char ghettoVga) {
if(ghettoVga >= 0x40 && ghettoVga <= 0x7f) return ghettoVga;
else return ghettoVga|0x80;
}
// Extract row, column addressing from woz's interlacing mode
static unsigned char g_row = 0, g_col = 0;
void decodeScreenAddress(unsigned short address) {
unsigned char block_of_lines = (address>>7) - 0x08;
unsigned char block_offset = (address&0x00FF) - ((block_of_lines&0x01) ? 0x80 : 0x00);
if(block_offset < 0x28) {
g_row = block_of_lines;
g_col = block_offset;
} else if(block_offset < 0x50) {
g_row = block_of_lines + 8;
g_col = block_offset-0x28;
} else {
g_row = block_of_lines + 16;
g_col = block_offset-0x50;
}
}
unsigned char screenRead(unsigned short address) {
//Find our row/column
decodeScreenAddress(address);
return ghettoVGAToApple(readCharacter(g_row, g_col));
}
void screenWrite(unsigned short address, unsigned char value) {
//Find our row/column
decodeScreenAddress(address);
// If not bell character
if(value != 0x87) writeCharacter(g_row, g_col, appleToGhettoVGA(value));
}

12
APPLEII/speaker.ino Normal file
View File

@ -0,0 +1,12 @@
#define SPEAKER_PIN 5
void speaker_begin() {
pinMode(SPEAKER_PIN, OUTPUT);
digitalWrite(SPEAKER_PIN, LOW);
}
void speaker_toggle() {
static boolean state = false;
state = (state)?false:true;
digitalWrite(SPEAKER_PIN, state);
}

View File

@ -1,2 +1,10 @@
# arduino-appleii
Emulating the original Apple II microcomputer on an Arduino Uno microcontroller.
Emulate the Apple II Microcomputer / 6502 on an Arduino Uno.
To be used in conjuction with video generation code in my arduino-vga repository.
Currently somewhere between 5 and 8 times slower than real hardware, however the
arduino is maybe 16-32x the speed of the original mos6502 CPU. Should be possible
to tighten things up and reach realtime.
Feel free to play arround!