FBS (or, an experiment of updating old code) (+source +game)

ZX80, ZX 81, ZX Spectrum, TS2068 and other clones
Post Reply
Timmy
Well known member
Posts: 392
Joined: Sat Mar 10, 2012 4:18 pm

FBS (or, an experiment of updating old code) (+source +game)

Post by Timmy »

While I was looking at some old thread this week, I found an old experiment of mine from 2014, called FBS.

So I decided to see if this still compiles in 2021, using the 2.1 official version (shouldn't matter that much in this case.) ;)

Source code and compiled version in enclosed in the zip file.
If you're not interested in the technical details of porting to 2021, then it's also fine to just play with it or read the (really old) code. :cool:

Anyway, it seems the differences between the 2012(!) and the 2021 compiler in this case, are very minimal, but important. And here they were all about the inline assembly functions. (PS. I kept the compiler options the same for the old and the current compilers.)

1) __CALLEE__ behaviour has changed. Back then the behaviour of callee was that the inline assembly code is responsible for the popping of the parameters. The current 2.1 instead adds all the POPs at the end of the callee function. So I added "ret"s at the end of each callee function so that those new POPs won't be invoked.

2) __FASTCALL__ behaviour has changed too. Back then all parameter declarations in the fastcall were ignored. In 2.1, inline fastcall functions with an input parameter starts with "push hl" instead of nothing. (and probably ends with something too, not checked). It seems that removing the parameter declaration will remove the push.

3) Oh, and the resulting tap file is twice the size now. No idea why. (No I haven't included the symbols or other output. I have no idea how to generate them. But I can generate them if you need them.) :)

I wonder why these things were changed. I can adapt to the function behaviour changes, but I'm worried about the size blow up.
You do not have the required permissions to view the files attached to this post.
User avatar
dom
Well known member
Posts: 2076
Joined: Sun Jul 15, 2007 10:01 pm

Re: FBS (or, an experiment of updating old code) (+source +game)

Post by dom »

Timmy wrote: Sun Mar 07, 2021 3:18 pm Anyway, it seems the differences between the 2012(!) and the 2021 compiler in this case, are very minimal, but important. And here they were all about the inline assembly functions. (PS. I kept the compiler options the same for the old and the current compilers.)
Wow, sccz80 has got a lot stricter over the years so congrats on not using any of the dodgy constructs that used to be supported!
1) __CALLEE__ behaviour has changed. Back then the behaviour of callee was that the inline assembly code is responsible for the popping of the parameters. The current 2.1 instead adds all the POPs at the end of the callee function. So I added "ret"s at the end of each callee function so that those new POPs won't be invoked.

2) __FASTCALL__ behaviour has changed too. Back then all parameter declarations in the fastcall were ignored. In 2.1, inline fastcall functions with an input parameter starts with "push hl" instead of nothing. (and probably ends with something too, not checked). It seems that removing the parameter declaration will remove the push.
That's actually easy to sort out - for a function that's written in assembler but framed in C, you need to mark the function as __naked This was introduced a while back for source compatibly with zsdcc.
3) Oh, and the resulting tap file is twice the size now. No idea why. (No I haven't included the symbols or other output. I have no idea how to generate them. But I can generate them if you need them.) :)
The best options to use when investigating this are "-Cl-v -m" the first one turns up the logging on the linker and second generates the map file.

Lets run through it (using whatever I've got in my environment)

Code: Select all

zcc +zx -zorg=24000 -create-app w1.c -Cl-v    -> 3843 bytes

Linking library module 'in_Inkey'
Linking library module 'in_keytranstbl'
Linking library module 'fputc_cons_generic_full'
Linking library module 'generic_console_attrs'
Linking library module 'generic_console_printc'
Linking library module 'generic_console_cls'
Linking library module 'console_vars'
Linking library module 'code_clib'
Linking library module 'console_vars'
Linking library module 'CRT_FONT'
Linking library module 'CRT_FONT_64'
Linking library module 'generic_console_scrollup'
Linking library module 'console_coords'
Linking library module 'gencon_vars_asm'
Linking library module 'zx_border'
Linking library module 'rand'
Linking library module 'asm_rand'
Linking library module '__stdlib_seed'
Linking library module 'asm_random_uniform_xor_32'
Linking library module 'l_gintspsp'
Linking library module 'l_gt'
Linking library module 'l_compare_result'
Linking library module 'l_lneg'
Running this I can see that the z88dk screen printer is being pulled in, and given that you're hitting rst 16 yourself we could do with disabling it.

Code: Select all

zcc +zx -zorg=24000 -create-app w1.c -Cl-v -pragma-define:fputc_cons=0 -Cl-v -> 2201 bytes
So we're immediately getting towards the right area. Let's see where the memory has got to (using the -Cl-v output):

Code: Select all

Section 'code_crt_init' size: 42 bytes ($5E8D to $5EB6)
Section 'code_crt_exit_exit' size: 1 bytes ($5EB8 to $5EB8)
Section 'code_compiler' size: 1251 bytes ($5EB9 to $639B)
Section 'code_clib' size: 227 bytes ($639C to $647E)
Section 'code_crt0_sccz80' size: 40 bytes ($647F to $64A6)
Section 'code_stdlib' size: 66 bytes ($648C to $64CD)
Section 'data_compiler' size: 6 bytes ($658F to $6594)
Section 'bss_crt' size: 105 bytes ($6595 to $65FD)
Section 'bss_compiler' size: 11 bytes ($65FE to $6608)
So we know that back in 2012, we didn't do any initialisation of BSS memory, let's remove the initialisation in 2021:

Code: Select all

zcc +zx -zorg=24000 -create-app w1.c -Cl-v -pragma-define:fputc_cons=0 -pragma-define:CRT_INITIALIZE_BSS=0 -Cl-v -> 2189 bytes

Section 'code_crt_init' size: 30 bytes ($5E8D to $5EAA)
Not much saving there, let's look at bss_crt though, it's fairly large and will mostly be made of the FILE handles. The size of these has grown over the years, you're not using them, so lets get rid of them:

Code: Select all

zcc +zx -zorg=24000 -create-app w1.c -Cl-v -pragma-define:fputc_cons=0 -pragma-define:CRT_INITIALIZE_BSS=0 -pragma-define:CRT_ENABLE_STDIO=0 -Cl-v -> 2074 bytes

Section 'code_crt_init' size: 15 bytes ($5E8D to $5E9B)
Section 'bss_crt' size: 5 bytes ($657A to $657E)
We're still above the original size from back in 2012, I know the random number routine changed so that will be a few bytes (probably 30ish), there's still some initialisation changes but the biggest chunk can be seen when we do a disassembly:

Code: Select all

z88dk-dis -x a.map -o 24000 a.bin

loadbanks:
                    ld      ix,$c000                        ;[5df2] dd 21 00 c0
                    ld      de,$0000                        ;[5df6] 11 00 00
                    ld      c,$10                           ;[5df9] 0e 10
                    call    load_block                      ;[5dfb] cd 66 5e
                    ret     c                               ;[5dfe] d8
....
That's the code to load data into the 128k banks in total it's 155 bytes. It looks like it's always included and there's no way to switch it off. So I'll try to add some code to only include it if it's needed.
User avatar
dom
Well known member
Posts: 2076
Joined: Sun Jul 15, 2007 10:01 pm

Re: FBS (or, an experiment of updating old code) (+source +game)

Post by dom »

Actually, there is a way to switch off that loader:

Code: Select all

zcc +zx -zorg=24000 -create-app w1.c -Cl-v -pragma-define:fputc_cons=0 -pragma-define:CRT_INITIALIZE_BSS=0 -pragma-define:CRT_ENABLE_STDIO=0 -pragma-define:CRT_DISABLELOADER=1 -Cl-v -m -> 1916 bytes
So we're now smaller than it was in 2012, some tweaking needed obviously but there are a few more features than there were back in 2012!
Timmy
Well known member
Posts: 392
Joined: Sat Mar 10, 2012 4:18 pm

Re: FBS (or, an experiment of updating old code) (+source +game)

Post by Timmy »

dom wrote: Sun Mar 07, 2021 5:22 pm
Timmy wrote: Sun Mar 07, 2021 3:18 pm Anyway, it seems the differences between the 2012(!) and the 2021 compiler in this case, are very minimal, but important. And here they were all about the inline assembly functions. (PS. I kept the compiler options the same for the old and the current compilers.)
Wow, sccz80 has got a lot stricter over the years so congrats on not using any of the dodgy constructs that used to be supported!
Well, this was the easiest of the codes. I'm sure there will be some more "dodgy constructs" later on, but since many of my games almost fully used the 48k memory, I haven't tried converting them yet. Maybe one day.
1) __CALLEE__ behaviour has changed. Back then the behaviour of callee was that the inline assembly code is responsible for the popping of the parameters. The current 2.1 instead adds all the POPs at the end of the callee function. So I added "ret"s at the end of each callee function so that those new POPs won't be invoked.

2) __FASTCALL__ behaviour has changed too. Back then all parameter declarations in the fastcall were ignored. In 2.1, inline fastcall functions with an input parameter starts with "push hl" instead of nothing. (and probably ends with something too, not checked). It seems that removing the parameter declaration will remove the push.
That's actually easy to sort out - for a function that's written in assembler but framed in C, you need to mark the function as __naked This was introduced a while back for source compatibly with zsdcc.
I had just some testing with __naked, and it seems that its behaviour is a bit different than the old compiler.
In short, the old compiler always added a RET at the end of every callee or fastcall function. Naked functions are completely naked, i.e. without a RET at the end.
I agree that it is a better solution, but it is still different than it was before, so I'd still need to append a RET at the end of every inline fastcall and callee function when I'm converting them. Good to know.

===========

And since it's already past 1AM over here, I'll just brainstorm a bit about the rest of your reply...

1) So many options to just make the code smaller for games.
2) Can I use #pragma inside my source code instead, for example like "#pragma fputc_cons 0"?
3) I can't even remember we have a feature to load data into 128k banks? I thought the idea was to load them externally and use bank switching in your own code?
4) Also why is the 128k banks loading option even a default?
5) Thanks a lot to explain all these pragma defines! I don't think most of us would figure them out. They are all useful, too!
6) And I also wonder whether it makes sense to just make some of those defines to be defaults, or since most people are writing games zith z88dk nowadays anyway. Or some simple way to explain to people that these are the default options when you make games.
7) I'll check the -Cl-v option later.

Sorry for the brainstorming, but my brain is telling me to go to sleep and I don't want to forget any of these things.

Thank you so much for all the explanations! This will save some unnecessary bytes (which is really important when making games on the 48k.)
User avatar
dom
Well known member
Posts: 2076
Joined: Sun Jul 15, 2007 10:01 pm

Re: FBS (or, an experiment of updating old code) (+source +game)

Post by dom »

Timmy wrote: Mon Mar 08, 2021 1:10 amWell, this was the easiest of the codes. I'm sure there will be some more "dodgy constructs" later on, but since many of my games almost fully used the 48k memory, I haven't tried converting them yet. Maybe one day.
Yeah, I saw it was mostly asm! I suspect 90% of the trouble will be around the following areas:

1. Function pointers being defined as a void * pointer (which we've run into in the past)
2. Struct pointers
3. sdcc harmonisation

And of course the default size being bigger now than they used to be; which is what this thread is about!
I had just some testing with __naked, and it seems that its behaviour is a bit different than the old compiler.
In short, the old compiler always added a RET at the end of every callee or fastcall function. Naked functions are completely naked, i.e. without a RET at the end.
I agree that it is a better solution, but it is still different than it was before, so I'd still need to append a RET at the end of every inline fastcall and callee function when I'm converting them. Good to know.
That's a good point that now I remember bit me a couple of times. I guess that's another reason why AA recommended not embedding asm in C files!
1) So many options to just make the code smaller for games.
2) Can I use #pragma inside my source code instead, for example like "#pragma fputc_cons 0"?
3) I can't even remember we have a feature to load data into 128k banks? I thought the idea was to load them externally and use bank switching in your own code?
4) Also why is the 128k banks loading option even a default?
5) Thanks a lot to explain all these pragma defines! I don't think most of us would figure them out. They are all useful, too!
6) And I also wonder whether it makes sense to just make some of those defines to be defaults, or since most people are writing games zith z88dk nowadays anyway. Or some simple way to explain to people that these are the default options when you make games.
1 and 6, I think the philosophy is really to make everything work by default and then prune when it's needed - can you imagine the grief we'd get if printf didn't work by default for example? Unfortunately with stdio we've sort of hung ourselves: back before we added sections we couldn't move the FILE block out into the library so an option as added to change the number of files. Now we've got sections we can't move the FILE block into the library because of the option to change the number of files since you can't change the size of a defs block based on a symbol defined elsewhere.

3. Yes, it was added last year sometime when I was doing all the banking stuff - I wanted a way to test that what I was doing worked across multiple platforms. And 4, it's a default because there's no way to exclude code based on a linker evaluation. It has no effect if there are no banks defined, PS -subtype=plus3 will load the banks from disc instead of tape.

5. I think most of them are detailed here: https://github.com/z88dk/z88dk/wiki/Classic--Pragmas
User avatar
dom
Well known member
Posts: 2076
Joined: Sun Jul 15, 2007 10:01 pm

Re: FBS (or, an experiment of updating old code) (+source +game)

Post by dom »

Oh, I forgot to say, yes #pragma can go into the C file or a separate file.

The separate file is the best way for incremental builds, see the top of: https://github.com/z88dk/z88dk/wiki/Classic--Pragmas

One thing that's missing is the format within files, it's:

Code: Select all

-pragma-define:XYZ=1 -> #pragma define XYZ=1
etc
Timmy
Well known member
Posts: 392
Joined: Sat Mar 10, 2012 4:18 pm

Re: FBS (or, an experiment of updating old code) (+source +game)

Post by Timmy »

dom wrote: Sun Mar 07, 2021 6:21 pm

Code: Select all

zcc +zx -zorg=24000 -create-app w1.c -Cl-v -pragma-define:fputc_cons=0 -pragma-define:CRT_INITIALIZE_BSS=0 -pragma-define:CRT_ENABLE_STDIO=0 -pragma-define:CRT_DISABLELOADER=1 -Cl-v -m -> 1916 bytes
dom wrote: Mon Mar 08, 2021 8:41 am
Timmy wrote: Mon Mar 08, 2021 1:10 am 5) Thanks a lot to explain all these pragma defines! I don't think most of us would figure them out. They are all useful, too!
5. I think most of them are detailed here: https://github.com/z88dk/z88dk/wiki/Classic--Pragmas
Just had a quick check on this one:

-pragma-define:fputc_cons=0 ==> not found.
-pragma-define:CRT_INITIALIZE_BSS=0 ==> found!
-pragma-define:CRT_ENABLE_STDIO=0 ==> not found, but there was a CRT_ENABLED_STDIO, likely a typo.
-pragma-define:CRT_DISABLELOADER=1 ==> not found.

1 out of 4, still not too bad. ;)

Also, I don't have to use -Cl-v twice in the above zcc command, right?
Timmy
Well known member
Posts: 392
Joined: Sat Mar 10, 2012 4:18 pm

Re: FBS (or, an experiment of updating old code) (+source +game)

Post by Timmy »

Ok, I've managed to get a compile of the old compiler with "-Cl-v -m", as I promised:

Here's that output, for comparison (note, I've changed some directory names in this output):
(Also note that the source code here is a bit different than the one I've posted earlier, because that code works on the 2.1 compiler. But this source is what generates fbs.tap.)

Code: Select all

C:\z88dk\FLAP>zcc +zx -vn w1.c -o w1.bin -lndos -Cl-v -m -create-app -zorg=24000
        1 file(s) copied.
        1 file(s) copied.
sccz80:"w1.c" L:513 Warning:#17:Expected ';'
Assemble only updated files.
Create symbol table file.
Link/relocate assembled modules.
Link library modules with code.
Create address map file.

Assembling 'C:\[...]\Temp\s3k4_1.asm'...
Pass1...
C:\z88dk\lib\/spec_crt0.asm
zcc_opt.def
C:\z88dk\lib\/float.asm
Pass2...
Size of module is 157 bytes

Total of 692 lines assembled.
linking module(s)...
Pass1...
ORG address for code is 5DC0
Linking library module <IN_INKEY>
Linking library module <IN_KEYTRANSTBL>
Linking library module <L_AND>
Linking library module <L_EQ>
Linking library module <L_GINTSPSP>
Linking library module <L_GT>
Linking library module <L_LNEG>
Linking library module <RAND>
Linking library module <ZX_BORDER>
Code size of linked modules is 1875 bytes
Pass2...
Creating map...
Code generation completed.
        1 file(s) copied.
and the map file:

Code: Select all

BASE_GRAPHICS			= 5DF0, G: ZX82_CRT0
CALL_ROM3			= 5DE4, G: ZX82_CRT0
CLEANUP				= 5DD9, G: ZX82_CRT0
CLEANUP_EXIT			= 5DDA, L: ZX82_CRT0
COORDS				= 5DEE, G: ZX82_CRT0
DLDPSH				= 5E16, G: ZX82_CRT0
DLOAD				= 5E0D, G: ZX82_CRT0
DPUSH				= 5E1E, G: ZX82_CRT0
DPUSH2				= 5E2D, G: ZX82_CRT0
DSTORE				= 5E02, G: ZX82_CRT0
EXITCOUNT			= 5DF6, G: ZX82_CRT0
EXITSP				= 5DF4, G: ZX82_CRT0
EXTRA				= 5E44, G: ZX82_CRT0
FA				= 5E4A, G: ZX82_CRT0
FASIGN				= 5E50, G: ZX82_CRT0
FLOORLOOP			= 5FEC, L: W1
FP_SEED				= 5E3E, G: ZX82_CRT0
HEAPBLOCKS			= 5DF9, G: ZX82_CRT0
HEAPLAST			= 5DF7, G: ZX82_CRT0
IN_INKEY			= 635D, G: IN_INKEY
IN_KEYTRANSTBL			= 6427, G: IN_KEYTRANSTBL
I_10				= 61FF, L: W1
I_11				= 6210, L: W1
I_12				= 6222, L: W1
I_13				= 6234, L: W1
I_14				= 6246, L: W1
I_15				= 624D, L: W1
I_16				= 6275, L: W1
I_17				= 6296, L: W1
I_18				= 62D3, L: W1
I_18_ULE			= 62A0, L: W1
I_19				= 62C3, L: W1
I_2				= 634C, L: W1
I_20				= 62DE, L: W1
I_21				= 6334, L: W1
I_22				= 631F, L: W1
I_23				= 6337, L: W1
I_24				= 633F, L: W1
I_25				= 633F, L: W1
I_26				= 6348, L: W1
I_5				= 614F, L: W1
I_6				= 6158, L: W1
I_7				= 615E, L: W1
I_8				= 61BD, L: W1
I_9				= 6337, L: W1
KEYHITA				= 63C5, L: IN_INKEY
KEYHITB				= 63DC, L: IN_INKEY
L_5CFE				= 60B2, L: W1
L_5D01				= 60B5, L: W1
L_5D40				= 60EF, L: W1
L_5D46				= 60F5, L: W1
L_5D4D				= 60FC, L: W1
L_5D53				= 6102, L: W1
L_5D5A				= 6109, L: W1
L_5D5F				= 610E, L: W1
L_9999				= 60A9, L: W1
L_AND				= 64C7, G: L_AND
L_DCAL				= 5DE3, G: ZX82_CRT0
L_EQ				= 64CE, G: L_EQ
L_GINTSPSP			= 64D5, G: L_GINTSPSP
L_GT				= 64DE, G: L_GT
L_LNEG				= 64EA, G: L_LNEG
NOCAPS				= 63F8, L: IN_INKEY
NOKEY				= 63C0, L: IN_INKEY
NOSYM				= 6403, L: IN_INKEY
NOWA2				= 611E, L: W1
NOWALLS				= 6116, L: W1
NUM3A				= 5F14, L: W1
NUM4A				= 5F16, L: W1
OK1				= 605A, L: W1
PP2				= 5F74, L: W1
PRINT2LOOP			= 5F62, L: W1
PRINTCLOOP			= 5F2D, L: W1
RAND				= 64EF, G: RAND
ROWTBL				= 6407, L: IN_INKEY
SND_TICK			= 5DFB, G: ZX82_CRT0
START				= 5DC0, L: ZX82_CRT0
START1				= 5DDF, L: ZX82_CRT0
WALLEND				= 6123, L: W1
ZX_BORDER			= 650C, G: ZX_BORDER
_BEEP4				= 5EE7, G: W1
_CHECKDEATH			= 607C, G: W1
_CLEARATTRS			= 60CF, G: W1
_DRAW4SPACES			= 6025, G: W1
_DRAWBIRD			= 604F, G: W1
_FLAPCOUNTER			= 6357, G: W1
_FLAPPING			= 6124, G: W1
_FRAMES				= 635A, G: W1
_GAME_END			= 6359, G: W1
_GEN_WALLS			= 60E0, G: W1
_HISCORE			= 5E5D, G: W1
_INITSCREEN			= 5FD5, G: W1
_MAIN				= 6128, G: W1
_OLD_PLAYER_Y			= 635C, G: W1
_PIPECOUNTER			= 6353, G: W1
_PL				= 6354, G: W1
_PLAYER_Y			= 6352, G: W1
_PRINTCXYW			= 5F35, G: W1
_PRINTLOGO			= 5F6A, G: W1
_PRINTSTRING2			= 5F62, G: W1
_PRINTSTRINGCXYS		= 5F1F, G: W1
_SCORE				= 6355, G: W1
_SCORECOUNTER			= 635B, G: W1
_SCROLLATTRSLEFT		= 60C3, G: W1
_SCROLLATTRSLEFT2		= 60AD, G: W1
_STD_SEED			= 5DF2, G: ZX82_CRT0
_TIMER				= 6358, G: W1
_UDG				= 5E5F, L: W1
_VFPRINTF			= 5DE4, G: ZX82_CRT0
_WTOA2				= 5EF2, G: W1
__SGOIOBLK			= 5DFC, G: ZX82_CRT0


START				= 5DC0, L: ZX82_CRT0
CLEANUP				= 5DD9, G: ZX82_CRT0
CLEANUP_EXIT			= 5DDA, L: ZX82_CRT0
START1				= 5DDF, L: ZX82_CRT0
L_DCAL				= 5DE3, G: ZX82_CRT0
_VFPRINTF			= 5DE4, G: ZX82_CRT0
CALL_ROM3			= 5DE4, G: ZX82_CRT0
COORDS				= 5DEE, G: ZX82_CRT0
BASE_GRAPHICS			= 5DF0, G: ZX82_CRT0
_STD_SEED			= 5DF2, G: ZX82_CRT0
EXITSP				= 5DF4, G: ZX82_CRT0
EXITCOUNT			= 5DF6, G: ZX82_CRT0
HEAPLAST			= 5DF7, G: ZX82_CRT0
HEAPBLOCKS			= 5DF9, G: ZX82_CRT0
SND_TICK			= 5DFB, G: ZX82_CRT0
__SGOIOBLK			= 5DFC, G: ZX82_CRT0
DSTORE				= 5E02, G: ZX82_CRT0
DLOAD				= 5E0D, G: ZX82_CRT0
DLDPSH				= 5E16, G: ZX82_CRT0
DPUSH				= 5E1E, G: ZX82_CRT0
DPUSH2				= 5E2D, G: ZX82_CRT0
FP_SEED				= 5E3E, G: ZX82_CRT0
EXTRA				= 5E44, G: ZX82_CRT0
FA				= 5E4A, G: ZX82_CRT0
FASIGN				= 5E50, G: ZX82_CRT0
_HISCORE			= 5E5D, G: W1
_UDG				= 5E5F, L: W1
_BEEP4				= 5EE7, G: W1
_WTOA2				= 5EF2, G: W1
NUM3A				= 5F14, L: W1
NUM4A				= 5F16, L: W1
_PRINTSTRINGCXYS		= 5F1F, G: W1
PRINTCLOOP			= 5F2D, L: W1
_PRINTCXYW			= 5F35, G: W1
_PRINTSTRING2			= 5F62, G: W1
PRINT2LOOP			= 5F62, L: W1
_PRINTLOGO			= 5F6A, G: W1
PP2				= 5F74, L: W1
_INITSCREEN			= 5FD5, G: W1
FLOORLOOP			= 5FEC, L: W1
_DRAW4SPACES			= 6025, G: W1
_DRAWBIRD			= 604F, G: W1
OK1				= 605A, L: W1
_CHECKDEATH			= 607C, G: W1
L_9999				= 60A9, L: W1
_SCROLLATTRSLEFT2		= 60AD, G: W1
L_5CFE				= 60B2, L: W1
L_5D01				= 60B5, L: W1
_SCROLLATTRSLEFT		= 60C3, G: W1
_CLEARATTRS			= 60CF, G: W1
_GEN_WALLS			= 60E0, G: W1
L_5D40				= 60EF, L: W1
L_5D46				= 60F5, L: W1
L_5D4D				= 60FC, L: W1
L_5D53				= 6102, L: W1
L_5D5A				= 6109, L: W1
L_5D5F				= 610E, L: W1
NOWALLS				= 6116, L: W1
NOWA2				= 611E, L: W1
WALLEND				= 6123, L: W1
_FLAPPING			= 6124, G: W1
_MAIN				= 6128, G: W1
I_5				= 614F, L: W1
I_6				= 6158, L: W1
I_7				= 615E, L: W1
I_8				= 61BD, L: W1
I_10				= 61FF, L: W1
I_11				= 6210, L: W1
I_12				= 6222, L: W1
I_13				= 6234, L: W1
I_14				= 6246, L: W1
I_15				= 624D, L: W1
I_16				= 6275, L: W1
I_17				= 6296, L: W1
I_18_ULE			= 62A0, L: W1
I_19				= 62C3, L: W1
I_18				= 62D3, L: W1
I_20				= 62DE, L: W1
I_22				= 631F, L: W1
I_21				= 6334, L: W1
I_9				= 6337, L: W1
I_23				= 6337, L: W1
I_25				= 633F, L: W1
I_24				= 633F, L: W1
I_26				= 6348, L: W1
I_2				= 634C, L: W1
_PLAYER_Y			= 6352, G: W1
_PIPECOUNTER			= 6353, G: W1
_PL				= 6354, G: W1
_SCORE				= 6355, G: W1
_FLAPCOUNTER			= 6357, G: W1
_TIMER				= 6358, G: W1
_GAME_END			= 6359, G: W1
_FRAMES				= 635A, G: W1
_SCORECOUNTER			= 635B, G: W1
_OLD_PLAYER_Y			= 635C, G: W1
IN_INKEY			= 635D, G: IN_INKEY
NOKEY				= 63C0, L: IN_INKEY
KEYHITA				= 63C5, L: IN_INKEY
KEYHITB				= 63DC, L: IN_INKEY
NOCAPS				= 63F8, L: IN_INKEY
NOSYM				= 6403, L: IN_INKEY
ROWTBL				= 6407, L: IN_INKEY
IN_KEYTRANSTBL			= 6427, G: IN_KEYTRANSTBL
L_AND				= 64C7, G: L_AND
L_EQ				= 64CE, G: L_EQ
L_GINTSPSP			= 64D5, G: L_GINTSPSP
L_GT				= 64DE, G: L_GT
L_LNEG				= 64EA, G: L_LNEG
RAND				= 64EF, G: RAND
ZX_BORDER			= 650C, G: ZX_BORDER
I'm not planning to make any comment on this; it's all new to me.
User avatar
dom
Well known member
Posts: 2076
Joined: Sun Jul 15, 2007 10:01 pm

Re: FBS (or, an experiment of updating old code) (+source +game)

Post by dom »

Thanks Timmy that's really useful.

In terms of the general setup, it looks like these things have changed:

1. The crt0 now has more features (initialise bss etc, but it can now be tuned down to a lot smaller)
2. The FILE block has increased size - I think it's around 60 bytes.
3. rand() is a different, much larger implementation that is actually random!
4. The comparison routine (l_gt) now as an accompanying l_compare_result routine
5. More code is being inlined (notice how there's no l_eq/l_and in the new compilation)
6. I think the actual w1.c now compiles to a smaller size - it looks like it was 1327 bytes, it's now 1266 bytes (*)
7. A screen printer gets dragged in by default
8. Incorporating sections makes it a little harder to figure out exact sizes of each component by eyeballing a .map file

(*) Easy way to see this with z88dk is to compile to an object file and then run z88dk-z80nm on the object file. Count the sizes of the listed sections.

I think on the whole it's ok, as we've added features, we've also added the ability to turn off those features. 7. is a bit annoying: because we've assigned the value of a function to a defc it gets pulled in to the binary, although we never use neither the function nor the defc. I thought there was a GitHub issue for it but I can't track it down.
User avatar
dom
Well known member
Posts: 2076
Joined: Sun Jul 15, 2007 10:01 pm

Re: FBS (or, an experiment of updating old code) (+source +game)

Post by dom »

As a follow up to this, I updated reidrac's Castaway to the latest z88dk, and sure enough I needed to do the following:

- Mark the assembler __z88dk_callee and __z88dk_fastcall as __naked
- Mark the joystick function pointer as __z88dk_fastcall (this has come up in a previous thread)
- Create a zpragma.inc to disable features

An extra gotcha was that at some point over the past decade labels have become case sensitive.

It looks like this might be the start of a recipe/checklist for updating code.
Timmy
Well known member
Posts: 392
Joined: Sat Mar 10, 2012 4:18 pm

Re: FBS (or, an experiment of updating old code) (+source +game)

Post by Timmy »

Thanks for letting me know Castaway was open sourced. Castaway was/is a really good "metroidvania". One day I will make my own too.

I like that his blog is mentioning this: https://www.usebox.net/jjm/blog/castaway-source-code/

The reason I started making this thread is to see if we can offer some backwards compatibility. There are so many codes out there that are using older z88dk versions that it's worth preserving. A recipe/checklist would be nice.

I will probably not using the source code myself because of the license, but it is good educational material (I hope, haven't really looked at it).

I never noticed the case sensitive labels before... I always use thought they were case sensitive in the first place. :)
User avatar
dom
Well known member
Posts: 2076
Joined: Sun Jul 15, 2007 10:01 pm

Re: FBS (or, an experiment of updating old code) (+source +game)

Post by dom »

Compatibility is always a tricky one, do you keep the quirks/bugs alive? I'd like to update a few more projects and see what else can trip people up - to be honest Castaway only took a couple of hours once I remembered about this thread! The biggest issue was a faulty optimisation rule. If you want to share (privately) with me some of your projects I'm happy to give them a go and see what else pops up and then create some docs.

I suspect it's worthwhile going further with some projects and play around with how the data is stored etc - eg, castaway uses ucl to compress the assets, trying with one of the ZX* might I suspect save even more space.

I'm in the process of updating the classic sp1 so that it's the same code as newlib (it seems to be marginally smaller), opening it up to sdcc/classic compilations. I'm contemplating a port of sp1 to another platform - I'm thinking the PC88 with the ALU might be quite good fun since a) Each pixel is a 1 bit, the ALU allows us to do colour cheaply - so if I can understand what needs to be done we might be able to do a few quick ports.

Yeah, it's a weird one, it looks like z80asm was case insensitive, so although C complained about mis-matched case, if you called a library/C function from assembler with the wrong case it linked ok.
Timmy
Well known member
Posts: 392
Joined: Sat Mar 10, 2012 4:18 pm

Re: FBS (or, an experiment of updating old code) (+source +game)

Post by Timmy »

dom wrote: Wed Apr 07, 2021 4:20 pm Compatibility is always a tricky one, do you keep the quirks/bugs alive?
I have been thinking about it all day, and for the most of the users that aren't on 2.1 or newer, that's a really interesting question.

What I understand is that a lot of users were/are stuck on 1.10 for a very long time. Not because of its quirks or bugs, but because there wasn't any official version for a long time, and because newer versions generated larger code, or that inline assembly was changed without anyone knowing how to fix it. I honestly haven't known about the naked keyword before this thread. And if I want to migrate my old code to 2.1, I'd also have to add naked, and a "ret" at the end, to every single inline assembly function I have used (that's a lot of functions). Migration alone is a lot of work, and even after a migration it wouldn't make any sense because the executable became larger and won't fit into 48k any more. (Most games use almost every single byte of memory, so if a migration makes the executable bigger, then it's never worth it. Also it's not like we need to update our games anyway.)
I'd like to update a few more projects and see what else can trip people up - to be honest Castaway only took a couple of hours once I remembered about this thread! The biggest issue was a faulty optimisation rule. If you want to share (privately) with me some of your projects I'm happy to give them a go and see what else pops up and then create some docs.
I don't have a problem with sharing some sources with you, but it would take a while to find my old stuff and pack them into a correct package and all the things. (My games has a lot of resource files and other temporary files, but for compilation purposes you'll only need like 5 to 10 files out of the 50+ files I have. It's a lot of work for me to pick the correct files for you, and I don't know if I can/want to. :lol:) Also I would need a way to send you the files. By the way, I was starting to port parts of the Cherry code to 2.1, and you can see the results in the Map Editor thread.

Fortunately there are enough other source code "out there" that you can play with. And for some low hanging fruits, if you (or me, or together) can migrate Churrera/MK1 (with splib) to 2.1 with a smaller executable than before, we'd be able to help out a lot of users already.
I suspect it's worthwhile going further with some projects and play around with how the data is stored etc - eg, castaway uses ucl to compress the assets, trying with one of the ZX* might I suspect save even more space.
That is a very interesting idea. According to the images on https://www.cpcwiki.eu/forum/programmin ... ncher-zx0/ it is certainly possible that a different compression will give at least 1 more screen.

On the other hand, setting "-pragma-define:fputc_cons=0" gives about 1600 bytes, if a screen costs about 140 bytes like it is in my Map Editor, about 10 extra screens. And that without any extra compression.
I'm in the process of updating the classic sp1 so that it's the same code as newlib (it seems to be marginally smaller), opening it up to sdcc/classic compilations.
I don't know if updating sp1 would help, as I understand that sp1 would still need basically every byte between 0xd000-0xffff. It's not going to get me any more bytes for more rooms, is it?
I'm contemplating a port of sp1 to another platform - I'm thinking the PC88 with the ALU might be quite good fun since a) Each pixel is a 1 bit, the ALU allows us to do colour cheaply - so if I can understand what needs to be done we might be able to do a few quick ports.
I have tried porting sp1 to the MSX, but I couldn't. Mostly because sp1 has a lot of hidden quirks, and lot of useful functions that are useful for a software sprite engine, but I can't map them to the MSX, at all. Other problems include that the datatypes used by sp1 are really large in some functions (for example, I meed a 768 byte array just for sp1_PutTiles(), see the example in Map Editor thread), or that I need to keep flipped functions of the same sprites in memory because sp1 can't do flipped sprites. (Probably why most of my sprites looks forward instead of looking left or right.)

My alternative suggestion is to start with something smaller, like splib1, or some xor based sprite engine. I could open source my engine for future looter; it's a really simple xor based 16x16 pre-shifted sprite engine with a copy of the screen in memory, so it's about 8k of memory footprint. (But it's probably too much work for now.)

Anyway, I think writing this post took me many hours. So I'll stop for now. :)
User avatar
dom
Well known member
Posts: 2076
Joined: Sun Jul 15, 2007 10:01 pm

Re: FBS (or, an experiment of updating old code) (+source +game)

Post by dom »

Timmy wrote: Thu Apr 08, 2021 5:04 pm Migration alone is a lot of work, and even after a migration it wouldn't make any sense because the executable became larger and won't fit into 48k any more. (Most games use almost every single byte of memory, so if a migration makes the executable bigger, then it's never worth it.
This is where things get interesting. On my sample (of 1!), I've made a saving of 500 bytes through the pragmas, sp1 updating and time.
Timmy wrote: Also it's not like we need to update our games anyway.
Very true, unless you're recycling code of course.
Timmy wrote:Fortunately there are enough other source code "out there" that you can play with. And for some low hanging fruits, if you (or me, or together) can migrate Churrera/MK1 (with splib) to 2.1 with a smaller executable than before, we'd be able to help out a lot of users already.
Yes, I looked at that and then realised that I need to find a tutorial because I have virtually zero clue as to what is going on there. I can see that it's generating C code and relies on a modified splib2, but I've not managed to find the source for splib2 which is a big hurdle.
Timmy wrote:I don't know if updating sp1 would help, as I understand that sp1 would still need basically every byte between 0xd000-0xffff. It's not going to get me any more bytes for more rooms, is it?
There's two bits to the memory usage; the big 16k-ish chunk and the library routines. The chunk you can't do much about, but the library routines save about 5 bytes which isn't massively significant but every little counts! :lol: It's also the last big chunk of effectively duplicated code in the repo and it's the last package outstanding that uses weird relocations that I really can't remember why they had to be done that way.
I have tried porting sp1 to the MSX, but I couldn't. Mostly because sp1 has a lot of hidden quirks, and lot of useful functions that are useful for a software sprite engine, but I can't map them to the MSX, at all.
Yes, I can see that it's going to be difficult to map the software sprites in sp1 to hardware sprites. I think for memory mapped VRAM a conversion should be "fairly easy", but you've made me think twice about the PC88, I think possibly a 6847 machine in hires mode (256x192 b&w) would be an easier starting point - I need to find one with a sensible memory layout to not have to disturb too much.

It may not be worth bothering with though, just one of those late night ideas when I forget I have a day job and thousands of other things to do.
User avatar
dom
Well known member
Posts: 2076
Joined: Sun Jul 15, 2007 10:01 pm

Re: FBS (or, an experiment of updating old code) (+source +game)

Post by dom »

dom wrote: Thu Apr 08, 2021 10:01 pm.., but I've not managed to find the source for splib2 which is a big hurdle.
I found a copy of it via the old geocities mirror here: http://www.oocities.org/aralbrec/sprite ... amples.htm

It looks like Alvin added most of the code (with asm rewrites) to the regular library, just with differing names, so modernising it should be possible.
Timmy
Well known member
Posts: 392
Joined: Sat Mar 10, 2012 4:18 pm

Re: FBS (or, an experiment of updating old code) (+source +game)

Post by Timmy »

dom wrote: Thu Apr 08, 2021 11:15 pm It looks like Alvin added most of the code (with asm rewrites) to the regular library, just with differing names, so modernising it should be possible.
Good to hear. I think I also have a copy of it (downloaded long ago).

Note that splib2 is not splib3, even though they might carry the same names. Some of the differences between them can be found in this thread: https://worldofspectrum.org/forums/disc ... edirect/p1

Also, I just realised that, I have been using 2.0+ versions for my MSX releases. That means that I already managed to migrate some of the games myself without having too much trouble. Of course the MSX is a different machine, so I didn't encounter the many quirks I've had with the Spectrum compilations.

That also means I think I had an idea how to convert some on my sp1 games to the MSX; it's easy if you only use the simple functions in sp1. And usually that means using only the functions that can be found in my sp1 flying saucers demo in the examples directory. Or the example in the map editors thread.

(I actually ported some of my action games to the MSX, but I'm still not happy with how it looks, and hardware limitations like max 4 sprites in a scanline makes conversion really difficult, so I may, or may not release them in the future.)
Timmy
Well known member
Posts: 392
Joined: Sat Mar 10, 2012 4:18 pm

Re: FBS (or, an experiment of updating old code) (+source +game)

Post by Timmy »

PS: If migrating Churrera directly is too difficult, some of the MK1 games sources have been released, you could try those instead. For example, I was playing a game called Red Planet the other day. I saw there were sources available but I didn't really looked into them. Also many of the Mojon's games have sources. Even if I'm really more interested into playing them. :cool:
User avatar
dom
Well known member
Posts: 2076
Joined: Sun Jul 15, 2007 10:01 pm

Re: FBS (or, an experiment of updating old code) (+source +game)

Post by dom »

Well, it's not that I'm desperately looking for things to do....

However, I took a look at Redplanet, and made the following changes:

1. zpragma.inc
2. Removing a # which was the old constant operator

I also:

1. Recompiled splib2 using the latest z88dk

Which took a handful of minutes (less time than it's taking me to write this post!). Then I recompiled...

Size of the binary before: 35935, size of the binary with the latest: 35199. Plenty of room for another few screens!
Timmy
Well known member
Posts: 392
Joined: Sat Mar 10, 2012 4:18 pm

Re: FBS (or, an experiment of updating old code) (+source +game)

Post by Timmy »

That sounds very promising! Perhaps this is the final step and we can now safely migrate to the 2.1!

I must say I have no idea what the # operator means, or how to recompile splib2. But I think we are there for the most part.

Because even people might need a first step to create using MK1 then can now compile it using 2.1 (with modifications) and perhaps we can get them over to 2.1.
User avatar
dom
Well known member
Posts: 2076
Joined: Sun Jul 15, 2007 10:01 pm

Re: FBS (or, an experiment of updating old code) (+source +game)

Post by dom »

Timmy wrote: Sat Apr 10, 2021 10:26 am That sounds very promising! Perhaps this is the final step and we can now safely migrate to the 2.1!

I must say I have no idea what the # operator means, or how to recompile splib2. But I think we are there for the most part.
Yes, I think it's very good, for me it was easy to do as well which makes me feel positive about the entire process. I suspect there's a bit more that can be squeezed out so I'll be carrying on tinkering. Given that 2.1 went out with a couple of clangers, my thoughts are:

- Raise a PR against MK1 to sort the issues I've found so far
- Creating an splib repo with usable artefacts
- Get hold of the modified source for splib2 and create artefacts (*)
- Release a 2.1.1 since there's a few clangers in 2.1
- Iterate splib2 so that all the support routines point to the routines in library (adt, heap, malloc etc)
- Import splib2 into z88dk as an alternate sprite library to sp1
- Another release

(*) I could transform the binary library, but that's more work than fiddling with the source.

Which should make the entire thing a drop in.
User avatar
dom
Well known member
Posts: 2076
Joined: Sun Jul 15, 2007 10:01 pm

Re: FBS (or, an experiment of updating old code) (+source +game)

Post by dom »

Just as an update, this in progress and going OK, there's a git project here: https://github.com/suborb/splib2 with my working copy of splib2 in it.

I've reverse engineered the MK2 source code changes (all pretty minor) and now have a variant of splib2 building with them that works.

There's also a 5 step process for updating the example MK1 projects which are all pretty easy to do. I'm fairly certain we can squeeze a bit more memory out and I do suspect I might need to fiddle with memory maps a little so that beeper code doesn't end up in contended memory.
Timmy
Well known member
Posts: 392
Joined: Sat Mar 10, 2012 4:18 pm

Re: FBS (or, an experiment of updating old code) (+source +game)

Post by Timmy »

I just read the page, that is a good result!

I think I understand most of it starting from "Recipe for adjusting the source" but I have problems understanding the upper part.

At the bottom part I don't understand why sp and origin needs to change.

Also, I have inlined code that use ix in some of my projects. That means that migrating that would be difficult?

Also, I have no idea what you were talking about in your post 2 posts above this one. I am not very into github, and I understand that PR is a pull request, but what does "artefacts" mean?
User avatar
dom
Well known member
Posts: 2076
Joined: Sun Jul 15, 2007 10:01 pm

Re: FBS (or, an experiment of updating old code) (+source +game)

Post by dom »

Sorry I descended into technobabble.

If you've written a game using MK1 then all you care about is steps 1-5 to update your code. I'm hoping that steps 1-3 will be accepted by the Mojon's via PR which just leaves 4 and 5.

The changing the stack point/origin in 4 is because I've just supplied an example file which may not match with what you've setup (I've seen different values for various MK1 games).

In terms of what the artefact is, this will take the form of a zip file containing (at least): splib2.lib, splib2_mk2.lib and spritepack.h which can be unzipped onto the top of an existing z88dk.

Coming back to your point regarding inlined ix, if you're using sccz80 (which you are) then don't worry about it!
Post Reply