From 7addadeb70727a053f31dfce43c4f9f78af84724 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Fr=C3=B6schle?= Date: Tue, 24 Dec 2013 09:37:29 +0000 Subject: [PATCH] added video files (shamlessly stolen from EmuTOS) --- Makefile | 6 +- bas.lk.in | 6 + include/screen.h | 122 +++++ include/videl.h | 98 ++++ include/video.h | 9 + sys/BaS.c | 24 + sys/sysinit.c | 22 + video/fnt_st_8x16.c | 338 +++++++++++++ video/vdi_fill.c | 1112 +++++++++++++++++++++++++++++++++++++++++++ video/videl.c | 858 +++++++++++++++++++++++++++++++++ video/video.c | 263 ++++++++++ 11 files changed, 2857 insertions(+), 1 deletion(-) create mode 100644 include/screen.h create mode 100644 include/videl.h create mode 100644 include/video.h create mode 100644 video/fnt_st_8x16.c create mode 100644 video/vdi_fill.c create mode 100644 video/videl.c create mode 100644 video/video.c diff --git a/Makefile b/Makefile index cf95730..64394ff 100644 --- a/Makefile +++ b/Makefile @@ -43,7 +43,7 @@ TRGTDIRS= ./firebee ./m5484lite OBJDIRS=$(patsubst %, %/objs,$(TRGTDIRS)) TOOLDIR=util -VPATH=dma exe flash fs if kbd pci spi sys usb net util xhdi +VPATH=dma exe flash fs if kbd pci spi sys usb net util video xhdi # Linker control file. The final $(LDCFILE) is intermediate only (preprocessed version of $(LDCSRC) LDCFILE=bas.lk @@ -101,6 +101,10 @@ CSRCS= \ udp.c \ arp.c \ bootp.c \ + tftp.c \ + \ + videl.c \ + video.c \ \ basflash.c \ basflash_start.c diff --git a/bas.lk.in b/bas.lk.in index 5ac9f68..d261273 100644 --- a/bas.lk.in +++ b/bas.lk.in @@ -58,6 +58,8 @@ SECTIONS OBJDIR/fec.o(.text) OBJDIR/ip.o(.text) OBJDIR/udp.o(text) + OBJDIR/bootp.o(text) + OBJDIR/tftp.o(text) OBJDIR/arp.o(text) OBJDIR/unicode.o(.text) @@ -73,6 +75,10 @@ SECTIONS OBJDIR/MCD_dmaApi.o(.text) OBJDIR/MCD_tasks.o(.text) OBJDIR/MCD_tasksInit.o(.text) + + OBJDIR/video.o + OBJDIR/videl.o + OBJDIR/xhdi_sd.o(.text) OBJDIR/xhdi_interface.o(.text) OBJDIR/xhdi_vec.o(.text) diff --git a/include/screen.h b/include/screen.h new file mode 100644 index 0000000..0b53e56 --- /dev/null +++ b/include/screen.h @@ -0,0 +1,122 @@ +/* + * screen.h - low-level screen routines + * + * Copyright (c) 2001-2013 The EmuTOS development team + * + * Authors: + * LVL Laurent Vogel + * THH Thomas Huth + * + * This file is distributed under the GPL, version 2 or at your + * option any later version. See doc/license.txt for details. + */ + +#ifndef SCREEN_H +#define SCREEN_H + +#define ST_VRAM_SIZE 32000UL +#define TT_VRAM_SIZE 153600UL +#define FALCON_VRAM_SIZE 307200UL + +#define VIDEOBASE_ADDR_HI 0xffff8201L +#define VIDEOBASE_ADDR_MID 0xffff8203L +#define VIDEOBASE_ADDR_LOW 0xffff820dL + +#define SYNCMODE 0xffff820aL + +#define ST_SHIFTER 0xffff8260L +#define TT_SHIFTER 0xffff8262L +#define SPSHIFT 0xffff8266L + +#define TT_SHIFTER_BITMASK 0x970f /* valid bits in TT_SHIFTER */ + +#define ST_PALETTE_REGS 0xffff8240L +#define FALCON_PALETTE_REGS 0xffff9800L + +#define TT_PALETTE_BITMASK 0x0fff /* valid bits in TT_PALETTE_REGS */ + +/* misc routines */ +int16_t check_moderez(int16_t moderez); +void initialise_palette_registers(int16_t rez,int16_t mode); + +/* hardware dependant xbios routines */ + +int16_t esetshift(int16_t mode); +int16_t egetshift(void); +int16_t esetbank(int16_t bank); +int16_t esetcolor(int16_t index,int16_t color); +void esetpalette(int16_t index,int16_t count,int16_t *rgb); +void egetpalette(int16_t index,int16_t count,int16_t *rgb); +int16_t esetgray(int16_t mode); +int16_t esetsmear(int16_t mode); + +/* pallette color definitions */ + +#define RGB_BLACK 0x0000 /* ST(e) palette */ +#define RGB_BLUE 0x000f +#define RGB_GREEN 0x00f0 +#define RGB_CYAN 0x00ff +#define RGB_RED 0x0f00 +#define RGB_MAGENTA 0x0f0f +#define RGB_LTGRAY 0x0555 +#define RGB_GRAY 0x0333 +#define RGB_LTBLUE 0x033f +#define RGB_LTGREEN 0x03f3 +#define RGB_LTCYAN 0x03ff +#define RGB_LTRED 0x0f33 +#define RGB_LTMAGENTA 0x0f3f +#define RGB_YELLOW 0x0ff0 +#define RGB_LTYELLOW 0x0ff3 +#define RGB_WHITE 0x0fff + +#define TTRGB_BLACK 0x0000 /* TT Palette */ +#define TTRGB_BLUE 0x000f +#define TTRGB_GREEN 0x00f0 +#define TTRGB_CYAN 0x00ff +#define TTRGB_RED 0x0f00 +#define TTRGB_MAGENTA 0x0f0f +#define TTRGB_LTGRAY 0x0aaa +#define TTRGB_GRAY 0x0666 +#define TTRGB_LTBLUE 0x099f +#define TTRGB_LTGREEN 0x09f9 +#define TTRGB_LTCYAN 0x09ff +#define TTRGB_LTRED 0x0f99 +#define TTRGB_LTMAGENTA 0x0f9f +#define TTRGB_YELLOW 0x0ff0 +#define TTRGB_LTYELLOW 0x0ff9 +#define TTRGB_WHITE 0x0fff + +/* TT resolutions */ +#define TT_HIGH 6 +#define TT_MEDIUM 4 +#define TT_LOW 7 + +/* ST(e) resolutions */ +#define ST_HIGH 2 +#define ST_MEDIUM 1 +#define ST_LOW 0 + +/* monitor types (from VgetMonitor()) */ +#define MON_MONO 0 /* ST monochrome */ +#define MON_COLOR 1 /* ST colour */ +#define MON_VGA 2 /* VGA */ +#define MON_TV 3 /* TV via RF modulator */ + +/* determine monitor type, ... */ +void screen_init(void); +void set_rez_hacked(void); +int rez_changeable(void); +int16_t get_monitor_type(void); +void screen_get_current_mode_info(uint16_t *planes, uint16_t *hz_rez, uint16_t *vt_rez); + +/* hardware independant xbios routines */ + +int32_t physbase(void); +int32_t logbase(void); +int16_t getrez(void); +void setscreen(int32_t logLoc, int32_t physLoc, int16_t rez, int16_t videlmode); +void setpalette(int32_t palettePtr); +int16_t setcolor(int16_t colorNum, int16_t color); +void vsync(void); + +#endif /* SCREEN_H */ diff --git a/include/videl.h b/include/videl.h new file mode 100644 index 0000000..8c4bf4c --- /dev/null +++ b/include/videl.h @@ -0,0 +1,98 @@ +/* + * screen.h - low-level screen routines + * + * Copyright (c) 2013 The EmuTOS development team + * + * Authors: + * PES Petr Stehlik + * RFB Roger Burrows + * + * This file is distributed under the GPL, version 2 or at your + * option any later version. See doc/license.txt for details. + */ + +#ifndef VIDEL_H +#define VIDEL_H + +#define SPSHIFT 0xffff8266L + +#define FRGB_BLACK 0x00000000 /* Falcon palette */ +#define FRGB_BLUE 0x000000ff +#define FRGB_GREEN 0x00ff0000 +#define FRGB_CYAN 0x00ff00ff +#define FRGB_RED 0xff000000 +#define FRGB_MAGENTA 0xff0000ff +#define FRGB_LTGRAY 0xbbbb00bb +#define FRGB_GRAY 0x88880088 +#define FRGB_LTBLUE 0x000000aa +#define FRGB_LTGREEN 0x00aa0000 +#define FRGB_LTCYAN 0x00aa00aa +#define FRGB_LTRED 0xaa000000 +#define FRGB_LTMAGENTA 0xaa0000aa +#define FRGB_YELLOW 0xffff0000 +#define FRGB_LTYELLOW 0xaaaa0000 +#define FRGB_WHITE 0xffff00ff + +/* bit settings for Falcon videomodes */ +#define VIDEL_VALID 0x01ff /* the only bits allowed in a videomode */ +#define VIDEL_VERTICAL 0x0100 /* if set, use interlace (TV), double line (VGA) */ +#define VIDEL_COMPAT 0x0080 /* ST-compatible if set */ +#define VIDEL_OVERSCAN 0x0040 /* overscan if set (not used with VGA) */ +#define VIDEL_PAL 0x0020 /* PAL if set; otherwise NTSC */ +#define VIDEL_VGA 0x0010 /* VGA if set; otherwise TV */ +#define VIDEL_80COL 0x0008 /* 80-column mode if set; otherwise 40 */ +#define VIDEL_BPPMASK 0x0007 /* mask for bits/pixel encoding */ +#define VIDEL_1BPP 0 /* 2 colours */ +#define VIDEL_2BPP 1 /* 4 colours */ +#define VIDEL_4BPP 2 /* 16 colours */ +#define VIDEL_8BPP 3 /* 256 colours */ +#define VIDEL_TRUECOLOR 4 /* 65536 colours */ + +/* test for VDI support of videomode */ +#define VALID_VDI_BPP(mode) ((mode&VIDEL_BPPMASK)<=VIDEL_8BPP) + +/* selected Falcon videomodes */ +#define FALCON_ST_HIGH (VIDEL_COMPAT|VIDEL_VGA|VIDEL_80COL|VIDEL_1BPP) + +#define FALCON_DEFAULT_BOOT (VIDEL_VERTICAL|VIDEL_80COL|VIDEL_8BPP) /* 640x480x256 colours, TV, NTSC */ + +#define FALCON_REZ 3 /* used as a Falcon indicator */ + +typedef struct { + int16_t vmode; /* video mode (-1 => end marker) */ + int16_t monitor; /* applicable monitors */ + uint16_t hht; /* H hold timer */ + uint16_t hbb; /* H border begin */ + uint16_t hbe; /* H border end */ + uint16_t hdb; /* H display begin */ + uint16_t hde; /* H display end */ + uint16_t hss; /* H SS */ + uint16_t vft; /* V freq timer */ + uint16_t vbb; /* V border begin */ + uint16_t vbe; /* V border end */ + uint16_t vdb; /* V display begin */ + uint16_t vde; /* V display end */ + uint16_t vss; /* V SS */ +} VMODE_ENTRY; + +void initialise_falcon_palette(int16_t mode); +const VMODE_ENTRY *lookup_videl_mode(int16_t mode,int16_t monitor); + +/* Public XBIOS functions */ +int16_t vsetmode(int16_t mode); +int16_t vmontype(void); +int16_t vsetsync(int16_t external); +int32_t vgetsize(int16_t mode); +int16_t vsetrgb(int16_t index,int16_t count,int32_t *rgb); +int16_t vgetrgb(int16_t index,int16_t count,int32_t *rgb); + +/* misc routines */ +int16_t get_videl_mode(void); +int16_t vfixmode(int16_t mode); +int16_t videl_check_moderez(int16_t moderez); +uint32_t videl_vram_size(void); +void videl_get_current_mode_info(uint16_t *planes, uint16_t *hz_rez, uint16_t *vt_rez); + +extern int16_t current_video_mode; + +#endif /* VIDEL_H */ diff --git a/include/video.h b/include/video.h new file mode 100644 index 0000000..055110f --- /dev/null +++ b/include/video.h @@ -0,0 +1,9 @@ +#ifndef _VIDEO_H_ +#define _VIDEO_H_ + +#include +#include +#include +#include "bas_printf.h" + +#endif /* _VIDEO_H_ */ diff --git a/sys/BaS.c b/sys/BaS.c index 833e3f9..2bd3cbf 100644 --- a/sys/BaS.c +++ b/sys/BaS.c @@ -297,6 +297,30 @@ void BaS(void) * (volatile uint32_t *) (0xf0000410 - 0x20) = 0x01070002; xprintf("finished\r\n"); + + enable_coldfire_interrupts(); + screen_init(); + + /* experimental */ + { + int i; + uint32_t *scradr = 0xd00000; + + for (i = 0; i < 100; i++) + { + uint32_t *p = scradr; + + for (p = scradr; p < scradr + 1024 * 150L; p++) + { + *p = 0xffffffff; + } + for (p = scradr; p < scradr + 1024 * 150L; p++) + { + *p = 0x0; + } + } + } + #endif /* MACHINE_FIREBEE */ sd_card_init(); diff --git a/sys/sysinit.c b/sys/sysinit.c index 0835aab..4cdc6ba 100644 --- a/sys/sysinit.c +++ b/sys/sysinit.c @@ -1103,6 +1103,28 @@ void initialize_hardware(void) init_pll(); init_video_ddr(); dvi_on(); + screen_init(); + + /* experimental */ + { + int i; + uint32_t *scradr = 0xd00000; + + for (i = 0; i < 100; i++) + { + uint32_t *p = scradr; + + for (p = scradr; p < scradr + 1024 * 150L; p++) + { + *p = 0xffffffff; + } + for (p = scradr; p < scradr + 1024 * 150L; p++) + { + *p = 0x0; + } + } + } + #endif /* MACHINE_FIREBEE */ init_pci(); diff --git a/video/fnt_st_8x16.c b/video/fnt_st_8x16.c new file mode 100644 index 0000000..8c323cc --- /dev/null +++ b/video/fnt_st_8x16.c @@ -0,0 +1,338 @@ +/* + * fnt-8x16.c - 8x16 font for Atari ST encoding + * + * Copyright (C) 2001-2002 The EmuTOS development team + * + * This file is distributed under the GPL, version 2 or at your + * option any later version. See doc/license.txt for details. + */ + +#include "config.h" +#include "portab.h" +#include "font.h" + +static const UWORD off_table[] = +{ + 0x0000, 0x0008, 0x0010, 0x0018, 0x0020, 0x0028, 0x0030, 0x0038, + 0x0040, 0x0048, 0x0050, 0x0058, 0x0060, 0x0068, 0x0070, 0x0078, + 0x0080, 0x0088, 0x0090, 0x0098, 0x00a0, 0x00a8, 0x00b0, 0x00b8, + 0x00c0, 0x00c8, 0x00d0, 0x00d8, 0x00e0, 0x00e8, 0x00f0, 0x00f8, + 0x0100, 0x0108, 0x0110, 0x0118, 0x0120, 0x0128, 0x0130, 0x0138, + 0x0140, 0x0148, 0x0150, 0x0158, 0x0160, 0x0168, 0x0170, 0x0178, + 0x0180, 0x0188, 0x0190, 0x0198, 0x01a0, 0x01a8, 0x01b0, 0x01b8, + 0x01c0, 0x01c8, 0x01d0, 0x01d8, 0x01e0, 0x01e8, 0x01f0, 0x01f8, + 0x0200, 0x0208, 0x0210, 0x0218, 0x0220, 0x0228, 0x0230, 0x0238, + 0x0240, 0x0248, 0x0250, 0x0258, 0x0260, 0x0268, 0x0270, 0x0278, + 0x0280, 0x0288, 0x0290, 0x0298, 0x02a0, 0x02a8, 0x02b0, 0x02b8, + 0x02c0, 0x02c8, 0x02d0, 0x02d8, 0x02e0, 0x02e8, 0x02f0, 0x02f8, + 0x0300, 0x0308, 0x0310, 0x0318, 0x0320, 0x0328, 0x0330, 0x0338, + 0x0340, 0x0348, 0x0350, 0x0358, 0x0360, 0x0368, 0x0370, 0x0378, + 0x0380, 0x0388, 0x0390, 0x0398, 0x03a0, 0x03a8, 0x03b0, 0x03b8, + 0x03c0, 0x03c8, 0x03d0, 0x03d8, 0x03e0, 0x03e8, 0x03f0, 0x03f8, + 0x0400, 0x0408, 0x0410, 0x0418, 0x0420, 0x0428, 0x0430, 0x0438, + 0x0440, 0x0448, 0x0450, 0x0458, 0x0460, 0x0468, 0x0470, 0x0478, + 0x0480, 0x0488, 0x0490, 0x0498, 0x04a0, 0x04a8, 0x04b0, 0x04b8, + 0x04c0, 0x04c8, 0x04d0, 0x04d8, 0x04e0, 0x04e8, 0x04f0, 0x04f8, + 0x0500, 0x0508, 0x0510, 0x0518, 0x0520, 0x0528, 0x0530, 0x0538, + 0x0540, 0x0548, 0x0550, 0x0558, 0x0560, 0x0568, 0x0570, 0x0578, + 0x0580, 0x0588, 0x0590, 0x0598, 0x05a0, 0x05a8, 0x05b0, 0x05b8, + 0x05c0, 0x05c8, 0x05d0, 0x05d8, 0x05e0, 0x05e8, 0x05f0, 0x05f8, + 0x0600, 0x0608, 0x0610, 0x0618, 0x0620, 0x0628, 0x0630, 0x0638, + 0x0640, 0x0648, 0x0650, 0x0658, 0x0660, 0x0668, 0x0670, 0x0678, + 0x0680, 0x0688, 0x0690, 0x0698, 0x06a0, 0x06a8, 0x06b0, 0x06b8, + 0x06c0, 0x06c8, 0x06d0, 0x06d8, 0x06e0, 0x06e8, 0x06f0, 0x06f8, + 0x0700, 0x0708, 0x0710, 0x0718, 0x0720, 0x0728, 0x0730, 0x0738, + 0x0740, 0x0748, 0x0750, 0x0758, 0x0760, 0x0768, 0x0770, 0x0778, + 0x0780, 0x0788, 0x0790, 0x0798, 0x07a0, 0x07a8, 0x07b0, 0x07b8, + 0x07c0, 0x07c8, 0x07d0, 0x07d8, 0x07e0, 0x07e8, 0x07f0, 0x07f8, + 0x0800, +}; + +static const UWORD dat_table[] = +{ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1104, + 0x0000, 0x0000, 0x1800, 0x3800, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x4000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x003c, + 0x0600, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x6032, 0x3200, 0x0000, 0x0000, 0x00f1, + 0x00f6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0060, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0018, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x05a0, + 0x7c00, 0x7c7c, 0x007c, 0x7c7c, 0x7c7c, 0x0000, 0x0000, 0x0b28, + 0x0000, 0x0000, 0x1800, 0x7c00, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1000, + 0x6000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x000e, 0x18e0, 0x0000, + 0x0000, 0x0618, 0x0060, 0x1c00, 0x1800, 0x6000, 0x1860, 0x6666, + 0x0c00, 0x3e18, 0x0060, 0x1860, 0x0066, 0x6600, 0x0e00, 0x0000, + 0x0606, 0x0606, 0x3232, 0x0000, 0x0000, 0x0060, 0x6000, 0x0000, + 0x3232, 0x0100, 0x0000, 0x307a, 0x7a66, 0x0610, 0x0000, 0x005b, + 0x66f6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0060, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x7c00, 0x001e, 0x0e00, 0x0000, + 0x0000, 0x0000, 0x0018, 0x0000, 0x3838, 0x0000, 0x0000, 0x00fe, + 0x0000, 0x0030, 0x0c7c, 0xfeee, 0x0100, 0x0008, 0x7838, 0x05a0, + 0xba02, 0x3a3a, 0x82b8, 0xb8ba, 0xbaba, 0x0078, 0x0000, 0x0dd8, + 0x0018, 0x6666, 0x3e66, 0x6c18, 0x0660, 0x6600, 0x0000, 0x0006, + 0x3c18, 0x3c7e, 0x0c7e, 0x1c7e, 0x3c3c, 0x0000, 0x0000, 0x003c, + 0x3818, 0x7c3c, 0x787e, 0x7e3e, 0x667e, 0x06cc, 0x60c6, 0x663c, + 0x7c3c, 0xf83e, 0x7e66, 0x66c6, 0x6666, 0x7e1e, 0x6078, 0x1000, + 0x7000, 0x6000, 0x0600, 0x0e00, 0x6018, 0x0cc0, 0x3800, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0018, 0x1830, 0x0000, + 0x3c66, 0x0c3c, 0x6630, 0x3600, 0x3c66, 0x3066, 0x3c30, 0x663c, + 0x1800, 0x7e3c, 0x6630, 0x3c30, 0x6666, 0x6618, 0x1e66, 0x180e, + 0x0c0c, 0x0c0c, 0x7a7a, 0x0000, 0x1800, 0x0020, 0x2000, 0x0000, + 0x7a7a, 0x3d00, 0x007e, 0x184c, 0x4c66, 0x0c7c, 0x7a7c, 0x7c5f, + 0x6666, 0x667c, 0x1e7e, 0x7e38, 0x1e7e, 0x6e3c, 0x3c7e, 0x6c1c, + 0xfe36, 0x7e6e, 0x3e7c, 0xd67e, 0x387e, 0x7e7e, 0x6e1c, 0x0000, + 0x0018, 0xfe00, 0xfe00, 0x0000, 0x103c, 0x383e, 0x1e10, 0x3e7c, + 0x0000, 0x6006, 0x0e18, 0x0000, 0x6c7c, 0x0000, 0x3030, 0x78fe, + 0x0018, 0x3c38, 0x1c38, 0xfec6, 0x013c, 0x000e, 0x4040, 0x05a0, + 0xc606, 0x0606, 0xc6c0, 0xc0c6, 0xc6c6, 0x0040, 0x0000, 0x0628, + 0x0018, 0x6666, 0x7e66, 0x6c18, 0x0c30, 0x6618, 0x0000, 0x0006, + 0x7e18, 0x7e7e, 0x0c7e, 0x3c7e, 0x7e7e, 0x0000, 0x0e00, 0xe07e, + 0x7c3c, 0x7e7e, 0x7c7e, 0x7e7e, 0x667e, 0x06cc, 0x60c6, 0x667e, + 0x7e7e, 0xfc7e, 0x7e66, 0x66c6, 0x6666, 0x7e1e, 0x6078, 0x3800, + 0x3800, 0x6000, 0x0600, 0x1e00, 0x6018, 0x0cc0, 0x3800, 0x0000, + 0x0000, 0x0000, 0x1800, 0x0000, 0x0000, 0x0018, 0x1830, 0x0000, + 0x7e66, 0x1866, 0x6618, 0x1c00, 0x6666, 0x1866, 0x6618, 0x1818, + 0x7e00, 0xf866, 0x6618, 0x6618, 0x6600, 0x0018, 0x3866, 0x3c1e, + 0x1818, 0x1818, 0x4c4c, 0x0000, 0x1800, 0x0020, 0x2018, 0x0000, + 0x4c4c, 0x7e00, 0x00fe, 0x0000, 0x0000, 0x1810, 0xcac6, 0xc655, + 0x0066, 0x767c, 0x1e7e, 0x7e38, 0x1e7e, 0x6e3c, 0x3e7e, 0x6e1c, + 0xfe36, 0x7e6e, 0x3e7e, 0xd67e, 0x387e, 0x3e7e, 0x6e36, 0x0000, + 0x003c, 0x7e00, 0xfe00, 0x0002, 0x107e, 0x6c20, 0x1010, 0x7efe, + 0x0018, 0x700e, 0x1918, 0x1802, 0x447c, 0x0000, 0x7848, 0x1800, + 0x003c, 0x242c, 0x34ba, 0xfed6, 0x0366, 0x180f, 0x7040, 0x05a0, + 0xc606, 0x0606, 0xc6c0, 0xc0c6, 0xc6c6, 0x0070, 0x0000, 0x07d0, + 0x0018, 0x66ff, 0x606c, 0x3818, 0x1c38, 0x3c18, 0x0000, 0x0006, + 0x6638, 0x660c, 0x1c60, 0x7006, 0x6666, 0x1818, 0x1c7e, 0x7066, + 0xe67e, 0x6666, 0x6e60, 0x6060, 0x6618, 0x06d8, 0x60ee, 0x6666, + 0x6666, 0xcc60, 0x1866, 0x66c6, 0x6666, 0x0c18, 0x6018, 0x3800, + 0x1c00, 0x6000, 0x0600, 0x1800, 0x6000, 0x00c0, 0x1800, 0x0000, + 0x0000, 0x0000, 0x1800, 0x0000, 0x0000, 0x0018, 0x1830, 0x0000, + 0x6600, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3c3c, + 0x7e00, 0xd800, 0x0000, 0x0000, 0x003c, 0x663c, 0x3066, 0x6618, + 0x0000, 0x0000, 0x0000, 0x3c3c, 0x0000, 0x0023, 0x2318, 0x0000, + 0x0000, 0x6601, 0x00d8, 0x3c3c, 0x3c00, 0x0010, 0xca82, 0x8251, + 0xe666, 0x760c, 0x060c, 0x0618, 0x0466, 0x660c, 0x0606, 0x3e0c, + 0xfe36, 0x6666, 0x3e06, 0xd666, 0x1806, 0x3666, 0x6632, 0x0066, + 0x6266, 0x6202, 0x601e, 0x007e, 0x7c66, 0xc630, 0x7c7c, 0xe0c6, + 0x7e18, 0x381c, 0x1b18, 0x183e, 0x6c7c, 0x0000, 0x4818, 0x3000, + 0x0066, 0x24e6, 0x6792, 0xfc92, 0x03c3, 0x3c09, 0x4040, 0x0db0, + 0xc606, 0x0606, 0xc6c0, 0xc0c6, 0xc6c6, 0x7c40, 0x0000, 0x2e10, + 0x0018, 0x66ff, 0x600c, 0x3818, 0x1818, 0x3c18, 0x0000, 0x000c, + 0x6638, 0x660c, 0x1c60, 0x6006, 0x6666, 0x1818, 0x387e, 0x3866, + 0xc266, 0x6666, 0x6660, 0x6060, 0x6618, 0x06d8, 0x60ee, 0x7666, + 0x6666, 0xcc60, 0x1866, 0x66c6, 0x3c66, 0x0c18, 0x3018, 0x6c00, + 0x0c3c, 0x7c3c, 0x3e3c, 0x183e, 0x7c38, 0x0ccc, 0x186c, 0x3c3c, + 0x7c3e, 0x7c3e, 0x7e66, 0x66c6, 0x6666, 0x7e18, 0x1830, 0x6218, + 0x6666, 0x3c3c, 0x3c3c, 0x3c3c, 0x3c3c, 0x3c38, 0x3838, 0x7e7e, + 0x6076, 0xd83c, 0x3c3c, 0x6666, 0x667e, 0x667e, 0x3066, 0x6618, + 0x3c38, 0x3c66, 0x3c66, 0x3e7e, 0x1800, 0x0026, 0x2600, 0x0000, + 0x3c3c, 0x663d, 0x7ed8, 0x7e7e, 0x7e00, 0x0010, 0xcaba, 0xba00, + 0x6666, 0x3e0c, 0x060c, 0x6618, 0x0c66, 0x660c, 0x0606, 0x360c, + 0xc636, 0x6636, 0x0606, 0xd666, 0x1806, 0x3666, 0x7618, 0x10f7, + 0xf666, 0x607e, 0x3038, 0x66fc, 0xc642, 0xc618, 0xd6d6, 0xc0c6, + 0x7e18, 0x1c38, 0x1b18, 0x007c, 0x3838, 0x001f, 0x4830, 0x1800, + 0x00c3, 0x2483, 0xc1d6, 0xfcba, 0x0691, 0x3c08, 0x4038, 0x0db0, + 0x8202, 0x3a3a, 0xbab8, 0xb882, 0xbaba, 0x7e78, 0x0000, 0x39e0, + 0x0018, 0x6666, 0x7c18, 0x7018, 0x1818, 0xff7e, 0x007e, 0x000c, + 0x6618, 0x0c18, 0x3c7c, 0x600c, 0x3c7e, 0x1818, 0x7000, 0x1c0c, + 0xda66, 0x7e60, 0x667c, 0x7c6e, 0x7e18, 0x06f0, 0x60fe, 0x7666, + 0x6666, 0xcc70, 0x1866, 0x66c6, 0x3c3c, 0x1818, 0x3018, 0x6c00, + 0x043e, 0x7e7c, 0x7e7e, 0x7e7e, 0x7e38, 0x0cdc, 0x18fe, 0x7e7e, + 0x7e7e, 0x7e7e, 0x7e66, 0x66c6, 0x6666, 0x7e38, 0x1838, 0xf218, + 0x6066, 0x7e3e, 0x3e3e, 0x3e7c, 0x7e7e, 0x7e38, 0x3838, 0x6666, + 0x607f, 0xde7e, 0x7e7e, 0x6666, 0x6666, 0x6666, 0x307e, 0x6618, + 0x3e38, 0x7e66, 0x7e66, 0x0666, 0x1800, 0x002c, 0x2c18, 0x1ab0, + 0x3e7e, 0x6e7e, 0xffde, 0x6666, 0x6600, 0x0010, 0xcaa2, 0xaa00, + 0x6666, 0x3c0c, 0x0e0c, 0x6618, 0x0c66, 0x6600, 0x0606, 0x660c, + 0xc636, 0x763e, 0x0606, 0xf666, 0x1806, 0x3676, 0x3e3c, 0x1099, + 0xdc66, 0x60fc, 0x186c, 0x6690, 0x8242, 0xc63c, 0x9292, 0xc0c6, + 0x007e, 0x0e70, 0x1818, 0x7e40, 0x0000, 0x0010, 0x4860, 0x4800, + 0x0081, 0xe783, 0xc1c6, 0xf838, 0x0691, 0x3c08, 0x0000, 0x1db8, + 0x0000, 0x7c7c, 0x7c7c, 0x7c00, 0x7c7c, 0x0600, 0x0000, 0x3800, + 0x0018, 0x6666, 0x3e18, 0x7018, 0x1818, 0xff7e, 0x007e, 0x0018, + 0x6e18, 0x0c18, 0x3c7e, 0x7c0c, 0x3c3e, 0x1818, 0xe000, 0x0e0c, + 0xd666, 0x7c60, 0x667c, 0x7c6e, 0x7e18, 0x06f0, 0x60d6, 0x7e66, + 0x6666, 0xfc38, 0x1866, 0x66d6, 0x183c, 0x1818, 0x1818, 0xc600, + 0x0006, 0x6660, 0x6666, 0x7e66, 0x6618, 0x0cf8, 0x18fe, 0x6666, + 0x6666, 0x6660, 0x1866, 0x66d6, 0x3c66, 0x0cf0, 0x181e, 0xbe3c, + 0x6066, 0x6606, 0x0606, 0x0660, 0x6666, 0x6618, 0x1818, 0x6666, + 0x7c1b, 0xde66, 0x6666, 0x6666, 0x6666, 0x6660, 0x303c, 0x7c7e, + 0x0618, 0x6666, 0x6676, 0x3e66, 0x1800, 0x0018, 0x1818, 0x36d8, + 0x0666, 0x6e66, 0xdbde, 0x6666, 0x6600, 0x0010, 0xcaa2, 0xb200, + 0x6666, 0x3c0c, 0x1e0c, 0x6618, 0x0c66, 0x6600, 0x060e, 0x660c, + 0xc636, 0x7618, 0x3606, 0xf666, 0x1806, 0x3676, 0x0e66, 0x3899, + 0x887c, 0x60a8, 0x0cc6, 0x6630, 0x827e, 0xc666, 0x9292, 0xfcc6, + 0x7e7e, 0x1c38, 0x1818, 0x7e02, 0x0000, 0x00d0, 0x4878, 0x3000, + 0x00e7, 0x81e6, 0x67d6, 0xfaba, 0x8c9d, 0x3c78, 0x1e1c, 0x399c, + 0x8202, 0xb83a, 0x3a3a, 0xba02, 0xba3a, 0x060e, 0x07f0, 0x0000, + 0x0018, 0x00ff, 0x0630, 0xde00, 0x1818, 0x3c18, 0x0000, 0x0018, + 0x7618, 0x180c, 0x6c06, 0x7e18, 0x6606, 0x0000, 0x707e, 0x1c18, + 0xd67e, 0x6660, 0x6660, 0x6066, 0x6618, 0x06d8, 0x60d6, 0x7e66, + 0x7e66, 0xf81c, 0x1866, 0x66d6, 0x1818, 0x3018, 0x1818, 0xc600, + 0x003e, 0x6660, 0x6666, 0x1866, 0x6618, 0x0cf0, 0x18d6, 0x6666, + 0x6666, 0x6070, 0x1866, 0x66d6, 0x3c66, 0x18f0, 0x181e, 0x9c24, + 0x6066, 0x663e, 0x3e3e, 0x3e60, 0x6666, 0x6618, 0x1818, 0x7e7e, + 0x7c7b, 0xf866, 0x6666, 0x6666, 0x6666, 0x6660, 0xfe18, 0x6618, + 0x3e18, 0x6666, 0x667e, 0x7e66, 0x3000, 0x0030, 0x3218, 0x6c6c, + 0x3e66, 0x766e, 0xdbd8, 0x7e7e, 0x6600, 0x0000, 0x7aa2, 0xba00, + 0x6666, 0x6e0c, 0x360c, 0x6618, 0x0c66, 0x6600, 0x061c, 0x660c, + 0xc636, 0x061c, 0x3606, 0xc666, 0x1806, 0x3606, 0x0666, 0x38ef, + 0x8866, 0x6028, 0x0cc6, 0x6630, 0x8242, 0x6c42, 0x9292, 0xfcc6, + 0x7e18, 0x381c, 0x1818, 0x003e, 0x0000, 0x00d0, 0x0000, 0x0000, + 0x0024, 0xc32c, 0x3492, 0xf292, 0x8c81, 0x3cf8, 0x1012, 0x799e, + 0xc606, 0xc006, 0x0606, 0xc606, 0xc606, 0x7e10, 0x0ff8, 0x0000, + 0x0018, 0x00ff, 0x0636, 0xde00, 0x1818, 0x3c18, 0x0000, 0x0030, + 0x6618, 0x180c, 0x6c06, 0x6618, 0x6606, 0x0000, 0x387e, 0x3818, + 0xdc7e, 0x6660, 0x6660, 0x6066, 0x6618, 0x06d8, 0x60c6, 0x6e66, + 0x7c66, 0xd80e, 0x1866, 0x66fe, 0x3c18, 0x3018, 0x0c18, 0x0000, + 0x007e, 0x6660, 0x667e, 0x1866, 0x6618, 0x0cf8, 0x18d6, 0x6666, + 0x6666, 0x603c, 0x1866, 0x66fe, 0x1866, 0x1838, 0x1838, 0x0066, + 0x6066, 0x7e7e, 0x7e7e, 0x7e60, 0x7e7e, 0x7e18, 0x1818, 0x7e7e, + 0x60ff, 0xf866, 0x6666, 0x6666, 0x6666, 0x6666, 0x307e, 0x6618, + 0x7e18, 0x6666, 0x667e, 0x6666, 0x307e, 0x7e6e, 0x6618, 0xd836, + 0x7e66, 0x767e, 0xdfd8, 0x7e7e, 0x6600, 0x0000, 0x0aba, 0xaa00, + 0x6666, 0x6e0c, 0x360c, 0x6618, 0x0c66, 0x6600, 0x0630, 0x6e0c, + 0xc636, 0x7e0e, 0x3606, 0xc666, 0x1806, 0x3606, 0x063c, 0x6c66, + 0xdc66, 0x6028, 0x18c6, 0x6630, 0x8242, 0x2842, 0x9292, 0xc0c6, + 0x0018, 0x700e, 0x1818, 0x187c, 0x0000, 0x1850, 0x0000, 0x0000, + 0x0024, 0x6638, 0x1cba, 0xf6d6, 0xd8c3, 0x7e70, 0x1c1c, 0x718e, + 0xc606, 0xc006, 0x0606, 0xc606, 0xc606, 0x660c, 0x1fec, 0x0000, + 0x0000, 0x0066, 0x7e66, 0xcc00, 0x1818, 0x6618, 0x1800, 0x1830, + 0x6618, 0x3066, 0x7e06, 0x6630, 0x6606, 0x1818, 0x1c00, 0x7018, + 0xc066, 0x6666, 0x6660, 0x6066, 0x6618, 0x66cc, 0x60c6, 0x6e66, + 0x6066, 0xcc06, 0x1866, 0x3cfe, 0x3c18, 0x6018, 0x0c18, 0x0000, + 0x0066, 0x6660, 0x6660, 0x1866, 0x6618, 0x0cd8, 0x18d6, 0x6666, + 0x6666, 0x600e, 0x1866, 0x3cfe, 0x3c66, 0x3018, 0x1830, 0x0042, + 0x6666, 0x6066, 0x6666, 0x6660, 0x6060, 0x6018, 0x1818, 0x6666, + 0x60d8, 0xd866, 0x6666, 0x6666, 0x6666, 0x667e, 0x3018, 0x6618, + 0x6618, 0x6666, 0x666e, 0x6666, 0x667e, 0x7ed3, 0xce18, 0x6c6c, + 0x6666, 0x6676, 0xd8d8, 0x6666, 0x6600, 0x0000, 0x0a82, 0x8200, + 0x6666, 0x667e, 0x360c, 0x6618, 0x0c66, 0x7e00, 0x3e30, 0x6e7c, + 0xfe7e, 0x7e7e, 0x3606, 0xfee6, 0x1806, 0x3e06, 0x0618, 0x6c00, + 0xf666, 0x6028, 0x30c6, 0x6630, 0xc666, 0xaa66, 0xd6d6, 0xc0c6, + 0x7e18, 0x6006, 0x18d8, 0x1840, 0x0000, 0x3c70, 0x0000, 0x0000, + 0x0024, 0x3c30, 0x0c38, 0xe6c6, 0x5866, 0xff00, 0x1014, 0x718e, + 0xc606, 0xc006, 0x0606, 0xc606, 0xc606, 0x6602, 0x1804, 0x0000, + 0x0000, 0x0066, 0x7c66, 0xcc00, 0x1c38, 0x6600, 0x1800, 0x1860, + 0x6618, 0x3066, 0x7e66, 0x6630, 0x660e, 0x1818, 0x0e00, 0xe000, + 0xe266, 0x6666, 0x6e60, 0x6066, 0x6618, 0x66cc, 0x60c6, 0x6666, + 0x606a, 0xcc06, 0x1866, 0x3cee, 0x6618, 0x6018, 0x0618, 0x0000, + 0x0066, 0x6660, 0x6660, 0x187e, 0x6618, 0x0ccc, 0x18c6, 0x6666, + 0x6666, 0x6006, 0x1866, 0x3cee, 0x3c7e, 0x3018, 0x1830, 0x00c3, + 0x6666, 0x6066, 0x6666, 0x6660, 0x6060, 0x6018, 0x1818, 0x6666, + 0x60d8, 0xd866, 0x6666, 0x6666, 0x7e66, 0x663c, 0x3018, 0x7c18, + 0x6618, 0x6666, 0x6666, 0x7e7e, 0x6660, 0x0606, 0x1a18, 0x36d8, + 0x6666, 0x6666, 0xd8d8, 0x6666, 0x6600, 0x0000, 0x0ac6, 0xc600, + 0x66f6, 0x627e, 0x360c, 0x6618, 0x0466, 0x7e00, 0x3c30, 0x6e7c, + 0x7c7e, 0x7e7e, 0x3606, 0xfee6, 0x1806, 0x3e06, 0x064c, 0xc600, + 0x627c, 0x6028, 0x606c, 0x7f20, 0x7c7e, 0xee7e, 0x7c7c, 0xe0c6, + 0x7e00, 0x0000, 0x18d8, 0x0000, 0x0000, 0x3c20, 0x0000, 0x0000, + 0x003c, 0x1800, 0x007c, 0xeeee, 0x703c, 0x1000, 0x1012, 0x6186, + 0xba02, 0xb83a, 0x023a, 0xba02, 0xba3a, 0x7e1c, 0x1804, 0x0000, + 0x0018, 0x0000, 0x1800, 0xfe00, 0x0c30, 0x0000, 0x1800, 0x1860, + 0x7e7e, 0x7e7e, 0x0c7e, 0x7e30, 0x7e3c, 0x1818, 0x0000, 0x0018, + 0x7e66, 0x7e7e, 0x7c7e, 0x607e, 0x667e, 0x7ec6, 0x7ec6, 0x667e, + 0x607c, 0xc67e, 0x187e, 0x18c6, 0x6618, 0x7e1e, 0x0678, 0x00fe, + 0x007e, 0x7e7e, 0x7e7e, 0x183e, 0x663c, 0x0cce, 0x3cc6, 0x667e, + 0x7e7e, 0x607e, 0x1e7e, 0x18c6, 0x663e, 0x7e18, 0x1830, 0x00ff, + 0x7e7e, 0x7e7e, 0x7e7e, 0x7e7e, 0x7e7e, 0x7e3c, 0x3c3c, 0x6666, + 0x7eff, 0xde7e, 0x7e7e, 0x7e7e, 0x3e7e, 0x7e18, 0x7f18, 0x6c18, + 0x7e3c, 0x7e7e, 0x6666, 0x3e3c, 0x7e60, 0x060c, 0x3218, 0x1ab0, + 0x7e7e, 0x7e7e, 0xfffe, 0x6666, 0x7e00, 0x0000, 0x0a7c, 0x7c00, + 0xf6f6, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x3000, 0x0000, 0x1806, 0x0006, 0x066c, 0xc600, + 0x006c, 0x6000, 0xfe38, 0x5d00, 0x103c, 0x6c3c, 0x1010, 0x7ec6, + 0x007e, 0x7e7e, 0x1898, 0x0000, 0x0000, 0x1800, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x3000, 0x3800, 0x0000, 0x4182, + 0x7c00, 0x7c7c, 0x007c, 0x7c00, 0x7c7c, 0x3c00, 0x1004, 0x0000, + 0x0018, 0x0000, 0x1800, 0x7600, 0x0660, 0x0000, 0x1800, 0x1860, + 0x3c7e, 0x7e3c, 0x0c3c, 0x3c30, 0x3c38, 0x1818, 0x0000, 0x0018, + 0x3c66, 0x7c3c, 0x787e, 0x603c, 0x667e, 0x3cc6, 0x7ec6, 0x663c, + 0x6036, 0xc67c, 0x183c, 0x1882, 0x6618, 0x7e1e, 0x0678, 0x00fe, + 0x003e, 0x7c3e, 0x3e3e, 0x1806, 0x663c, 0x0cc6, 0x3cc6, 0x663c, + 0x7c3e, 0x607c, 0x0e3e, 0x1882, 0x6606, 0x7e18, 0x1830, 0x0000, + 0x3c3e, 0x3e3e, 0x3e3e, 0x3e3e, 0x3e3e, 0x3e3c, 0x3c3c, 0x6666, + 0x7e7f, 0xde3c, 0x3c3c, 0x3e3e, 0x063c, 0x3c18, 0xff18, 0x6070, + 0x3e3c, 0x3c3e, 0x6666, 0x0000, 0x3c60, 0x0618, 0x3f18, 0x0000, + 0x3e3c, 0xbcbc, 0x7f7e, 0x6666, 0x3c00, 0x0000, 0x0a00, 0x0000, + 0x0e0e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x3000, 0x0000, 0x1806, 0x0006, 0x0638, 0x0000, + 0x0060, 0xf000, 0xfe00, 0xc000, 0x1000, 0x0000, 0xf010, 0x3ec6, + 0x007e, 0x7e7e, 0x1870, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x2000, 0x1000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1e3c, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0030, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x007e, 0x0000, 0x7c00, 0x0000, 0x0000, + 0x6006, 0x0000, 0x0000, 0x0000, 0x007e, 0x000e, 0x18e0, 0x0000, + 0x0c00, 0x0000, 0x0000, 0x000c, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x7e00, 0x0000, 0x0000, 0x4060, + 0x0000, 0x0000, 0x0000, 0x7e7e, 0x0000, 0x001f, 0x0218, 0x0000, + 0x0000, 0x8080, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x3c7c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x3000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0040, 0x0000, 0x0000, 0x8000, 0x7c00, 0x0000, 0xe000, 0x0000, + 0x0000, 0x0000, 0x1800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1754, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0020, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x007c, 0x0000, 0x7800, 0x0000, 0x0000, + 0x6006, 0x0000, 0x0000, 0x0000, 0x007c, 0x0000, 0x0000, 0x0000, + 0x3800, 0x0000, 0x0000, 0x0038, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x7c00, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x3878, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x1800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +}; + +const struct font_head fnt_st_8x16 = { + 1, /* WORD font_id */ + 10, /* WORD point */ + "8x16 system font", /* BYTE name[32] */ + 0, /* WORD first_ade */ + 255, /* WORD last_ade */ + 13, /* UWORD top */ + 11, /* UWORD ascent */ + 8, /* UWORD half */ + 2, /* UWORD descent */ + 2, /* UWORD bottom */ + 7, /* UWORD max_char_width */ + 8, /* UWORD max_cell_width */ + 1, /* UWORD left_offset */ + 7, /* UWORD right_offset */ + 1, /* UWORD thicken */ + 1, /* UWORD ul_size */ + 0x5555, /* UWORD lighten */ + 0x5555, /* UWORD skew */ + F_STDFORM | F_MONOSPACE | F_DEFAULT, /* UWORD flags */ + 0, /* UBYTE *hor_table */ + off_table, /* UWORD *off_table */ + dat_table, /* UWORD *dat_table */ + 256, /* UWORD form_width */ + 16, /* UWORD form_height */ + 0, /* struct font * next_font */ + 0 /* UWORD next_seg */ +}; diff --git a/video/vdi_fill.c b/video/vdi_fill.c new file mode 100644 index 0000000..6b789a9 --- /dev/null +++ b/video/vdi_fill.c @@ -0,0 +1,1112 @@ +/* + * + * + * Copyright 1982 by Digital Research Inc. All rights reserved. + * Copyright 1999 by Caldera, Inc. and Authors: + * Copyright 2002-2013 The EmuTOS development team + * + * This file is distributed under the GPL, version 2 or at your + * option any later version. See doc/license.txt for details. + */ + + + +#include "config.h" +#include "portab.h" +#include "vdi_defs.h" +#include "tosvars.h" +#include "lineavars.h" + +#define EMPTY 0xffff +#define DOWN_FLAG 0x8000 +#define QSIZE 200 +#define QMAX QSIZE-1 + + + +#define ABS(v) (v & 0x7FFF) + + + +/* prototypes */ +static void crunch_queue(void); +static BOOL clipbox(Vwk * vwk, Rect * rect); + + + +/* Global variables */ +static UWORD search_color; /* the color of the border */ + + +/* some kind of stack for the segments to fill */ +static WORD queue[QSIZE]; /* storage for the seed points */ +static WORD qbottom; /* the bottom of the queue (zero) */ +static WORD qtop; /* points top seed +3 */ +static WORD qptr; /* points to the active point */ +static WORD qtmp; +static WORD qhole; /* an empty space in the queue */ + + +/* the storage for the used defined fill pattern */ +const UWORD ROM_UD_PATRN[16] = { + 0x07E0, 0x0FF0, 0x1FD8, 0x1808, 0x1808, 0x1008, 0x1E78, 0x1348, + 0x1108, 0x0810, 0x0B70, 0x0650, 0x07A0, 0x1E20, 0x1BC0, 0x1800 +}; + +static const UWORD OEMMSKPAT = 7; +static const UWORD OEMPAT[128] = { + /* Brick */ + 0xFFFF, 0x8080, 0x8080, 0x8080, 0xFFFF, 0x0808, 0x0808, 0x0808, + /* Diagonal Bricks */ + 0x2020, 0x4040, 0x8080, 0x4141, 0x2222, 0x1414, 0x0808, 0x1010, + /* Grass */ + 0x0000, 0x0000, 0x1010, 0x2828, 0x0000, 0x0000, 0x0101, 0x8282, + /* Trees */ + 0x0202, 0x0202, 0xAAAA, 0x5050, 0x2020, 0x2020, 0xAAAA, 0x0505, + /* Dashed x's */ + 0x4040, 0x8080, 0x0000, 0x0808, 0x0404, 0x0202, 0x0000, 0x2020, + /* Cobble Stones */ + 0x6606, 0xC6C6, 0xD8D8, 0x1818, 0x8181, 0x8DB1, 0x0C33, 0x6000, + /* Sand */ + 0x0000, 0x0000, 0x0400, 0x0000, 0x0010, 0x0000, 0x8000, 0x0000, + /* Rough Weave */ + 0xF8F8, 0x6C6C, 0xC6C6, 0x8F8F, 0x1F1F, 0x3636, 0x6363, 0xF1F1, + /* Quilt */ + 0xAAAA, 0x0000, 0x8888, 0x1414, 0x2222, 0x4141, 0x8888, 0x0000, + /* Paterned Cross */ + 0x0808, 0x0000, 0xAAAA, 0x0000, 0x0808, 0x0000, 0x8888, 0x0000, + /* Balls */ + 0x7777, 0x9898, 0xF8F8, 0xF8F8, 0x7777, 0x8989, 0x8F8F, 0x8F8F, + /* Verticle Scales */ + 0x8080, 0x8080, 0x4141, 0x3E3E, 0x0808, 0x0808, 0x1414, 0xE3E3, + /* Diagonal scales */ + 0x8181, 0x4242, 0x2424, 0x1818, 0x0606, 0x0101, 0x8080, 0x8080, + /* Checker Board */ + 0xF0F0, 0xF0F0, 0xF0F0, 0xF0F0, 0x0F0F, 0x0F0F, 0x0F0F, 0x0F0F, + /* Filled Diamond */ + 0x0808, 0x1C1C, 0x3E3E, 0x7F7F, 0xFFFF, 0x7F7F, 0x3E3E, 0x1C1C, + /* Herringbone */ + 0x1111, 0x2222, 0x4444, 0xFFFF, 0x8888, 0x4444, 0x2222, 0xFFFF +}; + +static const UWORD DITHRMSK = 3; /* mask off all but four scans */ +static const UWORD DITHER[32] = { + 0x0000, 0x4444, 0x0000, 0x1111, /* intensity level 2 */ + 0x0000, 0x5555, 0x0000, 0x5555, /* intensity level 4 */ + 0x8888, 0x5555, 0x2222, 0x5555, /* intensity level 6 */ + 0xAAAA, 0x5555, 0xAAAA, 0x5555, /* intensity level 8 */ + 0xAAAA, 0xDDDD, 0xAAAA, 0x7777, /* intensity level 10 */ + 0xAAAA, 0xFFFF, 0xAAAA, 0xFFFF, /* intensity level 12 */ + 0xEEEE, 0xFFFF, 0xBBBB, 0xFFFF, /* intensity level 14 */ + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF /* intensity level 16 */ +}; + +static const UWORD HAT_0_MSK = 7; +static const UWORD HATCH0[48] = { + /* narrow spaced + 45 */ + 0x0101, 0x0202, 0x0404, 0x0808, 0x1010, 0x2020, 0x4040, 0x8080, + /* medium spaced thick 45 deg */ + 0x6060, 0xC0C0, 0x8181, 0x0303, 0x0606, 0x0C0C, 0x1818, 0x3030, + /* medium +-45 deg */ + 0x4242, 0x8181, 0x8181, 0x4242, 0x2424, 0x1818, 0x1818, 0x2424, + /* medium spaced vertical */ + 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, + /* medium spaced horizontal */ + 0xFFFF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* medium spaced cross */ + 0xFFFF, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080 +}; + +static const UWORD HAT_1_MSK = 0xF; +static const UWORD HATCH1[96] = { + /* wide +45 deg */ + 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, + 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, + /* widely spaced thick 45 deg */ + 0x8003, 0x0007, 0x000E, 0x001C, 0x0038, 0x0070, 0x00E0, 0x01C0, + 0x0380, 0x0700, 0x0E00, 0x1C00, 0x3800, 0x7000, 0x0E000, 0x0C001, + /* widely +- 45 deg */ + 0x8001, 0x4002, 0x2004, 0x1008, 0x0810, 0x0420, 0x0240, 0x0180, + 0x0180, 0x0240, 0x0420, 0x0810, 0x1008, 0x2004, 0x4002, 0x8001, + /* widely spaced vertical */ + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, + /* widely spaced horizontal */ + 0xFFFF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* widely spaced horizontal/vert cross */ + 0xFFFF, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, + 0xFFFF, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, +}; + +const UWORD HOLLOW = 0; +const UWORD SOLID = 0xFFFF; + + + +/* + * dsf_udpat - Update pattern + */ + +void +dsf_udpat(Vwk * vwk) +{ + WORD *sp, *dp, i, count; + + count = CONTRL[3]; + + if (count == 16) + vwk->multifill = 0; /* Single Plane Pattern */ + else if (count == (INQ_TAB[4] * 16)) + vwk->multifill = 1; /* Valid Multi-plane pattern */ + else + return; /* Invalid pattern, return */ + + sp = INTIN; + dp = &vwk->ud_patrn[0]; + for (i = 0; i < count; i++) + *dp++ = *sp++; +} + + + +/* + * _vsf_interior - Set fill style + */ + +void +_vsf_interior(Vwk * vwk) +{ + WORD fs; + + CONTRL[4] = 1; + fs = *INTIN; + if ((fs > MX_FIL_STYLE) || (fs < 0)) + fs = 0; + *INTOUT = vwk->fill_style = fs; + st_fl_ptr(vwk); +} + + + +/* S_FILL_INDEX: */ +void +_vsf_style(Vwk * vwk) +{ + WORD fi; + + CONTRL[4] = 1; + fi = *INTIN; + + if (vwk->fill_style == 2) { + if ((fi > MX_FIL_PAT_INDEX) || (fi < 1)) + fi = 1; + } else { + if ((fi > MX_FIL_HAT_INDEX) || (fi < 1)) + fi = 1; + } + vwk->fill_index = (*INTOUT = fi) - 1; + st_fl_ptr(vwk); +} + + + +/* S_FILL_COLOR: */ +void +_vsf_color(Vwk * vwk) +{ + WORD fc; + + *(CONTRL + 4) = 1; + fc = *INTIN; + if ((fc >= DEV_TAB[13]) || (fc < 0)) + fc = 1; + + *INTOUT = fc; + vwk->fill_color = MAP_COL[fc]; +} + + + +/* ST_FILLPERIMETER: */ +void +_vsf_perimeter(Vwk * vwk) +{ + WORD *int_out; + + int_out = INTOUT; + + if (*INTIN == 0) { + *int_out = 0; + vwk->fill_per = FALSE; + } else { + *(int_out) = 1; + vwk->fill_per = TRUE; + } + CONTRL[4] = 1; +} + + +/* + * dr_recfl - draw filled rectangle + */ + +void +dr_recfl(Vwk * vwk) +{ + Rect * rect = (Rect*)PTSIN; + + if (vwk->clip) + if (!clipbox(vwk, rect)) + return; + + /* do the real work... */ + draw_rect(vwk, rect, vwk->fill_color); +} + + + +/* + * _v_cellarray - Draw a square of sqares (just color devices) + */ +void +_v_cellarray(Vwk * vwk) +{ + /* not implemented */ +} + + + +/* + * _vq_cellarray - + */ +void +_vq_cellarray(Vwk * vwk) +{ + /* not implemented */ +} + + + +/* + * vql_attr - Inquire current fill area attributes + */ + +void +vqf_attr(Vwk * vwk) +{ + WORD *pointer; + + pointer = INTOUT; + *pointer++ = vwk->fill_style; + *pointer++ = REV_MAP_COL[vwk->fill_color]; + *pointer++ = vwk->fill_index + 1; + *pointer++ = vwk->wrt_mode + 1; + *pointer = vwk->fill_per; + + CONTRL[4] = 5; +} + + + +/* + * st_fl_ptr - set fill pattern? + */ + +void +st_fl_ptr(Vwk * vwk) +{ + WORD fi, pm; + const UWORD *pp = NULL; + + fi = vwk->fill_index; + pm = 0; + switch (vwk->fill_style) { + case 0: + pp = &HOLLOW; + break; + + case 1: + pp = &SOLID; + break; + + case 2: + if (fi < 8) { + pm = DITHRMSK; + pp = &DITHER[fi * (pm + 1)]; + } else { + pm = OEMMSKPAT; + pp = &OEMPAT[(fi - 8) * (pm + 1)]; + } + break; + case 3: + if (fi < 6) { + pm = HAT_0_MSK; + pp = &HATCH0[fi * (pm + 1)]; + } else { + pm = HAT_1_MSK; + pp = &HATCH1[(fi - 6) * (pm + 1)]; + } + break; + case 4: + pm = 0x000f; + pp = (UWORD *)&vwk->ud_patrn[0]; + break; + } + vwk->patptr = (UWORD *)pp; + vwk->patmsk = pm; +} + + + +/* + * bub_sort - sorts an array of words + * + * This routine bubble-sorts an array of words into ascending order. + * + * input: + * buf - ptr to start of array. + * count - number of words in array. + */ + +static void +bub_sort (WORD * buf, WORD count) +{ + int i, j; + + for (i = count-1; i > 0; i--) { + WORD * ptr = buf; /* reset pointer to the array */ + for (j = 0; j < i; j++) { + WORD val = *ptr++; /* word */ /* get next value */ + if ( val > *ptr ) { /* yes - do nothing */ + *(ptr-1) = *ptr; /* word */ /* nope - swap them */ + *ptr = val; /* word */ + } + } + } +} + + + +/* + * clc_flit - draw a filled polygon + * + * (Sutherland and Hodgman Polygon Clipping Algorithm) + * + * For each non-horizontal scanline crossing poly, do: + * - find intersection points of scan line with poly edges. + * - Sort intersections left to right + * - Draw pixels between each pair of points (x coords) on the scan line + */ +/* + * the buffer used by clc_flit() has been temporarily moved from the + * stack to a local static area. this avoids some cases of stack + * overflow when the VDI is called from the AES (and the stack is the + * small one located in the UDA). this fix allows GemAmigo to run. + * + * this change restores the situation that existed in the original + * DRI code, when clc_flit() was written in assembler; the buffer + * was moved to the stack when clc_flit() was re-implemented in C. + */ +#define MAX_INTERSECTIONS 256 +static WORD fill_buffer[MAX_INTERSECTIONS]; + +void +clc_flit (const VwkAttrib * attr, const VwkClip * clipper, const Point * point, WORD y, int vectors) +{ +// WORD fill_buffer[256]; /* must be 256 words or it will fail */ + WORD * bufptr; /* point to array of x-values. */ + int intersections; /* count of intersections */ + int i; + + /* Initialize the pointers and counters. */ + intersections = 0; /* reset counter */ + bufptr = fill_buffer; + + /* find intersection points of scan line with poly edges. */ + for (i = vectors - 1; i >= 0; i--) { + WORD x1, x2, y1, y2, dy; + + x1 = point->x; /* fetch x-value of 1st endpoint. */ + y1 = point->y; /* fetch y-value of 1st endpoint. */ + point++; + x2 = point->x; /* fetch x-value of 2nd endpoint. */ + y2 = point->y; /* fetch y-value of 2nd endpoint. */ + + /* if the current vector is horizontal, ignore it. */ + dy = y2 - y1; + if ( dy ) { + LONG dy1, dy2; + + /* fetch scan-line y. */ + dy1 = y - y1; /* d4 - delta y1. */ + dy2 = y - y2; /* d3 - delta y2. */ + + /* + * Determine whether the current vector intersects with the scan + * line we wish to draw. This test is performed by computing the + * y-deltas of the two endpoints from the scan line. + * If both deltas have the same sign, then the line does + * not intersect and can be ignored. The origin for this + * test is found in Newman and Sproull. + */ + if ((dy1 < 0) != (dy2 < 0)) { + int dx = (x2 - x1) << 1; /* so we can round by adding 1 below */ + if (++intersections > MAX_INTERSECTIONS) + break; + /* fill edge buffer with x-values */ + if ( dx < 0 ) { + *bufptr++ = ((dy2 * dx / dy + 1) >> 1) + x2; + } + else { + *bufptr++ = ((dy1 * dx / dy + 1) >> 1) + x1; + } + } + } + } + + /* + * All of the points of intersection have now been found. If there + * were none then there is nothing more to do. Otherwise, sort the + * list of points of intersection in ascending order. + * (The list contains only the x-coordinates of the points.) + */ + + /* anything to do? */ + if (intersections == 0) + return; + + /* bubblesort the intersections, if it makes sense */ + if ( intersections > 1 ) + bub_sort(fill_buffer, intersections); + + if (attr->clip) { + /* Clipping is in force. Once the endpoints of the line segment have */ + /* been adjusted for the border, clip them to the left and right sides */ + /* of the clipping rectangle. */ + + /* The x-coordinates of each line segment are adjusted so that the */ + /* border of the figure will not be drawn with the fill pattern. */ + + /* loop through buffered points */ + WORD * ptr = fill_buffer; + for (i = intersections / 2 - 1; i >= 0; i--) { + WORD x1, x2; + Rect rect; + + /* grab a pair of adjusted intersections */ + x1 = *ptr++ + 1; + x2 = *ptr++ - 1; + + /* do nothing, if starting point greater than ending point */ + if ( x1 > x2 ) + continue; + + if ( x1 < clipper->xmn_clip ) { + if ( x2 < clipper->xmn_clip ) + continue; /* entire segment clipped left */ + x1 = clipper->xmn_clip; /* clip left end of line */ + } + + if ( x2 > clipper->xmx_clip ) { + if ( x1 > clipper->xmx_clip ) + continue; /* entire segment clippped */ + x2 = clipper->xmx_clip; /* clip right end of line */ + } + rect.x1 = x1; + rect.y1 = y; + rect.x2 = x2; + rect.y2 = y; + + /* rectangle fill routine draws horizontal line */ + draw_rect_common(attr, &rect); + } + } + else { + /* Clipping is not in force. Draw from point to point. */ + + /* This code has been modified from the version in the screen driver. */ + /* The x-coordinates of each line segment are adjusted so that the */ + /* border of the figure will not be drawn with the fill pattern. If */ + /* the starting point is greater than the ending point then nothing is */ + /* done. */ + + /* loop through buffered points */ + WORD * ptr = fill_buffer; + for (i = intersections / 2 - 1; i >= 0; i--) { + WORD x1, x2; + Rect rect; + + /* grab a pair of adjusted endpoints */ + x1 = *ptr++ + 1 ; /* word */ + x2 = *ptr++ - 1 ; /* word */ + + /* If starting point greater than ending point, nothing is done. */ /* is start still to left of end? */ + if ( x1 <= x2 ) { + rect.x1 = x1; + rect.y1 = y; + rect.x2 = x2; + rect.y2 = y; + + /* rectangle fill routine draws horizontal line */ + draw_rect_common(attr, &rect); + } + } + } +} + + +/* + * polygon - draw a filled polygon + */ + +void +polygon(Vwk * vwk, Point * ptsin, int count) +{ + WORD i, k, y; + WORD fill_maxy, fill_miny; + Point * point, * ptsget, * ptsput; + VwkClip *clipper; + VwkAttrib attr; + + LSTLIN = FALSE; + + /* find out the total min and max y values */ + point = ptsin; + fill_maxy = fill_miny = point->y; + for (i = count - 1; i > 0; i--) { + point++; + k = point->y; + + if (k < fill_miny) + fill_miny = k; + else + if (k > fill_maxy) + fill_maxy = k; + } + + if (vwk->clip) { + if (fill_miny < vwk->ymn_clip) { + if (fill_maxy >= vwk->ymn_clip) { + /* polygon starts before clip */ + fill_miny = vwk->ymn_clip - 1; /* polygon partial overlap */ + if (fill_miny < 1) + fill_miny = 1; + } else + return; /* polygon entirely before clip */ + } + if (fill_maxy > vwk->ymx_clip) { + if (fill_miny <= vwk->ymx_clip) /* polygon ends after clip */ + fill_maxy = vwk->ymx_clip; /* polygon partial overlap */ + else + return; /* polygon entirely after clip */ + } + } + + /* close the polygon, connect last and first point */ + ptsget = ptsin; + ptsput = ptsin + count; + ptsput->x = ptsget->x; + ptsput->y = ptsget->y; + + /* cast structure needed by clc_flit */ + clipper = VDI_CLIP(vwk); + /* copy data needed by clc_flit -> draw_rect_common */ + Vwk2Attrib(vwk, &attr, vwk->fill_color); + + /* really draw it */ + for (y = fill_maxy; y > fill_miny; y--) { + clc_flit(&attr, clipper, ptsin, y, count); + } + if (vwk->fill_per == TRUE) { + LN_MASK = 0xffff; + polyline(vwk, ptsin, count+1, vwk->fill_color); + } +} + + + +/* + * _v_fillarea - Fill an area + */ + +void +_v_fillarea(Vwk * vwk) +{ + Point * point = (Point*)PTSIN; + int count = CONTRL[1]; + +#if 0 +#if HAVE_BEZIER + /* check, if we want to draw a filled bezier curve */ + if (CONTRL[5] == 13 && vwk->bez_qual ) + v_bez_fill(vwk, point, count); + else +#endif +#endif + polygon(vwk, point, count); +} + + + +/* + * clipbox - Just clips and copies the inputs for use by "rectfill" + * + * input: + * X1 = x coord of upper left corner. + * Y1 = y coord of upper left corner. + * X2 = x coord of lower right corner. + * Y2 = y coord of lower right corner. + * vwk->clip = clipping flag. (0 => no clipping.) + * vwk->xmn_clip = x clipping minimum. + * vwk->xmx_clip = x clipping maximum. + * vwk->ymn_clip = y clipping minimum. + * vwk->ymx_clip = y clipping maximum. + * + * output: + * X1 = x coord of upper left corner. + * Y1 = y coord of upper left corner. + * X2 = x coord of lower right corner. + * Y2 = y coord of lower right corner. + */ + +static BOOL +clipbox(Vwk * vwk, Rect * rect) +{ + WORD x1, y1, x2, y2; + + x1 = rect->x1; + y1 = rect->y1; + x2 = rect->x2; + y2 = rect->y2; + + /* clip x coordinates */ + if ( x1 < vwk->xmn_clip) { + if (x2 < vwk->xmn_clip) { + return(FALSE); /* clipped box is null */ + } + rect->x1 = vwk->xmn_clip; + } + if ( x2 > vwk->xmx_clip) { + if (x1 > vwk->xmx_clip) { + return(FALSE); /* clipped box is null */ + } + rect->x2 = vwk->xmx_clip; + } + /* clip y coordinates */ + if ( y1 < vwk->ymn_clip) { + if (y2 < vwk->ymn_clip) { + return(FALSE); /* clipped box is null */ + } + rect->y1 = vwk->ymn_clip; + } + if ( y2 > vwk->ymx_clip) { + if (y1 > vwk->ymx_clip) { + return(FALSE); /* clipped box is null */ + } + rect->y2 = vwk->ymx_clip; + } + return (TRUE); +} + + +/* + * get_color - Get color value of requested pixel. + */ +static UWORD +get_color (UWORD mask, UWORD * addr) +{ + UWORD color = 0; /* clear the pixel value accumulator. */ + WORD plane = v_planes; + + while(1) { + /* test the bit. */ + if ( *--addr & mask ) + color |= 1; /* if 1, set color accumulator bit. */ + + if ( --plane == 0 ) + break; + + color <<= 1; /* shift accumulator for next bit_plane. */ + } + + return color; /* this is the color we are searching for */ +} + +/* + * pixelread - gets a pixel's color index value + * + * input: + * PTSIN(0) = x coordinate. + * PTSIN(1) = y coordinate. + * output: + * pixel value + */ + +static UWORD +pixelread(const WORD x, const WORD y) +{ + UWORD *addr; + UWORD mask; + + /* convert x,y to start adress and bit mask */ + addr = get_start_addr(x, y); + addr += v_planes; /* start at highest-order bit_plane */ + mask = 0x8000 >> (x&0xf); /* initial bit position in WORD */ + + return get_color(mask, addr); /* return the composed color value */ +} + +static UWORD +search_to_right (Vwk * vwk, WORD x, UWORD mask, const UWORD search_col, UWORD * addr) +{ + /* is x coord < x resolution ? */ + while( x++ < vwk->xmx_clip ) { + UWORD color; + + /* need to jump over interleaved bit_plane? */ + mask = mask >> 1 | mask << 15; /* roll right */ + if ( mask & 0x8000 ) + addr += v_planes; + + /* search, while pixel color != search color */ + color = get_color(mask, addr); + if ( search_col != color ) { + break; + } + + } + + return x - 1; /* output x coord -1 to endxright. */ +} + +static UWORD +search_to_left (Vwk * vwk, WORD x, UWORD mask, const UWORD search_col, UWORD * addr) +{ + /* Now, search to the left. */ + while (x-- > vwk->xmn_clip) { + UWORD color; + + /* need to jump over interleaved bit_plane? */ + mask = mask >> 15 | mask << 1; /* roll left */ + if ( mask & 0x0001 ) + addr -= v_planes; + + /* search, while pixel color != search color */ + color = get_color(mask, addr); + if ( search_col != color ) + break; + + } + + return x + 1; /* output x coord + 1 to endxleft. */ +} + +/* + * end_pts - find the endpoints of a section of solid color + * + * (for the _seed_fill routine.) + * + * input: 4(sp) = xstart. + * 6(sp) = ystart. + * 8(sp) = ptr to endxleft. + * C(sp) = ptr to endxright. + * + * output: endxleft := left endpoint of solid color. + * endxright := right endpoint of solid color. + * d0 := success flag. + * 0 => no endpoints or xstart on edge. + * 1 => endpoints found. + * seed_type indicates the type of fill + */ + +static WORD +end_pts(Vwk * vwk, WORD x, WORD y, WORD *xleftout, WORD *xrightout, + BOOL seed_type) +{ + UWORD color; + UWORD * addr; + UWORD mask; + + /* see, if we are in the y clipping range */ + if ( y < vwk->ymn_clip || y > vwk->ymx_clip) + return 0; + + /* convert x,y to start adress and bit mask */ + addr = get_start_addr(x, y); + addr += v_planes; /* start at highest-order bit_plane */ + mask = 0x8000 >> (x & 0x000f); /* fetch the pixel mask. */ + + /* get search color and the left and right end */ + color = get_color (mask, addr); + *xrightout = search_to_right (vwk, x, mask, color, addr); + *xleftout = search_to_left (vwk, x, mask, color, addr); + + /* see, if the whole found segment is of search color? */ + if ( color != search_color ) { + return seed_type ^ 1; /* return segment not of search color */ + } + return seed_type ^ 0; /* return segment is of search color */ +} + +/* Prototypes local to this module */ +static WORD +get_seed(Vwk * vwk, WORD xin, WORD yin, WORD *xleftout, WORD *xrightout, + BOOL seed_type); + + +void +d_contourfill(Vwk * vwk) +{ + WORD newxleft; /* ends of line at oldy + */ + WORD newxright; /* the current direction */ + WORD oldxleft; /* left end of line at oldy */ + WORD oldxright; /* right end */ + WORD oldy; /* the previous scan line */ + WORD xleft; /* temporary endpoints */ + WORD xright; /* */ + WORD direction; /* is next scan line up or down */ + BOOL notdone; /* does seedpoint==search_color */ + BOOL gotseed; /* a seed was put in the Q */ + BOOL seed_type; /* indicates the type of fill */ + + xleft = PTSIN[0]; + oldy = PTSIN[1]; + + if (xleft < vwk->xmn_clip || xleft > vwk->xmx_clip || + oldy < vwk->ymn_clip || oldy > vwk->ymx_clip) + return; + + search_color = INTIN[0]; + + if ((WORD)search_color < 0) { + search_color = pixelread(xleft,oldy); + seed_type = 1; + } else { + const WORD plane_mask[] = { 1, 3, 7, 15 }; + + /* Range check the color and convert the index to a pixel value */ + if (search_color >= DEV_TAB[13]) + return; + + /* + * We mandate that white is all bits on. Since this yields 15 + * in rom, we must limit it to how many planes there really are. + * Anding with the mask is only necessary when the driver supports + * move than one resolution. + */ + search_color = + (MAP_COL[search_color] & plane_mask[INQ_TAB[4] - 1]); + seed_type = 0; + } + + /* Initialize the line drawing parameters */ + LSTLIN = FALSE; + + notdone = end_pts(vwk, xleft, oldy, &oldxleft, &oldxright, seed_type); + + qptr = qbottom = 0; + qtop = 3; /* one above highest seed point */ + queue[0] = (oldy | DOWN_FLAG); + queue[1] = oldxleft; + queue[2] = oldxright; /* stuff a point going down into the Q */ + + if (notdone) { + /* couldn't get point out of Q or draw it */ + while (1) { + Rect rect; + + direction = (oldy & DOWN_FLAG) ? 1 : -1; + gotseed = get_seed(vwk, oldxleft, (oldy + direction), + &newxleft, &newxright, seed_type); + + if ((newxleft < (oldxleft - 1)) && gotseed) { + xleft = oldxleft; + while (xleft > newxleft) { + --xleft; + get_seed(vwk, xleft, oldy ^ DOWN_FLAG, + &xleft, &xright, seed_type); + } + } + while (newxright < oldxright) { + ++newxright; + gotseed = get_seed(vwk, newxright, oldy + direction, + &xleft, &newxright, seed_type); + } + if ((newxright > (oldxright + 1)) && gotseed) { + xright = oldxright; + while (xright < newxright) { + ++xright; + get_seed(vwk, xright, oldy ^ DOWN_FLAG, + &xleft, &xright, seed_type); + } + } + + /* Eventually jump out here */ + if (qtop == qbottom) + break; + + while (queue[qptr] == EMPTY) { + qptr += 3; + if (qptr == qtop) + qptr = qbottom; + } + + oldy = queue[qptr]; + queue[qptr++] = EMPTY; + oldxleft = queue[qptr++]; + oldxright = queue[qptr++]; + if (qptr == qtop) + crunch_queue(); + + rect.x1 = oldxleft; + rect.y1 = ABS(oldy); + rect.x2 = oldxright; + rect.y2 = ABS(oldy); + + /* rectangle fill routine draws horizontal line */ + draw_rect(vwk, &rect, vwk->fill_color); + } + } +} /* end of fill() */ + +/* + * crunch_queue - move qtop down to remove unused seeds + */ +static void +crunch_queue(void) +{ + while ((queue[qtop - 3] == EMPTY) && (qtop > qbottom)) + qtop -= 3; + if (qptr >= qtop) + qptr = qbottom; +} + +/* + * get_seed - put seeds into Q, if (xin,yin) is not of search_color + */ +static WORD +get_seed(Vwk * vwk, WORD xin, WORD yin, WORD *xleftout, WORD *xrightout, + BOOL seed_type) +{ + if (end_pts(vwk, xin, ABS(yin), xleftout, xrightout, seed_type)) { + /* false if of search_color */ + for (qtmp = qbottom, qhole = EMPTY; qtmp < qtop; qtmp += 3) { + /* see, if we ran into another seed */ + if ( ((queue[qtmp] ^ DOWN_FLAG) == yin) && (queue[qtmp] != EMPTY) && + (queue[qtmp + 1] == *xleftout) ) + + { + /* we ran into another seed so remove it and fill the line */ + Rect rect; + + rect.x1 = *xleftout; + rect.y1 = ABS(yin); + rect.x2 = *xrightout; + rect.y2 = ABS(yin); + + /* rectangle fill routine draws horizontal line */ + draw_rect(vwk, &rect, vwk->fill_color); + + queue[qtmp] = EMPTY; + if ((qtmp + 3) == qtop) + crunch_queue(); + return 0; + } + if ((queue[qtmp] == EMPTY) && (qhole == EMPTY)) + qhole = qtmp; + } + + if (qhole == EMPTY) { + if ((qtop += 3) > QMAX) { + qtmp = qbottom; + qtop -= 3; + } + } else + qtmp = qhole; + + queue[qtmp++] = yin; /* put the y and endpoints in the Q */ + queue[qtmp++] = *xleftout; + queue[qtmp] = *xrightout; + return 1; /* we put a seed in the Q */ + } + + return 0; /* we didnt put a seed in the Q */ +} + + + +void +_v_get_pixel(Vwk * vwk) +{ + WORD pel; + WORD *int_out; + const WORD x = PTSIN[0]; /* fetch x coord. */ + const WORD y = PTSIN[1]; /* fetch y coord. */ + + /* Get the requested pixel */ + pel = (WORD)pixelread(x,y); + + int_out = INTOUT; + *int_out++ = pel; + + *int_out = REV_MAP_COL[pel]; + CONTRL[4] = 2; +} + + + +/* + * get_pix - gets a pixel (just for linea!) + * + * input: + * PTSIN(0) = x coordinate. + * PTSIN(1) = y coordinate. + * output: + * pixel value + */ +WORD +get_pix(void) +{ + /* return the composed color value */ + return pixelread(PTSIN[0], PTSIN[1]); +} + +/* + * put_pix - plot a pixel (just for linea!) + * + * input: + * INTIN(0) = pixel value. + * PTSIN(0) = x coordinate. + * PTSIN(1) = y coordinate. + */ +void +put_pix(void) +{ + UWORD *addr; + UWORD color; + UWORD mask; + int plane; + + const WORD x = PTSIN[0]; + const WORD y = PTSIN[1]; + + /* convert x,y to start adress */ + addr = get_start_addr(x, y); + /* co-ordinates can wrap, but cannot write outside screen, + * alternatively this could check against v_bas_ad+vram_size() + */ + if (addr < (UWORD*)v_bas_ad || addr >= get_start_addr(v_hz_rez, v_vt_rez)) { + return; + } + color = INTIN[0]; /* device dependent encoded color bits */ + mask = 0x8000 >> (x&0xf); /* initial bit position in WORD */ + + for (plane = v_planes-1; plane >= 0; plane-- ) { + color = color >> 1| color << 15; /* rotate color bits */ + if (color&0x8000) + *addr++ |= mask; + else + *addr++ &= ~mask; + } +} diff --git a/video/videl.c b/video/videl.c new file mode 100644 index 0000000..30fd8c0 --- /dev/null +++ b/video/videl.c @@ -0,0 +1,858 @@ +/* + * videl.c - Falcon VIDEL support + * + * Copyright (c) 2013 The EmuTOS development team + * + * Authors: + * PES Petr Stehlik + * RFB Roger Burrows + * + * This file is distributed under the GPL, version 2 or at your + * option any later version. See doc/license.txt for details. + */ + +#define DBG_VIDEL 0 + +#include +#include +#include +#include "bas_printf.h" +#include "screen.h" +#include "videl.h" + +uint16_t *colorptr; + +static const int32_t videl_dflt_palette[] = { + FRGB_WHITE, FRGB_RED, FRGB_GREEN, FRGB_YELLOW, + FRGB_BLUE, FRGB_MAGENTA, FRGB_CYAN, FRGB_LTGRAY, + FRGB_GRAY, FRGB_LTRED, FRGB_LTGREEN, FRGB_LTYELLOW, + FRGB_LTBLUE, FRGB_LTMAGENTA, FRGB_LTCYAN, FRGB_BLACK, + 0xffff00ff, 0xeded00ed, 0xdddd00dd, 0xcccc00cc, + 0xbaba00ba, 0xaaaa00aa, 0x99990099, 0x87870087, + 0x77770077, 0x66660066, 0x54540054, 0x44440044, + 0x33330033, 0x21210021, 0x11110011, 0x00000000, + 0xff000000, 0xff000011, 0xff000021, 0xff000033, + 0xff000044, 0xff000054, 0xff000066, 0xff000077, + 0xff000087, 0xff000099, 0xff0000aa, 0xff0000ba, + 0xff0000cc, 0xff0000dd, 0xff0000ed, 0xff0000ff, + 0xed0000ff, 0xdd0000ff, 0xcc0000ff, 0xba0000ff, + 0xaa0000ff, 0x990000ff, 0x870000ff, 0x770000ff, + 0x660000ff, 0x540000ff, 0x440000ff, 0x330000ff, + 0x210000ff, 0x110000ff, 0x000000ff, 0x001100ff, + 0x002100ff, 0x003300ff, 0x004400ff, 0x005400ff, + 0x006600ff, 0x007700ff, 0x008700ff, 0x009900ff, + 0x00aa00ff, 0x00ba00ff, 0x00cc00ff, 0x00dd00ff, + 0x00ed00ff, 0x00ff00ff, 0x00ff00ed, 0x00ff00dd, + 0x00ff00cc, 0x00ff00ba, 0x00ff00aa, 0x00ff0099, + 0x00ff0087, 0x00ff0077, 0x00ff0066, 0x00ff0054, + 0x00ff0044, 0x00ff0033, 0x00ff0021, 0x00ff0011, + 0x00ff0000, 0x11ff0000, 0x21ff0000, 0x33ff0000, + 0x44ff0000, 0x54ff0000, 0x66ff0000, 0x77ff0000, + 0x87ff0000, 0x99ff0000, 0xaaff0000, 0xbaff0000, + 0xccff0000, 0xddff0000, 0xedff0000, 0xffff0000, + 0xffed0000, 0xffdd0000, 0xffcc0000, 0xffba0000, + 0xffaa0000, 0xff990000, 0xff870000, 0xff770000, + 0xff660000, 0xff540000, 0xff440000, 0xff330000, + 0xff210000, 0xff110000, 0xba000000, 0xba000011, + 0xba000021, 0xba000033, 0xba000044, 0xba000054, + 0xba000066, 0xba000077, 0xba000087, 0xba000099, + 0xba0000aa, 0xba0000ba, 0xaa0000ba, 0x990000ba, + 0x870000ba, 0x770000ba, 0x660000ba, 0x540000ba, + 0x440000ba, 0x330000ba, 0x210000ba, 0x110000ba, + 0x000000ba, 0x001100ba, 0x002100ba, 0x003300ba, + 0x004400ba, 0x005400ba, 0x006600ba, 0x007700ba, + 0x008700ba, 0x009900ba, 0x00aa00ba, 0x00ba00ba, + 0x00ba00aa, 0x00ba0099, 0x00ba0087, 0x00ba0077, + 0x00ba0066, 0x00ba0054, 0x00ba0044, 0x00ba0033, + 0x00ba0021, 0x00ba0011, 0x00ba0000, 0x11ba0000, + 0x21ba0000, 0x33ba0000, 0x44ba0000, 0x54ba0000, + 0x66ba0000, 0x77ba0000, 0x87ba0000, 0x99ba0000, + 0xaaba0000, 0xbaba0000, 0xbaaa0000, 0xba990000, + 0xba870000, 0xba770000, 0xba660000, 0xba540000, + 0xba440000, 0xba330000, 0xba210000, 0xba110000, + 0x77000000, 0x77000011, 0x77000021, 0x77000033, + 0x77000044, 0x77000054, 0x77000066, 0x77000077, + 0x66000077, 0x54000077, 0x44000077, 0x33000077, + 0x21000077, 0x11000077, 0x00000077, 0x00110077, + 0x00210077, 0x00330077, 0x00440077, 0x00540077, + 0x00660077, 0x00770077, 0x00770066, 0x00770054, + 0x00770044, 0x00770033, 0x00770021, 0x00770011, + 0x00770000, 0x11770000, 0x21770000, 0x33770000, + 0x44770000, 0x54770000, 0x66770000, 0x77770000, + 0x77660000, 0x77540000, 0x77440000, 0x77330000, + 0x77210000, 0x77110000, 0x44000000, 0x44000011, + 0x44000021, 0x44000033, 0x44000044, 0x33000044, + 0x21000044, 0x11000044, 0x00000044, 0x00110044, + 0x00210044, 0x00330044, 0x00440044, 0x00440033, + 0x00440021, 0x00440011, 0x00440000, 0x11440000, + 0x21440000, 0x33440000, 0x44440000, 0x44330000, + 0x44210000, 0x44110000, FRGB_WHITE, FRGB_BLACK +}; + +int32_t falcon_shadow_palette[256]; /* real Falcon does this, used by vectors.S */ +static int16_t ste_shadow_palette[16]; + +#define MON_ALL -1 /* code used in VMODE_ENTRY for match on mode only */ + +/* + * tables that cover all(?) valid Falcon modes + * note: + * . 256-colour and Truecolor modes are not currently supported by the VDI + */ +static const VMODE_ENTRY vga_init_table[] = { + /* the entries in this table are for VGA/NTSC (i.e. VGA 60Hz) and VGA/PAL + * (i.e. VGA 50Hz). in *this* table, each entry applies to four video modes: + * mode, mode|VIDEL_VERTICAL, mode|VIDEL_PAL, mode|VIDEL_VERTICAL|VIDEL_PAL + */ + { 0x0011, MON_ALL, 0x0017, 0x0012, 0x0001, 0x020a, 0x0009, 0x0011, 0x0419, 0x03ff, 0x003f, 0x003f, 0x03ff, 0x0415 }, + { 0x0012, MON_ALL, 0x00c6, 0x008d, 0x0015, 0x028a, 0x006b, 0x0096, 0x0419, 0x03ff, 0x003f, 0x003f, 0x03ff, 0x0415 }, + { 0x0013, MON_ALL, 0x00c6, 0x008d, 0x0015, 0x029a, 0x007b, 0x0096, 0x0419, 0x03ff, 0x003f, 0x003f, 0x03ff, 0x0415 }, + { 0x0014, MON_ALL, 0x00c6, 0x008d, 0x0015, 0x02ac, 0x0091, 0x0096, 0x0419, 0x03ff, 0x003f, 0x003f, 0x03ff, 0x0415 }, + { 0x0018, MON_ALL, 0x00c6, 0x008d, 0x0015, 0x0273, 0x0050, 0x0096, 0x0419, 0x03ff, 0x003f, 0x003f, 0x03ff, 0x0415 }, + { 0x0019, MON_ALL, 0x0017, 0x0012, 0x0001, 0x020e, 0x000d, 0x0011, 0x0419, 0x03ff, 0x003f, 0x003f, 0x03ff, 0x0415 }, + { 0x001a, MON_ALL, 0x00c6, 0x008d, 0x0015, 0x02a3, 0x007c, 0x0096, 0x0419, 0x03ff, 0x003f, 0x003f, 0x03ff, 0x0415 }, + { 0x001b, MON_ALL, 0x00c6, 0x008d, 0x0015, 0x02ab, 0x0084, 0x0096, 0x0419, 0x03ff, 0x003f, 0x003f, 0x03ff, 0x0415 }, + { 0x0092, MON_ALL, 0x0017, 0x0012, 0x0001, 0x020e, 0x000d, 0x0011, 0x0419, 0x03af, 0x008f, 0x008f, 0x03af, 0x0415 }, + { 0x0098, MON_ALL, 0x00c6, 0x008d, 0x0015, 0x0273, 0x0050, 0x0096, 0x0419, 0x03af, 0x008f, 0x008f, 0x03af, 0x0415 }, + { 0x0099, MON_ALL, 0x0017, 0x0012, 0x0001, 0x020e, 0x000d, 0x0011, 0x0419, 0x03af, 0x008f, 0x008f, 0x03af, 0x0415 }, + { -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } +}; + +static const VMODE_ENTRY nonvga_init_table[] = { + /* the remaining entries are for TV+NTSC, TV+PAL, TV+NTSC+overscan, TV+PAL+overscan */ + { 0x0001, MON_ALL, 0x003e, 0x0030, 0x0008, 0x0239, 0x0012, 0x0034, 0x020d, 0x0201, 0x0016, 0x004d, 0x01dd, 0x0207 }, + { 0x0002, MON_ALL, 0x00fe, 0x00c9, 0x0027, 0x000c, 0x006d, 0x00d8, 0x020d, 0x0201, 0x0016, 0x004d, 0x01dd, 0x0207 }, + { 0x0003, MON_ALL, 0x00fe, 0x00c9, 0x0027, 0x001c, 0x007d, 0x00d8, 0x020d, 0x0201, 0x0016, 0x004d, 0x01dd, 0x0207 }, + { 0x0004, MON_ALL, 0x00fe, 0x00c9, 0x0027, 0x002e, 0x008f, 0x00d8, 0x020d, 0x0201, 0x0016, 0x004d, 0x01dd, 0x0207 }, + { 0x0008, MON_ALL, 0x01ff, 0x0197, 0x0050, 0x03f0, 0x009f, 0x01b4, 0x020d, 0x0201, 0x0016, 0x004d, 0x01dd, 0x0207 }, + { 0x0009, MON_ALL, 0x003e, 0x0030, 0x0008, 0x0002, 0x0020, 0x0034, 0x020d, 0x0201, 0x0016, 0x004d, 0x01dd, 0x0207 }, + { 0x000a, MON_ALL, 0x01ff, 0x0197, 0x0050, 0x004d, 0x00fd, 0x01b4, 0x020d, 0x0201, 0x0016, 0x004d, 0x01dd, 0x0207 }, + { 0x000b, MON_ALL, 0x01ff, 0x0197, 0x0050, 0x005d, 0x010d, 0x01b4, 0x020d, 0x0201, 0x0016, 0x004d, 0x01dd, 0x0207 }, + { 0x0021, MON_ALL, 0x003e, 0x0030, 0x0008, 0x0239, 0x0012, 0x0034, 0x0271, 0x0265, 0x002f, 0x007f, 0x020f, 0x026b }, + { 0x0022, MON_ALL, 0x00fe, 0x00cb, 0x0027, 0x000c, 0x006d, 0x00d8, 0x0271, 0x0265, 0x002f, 0x007f, 0x020f, 0x026b }, + { 0x0023, MON_ALL, 0x00fe, 0x00cb, 0x0027, 0x001c, 0x007d, 0x00d8, 0x0271, 0x0265, 0x002f, 0x007f, 0x020f, 0x026b }, + { 0x0024, MON_ALL, 0x00fe, 0x00cb, 0x0027, 0x002e, 0x008f, 0x00d8, 0x0271, 0x0265, 0x002f, 0x007f, 0x020f, 0x026b }, + { 0x0028, MON_ALL, 0x01fe, 0x0199, 0x0050, 0x03ef, 0x00a0, 0x01b2, 0x0271, 0x0265, 0x002f, 0x007f, 0x020f, 0x026b }, + { 0x0029, MON_ALL, 0x003e, 0x0030, 0x0008, 0x0002, 0x0020, 0x0034, 0x0271, 0x0265, 0x002f, 0x007f, 0x020f, 0x026b }, + { 0x002a, MON_ALL, 0x01fe, 0x0199, 0x0050, 0x004d, 0x00fe, 0x01b2, 0x0271, 0x0265, 0x002f, 0x007f, 0x020f, 0x026b }, + { 0x002b, MON_ALL, 0x01fe, 0x0199, 0x0050, 0x005d, 0x010e, 0x01b2, 0x0271, 0x0265, 0x002f, 0x007f, 0x020f, 0x026b }, + { 0x0041, MON_VGA, 0x003e, 0x0030, 0x0008, 0x0239, 0x0012, 0x0034, 0x020d, 0x0201, 0x0016, 0x0025, 0x0205, 0x0207 }, + { 0x0041, MON_ALL, 0x003e, 0x0030, 0x0008, 0x0232, 0x001b, 0x0034, 0x020d, 0x0201, 0x0016, 0x0025, 0x0205, 0x0207 }, + { 0x0042, MON_VGA, 0x00fe, 0x00c9, 0x0027, 0x000c, 0x006d, 0x00d8, 0x020d, 0x0201, 0x0016, 0x0025, 0x0205, 0x0207 }, + { 0x0042, MON_ALL, 0x00fe, 0x00c9, 0x0027, 0x02ec, 0x008d, 0x00d8, 0x020d, 0x0201, 0x0016, 0x0025, 0x0205, 0x0207 }, + { 0x0043, MON_VGA, 0x00fe, 0x00c9, 0x0027, 0x001c, 0x007d, 0x00d8, 0x020d, 0x0201, 0x0016, 0x0025, 0x0205, 0x0207 }, + { 0x0043, MON_ALL, 0x00fe, 0x00c9, 0x0027, 0x02fc, 0x009d, 0x00d8, 0x020d, 0x0201, 0x0016, 0x0025, 0x0205, 0x0207 }, + { 0x0044, MON_VGA, 0x00fe, 0x00c9, 0x0027, 0x002e, 0x008f, 0x00d8, 0x020d, 0x0201, 0x0016, 0x0025, 0x0205, 0x0207 }, + { 0x0044, MON_ALL, 0x00fe, 0x00c9, 0x0027, 0x000e, 0x00af, 0x00d8, 0x020d, 0x0201, 0x0016, 0x0025, 0x0205, 0x0207 }, + { 0x0048, MON_VGA, 0x01ff, 0x0197, 0x0050, 0x03f0, 0x009f, 0x01b4, 0x020d, 0x0201, 0x0016, 0x0025, 0x0205, 0x0207 }, + { 0x0048, MON_ALL, 0x01ff, 0x0197, 0x0050, 0x03b0, 0x00df, 0x01b4, 0x020d, 0x0201, 0x0016, 0x0025, 0x0205, 0x0207 }, + { 0x0049, MON_VGA, 0x003e, 0x0030, 0x0008, 0x023b, 0x001c, 0x0034, 0x020d, 0x0201, 0x0016, 0x0025, 0x0205, 0x0207 }, + { 0x0049, MON_ALL, 0x003e, 0x0030, 0x0008, 0x0237, 0x0020, 0x0034, 0x020d, 0x0201, 0x0016, 0x0025, 0x0205, 0x0207 }, + { 0x004a, MON_VGA, 0x01ff, 0x0197, 0x0050, 0x004d, 0x00fd, 0x01b4, 0x020d, 0x0201, 0x0016, 0x0025, 0x0205, 0x0207 }, + { 0x004a, MON_ALL, 0x01ff, 0x0197, 0x0050, 0x000d, 0x013d, 0x01b4, 0x020d, 0x0201, 0x0016, 0x0025, 0x0205, 0x0207 }, + { 0x004b, MON_VGA, 0x01ff, 0x0197, 0x0050, 0x005d, 0x010d, 0x01b4, 0x020d, 0x0201, 0x0016, 0x0025, 0x0205, 0x0207 }, + { 0x004b, MON_ALL, 0x01ff, 0x0197, 0x0050, 0x001d, 0x014d, 0x01b4, 0x020d, 0x0201, 0x0016, 0x0025, 0x0205, 0x0207 }, + { 0x0061, MON_VGA, 0x003e, 0x0030, 0x0008, 0x0239, 0x0012, 0x0034, 0x0271, 0x0265, 0x002f, 0x0057, 0x0237, 0x026b }, + { 0x0061, MON_ALL, 0x003e, 0x0030, 0x0008, 0x0232, 0x001b, 0x0034, 0x0271, 0x0265, 0x002f, 0x0057, 0x0237, 0x026b }, + { 0x0062, MON_VGA, 0x00fe, 0x00cb, 0x0027, 0x000c, 0x006d, 0x00d8, 0x0271, 0x0265, 0x002f, 0x0057, 0x0237, 0x026b }, + { 0x0062, MON_ALL, 0x00fe, 0x00cb, 0x0027, 0x02ec, 0x008d, 0x00d8, 0x0271, 0x0265, 0x002f, 0x0057, 0x0237, 0x026b }, + { 0x0063, MON_VGA, 0x00fe, 0x00cb, 0x0027, 0x001c, 0x007d, 0x00d8, 0x0271, 0x0265, 0x002f, 0x0057, 0x0237, 0x026b }, + { 0x0063, MON_ALL, 0x00fe, 0x00cb, 0x0027, 0x02fc, 0x009d, 0x00d8, 0x0271, 0x0265, 0x002f, 0x0057, 0x0237, 0x026b }, + { 0x0064, MON_VGA, 0x00fe, 0x00cb, 0x0027, 0x002e, 0x008f, 0x00d8, 0x0271, 0x0265, 0x002f, 0x0057, 0x0237, 0x026b }, + { 0x0064, MON_ALL, 0x00fe, 0x00cb, 0x0027, 0x000e, 0x00af, 0x00d8, 0x0271, 0x0265, 0x002f, 0x0057, 0x0237, 0x026b }, + { 0x0068, MON_VGA, 0x01fe, 0x0199, 0x0050, 0x03ef, 0x00a0, 0x01b2, 0x0271, 0x0265, 0x002f, 0x0057, 0x0237, 0x026b }, + { 0x0068, MON_ALL, 0x01fe, 0x0199, 0x0050, 0x03af, 0x00e0, 0x01b2, 0x0271, 0x0265, 0x002f, 0x0057, 0x0237, 0x026b }, + { 0x0069, MON_VGA, 0x003e, 0x0030, 0x0008, 0x023b, 0x001c, 0x0034, 0x0271, 0x0265, 0x002f, 0x0057, 0x0237, 0x026b }, + { 0x0069, MON_ALL, 0x003e, 0x0030, 0x0008, 0x0237, 0x0020, 0x0034, 0x0271, 0x0265, 0x002f, 0x0057, 0x0237, 0x026b }, + { 0x006a, MON_VGA, 0x01fe, 0x0199, 0x0050, 0x004d, 0x00fe, 0x01b2, 0x0271, 0x0265, 0x002f, 0x0057, 0x0237, 0x026b }, + { 0x006a, MON_ALL, 0x01fe, 0x0199, 0x0050, 0x000d, 0x013e, 0x01b2, 0x0271, 0x0265, 0x002f, 0x0057, 0x0237, 0x026b }, + { 0x006b, MON_VGA, 0x01fe, 0x0199, 0x0050, 0x005d, 0x010e, 0x01b2, 0x0271, 0x0265, 0x002f, 0x0057, 0x0237, 0x026b }, + { 0x006b, MON_ALL, 0x01fe, 0x0199, 0x0050, 0x001d, 0x014e, 0x01b2, 0x0271, 0x0265, 0x002f, 0x0057, 0x0237, 0x026b }, + { 0x0082, MON_ALL, 0x003e, 0x0032, 0x0009, 0x023f, 0x001c, 0x0034, 0x020d, 0x0201, 0x0016, 0x004d, 0x01dd, 0x0207 }, + { 0x0088, MON_MONO, 0x001a, 0x0000, 0x0000, 0x020f, 0x000c, 0x0014, 0x03e9, 0x0000, 0x0000, 0x0043, 0x0363, 0x03e7 }, + { 0x0088, MON_ALL, 0x01ff, 0x0197, 0x0050, 0x03f0, 0x009f, 0x01b4, 0x020d, 0x0201, 0x0016, 0x004d, 0x01dd, 0x0207 }, + { 0x0089, MON_ALL, 0x003e, 0x0032, 0x0009, 0x023f, 0x001c, 0x0034, 0x020d, 0x0201, 0x0016, 0x004d, 0x01dd, 0x0207 }, + { 0x00a2, MON_ALL, 0x003e, 0x0032, 0x0009, 0x023f, 0x001c, 0x0034, 0x0271, 0x0265, 0x002f, 0x006f, 0x01ff, 0x026b }, + { 0x00a8, MON_MONO, 0x001a, 0x0000, 0x0000, 0x020f, 0x000c, 0x0014, 0x03e9, 0x0000, 0x0000, 0x0043, 0x0363, 0x03e7 }, + { 0x00a8, MON_ALL, 0x01fe, 0x0199, 0x0050, 0x03ef, 0x00a0, 0x01b2, 0x0271, 0x0265, 0x002f, 0x007f, 0x020f, 0x026b }, + { 0x00a9, MON_ALL, 0x003e, 0x0032, 0x0009, 0x023f, 0x001c, 0x0034, 0x0271, 0x0265, 0x002f, 0x006f, 0x01ff, 0x026b }, + { 0x00c2, MON_ALL, 0x003e, 0x0032, 0x0009, 0x023f, 0x001c, 0x0034, 0x020d, 0x0201, 0x0016, 0x004d, 0x01dd, 0x0207 }, + { 0x00c8, MON_MONO, 0x001a, 0x0000, 0x0000, 0x020f, 0x000c, 0x0014, 0x03e9, 0x0000, 0x0000, 0x0043, 0x0363, 0x03e7 }, + { 0x00c8, MON_VGA, 0x01ff, 0x0197, 0x0050, 0x03f0, 0x009f, 0x01b4, 0x020d, 0x0201, 0x0016, 0x0025, 0x0205, 0x0207 }, + { 0x00c8, MON_ALL, 0x01ff, 0x0197, 0x0050, 0x03b0, 0x00df, 0x01b4, 0x020d, 0x0201, 0x0016, 0x0025, 0x0205, 0x0207 }, + { 0x00c9, MON_ALL, 0x003e, 0x0032, 0x0009, 0x023f, 0x001c, 0x0034, 0x020d, 0x0201, 0x0016, 0x004d, 0x01dd, 0x0207 }, + { 0x00e2, MON_ALL, 0x003e, 0x0032, 0x0009, 0x023f, 0x001c, 0x0034, 0x0271, 0x0265, 0x002f, 0x006f, 0x01ff, 0x026b }, + { 0x00e8, MON_MONO, 0x001a, 0x0000, 0x0000, 0x020f, 0x000c, 0x0014, 0x03e9, 0x0000, 0x0000, 0x0043, 0x0363, 0x03e7 }, + { 0x00e8, MON_VGA, 0x01fe, 0x0199, 0x0050, 0x03ef, 0x00a0, 0x01b2, 0x0271, 0x0265, 0x002f, 0x0057, 0x0237, 0x026b }, + { 0x00e8, MON_ALL, 0x01fe, 0x0199, 0x0050, 0x03af, 0x00e0, 0x01b2, 0x0271, 0x0265, 0x002f, 0x0057, 0x0237, 0x026b }, + { 0x00e9, MON_ALL, 0x003e, 0x0032, 0x0009, 0x023f, 0x001c, 0x0034, 0x0271, 0x0265, 0x002f, 0x006f, 0x01ff, 0x026b }, + { 0x0101, MON_ALL, 0x003e, 0x0030, 0x0008, 0x0239, 0x0012, 0x0034, 0x020c, 0x0201, 0x0016, 0x004c, 0x01dc, 0x0207 }, + { 0x0102, MON_ALL, 0x00fe, 0x00c9, 0x0027, 0x000c, 0x006d, 0x00d8, 0x020c, 0x0201, 0x0016, 0x004c, 0x01dc, 0x0207 }, + { 0x0103, MON_ALL, 0x00fe, 0x00c9, 0x0027, 0x001c, 0x007d, 0x00d8, 0x020c, 0x0201, 0x0016, 0x004c, 0x01dc, 0x0207 }, + { 0x0104, MON_ALL, 0x00fe, 0x00c9, 0x0027, 0x002e, 0x008f, 0x00d8, 0x020c, 0x0201, 0x0016, 0x004c, 0x01dc, 0x0207 }, + { 0x0108, MON_ALL, 0x01ff, 0x0197, 0x0050, 0x03f0, 0x009f, 0x01b4, 0x020c, 0x0201, 0x0016, 0x004c, 0x01dc, 0x0207 }, + { 0x0109, MON_ALL, 0x003e, 0x0030, 0x0008, 0x0002, 0x0020, 0x0034, 0x020c, 0x0201, 0x0016, 0x004c, 0x01dc, 0x0207 }, + { 0x010a, MON_ALL, 0x01ff, 0x0197, 0x0050, 0x004d, 0x00fd, 0x01b4, 0x020c, 0x0201, 0x0016, 0x004c, 0x01dc, 0x0207 }, + { 0x010b, MON_ALL, 0x01ff, 0x0197, 0x0050, 0x005d, 0x010d, 0x01b4, 0x020c, 0x0201, 0x0016, 0x004c, 0x01dc, 0x0207 }, + { 0x0121, MON_ALL, 0x003e, 0x0030, 0x0008, 0x0239, 0x0012, 0x0034, 0x0270, 0x0265, 0x002f, 0x007e, 0x020e, 0x026b }, + { 0x0122, MON_ALL, 0x00fe, 0x00cb, 0x0027, 0x000c, 0x006d, 0x00d8, 0x0270, 0x0265, 0x002f, 0x007e, 0x020e, 0x026b }, + { 0x0123, MON_ALL, 0x00fe, 0x00cb, 0x0027, 0x001c, 0x007d, 0x00d8, 0x0270, 0x0265, 0x002f, 0x007e, 0x020e, 0x026b }, + { 0x0124, MON_ALL, 0x00fe, 0x00cb, 0x0027, 0x002e, 0x008f, 0x00d8, 0x0270, 0x0265, 0x002f, 0x007e, 0x020e, 0x026b }, + { 0x0128, MON_ALL, 0x01fe, 0x0199, 0x0050, 0x03ef, 0x00a0, 0x01b2, 0x0270, 0x0265, 0x002f, 0x007e, 0x020e, 0x026b }, + { 0x0129, MON_ALL, 0x003e, 0x0030, 0x0008, 0x0002, 0x0020, 0x0034, 0x0270, 0x0265, 0x002f, 0x007e, 0x020e, 0x026b }, + { 0x012a, MON_ALL, 0x01fe, 0x0199, 0x0050, 0x004d, 0x00fe, 0x01b2, 0x0270, 0x0265, 0x002f, 0x007e, 0x020e, 0x026b }, + { 0x012b, MON_ALL, 0x01fe, 0x0199, 0x0050, 0x005d, 0x010e, 0x01b2, 0x0270, 0x0265, 0x002f, 0x007e, 0x020e, 0x026b }, + { 0x0141, MON_VGA, 0x003e, 0x0030, 0x0008, 0x0239, 0x0012, 0x0034, 0x020c, 0x0201, 0x0016, 0x0024, 0x0204, 0x0207 }, + { 0x0141, MON_ALL, 0x003e, 0x0030, 0x0008, 0x0232, 0x001b, 0x0034, 0x020c, 0x0201, 0x0016, 0x0024, 0x0204, 0x0207 }, + { 0x0142, MON_VGA, 0x00fe, 0x00c9, 0x0027, 0x000c, 0x006d, 0x00d8, 0x020c, 0x0201, 0x0016, 0x0024, 0x0204, 0x0207 }, + { 0x0142, MON_ALL, 0x00fe, 0x00c9, 0x0027, 0x02ec, 0x008d, 0x00d8, 0x020c, 0x0201, 0x0016, 0x0024, 0x0204, 0x0207 }, + { 0x0143, MON_VGA, 0x00fe, 0x00c9, 0x0027, 0x001c, 0x007d, 0x00d8, 0x020c, 0x0201, 0x0016, 0x0024, 0x0204, 0x0207 }, + { 0x0143, MON_ALL, 0x00fe, 0x00c9, 0x0027, 0x02fc, 0x009d, 0x00d8, 0x020c, 0x0201, 0x0016, 0x0024, 0x0204, 0x0207 }, + { 0x0144, MON_VGA, 0x00fe, 0x00c9, 0x0027, 0x002e, 0x008f, 0x00d8, 0x020c, 0x0201, 0x0016, 0x0024, 0x0204, 0x0207 }, + { 0x0144, MON_ALL, 0x00fe, 0x00c9, 0x0027, 0x000e, 0x00af, 0x00d8, 0x020c, 0x0201, 0x0016, 0x0024, 0x0204, 0x0207 }, + { 0x0148, MON_VGA, 0x01ff, 0x0197, 0x0050, 0x03f0, 0x009f, 0x01b4, 0x020c, 0x0201, 0x0016, 0x0024, 0x0204, 0x0207 }, + { 0x0148, MON_ALL, 0x01ff, 0x0197, 0x0050, 0x03b0, 0x00df, 0x01b4, 0x020c, 0x0201, 0x0016, 0x0024, 0x0204, 0x0207 }, + { 0x0149, MON_VGA, 0x003e, 0x0030, 0x0008, 0x023b, 0x001c, 0x0034, 0x020c, 0x0201, 0x0016, 0x0024, 0x0204, 0x0207 }, + { 0x0149, MON_ALL, 0x003e, 0x0030, 0x0008, 0x0237, 0x0020, 0x0034, 0x020c, 0x0201, 0x0016, 0x0024, 0x0204, 0x0207 }, + { 0x014a, MON_VGA, 0x01ff, 0x0197, 0x0050, 0x004d, 0x00fd, 0x01b4, 0x020c, 0x0201, 0x0016, 0x0024, 0x0204, 0x0207 }, + { 0x014a, MON_ALL, 0x01ff, 0x0197, 0x0050, 0x000d, 0x013d, 0x01b4, 0x020c, 0x0201, 0x0016, 0x0024, 0x0204, 0x0207 }, + { 0x014b, MON_VGA, 0x01ff, 0x0197, 0x0050, 0x005d, 0x010d, 0x01b4, 0x020c, 0x0201, 0x0016, 0x0024, 0x0204, 0x0207 }, + { 0x014b, MON_ALL, 0x01ff, 0x0197, 0x0050, 0x001d, 0x014d, 0x01b4, 0x020c, 0x0201, 0x0016, 0x0024, 0x0204, 0x0207 }, + { 0x0161, MON_VGA, 0x003e, 0x0030, 0x0008, 0x0239, 0x0012, 0x0034, 0x0270, 0x0265, 0x002f, 0x0056, 0x0236, 0x026b }, + { 0x0161, MON_ALL, 0x003e, 0x0030, 0x0008, 0x0232, 0x001b, 0x0034, 0x0270, 0x0265, 0x002f, 0x0056, 0x0236, 0x026b }, + { 0x0162, MON_VGA, 0x00fe, 0x00cb, 0x0027, 0x000c, 0x006d, 0x00d8, 0x0270, 0x0265, 0x002f, 0x0056, 0x0236, 0x026b }, + { 0x0162, MON_ALL, 0x00fe, 0x00cb, 0x0027, 0x02ec, 0x008d, 0x00d8, 0x0270, 0x0265, 0x002f, 0x0056, 0x0236, 0x026b }, + { 0x0163, MON_VGA, 0x00fe, 0x00cb, 0x0027, 0x001c, 0x007d, 0x00d8, 0x0270, 0x0265, 0x002f, 0x0056, 0x0236, 0x026b }, + { 0x0163, MON_ALL, 0x00fe, 0x00cb, 0x0027, 0x02fc, 0x009d, 0x00d8, 0x0270, 0x0265, 0x002f, 0x0056, 0x0236, 0x026b }, + { 0x0164, MON_VGA, 0x00fe, 0x00cb, 0x0027, 0x002e, 0x008f, 0x00d8, 0x0270, 0x0265, 0x002f, 0x0056, 0x0236, 0x026b }, + { 0x0164, MON_ALL, 0x00fe, 0x00cb, 0x0027, 0x000e, 0x00af, 0x00d8, 0x0270, 0x0265, 0x002f, 0x0056, 0x0236, 0x026b }, + { 0x0168, MON_VGA, 0x01fe, 0x0199, 0x0050, 0x03ef, 0x00a0, 0x01b2, 0x0270, 0x0265, 0x002f, 0x0056, 0x0236, 0x026b }, + { 0x0168, MON_ALL, 0x01fe, 0x0199, 0x0050, 0x03af, 0x00e0, 0x01b2, 0x0270, 0x0265, 0x002f, 0x0056, 0x0236, 0x026b }, + { 0x0169, MON_VGA, 0x003e, 0x0030, 0x0008, 0x023b, 0x001c, 0x0034, 0x0270, 0x0265, 0x002f, 0x0056, 0x0236, 0x026b }, + { 0x0169, MON_ALL, 0x003e, 0x0030, 0x0008, 0x0237, 0x0020, 0x0034, 0x0270, 0x0265, 0x002f, 0x0056, 0x0236, 0x026b }, + { 0x016a, MON_VGA, 0x01fe, 0x0199, 0x0050, 0x004d, 0x00fe, 0x01b2, 0x0270, 0x0265, 0x002f, 0x0056, 0x0236, 0x026b }, + { 0x016a, MON_ALL, 0x01fe, 0x0199, 0x0050, 0x000d, 0x013e, 0x01b2, 0x0270, 0x0265, 0x002f, 0x0056, 0x0236, 0x026b }, + { 0x016b, MON_VGA, 0x01fe, 0x0199, 0x0050, 0x005d, 0x010e, 0x01b2, 0x0270, 0x0265, 0x002f, 0x0056, 0x0236, 0x026b }, + { 0x016b, MON_ALL, 0x01fe, 0x0199, 0x0050, 0x001d, 0x014e, 0x01b2, 0x0270, 0x0265, 0x002f, 0x0056, 0x0236, 0x026b }, + { 0x0182, MON_ALL, 0x003e, 0x0032, 0x0009, 0x023f, 0x001c, 0x0034, 0x020d, 0x0201, 0x0016, 0x004d, 0x01dd, 0x0207 }, + { 0x0188, MON_MONO, 0x001a, 0x0000, 0x0000, 0x020f, 0x000c, 0x0014, 0x03e9, 0x0000, 0x0000, 0x0043, 0x0363, 0x03e7 }, + { 0x0188, MON_ALL, 0x01ff, 0x0197, 0x0050, 0x03f0, 0x009f, 0x01b4, 0x020c, 0x0201, 0x0016, 0x004c, 0x01dc, 0x0207 }, + { 0x0189, MON_ALL, 0x003e, 0x0032, 0x0009, 0x023f, 0x001c, 0x0034, 0x020d, 0x0201, 0x0016, 0x004d, 0x01dd, 0x0207 }, + { 0x01a2, MON_ALL, 0x003e, 0x0032, 0x0009, 0x023f, 0x001c, 0x0034, 0x0271, 0x0265, 0x002f, 0x006f, 0x01ff, 0x026b }, + { 0x01a8, MON_MONO, 0x001a, 0x0000, 0x0000, 0x020f, 0x000c, 0x0014, 0x03e9, 0x0000, 0x0000, 0x0043, 0x0363, 0x03e7 }, + { 0x01a8, MON_ALL, 0x01fe, 0x0199, 0x0050, 0x03ef, 0x00a0, 0x01b2, 0x0270, 0x0265, 0x002f, 0x007e, 0x020e, 0x026b }, + { 0x01a9, MON_ALL, 0x003e, 0x0032, 0x0009, 0x023f, 0x001c, 0x0034, 0x0271, 0x0265, 0x002f, 0x006f, 0x01ff, 0x026b }, + { 0x01c2, MON_ALL, 0x003e, 0x0032, 0x0009, 0x023f, 0x001c, 0x0034, 0x020d, 0x0201, 0x0016, 0x004d, 0x01dd, 0x0207 }, + { 0x01c8, MON_MONO, 0x001a, 0x0000, 0x0000, 0x020f, 0x000c, 0x0014, 0x03e9, 0x0000, 0x0000, 0x0043, 0x0363, 0x03e7 }, + { 0x01c8, MON_VGA, 0x01ff, 0x0197, 0x0050, 0x03f0, 0x009f, 0x01b4, 0x020c, 0x0201, 0x0016, 0x0024, 0x0204, 0x0207 }, + { 0x01c8, MON_ALL, 0x01ff, 0x0197, 0x0050, 0x03b0, 0x00df, 0x01b4, 0x020c, 0x0201, 0x0016, 0x0024, 0x0204, 0x0207 }, + { 0x01c9, MON_ALL, 0x003e, 0x0032, 0x0009, 0x023f, 0x001c, 0x0034, 0x020d, 0x0201, 0x0016, 0x004d, 0x01dd, 0x0207 }, + { 0x01e2, MON_ALL, 0x003e, 0x0032, 0x0009, 0x023f, 0x001c, 0x0034, 0x0271, 0x0265, 0x002f, 0x006f, 0x01ff, 0x026b }, + { 0x01e8, MON_MONO, 0x001a, 0x0000, 0x0000, 0x020f, 0x000c, 0x0014, 0x03e9, 0x0000, 0x0000, 0x0043, 0x0363, 0x03e7 }, + { 0x01e8, MON_VGA, 0x01fe, 0x0199, 0x0050, 0x03ef, 0x00a0, 0x01b2, 0x0270, 0x0265, 0x002f, 0x0056, 0x0236, 0x026b }, + { 0x01e8, MON_ALL, 0x01fe, 0x0199, 0x0050, 0x03af, 0x00e0, 0x01b2, 0x0270, 0x0265, 0x002f, 0x0056, 0x0236, 0x026b }, + { 0x01e9, MON_ALL, 0x003e, 0x0032, 0x0009, 0x023f, 0x001c, 0x0034, 0x0271, 0x0265, 0x002f, 0x006f, 0x01ff, 0x026b }, + { -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } +}; + +void set_palette(uint16_t *colorptr) +{ + int i; + uint16_t *palette_regs = (uint16_t *) 0xffff9800; + + do + { + *palette_regs++ = *colorptr++; + } while (palette_regs < 0xffff9600 + 16 * 2); +} + +/* + * functions for VIDEL programming + */ + +static uint16_t get_videl_bpp(void) +{ + uint16_t f_shift = *(volatile uint16_t *)SPSHIFT; + uint8_t st_shift = *(volatile uint8_t *)ST_SHIFTER; + /* to get bpp, we must examine f_shift and st_shift. + * f_shift is valid if any of bits no. 10, 8 or 4 + * is set. Priority in f_shift is: 10 ">" 8 ">" 4, i.e. + * if bit 10 set then bit 8 and bit 4 don't care... + * If all these bits are 0 get display depth from st_shift + * (as for ST and STe) + */ + int bits_per_pixel = 1; + if (f_shift & 0x400) /* 2 colors */ + bits_per_pixel = 1; + else if (f_shift & 0x100) /* hicolor */ + bits_per_pixel = 16; + else if (f_shift & 0x010) /* 8 bitplanes */ + bits_per_pixel = 8; + else if (st_shift == 0) + bits_per_pixel = 4; + else if (st_shift == 0x1) + bits_per_pixel = 2; + else /* if (st_shift == 0x2) */ + bits_per_pixel = 1; + + return bits_per_pixel; +} + +static uint16_t get_videl_width(void) +{ + return (*(volatile uint16_t *)0xffff8210) * 16 / get_videl_bpp(); +} + +static uint16_t get_videl_height(void) +{ + uint16_t vdb = *(volatile uint16_t *)0xffff82a8; + uint16_t vde = *(volatile uint16_t *)0xffff82aa; + uint16_t vmode = *(volatile uint16_t *)0xffff82c2; + + /* visible y resolution: + * Graphics display starts at line VDB and ends at line + * VDE. If interlace mode off unit of VC-registers is + * half lines, else lines. + */ + uint16_t yres = vde - vdb; + if (!(vmode & 0x02)) /* interlace */ + yres >>= 1; + if (vmode & 0x01) /* double */ + yres >>= 1; + + return yres; +} + + +/* + * lookup videl initialisation data for specified mode/monitor + * returns NULL if mode/monitor combination is invalid + */ +const VMODE_ENTRY *lookup_videl_mode(int16_t mode,int16_t monitor) +{ + const VMODE_ENTRY *vmode_init_table, *p; + + if (mode&VIDEL_VGA) { + vmode_init_table = vga_init_table; + /* ignore bits that don't affect initialisation data */ + mode &= ~(VIDEL_VERTICAL|VIDEL_PAL); + } else { + vmode_init_table = nonvga_init_table; + } + + for (p = vmode_init_table; p->vmode >= 0; p++) + if (p->vmode == mode) + if ((p->monitor == MON_ALL) || (p->monitor == monitor)) + return p; + + return NULL; +} + + +/* + * determine scanline width based on video mode + */ +static int16_t determine_width(int16_t mode) +{ + int16_t linewidth; + + linewidth = (mode&VIDEL_80COL) ? 40 : 20; + linewidth <<= (mode & VIDEL_BPPMASK); + if (mode&VIDEL_OVERSCAN) + linewidth = linewidth * 12 / 10; /* multiply by 1.2 */ + + return linewidth; +} + + +/* + * determine vctl based on video mode and monitor type + */ +static int16_t determine_vctl(int16_t mode,int16_t monitor) +{ + int16_t vctl; + + if (mode&VIDEL_VGA) { + vctl = (mode&VIDEL_80COL) ? 0x08 : 0x04; + if (mode&VIDEL_VERTICAL) + vctl |= 0x01; + } else { + vctl = (mode&VIDEL_80COL) ? 0x04 : 0x00; + if (mode&VIDEL_VERTICAL) + vctl |= 0x02; + } + + if (!(mode&VIDEL_COMPAT)) + return vctl; + + switch(mode&VIDEL_BPPMASK) { + case VIDEL_1BPP: + if (!(mode&VIDEL_VGA) && (monitor == MON_MONO)) + vctl = 0x08; + break; + case VIDEL_2BPP: + vctl = (mode&VIDEL_VGA)? 0x09 : 0x04; + break; + case VIDEL_4BPP: + vctl = (mode&VIDEL_VGA)? 0x05 : 0x00; + break; + } + + return vctl; +} + + +/* + * determine regc0 based on video mode & monitor type + */ +static int16_t determine_regc0(int16_t mode,int16_t monitor) +{ + if (mode&VIDEL_VGA) + return 0x0186; + + if (!(mode&VIDEL_COMPAT)) + return (monitor==MON_TV)?0x0183:0x0181; + + /* handle ST-compatible modes */ + if ((mode&(VIDEL_80COL|VIDEL_BPPMASK)) == (VIDEL_80COL|VIDEL_1BPP)) { /* 80-column, 2-colour */ + switch(monitor) { + case MON_MONO: + return 0x0080; + case MON_TV: + return 0x0183; + default: + return 0x0181; + } + } + + return (monitor==MON_TV)?0x0083:0x0081; +} + + +/* + * this routine can set VIDEL to 1,2,4 or 8 bitplanes mode on VGA + */ +static int set_videl_vga(int16_t mode) +{ + volatile char *videlregs = (char *)0xffff8200; +#define videlword(n) (*(volatile uint16_t *)(videlregs+(n))) + const VMODE_ENTRY *p; + int16_t linewidth, monitor, vctl; + + monitor = vmontype(); + + p = lookup_videl_mode(mode,monitor);/* validate mode */ + if (!p) + return -1; + + videlregs[0x0a] = (mode&VIDEL_PAL) ? 2 : 0; /* video sync to 50Hz if PAL */ + + // FIXME: vsync() can't work if the screen is initially turned off + //vsync(); /* wait for vbl so we're not interrupted :-) */ + + videlword(0x82) = p->hht; /* H hold timer */ + videlword(0x84) = p->hbb; /* H border begin */ + videlword(0x86) = p->hbe; /* H border end */ + videlword(0x88) = p->hdb; /* H display begin */ + videlword(0x8a) = p->hde; /* H display end */ + videlword(0x8c) = p->hss; /* H SS */ + + videlword(0xa2) = p->vft; /* V freq timer */ + videlword(0xa4) = p->vbb; /* V border begin */ + videlword(0xa6) = p->vbe; /* V border end */ + videlword(0xa8) = p->vdb; /* V display begin */ + videlword(0xaa) = p->vde; /* V display end */ + videlword(0xac) = p->vss; /* V SS */ + + videlregs[0x60] = 0x00; /* clear ST shift for safety */ + + videlword(0x0e) = 0; /* offset */ + + linewidth = determine_width(mode); + vctl = determine_vctl(mode,monitor); + + videlword(0x10) = linewidth; /* scanline width */ + videlword(0xc2) = vctl; /* video control */ + videlword(0xc0) = determine_regc0(mode,monitor); + videlword(0x66) = 0x0000; /* clear SPSHIFT */ + + switch(mode&VIDEL_BPPMASK) { /* set SPSHIFT / ST shift */ + case VIDEL_1BPP: /* 2 colours (mono) */ + if (monitor == MON_MONO) + videlregs[0x60] = 0x02; + else videlword(0x66) = 0x0400; + break; + case VIDEL_2BPP: /* 4 colours */ + videlregs[0x60] = 0x01; + videlword(0x10) = linewidth; /* writing to the ST shifter has */ + videlword(0xc2) = vctl; /* just overwritten these registers */ + break; + case VIDEL_4BPP: /* 16 colours */ + /* if not ST-compatible, SPSHIFT was already set correctly above */ + if (mode&VIDEL_COMPAT) + videlregs[0x60] = 0x00; /* else set ST shifter */ + break; + case VIDEL_8BPP: /* 256 colours */ + videlword(0x66) = 0x0010; + break; + case VIDEL_TRUECOLOR: /* 65536 colours (Truecolor) */ + videlword(0x66) = 0x0100; + break; + } + + return 0; +} + +/* + * the current Falcon video mode; used by vsetmode() & vfixmode() + */ +int16_t current_video_mode; + +/* + * Set Falcon video mode + */ +int16_t vsetmode(int16_t mode) +{ + int16_t ret; + + if (mode == -1) + return current_video_mode; + +#if DBG_VIDEL + kprintf("vsetmode(0x%04x)\n", mode); +#endif + + if (set_videl_vga(mode) < 0) /* invalid mode */ + return current_video_mode; + + ret = current_video_mode; + current_video_mode = mode; + + return ret; +} + +/* + * Get Videl monitor type + */ +int16_t vmontype(void) +{ + return ((*(volatile uint8_t *)0xffff8006) >> 6) & 3; +} + +/* + * Set external video sync mode + */ +int16_t vsetsync(int16_t external) +{ + uint16_t spshift; + + if (external & 0x01) /* external clock wanted? */ + *(volatile int8_t *)SYNCMODE |= 0x01; + else *(volatile int8_t *)SYNCMODE &= 0xfe; + + spshift = *(volatile uint16_t *)SPSHIFT; + + if (external&0x02) /* external vertical sync wanted? */ + spshift |= 0x0020; + else spshift &= 0xffdf; + + if (external&0x04) /* external horizontal sync wanted? */ + spshift |= 0x0040; + else spshift &= 0xffbf; + + *(volatile uint16_t *)SPSHIFT = spshift; + + return 0; /* OK */ +} + +/* + * get video ram size according to mode + */ +int32_t vgetsize(int16_t mode) +{ + const VMODE_ENTRY *p; + int height; + int16_t vctl, monitor; + + monitor = vmontype(); + + mode &= VIDEL_VALID; /* ignore invalid bits */ + if ((mode&VIDEL_BPPMASK) > VIDEL_TRUECOLOR) { /* fixup invalid bpp */ + mode &= ~VIDEL_BPPMASK; + mode |= VIDEL_TRUECOLOR; + } + + p = lookup_videl_mode(mode,monitor); + if (!p) { /* invalid mode */ + if (mode&VIDEL_COMPAT) + return ST_VRAM_SIZE; + mode &= ~(VIDEL_OVERSCAN|VIDEL_PAL);/* ignore less-important bits */ + p = lookup_videl_mode(mode,monitor);/* & try again */ + if (!p) /* "can't happen" */ + return FALCON_VRAM_SIZE; + } + + vctl = determine_vctl(mode,monitor); + height = p->vde - p->vdb; + if (!(vctl&0x02)) + height >>= 1; + if (vctl&0x01) + height >>= 1; + + return (int32_t)determine_width(mode) * 2 * height; +} + +/* + * convert from Falcon palette format to STe palette format + */ +#define falc2ste(a) ((((a)>>1)&0x08)|(((a)>>5)&0x07)) +static void convert2ste(int16_t *ste,int32_t *falcon) +{ + union { + int32_t l; + uint8_t b[4]; + } u; + int i; + + for (i = 0; i < 16; i++) { + u.l = *falcon++; + *ste++ = (falc2ste(u.b[0])<<8) | (falc2ste(u.b[1])<<4) | falc2ste(u.b[3]); + } +} + +/* + * determine whether to update STe or Falcon h/w palette registers + * returns true if we need to update the STe h/w palette + */ +static int use_ste_palette(int16_t videomode) +{ + if (vmontype() == MON_MONO) /* always for ST mono monitor */ + return true; + + if ((videomode&VIDEL_BPPMASK) == VIDEL_2BPP) /* always for 4-colour modes */ + return true; + + if ((videomode&VIDEL_COMPAT) && ((videomode&VIDEL_BPPMASK) == VIDEL_4BPP)) + return true; /* and for ST low */ + + return false; +} + +/* + * set palette registers + * + * note that the actual update of the hardware registers is done by the + * VBL interrupt handler, according to the setting of 'colorptr'. since + * the address in colorptr must be even, we use bit 0 as a flag. + * + * colorptr contents VBL interrupt handler action + * ----------------- ---------------------------- + * 0 do nothing + * address load STe palette regs from address + * address | 0x01 load first 16 Falcon palette regs from address + * 0 | 0x01 load 256 Falcon palette regs from falcon_shadow_palette[] + */ +int16_t vsetrgb(int16_t index,int16_t count,int32_t *rgb) +{ + int32_t *shadow, *source; + union { + int32_t l; + uint8_t b[4]; + } u; + int16_t limit; + + if ((index < 0) || (count <= 0)) + return -1; /* Generic error */ + + limit = (get_videl_bpp()<=4) ? 16 : 256; + if ((index+count) > limit) + return -1; /* Generic error */ + + /* + * we always update the Falcon shadow palette, since that's + * what we'll return for VgetRGB() + */ + shadow = falcon_shadow_palette + index; + source = rgb; + while(count--) { + u.l = *source++; + u.b[0] = u.b[1]; /* shift R & G */ + u.b[1] = u.b[2]; + u.b[2] = 0x00; + *shadow++ = u.l; + } + + /* + * for ST low or 4-colour modes, we need to convert the + * Falcon shadow registers to STe palette register format, and + * request the VBL interrupt handler to update the STe palette + * registers rather than the Falcon registers + */ + if (use_ste_palette(vsetmode(-1))) { + convert2ste(ste_shadow_palette, falcon_shadow_palette); + colorptr = ste_shadow_palette; + + + return 0; /* OK */ + } + + colorptr = (limit==256) ? (int16_t *) 0x01L : (int16_t *) ((int32_t) falcon_shadow_palette|0x01L); + + set_palette(colorptr); + return 0; /* OK */ +} + +/* + * get palette registers + */ +int16_t vgetrgb(int16_t index,int16_t count,int32_t *rgb) +{ + int32_t *shadow; + union { + int32_t l; + uint8_t b[4]; + } u; + int16_t limit; + + if ((index < 0) || (count <= 0)) + return -1; /* Generic error */ + + limit = (get_videl_bpp()<=4) ? 16 : 256; + if ((index+count) > limit) + return -1; /* Generic error */ + + shadow = falcon_shadow_palette + index; + while(count--) { + u.l = *shadow++; + u.b[2] = u.b[1]; /* shift R & G right*/ + u.b[1] = u.b[0]; + u.b[0] = 0x00; + *rgb++ = u.l; + } + + return 0; /* OK */ +} + +/* + * Fix Videl mode + * + * This converts an (assumed legal) input mode into the + * corresponding output mode for the current monitor type + */ +int16_t vfixmode(int16_t mode) +{ + int16_t monitor, currentmode; + + monitor = vmontype(); + if (monitor == MON_MONO) + return FALCON_ST_HIGH; + + currentmode = vsetmode(-1); + if (currentmode & VIDEL_PAL) /* set PAL bit per current value */ + mode |= VIDEL_PAL; + else mode &= ~VIDEL_PAL; + + /* handle VGA monitor */ + if (monitor == MON_VGA) { + mode &= ~VIDEL_OVERSCAN; /* turn off overscan (not used with VGA) */ + if (!(mode & VIDEL_VGA)) /* if mode doesn't have VGA set, */ + mode ^= (VIDEL_VERTICAL | VIDEL_VGA); /* set it & flip vertical */ + if (mode & VIDEL_COMPAT) { + if ((mode&VIDEL_BPPMASK) == VIDEL_1BPP) + mode &= ~VIDEL_VERTICAL; /* clear vertical for ST high */ + else mode |= VIDEL_VERTICAL; /* set it for ST medium, low */ + } + return mode; + } + + /* handle RGB or TV */ + if (mode & VIDEL_VGA) /* if mode has VGA set, */ + mode ^= (VIDEL_VERTICAL | VIDEL_VGA); /* clear it & flip vertical */ + if (mode & VIDEL_COMPAT) { + if ((mode&VIDEL_BPPMASK) == VIDEL_1BPP) + mode |= VIDEL_VERTICAL; /* set vertical for ST high */ + else mode &= ~VIDEL_VERTICAL; /* clear it for ST medium, low */ + } + + return mode; +} + +int16_t videl_check_moderez(int16_t moderez) +{ + int16_t current_mode, return_mode; + + if (moderez < 0) /* ignore rez values */ + return 0; + + current_mode = get_videl_mode(); + return_mode = vfixmode(moderez);/* adjust */ + return (return_mode==current_mode)?0:return_mode; +} + +uint32_t videl_vram_size(void) +{ + return get_videl_width() / 8L * get_videl_height() * get_videl_bpp(); +} + +void videl_get_current_mode_info(uint16_t *planes, uint16_t *hz_rez, uint16_t *vt_rez) +{ + *planes = get_videl_bpp(); + *hz_rez = get_videl_width(); + *vt_rez = get_videl_height(); +} + +/* + * Initialise Falcon palette + */ +void initialise_falcon_palette(int16_t mode) +{ + volatile int16_t *col_regs = (int16_t *) ST_PALETTE_REGS; + volatile int32_t *fcol_regs = (int32_t *) FALCON_PALETTE_REGS; + int i, limit; + + /* first, set up Falcon shadow palette and real registers */ + for (i = 0; i < 256; i++) + falcon_shadow_palette[i] = videl_dflt_palette[i]; + + switch(mode&VIDEL_BPPMASK) { + case VIDEL_1BPP: /* 2-colour mode */ + falcon_shadow_palette[1] = falcon_shadow_palette[15]; + break; + case VIDEL_2BPP: /* 4-colour mode */ + falcon_shadow_palette[3] = falcon_shadow_palette[15]; + break; + } + + /* a 'feature' of the Falcon hardware: if we're in a mode with less + * than 256 colours, and we attempt to set the Falcon hardware + * palette registers for colours 16 & above, it will screw up the + * values in the first 16 hardware palette registers, resulting in + * a messed-up display ... + * NOTE: what happens in the Truecolor case is yet to be determined, + * although it is probably not important since we don't use those + * registers. + */ + limit = ((mode&VIDEL_BPPMASK)==VIDEL_8BPP) ? 256 : 16; + for (i = 0; i < limit; i++) + fcol_regs[i] = falcon_shadow_palette[i]; + + /* + * if appropriate, set up the STe shadow & real palette registers + */ + if (use_ste_palette(mode)) { + convert2ste(ste_shadow_palette,falcon_shadow_palette); + for (i = 0; i < 16; i++) + col_regs[i] = ste_shadow_palette[i]; + } +} + +/* + * Get videl mode + * This is the same as vsetmode(-1) except that it returns + * zero when there is no videl. Used by app_save(). + */ +int16_t get_videl_mode(void) +{ + return vsetmode(-1); +} + diff --git a/video/video.c b/video/video.c new file mode 100644 index 0000000..d1a46fb --- /dev/null +++ b/video/video.c @@ -0,0 +1,263 @@ +#include "video.h" +#include "videl.h" +#include "screen.h" + +#define MON_ALL -1 /* code used in VMODE_ENTRY for match on mode only */ + +/* + * tables that cover all(?) valid Falcon modes + * note: + * . 256-colour and Truecolor modes are not currently supported by the VDI + */ +static const VMODE_ENTRY vga_init_table[] = { + /* the entries in this table are for VGA/NTSC (i.e. VGA 60Hz) and VGA/PAL + * (i.e. VGA 50Hz). in *this* table, each entry applies to four video modes: + * mode, mode|VIDEL_VERTICAL, mode|VIDEL_PAL, mode|VIDEL_VERTICAL|VIDEL_PAL + */ + { 0x0011, MON_ALL, 0x0017, 0x0012, 0x0001, 0x020a, 0x0009, 0x0011, 0x0419, 0x03ff, 0x003f, 0x003f, 0x03ff, 0x0415 }, + { 0x0012, MON_ALL, 0x00c6, 0x008d, 0x0015, 0x028a, 0x006b, 0x0096, 0x0419, 0x03ff, 0x003f, 0x003f, 0x03ff, 0x0415 }, + { 0x0013, MON_ALL, 0x00c6, 0x008d, 0x0015, 0x029a, 0x007b, 0x0096, 0x0419, 0x03ff, 0x003f, 0x003f, 0x03ff, 0x0415 }, + { 0x0014, MON_ALL, 0x00c6, 0x008d, 0x0015, 0x02ac, 0x0091, 0x0096, 0x0419, 0x03ff, 0x003f, 0x003f, 0x03ff, 0x0415 }, + { 0x0018, MON_ALL, 0x00c6, 0x008d, 0x0015, 0x0273, 0x0050, 0x0096, 0x0419, 0x03ff, 0x003f, 0x003f, 0x03ff, 0x0415 }, + { 0x0019, MON_ALL, 0x0017, 0x0012, 0x0001, 0x020e, 0x000d, 0x0011, 0x0419, 0x03ff, 0x003f, 0x003f, 0x03ff, 0x0415 }, + { 0x001a, MON_ALL, 0x00c6, 0x008d, 0x0015, 0x02a3, 0x007c, 0x0096, 0x0419, 0x03ff, 0x003f, 0x003f, 0x03ff, 0x0415 }, + { 0x001b, MON_ALL, 0x00c6, 0x008d, 0x0015, 0x02ab, 0x0084, 0x0096, 0x0419, 0x03ff, 0x003f, 0x003f, 0x03ff, 0x0415 }, + { 0x0092, MON_ALL, 0x0017, 0x0012, 0x0001, 0x020e, 0x000d, 0x0011, 0x0419, 0x03af, 0x008f, 0x008f, 0x03af, 0x0415 }, + { 0x0098, MON_ALL, 0x00c6, 0x008d, 0x0015, 0x0273, 0x0050, 0x0096, 0x0419, 0x03af, 0x008f, 0x008f, 0x03af, 0x0415 }, + { 0x0099, MON_ALL, 0x0017, 0x0012, 0x0001, 0x020e, 0x000d, 0x0011, 0x0419, 0x03af, 0x008f, 0x008f, 0x03af, 0x0415 }, + { -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } +}; + +/* + * Initialise palette registers + * This routine is also used by resolution change + */ +void initialise_palette_registers(int16_t rez,int16_t mode) +{ + int16_t mask; + + mask = 0x0fff; + initialise_falcon_palette(mode); +} + + +/* + * determine regc0 based on video mode & monitor type + */ +static int16_t determine_regc0(int16_t mode, int16_t monitor) +{ + if (mode&VIDEL_VGA) + return 0x0186; + + if (!(mode&VIDEL_COMPAT)) + return (monitor==MON_TV)?0x0183:0x0181; + + /* handle ST-compatible modes */ + if ((mode&(VIDEL_80COL|VIDEL_BPPMASK)) == (VIDEL_80COL|VIDEL_1BPP)) { /* 80-column, 2-colour */ + switch(monitor) { + case MON_MONO: + return 0x0080; + case MON_TV: + return 0x0183; + default: + return 0x0181; + } + } + + return (monitor==MON_TV)?0x0083:0x0081; +} + +/* + * determine vctl based on video mode and monitor type + */ +static int16_t determine_vctl(int16_t mode,int16_t monitor) +{ + int16_t vctl; + + if (mode&VIDEL_VGA) { + vctl = (mode&VIDEL_80COL) ? 0x08 : 0x04; + if (mode&VIDEL_VERTICAL) + vctl |= 0x01; + } else { + vctl = (mode&VIDEL_80COL) ? 0x04 : 0x00; + if (mode&VIDEL_VERTICAL) + vctl |= 0x02; + } + + if (!(mode&VIDEL_COMPAT)) + return vctl; + + switch(mode&VIDEL_BPPMASK) { + case VIDEL_1BPP: + if (!(mode&VIDEL_VGA) && (monitor == MON_MONO)) + vctl = 0x08; + break; + case VIDEL_2BPP: + vctl = (mode&VIDEL_VGA)? 0x09 : 0x04; + break; + case VIDEL_4BPP: + vctl = (mode&VIDEL_VGA)? 0x05 : 0x00; + break; + } + + return vctl; +} + + +/* + * determine scanline width based on video mode + */ +static int16_t determine_width(int16_t mode) +{ + int16_t linewidth; + + linewidth = (mode&VIDEL_80COL) ? 40 : 20; + linewidth <<= (mode & VIDEL_BPPMASK); + if (mode&VIDEL_OVERSCAN) + linewidth = linewidth * 12 / 10; /* multiply by 1.2 */ + + return linewidth; +} + +static int set_videl_vga(int16_t mode) +{ + volatile char *videlregs = (char *)0xffff8200; +#define videlword(n) (*(volatile uint16_t *)(videlregs+(n))) + const VMODE_ENTRY *p; + int16_t linewidth, monitor, vctl; + + monitor = vmontype(); + + p = lookup_videl_mode(mode,monitor);/* validate mode */ + if (!p) + return -1; + + videlregs[0x0a] = (mode&VIDEL_PAL) ? 2 : 0; /* video sync to 50Hz if PAL */ + + // FIXME: vsync() can't work if the screen is initially turned off + //vsync(); /* wait for vbl so we're not interrupted :-) */ + + videlword(0x82) = p->hht; /* H hold timer */ + videlword(0x84) = p->hbb; /* H border begin */ + videlword(0x86) = p->hbe; /* H border end */ + videlword(0x88) = p->hdb; /* H display begin */ + videlword(0x8a) = p->hde; /* H display end */ + videlword(0x8c) = p->hss; /* H SS */ + + videlword(0xa2) = p->vft; /* V freq timer */ + videlword(0xa4) = p->vbb; /* V border begin */ + videlword(0xa6) = p->vbe; /* V border end */ + videlword(0xa8) = p->vdb; /* V display begin */ + videlword(0xaa) = p->vde; /* V display end */ + videlword(0xac) = p->vss; /* V SS */ + + videlregs[0x60] = 0x00; /* clear ST shift for safety */ + + videlword(0x0e) = 0; /* offset */ + + linewidth = determine_width(mode); + vctl = determine_vctl(mode,monitor); + + videlword(0x10) = linewidth; /* scanline width */ + videlword(0xc2) = vctl; /* video control */ + videlword(0xc0) = determine_regc0(mode,monitor); + videlword(0x66) = 0x0000; /* clear SPSHIFT */ + + switch(mode&VIDEL_BPPMASK) { /* set SPSHIFT / ST shift */ + case VIDEL_1BPP: /* 2 colours (mono) */ + if (monitor == MON_MONO) + videlregs[0x60] = 0x02; + else videlword(0x66) = 0x0400; + break; + case VIDEL_2BPP: /* 4 colours */ + videlregs[0x60] = 0x01; + videlword(0x10) = linewidth; /* writing to the ST shifter has */ + videlword(0xc2) = vctl; /* just overwritten these registers */ + break; + case VIDEL_4BPP: /* 16 colours */ + /* if not ST-compatible, SPSHIFT was already set correctly above */ + if (mode&VIDEL_COMPAT) + videlregs[0x60] = 0x00; /* else set ST shifter */ + break; + case VIDEL_8BPP: /* 256 colours */ + videlword(0x66) = 0x0010; + break; + case VIDEL_TRUECOLOR: /* 65536 colours (Truecolor) */ + videlword(0x66) = 0x0100; + break; + } + + return 0; +} + +int16_t current_video_mode; + +/* Set physical screen address */ + +static void setphys(int32_t addr,int checkaddr) +{ + *(volatile uint8_t *) VIDEOBASE_ADDR_HI = ((uint32_t) addr) >> 16; + *(volatile uint8_t *) VIDEOBASE_ADDR_MID = ((uint32_t) addr) >> 8; + *(volatile uint8_t *) VIDEOBASE_ADDR_LOW = ((uint32_t) addr); +} + +/* + * In the original TOS there used to be an early screen init, + * before memory configuration. This is not used here, and all is + * done at the same time from C. + */ + +void screen_init(void) +{ + uint32_t screen_start; + uint16_t boot_resolution = FALCON_DEFAULT_BOOT; + int16_t monitor_type, sync_mode; + int16_t rez = 0; /* avoid 'may be uninitialized' warning */ + + /* Initialize the interrupt handlers. + * It is important to do this first because the initialization code below + * may call vsync(), which temporarily enables the interrupts. */ + + /* TODO: VEC_HBL = int_hbl; */ + /* TODO: VEC_VBL = int_vbl; */ + +/* + * first, see what we're connected to, and set the + * resolution / video mode appropriately + */ + monitor_type = MON_COLOR; + xprintf("monitor_type = %d\n", monitor_type); + + /* reset VIDEL on boot-up */ + /* first set the physbase to a safe memory */ + setphys(0xd00000,0); + + if (!lookup_videl_mode(boot_resolution, monitor_type)) { /* mode isn't in table */ + xprintf("Invalid video mode 0x%04x changed to 0x%04x\n", + boot_resolution, FALCON_DEFAULT_BOOT); + boot_resolution = FALCON_DEFAULT_BOOT; /* so pick one that is */ + } + + if (!VALID_VDI_BPP(boot_resolution)) { /* mustn't confuse VDI */ + xprintf("VDI doesn't support video mode 0x%04x, changed to 0x%04x\n", + boot_resolution, FALCON_DEFAULT_BOOT); + boot_resolution = FALCON_DEFAULT_BOOT; /* so use default */ + } + + vsetmode(boot_resolution); + rez = FALCON_REZ; /* fake value indicates Falcon/Videl */ + sync_mode = (boot_resolution & VIDEL_PAL) ? 0x02 : 0x00; + *(volatile uint8_t *) SYNCMODE = sync_mode; + + /* + * next, set up the palette(s) + */ + initialise_palette_registers(rez, boot_resolution); + /* FIXME: sshiftmod = rez; */ + + /* videoram is placed just below the phystop */ + screen_start = 0xd00000; + + /* correct physical address */ + setphys(screen_start, 1); +}