/**************************************************************************** * 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); } }