News:

Printed Amstrad Addict magazine announced, check it out here!

Main Menu

Z80 Libraries Locomotive BASIC Integration

Started by bert003, 04:57, 14 August 23

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

bert003

Hello everyone,

I am looking for a tutorial that explains to me how I can achieve the following:

1. Write Z80 routines and save them into a binary file. The routines will include:
a) Output a character passed as a parameter
b) Output a string passed as a parameter
c) Plot a pixel given 2 co-ordinates passed as parameters

Once these routines are saved into a binary file, I want to load the BIN file in BASIC and use these routines via calls.

For example (addresses are fictitious)

CALL &3C732, A            <--- This will call the routine to output a character on screen, passing the variable A
CALL &3C832, B            <--- This will call the routine to output a string on screen, passing the variable B
CALL &3C932, X, Y        <--- This will call the routine to plot a pixel on screen, passing the variables X and Y

I owned an Amstrad 6128 plus, I know BASIC programming and also have done some work with Z80 assembly.

I am curious how to properly integrate both languages to obtain faster screen output since I am planning to do a simple game.

Thanks for your time.

Neurox66

#1
Hi,
What you are asking for is very simple to do :D 
First of all there are Firmware calls that help you a lot,
here is a detailed list: https://www.grimware.org/doku.php/documentations/firmware/guide/jumpblock

This is a small example of what you can do:
ld DE, 200; contains the relative X-coordinate.
ld HL, 100; contains the relative Y-coordinate.
call &BBED ;Firmware routine GRA PLOT RELATIVE
;---------------------------------------------
ld A, 'C' ; contains the character to be printed.
call &BB5D ;Firmware routine TXT WR CHAR
;---------------------------------------------
;For print a string
ld hl,textToPrint ;Load a string
call _prints

textToPrint: defb "C","i","a","o"," ","M","o","n","d","o","!",#00
; Print string routine
_prints:
ld a,(hl)
or a
ret z
call &BB5A
inc hl
jr _prints

To compile I use Pasmo
Obviously this is the first step, then you have to create specific routines for yourself.
Take for example the _prints routine where the first LD instruction loads the string to be printed on the screen.

Neurox66
CPC 464+ with C4CPC and Gotek HxC USB Drive - 
CPC 6128+ with Nova, FlashGordon,AmsDap, SymbiFace III -
CPC 6128 with M4 ... and other Amstrad computers

bert003

Thanks for your reply Neurox66.

The link you provided is very useful.

However your code executes from top to bottom sequentially. I want to wrap each part into a function and then call it from BASIC passing parameters. In your code you used static variables and strings.

How can I do that please? And how will I then know the address to call from BASIC for each function?

ajcasado

Hi Bert003,

Take a look at this link of the wiki: https://www.cpcwiki.eu/index.php?title=Technical_information_about_Locomotive_BASIC&mobileaction=toggle_view_desktop

You'll find the information about passing parameters to a machine code routine from basic using the CALL statement.

CPC 664

Empiezas a envejecer cuando dejas de aprender.
You start to get old when you stop learning.

bert003

Thanks for the link @ajcasado

I guess you are referring to the code below:

ROUT1:  CP  x          ;test register A if "x" parameters were given, e.g. x = 2
        RET  NZ        ; if not exactly x parameters then do not execute RSX.
        LD  L,(IX+0)
        LD  H,(IX+1)   ; HL = value of last parameter       
        LD  E,(IX+2)
        LD  D,(IX+3)   ; DE = value of next to last parameter

Now what I am not understanding is how to put the 3 functions I mentioned in a single BIN file and then using the CALL command from BASIC to call each function. How will I get the address of each function?

A sample code would really help me, even for just one functiom (ex: the output character function). I will then implement the others myself once I understand exactly how things work.

Thanks

ajcasado

#5
I think that a neat way to achieve your target is the use of RSX commands.
See this sample code: https://cpctech.cpcwiki.de/source/rsxshll.html
  • You should put the address of the code following the org directive (&8000 in the sample).
  • Use the MEMORY basic statement to reserve RAM space for the binary code:
    MEMORY ‹address-1›
  • Load the binary file from basic using the LOAD statement:
    LOAD ‹file name›[,‹address›]
  • Initialize your RSX functions using the CALL basic statement:
    CALL ‹address›

After that you can use your RSX functions in your basic code as is explained in the link: https://www.cpcwiki.eu/index.php?title=Technical_information_about_Locomotive_BASIC&mobileaction=toggle_view_desktop#Passing_parameters_to_a_RSX_.28Resident_System_Extension.29_command_or_binary_function

You should set the beginning address of the binary code for the RSX commands as high as you can taking into account that the last used address of the binary code cannot surpass the address &a7ff. The higher address you set the more RAM available for your basic code you get.

EDIT: Actually, you can know the address you cannot surpass using in basic:
PRINT HIMEM
This should be executed just before switching on the computer, and depends on the ROM installed.

CPC 664

Empiezas a envejecer cuando dejas de aprender.
You start to get old when you stop learning.

asertus

Yes, RSX commands are quite convenient, by the way, you can find plenty of examples of what you ask in the 8bp library, that is mainly intended to be called by BASIC.

https://github.com/jjaranda13/8BP

andycadley

Assuming your assembler produces a listing of code or at least labels, the easiest way to find the correct addresses is to label each routine and check them there.

RSX provides a more convenient version, but it's obviously trading a certain amount of speed for the convenience of named commands.

And note that if all you do is make firmware calls from your code (to print characters or plot pixels for example) you will likely find it's not much faster than just using PRINT or PLOT. Improving performance there really requires sacrificing some of the functionality that the firmware code provides (not supporting multiple MODEs or screen scrolling etc)

bert003

Thanks a lot everyone for your replies and links. I really appreciate the support here.

@ajcasado your sample code and explanation really helped me understand.

@asertus I never heard about 8BP  :o will surely give it a try

@andycadley so from your comment I can conclude that you have to code in pure assembly if you want turbo speed. I always asked myself... Is it possible that so many great Amstrad CPC games were fully coded in assembly language?

andycadley

Quote from: bert003 on 17:58, 14 August 23@andycadley so from your comment I can conclude that you have to code in pure assembly if you want turbo speed. I always asked myself... Is it possible that so many great Amstrad CPC games were fully coded in assembly language?
Pretty much all commercial games were written entirely in machine code. BASIC is reasonably fast for a general purpose interpreted language, but it doesn't come close to what you can achieve by writing directly in Z80.

bert003

#10
@andycadley based on your last comment.... I am also interested in coding for the Amstrad CPC using the C programming language. Searching online I came across various suggestions on which programs to use.

Can you suggest which is the "best" way to go if you would like to program in C? IDE? Compiler? And are there are ready made libraries that I can use to test and learn from please?

Will C programming output machine code with speeds comparable to pure assembly?

UPDATE: In the meantime, I found this https://retrofun.pl/2023/02/19/writing-for-cpc6128-in-year-2023/ but obviously your professional opinion matters a lot to me

andycadley

You may want to look into CPCTelera, which is a C setup that also includes a bunch of extra libraries for doing CPC specific things. C won't be as fast or as small as hand tuned assembly, but it's certainly fast enough to write acceptable games and such in and a lot faster than BASIC.

I can't say I've used it much though, so I'll let the experts comment on that more.

bert003

Thanks again @andycadley ... I'll surely give it a try ;)

bert003

Managed to install it on Windows... now searching for a beginners tutorial since I am eager to start developing with it. No luck so far :'( ... 

andycadley

Quote from: bert003 on 09:46, 15 August 23Managed to install it on Windows... now searching for a beginners tutorial since I am eager to start developing with it. No luck so far :'( ...
Might be worth starting another thread here mentioning it in the title, there are plenty of people using it (and the developer is on the forum) but they might not be reading a thread about BASIC development.  :)

bert003

Thanks for the suggestion. You are right. Will do  :)

asertus

Quote from: bert003 on 08:49, 15 August 23Thanks again @andycadley ... I'll surely give it a try ;)
Actually, CPCtelera is very convenient to develop assembler programs too. All C functions have their corresponding ASM version, and most are already implemented directly in assembler.

In CPCtelera github there are small examples of asm projects.

bert003

@asertus thanks for your feedback. Yes I saw the examples (ASM and also C).

They look useful so unless I find a beginner's tutorial I will start experimenting with them.

asertus

Quote from: bert003 on 11:51, 15 August 23@asertus thanks for your feedback. Yes I saw the examples (ASM and also C).

They look useful so unless I find a beginner's tutorial I will start experimenting with them.
You know, every year we have the CPCRetrodev contest. Many games are developed using CPCtelera, and some of them are in assembler. You may look at them and analyze the source code.

Rabs

Quote from: bert003 on 11:51, 15 August 23@asertus thanks for your feedback. Yes I saw the examples (ASM and also C).

They look useful so unless I find a beginner's tutorial I will start experimenting with them.
Have you had a look at Z80 Assembly programming for the Amstrad CPC?

bert003

Quote from: asertus on 16:21, 15 August 23You know, every year we have the CPCRetrodev contest. Many games are developed using CPCtelera, and some of them are in assembler. You may look at them and analyze the source code.
I did not know about this @asertus and that is exactly what I was looking for to get an idea. Thanks a lot

bert003

Quote from: Rabs on 19:09, 15 August 23Have you had a look at Z80 Assembly programming for the Amstrad CPC?
Thanks @Rabs. Yes I came across that page earlier on and it has a lot of great examples and explanations. I might consider in fact going totally assembly programming one day.

However for the time being, I think CPCtelera bridges the gap between total assembly programming and BASIC and still allows you to program at a "higher" level while still obtaining near to assembly speed.

Powered by SMFPacks Menu Editor Mod