From 656065553ff18b2709bffb23110cd978b3db0f39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Fr=C3=B6schle?= Date: Fri, 18 Nov 2016 17:00:04 +0000 Subject: [PATCH] first (crude) implementation for Radeon console output --- BaS_gcc.files | 2 + BaS_gcc.includes | 110 +++++----- Makefile | 3 + bas.lk.in | 1 + include/conout.h | 63 ++++++ include/font.h | 2 + util/conout.c | 561 +++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 687 insertions(+), 55 deletions(-) create mode 100755 include/conout.h create mode 100755 util/conout.c diff --git a/BaS_gcc.files b/BaS_gcc.files index cc3c18b..1e4871a 100644 --- a/BaS_gcc.files +++ b/BaS_gcc.files @@ -893,3 +893,5 @@ tos/Makefile radeon/radeon_i2c.c basflash.lk.in radeon/i2c-algo-bit.c +util/conout.c +include/conout.h diff --git a/BaS_gcc.includes b/BaS_gcc.includes index a0aa337..edd3421 100644 --- a/BaS_gcc.includes +++ b/BaS_gcc.includes @@ -1,55 +1,55 @@ -include -tos/jtagwait/include -tos/pci_test/include -/usr/m68k-atari-mint/include -/opt/cross-mint/m68k-atari-mint/include -/opt/gygwin/opt/cross-mint/m68k-atari-mint/include -/opt/m68k-elf/include -/opt/cygwin/opt/m68k-elf/include -/opt/cygwin/opt/m68k-elf/lib/gcc/m68k-elf/4.6.4/include -dma -m54455 -sys -pci -tos/pci_test -tos/jtagwait/m5475/mshort -m5484lite -tos/pci_test/include -tos/bascook -tos/vmem_test/m5475/mshort -i2c -fs -tos/vmem_test/m5475 -tos/pci_test/m5475 -spi -if -tos/jtagwait/m5475 -util -kbd -flash_scripts -video -usb -exe -tos/vmem_test/sources -tos -nutil -tos/jtagwait/sources -x86emu -flash -tos/vmem_test/include -tos/bascook/sources -tos/pci_test/m5475/mshort -. -radeon -net -xhdi -tos/vmem_test -tos/pci_test/sources -firebee -tos/jtagwait -tos/fpga_test/include -tos/fpga_test -tos/fpga_test/sources -tos/pci_mem -tos/pci_mem/include -tos/pci_mem/sources +include +tos/jtagwait/include +tos/pci_test/include +/usr/m68k-atari-mint/include +/opt/cross-mint/m68k-atari-mint/include +/opt/gygwin/opt/cross-mint/m68k-atari-mint/include +/opt/m68k-elf/include +/opt/cygwin/opt/m68k-elf/include +/opt/cygwin/opt/m68k-elf/lib/gcc/m68k-elf/4.6.4/include +dma +m54455 +sys +pci +tos/pci_test +tos/jtagwait/m5475/mshort +m5484lite +tos/pci_test/include +tos/bascook +tos/vmem_test/m5475/mshort +i2c +fs +tos/vmem_test/m5475 +tos/pci_test/m5475 +spi +if +tos/jtagwait/m5475 +util +kbd +flash_scripts +video +usb +exe +tos/vmem_test/sources +tos +nutil +tos/jtagwait/sources +x86emu +flash +tos/vmem_test/include +tos/bascook/sources +tos/pci_test/m5475/mshort +. +radeon +net +xhdi +tos/vmem_test +tos/pci_test/sources +firebee +tos/jtagwait +tos/fpga_test/include +tos/fpga_test +tos/fpga_test/sources +tos/pci_mem +tos/pci_mem/include +tos/pci_mem/sources diff --git a/Makefile b/Makefile index 478cdc7..3970dbf 100644 --- a/Makefile +++ b/Makefile @@ -87,8 +87,11 @@ CSRCS= \ init_fpga.c \ fault_vectors.c \ interrupts.c \ + \ bas_printf.c \ bas_string.c \ + conout.c \ + \ BaS.c \ cache.c \ mmu.c \ diff --git a/bas.lk.in b/bas.lk.in index 93dc890..d0b01b8 100644 --- a/bas.lk.in +++ b/bas.lk.in @@ -82,6 +82,7 @@ SECTIONS OBJDIR/s19reader.o(.text) OBJDIR/bas_printf.o(.text) OBJDIR/bas_string.o(.text) + OBJDIR/conout.o(.text) #if (FORMAT_ELF == 1) OBJDIR/libgcc_helper.o(.text) #endif diff --git a/include/conout.h b/include/conout.h new file mode 100755 index 0000000..1785948 --- /dev/null +++ b/include/conout.h @@ -0,0 +1,63 @@ +#ifndef __CONOUT_H__ +#define __CONOUT_H__ + +#include "bas_types.h" + +/* + * conout.h - lowlevel color model dependent screen handling routines + * + * + * Copyright (C) 2004-2016 by Authors: + * + * Authors: + * MAD Martin Doering + * + * This file is distributed under the GPL, version 2 or at your + * option any later version. See doc/license.txt for details. + */ + + + +/* Defines for cursor */ +#define M_CFLASH 0x0001 /* cursor flash 0:disabled 1:enabled */ +#define M_CSTATE 0x0002 /* cursor flash state 0:off 1:on */ +#define M_CVIS 0x0004 /* cursor visibility 0:invisible 1:visible */ + +/* + * The visibility flag is also used as a semaphore to prevent + * the interrupt-driven cursor blink logic from colliding with + * escape function/sequence cursor drawing activity. + */ + +#define M_CEOL 0x0008 /* end of line handling 0:overwrite 1:wrap */ +#define M_REVID 0x0010 /* reverse video 0:on 1:off */ +#define M_SVPOS 0x0020 /* position saved flag. 0:false, 1:true */ +#define M_CRIT 0x0040 /* reverse video 0:on 1:off */ + +/* Color related linea variables */ + +extern int16_t v_col_bg; /* current background color */ +extern int16_t v_col_fg; /* current foreground color */ + +/* Cursor related linea variables */ + +extern uint8_t *v_cur_ad; /* current cursor address */ +extern int16_t v_cur_of; /* cursor offset */ +extern int8_t v_cur_tim; /* cursor blink timer */ + +extern int8_t v_period; +extern int16_t disab_cnt; /* disable depth count. (>0 means disabled) */ +extern int8_t v_stat_0; /* video cell system status */ +extern int16_t sav_cur_x; /* saved cursor cell x */ +extern int16_t sav_cur_y; /* saved cursor cell y */ + +/* Prototypes */ + +extern void ascii_out(int); +extern void move_cursor(int, int); +extern void blank_out (int, int, int, int); +extern void invert_cell(int, int); +extern void scroll_up(int); +extern void scroll_down(int); + +#endif /* __CONOUT_H__ */ diff --git a/include/font.h b/include/font.h index 84ba317..2091ca3 100644 --- a/include/font.h +++ b/include/font.h @@ -95,4 +95,6 @@ struct font_head { void font_init(void); /* initialize BIOS font ring */ void font_set_default(void); /* choose the default font */ +extern const struct font_head *fnt_st_8x16; + #endif /* FONT_H */ diff --git a/util/conout.c b/util/conout.c new file mode 100755 index 0000000..b50e11d --- /dev/null +++ b/util/conout.c @@ -0,0 +1,561 @@ +/* + * conout.c - lowlevel color model dependent screen handling routines + * + * + * Copyright (C) 2004 by Authors (see below) + * Copyright (C) 2016 The EmuTOS development team + * + * Authors: + * MAD Martin Doering + * + * This file is distributed under the GPL, version 2 or at your + * option any later version. See doc/license.txt for details. + */ + +#include "conout.h" +#include "video.h" +#include "font.h" +#include "fb.h" + +#define plane_offset 2 /* interleaved planes */ + +#define v_fnt_st fnt_st_8x16->first_ade +#define v_fnt_nd fnt_st_8x16->last_ade +#define v_off_ad fnt_st_8x16->off_table +#define v_bas_ad info_fb->screen_base + +uint8_t *v_cur_ad; /* cursor address */ +int8_t v_stat_0; /* console status byte */ +uint16_t v_cur_cx; +uint16_t v_cur_cy; +const int16_t v_planes = 8; +extern struct fb_info *info_fb; +#define v_lin_wr (info_fb->var.width / 2) /* length of a screen line in words */ + +/* + * internal prototypes + */ +static void neg_cell(uint8_t *); +static uint8_t * cell_addr(int, int); +static void cell_xfer(uint8_t *, uint8_t *); +static bool next_cell(void); + + +/* + * char_addr - retrieve the address of the source cell + * + * + * Given an offset value. + * + * in: + * ch - source cell code + * + * out: + * pointer to first byte of source cell if code was valid + */ + +static uint8_t *char_addr(int16_t ch) +{ + uint16_t offs; + + /* test against limits */ + if (ch >= v_fnt_st) + { + if (ch <= v_fnt_nd) + { + /* getch offset from offset table */ + offs = v_off_ad[ch]; + offs >>= 3; /* convert from pixels to bytes. */ + + /* return valid address */ + return (uint8_t*) v_fnt_ad + offs; + } + } + + /* invalid code. no address returned */ + return NULL; +} + + + +/* + * ascii_out - prints an ascii character on the screen + * + * in: + * + * ch.w ascii code for character + */ + +void ascii_out(int ch) +{ + uint8_t * src, * dst; + bool visible; /* was the cursor visible? */ + + src = char_addr(ch); /* a0 -> get character source */ + if (src == NULL) + return; /* no valid character */ + + dst = v_cur_ad; /* a1 -> get destination */ + + visible = v_stat_0 & M_CVIS; /* test visibility bit */ + if ( visible ) { + neg_cell(v_cur_ad); /* delete cursor. */ + v_stat_0 &= ~M_CVIS; /* start of critical section */ + } + + /* put the cell out (this covers the cursor) */ + cell_xfer(src, dst); + + /* advance the cursor and update cursor address and coordinates */ + if (next_cell()) + { + uint8_t * cell; + + int y = v_cur_cy; + + /* perform cell carriage return. */ + cell = v_bas_ad + (uint32_t) v_cel_wr * y; + v_cur_cx = 0; /* set X to first cell in line */ + + /* perform cell line feed. */ + if ( y < v_cel_my ) + { + cell += v_cel_wr; /* move down one cell */ + v_cur_cy = y + 1; /* update cursor's y coordinate */ + } + else { + scroll_up(0); /* scroll from top of screen */ + } + v_cur_ad = cell; /* update cursor address */ + } + + /* if visible */ + if ( visible ) { + neg_cell(v_cur_ad); /* display cursor. */ + v_stat_0 |= M_CSTATE; /* set state flag (cursor on). */ + v_stat_0 |= M_CVIS; /* end of critical section. */ + + /* do not flash the cursor when it moves */ + if (v_stat_0 & M_CFLASH) { + v_cur_tim = v_period; /* reset the timer. */ + } + } +} + + + + +/* + * blank_out - Fills region with the background color. + * + * Fills a cell-word aligned region with the background color. + * + * The rectangular region is specified by a top/left cell x,y and a + * bottom/right cell x,y, inclusive. Routine assumes top/left x is + * even and bottom/right x is odd for cell-word alignment. This is, + * because this routine is heavily optimized for speed, by always + * blanking as much space as possible in one go. + * + * in: + * topx - top/left cell x position (must be even) + * topy - top/left cell y position + * botx - bottom/right cell x position (must be odd) + * boty - bottom/right cell y position + */ + +void blank_out(int topx, int topy, int botx, int boty) +{ + +} + + + +/* + * cell_addr - convert cell X,Y to a screen address. + * + * + * convert cell X,Y to a screen address. also clip cartesian coordinates + * to the limits of the current screen. + * + * latest update: + * + * 18-sep-84 + * in: + * + * d0.w cell X + * d1.w cell Y + * + * out: + * a1 points to first byte of cell + */ + +static uint8_t *cell_addr(int x, int y) +{ + int32_t disx, disy; + + /* check bounds against screen limits */ + if ( x >= v_cel_mx ) + x = v_cel_mx; /* clipped x */ + + if ( y >= v_cel_my ) + y = v_cel_my; /* clipped y */ + + /* X displacement = even(X) * v_planes + Xmod2 */ + disx = (int32_t)v_planes * (x & ~1); + if ( x & 1 ) { /* Xmod2 = 0 ? */ + disx++; /* Xmod2 = 1 */ + } + + /* Y displacement = Y // cell conversion factor */ + disy = (int32_t)v_cel_wr * y; + + /* + * cell address = screen base address + Y displacement + * + X displacement + offset from screen-begin (fix) + */ + return v_bas_ad + disy + disx + v_cur_of; +} + + + +/* + * cell_xfer - Performs a byte aligned block transfer. + * + * + * This routine performs a byte aligned block transfer for the purpose of + * manipulating monospaced byte-wide text. the routine maps a single-plane, + * arbitrarily-long byte-wide image to a multi-plane bit map. + * all transfers are byte aligned. + * + * in: + * a0.l points to contiguous source block (1 byte wide) + * a1.l points to destination (1st plane, top of block) + * + * out: + * a4 points to byte below this cell's bottom + */ + +static void cell_xfer(uint8_t * src, uint8_t * dst) +{ + uint8_t * src_sav, * dst_sav; + uint16_t fg; + uint16_t bg; + int fnt_wr, line_wr; + int plane; + + fnt_wr = v_fnt_wr; + line_wr = v_lin_wr; + + /* check for reversed foreground and background colors */ + if ( v_stat_0 & M_REVID) + { + fg = v_col_bg; + bg = v_col_fg; + } + else + { + fg = v_col_fg; + bg = v_col_bg; + } + + src_sav = src; + dst_sav = dst; + + for (plane = v_planes; plane--;) + { + int i; + + src = src_sav; /* reload src */ + dst = dst_sav; /* reload dst */ + + if (bg & 0x0001) + { + if (fg & 0x0001) + { + /* back:1 fore:1 => all ones */ + for (i = v_cel_ht; i--;) + { + *dst = 0xff; /* inject a block */ + dst += line_wr; + } + } + else + { + /* back:1 fore:0 => invert block */ + for (i = v_cel_ht; i--; ) + { + /* inject the inverted source block */ + *dst = ~*src; + dst += line_wr; + src += fnt_wr; + } + } + } + else { + if (fg & 0x0001) + { + /* back:0 fore:1 => direct substitution */ + for (i = v_cel_ht; i--;) + { + *dst = *src; + dst += line_wr; + src += fnt_wr; + } + } + else + { + /* back:0 fore:0 => all zeros */ + for (i = v_cel_ht; i--; ) + { + *dst = 0x00; /* inject a block */ + dst += line_wr; + } + } + } + + bg >>= 1; /* next background color bit */ + fg >>= 1; /* next foreground color bit */ + dst_sav += plane_offset; /* top of block in next plane */ + } +} + + + +/* + * move_cursor - move the cursor. + * + * move the cursor and update global parameters + * erase the old cursor (if necessary) and draw new cursor (if necessary) + * + * in: + * d0.w new cell X coordinate + * d1.w new cell Y coordinate + */ + +void move_cursor(int x, int y) +{ + /* update cell position */ + + /* clamp x,y to valid ranges */ + if (x < 0) + x = 0; + else if (x > v_cel_mx) + x = v_cel_mx; + + if (y < 0) + y = 0; + else if (y > v_cel_my) + y = v_cel_my; + + v_cur_cx = x; + v_cur_cy = y; + + /* is cursor visible? */ + if ( !(v_stat_0 & M_CVIS) ) { + /* not visible */ + v_cur_ad = cell_addr(x, y); /* just set new coordinates */ + return; /* and quit */ + } + + /* is cursor flashing? */ + if ( v_stat_0 & M_CFLASH ) { + v_stat_0 &= ~M_CVIS; /* yes, make invisible...semaphore. */ + + /* is cursor presently displayed ? */ + if ( !(v_stat_0 & M_CSTATE )) { + /* not displayed */ + v_cur_ad = cell_addr(x, y); /* just set new coordinates */ + + /* show the cursor when it moves */ + neg_cell(v_cur_ad); /* complement cursor. */ + v_stat_0 |= M_CSTATE; + v_cur_tim = v_period; /* reset the timer. */ + + v_stat_0 |= M_CVIS; /* end of critical section. */ + return; + } + } + + /* move the cursor after all special checks failed */ + neg_cell(v_cur_ad); /* erase present cursor */ + + v_cur_ad = cell_addr(x, y); /* fetch x and y coords. */ + neg_cell(v_cur_ad); /* complement cursor. */ + + /* do not flash the cursor when it moves */ + v_cur_tim = v_period; /* reset the timer. */ + + v_stat_0 |= M_CVIS; /* end of critical section. */ +} + + + +/* + * neg_cell - negates + * + * This routine negates the contents of an arbitrarily-tall byte-wide cell + * composed of an arbitrary number of (Atari-style) bit-planes. + * Cursor display can be accomplished via this procedure. Since a second + * negation restores the original cell condition, there is no need to save + * the contents beneath the cursor block. + * + * in: + * a1.l points to destination (1st plane, top of block) + * + * out: + */ + +static void neg_cell(uint8_t * cell) +{ + int plane, len; + int cell_len = v_cel_ht; + + v_stat_0 |= M_CRIT; /* start of critical section. */ + + for (plane = v_planes; plane--; ) { + uint8_t * addr = cell; /* top of current dest plane */ + + /* reset cell length counter */ + for (len = cell_len; len--; ) { + *addr = ~*addr; + addr += v_lin_wr; + } + cell += plane_offset; /* a1 -> top of block in next plane */ + } + v_stat_0 &= ~M_CRIT; /* end of critical section. */ +} + + + +/* + * invert_cell - negates the cells bits + * + * This routine negates the contents of an arbitrarily-tall byte-wide cell + * composed of an arbitrary number of (Atari-style) bit-planes. + * + * Wrapper for neg_cell(). + * + * in: + * x - cell X coordinate + * y - cell Y coordinate + */ + +void invert_cell(int x, int y) +{ + /* fetch x and y coords and invert cursor. */ + neg_cell(cell_addr(x, y)); +} + + + +/* + * next_cell - Return the next cell address. + * + * sets next cell address given the current position and screen constraints + * + * returns: + * false - no wrap condition exists + * true - CR LF required (position has not been updated) + */ + +static bool next_cell(void) +{ + /* check bounds against screen limits */ + if (v_cur_cx == v_cel_mx) + { + /* increment cell ptr */ + if (!(v_stat_0 & M_CEOL)) + { + /* overwrite in effect */ + return 0; /* no wrap condition exists */ + /* don't change cell parameters */ + } + + /* call carriage return routine */ + /* call line feed routine */ + return 1; /* indicate that CR LF is required */ + } + + v_cur_cx += 1; /* next cell to right */ + + /* if X is even, move to next word in the plane */ + if (v_cur_cx & 1) + { + /* x is odd */ + v_cur_ad += 1; /* a1 -> new cell */ + return 0; /* indicate no wrap needed */ + } + + /* new cell (1st plane), added offset to next word in plane */ + v_cur_ad += (v_planes << 1) - 1; + + return 0; /* indicate no wrap needed */ +} + + +/* + * scroll_up - Scroll upwards + * + * + * Scroll copies a source region as wide as the screen to an overlapping + * destination region on a one cell-height offset basis. Two entry points + * are provided: Partial-lower scroll-up, partial-lower scroll-down. + * Partial-lower screen operations require the cell y # indicating the + * top line where scrolling will take place. + * + * After the copy is performed, any non-overlapping area of the previous + * source region is "erased" by calling blank_out which fills the area + * with the background color. + * + * in: + * top_line - cell y of cell line to be used as top line in scroll + */ + +void scroll_up(int top_line) +{ + uint32_t count; + uint8_t * src, * dst; + + /* screen base addr + cell y nbr * cell wrap */ + dst = v_bas_ad + (uint32_t) top_line * v_cel_wr; + + /* form source address from cell wrap + base address */ + src = dst + v_cel_wr; + + /* form # of bytes to move */ + count = (uint32_t) v_cel_wr * (v_cel_my - top_line); + + /* move BYTEs of memory*/ + memmove(dst, src, count); + + /* exit thru blank out, bottom line cell address y to top/left cell */ + blank_out(0, v_cel_my , v_cel_mx, v_cel_my ); +} + + + +/* + * scroll_down - Scroll (partially) downwards + */ + +void scroll_down(int start_line) +{ + uint32_t count; + uint8_t * src, * dst; + + /* screen base addr + offset of start line */ + src = v_bas_ad + (uint32_t) start_line * v_cel_wr; + + /* form destination from source + cell wrap */ + dst = src + v_cel_wr; + + /* form # of bytes to move */ + count = (uint32_t) v_cel_wr * (v_cel_my - start_line); + + /* move BYTEs of memory*/ + memmove(dst, src, count); + + /* exit thru blank out */ + blank_out(0, start_line , v_cel_mx, start_line); +} +