Random crashes

ZX80, ZX 81, ZX Spectrum, TS2068 and other clones
Post Reply
baltasarq
Member
Posts: 34
Joined: Wed May 11, 2016 7:53 pm

Random crashes

Post by baltasarq »

Hi,

I'm developing a text-based game with some graphics for the ZX Spectrum (i.e., 48k), using a command-key-press-like input.
The problem is that the game runs and pasts the presentation screen, but then it sometimes immediately gets stuck, or maybe after a key presses.

My guesses so far are:
a) I've a bug I don't know about, specifically a crazy pointer.
b) I've reached some memory limit. My program's size is of around 21kb. Don't know what its the max size.
c) Somehow the input (in_Input) or output (fputc_cons/println) crash [see some warnings below].

Github code:
https://github.com/Baltasarq/reveni

So, I'd like to be able to discard something. Any idea? Follows the makefile and the compilation output.
Note that the game does not use the standard stdio, but it does use the library fputc_cons instead of the ROM one in order to be able to do effects such as relocate the cursor, clear the screen, change text color, etc.

Part of the code is reused from a previous classic text game, Bares.
Thanks in advance for any hint.

Code: Select all

CC=zcc
CFLAGS=+zx
OBJ=obj

all: reveni

reveni: reveni.c ctrl player locs objs cmds
	$(CC) $(CFLAGS) -create-app reveni.c $(OBJ)/ctrl.o  $(OBJ)/player.o  $(OBJ)/locs.o  $(OBJ)/objs.o  $(OBJ)/cmds.o -oreveni -pragma-define:CLIB_CONIO_NATIVE_COLOUR=1 -pragma-define:CRT_ENABLE_STDIO=0 -pragma-redirect:fputc_cons=fputc_cons_generic

ctrl: ctrl.h ctrl.c
	$(CC) $(CFLAGS) -c ctrl.c -o $(OBJ)/ctrl.o

player: player.h player.c
	$(CC) $(CFLAGS) -c player.c -o $(OBJ)/player.o

locs: locs.h locs.c
	$(CC) $(CFLAGS) -c locs.c -o $(OBJ)/locs.o

objs: objs.h objs.c
	$(CC) $(CFLAGS) -c objs.c -o $(OBJ)/objs.o

cmds: cmds.h cmds.c
	$(CC) $(CFLAGS) -c cmds.c -o $(OBJ)/cmds.o

clean:
	$(RM) $(OBJ)/*.o
	$(RM) reveni
	$(RM) *.tap
	$(RM) *.cpc
	$(RM) *.dsk
	$(RM) *.bin
	$(RM) *.def
	$(RM) *.reloc

run:
	fuse reveni.tap &
The compilation output follows. Here is where things are somehow weirs due to the warning about fputc_cons, though I include spectrum.h, in objs.c and cmds.c, but not in ctrl.c, for instance.

Code: Select all

zcc +zx -c ctrl.c -o obj/ctrl.o
zcc +zx -c player.c -o obj/player.o
zcc +zx -c locs.c -o obj/locs.o
zcc +zx -c objs.c -o obj/objs.o
objs.c:167:24: warning: Implicit definition of function 'fputc_cons' it will return an int. Prototype it explicitly if this is not what you want. [-Wimplicit-function-definition]
zcc +zx -c cmds.c -o obj/cmds.o
cmds.c:185:56: warning: Implicit definition of function 'fputc_cons' it will return an int. Prototype it explicitly if this is not what you want. [-Wimplicit-function-definition]
zcc +zx -create-app reveni.c obj/ctrl.o  obj/player.o  obj/locs.o  obj/objs.o  obj/cmds.o -oreveni -pragma-define:CLIB_CONIO_NATIVE_COLOUR=1 -pragma-define:CRT_ENABLE_STDIO=0 -pragma-redirect:fputc_cons=fputc_cons_generic
reveni.c:33:13: warning: Implicit definition of function 'fputc_cons' it will return an int. Prototype it explicitly if this is not what you want. [-Wimplicit-function-definition]
User avatar
dom
Well known member
Posts: 1559
Joined: Sun Jul 15, 2007 10:01 pm

Re: Random crashes

Post by dom »

fputc_cons is defined in <stdio.h> hence the warning. I don't think that's the source of the problems though. Likewise you should be able to go up to 32k in program size without any issues (since you've got an origin of 32768)

With random pressing I've not managed to make it crash so the only thought I've got about crashing is the handling of iy. circle() uses iy, but doesn't restore it. It looks like you've got ROM interrupts on and that expects iy to have the value 23610. Given that draw_circle adjusts iy to point to the stack, then you could end up with random stack corruption which might crash.

So, if you remove the circle() calls does it still crash?
baltasarq
Member
Posts: 34
Joined: Wed May 11, 2016 7:53 pm

Re: Random crashes

Post by baltasarq »

Hi dom,
dom wrote: Wed Dec 29, 2021 1:55 pm fputc_cons is defined in <stdio.h> hence the warning. I don't think that's the source of the problems though.
Yep, but I was truly desperate.
Likewise you should be able to go up to 32k in program size without any issues (since you've got an origin of 32768)
Interesting. Can you change the origin of the program? I guess that you have to be careful not to use the screen and some other memory parts.
I see in the Speccy manual that there is a quite big chunk of memory that you can use. Unfortunately, the UDG area is just before 32768, so I guess if you moved the origin then you would not be able to use them.
With random pressing I've not managed to make it crash so the only thought I've got about crashing is the handling of iy. circle() uses iy, but doesn't restore it. Given that draw_circle adjusts iy to point to the stack, then you could end up with random stack corruption which might crash.

So, if you remove the circle() calls does it still crash?
And that was it. It now works perfectly, after commenting out the calls to circle() and fill() (since it'd have filled the entire screen).
How could I call circle() without these problems?
It looks like you've got ROM interrupts on and that expects iy to have the value 23610.
Can I set ROM interrupts off? Would that help? Do I need them in my program?

Thanks a lot. I've been working intermittently in the code for more than a year without being able to figure the bug out. Yeah, the bug appeared after I added the graphics, but I could not have imagined calling circle() would provoke that mess...

-- Baltasar
User avatar
dom
Well known member
Posts: 1559
Joined: Sun Jul 15, 2007 10:01 pm

Re: Random crashes

Post by dom »

baltasarq wrote: Wed Dec 29, 2021 6:13 pmInteresting. Can you change the origin of the program?
Of course! Just add -pragma-define:CRT_ORG_CODE=24576 and you'll get an extra 8k of space. It'll be contended memory but for an adventure game I don't think that will affect you that much.

UDGs are actually wherever you want them to be, by default they'll pick them up from the BASIC location which is 65368d but you can point the screen driver to a different address.
And that was it. It now works perfectly, after commenting out the calls to circle() and fill() (since it'd have filled the entire screen).
How could I call circle() without these problems?
Sometimes hunches are the greatest things!

I'll switch out the circle implementation for the portable version which is used on 808x targets - that'll sidestep the issue.
Can I set ROM interrupts off? Would that help? Do I need them in my program?
I suspect you do for reading the keyboard. Until I fix the library above, you could fudge with an interposer function along the lines of (I've not tested this at all, but you can see the idea):

Code: Select all

void mycircle(int x, int y, int radius, int skip) __smallc
{
__asm
    di
__endasm;
    circle(x,y,radius,skip);
__asm
    ld iy,23610
    ei
__endasm;
}
baltasarq
Member
Posts: 34
Joined: Wed May 11, 2016 7:53 pm

Re: Random crashes

Post by baltasarq »

Hi dom,
dom wrote: Wed Dec 29, 2021 6:30 pm
baltasarq wrote: Wed Dec 29, 2021 6:13 pmInteresting. Can you change the origin of the program?
Of course! Just add -pragma-define:CRT_ORG_CODE=24576 and you'll get an extra 8k of space. It'll be contended memory but for an adventure game I don't think that will affect you that much.
Yep, it works without any issue. That's great.
UDGs are actually wherever you want them to be, by default they'll pick them up from the BASIC location which is 65368d but you can point the screen driver to a different address.
I am not really sure whether I want to use them or not. The problem, I guess, is to be able to create attractive graphics or not. So I don't know whether I will need them, mix them with circles/lines/plot...

Where can I find a step by step tutorial on how to use UDG?
And that was it. It now works perfectly, after commenting out the calls to circle() and fill() (since it'd have filled the entire screen).
How could I call circle() without these problems?
Sometimes hunches are the greatest things!
Thank you again.
Can I set ROM interrupts off? Would that help? Do I need them in my program?
I suspect you do for reading the keyboard.
Sure, silly of me!
I'll switch out the circle implementation for the portable version which is used on 808x targets - that'll sidestep the issue.
Until I fix the library above, you could fudge with an interposer function along the lines of (I've not tested this at all, but you can see the idea):

Code: Select all

void mycircle(int x, int y, int radius, int skip) __smallc
{
__asm
    di
__endasm;
    circle(x,y,radius,skip);
__asm
    ld iy,23610
    ei
__endasm;
}
Well, it works, but the lower part of the screen now shows blocks with different color attributes. They seem to roll while the circle is being drawn. Now it does not crash, though.
From my limited assembly knowledge, I guess you are saving and loading iy.
My question is... should not be easier to use the circle routine in ROM? The one that is called from BASIC? Or is it too slow?
All right, I answer myself after seeing this project. It is really slow.
User avatar
dom
Well known member
Posts: 1559
Joined: Sun Jul 15, 2007 10:01 pm

Re: Random crashes

Post by dom »

Sorry I forgot to get back onto this thread.

Back when this issue was raised, I adjusted the circle() routine so that it only uses a single index register which makes it compatible with our self-imposed policy of only using a single index register in the libraries.
baltasarq
Member
Posts: 34
Joined: Wed May 11, 2016 7:53 pm

Re: Random crashes

Post by baltasarq »

Hi, Dom
dom wrote: Fri Jan 14, 2022 7:47 pm Sorry I forgot to get back onto this thread.

Back when this issue was raised, I adjusted the circle() routine so that it only uses a single index register which makes it compatible with our self-imposed policy of only using a single index register in the libraries.
But... What do you mean with that?
Sorry.
-- Baltasar
baltasarq
Member
Posts: 34
Joined: Wed May 11, 2016 7:53 pm

Re: Random crashes

Post by baltasarq »

Where can I find a tutorial about creating UDG with a font?
User avatar
dom
Well known member
Posts: 1559
Joined: Sun Jul 15, 2007 10:01 pm

Re: Random crashes

Post by dom »

But... What do you mean with that?
It means that circle() should now work without any need for a workaround.

[Classic supports many machines where the firmware reserves an index register: for example +zx and the iy register (for system variables), +zx81 needs the ix register for the display. As a result, the library is meant to only use a single index register so that we don't run into the problems you ran into. Unfortunately circle() ended up using both ix and iy]

There's some information about UDGs here: https://github.com/z88dk/z88dk/wiki/Cla ... ining-udgs, and a version of DStar that uses UDGS is here: https://github.com/z88dk/z88dk/blob/mas ... r_gencon.c

Since you're creating an adventure game, then an alternate way might be to use SVG graphics (converted of course!): https://github.com/z88dk/z88dk/wiki/Cla ... fxprofileh Stefano added some to Adventure A the you compile with -DPICS: https://github.com/z88dk/z88dk/blob/mas ... le/adv_a.c
baltasarq
Member
Posts: 34
Joined: Wed May 11, 2016 7:53 pm

Re: Random crashes

Post by baltasarq »

Hi Dom,
dom wrote: Fri Jan 14, 2022 9:28 pm
But... What do you mean with that?
It means that circle() should now work without any need for a workaround.
The problem is what I described previously: there are blocks of attributes rolling in the last line. The program works, but this effect is really bothering.
Since you're creating an adventure game, then an alternate way might be to use SVG graphics (converted of course!): https://github.com/z88dk/z88dk/wiki/Cla ... fxprofileh Stefano added some to Adventure A the you compile with -DPICS: https://github.com/z88dk/z88dk/blob/mas ... le/adv_a.c
¡Really interesting! I was actually looking for something like that. I have to experiment a little bit, but probably choose vector graphics.
Thanks,
-- Baltasar
User avatar
dom
Well known member
Posts: 1559
Joined: Sun Jul 15, 2007 10:01 pm

Re: Random crashes

Post by dom »

baltasarq wrote: Mon Jan 17, 2022 12:18 pmThe problem is what I described previously: there are blocks of attributes rolling in the last line. The program works, but this effect is really bothering.
I can't seem to reproduce that - can you attach the binary and .map file generated and I'll see what's happening.
baltasarq
Member
Posts: 34
Joined: Wed May 11, 2016 7:53 pm

Re: Random crashes

Post by baltasarq »

Hi Dom,
dom wrote: Mon Jan 17, 2022 10:19 pm
baltasarq wrote: Mon Jan 17, 2022 12:18 pmThe problem is what I described previously: there are blocks of attributes rolling in the last line. The program works, but this effect is really bothering.
I can't seem to reproduce that - can you attach the binary and .map file generated and I'll see what's happening.
I've verified that is a problem wit circle() commenting it out: the attribute blocks do not appear.
The Github url, in case you want to download and compile the game.
I have attached the files you requested.

Thank you!
-- Baltasar
You do not have the required permissions to view the files attached to this post.
User avatar
dom
Well known member
Posts: 1559
Joined: Sun Jul 15, 2007 10:01 pm

Re: Random crashes

Post by dom »

After you updated the repo I've managed to reproduce it.

Looking at the colours it looks like the stack is intruding onto the display - this is due to how the fill() routine uses the stack. The fill routine reserves 192 *8 = 1536 bytes on the stack which, takes it down into the attribute memory (say 24576 - 1536 = 23040, attribute memory ends at 23296)

It's shown up by moving the code from 32768 to 24576 which is why I couldn't reproduce it!
baltasarq
Member
Posts: 34
Joined: Wed May 11, 2016 7:53 pm

Re: Random crashes

Post by baltasarq »

Oh dear. I also commented out fill because otherwise it would've filled the whole screen.
I see.
Okay, so I changed the program from 24576 to 24576 + 1536 = 26112, and yes, problem solved!
Many thanks,
-- Baltasar
Post Reply