Exemple #1
0
        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]);
        }
Exemple #2
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]);
        }
        public void RomSpeedShouldBeValid(string romSpeed)
        {
            const string inputTemplate = @"
header
{{
    RomSpeed = {0}
}}

vectors
{{

}}

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

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

            Assert.Throws <CompilerErrorException>(() => driver.Parse());
        }
Exemple #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"));
        }
Exemple #5
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);
        }
        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());
        }
        public void ShouldFailOnInvalidInstructionLabel()
        {
            const string  input  = @"
vectors
{
    BRK = EmptyVector
    NMI = EmptyVector
    IRQ = EmptyVector
    Reset = Main
}

procedure Main
{
    sei
    clc
    xce
mainLoop:
    jmp infinite
}

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

            driver.Parse();
            Assert.Throws <CompilerErrorException>(() => driver.SecondPass());
        }
Exemple #8
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);
        }
        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);
        }
        public void VersionExceptsANumberiteral(string invalidVersion)
        {
            const string inputTemplate = @"
header
{{
    Version = {0}
}}

vectors
{{

}}

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

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

            Assert.Throws <CompilerErrorException>(() => driver.Parse());
        }
Exemple #11
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);
        }
Exemple #12
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);
        }
Exemple #13
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);
        }
Exemple #14
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);
        }
Exemple #15
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);
        }
Exemple #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);
        }
Exemple #17
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);
        }
Exemple #18
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"));
        }
        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());
        }
        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());
        }
Exemple #21
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);
        }
Exemple #22
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);
        }
        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());
        }
        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());
        }
Exemple #25
0
 public CpuPass(ZealCpuDriver driver)
 {
     _driver = driver;
 }
        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);
        }
Exemple #27
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);
        }
Exemple #28
0
 public SecondCpuPass(ZealCpuDriver driver)
     : base(driver)
 {
 }
Exemple #29
0
 public ParseCpuPass(ZealCpuDriver driver)
     : base(driver)
 {
 }