/****************************************************************************
* Copyright (C) 2015-2016 by the SotS Team *
* *
* This file is part of Sovereign of the Skies. *
* *
* Sovereign of the Skies is free software: you can redistribute it *
* and/or modify it *
* under the terms of the GNU Lesser General Public License as published *
* by the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version provided you include a copy of the *
* licence and this header. *
* *
* Sovereign of the Skies is distributed in the hope that it will be *
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with Sovereign of the Skies. *
* If not, see . *
****************************************************************************/
/**
* @file cutscene_meteor.c
* @author Sturmvogel
* @date 15 dec 2016
* @brief Cutscene to play "crashing meteor"
*
* This source is able to play a cutscene, a meteor crashing on earth.
*/
/* === INCLUDES === */
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
/* === MACROS & DEFINES === */
#define CLOUD_THROTTLE 4
#define PALETTE_BG 0
#define PALETTE_SKY 1
#define PALETTE_CLOUD 2
#define PALETTE_FG 3
#define TAG_METEOR 0x2000
/* === STRUCTURES === */
struct meteor_memory{
void* bg_gfx;
void* bg_map;
void* sky_gfx;
void* sky_map;
void* cloud_gfx;
void* cloud_map;
void* fg_gfx;
void* fg_map;
u8 animate_clouds;
u8 cloud_animation_state;
u8 meteor_moving;
u16 delay;
u16 delay_end;
};
/* === STATIC STRUCTURES === */
static struct bg_config met_bg_config[4] = {
{0, 0, 0x19, 0, 0, 0},
{1, 1, 0x1A, 0, 0, 1},
{2, 2, 0x1B, 0, 0, 2},
{3, 3, 0x1C, 0, 0, 3}
};
/* === PROTOTYPES === */
/**
* @brief readies VRAM for our graphic setup
*/
void met_setup_vram();
/**
* @brief callback for doing the actual animation
*/
void met_cutscene_cb();
/**
* @brief callback to update the screen elements
*/
void met_update_screen();
/**
* @brief callback for the meteor object entity
* @param self pointer to the meteor object entity
*/
void met_entity_cb(struct obj_entity* self);
/**
* @brief finish the animation and free memory
*/
void met_free_end();
/**
* @brief disable overworld scrolling in scrolling controller
*/
void met_setup_scrolling();
/**
* @brief setup palettes for cutscene environment
*/
void met_setup_palettes();
/* === STATIC ELEMENTS === */
/*static memory block pointer for used structure*/
static struct meteor_memory* memory = (struct meteor_memory*)(0x0203FFC0);
/*oam attributes for the meteor object entity*/
static struct obj_oam_attributes sprite_meteor = {0, 0x8000, 0x800, 0x0};
/*frame list for the meteor object entity*/
static struct obj_frame meteor_frames [4] = {
{0, 10},
{16, 10},
{32, 10},
{0xFFFE, 0}
};
/*pointer to the frame list*/
static struct obj_frame* meteor_frames_a [1] = {
meteor_frames
};
/*template for the meteor object entity*/
static struct obj_template template_meteor = {
TAG_METEOR,
TAG_METEOR,
&sprite_meteor,
meteor_frames_a,
0,
(struct obj_rotscale_frame **) 0x08231CFC,
met_entity_cb
};
void met_entity_cb(struct obj_entity* self)
{
if(memory->meteor_moving > 0)
{
self->x--;
self->y++;
if(self->y > 130)
{
memory->meteor_moving = 0;
m4aSongNumStart(0xAB);
}
}
}
void met_play()
{
memory->animate_clouds = 0;
memory->cloud_animation_state = 0;
memory-> meteor_moving = 0;
superstate.multi_purpose_state_tracker = 0;
vblank_handler_set(met_update_screen);
set_callback2(met_cutscene_cb);
}
void met_cutscene_cb()
{
if(superstate.multi_purpose_state_tracker == 0)
{
fade_screen(0xFFFFFFFF, 0, 0, 0x10, 0x0000);
superstate.multi_purpose_state_tracker++;
}
else if(superstate.multi_purpose_state_tracker == 1)
{
if((fade_controller.mix_color & 0x8000) == 0)
{
met_setup_vram();
fade_screen(0xFFFFFFFF,0,0x10,0,0x0000);
memory->delay = 60*3;
memory->delay_end = 90;
superstate.multi_purpose_state_tracker++;
}
}
else if(superstate.multi_purpose_state_tracker == 2)
{
if((fade_controller.mix_color & 0x8000) == 0)
{
if(memory->delay == 0)
{
//tint screen
fade_screen(0xE, 28,0,0x6, 0x015C);
//play sound
m4aSongNumStart(0x64);
superstate.multi_purpose_state_tracker++;
}
else
memory->delay--;
}
}
else if (superstate.multi_purpose_state_tracker == 3)
{
superstate.multi_purpose_state_tracker++;
}
else if(superstate.multi_purpose_state_tracker == 4)
{
if((fade_controller.mix_color & 0x8000) == 0)
{
memory->meteor_moving = 1;
superstate.multi_purpose_state_tracker++;
}
}
else if(superstate.multi_purpose_state_tracker == 5)
{
if(memory->meteor_moving == 0)
{
superstate.multi_purpose_state_tracker++;
}
}
else if(superstate.multi_purpose_state_tracker == 6)
{
if(memory->delay_end == 0)
met_free_end();
else
memory->delay_end--;
}
memory->cloud_animation_state++;
if(memory->cloud_animation_state >= CLOUD_THROTTLE)
memory->cloud_animation_state=0;
}
void met_free_end()
{
set_callback2(callback_overworld);
free(memory->bg_gfx);
free(memory->bg_map);
free(memory->fg_gfx);
free(memory->fg_map);
free(memory->sky_gfx);
free(memory->sky_map);
free(memory->cloud_gfx);
free(memory->cloud_map);
}
void met_setup_scrolling()
{
lcd_io_set_func(0x14, 0x0);
lcd_io_set_func(0x16, 0x0);
lcd_io_set_func(0x18, 0x0);
lcd_io_set_func(0x1A, 0x0);
lcd_io_set_func(0x1C, 0x0);
lcd_io_set_func(0x1E, 0x0);
}
void met_setup_palettes()
{
wram_decompress((void*)met_skyPal, palette_unfaded_buffer + PALETTE_SKY*16);
wram_decompress((void*)met_cloudsPal, palette_unfaded_buffer + PALETTE_CLOUD*16);
wram_decompress((void*)met_foregroundPal, palette_unfaded_buffer + PALETTE_FG*16);
wram_decompress((void*)met_backgroundPal, palette_unfaded_buffer + PALETTE_BG*16);
}
void met_setup_vram()
{
gpu_tile_bg_drop_all_sets(0);
gpu_tile_bg_drop_all_sets(1);
gpu_tile_bg_drop_all_sets(2);
gpu_tile_bg_drop_all_sets(3);
gpu_bg_vram_setup(0, met_bg_config, 4);
gpu_bg_show(0);
gpu_bg_show(1);
gpu_bg_show(2);
gpu_bg_show(3);
gpu_sync_bg_visibility_and_mode();
met_setup_scrolling();
//copy tilesets
memory->bg_gfx = malloc(0x40);
wram_decompress((void*)met_backgroundTiles, memory->bg_gfx);
gpu_copy_to_vram_by_bgid(0, memory->bg_gfx, 0x40, 0, 1);
memory->fg_gfx = malloc(0x1180);
wram_decompress((void*)met_foregroundTiles, memory->fg_gfx);
gpu_copy_to_vram_by_bgid(1, memory->fg_gfx, 0x1180, 0, 1);
memory->cloud_gfx = malloc(0x5E0);
wram_decompress((void*)met_cloudsTiles, memory->cloud_gfx);
gpu_copy_to_vram_by_bgid(2, memory->cloud_gfx, 0x5E0,0,1);
memory->sky_gfx = malloc(0x7A0);
wram_decompress((void*)met_skyTiles, memory->sky_gfx);
gpu_copy_to_vram_by_bgid(3, memory->sky_gfx,0x7A0,0,1);
//copy tilemaps
memory->bg_map = malloc(0x500);
wram_decompress((void*)met_backgroundMap, memory->bg_map);
gpu_copy_to_vram_by_bgid(0, memory->bg_map,0x500,0,2);
memory->fg_map = malloc(0x500);
wram_decompress((void*)met_foregroundMap, memory->fg_map);
gpu_copy_to_vram_by_bgid(1, memory->fg_map,0x500,0,2);
memory->cloud_map = malloc(0x500);
wram_decompress((void*)met_cloudsMap, memory->cloud_map);
gpu_copy_to_vram_by_bgid(2, memory->cloud_map,0x500,0,2);
memory->sky_map = malloc(0x500);
wram_decompress((void*)met_skyMap, memory->sky_map);
gpu_copy_to_vram_by_bgid(3, memory->sky_map,0x500,0,2);
met_setup_palettes();
//setup oam
obj_delete_all();
struct obj_resource gfx_meteor = {(void*)met_meteorTiles, 0x1C00, TAG_METEOR};
struct obj_resource pal_meteor = {(void*)met_meteorPal, TAG_METEOR};
obj_gpu_pal_alloc_tag_and_apply(&pal_meteor);
obj_gpu_tile_decompress_alloc_tag_and_upload(&gfx_meteor);
u8 meteor_id = obj_template_instanciate_forward_search(&template_meteor, 0, 100, 1);
objects[meteor_id].x = 200;
objects[meteor_id].y = 0;
memory->animate_clouds = 1;
}
void met_update_screen()
{
fade_update();
task_exec();
objc_exec();
obj_sync();
gpu_pal_upload();
obj_gpu_sprites_upload();
if(memory->cloud_animation_state == 0 && memory->animate_clouds != 0)
{
u16 sky_h = lcd_io_get(0x18);
lcd_io_set_func(0x18, sky_h + 1);
}
}