mirror of
https://github.com/Lorenzooone/Pokemon-Gen3-to-Gen-X.git
synced 2026-03-21 17:24:39 -05:00
315 lines
9.3 KiB
C
315 lines
9.3 KiB
C
#include <gba.h>
|
|
#include "sprite_handler.h"
|
|
#include "graphics_handler.h"
|
|
#include "print_system.h"
|
|
|
|
#include "sprite_cursor_bin.h"
|
|
#include "item_icon_bin.h"
|
|
#include "sprite_palettes_bin.h"
|
|
#include "item_icon_palette_bin.h"
|
|
|
|
#define CPUFASTSET_FILL (0x1000000)
|
|
|
|
#define ITEM_ICON_INC_Y 24
|
|
#define ITEM_ICON_INC_X 24
|
|
|
|
#define SPRITE_BASE_TILE_SIZE 0x10
|
|
#define SPRITE_ALT_DISTANCE (SPRITE_BASE_TILE_SIZE*TILE_SIZE)
|
|
|
|
#define SPRITE_SIZE (2*SPRITE_ALT_DISTANCE)
|
|
#define OVRAM_START ((u32)OBJ_BASE_ADR)
|
|
#define OVRAM_SIZE 0x8000
|
|
#define OVRAM_END (OVRAM_START+OVRAM_SIZE)
|
|
#define POSSIBLE_SPRITES (OVRAM_SIZE/SPRITE_SIZE)
|
|
|
|
#define OAM_ENTITIES 0x80
|
|
|
|
#define DISABLE_SPRITE (1<<9)
|
|
#define OFF_SCREEN_SPRITE SCREEN_HEIGHT
|
|
|
|
u8 check_for_same_address(const u8*);
|
|
u32 get_vram_pos(void);
|
|
void set_updated_shadow_oam(void);
|
|
void inc_inner_sprite_counter(void);
|
|
u8 get_sprite_counter(void);
|
|
void inc_sprite_counter(void);
|
|
void set_attributes(u16, u16, u16);
|
|
u8 get_first_variable_palette(void);
|
|
u8 get_3bpp_palette(int);
|
|
void set_palette_3bpp(u8*, int, int);
|
|
u16 get_item_icon_tile(void);
|
|
u16 get_mail_icon_tile(void);
|
|
void set_item_icon(u16, u16);
|
|
void set_mail_icon(u16, u16);
|
|
void raw_update_cursor_x(u16);
|
|
|
|
const u16* sprite_cursor_gfx = (const u16*)sprite_cursor_bin;
|
|
const u16* item_icon_gfx = (const u16*)item_icon_bin;
|
|
const u16* sprite_palettes_bin_16 = (const u16*)sprite_palettes_bin;
|
|
const u16* item_icon_palette_bin_16 = (const u16*)item_icon_palette_bin;
|
|
|
|
u8 __sprite_counter;
|
|
u8 __inner_sprite_counter;
|
|
u8 __party_sprite_counter;
|
|
u8 __party_inner_sprite_counter;
|
|
u8 cursor_sprite;
|
|
u8 inner_cursor_sprite;
|
|
u16 cursor_base_x;
|
|
const u8* sprite_pointers[POSSIBLE_SPRITES];
|
|
|
|
u8 updated_shadow_oam;
|
|
u8 loaded_inner_sprite_counter;
|
|
u16 loaded_cursor_base_x;
|
|
OBJATTR shadow_oam[OAM_ENTITIES];
|
|
|
|
void init_sprite_counter(){
|
|
__sprite_counter = 0;
|
|
__inner_sprite_counter = 0;
|
|
loaded_inner_sprite_counter = 0;
|
|
loaded_cursor_base_x = 0;
|
|
}
|
|
|
|
void set_updated_shadow_oam() {
|
|
wait_for_vblank_if_needed();
|
|
updated_shadow_oam = 1;
|
|
}
|
|
|
|
IWRAM_CODE void update_normal_oam() {
|
|
if(updated_shadow_oam) {
|
|
u32* oam_ptr = (u32*)OAM;
|
|
u32* shadow_oam_ptr = (u32*)shadow_oam;
|
|
for(u32 i = 0; i < ((sizeof(OBJATTR)*OAM_ENTITIES)>>2); i++)
|
|
oam_ptr[i] = shadow_oam_ptr[i];
|
|
updated_shadow_oam = 0;
|
|
}
|
|
loaded_inner_sprite_counter = __inner_sprite_counter;
|
|
loaded_cursor_base_x = cursor_base_x;
|
|
}
|
|
|
|
void set_party_sprite_counter(){
|
|
__party_sprite_counter = __sprite_counter;
|
|
__party_inner_sprite_counter = __inner_sprite_counter;
|
|
}
|
|
|
|
void init_sprites(){
|
|
reset_sprites(0);
|
|
update_normal_oam();
|
|
}
|
|
|
|
u8 get_sprite_counter(){
|
|
return __sprite_counter;
|
|
}
|
|
|
|
void inc_sprite_counter(){
|
|
__sprite_counter++;
|
|
__inner_sprite_counter++;
|
|
}
|
|
|
|
void inc_inner_sprite_counter(){
|
|
__inner_sprite_counter++;
|
|
}
|
|
|
|
u8 get_first_variable_palette(){
|
|
return ((sprite_palettes_bin_size + item_icon_palette_bin_size)>>5);
|
|
}
|
|
|
|
u32 get_vram_pos(){
|
|
u32 vram_pos = OVRAM_START+(__sprite_counter*SPRITE_SIZE);
|
|
if(vram_pos >= OVRAM_END)
|
|
vram_pos = OVRAM_END - SPRITE_SIZE;
|
|
return vram_pos;
|
|
}
|
|
|
|
u8 get_3bpp_palette(int index) {
|
|
return (index>>1) + get_first_variable_palette();
|
|
}
|
|
|
|
void set_palette_3bpp(u8* colors, int index, int palette) {
|
|
u8 new_palette = get_3bpp_palette(index);
|
|
const u8 num_colors = 1<<3;
|
|
const u8 base = num_colors*(index & 1);
|
|
|
|
for(int i = 0; i < num_colors; i++) {
|
|
if(i)
|
|
SPRITE_PALETTE[base+i+(new_palette<<4)] = SPRITE_PALETTE[colors[i]+(palette<<4)];
|
|
else
|
|
SPRITE_PALETTE[i+(new_palette<<4)] = SPRITE_PALETTE[colors[i]+(palette<<4)];
|
|
}
|
|
}
|
|
|
|
void init_cursor(){
|
|
sprite_pointers[__sprite_counter] = (const u8*)sprite_cursor_gfx;
|
|
u16* vram_pos = (u16*)get_vram_pos();
|
|
for(u32 i = 0; i < (sprite_cursor_bin_size>>1); i++)
|
|
vram_pos[i] = sprite_cursor_gfx[i];
|
|
vram_pos = (u16*)(get_vram_pos() + SPRITE_ALT_DISTANCE);
|
|
for(u32 i = 0; i < (sprite_cursor_bin_size>>1); i++)
|
|
vram_pos[i] = sprite_cursor_gfx[i];
|
|
for(int i = 0; i < TOTAL_BG; i++) {
|
|
set_attributes(OFF_SCREEN_SPRITE, 0, (32*__sprite_counter) | ((3-i)<<10));
|
|
if(i < TOTAL_BG-1)
|
|
inc_inner_sprite_counter();
|
|
}
|
|
cursor_sprite = __sprite_counter;
|
|
inner_cursor_sprite = __inner_sprite_counter;
|
|
update_cursor_base_x(0);
|
|
inc_sprite_counter();
|
|
}
|
|
|
|
void init_oam_palette(){
|
|
for(u32 i = 0; i < (sprite_palettes_bin_size>>1); i++)
|
|
SPRITE_PALETTE[i] = sprite_palettes_bin_16[i];
|
|
for(u32 i = 0; i < (item_icon_palette_bin_size>>1); i++)
|
|
SPRITE_PALETTE[i+(sprite_palettes_bin_size>>1)] = item_icon_palette_bin_16[i];
|
|
}
|
|
|
|
void init_item_icon(){
|
|
u16* vram_pos = (u16*)(get_vram_pos() + sprite_cursor_bin_size);
|
|
for(u32 i = 0; i < (item_icon_bin_size>>1); i++)
|
|
vram_pos[i] = item_icon_gfx[i];
|
|
vram_pos = (u16*)(get_vram_pos() + SPRITE_ALT_DISTANCE + sprite_cursor_bin_size);
|
|
for(u32 i = 0; i < (item_icon_bin_size>>1); i++)
|
|
vram_pos[i] = item_icon_gfx[i];
|
|
}
|
|
|
|
u16 get_item_icon_tile(){
|
|
return (32*cursor_sprite) + (sprite_cursor_bin_size>>5);
|
|
}
|
|
|
|
u16 get_mail_icon_tile(){
|
|
return get_item_icon_tile() + 1;
|
|
}
|
|
|
|
void set_item_icon(u16 y, u16 x){
|
|
set_attributes(y + ITEM_ICON_INC_Y, x + ITEM_ICON_INC_X, get_item_icon_tile() | (get_curr_priority()<<10) | ((sprite_palettes_bin_size>>5)<<12));
|
|
inc_inner_sprite_counter();
|
|
}
|
|
|
|
void set_mail_icon(u16 y, u16 x){
|
|
set_attributes(y + ITEM_ICON_INC_Y, x + ITEM_ICON_INC_X, get_mail_icon_tile() | (get_curr_priority()<<10) | ((sprite_palettes_bin_size>>5)<<12));
|
|
inc_inner_sprite_counter();
|
|
}
|
|
|
|
u8 check_for_same_address(const u8* address){
|
|
u8 limit = __sprite_counter;
|
|
if(__sprite_counter > POSSIBLE_SPRITES)
|
|
limit = POSSIBLE_SPRITES;
|
|
for(int i = 0; i < limit; i++)
|
|
if(sprite_pointers[i] == address)
|
|
return i;
|
|
return POSSIBLE_SPRITES;
|
|
}
|
|
|
|
void set_pokemon_sprite(const u8* address, u8 palette, u8 info, u8 display_item, u8 display_mail, u16 y, u16 x){
|
|
set_updated_shadow_oam();
|
|
if(display_mail)
|
|
set_mail_icon(y, x);
|
|
else if(display_item)
|
|
set_item_icon(y, x);
|
|
u8 is_3bpp = info&2;
|
|
u8 zero_fill = info&1;
|
|
u8 position = check_for_same_address(address);
|
|
if(position == POSSIBLE_SPRITES) {
|
|
u8 colors[8];
|
|
load_pokemon_sprite_gfx((const u32*)address, (u32*)get_vram_pos(), is_3bpp, zero_fill, __sprite_counter-(cursor_sprite+1), colors);
|
|
if(is_3bpp)
|
|
set_palette_3bpp(colors, __sprite_counter-(cursor_sprite+1), palette);
|
|
position = __sprite_counter;
|
|
__sprite_counter++;
|
|
}
|
|
if(is_3bpp)
|
|
palette = get_3bpp_palette(position-(cursor_sprite+1));
|
|
if(position < POSSIBLE_SPRITES)
|
|
sprite_pointers[position] = address;
|
|
set_attributes(y, x|ATTR1_SIZE_32, (32*position)|(get_curr_priority()<<10)|(palette<<12));
|
|
inc_inner_sprite_counter();
|
|
}
|
|
|
|
void update_cursor_y(u16 cursor_y){
|
|
set_updated_shadow_oam();
|
|
shadow_oam[inner_cursor_sprite-get_curr_priority()].attr0 = cursor_y;
|
|
}
|
|
|
|
void raw_update_cursor_x(u16 cursor_x){
|
|
OAM[inner_cursor_sprite-get_loaded_priority()].attr1 = cursor_x;
|
|
shadow_oam[inner_cursor_sprite-get_loaded_priority()].attr1 = cursor_x;
|
|
}
|
|
|
|
void update_cursor_base_x(u16 cursor_x){
|
|
cursor_base_x = cursor_x;
|
|
}
|
|
|
|
void disable_cursor(){
|
|
update_cursor_y(OFF_SCREEN_SPRITE);
|
|
}
|
|
|
|
void disable_all_cursors(){
|
|
set_updated_shadow_oam();
|
|
for(int i = 0; i < TOTAL_BG; i++)
|
|
shadow_oam[inner_cursor_sprite-i].attr0 = OFF_SCREEN_SPRITE;
|
|
}
|
|
|
|
void set_attributes(u16 obj_attr_0, u16 obj_attr_1, u16 obj_attr_2) {
|
|
set_updated_shadow_oam();
|
|
u8 position = __inner_sprite_counter;
|
|
if(__inner_sprite_counter >= OAM_ENTITIES)
|
|
position = OAM_ENTITIES-1;
|
|
shadow_oam[position].attr0 = obj_attr_0;
|
|
shadow_oam[position].attr1 = obj_attr_1;
|
|
shadow_oam[position].attr2 = obj_attr_2;
|
|
}
|
|
|
|
void reset_sprites_to_cursor(){
|
|
__sprite_counter = cursor_sprite+1;
|
|
__inner_sprite_counter = inner_cursor_sprite+1;
|
|
reset_sprites(__inner_sprite_counter);
|
|
}
|
|
|
|
void reset_sprites(u8 start){
|
|
set_updated_shadow_oam();
|
|
for(int i = start; i < OAM_ENTITIES; i++) {
|
|
shadow_oam[i].attr0 = OFF_SCREEN_SPRITE;
|
|
shadow_oam[i].attr1 = 0;
|
|
shadow_oam[i].attr2 = 0;
|
|
}
|
|
}
|
|
|
|
void disable_all_sprites(){
|
|
set_updated_shadow_oam();
|
|
for(int i = 0; i < OAM_ENTITIES; i++)
|
|
shadow_oam[i].attr0 |= DISABLE_SPRITE;
|
|
}
|
|
|
|
void enable_all_sprites(){
|
|
set_updated_shadow_oam();
|
|
for(int i = 0; i < OAM_ENTITIES; i++)
|
|
shadow_oam[i].attr0 &= ~DISABLE_SPRITE;
|
|
}
|
|
|
|
void reset_sprites_to_party(){
|
|
__sprite_counter = __party_sprite_counter;
|
|
__inner_sprite_counter = __party_inner_sprite_counter;
|
|
reset_sprites(__party_inner_sprite_counter);
|
|
}
|
|
|
|
void move_sprites(u8 counter){
|
|
u8 counter_kind = counter & 8;
|
|
u8 limit = loaded_inner_sprite_counter;
|
|
if(loaded_inner_sprite_counter > OAM_ENTITIES)
|
|
limit = OAM_ENTITIES;
|
|
for(int i = inner_cursor_sprite+1; i < limit; i++) {
|
|
u16 obj_attr_2 = OAM[i].attr2 & ~SPRITE_BASE_TILE_SIZE;
|
|
if(counter_kind)
|
|
obj_attr_2 |= SPRITE_BASE_TILE_SIZE;
|
|
OAM[i].attr2 = obj_attr_2;
|
|
}
|
|
}
|
|
|
|
void move_cursor_x(u8 counter){
|
|
counter = counter & 0x3F;
|
|
u8 pos = counter >> 3;
|
|
if(pos > 4)
|
|
pos = 8-pos;
|
|
raw_update_cursor_x(loaded_cursor_base_x + pos);
|
|
}
|