#include "libs/SMSlib.h"
#include "banks/bank2.h"
#include "banks/bank3.h"
#include "banks/bank4.h"

#define FRAME_SPEED 6

// Ken animation
const unsigned char ken_idle_00[] = { 8, 0, 34, 16, 0, 36, 24, 0, 38, 32, 0, 40, 8, 16, 42, 16, 16, 44, 24, 16, 46, 32, 16, 48, 0, 32, 50, 8, 32, 52, 16, 32, 54, 24, 32, 56, 32, 32, 58, 0, 48, 60, 8, 48, 62, 16, 48, 64, 24, 48, 66, 32, 48, 68, 0, 64, 70, 8, 64, 72, 16, 64, 74, 24, 64, 76, 32, 64, 78, METASPRITE_END };
const unsigned char ken_idle_01[] = { 8, 0, 34, 16, 0, 36, 24, 0, 38, 32, 0, 40, 8, 16, 42, 16, 16, 44, 24, 16, 46, 32, 16, 48, 0, 32, 50, 8, 32, 52, 16, 32, 54, 24, 32, 56, 32, 32, 58, 0, 48, 60, 8, 48, 62, 16, 48, 64, 24, 48, 66, 32, 48, 68, 0, 64, 70, 8, 64, 72, 16, 64, 74, 24, 64, 76, 32, 64, 78, METASPRITE_END };
const unsigned char ken_idle_02[] = { 8, 0, 34, 16, 0, 36, 24, 0, 38, 32, 0, 40, 8, 16, 42, 16, 16, 44, 24, 16, 46, 32, 16, 48, 0, 32, 50, 8, 32, 52, 16, 32, 54, 24, 32, 56, 32, 32, 58, 0, 48, 60, 8, 48, 62, 16, 48, 64, 24, 48, 66, 32, 48, 68, 0, 64, 70, 8, 64, 72, 16, 64, 74, 24, 64, 76, 32, 64, 78, METASPRITE_END };
const unsigned char ken_idle_03[] = { 8, 0, 34, 16, 0, 36, 24, 0, 38, 32, 0, 40, 8, 16, 42, 16, 16, 44, 24, 16, 46, 32, 16, 48, 0, 32, 50, 8, 32, 52, 16, 32, 54, 24, 32, 56, 32, 32, 58, 0, 48, 60, 8, 48, 62, 16, 48, 64, 24, 48, 66, 32, 48, 68, 0, 64, 70, 8, 64, 72, 16, 64, 74, 24, 64, 76, 32, 64, 78, METASPRITE_END };
const unsigned char *ken_idle[] = { ken_idle_00, ken_idle_01, ken_idle_02, ken_idle_03 };
const unsigned int ken_frames_00[] = { 0, 1472, 2944, 4416 };
const unsigned int ken_frames_01[] = { 736, 2208, 3680, 5152 };

// Variables
static unsigned int KeysPressed;                    // Controls pressed down
static unsigned int KeysHeld;                       // Controls being held down
static unsigned char X = 0;                         // Player horizontal position
static unsigned char Y = 0;                         // Player vertical position
static unsigned char MoveSpeed = 1;                 // Player move speed in pixels
static unsigned char FrameCounter = 0;              // General use frame counter
static signed char FrameDuration = -1;              // Frame duration countdown
static signed char Frame = 0;                       // Current frame of animation

// Gets input values
void PollInput(void) {
	KeysPressed = SMS_getKeysPressed();
    KeysHeld = SMS_getKeysHeld();
}

// Updates player animation frame
void UpdatePlayerFrame(void) {
    // If not ready to update frame, return
    if (--FrameDuration > -1) {
		return;
	}
    // Reset duration
    FrameDuration = FRAME_SPEED;
	Frame = (Frame + 1 >= 4) ? 0 : Frame + 1;
}

// Updates player meta sprite
void UpdatePlayerSprites(void) {
	SMS_addMetaSprite(X, Y, ken_idle[Frame]);
}

// Updates streamed player tiles
void UpdatePlayerTiles(void) {
    UpdatePlayerFrame();
	SMS_mapROMBank(ken_idle_tiles_bin_bank);
	if (FrameCounter & 1) {
    	UNSAFE_SMS_loadTiles(&ken_idle_tiles_bin[ken_frames_00[Frame]], 290, 736);
	} else {
		UNSAFE_SMS_loadTiles(&ken_idle_tiles_bin[ken_frames_01[Frame]], 313, 736);
	}
    SMS_initSprites();
    UpdatePlayerSprites();
    SMS_copySpritestoSAT();
}

// Moves player
void MovePlayer(void) {
	// Process directional input
	if (KeysHeld & PORT_A_KEY_UP) {
        Y--;
	} else if (KeysHeld & PORT_A_KEY_DOWN) {
        Y++;
	} else if (KeysHeld & PORT_A_KEY_LEFT) {
        X--;
	} else if (KeysHeld & PORT_A_KEY_RIGHT) {
        X++;
	}
}

// Program entry
void main(void) {
    SMS_displayOff();

	// Set sprite mode
	SMS_useFirstHalfTilesforSprites(0);
	SMS_setSpriteMode(SPRITEMODE_TALL);

	// Clear sprites and vram
	SMS_initSprites();
    SMS_VRAMmemset(0x4000, 0x00, 0x4000);
	SMS_VRAMmemset(0xC000, 0x00, 0x0020);
	SMS_copySpritestoSAT();

	// Palettes
	SMS_mapROMBank(ts_test_bg_pal_bin_bank);
    SMS_loadBGPalette(ts_test_bg_pal_bin);
	SMS_mapROMBank(ken_spr_pal_bin_bank);
	SMS_loadSpritePalette(ken_spr_pal_bin);

	// HUD
	SMS_mapROMBank(ts_hud_tiles_bin_bank);
	SMS_loadTiles(ts_hud_tiles_bin, 416, ts_hud_tiles_bin_size);
	SMS_mapROMBank(ts_hud_map_bin_bank);
	SMS_loadTileMap(0, 0, ts_hud_map_bin, ts_hud_map_bin_size);

	// Binary tiles
	SMS_mapROMBank(ts_test_tiles_bin_bank);
	SMS_loadTiles(ts_test_tiles_bin, 0, ts_test_tiles_bin_size);

	// PS Gaiden tiles
	// SMS_mapROMBank(ts_test_psgaiden_tiles_bin_bank);
	// SMS_loadPSGaidencompressedTiles(ts_test_psgaiden_tiles_bin, 0);

	// STC0 tiles
	// SMS_mapROMBank(ts_test_stc0_tiles_bin_bank);
	// SMS_loadSTC0compressedTiles(ts_test_stc0_tiles_bin, 0);

    // STC4 tiles
	// SMS_mapROMBank(ts_test_stc4_tiles_bin_bank);
	// SMS_loadSTC4compressedTiles(ts_test_stc4_tiles_bin, 0);

	// Binary map
	// SMS_mapROMBank(ts_test_map_bin_bank);
	// SMS_loadTileMap(0, 3, ts_test_map_bin, ts_test_map_bin_size);

	// STM map
	SMS_mapROMBank(ts_test_stm_map_bin_bank);
	SMS_loadSTMcompressedTileMap(0, 3, ts_test_stm_map_bin);

    SMS_displayOn();

	// Main game loop
    for (;;) {
		SMS_waitForVBlank();
		FrameCounter++;
		UpdatePlayerTiles();
		PollInput();
		MovePlayer();
	}
}

// SMS ROM Header information
SMS_EMBED_SEGA_ROM_HEADER(6175, 1);
SMS_EMBED_SDSC_HEADER_AUTO_DATE(1, 0, "xfixium", "Crompression", "Test");