C API and graphics library for Next layer 2 screen

If you like transforming your statements into code, this is the place for you

Moderator: Programming Moderators

Stefan123
Posts: 102
Joined: Mon Jun 05, 2017 9:38 pm

C API and graphics library for Next layer 2 screen

Post by Stefan123 » Sat Aug 19, 2017 4:03 pm

I have created a C API and graphics library for the Next layer 2 screen. The project is available on GitHub at:
https://github.com/stefanbylund/zxnext_layer2

I have also created an example program on GitHub for demonstration and regression testing of the API:
https://github.com/stefanbylund/zxnext_layer2_demo

The API provides access to the I/O port interface of the Next layer 2 screen. In addition to this, it provides a graphics library for drawing on the layer 2 screen or a layer 2 off-screen buffer. Note that the 48 KB layer 2 screen is divided in three 16 KB sections (top, middle, bottom), which have to be paged-in separately when drawing on the screen. The drawing functions handle this paging internally and take care of the complications when a drawing operation covers more than one section.

Any feedback, suggestions for improvements or contributions to the API is much appreciated.

The source code has been compiled with the Z88DK C compiler (2017-08-18 snapshot) and successfully tested with the ZEsarUX 5.1 (2017-07-24 snapshot) and CSpect 0.6 Next emulators. See https://github.com/stefanbylund/zxnext_layer2 for a list of known problems and workarounds.

This API is a work in progress and will be continuously updated as more information about the layer 2 screen is made known and implemented by the emulators and when the specification is finally released. I also intend to add more drawing functions for circles/ellipses etc. The new layer 2 front/back double buffer feature supported by CSpect is not yet supported by this API. Some details around this feature are still a bit unclear to me and ZEsarUX doesn't support it yet. However, by already having support for off-screen buffers in general in the API, adding support for the new double buffer feature seems like a natural fit. When ZEsarUX supports hardware scrolling (only CSpect supports that for now), I will add examples of doing that and investigate if any helper functions should be added to the API.

I think the performance of the drawing functions is pretty decent (especially when using the sdcc_iy flavour of zxnext_layer2.lib) except for the layer2_blit_transparent() function. This function needs to blit at pixel level in order to handle transparency and can probably be heavily improved by using the Next-specific ldi*/ldd* Z80 instructions. The basic layer2_blit() function could probably benefit from using the DMA when supported by the emulators. The new fillde instruction could probably be used for improved drawing of horizontal lines and filled rectangles.

Stefan123
Posts: 102
Joined: Mon Jun 05, 2017 9:38 pm

Re: C API and graphics library for Next layer 2 screen

Post by Stefan123 » Mon Aug 28, 2017 8:13 pm

Update

I have updated the C layer 2 graphics library with documentation on layer 2 hardware scrolling and added two specialized blit functions optimized for blitting new columns and rows in horizontal and vertical scrolling. I have also added several examples on horizontal and vertical scrolling of a single layer 2 screen and between multiple layer 2 screens. As you can see from the examples, once you understand how the layer 2 scrolling works, it's quite easy to use it from C.

https://github.com/stefanbylund/zxnext_layer2
https://github.com/stefanbylund/zxnext_layer2_demo

The graphics library now supports the Next's extended RAM bank switching model when working with layer 2 off-screen buffers.

Note that layer 2 hardware scrolling is currently only supported by CSpect and not ZEsarUX.

Tip: There are two C compilers in z88dk; the SDCC compiler and the SCCZ80 compiler. I recommend to use the SDCC compiler since it generates much more optimized code than the SCCZ80 compiler. When working with layer 2 graphics, the difference between the two compilers is quite significant.

Alcoholics Anonymous
Posts: 511
Joined: Mon May 29, 2017 7:00 pm

Re: C API and graphics library for Next layer 2 screen

Post by Alcoholics Anonymous » Tue Aug 29, 2017 4:12 am

Nice Stefan but people likely won't try it unless you supply a snapshot to run!
https://drive.google.com/file/d/0B6XhJJ ... sp=sharing

There is layer 2 scrolling in there that will only work with cspect (at least until the next binary release of zersarux). Copy all the files to cspect's directory, start cspect with "cspect -zxnext -mmc=.\" and hit F2 to load the snapshot.

Just keep pressing enter to see all 32 screens.

I cheated a bit - I didn't do all the makefiles and build the library and whatnot. Instead I just copied the already built lib files and the includes so that I could build the demo with the compile line at the top of the .c file. I think a simple approach will make it easier for people to try.

I think what we are missing is a means to easily install 3rd party libraries:
https://github.com/z88dk/z88dk/issues/337
Last edited by Alcoholics Anonymous on Tue Aug 29, 2017 3:14 pm, edited 1 time in total.

User avatar
chernandezba
Posts: 229
Joined: Mon May 29, 2017 8:14 pm

Re: C API and graphics library for Next layer 2 screen

Post by chernandezba » Tue Aug 29, 2017 12:23 pm

Stefan123 wrote:
Mon Aug 28, 2017 8:13 pm


Note that layer 2 hardware scrolling is currently only supported by CSpect and not ZEsarUX.

ZEsarUX does support hardware scrolling on the last source code, so you must compile the sources to try it. There's not any new beta version which supports it, but it will on the next days ;)
----

ZEsarUX
ZX Second-Emulator And Released for UniX
https://github.com/chernandezba/zesarux

Stefan123
Posts: 102
Joined: Mon Jun 05, 2017 9:38 pm

Re: C API and graphics library for Next layer 2 screen

Post by Stefan123 » Tue Aug 29, 2017 9:02 pm

Alvin, thanks for your suggestions :) I have now created a prebuilt snapshot that is automatically rebuilt when the project is updated. It is available here:

https://github.com/stefanbylund/zxnext_ ... 2_demo.zip

I have also added the required z88dk command-line invocation to the header of the zxnext_layer2_demo.c source file.

Your idea about providing a tool in z88dk for installing 3rd party libraries and headers into a z88dk installation sounds really good. This will make it a lot easier to use 3rd party libraries in your programs.

Stefan123
Posts: 102
Joined: Mon Jun 05, 2017 9:38 pm

Re: C API and graphics library for Next layer 2 screen

Post by Stefan123 » Tue Aug 29, 2017 9:07 pm

Cesar, I'm looking forward to test the new beta version of ZEsarUX with its support for hardware scrolling :) Keep up the good work!

Alcoholics Anonymous
Posts: 511
Joined: Mon May 29, 2017 7:00 pm

Re: C API and graphics library for Next layer 2 screen

Post by Alcoholics Anonymous » Sun Sep 03, 2017 3:34 pm

Stefan123 wrote:
Tue Aug 29, 2017 9:02 pm
Your idea about providing a tool in z88dk for installing 3rd party libraries and headers into a z88dk installation sounds really good. This will make it a lot easier to use 3rd party libraries in your programs.

z88dk-install has been added for the Sep 4 build.

This is an example:
https://drive.google.com/file/d/0B6XhJJ ... sp=sharing
The readme.txt in there gives instructions for installation and removal.

After the library is installed, the header file is accessed via:
#include <lib/zxn/zxnext_layer2.h>
and the library is linked against via:
-llib/zxn/zxnext_layer2

If you see something that can be improved let me know.

Stefan123
Posts: 102
Joined: Mon Jun 05, 2017 9:38 pm

Re: C API and graphics library for Next layer 2 screen

Post by Stefan123 » Mon Sep 04, 2017 8:39 pm

Great! I will test it as soon as I get some spare time, I have long working hours this week...

Stefan123
Posts: 102
Joined: Mon Jun 05, 2017 9:38 pm

Re: C API and graphics library for Next layer 2 screen

Post by Stefan123 » Wed Sep 06, 2017 9:07 pm

Hi Alvin, I have now tested the new z88dk-install tool in the z88dk snapshot from 2017-09-06 on my Windows 10 computer. I have been able to successfully install, update and remove your 3rd party packaging example of zxnext_layer2. However, I have encountered the following problems:

1. The z88dk-install tool does not run under MinGW/MSYS but gives the error "sh: /d/Spectrum/z88dk/bin/z88dk-install.exe: Bad file number". Note that the main zcc tool runs fine in this environment.

2. When running z88dk-install in a standard Windows command window, there is an irritating popup dialog which requires confirmation for allowing the program to perform changes in the system. Note that the main zcc tool does not trigger any popup dialogs.

3. When running z88dk-install without any options, it doesn't show the help text. However, it seems to quickly open and close a second window.

4. When running z88dk-install with only a target option (e.g. z88dk-install +zxn), it doesn't show the installed 3rd party libraries. However, it seems to quickly open and close a second window.

5. When installing, there are a couple of "The system cannot find the path specified" errors after the text "Generating newlib headers...". However, the actual installation seems to work fine anyway.

6. When removing, the text "Generating newlib headers..." appears but is a bit misleading. The same "The system cannot find the path specified" errors that appear when installing also show up when removing.

7. Only headers and libraries in a 3rd party library that have exactly the same name as the 3rd party library package are installed. For example, in zxnext_layer2 there are two headers, zxnext_layer2.h and zxnext_registers.h, but only the zxnext_layer2.h header is installed. For this particular case, I plan to retire the zxnext_registers.h header later on and use the definitions in z88dk but I'm not there yet. It does seem a bit restrictive to only allow a 3rd party library to have only one header and with the exact same name as the 3rd party library.

8. The header files installed in the z88dk/include/_DEVELOPMENT/proto/lib/zxn directory are converted to DOS format while the header files installed in the clang, sccz80 and sdcc directories are copied without any modification. What are the headers in proto and clang used for? Does the installation tool do anything more than just copying the files to be installed?


The required include and library paths are a bit long:

#include <lib/zxn/zxnext_layer2.h>
-llib/zxn/zxnext_layer2

I would prefer to be able to use "#include <zxnext_layer2.h>" and "-lzxnext_layer2". The "zxn" part seems redundant since it is implied when specifying the target when compiling. The long include path is especially troublesome if you want to have source files that should be compilable with a 3rd party library regardless of whether the 3rd party library is used outside of z88dk or installed within z88dk using z88dk-install.

The only problem I can see with skipping the long include and library paths is if a 3rd party library would provide a header or library with a filename that collides with the standard headers and libraries in z88dk. In that case, it makes sense for the standard headers and libraries to have priority. In practice, I don't think this is a problem and as a 3rd party library author you should respect the standard namespace.

Multiple 3rd party libraries having headers and libraries with the same filenames would be a problem regardless of using long or short include and library paths. In practice, this will only be a problem if the 3rd party library author uses filenames that are too common and non-descriptive (which, in my opinion, is the author's responsibility to fix) or if installing two 3rd party libraries with the same purpose (e.g. two ZIP compression libraries) that happen to use exactly the same filenames.

I hope you don't feel bad with all my comments, I just want this tool to be really good. If you fix any of the above issues, I'm more than happy to test them :)

Alcoholics Anonymous
Posts: 511
Joined: Mon May 29, 2017 7:00 pm

Re: C API and graphics library for Next layer 2 screen

Post by Alcoholics Anonymous » Thu Sep 07, 2017 5:46 am

Thanks for testing Stefan. The nightly build of z88dk-install is incorrect and I'm looking at fixing that. We removed windows-specific code by adding a compatibility header for dirent.h and that does not agree with the cross-compiler used for the build. It works fine for vs2015. My binaries are here, including a working z88dk-install: https://drive.google.com/file/d/0B6XhJJ ... sp=sharing
5. When installing, there are a couple of "The system cannot find the path specified" errors after the text "Generating newlib headers...". However, the actual installation seems to work fine anyway.
This one is unrelated - another target has had new headers added but some directories were not created.
7. Only headers and libraries in a 3rd party library that have exactly the same name as the 3rd party library package are installed. For example, in zxnext_layer2 there are two headers, zxnext_layer2.h and zxnext_registers.h, but only the zxnext_layer2.h header is installed. For this particular case, I plan to retire the zxnext_registers.h header later on and use the definitions in z88dk but I'm not there yet. It does seem a bit restrictive to only allow a 3rd party library to have only one header and with the exact same name as the 3rd party library.
For this I would have to change how things are done and I may do that. For uninstall, the problem is knowing what headers belong to the library and if that information is not in the name, it has to be somewhere else, maybe a special file listing what's part of the library and what's not.
8. The header files installed in the z88dk/include/_DEVELOPMENT/proto/lib/zxn directory are converted to DOS format while the header files installed in the clang, sccz80 and sdcc directories are copied without any modification. What are the headers in proto and clang used for? Does the installation tool do anything more than just copying the files to be installed?
The proto header will be an exact copy of the one provided (it's opened in binary mode so there will be no text mode cr/lf stuff added). This header prototype is used to generate versions for each of the three c compilers supported: clang, sccz80 and zsdcc. m4 is used to process the prototype header which will operate in text mode and make sure the headers generated for the compilers have unix line endings.

There is a difference in the headers used for each compiler when the library routines are written in assembler because you can add information about function call linkage and what registers are unaffected by a subroutine. Each compiler may or may not support such things and they require different syntax so we write one header in the proto tree and have m4 automatically generate the proper syntax for each compiler in the clang/sccz80/sdcc trees. For C, this won't really matter so you can just have a standard header placed in proto in which case straight copies will be made for the compiler trees. If you have asm routines or mixed c and asm routines, the header should be written in the same way as other headers in the proto tree to take advantage of this extra information.

When the "generating newlib header" message is printed, m4 is being run to generate the compiler headers from the master in the proto tree.
The required include and library paths are a bit long:

#include <lib/zxn/zxnext_layer2.h>
-llib/zxn/zxnext_layer2

I would prefer to be able to use "#include <zxnext_layer2.h>" and "-lzxnext_layer2".
Yes I was thinking about the same thing and it can be done by adding another search path in each target's config file.

Post Reply