package io.github.applecommander.bastools.api.code; import java.io.IOException; import java.util.Objects; /** * {@code AsmBuilder} allows generation of assembly code to embed into the output stream. *

* By no means is this complete, but is being built out as the need arises. */ public class AsmBuilder { private CodeBuilder builder; public AsmBuilder(CodeBuilder builder) { Objects.requireNonNull(builder); this.builder = builder; } public CodeBuilder end() { return this.builder; } /** Generate a "LDY #value" in the output stream. */ public AsmBuilder ldy(int value) { builder.add(state -> internalLDY(state, value)); return this; } /** Generate a "JMP address" in the output stream. */ public AsmBuilder jmp(int address) { builder.add(state -> internalJMP(state, address)); return this; } /** Generate a "LDA #value" in the output stream. */ public AsmBuilder lda(int value) throws IOException { builder.add(state -> internalLDA(state, value)); return this; } /** Generate a "STA address" in the output stream. */ public AsmBuilder sta(int address) throws IOException { builder.add(state -> internalSTA(state, address)); return this; } /** * Generate an address setup in the output stream of the format: *

     * LDA #low(value)
     * STA address
     * LDA #high(value)
     * STA address+1
     * 
*/ public AsmBuilder setAddress(int value, int address) { builder.add(state -> { internalLDA(state, value & 0xff); internalSTA(state, address); internalLDA(state, value >> 8); internalSTA(state, address+1); }); return this; } /** * Generate an address setup for a mark in the output stream of the format: *
     * LDA #low(mark)
     * STA address
     * LDA #high(mark)
     * STA address+1
     * 
*/ public AsmBuilder setAddress(CodeMark mark, int address) { builder.add(state -> { int value = mark.getAddress(); internalLDA(state, value & 0xff); internalSTA(state, address); internalLDA(state, value >> 8); internalSTA(state, address+1); }); return this; } private void internalJMP(GeneratorState state, int address) { state.write(0x4c); state.write(address & 0xff); state.write(address >> 8); } private void internalLDY(GeneratorState state, int value) { state.write(0xa0); state.write(value); } private void internalLDA(GeneratorState state, int value) { state.write(0xa9); state.write(value); } private void internalSTA(GeneratorState state, int address) { if ((address & 0xff00) == 0) { state.write(0x85); state.write(address); } else { throw new RuntimeException("sta does not handle 16 bit addresses yet!"); } } }