Welcome, Guest. Please login or register.


Author Topic: Enterprise C compiler for PC (Read 15020 times)

Offline Povi

  • EP addict
  • *
  • Posts: 1875
  • Country: hu
  • OS:
  • Windows 7/Server 2008 R2 Windows 7/Server 2008 R2
  • Browser:
  • Firefox 37.0 Firefox 37.0
    • View Profile
    • http://povi.fw.hu
Re: Enterprise C compiler for PC
« Reply #15 on: 2015.May.05. 15:09:09 »
it seems the LLVM uses similar technology to passing parameters as HiSoft Pascal compiler did.
*** Speicherplatz zu klein

Offline Tuby128

  • EP lover
  • *
  • Posts: 955
  • Country: hu
  • OS:
  • Windows 7/Server 2008 R2 Windows 7/Server 2008 R2
  • Browser:
  • Firefox 21.0 Firefox 21.0
    • View Profile
Re: Enterprise C compiler for PC
« Reply #16 on: 2015.May.05. 17:12:37 »
Can you present me an example?

Offline Povi

  • EP addict
  • *
  • Posts: 1875
  • Country: hu
  • OS:
  • Windows 7/Server 2008 R2 Windows 7/Server 2008 R2
  • Browser:
  • Firefox 37.0 Firefox 37.0
    • View Profile
    • http://povi.fw.hu
Re: Enterprise C compiler for PC
« Reply #17 on: 2015.May.05. 18:02:00 »
Code: [Select]
        push ix
        ld   ix, 0x0004
        add  ix, sp
        ld   hl, 0x0000
        add  hl, sp
        ld   de, (0x1501)
        add  hl, de
        call nc, 0x0693
        ld   l, (ix + 4)
        ld   h, (ix + 5)
        push hl
        ld   l, (ix + 2)
        ld   h, (ix + 3)
        pop  de
        or   a
        add  hl, de
        call pe, 0x06a6
        ld   (ix + 6), l
        ld   (ix + 7), h
        pop  ix
        pop  de
        ld   hl, 0x0006
        add  hl, sp
        ld   sp, hl
        ex   de, hl
        jp   (hl)
       

Code: [Select]
function addint(a, b : integer) : integer;
begin
  addint := a + b;
end;
*** Speicherplatz zu klein

Offline Mobsie

  • Beginner
  • *
  • Posts: 27
  • Country: de
  • OS:
  • Mac OS X 10.10.2 Mac OS X 10.10.2
  • Browser:
  • Chrome 40.0.2214.111 Chrome 40.0.2214.111
    • View Profile
Re: Enterprise C compiler for PC
« Reply #18 on: 2015.May.11. 20:45:01 »
Hi,
interesting!
I just now setup my Enterprise 128, after years, also with the great SD-Cart.

I plan to write some small games, i wirte mostly games on the vtech CreatiVisio in ASM.

But the Enterprise was one of my dream machines for years.

I will test http://www.z88dk.org/wiki/doku.php?id=platform:enterprise
looks interesting and the samples show also Inline Assembler.

Best Regards,
Mobsie

Offline Alcoholics Anonymous

  • Newbie
  • Posts: 10
  • Country: ca
  • OS:
  • Windows NT 6.2 Windows NT 6.2
  • Browser:
  • Firefox 40.0 Firefox 40.0
    • View Profile
    • Z88DK Homepage
Re: Enterprise C compiler for PC
« Reply #19 on: 2015.August.18. 08:21:05 »
some time ago I played with sdcc for EP: http://ep.lgb.hu/sdcc/

Has anyone gone further than this in trying C for the EP on either sdcc or z88dk?  Any crts, assembler libraries, etc?

Quote
I found the solution here, I searched for 'CRT0'
http://sdcc.sourceforge.net/mediawiki/index.php/Z80_port
To get rid of the problem I have to use the '--no-std-crt0' option. And it works perfectly.

The crt sets up the environment before calling main().  Some of the things it's supposed to do is initialize the data segment, zero the bss segment and initialize the heap.  If you eliminate it and don't initialize those segments, the global variables may not have correct initial values and malloc() may not work.


Offline lgb

  • EP addict
  • *
  • Posts: 3497
  • Country: hu
  • æðsta yfirmaður
  • OS:
  • Linux (Ubuntu) Linux (Ubuntu)
  • Browser:
  • Firefox 40.0 Firefox 40.0
    • View Profile
    • http://lgb.hu/
Re: Enterprise C compiler for PC
« Reply #20 on: 2015.August.18. 09:05:36 »
The crt sets up the environment before calling main().  Some of the things it's supposed to do is initialize the data segment, zero the bss segment and initialize the heap.  If you eliminate it and don't initialize those segments, the global variables may not have correct initial values and malloc() may not work.

Yes, but as I mentioned at the first URL I wrote my own crt0 for EP ...

http://ep.lgb.hu/sdcc/crt0.s

(so the no std crt0 was about using my own crt0)

I did this project some time ago, so I can't remember everything. Unfortunately sdcc was (or "is" still?) a moving target: its internals was changed all the time, but I couldn't stick with a given version (which would be a better strategy) since it had another annoying bugs (fixed later, but also introduced changes affected my tries as well). So this was a reason I lost my interest. Maybe it's time now to re-check the situation now :) I also had an "official" bugreport (about _one_ bug only) to the sdcc team:

https://sourceforge.net/p/sdcc/bugs/2089/

About 3 years, and the bug report is still have status of "open" ... :(

And for sure my work was so "initial only" that it can't be used for more serious stuffs too much.

Offline Alcoholics Anonymous

  • Newbie
  • Posts: 10
  • Country: ca
  • OS:
  • Windows NT 6.2 Windows NT 6.2
  • Browser:
  • Firefox 40.0 Firefox 40.0
    • View Profile
    • Z88DK Homepage
Re: Enterprise C compiler for PC
« Reply #21 on: 2015.August.18. 17:45:26 »
Quote
I did this project some time ago, so I can't remember everything. Unfortunately sdcc was (or "is" still?) a moving target: its internals was changed all the time, but I couldn't stick with a given version (which would be a better strategy) since it had another annoying bugs (fixed later, but also introduced changes affected my tries as well). So this was a reason I lost my interest. Maybe it's time now to re-check the situation now :)

It looks like you got involved while the z80 port was being rewritten.  Things are stable now :)

Quote
I also had an "official" bugreport (about _one_ bug only) to the sdcc team:
https://sourceforge.net/p/sdcc/bugs/2089/
About 3 years, and the bug report is still have status of "open" ... :(

To be fair, they do have eight pages of bug reports -- enough that they probably pick the easiest and/or most interesting (to them) to fix first.

That bug report I know about (I'm a dev at z88dk) and it also affects another major project (fuzix).  Fuzix has resolved it like you did -- they post process the source and remove the redundant space.  The solution is not as straightforward to fix with postprocessing as it might seem at first and I'm not sure if fuzix's solution considers the following.

If you change your code example a little bit:

Code: [Select]
char *test = "Hello world, this is not const!";
char welcome[] = "Hello world, this is not const!";

The generated output (with z88dk tools but the output comes from sdcc):

Code: [Select]
SECTION code_compiler

___str_0:
DEFM "Hello world, this is not const!"
DEFB 0x00

SECTION data_compiler

_test:
DEFW ___str_0
_welcome:
DEFM "Hello world, this is not const!"
DEFB 0x00

The third extra bit of space is eliminated by z88dk but there is still the string constant in section code_compiler which is not required.  However it's not safe to blindly remove it :- you can see that that the same string "Hello world, this is not const!" is reused for assignment to variable test.  Without test there, ___str_0 is redundant and can be removed.

Anyway I do agree with you that this bug is annoying and probably deserves a bump to gain some present day attention.

What I was mainly wondering is if anyone had taken the EP further with C compilation.  It looks like it stalled with your efforts a few years ago :(  The EP is an especially interesting target and we're all interested in it but it's also one of the more difficult ones that would require some input from experienced EP users to do well.
« Last Edit: 2015.August.18. 18:24:19 by Alcoholics Anonymous »

Offline lgb

  • EP addict
  • *
  • Posts: 3497
  • Country: hu
  • æðsta yfirmaður
  • OS:
  • Linux (Ubuntu) Linux (Ubuntu)
  • Browser:
  • Firefox 40.0 Firefox 40.0
    • View Profile
    • http://lgb.hu/
Re: Enterprise C compiler for PC
« Reply #22 on: 2015.August.18. 19:45:21 »
It looks like you got involved while the z80 port was being rewritten.  Things are stable now :)

Sounds cool. About your previous message in general: my try with sdcc was more or less a "one night coding experiment". Please do not treat that I am so great in sdcc internals or such, all of my work was just experimenting, and checking out what sdcc generates and try to "squeeze it" into some usage program on the Ep128 :) That's about all.

Since it was years ago, you must be right: things can change during the time passed meanwhile.

Honestly I can't remember what was the details about my problems with sdcc, but surely one of was the "stored twice" stuff (the bug report). Another issue was (but again: I can't remember too much) that sdcc generated CODE to initialize data ... of course it's totally useless and unacceptable, I guess it was because of some MCU support (sdcc was - originally? - written for, where there is strict separation between code and data usually, the so called Harvard-architecture).


Quote
To be fair, they do have eight pages of bug reports -- enough that they probably pick the easiest and/or most interesting (to them) to fix first.

Well, do not misunderstand me. I don't want to "blame" sdcc project, just it was "too much" for the knowledge/time I have for a "proof of the concept" EP/sdcc project only with some "Hello world!" style result :)

Quote
What I was mainly wondering is if anyone had taken the EP further with C compilation.  It looks like it stalled with your efforts a few years ago :(  The EP is an especially interesting target and we're all interested in it but it's also one of the more difficult ones that would require some input from experienced EP users to do well.

Well I am not sure how experienced EP user I am, but since I wrote (well, "am writing") two EP emulators, maybe I have enough knowledge on the EP side, but not on the sdcc :(  I would be interested, but I have not so much time ...

Offline Alcoholics Anonymous

  • Newbie
  • Posts: 10
  • Country: ca
  • OS:
  • Windows NT 6.2 Windows NT 6.2
  • Browser:
  • Firefox 40.0 Firefox 40.0
    • View Profile
    • Z88DK Homepage
Re: Enterprise C compiler for PC
« Reply #23 on: 2015.August.19. 02:17:14 »
Honestly I can't remember what was the details about my problems with sdcc, but surely one of was the "stored twice" stuff (the bug report). Another issue was (but again: I can't remember too much) that sdcc generated CODE to initialize data ...

Yes that problem is gone now too.

Quote
Well I am not sure how experienced EP user I am, but since I wrote (well, "am writing") two EP emulators, maybe I have enough knowledge on the EP side, but not on the sdcc :(  I would be interested, but I have not so much time ...

Well I can do the compiler side; it's the EP side that I would need the help with :)  This would be under z88dk but sdcc can be used with z88dk too.   When used with z88dk, sdcc gains access to the much larger set of libraries in z88dk which are all written in assembly language.

I will see what I can learn tonight but mainly I'm looking at:

1. What sort of executables should be produced..   Cartridge?  Com?  Binary loaded into ram?

2. Is EP64 and EP128 different enough that they should be two different targets?

3. What does the memory map look like.  Is there any 'slow' ram to be aware of?

4. Who owns the interrupts and does the program field them?

5. The display file is a difficult one.. it's programmable so I'd need to know what sort of resolutions should be supported and then pick one to start with.  Ideally it's a bitmapped screen.

6. For stdin/stdout/stderr, z88dk can supply its own terminals.  These terminals support non-overlapping windows and proportional fonts so we usually want to implement terminals using z88dk's drivers for every target and then supply another set of terminals as supported by the target (eg EXOS).  These will occupy less space in the binary but the native terminals can't always do the type of terminal expected by C, particularly the line-oriented editing.  I'd need to figure out if EXOS can be used for these lightweight terminals.

7. The initial main block of asm code we look for from the target is a set of display file primitives that can compute screen addresses from pixel and character coordinates, scroll a rectangle upward, clear a rectangle so that the terminal drivers can be easily implemented.  If these are missing we have to write them.  As an example, here is a set for the spectrum: http://z88dk.cvs.sourceforge.net/viewvc/z88dk/z88dk/libsrc/_DEVELOPMENT/arch/zx/display/z80/  Again we've tended to implement them separately from the existing OS code (EXOS in EP's case) because they tend to be quicker and it gives the tools the ability to generate code that doesn't rely on the firmware.  Sometimes cartridge targets cannot access system firmware.

Offline lgb

  • EP addict
  • *
  • Posts: 3497
  • Country: hu
  • æðsta yfirmaður
  • OS:
  • Linux (Ubuntu) Linux (Ubuntu)
  • Browser:
  • Firefox 40.0 Firefox 40.0
    • View Profile
    • http://lgb.hu/
Re: Enterprise C compiler for PC
« Reply #24 on: 2015.August.19. 08:46:37 »
Well, sorry in advance, I type this in hurry, hopefully it's understandable even with my English :)

Quote
1. What sort of executables should be produced..   Cartridge?  Com?  Binary loaded into ram?

It depends what you want to use :) But in general, I think the most useful on EP (for a program compiled from C source) is maybe the loadable program (into RAM). I am not sure if it's important that someone want to write a C program can be complied into ROMable code ... What people usually does, is the type-5 EXOS header applications (EXOS have the notion of file headers which is basically makes possible that EXOS will "know" what to do with a file ... it's a "machine code user app", an IS-BASIC program, or a system extension or even some gfx information with some special EXOS extensions, and so on). So you don't need "BASIC loader" what many 8 bit micros, for machine code programs.

http://ep.homeserver.hu/Dokumentacio/Konyvek/EXOS_2.1_technikal_information/exos/kernel/Ch10.html

(see: 10.4 New Applications Programs)

Quote
2. Is EP64 and EP128 different enough that they should be two different targets?

Not so much, the main difference is the amount of RAM. In general, EP is quite flexible on memory configurations, it has 4Mbyte (22 bit) address space and address bus width on the motherboard, and it's not uncommon nowdays to have EPs with 512K or even more RAM installed. On the software side, I think original EP64 had older EXOS version.

Quote
3. What does the memory map look like.  Is there any 'slow' ram to be aware of?

Z80 as the CPU has four 16K long pages of the 64K address space. The system bus instead is 4Mbyte wide, also divided into 16K long segments (256 segments). Any of the segments can be "mapped" to any of the pages. A segment can contain ROM, RAM or undecoded. The last four segments is the VRAM (Video RAM) used by the video chip ("Nick") of the Enteprise. On EP64 this is the only RAM in the system without expansion. On EP128 there are another 64K RAM in the system as a form of a PCB "stacked over" on the mother board. VRAM access by the CPU is slower as it must share the time with the Nick chip (actually VRAM access by the CPU is done through the Nick chip which used the "CPU clock deformation" trick). Please note, that Nick *always* accesses the 64K VRAM directly, the segment/page mapping stuff is only for the CPU (but from the view point of the CPU VRAM are the segments 0xFC-0xFF). Also please note, that RAM segments are not needed to be continuous and often it's not (EP's own - EXOS - is flexible enough to handle situations like this). EXOS has the function 24 - allocate segment which can be used by programs to allocate RAM segment, it always gives the lowest numbered segment. Thus it only gives video segment ("slower") if "other" RAM segments are all used. Segment 0xFF (which is the top segment in VRAM too) is used by EXOS as the "system segment".

http://ep.homeserver.hu/Dokumentacio/Konyvek/EXOS_2.1_technikal_information/exos/kernel/Ch11.html

Quote
4. Who owns the interrupts and does the program field them?

Usually (see memory mapping) page 0 (so 0-3fff Z80 addresses) should always contain the "zero page". A segment for this (if I am correct the lower numbered segment with RAM on the system detected by EXOS memory test on boot etc) is selected by EXOS. This contains the interrupt vector for "hardware" interrupt (in IM1 mode of Z80), and also eg the vector for RST 0x30 used by EXOS calls for example. The memory mapping applied by the user is preserved, and restored after execution of the interrupt handler but of course it is modified meanwhile eg to page EXOS ROM code in, etc, meanwhile. In EP, there can be more sources of interrupts: Nick, the video chip can generate interrupt baed on the LPT definition, the Dave chip (which does eg sound, interrupt "controller" purposes and for example the memory "mapping" itself) can generate 1Hz interrupt or even a programmable one, etc. Of course, if you disable interrupts, or having own interrupt service routine then you can map another segment into page 0 as well.

Quote
5. The display file is a difficult one.. it's programmable so I'd need to know what sort of resolutions should be supported and then pick one to start with.  Ideally it's a bitmapped screen.

Complex topic. Nick is quite flexible, no "global video mode" as with most video chips, but only the starting address of the LPT (Line Parameter Table) is set, and even for every scan lines you can have entries (LPB - Line Parameter Block) in LPT with the video mode, colour mode, margin parameters, and so on. The time of a scanline is divided into 57 "slots". The main rule of Nick, that it can read two bytes within a slot from VRAM. The first 8 slots are used to fetch the current LPB (2*8=16 bytes) the last three is used for horizontal retrace and memory referesh. So in theory, there is 46 slots left, but it can be outside of the visible area of video displays to show all, so sometimes fewer (like 42) is really used. Anyway, let's the example with 42 now. As within a slot Nick can read 2 bytes, for 1 bpp mode it means 2*8=16 pixels, which is 16*42=672 pixel horizontal resolution. You can see that in 2 bpp (= 4 colour mode) it's the half of that, and so on. This is "pixel mode", but there is eg text mode (I mean the hardware text, the "80 coloumn text mode" is a pixel mode for real not hardware text) uses one byte for character code and one byte for chargen access, and attribute mode for screen/attrib access (I don't know too much on ZX Spectrum, but I think this attribute mode is the most similar to ZX screen, just the definition of the attribute bytes are a bit different and there is no hardware flashing stuff). Colour modes: 1bpp=2col, 2bpp=4col, 4bpp=16col, 8bpp=256col. An LPB contains 8 colours for palette information used in 2/4/16 colour modes (in 16, only the first 8 colours, and the "FIXBIAS" register is needed). In 256 colour mode the palette is not used at all and controls the output directly. The vertical resolution is limited more by the requirements of the PAL video standard, and you must provide the correct vblank/vsync as well (in the LPT). This sounds too complex but it allows tricks to use eg even interlace modes, and other tricks. Even the location of the given video memory address is stored on per LPB basis! It allows nice tricks eg show the same scanline more on the screen or even "faked" reflection like tricks / whatever, or animation by hardware without any CPU usage, and so on.

http://ep.lgb.hu/doc/Nick.html

Quote
6. For stdin/stdout/stderr, z88dk can supply its own terminals.  These terminals support non-overlapping windows and proportional fonts so we usually want to implement terminals using z88dk's drivers for every target and then supply another set of terminals as supported by the target (eg EXOS).  These will occupy less space in the binary but the native terminals can't always do the type of terminal expected by C, particularly the line-oriented editing.  I'd need to figure out if EXOS can be used for these lightweight terminals.

I am not sure about this one, especially about the control characters. EXOS (as always ...) has a quite complex and advanced solution for this topic as well: if you want to display anything you must open a channel (similar notion as open a file in other OSes, just the special name "DISPLAY:" needed, with some preparation call). In theory you can even have more video channels open at the same time "allocated" from different space of the visible area but not side-by-side, so a given scanline describes one mode for the Nick.

http://ep.homeserver.hu/Dokumentacio/Konyvek/EXOS_2.1_technikal_information/exos/video/

For stdin if it's the keyboard, you must also open a channel for the keyboard device. And for sound, the sound device. :) Anyway, all of these channels have the common attribute that then normal read/write calls are used as with "regular files". For speaking of C, it's similar that stdin has fd=0 and stdout fd=1, stderr=2, and you can have other files open, and depending the file descriptor value the underlaying OS will do different things of course. Just one difference with EXOS channels, that in EXOS you must give a number to be used later on open, while with C file open function you will get some number at open (excluding the "well known fd numbers" like the mentioned stdin/stdout/stderr).

http://ep.homeserver.hu/Dokumentacio/Konyvek/EXOS_2.1_technikal_information/exos/keyboard/

Quote
7. The initial main block of asm code we look for from the target is a set of display file primitives that can compute screen addresses from pixel and character coordinates, scroll a rectangle upward, clear a rectangle so that the terminal drivers can be easily implemented.  If these are missing we have to write them.  As an example, here is a set for the spectrum: http://z88dk.cvs.sourceforge.net/viewvc/z88dk/z88dk/libsrc/_DEVELOPMENT/arch/zx/display/z80/  Again we've tended to implement them separately from the existing OS code (EXOS in EP's case) because they tend to be quicker and it gives the tools the ability to generate code that doesn't rely on the firmware.  Sometimes cartridge targets cannot access system firmware.

One problem (in my opionion - I mean) that if you use EXOS to set video mode / open video channel etc EXOS stuffs. Though you don't need to mess with LPT/LPB and things like this, the allocated structure for the video information in VRAM (done by EXOS for you) LPT etc, but you can't know exactly where the video information is put (eg start of the video information) also it may not be linear. For example EXOS on scrolling the screen can modify LPT (the start address of video information in LPBs) instead of "scrolling information on memory" which is good for the performance, but problematic if you want to use the memory directly. Through EXOS you can dispaly stuffs of course, but as you can expect, it's much slower than doing it "directly".

If you see my crt0 implementation is barely the type-5 EXOS file header, opening video and keyboard channel, and simple routines to get a char from keyboard or output one to the screen using EXOS functions.

Offline Alcoholics Anonymous

  • Newbie
  • Posts: 10
  • Country: ca
  • OS:
  • Windows NT 6.2 Windows NT 6.2
  • Browser:
  • Firefox 40.0 Firefox 40.0
    • View Profile
    • Z88DK Homepage
Re: Enterprise C compiler for PC
« Reply #25 on: 2015.August.19. 19:53:20 »
Well, sorry in advance, I type this in hurry, hopefully it's understandable even with my English :)

Ha, your English is better than most Englishmen's.  Example:

Quote
it's a "machine code user app"

You know the difference between "it's" and "its".  This is a 'tell' for people educated in the UK - a very large number have difficulty with correct usage of apostrophes.  I've spent some time on UK-dominated forums and, sadly, it's beginning to rub off on me too when I write quickly.  Maybe some Hungarian English will set things right :)

Quote
Quote
1. What sort of executables should be produced..   Cartridge?  Com?  Binary loaded into ram?
It depends what you want to use :) But in general, I think the most useful on EP (for a program compiled from C source) is maybe the loadable program (into RAM). I am not sure if it's important that someone want to write a C program can be complied into ROMable code ...

I'd like to support all types even if people only use the RAM executable.  It's not difficult to do since the tools are already there to produce ROMs.

Quote
What people usually does, is the type-5 EXOS header applications (EXOS have the notion of file headers which is basically makes possible that EXOS will "know" what to do with a file ... it's a "machine code user app", an IS-BASIC program, or a system extension or even some gfx information with some special EXOS extensions, and so on). So you don't need "BASIC loader" what many 8 bit micros, for machine code programs.
http://ep.homeserver.hu/Dokumentacio/Konyvek/EXOS_2.1_technikal_information/exos/kernel/Ch10.html
(see: 10.4 New Applications Programs)

Thanks for the link - I'm still working through all the documentation on that site.

EP devices are not interrupt driven then, other than what dave & nick are doing?  For example, disk / network / serial devices are not depending on an interrupt to do i/o or turn off motors or anything like that?  And the interrupters (including new peripherals) are not im2 devices?

Quote
In general, EP is quite flexible on memory configurations, it has 4Mbyte (22 bit) address space and address bus width on the motherboard, and it's not uncommon nowdays to have EPs with 512K or even more RAM installed. On the software side, I think original EP64 had older EXOS version.

What I'm thinking about doing initially is a 64k target with 48kish ram at the bottom and the top 16kish containing the display data and being pageable for extra ram.  This fits with the simple model many other machines are currently using for games where a 16k window is used to copy level data (eg) into the main ram as needed.  The EP is more flexible than that but this would provide a simple starting point familiar to everyone where we don't have to worry about code being generated into individual 16k pages.

The -ish part depends on how much ram EXOS is using on the top segment on EP64 machines.

Quote
EXOS has the function 24 - allocate segment which can be used by programs to allocate RAM segment, it always gives the lowest numbered segment. Thus it only gives video segment ("slower") if "other" RAM segments are all used. Segment 0xFF (which is the top segment in VRAM too) is used by EXOS as the "system segment".

Ok so you always get fast ram if it's available when you load in.  Executables output by the compiler consist of CODE/DATA/BSS sections in order and on other targets, BSS is sometimes left off to improve loading times.  The EXOS header for New Application Programs (bytes 2&3) contain a length which I assume corresponds to how many pages will be allocated for the program by the loader.  Does that length have to correspond to the length of the file on disk or tape?  What I want to do is chop off BSS so that only CODE+DATA sections are loaded but the length parameter in the header must be CODE+DATA+BSS size to reserve the necessary number of pages.

Quote
(display)
Complex topic. Nick is quite flexible, no "global video mode" as with most video chips, but only the starting address of the LPT (Line Parameter Table) is set, and even for every scan lines you can have entries (LPB - Line Parameter Block) in LPT with the video mode, colour mode, margin parameters, and so on.

Yes it is.. that flexibility also makes it difficult to settle on a good way to do things.  I think what I will do is take over the machine and access hw directly except for file / printer / serial i/o.  I'm guessing that EXOS can't be used to implement the sort of terminal io expected from C but we can put that decision off until much later.

For display, I think there should be a way to declare surfaces of variable size for different modes.  The data for the surface would be directly written by the terminal / graphics / sprite engines and then the LPT is under program control so that you can pick out where and how much of these surface are displayed.  I think we can define LPTs declaratively in the crt so you could split a screen into hi-res top, text bottom, eg without too much trouble and we can do the same for display surfaces.  This would be an extension of how we statically instantiate drivers on stdin/stdout/stderr in crts now and would get some good defaults for users and at the same time leave it open to more advanced users to make their own crts with their own custom resolutions.

Offline lgb

  • EP addict
  • *
  • Posts: 3497
  • Country: hu
  • æðsta yfirmaður
  • OS:
  • Linux (Ubuntu) Linux (Ubuntu)
  • Browser:
  • Firefox 40.0 Firefox 40.0
    • View Profile
    • http://lgb.hu/
Re: Enterprise C compiler for PC
« Reply #26 on: 2015.August.21. 20:51:12 »
Ha, your English is better than most Englishmen's.  Example:

You know the difference between "it's" and "its".  This is a 'tell' for people educated in the UK - a very large number have difficulty with correct usage of apostrophes.  I've spent some time on UK-dominated forums and, sadly, it's beginning to rub off on me too when I write quickly.  Maybe some Hungarian English will set things right :)

Maybe it's because we ("we" as non-native speakers) learn English with the "logic" of the grammar rules, where native speakers don't even think too much about the "logic" so it can result in confusing similarly spelled (but quite different) constructs like "its" and "it's" because they would say "well I know WHAT meaning of the confused it's/its is used there so who cares". But learners/non-native speakers would have problems not to see the exact (and right) word thus it looks like confusing for them then.

Quote
I'd like to support all types even if people only use the RAM executable.  It's not difficult to do since the tools are already there to produce ROMs.

I see. EP ROM's are usually in the form of EXOS_ROM stuffs, that the ROM image starts with the identifier of string "EXOS_ROM". EXOS itself (by its "boot process") will find these (because of the identifier strings). These ROMs then are "attached into the system", eg an EXOS command will ask these ROMs too if they "owns" the command and want to react, or it's not the command it is aware of. The same applies for device drivers, you can even create a DISPLAY: device which then "overrides" the internal DISPLAY: of EXOS (the display device driver, I mean). Also, EXOS makes it possible to "decode" HELP requests in the system or custom error strings. EXDOS itself is also an EXOS_ROM in this manner to be "connected into" the EXOS "system flow" this way.
However this requires quite "tight" bonding eg passing values/return codes in registers, preserving some other registers. Maybe that is a bit hard doing in C code. Of course the situation is more simple if you want a more complex program in ROM. In this case you can have an EXOS command to "start" your program, then you will have some minimal code to "respond" the EXOS requests, but then you do whatever you want. Hmm, I am not sure if I can explain myself well enough in an understandable way though ...

What I also wanted to say: the situation is a bit more complex than on other 8 bit systems where you usually put a ROM image in the system without too much interaction with the rest of the software components on the system. But it's more like a "my feeling" like difference ...

Quote
Thanks for the link - I'm still working through all the documentation on that site.

You're welcome.

Quote
EP devices are not interrupt driven then, other than what dave & nick are doing?  For example, disk / network / serial devices are not depending on an interrupt to do i/o or turn off motors or anything like that?  And the interrupters (including new peripherals) are not im2 devices?

Not IM2, but IM1, if I remember correctly :) Interrupts from various sources are routed through the Dave chip acting as "interrupt controller" (generating the single interrupt for the Z80 then, well, if it's enabled in Dave). So though there is only one "hardware interrupt" entry for Z80, the interrupt handler code of EXOS can look bits in Dave up to get to know what is the source of the given interrupt. You can even disable one or more interrupt sources in Dave. Also Dave contains latches for the interrupt sources you must clear to stop generating interrupt for the Z80. So, if there is an interrupt and other sources would generate one for another source meanwhile, it won't lost this way, at least I can see the situation.

Interrupt sources can be Nick (each LPB in LPT can specify VINT to generate an interrupt but since it's edge triggered, you can't have interrupt for two (or more) neighbour LPBs as it won't provide an edge between them. So it's some kind of "raster interrupt" programmable for even more raster lines (with the constraint I mentioned above). EXOS creates its LPTs to generate one VINT per frame to provide the 50Hz (PAL video timing) interrupt needed eg for keyboard scanning to fill the kbd buffer which can be queried by software then. This is one of the two external interrupt pins of Dave (connected with the VINT pin of Nick). The other is not used, or hmm maybe it's the serial stuff, I am not sure about this, since I've never wanted to use serial connection with the EP). The two other interrupt sources are generated internally by the Dave itself (well, if they're enabled of course). One of that is the 1Hz interrupt which can be useful for real-time clock stuff (for example Zozosoft's RTC card uses that to display time on the top of the screen with its ROM, ZT - ZozoTools). The other internal interrupt is the "sound interrupt". I guess it's named that way since it uses a programmable frequency oscillator of the Dave which would be used to generate a sound normally or can be switched to a constant frequency (1KHz or 50Hz).

http://ep.lgb.hu/doc/Dave.html

I don't know if other components in EP uses interrupts anyway ... The FDC motor auto-off is maybe used by EXDOS (I'm sorry, I can't remember ...) but I don't think there are too much other uses. Of course the VINT generated std 50Hz EXOS interrupt as I've written, is used keyboard scanning and maybe the FDC motor stuffs and also some internal EXOS stuffs (increment its internal software clock, etc). What I meant that FDC controller for example don't use hardware interrupts, EXDOS uses (as far as I can guess, maybe I am not the most clever person in this area on the forum, I have to say ...) polling to wait for a completed operation for example (possible with some upper limit for timing the operation out).

Quote
What I'm thinking about doing initially is a 64k target with 48kish ram at the bottom and the top 16kish containing the display data and being pageable for extra ram.  This fits with the simple model many other machines are currently using for games where a 16k window is used to copy level data (eg) into the main ram as needed.  The EP is more flexible than that but this would provide a simple starting point familiar to everyone where we don't have to worry about code being generated into individual 16k pages.

The -ish part depends on how much ram EXOS is using on the top segment on EP64 machines.

This sounds good for me. There is a more complex scenario but I don't think sdcc can support it: ie the "far pointer" scenario where a segment number and offset is also stored within a pointer (in contrast of "near pointer" which is simply a 16 bit value directly accessible for the Z80 without extra ops) and an access would cause to alter the segment mapping. But it's complex, slow, and requires extra code in the core compiler code, I think. If I am right ...

Quote
Ok so you always get fast ram if it's available when you load in.  Executables output by the compiler consist of CODE/DATA/BSS sections in order and on other targets, BSS is sometimes left off to improve loading times.  The EXOS header for New Application Programs (bytes 2&3) contain a length which I assume corresponds to how many pages will be allocated for the program by the loader.  Does that length have to correspond to the length of the file on disk or tape?  What I want to do is chop off BSS so that only CODE+DATA sections are loaded but the length parameter in the header must be CODE+DATA+BSS size to reserve the necessary number of pages.

As far as I can remember, EXOS files with type-5 header can be max of 48K (well, minus 256 bytes, since they are loaded to $100 - the 16 bytes long header is not loaded though), and the memory used by the loaded program is allocated, and segments are mapped to be able to access them by the CPU directly. However, there is some problem if you have large BSS area. What I mean here, that your program (let's say) would fit in 16K after loaded, but with the BSS part it's over of 16K. Then you have some extra work to allocate and then map a segment as page 1 ($4000-$7FFF) so you can use it for the "tail of the BSS area". Some people are lazy :) and have the habit to simply enlarge the binary enough to also contains the BSS thus no problem, and no "manual" memory allocation + mapping work is needed. However in my opinion it's not so nice to enlarge the binaries just to save this work which can be done in some bytes of asm code (even with some code to zero the BSS area to have a well defined state, if it's needed at all, since in C, I think nobody says that it's a good idea to access uninitialized variables before some value assignment ...).

To be honest, I can't recall now what the size info in the header means exactly, but if you see the example crt0 code, you will see hopefully :) I so often confuse this that I usually have a look of an older work of mine and do that way :) I must admit, this is a very lame answer from me, I'm sorry :oops:

Quote
Yes it is.. that flexibility also makes it difficult to settle on a good way to do things.  I think what I will do is take over the machine and access hw directly except for file / printer / serial i/o.  I'm guessing that EXOS can't be used to implement the sort of terminal io expected from C but we can put that decision off until much later.

Well, that's a hard question. As I will mention later :) in this post, some may want to use "EXOS centric" simple stream like console I/O which can be integrated into std EXOS I/O for some reason. Without even using any (console) control codes other than maybe newline or such. It's more like a C program can also use only putchar() (or some "frontend" on top of it like printf()), but others may expect a conio-level interface for some _other_ purpose. Both of them can be important and useful in some cases, hard to replace with the other!

Quote
For display, I think there should be a way to declare surfaces of variable size for different modes.  The data for the surface would be directly written by the terminal / graphics / sprite engines and then the LPT is under program control so that you can pick out where and how much of these surface are displayed.  I think we can define LPTs declaratively in the crt so you could split a screen into hi-res top, text bottom, eg without too much trouble and we can do the same for display surfaces.  This would be an extension of how we statically instantiate drivers on stdin/stdout/stderr in crts now and would get some good defaults for users and at the same time leave it open to more advanced users to make their own crts with their own custom resolutions.

I like the idea to create an API which can provide most of the features what EP can do. Split screen with different resolution (thanks to Nick and its LPT feature) is one of that. But not only hardware is what someone should relay on, but also the software. Eg EXOS has the channel notion to open files. For screen/display stuff I would vote for direct hardware access because of the speed. However for file I/O it's better to use it trough the EXOS (and EXDOS) of course, especially because of the great spectrum of possible "modern" storage solutions (just two examples: SD card cartridge, and the IDE HDD interface) which are totally incompatible at hardware level, but there is a common ground (implemented in software), in the form of EXDOS. For example Bruce (one of the creator of Enterprise) has the nice EPNET project to build ethernet connectivity for the EP with the help of "hardware tcp/ip chip" from Wiznet (W5300). If I know well enough the details, it's also considered to provide EXOS compatibility later, that is, you can open a channel (like a file channel ...) to open - for example - a TCP connection to a remote server on the Internet. Just supporting this channel notion through the planned C API/SDK would make it possible to support even future projects more or less.

Thanks to the well designed (especially to its age!) software of the EP, most software would use software access anyway for many things, especially file I/O unlike on computers like Commodore 64 (don't get me wrong: I am a great fan of C64 too), where a new storage solution is kinda problematic because of the not so well defined software layer (first: you need a modified KERNAL ROM, but even then many software use non-standard entry points, IEC-serial direct routines or even hardware access, and so on. Just read the description of IDE-DOS for C64 with the guide how to port/write "good" softwares works with IDE-DOS then too). Nice thing about EXOS/EXDOS that you don't need too much to "modify" ROM etc, because you can add "extensions" expanding the base set of OS routines, if I can say this way. For example SD card cartridge only needs a quite short "block level routines" used by the base EXDOS then to "hook it up" into the system then quite naturally.

But it raises a question (better say: a bunch of questions): let's see open file first. One can support EXOS specific/centric functions like exos_open() with the semantics of the EXOS to be able to exploit all the EXOS features. At the other hand, for C portability some can support fopen() or open() too. For simple I/O some can support simple putchar() and higher level stuffs like printf() which does not even assume too much control characters or such (some programs needs only this!), but others would prefer conio like functions, or even (well, let's say an example BGI/TGI like stuff) gfx functions. I think, the best would be providing all of the possibilities and usage cases ... But that requires great amount of work, of course. Also, static linking the full feature set would result in too large binaries.

Sorry, I do not know enough about the features of sdcc and its standard library/libraries, maybe my ideas are simply odd or overkill.
« Last Edit: 2015.August.21. 21:48:08 by lgb »

Offline Alcoholics Anonymous

  • Newbie
  • Posts: 10
  • Country: ca
  • OS:
  • Windows NT 6.2 Windows NT 6.2
  • Browser:
  • Firefox 40.0 Firefox 40.0
    • View Profile
    • Z88DK Homepage
Re: Enterprise C compiler for PC
« Reply #27 on: 2015.August.22. 01:37:34 »
This sounds good for me. There is a more complex scenario but I don't think sdcc can support it: ie the "far pointer" scenario where a segment number and offset is also stored within a pointer (in contrast of "near pointer" which is simply a 16 bit value directly accessible for the Z80 without extra ops) and an access would cause to alter the segment mapping. But it's complex, slow, and requires extra code in the core compiler code, I think. If I am right ...

sdcc is beginning to support C Embedded, which is a C language extension for embedded systems.  C Embedded specifies how to deal with bankswitched memory and sdcc is starting to do that but I haven't looked in detail at it yet.  sccz80 does have 3-byte far pointers but again it's preliminary.  This is on my to-do list so once I've studied it I will include it in the crts.  I don't think it needs more than providing a subroutine in page-0 (the 'HOME' bank) to perform bankswitching and maybe provide some trampoline code.

So for now, it's left to the user program to handle bankswitched memory intelligently.  What we can do with the crt, for the ep, is make sure all the video-related stuff, some key functions like memcpy, and interrupt related handlers are in page-0 so that user code can be free to place two 16k pages in page-2/3 to copy or operate on data in different banks.  The ep will be the first target that needs a special memory map for this sort of thing :)

Quote
As far as I can remember, EXOS files with type-5 header can be max of 48K (well, minus 256 bytes, since they are loaded to $100 - the 16 bytes long header is not loaded though), and the memory used by the loaded program is allocated, and segments are mapped to be able to access them by the CPU directly. However, there is some problem if you have large BSS area. What I mean here, that your program (let's say) would fit in 16K after loaded, but with the BSS part it's over of 16K. Then you have some extra work to allocate and then map a segment as page 1 ($4000-$7FFF) so you can use it for the "tail of the BSS area". Some people are lazy :)

Heh yeah :)  That's what I want to do:  tell EXOS that the program is CODE+DATA+BSS bytes in size and have it allocate the pages but only load CODE+DATA bytes.  But because of the 48k limit it might be better just to do the BSS allocation at runtime so that it is possible to go beyond 48k.

Quote
since in C, I think nobody says that it's a good idea to access uninitialized variables before some value assignment ...).

The BSS segment has to be zero according to the C standard but the crt takes care of all initialization details so the loader doesn't have to worry about it.

Quote
Well, that's a hard question. As I will mention later :) in this post, some may want to use "EXOS centric" simple stream like console I/O which can be integrated into std EXOS I/O for some reason. Without even using any (console) control codes other than maybe newline or such. It's more like a C program can also use only putchar() (or some "frontend" on top of it like printf()), but others may expect a conio-level interface for some _other_ purpose. Both of them can be important and useful in some cases, hard to replace with the other!

I like the idea to create an API which can provide most of the features what EP can do. Split screen with different resolution (thanks to Nick and its LPT feature) is one of that. But not only hardware is what someone should relay on, but also the software. Eg EXOS has the channel notion to open files. For screen/display stuff I would vote for direct hardware access because of the speed. However for file I/O it's better to use it trough the EXOS (and EXDOS) of course, especially because of the great spectrum of possible "modern" storage solutions (just two examples: SD card cartridge, and the IDE HDD interface) which are totally incompatible at hardware level, but there is a common ground (implemented in software), in the form of EXDOS. For example Bruce (one of the creator of Enterprise) has the nice EPNET project to build ethernet connectivity for the EP with the help of "hardware tcp/ip chip" from Wiznet (W5300). If I know well enough the details, it's also considered to provide EXOS compatibility later, that is, you can open a channel (like a file channel ...) to open - for example - a TCP connection to a remote server on the Internet. Just supporting this channel notion through the planned C API/SDK would make it possible to support even future projects more or less.

I agree with all the above.  I've read quite a bit more and I've started to write some of the library code (I'll mention what's missing below).

I've given the ep's different video modes my own names (I don't know if something better already exists) and I'm measuring characters as 8x8 pixels:

* p2 (pixel 2 colour mode) 80x25 characters full screen
* p4 (pixel 4 colour mode) 40x25 characters full screen
* p16 (pixel 16 colour mode) 20x25 characters full screen
* a8 (attr 8 scan lines tall) 40x25 characters full screen, 40x25 attributes
* c128 (hardware characters)

a8 corresponds to the zx spectrum, a1 corresponds to the ts2068 (1 attribute byte per 8 pixels) and of course there are other aN and cN.

The crt will be able to statically declare up to one display surface per mode.  The size of each display surface would be specified in characters and could be anything from very small to very large.  Memory for these surfaces would be allocated at startup from video memory and how they are displayed would be up to the LPT.  The LPT may only display a portion or all of each surface.  The video memory address and dimensions of each display surface would be stored in global variables accessible by the C library.

The C library will operate on the video memory corresponding to each display surface directly.  The library will have to supply video primitives for each display surface type.

I'm going to write the p4 primitives first and possibly the p2, c128 and a8 modes later.  Ultimately all of them should be there but I think it will be up to the EP community if they are interested in it.  I'm picking on the a8 mode specifically because this is compatible with the zx spectrum and the zx spectrum has a sprite library that has been used by many games which could easily use this mode on the EP.  That sprite library is intended to support many video modes so it could be modified for other of the EP's modes but that is also a lot of work.

Does this sound like a good method to deal with the EP's flexibility?

For file i/o, the clib in z88dk has not finalized it yet -- all the code is present for file systems but the drivers have not been written to do file i/o yet.  The design is object oriented and operates like a stack where you would inject the target's native system at the level it can support.  If the target does not supply any disk device the idea is we will supply the entire stack including a fat driver.  But that's a long time for now.

For the first pass, I'll ignore file i/o (and don't forget you can always call EXOS directly from within C) and then second pass maybe look at connecting stdio to any sort of streaming that EXOS can support.  At the lowest level, stdio generates about a dozen messages for i/o and if those messages can be satisfied by EXOS, it can be plugged in.  I think things like the printer, serial i/o, built-in EXOS video drivers can probably plug into stdio but EXDOS (disk i/o) doesn't seem to be a candidate.  It looks like it performs one whole read.write operation and then closes the channel.  So in order to use it like a streaming device, the z88dk driver would have to cache disk blocks in ram for stdio to access.

Quote
... But that requires great amount of work, of course. Also, static linking the full feature set would result in too large binaries.

Sorry, I do not know enough about the features of sdcc and its standard library/libraries, maybe my ideas are simply odd or overkill.

z80asm is a linking assembler so it will only pull in code if the program uses it.  You can add all sorts of things to the library without worrying about it being attached to the binary all the time.

sdcc's libraries are minimal but z88dk's are fairly substantial.  The two shouldn't be operated separately :)

The EP-specific code that needs to be written includes:

* direct access to keyboard and joystick hw.   There is also an api for mice but this is the minimum.  I found details on port $b5 for reading the keyboard directly but I got a little confused with the built in joystick.

Key matrix:

Code: [Select]
;EP keyboard matrix:
 ;        b7    b6    b5    b4    b3    b2    b1    b0
 ;Row    80H   40H   20H   10H   08H   04H   02H   01H
 ; 0   L.SH.     Z     X     V     C     B     \     N
 ; 1    CTRL     A     S     F     D     G  LOCK     H
 ; 2     TAB     W     E     T     R     Y     Q     U
 ; 3     ESC     2     3     5     4     6     1     7
 ; 4      F1    F2    F7    F5    F6    F3    F8    F4
 ; 5         ERASE     ^     0     -     9           8
 ; 6             ]     :     L     ;     K           J
 ; 7     ALT ENTER   LEFT  HOLD   UP   RIGHT DOWN  STOP
 ; 8     INS SPACE R.SH.     .     /     ,   DEL     M
 ; 9                   [     P     @     0           I

I thought left, right, up, down (and space for fire) were the built in joystick.

But then I saw mention of port $b6 in connections with the joystick... how do I read the joystick directly?  There's also mention of external joysticks in the EP tech docs -- is there a standard way to directly read that hw?

* display primitives that can compute pixel addresses for different display modes given the surface declared by the crt.  The C library will use these to print and draw.

* fzx draw character primitive for each video mode.  This is the putchar for proportional fonts.

* sound.  The sound library is 1-bit oriented but it contains some really good music synthesis routines.  It should be compatible with Dave.

* drivers for fixed width and proportional font terminals.  This is mostly implemented through code inheritance.

The rest is common code.

Offline lgb

  • EP addict
  • *
  • Posts: 3497
  • Country: hu
  • æðsta yfirmaður
  • OS:
  • Linux (Ubuntu) Linux (Ubuntu)
  • Browser:
  • Firefox 40.0 Firefox 40.0
    • View Profile
    • http://lgb.hu/
Re: Enterprise C compiler for PC
« Reply #28 on: 2015.August.22. 21:04:40 »
sdcc is beginning to support C Embedded, which is a C language extension for embedded systems.  C Embedded specifies how to deal with bankswitched memory and sdcc is starting to do that but I haven't looked in detail at it yet.  sccz80 does have 3-byte far pointers but again it's preliminary.  This is on my to-do list so once I've studied it I will include it in the crts.  I don't think it needs more than providing a subroutine in page-0 (the 'HOME' bank) to perform bankswitching and maybe provide some trampoline code.

So page-0 is always "fixed" and not "mapped out" ever. That's a good thing, especially if you plan to use EXOS calls, and of course because interrupts, etc.

Quote
So for now, it's left to the user program to handle bankswitched memory intelligently.  What we can do with the crt, for the ep, is make sure all the video-related stuff, some key functions like memcpy, and interrupt related handlers are in page-0 so that user code can be free to place two 16k pages in page-2/3 to copy or operate on data in different banks.  The ep will be the first target that needs a special memory map for this sort of thing :)

I see.

Quote
Heh yeah :)  That's what I want to do:  tell EXOS that the program is CODE+DATA+BSS bytes in size and have it allocate the pages but only load CODE+DATA bytes.  But because of the 48k limit it might be better just to do the BSS allocation at runtime so that it is possible to go beyond 48k.

Well, you define the length of the loaded program in the type-5 EXOS header (contains CODE+DATA, so the "pre-defined" areas unlike BSS). Then you may need to check that if BSS size in addition to that size (CODE+DATA) would span into a new segment(s?). If yes, you need to allocate another segment(s). And then you fill the BSS area with zeroes (regardless you needed to allocate segments or not, because BSS could fit into the already used segments for the loaded program). Getting beyond 48K is interesting, but also problematic: if CODE+DATA+BSS bypasses 48K boundary you need modify segment mapping (port $B3) all the time between video RAM and "tail" of the BSS, especially if the program needs frequent access of screen routines, thus a video RAM segment. But if you really need to have more code+data+bss than 48K than you can't do too much. Well, maybe one thing: if you need direct VRAM access and you allocated a VRAM segment for page-3 (C000-FFFF) and it's not used fully, you can use VRAM to store eg BSS data as well. Yes, VRAM is slower, but maybe it's still faster if you can avoid memory paging all the time! It depends on the exact situation though.

For example EXOS uses a segment (or more segments, but by default one) in VRAM (segment $FF) as its own RAM area also called "system segment". It's a VRAM segment because it's also used to store LPTs, video RAM, etc, not just EXOS variables and similar things. Though it can be faster to use VRAM only for video purpose data, and "normal RAM" for other EXOS data, it would fragment the available memory map, and also the situation would be more complicated because of the needed mapping changes all the time. That system segment btw grows downwards, eg if you open an EXOS channel (let it be a file, or DISPLAY:, etc) EXOS need some RAM, and system segment usage is maintained (the lowest used address) in the form of "EXOS boundary" (technically you - as user app - can even allocate segment when all segments are used, then EXOS will provide the system segment as "shared segment" providing EXOS boundary is the address you should not use beyond).

Quote
The BSS segment has to be zero according to the C standard but the crt takes care of all initialization details so the loader doesn't have to worry about it.

Well, yes, it's only me that I hate to rely on initialized BSS, eg a variable in the global scope "int a;" should be zero according to the C standard, but the same "int a;" will not within a function (since it will be allocated on the stack). And some compilers will complain about "uninitialized variable" even if it's in the global scope, so it's initialized to zero according to the C standard anyway, if I am right ... Anyway, just ignore my comment, of course it is almost nothing to fill the BSS area with zero bytes and it seems it is expected by standards.

Quote
I've given the ep's different video modes my own names (I don't know if something better already exists) and I'm measuring characters as 8x8 pixels:

* p2 (pixel 2 colour mode) 80x25 characters full screen
* p4 (pixel 4 colour mode) 40x25 characters full screen
* p16 (pixel 16 colour mode) 20x25 characters full screen
* a8 (attr 8 scan lines tall) 40x25 characters full screen, 40x25 attributes
* c128 (hardware characters)

You can do this, but please note that EXOS usually refers vertical resolution in units of 9 pixels instead of 8. Of course if you plan to have your own routines to set up video modes (so: defining LPT) that it's your business to use 8 pixel tail characters, etc, whatever. But eg the character set definition for hardware character mode is also 8*9 pixels by EXOS (though of course, you can embed your own charset to the binary, but it also enlarges your binary of course). By the way, Nick allows any tail of characters in hardware character mode, also the definition of characters has the layout to support this (that is, eg in ch128 mode, 128 bytes for the first rasterline of the 128 characters, than again 128 bytes for the second, etc, unlike other schemes eg with Commodore 64 where the first 8 bytes are for the first character of the charset for all rasters, etc). And if you are in doubt: Nick can access the VRAM _only_ so even character set must be stored there. Of course EXOS ROM contains the charset, but it's copied into the VRAM to be used by Nick then. "Software character mode" is of course a simple gfx mode at the other hand (the "80 column text mode" is that, in contrast of "40 column text mode" which is really a text mode!). In this case the "charset definition itself" is only used by software to "draw" characters thus - of course - it's not compulsory to store it in VRAM to be able to accessible by Nick.

Quote
I'm going to write the p4 primitives first and possibly the p2, c128 and a8 modes later.  Ultimately all of them should be there but I think it will be up to the EP community if they are interested in it.  I'm picking on the a8 mode specifically because this is compatible with the zx spectrum and the zx spectrum has a sprite library that has been used by many games which could easily use this mode on the EP.  That sprite library is intended to support many video modes so it could be modified for other of the EP's modes but that is also a lot of work.

Yes, but Spectrum compatibility is limited because of the different attribute by "layout". Though it's a minor point.

Quote
Does this sound like a good method to deal with the EP's flexibility?

I think, other people should answer too. To be honest, I never had EP till 2002 or so, I get to know it as its "retro computing" state already, unlike more people here who were active even in the age of the EP. I still feel sometimes that I can't "beat" others' experience and knowledge originated from the "golden age" and not only "recently" :)

Quote
For file i/o, the clib in z88dk has not finalized it yet -- all the code is present for file systems but the drivers have not been written to do file i/o yet.  The design is object oriented and operates like a stack where you would inject the target's native system at the level it can support.  If the target does not supply any disk device the idea is we will supply the entire stack including a fat driver.  But that's a long time for now.

Well, in case of EP it is not needed and probably you can't do it either (because of the different used hw solutions, I've already written about). Internally EXDOS uses FAT12 btw, but you don't need to know that too much, if you want to use only the "file level" functions. It's interesting to hear what z88dk plans, FAT driver etc, huh. I mean it's almost an OS then, and not only a compiler with its standard library too much :) But EP has its own OS already, and not even a bad one! I don't know the goals of z88dk etc, but for me, I would vote for an ANSI-C like library eg usage of open() fopen() etc, so code can be portable between different systems at source code level, let it be an EP, or a modern PC ... But I know, it can be only *one* goal, the other can be - for example - to be able to exploit the target machine's abilities using the C language which may need its own "standard" suitable for the purpose. So it's really hard to judge, what would be better, at least it's hard for me ... Since you seem to know a way much on sdcc/z88dk etc, I wouldn't even dare to write on these too much more :)

Quote
For the first pass, I'll ignore file i/o (and don't forget you can always call EXOS directly from within C) and then second pass maybe look at connecting stdio to any sort of streaming that EXOS can support.  At the lowest level, stdio generates about a dozen messages for i/o and if those messages can be satisfied by EXOS, it can be plugged in.  I think things like the printer, serial i/o, built-in EXOS video drivers can probably plug into stdio but EXDOS (disk i/o) doesn't seem to be a candidate.  It looks like it performs one whole read.write operation and then closes the channel.  So in order to use it like a streaming device, the z88dk driver would have to cache disk blocks in ram for stdio to access.

I still think that for _EP_ C coders they would welcome EXOS-specific API as well, besided ANSI-C/z88dk/anything else. That would be a quite small and simple "glue" to call EXOS functions for the (for example) exos_CALLNAME() functions. Of course C code which use these are not so much portable anymore, but we shouldn't forget that 8 bit micros are not power machines, and often the best performing code can be written using platform specific own solutions instead of "abstraction layers" (in the form of APIs) providing cross-platform compatibility. Yes, that sounds the reverse of my previous thoughts that I would welcome ANSI-C like stuffs. Well, hard question, and both scenarios can be useful in some situations, I think!

Quote
I thought left, right, up, down (and space for fire) were the built in joystick.

Yes, they are.

Quote
But then I saw mention of port $b6 in connections with the joystick... how do I read the joystick directly?  There's also mention of external joysticks in the EP tech docs -- is there a standard way to directly read that hw?

The _internal joystick_ is just like other keys on the keyboard, even the same membrane is used. The only difference, that other keys uses buttons to be able to be operated, while up/down/left/right keys use mechanically different solution and the designers used a joystick handle to be able to use them instead of buttons. So, yes, the internal joystick can be interpreted as other keys, keyboard matrix contains them. For the _external_ joysticks, the situation is different, they are handled differently, as you mentioned with the $b6 port, they are not part of the keyboard matrix. That also mean that a software want to use internal _and_ external joystick they must use separated routine for that purposes.

You can also think about mouse, which is a "hot" topic recently, especially because software like SymbOS makes it almost "a must", and it seems many people interested in this topic anyway. You should check other topics on the forum about this :)
 
But btw the keyboard matrix: do you plan to use your own keyboard scanning routine instead of EXOS' one? Well, it can cause some problems at least since there is eg UK and BRD (and HUN) layouts defined in software, and layout can be changed. Also, there were some projects to interface with an external keyboard without the hardware level compatibility (though to be honest, it can cause problems with many EP software as well, since many of them doing direct hw access), and only on software level the compatibility is provided. I'm really unsure here what can be the best solution, in some situation there can be a significant overhead to allow EXOS interrupt, keyboard scan, than doing EXOS calls to check keyboard etc ...

Quote
* sound.  The sound library is 1-bit oriented but it contains some really good music synthesis routines.  It should be compatible with Dave.

Btw, Dave supports 6 bit D/A too. And "of course" it has got oscillators with some modulation/distortion/etc settings which are more like digital implementation (unlike with C64 SID, where there are analogue filters for example). Dave is stereo btw.

EXOS here is quite elegant btw, it again uses the channel notion, so you can open a channel (with "file name" of SOUND:). You can write quite "complex" sound definition "control codes" there, and EXOS within the EXOS interrupt will "play it" in the "background". Or something like that, honestly I have never used these ...

http://ep.homeserver.hu/Dokumentacio/Konyvek/EXOS_2.1_technikal_information/exos/sound/Ch2.html

But in general, you can see how advanced EXOS is :) I was really surprised that a "8 bit micro" uses an OS like EXOS (biut . I don't want to say that you "must" use EXOS for SOUND at any price, just I mentioned it here for the completeness.

And feel free to write me "you're too much with those novels", I know I can write just too much :) Hopefully my long posts are not only for enlarge the database of the forum :)

Offline Alcoholics Anonymous

  • Newbie
  • Posts: 10
  • Country: ca
  • OS:
  • Windows NT 6.2 Windows NT 6.2
  • Browser:
  • Firefox 40.0 Firefox 40.0
    • View Profile
    • Z88DK Homepage
Re: Enterprise C compiler for PC
« Reply #29 on: 2015.August.24. 01:44:25 »
You can do this, but please note that EXOS usually refers vertical resolution in units of 9 pixels instead of 8. Of course if you plan to have your own routines to set up video modes (so: defining LPT) that it's your business to use 8 pixel tail characters, etc, whatever.

For the hardware modes, the native character set can be used at 9 pixels tall.  The screen size is still measured in characters.

For the other modes, the difficulty is the max common vertical screen resolution does not divide into 9.  Eg, p4 is typically max 320x200.  200 pixels is 25 chars tall if the chars are 8 pixels tall.  But if they are 9 pixels, it is 200/9 = 22.2 chars tall.  You can reduce the max vertical res to 9*22 = 198 pixels so it's not really a big deal.  The other things that are making me think 8 pixels is 8 is a power of 2 (add a register to itself three times to multiply by 8) and, most importantly, other z80 targets use height 8 pix for their fonts so doing it like this lets the EP benefit from fonts and code on other machines.

There's also a proportional font driver where fonts can be any height so the 9-pixel height specialness of the EP does not have to be lost.

Quote
Well, in case of EP it is not needed and probably you can't do it either (because of the different used hw solutions, I've already written about). Internally EXDOS uses FAT12 btw, but you don't need to know that too much, if you want to use only the "file level" functions. It's interesting to hear what z88dk plans, FAT driver etc, huh. I mean it's almost an OS then, and not only a compiler with its standard library too much :)

Yes it's meant to provide a complete system on z80 embedded systems so there are a lot of extras that other targets can select from as appropriate.

The user-level documentation I found on EXDOS mentioned that a disk channel was automatically closed after a read or write operation, so it seemed like EXDOS would not be able to support streamed i/o.  I was reading user-level documentation which was concerned with loadng and saving entire files rather than random access so it could be I was unlucky to look at the wrong place.

Would something like this be able to be efficiently implemented using just EXDOS?

Code: [Select]
while ((c = fgetc(in)) != EOF)
   fputc(process(c), out);

For this kind of common code to be efficient, the implementation has to cache several disk sectors in memory so that individual reads and writes go to memory rather than disk.  Most z80 disk implementations have been as simple as possible and perform very badly under C without assistance which is why z88dk is trying to supply disk i.o in a layered manner so that these simple systems can sit on top of a caching mechanism.


Quote
for example - to be able to exploit the target machine's abilities using the C language which may need its own "standard" suitable for the purpose. So it's really hard to judge, what would be better, at least it's hard for me ...

We don't replace the underlying system, only add to it.  So eg, a cpm system can still do file i/o by calling the bdos directly but the c standard i/o is also available to use.

Quote
The _internal joystick_ is just like other keys on the keyboard, even the same membrane is used. The only difference, that other keys uses buttons to be able to be operated, while up/down/left/right keys use mechanically different solution and the designers used a joystick handle to be able to use them instead of buttons. So, yes, the internal joystick can be interpreted as other keys, keyboard matrix contains them. For the _external_ joysticks, the situation is different, they are handled differently, as you mentioned with the $b6 port, they are not part of the keyboard matrix. That also mean that a software want to use internal _and_ external joystick they must use separated routine for that purposes.

Ok, is there any documentation on what is returned from a port read of $b6?  The only doc I've found so far is this:

http://gafz.enterpriseforever.com/Dokumentacio/Konyvek/EXOS_2.1_technikal_information/exos/keyboard/Ch3.html#3.7
which is using the EXOS keyboard driver to read the joystick.  The bits are obviously moved because when you read the internal joystick those bits do not correspond to the keys read from $b5.

Quote
But btw the keyboard matrix: do you plan to use your own keyboard scanning routine instead of EXOS' one? Well, it can cause some problems at least since there is eg UK and BRD (and HUN) layouts defined in software, and layout can be changed. Also, there were some projects to interface with an external keyboard without the hardware level compatibility (though to be honest, it can cause problems with many EP software as well, since many of them doing direct hw access), and only on software level the compatibility is provided. I'm really unsure here what can be the best solution, in some situation there can be a significant overhead to allow EXOS interrupt, keyboard scan, than doing EXOS calls to check keyboard etc ...

Yes, here's the untested and first pass at the code:

Code: [Select]
; ===============================================================
; Aug 2015
; ===============================================================
;
; int in_inkey(void)
;
; Read instantaneous state of the keyboard and return ascii code
; if only one key is pressed.
;
; ===============================================================

SECTION code_input

PUBLIC asm_in_inkey

EXTERN in_key_translation_table, error_znc, error_zc

asm_in_inkey:

   ; exit : if one key is pressed
   ;
   ;           hl = ascii code
   ;           carry reset
   ;
   ;         if no keys are pressed
   ;
   ;            hl = 0
   ;            carry reset
   ;
   ;         if more than one key is pressed
   ;
   ;            hl = 0
   ;            carry set
   ;
   ; uses : af, bc, de, hl

   ;EP keyboard matrix:
   ;        b7    b6    b5    b4    b3    b2    b1    b0
   ;Row    80H   40H   20H   10H   08H   04H   02H   01H
   ; 0   L.SH.     Z     X     V     C     B     \     N
   ; 1    CTRL     A     S     F     D     G  LOCK     H
   ; 2     TAB     W     E     T     R     Y     Q     U
   ; 3     ESC     2     3     5     4     6     1     7
   ; 4      F1    F2    F7    F5    F6    F3    F8    F4
   ; 5         ERASE     ^     0     -     9           8
   ; 6             ]     :     L     ;     K           J
   ; 7     ALT ENTER   LEFT  HOLD   UP   RIGHT DOWN  STOP
   ; 8     INS SPACE R.SH.     .     /     ,   DEL     M
   ; 9                   [     P     @     0           I
 
   ld bc,$09b5
   ld d,$ff
   ld hl,shift_table + 9

hit_loop:

   out (c),b                   ; select key row
   in a,(c)                    ; read key state active low
  
   or (hl)                     ; ignore shift keys in this row
   dec hl
  
   cp d
   jr nz, key_hit_0            ; if at least one key pressed in row
  
   dec b
   jp p, hit_loop              ; repeat for rows 9 to 0
  
   jp error_znc                ; if no keys pressed

key_hit_0:

   ; at least one key row is active

   ;  a = active low key result
   ;  b = row containing key press
   ;  c = $b5
   ;  d = $ff
   ; hl = shift table address corresponding to key press - 1

   ; find bit position corresponding to key press

   ld e,d

bit_loop:

   inc e
   rrca
   jr c, bit_loop
  
   cp $7f
   jp nz, error_zc             ; if multiple keys pressed

   ; make sure no other rows are active
  
   ;  e = key bit position 0-7
   ;  b = row containing key press
   ;  c = $b5
   ;  d = $ff
   ; hl = shift table address corresponding to key press - 1
  
   ld h,l
   push hl
  
miss_loop:

   dec b
   jp m, key_hit_1             ; if done checking other key rows
  
   out (c),b                   ; select key row
   in a,(c)                    ; read key state active low
  
   or (hl)                     ; ignore shift keys in this row
   dec hl
  
   cp d
   jr z, miss_loop             ; if no keys pressed in row
  
   jp error_zc - 1             ; if multiple keys pressed

key_hit_1:

   ; exactly one key is pressed
  
   ;     c = $b5
   ;     e = key bit position 0-7
   ;     d = $ff
   ; stack = LSB shift table address corresponding to key press - 1

   pop af                      ; a = LSB of shift table address for key press
  
   inc a
   sub shift_table & 0xff
   add a,a
   add a,a
   add a,a                     ; row offset into table in bytes
  
   add a,e                     ; add key bit offset into table
  
   ld e,a
   inc d                       ; de = key offset into table
  
   ; check for shift modifiers

   ; de = key offset into table 0-79
   ; hl = & key translation table
  
check_LSHIFT:

   xor a
   out ($b5),a                 ; select row 0

   in a,($b5)
   and $80                     ; LSHIFT
  
   ld hl,in_key_translation_table + 80  
   jr z, ascii                 ; if pressed

check_RSHIFT:

   ld a,8
   out ($b5),a                 ; select row 8
  
   in a,($b5)
   and $20                     ; RSHIFT
   jr z, ascii                 ; if pressed

check_CTRL:

   ld a,1
   out ($b5),a                 ; select row 1
  
   in a,($b5)
   and $80                     ; CTRL
  
   ld hl,in_key_translation_table + 160
   jr z, ascii                 ; if pressed

check_ALT:

   ld a,7
   out ($b5),a                 ; select row 7
  
   in a,($b5)
   and $80                     ; ALT
  
   ld hl,in_key_translation_table + 240
   jr z, ascii                 ; if pressed
  
   ; no shift modifiers
  
   ld hl,in_key_translation_table

ascii:

   add hl,de
  
   ld l,(hl)
   ld h,0
  
   ret

shift_table:

   defb $80 ; row 0 ignore LSHIFT
   defb $80 ; row 1 ignore CTRL
   defb $00 ; row 2
   defb $00 ; row 3
   defb $00 ; row 4
   defb $80 ; row 5 ignore unconnected
   defb $80 ; row 6 ignore unconnected
   defb $80 ; row 7 ignore ALT
   defb $20 ; row 8 ignore RSHIFT
   defb $c2 ; row 9 ignore unconnected

in_inkey() returns the ascii char corresponding to exactly one key pressed.  It processes SHIFT, CTRL and ALT and looks up ascii codes in a 320-byte table.  I didn't quite like the size of that but it can be looked at again later.  This subroutine would be used by the terminals to read input.  Related code generates a 16-bit scancode corresponding to an ascii keypress and another subroutine takes this scancode to see if the key is pressed.  This gives very fast keyboard scanning in games, eg.

We can accommodate different language keyboards easily by specifying a keyboard type in the config file and just choosing a different ascii table depending on the keyboard type.

Quote
Btw, Dave supports 6 bit D/A too. And "of course" it has got oscillators with some modulation/distortion/etc settings which are more like digital implementation (unlike with C64 SID, where there are analogue filters for example). Dave is stereo btw.

EXOS here is quite elegant btw, it again uses the channel notion, so you can open a channel (with "file name" of SOUND:). You can write quite "complex" sound definition "control codes" there, and EXOS within the EXOS interrupt will "play it" in the "background". Or something like that, honestly I have never used these ...

Yes I don't want to take away from that - I'm just looking for a way to bring what is in the z88dk library now to the EP.  The D/A can probably give volume-controlled 1-bit sound effects and music.

Quote
But in general, you can see how advanced EXOS is  I was really surprised that a "8 bit micro" uses an OS like EXOS (biut . I don't want to say that you "must" use EXOS for SOUND at any price, just I mentioned it here for the completeness.

Yes it is - that's why I'm sort of staggering around to figure out the best way to do this   I'm sure the best way will evolve over time.

Quote
And feel free to write me "you're too much with those novels", I know I can write just too much  Hopefully my long posts are not only for enlarge the database of the forum

I don't mind.. the more info the better.   Once I have something preliminary ready I'm sure it will be easier to point out how to improve things.
[/code][/code]