93 lines
3.0 KiB
C++
93 lines
3.0 KiB
C++
#pragma once
|
|
|
|
#include "coordinates.hpp"
|
|
#include "gen/maps.hpp"
|
|
#include "map_objects.hpp"
|
|
#include "vdp2.h"
|
|
|
|
constexpr inline uint8_t get_block(const map_t& map, block_t block)
|
|
{
|
|
const uint8_t border_block = map_objects[map.id].border_block;
|
|
|
|
const bool x_lt = block.x < static_cast<int32_t>(map.width);
|
|
const bool y_lt = block.y < static_cast<int32_t>(map.height);
|
|
const bool x_gt = block.x >= 0;
|
|
const bool y_gt = block.y >= 0;
|
|
|
|
const bool inside_map = x_lt && y_lt && x_gt && y_gt;
|
|
const bool north = x_lt && x_gt && !y_gt;
|
|
const bool south = x_lt && x_gt && !y_lt;
|
|
const bool west = y_lt && y_gt && !x_gt;
|
|
const bool east = y_lt && y_gt && !x_lt;
|
|
|
|
#define _has(_dir_) (map.connections[map_t::connection_t::_dir_].map != map_t::unconnected)
|
|
#define _get(_dir_) (maps[map.connections[map_t::connection_t::_dir_].map])
|
|
#define _offset(_dir_) (map.connections[map_t::connection_t::_dir_].offset)
|
|
|
|
if (inside_map) {
|
|
return map.blocks.start[map.width * block.y + block.x];
|
|
} else if (north && _has(north)) {
|
|
const map_t& north_map = _get(north);
|
|
return get_block(north_map, {
|
|
.x = block.x - _offset(north),
|
|
.y = static_cast<int32_t>(north_map.height + block.y),
|
|
});
|
|
} else if (south && _has(south)) {
|
|
const map_t& south_map = _get(south);
|
|
return get_block(south_map, {
|
|
.x = block.x - _offset(south),
|
|
.y = static_cast<int32_t>(block.y - map.height),
|
|
});
|
|
} else if (west && _has(west)) {
|
|
const map_t& west_map = _get(west);
|
|
return get_block(west_map, {
|
|
.x = static_cast<int32_t>(west_map.width + block.x),
|
|
.y = block.y - _offset(west),
|
|
});
|
|
} else if (east && _has(east)) {
|
|
const map_t& east_map = _get(east);
|
|
return get_block(east_map, {
|
|
.x = static_cast<int32_t>(block.x - map.width),
|
|
.y = block.y - _offset(east),
|
|
});
|
|
} else {
|
|
return border_block;
|
|
}
|
|
|
|
#undef _offset
|
|
#undef _get
|
|
#undef _has
|
|
}
|
|
|
|
namespace cell_offset
|
|
{
|
|
int32_t x = (320 - 160) / (2 * 8);
|
|
int32_t y = (240 - 144) / (2 * 8);
|
|
}
|
|
|
|
static inline void render_screen(const uint32_t base_pattern,
|
|
const map_t& map,
|
|
const world_t& origin,
|
|
const screen_t& screen)
|
|
{
|
|
const world_t world = screen.to_world(origin);
|
|
// keep this synchronized with collision()
|
|
const uint8_t block_ix = get_block(map, world.to_block());
|
|
const tileset_t& tileset = tilesets[map.tileset];
|
|
const uint8_t * block_start = &(tileset.blockset.start)[block_ix * 4 * 4];
|
|
const int32_t quadrant_x = 2 * (world.x & 1);
|
|
const int32_t quadrant_y = 2 * (world.y & 1);
|
|
|
|
for (int32_t tile_y = quadrant_y; tile_y < quadrant_y + 2; tile_y++) {
|
|
const int32_t block_row = 4 * tile_y;
|
|
for (int32_t tile_x = quadrant_x; tile_x < quadrant_x + 2; tile_x++) {
|
|
const uint8_t tile_ix = block_start[block_row + tile_x];
|
|
|
|
const uint32_t cell_y = cell_offset::y + screen.y * 2 + tile_y - quadrant_y;
|
|
const uint32_t cell_x = cell_offset::x + screen.x * 2 + tile_x - quadrant_x;
|
|
|
|
vdp2.vram.u16[64 * (cell_y % 64) + (cell_x % 64)] = (base_pattern & 0xfff) + tile_ix;
|
|
}
|
|
}
|
|
}
|