

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/bios.h>

#include "wwheap.h"


#define _DEBUG
#include "ivram.h"

#define IVDEMOB_FILE      "/rom0/ivdemob.iv"
#define IVDEMOB_ID        10
#define IVDEMOB_BIG       0
#define IVDEMOB_MID       8
#define IVDEMOB_SMA       (ivdemob_width * 4 + 8)
#define IVDEMOB_BACK      (ivdemob_width - 2)
#define IVDEMOB_BOSS      (ivdemob_width * 8)


#define SPRITE_MAX 3000

BYTE* sprite_buf;
BYTE* vvram_buf;
BYTE* charinfo_buf;
BYTE far * chardata_buf;


int ivdemob_width;
int ivdemob_height;
int ivdemob_max;


enum {
    state_first,
    state_exit,
    state_loop
} main_state;

int main_counter;
int keys;


int my_x, my_y;
int boss_x, boss_y;


#define SHOT_MAX 16

BOOL small[SHOT_MAX];
int small_x[SHOT_MAX];
int small_y[SHOT_MAX];
BOOL big[SHOT_MAX];
int big_x[SHOT_MAX];
int big_y[SHOT_MAX];


void add_demo_render(void);


void add_back(void)
{
    int x, y;
    for (x = 0; x < IV_CX; x += 2) {
        for (y = 0; y < IV_CY; y += 2) {
            ivs_add_sprite_rect(IVDEMOB_BACK, x, y, 2, 2, ivdemob_width - 2);
        }
    }
    add_demo_render();
}


void add_me(void)
{
    ivs_add_sprite_rect(IVDEMOB_BIG, my_x, my_y, 8, 8, ivdemob_width - 8);
}


void add_boss(void)
{
    ivs_add_sprite_rect(IVDEMOB_BOSS, boss_x, boss_y, ivdemob_width, 8, 0);
}



void do_first(void)
{
    my_x = 12;
    my_y = 7;
    boss_x = IV_CX + 5;
    boss_y = 4;

    add_back();
    add_me();
    main_state = state_loop;
}


void shot_small(void)
{
    int i;
    for (i = 0; i < SHOT_MAX; i++) {
        if (! small[i]) {
            small_x[i] = my_x + 6;
            small_y[i] = my_y + 3;
            small[i] = TRUE;
            return;
        }
    }
}


void shot_big(void)
{
    int i;
    for (i = 0; i < SHOT_MAX; i++) {
        if (! big[i]) {
            big_x[i] = my_x + 4;
            big_y[i] = my_y + 2;
            big[i] = TRUE;
            return;
        }
    }
}


void move_shot(void)
{
    int i;
    for (i = 0; i < SHOT_MAX; i++) {
        if (small[i]) {
            small_x[i]++;
            if (small_x[i] > IV_CX) {
                small[i] = FALSE;
            } else {
                ivs_add_sprite_rect(IVDEMOB_SMA,
                                    small_x[i], small_y[i],
                                    2, 2, ivdemob_width - 2);
                
            }
        }
        if (big[i]) {
            big_x[i]++;
            if (big_x[i] > IV_CX) {
                big[i] = FALSE;
            } else {
                ivs_add_sprite_rect(IVDEMOB_MID,
                                    big_x[i], big_y[i],
                                    4, 4, ivdemob_width - 4);
                
            }
        }
    }
}



void key_shot(void)
{
    if (keys & KEY_A) {
        if (main_counter & 1) {
            shot_small();
        }
    }
    if (keys & KEY_B) {
        if (! (main_counter & 1)) {
            shot_big();
        }
    }
}


void key_move(void)
{
    if (keys & KEY_LEFT1) {
        if (my_x > -4) {
            my_x--;
        }
    }
    if (keys & KEY_RIGHT1) {
        if (my_x < 24) {
            my_x++;
        }
    }
    if (keys & KEY_UP1) {
        if (my_y > -2) {
            my_y--;
        }
    }
    if (keys & KEY_DOWN1) {
        if (my_y < 12) {
            my_y++;
        }
    }
}

void do_loop(void)
{
    if (keys & KEY_START) {
        main_state = state_exit;
        return;
    }

    boss_x--;
    if (boss_x < 0 - ivdemob_width) {
        boss_x = IV_CX + 3;
    }

    key_move();
    key_shot();
    add_back();
    add_me();
    add_boss();
    move_shot();
}


void main2(void)
{
    char s[200];
    unsigned long start_time, end_time;
    int diff;
    iv_res_image_t far *res;

    /* ファイルをmmap()でマップするとき */
/*
    res = (iv_res_image_t far*)
        iv_get_resource(mmap(IVDEMOB_FILE), IV_RESID_IMAGE, IVDEMOB_ID);
*/
    /* 直接自分自身のリソースを使うとき */
    res = (iv_res_image_t far*)
        iv_get_resource(NULL, IV_RESID_IMAGE, IVDEMOB_ID);

    ivdemob_width = (int)res->width;
    ivdemob_height = (int)res->height;
    ivdemob_max = ivdemob_width * ivdemob_height;

    sprite_buf = (BYTE*)malloc(SPRITE_MAX * IV_SPRITE_UNITSIZE);
    vvram_buf = (BYTE*)malloc(IV_VVRAM_MINSIZE);
    charinfo_buf = (BYTE*)malloc(ivdemob_max * IV_CHARINFO_UNITSIZE);
    chardata_buf = iv_res_pchardata(res);

    ivs_sprite_init(sprite_buf, SPRITE_MAX, vvram_buf, 0);
    ivs_make_chartable(charinfo_buf, res);
    ivs_set_chartable(0, ivdemob_max, charinfo_buf, chardata_buf);

    start_time = sys_get_tick_count();
    for (main_counter = 0; main_counter < 1000; main_counter++) {
        if (main_state == state_exit) {
            break;
        }

        ivs_start_render(0);
        keys = key_press_check();

        switch (main_state) {
        case state_first:
            do_first();
            break;
        case state_loop:
            do_loop();
            break;
        default:
            main_state = state_exit;
        }

        ivs_end_render();
        sys_wait(1);
    }
    end_time = sys_get_tick_count();

    text_screen_init();
    diff = (int)(end_time - start_time);
    sprintf(s, "count:%d/%d=%d(%dFPS)",
            diff, main_counter, diff / main_counter,
            75 / (diff / main_counter));
    text_put_string(0, 0, s);
    key_wait();
}



void main(void)
{
    iv_init(IV_PALETTE_AWGB);
    main2();
    bios_exit();
}

