819 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			819 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
#ifdef TINY_FONT
 | 
						|
    #define ROWS 20
 | 
						|
    #define COLS 40
 | 
						|
    #define CHAR_LEADING 0
 | 
						|
    #define CHAR_WIDTH 4
 | 
						|
    #define CHAR_HEIGHT 6
 | 
						|
#else
 | 
						|
    // NOTE: Normal chars have a horizontal offset of 2, 26 chars
 | 
						|
    #define ROWS 15
 | 
						|
    #define COLS 26
 | 
						|
    #define CHAR_LEADING 0
 | 
						|
    #define CHAR_WIDTH 6
 | 
						|
    #define CHAR_HEIGHT 8
 | 
						|
#endif
 | 
						|
 | 
						|
#define MAX_X (COLS*CHAR_WIDTH)
 | 
						|
#define MAX_Y (ROWS*(CHAR_HEIGHT+CHAR_LEADING))
 | 
						|
 | 
						|
// Standard includes
 | 
						|
#include <limits.h>
 | 
						|
#include <stdarg.h>
 | 
						|
#include <stdio.h>
 | 
						|
 | 
						|
// System include
 | 
						|
#include <Gigatron.h>
 | 
						|
 | 
						|
// SPI ports (active low)
 | 
						|
#define SS0 0x04
 | 
						|
#define SS1 0x08
 | 
						|
#define SS2 0x10
 | 
						|
#define SS3 0x20
 | 
						|
#define BANK0 0x40
 | 
						|
#define BANK1 0x80
 | 
						|
#define SPI_MASK 0x3c
 | 
						|
#define BANK_MASK 0xc0
 | 
						|
 | 
						|
#define DarkYellow              0x05
 | 
						|
#define Yellow                  0x0a
 | 
						|
#define LightYellow             0x0f
 | 
						|
 | 
						|
#define DarkMagenta             0x11
 | 
						|
#define Magenta                 0x22
 | 
						|
#define LightMagenta            0x33
 | 
						|
 | 
						|
#define DarkCyan                0x14
 | 
						|
#define Cyan                    0x28
 | 
						|
#define LightCyan               0x3c
 | 
						|
 | 
						|
#define DarkGray                0x15
 | 
						|
#define LightGray               0x2a
 | 
						|
 | 
						|
#define romType                 (*(byte*)0x0021)
 | 
						|
#define romTypeValue_ROMv4      0x38
 | 
						|
#define romTypeValue_DEVROM     0xf8
 | 
						|
 | 
						|
#define xoutMask                (*(byte*)0x0014)
 | 
						|
#define ledState                (*(byte*)0x002E)
 | 
						|
#define ledTempo                (*(byte*)0x002F)
 | 
						|
 | 
						|
#define SYS_VDrawWord_134               0x00cb
 | 
						|
#define SYS_Draw4_30                    0x04d4
 | 
						|
#define SYS_SetMode_v2_80               0x0b00
 | 
						|
#define SYS_SetMemory_v2_54             0x0b03
 | 
						|
#define SYS_ExpanderControl_v4_40       0x0b09
 | 
						|
#define SYS_SpiExchangeBytes_v4_134     0x0b15
 | 
						|
 | 
						|
// Forward declaration
 | 
						|
void cursorDown( byte _amount, byte _allowScroll );
 | 
						|
#define NEWLINE_EX() {cursorDown(1,1);ScreenPos &= 0xff00;}
 | 
						|
#define NEWLINE_EX2() {cursorDown(1,1);ScreenPos &= 0xff00;ScreenPos |= 0x0002;}
 | 
						|
#define ROW_TO_SCREEN(_r,_s){\
 | 
						|
    ((byte*)&_s)[1] = _r * ( CHAR_HEIGHT + CHAR_LEADING ) + videoTable[0];\
 | 
						|
    if ( ((byte*)&_s)[1] > 0x7f )\
 | 
						|
        ((byte*)&_s)[1] -= 120;\
 | 
						|
}
 | 
						|
 | 
						|
#ifdef TINY_FONT
 | 
						|
// Hijack original functions
 | 
						|
#define PutChar(c) PutChar_ex(c)
 | 
						|
//#define puts(s) puts_ex(s)
 | 
						|
#define Newline() NEWLINE_EX()
 | 
						|
#else
 | 
						|
#define Newline() NEWLINE_EX2()
 | 
						|
#endif
 | 
						|
 | 
						|
int cursor[ 12 ];
 | 
						|
 | 
						|
const int tinyfont[96] = {
 | 
						|
  #include "../Utils/BabelFish/tinyfont.h"
 | 
						|
};
 | 
						|
 | 
						|
void EraseInLine( byte _mode, int _screenCoord )
 | 
						|
{
 | 
						|
    byte size;
 | 
						|
    char line;
 | 
						|
 | 
						|
    switch ( _mode )
 | 
						|
    {
 | 
						|
        case 0:
 | 
						|
            // Erase from the active position to the end of the line, inclusive (default)
 | 
						|
            //size = 160 - (_screenCoord & 0x00ff);
 | 
						|
            size = 160 - ((byte*)&_screenCoord)[0];
 | 
						|
 | 
						|
            break;
 | 
						|
 | 
						|
        case 1:
 | 
						|
            // Erase from the start of the line to the active position, inclusive
 | 
						|
            size = 160 - ((byte*)&_screenCoord)[0] + CHAR_WIDTH;
 | 
						|
            _screenCoord = _screenCoord & 0xff00;
 | 
						|
            break;
 | 
						|
 | 
						|
        case 2:
 | 
						|
            // Erase all of the line, inclusive
 | 
						|
            _screenCoord = _screenCoord & 0xff00;
 | 
						|
            size = 160;
 | 
						|
            break;
 | 
						|
    }
 | 
						|
 | 
						|
    // Clear this line
 | 
						|
    sysFn = SYS_SetMemory_v2_54;
 | 
						|
    sysArgs[1] = BgColor;       // Set background color
 | 
						|
 | 
						|
    for ( line = 0; line < CHAR_HEIGHT; ++line )
 | 
						|
    {
 | 
						|
        *(int*)(sysArgs+2) = _screenCoord; // Destination
 | 
						|
        sysArgs[0] = size;          // Count
 | 
						|
        __syscall(243);             // 270-54/2
 | 
						|
        _screenCoord += 256;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void PutChar_ex( byte c )
 | 
						|
{
 | 
						|
    // DECAWM->autowrap to newline (allow scroll) or overwrite last char
 | 
						|
    byte i;
 | 
						|
 | 
						|
#ifdef TERMINAL_MODES
 | 
						|
    byte wrap = (terminalModes & DECAWM) ? 1 : 0;
 | 
						|
#else
 | 
						|
    byte wrap = 1;
 | 
						|
#endif
 | 
						|
 | 
						|
    // Accept newlines
 | 
						|
    if (c == '\n')
 | 
						|
    {
 | 
						|
        Newline();
 | 
						|
        return;
 | 
						|
    }
 | 
						|
    
 | 
						|
    if ( c == 9 )
 | 
						|
    {
 | 
						|
        // TODO: make tab work for big font as well
 | 
						|
        ScreenPos += 8 * CHAR_WIDTH;
 | 
						|
        ScreenPos &= ~(8*CHAR_WIDTH - 1);
 | 
						|
    }
 | 
						|
    else if ( c < 32 || c > 127 )
 | 
						|
        return;
 | 
						|
 | 
						|
    // Wrap to new line if we're outside the view
 | 
						|
    if (((byte*)&ScreenPos)[0] >= MAX_X )
 | 
						|
    {
 | 
						|
        if ( wrap )
 | 
						|
        {
 | 
						|
            Newline();
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            ScreenPos -= CHAR_WIDTH;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if ( c == 9 )
 | 
						|
        return;
 | 
						|
 | 
						|
    i = c - 32;
 | 
						|
    sysFn = SYS_VDrawWord_134;
 | 
						|
    sysArgs[0] = BgColor;
 | 
						|
    sysArgs[1] = Color;
 | 
						|
    *(int*)(sysArgs+2) = tinyfont[ i ];
 | 
						|
    *(int*)(sysArgs+4) = ScreenPos;
 | 
						|
 | 
						|
    __syscall(202); // 270-135/2
 | 
						|
 | 
						|
    // Note that the column can be out of the display area
 | 
						|
    // (to prevent automatic newlines at the end of the screen)
 | 
						|
    //column++;
 | 
						|
    ScreenPos += CHAR_WIDTH;
 | 
						|
}
 | 
						|
 | 
						|
signed char puts_ex(const char *s)
 | 
						|
{
 | 
						|
    // Note that this fuction is dumbed down: no stream support
 | 
						|
    for (; *s; s++)
 | 
						|
    {
 | 
						|
        PutChar(*s);
 | 
						|
    }
 | 
						|
    return EOF;
 | 
						|
}
 | 
						|
 | 
						|
void ScrollUp()
 | 
						|
{
 | 
						|
    int screenCoord;
 | 
						|
    byte i;
 | 
						|
 | 
						|
    // Clear first line since video rolls over
 | 
						|
    ROW_TO_SCREEN( 0, screenCoord );
 | 
						|
    EraseInLine( 2, screenCoord );
 | 
						|
 | 
						|
    // Scroll up by manipulating video indirection table
 | 
						|
    i = 240;
 | 
						|
    do
 | 
						|
    {
 | 
						|
        byte page;
 | 
						|
        i -= 2;
 | 
						|
        page = videoTable[i] + CHAR_HEIGHT + CHAR_LEADING;
 | 
						|
        videoTable[i] = page & 128 ? page - 120 : page;
 | 
						|
    } while (i);
 | 
						|
}
 | 
						|
 | 
						|
void PutGlyph( unsigned long _g )
 | 
						|
{
 | 
						|
    // Wrap to new line if we're outside the view
 | 
						|
    if (((byte*)&ScreenPos)[0] >= MAX_X )
 | 
						|
        Newline();
 | 
						|
 | 
						|
    sysFn = SYS_VDrawWord_134;
 | 
						|
    sysArgs[0] = BgColor;
 | 
						|
    sysArgs[1] = Color;
 | 
						|
    *(int*)(sysArgs+2) = _g;
 | 
						|
    *(int*)(sysArgs+4) = ScreenPos;
 | 
						|
 | 
						|
    __syscall(202); // 270-135/2
 | 
						|
 | 
						|
    // Note that the column can be out of the display area
 | 
						|
    // (to prevent automatic newlines at the end of the screen)
 | 
						|
    //column++;
 | 
						|
    ScreenPos += CHAR_WIDTH;
 | 
						|
}
 | 
						|
 | 
						|
void drawChar( int* _char )
 | 
						|
{
 | 
						|
    if (((byte*)&ScreenPos)[0] >= MAX_X )
 | 
						|
        return;
 | 
						|
 | 
						|
    *(int*)ScreenPos = _char[0];
 | 
						|
    *(int*)(ScreenPos + 2) = _char[1];
 | 
						|
 | 
						|
    *(int*)(ScreenPos + 256) = _char[2];
 | 
						|
    *(int*)(ScreenPos + 258) = _char[3];
 | 
						|
 | 
						|
    *(int*)(ScreenPos + 512) = _char[4];
 | 
						|
    *(int*)(ScreenPos + 514) = _char[5];
 | 
						|
 | 
						|
    *(int*)(ScreenPos + 768) = _char[6];
 | 
						|
    *(int*)(ScreenPos + 770) = _char[7];
 | 
						|
 | 
						|
    *(int*)(ScreenPos + 1024) = _char[8];
 | 
						|
    *(int*)(ScreenPos + 1026) = _char[9];
 | 
						|
 | 
						|
    *(int*)(ScreenPos + 1280) = _char[10];
 | 
						|
    *(int*)(ScreenPos + 1282) = _char[11];
 | 
						|
}
 | 
						|
 | 
						|
void drawCursor( byte _copy )
 | 
						|
{
 | 
						|
    byte i;
 | 
						|
 | 
						|
    // TODO: maybe try and draw on the next line
 | 
						|
    if (((byte*)&ScreenPos)[0] >= MAX_X )
 | 
						|
        return;
 | 
						|
 | 
						|
    // TODO: MAX_Y
 | 
						|
 | 
						|
    if ( _copy )
 | 
						|
    {
 | 
						|
        cursor[0] = *(int*)ScreenPos;
 | 
						|
        cursor[1] = *(int*)(ScreenPos + 2);
 | 
						|
 | 
						|
        cursor[2] = *(int*)(ScreenPos + 256);
 | 
						|
        cursor[3] = *(int*)(ScreenPos + 258);
 | 
						|
 | 
						|
        cursor[4] = *(int*)(ScreenPos + 512);
 | 
						|
        cursor[5] = *(int*)(ScreenPos + 514);
 | 
						|
 | 
						|
        cursor[6] = *(int*)(ScreenPos + 768);
 | 
						|
        cursor[7] = *(int*)(ScreenPos + 770);
 | 
						|
 | 
						|
        cursor[8] = *(int*)(ScreenPos + 1024);
 | 
						|
        cursor[9] = *(int*)(ScreenPos + 1026);
 | 
						|
 | 
						|
        cursor[10] = *(int*)(ScreenPos + 1280);
 | 
						|
        cursor[11] = *(int*)(ScreenPos + 1282);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        for ( i = 0; i < 12; i++ )
 | 
						|
            cursor[i] = BgColor << 8 | BgColor;
 | 
						|
    }
 | 
						|
 | 
						|
    // Prepare SYS call
 | 
						|
    sysFn = SYS_Draw4_30;
 | 
						|
    sysArgs[0] = Color;
 | 
						|
    sysArgs[1] = Color;
 | 
						|
    sysArgs[2] = Color;
 | 
						|
    sysArgs[3] = BgColor;
 | 
						|
    *(int*)(sysArgs+4) = ScreenPos;
 | 
						|
 | 
						|
    // Draw bitmap to screen as 'n' vertical slices
 | 
						|
    // TODO: there are not enough cycles to include the 6th line when drawing a character; dont draw any pixels in it for now to avoid clutter
 | 
						|
    //for (i=CHAR_HEIGHT; i>0; --i)
 | 
						|
    for (i=5; i>0; --i)
 | 
						|
    {
 | 
						|
        __syscall(255); // 270-30/2
 | 
						|
        sysArgs[5]++;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void setCursor( byte _r, byte _c )
 | 
						|
{
 | 
						|
    // Restore character behind cursor
 | 
						|
    //drawChar( cursor );
 | 
						|
 | 
						|
    if ( _r >= ROWS )
 | 
						|
        _r = ROWS - 1;
 | 
						|
 | 
						|
    if ( _c >= COLS )
 | 
						|
        _c = COLS - 1;
 | 
						|
 | 
						|
    // Calculate row with scroll offset in mind
 | 
						|
    ROW_TO_SCREEN( _r, ScreenPos );
 | 
						|
    ScreenPos &= 0xff00;
 | 
						|
 | 
						|
#ifdef TINY_FONT
 | 
						|
    ScreenPos |= (( _c * CHAR_WIDTH + videoTable[1] ) & 0x00ff );
 | 
						|
#else
 | 
						|
    ScreenPos |= (( _c * CHAR_WIDTH + videoTable[1] + 2) & 0x00ff );
 | 
						|
#endif
 | 
						|
 | 
						|
    // Draw cursor
 | 
						|
    //drawCursor( 1 );
 | 
						|
}
 | 
						|
 | 
						|
void EraseInDisplay( byte _mode, int _screenCoord )
 | 
						|
{
 | 
						|
    byte line;
 | 
						|
    byte row = ((byte*)&_screenCoord)[1];
 | 
						|
    if ( videoTable[0] > row )
 | 
						|
        row += 120;
 | 
						|
    row -= videoTable[0];
 | 
						|
    row /= ( CHAR_HEIGHT + CHAR_LEADING );
 | 
						|
 | 
						|
    // Erase current line
 | 
						|
    EraseInLine( _mode, _screenCoord );
 | 
						|
 | 
						|
    // 0: end
 | 
						|
    // 1: begin
 | 
						|
    // 2: all
 | 
						|
    if ( _mode && row )
 | 
						|
    {
 | 
						|
        // Erase begin or all of screen
 | 
						|
        for ( line = 0; line < row; ++line )
 | 
						|
        {
 | 
						|
#if defined( SLOW ) && defined( TESTS )
 | 
						|
            BusyWait( 10 );
 | 
						|
#endif
 | 
						|
            ROW_TO_SCREEN( line, _screenCoord );
 | 
						|
            EraseInLine( 2, _screenCoord );
 | 
						|
        }
 | 
						|
    }
 | 
						|
    if ( _mode != 1 )
 | 
						|
    {
 | 
						|
        // Erase end or all of screen
 | 
						|
        //for ( ++row; row < ROWS - 1; ++row )
 | 
						|
        for ( ++row; row < ROWS; ++row )
 | 
						|
        {
 | 
						|
#if defined( SLOW ) && defined( TESTS )
 | 
						|
            BusyWait( 10 );
 | 
						|
#endif
 | 
						|
            ROW_TO_SCREEN( row, _screenCoord );
 | 
						|
            EraseInLine( 2, _screenCoord );
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
void cursorUp( byte _amount, byte _allowScroll )
 | 
						|
{
 | 
						|
    // TODO: avoid usage of int -> (byte*)&_screenCoord)[1];
 | 
						|
/*
 | 
						|
    byte row = ((byte*)&_screenCoord)[1];
 | 
						|
    if ( videoTable[0] > row )
 | 
						|
        row += 120;
 | 
						|
    row -= videoTable[0];
 | 
						|
    row /= ( CHAR_HEIGHT + CHAR_LEADING );
 | 
						|
*/
 | 
						|
    int y = (ScreenPos >> 8) - videoTable[0];
 | 
						|
 | 
						|
    if ( y < 0 )
 | 
						|
        y += 120;
 | 
						|
 | 
						|
    while ( _amount-- )
 | 
						|
    {
 | 
						|
        if ( y >= ( CHAR_HEIGHT + CHAR_LEADING ) )
 | 
						|
        {
 | 
						|
            ScreenPos -= (( CHAR_HEIGHT + CHAR_LEADING ) << 8 );
 | 
						|
            y -= CHAR_HEIGHT + CHAR_LEADING;
 | 
						|
        }
 | 
						|
        else if ( _allowScroll )
 | 
						|
        {
 | 
						|
            // TODO: ScrollDown();
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            break;
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void cursorDown( byte _amount, byte _allowScroll )
 | 
						|
{
 | 
						|
    // Determine y offset (avoid usage of int)
 | 
						|
    byte row = ((byte*)&ScreenPos)[1];
 | 
						|
    if ( videoTable[0] > row )
 | 
						|
        row += 120;
 | 
						|
    row -= videoTable[0];
 | 
						|
    row /= ( CHAR_HEIGHT + CHAR_LEADING );
 | 
						|
 | 
						|
    while ( _amount-- )
 | 
						|
    {
 | 
						|
        if ( row < (ROWS - 1) )
 | 
						|
        {
 | 
						|
            row++;
 | 
						|
            ROW_TO_SCREEN( row, ScreenPos );
 | 
						|
        }
 | 
						|
        else if ( _allowScroll )
 | 
						|
        {
 | 
						|
            ScrollUp();
 | 
						|
            ROW_TO_SCREEN( row, ScreenPos );
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            break;
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void cursorLeft( byte _amount )
 | 
						|
{
 | 
						|
    // TODO: avoid usage of int
 | 
						|
    int x = (ScreenPos & 0xff );
 | 
						|
    while ( _amount-- )
 | 
						|
    {
 | 
						|
        if ( x >= CHAR_WIDTH )
 | 
						|
        {
 | 
						|
            ScreenPos -= CHAR_WIDTH;
 | 
						|
            x -= CHAR_WIDTH;
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            break;
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void cursorRight( byte _amount )
 | 
						|
{
 | 
						|
    // TODO: avoid usage of int
 | 
						|
    int x = (ScreenPos & 0xff );
 | 
						|
    while ( _amount-- )
 | 
						|
    {
 | 
						|
        if ( x < (MAX_X - CHAR_WIDTH) )
 | 
						|
        {
 | 
						|
            ScreenPos += CHAR_WIDTH;
 | 
						|
            x += CHAR_WIDTH;
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            break;
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
#ifdef TESTS
 | 
						|
void test()
 | 
						|
{
 | 
						|
    reset();
 | 
						|
 | 
						|
    setCursor( 0, 0 );
 | 
						|
    puts_ex( "Tests:" );
 | 
						|
 | 
						|
    reset();
 | 
						|
    test_cursor();
 | 
						|
    reset();
 | 
						|
    test_clear();
 | 
						|
    reset();
 | 
						|
    test_colors();
 | 
						|
    reset();
 | 
						|
    test_linewrap();
 | 
						|
    reset();
 | 
						|
    test_scroll();
 | 
						|
    reset();
 | 
						|
    test_cursorscroll();
 | 
						|
    reset();
 | 
						|
    test_newline();
 | 
						|
    reset();
 | 
						|
    test_e3();
 | 
						|
    // Done
 | 
						|
    reset();
 | 
						|
    ledState = 0;
 | 
						|
 | 
						|
    setCursor( 2, 2 );
 | 
						|
    puts_ex( "Done." );
 | 
						|
}
 | 
						|
 | 
						|
void test_cursor()
 | 
						|
{
 | 
						|
    // test setCursor, drawCursor and cursor up/down/left/right
 | 
						|
    setCursor( 2, 2 );
 | 
						|
    puts_ex( "Cursor" );
 | 
						|
    // bottom right corner: '#'
 | 
						|
    drawChar( cursor );
 | 
						|
    setCursor( 100, 100 );
 | 
						|
    PutChar( '#' );
 | 
						|
    drawCursor( 1 );
 | 
						|
    xoutMask++;
 | 
						|
    BusyWait( 60 );
 | 
						|
 | 
						|
    // top right corner: 'B'
 | 
						|
    drawChar( cursor );
 | 
						|
    cursorLeft( 1 ); // TODO: fix cursor
 | 
						|
    cursorUp( 100, 0 );
 | 
						|
    PutChar( 'B' );
 | 
						|
    drawCursor( 1 );
 | 
						|
    xoutMask++;
 | 
						|
    BusyWait( 60 );
 | 
						|
 | 
						|
    // top left corner: 'A'
 | 
						|
    drawChar( cursor );
 | 
						|
    cursorLeft( 100 );
 | 
						|
    PutChar( 'A' );
 | 
						|
    drawCursor( 1 );
 | 
						|
    xoutMask++;
 | 
						|
    BusyWait( 60 );
 | 
						|
 | 
						|
    // bottom left corner: 'D'
 | 
						|
    drawChar( cursor );
 | 
						|
    cursorLeft( 1 ); // TODO: fix cursor
 | 
						|
    cursorDown( 100, 0 );
 | 
						|
    PutChar( 'D' );
 | 
						|
    drawCursor( 1 );
 | 
						|
    xoutMask++;
 | 
						|
    BusyWait( 60 );
 | 
						|
 | 
						|
    // bottom right corner: 'C'
 | 
						|
    drawChar( cursor );
 | 
						|
    cursorRight( 100 );
 | 
						|
    PutChar( 'C' );
 | 
						|
    drawCursor( 1 );
 | 
						|
    xoutMask++;
 | 
						|
    BusyWait( 60 );
 | 
						|
}
 | 
						|
 | 
						|
void test_clear()
 | 
						|
{
 | 
						|
    // Test EraseInDisplay and inherently, EraseInLine in all 3 variations
 | 
						|
    setCursor( 2, 2 );
 | 
						|
    puts_ex( "Clear" );
 | 
						|
 | 
						|
    // Erase lower half with red
 | 
						|
    BgColor = DarkRed;
 | 
						|
    setCursor( ROWS / 2, COLS / 2 );
 | 
						|
    EraseInDisplay( 0, ScreenPos );    
 | 
						|
    xoutMask++;
 | 
						|
    BusyWait( 60 );
 | 
						|
 | 
						|
    // Erase upper half with green
 | 
						|
    BgColor = DarkGreen;
 | 
						|
    EraseInDisplay( 1, ScreenPos );    
 | 
						|
    xoutMask++;
 | 
						|
    BusyWait( 60 );
 | 
						|
 | 
						|
    // Erase all with black
 | 
						|
    BgColor = Black;
 | 
						|
    EraseInDisplay( 2, ScreenPos );    
 | 
						|
    xoutMask++;
 | 
						|
    BusyWait( 60 );
 | 
						|
}
 | 
						|
 | 
						|
void test_colors()
 | 
						|
{
 | 
						|
    // Test all 64 foreground and background colors
 | 
						|
    byte r;
 | 
						|
    byte c;
 | 
						|
 | 
						|
    setCursor( 2, 2 );
 | 
						|
    puts_ex( "Colors" );
 | 
						|
 | 
						|
    BgColor = Black;
 | 
						|
    for ( r = 0; r < 8; ++r )
 | 
						|
    {
 | 
						|
        for ( c = 0; c < 8; ++c )
 | 
						|
        {
 | 
						|
            setCursor( r + 5, c + 8 );
 | 
						|
            Color = 8 * r + c;
 | 
						|
            PutChar( '#' );
 | 
						|
        }
 | 
						|
    }
 | 
						|
    xoutMask++;
 | 
						|
 | 
						|
    Color = White;
 | 
						|
    for ( r = 0; r < 8; ++r )
 | 
						|
    {
 | 
						|
        for ( c = 0; c < 8; ++c )
 | 
						|
        {
 | 
						|
            setCursor( r + 5, c + 24 );
 | 
						|
            BgColor = 8 * r + c;
 | 
						|
            PutChar( '.' );
 | 
						|
        }
 | 
						|
    }
 | 
						|
    xoutMask++;
 | 
						|
 | 
						|
    BusyWait( 60 );
 | 
						|
}
 | 
						|
 | 
						|
void test_linewrap()
 | 
						|
{
 | 
						|
    // Test line wrapping
 | 
						|
    byte count;
 | 
						|
    char linewrap[] = "Line wrap";
 | 
						|
    setCursor( 2, 2 );
 | 
						|
    puts_ex( linewrap );
 | 
						|
 | 
						|
    BusyWait( 60 );
 | 
						|
 | 
						|
    setCursor( 0, 0 );
 | 
						|
    count = 20;
 | 
						|
    Color = LightGreen;
 | 
						|
    while ( count-- )
 | 
						|
    {
 | 
						|
        puts_ex( linewrap );
 | 
						|
        xoutMask++;
 | 
						|
        BusyWait( 5 );
 | 
						|
    }
 | 
						|
 | 
						|
    // Force DECAWM (automatic wrap mode) off
 | 
						|
#ifdef TERMINAL_MODES
 | 
						|
    terminalModes &= ~DECAWM;
 | 
						|
 | 
						|
    count = 5;
 | 
						|
    Color = LightRed;
 | 
						|
    while ( count-- )
 | 
						|
    {
 | 
						|
        puts_ex( linewrap );
 | 
						|
        xoutMask++;
 | 
						|
        BusyWait( 5 );
 | 
						|
    }
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
void test_scroll()
 | 
						|
{
 | 
						|
    // Test screen scrolling
 | 
						|
    byte count = 21;
 | 
						|
 | 
						|
    setCursor( 2, 2 );
 | 
						|
    puts_ex( "Scroll" );
 | 
						|
 | 
						|
    while ( count-- )
 | 
						|
    {
 | 
						|
        ScrollUp();
 | 
						|
        setCursor( 0, 10 );
 | 
						|
        puts_ex( "line 1 will be erased" );
 | 
						|
        setCursor( 19, 16 );
 | 
						|
        puts_ex( "line 20" );
 | 
						|
        xoutMask++;
 | 
						|
        BusyWait( 10 );
 | 
						|
    }
 | 
						|
 | 
						|
    // TODO: scroll down/left/up
 | 
						|
}
 | 
						|
 | 
						|
void test_cursorscroll()
 | 
						|
{
 | 
						|
    // Test cursor scrolling
 | 
						|
    byte count;
 | 
						|
 | 
						|
    setCursor( 2, 2 );
 | 
						|
    puts_ex( "CursorScroll" );
 | 
						|
 | 
						|
    // Center
 | 
						|
    setCursor( ROWS / 2, COLS / 2 );
 | 
						|
    count = 21;
 | 
						|
    while ( count-- )
 | 
						|
    {
 | 
						|
        cursorDown( 1, 1 );
 | 
						|
        PutChar( '^' );
 | 
						|
        xoutMask++;
 | 
						|
        BusyWait( 30 );
 | 
						|
    }
 | 
						|
 | 
						|
/*
 | 
						|
    // Center
 | 
						|
    setCursor( ROWS / 2, COLS / 2 );
 | 
						|
    count = 21;
 | 
						|
    while ( count-- )
 | 
						|
    {
 | 
						|
        cursorUp( 1, 1 );
 | 
						|
        PutChar( 'v' );
 | 
						|
        xoutMask++;
 | 
						|
        BusyWait( 30 );
 | 
						|
    }
 | 
						|
*/
 | 
						|
}
 | 
						|
 | 
						|
void test_newline()
 | 
						|
{
 | 
						|
    // Test newline scrolling
 | 
						|
    byte count = 21;
 | 
						|
    char newline[] = "Newline";
 | 
						|
 | 
						|
    setCursor( 2, 2 );
 | 
						|
    puts_ex( newline );
 | 
						|
 | 
						|
    setCursor( 8, 0 );
 | 
						|
    drawCursor( 0 );
 | 
						|
    while ( count-- )
 | 
						|
    {
 | 
						|
        drawChar( cursor );
 | 
						|
        Newline();
 | 
						|
        puts_ex( newline );
 | 
						|
        drawCursor( 1 );
 | 
						|
        xoutMask++;
 | 
						|
        BusyWait( 30 );
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void test_e3()
 | 
						|
{
 | 
						|
    // Fill screen with 'E', wait a second and fill the next 3 lines with '3'
 | 
						|
    byte c;
 | 
						|
    byte r = ROWS;
 | 
						|
 | 
						|
    setCursor( 2, 2 );
 | 
						|
    puts_ex( "E3" );
 | 
						|
    drawCursor( 1 );
 | 
						|
 | 
						|
    BusyWait( 60 );
 | 
						|
    drawChar( cursor );
 | 
						|
    setCursor( 0, 0 );
 | 
						|
    drawCursor( 1 );
 | 
						|
 | 
						|
    // Fill screen with 'E'
 | 
						|
    while ( r-- )
 | 
						|
    {
 | 
						|
        c = COLS;
 | 
						|
        while ( c-- )
 | 
						|
        {
 | 
						|
            PutChar( 'E' );
 | 
						|
            drawCursor( 0 );
 | 
						|
#ifdef SLOW
 | 
						|
            BusyWait( 1 );
 | 
						|
#endif
 | 
						|
            xoutMask++;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    BusyWait( 60 );
 | 
						|
    r = 3;
 | 
						|
    while ( r-- )
 | 
						|
    {
 | 
						|
        c = COLS;
 | 
						|
        while ( c-- )
 | 
						|
        {
 | 
						|
            PutChar( '3' );
 | 
						|
            drawCursor( 0 );
 | 
						|
#ifdef SLOW
 | 
						|
            BusyWait( 3 );
 | 
						|
#endif
 | 
						|
            xoutMask++;
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void reset()
 | 
						|
{
 | 
						|
    byte i = 240;
 | 
						|
    byte t = 127;
 | 
						|
 | 
						|
    ledState = 0;
 | 
						|
    BusyWait( 60 );
 | 
						|
 | 
						|
    // LEDs static on
 | 
						|
    ledState = 1;
 | 
						|
    xoutMask = 0xf;
 | 
						|
 | 
						|
    //Reset cursor
 | 
						|
    ScreenPos = (int)screenMemory;
 | 
						|
 | 
						|
 | 
						|
    // Clear display
 | 
						|
    BgColor = Blue;
 | 
						|
    Color = White;
 | 
						|
    EraseInDisplay( 2, ScreenPos );    
 | 
						|
 | 
						|
    // Reset scroll
 | 
						|
    // Scroll up by manipulating video indirection table
 | 
						|
    do
 | 
						|
    {
 | 
						|
        i -= 2;
 | 
						|
        videoTable[i] = t--;
 | 
						|
    } while (i);
 | 
						|
 | 
						|
    // Store and draw (empty) cursor
 | 
						|
    drawCursor( 0 );
 | 
						|
    drawChar( cursor );
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#endif
 |