diff --git a/6502tests/test.c b/6502tests/test.c new file mode 100644 index 0000000..9d341e4 --- /dev/null +++ b/6502tests/test.c @@ -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 +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; +} \ No newline at end of file diff --git a/6502tests/test/test.iml b/6502tests/test/test.iml new file mode 100644 index 0000000..284429d --- /dev/null +++ b/6502tests/test/test.iml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/6502tests/test/testAdc.c b/6502tests/test/testAdc.c new file mode 100644 index 0000000..2b449b2 --- /dev/null +++ b/6502tests/test/testAdc.c @@ -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; +} \ No newline at end of file diff --git a/6502tests/test/testAnd.c b/6502tests/test/testAnd.c new file mode 100644 index 0000000..7a3cede --- /dev/null +++ b/6502tests/test/testAnd.c @@ -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; +} \ No newline at end of file diff --git a/6502tests/test/testAsl.c b/6502tests/test/testAsl.c new file mode 100644 index 0000000..21bd26e --- /dev/null +++ b/6502tests/test/testAsl.c @@ -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; +} \ No newline at end of file diff --git a/6502tests/test/testBcc.c b/6502tests/test/testBcc.c new file mode 100644 index 0000000..75ddd0b --- /dev/null +++ b/6502tests/test/testBcc.c @@ -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; +} \ No newline at end of file diff --git a/6502tests/test/testBcs.c b/6502tests/test/testBcs.c new file mode 100644 index 0000000..aa6334c --- /dev/null +++ b/6502tests/test/testBcs.c @@ -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; +} \ No newline at end of file diff --git a/6502tests/test/testBeq.c b/6502tests/test/testBeq.c new file mode 100644 index 0000000..bc66157 --- /dev/null +++ b/6502tests/test/testBeq.c @@ -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; +} \ No newline at end of file diff --git a/6502tests/test/testBit.c b/6502tests/test/testBit.c new file mode 100644 index 0000000..a255110 --- /dev/null +++ b/6502tests/test/testBit.c @@ -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; +} \ No newline at end of file diff --git a/6502tests/test/testBmi.c b/6502tests/test/testBmi.c new file mode 100644 index 0000000..ef14d5f --- /dev/null +++ b/6502tests/test/testBmi.c @@ -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; +} \ No newline at end of file diff --git a/6502tests/test/testBne.c b/6502tests/test/testBne.c new file mode 100644 index 0000000..ab53a7a --- /dev/null +++ b/6502tests/test/testBne.c @@ -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; +} \ No newline at end of file diff --git a/6502tests/test/testBpl.c b/6502tests/test/testBpl.c new file mode 100644 index 0000000..0ee4eab --- /dev/null +++ b/6502tests/test/testBpl.c @@ -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; +} \ No newline at end of file diff --git a/6502tests/test/testBrk.c b/6502tests/test/testBrk.c new file mode 100644 index 0000000..ad4f072 --- /dev/null +++ b/6502tests/test/testBrk.c @@ -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; +} \ No newline at end of file diff --git a/6502tests/test/testBvc.c b/6502tests/test/testBvc.c new file mode 100644 index 0000000..daf36e6 --- /dev/null +++ b/6502tests/test/testBvc.c @@ -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; +} \ No newline at end of file diff --git a/6502tests/test/testBvs.c b/6502tests/test/testBvs.c new file mode 100644 index 0000000..81e8ba0 --- /dev/null +++ b/6502tests/test/testBvs.c @@ -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; +} \ No newline at end of file diff --git a/6502tests/test/testClear.c b/6502tests/test/testClear.c new file mode 100644 index 0000000..54f5ad4 --- /dev/null +++ b/6502tests/test/testClear.c @@ -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; +} \ No newline at end of file diff --git a/6502tests/test/testCmp.c b/6502tests/test/testCmp.c new file mode 100644 index 0000000..0c7d3ac --- /dev/null +++ b/6502tests/test/testCmp.c @@ -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; +} \ No newline at end of file diff --git a/6502tests/test/testCpx.c b/6502tests/test/testCpx.c new file mode 100644 index 0000000..f228f7a --- /dev/null +++ b/6502tests/test/testCpx.c @@ -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; +} \ No newline at end of file diff --git a/6502tests/test/testCpy.c b/6502tests/test/testCpy.c new file mode 100644 index 0000000..bf0a896 --- /dev/null +++ b/6502tests/test/testCpy.c @@ -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; +} \ No newline at end of file diff --git a/6502tests/test/testDec.c b/6502tests/test/testDec.c new file mode 100644 index 0000000..abebe63 --- /dev/null +++ b/6502tests/test/testDec.c @@ -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; +} \ No newline at end of file diff --git a/6502tests/test/testEor.c b/6502tests/test/testEor.c new file mode 100644 index 0000000..369d72a --- /dev/null +++ b/6502tests/test/testEor.c @@ -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; +} \ No newline at end of file diff --git a/6502tests/test/testInc.c b/6502tests/test/testInc.c new file mode 100644 index 0000000..63dcec8 --- /dev/null +++ b/6502tests/test/testInc.c @@ -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; +} \ No newline at end of file diff --git a/6502tests/test/testJmp.c b/6502tests/test/testJmp.c new file mode 100644 index 0000000..d3dcde2 --- /dev/null +++ b/6502tests/test/testJmp.c @@ -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; +} \ No newline at end of file diff --git a/6502tests/test/testLd.c b/6502tests/test/testLd.c new file mode 100644 index 0000000..2dae4b6 --- /dev/null +++ b/6502tests/test/testLd.c @@ -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; +} \ No newline at end of file diff --git a/6502tests/test/testLsr.c b/6502tests/test/testLsr.c new file mode 100644 index 0000000..b6b5681 --- /dev/null +++ b/6502tests/test/testLsr.c @@ -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; +} \ No newline at end of file diff --git a/6502tests/test/testOra.c b/6502tests/test/testOra.c new file mode 100644 index 0000000..afcf123 --- /dev/null +++ b/6502tests/test/testOra.c @@ -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; +} \ No newline at end of file diff --git a/6502tests/test/testPha.c b/6502tests/test/testPha.c new file mode 100644 index 0000000..0574d7e --- /dev/null +++ b/6502tests/test/testPha.c @@ -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; +} \ No newline at end of file diff --git a/6502tests/test/testPhp.c b/6502tests/test/testPhp.c new file mode 100644 index 0000000..a3ca6d2 --- /dev/null +++ b/6502tests/test/testPhp.c @@ -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; +} \ No newline at end of file diff --git a/6502tests/test/testPla.c b/6502tests/test/testPla.c new file mode 100644 index 0000000..3db7720 --- /dev/null +++ b/6502tests/test/testPla.c @@ -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; +} \ No newline at end of file diff --git a/6502tests/test/testPlp.c b/6502tests/test/testPlp.c new file mode 100644 index 0000000..648747c --- /dev/null +++ b/6502tests/test/testPlp.c @@ -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; +} \ No newline at end of file diff --git a/6502tests/test/testRol.c b/6502tests/test/testRol.c new file mode 100644 index 0000000..fb5947b --- /dev/null +++ b/6502tests/test/testRol.c @@ -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; +} \ No newline at end of file diff --git a/6502tests/test/testRor.c b/6502tests/test/testRor.c new file mode 100644 index 0000000..768bf59 --- /dev/null +++ b/6502tests/test/testRor.c @@ -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; +} \ No newline at end of file diff --git a/6502tests/test/testRti.c b/6502tests/test/testRti.c new file mode 100644 index 0000000..76f175c --- /dev/null +++ b/6502tests/test/testRti.c @@ -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; +} \ No newline at end of file diff --git a/6502tests/test/testRts.c b/6502tests/test/testRts.c new file mode 100644 index 0000000..0efb231 --- /dev/null +++ b/6502tests/test/testRts.c @@ -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; +} \ No newline at end of file diff --git a/6502tests/test/testSbc.c b/6502tests/test/testSbc.c new file mode 100644 index 0000000..5bdbf71 --- /dev/null +++ b/6502tests/test/testSbc.c @@ -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; +} \ No newline at end of file diff --git a/6502tests/test/testSet.c b/6502tests/test/testSet.c new file mode 100644 index 0000000..04e93dd --- /dev/null +++ b/6502tests/test/testSet.c @@ -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; +} \ No newline at end of file diff --git a/6502tests/test/testSt.c b/6502tests/test/testSt.c new file mode 100644 index 0000000..da39f1a --- /dev/null +++ b/6502tests/test/testSt.c @@ -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; +} \ No newline at end of file diff --git a/6502tests/test/testSta.c b/6502tests/test/testSta.c new file mode 100644 index 0000000..e174d20 --- /dev/null +++ b/6502tests/test/testSta.c @@ -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; +} diff --git a/6502tests/test/testTransfer.c b/6502tests/test/testTransfer.c new file mode 100644 index 0000000..fc0817b --- /dev/null +++ b/6502tests/test/testTransfer.c @@ -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; +} \ No newline at end of file diff --git a/APPLEII/APPLEII.ino b/APPLEII/APPLEII.ino new file mode 100644 index 0000000..655b764 --- /dev/null +++ b/APPLEII/APPLEII.ino @@ -0,0 +1,42 @@ +/* +Copyright (c) 2015, Damian Peckett +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 + +void setup() { + Serial.begin(115200); + clearScreen(); + speaker_begin(); + cassette_begin(); + keyboard_begin(); + sei(); +} + +void loop() { + run(); +} diff --git a/APPLEII/cassette.ino b/APPLEII/cassette.ino new file mode 100644 index 0000000..3ef7093 --- /dev/null +++ b/APPLEII/cassette.ino @@ -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); +} diff --git a/APPLEII/cpu.ino b/APPLEII/cpu.ino new file mode 100644 index 0000000..561a4e8 --- /dev/null +++ b/APPLEII/cpu.ino @@ -0,0 +1,528 @@ +// μ6502 - Barebones 6502 Emulator By Damian Peckett +// dpeckett.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; + } + } +} diff --git a/APPLEII/ghettovga.ino b/APPLEII/ghettovga.ino new file mode 100644 index 0000000..81b4cee --- /dev/null +++ b/APPLEII/ghettovga.ino @@ -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); +} diff --git a/APPLEII/keyboard.ino b/APPLEII/keyboard.ino new file mode 100644 index 0000000..8a84d9f --- /dev/null +++ b/APPLEII/keyboard.ino @@ -0,0 +1,87 @@ +#include + +#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; + } +} diff --git a/APPLEII/memory.ino b/APPLEII/memory.ino new file mode 100644 index 0000000..e41842b --- /dev/null +++ b/APPLEII/memory.ino @@ -0,0 +1,1077 @@ +const unsigned char rom[] PROGMEM = { //$E000 - FFFF + 0x20, 0x00, 0xf0, 0x4c, 0xb3, 0xe2, 0x85, 0x33, + 0x4c, 0xed, 0xfd, 0x60, 0x8a, 0x29, 0x20, 0xf0, + 0x23, 0xa9, 0xa0, 0x85, 0xe4, 0x4c, 0xed, 0xfd, + 0xa9, 0x20, 0xc5, 0x24, 0xb0, 0x0c, 0xa9, 0x8d, + 0xa0, 0x07, 0x20, 0xed, 0xfd, 0xa9, 0xa0, 0x88, + 0xd0, 0xf8, 0xa0, 0x00, 0xb1, 0xe2, 0xe6, 0xe2, + 0xd0, 0x02, 0xe6, 0xe3, 0x60, 0x20, 0x15, 0xe7, + 0x20, 0x76, 0xe5, 0xa5, 0xe2, 0xc5, 0xe6, 0xa5, + 0xe3, 0xe5, 0xe7, 0xb0, 0xef, 0x20, 0x6d, 0xe0, + 0x4c, 0x3b, 0xe0, 0xa5, 0xca, 0x85, 0xe2, 0xa5, + 0xcb, 0x85, 0xe3, 0xa5, 0x4c, 0x85, 0xe6, 0xa5, + 0x4d, 0x85, 0xe7, 0xd0, 0xde, 0x20, 0x15, 0xe7, + 0x20, 0x6d, 0xe5, 0xa5, 0xe4, 0x85, 0xe2, 0xa5, + 0xe5, 0x85, 0xe3, 0xb0, 0xc7, 0x86, 0xd8, 0xa9, + 0xa0, 0x85, 0xfa, 0x20, 0x2a, 0xe0, 0x98, 0x85, + 0xe4, 0x20, 0x2a, 0xe0, 0xaa, 0x20, 0x2a, 0xe0, + 0x20, 0x1b, 0xe5, 0x20, 0x18, 0xe0, 0x84, 0xfa, + 0xaa, 0x10, 0x18, 0x0a, 0x10, 0xe9, 0xa5, 0xe4, + 0xd0, 0x03, 0x20, 0x11, 0xe0, 0x8a, 0x20, 0xed, + 0xfd, 0xa9, 0x25, 0x20, 0x1a, 0xe0, 0xaa, 0x30, + 0xf5, 0x85, 0xe4, 0xc9, 0x01, 0xd0, 0x05, 0xa6, + 0xd8, 0x4c, 0x8e, 0xfd, 0x48, 0x84, 0xce, 0xa2, + 0xed, 0x86, 0xcf, 0xc9, 0x51, 0x90, 0x04, 0xc6, + 0xcf, 0xe9, 0x50, 0x48, 0xb1, 0xce, 0xaa, 0x88, + 0xb1, 0xce, 0x10, 0xfa, 0xe0, 0xc0, 0xb0, 0x04, + 0xe0, 0x00, 0x30, 0xf2, 0xaa, 0x68, 0xe9, 0x01, + 0xd0, 0xe9, 0x24, 0xe4, 0x30, 0x03, 0x20, 0xf8, + 0xef, 0xb1, 0xce, 0x10, 0x10, 0xaa, 0x29, 0x3f, + 0x85, 0xe4, 0x18, 0x69, 0xa0, 0x20, 0xed, 0xfd, + 0x88, 0xe0, 0xc0, 0x90, 0xec, 0x20, 0x0c, 0xe0, + 0x68, 0xc9, 0x5d, 0xf0, 0xa4, 0xc9, 0x28, 0xd0, + 0x8a, 0xf0, 0x9e, 0x20, 0x18, 0xe1, 0x95, 0x50, + 0xd5, 0x78, 0x90, 0x11, 0xa0, 0x2b, 0x4c, 0xe0, + 0xe3, 0x20, 0x34, 0xee, 0xd5, 0x50, 0x90, 0xf4, + 0x20, 0xe4, 0xef, 0x95, 0x78, 0x4c, 0x23, 0xe8, + 0x20, 0x34, 0xee, 0xf0, 0xe7, 0x38, 0xe9, 0x01, + 0x60, 0x20, 0x18, 0xe1, 0x95, 0x50, 0x18, 0xf5, + 0x78, 0x4c, 0x02, 0xe1, 0xa0, 0x14, 0xd0, 0xd6, + 0x20, 0x18, 0xe1, 0xe8, 0xb5, 0x50, 0x85, 0xda, + 0x65, 0xce, 0x48, 0xa8, 0xb5, 0x78, 0x85, 0xdb, + 0x65, 0xcf, 0x48, 0xc4, 0xca, 0xe5, 0xcb, 0xb0, + 0xe3, 0xa5, 0xda, 0x69, 0xfe, 0x85, 0xda, 0xa9, + 0xff, 0xa8, 0x65, 0xdb, 0x85, 0xdb, 0xc8, 0xb1, + 0xda, 0xd9, 0xcc, 0x00, 0xd0, 0x0f, 0x98, 0xf0, + 0xf5, 0x68, 0x91, 0xda, 0x99, 0xcc, 0x00, 0x88, + 0x10, 0xf7, 0xe8, 0x60, 0xea, 0xa0, 0x80, 0xd0, + 0x95, 0xa9, 0x00, 0x20, 0x0a, 0xe7, 0xa0, 0x02, + 0x94, 0x78, 0x20, 0x0a, 0xe7, 0x86, 0xd8, 0xaa, + 0xe6, 0x33, 0x20, 0x51, 0xf3, 0xc6, 0x33, 0x8a, + 0xa6, 0xd8, 0x95, 0x78, 0xb5, 0x51, 0x85, 0xce, + 0xb5, 0x79, 0x85, 0xcf, 0xe8, 0xe8, 0x20, 0xbc, + 0xe1, 0xb5, 0x4e, 0xd5, 0x76, 0xb0, 0x15, 0xf6, + 0x4e, 0xa8, 0xb1, 0xce, 0xb4, 0x50, 0xc4, 0xe4, + 0x90, 0x04, 0xa0, 0x83, 0xd0, 0xc1, 0x91, 0xda, + 0xf6, 0x50, 0x90, 0xe5, 0xb4, 0x50, 0x8a, 0x91, + 0xda, 0x4c, 0x23, 0xf2, 0xb5, 0x51, 0x85, 0xda, + 0x38, 0xe9, 0x02, 0x85, 0xe4, 0xb5, 0x79, 0x85, + 0xdb, 0xe9, 0x00, 0x85, 0xe5, 0xa0, 0x00, 0xb1, + 0xe4, 0x18, 0xe5, 0xda, 0x85, 0xe4, 0x60, 0xb5, + 0x53, 0x85, 0xce, 0xb5, 0x7b, 0x85, 0xcf, 0xb5, + 0x51, 0x85, 0xda, 0xb5, 0x79, 0x85, 0xdb, 0xe8, + 0xe8, 0xe8, 0xa0, 0x00, 0x94, 0x78, 0x94, 0xa0, + 0xc8, 0x94, 0x50, 0xb5, 0x4d, 0xd5, 0x75, 0x08, + 0x48, 0xb5, 0x4f, 0xd5, 0x77, 0x90, 0x07, 0x68, + 0x28, 0xb0, 0x02, 0x56, 0x50, 0x60, 0xa8, 0xb1, + 0xce, 0x85, 0xe4, 0x68, 0xa8, 0x28, 0xb0, 0xf3, + 0xb1, 0xda, 0xc5, 0xe4, 0xd0, 0xed, 0xf6, 0x4f, + 0xf6, 0x4d, 0xb0, 0xd7, 0x20, 0xd7, 0xe1, 0x4c, + 0x36, 0xe7, 0x20, 0x54, 0xe2, 0x06, 0xce, 0x26, + 0xcf, 0x90, 0x0d, 0x18, 0xa5, 0xe6, 0x65, 0xda, + 0x85, 0xe6, 0xa5, 0xe7, 0x65, 0xdb, 0x85, 0xe7, + 0x88, 0xf0, 0x09, 0x06, 0xe6, 0x26, 0xe7, 0x10, + 0xe4, 0x4c, 0x7e, 0xe7, 0xa5, 0xe6, 0x20, 0x08, + 0xe7, 0xa5, 0xe7, 0x95, 0xa0, 0x06, 0xe5, 0x90, + 0x28, 0x4c, 0x6f, 0xe7, 0xa9, 0x55, 0x85, 0xe5, + 0x20, 0x5b, 0xe2, 0xa5, 0xce, 0x85, 0xda, 0xa5, + 0xcf, 0x85, 0xdb, 0x20, 0x15, 0xe7, 0x84, 0xe6, + 0x84, 0xe7, 0xa5, 0xcf, 0x10, 0x09, 0xca, 0x06, + 0xe5, 0x20, 0x6f, 0xe7, 0x20, 0x15, 0xe7, 0xa0, + 0x10, 0x60, 0x20, 0x6c, 0xee, 0xf0, 0xc5, 0xff, + 0xe6, 0x33, 0xa0, 0x00, 0x20, 0xce, 0xe3, 0xc6, + 0x33, 0x60, 0x20, 0x34, 0xee, 0x4a, 0x08, 0x20, + 0x47, 0xf8, 0x20, 0x34, 0xee, 0xa8, 0xb1, 0x26, + 0x28, 0x90, 0x04, 0x4a, 0x4a, 0x4a, 0x4a, 0x29, + 0x0f, 0xa0, 0x00, 0x20, 0x08, 0xe7, 0x94, 0xa0, + 0x88, 0x84, 0xd7, 0x60, 0xff, 0xff, 0xff, 0xff, + 0x20, 0xd3, 0xef, 0x20, 0x8e, 0xfd, 0x46, 0xd9, + 0xa9, 0xbe, 0x20, 0x06, 0xe0, 0xa0, 0x00, 0x84, + 0xfa, 0x24, 0xf8, 0x10, 0x0c, 0xa6, 0xf6, 0xa5, + 0xf7, 0x20, 0x1b, 0xe5, 0xa9, 0xa0, 0x20, 0xed, + 0xfd, 0xa2, 0xff, 0x9a, 0x20, 0xce, 0xe3, 0x84, + 0xf1, 0x8a, 0x85, 0xc8, 0xa2, 0x20, 0x20, 0x91, + 0xe4, 0xa5, 0xc8, 0x69, 0x00, 0x85, 0xe0, 0xa9, + 0x00, 0xaa, 0x69, 0x02, 0x85, 0xe1, 0xa1, 0xe0, + 0x29, 0xf0, 0xc9, 0xb0, 0xf0, 0x03, 0x4c, 0x83, + 0xe8, 0xa0, 0x02, 0xb1, 0xe0, 0x99, 0xcd, 0x00, + 0x88, 0xd0, 0xf8, 0x20, 0x8a, 0xe3, 0xa5, 0xf1, + 0xe5, 0xc8, 0xc9, 0x04, 0xf0, 0xa8, 0x91, 0xe0, + 0xa5, 0xca, 0xf1, 0xe0, 0x85, 0xe4, 0xa5, 0xcb, + 0xe9, 0x00, 0x85, 0xe5, 0xa5, 0xe4, 0xc5, 0xcc, + 0xa5, 0xe5, 0xe5, 0xcd, 0x90, 0x45, 0xa5, 0xca, + 0xf1, 0xe0, 0x85, 0xe6, 0xa5, 0xcb, 0xe9, 0x00, + 0x85, 0xe7, 0xb1, 0xca, 0x91, 0xe6, 0xe6, 0xca, + 0xd0, 0x02, 0xe6, 0xcb, 0xa5, 0xe2, 0xc5, 0xca, + 0xa5, 0xe3, 0xe5, 0xcb, 0xb0, 0xe0, 0xb5, 0xe4, + 0x95, 0xca, 0xca, 0x10, 0xf9, 0xb1, 0xe0, 0xa8, + 0x88, 0xb1, 0xe0, 0x91, 0xe6, 0x98, 0xd0, 0xf8, + 0x24, 0xf8, 0x10, 0x09, 0xb5, 0xf7, 0x75, 0xf5, + 0x95, 0xf7, 0xe8, 0xf0, 0xf7, 0x10, 0x7e, 0x00, + 0x00, 0x00, 0x00, 0xa0, 0x14, 0xd0, 0x71, 0x20, + 0x15, 0xe7, 0xa5, 0xe2, 0x85, 0xe6, 0xa5, 0xe3, + 0x85, 0xe7, 0x20, 0x75, 0xe5, 0xa5, 0xe2, 0x85, + 0xe4, 0xa5, 0xe3, 0x85, 0xe5, 0xd0, 0x0e, 0x20, + 0x15, 0xe7, 0x20, 0x6d, 0xe5, 0xa5, 0xe6, 0x85, + 0xe2, 0xa5, 0xe7, 0x85, 0xe3, 0xa0, 0x00, 0xa5, + 0xca, 0xc5, 0xe4, 0xa5, 0xcb, 0xe5, 0xe5, 0xb0, + 0x16, 0xa5, 0xe4, 0xd0, 0x02, 0xc6, 0xe5, 0xc6, + 0xe4, 0xa5, 0xe6, 0xd0, 0x02, 0xc6, 0xe7, 0xc6, + 0xe6, 0xb1, 0xe4, 0x91, 0xe6, 0x90, 0xe0, 0xa5, + 0xe6, 0x85, 0xca, 0xa5, 0xe7, 0x85, 0xcb, 0x60, + 0x20, 0xed, 0xfd, 0xc8, 0xb9, 0x00, 0xeb, 0x30, + 0xf7, 0x09, 0x80, 0x4c, 0xed, 0xfd, 0x98, 0xaa, + 0x20, 0x75, 0xfd, 0x8a, 0xa8, 0xa9, 0xdf, 0x99, + 0x00, 0x02, 0xa2, 0xff, 0x60, 0x60, 0xa0, 0x06, + 0x20, 0xd3, 0xee, 0x24, 0xd9, 0x30, 0x03, 0x4c, + 0xb6, 0xe2, 0x4c, 0x9a, 0xeb, 0x2a, 0x69, 0xa0, + 0xdd, 0x00, 0x02, 0xd0, 0x53, 0xb1, 0xfe, 0x0a, + 0x30, 0x06, 0x88, 0xb1, 0xfe, 0x30, 0x29, 0xc8, + 0x86, 0xc8, 0x98, 0x48, 0xa2, 0x00, 0xa1, 0xfe, + 0xaa, 0x4a, 0x49, 0x40, 0x11, 0xfe, 0xc9, 0xc0, + 0x90, 0x01, 0xe8, 0xc8, 0xd0, 0xf3, 0x68, 0xa8, + 0x8a, 0x4c, 0xf8, 0xf2, 0xe6, 0xf1, 0xa6, 0xf1, + 0xf0, 0xbc, 0x9d, 0x00, 0x02, 0x60, 0xa6, 0xc8, + 0xa9, 0xa0, 0xe8, 0xdd, 0x00, 0x02, 0xb0, 0xfa, + 0xb1, 0xfe, 0x29, 0x3f, 0x4a, 0xd0, 0xb6, 0xbd, + 0x00, 0x02, 0xb0, 0x06, 0x69, 0x3f, 0xc9, 0x1a, + 0x90, 0x6f, 0x69, 0x4f, 0xc9, 0x0a, 0x90, 0x69, + 0xa6, 0xfd, 0xc8, 0xb1, 0xfe, 0x29, 0xe0, 0xc9, + 0x20, 0xf0, 0x7a, 0xb5, 0xa8, 0x85, 0xc8, 0xb5, + 0xd1, 0x85, 0xf1, 0x88, 0xb1, 0xfe, 0x0a, 0x10, + 0xfa, 0x88, 0xb0, 0x38, 0x0a, 0x30, 0x35, 0xb4, + 0x58, 0x84, 0xff, 0xb4, 0x80, 0xe8, 0x10, 0xda, + 0xf0, 0xb3, 0xc9, 0x7e, 0xb0, 0x22, 0xca, 0x10, + 0x04, 0xa0, 0x06, 0x10, 0x29, 0x94, 0x80, 0xa4, + 0xff, 0x94, 0x58, 0xa4, 0xc8, 0x94, 0xa8, 0xa4, + 0xf1, 0x94, 0xd1, 0x29, 0x1f, 0xa8, 0xb9, 0x97, + 0xf1, 0x0a, 0xa8, 0xa9, 0x76, 0x2a, 0x85, 0xff, + 0xd0, 0x01, 0xc8, 0xc8, 0x86, 0xfd, 0xb1, 0xfe, + 0x30, 0x84, 0xd0, 0x05, 0xa0, 0x0e, 0x4c, 0xe0, + 0xe3, 0xc9, 0x03, 0xb0, 0xc3, 0x4a, 0xa6, 0xc8, + 0xe8, 0xbd, 0x00, 0x02, 0x90, 0x04, 0xc9, 0xa2, + 0xf0, 0x0a, 0xc9, 0xdf, 0xf0, 0x06, 0x86, 0xc8, + 0x20, 0x1c, 0xe4, 0xc8, 0x88, 0xa6, 0xfd, 0xb1, + 0xfe, 0x88, 0x0a, 0x10, 0xcf, 0xb4, 0x58, 0x84, + 0xff, 0xb4, 0x80, 0xe8, 0xb1, 0xfe, 0x29, 0x9f, + 0xd0, 0xed, 0x85, 0xf2, 0x85, 0xf3, 0x98, 0x48, + 0x86, 0xfd, 0xb4, 0xd0, 0x84, 0xc9, 0x18, 0xa9, + 0x0a, 0x85, 0xf9, 0xa2, 0x00, 0xc8, 0xb9, 0x00, + 0x02, 0x29, 0x0f, 0x65, 0xf2, 0x48, 0x8a, 0x65, + 0xf3, 0x30, 0x1c, 0xaa, 0x68, 0xc6, 0xf9, 0xd0, + 0xf2, 0x85, 0xf2, 0x86, 0xf3, 0xc4, 0xf1, 0xd0, + 0xde, 0xa4, 0xc9, 0xc8, 0x84, 0xf1, 0x20, 0x1c, + 0xe4, 0x68, 0xa8, 0xa5, 0xf3, 0xb0, 0xa9, 0xa0, + 0x00, 0x10, 0x8b, 0x85, 0xf3, 0x86, 0xf2, 0xa2, + 0x04, 0x86, 0xc9, 0xa9, 0xb0, 0x85, 0xf9, 0xa5, + 0xf2, 0xdd, 0x63, 0xe5, 0xa5, 0xf3, 0xfd, 0x68, + 0xe5, 0x90, 0x0d, 0x85, 0xf3, 0xa5, 0xf2, 0xfd, + 0x63, 0xe5, 0x85, 0xf2, 0xe6, 0xf9, 0xd0, 0xe7, + 0xa5, 0xf9, 0xe8, 0xca, 0xf0, 0x0e, 0xc9, 0xb0, + 0xf0, 0x02, 0x85, 0xc9, 0x24, 0xc9, 0x30, 0x04, + 0xa5, 0xfa, 0xf0, 0x0b, 0x20, 0xed, 0xfd, 0x24, + 0xf8, 0x10, 0x04, 0x99, 0x00, 0x02, 0xc8, 0xca, + 0x10, 0xc1, 0x60, 0x01, 0x0a, 0x64, 0xe8, 0x10, + 0x00, 0x00, 0x00, 0x03, 0x27, 0xa5, 0xca, 0x85, + 0xe6, 0xa5, 0xcb, 0x85, 0xe7, 0xe8, 0xa5, 0xe7, + 0x85, 0xe5, 0xa5, 0xe6, 0x85, 0xe4, 0xc5, 0x4c, + 0xa5, 0xe5, 0xe5, 0x4d, 0xb0, 0x26, 0xa0, 0x01, + 0xb1, 0xe4, 0xe5, 0xce, 0xc8, 0xb1, 0xe4, 0xe5, + 0xcf, 0xb0, 0x19, 0xa0, 0x00, 0xa5, 0xe6, 0x71, + 0xe4, 0x85, 0xe6, 0x90, 0x03, 0xe6, 0xe7, 0x18, + 0xc8, 0xa5, 0xce, 0xf1, 0xe4, 0xc8, 0xa5, 0xcf, + 0xf1, 0xe4, 0xb0, 0xca, 0x60, 0x46, 0xf8, 0xa5, + 0x4c, 0x85, 0xca, 0xa5, 0x4d, 0x85, 0xcb, 0xa5, + 0x4a, 0x85, 0xcc, 0xa5, 0x4b, 0x85, 0xcd, 0xa9, + 0x00, 0x85, 0xfb, 0x85, 0xfc, 0x85, 0xfe, 0xa9, + 0x00, 0x85, 0x1d, 0x60, 0xa5, 0xd0, 0x4c, 0x6b, + 0xe3, 0xa0, 0xff, 0x84, 0xd8, 0xc8, 0xb1, 0xe0, + 0x30, 0x06, 0xc9, 0x40, 0xd0, 0x68, 0x85, 0xd8, + 0xd1, 0xd0, 0xf0, 0xf1, 0xb1, 0xd0, 0xc8, 0x4a, + 0xd0, 0xfa, 0xb1, 0xd0, 0x48, 0xc8, 0xb1, 0xd0, + 0xa8, 0x68, 0x85, 0xd0, 0x84, 0xd1, 0xc5, 0xcc, + 0xd0, 0xd7, 0xc4, 0xcd, 0xd0, 0xd3, 0xa0, 0x00, + 0xc8, 0xb1, 0xe0, 0x30, 0xfb, 0x49, 0x40, 0xf0, + 0xf7, 0x98, 0x69, 0x04, 0x48, 0x65, 0xd0, 0xa8, + 0xa5, 0xd1, 0x69, 0x00, 0x48, 0xc4, 0xca, 0xe5, + 0xcb, 0xb0, 0xb3, 0x84, 0xcc, 0x68, 0x85, 0xcd, + 0x68, 0xa8, 0xa9, 0x00, 0x88, 0x91, 0xd0, 0x88, + 0x91, 0xd0, 0x88, 0xa5, 0xcd, 0x91, 0xd0, 0x88, + 0xa5, 0xcc, 0x91, 0xd0, 0x88, 0xa9, 0x00, 0x91, + 0xd0, 0x88, 0x30, 0x97, 0xb1, 0xe0, 0xd0, 0xf7, + 0xa5, 0x4a, 0xa4, 0x4b, 0xd0, 0xac, 0xb1, 0xd0, + 0xc9, 0x40, 0xb0, 0x9a, 0x95, 0x9f, 0x98, 0x69, + 0x03, 0x48, 0x65, 0xd0, 0x20, 0x0a, 0xe7, 0x20, + 0xff, 0xe6, 0x88, 0xd0, 0xfa, 0x98, 0x65, 0xd1, + 0x95, 0x78, 0x68, 0x24, 0xd8, 0x30, 0x1d, 0xa8, + 0xa9, 0x00, 0x20, 0x0a, 0xe7, 0x95, 0x78, 0xb1, + 0xd0, 0x10, 0x0f, 0xf6, 0x78, 0xc8, 0xd0, 0xf7, + 0x09, 0xa9, 0x00, 0x85, 0xd4, 0x85, 0xd5, 0xa2, + 0x20, 0x48, 0xa0, 0x00, 0xb1, 0xe0, 0x10, 0x18, + 0x0a, 0x30, 0xb5, 0x20, 0xff, 0xe6, 0x20, 0x08, + 0xe7, 0x20, 0xff, 0xe6, 0x95, 0xa0, 0x24, 0xd4, + 0x10, 0x01, 0xca, 0x20, 0xff, 0xe6, 0xb0, 0xe6, + 0xc9, 0x28, 0xd0, 0x1f, 0xa5, 0xe0, 0x20, 0x0a, + 0xe7, 0xa5, 0xe1, 0x95, 0x78, 0x24, 0xd4, 0x30, + 0x0b, 0xa9, 0x01, 0x20, 0x0a, 0xe7, 0xa9, 0x00, + 0x95, 0x78, 0xf6, 0x78, 0x20, 0xff, 0xe6, 0x30, + 0xf9, 0xb0, 0xd3, 0x24, 0xd4, 0x10, 0x06, 0xc9, + 0x04, 0xb0, 0xd0, 0x46, 0xd4, 0xa8, 0x85, 0xd6, + 0xb9, 0x80, 0xe9, 0x29, 0x55, 0x0a, 0x85, 0xd7, + 0x68, 0xa8, 0xb9, 0x80, 0xe9, 0x29, 0xaa, 0xc5, + 0xd7, 0xb0, 0x09, 0x98, 0x48, 0x20, 0xeb, 0xf3, + 0xa5, 0xd6, 0x90, 0x95, 0xb9, 0x00, 0xea, 0x85, + 0xce, 0xb9, 0x80, 0xea, 0x85, 0xcf, 0x20, 0xfc, + 0xe6, 0x4c, 0xd8, 0xe6, 0x6c, 0xce, 0x00, 0xe6, + 0xe0, 0xd0, 0x02, 0xe6, 0xe1, 0xb1, 0xe0, 0x60, + 0x94, 0x77, 0xca, 0x30, 0x03, 0x95, 0x50, 0x60, + 0xa0, 0x66, 0x4c, 0xe0, 0xe3, 0xa0, 0x00, 0xb5, + 0x50, 0x85, 0xce, 0xb5, 0xa0, 0x85, 0xcf, 0xb5, + 0x78, 0xf0, 0x0e, 0x85, 0xcf, 0xb1, 0xce, 0x48, + 0xc8, 0xb1, 0xce, 0x85, 0xcf, 0x68, 0x85, 0xce, + 0x88, 0xe8, 0x60, 0x20, 0x4a, 0xe7, 0x20, 0x15, + 0xe7, 0x98, 0x20, 0x08, 0xe7, 0x95, 0xa0, 0xc5, + 0xce, 0xd0, 0x06, 0xc5, 0xcf, 0xd0, 0x02, 0xf6, + 0x50, 0x60, 0x20, 0x82, 0xe7, 0x20, 0x59, 0xe7, + 0x20, 0x15, 0xe7, 0x24, 0xcf, 0x30, 0x1b, 0xca, + 0x60, 0x20, 0x15, 0xe7, 0xa5, 0xcf, 0xd0, 0x04, + 0xa5, 0xce, 0xf0, 0xf3, 0xa9, 0xff, 0x20, 0x08, + 0xe7, 0x95, 0xa0, 0x24, 0xcf, 0x30, 0xe9, 0x20, + 0x15, 0xe7, 0x98, 0x38, 0xe5, 0xce, 0x20, 0x08, + 0xe7, 0x98, 0xe5, 0xcf, 0x50, 0x23, 0xa0, 0x00, + 0x10, 0x90, 0x20, 0x6f, 0xe7, 0x20, 0x15, 0xe7, + 0xa5, 0xce, 0x85, 0xda, 0xa5, 0xcf, 0x85, 0xdb, + 0x20, 0x15, 0xe7, 0x18, 0xa5, 0xce, 0x65, 0xda, + 0x20, 0x08, 0xe7, 0xa5, 0xcf, 0x65, 0xdb, 0x70, + 0xdd, 0x95, 0xa0, 0x60, 0x20, 0x34, 0xee, 0xa8, + 0xd0, 0x03, 0x4c, 0xcb, 0xee, 0x88, 0x4c, 0xf4, + 0xf3, 0xa5, 0x24, 0x09, 0x07, 0xa8, 0xc8, 0xd0, + 0xf5, 0xc8, 0xd0, 0xf5, 0xb0, 0xf9, 0x60, 0x00, + 0x00, 0x20, 0xb1, 0xe7, 0x20, 0x15, 0xe7, 0xa5, + 0xcf, 0x10, 0x0a, 0xa9, 0xad, 0x20, 0xed, 0xfd, + 0x20, 0x72, 0xe7, 0x50, 0xef, 0x88, 0x84, 0xd5, + 0x86, 0xcf, 0xa6, 0xce, 0x20, 0x1b, 0xe5, 0xa6, + 0xcf, 0x60, 0x20, 0x15, 0xe7, 0xa5, 0xce, 0x85, + 0xf6, 0xa5, 0xcf, 0x85, 0xf7, 0x88, 0x84, 0xf8, + 0xc8, 0xa9, 0x0a, 0x85, 0xf4, 0x84, 0xf5, 0x60, + 0x20, 0x15, 0xe7, 0xa5, 0xce, 0xa4, 0xcf, 0x10, + 0xf2, 0x20, 0x15, 0xe7, 0xb5, 0x50, 0x85, 0xda, + 0xb5, 0x78, 0x85, 0xdb, 0xa5, 0xce, 0x91, 0xda, + 0xc8, 0xa5, 0xcf, 0x4c, 0x07, 0xf2, 0x60, 0x68, + 0x68, 0x24, 0xd5, 0x10, 0x05, 0x20, 0x8e, 0xfd, + 0x46, 0xd5, 0x60, 0xa0, 0xff, 0x84, 0xd7, 0x60, + 0x20, 0xcd, 0xef, 0xf0, 0x07, 0xa9, 0x25, 0x85, + 0xd6, 0x88, 0x84, 0xd4, 0xe8, 0x60, 0xa5, 0xca, + 0xa4, 0xcb, 0xd0, 0x5a, 0xa0, 0x41, 0xa5, 0xfc, + 0xc9, 0x10, 0xb0, 0x5e, 0xa8, 0xe6, 0xfc, 0xa5, + 0xe0, 0x99, 0x00, 0x01, 0xa5, 0xe1, 0x99, 0x10, + 0x01, 0xa5, 0xdc, 0x99, 0x20, 0x01, 0xa5, 0xdd, + 0x99, 0x30, 0x01, 0x20, 0x15, 0xe7, 0x20, 0x6d, + 0xe5, 0x90, 0x04, 0xa0, 0x37, 0xd0, 0x3b, 0xa5, + 0xe4, 0xa4, 0xe5, 0x85, 0xdc, 0x84, 0xdd, 0x18, + 0x69, 0x03, 0x90, 0x01, 0xc8, 0xa2, 0xff, 0x86, + 0xd9, 0x9a, 0x85, 0xe0, 0x84, 0xe1, 0x20, 0x2e, + 0xf0, 0xa0, 0x00, 0x20, 0x79, 0xe6, 0x24, 0xd9, + 0x10, 0x49, 0x18, 0xa0, 0x00, 0xa5, 0xdc, 0x71, + 0xdc, 0xa4, 0xdd, 0x90, 0x01, 0xc8, 0xc5, 0x4c, + 0xd0, 0xd1, 0xc4, 0x4d, 0xd0, 0xcd, 0xa0, 0x31, + 0x46, 0xd9, 0x4c, 0xe0, 0xe3, 0xa0, 0x4a, 0xa5, + 0xfc, 0xf0, 0xf7, 0xc6, 0xfc, 0xa8, 0xb9, 0x1f, + 0x01, 0x85, 0xdc, 0xb9, 0x2f, 0x01, 0x85, 0xdd, + 0xbe, 0xff, 0x00, 0xb9, 0x0f, 0x01, 0xa8, 0x8a, + 0x4c, 0x75, 0xe8, 0xa0, 0x63, 0x20, 0xc4, 0xe3, + 0xa0, 0x01, 0xb1, 0xdc, 0xaa, 0xc8, 0xb1, 0xdc, + 0x20, 0x1b, 0xe5, 0x4c, 0xb3, 0xe2, 0xc6, 0xfb, + 0xa0, 0x5b, 0xa5, 0xfb, 0xf0, 0xc4, 0xa8, 0xb5, + 0x50, 0xd9, 0x3f, 0x01, 0xd0, 0xf0, 0xb5, 0x78, + 0xd9, 0x4f, 0x01, 0xd0, 0xe9, 0xb9, 0x5f, 0x01, + 0x85, 0xda, 0xb9, 0x6f, 0x01, 0x85, 0xdb, 0x20, + 0x15, 0xe7, 0xca, 0x20, 0x93, 0xe7, 0x20, 0x01, + 0xe8, 0xca, 0xa4, 0xfb, 0xb9, 0xcf, 0x01, 0x95, + 0x9f, 0xb9, 0xbf, 0x01, 0xa0, 0x00, 0x20, 0x08, + 0xe7, 0x20, 0x82, 0xe7, 0x20, 0x59, 0xe7, 0x20, + 0x15, 0xe7, 0xa4, 0xfb, 0xa5, 0xce, 0xf0, 0x05, + 0x59, 0x6f, 0x01, 0x10, 0x12, 0xb9, 0x7f, 0x01, + 0x85, 0xdc, 0xb9, 0x8f, 0x01, 0x85, 0xdd, 0xbe, + 0x9f, 0x01, 0xb9, 0xaf, 0x01, 0xd0, 0x87, 0xc6, + 0xfb, 0x60, 0xa0, 0x54, 0xa5, 0xfb, 0xc9, 0x10, + 0xf0, 0x9a, 0xe6, 0xfb, 0xa8, 0xb5, 0x50, 0x99, + 0x40, 0x01, 0xb5, 0x78, 0x4c, 0x88, 0xf2, 0x60, + 0x20, 0x15, 0xe7, 0xa4, 0xfb, 0xa5, 0xce, 0x99, + 0xbf, 0x01, 0xa5, 0xcf, 0x99, 0xcf, 0x01, 0xa9, + 0x01, 0x99, 0x5f, 0x01, 0xa9, 0x00, 0x99, 0x6f, + 0x01, 0xa5, 0xdc, 0x99, 0x7f, 0x01, 0xa5, 0xdd, + 0x99, 0x8f, 0x01, 0xa5, 0xe0, 0x99, 0x9f, 0x01, + 0xa5, 0xe1, 0x99, 0xaf, 0x01, 0x60, 0x20, 0x15, + 0x00, 0x00, 0x00, 0xab, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x3f, 0x3f, 0xc0, 0xc0, 0x3c, 0x3c, + 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x30, 0x0f, 0xc0, + 0xc3, 0xff, 0x55, 0x00, 0xab, 0xab, 0x03, 0x03, + 0xff, 0xff, 0x55, 0xff, 0xff, 0x55, 0xcf, 0xcf, + 0xcf, 0xcf, 0xcf, 0xff, 0x55, 0xc6, 0xc6, 0xc6, + 0x55, 0xf0, 0xf0, 0xcf, 0xcf, 0x55, 0x01, 0x55, + 0xff, 0xff, 0x55, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0xab, 0x03, + 0x57, 0x03, 0x03, 0x03, 0x03, 0x07, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0xaa, 0xff, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x17, 0xff, 0xff, 0x19, 0xdf, 0x42, 0x0a, 0xf2, + 0xec, 0x87, 0x6f, 0xad, 0xb7, 0xe2, 0xf8, 0x54, + 0x4d, 0xc9, 0x85, 0x82, 0x22, 0x10, 0x33, 0x4a, + 0x5b, 0x4e, 0x53, 0x4a, 0x49, 0x66, 0x6d, 0x7a, + 0x71, 0xff, 0x23, 0x09, 0x5b, 0x16, 0xb6, 0xcb, + 0xff, 0xff, 0xfb, 0xff, 0xff, 0x24, 0xf6, 0x4e, + 0x59, 0x50, 0x3b, 0xff, 0x23, 0xa3, 0x6f, 0x36, + 0x23, 0xd7, 0x1c, 0x22, 0x1d, 0x8a, 0xab, 0x23, + 0xff, 0xff, 0x21, 0x30, 0x1e, 0x03, 0xc4, 0x20, + 0x00, 0xc1, 0xba, 0x39, 0x40, 0xa0, 0x30, 0x1e, + 0xa4, 0xd3, 0xb6, 0xbc, 0xaa, 0x3a, 0x01, 0x50, + 0x79, 0xd8, 0xd8, 0xa5, 0x3c, 0xff, 0x16, 0x5b, + 0x28, 0x03, 0xc4, 0x1d, 0x08, 0x00, 0x4e, 0x00, + 0x3e, 0x00, 0xa6, 0xb0, 0x00, 0xbc, 0xc6, 0x57, + 0x8c, 0x01, 0x27, 0xff, 0x5d, 0x35, 0x4b, 0x67, + 0xe0, 0xe1, 0x76, 0x04, 0x05, 0x71, 0xc9, 0x1a, + 0xe8, 0xff, 0xff, 0xe8, 0xf0, 0xf1, 0xf3, 0xef, + 0xef, 0xe3, 0xe3, 0xe5, 0xe5, 0xe7, 0xe7, 0xee, + 0xf0, 0xf0, 0xe7, 0xe7, 0xe2, 0xef, 0xe7, 0xe7, + 0xf2, 0xf2, 0xf2, 0xe7, 0xf2, 0xf2, 0xf2, 0xe2, + 0xf3, 0xff, 0xe8, 0xe1, 0xe8, 0xe8, 0xef, 0xeb, + 0xff, 0xff, 0xe0, 0xff, 0xff, 0xef, 0xee, 0xef, + 0xe7, 0xe7, 0xf3, 0xff, 0xe8, 0xe7, 0xe7, 0xe7, + 0xe8, 0xe1, 0xe2, 0xee, 0xf3, 0xe2, 0xe2, 0xe8, + 0xff, 0xff, 0xe1, 0xe1, 0xef, 0xee, 0xe7, 0xe8, + 0xee, 0xe7, 0xf3, 0xfb, 0xfb, 0xee, 0xe1, 0xef, + 0xe7, 0xe8, 0xef, 0xef, 0xeb, 0xe9, 0xe8, 0xe9, + 0xf2, 0xe8, 0xe8, 0xe8, 0xe8, 0xff, 0xe8, 0xe8, + 0xe8, 0xee, 0xe7, 0xe8, 0xef, 0xef, 0xee, 0xef, + 0xee, 0xef, 0xee, 0xee, 0xef, 0xee, 0xee, 0xee, + 0xe1, 0xe8, 0xe8, 0xff, 0xe0, 0xe0, 0xe0, 0xf1, + 0xf2, 0xf2, 0xf1, 0xf3, 0xf3, 0xf1, 0xf3, 0xf4, + 0xbe, 0xb3, 0xb2, 0xb7, 0xb6, 0x37, 0xd4, 0xcf, + 0xcf, 0xa0, 0xcc, 0xcf, 0xce, 0x47, 0xd3, 0xd9, + 0xce, 0xd4, 0xc1, 0x58, 0xcd, 0xc5, 0xcd, 0xa0, + 0xc6, 0xd5, 0xcc, 0x4c, 0xd4, 0xcf, 0xcf, 0xa0, + 0xcd, 0xc1, 0xce, 0xd9, 0xa0, 0xd0, 0xc1, 0xd2, + 0xc5, 0xce, 0x53, 0xd3, 0xd4, 0xd2, 0xc9, 0xce, + 0x47, 0xce, 0xcf, 0xa0, 0xc5, 0xce, 0x44, 0xc2, + 0xc1, 0xc4, 0xa0, 0xc2, 0xd2, 0xc1, 0xce, 0xc3, + 0x48, 0xb1, 0xb6, 0xa0, 0xc7, 0xcf, 0xd3, 0xd5, + 0xc2, 0x53, 0xc2, 0xc1, 0xc4, 0xa0, 0xd2, 0xc5, + 0xd4, 0xd5, 0xd2, 0x4e, 0xb1, 0xb6, 0xa0, 0xc6, + 0xcf, 0xd2, 0x53, 0xc2, 0xc1, 0xc4, 0xa0, 0xce, + 0xc5, 0xd8, 0x54, 0xd3, 0xd4, 0xcf, 0xd0, 0xd0, + 0xc5, 0xc4, 0xa0, 0xc1, 0xd4, 0x20, 0xaa, 0xaa, + 0xaa, 0x20, 0xa0, 0xc5, 0xd2, 0xd2, 0x0d, 0xbe, + 0xb2, 0xb5, 0x35, 0xd2, 0xc1, 0xce, 0xc7, 0x45, + 0xc4, 0xc9, 0x4d, 0xd3, 0xd4, 0xd2, 0xa0, 0xcf, + 0xd6, 0xc6, 0x4c, 0xdc, 0x0d, 0xd2, 0xc5, 0xd4, + 0xd9, 0xd0, 0xc5, 0xa0, 0xcc, 0xc9, 0xce, 0xc5, + 0x8d, 0x3f, 0x46, 0xd9, 0x90, 0x03, 0x4c, 0xc3, + 0xe8, 0xa6, 0xcf, 0x9a, 0xa6, 0xce, 0xa0, 0x8d, + 0xd0, 0x02, 0xa0, 0x99, 0x20, 0xc4, 0xe3, 0x86, + 0xce, 0xba, 0x86, 0xcf, 0x20, 0x66, 0xf3, 0x84, + 0xf1, 0xa9, 0xff, 0x85, 0xc8, 0x0a, 0x85, 0xd9, + 0xa2, 0x20, 0xa9, 0x15, 0x20, 0x91, 0xe4, 0xe6, + 0xd9, 0xa6, 0xce, 0xa4, 0xc8, 0x0a, 0x85, 0xce, + 0xc8, 0xb9, 0x00, 0x02, 0xc9, 0x80, 0xf0, 0xd2, + 0x49, 0xb0, 0xc9, 0x0a, 0xb0, 0xf0, 0xc8, 0xc8, + 0x84, 0xc8, 0xb9, 0x00, 0x02, 0x48, 0xb9, 0xff, + 0x01, 0xa0, 0x00, 0x20, 0x08, 0xe7, 0x68, 0x95, + 0xa0, 0xa5, 0xce, 0xc9, 0x33, 0xd0, 0x03, 0x20, + 0x6f, 0xe7, 0x4c, 0x01, 0xe8, 0xff, 0xff, 0xff, + 0x50, 0x20, 0x4f, 0xc0, 0xf4, 0xa1, 0xe4, 0xaf, + 0xad, 0xf2, 0xaf, 0xe4, 0xae, 0xa1, 0xf0, 0xa5, + 0xb4, 0xb3, 0xef, 0xb4, 0xee, 0xa5, 0xa8, 0xb4, + 0x5c, 0x80, 0x00, 0x40, 0x60, 0x8d, 0x60, 0x8b, + 0x7f, 0x1d, 0x20, 0x7e, 0x8c, 0x33, 0x00, 0x00, + 0x60, 0x03, 0xbf, 0x12, 0x47, 0x83, 0xae, 0xa9, + 0x67, 0x83, 0xb2, 0xb0, 0xe5, 0xa3, 0xa1, 0xb2, + 0xb4, 0x79, 0xb0, 0xb3, 0xa4, 0x69, 0xb0, 0xb3, + 0xa4, 0xe5, 0xa3, 0xa1, 0xb2, 0xb4, 0xaf, 0xae, + 0x79, 0xb0, 0xb3, 0xa4, 0xaf, 0xae, 0x69, 0xb0, + 0xb3, 0xa4, 0xaf, 0xae, 0xf0, 0xaf, 0xb0, 0xf4, + 0xb3, 0xa9, 0xac, 0x60, 0x8c, 0x20, 0xb4, 0xb3, + 0xa9, 0xac, 0x00, 0x40, 0x89, 0xc9, 0x47, 0x9d, + 0x17, 0x68, 0x9d, 0x0a, 0x58, 0x7b, 0x67, 0xa2, + 0xa1, 0xb4, 0xb6, 0x67, 0xb4, 0xa1, 0x07, 0x8c, + 0x07, 0xae, 0xa9, 0xac, 0xb6, 0x67, 0xb4, 0xa1, + 0x07, 0x8c, 0x07, 0xae, 0xa9, 0xac, 0xa8, 0x67, + 0x8c, 0x07, 0xb4, 0xaf, 0xac, 0xb0, 0x67, 0x9d, + 0xb2, 0xaf, 0xac, 0xaf, 0xa3, 0x67, 0x8c, 0x07, + 0xa5, 0xab, 0xaf, 0xb0, 0xf4, 0xae, 0xa9, 0xb2, + 0xb0, 0x7f, 0x0e, 0x27, 0xb4, 0xae, 0xa9, 0xb2, + 0xb0, 0x7f, 0x0e, 0x28, 0xb4, 0xae, 0xa9, 0xb2, + 0xb0, 0x64, 0x07, 0xa6, 0xa9, 0x67, 0xaf, 0xb4, + 0xaf, 0xa7, 0x78, 0xb4, 0xa5, 0xac, 0x6b, 0x7f, + 0x02, 0xad, 0xa5, 0xb2, 0x67, 0xa2, 0xb5, 0xb3, + 0xaf, 0xa7, 0xee, 0xb2, 0xb5, 0xb4, 0xa5, 0xb2, + 0x7e, 0x8c, 0x39, 0xb4, 0xb8, 0xa5, 0xae, 0x67, + 0xb0, 0xa5, 0xb4, 0xb3, 0x27, 0xaf, 0xb4, 0x07, + 0x9d, 0x19, 0xb2, 0xaf, 0xa6, 0x7f, 0x05, 0x37, + 0xb4, 0xb5, 0xb0, 0xae, 0xa9, 0x7f, 0x05, 0x28, + 0xb4, 0xb5, 0xb0, 0xae, 0xa9, 0x7f, 0x05, 0x2a, + 0xb4, 0xb5, 0xb0, 0xae, 0xa9, 0xe4, 0xae, 0xa5, + 0x00, 0x47, 0xa2, 0xa1, 0xb4, 0x7f, 0x0d, 0x30, + 0xad, 0xa9, 0xa4, 0x7f, 0x0d, 0x23, 0xad, 0xa9, + 0xa4, 0x67, 0xac, 0xac, 0xa1, 0xa3, 0xf2, 0xa7, + 0xf4, 0xb8, 0xa5, 0xb4, 0x00, 0x4d, 0xcc, 0x67, + 0x8c, 0x68, 0x8c, 0xdb, 0x67, 0x9b, 0x68, 0x9b, + 0x50, 0x8c, 0x63, 0x8c, 0x7f, 0x01, 0x51, 0x07, + 0x88, 0x29, 0x84, 0x80, 0xc4, 0x19, 0x57, 0x71, + 0x07, 0x88, 0x14, 0x71, 0x07, 0x8c, 0x07, 0x88, + 0xae, 0xb2, 0xa3, 0xb3, 0x71, 0x08, 0x88, 0xa3, + 0xb3, 0xa1, 0x71, 0x08, 0x88, 0xae, 0xa5, 0xac, + 0x68, 0x83, 0x08, 0x68, 0x9d, 0x08, 0x71, 0x07, + 0x88, 0x60, 0x75, 0xb4, 0xaf, 0xae, 0x75, 0x8d, + 0x75, 0x8b, 0x51, 0x07, 0x88, 0x19, 0xb8, 0xa4, + 0xae, 0xb2, 0xec, 0xa4, 0xb0, 0xf3, 0xa2, 0xa1, + 0xee, 0xa7, 0xb3, 0xe4, 0xae, 0xb2, 0xeb, 0xa5, + 0xa5, 0xb0, 0x51, 0x07, 0x88, 0x39, 0x81, 0xc1, + 0x4f, 0x7f, 0x0f, 0x2f, 0x00, 0x51, 0x06, 0x88, + 0x29, 0xc2, 0x0c, 0x82, 0x57, 0x8c, 0x6a, 0x8c, + 0x42, 0xae, 0xa5, 0xa8, 0xb4, 0x60, 0xae, 0xa5, + 0xa8, 0xb4, 0x4f, 0x7e, 0x1e, 0x35, 0x8c, 0x27, + 0x51, 0x07, 0x88, 0x09, 0x8b, 0xfe, 0xe4, 0xaf, + 0xad, 0xf2, 0xaf, 0xe4, 0xae, 0xa1, 0xdc, 0xde, + 0x9c, 0xdd, 0x9c, 0xde, 0xdd, 0x9e, 0xc3, 0xdd, + 0xcf, 0xca, 0xcd, 0xcb, 0x00, 0x47, 0x9a, 0xad, + 0xa5, 0xad, 0xaf, 0xac, 0x67, 0x9a, 0xad, 0xa5, + 0xad, 0xa9, 0xa8, 0xee, 0xa1, 0xad, 0x60, 0x8c, + 0x20, 0xaf, 0xb4, 0xb5, 0xa1, 0xf2, 0xac, 0xa3, + 0xf7, 0xa5, 0xae, 0x60, 0x8c, 0x20, 0xac, 0xa5, + 0xa4, 0xee, 0xb5, 0xb2, 0x60, 0xae, 0xb5, 0xb2, + 0xee, 0xaf, 0xa3, 0xe5, 0xb6, 0xa1, 0xb3, 0xe4, + 0xa1, 0xaf, 0xac, 0x7a, 0x7e, 0x9a, 0x22, 0x20, + 0x00, 0x60, 0x03, 0xbf, 0x60, 0x03, 0xbf, 0x1f, + 0x20, 0xb1, 0xe7, 0xe8, 0xe8, 0xb5, 0x4f, 0x85, + 0xda, 0xb5, 0x77, 0x85, 0xdb, 0xb4, 0x4e, 0x98, + 0xd5, 0x76, 0xb0, 0x09, 0xb1, 0xda, 0x20, 0xed, + 0xfd, 0xc8, 0x4c, 0x0f, 0xee, 0xa9, 0xff, 0x85, + 0xd5, 0x60, 0xe8, 0xa9, 0x00, 0x95, 0x78, 0x95, + 0xa0, 0xb5, 0x77, 0x38, 0xf5, 0x4f, 0x95, 0x50, + 0x4c, 0x23, 0xe8, 0xff, 0x20, 0x15, 0xe7, 0xa5, + 0xcf, 0xd0, 0x28, 0xa5, 0xce, 0x60, 0x20, 0x34, + 0xee, 0xa4, 0xc8, 0xc9, 0x30, 0xb0, 0x21, 0xc0, + 0x28, 0xb0, 0x1d, 0x4c, 0x00, 0xf8, 0x20, 0x34, + 0xee, 0x4c, 0x64, 0xf8, 0x46, 0xf8, 0x60, 0x20, + 0xb3, 0xf3, 0xc9, 0x18, 0xb0, 0x0a, 0x85, 0x25, + 0x4c, 0x22, 0xfc, 0xa0, 0x77, 0x4c, 0xe0, 0xe3, + 0xa0, 0x7b, 0xd0, 0xf9, 0x20, 0x54, 0xe2, 0xa5, + 0xda, 0xd0, 0x07, 0xa5, 0xdb, 0xd0, 0x03, 0x4c, + 0x7e, 0xe7, 0x06, 0xce, 0x26, 0xcf, 0x26, 0xe6, + 0x26, 0xe7, 0xa5, 0xe6, 0xc5, 0xda, 0xa5, 0xe7, + 0xe5, 0xdb, 0x90, 0x0a, 0x85, 0xe7, 0xa5, 0xe6, + 0xe5, 0xda, 0x85, 0xe6, 0xe6, 0xce, 0x88, 0xd0, + 0xe1, 0x60, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x20, 0x15, 0xe7, 0x6c, 0xce, 0x00, 0x20, 0x34, + 0xee, 0xc5, 0xc8, 0x90, 0xbb, 0x85, 0x2c, 0x60, + 0x20, 0x34, 0xee, 0xc9, 0x30, 0xb0, 0xb1, 0xa4, + 0xc8, 0x4c, 0x19, 0xf8, 0x20, 0x34, 0xee, 0xc5, + 0xc8, 0x90, 0xa5, 0x85, 0x2d, 0x60, 0x20, 0x34, + 0xee, 0xc9, 0x28, 0xb0, 0x9b, 0xa8, 0xa5, 0xc8, + 0x4c, 0x28, 0xf8, 0x98, 0xaa, 0xa0, 0x6e, 0x20, + 0xc4, 0xe3, 0x8a, 0xa8, 0x20, 0xc4, 0xe3, 0xa0, + 0x72, 0x4c, 0x61, 0xf1, 0x20, 0x3f, 0xf2, 0x06, + 0xce, 0x26, 0xcf, 0x30, 0xfa, 0xb0, 0xdc, 0xd0, + 0x04, 0xc5, 0xce, 0xb0, 0xd6, 0x60, 0x20, 0x15, + 0xe7, 0xb1, 0xce, 0x94, 0x9f, 0x4c, 0x08, 0xe7, + 0x20, 0x34, 0xee, 0xa5, 0xce, 0x85, 0xc8, 0x60, + 0x20, 0x15, 0xe7, 0xa5, 0xc8, 0x91, 0xce, 0x60, + 0x20, 0x6c, 0xee, 0xa5, 0xce, 0x85, 0xe6, 0xa5, + 0xcf, 0x85, 0xe7, 0x4c, 0x44, 0xe2, 0x20, 0xe4, + 0xee, 0x4c, 0x34, 0xe1, 0x20, 0xe4, 0xee, 0xb4, + 0x78, 0xb5, 0x50, 0x69, 0xfe, 0xb0, 0x01, 0x88, + 0x85, 0xda, 0x84, 0xdb, 0x18, 0x65, 0xce, 0x95, + 0x50, 0x98, 0x65, 0xcf, 0x95, 0x78, 0xa0, 0x00, + 0xb5, 0x50, 0xd1, 0xda, 0xc8, 0xb5, 0x78, 0xf1, + 0xda, 0xb0, 0x80, 0x4c, 0x23, 0xe8, 0x20, 0x15, + 0xe7, 0xa5, 0x4e, 0x20, 0x08, 0xe7, 0xa5, 0x4f, + 0xd0, 0x04, 0xc5, 0x4e, 0x69, 0x00, 0x29, 0x7f, + 0x85, 0x4f, 0x95, 0xa0, 0xa0, 0x11, 0xa5, 0x4f, + 0x0a, 0x18, 0x69, 0x40, 0x0a, 0x26, 0x4e, 0x26, + 0x4f, 0x88, 0xd0, 0xf2, 0xa5, 0xce, 0x20, 0x08, + 0xe7, 0xa5, 0xcf, 0x95, 0xa0, 0x4c, 0x7a, 0xe2, + 0x20, 0x15, 0xe7, 0xa4, 0xce, 0xc4, 0x4a, 0xa5, + 0xcf, 0xe5, 0x4b, 0x90, 0x1e, 0x84, 0x4c, 0xa5, + 0xcf, 0x85, 0x4d, 0x4c, 0xad, 0xe5, 0x20, 0x15, + 0xe7, 0xa4, 0xce, 0xc4, 0x4c, 0xa5, 0xcf, 0xe5, + 0x4d, 0xb0, 0x08, 0x84, 0x4a, 0xa5, 0xcf, 0x85, + 0x4b, 0x90, 0xe8, 0x4c, 0xcb, 0xee, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x20, 0x71, + 0xe1, 0x4c, 0xbf, 0xef, 0x20, 0x03, 0xee, 0xa9, + 0xff, 0x85, 0xc8, 0xa9, 0x80, 0x8d, 0x00, 0x02, + 0x60, 0x20, 0x36, 0xe7, 0xe8, 0x20, 0x36, 0xe7, + 0xb5, 0x50, 0x60, 0xa9, 0x00, 0x85, 0x4a, 0x85, + 0x4c, 0xa9, 0x08, 0x85, 0x4b, 0xa9, 0x10, 0x85, + 0x4d, 0x4c, 0xad, 0xe5, 0xd5, 0x78, 0xd0, 0x01, + 0x18, 0x4c, 0x02, 0xe1, 0x20, 0xb7, 0xe5, 0x4c, + 0x36, 0xe8, 0x20, 0xb7, 0xe5, 0x4c, 0x5b, 0xe8, + 0xe0, 0x80, 0xd0, 0x01, 0x88, 0x4c, 0x0c, 0xe0, + 0xa0, 0x00, 0x84, 0xa0, 0x84, 0x4a, 0x84, 0x4c, + 0xa9, 0x08, 0x85, 0x4b, 0x85, 0x4d, 0xe6, 0x4d, + 0xb1, 0x4c, 0x49, 0xff, 0x91, 0x4c, 0xd1, 0x4c, + 0xd0, 0x08, 0x49, 0xff, 0x91, 0x4c, 0xd1, 0x4c, + 0xf0, 0xec, 0x4c, 0xad, 0xe5, 0x4c, 0x79, 0xf1, + 0x20, 0x32, 0xf0, 0x4c, 0xbe, 0xe8, 0xa6, 0xe0, + 0xa5, 0xe1, 0xac, 0x00, 0xc0, 0xc0, 0x83, 0xd0, + 0xec, 0x2c, 0x10, 0xc0, 0x86, 0x50, 0x85, 0x51, + 0xa5, 0xdc, 0x85, 0x78, 0xa5, 0xdd, 0x85, 0x79, + 0x4c, 0xc3, 0xe8, 0xff, 0xff, 0x20, 0x15, 0xe7, + 0x86, 0xd8, 0xa2, 0xfe, 0x38, 0xb5, 0xd0, 0x95, + 0xe6, 0xb5, 0x4e, 0xf5, 0xd0, 0x95, 0xdc, 0xe8, + 0xd0, 0xf3, 0x90, 0x4b, 0xca, 0xb5, 0xcb, 0x95, + 0xe7, 0xf5, 0xdb, 0x95, 0xe5, 0xe8, 0xf0, 0xf5, + 0x90, 0x0a, 0xa5, 0xcc, 0xc5, 0xe4, 0xa5, 0xcd, + 0xe5, 0xe5, 0x90, 0x13, 0x4c, 0x6b, 0xe3, 0xb1, + 0xe6, 0x91, 0xe4, 0xe6, 0xe4, 0xd0, 0x02, 0xe6, + 0xe5, 0xe6, 0xe6, 0xd0, 0x02, 0xe6, 0xe7, 0xa5, + 0xe6, 0xc5, 0x4c, 0xa5, 0xe7, 0xe5, 0x4d, 0x90, + 0xe6, 0xa2, 0xfe, 0xb5, 0xe6, 0x95, 0x4e, 0xb5, + 0xcc, 0xf5, 0xdc, 0x95, 0xcc, 0xe8, 0xd0, 0xf3, + 0xa6, 0xd8, 0x60, 0xb1, 0x4c, 0x91, 0xce, 0xa5, + 0xce, 0xd0, 0x02, 0xc6, 0xcf, 0xc6, 0xce, 0xa5, + 0x4c, 0xd0, 0x02, 0xc6, 0x4d, 0xc6, 0x4c, 0xc5, + 0xca, 0xa5, 0x4d, 0xe5, 0xcb, 0x90, 0xe4, 0xb0, + 0xd0, 0x20, 0x15, 0xe7, 0xa4, 0xce, 0xc0, 0xca, + 0xa5, 0xcf, 0xe5, 0xcb, 0xb0, 0xa6, 0x84, 0x4a, + 0xa5, 0xcf, 0x85, 0x4b, 0x4c, 0xb7, 0xe5, 0x86, + 0xd8, 0x20, 0x1e, 0xf1, 0x20, 0xfd, 0xfe, 0xa2, + 0xff, 0x38, 0xb5, 0x4d, 0xf5, 0xcf, 0x95, 0xdb, + 0xe8, 0xf0, 0xf7, 0x90, 0x87, 0xa5, 0xcc, 0xc5, + 0xda, 0xa5, 0xcd, 0xe5, 0xdb, 0xb0, 0xd5, 0xa5, + 0xce, 0xd0, 0x04, 0xa5, 0xcf, 0xf0, 0x11, 0xa5, + 0xda, 0x85, 0xca, 0xa5, 0xdb, 0x85, 0xcb, 0x20, + 0x2c, 0xf1, 0x20, 0xfd, 0xfe, 0xa6, 0xd8, 0x60, + 0x20, 0x3a, 0xff, 0x4c, 0x15, 0xf1, 0xa0, 0xce, + 0x84, 0x3c, 0xc8, 0x84, 0x3e, 0xa0, 0x00, 0x84, + 0x3d, 0x84, 0x3f, 0x60, 0xb5, 0xca, 0x95, 0x3c, + 0xb4, 0x4c, 0x94, 0x3e, 0xca, 0x10, 0xf5, 0xa5, + 0x3e, 0xd0, 0x02, 0xc6, 0x3f, 0xc6, 0x3e, 0x60, + 0x86, 0xd8, 0x38, 0xa2, 0xff, 0xb5, 0x4d, 0xf5, + 0xcb, 0x95, 0xcf, 0xe8, 0xf0, 0xf7, 0x20, 0x1e, + 0xf1, 0x20, 0xcd, 0xfe, 0xa2, 0x01, 0x20, 0x2c, + 0xf1, 0xa9, 0x1a, 0x20, 0xcf, 0xfe, 0xa6, 0xd8, + 0x60, 0x20, 0xc4, 0xe3, 0x4c, 0x3a, 0xff, 0xa5, + 0xfc, 0xd0, 0x03, 0x4c, 0xa5, 0xe8, 0xc6, 0xfc, + 0x60, 0xa9, 0xff, 0x85, 0xa0, 0x60, 0x46, 0xa0, + 0x60, 0x24, 0xa0, 0x10, 0x19, 0xa9, 0xa3, 0x20, + 0xed, 0xfd, 0xa0, 0x01, 0xb1, 0xdc, 0xaa, 0xc8, + 0xb1, 0xdc, 0x20, 0x1b, 0xe5, 0xa9, 0xa0, 0x4c, + 0xed, 0xfd, 0xa5, 0xdc, 0xa4, 0xdd, 0x60, 0xc1, + 0x00, 0x7f, 0xd1, 0xcc, 0xc7, 0xcf, 0xce, 0xc5, + 0x9a, 0x98, 0x8d, 0x96, 0x95, 0x93, 0xbf, 0xb2, + 0x32, 0x12, 0x0f, 0xbc, 0xb0, 0xac, 0xbe, 0x35, + 0x0c, 0x61, 0x30, 0x10, 0x0b, 0xdd, 0xfb, 0xa0, + 0x00, 0x20, 0xc7, 0xe7, 0xa9, 0xa0, 0x4c, 0xed, + 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xa4, 0x4a, 0xa5, 0x4b, 0x48, 0xc4, 0xda, + 0xe5, 0xdb, 0xb0, 0x1c, 0x68, 0x84, 0xd0, 0x85, + 0xd1, 0xa0, 0xff, 0xc8, 0xb1, 0xd0, 0x30, 0xfb, + 0xc9, 0x40, 0xf0, 0xf7, 0xc8, 0xc8, 0xb1, 0xd0, + 0x48, 0x88, 0xb1, 0xd0, 0xa8, 0x68, 0xd0, 0xdd, + 0x68, 0xa0, 0x00, 0xb1, 0xd0, 0x30, 0x05, 0x4a, + 0xf0, 0x08, 0xa9, 0xa4, 0x20, 0xed, 0xfd, 0xc8, + 0xd0, 0xf1, 0xa9, 0xbd, 0x4c, 0xed, 0xfd, 0x91, + 0xda, 0xe8, 0xb5, 0x9f, 0xf0, 0x30, 0x4c, 0xd5, + 0xf3, 0xa0, 0x30, 0x07, 0xa5, 0xdc, 0xa4, 0xdd, + 0x20, 0x7d, 0xf1, 0x20, 0xc9, 0xf1, 0xa6, 0xd8, + 0x4c, 0xb7, 0xf1, 0xe8, 0xe8, 0xb5, 0x9f, 0xf0, + 0x1f, 0x4c, 0xe0, 0xf3, 0x30, 0x07, 0xa5, 0xdc, + 0xa4, 0xdd, 0x20, 0x7d, 0xf1, 0x20, 0xc9, 0xf1, + 0xa6, 0xd8, 0x4c, 0x09, 0xf4, 0xe8, 0x60, 0x20, + 0x15, 0xe7, 0xe6, 0xce, 0xd0, 0x02, 0xe6, 0xcf, + 0x60, 0x20, 0x5b, 0xf2, 0xd0, 0x15, 0x20, 0x53, + 0xf2, 0xd0, 0x10, 0x20, 0x82, 0xe7, 0x20, 0x6f, + 0xe7, 0x50, 0x03, 0x20, 0x82, 0xe7, 0x20, 0x59, + 0xe7, 0x56, 0x50, 0x4c, 0x36, 0xe7, 0x20, 0xc9, + 0xef, 0x15, 0x4f, 0x10, 0x05, 0x20, 0xc9, 0xef, + 0x35, 0x4f, 0x95, 0x50, 0x10, 0xed, 0x4c, 0xc9, + 0xef, 0x20, 0x15, 0xe7, 0xa4, 0xfb, 0xa5, 0xce, + 0x99, 0x5f, 0x01, 0xa5, 0xcf, 0x4c, 0x66, 0xe9, + 0x99, 0x50, 0x01, 0x88, 0x30, 0x51, 0xb9, 0x40, + 0x01, 0xd5, 0x50, 0xd0, 0xf6, 0xb9, 0x50, 0x01, + 0xd5, 0x78, 0xd0, 0xef, 0xc6, 0xfb, 0xb9, 0x41, + 0x01, 0x99, 0x40, 0x01, 0xb9, 0x51, 0x01, 0x99, + 0x50, 0x01, 0xb9, 0xc1, 0x01, 0x99, 0xc0, 0x01, + 0xb9, 0xd1, 0x01, 0x99, 0xd0, 0x01, 0xb9, 0x61, + 0x01, 0x99, 0x60, 0x01, 0xb9, 0x71, 0x01, 0x99, + 0x70, 0x01, 0xb9, 0x81, 0x01, 0x99, 0x80, 0x01, + 0xb9, 0x91, 0x01, 0x99, 0x90, 0x01, 0xb9, 0xa1, + 0x01, 0x99, 0xa0, 0x01, 0xb9, 0xa1, 0x01, 0x99, + 0xa0, 0x01, 0xc8, 0xc4, 0xfb, 0x90, 0xbf, 0x60, + 0xe8, 0xa9, 0x00, 0x48, 0xb5, 0x50, 0x38, 0xe9, + 0x03, 0x85, 0xce, 0xb5, 0x78, 0xe9, 0x00, 0x85, + 0xcf, 0x68, 0xa0, 0x00, 0x91, 0xce, 0xe8, 0x60, + 0xc9, 0x85, 0xb0, 0x03, 0x4c, 0xc0, 0xe4, 0xa0, + 0x02, 0x4c, 0x48, 0xe4, 0xe8, 0xa9, 0x01, 0xd0, + 0xda, 0xe8, 0xa5, 0x78, 0x85, 0xdc, 0xa5, 0x79, + 0x85, 0xdd, 0xa5, 0x50, 0xa4, 0x51, 0x4c, 0x75, + 0xe8, 0xa9, 0x01, 0xd0, 0xc6, 0xb5, 0x50, 0xd5, + 0x78, 0x90, 0x03, 0x4c, 0x68, 0xee, 0xa8, 0xb5, + 0x51, 0x85, 0xce, 0xb5, 0x79, 0x85, 0xcf, 0xb1, + 0xce, 0xa0, 0x00, 0xe8, 0xe8, 0x20, 0x08, 0xe7, + 0x4c, 0x04, 0xf4, 0x20, 0x34, 0xee, 0x86, 0xd8, + 0x29, 0x03, 0xaa, 0x20, 0x1e, 0xfb, 0xa6, 0xd8, + 0x98, 0xa0, 0x00, 0x20, 0x08, 0xe7, 0x94, 0xa0, + 0x60, 0x20, 0x75, 0xfd, 0x8a, 0x48, 0xbd, 0x00, + 0x02, 0xc9, 0x83, 0xd0, 0x03, 0x4c, 0x03, 0xe0, + 0xca, 0x10, 0xf3, 0x68, 0xaa, 0x60, 0x20, 0x80, + 0xe2, 0x98, 0xaa, 0x20, 0x54, 0xf3, 0x8a, 0xa8, + 0x60, 0x20, 0x15, 0xe7, 0xa5, 0xcf, 0x10, 0x08, + 0x98, 0xca, 0x20, 0x08, 0xe7, 0x94, 0xa0, 0x60, + 0x85, 0xd1, 0xa5, 0xce, 0x85, 0xd0, 0x20, 0x15, + 0xe7, 0xa5, 0xce, 0x85, 0xd2, 0xa5, 0xcf, 0x85, + 0xd3, 0xa9, 0x01, 0x20, 0x08, 0xe7, 0x94, 0xa0, + 0xa5, 0xd0, 0xd0, 0x04, 0xc6, 0xd1, 0x30, 0xdf, + 0xc6, 0xd0, 0xa5, 0xd2, 0xa0, 0x00, 0x20, 0x08, + 0xe7, 0xa5, 0xd3, 0x95, 0xa0, 0x20, 0x22, 0xe2, + 0x4c, 0x98, 0xf3, 0x20, 0x34, 0xee, 0x18, 0x69, + 0xff, 0x60, 0x20, 0xb1, 0xe7, 0x46, 0xd5, 0x60, + 0x86, 0xd9, 0x9a, 0x20, 0x2e, 0xf0, 0x4c, 0x83, + 0xe8, 0x20, 0x34, 0xee, 0x86, 0xd8, 0x20, 0x95, + 0xfe, 0xa6, 0xd8, 0x60, 0xfe, 0x24, 0xd9, 0x10, + 0xe0, 0x86, 0xd8, 0x24, 0xa0, 0x4c, 0x12, 0xf2, + 0x24, 0xd9, 0x10, 0xd5, 0x86, 0xd8, 0x24, 0xa0, + 0x4c, 0x2c, 0xf2, 0xa0, 0x00, 0x4c, 0xff, 0xe6, + 0xa8, 0x20, 0x8e, 0xfd, 0x98, 0x38, 0xe5, 0x21, + 0xb0, 0xf6, 0x84, 0x24, 0x60, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x94, 0xa0, 0x4c, 0x23, + 0xe8, 0xa0, 0x00, 0xf0, 0x04, 0x20, 0xed, 0xfd, + 0xc8, 0xb1, 0xda, 0x30, 0xf8, 0xa9, 0xff, 0x85, + 0xd5, 0x60, 0x20, 0x34, 0xee, 0x86, 0xd8, 0x20, + 0x8b, 0xfe, 0xa6, 0xd8, 0x60, 0x18, 0xa2, 0x02, + 0xb5, 0xf9, 0x75, 0xf5, 0x95, 0xf9, 0xca, 0x10, + 0xf7, 0x60, 0x06, 0xf3, 0x20, 0x37, 0xf4, 0x24, + 0xf9, 0x10, 0x05, 0x20, 0xa4, 0xf4, 0xe6, 0xf3, + 0x38, 0xa2, 0x04, 0x94, 0xfb, 0xb5, 0xf7, 0xb4, + 0xf3, 0x94, 0xf7, 0x95, 0xf3, 0xca, 0xd0, 0xf3, + 0x60, 0xa9, 0x8e, 0x85, 0xf8, 0xa5, 0xf9, 0xc9, + 0xc0, 0x30, 0x0c, 0xc6, 0xf8, 0x06, 0xfb, 0x26, + 0xfa, 0x26, 0xf9, 0xa5, 0xf8, 0xd0, 0xee, 0x60, + 0x20, 0xa4, 0xf4, 0x20, 0x7b, 0xf4, 0xa5, 0xf4, + 0xc5, 0xf8, 0xd0, 0xf7, 0x20, 0x25, 0xf4, 0x50, + 0xea, 0x70, 0x05, 0x90, 0xc4, 0xa5, 0xf9, 0x0a, + 0xe6, 0xf8, 0xf0, 0x75, 0xa2, 0xfa, 0x76, 0xff, + 0xe8, 0xd0, 0xfb, 0x60, 0x20, 0x32, 0xf4, 0x65, + 0xf8, 0x20, 0xe2, 0xf4, 0x18, 0x20, 0x84, 0xf4, + 0x90, 0x03, 0x20, 0x25, 0xf4, 0x88, 0x10, 0xf5, + 0x46, 0xf3, 0x90, 0xbf, 0x38, 0xa2, 0x03, 0xa9, + 0x00, 0xf5, 0xf8, 0x95, 0xf8, 0xca, 0xd0, 0xf7, + 0xf0, 0xc5, 0x20, 0x32, 0xf4, 0xe5, 0xf8, 0x20, + 0xe2, 0xf4, 0x38, 0xa2, 0x02, 0xb5, 0xf5, 0xf5, + 0xfc, 0x48, 0xca, 0x10, 0xf8, 0xa2, 0xfd, 0x68, + 0x90, 0x02, 0x95, 0xf8, 0xe8, 0xd0, 0xf8, 0x26, + 0xfb, 0x26, 0xfa, 0x26, 0xf9, 0x06, 0xf7, 0x26, + 0xf6, 0x26, 0xf5, 0xb0, 0x1c, 0x88, 0xd0, 0xda, + 0xf0, 0xbe, 0x86, 0xfb, 0x86, 0xfa, 0x86, 0xf9, + 0xb0, 0x0d, 0x30, 0x04, 0x68, 0x68, 0x90, 0xb2, + 0x49, 0x80, 0x85, 0xf8, 0xa0, 0x17, 0x60, 0x10, + 0xf7, 0x4c, 0xf5, 0x03, 0xff, 0xff, 0xff, 0xff, + 0xe9, 0x81, 0x4a, 0xd0, 0x14, 0xa4, 0x3f, 0xa6, + 0x3e, 0xd0, 0x01, 0x88, 0xca, 0x8a, 0x18, 0xe5, + 0x3a, 0x85, 0x3e, 0x10, 0x01, 0xc8, 0x98, 0xe5, + 0x3b, 0xd0, 0x6b, 0xa4, 0x2f, 0xb9, 0x3d, 0x00, + 0x91, 0x3a, 0x88, 0x10, 0xf8, 0x20, 0x1a, 0xfc, + 0x20, 0x1a, 0xfc, 0x20, 0xd0, 0xf8, 0x20, 0x53, + 0xf9, 0x84, 0x3b, 0x85, 0x3a, 0x4c, 0x95, 0xf5, + 0x20, 0xbe, 0xff, 0xa4, 0x34, 0x20, 0xa7, 0xff, + 0x84, 0x34, 0xa0, 0x17, 0x88, 0x30, 0x4b, 0xd9, + 0xcc, 0xff, 0xd0, 0xf8, 0xc0, 0x15, 0xd0, 0xe8, + 0xa5, 0x31, 0xa0, 0x00, 0xc6, 0x34, 0x20, 0x00, + 0xfe, 0x4c, 0x95, 0xf5, 0xa5, 0x3d, 0x20, 0x8e, + 0xf8, 0xaa, 0xbd, 0x00, 0xfa, 0xc5, 0x42, 0xd0, + 0x13, 0xbd, 0xc0, 0xf9, 0xc5, 0x43, 0xd0, 0x0c, + 0xa5, 0x44, 0xa4, 0x2e, 0xc0, 0x9d, 0xf0, 0x88, + 0xc5, 0x2e, 0xf0, 0x9f, 0xc6, 0x3d, 0xd0, 0xdc, + 0xe6, 0x44, 0xc6, 0x35, 0xf0, 0xd6, 0xa4, 0x34, + 0x98, 0xaa, 0x20, 0x4a, 0xf9, 0xa9, 0xde, 0x20, + 0xed, 0xfd, 0x20, 0x3a, 0xff, 0xa9, 0xa1, 0x85, + 0x33, 0x20, 0x67, 0xfd, 0x20, 0xc7, 0xff, 0xad, + 0x00, 0x02, 0xc9, 0xa0, 0xf0, 0x13, 0xc8, 0xc9, + 0xa4, 0xf0, 0x92, 0x88, 0x20, 0xa7, 0xff, 0xc9, + 0x93, 0xd0, 0xd5, 0x8a, 0xf0, 0xd2, 0x20, 0x78, + 0xfe, 0xa9, 0x03, 0x85, 0x3d, 0x20, 0x34, 0xf6, + 0x0a, 0xe9, 0xbe, 0xc9, 0xc2, 0x90, 0xc1, 0x0a, + 0x0a, 0xa2, 0x04, 0x0a, 0x26, 0x42, 0x26, 0x43, + 0xca, 0x10, 0xf8, 0xc6, 0x3d, 0xf0, 0xf4, 0x10, + 0xe4, 0xa2, 0x05, 0x20, 0x34, 0xf6, 0x84, 0x34, + 0xdd, 0xb4, 0xf9, 0xd0, 0x13, 0x20, 0x34, 0xf6, + 0xdd, 0xba, 0xf9, 0xf0, 0x0d, 0xbd, 0xba, 0xf9, + 0xf0, 0x07, 0xc9, 0xa4, 0xf0, 0x03, 0xa4, 0x34, + 0x18, 0x88, 0x26, 0x44, 0xe0, 0x03, 0xd0, 0x0d, + 0x20, 0xa7, 0xff, 0xa5, 0x3f, 0xf0, 0x01, 0xe8, + 0x86, 0x35, 0xa2, 0x03, 0x88, 0x86, 0x3d, 0xca, + 0x10, 0xc9, 0xa5, 0x44, 0x0a, 0x0a, 0x05, 0x35, + 0xc9, 0x20, 0xb0, 0x06, 0xa6, 0x35, 0xf0, 0x02, + 0x09, 0x80, 0x85, 0x44, 0x84, 0x34, 0xb9, 0x00, + 0x02, 0xc9, 0xbb, 0xf0, 0x04, 0xc9, 0x8d, 0xd0, + 0x80, 0x4c, 0x5c, 0xf5, 0xb9, 0x00, 0x02, 0xc8, + 0xc9, 0xa0, 0xf0, 0xf8, 0x60, 0x20, 0x7d, 0xf4, + 0xa5, 0xf8, 0x10, 0x13, 0xc9, 0x8e, 0xd0, 0xf5, + 0x24, 0xf9, 0x10, 0x0a, 0xa5, 0xfb, 0xf0, 0x06, + 0xe6, 0xfa, 0xd0, 0x02, 0xe6, 0xf9, 0x60, 0xa9, + 0x00, 0x85, 0xf9, 0x85, 0xfa, 0x60, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4c, 0x92, + 0xf5, 0x84, 0x58, 0x86, 0x57, 0x85, 0x56, 0x08, + 0x68, 0x85, 0x59, 0xba, 0xe8, 0xe8, 0xbd, 0x00, + 0x01, 0x0a, 0x0a, 0x0a, 0x0a, 0x60, 0xa4, 0x58, + 0xa6, 0x57, 0xa5, 0x59, 0x48, 0xa5, 0x56, 0x28, + 0x60, 0x20, 0x4a, 0xff, 0x68, 0x85, 0x1e, 0x68, + 0x85, 0x1f, 0x20, 0x98, 0xf6, 0x4c, 0x92, 0xf6, + 0xe6, 0x1e, 0xd0, 0x02, 0xe6, 0x1f, 0xa9, 0xf7, + 0x48, 0xa0, 0x00, 0xb1, 0x1e, 0x29, 0x0f, 0x0a, + 0xaa, 0x4a, 0x51, 0x1e, 0xf0, 0x0b, 0x86, 0x1d, + 0x4a, 0x4a, 0x4a, 0xa8, 0xb9, 0xe1, 0xf6, 0x48, + 0x60, 0xe6, 0x1e, 0xd0, 0x02, 0xe6, 0x1f, 0xbd, + 0xe4, 0xf6, 0x48, 0xa5, 0x1d, 0x4a, 0x60, 0x68, + 0x68, 0x20, 0x3f, 0xff, 0x6c, 0x1e, 0x00, 0xb1, + 0x1e, 0x95, 0x01, 0x88, 0xb1, 0x1e, 0x95, 0x00, + 0x98, 0x38, 0x65, 0x1e, 0x85, 0x1e, 0x90, 0x02, + 0xe6, 0x1f, 0x60, 0x02, 0xf9, 0x04, 0x9d, 0x0d, + 0x9e, 0x25, 0xaf, 0x16, 0xb2, 0x47, 0xb9, 0x51, + 0xc0, 0x2f, 0xc9, 0x5b, 0xd2, 0x85, 0xdd, 0x6e, + 0x05, 0x33, 0xe8, 0x70, 0x93, 0x1e, 0xe7, 0x65, + 0xe7, 0xe7, 0xe7, 0x10, 0xca, 0xb5, 0x00, 0x85, + 0x00, 0xb5, 0x01, 0x85, 0x01, 0x60, 0xa5, 0x00, + 0x95, 0x00, 0xa5, 0x01, 0x95, 0x01, 0x60, 0xa5, + 0x00, 0x81, 0x00, 0xa0, 0x00, 0x84, 0x1d, 0xf6, + 0x00, 0xd0, 0x02, 0xf6, 0x01, 0x60, 0xa1, 0x00, + 0x85, 0x00, 0xa0, 0x00, 0x84, 0x01, 0xf0, 0xed, + 0xa0, 0x00, 0xf0, 0x06, 0x20, 0x66, 0xf7, 0xa1, + 0x00, 0xa8, 0x20, 0x66, 0xf7, 0xa1, 0x00, 0x85, + 0x00, 0x84, 0x01, 0xa0, 0x00, 0x84, 0x1d, 0x60, + 0x20, 0x26, 0xf7, 0xa1, 0x00, 0x85, 0x01, 0x4c, + 0x1f, 0xf7, 0x20, 0x17, 0xf7, 0xa5, 0x01, 0x81, + 0x00, 0x4c, 0x1f, 0xf7, 0x20, 0x66, 0xf7, 0xa5, + 0x00, 0x81, 0x00, 0x4c, 0x43, 0xf7, 0xb5, 0x00, + 0xd0, 0x02, 0xd6, 0x01, 0xd6, 0x00, 0x60, 0xa0, + 0x00, 0x38, 0xa5, 0x00, 0xf5, 0x00, 0x99, 0x00, + 0x00, 0xa5, 0x01, 0xf5, 0x01, 0x99, 0x01, 0x00, + 0x98, 0x69, 0x00, 0x85, 0x1d, 0x60, 0xa5, 0x00, + 0x75, 0x00, 0x85, 0x00, 0xa5, 0x01, 0x75, 0x01, + 0xa0, 0x00, 0xf0, 0xe9, 0xa5, 0x1e, 0x20, 0x19, + 0xf7, 0xa5, 0x1f, 0x20, 0x19, 0xf7, 0x18, 0xb0, + 0x0e, 0xb1, 0x1e, 0x10, 0x01, 0x88, 0x65, 0x1e, + 0x85, 0x1e, 0x98, 0x65, 0x1f, 0x85, 0x1f, 0x60, + 0xb0, 0xec, 0x60, 0x0a, 0xaa, 0xb5, 0x01, 0x10, + 0xe8, 0x60, 0x0a, 0xaa, 0xb5, 0x01, 0x30, 0xe1, + 0x60, 0x0a, 0xaa, 0xb5, 0x00, 0x15, 0x01, 0xf0, + 0xd8, 0x60, 0x0a, 0xaa, 0xb5, 0x00, 0x15, 0x01, + 0xd0, 0xcf, 0x60, 0x0a, 0xaa, 0xb5, 0x00, 0x35, + 0x01, 0x49, 0xff, 0xf0, 0xc4, 0x60, 0x0a, 0xaa, + 0xb5, 0x00, 0x35, 0x01, 0x49, 0xff, 0xd0, 0xb9, + 0x60, 0xa2, 0x18, 0x20, 0x66, 0xf7, 0xa1, 0x00, + 0x85, 0x1f, 0x20, 0x66, 0xf7, 0xa1, 0x00, 0x85, + 0x1e, 0x60, 0x4c, 0xc7, 0xf6, 0xf6, 0xff, 0xff, + 0x4a, 0x08, 0x20, 0x47, 0xf8, 0x28, 0xa9, 0x0f, + 0x90, 0x02, 0x69, 0xe0, 0x85, 0x2e, 0xb1, 0x26, + 0x45, 0x30, 0x25, 0x2e, 0x51, 0x26, 0x91, 0x26, + 0x60, 0x20, 0x00, 0xf8, 0xc4, 0x2c, 0xb0, 0x11, + 0xc8, 0x20, 0x0e, 0xf8, 0x90, 0xf6, 0x69, 0x01, + 0x48, 0x20, 0x00, 0xf8, 0x68, 0xc5, 0x2d, 0x90, + 0xf5, 0x60, 0xa0, 0x2f, 0xd0, 0x02, 0xa0, 0x27, + 0x84, 0x2d, 0xa0, 0x27, 0xa9, 0x00, 0x85, 0x30, + 0x20, 0x28, 0xf8, 0x88, 0x10, 0xf6, 0x60, 0x48, + 0x4a, 0x29, 0x03, 0x09, 0x04, 0x85, 0x27, 0x68, + 0x29, 0x18, 0x90, 0x02, 0x69, 0x7f, 0x85, 0x26, + 0x0a, 0x0a, 0x05, 0x26, 0x85, 0x26, 0x60, 0xa5, + 0x30, 0x18, 0x69, 0x03, 0x29, 0x0f, 0x85, 0x30, + 0x0a, 0x0a, 0x0a, 0x0a, 0x05, 0x30, 0x85, 0x30, + 0x60, 0x4a, 0x08, 0x20, 0x47, 0xf8, 0xb1, 0x26, + 0x28, 0x90, 0x04, 0x4a, 0x4a, 0x4a, 0x4a, 0x29, + 0x0f, 0x60, 0xa6, 0x3a, 0xa4, 0x3b, 0x20, 0x96, + 0xfd, 0x20, 0x48, 0xf9, 0xa1, 0x3a, 0xa8, 0x4a, + 0x90, 0x09, 0x6a, 0xb0, 0x10, 0xc9, 0xa2, 0xf0, + 0x0c, 0x29, 0x87, 0x4a, 0xaa, 0xbd, 0x62, 0xf9, + 0x20, 0x79, 0xf8, 0xd0, 0x04, 0xa0, 0x80, 0xa9, + 0x00, 0xaa, 0xbd, 0xa6, 0xf9, 0x85, 0x2e, 0x29, + 0x03, 0x85, 0x2f, 0x98, 0x29, 0x8f, 0xaa, 0x98, + 0xa0, 0x03, 0xe0, 0x8a, 0xf0, 0x0b, 0x4a, 0x90, + 0x08, 0x4a, 0x4a, 0x09, 0x20, 0x88, 0xd0, 0xfa, + 0xc8, 0x88, 0xd0, 0xf2, 0x60, 0xff, 0xff, 0xff, + 0x20, 0x82, 0xf8, 0x48, 0xb1, 0x3a, 0x20, 0xda, + 0xfd, 0xa2, 0x01, 0x20, 0x4a, 0xf9, 0xc4, 0x2f, + 0xc8, 0x90, 0xf1, 0xa2, 0x03, 0xc0, 0x04, 0x90, + 0xf2, 0x68, 0xa8, 0xb9, 0xc0, 0xf9, 0x85, 0x2c, + 0xb9, 0x00, 0xfa, 0x85, 0x2d, 0xa9, 0x00, 0xa0, + 0x05, 0x06, 0x2d, 0x26, 0x2c, 0x2a, 0x88, 0xd0, + 0xf8, 0x69, 0xbf, 0x20, 0xed, 0xfd, 0xca, 0xd0, + 0xec, 0x20, 0x48, 0xf9, 0xa4, 0x2f, 0xa2, 0x06, + 0xe0, 0x03, 0xf0, 0x1c, 0x06, 0x2e, 0x90, 0x0e, + 0xbd, 0xb3, 0xf9, 0x20, 0xed, 0xfd, 0xbd, 0xb9, + 0xf9, 0xf0, 0x03, 0x20, 0xed, 0xfd, 0xca, 0xd0, + 0xe7, 0x60, 0x88, 0x30, 0xe7, 0x20, 0xda, 0xfd, + 0xa5, 0x2e, 0xc9, 0xe8, 0xb1, 0x3a, 0x90, 0xf2, + 0x20, 0x56, 0xf9, 0xaa, 0xe8, 0xd0, 0x01, 0xc8, + 0x98, 0x20, 0xda, 0xfd, 0x8a, 0x4c, 0xda, 0xfd, + 0xa2, 0x03, 0xa9, 0xa0, 0x20, 0xed, 0xfd, 0xca, + 0xd0, 0xf8, 0x60, 0x38, 0xa5, 0x2f, 0xa4, 0x3b, + 0xaa, 0x10, 0x01, 0x88, 0x65, 0x3a, 0x90, 0x01, + 0xc8, 0x60, 0x04, 0x20, 0x54, 0x30, 0x0d, 0x80, + 0x04, 0x90, 0x03, 0x22, 0x54, 0x33, 0x0d, 0x80, + 0x04, 0x90, 0x04, 0x20, 0x54, 0x33, 0x0d, 0x80, + 0x04, 0x90, 0x04, 0x20, 0x54, 0x3b, 0x0d, 0x80, + 0x04, 0x90, 0x00, 0x22, 0x44, 0x33, 0x0d, 0xc8, + 0x44, 0x00, 0x11, 0x22, 0x44, 0x33, 0x0d, 0xc8, + 0x44, 0xa9, 0x01, 0x22, 0x44, 0x33, 0x0d, 0x80, + 0x04, 0x90, 0x01, 0x22, 0x44, 0x33, 0x0d, 0x80, + 0x04, 0x90, 0x26, 0x31, 0x87, 0x9a, 0x00, 0x21, + 0x81, 0x82, 0x00, 0x00, 0x59, 0x4d, 0x91, 0x92, + 0x86, 0x4a, 0x85, 0x9d, 0xac, 0xa9, 0xac, 0xa3, + 0xa8, 0xa4, 0xd9, 0x00, 0xd8, 0xa4, 0xa4, 0x00, + 0x1c, 0x8a, 0x1c, 0x23, 0x5d, 0x8b, 0x1b, 0xa1, + 0x9d, 0x8a, 0x1d, 0x23, 0x9d, 0x8b, 0x1d, 0xa1, + 0x00, 0x29, 0x19, 0xae, 0x69, 0xa8, 0x19, 0x23, + 0x24, 0x53, 0x1b, 0x23, 0x24, 0x53, 0x19, 0xa1, + 0x00, 0x1a, 0x5b, 0x5b, 0xa5, 0x69, 0x24, 0x24, + 0xae, 0xae, 0xa8, 0xad, 0x29, 0x00, 0x7c, 0x00, + 0x15, 0x9c, 0x6d, 0x9c, 0xa5, 0x69, 0x29, 0x53, + 0x84, 0x13, 0x34, 0x11, 0xa5, 0x69, 0x23, 0xa0, + 0xd8, 0x62, 0x5a, 0x48, 0x26, 0x62, 0x94, 0x88, + 0x54, 0x44, 0xc8, 0x54, 0x68, 0x44, 0xe8, 0x94, + 0x00, 0xb4, 0x08, 0x84, 0x74, 0xb4, 0x28, 0x6e, + 0x74, 0xf4, 0xcc, 0x4a, 0x72, 0xf2, 0xa4, 0x8a, + 0x00, 0xaa, 0xa2, 0xa2, 0x74, 0x74, 0x74, 0x72, + 0x44, 0x68, 0xb2, 0x32, 0xb2, 0x00, 0x22, 0x00, + 0x1a, 0x1a, 0x26, 0x26, 0x72, 0x72, 0x88, 0xc8, + 0xc4, 0xca, 0x26, 0x48, 0x44, 0x44, 0xa2, 0xc8, + 0xff, 0xff, 0xff, 0x20, 0xd0, 0xf8, 0x68, 0x85, + 0x2c, 0x68, 0x85, 0x2d, 0xa2, 0x08, 0xbd, 0x10, + 0xfb, 0x95, 0x3c, 0xca, 0xd0, 0xf8, 0xa1, 0x3a, + 0xf0, 0x42, 0xa4, 0x2f, 0xc9, 0x20, 0xf0, 0x59, + 0xc9, 0x60, 0xf0, 0x45, 0xc9, 0x4c, 0xf0, 0x5c, + 0xc9, 0x6c, 0xf0, 0x59, 0xc9, 0x40, 0xf0, 0x35, + 0x29, 0x1f, 0x49, 0x14, 0xc9, 0x04, 0xf0, 0x02, + 0xb1, 0x3a, 0x99, 0x3c, 0x00, 0x88, 0x10, 0xf8, + 0x20, 0x3f, 0xff, 0x4c, 0x3c, 0x00, 0x85, 0x45, + 0x68, 0x48, 0x0a, 0x0a, 0x0a, 0x30, 0x03, 0x6c, + 0xfe, 0x03, 0x28, 0x20, 0x4c, 0xff, 0x68, 0x85, + 0x3a, 0x68, 0x85, 0x3b, 0x20, 0x82, 0xf8, 0x20, + 0xda, 0xfa, 0x4c, 0x65, 0xff, 0x18, 0x68, 0x85, + 0x48, 0x68, 0x85, 0x3a, 0x68, 0x85, 0x3b, 0xa5, + 0x2f, 0x20, 0x56, 0xf9, 0x84, 0x3b, 0x18, 0x90, + 0x14, 0x18, 0x20, 0x54, 0xf9, 0xaa, 0x98, 0x48, + 0x8a, 0x48, 0xa0, 0x02, 0x18, 0xb1, 0x3a, 0xaa, + 0x88, 0xb1, 0x3a, 0x86, 0x3b, 0x85, 0x3a, 0xb0, + 0xf3, 0xa5, 0x2d, 0x48, 0xa5, 0x2c, 0x48, 0x20, + 0x8e, 0xfd, 0xa9, 0x45, 0x85, 0x40, 0xa9, 0x00, + 0x85, 0x41, 0xa2, 0xfb, 0xa9, 0xa0, 0x20, 0xed, + 0xfd, 0xbd, 0x1e, 0xfa, 0x20, 0xed, 0xfd, 0xa9, + 0xbd, 0x20, 0xed, 0xfd, 0xb5, 0x4a, 0x20, 0xda, + 0xfd, 0xe8, 0x30, 0xe8, 0x60, 0x18, 0xa0, 0x01, + 0xb1, 0x3a, 0x20, 0x56, 0xf9, 0x85, 0x3a, 0x98, + 0x38, 0xb0, 0xa2, 0x20, 0x4a, 0xff, 0x38, 0xb0, + 0x9e, 0xea, 0xea, 0x4c, 0x0b, 0xfb, 0x4c, 0xfd, + 0xfa, 0xc1, 0xd8, 0xd9, 0xd0, 0xd3, 0xad, 0x70, + 0xc0, 0xa0, 0x00, 0xea, 0xea, 0xbd, 0x64, 0xc0, + 0x10, 0x04, 0xc8, 0xd0, 0xf8, 0x88, 0x60, 0xa9, + 0x00, 0x85, 0x48, 0xad, 0x56, 0xc0, 0xad, 0x54, + 0xc0, 0xad, 0x51, 0xc0, 0xa9, 0x00, 0xf0, 0x0b, + 0xad, 0x50, 0xc0, 0xad, 0x53, 0xc0, 0x20, 0x36, + 0xf8, 0xa9, 0x14, 0x85, 0x22, 0xa9, 0x00, 0x85, + 0x20, 0xa9, 0x20, 0x85, 0x21, 0xa9, 0x0f, 0x85, + 0x23, 0xa9, 0x0e, 0x85, 0x25, 0x4c, 0x22, 0xfc, + 0x20, 0xa4, 0xfb, 0xa0, 0x10, 0xa5, 0x50, 0x4a, + 0x90, 0x0c, 0x18, 0xa2, 0xfe, 0xb5, 0x54, 0x75, + 0x56, 0x95, 0x54, 0xe8, 0xd0, 0xf7, 0xa2, 0x03, + 0x76, 0x50, 0xca, 0x10, 0xfb, 0x88, 0xd0, 0xe5, + 0x60, 0x20, 0xa4, 0xfb, 0xa0, 0x10, 0x06, 0x50, + 0x26, 0x51, 0x26, 0x52, 0x26, 0x53, 0x38, 0xa5, + 0x52, 0xe5, 0x54, 0xaa, 0xa5, 0x53, 0xe5, 0x55, + 0x90, 0x06, 0x86, 0x52, 0x85, 0x53, 0xe6, 0x50, + 0x88, 0xd0, 0xe3, 0x60, 0xa0, 0x00, 0x84, 0x2f, + 0xa2, 0x54, 0x20, 0xaf, 0xfb, 0xa2, 0x50, 0xb5, + 0x01, 0x10, 0x0d, 0x38, 0x98, 0xf5, 0x00, 0x95, + 0x00, 0x98, 0xf5, 0x01, 0x95, 0x01, 0xe6, 0x2f, + 0x60, 0x48, 0x4a, 0x29, 0x03, 0x09, 0x04, 0x85, + 0x29, 0x68, 0x29, 0x18, 0x90, 0x02, 0x69, 0x7f, + 0x85, 0x28, 0x0a, 0x0a, 0x05, 0x28, 0x85, 0x28, + 0x60, 0xc9, 0x87, 0xd0, 0x12, 0xa9, 0x40, 0x20, + 0xa8, 0xfc, 0xa0, 0xc0, 0xa9, 0x0c, 0x20, 0xa8, + 0xfc, 0xad, 0x30, 0xc0, 0x88, 0xd0, 0xf5, 0x60, + 0xa4, 0x24, 0x91, 0x28, 0xe6, 0x24, 0xa5, 0x24, + 0xc5, 0x21, 0xb0, 0x66, 0x60, 0xc9, 0xa0, 0xb0, + 0xef, 0xa8, 0x10, 0xec, 0xc9, 0x8d, 0xf0, 0x5a, + 0xc9, 0x8a, 0xf0, 0x5a, 0xc9, 0x88, 0xd0, 0xc9, + 0xc6, 0x24, 0x10, 0xe8, 0xa5, 0x21, 0x85, 0x24, + 0xc6, 0x24, 0xa5, 0x22, 0xc5, 0x25, 0xb0, 0x0b, + 0xc6, 0x25, 0xa5, 0x25, 0x20, 0xc1, 0xfb, 0x65, + 0x20, 0x85, 0x28, 0x60, 0x49, 0xc0, 0xf0, 0x28, + 0x69, 0xfd, 0x90, 0xc0, 0xf0, 0xda, 0x69, 0xfd, + 0x90, 0x2c, 0xf0, 0xde, 0x69, 0xfd, 0x90, 0x5c, + 0xd0, 0xe9, 0xa4, 0x24, 0xa5, 0x25, 0x48, 0x20, + 0x24, 0xfc, 0x20, 0x9e, 0xfc, 0xa0, 0x00, 0x68, + 0x69, 0x00, 0xc5, 0x23, 0x90, 0xf0, 0xb0, 0xca, + 0xa5, 0x22, 0x85, 0x25, 0xa0, 0x00, 0x84, 0x24, + 0xf0, 0xe4, 0xa9, 0x00, 0x85, 0x24, 0xe6, 0x25, + 0xa5, 0x25, 0xc5, 0x23, 0x90, 0xb6, 0xc6, 0x25, + 0xa5, 0x22, 0x48, 0x20, 0x24, 0xfc, 0xa5, 0x28, + 0x85, 0x2a, 0xa5, 0x29, 0x85, 0x2b, 0xa4, 0x21, + 0x88, 0x68, 0x69, 0x01, 0xc5, 0x23, 0xb0, 0x0d, + 0x48, 0x20, 0x24, 0xfc, 0xb1, 0x28, 0x91, 0x2a, + 0x88, 0x10, 0xf9, 0x30, 0xe1, 0xa0, 0x00, 0x20, + 0x9e, 0xfc, 0xb0, 0x86, 0xa4, 0x24, 0xa9, 0xa0, + 0x91, 0x28, 0xc8, 0xc4, 0x21, 0x90, 0xf9, 0x60, + 0x38, 0x48, 0xe9, 0x01, 0xd0, 0xfc, 0x68, 0xa9, + 0x00, 0x60, 0xea, 0xea, 0xe6, 0x42, 0xd0, 0x02, + 0xe6, 0x43, 0xa5, 0x3c, 0xc5, 0x3e, 0xa5, 0x3d, + 0xe5, 0x3f, 0xe6, 0x3c, 0xd0, 0x02, 0xe6, 0x3d, + 0x60, 0xa0, 0x4b, 0x20, 0xdb, 0xfc, 0xd0, 0xf9, + 0x69, 0xfe, 0xb0, 0xf5, 0xa0, 0x21, 0x20, 0xdb, + 0xfc, 0xc8, 0xc8, 0x88, 0xd0, 0xfd, 0x90, 0x05, + 0xa0, 0x32, 0x88, 0xd0, 0xfd, 0xac, 0x20, 0xc0, + 0xa0, 0x2c, 0xca, 0x60, 0xa2, 0x08, 0x48, 0x20, + 0xfa, 0xfc, 0x68, 0x2a, 0xa0, 0x3a, 0xca, 0xd0, + 0xf5, 0x60, 0x20, 0xfd, 0xfc, 0x88, 0xad, 0x60, + 0xc0, 0x45, 0x2f, 0x10, 0xf8, 0x45, 0x2f, 0x85, + 0x2f, 0xc0, 0x80, 0x60, 0xa4, 0x24, 0xb1, 0x28, + 0x48, 0x29, 0x3f, 0x09, 0x40, 0x91, 0x28, 0x68, + 0x6c, 0x38, 0x00, 0xe6, 0x4e, 0xd0, 0x02, 0xe6, + 0x4f, 0x2c, 0x00, 0xc0, 0x10, 0xf5, 0x91, 0x28, + 0xad, 0x00, 0xc0, 0x2c, 0x10, 0xc0, 0x60, 0x20, + 0x0c, 0xfd, 0x20, 0x2c, 0xfc, 0x20, 0x0c, 0xfd, + 0xc9, 0x9b, 0xf0, 0xf3, 0x60, 0xa5, 0x32, 0x48, + 0xa9, 0xff, 0x85, 0x32, 0xbd, 0x00, 0x02, 0x20, + 0xed, 0xfd, 0x68, 0x85, 0x32, 0xbd, 0x00, 0x02, + 0xc9, 0x88, 0xf0, 0x1d, 0xc9, 0x98, 0xf0, 0x0a, + 0xe0, 0xf8, 0x90, 0x03, 0x20, 0x3a, 0xff, 0xe8, + 0xd0, 0x13, 0xa9, 0xdc, 0x20, 0xed, 0xfd, 0x20, + 0x8e, 0xfd, 0xa5, 0x33, 0x20, 0xed, 0xfd, 0xa2, + 0x01, 0x8a, 0xf0, 0xf3, 0xca, 0x20, 0x35, 0xfd, + 0xc9, 0x95, 0xd0, 0x02, 0xb1, 0x28, 0xc9, 0xe0, + 0x90, 0x02, 0x29, 0xdf, 0x9d, 0x00, 0x02, 0xc9, + 0x8d, 0xd0, 0xb2, 0x20, 0x9c, 0xfc, 0xa9, 0x8d, + 0xd0, 0x5b, 0xa4, 0x3d, 0xa6, 0x3c, 0x20, 0x8e, + 0xfd, 0x20, 0x40, 0xf9, 0xa0, 0x00, 0xa9, 0xad, + 0x4c, 0xed, 0xfd, 0xa5, 0x3c, 0x09, 0x07, 0x85, + 0x3e, 0xa5, 0x3d, 0x85, 0x3f, 0xa5, 0x3c, 0x29, + 0x07, 0xd0, 0x03, 0x20, 0x92, 0xfd, 0xa9, 0xa0, + 0x20, 0xed, 0xfd, 0xb1, 0x3c, 0x20, 0xda, 0xfd, + 0x20, 0xba, 0xfc, 0x90, 0xe8, 0x60, 0x4a, 0x90, + 0xea, 0x4a, 0x4a, 0xa5, 0x3e, 0x90, 0x02, 0x49, + 0xff, 0x65, 0x3c, 0x48, 0xa9, 0xbd, 0x20, 0xed, + 0xfd, 0x68, 0x48, 0x4a, 0x4a, 0x4a, 0x4a, 0x20, + 0xe5, 0xfd, 0x68, 0x29, 0x0f, 0x09, 0xb0, 0xc9, + 0xba, 0x90, 0x02, 0x69, 0x06, 0x6c, 0x36, 0x00, + 0xc9, 0xa0, 0x90, 0x02, 0x25, 0x32, 0x84, 0x35, + 0x48, 0x20, 0xfd, 0xfb, 0x68, 0xa4, 0x35, 0x60, + 0xc6, 0x34, 0xf0, 0x9f, 0xca, 0xd0, 0x16, 0xc9, + 0xba, 0xd0, 0xbb, 0x85, 0x31, 0xa5, 0x3e, 0x91, + 0x40, 0xe6, 0x40, 0xd0, 0x02, 0xe6, 0x41, 0x60, + 0xa4, 0x34, 0xb9, 0xff, 0x01, 0x85, 0x31, 0x60, + 0xa2, 0x01, 0xb5, 0x3e, 0x95, 0x42, 0x95, 0x44, + 0xca, 0x10, 0xf7, 0x60, 0xb1, 0x3c, 0x91, 0x42, + 0x20, 0xb4, 0xfc, 0x90, 0xf7, 0x60, 0xb1, 0x3c, + 0xd1, 0x42, 0xf0, 0x1c, 0x20, 0x92, 0xfd, 0xb1, + 0x3c, 0x20, 0xda, 0xfd, 0xa9, 0xa0, 0x20, 0xed, + 0xfd, 0xa9, 0xa8, 0x20, 0xed, 0xfd, 0xb1, 0x42, + 0x20, 0xda, 0xfd, 0xa9, 0xa9, 0x20, 0xed, 0xfd, + 0x20, 0xb4, 0xfc, 0x90, 0xd9, 0x60, 0x20, 0x75, + 0xfe, 0xa9, 0x14, 0x48, 0x20, 0xd0, 0xf8, 0x20, + 0x53, 0xf9, 0x85, 0x3a, 0x84, 0x3b, 0x68, 0x38, + 0xe9, 0x01, 0xd0, 0xef, 0x60, 0x8a, 0xf0, 0x07, + 0xb5, 0x3c, 0x95, 0x3a, 0xca, 0x10, 0xf9, 0x60, + 0xa0, 0x3f, 0xd0, 0x02, 0xa0, 0xff, 0x84, 0x32, + 0x60, 0xa9, 0x00, 0x85, 0x3e, 0xa2, 0x38, 0xa0, + 0x1b, 0xd0, 0x08, 0xa9, 0x00, 0x85, 0x3e, 0xa2, + 0x36, 0xa0, 0xf0, 0xa5, 0x3e, 0x29, 0x0f, 0xf0, + 0x06, 0x09, 0xc0, 0xa0, 0x00, 0xf0, 0x02, 0xa9, + 0xfd, 0x94, 0x00, 0x95, 0x01, 0x60, 0xea, 0xea, + 0x4c, 0x00, 0xe0, 0x4c, 0x03, 0xe0, 0x20, 0x75, + 0xfe, 0x20, 0x3f, 0xff, 0x6c, 0x3a, 0x00, 0x4c, + 0xd7, 0xfa, 0xc6, 0x34, 0x20, 0x75, 0xfe, 0x4c, + 0x43, 0xfa, 0x4c, 0xf8, 0x03, 0xa9, 0x40, 0x20, + 0xc9, 0xfc, 0xa0, 0x27, 0xa2, 0x00, 0x41, 0x3c, + 0x48, 0xa1, 0x3c, 0x20, 0xed, 0xfe, 0x20, 0xba, + 0xfc, 0xa0, 0x1d, 0x68, 0x90, 0xee, 0xa0, 0x22, + 0x20, 0xed, 0xfe, 0xf0, 0x4d, 0xa2, 0x10, 0x0a, + 0x20, 0xd6, 0xfc, 0xd0, 0xfa, 0x60, 0x20, 0x00, + 0xfe, 0x68, 0x68, 0xd0, 0x6c, 0x20, 0xfa, 0xfc, + 0xa9, 0x16, 0x20, 0xc9, 0xfc, 0x85, 0x2e, 0x20, + 0xfa, 0xfc, 0xa0, 0x24, 0x20, 0xfd, 0xfc, 0xb0, + 0xf9, 0x20, 0xfd, 0xfc, 0xa0, 0x3b, 0x20, 0xec, + 0xfc, 0x81, 0x3c, 0x45, 0x2e, 0x85, 0x2e, 0x20, + 0xba, 0xfc, 0xa0, 0x35, 0x90, 0xf0, 0x20, 0xec, + 0xfc, 0xc5, 0x2e, 0xf0, 0x0d, 0xa9, 0xc5, 0x20, + 0xed, 0xfd, 0xa9, 0xd2, 0x20, 0xed, 0xfd, 0x20, + 0xed, 0xfd, 0xa9, 0x87, 0x4c, 0xed, 0xfd, 0xa5, + 0x48, 0x48, 0xa5, 0x45, 0xa6, 0x46, 0xa4, 0x47, + 0x28, 0x60, 0x85, 0x45, 0x86, 0x46, 0x84, 0x47, + 0x08, 0x68, 0x85, 0x48, 0xba, 0x86, 0x49, 0xd8, + 0x60, 0x20, 0x84, 0xfe, 0x20, 0x2f, 0xfb, 0x20, + 0x93, 0xfe, 0x20, 0x89, 0xfe, 0xd8, 0x20, 0x3a, + 0xff, 0xa9, 0xaa, 0x85, 0x33, 0x20, 0x67, 0xfd, + 0x20, 0xc7, 0xff, 0x20, 0xa7, 0xff, 0x84, 0x34, + 0xa0, 0x17, 0x88, 0x30, 0xe8, 0xd9, 0xcc, 0xff, + 0xd0, 0xf8, 0x20, 0xbe, 0xff, 0xa4, 0x34, 0x4c, + 0x73, 0xff, 0xa2, 0x03, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x26, 0x3e, 0x26, 0x3f, 0xca, 0x10, 0xf8, + 0xa5, 0x31, 0xd0, 0x06, 0xb5, 0x3f, 0x95, 0x3d, + 0x95, 0x41, 0xe8, 0xf0, 0xf3, 0xd0, 0x06, 0xa2, + 0x00, 0x86, 0x3e, 0x86, 0x3f, 0xb9, 0x00, 0x02, + 0xc8, 0x49, 0xb0, 0xc9, 0x0a, 0x90, 0xd3, 0x69, + 0x88, 0xc9, 0xfa, 0xb0, 0xcd, 0x60, 0xa9, 0xfe, + 0x48, 0xb9, 0xe3, 0xff, 0x48, 0xa5, 0x31, 0xa0, + 0x00, 0x84, 0x31, 0x60, 0xbc, 0xb2, 0xbe, 0xed, + 0xef, 0xc4, 0xec, 0xa9, 0xbb, 0xa6, 0xa4, 0x06, + 0x95, 0x07, 0x02, 0x05, 0xf0, 0x00, 0xeb, 0x93, + 0xa7, 0xc6, 0x99, 0xb2, 0xc9, 0xbe, 0xc1, 0x35, + 0x8c, 0xc3, 0x96, 0xaf, 0x17, 0x17, 0x2b, 0x1f, + 0x83, 0x7f, 0x5d, 0xcc, 0xb5, 0xfc, 0x17, 0x17, + 0xf5, 0x03, 0xfb, 0x03, 0x59, 0xff, 0x86, 0xfa +}; + +unsigned char ram[1024]; +// Free memory for storing BASIC programs +unsigned char basic[512]; + +unsigned char read8(unsigned short address) { + unsigned char page = address>>8; + if(page < 0x04) { + return ram[address]; + } else if (page >= 0x04 && page < 0x08) { + return screenRead(address); + } else if (page >= 0x08 && page < 0x10) { + return basic[address-0x800]; + } else if (page >= 0xE0) { + return pgm_read_byte_near(rom+address-0xE000); + } else { + // Keyboard Data + if(address == 0xC000) return keyboard_read(); + // Keyboard Strobe + if(address == 0xC010) keyboard_strobe(); + // Speaker toggle + if(address == 0xC030) speaker_toggle(); + return 0; + } +} + +unsigned short read16(unsigned short address) { + return (unsigned short)read8(address) | (((unsigned short)read8(address+1))<<8); +} + +void write8(unsigned short address, unsigned char value) { + unsigned char page = address>>8; + if(page < 0x04) { + ram[address] = value; + } else if(page >= 0x04 && page < 0x08) { + screenWrite(address, value); + } else if (page >= 0x08 && page < 0x10) { + basic[address-0x800] = value; + } else { + // Keyboard Strobe + if(address == 0xC010) keyboard_strobe(); + // Speaker toggle + if(address == 0xC030) speaker_toggle(); + } +} + +void write16(unsigned short address, unsigned short value) { + write8(address, value&0x00FF); + write8(address+1, (value>>8)&0x00FF); +} + diff --git a/APPLEII/monitor.ino b/APPLEII/monitor.ino new file mode 100644 index 0000000..f395b69 --- /dev/null +++ b/APPLEII/monitor.ino @@ -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; + } +} diff --git a/APPLEII/screen.ino b/APPLEII/screen.ino new file mode 100644 index 0000000..e50fae9 --- /dev/null +++ b/APPLEII/screen.ino @@ -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)); +} diff --git a/APPLEII/speaker.ino b/APPLEII/speaker.ino new file mode 100644 index 0000000..772b5ad --- /dev/null +++ b/APPLEII/speaker.ino @@ -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); +} diff --git a/README.md b/README.md index bde648e..e16884d 100644 --- a/README.md +++ b/README.md @@ -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! \ No newline at end of file