#![warn(missing_docs)]
#![allow(clippy::cast_lossless)]
#![allow(clippy::mixed_case_hex_literals)]
#![allow(dead_code)]
#![allow(unused_imports)]
#[cfg(all(feature = "avoid_std", not(test), windows))]
extern crate std;
#[cfg(all(feature = "just_a_no_std_lib", not(test), not(windows)))]
unsafe fn sdl_quit_and_exit_failure() -> ! {
sdl2_sys::SDL_Quit();
libc::exit(libc::EXIT_FAILURE);
}
#[cfg(all(feature = "just_a_no_std_lib", not(test), not(windows)))]
#[panic_handler]
fn panic_exit(_info: &core::panic::PanicInfo) -> ! {
unsafe { sdl_quit_and_exit_failure() }
}
#[cfg(all(feature = "just_a_no_std_lib", not(test), not(windows)))]
#[alloc_error_handler]
fn alloc_exit(_layout: core::alloc::Layout) -> ! {
unsafe { sdl_quit_and_exit_failure() }
}
pub mod interchange;
use interchange::*;
pub mod color;
use color::*;
pub mod dmg_render;
use dmg_render::*;
pub mod dmg_apu;
use dmg_apu::*;
#[allow(dead_code)]
const UPDATE_AND_RENDER_CHECK: GameUpdateAndRenderFn = game_update_and_render;
#[allow(dead_code)]
const GET_SOUND_SAMPLES_CHECK: GameGetSoundSamplesFn = game_get_sound_samples;
#[cfg(feature = "dynamic_link")]
#[no_mangle]
pub extern "C" fn game_update_and_render(
memory: &mut GameMemory, input: &GameInput, bitmap: &mut Bitmap,
) {
game_update_and_render_inner(memory, input, bitmap)
}
#[cfg(not(feature = "dynamic_link"))]
pub fn game_update_and_render(memory: &mut GameMemory, input: &GameInput, bitmap: &mut Bitmap) {
game_update_and_render_inner(memory, input, bitmap)
}
fn game_update_and_render_inner(memory: &mut GameMemory, input: &GameInput, bitmap: &mut Bitmap) {
let config = &mut memory.config;
let controller = &input.gamepads[0];
if controller.arrow_right {
memory.px = memory.px.wrapping_add(1);
}
if controller.arrow_left {
memory.px = memory.px.wrapping_sub(1);
}
if controller.arrow_up {
memory.py = memory.py.wrapping_sub(1);
}
if controller.arrow_down {
memory.py = memory.py.wrapping_add(1);
}
if controller.l && !memory.l_was_down {
memory.apu.pulse_a.play_samples_remaining = core::usize::MAX;
memory.apu.pulse_a.sweep = FrequencySweep::new(260, 5, 7, 48000);
memory.apu.pulse_a.envelope = LevelEnvelope::new(0, 1.0, 48000);
memory.apu.pulse_a.duty = 0.5;
}
if controller.r && !memory.r_was_down {
memory.apu.pulse_b.play_samples_remaining = core::usize::MAX;
memory.apu.pulse_b.sweep = FrequencySweep::new(360, -3, 1, 48000);
memory.apu.pulse_b.envelope = LevelEnvelope::new(0, 1.0, 48000);
memory.apu.pulse_b.duty = 0.5;
}
if controller.east && !memory.east_was_down {
memory.apu.wave.play_samples_remaining = 48000;
memory.apu.wave.sweep = FrequencySweep::new(360, -3, 1, 48000);
memory.apu.wave.wave = [
0x7, 0xA, 0xA, 0x8, 0x6, 0x4, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x3, 0xB, 0xA, 0x3, 0x1,
0x0, 0x0, 0x3, 0x6, 0x9, 0xB, 0xA, 0x9, 0x7, 0x6, 0x5, 0x6, 0x6, 0x7,
]
.iter()
.cloned()
.map(|u| u as f32 / 15.0)
.collect();
}
if controller.south && !memory.south_was_down {
memory.apu.wave.play_samples_remaining = 12000;
memory.apu.wave.sweep = FrequencySweep::new(200, 0, 0, 48000);
memory.apu.wave.wave = [
0x7, 0xA, 0xA, 0x8, 0x6, 0x4, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x3, 0xB, 0xA, 0x3, 0x1,
0x0, 0x0, 0x3, 0x6, 0x9, 0xB, 0xA, 0x9, 0x7, 0x6, 0x5, 0x6, 0x6, 0x7,
]
.iter()
.cloned()
.map(|u| u as f32 / 15.0)
.collect();
}
if controller.north && !memory.north_was_down {
memory.apu.noise.play_samples_remaining = 48000;
memory.apu.noise.level = LevelEnvelope::new(0, 1.0, 48000);
memory.apu.noise.frequency = NoiseVoice::frequency_for(3, 3);
memory.apu.noise.counter = NoiseCounter::default();
}
memory.l_was_down = controller.l;
memory.r_was_down = controller.r;
memory.east_was_down = controller.east;
memory.south_was_down = controller.south;
memory.north_was_down = controller.north;
render_weird_gradient(bitmap, 0, 0);
let mut tile_memory = DMGTileMemory::default();
dmg_inflate_tile_data(&mut tile_memory.tiles, TERRAIN_TILES);
dmg_inflate_tile_data(
&mut tile_memory.tiles[DMGTileMemory::INFLATED_BYTES_PER_TILE
* (TERRAIN_TILES.len() / DMGTileMemory::COMPRESSED_BYTES_PER_TILE)..],
CREATURE_TILES,
);
let mut bg_screenblock = DMGScreenblock::default();
bg_screenblock
.entries
.iter_mut()
.for_each(|e_mut| *e_mut = 4);
let row_col = |row: usize, col: usize| col + row * 32;
for row in 0..32 {
for col in 0..32 {
if row == 0 || row == 31 || col == 0 || col == 31 {
bg_screenblock.entries[row_col(row, col)] = 8;
} else {
bg_screenblock.entries[row_col(row, col)] = 4;
}
}
}
let mut win_screenblock = DMGScreenblock::default();
win_screenblock
.entries
.iter_mut()
.for_each(|e_mut| *e_mut = b'.');
for n in 0..32 {
win_screenblock.entries[n] = b'0' + n as u8;
}
config.window_enabled = true;
config.window_xp7 = 7;
config.window_y = 17 * 8;
config.objects_enabled = true;
config.objects_are_tall = true;
let mut oam = vec![
DMGOAMEntry {
xm8: memory.px.wrapping_add(8),
ym16: memory.py.wrapping_add(16 + 16),
tile_id: 128,
display_behind_bg_win_13: false,
vflip: false,
hflip: false,
use_high_palette: false,
},
DMGOAMEntry {
xm8: memory.px.wrapping_add(8 + 8),
ym16: memory.py.wrapping_add(16 + 16),
tile_id: 130,
display_behind_bg_win_13: false,
vflip: false,
hflip: false,
use_high_palette: false,
},
];
let saved_xp7 = config.window_xp7;
dmg_hblank_render(
bitmap,
config,
&mut tile_memory,
&mut [&mut bg_screenblock, &mut win_screenblock],
&mut oam,
&FOUR_COLOR_PALETTES[memory.pal_index % FOUR_COLOR_PALETTES.len()],
|config: &mut DMGConfig,
_: &mut DMGTileMemory,
_: &mut [&mut DMGScreenblock],
_: &mut [DMGOAMEntry]| {
config.window_xp7 = config.window_xp7.wrapping_add(0);
},
);
config.window_xp7 = saved_xp7;
}
#[cfg(feature = "dynamic_link")]
#[no_mangle]
pub extern "C" fn game_get_sound_samples(
memory: &mut GameMemory, samples_per_second: i32, buf: &mut [StereoI16],
) {
game_get_sound_samples_inner(memory, samples_per_second, buf)
}
#[cfg(not(feature = "dynamic_link"))]
pub fn game_get_sound_samples(
memory: &mut GameMemory, samples_per_second: i32, buf: &mut [StereoI16],
) {
game_get_sound_samples_inner(memory, samples_per_second, buf)
}
#[allow(unused)]
fn game_get_sound_samples_inner(
memory: &mut GameMemory, samples_per_second: i32, buf: &mut [StereoI16],
) {
buf
.iter_mut()
.for_each(|s| *s = StereoI16 { left: 0, right: 0 });
memory.apu.fill_sound_buffer(samples_per_second, buf);
}
pub fn render_weird_gradient(bitmap: &mut Bitmap, blue_offset: i32, green_offset: i32) {
let bitmap_memory = bitmap.memory;
let width = bitmap.width;
let height = bitmap.height;
let pitch = bitmap.pitch;
let mut row_start = bitmap_memory;
for y in 0..height {
#[allow(clippy::cast_ptr_alignment)]
let mut pixel = row_start as *mut u32;
for x in 0..width {
let blue = (x + blue_offset) as u8 as u32;
let green = (y + green_offset) as u8 as u32;
unsafe {
pixel.write_unaligned(blue | (green << 8));
pixel = pixel.offset(1);
}
}
row_start = unsafe { row_start.offset(pitch) };
}
}
const TERRAIN_TILES: &[u8] = &[
0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x24, 0x00, 0x18, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x28, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x68, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x14, 0x00, 0x28, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00,
0x00, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x20, 0x00, 0x00, 0x00,
0x80, 0x00, 0xC0, 0x00, 0xE2, 0x00, 0x66, 0x00, 0x6E, 0x00, 0x2C, 0x00, 0x0C, 0x00, 0x08, 0x00,
0x00, 0x00, 0x41, 0x00, 0x61, 0x00, 0x63, 0x00, 0x36, 0x00, 0x36, 0x00, 0x16, 0x00, 0x14, 0x00,
0x80, 0x00, 0xC0, 0x00, 0xC2, 0x00, 0x46, 0x00, 0x6E, 0x00, 0x2C, 0x00, 0x2C, 0x00, 0x28, 0x00,
0x1C, 0x1C, 0x36, 0x2A, 0x43, 0x7D, 0xC1, 0xBF, 0x81, 0xFF, 0x81, 0xFF, 0x4E, 0x7E, 0x30, 0x30,
0x18, 0x18, 0x34, 0x2C, 0x26, 0x3A, 0x43, 0x7D, 0x81, 0xFF, 0x81, 0xFF, 0x62, 0x7E, 0x1C, 0x1C,
0x48, 0x48, 0xBC, 0xF4, 0x84, 0xFC, 0x42, 0x7E, 0x43, 0x7D, 0x41, 0x7F, 0x46, 0x7E, 0x38, 0x38,
0x00, 0x00, 0x38, 0x38, 0x6E, 0x56, 0x83, 0xFD, 0x81, 0xFF, 0x81, 0xFF, 0x42, 0x7E, 0x3C, 0x3C,
0x00, 0x07, 0x05, 0x18, 0x0A, 0x20, 0x15, 0x40, 0x2A, 0x80, 0x55, 0x80, 0x6B, 0x80, 0x7F, 0x80,
0x7F, 0x80, 0x7F, 0x40, 0x3F, 0x20, 0x1F, 0x10, 0x0F, 0x0F, 0x02, 0x03, 0x03, 0x02, 0x02, 0x03,
0x00, 0xE0, 0x40, 0x18, 0xA8, 0x04, 0x54, 0x02, 0xAA, 0x01, 0x7E, 0x01, 0xFE, 0x01, 0xFE, 0x01,
0xFE, 0x01, 0xFE, 0x02, 0xFC, 0x04, 0xF8, 0x08, 0xF0, 0xF0, 0xC0, 0x40, 0x40, 0xC0, 0xC0, 0x40,
0x00, 0x00, 0x7F, 0x7F, 0x40, 0x7F, 0x44, 0x7B, 0x50, 0x6F, 0x40, 0x7F, 0x43, 0x7F, 0x42, 0x7E,
0x42, 0x7E, 0x43, 0x7F, 0x40, 0x7F, 0x50, 0x6F, 0x42, 0x7D, 0x40, 0x7F, 0x7F, 0x7F, 0x00, 0x00,
0x00, 0x00, 0xFE, 0xFE, 0x02, 0xFE, 0x22, 0xDE, 0x02, 0xFE, 0x0A, 0xF6, 0xC2, 0xFE, 0x42, 0x7E,
0x42, 0x7E, 0xC2, 0xFE, 0x22, 0xDE, 0x0A, 0xF6, 0x02, 0xFE, 0x02, 0xFE, 0xFE, 0xFE, 0x00, 0x00,
0x00, 0x00, 0x7E, 0x7E, 0x42, 0x7E, 0x4A, 0x76, 0x42, 0x7E, 0x42, 0x7E, 0x42, 0x7E, 0x62, 0x5E,
0x42, 0x7E, 0x42, 0x7E, 0x42, 0x7E, 0x4A, 0x76, 0x42, 0x7E, 0x42, 0x7E, 0x7E, 0x7E, 0x00, 0x00,
0x00, 0x00, 0xFE, 0xFE, 0x02, 0xFE, 0x22, 0xDE, 0x0A, 0xF6, 0x02, 0xFE, 0xFE, 0xFE, 0x00, 0x00,
0x00, 0x00, 0x7F, 0x7F, 0x40, 0x7F, 0x50, 0x6F, 0x42, 0x7D, 0x40, 0x7F, 0x7F, 0x7F, 0x00, 0x00,
0x00, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x40, 0xBF, 0x04, 0xFB, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
0x42, 0x7E, 0x4A, 0x76, 0x42, 0x7E, 0x42, 0x7E, 0x42, 0x7E, 0x52, 0x6E, 0x42, 0x7E, 0x42, 0x7E,
0x00, 0x00, 0x7E, 0x7E, 0x42, 0x7E, 0x42, 0x7E, 0x42, 0x7E, 0x42, 0x7E, 0x7E, 0x7E, 0x00, 0x00,
0x00, 0xFF, 0x02, 0xFF, 0x40, 0xBF, 0x00, 0xFF, 0x00, 0xFF, 0x20, 0xFF, 0x01, 0xFE, 0x00, 0xFF,
0x00, 0xFF, 0x20, 0xFF, 0x02, 0xFD, 0x00, 0xFF, 0x00, 0xFF, 0x40, 0xBF, 0x00, 0xFF, 0x08, 0xFF,
0x00, 0xFF, 0x10, 0xEF, 0x00, 0xFF, 0x02, 0xFF, 0x00, 0xFF, 0x20, 0xFF, 0x02, 0xFD, 0x00, 0xFF,
0x00, 0xFF, 0x21, 0xFE, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x21, 0xDF, 0x00, 0xFF, 0x00, 0xFF,
0xFF, 0xFF, 0xFF, 0x81, 0xFF, 0xB5, 0xFF, 0x81, 0x81, 0xFF, 0xFF, 0xFF, 0x08, 0x08, 0x08, 0x08,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10,
0x00, 0x00, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x24, 0x24, 0x24, 0x24, 0x7E, 0x7E, 0x24, 0x24, 0x7E, 0x7E, 0x24, 0x24, 0x24, 0x24,
0x08, 0x08, 0x3E, 0x3E, 0x40, 0x40, 0x3C, 0x3C, 0x02, 0x02, 0x7C, 0x7C, 0x10, 0x10, 0x00, 0x00,
0x20, 0x20, 0x52, 0x52, 0x24, 0x24, 0x08, 0x08, 0x10, 0x10, 0x24, 0x24, 0x4A, 0x4A, 0x04, 0x04,
0x38, 0x38, 0x44, 0x44, 0x40, 0x40, 0x20, 0x20, 0x54, 0x54, 0x48, 0x48, 0x44, 0x44, 0x3A, 0x3A,
0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08,
0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10,
0x00, 0x00, 0x10, 0x10, 0x54, 0x54, 0x38, 0x38, 0x54, 0x54, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x7C, 0x7C, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x30,
0x04, 0x04, 0x04, 0x04, 0x08, 0x08, 0x08, 0x08, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20,
0x00, 0x00, 0x08, 0x08, 0x3C, 0x3C, 0x7E, 0x7E, 0x3C, 0x3C, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1E, 0x1E, 0x20, 0x20, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00,
0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04,
0x1C, 0x1C, 0x20, 0x20, 0x40, 0x40, 0x40, 0x40, 0x78, 0x78, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08,
0x00, 0x00, 0x1E, 0x1E, 0x48, 0x48, 0x24, 0x24, 0x10, 0x10, 0x08, 0x08, 0x44, 0x44, 0x38, 0x38,
0x3C, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x40, 0x40, 0x78, 0x78, 0x20, 0x20, 0x38, 0x38, 0x10, 0x10,
0x00, 0x00, 0x80, 0x80, 0x42, 0x42, 0x24, 0x24, 0x38, 0x38, 0x24, 0x24, 0x24, 0x24, 0x04, 0x04,
0x02, 0x02, 0x44, 0x44, 0x48, 0x48, 0xA8, 0xA8, 0x18, 0x18, 0x28, 0x28, 0x04, 0x04, 0x02, 0x02,
0x00, 0x00, 0x81, 0x81, 0x5A, 0x5A, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x5A, 0x5A, 0x99, 0x99,
0x10, 0x10, 0x38, 0x38, 0x54, 0x54, 0x92, 0x92, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x38, 0x38,
0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x30,
0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20,
0x00, 0x00, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x3C, 0x00, 0x00, 0x3C, 0x3C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20,
0x38, 0x38, 0x44, 0x44, 0x44, 0x44, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10,
0x3C, 0x3C, 0x42, 0x42, 0x99, 0x99, 0xA5, 0xA5, 0xA5, 0xA5, 0x9A, 0x9A, 0x40, 0x40, 0x3C, 0x3C,
0x38, 0x38, 0x44, 0x44, 0x82, 0x82, 0x82, 0x82, 0xFE, 0xFE, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
0x70, 0x70, 0x48, 0x48, 0x44, 0x44, 0x44, 0x44, 0x78, 0x78, 0x44, 0x44, 0x44, 0x44, 0x78, 0x78,
0x38, 0x38, 0x44, 0x44, 0x82, 0x82, 0x80, 0x80, 0x80, 0x80, 0x82, 0x82, 0x44, 0x44, 0x38, 0x38,
0x78, 0x78, 0x44, 0x44, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x44, 0x44, 0x78, 0x78,
0x7C, 0x7C, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x78, 0x78, 0x40, 0x40, 0x40, 0x40, 0x7C, 0x7C,
0x7E, 0x7E, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x78, 0x78, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x38, 0x38, 0x44, 0x44, 0x82, 0x82, 0x80, 0x80, 0x9C, 0x9C, 0x82, 0x82, 0x44, 0x44, 0x38, 0x38,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x7C, 0x7C, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
0x7C, 0x7C, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7C, 0x7C,
0x3E, 0x3E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x48, 0x48, 0x48, 0x48, 0x30, 0x30,
0x44, 0x44, 0x48, 0x48, 0x50, 0x50, 0x60, 0x60, 0x60, 0x60, 0x50, 0x50, 0x48, 0x48, 0x44, 0x44,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x7C, 0x7C,
0x82, 0x82, 0xC6, 0xC6, 0xAA, 0xAA, 0x92, 0x92, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
0x82, 0x82, 0xC2, 0xC2, 0xA2, 0xA2, 0x92, 0x92, 0x8A, 0x8A, 0x86, 0x86, 0x82, 0x82, 0x82, 0x82,
0x3C, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x3C,
0x78, 0x78, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x78, 0x78, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x38, 0x38, 0x44, 0x44, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x8A, 0x8A, 0x44, 0x44, 0x3A, 0x3A,
0x78, 0x78, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x78, 0x78, 0x50, 0x50, 0x48, 0x48, 0x44, 0x44,
0x3C, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x40, 0x40, 0x3C, 0x3C, 0x02, 0x02, 0x42, 0x42, 0x3C, 0x3C,
0xFE, 0xFE, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x42, 0x3C, 0x3C,
0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x44, 0x44, 0x44, 0x44, 0x28, 0x28, 0x28, 0x28, 0x10, 0x10,
0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x28, 0x28, 0x28, 0x28,
0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x28, 0x28, 0x10, 0x10, 0x28, 0x28, 0x44, 0x44, 0x44, 0x44,
0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x28, 0x28, 0x28, 0x28, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
0x00, 0x00, 0x7E, 0x7E, 0x02, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x7E, 0x7E,
0x38, 0x38, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x38, 0x38,
0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04,
0x1C, 0x1C, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1C, 0x1C,
0x10, 0x10, 0x28, 0x28, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E,
0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1E, 0x1E, 0x20, 0x20, 0x20, 0x20, 0x78, 0x78, 0x40, 0x40, 0x80, 0x80, 0x7E, 0x7E,
0x00, 0x00, 0x06, 0x06, 0x28, 0x28, 0x70, 0x70, 0x28, 0x28, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04,
0x00, 0x00, 0x22, 0x22, 0x52, 0x52, 0x8A, 0x8A, 0x06, 0x06, 0x02, 0x02, 0x04, 0x04, 0x38, 0x38,
0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x12, 0x12, 0x22, 0x22, 0x42, 0x42, 0x24, 0x24, 0x10, 0x10,
0x00, 0x00, 0x7E, 0x7E, 0x7E, 0x7E, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20,
0xFE, 0xFE, 0x71, 0x71, 0x31, 0x31, 0x12, 0x12, 0x20, 0x20, 0x40, 0x40, 0x40, 0x40, 0x30, 0x30,
0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E, 0x08, 0x08, 0x08, 0x08, 0x10, 0x10, 0x3E, 0x3E, 0x40, 0x40,
0x38, 0x38, 0x6C, 0x6C, 0x44, 0x44, 0x44, 0x44, 0x28, 0x28, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04,
0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x28, 0x28, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04,
0x00, 0x00, 0x40, 0x40, 0xBE, 0xBE, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x44, 0x44, 0x80, 0x80,
0x00, 0x00, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08,
0x10, 0x10, 0x28, 0x28, 0x24, 0x24, 0x42, 0x42, 0x40, 0x40, 0x80, 0x80, 0xF0, 0xF0, 0x10, 0x10,
0x38, 0x38, 0x7C, 0x7C, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0x60, 0x60, 0x10, 0x10, 0x08, 0x08,
0x38, 0x38, 0x44, 0x44, 0x82, 0x82, 0x80, 0x80, 0x78, 0x78, 0x20, 0x20, 0x10, 0x10, 0x0C, 0x0C,
0x00, 0x00, 0xFE, 0xFE, 0x3A, 0x3A, 0x1C, 0x1C, 0x0C, 0x0C, 0x08, 0x08, 0x10, 0x10, 0x08, 0x08,
0x00, 0x00, 0x10, 0x10, 0x20, 0x20, 0x58, 0x58, 0x04, 0x04, 0x04, 0x04, 0x48, 0x48, 0x30, 0x30,
0x00, 0x00, 0x06, 0x06, 0x18, 0x18, 0x20, 0x20, 0x70, 0x70, 0x08, 0x08, 0x04, 0x04, 0x08, 0x08,
0x00, 0x00, 0xFE, 0xFE, 0x78, 0x78, 0x3A, 0x3A, 0x1C, 0x1C, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20,
0x44, 0x44, 0x38, 0x38, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x4C, 0x4C, 0x00, 0x00,
0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x22, 0x22, 0x26, 0x26, 0x4E, 0x4E, 0x70, 0x70, 0x80, 0x80,
0x00, 0x00, 0x04, 0x04, 0x0C, 0x0C, 0x14, 0x14, 0x20, 0x20, 0x42, 0x42, 0x7E, 0x7E, 0x80, 0x80,
0x01, 0x01, 0x02, 0x02, 0x44, 0x44, 0x7C, 0x7C, 0x7C, 0x7C, 0x44, 0x44, 0x82, 0x82, 0x02, 0x02,
0x00, 0x00, 0x00, 0x00, 0x7C, 0x7C, 0x40, 0x40, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04,
0x26, 0x26, 0x52, 0x52, 0x92, 0x92, 0x14, 0x14, 0x18, 0x18, 0x30, 0x30, 0x18, 0x18, 0x0C, 0x0C,
0x00, 0x00, 0x3E, 0x3E, 0x64, 0x64, 0x64, 0x64, 0x7C, 0x7C, 0x38, 0x38, 0x18, 0x18, 0x04, 0x04,
0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0C, 0x0C, 0x10, 0x10, 0x10, 0x10, 0x60, 0x60, 0x10, 0x10, 0x10, 0x10, 0x0C, 0x0C,
0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
0x00, 0x00, 0x30, 0x30, 0x08, 0x08, 0x08, 0x08, 0x06, 0x06, 0x08, 0x08, 0x08, 0x08, 0x30, 0x30,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x32, 0x4C, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xC3, 0xFF, 0xA5, 0xFF, 0x99, 0xFF, 0x99, 0xFF, 0xA5, 0xFF, 0xC3, 0xFF, 0xFF, 0xFF,
];
const CREATURE_TILES: &[u8] = &[
0x00, 0x00, 0x08, 0x08, 0x0C, 0x0C, 0x0A, 0x0E, 0x09, 0x0F, 0x08, 0x0F, 0x0A, 0x0F, 0x0A, 0x0F,
0x08, 0x0F, 0x48, 0x4F, 0x38, 0x3F, 0x08, 0x0F, 0x34, 0x37, 0x43, 0x42, 0x01, 0x01, 0x00, 0x00,
0x00, 0x00, 0x10, 0x10, 0x30, 0x30, 0x50, 0x70, 0x90, 0xF0, 0x10, 0xF0, 0x50, 0xF0, 0x50, 0xF0,
0x10, 0xF0, 0x12, 0xF2, 0x1C, 0xFC, 0x10, 0xF0, 0x2C, 0xEC, 0xC2, 0x42, 0x80, 0x80, 0x00, 0x00,
0x48, 0x48, 0x6C, 0x6C, 0x5A, 0x7E, 0x69, 0x5F, 0x74, 0x4F, 0x5A, 0x67, 0x41, 0x7F, 0x40, 0x7F,
0x41, 0x7F, 0x40, 0x7F, 0x40, 0x7F, 0x40, 0x7F, 0x40, 0x7F, 0x20, 0x3F, 0x1F, 0x1F, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x40, 0xC0, 0xE0, 0xE0, 0x10, 0xF0,
0x88, 0xF8, 0xC4, 0xFC, 0x02, 0xFE, 0x04, 0xFC, 0x08, 0xF8, 0x10, 0xF0, 0xE0, 0xE0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x02, 0x0F, 0x0C, 0x1D, 0x12, 0x3F, 0x21,
0x7F, 0x7E, 0x7F, 0x40, 0x7F, 0x40, 0x77, 0x48, 0x7F, 0x40, 0x7F, 0x40, 0x7F, 0x7F, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xC0, 0x40, 0xE0, 0x20, 0x70, 0x90, 0xF8, 0x18, 0xFC, 0xE4,
0xFC, 0x04, 0xEC, 0x14, 0x7C, 0x84, 0xFC, 0x04, 0xDC, 0x24, 0xFC, 0x04, 0xFC, 0xFC, 0x00, 0x00,
];