yagbas 0.2.0

Yagbas is a programming language that builds programs for the Game Boy.
Documentation

const TILEMAP_WIDTH: u8 = 32;
const TILEMAP_HEIGHT: u8 = 32;
const SCREEN_WIDTH_TILES: u8 = 20;
const SCREEN_HEIGHT_TILES: u8 = 18;

#[location($FE00)]
static mmio OAM_RAM: [Obj; 40];

struct Obj {
  y: u8,
  x: u8,
  tile_id: u8,
  attrs: ObjAttrs,
}

bitbag ObjAttrs {
  cgb_palette: 0-2,
  cgb_tile_bank: 3,
  dmg_pal_1: 4,
  x_flip: 5,
  y_flip: 6,
  bg_win_priority: 7,
}

#[location($FF00)]
static mmio P1: u8;

bitbag KeysPressed {
  a: 0,
  b: 1,
  select: 2,
  start: 3,
  right: 4,
  left: 5,
  up: 6,
  down: 7,
}

fn get_keys_pressed() -> KeysPressed {
  // set for button reading, then read twice to ensure
  // the correct data comes in.
  *P1 = 0b1101_1111;
  let buttons_released = *P1;
  let buttons_released = *P1;
  // switch to reading directions, now we read 8 times
  // to allow the register signals to fully update.
  *P1 = 0b1110_1111;
  let dpad_released;
  loop 8 times {
    dpad_released = *P1;
  }
  // release the input reading, which saves some power.
  *P1 = 0b1111_1111;
  buttons_released |= $F0;
  dpad_released |= $F0;
  let all_released = swap!(dpad_released) | buttons_released;
  let all_pressed = all_released ^ -1;
  return KeysPressed(all_pressed)
}

// https://gbdev.io/pandocs/Interrupts.html#ff0f--if-interrupt-flag
#[location($FF0F)]
static mmio IF: Interrupts;

bitbag Interrupts {
  vblank: 0,
  lcd_stat: 1,
  timer: 2,
  serial: 3,
  joypad: 4,
}

#[location($FF26)]
static mmio NR52: AudioMain;

bitbag AudioMain {
  ch1_active: 0,
  ch2_active: 1,
  ch3_active: 2,
  ch4_active: 3,
  audio_enabled: 7,
}

#[location($FF40)]
static mmio LCDC: LcdCtrl;

bitbag LcdCtrl {
  bg_win_enabled: 0,
  objects_enabled: 1,
  object16: 2,
  bg_tilemap_1: 3,
  bg_win_tiles_signed: 4,
  window_enabled: 5,
  win_tilemap_1: 4,
  lcd_enabled: 7,
}

#[location($FF41)]
static mmio STAT: LcdStatus;

bitbag LcdStatus {
  ppu_mode: 0-1,
  lyc_eq_ly_currently: 2,
  mode_0_irq: 3,
  mode_1_irq: 4,
  mode_2_irq: 5,
  lyc_eq_ly_irq: 6,
}

#[location($FF42)]
static mmio SCY: u8;

#[location($FF43)]
static mmio SCX: u8;

#[location($FF44)]
static mmio LY: u8;

#[location($FF45)]
static mmio LYC: u8;

const VBLANK_START: u8 = 144;

// https://gbdev.io/pandocs/OAM_DMA_Transfer.html
#[location($FF46)]
static mmio DMA: u8;

// non-CGB mode background palette
#[location($FF47)]
static mmio BGP: Palette;

bitbag Palette {
  i0: 0-1,
  i1: 2-3,
  i2: 4-5,
  i3: 6-7,
}

const STANDARD_PALETTE: Palette = Palette {
  i0 = 0,
  i1 = 1,
  i2 = 2,
  i3 = 3,
};

// https://gbdev.io/pandocs/Interrupts.html#ffff--ie-interrupt-enable
#[location($FFFF)]
static mmio IE: Interrupts;

fn memcpy(dst: ptr, src: ptr, count: u16) {
  loop count times {
    *dst = *src;
    dst += 1;
    src += 1;
  }
}

fn memclr(dst: ptr, count: u16) {
  loop count times {
    *dst = 0;
    dst += 1;
  }
}

fn memclr_small(dst: ptr, count: u8) {
  loop count times {
    *dst = 0;
    dst += 1;
  }
}