Example #1
0
        public void CartridgeNameExceptsAStringLiteral(string invalidCartridgeName)
        {
            const string inputTemplate = @"
            header
            {{
            CartridgeName = {0}
            }}

            vectors
            {{

            }}

            procedure Main
            {{
            sei
            clc
            xce
            }}
            ";
            string input = String.Format(inputTemplate, invalidCartridgeName);

            ZealCpuDriver driver = new ZealCpuDriver(input.ToMemoryStream());
            Assert.Throws<CompilerErrorException>(() => driver.Parse());
        }
        public void ShouldGenerateAbsoluteInstructionsWithLabel()
        {
            string input = @"procedure Test
            {
            php

            mainLoop:
            jmp mainLoop
            }
            ";

            ZealCpuDriver driver = new ZealCpuDriver(input.ToMemoryStream());
            driver.Parse();

            RomHeader fakeHeader = new RomHeader();
            fakeHeader.MapMode = MapMode.LoROM;
            fakeHeader.RomSpeed = RomSpeed.SlowROM;

            MemoryStream memoryStream = new MemoryStream(32);
            CpuCodeGenerator generator = new CpuCodeGenerator(memoryStream);
            generator.Instructions = driver.GlobalScope.Children[0].Statements.Where(x => x is CpuInstructionStatement).Select(x => x as CpuInstructionStatement).ToList();
            generator.Scope = driver.GlobalScope.Children[0];
            generator.Header = fakeHeader;
            generator.Generate();

            Assert.Equal(0x01, memoryStream.GetBuffer()[2]);
            Assert.Equal(0x80, memoryStream.GetBuffer()[3]);
        }
Example #3
0
        public void CheckInvalidAddressingMode(string instruction)
        {
            const string inputTemplate = @"
            vectors
            {{
            BRK = EmptyVector
            NMI = EmptyVector
            IRQ = EmptyVector
            Reset = Main
            }}

            procedure Main
            {{
            {0}
            }}

            interrupt EmptyVector
            {{
            }}
            ";
            string input = String.Format(inputTemplate, instruction);

            ZealCpuDriver driver = new ZealCpuDriver(input.ToMemoryStream());
            Assert.Throws<CompilerErrorException>(() => driver.Parse());
        }
Example #4
0
        public void ShoulResolveLabelsToAddress()
        {
            string input = @"procedure Test
            {
            php
            pha

            mainLoop:
            lda $2007
            jmp mainLoop
            bra exit

            exit:
            rts
            }

            interrupt EmptyVector
            {
            }
            ";

            ZealCpuDriver driver = new ZealCpuDriver(input.ToMemoryStream());
            driver.Parse();

            Assert.Equal(0, driver.GlobalScope.AddressFor("Test"));
            Assert.Equal(11, driver.GlobalScope.AddressFor("EmptyVector"));

            var testScope = driver.GlobalScope.Children[0];
            Assert.Equal(2, testScope.AddressFor("mainLoop"));
            Assert.Equal(10, testScope.AddressFor("exit"));
        }
Example #5
0
        public void ShouldMarkRelativeLabelArgument(string instructionText)
        {
            string input = String.Format(ProcedureTemplate, instructionText);

            ZealCpuDriver driver = new ZealCpuDriver(input.ToMemoryStream());
            driver.Parse();

            var instruction = driver.GlobalScope.Children[0].Statements[0] as CpuInstructionStatement;

            Assert.Equal(CpuAddressingMode.Relative, instruction.AddressingMode);
        }
Example #6
0
        public void ShouldResolveLabelsOutsideScope()
        {
            const string input =
            @"
            vectors
            {
            BRK = EmptyVector
            IRQ = EmptyVector
            NMI = EmptyVector
            Reset = Main
            }

            procedure Main
            {
            jsr Test
            }

            procedure Test
            {
            php
            rep #$30
            pha

            lda #$03

            pla
            plp
            rts
            }

            interrupt EmptyVector
            {
            }
            ";
            ZealCpuDriver driver = new ZealCpuDriver(input.ToMemoryStream());

            driver.Parse();
            driver.SecondPass();

            var mainProcedure = driver.GlobalScope.Children[0];
            Assert.Equal(true, mainProcedure.IsLabelValid("Test"));
            Assert.Equal(3, mainProcedure.AddressFor("Test"));
        }
Example #7
0
        public void ShouldAddRTIWhenParsingInterrupt()
        {
            const string input = @"interrupt NMI
            {
            php
            pha

            pla
            plp
            }";
            ZealCpuDriver driver = new ZealCpuDriver(input.ToMemoryStream());
            driver.Parse();

            var cpuInstruction = driver.GlobalScope.Children[0].Statements[driver.GlobalScope.Children[0].Statements.Count - 1] as CpuInstructionStatement;

            Assert.Equal("NMI", driver.GlobalScope.Children[0].Name);
            Assert.Equal(ScopeType.Interrupt, driver.GlobalScope.Children[0].Type);
            Assert.Equal(CpuInstructions.rti, cpuInstruction.Opcode);
            Assert.Equal(CpuAddressingMode.Implied, cpuInstruction.AddressingMode);
        }
Example #8
0
        public void ShouldFailOnInvalidVectorsEntryName()
        {
            const string input = @"
            vectors
            {
            NormalNMI = Main
            }

            procedure Main
            {
            sei
            clc
            xce
            }
            "
            ;
            ZealCpuDriver driver = new ZealCpuDriver(input.ToMemoryStream());
            Assert.Throws<CompilerErrorException>(() => driver.Parse());
        }
Example #9
0
        public void ShouldFailOnInvalidHeaderEntryName()
        {
            const string input = @"
            header
            {
            CartName = ""HELLO WORLD""
            }

            vectors
            {

            }

            procedure Main
            {
            sei
            clc
            xce
            }
            ";
            ZealCpuDriver driver = new ZealCpuDriver(input.ToMemoryStream());
            Assert.Throws<CompilerErrorException>(() => driver.Parse());
        }
Example #10
0
        public void ShouldFailOnBranchTooLong()
        {
            const string input = @"
            vectors
            {
            BRK = EmptyVector
            NMI = EmptyVector
            IRQ = EmptyVector
            Reset = Main
            }

            procedure Main
            {
            bra forwardLabel
            backwardLabel:
            sta $7E0000
            sta $7E0000
            sta $7E0000
            sta $7E0000
            sta $7E0000
            sta $7E0000
            sta $7E0000
            sta $7E0000
            sta $7E0000
            sta $7E0000
            sta $7E0000
            sta $7E0000
            sta $7E0000
            sta $7E0000
            sta $7E0000
            sta $7E0000
            sta $7E0000
            sta $7E0000
            sta $7E0000
            sta $7E0000
            sta $7E0000
            sta $7E0000
            sta $7E0000
            sta $7E0000
            sta $7E0000
            sta $7E0000
            sta $7E0000
            sta $7E0000
            sta $7E0000
            sta $7E0000
            sta $7E0000
            sta $7E0000
            sta $7E0000
            sta $7E0000
            sta $7E0000
            sta $7E0000
            sta $7E0000
            sta $7E0000
            sta $7E0000
            forwardLabel:
            bra backwardLabel
            }

            interrupt EmptyVector
            {
            }
            ";

            ZealCpuDriver driver = new ZealCpuDriver(input.ToMemoryStream());
            Assert.Throws<CompilerErrorException>(() => driver.Parse());
            Assert.Equal(2, driver.Errors.Count);
        }
Example #11
0
        public void ShouldParseHeaderInfo()
        {
            const string input = @"
            header
            {
            CartridgeName = ""HELLO WORLD SNES""
            RomSpeed = FastROM
            MapMode = HiROM
            SramSize = 32
            Country = NorthAmerica
            Developer = $1A
            Version = %1010
            }
            ";
            ZealCpuDriver driver = new ZealCpuDriver(input.ToMemoryStream());
            driver.Parse();

            Assert.Equal("HELLO WORLD SNES", driver.Header.CartridgeName);
            Assert.Equal(RomSpeed.FastROM, driver.Header.RomSpeed);
            Assert.Equal(MapMode.HiROM, driver.Header.MapMode);
            Assert.Equal(32u, driver.Header.SramSize);
            Assert.Equal(Country.NorthAmerica, driver.Header.Country);
            Assert.Equal(0x1Au, driver.Header.Developer);
            Assert.Equal(10u, driver.Header.Version);
        }
Example #12
0
        public void CountryShouldBeValid(string country)
        {
            const string inputTemplate = @"
            header
            {{
            Country = {0}
            }}

            vectors
            {{

            }}

            procedure Main
            {{
            sei
            clc
            xce
            }}
            ";
            string input = String.Format(inputTemplate, country);

            ZealCpuDriver driver = new ZealCpuDriver(input.ToMemoryStream());
            Assert.Throws<CompilerErrorException>(() => driver.Parse());
        }
Example #13
0
        public void VectorsShouldBeFullyPopulated()
        {
            const string input = @"
            vectors
            {
            Reset = Main
            }

            procedure Main
            {
            sei
            clc
            xce
            }
            "
            ;
            ZealCpuDriver driver = new ZealCpuDriver(input.ToMemoryStream());
            Assert.Throws<CompilerErrorException>(() => driver.Parse());
        }
Example #14
0
        public void ShouldParseVectorsInfo()
        {
            const string input = @"
            vectors
            {
            BRK = BrkVector
            IRQ = IrqVector
            NMI = NmiVector
            Reset = Main
            }
            ";
            ZealCpuDriver driver = new ZealCpuDriver(input.ToMemoryStream());
            driver.Parse();

            Assert.Equal("BrkVector", driver.Vectors.BRK);
            Assert.Equal("IrqVector", driver.Vectors.IRQ);
            Assert.Equal("NmiVector", driver.Vectors.NMI);
            Assert.Equal("Main", driver.Vectors.Reset);
        }
Example #15
0
        public void ShouldParseProcedure()
        {
            const string input = @"procedure Test
            {
            }";
            ZealCpuDriver driver = new ZealCpuDriver(input.ToMemoryStream());
            driver.Parse();

            Assert.Equal("Test", driver.GlobalScope.Children[0].Name);
            Assert.Equal(ScopeType.Procedure, driver.GlobalScope.Children[0].Type);
        }
Example #16
0
        public void ShouldParseLabelArgument()
        {
            string input = @"procedure Test
            {
            jmp mainLoop
            }";

            ZealCpuDriver driver = new ZealCpuDriver(input.ToMemoryStream());
            driver.Parse();

            var instruction = driver.GlobalScope.Children[0].Statements[0] as CpuInstructionStatement;
            var argument = instruction.Arguments[0] as LabelInstructionArgument;

            Assert.Equal("mainLoop", argument.Label);
        }
Example #17
0
        public void ShouldParseLabel()
        {
            const string input = @"procedure Test
            {
            php
            pha

            mainLoop:
            lda $2007
            jmp mainLoop

            exit:
            rts
            }";

            ZealCpuDriver driver = new ZealCpuDriver(input.ToMemoryStream());
            driver.Parse();

            var thirdInstruction = driver.GlobalScope.Children[0].Statements[2];
            var fiveInstruction = driver.GlobalScope.Children[0].Statements[4];

            Assert.Equal("mainLoop", thirdInstruction.AssociatedLabel);
            Assert.Equal("exit", fiveInstruction.AssociatedLabel);
        }
Example #18
0
        public void ShouldParseInterrupt()
        {
            const string input = @"interrupt EmptyVector
            {
            }";
            ZealCpuDriver driver = new ZealCpuDriver(input.ToMemoryStream());
            driver.Parse();

            Assert.Equal("EmptyVector", driver.GlobalScope.Children[0].Name);
            Assert.Equal(ScopeType.Interrupt, driver.GlobalScope.Children[0].Type);
        }
Example #19
0
        public void ShouldParseImpliedInstructions(string opcodeText, CpuInstructions opcodeEnum)
        {
            string input = String.Format(ProcedureTemplate, opcodeText);

            ZealCpuDriver driver = new ZealCpuDriver(input.ToMemoryStream());
            driver.Parse();

            CpuInstructionStatement instructionStatement = driver.GlobalScope.Children[0].Statements[0] as CpuInstructionStatement;
            Assert.Equal(opcodeEnum, instructionStatement.Opcode);
            Assert.Equal(CpuAddressingMode.Implied, instructionStatement.AddressingMode);
        }
Example #20
0
        public void ShouldFailOnInvalidVectorsLabel()
        {
            const string input = @"
            vectors
            {
            BRK = EmptyVector
            NMI = EmptyVector
            IRQ = EmptyVector
            Reset = NotValidReset
            }

            procedure Main
            {
            sei
            clc
            xce
            }

            interrupt EmptyVector
            {
            }
            ";
            ZealCpuDriver driver = new ZealCpuDriver(input.ToMemoryStream());
            driver.Parse();
            Assert.Throws<CompilerErrorException>(() => driver.SecondPass());
        }
Example #21
0
 public SecondCpuPass(ZealCpuDriver driver)
     : base(driver)
 {
 }
Example #22
0
        public void VectorsIsRequired()
        {
            const string input = @"
            header
            {
            CartridgeName = ""HELLO WORLD SNES""
            RomSpeed = SlowROM
            MapMode = LoROM
            SramSize = 0
            Country = Japan
            Developer = 0
            Version = 0
            }

            procedure Main
            {
            sei
            clc
            xce
            }
            "
            ;
            ZealCpuDriver driver = new ZealCpuDriver(input.ToMemoryStream());
            driver.Parse();
            Assert.Throws<CompilerErrorException>(() => driver.SecondPass());
            Assert.Equal(1, driver.Errors.Count);
        }
Example #23
0
 public ParseCpuPass(ZealCpuDriver driver)
     : base(driver)
 {
 }
Example #24
0
        static int Main(string[] args)
        {
            if (args.Length < 1)
            {
                Console.Error.WriteLine("No source file provided.");
                return 1;
            }

            if (Path.GetExtension(args[0]) != ".zcpu")
            {
                Console.Error.WriteLine("The source file is in the wrong format. The source file must ends with .zcpu.");
                return 1;
            }

            ZealCpuDriver driver = new ZealCpuDriver(args[0]);
            try
            {
                driver.Parse();
                driver.SecondPass();
            }
            catch(CompilerErrorException)
            {
                foreach (var error in driver.Errors)
                {
                    printErrorMessage(error);
                }

            #if DEBUG
                Console.Read();
            #endif

                return 1;
            }

            FileStream outputRom = new FileStream(Path.ChangeExtension(args[0], ".sfc"), FileMode.Create);

            CpuCodeGenerator codeGenerator = new CpuCodeGenerator(outputRom);
            codeGenerator.Header = driver.Header;

            foreach (var scope in driver.GlobalScope.Children)
            {
                codeGenerator.Scope = scope;

                List<CpuInstructionStatement> instructions = new List<CpuInstructionStatement>();

                foreach (var statement in scope.Statements)
                {
                    if (statement is CpuInstructionStatement)
                    {
                        instructions.Add((CpuInstructionStatement)statement);
                    }
                }

                codeGenerator.Instructions = instructions;
                codeGenerator.Generate();
            }

            SfcRomWriter romWriter = new SfcRomWriter(outputRom);
            romWriter.Driver = driver;
            romWriter.Write();

            outputRom.Close();

            using (FileStream newRom = new FileStream(Path.ChangeExtension(args[0], ".sfc"), FileMode.Open))
            {
                SfcRomWriter checksumWriter = new SfcRomWriter(newRom);
                checksumWriter.Driver = driver;
                checksumWriter.ComputeChecksum();
            }

            return 0;
        }
Example #25
0
        public void InstructionsShouldHaveArguments()
        {
            const string input = @"
            vectors
            {
            BRK = EmptyVector
            NMI = EmptyVector
            IRQ = EmptyVector
            Reset = Main
            }

            procedure Main
            {
            lda
            }

            interrupt EmptyVector
            {
            }
            ";
            ZealCpuDriver driver = new ZealCpuDriver(input.ToMemoryStream());
            Assert.Throws<CompilerErrorException>(() => driver.Parse());
        }
Example #26
0
 public CpuErrorListener(ZealCpuDriver driver)
 {
     _driver = driver;
 }
Example #27
0
 public CpuErrorListener(ZealCpuDriver driver)
 {
     _driver = driver;
 }
Example #28
0
        public void ShouldParseAbsoluteInstructions(string instruction, CpuInstructions opcodeEnum, int value)
        {
            string input = String.Format(ProcedureTemplate, instruction);

            ZealCpuDriver driver = new ZealCpuDriver(input.ToMemoryStream());
            driver.Parse();

            CpuInstructionStatement instructionStatement = driver.GlobalScope.Children[0].Statements[0] as CpuInstructionStatement;
            Assert.Equal(opcodeEnum, instructionStatement.Opcode);
            Assert.Equal(CpuAddressingMode.Absolute, instructionStatement.AddressingMode);

            var numberArgument = instructionStatement.Arguments[0] as NumberInstructionArgument;
            Assert.Equal(value, numberArgument.Number);
        }
Example #29
0
        public void ShouldParseArgumentSizeCorrectly(string instruction, int value, ArgumentSize size)
        {
            string input = String.Format(ProcedureTemplate, instruction);

            ZealCpuDriver driver = new ZealCpuDriver(input.ToMemoryStream());
            driver.Parse();

            CpuInstructionStatement instructionStatement = driver.GlobalScope.Children[0].Statements[0] as CpuInstructionStatement;

            var argument = instructionStatement.Arguments[0] as NumberInstructionArgument;

            Assert.Equal(value, argument.Number);
            Assert.Equal(size, argument.Size);
        }
Example #30
0
 public CpuPass(ZealCpuDriver driver)
 {
     _driver = driver;
 }
Example #31
0
        public void ShouldGenerateRelativeInstructionsWithLabel()
        {
            string input = @"procedure Test
            {
            php

            backwardBranch:
            sec
            bvs backwardBranch
            lda #$03
            bra forwardBranch
            tax
            tay

            forwardBranch:
            rts
            }
            ";

            ZealCpuDriver driver = new ZealCpuDriver(input.ToMemoryStream());
            driver.Parse();

            MemoryStream memoryStream = new MemoryStream(32);
            CpuCodeGenerator generator = new CpuCodeGenerator(memoryStream);
            generator.Instructions = driver.GlobalScope.Children[0].Statements.Where(x => x is CpuInstructionStatement).Select(x => x as CpuInstructionStatement).ToList();
            generator.Scope = driver.GlobalScope.Children[0];
            generator.Generate();

            Assert.Equal(0xFD, memoryStream.GetBuffer()[3]);
            Assert.Equal(0x02, memoryStream.GetBuffer()[7]);
        }