/*
 * QEMU TCX Frame buffer
 * 
 * Copyright (c) 2003-2005 Fabrice Bellard
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#include "vl.h"

#define MAXX 1024
#define MAXY 768
#define TCX_DAC_NREGS 16

typedef struct TCXState {
    uint32_t addr;
    DisplayState *ds;
    uint8_t *vram;
    unsigned long vram_offset;
    uint16_t width, height;
    uint8_t r[256], g[256], b[256];
    uint8_t dac_index, dac_state;
} TCXState;

static void tcx_draw_line32(TCXState *s1, uint8_t *d, 
			    const uint8_t *s, int width)
{
    int x;
    uint8_t val;

    for(x = 0; x < width; x++) {
	val = *s++;
	*d++ = s1->b[val];
	*d++ = s1->g[val];
	*d++ = s1->r[val];
	d++;
    }
}

static void tcx_draw_line24(TCXState *s1, uint8_t *d, 
			    const uint8_t *s, int width)
{
    int x;
    uint8_t val;

    for(x = 0; x < width; x++) {
	val = *s++;
	*d++ = s1->b[val];
	*d++ = s1->g[val];
	*d++ = s1->r[val];
    }
}

static void tcx_draw_line8(TCXState *s1, uint8_t *d, 
			   const uint8_t *s, int width)
{
    int x;
    uint8_t val;

    for(x = 0; x < width; x++) {
	val = *s++;
	/* XXX translate between palettes? */
	*d++ = val;
    }
}

/* Fixed line length 1024 allows us to do nice tricks not possible on
   VGA... */
void tcx_update_display(void *opaque)
{
    TCXState *ts = opaque;
    uint32_t page;
    int y, page_min, page_max, y_start, dd, ds;
    uint8_t *d, *s;
    void (*f)(TCXState *s1, uint8_t *d, const uint8_t *s, int width);

    if (ts->ds->depth == 0)
	return;
    page = ts->vram_offset;
    y_start = -1;
    page_min = 0x7fffffff;
    page_max = -1;
    d = ts->ds->data;
    s = ts->vram;
    dd = ts->ds->linesize;
    ds = 1024;

    switch (ts->ds->depth) {
    case 32:
	f = tcx_draw_line32;
	break;
    case 24:
	f = tcx_draw_line24;
	break;
    default:
    case 8:
	f = tcx_draw_line8;
	break;
    case 0:
	return;
    }
    
    for(y = 0; y < ts->height; y += 4, page += TARGET_PAGE_SIZE) {
	if (cpu_physical_memory_get_dirty(page, VGA_DIRTY_FLAG)) {
	    if (y_start < 0)
                y_start = y;
            if (page < page_min)
                page_min = page;
            if (page > page_max)
                page_max = page;
	    f(ts, d, s, ts->width);
	    d += dd;
	    s += ds;
	    f(ts, d, s, ts->width);
	    d += dd;
	    s += ds;
	    f(ts, d, s, ts->width);
	    d += dd;
	    s += ds;
	    f(ts, d, s, ts->width);
	    d += dd;
	    s += ds;
	} else {
            if (y_start >= 0) {
                /* flush to display */
                dpy_update(ts->ds, 0, y_start, 
                           ts->width, y - y_start);
                y_start = -1;
            }
	    d += dd * 4;
	    s += ds * 4;
	}
    }
    if (y_start >= 0) {
	/* flush to display */
	dpy_update(ts->ds, 0, y_start, 
		   ts->width, y - y_start);
    }
    /* reset modified pages */
    if (page_max != -1) {
        cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
                                        VGA_DIRTY_FLAG);
    }
}

void tcx_invalidate_display(void *opaque)
{
    TCXState *s = opaque;
    int i;

    for (i = 0; i < MAXX*MAXY; i += TARGET_PAGE_SIZE) {
	cpu_physical_memory_set_dirty(s->vram_offset + i);
    }
}

static void tcx_save(QEMUFile *f, void *opaque)
{
    TCXState *s = opaque;
    
    qemu_put_be32s(f, (uint32_t *)&s->addr);
    qemu_put_be32s(f, (uint32_t *)&s->vram);
    qemu_put_be16s(f, (uint16_t *)&s->height);
    qemu_put_be16s(f, (uint16_t *)&s->width);
    qemu_put_buffer(f, s->r, 256);
    qemu_put_buffer(f, s->g, 256);
    qemu_put_buffer(f, s->b, 256);
    qemu_put_8s(f, &s->dac_index);
    qemu_put_8s(f, &s->dac_state);
}

static int tcx_load(QEMUFile *f, void *opaque, int version_id)
{
    TCXState *s = opaque;
    
    if (version_id != 1)
        return -EINVAL;

    qemu_get_be32s(f, (uint32_t *)&s->addr);
    qemu_get_be32s(f, (uint32_t *)&s->vram);
    qemu_get_be16s(f, (uint16_t *)&s->height);
    qemu_get_be16s(f, (uint16_t *)&s->width);
    qemu_get_buffer(f, s->r, 256);
    qemu_get_buffer(f, s->g, 256);
    qemu_get_buffer(f, s->b, 256);
    qemu_get_8s(f, &s->dac_index);
    qemu_get_8s(f, &s->dac_state);
    return 0;
}

static void tcx_reset(void *opaque)
{
    TCXState *s = opaque;

    /* Initialize palette */
    memset(s->r, 0, 256);
    memset(s->g, 0, 256);
    memset(s->b, 0, 256);
    s->r[255] = s->g[255] = s->b[255] = 255;
    memset(s->vram, 0, MAXX*MAXY);
    cpu_physical_memory_reset_dirty(s->vram_offset, s->vram_offset + MAXX*MAXY,
                                    VGA_DIRTY_FLAG);
    s->dac_index = 0;
    s->dac_state = 0;
}

static uint32_t tcx_dac_readl(void *opaque, target_phys_addr_t addr)
{
    return 0;
}

static void tcx_dac_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
{
    TCXState *s = opaque;
    uint32_t saddr;

    saddr = (addr & (TCX_DAC_NREGS - 1)) >> 2;
    switch (saddr) {
    case 0:
	s->dac_index = val >> 24;
	s->dac_state = 0;
	break;
    case 1:
	switch (s->dac_state) {
	case 0:
	    s->r[s->dac_index] = val >> 24;
	    s->dac_state++;
	    break;
	case 1:
	    s->g[s->dac_index] = val >> 24;
	    s->dac_state++;
	    break;
	case 2:
	    s->b[s->dac_index] = val >> 24;
	default:
	    s->dac_state = 0;
	    break;
	}
	break;
    default:
	break;
    }
    return;
}

static CPUReadMemoryFunc *tcx_dac_read[3] = {
    tcx_dac_readl,
    tcx_dac_readl,
    tcx_dac_readl,
};

static CPUWriteMemoryFunc *tcx_dac_write[3] = {
    tcx_dac_writel,
    tcx_dac_writel,
    tcx_dac_writel,
};

void *tcx_init(DisplayState *ds, uint32_t addr, uint8_t *vram_base,
	       unsigned long vram_offset, int vram_size, int width, int height)
{
    TCXState *s;
    int io_memory;

    s = qemu_mallocz(sizeof(TCXState));
    if (!s)
        return NULL;
    s->ds = ds;
    s->addr = addr;
    s->vram = vram_base;
    s->vram_offset = vram_offset;
    s->width = width;
    s->height = height;

    cpu_register_physical_memory(addr + 0x800000, vram_size, vram_offset);
    io_memory = cpu_register_io_memory(0, tcx_dac_read, tcx_dac_write, s);
    cpu_register_physical_memory(addr + 0x200000, TCX_DAC_NREGS, io_memory);

    register_savevm("tcx", addr, 1, tcx_save, tcx_load, s);
    qemu_register_reset(tcx_reset, s);
    tcx_reset(s);
    dpy_resize(s->ds, width, height);
    return s;
}

void tcx_screen_dump(void *opaque, const char *filename)
{
    TCXState *s = opaque;
    FILE *f;
    uint8_t *d, *d1, v;
    int y, x;

    f = fopen(filename, "wb");
    if (!f)
        return;
    fprintf(f, "P6\n%d %d\n%d\n", s->width, s->height, 255);
    d1 = s->vram;
    for(y = 0; y < s->height; y++) {
        d = d1;
        for(x = 0; x < s->width; x++) {
            v = *d;
            fputc(s->r[v], f);
            fputc(s->g[v], f);
            fputc(s->b[v], f);
            d++;
        }
        d1 += MAXX;
    }
    fclose(f);
    return;
}



