
package paavohuh.sourcream.emulation.instructions;

import org.jooq.lambda.Seq;
import org.joou.UShort;
import paavohuh.sourcream.emulation.Instruction;
import paavohuh.sourcream.emulation.Register;
import paavohuh.sourcream.emulation.State;
import static paavohuh.sourcream.emulation.InstructionFactory.*;

/**
 * Contains instructions related to input.
 */
public final class Input {
    
    /**
     * Skips the next instruction if the key with the id VX is pressed.
     */
    public static class SkipIfKeyPressed extends Instruction.WithRegister {

        /**
         * Skips the next instruction if the key with the id VX is pressed.
         * @param register Contains the key id.
         */
        public SkipIfKeyPressed(Register register) {
            super(register);
        }
        
        @Override
        protected int getRegisterOffset() {
            return 2;
        }

        @Override
        protected UShort getBaseCode() {
            return UShort.valueOf(0xE09E);
        }

        @Override
        public State execute(State state) {
            int key = getRegister(state).intValue();
            
            if (state.getInputState().getKey(key)) {
                return state.withIncrementedPc();
            } else {
                return new State(state);
            }
        }
    }
    
    /**
     * Skips the next instruction if the key with the id VX is up.
     */
    public static class SkipIfKeyNotPressed extends Instruction.WithRegister {

        /**
         * Skips the next instruction if the key with the id VX is up.
         * @param register Contains the key id.
         */
        public SkipIfKeyNotPressed(Register register) {
            super(register);
        }
        
        @Override
        protected int getRegisterOffset() {
            return 2;
        }

        @Override
        protected UShort getBaseCode() {
            return UShort.valueOf(0xE0A1);
        }

        @Override
        public State execute(State state) {
            int key = getRegister(state).intValue();
            
            if (!state.getInputState().getKey(key)) {
                return state.withIncrementedPc();
            } else {
                return new State(state);
            }
        }
    }
    
    /**
     * Gets all input instructions.
     * @return A sequence of instructions.
     */
    public static Seq<Instruction> getAll() {
        return Seq.concat(
                getAllInstances(SkipIfKeyPressed::new),
                getAllInstances(SkipIfKeyNotPressed::new));
    }
}

@@ -2286,24 +2286,816 @@
    %0A    /**%0A
+     * Halts the interpreter until a key is pressed. The key is stored at the%0A     * register.%0A     */%0A    public static class HaltUntilKeyPressed extends Instruction.WithRegister %7B%0A        %0A        /**%0A         * Halts the interpreter until a key is pressed.%0A         * @param register The register to store they key id in.%0A         */%0A        public HaltUntilKeyPressed(Register register) %7B%0A            super(register);%0A        %7D%0A        %0A        @Override%0A        protected int getRegisterOffset() %7B%0A            return 2;%0A        %7D%0A%0A        @Override%0A        protected UShort getBaseCode() %7B%0A            return UShort.valueOf(0xF00A);%0A        %7D%0A%0A        @Override%0A        public State execute(State state) %7B%0A            return state.asWaitingForKey(register);%0A        %7D%0A    %7D%0A    %0A    /**%0A
      * Gets 
@@ -3241,33 +3241,16 @@
 .concat(
-%0A                
 getAllIn
@@ -3338,16 +3338,75 @@
 ed::new)
+,%0A                getAllInstances(HaltUntilKeyPressed::new)
 );%0A    %7D

Implement the final missing instruction*