Building sdcc projects with z88dk

Other misc things
Post Reply
megatronuk
Member
Posts: 34
Joined: Fri Jan 28, 2022 11:39 pm

Building sdcc projects with z88dk

Post by megatronuk »

Now that I've figured out the route forward with banked function calls in MSX-DOS2, I am trying to leverage some existing work that has been done in SDCC with the MSX2/MSX2+ additional VDP hardware in the MSXgl project (https://github.com/aoineko-fr/MSXgl).

I decided not to use the MSXgl project from the start as the build system (Windows, no makefiles) doesn't fit in with my current development environment (Linux, makefiles)... but the guy has done a tremendous amount of work to bring a whole suite of addons to the C environment for hardware interaction on the MSX.

First thing is that they have all been built with vanilla SDCC (>4.1.x), with the new assembler calling convention. I realise that I'll need to convert any inline assembly to the style used by z88dk, and there will be some tradeoff in speed.

However, I'm trying to compile the first part of the project, the vdp functions (https://github.com/aoineko-fr/MSXgl/blo ... /src/vdp.c), and am stumbling at the first hurdle:

Code: Select all

zcc -compiler=sdcc +msx -m -subtype=msxdos2 -pragma-define:CRT_DISABLELOADER=0  -I./src -I./src/msxgl -o src/msxgl/vdp.o -c src/msxgl/vdp.c
src/msxgl/vdp.c:1655: error: syntax error
  ^---- .rept 15 -1
      ^---- rept:15-1
src/msxgl/vdp.c:1676: error: syntax error
  ^---- .rept 11 -1
      ^---- rept:11-1
src/msxgl/vdp.c:1678: error: duplicate definition: endm
  ^---- .endm
      ^---- endm:
make: *** [Makefile:135: src/msxgl/vdp.o] Error 1
Here's an extract of the lines in question:

Code: Select all

#endif // (MSX_VERSION >= MSX_2)
#endif // (VDP_USE_DEFAULT_SETTINGS)
}     // <---- THIS IS LINE 1655

//-----------------------------------------------------------------------------
// Get VDP version
//	@return					0: TMS9918A, 1: V9938, 2: V9958, x: VDP ID
// @note Code by Grauw (http://map.grauw.nl/sources/vdp_detection.php)
u8 VDP_GetVersion() __naked
{
__asm
	// Detect VDP version
	//
	// a <- 0: TMS9918A, 1: V9938, 2: V9958, x: VDP ID
	// f <- z: TMS9918A, nz: other
	VDP_GetVersionAsm:
		call	VDP_IsTMS9918A	// use a different way to detect TMS9918A
		ret		z
		ld		a, #1			// select s#1
		VDP_DI
		out		(P_VDP_ADDR), a
		ld		a, #VDP_REG(15)
		out		(P_VDP_ADDR), a
		in		a, (P_VDP_ADDR)		// read s#1         // <---- THIS IS LINE 1676
		and		#0b00111110			// get VDP ID
		rrca       // <---- THIS IS LINE 1678
That makes zero sense to me - there's nothing on those lines that would cause syntax errors (at least one of them is a comment). What I think is happening is the preprocessor is stripping things out, but the printed line numbers of where the syntax errors occur are referring to the absolute position in the temporary file.

The .rept and .endm directives are present in that file, but way off on other lines.

I'm not an assembler person (that's why I write in C), but is there an option to zcc to retain the intermediate file so that I can see exactly what (I suppose z80asm?) is actually trying to be assembled here?
megatronuk
Member
Posts: 34
Joined: Fri Jan 28, 2022 11:39 pm

Re: Building sdcc projects with z88dk

Post by megatronuk »

Looking at the issue logged in Github here: https://github.com/z88dk/z88dk/issues/814

I see that z80asm did not originally have macro support, these directives were then added, but rather than .rept/rept and .endm/endm, the variants listed in that issue above were used. That is fine, I can handle that (unless I come across any more sdasm specifics), but I would still like to find out how I can get better assembler warning/error messages with accurate line numbers.
pjshumphreys
Member
Posts: 66
Joined: Sat Feb 06, 2021 2:32 pm

Re: Building sdcc projects with z88dk

Post by pjshumphreys »

According to https://github.com/z88dk/z88dk/wiki/Tool---zcc you can just run the preprocessor with the "-E" command line option
megatronuk
Member
Posts: 34
Joined: Fri Jan 28, 2022 11:39 pm

Re: Building sdcc projects with z88dk

Post by megatronuk »

Excellent, that's what I'll do. It is quite confusing that the error messages from the assembler stage refer to line numbers in the .c source file though (and those line numbers are not the actual source of the error by the time the source reaches the assembler).

I think I tracked down the source of this particular issue to the use of the sdcc assembler directives .rept and .endm needing to be replaced by rept and endr directives from the internal z80asm assembler, but the line number issue when tracking down errors from the assembler still stands.
megatronuk
Member
Posts: 34
Joined: Fri Jan 28, 2022 11:39 pm

Re: Building sdcc projects with z88dk

Post by megatronuk »

Okay, now that the code compiles, on to the next SDCC to z88dk issue - external symbols.

Included in the code I am trying to port over is a header file for the MSX bios, let's call it bios.h. It has some structures defined which represent the various bytes in memory for the state of the machine; keyboard type, screen frequency etc. I know there is duplication of some of the z88dk MSX library going on here, but there's no way I can attempt to backport all of the z88dk library calls to this codebase, and some of the things this sdk does just doesn't exist in z88dk (and is why I am using it). Here's the bios data structure definition:

Code: Select all

#define R_BASRVN	0x002B // Basic ROM version
struct BasicROMVersion
{
	u8 CharacterSet: 4; // Character Set
	u8 DateFormat: 3; // Date Format
	u8 VSF: 1; // Vertical Synchronism and interruption Frequency
	u8 KeyboardType: 4; // Character Set
	u8 SSM: 1; // Start-up Screen Mode
	u8 SLS: 1; // String Length Specificator Character of PRINT USING
	u8 SRC: 1; // String Replacement Character of PRINT USING
	u8 Cur: 1; // Currency Symbol
};
Originally, within the same 'bios.h' header there was an instance of this structure defined as:

Code: Select all

const struct BasicROMVersion __at(R_BASRVN) g_ROMVersion;
... but since this header file is included by many difference source files (I don't know how it was built in SDCC, the build system uses a very complex series of Windows batch files to process it), when I tried first to build the vdp.c file (which of course includes it, and other headers) I get a duplicate definition error for g_ROMVersion, as follows:

Code: Select all

zcc -compiler=sdcc +msx -O3 -m -subtype=msxdos2 -pragma-define:CRT_DISABLELOADER=0  -I./src -I./src/msxgl -I./common -o bin/game.o -c src/game.c
zcc -compiler=sdcc +msx -O3 -m -subtype=msxdos2 -pragma-define:CRT_DISABLELOADER=0  -I./src -I./src/msxgl -I./common -o bin/vdp.o -c src/msxgl/vdp.c
zcc -compiler=sdcc +msx -O3 -m -subtype=msxdos2 -pragma-define:CRT_DISABLELOADER=0  -I./src -I./src/msxgl -I./common -o bin/bank1.o -c src/bank1.c
zcc -compiler=sdcc +msx -subtype=msxdos2 -pragma-define:CRT_DISABLELOADER=0 -o bin/game.com -create-app bin/game.o bin/vdp.o bin/bank1.o
bin/vdp.asm: error: duplicate definition: game_c::_g_ROMVersion
make: *** [Makefile:160: game] Error 1
Instead I've changed the definition of the instance of the struct to be extern, which I believe to be the correct course of action - there will be multiple source files including the bios.h header, but of course there should only be one instance of the g_ROMVersion object globally, hence:

Code: Select all

extern const struct BasicROMVersion __at(R_BASRVN) g_ROMVersion;
This now builds without the duplicate definition error, however, I instead get undefined symbol errors:

Code: Select all

zcc -compiler=sdcc +msx -O3 -m -subtype=msxdos2 -pragma-define:CRT_DISABLELOADER=0  -I./src -I./src/msxgl -I./common -o bin/game.o -c src/game.c
zcc -compiler=sdcc +msx -O3 -m -subtype=msxdos2 -pragma-define:CRT_DISABLELOADER=0  -I./src -I./src/msxgl -I./common -o bin/vdp.o -c src/msxgl/vdp.c
zcc -compiler=sdcc +msx -O3 -m -subtype=msxdos2 -pragma-define:CRT_DISABLELOADER=0  -I./src -I./src/msxgl -I./common -o bin/bank1.o -c src/bank1.c
zcc -compiler=sdcc +msx -subtype=msxdos2 -pragma-define:CRT_DISABLELOADER=0 -o bin/game.com -create-app bin/game.o bin/vdp.o bin/bank1.o
src/msxgl/vdp.c:1189: error: undefined symbol: _g_ROMVersion
  ^---- (_g_ROMVersion+0)
make: *** [Makefile:160: game] Error 1
I want to know if z88dk-z80nm is actually telling me that g_ROMVersion is present in the vdp.o object file:

Code: Select all

$ /opt/toolchains/z88dk/bin/z88dk-z80nm bin/vdp.o 
Object  file bin/vdp.o at $0000: Z80RMF16
  Name: vdp_c
  Section bss_compiler: 54 bytes
  Section IGNORE: 0 bytes
  Section code_crt_init: 0 bytes
  Section code_compiler: 1578 bytes
  Symbols:
    G A $0035 _g_ScreenPatternHigh (section bss_compiler) (file src/msxgl/vdp.c:505)
   ...
   SNIP LOTS MORE SYMBOLS HERE
   ...
    G A $05DE _VDP_SetPatternTable (section code_compiler) (file src/msxgl/vdp.c:1536)
  Externs:
    U         _g_ROMVersion
As I say, I really don't know how this was all getting built under Windows with batch files directly in SDCC, but I'd appreciate some guidance on what I should be doing here. Is 'extern'-ing those symbols in the headers the correct course of action?
megatronuk
Member
Posts: 34
Joined: Fri Jan 28, 2022 11:39 pm

Re: Building sdcc projects with z88dk

Post by megatronuk »

Question - does the pre-processor support "pragma once"?

... the source and headers I'm trying to build are littered with it.
megatronuk
Member
Posts: 34
Joined: Fri Jan 28, 2022 11:39 pm

Re: Building sdcc projects with z88dk

Post by megatronuk »

Okay, so it looks like it is down to the SDCC project parts of the code using "#pragma once". I've started adding traditional include guards to the headers included so far and it looks like that's taken care of it.

Code is compiling, linking and running on OpenMSX. Not running correctly (suspect it is the inline assembly portions of the SDCC project - the functions I'm calling so far are using the __naked decorator, so I probably need to get out a Z80 assembly book and figure out what they are doing [VDP chip type identification]), but not blowing up either!
Post Reply