Help porting spectranet code to current release

ZX80, ZX 81, ZX Spectrum, TS2068 and other clones
Post Reply
Guesser
Member
Posts: 52
Joined: Mon Nov 21, 2011 2:00 pm

Help porting spectranet code to current release

Post by Guesser »

With the excitement of an imminent new batch of spectranets, I've been trying to get stuff compiling again.

I'd previously ported the spectranet and socklib libraries to the new z80asm syntax, but never got the libhttp to work. The former are written in asm, but libhttp is all C.
I can build the library with a couple of small ammendments (a missing header and adding missing "struct" in a sizeof(), but the resulting lib doesn't link.
Trying to compile the twitter example (which no longer works because they changed the API, but that's beside the point) just gives a screen full of errors of the form:

Code: Select all

Error at file 'foo.c' line xx: symbol '_bar' not defined
Is there a chance it's something obvious?

Unfortunately the original subversion repo has been inaccessible for a number of years and the only way to download the code is via http://spectrum.alioth.net/svn/listing. ... &path=%2F&
Guesser
Member
Posts: 52
Joined: Mon Nov 21, 2011 2:00 pm

Post by Guesser »

the makefile looks like this:

Code: Select all

# Makefile for the simple HTTP library.
LIBNAME = libhttp
COBJS = addFormData.o freeFormData.o parseURI.o parseproto.o \
        allocURI.o freeURI.o base64enc.o request.o readData.o \
        postsize.o getheader.o freeheaders.o readHeaders.o htrecv.o
CFLAGS = +zx -I./include -O2 -preserve -vn

all:        $(COBJS)
        $(LIBLINKER) $(LIBLDFLAGS) -x$(LIBNAME) $(COBJS)

install:
        $(CP) *.lib $(Z80_OZFILES)/clibs
        $(CP) -r ./include $(Z80_OZFILES)/../

include ../make.inc
User avatar
dom
Well known member
Posts: 2076
Joined: Sun Jul 15, 2007 10:01 pm

Post by dom »

I've obviously not compiled everything, but the errors I see are along the lines of:

Code: Select all

Error at file 'readHeaders.c' line 140: symbol '_headerbuf' not defined

include/http.h:

extern char *headerbuf;

readData.c:

static char *headerbuf;
i.e. what should be a global variable isn't exported from the file it's declared in.
User avatar
dom
Well known member
Posts: 2076
Joined: Sun Jul 15, 2007 10:01 pm

Post by dom »

Guesser wrote:With the excitement of an imminent new batch of spectranets, I've been trying to get stuff compiling again.
I've wanted one of those for years - where can I get hold of one?
Guesser
Member
Posts: 52
Joined: Mon Nov 21, 2011 2:00 pm

Post by Guesser »

dom wrote:
Guesser wrote:With the excitement of an imminent new batch of spectranets, I've been trying to get stuff compiling again.
I've wanted one of those for years - where can I get hold of one?
Nowhere yet, but Ben Versteeg of bytedelight.com will be producing a batch Soon?
Guesser
Member
Posts: 52
Joined: Mon Nov 21, 2011 2:00 pm

Post by Guesser »

dom wrote:i.e. what should be a global variable isn't exported from the file it's declared in.
And how would one go about doing that now? I assume the old -make-lib argument took care of that.
User avatar
dom
Well known member
Posts: 2076
Joined: Sun Jul 15, 2007 10:01 pm

Post by dom »

Guesser wrote:
dom wrote:i.e. what should be a global variable isn't exported from the file it's declared in.
And how would one go about doing that now? I assume the old -make-lib argument took care of that.
Just drop the static qualifier on the variable in readData.c - I guess there was a bug many years ago where static didn?t mean ?don?t export?.
Guesser
Member
Posts: 52
Joined: Mon Nov 21, 2011 2:00 pm

Post by Guesser »

Thanks, that appears to have sorted everything. To really test stuff I'd have to write a program using the library since as far as I'm aware the only code that does is the defunct twitter client.

One thing that caught me out to begin with was the new colour codes. I was just about to start a bug thread on here when I found -pragma-define:CLIB_CONIO_NATIVE_COLOUR=1 :lol:


One other issue that I've had to work around is in the spectank capture the flag game.
In the matchmaking client the input loop scans for keypresses and when '1' or '2' are pressed it calls sendJoinTeam(0); or sendJoinTeam(1);

That function looks like this:

Code: Select all

int sendJoinTeam(uchar team) {
        zx_border(INK_RED);
        sendbuf[0]=TEAMREQUEST;
        sendbuf[1]=team;
        zx_border(INK_BLACK);
        return sendMsg(2);
}
For some reason that is putting '1' or '2' into sendbuf[1] instead of 0 and 1. If I printf("%d", team); it outputs 0 and 1 rather than 49 and 50.

I fixed it by changing the code to:

Code: Select all

int sendJoinTeam(int team) {
        zx_border(INK_RED);
        sendbuf[0]=TEAMREQUEST;
        sendbuf[1]=(uchar)team;
        zx_border(INK_BLACK);
        return sendMsg(2);
}
User avatar
dom
Well known member
Posts: 2076
Joined: Sun Jul 15, 2007 10:01 pm

Post by dom »

That was a good one - there was a bug in the optimisation rules (it's been a long time since there's been one of those) which meant the -O2 code was pulling the team variable from the wrong place in the stack. I've raised and fixed https://github.com/z88dk/z88dk/issues/1126
Guesser
Member
Posts: 52
Joined: Mon Nov 21, 2011 2:00 pm

Post by Guesser »

Hurrah!

What conditions triggered the bug? (If that's a question that makes sense to ask from the perspective of some C code)
User avatar
dom
Well known member
Posts: 2076
Joined: Sun Jul 15, 2007 10:01 pm

Post by dom »

It's copying a byte from the stack into a static buffer followed by a ld hl, the following example shows it:

Code: Select all

unsigned char buf[10];

void extra(unsigned char *);

void func(unsigned char x)
{
   buf[1] = x;
   extra(buf);
}
This generates the following at -O0:

Code: Select all

._func
        ld      hl,_buf
        inc     hl
        push    hl
        ld      hl,4    ;const
        add     hl,sp
        ld      l,(hl)
        ld      h,0
        ld      h,0
        pop     de
        ld      a,l
        ld      (de),a
        ld      hl,_buf
        push    hl
        call    _extra
        pop     bc
        ret
Which is is correct, but obviously can have some efficiencies applied, which is what happens at -O2:

Code: Select all

; Function func flags 0x00000200 __smallc
; void func(unsigned char x)
; parameter 'unsigned char x' at 2 size(1)
._func
        ld      de,_buf+1
        ld      hl,4    ;const
        add     hl,sp
        ld      a,(hl)
        ld      (de),a
        ld      hl,_buf
        push    hl
        call    _extra
        pop     bc
        ret
You can see a push/pop cycle has been removed, but the ld hl,4: add hl,sp which was inside the push/pop it hasn't been modified so now references a variable in the calling frame.
Post Reply