/* STI console code
 *
 * Copyright (C) 2019 Sven Schnelle <svens@stackframe.org>
 *
 * This file may be distributed under the terms of the GNU LGPLv3 license.
 */

#include "autoconf.h"
#include "types.h"
#include "std/optionrom.h"
#include "vgahw.h"
#include "parisc/sticore.h"
#include "output.h"
#include "pdc.h"

#define PAGE0 ((volatile struct zeropage *) 0UL)

static int sti_enabled;

static struct sti_init_flags sti_init_flags = {
        .wait = 1,
        .reset = 1,
        .text = 1,
        .nontext = 1,
        .cmap_blk = 1,
        .no_chg_bet = 1,
        .no_chg_bei = 1,
        .init_cmap_tx = 1,
};

static struct sti_glob_cfg_ext sti_glob_ext_cfg = {
};

static struct sti_glob_cfg sti_glob_cfg = {
        .region_ptrs = { 0, 0xf9000000, 0xf8100000, 0xf8380000, 0, 0, 0, 0 },
        .ext_ptr = (u32)&sti_glob_ext_cfg,
};

static struct sti_init_inptr_ext sti_init_inptr_ext = {
        .config_mon_type = 1,
};

static struct sti_init_inptr sti_init_inptr = {
        .text_planes = 3,
        .ext_ptr = (u32)&sti_init_inptr_ext,
};

static struct sti_init_outptr sti_init_outptr = {
};

static struct sti_font_flags sti_font_flags = {
        .wait = 1,
};

static struct sti_font_inptr sti_font_inptr = {
        .fg_color = 1,
        .bg_color = 0,
};

static struct sti_font_outptr sti_font_outptr = {
};

static struct sti_blkmv_flags sti_blkmv_flags = {
        .wait = 1,
};

static struct sti_blkmv_inptr sti_blkmv_inptr = {
};

static struct sti_blkmv_outptr sti_blkmv_outptr = {
};

static void sti_putchar(struct sti_rom *rom, int row, int column, const char c)
{
    int (*sti_unpmv)(struct sti_font_flags *,
                     struct sti_font_inptr *,
                     struct sti_font_outptr *,
                     struct sti_glob_cfg *);

    struct sti_rom_font *font = (void *)rom + rom->font_start;
    sti_unpmv = (void *)rom + rom->font_unpmv;

    sti_font_inptr.dest_x = column * font->width;
    sti_font_inptr.dest_y = row * font->height;
    sti_font_inptr.index = c;
    sti_font_inptr.font_start_addr = (u32)rom + rom->font_start;

    sti_unpmv(&sti_font_flags, &sti_font_inptr,
        &sti_font_outptr, &sti_glob_cfg);
}

static void sti_block_move(struct sti_rom *rom, int src_x, int src_y,
                                          int dest_x, int dest_y,
                                          int width, int height,
                                          int clear)
{
    int (*sti_block_move)(struct sti_blkmv_flags *,
                          struct sti_blkmv_inptr *,
                          struct sti_blkmv_outptr *,
                          struct sti_glob_cfg *);
    sti_block_move = (void *)rom + rom->block_move;

    sti_blkmv_inptr.src_x = src_x;
    sti_blkmv_inptr.src_y = src_y;
    sti_blkmv_inptr.dest_x = dest_x;
    sti_blkmv_inptr.dest_y = dest_y;
    sti_blkmv_inptr.width = width;
    sti_blkmv_inptr.height = height;
    sti_blkmv_flags.clear = clear;

    sti_block_move(&sti_blkmv_flags, &sti_blkmv_inptr,
                   &sti_blkmv_outptr, &sti_glob_cfg);
}

void sti_console_init(struct sti_rom *rom)
{
    int (*sti_init)(struct sti_init_flags *,
                    struct sti_init_inptr *,
                    struct sti_init_outptr *,
                    struct sti_glob_cfg *);

    sti_init = (void *)rom + rom->init_graph;

    sti_init(&sti_init_flags, &sti_init_inptr,
             &sti_init_outptr, &sti_glob_cfg);

    sti_enabled = 1;
}

void sti_putc(const char c)
{
    struct sti_rom *rom = (struct sti_rom *)PAGE0->proc_sti;
    struct sti_rom_font *font = (void *)rom + rom->font_start;
    static int row, col;

    if (!sti_enabled)
        return;

    if (c == '\r') {
        col = 0;
        return;
    }

    if (c == 0x08) {
        if (col > 0)
            col--;
        return;
    }

    if (c == '\n') {
        col = 0;
        row++;

        if (row >= sti_glob_cfg.onscreen_y / font->height) {
            sti_block_move(rom,
                    0, font->height,
                    0, 0,
                    sti_glob_cfg.total_x, sti_glob_cfg.onscreen_y - font->height, 0);

            /* clear new line at bottom */
            sti_block_move(rom,
                    0, 0, /* source */
                    0, sti_glob_cfg.onscreen_y - font->height, /* dest */
                    sti_glob_cfg.onscreen_x, font->height,
                    1);

            row = (sti_glob_cfg.onscreen_y / font->height)-1;
        }
        return;
    }

    /* wrap to next line or scroll screen if EOL reached */
    if (col >= ((sti_glob_cfg.onscreen_x / font->width) - 1))
	sti_putc('\n');

    sti_putchar(rom, row, col++, c);
}
