#ifndef __BOTPAK_H
#define __BOTPAK_H

/* asmhead.nas */
struct BOOTINFO { /* 0x0ff0-0x0fff */
	char cyls; /* ブートセクタはどこまでディスクを読んだのか */
	char leds; /* ブート時のキーボードのLEDの状態 */
	char vmode; /* ビデオモード  何ビットカラーか */
	char reserve;
	short scrnx, scrny; /* 画面解像度 */
	char *vram;
};
#define ADR_BOOTINFO	0x00000ff0
#define ADR_DISKIMG		0x00100000
#define ADR_DMABUF		0x00268000
#define MAX_ENTRY		4096

#define CUR_UP 0xa0
#define CUR_DOWN 0xff
#define CUR_LEFT 0xfd
#define CUR_RIGHT 0xfe

/* naskfunc.nas */
void io_hlt(void);
void io_cli(void);
void io_sti(void);
void io_stihlt(void);
int io_in8(int port);
void io_out8(int port, int data);
void io_outb(int data, int port);
int io_load_eflags(void);
void io_store_eflags(int eflags);
void load_gdtr(int limit, int addr);
void load_idtr(int limit, int addr);
int load_cr0(void);
void store_cr0(int cr0);
void load_tr(int tr);
void clts(void);
void fnsave(int *addr);
void frstor(int *addr);
void asm_inthandler07(void);
void asm_inthandler0c(void);
void asm_inthandler0d(void);
void asm_inthandler20(void);
void asm_inthandler21(void);
void asm_inthandler26(void);
void asm_inthandler2c(void);
unsigned int memtest_sub(unsigned int start, unsigned int end);
void farjmp(int eip, int cs);
void farcall(int eip, int cs);
void asm_hrb_api(void);
void start_app(int eip, int cs, int esp, int ds, int *tss_esp0);
void asm_end_app(void);
//void memcpy(void *a, void *b, int c);

/* fifo.c */
struct FIFO32 {
	int *buf;
	int p, q, size, free, flags;
	struct TASK *task;
};
void fifo32_init(struct FIFO32 *fifo, int size, int *buf, struct TASK *task);
int fifo32_put(struct FIFO32 *fifo, int data);
int fifo32_put_io(struct FIFO32 *fifo, int data);
int fifo32_get(struct FIFO32 *fifo);
int fifo32_status(struct FIFO32 *fifo);

/* graphic.c */
void init_palette(void);
void set_palette(int start, int end, unsigned char *rgb);
void boxfill8(unsigned int *vram, int xsize, unsigned int c, int x0, int y0, int x1, int y1);
void init_screen8(int *vram, int x, int y);
void putfont8(int *vram, int xsize, int x, int y, int c, char *font);
void putfont8_sjis(int *vram, int xsize, int x, int y, int c, char *font);
void putfonts8(int *vram, int xsize, int x, int y, int c, unsigned char *s);
void putfonts8_asc(int *vram, int xsize, int x, int y, int c, unsigned char *s);
void init_mouse_cursor8(int *mouse, int bc);
void push_menu(int *vram, int bxsize, int bysize);
void pull_menu(int *vram, int bxsize, int bysize);
void draw_line(int *vram, int xsize, int x0, int y0, int x1, int y1, int col);
unsigned short rgb2pal_16(int r, int g, int b);
unsigned char rgb2pal_8(int r, int g, int b, int x, int y);
void col2rgb(int col, int *r, int *g, int *b);
int get_int(unsigned char c);
void draw_pixel(unsigned int *vram, unsigned int col, int x, int y);
void putblock8_fb(unsigned int *vram, unsigned char *img, int x0, int y0, int sx, int sy);
void boxfill8_fb(unsigned int *vram, unsigned int c, int x0, int y0, int x1, int y1);
#define COL8_000000		0x00000000
#define COL8_FF0000		0x00ff0000
#define COL8_00FF00		0x0000ff00
#define COL8_FFFF00		0x00ffff00
#define COL8_0000FF		0x000000ff
#define COL8_FF00FF		0x00ff00ff
#define COL8_00FFFF		0x0000ffff
#define COL8_FFFFFF		0x00ffffff
#define COL8_C6C6C6		0x00c6c6c6
#define COL8_840000		0x00840000
#define COL8_008400		0x00008400
#define COL8_848400		0x00848400
#define COL8_000084		0x00000084
#define COL8_840084		0x00840084
#define COL8_008484		0x00008484
#define COL8_848484		0x00848484
#define COL8_333333		0x00333333
#define COL8_FF7F27		0x00ff7f27
#define COL8_ffffff		0x00fefefe

/* dsctbl.c */
struct SEGMENT_DESCRIPTOR {
	short limit_low, base_low;
	char base_mid, access_right;
	char limit_high, base_high;
};
struct GATE_DESCRIPTOR {
	short offset_low, selector;
	char dw_count, access_right;
	short offset_high;
};
void init_gdtidt(void);
void set_segmdesc(struct SEGMENT_DESCRIPTOR *sd, unsigned int limit, int base, int ar);
void set_gatedesc(struct GATE_DESCRIPTOR *gd, int offset, int selector, int ar);
#define ADR_IDT			0x0026f800
#define LIMIT_IDT		0x000007ff
#define ADR_GDT			0x00270000
#define LIMIT_GDT		0x0000ffff
#define ADR_BOTPAK		0x00280000
#define LIMIT_BOTPAK	0x0007ffff
#define AR_DATA32_RW	0x4092
#define AR_CODE32_ER	0x409a
#define AR_LDT			0x0082
#define AR_TSS32		0x0089
#define AR_INTGATE32	0x008e

/* int.c */
void init_pic(void);
#define PIC0_ICW1		0x0020
#define PIC0_OCW2		0x0020
#define PIC0_IMR		0x0021
#define PIC0_ICW2		0x0021
#define PIC0_ICW3		0x0021
#define PIC0_ICW4		0x0021
#define PIC1_ICW1		0x00a0
#define PIC1_OCW2		0x00a0
#define PIC1_IMR		0x00a1
#define PIC1_ICW2		0x00a1
#define PIC1_ICW3		0x00a1
#define PIC1_ICW4		0x00a1

/* keyboard.c */
void inthandler21(int *esp);
void wait_KBC_sendready(void);
void init_keyboard(struct FIFO32 *fifo, int data0);
#define PORT_KEYDAT		0x0060
#define PORT_KEYCMD		0x0064

/* mouse.c */
struct MOUSE_DEC {
	unsigned char buf[3], phase;
	int x, y, btn;
};
void inthandler2c(int *esp);
void enable_mouse(struct FIFO32 *fifo, int data0, struct MOUSE_DEC *mdec);
int mouse_decode(struct MOUSE_DEC *mdec, unsigned char dat);

/* memory.c */
#define MEMMAN_FREES		4096	/* これで約32KB */
#define MEMMAN_ADDR			0x003c0000
struct FREEINFO {	/* あき情報 */
	unsigned int addr, size;
};
struct MEMMAN {		/* メモリ管理 */
	int frees, maxfrees, lostsize, losts;
	struct FREEINFO free[MEMMAN_FREES];
};
unsigned int memtest(unsigned int start, unsigned int end);
void memman_init(struct MEMMAN *man);
unsigned int memman_total(struct MEMMAN *man);
unsigned int memman_alloc(struct MEMMAN *man, unsigned int size);
int memman_free(struct MEMMAN *man, unsigned int addr, unsigned int size);
unsigned int memman_alloc_4k(struct MEMMAN *man, unsigned int size);
int memman_free_4k(struct MEMMAN *man, unsigned int addr, unsigned int size);

/* sheet.c */
#define MAX_SHEETS		256
struct SHEET {
	unsigned int *buf; /* XXRRGGBB */
	int bxsize, bysize, vx0, vy0, col_inv, height, flags;
	int flag2;
	int act;
	struct SHTCTL *ctl;
	struct TASK *task;
};
struct SHTCTL {
	unsigned char *vram, *map;
	int xsize, ysize, top;
	struct SHEET *sheets[MAX_SHEETS];
	struct SHEET sheets0[MAX_SHEETS];
};
struct SHTCTL *shtctl_init(struct MEMMAN *memman, unsigned char *vram, int xsize, int ysize);
struct SHEET *sheet_alloc(struct SHTCTL *ctl);
void sheet_setbuf(struct SHEET *sht, unsigned int *buf, int xsize, int ysize, int col_inv);
void sheet_setbuf2(struct SHEET *sht, unsigned int buf_addr, int xsize, int ysize, int col_inv);
void sheet_updown(struct SHEET *sht, int height);
void sheet_refresh(struct SHEET *sht, int bx0, int by0, int bx1, int by1);
void sheet_slide(struct SHEET *sht, int vx0, int vy0);
void sheet_free(struct SHEET *sht);
void sheet_set8(struct SHTCTL *ctl, struct SHEET *sht, unsigned int *buf, char *vram, int vx, int vy, int bx, int by);
void sheet_set16(struct SHTCTL *ctl, struct SHEET *sht, unsigned int *buf, char *vram, int vx, int vy, int bx, int by);
void sheet_set24(struct SHTCTL *ctl, struct SHEET *sht, unsigned int *buf, char *vram, int vx, int vy, int bx, int by);
void sheet_set32(struct SHTCTL *ctl, struct SHEET *sht, unsigned int *buf, char *vram, int vx, int vy, int bx, int by);

/* timer.c */
#define MAX_TIMER		1024
struct TIMER {
	struct TIMER *next;
	unsigned int timeout;
	char flags, flags2;
	struct FIFO32 *fifo;
	int data;
};
struct TIMERCTL {
	unsigned int count, next;
	struct TIMER *t0;
	struct TIMER timers0[MAX_TIMER];
};
extern struct TIMERCTL timerctl;
void init_pit(void);
struct TIMER *timer_alloc(void);
void timer_free(struct TIMER *timer);
void timer_init(struct TIMER *timer, struct FIFO32 *fifo, int data);
void timer_settime(struct TIMER *timer, unsigned int timeout);
void inthandler20(int *esp);
int timer_cancel(struct TIMER *timer);
void timer_cancelall(struct FIFO32 *fifo);

/* mtask.c */
#define MAX_TASKS		1000	/* 最大タスク数 */
#define TASK_GDT0		3		/* TSSをGDTの何番から割り当てるのか */
#define MAX_TASKS_LV	100
#define MAX_TASKLEVELS	10
struct TSS32 {
	int backlink, esp0, ss0, esp1, ss1, esp2, ss2, cr3;
	int eip, eflags, eax, ecx, edx, ebx, esp, ebp, esi, edi;
	int es, cs, ss, ds, fs, gs;
	int ldtr, iomap;
};
struct TASK {
	int sel, flags; /* selはGDTの番号のこと */
	int level, priority;
	struct FIFO32 fifo;
	struct TSS32 tss;
	int fpu[108 / 4];
	struct SEGMENT_DESCRIPTOR ldt[2];
	struct CONSOLE *cons;
	int ds_base, cons_stack;
	struct FILEHANDLE *fhandle;
	int *fat;
	char *cmdline;
	char taskname[16];
	unsigned char langmode, langbyte1;
	int appf;
};
struct TASKLEVEL {
	int running; /* 動作しているタスクの数 */
	int now; /* 現在動作しているタスクがどれだか分かるようにするための変数 */
	struct TASK *tasks[MAX_TASKS_LV];
};
struct TASKCTL {
	int now_lv; /* 現在動作中のレベル */
	struct TASK *task_fpu;
	char lv_change; /* 次回タスクスイッチのときに、レベルも変えたほうがいいかどうか */
	struct TASKLEVEL level[MAX_TASKLEVELS];
	struct TASK tasks0[MAX_TASKS];
};
extern struct TASKCTL *taskctl;
extern struct TIMER *task_timer;
struct TASK *task_now(void);
struct TASK *task_init(struct MEMMAN *memman);
struct TASK *task_alloc(void);
void task_run(struct TASK *task, int level, int priority);
void task_switch(void);
void task_sleep(struct TASK *task);
int *inthandler07(int *esp);

/* window.c */
void make_window8(unsigned int *buf, int xsize, int ysize, char *title, char act);
void putfonts8_asc_sht(struct SHEET *sht, int x, int y, int c, int b, char *s, int l);
void make_textbox8(struct SHEET *sht, int x0, int y0, int sx, int sy, int c);
void make_wtitle8(unsigned int *buf, int xsize, char *title, char act);
void change_wtitle8(struct SHEET *sht, char act);

/* console.c */

struct CONSOLE {
	struct SHEET *sht;
	int cur_x, cur_y, cur_c;
	struct TIMER *timer;
};
struct FILEHANDLE {
	char *buf, mode;
	int size;
	int pos;
	int bpos, bcaddr, baddr;
	int clustno;
	int add;
	int inadd;
	struct FILEINFO *finfo;
};
struct BUTTON {
	int x0, y0, x1, y1;
	char title[256];
};
void console_task(struct SHEET *sheet, int memtotal);
void cons_putchar(struct CONSOLE *cons, int chr, char move);
void cons_newline(struct CONSOLE *cons);
void cons_putstr0(struct CONSOLE *cons, char *s);
void cons_putstr1(struct CONSOLE *cons, char *s, int l);
void cons_runcmd(char *cmdline, struct CONSOLE *cons, int *fat, int memtotal);
void cmd_mem(struct CONSOLE *cons, int memtotal);
void cmd_cls(struct CONSOLE *cons);
void cmd_dir(struct CONSOLE *cons, int *fat);
void cmd_exit(struct CONSOLE *cons, int *fat);
void cmd_start(struct CONSOLE *cons, char *cmdline, int memtotal);
void cmd_ncst(struct CONSOLE *cons, char *cmdline, int memtotal);
void cmd_langmode(struct CONSOLE *cons, char *cmdline);
void cmd_rem(struct CONSOLE *cons, char *cmdline);
void cmd_del(struct CONSOLE *cons, char *cmdline);
void cmd_cd(struct CONSOLE *cons, char *cmdline, int* fat);
int cmd_app(struct CONSOLE *cons, int *fat, char *cmdline, int sysf);
int *hrb_api(int edi, int esi, int ebp, int esp, int ebx, int edx, int ecx, int eax);
int *inthandler0d(int *esp);
int *inthandler0c(int *esp);
void hrb_api_linewin(struct SHEET *sht, int x0, int y0, int x1, int y1, int col);

/* file.c */
struct FILEINFO {
	unsigned char name[8], ext[3], type;
	char reserve[10];
	unsigned short time, date, clustno;
	unsigned int size;
};
void file_readfat(int *fat, unsigned char *img);
void file_loadfile(int clustno, int size, char *buf, int *fat, char *img);
struct FILEINFO *file_search(char *name, struct FILEINFO *finfo, int max);
struct FILEINFO *file_search2(char *name, struct FILEINFO *finfo, int max, int *fat);
char *file_loadfile2(int clustno, int *psize, int *fat);
struct FILEINFO *file_insert(char *name, struct FILEINFO *finfo, int max, int *fat);
int file_savefile(struct FILEHANDLE *fh, int size, int *fat, char *img);
int file_searchfat(int *fat);
void file_move(char *name, struct FILEINFO *finfo);
void file_clearfat(int *fat, int clustno);
void file_inittbl(void);

/* tek.c */
int tek_getsize(unsigned char *p);
int tek_decomp(unsigned char *p, char *q, int size);

/* bootpack.c */
struct TASK *open_constask(struct SHEET *sht, unsigned int memtotal);
struct SHEET *open_console(struct SHTCTL *shtctl, unsigned int memtotal);
void keywin_off(struct SHEET *key_win);
void keywin_on(struct SHEET *key_win);

/* clock.c */
struct CLOCK {
	int year;	// 年
	int mon;	// 月
	int day;	// 日
	int hou;	// 時
	int min;	// 分
	int sec;	// 秒
};
struct CLOCK checktime(void);
void clock_task(struct SHEET *sht_back);

/* menu.c */
struct MENU {
	char label[16];
	char command[37];
};

void menu_task(int memtotal);

/* beep.c */
struct BEEP_REQ {
	int freq;
	int time;
};
void beep_task(void);
void play_beep(int freq);
void pcm_read(void);

/* ime.c */
void ime_fifoputs(unsigned char *s);
void ime_task(void);

/* fdc.c */
struct FDCSV {
	int  rw;
	char cyl, hed;
	char sec, num;
};
void inthandler26(int *esp);

/* stack.c */
struct CHUNK_STACK {
	char string[512][1024];
	int sp;
};
struct CHUNK_STACK *stack_alloc(void);
void stack_free(struct CHUNK_STACK *stack);
void stack_init(struct CHUNK_STACK *stack);
void stack_push(struct CHUNK_STACK *stack, char *chunk);
char *stack_pop(struct CHUNK_STACK *stack);
#endif
