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"), });
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); }
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); }
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); }
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); }
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; } }
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); }
/* * 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; }
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); } }