byte* print_screen = $0400;
byte* print_line_cursor = print_screen;
byte* print_char_cursor = print_line_cursor;

// Print a number of zero-terminated strings, each followed by a newline.
// The sequence of lines is terminated by another zero.
void print_str_lines(byte* str) {
    while(*str!='@') {
        do {
            byte ch = *(str++);
            if(ch!='@') {
                *(print_char_cursor++) = ch;
            }
        } while (ch!='@');
        print_ln();
    }
}

// Print a zero-terminated string followed by a newline
void print_str_ln(byte* str) {
    print_str(str);
    print_ln();
}

// Print a zero-terminated string
void print_str(byte* str) {
    while(*str!='@') {
        *(print_char_cursor++) = *(str++);
    }
}

// Print a string at a specific screen position
void print_str_at(byte* str, byte* at) {
    while(*str!='@') {
        *(at++) = *(str++);
    }
}

// Print a newline
void print_ln() {
    do {
        print_line_cursor = print_line_cursor + $28;
    } while (print_line_cursor<print_char_cursor);
    print_char_cursor = print_line_cursor;
}

// Print a signed word as HEX
void print_sword(signed word w) {
    if(w<0) {
        print_char('-');
        w = -w;
    }
    print_word((word)w);
}

// Print a signed byte as HEX
void print_sbyte(signed byte b) {
    if(b<0) {
        print_char('-');
        b = -b;
    } else {
        print_char(' ');        
    }
    print_byte((byte)b);
}

// Prints a signed byte as HEX at a specific position on the screen
// row and col are 0-based indices
inline void print_sbyte_pos(signed byte sb, byte row, byte col) {
    print_sbyte_at(sb, print_screen+row*40+col);
}

// Print a signed byte as hex at a specific screen position
void print_sbyte_at(signed byte b, byte* at) {
    if(b<0) {
        print_char_at('-', at);
        b = -b;
    } else {
        print_char_at(' ', at);        
    }
    print_byte_at((byte)b, at+1);
}

// Print a word as HEX
void print_word(word w) {
    print_byte(>w);
    print_byte(<w);
}

// Print a dword as HEX
void print_dword(dword dw) {
    print_word(>dw);
    print_word(<dw);
}

// Print a signed dword as HEX
void print_sdword(signed dword dw) {
    if(dw<0) {
        print_char('-');
        dw = -dw;
    }
    print_dword((dword)dw);
}

const byte[] print_hextab = "0123456789abcdef";

// Print a byte as HEX
void print_byte(byte b) {
    // Table of hexadecimal digits
    print_char(print_hextab[b>>4]);
    print_char(print_hextab[b&$f]);
}

// Prints a byte as HEX at a specific position on the screen
// row and col are 0-based indices
inline void print_byte_pos(byte b, byte row, byte col) {
    print_byte_at(b, print_screen+row*40+col);
}

// Print a byte as HEX at a specific position
void print_byte_at(byte b, byte* at) {
    // Table of hexadecimal digits
    print_char_at(print_hextab[b>>4], at);
    print_char_at(print_hextab[b&$f], at+1);
}

// Print a single char
void print_char(byte ch) {
    *(print_char_cursor++) = ch;
}

// Print a single char
void print_char_at(byte ch, byte* at) {
    *(at) = ch;
}

// Clear the screen. Also resets current line/char cursor.
void print_cls() {
    for(byte* sc=print_screen; sc!=print_screen+1000; sc++) {
        *sc = ' ';
    }
    print_line_cursor = print_screen;
    print_char_cursor = print_line_cursor;
}

// Set the screen to print on. Also resets current line/char cursor.
void print_set_screen(byte* screen) {
    print_screen = screen;
    print_line_cursor = print_screen;
    print_char_cursor = print_line_cursor;
}
