/* c.main

   Search out sprite files and correct their palettes to ensure that
   the lower nibble of the RGB components is the same as the upper nibble
*/

#define INFO_VERSION_FIELD      3
#define MENU_INFO               1
#define MENU_QUIT               2

#include <stdlib.h>
#include <string.h>

#include "h.bbc"
#include "h.dbox"
#include "h.drawftypes"
#include "h.event"
#include "h.menu"
#include "h.msgs"
#include "h.res"
#include "h.template"
#include "h.visdelay"
#include "h.werr"
#include "h.wimp"
#include "h.wimpt"
#include "h.win"

  menu M_main;
wimp_w W_main;

BOOL main_hack_sprite_palette(sprite_header *sprite)
{
        int ncols = bbc_modevar(sprite->mode, bbc_NColour), i, part1, part2, returnflag = FALSE;
        int *palette = (int *)((int)sprite + 11*4);

        /* if there isn't a palette to process, or it isn't a 16 colour palette, quit now */
        if (sprite->image == 11*4 || ncols != 15)
                return FALSE;
        for (i = 0; i < 32; i++)
        {
                part1 = (palette[i] & 0xF0F0F000) >> 4;
                part2 = (palette[i] & 0x0F0F0F00);
                if (part1 != part2)
                {
                        palette[i] = (palette[i] & 0xFF) + part1 + (part1 << 4);
                        if (!returnflag)
                        {
                                returnflag = TRUE;
                                printf("Adjusting palette of '%s'\n",sprite->name);
                        }
                }
        }
        return returnflag;
}

BOOL main_translate_sprite(char *name)
{
        os_filestr filestr;
        sprite_area *sprites;
        sprite_header *sprite;
        int i, fixed = FALSE;

        filestr.action = 17;
        filestr.name = name;
        if (wimpt_complain(os_file(&filestr)))
                return FALSE;
        sprites = (sprite_area *)malloc(filestr.start+4);
        if (!sprites)
        {
                printf("%s\n%s\n",msgs_lookup("OK2"),msgs_lookup("OK0"));
                return FALSE;
        }
        sprites->size = filestr.start+4;
        sprites->sproff = 16;
        if (wimpt_complain(sprite_area_reinit(sprites)) ||
            wimpt_complain(sprite_area_load(sprites,name)))
        {
                free(sprites);
                return FALSE;
        }
        i = sprites->number;
        sprite = (sprite_header *)((int)sprites + sprites->sproff);
        printf("Checking '%s'\n",name);
        while (i)
        {
                if (main_hack_sprite_palette(sprite))
                        fixed = TRUE;
                sprite = (sprite_header *)((int)sprite + sprite->next);
                i--;
        }
        if (fixed && wimpt_complain(sprite_area_save(sprites,name)))
        {
                free(sprites);
                return FALSE;
        }
        free(sprites);
        return TRUE;
}

BOOL main_translate_draw(char *name)
{
        os_filestr filestr;
        sprite_header *sprite;
        char *draw, *current, *draw_end;
        int fixed = FALSE, output_details = FALSE;

        filestr.action = 17;
        filestr.name = name;
        if (wimpt_complain(os_file(&filestr)))
                return FALSE;
        draw = (char *)malloc(filestr.start);
        draw_end = draw + filestr.start;
        current = draw + sizeof(draw_fileheader);
        if (!draw)
        {
                printf("%s\n%s\n",msgs_lookup("OK3"),msgs_lookup("OK0"));
                return FALSE;
        }
        filestr.action = 16;
        filestr.name = name;
        filestr.loadaddr = (int)draw;
        filestr.execaddr = 0;
        if (wimpt_complain(os_file(&filestr)))
        {
                free(draw);
                return FALSE;
        }
        while (current < draw_end)
        {
                draw_objhdr *objhdr = (draw_objhdr *)current;

                if (objhdr->tag == 5)
                {
                        if (!output_details)
                        {
                                printf("Checking '%s'\n",name);
                                output_details = TRUE;
                        }

                        sprite = &((draw_spristr *)objhdr)->sprite;
                        if (main_hack_sprite_palette(sprite))
                                fixed = TRUE;
                }
                current += objhdr->size;
        }
        if (fixed)
        {
                filestr.action = 0;
                filestr.start = (int)draw;
                filestr.end = (int)draw_end;
                if (wimpt_complain(os_file(&filestr)))
                {
                        free(draw);
                        return FALSE;
                }
        }
        free(draw);
        return TRUE;
}

typedef struct
{
        int load_address;
        int execution_address;
        int length;
        int file_attributes;
        int object_type;
        char name[256];
} gbpb_10_str;

BOOL main_translate_dirs(char *name)
{
        char entries[256];
        os_gbpbstr gbpbstr;

        printf("Checking '%s'\n",name);
        gbpbstr.action = 10;
        gbpbstr.file_handle = (int)name;
        gbpbstr.data_addr = entries;
        gbpbstr.seq_point = 0;
        gbpbstr.buf_len = 256;
        gbpbstr.wild_fld = "*";
        do {
                gbpbstr.number = 1;
                if (wimpt_complain(os_gbpb(&gbpbstr)))
                        return FALSE;
                if (gbpbstr.number == 1)
                {
                        gbpb_10_str *gbpb_10 = (gbpb_10_str *)entries;
                        char *new_name = (char *)malloc(strlen(name)+strlen(gbpb_10->name)+2);
                        BOOL result=TRUE;

                        strcpy(new_name,name);
                        strcat(new_name,".");
                        strcat(new_name,gbpb_10->name);

                        if (gbpb_10->object_type == 2)
                        {

                                result = main_translate_dirs(new_name);
                        }
                        else if ((gbpb_10->load_address & 0xFFF00000) == 0xFFF00000)
                        {
                                switch ((gbpb_10->load_address & 0x000FFF00)>>8)
                                {
                                        case 0xFF9: /* Sprite */
                                                result = main_translate_sprite(new_name);
                                                break;
                                        case 0xAFF: /* Draw file */
                                                result = main_translate_draw(new_name);
                                                break;
                                }
                        }

                        free(new_name);
                        if (!result)
                                return FALSE;
                }
        } while (gbpbstr.seq_point != -1);

        return TRUE;
}

void main_open_command(void)
{
        wimp_commandwind windinfo;

        windinfo.tag = wimp_command_TITLE;
        windinfo.title = "HackSprites status";
        wimp_commandwindow(windinfo);
}

void main_close_command(BOOL prompt)
{
        wimp_commandwind windinfo;

        if (prompt)
                windinfo.tag = wimp_command_CLOSE_PROMPT;
        else
                windinfo.tag = wimp_command_CLOSE_NOPROMPT;
        wimp_commandwindow(windinfo);
}

void main_do_info(void)
{
        dbox d = dbox_new("info");

        if (d)
        {
                dbox_setfield(d, INFO_VERSION_FIELD, msgs_lookup("VSN"));
                dbox_show(d);
                dbox_fillin(d);
                dbox_dispose(&d);
        }
}

void main_menuproc(void *handle, char *hit)
{
        switch (hit[0])
        {
                case MENU_INFO:
                        if (hit[1]) main_do_info();
                        break;
                case MENU_QUIT:
                        exit(0);
        }
}

void main_event_handler(wimp_eventstr *e, void *handle)
{
        switch (e->e)
        {
                case wimp_EOPEN:
                        wimp_open_wind(&e->data.o);
                        break;
                case wimp_ECLOSE:
                        win_activedec();
                        break;
                case wimp_ESEND:
                case wimp_ESENDWANTACK:
                        if (e->data.msg.hdr.action == wimp_MDATALOAD)
                        {
                                BOOL prompt_wanted = TRUE;

                                if (e->data.msg.data.dataload.type == 0xFF9 ||
                                    e->data.msg.data.dataload.type == 0xAFF ||
                                    e->data.msg.data.dataload.type == 0x1000 ||
                                    e->data.msg.data.dataload.type == 0x2000)
                                        main_open_command();

                                switch (e->data.msg.data.dataload.type)
                                {
                                        case 0xFF9: /* Sprite */
                                                prompt_wanted = main_translate_sprite(e->data.msg.data.dataload.name);
                                                break;
                                        case 0xAFF: /* Draw file */
                                                prompt_wanted = main_translate_draw(e->data.msg.data.dataload.name);
                                                break;
                                        case 0x1000:
                                        case 0x2000:
                                                prompt_wanted = main_translate_dirs(e->data.msg.data.dataload.name);
                                                break;
                                        default:
                                                werr(FALSE,msgs_lookup("OK1"));
                                                break;
                                }

                                if (e->data.msg.data.dataload.type == 0xFF9 ||
                                    e->data.msg.data.dataload.type == 0xAFF ||
                                    e->data.msg.data.dataload.type == 0x1000 ||
                                    e->data.msg.data.dataload.type == 0x2000)
                                        main_close_command(prompt_wanted);
                        }
                        break;
        }
}

int main_initialise(void)
{
        wimp_wstate res;

        visdelay_begin();
        res_init("HackSpr");
        msgs_init();
        wimpt_init(msgs_lookup("ID"));
        template_init();
        if (wimp_create_wind(template_syshandle("main"),&W_main))
                return FALSE;
        win_register_event_handler(W_main,main_event_handler,0);
        if ((M_main = menu_new(msgs_lookup("ME1"),msgs_lookup("ME2"))) == NULL)
                return FALSE;
        if (!event_attachmenu(W_main,M_main,main_menuproc,0))
                return FALSE;

        visdelay_end();

        win_activeinc();
        wimp_get_wind_state(W_main, &res);
        wimp_open_wind(&res.o);

        return TRUE;
}

int main(void)
{
        if (!main_initialise())
        {
                werr(FALSE, "Failed to initialise!");
                exit(0);
        }

        while(TRUE)
                event_process();
}
