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

#include <oslib/os.h>

#include "ztypes.h"
#include "operand.h"
#include "osdepend.h"
#include "screen.h"
#include "screenio.h"
#include "control.h"
#include "text.h"
#include "quetzal.h"
#include "blorb.h"
#include "blorblow.h"
#include "fileio.h"
#include "v6.h"
#include "v6ro.h"
#include "graphics.h"
#include "pngro.h"
#include "jpegro.h"
#include "variable.h"


int mouse_window;
int game_wants_caret;

unsigned wind_prop[8][18];

FILE * restrict GFile;
gfx_header GHeader;
static gfx_dir * restrict GDir;
static int max_image;
int buffer_screen_mode;

#define type_PNG  0x504E4720
#define type_JPEG 0x4A504547
#define type_Rect 0x52656374
#define type_APal 0x4150616C

/*
 * draw_picture
 *
 * Draw picture argv[0] at (argv[1],argv[2]), or at the cursor
 * pos if co-ords are (0,0) or not supplied
 */
void z_draw_picture(int argc, unsigned *argv)
{
    int x, y;
    gfx_dir *imdir;

    if (!blorb_map && !GFile)
    	fatal_lookup("NoGfx");

    if (argc<3)
    {
        argv[1]=0;
        argv[2]=0;
    }
    y=(short)argv[1];
    x=(short)argv[2];

    if (x==0 || y==0)
    {
        int tx, ty;
        v6ro_get_cursor_position(&ty, &tx);
        if (x==0) x=tx;
        if (y==0) y=ty;
    }

    imdir = v6_image_info(argv[0]);

    if (imdir == NULL)
    {
        char buffer[32];
        sprintf(buffer, "%d", argv[0]);
        warning_lookup_1("NoGfxN", buffer);
    }
    else
        v6ro_plot_picture(argv[0], imdir, y, x);
}

/*
 * picture_data
 *
 * If the picture number is valid, data on it is filled into the
 * table and the branch happens.
 *
 * If the picture number is 0, the number of valid pictures
 * is written into the table, the release number of the picture
 * file is written into the second word.
 *
 * Otherwise, nothing happens.
 */
void z_picture_data(unsigned picture, unsigned table)
{
    gfx_dir *imdir;

    //if (!blorb_map && !GFile)
      //	fatal_lookup("NoGfx");

    if (picture==0)
    {
        set_word(table, GHeader.images);
        set_word(table+2, GHeader.version);
        conditional_jump(GHeader.images != 0);
    }
    else
    {
        //char buf[200];
        imdir=v6_image_info(picture);
        if (imdir==0)
        {
            //sprintf(buf, "Picture %d not available", picture);
            //warning(buf);
            conditional_jump(FALSE);
            return;
        }
        //sprintf(buf, "Picture %d is %dx%d", picture, imdir->image_width, imdir->image_height);
        //warning(buf);
        set_word(table, imdir->image_height);
        set_word(table+2, imdir->image_width);
        conditional_jump(TRUE);
    }
}

/*
 * erase_picture
 */
void z_erase_picture(int argc, unsigned *argv)
{
    int x, y;
    gfx_dir *imdir;

    if (!blorb_map && !GFile)
    	fatal_lookup("NoGfx");

    if (argc<3)
    {
        argv[1]=0;
        argv[2]=0;
    }
    y=(short)argv[1];
    x=(short)argv[2];

    if (x==0 || y==0)
    {
        int tx, ty;
        v6ro_get_cursor_position(&ty, &tx);
        if (x==0) x=tx;
        if (y==0) y=ty;
    }

    imdir = v6_image_info(argv[0]);

    if (imdir == NULL)
    {
        char buffer[32];
        sprintf(buffer, "%d", argv[0]);
        warning_lookup_1("NoGfxN", buffer);
    }
    else
        v6ro_remove_picture(argv[0], imdir, y, x);
}

/*
 * set_margins
 *
 * Set L&R text margins for given window
 */
void z_set_margins(int argc, unsigned *argv)
{
    unsigned l,r;
    int w;
    if (argc<3)
    	w=screen_window;
    else
    	w=(short)argv[2];

    if (argc<2)
    	r=0;
    else
    	r=argv[1];

    if (argc<1)
    	l=0;
    else
    	l=argv[0];

    if (w==-3)
    	w=screen_window;

    if (wind_prop[w][WPROP_X_CURSOR]<l+1)
    {
    	wind_prop[w][WPROP_X_CURSOR]=(zword_t)(l+1);
    	if (w==screen_window)
    	    v6ro_move_cursor(wind_prop[w][WPROP_Y_CURSOR], l+1);
    }
    else if (wind_prop[w][WPROP_X_CURSOR]>wind_prop[w][WPROP_X_WIDTH]-r)
    {
    	wind_prop[w][WPROP_X_CURSOR]=(zword_t)(wind_prop[w][WPROP_X_WIDTH]-r);
    	if (w==screen_window)
    	    v6ro_move_cursor(wind_prop[w][WPROP_Y_CURSOR], wind_prop[w][WPROP_X_WIDTH]-r);
    }
    wind_prop[w][WPROP_L_MARGIN]=(zword_t) l;
    wind_prop[w][WPROP_R_MARGIN]=(zword_t) r;
    if (w==screen_window)
        v6ro_update_margins();
}

/*
 * move_window
 *
 */
void z_move_window(short window, unsigned y, unsigned x)
{
    if (window == -3)
    	window=screen_window;

    wind_prop[window][WPROP_Y]=(zword_t) y;
    wind_prop[window][WPROP_X]=(zword_t) x;

    if (window==screen_window)
    	v6ro_select_window(window);   /* Hack to move cursor etc */
}

/*
 * window_size
 */
void z_window_size(short window, unsigned y, unsigned x)
{
    if (h_type!=V6)
    {
    	warn_bad_use("window_size");
    	return;
    }

    if (window==-3)
    	window=screen_window;

    wind_prop[window][WPROP_Y_HEIGHT]=(zword_t) y;
    wind_prop[window][WPROP_X_WIDTH]=(zword_t) x;

    if (wind_prop[window][WPROP_Y_CURSOR] > y ||
          wind_prop[window][WPROP_X_CURSOR] > x)
    {
        wind_prop[window][WPROP_Y_CURSOR]=1;
        wind_prop[window][WPROP_X_CURSOR]=wind_prop[window][WPROP_L_MARGIN]+1;
    }

    if (window==screen_window)
    	v6ro_select_window(window);   /* Hack to move cursor etc */
}

/*
 * window_style
 */
void z_window_style(int argc, unsigned *argv)
{
    int window;
    unsigned flags, operation;

    if (h_type!=V6)
    {
    	warn_bad_use("window_style");
    	return;
    }

    if (argc<3)
    	argv[2]=0;

    window=(short)argv[0];
    flags=argv[1];
    operation=argv[2];

    if (window==-3)
    	window=screen_window;

    if (window==screen_window)
        flush_buffer();

    switch (operation)
    {
        case 0:
            wind_prop[window][WPROP_ATTRIBUTES] = flags;
            break;

        case 1:
            wind_prop[window][WPROP_ATTRIBUTES] |= flags;
            break;

        case 2:
            wind_prop[window][WPROP_ATTRIBUTES] &=~ flags;
            break;

        case 3:
            wind_prop[window][WPROP_ATTRIBUTES] ^= flags;
            break;
    }

    if (window==screen_window)
    {
        buffering=wind_prop[window][WPROP_ATTRIBUTES] & WATTR_BUFFER ? ON : OFF;
        wrapping=wind_prop[window][WPROP_ATTRIBUTES] & WATTR_WRAPPING ? ON : OFF;
        scripting_disable=wind_prop[window][WPROP_ATTRIBUTES] & WATTR_SCRIPT ? OFF : ON;
    }
}

/*
 * get_wind_prop
 */
void z_get_wind_prop(short window, unsigned property)
{
    if (window == -3)
    	window=screen_window;

    if (window==screen_window && (property==WPROP_X_CURSOR ||
                                  property==WPROP_Y_CURSOR))
        flush_buffer();

    store_operand(wind_prop[window][property]);
}

void v6_update_char_size(void)
{
    unsigned size = v6ro_char_size(wind_prop[screen_window][WPROP_FONT_NUMBER],
                                   wind_prop[screen_window][WPROP_TEXT_STYLE]);

    wind_prop[screen_window][WPROP_FONT_SIZE] = size;
    set_word_priv(H_CHAR_HEIGHT_V6, size);
}

void v6_set_text_style(int style)
{
    if (style == 0)
        wind_prop[screen_window][WPROP_TEXT_STYLE] = 0;
    else
        wind_prop[screen_window][WPROP_TEXT_STYLE] |= style;

    v6_update_char_size();
}

/*
 * scroll_window
 */
void z_scroll_window(unsigned window, short pixels)
{
    v6ro_scroll_pixels(window, pixels);
}

/*
 * push_stack
 *
 * Push a value onto the system stack, or a user stack, branching
 * if successful, not branching if no room.
 */
void z_push_stack(int argc, unsigned *argv)
{
    int value=argv[0];

    if (argc==1)
    {
        /* Push the value onto the stack */
        z_push(value);
        conditional_jump(TRUE);
    }
    else
    {
        int stack, free_slots;

        stack=argv[1];
        free_slots=get_word(stack);

        if (free_slots==0)
        {
            conditional_jump(FALSE);
        }
        else
        {
            set_word(stack+free_slots*2, value);
            set_word(stack, free_slots-1);
            conditional_jump(TRUE);
        }
    }
}

/*
 * pop_stack
 */
void z_pop_stack(int argc, unsigned *argv)
{
    int items=argv[0];

    if (argc==1)
    {
        /* Pop some values off the stack */
        sp+=items;
        return;
    }
    else
    {
        /* Otherwise pop some values of a user stack */

    	int stack, free_slots;

    	stack=argv[1];
        free_slots=get_word(stack);

        set_word(stack, free_slots+items);
    }
}

/*
 * mouse_window
 */

void z_mouse_window(short window)
{
    if (window == -3)
    	window=screen_window;

    mouse_window=window;
}

/*
 * put_wind_prop
 */

void z_put_wind_prop(short window, unsigned property, unsigned value)
{
    if (h_type!=V6)
    	warn_bad_use("put_wind_prop");
    else
    {
        if (window == -3)
            window=screen_window;

        if (window < 0 || window > 7)
            warning_lookup("BadWind");
        else
        {
            if (property != WPROP_INTERRUPT_ROUTINE &&
                property != WPROP_INTERRUPT_COUNT &&
                property != WPROP_LINE_COUNT)
                warning_lookup("BadProp");
            else
    	    	wind_prop[window][property]=(zword_t) value;
    	}
    }
}

/*
 * print_form
 */

void z_print_form(unsigned table)
{
    int len, i;

    while ((len=get_word(table)) != 0)
    {
        table+=2;
        for (i=0; i<len; i++, table++)
            z_print_char(get_byte(table));
        z_new_line();
    }
}

/*
 * make_menu
 */
void z_make_menu(unsigned menu, unsigned table)
{
    char *rlist[32];
    int entries, entry, i;

    if (menu < 3 || menu > 32)
    {
        conditional_jump(FALSE);
        return;
    }

    if (table)
    {
        entries=get_word(table);
        if (entries>32)
        {
            conditional_jump(FALSE);
            return;
        }
        for (i=0; i<entries; i++)
        {
            int len, j;
            entry=get_word(table+2+2*i);
            len=datap[entry];
            if ((rlist[i]=malloc(len+1)) == NULL)
            {
                for (j=0; j<i; j++)
                    free(rlist[j]);
                conditional_jump(FALSE);
                return;
            }
            memset(rlist[i], '?', len);
            rlist[i][len]='\0';
            for (j=0; j<len; j++)
                rlist[i][j] =
                  unicode_to_system(zscii_to_unicode(datap[entry+1+j]), '?');
        }
        v6ro_add_menu(menu, entries, rlist);
        for (i=0; i<entries; i++)
            free(rlist[i]);
    }
    else
        v6ro_remove_menu(menu);

    conditional_jump(TRUE);
}

/*
 * picture_table
 */
void z_picture_table(unsigned table)
{
    int pic;

    v6ro_clear_cache();

    while ((pic=get_word(table)) != 0)
    {
    	v6ro_cache_picture(v6_image_info(pic));
    	table+=2;
    }
}

int buffer_screen_mode;

void z_buffer_screen(short mode)
{
    if (h_type!=V6)
    {
    	warn_bad_use("buffer_screen");
    	return;
    }
    store_operand(buffer_screen_mode);
    if (mode==0 || mode==1)
    {
        buffer_screen_mode=mode;
    }
    else if (mode==-1)
        v6ro_update_window();
}

void v6z_get_cursor(int table)
{
    flush_buffer();
    set_word(table, wind_prop[screen_window][WPROP_Y_CURSOR]);
    set_word(table+2, wind_prop[screen_window][WPROP_X_CURSOR]);
}

extern void place_caret(void);

void v6z_set_cursor(int argc, unsigned *argv)
{
    int window;

    if (argv[0] == (zword_t) -1)
    {
        game_wants_caret=0;
        place_caret();
        return;
    }
    if (argv[0] == (zword_t) -2)
    {
        game_wants_caret=1;
        place_caret();
        return;
    }

    if (argc<3)
    	window=screen_window;
    else
    {
    	window=(short)argv[2];
    	if (window == -3)
    	    window=screen_window;
    }

    {
        static int warned;
        int bad = 0;

        if (argv[0] < 1)
            bad = 1, argv[0] = 1;
        else if (argv[0] > 1 + wind_prop[window][WPROP_Y_HEIGHT])
            bad = 1, argv[0] = 1 + wind_prop[window][WPROP_Y_HEIGHT];
        if (argv[1] < 1)
            bad = 1, argv[1] = 1;
        else if (argv[1] > 1 + wind_prop[window][WPROP_X_WIDTH])
            bad = 1, argv[1] = 1 + wind_prop[window][WPROP_X_WIDTH];

        if (bad && !warned)
        {
            warned = 1;
            warning_lookup("BadCursor");
        }
    }

    /* Confine within margins */
    if (argv[1] < 1+wind_prop[window][WPROP_L_MARGIN])
        argv[1] = 1+wind_prop[window][WPROP_L_MARGIN];

    if (argv[1] > 1+wind_prop[window][WPROP_X_WIDTH]-wind_prop[window][WPROP_R_MARGIN])
    	argv[1] = 1+wind_prop[window][WPROP_X_WIDTH]-wind_prop[window][WPROP_R_MARGIN];

    if (window==screen_window)
    {
        flush_buffer();
    	v6ro_move_cursor(argv[0], argv[1]);
    }
    else
    {
    	wind_prop[window][WPROP_Y_CURSOR]=(zword_t)argv[0];
    	wind_prop[window][WPROP_X_CURSOR]=(zword_t)argv[1];
    }
}

void v6_output_new_line(void)
{
    int y, x;
    unsigned arglist[2];
    short count=wind_prop[screen_window][WPROP_LINE_COUNT];

    if (output_stream_1==OFF)
    	return;

#ifndef OldInt
    if (wind_prop[screen_window][WPROP_INTERRUPT_COUNT] &&
        --wind_prop[screen_window][WPROP_INTERRUPT_COUNT] == 0)
    {
        int z0_hack;
        /* Don't ask - Spec 1.0 8.8.3.2.2.1 */
        if (h_release == 393 && h_interpreter == 6 &&
                      memcmp(datap + H_SERIAL_NUMBER, "890714", 6) == 0)
            z0_hack = 1;
        else
            z0_hack = 0;

        if (z0_hack) v6ro_scroll_line();
        call_interrupt(wind_prop[screen_window][WPROP_INTERRUPT_ROUTINE]);
        if (!z0_hack) v6ro_scroll_line();
    }
    else
        v6ro_scroll_line();
#else
    v6ro_scroll_line();
#endif


    count++;

    if (count >= (signed)(wind_prop[screen_window][WPROP_Y_HEIGHT]/V6_CHAR_H-1)
        && (wind_prop[screen_window][WPROP_ATTRIBUTES] & WATTR_SCROLL))
    {
        wind_prop[screen_window][WPROP_LINE_COUNT]=0;

        if (replaying==OFF)
        {
            y=wind_prop[screen_window][WPROP_Y_CURSOR];
            x=wind_prop[screen_window][WPROP_X_CURSOR];
            output_string(msgs_lookup_u("More"));
            input_character(0);
            arglist[0]=y; arglist[1]=x;
            v6z_set_cursor(2, arglist);
            z_erase_line(1);
        }
    }
    else
     	wind_prop[screen_window][WPROP_LINE_COUNT]=(zword_t) count;

#ifdef OldInt
    if (wind_prop[screen_window][WPROP_INTERRUPT_COUNT])
        if (--wind_prop[screen_window][WPROP_INTERRUPT_COUNT] == 0)
            call_interrupt(wind_prop[screen_window][WPROP_INTERRUPT_ROUTINE]);
#endif
}

void v6z_erase_window(short w)
{
    if (w == -1 || w == -2)
    {
        if (w == -1)
            z_set_window(0);
        v6ro_clear_screen();
        if (w == -1)
        {
            unsigned args[2] = {1, 1};
            v6z_split_window(0);
            v6z_set_cursor(2, args);
        }

        reset_line_counts();
    }
    else
    {
        unsigned arglist[3];

        if (w == -3)
            w=screen_window;

    	v6ro_clear_window(w);

    	/* Why was this in here?
    	arglist[0]=0;
    	arglist[1]=0;
    	arglist[2]=w;
    	z_set_margins(3, arglist);
    	*/

    	arglist[0]=1;
    	arglist[1]=1+wind_prop[w][WPROP_L_MARGIN];
    	arglist[2]=w;
    	v6z_set_cursor(3, arglist);

    	wind_prop[w][WPROP_LINE_COUNT]=0;
    }
}

void v6z_split_window(int lines)
{
    unsigned arglist[3];
    int x, y;

    flush_buffer();

    x = wind_prop[0][WPROP_X_CURSOR];
    y = wind_prop[0][WPROP_Y_CURSOR] + (wind_prop[0][WPROP_Y] - 1);

    if (lines > h_screen_height) lines = h_screen_height;

    z_move_window(1, 1, wind_prop[1][WPROP_X]);        /* Move window 1 to top */
    z_window_size(1, lines, wind_prop[1][WPROP_X_WIDTH]);  /* Make it appropriate height */
    z_move_window(0, lines+1, wind_prop[0][WPROP_X]);  /* Put window 0 below it */
    z_window_size(0, h_screen_height-lines, wind_prop[0][WPROP_X_WIDTH]);
    /* Keep cursor in same absolute position */
    y = y - (wind_prop[0][WPROP_Y] - 1);
    /* If it falls out of the window, move it to the top left */
    if (y < 1 || y > wind_prop[0][WPROP_Y_HEIGHT])
    {
        y = 1;
        x = wind_prop[0][WPROP_L_MARGIN]+1;
    }
    arglist[0] = y;
    arglist[1] = x;
    arglist[2] = 0;
    v6z_set_cursor(3, arglist);
    /* Select window 0 */
    z_set_window(0);
}

void v6z_set_font(unsigned new_font, short w)
{
    if (w==-3) w=screen_window;
    switch (new_font)
    {
      case 1:
      case 3:
      case 4:
        store_operand(wind_prop[w][WPROP_FONT_NUMBER]);
        if (w==screen_window)
        {
            font=new_font;
            write_char(new_font+EMBED_FONT);
        }
        wind_prop[w][WPROP_FONT_NUMBER] = new_font;
        v6_update_char_size();
        break;

      case 0:
        store_operand(wind_prop[w][WPROP_FONT_NUMBER]);
        break;

      default:
        store_operand(0);
        break;
    }
}

static void v6_prepare_mga_gfx(void)
{
    int i;

    v6ro_open_gfx();

    if (!GFile)
    	return;

    if (fread(&GHeader, sizeof GHeader, 1, GFile) < 1)
    {
    	fatal_lookup("GfxErr");
    	return;
    }

    GDir=calloc(GHeader.images, sizeof *GDir);

    if (GDir==NULL)
    {
        fatal_lookup("NoMem");
        return;
    }

    for (i=0; i<GHeader.images; i++)
    {
    	if (fread(GDir+i, 8, 1, GFile) < 1)
    	{
            fatal_lookup("GfxErr");
            return;
    	}
    	GDir[i].image_width = GDir[i].phys_width * 2;
    	GDir[i].image_height = GDir[i].phys_height * 2;
    	GDir[i].image_data_addr = fget24(GFile);
    	if (GHeader.dir_size == 14)
            GDir[i].image_cm_addr = fget24(GFile);
        if (GDir[i].image_number > max_image)
            max_image=GDir[i].image_number;
        if (GDir[i].image_flags & 1)
            GDir[i].alphatype = 1;
    }
}

static void rescale_gfx(void)
{
    bb_resolution_t *reso;
    float ERF = 1.0F;
    int i;

    if (!blorb_map) return;

    reso = bb_get_resolution(blorb_map);
    if (reso)
    {
        float tmp1, tmp2;
        tmp1 = (float) h_screen_width / reso->px;
        tmp2 = (float) h_screen_height / reso->py;
        ERF = tmp1 < tmp2 ? tmp1 : tmp2;
    }

    for (i = 0; i < GHeader.images; i++)
    {
        bb_aux_pict_t *aux = GDir[i].aux;

        if (aux)
        {
            float min, max, R;
            R = ERF * aux->ratnum / aux->ratden;
            if (aux->minnum)
            {
                min = (float) aux->minnum / aux->minden;
                if (R < min) R = min;
            }
            if (aux->maxnum)
            {
                max = (float) aux->maxnum / aux->maxden;
                if (R > max) R = max;
            }
            GDir[i].image_width = (int)(GDir[i].phys_width * R + 0.5F);
            GDir[i].image_height = (int)(GDir[i].phys_height * R + 0.5F);
        }
        else
        {
            GDir[i].image_width = GDir[i].phys_width;
            GDir[i].image_height = GDir[i].phys_height;
        }
    }
}

static void v6_prepare_blorb_gfx(void)
{
    bb_err_t err;
    bb_result_t res;
    int images, i, r, min_image;

    err = bb_count_resources(blorb_map, bb_ID_Pict, &images,
                             &min_image, &max_image);
    if (err)
        fatal_lookup_1("BlorbErr", bb_err_to_string(err));
    GHeader.version = bb_get_release_num(blorb_map);
    GHeader.images = (unsigned short) images;

    if (images == 0) return;

    GDir=calloc(images, sizeof *GDir);
    if (GDir==NULL)
    {
        fatal_lookup("NoMem");
        return;
    }

    for (i=0, r=min_image; r <= max_image; r++)
    {
        unsigned type;

        err = bb_load_resource_pict(blorb_map, bb_method_FilePos,
                                    &res, r, &GDir[i].aux);
        if (err == bb_err_NotFound) continue;
        else if (err) fatal_lookup_1("BlorbErr", bb_err_to_string(err));

        type = (unsigned) blorb_map->chunks[res.chunknum].type;
        if (type != type_JPEG && type != type_PNG && type != type_Rect)
        {
            static int warned;
            if (!warned)
            {
                char buffer[5];
                buffer[0] = (type >> 24) & 0xFF;
                buffer[1] = (type >> 16) & 0xFF;
                buffer[2] = (type >> 8) & 0xFF;
                buffer[3] = type & 0xFF;
                buffer[4] = 0;
                warning_lookup_1("BadGfxType", buffer);
                warned = TRUE;
            }
            continue;
        }
        GDir[i].jpeg = (type == type_JPEG);
        GDir[i].image_number = r;
        GDir[i].image_data_addr = (type == type_Rect) ? 0 : res.data.startpos;
        GDir[i].image_data_length = res.length;
        if (GDir[i].jpeg)
        {
            if (!get_jpeg_dimensions(r, res.chunknum,
                                     &GDir[i].phys_width, &GDir[i].phys_height))
                continue;
        }
        else if (type == type_Rect)
        {
            fseek(bfp, res.data.startpos, SEEK_SET);
            GDir[i].phys_width = fget32(bfp);
            GDir[i].phys_height = fget32(bfp);
        }
        else
        {
            fseek(bfp, res.data.startpos + 16L, SEEK_SET);
            GDir[i].phys_width = fget32(bfp);
            GDir[i].phys_height = fget32(bfp);
        }
        i++;
    }

    rescale_gfx();

    err = bb_load_chunk_by_type(blorb_map, bb_method_FilePos, &res, type_APal, 0);
    if (err == bb_err_NotFound) return;
    else if (err) fatal_lookup_1("BlorbErr", bb_err_to_string(err));
    else if (res.length != 0)
    {
        long n = res.length / 4;

        have_adaptive = TRUE;
        fseek(bfp, res.data.startpos, SEEK_SET);
        for (i = 0; i < n; i++)
        {
            unsigned image = fget32(bfp);
            int j;
            for (j = 0; j < images; j++)
            {
                if (GDir[j].image_number == image)
                {
                    GDir[j].adaptive = TRUE;
                    break;
                }
            }
        }
    }
}

void v6_signal_refresh(void)
{
    unsigned flags;

    /* Attempt to get them to refresh */
    flags = get_word_priv(H_FLAGS) | REFRESH_FLAG;
    set_word_priv(H_FLAGS, flags);
}

void v6_resize_screen(int new_cols, int new_rows)
{
    if (!v6ro_resize_screen(new_cols, new_rows))
        return;

    h_screen_cols = new_cols;
    h_screen_width = h_screen_cols * V6_CHAR_W;
    h_screen_rows = new_rows;
    h_screen_height = h_screen_rows * V6_CHAR_H;

    rescale_gfx();

    v6_signal_refresh();

    restart_header();
}

void v6_prepare_gfx(void)
{
    if (blorb_map)
        v6_prepare_blorb_gfx();
    else
        v6_prepare_mga_gfx();
}


gfx_dir *v6_image_info(int image)
{
    int i;

    for (i=0; i<GHeader.images; i++)
        if (GDir[i].image_number==image)
            return GDir+i;

    return NULL;
}

unsigned short ntohs(unsigned short s)
{
    return s>>8 | (s & 0xFF)<<8;
}

unsigned long ntohl(unsigned long s)
{
    unsigned long r;

    r=(s>>24);
    r|=(s>>8) & 0xFF00;
    r|=(s<<8) & 0xFF0000;
    r|=(s<<24);

    return r;
}
