Exemple #1
0
 private static long GetValueForInput(IIntCodeMemory workingMemory, long relativeBase, InstructionMode modeParam, long input)
 {
     return(modeParam switch
     {
         InstructionMode.PositionMode => workingMemory[input],
         InstructionMode.ImmediateMode => input,
         InstructionMode.RelativeMode => workingMemory[relativeBase + input],
         _ => throw new Exception("Unexpected instruction mode"),
     });
Exemple #2
0
        private static long HandleAdjustRelativeBaseCommand(IIntCodeMemory workingMemory, long relativeBase, long programPosition, InstructionMode modeParam1)
        {
            long input1 = workingMemory[programPosition + 1];
            long value1 = GetValueForInput(workingMemory, relativeBase, modeParam1, input1);

            relativeBase += value1;
            return(relativeBase);
        }
Exemple #3
0
        private static void HandleOutputCommand(Action <long>?output, IIntCodeMemory workingMemory, long relativeBase, long programPosition, InstructionMode modeParam1)
        {
            long input1 = workingMemory[programPosition + 1];
            long param1 = GetValueForInput(workingMemory, relativeBase, modeParam1, input1);

            if (output == null)
            {
                throw new Exception("Program is expecting Output to be wired up");
            }

            output(param1);
        }
Exemple #4
0
        private static void HandleAdditionOrMultiplicationCommands(IIntCodeMemory workingMemory, long programPosition, long relativeBase, IntInstruction instruction, InstructionMode modeParam1, InstructionMode modeParam2, InstructionMode modeParam3)
        {
            long input1 = workingMemory[programPosition + 1];
            long value1 = GetValueForInput(workingMemory, relativeBase, modeParam1, input1);

            long input2 = workingMemory[programPosition + 2];
            long value2 = GetValueForInput(workingMemory, relativeBase, modeParam2, input2);

            long input3 = workingMemory[programPosition + 3];

            long result = instruction switch
            {
                IntInstruction.Add => value1 + value2,
                IntInstruction.Multiply => value1 * value2,
                _ => throw new Exception("Unrecognized IntInstruction"),
            };

            WriteResultToWorkingMemory(result, workingMemory, relativeBase, modeParam3, input3);
        }
Exemple #5
0
        private static void HandleInputCommand(Func <long>?input, IIntCodeMemory workingMemory, long relativeBase, long programPosition, InstructionMode modeParam1)
        {
            if (input == null)
            {
                throw new Exception("Program is expecting Input to be wired up");
            }

            long input1 = workingMemory[programPosition + 1];

            WriteResultToWorkingMemory(input(), workingMemory, relativeBase, modeParam1, input1);
        }
Exemple #6
0
        private static void HandleJumpCommands(IIntCodeMemory workingMemory, ref int sizeOfInstruction, long relativeBase, ref long programPosition, IntInstruction instruction, InstructionMode modeParam1, InstructionMode modeParam2)
        {
            long input1 = workingMemory[programPosition + 1];
            long param1 = GetValueForInput(workingMemory, relativeBase, modeParam1, input1);

            long input2 = workingMemory[programPosition + 2];
            long param2 = GetValueForInput(workingMemory, relativeBase, modeParam2, input2);

            if ((instruction == IntInstruction.JumpIfTrue && (param1 != 0)) ||
                (instruction == IntInstruction.JumpIfFalse && (param1 == 0)))
            {
                programPosition   = param2;
                sizeOfInstruction = 0;
            }
        }
Exemple #7
0
        private static void HandleComparisonCommands(IIntCodeMemory workingMemory, long relativeBase, long programPosition, IntInstruction instruction, InstructionMode modeParam1, InstructionMode modeParam2, InstructionMode modeParam3)
        {
            long input1 = workingMemory[programPosition + 1];
            long value1 = GetValueForInput(workingMemory, relativeBase, modeParam1, input1);

            long input2 = workingMemory[programPosition + 2];
            long value2 = GetValueForInput(workingMemory, relativeBase, modeParam2, input2);

            long input3 = workingMemory[programPosition + 3];

            var result = instruction switch
            {
                IntInstruction.LessThan => value1 < value2 ? 1 : 0,
                IntInstruction.Equals => value1 == value2 ? 1 : 0,
                _ => throw new Exception("Unexpected instruction")
            };

            WriteResultToWorkingMemory(result, workingMemory, relativeBase, modeParam3, input3);
        }
Exemple #8
0
        /*
         * Modes:
         * 0: A        ....	Accumulator	            OPC A	        operand is AC (implied single byte instruction)
         * 1: abs      ....	absolute	            OPC $LLHH	    operand is address $HHLL *
         * 2: abs,X    ....	absolute, X-indexed	    OPC $LLHH,X	    operand is address; effective address is address incremented by X with carry **
         * 3: abs,Y    ....	absolute, Y-indexed	    OPC $LLHH,Y	    operand is address; effective address is address incremented by Y with carry **
         * 4: #	    ....	immediate	            OPC #$BB	    operand is byte BB
         * 5: impl	    ....	implied	                OPC	            operand implied
         * 6: ind	    ....	indirect	            OPC ($LLHH)	    operand is address; effective address is contents of word at address: C.w($HHLL)
         * 7: X,ind    ....	X-indexed, indirect	    OPC ($LL,X)	    operand is zeropage address; effective address is word in (LL + X, LL + X + 1), inc. without carry: C.w($00LL + X)
         * 8: ind,Y    ....	indirect, Y-indexed	    OPC ($LL),Y	    operand is zeropage address; effective address is word in (LL, LL + 1) incremented by Y with carry: C.w($00LL) + Y
         * 9: rel      ....	relative	            OPC $BB	        branch target is PC + signed offset BB ***
         * 10: zpg     ....	zeropage	            OPC $LL	        operand is zeropage address (hi-byte is zero, address = $00LL)
         * 11: zpg,X   ....	zeropage, X-indexed	    OPC $LL,X	    operand is zeropage address; effective address is address incremented by X without carry **
         * 12: zpg,Y   ....	zeropage, Y-indexed	    OPC $LL,Y	    operand is zeropage address; effective address is address incremented by Y without carry **
         *
         * 13: internal
         */

        public InstructionCaller(Func <InstructionMode, int> method, InstructionMode mode)
        {
            this.method = method;
            this.mode   = mode;
        }
Exemple #9
0
        private void getOper(InstructionMode mode)
        {
            byte ll;
            byte hh;

            switch (mode)
            {
            case InstructionMode.A:
                this.oper       = -0x100;
                this.pageChange = (byte)0;
                return;

            case InstructionMode.abs:
                ll = this.getCurrent();
                this.incrPc();
                hh = this.getCurrent();
                this.incrPc();

                this.oper       = 0x100 * hh + ll;
                this.pageChange = (byte)0;
                return;

            case InstructionMode.absX:
                ll = this.getCurrent();
                this.incrPc();
                hh = this.getCurrent();
                this.incrPc();

                this.oper       = (hh * 0x100 + ll + this.x) % 0x10000;
                this.pageChange = (byte)(ll + this.x > 0xff ? 1 : 0);
                return;

            case InstructionMode.absY:
                ll = this.getCurrent();
                this.incrPc();
                hh = this.getCurrent();
                this.incrPc();

                this.oper       = (hh * 0x100 + ll + this.y) % 0x10000;
                this.pageChange = (byte)(ll + this.y > 0xff ? 1 : 0);
                return;

            case InstructionMode.imm:
                this.oper = -0x200 - this.getCurrent();
                this.incrPc();

                this.pageChange = (byte)0;
                return;

            case InstructionMode.impl:
                this.oper       = -1;
                this.pageChange = (byte)0;
                return;

            case InstructionMode.ind:      // only used by JMP
                ll = this.getCurrent();
                this.incrPc();
                hh = this.getCurrent();
                this.incrPc();

                this.oper       = 0x100 * hh + ll;
                this.pageChange = (byte)0;
                return;

            case InstructionMode.Xind:      // X,ind
                ll = this.getCurrent();
                this.incrPc();

                this.oper       = this[(ll + this.x) % 0x100] + 0x100 * this[(ll + this.x + 1) % 0x100];
                this.pageChange = (byte)0;
                return;

            case InstructionMode.indY:      // ind,Y
                ll = this.getCurrent();
                this.incrPc();

                int effective_low  = this[ll];
                int effective_high = this[(ll + 1) % 0x100] * 0x100;
                this.oper = (effective_high + effective_low + this.y) % 0x10000;

                this.pageChange = (byte)(effective_low + this.y > 0xff ? 1 : 0);
                return;

            case InstructionMode.rel:      // rel
                this.oper = this.getCurrent();
                this.incrPc();

                this.pageChange = (byte)0;
                return;

            case InstructionMode.zpg:      // zpg
                ll = this.getCurrent();
                this.incrPc();

                this.oper       = ll;
                this.pageChange = (byte)0;
                return;

            case InstructionMode.zpgX:      // zpg,X
                ll = this.getCurrent();
                this.incrPc();

                this.oper       = (ll + this.x) % 0x100;
                this.pageChange = (byte)0;
                return;

            case InstructionMode.zpgY:      // zpg,Y
                ll = this.getCurrent();
                this.incrPc();

                this.oper       = (ll + this.y) % 0x100;
                this.pageChange = (byte)0;
                return;

            default:
                throw new Exception("Unknown mode: " + mode);
            }
        }