News:

Printed Amstrad Addict magazine announced, check it out here!

Main Menu
avatar_Arnaud

Migration of Cpcrslib to Cpctelera

Started by Arnaud, 09:26, 21 August 15

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Arnaud

Hello,
i am trying to migrate my game from Cpcrslib to Cpctelera.

To start my migration, i want in a first step use the build chain of Cpctelera to compile my program made with Cpcrslib.
It compiles but crashes when running and i think it's a memory problem.

I use SDCC 3.5.0, hex2bin 2.0 and Cpctelera 1.2.0.

First of all i have a question, in my project i have two files from Cpcrslib examples crt0_cpc.s and putchar_cpc.s and i don't see them in the Cpctelera examples. They are not needed ?
- If i don't include them it compiles but the binary file is smaller (7ko instand of 16ko) and it crashes.
- If i include them it compiles, the binary file have the same size than with my Cpcrslib build but it crashes.

Here my compilation batch for Cpcrslib and the configuration file of Cpctelera.

Thank for your help.

KaosOverride

#1
Ronaldo(cpctelera) and Artaburu(cpcrslib) are speaking about optimizing cpcrslib under SDCC. So spect to have a cpctelera friendly cpcrslib!! :)

(More info at Amstrad.es forum, but is in spanish)


The crt0 and putchar are functions not found in SDCC for CPC. Crt0 defines the entrypoint, data segment and more CPC dependant definitions, putchar the basic char printing routine for C libs
KaosOverride · GitHub
MEGA Amstrad Public Amstrad folder

ronaldo

#2
@Arnaud Bouche, compiling CPCRSLib projects using CPCtelera is not difficult, buy some details must be taken into account:

       
  • First, add --fomit-frame-pointer compilation option to the build options (cfg/build_config.mk). This is what makes code crash:

Z80CCFLAGS    := --fomit-frame-pointer
Z80CCLINKARGS := -mz80 --fomit-frame-pointer --no-std-crt0 -Wl-u \

       

       
  • Second, add include directory (-I) path for CPCRSLib header files:

CPCRSLIB_INC   := /path/to/cpcrslib_include_dir/
Z80CCINCLUDE  := -I$(CPCRSLIB_INC)

       

       
  • Third, add linkage flags (-l) for CPCRSLib and CPCWyzLib:

CPCRSLIB_LIB  := /path/to/cpcrslib.lib
CPCWYZLIB_LIB := /path/to/cpcwyzlib.lib
Z80CCLINKARGS := -mz80 --fomit-frame-pointer --no-std-crt0 -Wl-u \
                 --code-loc $(Z80CODELOC) \
                 --data-loc 0 -l$(CPCT_LIB) -l$(CPCRSLIB_LIB) -l$(WYZLIB_LIB)


Complete Code Example
: suppose you have CPCRSLib installed under /home/user/cpcrslib, with include files in /home/user/cpcrslib/include and library files in /home/user/cpcrslib/lib. Your build_config.mk should look like this:

CPCRSLIB_DIR  := /home/user/cpcrslib
CPCRSLIB_INC  := $(CPCRSLIB_DIR)/include
CPCRSLIB_LIB  := $(CPCRSLIB_DIR)/lib/cpcrslib.lib
WYZLIB_LIB    := $(CPCRSLIB_DIR)/lib/cpcwyzlib.lib
Z80CCFLAGS    := --fomit-frame-pointer
Z80ASMFLAGS   := -l -o -s
Z80CCINCLUDE  := -I$(CPCRSLIB_INC)
Z80CCLINKARGS := -mz80 --fomit-frame-pointer --no-std-crt0 -Wl-u \
                 --code-loc $(Z80CODELOC) \
                 --data-loc 0 -l$(CPCRSLIB_LIB) -l$(WYZLIB_LIB) -l$(CPCT_LIB)


You may optionally remove linkage with CPCtelera lib if you are not using it. However, there is no harm done on keeping it: only the functions that you call in your program will be linked (if you call no CPCtelera function, no code is included, even linking against it). Also take into account that this does not happen with present version of CPCRSLib: a great portion of code is included even if you don't use it. Hopefully next version will solve this issue, as Artaburu is already working on it.

With respect to the files, crtc0_cpc.s is not required anymore (SDCC 3.5.0. provides a standard one) and putchar_cpc.s is already included with CPCtelera.

Hope this helps :) .

Arnaud

Thanks for your explanations and help but it always crash, there must be something obvious i can't see  ??? .

I also have tried to add the option --oldralloc i used in my batch but it does nothing better.

Z80CODELOC := 0x0100

CPCRSLIB_DIR  := /home/ArnaudPC/cpcrslib
CPCRSLIB_INC  := $(CPCRSLIB_DIR)/include
CPCRSLIB_LIB  := $(CPCRSLIB_DIR)/lib/cpcrslib.lib

Z80CCFLAGS    := --oldralloc --fomit-frame-pointer
Z80ASMFLAGS   := -l -o -s
Z80CCINCLUDE  := -I$(CPCT_SRC) -I$(CPCRSLIB_INC)
Z80CCLINKARGS := -mz80 --fomit-frame-pointer --no-std-crt0 -Wl-u  \
                 --code-loc $(Z80CODELOC) \
                 --data-loc 0 -l$(CPCRSLIB_LIB) -l$(CPCT_LIB)


It crashes when the asm function to read binary file in static buffer[4096]  is call.

ronaldo

#4
Have you tried first to compile CPCRSLib examples? If you build them you also have to set Z80CODELOC to 0x6038. Did your original compilation use 0x100 as location to load the binary? Do not use oldralloc unless you have a good reason for that. Also, try not to use malloc in your code, as It doesn't make much sense in a CPC and it's limited under SDCC.

It's very difficult to know what could be your problem without knowing anything about your sources. I don't know what function is the one for "reading binary file in static buffer"  :blank:

Arnaud

#5
Quote from: ronaldo on 23:08, 21 August 15
Have you tried first to compile CPCRSLib examples?
No i'll try to see the result.

Quote from: ronaldo on 23:08, 21 August 15
If you build them you also have to set Z80CODELOC to 0x6038.
If i modify the Z80CODELOC  to 0x6038, do i have to modify my code for specific address pointer or memory location ? I don't understand really well the impact of the code location.

Quote from: ronaldo on 23:08, 21 August 15
Did your original compilation use 0x100 as location to load the binary?
In fact it's 0x138 but i also try 0x100

Quote from: ronaldo on 23:08, 21 August 15
It's very difficult to know what could be your problem without knowing anything about your sources. I don't know what function is the one for "reading binary file in static buffer"  :blank:
Effectivly  :D , in fact it was just to indicate the problem was not in a cpcrslib function call

ronaldo

Z80CODELOC controls the place in memory where your produced binary will be loaded. When you were using CPCRSLib + SDCC directly, you should have being placing your code with the --code-loc <dir> modifier. If your code does not depend on something being loaded at a specific memory address, this shouldn't be an issue. You only have to respect the rst vector (0x00-0x40) and the firmware variables (0xA6FC - 0xBFFF) which are required for the loading process (for more details, see the amstrad firmware)

Was your code working when you compiled it previously with CPCRSLib? If the batch file you attached was what you used to compile, you should set Z80CODELOC = 0x0138. I see you used --fno-omit-frame-pointer, which is contrary to CPCRSLib requirements. That should make most of CPCRSLib functions fail: are you sure that your code was working?. Why did you encourage SDCC to follow C99 standard with SDCC extensions (--std-sdcc99)? SDCC warns that the implementation for that standard is incomplete.

I think this would be a lot easier if I could have a look at your code :) .

Arnaud

Here my full code and the disc with the resources.

I am going in vacation now i shut down the pc, and i'll work on the subject when i'll back.

Thanks for your help ronaldo, don't take too many time on this, my problem is very not urgent.  ;)

ronaldo

#8
Ok, I know understand your problems much better. I have fixed them and here you are: your project now generates and compiles perfectly with CPCtelera and CPCRSLib together.

This is the list of changed things and reasons:

       
  • Removed --oldralloc: this was used to force IX to be synchronized with SP, pointing to the top of the stack and being used to retrieve parameters. This is deprecated (hence the --oldralloc modifier), forces SDCC to do a bad job allocating register (old style is not quite as good as new) and was also in conflict with CPCRSLib. This was causing most of the problems. To get rid of this, this code has been inserted in every assembly function that gets parameters using IX:
PUSH IX   ;; Save IX (Very important!)
LD IX, #0 ;; Make IX point to the top of the stack
ADD IX, SP
;;
;; Use IX normally to get parameters here
;;
POP IX    ;; Restore IX (Very Important!)

          
  • Added --fomit-frame-pointer: Getting rid of --oldralloc let us use --fomit-frame-pointer, which fixes all the problems CPCRSLib is can create in your code. CPCRSLib requires this modifier not to produce side effects when calling functions like cpc_PutSp, due to IX register modification.
  • Optimizations enabled: Using --oldralloc, your other modifiers had no effect (--fno-omit-frame-pointer, --max-allocs-per-node 2000000 --opt-code-speed) because optimizations cannot be done using old register allocation. Both things are not compatible.
  • Removed --std-sdcc99: as you are not using any special C99 characteristic, so it's not required.
  • Created Makefile rules for automatic DSK population: Now, when you type in make and DSK file is generated, it is automatically populated with the files put in src/dsk_files/ folder of your project. So, every time you modify a file in that folder or add a new one, that file will automatically be included in the DSK file produced by make.
The only thing you have to do in your system, other than having latest version of CPCtelera installed (release 1.2.3) is modifying cfg/build_config.mk to change this lines:

CPCRSLIB_DIR  := $(CPCT_SRC)/../z80libs/cpcrslib/
CPCRSLIB_INC  := $(CPCRSLIB_DIR)
CPCRSLIB_LIB  := $(CPCRSLIB_DIR)/cpcrslib.lib
WYZLIB_LIB    := $(CPCRSLIB_DIR)/cpcwyzlib.lib


To make them point to the appropriate folders where you have CPCRSLib installed.

You will also notice that compilation is much slower, due to optimizations taking place now (they were being ignored because of --oldralloc). I recommend you to use less intensive optimization parameters while developing to have an affordable compilation time.

[attachurl=2]

ronaldo

#9
Some more quick words:

       
  • I've added this functionality in latest under-development version of CPCtelera (master branch at github). Now you can configure DSKFILESDIR variable on any new project: DSKFILESDIR holds the folder containing files you want to be automatically included in the final DSK. You can see Platform Climber example for reference.
  • We've fixed a bug in iDSK that can corrupt your data in your DSK. Therefore, I strongly recommend you to use latest CPCtelera development version for your project (get it from master branch at github).
  • Note: people not using automatic inclusion of files in DSK do not need to update. This only affects DSKs created with more than one file included using automatic inclusion feature.

Arnaud

#10
Hello,
thanks Ronaldo for your reply.

The version of CPCTelera used is the latest build from github :

       
  • I have used your project, it compiles perfectly but it always crashes when running.
  • I used the same compilation arguments with my batch and my game runs (it also solves problem with printf).
For information i have look at the generated dsk file with CPCDiskXP :

       
  • The datas file are at address 0x100
  • The binary file is at address 0x138 and entry Address at 0x2239
I don't know if it's OK but in my own dsk all is at 0x100.

Here my full CPCTelera project if you have time to look at.

ronaldo

Yes, your original code already crashed because of the problem managing IX register in your assembly routines, mainly. If you continue to use your original code, it will continue to crash. That's not because of CPCtelera or CPCRSLib: it's a problem in your assembly routines.

The project I attached you on previous post is your project but with these problems fixed. You should use all the project, not only the project files. You have already introduced your bugs in the zip file you are attaching. The fixes I did are again gone in this latest zip file, hence the crash.

The project I attached you was tested and worked exactly the same as your original project. It compiles, adds files to dsk, runs and does exactly the same as your original project did. Please, start using it changing only CPCRSLib linking directories. Starting with this project and latest version of CPCtelera should work same as it does for me.

I set the load address at 0x138 because that was what your original compilation code did. This was on your original .bat file:

sdcc -mz80 --std-sdcc99 --max-allocs-per-node 2000000 --disable-warning 196 --opt-code-speed --fno-omit-frame-pointer --oldralloc --code-loc 0x0138 --data-loc 0 --no-std-crt0 crt0_cpc.rel putchar_cpc.rel actions.rel world.rel character.rel -lcpcrslib.lib code.c

However, you may change it as you like, just set Z80CODELOC to wherever you wanted or required. That's not a problem.

Please, test my modified project without changes (no other than setting CPCRSLib folders) and report the result.

Arnaud

#12
It works perfectly... :-[

Now i can begin to migrate my code to CPCtelera, all i need to keep from Cpcrslib is the cpc_UnExo function.
Are the sprites compatible between Cpcrslib and Cpctelera ?

Thanks again Ronaldo.

ronaldo

#13
It's nice to know that it works to you too. I was sweating thinking of extrange bugs and/or configurations :) .

Normal sprites, with/without mask, are codified the same in CPCRSLib and CPCtelera. cpct_drawSprite and cpct_drawSpriteMasked should work for you, if their equivalents (cpc_PutSp and cpc_PutMaskSp) did with CPCRSLib. Please, do read documentation on both before using them, and check that your sprites meet function requisites (maximum sizes, mainly).

You're welcome, man :) . Hope you can finish your project and publish a new game for our Amstrads :D

Arnaud

I worked on the migration today and there're some things i don't know how to do with cpctelera :

       
  • The sprite of the room have a width of 260pix (65bytes) and i can't draw it with cpct_drawSprite due to width limitation to 63 bytes
  • The icons and objects are also in a large sprite (width 280pix) and i split them in an array of smaller sprites with the functions of cpcrslib cpc_GetSp and cpc_SetSp
In fact a great feature would be a partial draw of an sprite (with this function i could do a better scrolling than actual with line per line  :D )

       
  • For input keyboard migration no problem
  • For cpct_setVideoMode and cpct_setPalette i can't use them because i use firmware for files input/output (maybe an evolution for cpct, i/o without firmware)
With the mix of cpcrslib and cpctelera my program works but i'd like to have 100% cpctelera  ;)

ronaldo

At present moment, there is no function for drawing subsprites, but that is on the task list :). I have though many times about writing subsprite drawing routines and I think they will be very useful :). However, i think it will be faster and better for you to have your icons stored as individual sprites. You only have to split them once, store them, and use them as individual sprites. That would be a faster and more flexible approach than having them on a big image.

Right now, drawing a sprite wider than 63 bytes requires splitting it in 2 smaller sprites. I can code a sprite routine for wider sprites, and it wouldn't be difficult, but it would be slower. Anyway, I will think of it :) (I've added to the task list).

There are also future I/O features planned to be able to do it without firmware. They are planned for medium term, but they are there. I/O is really important to do big games with lot of content. It will be a feature for future versions of CPCtelera for sure :).

Thank you again for your feedback :D. Hope to be able to include all requested features in the future ;).

Arnaud

#16
Quote from: ronaldo on 15:08, 01 September 15
However, i think it will be faster and better for you to have your icons stored as individual sprites. You only have to split them once, store them, and use them as individual sprites. That would be a faster and more flexible approach than having them on a big image.
Yes it's exactly what i do, i load the big sprites sheet in video memory and and i split it into smaller sprites to be used directly.
But the sprite sheet is too large to be displayed with cpctelera and there's not equivalent function of cpc_GetSp to make a copy of partial screen to memory.
So i keep cpcrslib to do this task, i also need it to un_exo my data files

Quote from: ronaldo on 15:08, 01 September 15
Thank you again for your feedback :D . Hope to be able to include all requested features in the future ;) .
With pleasure, and you can take your time my game is far to be finished  ;)

ronaldo

Quote from: Arnaud Bouche on 18:24, 01 September 15
Yes it's exactly what i do, i load the big sprites sheet in video memory and and split into smaller sprites.
But the sprite sheet is too large to be displayed with cpctelera and there's not equivalent function of cpc_GetSp to make a copy of partial screen to memory.
Yes, I understood your method. What I'm suggesting is that you convert your sprite into several sprites outside the CPC. Then, make the CPC load all the sprites for the icons separately. You will get rid of cpc_GetSp and/or any subsprite routine. I think you don't need them and they may just be wasting time and memory. Unless you actually do need the full image with all the sprites for another unavoidable operation, I think is much better to have individual sprites.

Even if I implement subsprite routines for CPCtelera, I think that them will be a worse solution for your concrete probleme than pre-splitting your sprites before they are loaded by the CPC.

Arnaud

Quote from: ronaldo on 18:31, 01 September 15
Unless you actually do need the full image with all the sprites for another unavoidable operation, I think is much better to have individual sprites.

In fact it's because my original bitmap on my PC contains all elements for user interface in only one file and it's easier for me to update my graphics in this way.
But you are right about wasting time and memory, it could be done better or outside CPC process  :) .

AugustoRuiz

If all elements are the same size,  you can use img2cpc to convert the image into multiple unique sprites/tiles...

Arnaud

Quote from: AugustoRuiz on 21:28, 01 September 15
If all elements are the same size,  you can use img2cpc to convert the image into multiple unique sprites/tiles...
Thanks for information i'll try that.

Arnaud

Quote from: AugustoRuiz on 21:28, 01 September 15
If all elements are the same size,  you can use img2cpc to convert the image into multiple unique sprites/tiles...
It works perfectly ! Now my sprites are splitted in individual file and i can compress them.
After i concatenate all i one file for loading, my code is smaller and faster  ;D

Have a question, i have not found how to set an output directory.
When i generate my sprites i'd like to create them in another directory than current.

ronaldo

I normally do that in 2 commands:

       
  • First use cpct_img2tileset to convert image files to C arrays
  • Second, use mv to move resulting .c and .h files to the desired ouput directory.
I put these commands as rules in the makefile, so that images are automatically converted each time they are modified. That automates everything :D.

AugustoRuiz

Quote from: Arnaud on 19:40, 18 September 15
It works perfectly ! Now my sprites are splitted in individual file and i can compress them.
After i concatenate all i one file for loading, my code is smaller and faster  ;D

Have a question, i have not found how to set an output directory.
When i generate my sprites i'd like to create them in another directory than current.
You can use the output file name option. You can use relative paths there...

Arnaud

#24
Quote from: AugustoRuiz on 15:09, 19 September 15
You can use the output file name option. You can use relative paths there...

When i use this command :

img2cpc.exe -p manor.json -im -m 1 -t 4 -w 32 -h 64 -o .\data\monsters -of bin monsters.png

All my files monsters_0.bin, monsters_1.bin,... are in the current directory and the asm is in .\data\monsters.asm.

What  i'd expect is to have all my monsters_* also in .\data, but i can do that with batch, img2cpc works very well in this way.

Powered by SMFPacks Menu Editor Mod