"printf()" Cursor Repositioning

ZX80, ZX 81, ZX Spectrum, TS2068 and other clones
Post Reply
Zetr0
Member
Posts: 60
Joined: Mon Aug 22, 2011 12:38 pm

"printf()" Cursor Repositioning

Post by Zetr0 »

Hello my fellow Z88dk'ers,

I promise this will be the last time I bug the boards today - so I will be brief as I can.


I want to use the printf() command in 64 column mode

I have achieved this quite simply.

I want to add PAPER and INK to the text I want to print

I have achieved this also

However getting the Print Cursor to move is simply not working as expected I suspect that I have gotten the wrong end of the stick here.


so lets look

Code: Select all

/*
        _BRIGHT = 19
        _INK       = 16
        _PAPER   = 17

        _ON        = 1
        _OFF       = 0

*/

printf("\x08%c%c%c%c%c%cTest", _BRIGHT,  _ON, _INK,  RED,  _PAPER, YELLOW);
The above works as expected, however

Code: Select all

/*
        _AT        = 22
        _BRIGHT = 19
        _INK       = 16
        _PAPER   = 17

        _ON        = 1
        _OFF       = 0

*/

printf("\x08%c%c%c%c%c%c%c%c%cTest", _AT, row, col, _BRIGHT,  _ON, _INK,  RED,  _PAPER, YELLOW);
does exactly the same as the above, it is as though the "_AT" (\x08 22) is not processed...

I am pretty sure I have had this working in the past, I just favoured a faster (much lesser ability) ASM print routine using the ROM call ( fixed 32 column mode), however it does indeed work with the above Print Codes.

So I have had a play for an hour - sadly I cannot fathom what I have done wrong - any ideas would be welcome.
User avatar
dom
Well known member
Posts: 2076
Joined: Sun Jul 15, 2007 10:01 pm

Post by dom »

I can't see your values, but the row/column should be offset by 32: https://github.com/z88dk/z88dk/wiki/Pla ... ole-driver and hence to https://github.com/z88dk/z88dk/wiki/Cla ... ricConsole

Technically the others should be as well, but the code does effectively an "and 7" it doesn't actually matter.
Zetr0
Member
Posts: 60
Joined: Mon Aug 22, 2011 12:38 pm

Post by Zetr0 »

@dom

I suspect you live here ;) - Cheers for the heads up, however I am struggling to get this (the AT command) to work - such that

Code: Select all

printf("\x08%c%c%cTEST", 22, 32, 32 );
This prints in the top left corner of the screen (at cells 0,0), however try as I might I cannot get this to print anywhere else on the screen, clearly I have been missing something.

Code: Select all

printf("\x08%c%c%cTEST", 22, 10,10);
printf("\x08%c%c%cTEST", 22, 5,5);
printf("\x08%c%c%cTEST", 22,40,100);
its matters not what row or column coordinates I use, the AT (\x0822) simply seems to be ignored and only prints in the top left of the screen. its very strange I am sure I had this working on my old install.

I have tried

Code: Select all

fputc( 22, stdout);
followed by

Code: Select all

printf("\x08%c%c", row, col );
Sadly no change, no matter the values of row or col.


If I am not mistaken and I am only assuming, that the 64 column mode that printf() uses is in fact a text render'er that uses bitwise operations to write text/font to the screen in a cell by cell basis. Could this be invoked with an assembly routine ?

This is how I am currently banging it to the screen -

Code: Select all

void asm_print( char *text )
{
     #asm
         ld a,2          ; channel 2 = "S" for screen
         call $1601      ; select print channel using ROM

         ld hl,2
         add hl,sp       ; skip over the return address  (Stack Pointer)

         ld e,(hl)
         inc hl
         ld d,(hl)       ; should = *text

         ex de,hl        ; exchange registers?

         call printtext  ; call printline routine
         ret

         printtext:      ; routine to print out a line
         ld a,(hl)       ; get character to print
         cp 255          ; see if it is terminator char
         jr z,textend    ; were done if it is
         rst 16          ; spectrum: print the character in register 'A'
         inc hl          ; move onto the next character
         jr printtext    ; loop round

         textend:       ; condition met to end the routine
         ret            ; return.

     #endasm

}
The above routine I use predominately for speed, its very basic and the attributes, cursor position(s) are encoded at the beginning of the text string - such that

Code: Select all

void printMSG( struct PrintMessage *msg )
{
     char mindex =0, lindex=0;
     char msg_line[42];

     msg_line[0] = _AT;
     msg_line[1] = msg->row;
     msg_line[2] = msg->col;
     msg_line[3] = _PAPER;
     msg_line[4] = msg->pcol;
     msg_line[5] = _INK;
     msg_line[6] = msg->icol;
     msg_line[7] = _FLASH;
     msg_line[8] = msg->flash;
     msg_line[9] = _BRIGHT;
     msg_line[10] = msg->bright;

     lindex = 11;

     while( msg->msgstr[ mindex ] !='\0')
     {
            msg_line [ lindex ] = msg->msgstr[ mindex ];
            lindex +=1;
            mindex +=1;
     }

     msg_line[ lindex ] = 255;                // asm routine terminator

     asm_print( msg_line );

}
such that I would call this function prior to calling printMSG()

Code: Select all

void print_AT( char row, char col, char pcol, char icol, char flash, char bright, char *str )
{
     int index = 0;
     struct PrintMessage msg;

     setMXY( row, col, msg );

     setMPENS( pcol, icol, msg );
     setMFLASH( flash, msg);
     setMBRIGHT( bright, msg );

     setMTEXT( str, msg );

     printMSG( msg );
}
A simple struct to hold the message.

Code: Select all

struct PrintMessage                     // 44 bytes Print Line encapsulation
{
       char row;
       char col;
       char pcol;
       char icol;
       char flash;
       char bright;
       char msgstr[32];
};
Obviously I do have a quicker, less featured print for debugging -

Code: Select all

void print_char_AT( char row, char col, char *str)
{
     //set message pens
     char mindex =0, lindex=0;
     char msg_line[42];

     struct PrintMessage *msg;

     msg = &Msg;

     msg_line[0] = _AT;
     msg_line[1] = msg->row;
     msg_line[2] = msg->col;

     lindex = 3;

     while( msg->msgstr[ mindex ] !='\0')
     {
            msg_line [ lindex ] = msg->msgstr[ mindex ];
            lindex +=1;
            mindex +=1;
     }

     msg_line[ lindex ] = 255;                // asm routine terminator

     asm_print( msg_line );
}
So where is all this going?

Well I had thought of writing my own text render'er as I would like more information on the screen for the user. Currently I am writing a menu-driven system to create a database of games / applications on the +3e hard disk. This contains the Unit, Partition, Title and File name. from this there is a very simple application launcher loaded from disk, loads records from the database and the user can select what application to run / load.

A very simple (dirty trick) shuffle of data later - the unit, partition and filename are copied to strings defined in BASIC to which BASIC then LOAD $s -

I have so far over 2,000 lines of code with mixed ASM to speed up some of the screen drawing and I am quite excited to complete this, after some optomisations I would like to post some of the project here as it may help others with their coding projects, and to be sincerely honest I have really fallen in love with Z88dk!

So with the current project, I can achieve this in 32 column printing (via ASM) routines however I do like the look and the amount of data that can be put on the screen using the 64 column mode, the more I see it, the more I want it LOL, so any help in getting this working is muchly appreciated.

Thanks for reading this wall of text!
Zetr0
Member
Posts: 60
Joined: Mon Aug 22, 2011 12:38 pm

Post by Zetr0 »

I wonder if it could be my compile line

build.bat

Code: Select all

zcc +zx -startup=5 -lp3 -DPLUS3 -lm -create-app textprint.c >build.txt
User avatar
dom
Well known member
Posts: 2076
Joined: Sun Jul 15, 2007 10:01 pm

Post by dom »

I'm assuming you're running a nightly version.

It might be best to take a look at examples/console/zxterminal.c - it's a little test program that exercises the ZXcodes supported by the console.

The AT command sequence is just 22, y + 32, x +32 - the \x08 you've got there is an additional backspace. An important thing to note is that if either the y or the x is out of bounds then neither will take affect - in your examples all the coordinates you give are out of bounds! The bounds are either 24x64 or 24x32 depending on whether it's in 32 or 64 column mode.

BTW, in conio.h there's some nice shortcuts for setting colour, coordinates etc:

Code: Select all

extern void __LIB__        gotoxy(unsigned int x, unsigned int y) __smallc;
extern void __LIB__        textcolor(int c) __z88dk_fastcall;
extern void __LIB__        textbackground(int c) __z88dk_fastcall;
These can save you writing to fixed bits of the string.

In summary, I think this bit of code:

Code: Select all

     msg_line[0] = _AT;
     msg_line[1] = msg->row;
     msg_line[2] = msg->col;
Should be this:

Code: Select all

     msg_line[0] = _AT;
     msg_line[1] = msg->row + 32;
     msg_line[2] = msg->col + 32;
if you're not using rst 16 to print on screen.
Zetr0
Member
Posts: 60
Joined: Mon Aug 22, 2011 12:38 pm

Post by Zetr0 »

@dom

Thank you, this one had been bugging me so much!

its a relief!
User avatar
dom
Well known member
Posts: 2076
Joined: Sun Jul 15, 2007 10:01 pm

Post by dom »

Zetr0 wrote:I wonder if it could be my compile line

build.bat

Code: Select all

zcc +zx -startup=5 -lp3 -DPLUS3 -lm -create-app textprint.c >build.txt
Sorry, I just spotted this, for classic there's only two startup values: 1 = .TAP file with file loaded to 32768 (by default) and 2 = .ROM file for Interface 2

-startup=5 is a newlib thing.
Zetr0
Member
Posts: 60
Joined: Mon Aug 22, 2011 12:38 pm

Post by Zetr0 »

Image

Thank you!
Post Reply