414 lines
12 KiB
C
414 lines
12 KiB
C
|
/**
|
||
|
* @brief Graphics engine
|
||
|
*/
|
||
|
|
||
|
#include "graphics_sub.h"
|
||
|
#include "engine.h"
|
||
|
|
||
|
#include "text.h"
|
||
|
#include "title.h"
|
||
|
#include "kc_full.h"
|
||
|
|
||
|
#define TEXT_TILE_OFFSET_SUB_0 6
|
||
|
#define TEXT_TILE_OFFSET_SUB_1 7
|
||
|
#define TEXT_TILE_MAP_SUB_0 BG_MAP_RAM_SUB(TEXT_TILE_OFFSET_SUB_0)
|
||
|
#define TEXT_TILE_MAP_SUB_1 BG_MAP_RAM_SUB(TEXT_TILE_OFFSET_SUB_1)
|
||
|
#define CLEAR_TEXT_TILE_MAP_0() memset(TEXT_TILE_MAP_SUB_0,0,32*48);
|
||
|
#define CLEAR_TEXT_TILE_MAP_1() memset(TEXT_TILE_MAP_SUB_1,0,32*48);
|
||
|
#define DRAW_TILE_AT_IDX(top,left) TEXT_TILE_MAP_SUB_0[(top) * 32 + (left)]
|
||
|
|
||
|
|
||
|
#define SPRITE_WIDTH 32
|
||
|
#define SPRITE_HEIGHT 32
|
||
|
|
||
|
#define KC_ROT 0
|
||
|
#define KC_IDX 0
|
||
|
|
||
|
#define GFX_PTR_OFFSET(offset) (((u32)offset & 0xFFFFF) >> oamSub.gfxOffsetStep)
|
||
|
|
||
|
#define SET_KC(gfxx) \
|
||
|
do { \
|
||
|
oamSub.oamMemory[KC_IDX].gfxIndex = GFX_PTR_OFFSET(gfxx); \
|
||
|
} while(false)
|
||
|
|
||
|
|
||
|
#define MOVE_KC(xx, yy) \
|
||
|
do { \
|
||
|
oamSub.oamMemory[KC_IDX].x = (xx); \
|
||
|
oamSub.oamMemory[KC_IDX].y = (yy); \
|
||
|
} while(false)
|
||
|
|
||
|
#define AFFINE_TRANSFORM(hx,vx,hy,vy)\
|
||
|
do { \
|
||
|
oamSub.oamRotationMemory[KC_ROT].hdx = hx;\
|
||
|
oamSub.oamRotationMemory[KC_ROT].vdx = vx;\
|
||
|
oamSub.oamRotationMemory[KC_ROT].hdy = hy;\
|
||
|
oamSub.oamRotationMemory[KC_ROT].vdy = vy;\
|
||
|
} while(false)
|
||
|
|
||
|
|
||
|
#define SCALE_KC(x,y) AFFINE_TRANSFORM(256*x,0,0,256*y)
|
||
|
|
||
|
u16* gfx_kc;
|
||
|
u16* gfx_kc_val;
|
||
|
u16* gfx_kc_inv;
|
||
|
u16* gfx_kc_slot;
|
||
|
|
||
|
#define SWITCH_KC_GRAPHICS(part,slot)\
|
||
|
do{\
|
||
|
if(slot >0 && part >0){\
|
||
|
if(slot == part){\
|
||
|
SET_KC(gfx_kc_val);\
|
||
|
}else{\
|
||
|
SET_KC(gfx_kc_inv);\
|
||
|
}\
|
||
|
}else if(slot > 0){\
|
||
|
SET_KC(gfx_kc_slot);\
|
||
|
}else if (part > 0){\
|
||
|
SET_KC(gfx_kc);\
|
||
|
}else{\
|
||
|
SET_KC(gfx_kc_slot);\
|
||
|
}\
|
||
|
}while(false)
|
||
|
|
||
|
|
||
|
u8 loading_screen_id = 0;
|
||
|
#define LOADING_SCREEN_COUNT 2
|
||
|
|
||
|
|
||
|
void configure_graphics_sub()
|
||
|
{
|
||
|
videoSetModeSub(MODE_5_2D);
|
||
|
vramSetBankC(VRAM_C_SUB_BG_0x06200000);
|
||
|
bgInitSub(0, BgType_Text8bpp, BgSize_T_256x256, TEXT_TILE_OFFSET_SUB_0, 0);
|
||
|
bgInitSub(1, BgType_Text8bpp, BgSize_T_256x256, TEXT_TILE_OFFSET_SUB_1, 0);
|
||
|
bgInitSub(2, BgType_Bmp8, BgSize_B8_256x256, 1, 0);
|
||
|
|
||
|
REG_BG2PA_SUB = 256;
|
||
|
REG_BG2PC_SUB = 0;
|
||
|
REG_BG2PB_SUB = 0;
|
||
|
REG_BG2PD_SUB = 256;
|
||
|
|
||
|
bgSetPriority(0,2);
|
||
|
bgSetPriority(1,1);
|
||
|
bgSetPriority(2,3);
|
||
|
|
||
|
swiCopy(titleBitmap + loading_screen_id * 64 * 192, BG_BMP_RAM_SUB(1), SCREEN_WIDTH * SCREEN_HEIGHT);
|
||
|
swiCopy(textTiles, BG_TILE_RAM_SUB(0), textTilesLen);
|
||
|
CLEAR_TEXT_TILE_MAP_0();
|
||
|
CLEAR_TEXT_TILE_MAP_1();
|
||
|
}
|
||
|
|
||
|
void create_palette_sub()
|
||
|
{
|
||
|
vramSetBankH(VRAM_H_SUB_BG_EXT_PALETTE);
|
||
|
swiCopy(titlePal, BG_PALETTE_SUB, titlePalLen);
|
||
|
SET_PERSONAL_PALETTE(BG_PALETTE_SUB);
|
||
|
}
|
||
|
|
||
|
void create_object_sub()
|
||
|
{
|
||
|
vramSetBankD(VRAM_D_SUB_SPRITE);
|
||
|
vramSetBankI(VRAM_I_SUB_SPRITE_EXT_PALETTE);
|
||
|
|
||
|
oamInit(&oamSub, SpriteMapping_1D_32, false);
|
||
|
|
||
|
gfx_kc = oamAllocateGfx(&oamSub, SpriteSize_32x64, SpriteColorFormat_256Color);
|
||
|
gfx_kc_val = oamAllocateGfx(&oamSub, SpriteSize_32x64, SpriteColorFormat_256Color);
|
||
|
gfx_kc_inv = oamAllocateGfx(&oamSub, SpriteSize_32x64, SpriteColorFormat_256Color);
|
||
|
gfx_kc_slot = oamAllocateGfx(&oamSub, SpriteSize_32x64, SpriteColorFormat_256Color);
|
||
|
|
||
|
//Copy data for the graphic (palette and bitmap)
|
||
|
swiCopy(kc_fullPal, SPRITE_PALETTE_SUB, kc_fullPalLen);
|
||
|
swiCopy(kc_fullTiles, gfx_kc, kc_fullTilesLen / (2 * 4));
|
||
|
swiCopy(kc_fullTiles + (64 * 8), gfx_kc_val, kc_fullTilesLen / (2 * 4));
|
||
|
swiCopy(kc_fullTiles + (64 * 16), gfx_kc_inv, kc_fullTilesLen / (2 * 4));
|
||
|
swiCopy(kc_fullTiles + (64 * 24), gfx_kc_slot, kc_fullTilesLen / (2 * 4));
|
||
|
oamSet(&oamSub, KC_IDX, SCREEN_WIDTH, 0, 0, 0, SpriteSize_32x64, SpriteColorFormat_256Color, gfx_kc,
|
||
|
KC_ROT, false, false, false, false, false);
|
||
|
}
|
||
|
|
||
|
|
||
|
void switch_mode_sub(gmode_t mode)
|
||
|
{
|
||
|
switch (mode) {
|
||
|
case GGAME:
|
||
|
CLEAR_TEXT_TILE_MAP_0();
|
||
|
CLEAR_TEXT_TILE_MAP_1();
|
||
|
SET_PERSONAL_PALETTE(BG_PALETTE_SUB);
|
||
|
break;
|
||
|
case GMENU:
|
||
|
CLEAR_TEXT_TILE_MAP_0();
|
||
|
CLEAR_TEXT_TILE_MAP_1();
|
||
|
swiCopy(titlePal, BG_PALETTE_SUB, titlePalLen);
|
||
|
swiCopy(titleBitmap + loading_screen_id * 64 * 192, BG_BMP_RAM_SUB(1), SCREEN_WIDTH * SCREEN_HEIGHT);
|
||
|
MOVE_KC(SCREEN_WIDTH, SCREEN_HEIGHT);
|
||
|
break;
|
||
|
case GGAME_ALT:
|
||
|
CLEAR_TEXT_TILE_MAP_0();
|
||
|
CLEAR_TEXT_TILE_MAP_1();
|
||
|
memset(BG_BMP_RAM_SUB(1), 0, SCREEN_WIDTH * SCREEN_HEIGHT);
|
||
|
swiCopy(textPal, BG_PALETTE_SUB, textPalLen);
|
||
|
MOVE_KC(SCREEN_WIDTH, SCREEN_HEIGHT);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void next_loading_isr(u8 f)
|
||
|
{
|
||
|
++loading_screen_id;
|
||
|
|
||
|
if (loading_screen_id >= LOADING_SCREEN_COUNT || f != 0) {
|
||
|
loading_screen_id = LOADING_SCREEN_COUNT;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void draw_title_sub()
|
||
|
{
|
||
|
swiCopy(titleBitmap + loading_screen_id * 64 * 192, BG_BMP_RAM_SUB(1), SCREEN_WIDTH * SCREEN_HEIGHT);
|
||
|
MOVE_KC(SCREEN_WIDTH, SCREEN_HEIGHT);
|
||
|
|
||
|
}
|
||
|
|
||
|
u8 hit_kc = 0;
|
||
|
u8 screen_buff[SCREEN_WIDTH * SCREEN_HEIGHT] = {0};
|
||
|
|
||
|
void draw_vertical_line(const u32 col, const position_t* const pos, const room_t room, const s16 slot_left)
|
||
|
{
|
||
|
s16 angle = MOD((pos->r - (FOV / 2) + (col * FOV) / (SCREEN_WIDTH * 1.0)), 360);
|
||
|
float32 raydir_x = fixedToFloat(sinLerp(degreesToAngle(angle)), 12);
|
||
|
float32 raydir_y = fixedToFloat(cosLerp(degreesToAngle(angle)), 12);
|
||
|
|
||
|
s16 map_x = (s16)(pos->x);
|
||
|
s16 map_y = (s16)(pos->y);
|
||
|
|
||
|
float32 delta_dist_x = ABS(1.0 / raydir_x);
|
||
|
float32 delta_dist_y = ABS(1.0 / raydir_y);
|
||
|
float32 perp_dist = 0.1;
|
||
|
|
||
|
s8 step_x;
|
||
|
s8 step_y;
|
||
|
float32 border_dist_x;
|
||
|
float32 border_dist_y;
|
||
|
|
||
|
if (raydir_x < 0) {
|
||
|
step_x = -1;
|
||
|
border_dist_x = (pos->x - map_x) * delta_dist_x;
|
||
|
} else {
|
||
|
step_x = 1;
|
||
|
border_dist_x = (map_x + 1.0 - pos->x) * delta_dist_x;
|
||
|
}
|
||
|
|
||
|
if (raydir_y < 0) {
|
||
|
step_y = -1;
|
||
|
border_dist_y = (pos->y - map_y) * delta_dist_y;
|
||
|
} else {
|
||
|
step_y = 1;
|
||
|
border_dist_y = (map_y + 1.0 - pos->y) * delta_dist_y;
|
||
|
}
|
||
|
|
||
|
u8 side = 0;
|
||
|
u8 hit = 0;
|
||
|
|
||
|
part_t slot = get_slot_id(room);
|
||
|
part_t part = get_part_id(room);
|
||
|
|
||
|
|
||
|
while (hit == 0) {
|
||
|
if (border_dist_x < border_dist_y) {
|
||
|
border_dist_x += delta_dist_x;
|
||
|
map_x += step_x;
|
||
|
side = 0;
|
||
|
} else {
|
||
|
border_dist_y += delta_dist_y;
|
||
|
map_y += step_y;
|
||
|
side = 1;
|
||
|
}
|
||
|
|
||
|
if ((slot > 0 || part > 0) && (map_x-1 == ROOM_SIZE / 2) && map_y-1 == ROOM_SIZE / 2) {
|
||
|
hit_kc = 1;
|
||
|
|
||
|
if (side == 0) {
|
||
|
perp_dist = (map_x - pos->x + (1.0 - step_x) / 2.0) / raydir_x;
|
||
|
} else {
|
||
|
perp_dist = (map_y - pos->y + (1.0 - step_y) / 2.0) / raydir_y;
|
||
|
}
|
||
|
s16 lheight = (s16)(SCREEN_HEIGHT / perp_dist);
|
||
|
s16 lpos = MAX(0, -lheight / 2 + SCREEN_HEIGHT / 2);
|
||
|
|
||
|
SCALE_KC(MAX(1, perp_dist), MAX(1, perp_dist));
|
||
|
MOVE_KC(col - 32, SCREEN_HEIGHT - lpos - 64 / MAX(1, perp_dist));
|
||
|
SWITCH_KC_GRAPHICS(part, slot);
|
||
|
}
|
||
|
|
||
|
if ((is_wall(map_x, map_y, room) != 0) || (is_door(map_x, map_y, room) != 0)) hit = 1;
|
||
|
}
|
||
|
|
||
|
if (side == 0) {
|
||
|
perp_dist = (map_x - pos->x + (1.0 - step_x) / 2.0) / raydir_x;
|
||
|
} else {
|
||
|
perp_dist = (map_y - pos->y + (1.0 - step_y) / 2.0) / raydir_y;
|
||
|
}
|
||
|
s16 vheight = (SCREEN_HEIGHT / perp_dist);
|
||
|
|
||
|
if(perp_dist <= 0)
|
||
|
vheight = SCREEN_HEIGHT;
|
||
|
|
||
|
s16 vstart = (SCREEN_HEIGHT / 2) - (vheight / 2);
|
||
|
s16 vend = (SCREEN_HEIGHT / 2) + (vheight / 2);
|
||
|
|
||
|
u16 color = (is_door(map_x, map_y, room) > 0) ?
|
||
|
P_BLUE :
|
||
|
((is_wall(map_x, map_y, room) > 0) ?
|
||
|
(check_room_has_element(room, RTRAP) ?
|
||
|
P_VIOLET :
|
||
|
P_WHITE) :
|
||
|
P_TRANSPARENT);
|
||
|
|
||
|
if (side == 1) {
|
||
|
color = color + 1;
|
||
|
}
|
||
|
|
||
|
u8* buff = (u8*) screen_buff;
|
||
|
u32 row;
|
||
|
|
||
|
for (row = 0; row < SCREEN_HEIGHT; row++) {
|
||
|
if (row < vstart) {
|
||
|
buff[row * SCREEN_WIDTH + col] = P_DARK_DARK_WHITE;
|
||
|
} else if (row <= vend) {
|
||
|
buff[row * SCREEN_WIDTH + col] = color;
|
||
|
} else {
|
||
|
buff[row * SCREEN_WIDTH + col] = check_room_has_element(room, REXIT) ? (slot_left == 0 ? P_DARK_GREEN : P_DARK_RED) : P_DARK_DARK_WHITE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void draw_view_sub(const position_t* const pos, const room_t room, const s16 left)
|
||
|
{
|
||
|
u32 col = 0;
|
||
|
hit_kc = 0;
|
||
|
|
||
|
for (col = 0; col < SCREEN_WIDTH; col++) {
|
||
|
|
||
|
draw_vertical_line(col, pos, room, left);
|
||
|
|
||
|
}
|
||
|
|
||
|
swiCopy(screen_buff, BG_BMP_RAM_SUB(1), SCREEN_WIDTH * SCREEN_HEIGHT);
|
||
|
|
||
|
if (hit_kc == 0) {
|
||
|
MOVE_KC(SCREEN_WIDTH, SCREEN_HEIGHT);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void draw_game_sub(const position_t* const pos, const room_t room, const s16 left)
|
||
|
{
|
||
|
draw_view_sub(pos, room, left);
|
||
|
}
|
||
|
|
||
|
|
||
|
static u16 elem_to_tile(room_elements elem){
|
||
|
switch(elem){
|
||
|
case NWALL:
|
||
|
case SWALL:
|
||
|
case WWALL:
|
||
|
case EWALL:
|
||
|
return 92;
|
||
|
break;
|
||
|
case RSLOT:
|
||
|
return 93;
|
||
|
break;
|
||
|
case RPART:
|
||
|
return 94;
|
||
|
break;
|
||
|
case RTRAP:
|
||
|
return 95;
|
||
|
break;
|
||
|
case REXIT:
|
||
|
return 96;
|
||
|
break;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
#define NET_ROOM_SIZE 16
|
||
|
#define NET_DOOR_SIZE (NET_ROOM_SIZE/4)
|
||
|
|
||
|
#define RMLO (16-NET_ROOM_SIZE/2)
|
||
|
#define RMTO 3
|
||
|
#define RMDO (16-NET_DOOR_SIZE/2)
|
||
|
|
||
|
void draw_game_multi_sub(const room_t room, const u32 slot_left){
|
||
|
memset(BG_BMP_RAM_SUB(1), 0, SCREEN_WIDTH * SCREEN_HEIGHT);
|
||
|
u16 i;
|
||
|
for(i = 0; i < NET_ROOM_SIZE; ++i){
|
||
|
DRAW_TILE_AT_IDX(RMTO,RMLO+i) = elem_to_tile(WWALL);
|
||
|
DRAW_TILE_AT_IDX(RMTO+1,RMLO+i) = elem_to_tile(WWALL);
|
||
|
DRAW_TILE_AT_IDX(RMTO+i,RMLO) = elem_to_tile(WWALL);
|
||
|
DRAW_TILE_AT_IDX(RMTO+i,RMLO+1) = elem_to_tile(WWALL);
|
||
|
DRAW_TILE_AT_IDX(RMTO+i,RMLO+NET_ROOM_SIZE-2) = elem_to_tile(WWALL);
|
||
|
DRAW_TILE_AT_IDX(RMTO+i,RMLO+NET_ROOM_SIZE-1) = elem_to_tile(WWALL);
|
||
|
DRAW_TILE_AT_IDX(RMTO+NET_ROOM_SIZE-2,RMLO+i) = elem_to_tile(WWALL);
|
||
|
DRAW_TILE_AT_IDX(RMTO+NET_ROOM_SIZE-1,RMLO+i) = elem_to_tile(WWALL);
|
||
|
|
||
|
}
|
||
|
for (i = 0; i < NET_DOOR_SIZE; ++i) {
|
||
|
if(!check_room_has_element(room, NWALL)){
|
||
|
DRAW_TILE_AT_IDX(RMTO,RMDO+i) = 0;
|
||
|
DRAW_TILE_AT_IDX(RMTO+1,RMDO+i) = 0;
|
||
|
}
|
||
|
if (!check_room_has_element(room, SWALL)) {
|
||
|
DRAW_TILE_AT_IDX(RMTO+NET_ROOM_SIZE-2,RMDO+i) = 0;
|
||
|
DRAW_TILE_AT_IDX(RMTO+NET_ROOM_SIZE-1,RMDO+i) = 0;
|
||
|
}
|
||
|
if (!check_room_has_element(room, WWALL)) {
|
||
|
DRAW_TILE_AT_IDX(RMTO+(NET_ROOM_SIZE/2)-(NET_DOOR_SIZE/2)+i,RMLO) = 0;
|
||
|
DRAW_TILE_AT_IDX(RMTO+(NET_ROOM_SIZE/2)-(NET_DOOR_SIZE/2)+i,RMLO+1) = 0;
|
||
|
}
|
||
|
if (!check_room_has_element(room, EWALL)) {
|
||
|
DRAW_TILE_AT_IDX(RMTO+(NET_ROOM_SIZE/2)-(NET_DOOR_SIZE/2)+i,RMLO+NET_ROOM_SIZE-2) = 0;
|
||
|
DRAW_TILE_AT_IDX(RMTO+(NET_ROOM_SIZE/2)-(NET_DOOR_SIZE/2)+i,RMLO+NET_ROOM_SIZE-1) = 0;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < ELEM_SIZE; ++i) {
|
||
|
if(check_room_has_element(room, RSLOT)){
|
||
|
u16 j;
|
||
|
for(j=0; j< ELEM_SIZE; ++j){
|
||
|
DRAW_TILE_AT_IDX(RMTO+(NET_ROOM_SIZE/2) - ELEM_SIZE/2+i, 16-2 + j)= elem_to_tile(RSLOT);
|
||
|
}
|
||
|
}
|
||
|
if(check_room_has_element(room, RPART)){
|
||
|
u16 j;
|
||
|
for(j=0; j< ELEM_SIZE; ++j){
|
||
|
DRAW_TILE_AT_IDX(RMTO+(NET_ROOM_SIZE/2) - ELEM_SIZE/2+1+i/2, 16-1 + j/2)= elem_to_tile(RPART);
|
||
|
}
|
||
|
}
|
||
|
if(check_room_has_element(room, REXIT)){
|
||
|
u16 spridx = elem_to_tile(REXIT) + ((slot_left == 0)?0:1);
|
||
|
DRAW_TILE_AT_IDX(RMTO+(ELEM_SIZE/2)+i - 2*(i/2), RMLO+(ELEM_SIZE/2) + i/2)= spridx;
|
||
|
DRAW_TILE_AT_IDX(RMTO+(ELEM_SIZE/2)+i - 2*(i/2), RMLO+NET_ROOM_SIZE-(ELEM_SIZE) + i/2)= spridx;
|
||
|
DRAW_TILE_AT_IDX(RMTO+NET_ROOM_SIZE-(ELEM_SIZE)+i - 2*(i/2), RMLO+NET_ROOM_SIZE-(ELEM_SIZE) + i/2)= spridx;
|
||
|
DRAW_TILE_AT_IDX(RMTO+NET_ROOM_SIZE-(ELEM_SIZE)+i - 2*(i/2), RMLO+(ELEM_SIZE/2) + i/2)= spridx;
|
||
|
}
|
||
|
if(check_room_has_element(room, RTRAP)){
|
||
|
DRAW_TILE_AT_IDX(RMTO+i - 2*(i/2), RMLO + i/2)= elem_to_tile(RTRAP) ;
|
||
|
DRAW_TILE_AT_IDX(RMTO+i - 2*(i/2), RMLO+NET_ROOM_SIZE-(ELEM_SIZE/2) + i/2)= elem_to_tile(RTRAP);
|
||
|
DRAW_TILE_AT_IDX(RMTO+NET_ROOM_SIZE-(ELEM_SIZE/2)+i - 2*(i/2), RMLO+NET_ROOM_SIZE-(ELEM_SIZE/2) + i/2)= elem_to_tile(RTRAP);
|
||
|
DRAW_TILE_AT_IDX(RMTO+NET_ROOM_SIZE-(ELEM_SIZE/2)+i - 2*(i/2), RMLO + i/2)= elem_to_tile(RTRAP);
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
void draw_player_multi_sub(const net_player_t* const player, const bool ghost){
|
||
|
TEXT_TILE_MAP_SUB_1[(RMTO+player->y) * 32 + (RMLO+player->x)] = elem_to_tile(REXIT)+1;
|
||
|
TEXT_TILE_MAP_SUB_0[(RMTO+player->y) * 32 + (RMLO+player->x)] = char_to_tile('A');//player->name[0]);
|
||
|
}
|