Simple way of getting extended functions on BDS-C

By Josb

Master (206)

Josb's picture

12-10-2015, 21:12

I know that there are other compilers which are better than this one, but this is my favourite because is free, bizarre and totally coded under CP/M systems long time ago.

However, I would like to show a simple way of getting new functions on BDS-C for MSX-DOS using macros Big smile. As I explain inside the msxbios.h file there are other ways but I haven't been not able to build a .CRL file using current cross assemblers and I dont feel like to use M80 compiler. I usually obtain too many errors in some library functions Sad.

Anyway, '.CRL' format is clearly explained in the BDS-C book If someone wants to try it.

My way of doing is including these files in the same folder

msxbios.h

/*
	WHAT IS THIS:
	------------
	Here  you can find MACROS and FUNCTIONS  to be used for calling
	MSX-BIOS functions on MSX DOS programs. 

	This file is a simple way to get new functions for BDS C due to
	the fact that it was created for CP/M OS. There are two ways of
	getting that BDS C can use new	functions.  The  first	one is,
	modify and re-compile all source files	what is no easy because
	it was written	using 8080 assembler language. And  the  second 
	one is,  create a specific library in .CRL  format what   I was 
	unable to make it in spite of hardly trying it.

	Therefore, I've made  this file  which has MACROS and FUNCTIONS
	defined for being used straightly in your source code.

	But, Remind  that this file is just a  simple example of how to 
	make new functions for BDSC-C.	 
	
	HOW TO USE THIS FILE:
	--------------------
	It is needed to be in the same folder that the main file or you
	should aim at new folder in your source file.

	Later on, at the  beginning of your code  you had  to write the 
	next line:  
	
		#include "msxbios.h"

	Starting the object-code calling the next function:

		setmsxbios();		/* Put code in memory	  */

	Then, call  the  BIOS  functions  through  MACROS and FUNCTIONS 
	defined in this file as it is showed in the next lines:
			
		locate(1,2);		/* MACRO		  */
		a=vpeek(0x1000);	/* FUNCTION		  */			  
  
	HOW TO COMPILE YOUR CODE 
	------------------------
	The way of compiling is...
		
		'cc source.c'                   (first step)

		'clink source' or 'l2 source'   (second step)

	...and your msx dos app should appear in your folder

	LIST OF FUNCTIONS AND THEIR PARAMETERS:
	--------------------------------------
	- beep()
	- cls()
	- color(mode,foreground color, background color, border color)
	- locate(colum, row)
	- screen(screen mode)
	- vpoke(vram address, value to put in)
	- _vpeek(address) do not use it, vpeek instead of
	- vpeek(vram address to read from) returns 'char' value

	UNNECESSARY APOLOGIES
	---------------------
	I would be so sorry if it didn't work out correctly. I couldn't 
	test the whole of functions included.I won't be responsible for
	any badly behaviour of it.

	AUTHOR
	------
	JOSE JAVIER (Jos'b & FranChesstein All-in-one)
	2014 Copyleft - Spain
*/

			/* MSX2 macros like functions */

#define beep()		msxbios[21]=0x01;msxbios[20]=0x7D;call(&msxbios[14],0,0,0,0)
#define cls()		msxbios[21]=0x00;msxbios[20]=0xC3;call(&msxbios[14],0,0,0,0)
#define color(w,x,y,z)	msxbios[13]=w;poke(0xF3E9,x);poke(0xF3EA,y);poke(0xF3EB,z);msxbios[21]=0x00;msxbios[20]=0x62;call(&msxbios[12],0,0,0,0)
#define locate(x,y)	msxbios[11]=x;msxbios[9]=y;msxbios[21]=0x00;msxbios[20]=0xC6;call(&msxbios[8],0,0,0,0)
#define screen(x)	msxbios[13]=x;msxbios[21]=0x00;msxbios[20]=0x5F;call(&msxbios[12],0,0,0,0)
#define _vpeek(x)	msxbios[11]=x/0x100;msxbios[9]=x%0x100;msxbios[21]=0x01;msxbios[20]=0x74;call(&msxbios[8],0,0,0,0)
#define vpoke(x,y)	msxbios[11]=x/0x100;msxbios[9]=x%0x100;msxbios[13]=y;msxbios[21]=0x01;msxbios[20]=0x77;call(&msxbios[8],0,0,0,0)

char msxbios[100];

setmsxbios()
{
	/*
		IN:	A,H,L,B,C,D,E	Regiters
		OUT:	AF,HL		Registers
	*/

	int registers;	       

			  /* OP-CODEs are written in memory */

			  /* Given values to registers	  */	 
			
	msxbios[ 0]=0x1E; /*	   LD E,11h	   */  
	msxbios[ 1]=0x11; 
	msxbios[ 2]=0x16; /*	   LD D,22h	   */
	msxbios[ 3]=0x22;
	msxbios[ 4]=0x0E; /*	   LD C,33h	   */	  
	msxbios[ 5]=0x33;
	msxbios[ 6]=0x06; /*	   LD B,44h	   */  
	msxbios[ 7]=0x44; 
	msxbios[ 8]=0x2E; /*	   LD L,55h	   */
	msxbios[ 9]=0x55;
	msxbios[10]=0x26; /*	   LD H,66h	   */	  
	msxbios[11]=0x66;
	msxbios[12]=0x3E; /*	   LD A,77h	   */	  
	msxbios[13]=0x77;

			  /* Calling BIOS rutine   */	   

	msxbios[14]=0xFD; /*	   LD IY, FCC0h    */ /* EXPTBL - 1  */
	msxbios[15]=0x2A;
	msxbios[16]=0xC0;
	msxbios[17]=0xFC;

	msxbios[18]=0xDD; /*	   LD IX, EEFFh    */ /* BIOS rutine */
	msxbios[19]=0x21;
	msxbios[20]=0xFF;
	msxbios[21]=0xEE;

	msxbios[22]=0xCD; /*	   CALL 001Ch	    */
	msxbios[23]=0x1C;
	msxbios[24]=0x00;

			  /* Saving register values */
	
	msxbios[25]=0xF5; /*	   PUSH AF & POP BC */
	msxbios[26]=0xC1;
	msxbios[27]=0xED;

	msxbios[28]=0x43; /*	   LD (----),BC = AF */
	registers  = &msxbios[35];
	msxbios[29]= registers % 0x100; /* Low	byte */
	msxbios[30]= registers / 0x100; /* High byte */

	msxbios[31]=0x22; /*	   LD (----),HL     */	    
	registers  = &msxbios[37];
	msxbios[32]= registers % 0x100; /* low	byte */
	msxbios[33]= registers / 0x100; /* high byte */

	msxbios[34]=0xC9; /*	   RET		    */

			  /* Buffer		*/

	msxbios[35]=0x00; /* Store AF register	*/
	msxbios[36]=0x00;
	msxbios[37]=0x00; /* Store HL register	*/
	msxbios[38]=0x00;		

}

/* Functions which return values */
char vpeek(address)
int address;
{
	_vpeek ( address );	/* Run MACRO */
	return ( msxbios[36] ); /* Return just A register value */
} 

/* Just return AF register value */
int ldaf()
{
       return ( msxbios[36] * 256 + msxbios[35] );	   
}

/* Just return HL regiter value */
int ldhl()
{
	return ( msxbios[38] * 256 + msxbios[37] );
}

example.c

/*
	testing 'msxbios.h' file by Jos'b
*/

#include 
#include "msxbios.h"

main(argc,argv)
int	argc;
char	*argv[];
{
	int i;

	printf("BDS-C Show");
	getchar();   

	/* Set MSXBIOS */
	setmsxbios();
	printf("1.- msxbios is ready");
	getchar();

	cls();
	printf("2.- screen cleared\n");
	printf("    Register AF value %d\n", ldaf() );
	printf("    Register A  value %d\n",ldaf()/0x100);
	printf("    Register F  value %d\n",ldaf()%0x100);
	printf("    Register HL value %d\n", ldhl() );
	printf("    Register H  value %d\n",ldhl()/0x100);
	printf("    Register L  value %d\n",ldhl()%0x100);

	getchar();
	cls();
	for(i=1;i<18;i++)
	{
		locate(i,i);printf("@");
	}
	locate(1,19);printf("3.- calling locate(x,y) macro\n");
	vpoke(0,65);
	locate(1,20);
	printf("5.- Written value inside VRAM");
	getchar();

	beep();
	printf("4.- BEEP");
	getchar();				 
	
	cls();
	for (i=65;i<75;i++) 
	{
		cls();	     
		printf("%c\n",i); 
		printf("6.- Address value in 0000h VRAM  %d\n", vpeek(0) );
		printf("    Register AF value %d\n",ldaf() );
		printf("    Register A  value %d\n",ldaf()/0x100);
		printf("    Register F  value %d\n",ldaf()%0x100);
		getchar();
	}

	color(0,4,14,14);
	printf("7.- changing colour");
	getchar();

	color(0,6,7,8);
	screen(5);
	getchar();

	screen(1);
	color(0,11,14,15);
	locate(2,4);
	printf("8.- setting screen 1\n"); 
	printf("Register HL value %d\n",ldhl() );
	printf("Register H  value %d\n",ldhl()/0x100);
	printf("Register L  value %d\n",ldhl()%0x100);
	getchar();

	screen(0);	  
	color(0,15,4,4);
	cls();
	exit();
}

and then run the compiler commands

'cc example.c'
'clink example' or 'l2 example'

Eventually, this is just for fun, so you wouldn't find a huge number of functions or anyelse amazing thing

Login or register to post comments

By Manuel

Ascended (19273)

Manuel's picture

25-01-2017, 09:38

Why use macros and not functions?

By Josb

Master (206)

Josb's picture

25-01-2017, 13:25

Just for fun
BDS-C doesn’t have specific functions for MSX. It is a pity. However it is easy to create functions using native assemblers. It is detailly explained in the user manual. In fact, the own compiler offers an app to translate the pseudo-code to bare asm file for M80.
As I said, I have tried to make one using cross-compilers but I was on troubles with some fucntions which worked with many parameters, so, I decided don’t keep giving a go.
Anyway, I think BDS-C is a good compiler for enjoy coding and MSX. It lets us lots of posibilities for our creativity. Nothing is done for it.

Big smile

By Manuel

Ascended (19273)

Manuel's picture

25-01-2017, 13:46

The problem with the macros is that every time you use them, the whole macro content is put in the code... So, I wondered why you didn't create an MSX library with actual C-functions in them to do all that stuff, instead of defining macros for them.

By Josb

Master (206)

Josb's picture

25-01-2017, 14:15

Sorry, I misunderstood.

Because it is not something serious. Just a way of showing how to outdo some inconviences in BDS-C in a easy way.

By Wolverine_nl

Paragon (1160)

Wolverine_nl's picture

25-01-2017, 14:34

Josb wrote:

Because it is not something serious. Just a way of showing how to outdo some inconviences in BDS-C in a easy way.

I would use a library with functions as well. The reason this would be fun is because then your code becomes more compact and the possibilities grow. More possibilities means more room for experimentation etc. etc.

Cool that you use BDS-C, an old one, we were talking about this on another topic as well, Dark Schneider was checking some of the differences.

By Josb

Master (206)

Josb's picture

25-01-2017, 16:30

Quote:

I would use a library with functions as well. The reason this would be fun is because then your code becomes more compact and the possibilities grow. More possibilities means more room for experimentation etc. etc.

I agree with you.

For me part, I think the best thing about BDS-C is that it is totally open-source and it will be possible to create a new brand c compiler for MSX adding the whole of whatever you want. That is as easy as taking the code and switching from the old 8080 instructions to the modern z80 instructions. So, we could have a native compiler with real functions for MSX without any necessity of using external libraries as MSX-C has. Just write and compile.

But, that is another interesting matter.

Quote:

The problem with the macros is that every time you use them, the whole macro content is put in the code... So, I wondered why you didn't create an MSX library with actual C-functions in them to do all that stuff, instead of defining macros for them.

The first idea was to include directly object code in arrays in order to be called by call() bds-c function. Extremely faster and less spend of memory. But leisure is so, you be allowed to do things without any explanation.

The problem with BDS-C is that if you make a specific library for it (obviously for Z80), you will have a program where part of the code will be working just with 8080 op-codes and the other part will be using z80 instructions and mixing different processors doesn't seem very efficient. Smile

Anyway, I think it is a good way of enjoying yourself with real machines due to its extreme simplicity.

By Louthrax

Prophet (2436)

Louthrax's picture

25-01-2017, 19:01

Manuel wrote:

The problem with the macros is that every time you use them, the whole macro content is put in the code... So, I wondered why you didn't create an MSX library with actual C-functions in them to do all that stuff, instead of defining macros for them.

Well, if you have functions that will NEVER be re-entered, it might be more efficient to store the parameters in static memory location like Josb does (stacking the parameters can take more code and be slower, depending on the compiler). In the case of DOS functions, it might be interesting to do so, unless you define your own DOS error-handling routines (but IIRC you are not allowed to call DOS functions again inside error-handling routines).

I was planning to test an approach like that for my MSX2 VDP-related functions (setting the VDP registers on the "macro" side, then just call a generic function that executes the command).