zx_attr() vs. zx_screenstr()

ZX80, ZX 81, ZX Spectrum, TS2068 and other clones
Post Reply
cha05e90
Member
Posts: 23
Joined: Fri Jan 04, 2019 11:06 am

zx_attr() vs. zx_screenstr()

Post by cha05e90 »

Me again. :-)

I'm working with some of the ZX Spectrum screen functions and stumbled across the different behavior of zx_attr() and zx_screenstr(). While the first one works as expected and returns an usable attribute byte the latter doesn't seem to work at all. Or - to be more precise - it returns usually a "32" (WHITESPACE) for empty screen portions and "0" (ZERO) for anything else, which is not what I expected. Am I doing something wrong here?

Code: Select all

/*
Test for zx_attr()/zx_screenstr().

10 PRINT AT 10,10; PAPER 6;"q"
20 RANDOMIZE USR 60000
30 PRINT alpha,attr

zcc +zx -lm -lndos XXXXXX.c -oXXXXXX.bin -zorg60000
*/

#include <spectrum.h>
#include <stdio.h>

uchar row, col;
uint alpha, attr;

int main(void) {
    row = 10;
    col = 10;
    attr = zx_attr(row,col);
    alpha =  zx_screenstr(row, col);
    zx_setint("alpha", (int)alpha);
    zx_setint("attr",(int)attr);
    return(0);
}
Timmy
Well known member
Posts: 392
Joined: Sat Mar 10, 2012 4:18 pm

Post by Timmy »

No, I don't think you're doing something wrong there...

My guess is that there's a bug in zx_screenstr().

When I replaced the code in zx_screenstr_callee.asm where it said "ld a,8 sub b" into "ld a,b nop nop" then your code seems to work.

(Note that I have not tested this "fix" at all. My replacement is *not* a fix and I seriously doubt it would work in all cases.)
User avatar
dom
Well known member
Posts: 2076
Joined: Sun Jul 15, 2007 10:01 pm

Post by dom »

I've committed your fix Timmy, it's right as far as I can see since b holds the number of rows in the character still to match.

As a note, the same functionality is available via <conio.h> - cvpeek() albeit with reversed parameters.
cha05e90
Member
Posts: 23
Joined: Fri Jan 04, 2019 11:06 am

Post by cha05e90 »

Hi, I just downloaded the lastest nightly build which seem to include dom's fix. Nevertheless a re-build of that little code snippet from above does not show any change. Sadly zx_screenstr() still does not return a valid code (except those standard WHITESPACEs for empty screen portions...).
cha05e90
Member
Posts: 23
Joined: Fri Jan 04, 2019 11:06 am

Post by cha05e90 »

I just tried the <conio.h> alternative, which seems to work (alas you have to switch to the standard ZX Spectrum "32-column-mode"). Thanks for this tip!

Code: Select all

/*
Test for zx_attr()/zx_screenstr()/cvpeek().

10 PRINT AT 10,10; PAPER 6;"q"
20 RANDOMIZE USR 60000
30 PRINT alpha,attr,beta

ITERATION 05

zcc +zx -lm -lndos XXXXXX.c -oXXXXXX.bin -zorg60000
*/

#include <spectrum.h>
#include <stdio.h>
#include <conio.h>

uchar row, col;
uint alpha, attr;
int beta;

int main(void) {
    row = 10;
    col = 10;
    cprintf("\x01\x20"); //switching 32-column mode
    attr = zx_attr(row,col);
    alpha =  zx_screenstr(row, col);
    beta =  cvpeek(row, col);
    zx_setint("alpha", (int)alpha);
    zx_setint("attr",(int)attr);
    zx_setint("beta",beta);
    return(0);
}
Nevertheless it would be nice to have a working zx_screenstr() function...:-)
User avatar
dom
Well known member
Posts: 2076
Joined: Sun Jul 15, 2007 10:01 pm

Post by dom »

I'll admit that I'm not using your test case, but this one:

Code: Select all

// zcc +zx scrtest.c -lndos -create-app -Cl-v -pragma-redirect:fputc_cons=fputc_cons_rom_rst
#include <stdio.h>
#include <spectrum.h>


int main() {
        printf("%c%c%cX",22,10,10);

        printf("\n%d",zx_screenstr(10,10));
        return 0;
}
Which uses the ROM printer routine (so the same as calling from BASIC), prints 88 as expected so I've no idea what's happening for you unless you've not actually updated the library.

As to why the parameters are reversed on cvpeek() - I think that was to match up with gotoxy() and the other conio.h functions
Timmy
Well known member
Posts: 392
Joined: Sat Mar 10, 2012 4:18 pm

Post by Timmy »

screen$ and attr functions only works in 32 column mode, as far as i understand.

other modes are not supported (this is not my code obviously, but anything other than 32 column mode does not make sense at all).
cha05e90
Member
Posts: 23
Joined: Fri Jan 04, 2019 11:06 am

Post by cha05e90 »

dom wrote:...for you unless you've not actually updated the library.
Yeah, I checked again and indeed I'll have the new version. I must admit that i'm a littlebit puzzled, 'cos with my "code" it still doesn't work. Using your test code from above (incl. your build line incl. the pragma directive *and* the create-app) I were able to have the zx_screenstr() function working *once*! I assume there's still something fishy there. If you call the code via RANDOMIZE... a second time (after the "autoload" from the TAP file) you'll see that output and test promptly fails.

In the end I fiddled a littlebit and came to the conclusion that you have to (somehow?!?) have to reset the "cursor" position to make zx_screenstr() work again. This can be done for example via a simple BASIC "PRINT" command. So back to using my own "build" line (without pragma and create-app) I had to tweek the cursor position.

Code: Select all

/*
Test for zx_attr()/zx_screenstr()/cvpeek().

10 PRINT AT 10,10; PAPER 6;"q"
20 RANDOMIZE USR 60000
30 PRINT alpha,attr,beta

ITERATION 07

zcc +zx -lm -lndos XXXXXX.c -oXXXXXX.bin -zorg60000
*/

#include <spectrum.h>
#include <stdio.h>
#include <conio.h>

uchar row, col;
uint alpha, attr;
int beta;

int main(void) {
    row = 10;
    col = 10;
    cprintf("\x01\x20"); //switching 32-column mode
    cprintf("%c%c%c",22,0,0); // re-set cursor
    attr = zx_attr(row,col);
    alpha =  zx_screenstr(row, col);
    beta =  cvpeek(col, row);
    zx_setint("alpha", (int)alpha);
    zx_setint("attr",(int)attr);
    zx_setint("beta",beta);
    return(0);
}
cha05e90
Member
Posts: 23
Joined: Fri Jan 04, 2019 11:06 am

Post by cha05e90 »

Timmy wrote:screen$ and attr functions only works in 32 column mode, as far as i understand.

other modes are not supported (this is not my code obviously, but anything other than 32 column mode does not make sense at all).
Yes, seems so - which is indeed my "use case" (standard ZX Spectrum 32 column screen). But as dom said, the conio functions can do the same even for 64 column screens - really nice!
User avatar
dom
Well known member
Posts: 2076
Joined: Sun Jul 15, 2007 10:01 pm

Post by dom »

I spent a while chasing a weird problem and then realised fuse was emulating a Timex machine.

Anyway, I think what happens when you run from the basic prompt is that the K channel is the currently active one - so the wrong things appear on screen, thus you have to reset the cursor. We used to have ld a,2 ; call 5633 in the crt0 but it got removed a long time ago.
cha05e90
Member
Posts: 23
Joined: Fri Jan 04, 2019 11:06 am

Post by cha05e90 »

dom wrote:We used to have ld a,2 ; call 5633 in the crt0 but it got removed a long time ago.
Ah, ok - the channel/stream opening... I did not know that, but "resetting" that isn't a big deal. Thanks for caring!
Post Reply