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;
}
}