neilsf / XC-BASIC

A compiling BASIC dialect for the Commodore-64
https://xc-basic.net/
MIT License
74 stars 15 forks source link

Stepping towards a multi-target compiler #82

Open neilsf opened 4 years ago

neilsf commented 4 years ago

The compiler is currently targeted to C64 only. Many users have already suggested that it should be possible to compile XC=BASIC programs to other platforms e.g Plus/4, C16, VIC-20, BBC Micro, the upcoming X16, and others.

This task requires involvement of developers who are familiar with the new target systems.

Here is a brief explanation of the current library system for reference. The compiler includes the following libraries in the intermediate assembly source:

For the future I envision a library structure something similar to the following:

lib/
  c64/
    stdlib.asm
  plus4/
    stdlib.asm
  vic20/
    stdlib.asm
  nucleus.asm
  strings.asm
  mem.asm
  opt.asm

Meaning that all platform-agnostic libraries go to the library root and and all platform-specific libraries go to their own dir.

The following steps are required (in a nutshell):

  1. Move all platform-specific code from the nucleus to the standard library or another library. Strings and memory libraries are (should be) already platform-agnostic. It is possible that we will need to exclude floating point ops to a separate library as well.
  2. Check the compiler's source - it should not include any platform-specific code in the assembly source.
  3. Write the standard libraries for each platform - DEVELOPERS, DEVELOPERS, DEVELOPERS!
  4. Add a PRAGMA directive that instructs the compiler which platform to target to.
  5. Test
  6. Happiness

Please add your thoughts and/or let me know if you can help in coding. Thanks.

Majikeyric commented 4 years ago

I can help with C16 (CPlus/4 = C16 with 64K) and VIC20. Their architecture is not so different than the C64. The VIC20 can have multiple memory configurations (not expanded, +3K and >=+8K ) maybe it would be better with the PRAGMA directive to select one of the 3 memory configurations for VIC20. according to the memory configuration selected, the start address of basic programs and the addresses of the screen and colors locations are differents. With the VIC20 you can't bank out BASIC or KERNAL, there is no mechanism like the C64 with $01 register. the biggest contiguous chunk of memory available will be 28K ($1000-$7fff) with the >=+8K configuration. There could be 8KB of more RAM but they are located after CHARGEN and IOs areas in memory (at $a000-$bfff)

With the CPlus/4, BASIC+KERNAL are located at $8000-$FCFF, they take half of the memory. they can be banked out to access ram under but they are only banked out simultaneously. CPlus/4 can access all ram, when C16 ram is located at $0000-$3fff

neilsf commented 4 years ago

Thanks!

To tell the truth, there is no upper memory limit check currently. As long as DASM compiles the intermediate code (I think up until $FFFF), no error will occur. So this is again another task - to set up some limit check depending the platform and configuration (using PRAGMA as you suggest).

Are BASIC/KERNAL floating point routines in Plus/4, C16 and VIC20 the same? XC=BASIC does not have its own floating point library, it just uses the FP routines in BASIC/KERNAL (temporarily banking it in for the calculations).

The rest seems okay, I think I'll start with separating the nucleus and the libs and when it's done I'll ask you to do the other platforms.

Majikeyric commented 4 years ago

FP routines in CPlus/4 and VIC20 should be at different addresses but work like the C64.

neilsf commented 4 years ago

Hi @Majikeyric

I have created a new branch feature/multiarch. It contains all the necessary changes for you to start working on the c16 and vic-20 platforms.

Let me provide you some basic information. The lib directory now contains subdirs for each platform. In each platform subdir you'll find:

(I wasn't sure if I should make 1 or 2 dirs for c16 and plus/4, we can discuss this later.)

There's a new PRAGMA directive that looks like this:

pragma target = "c16"
pragma target = "c64"
pragma target = "cplus4"
pragma target = "vic20"

This tells the compiler which platform to compile to. Defaults to "c64".

I have only did a couple of tests (you'll find it in tests/multiarch.bas) but it seems to be working so far - I mean no regression at least.

It is worth noting that whenever you change a file in the lib directory, xcbasic64 must be recompiled. You'll need the dmd compiler and the dub package manager for this purpose. The command to recompile is dub build --force.

Please contact me in email (feketecsaba [at] gmail) if you need to discuss the details.

Thank you so much and welcome aboard! I'm very excited about this new feature as it opens the door to other retro worlds!

PS. Some addresses are still hard-coded, e. g $0400 and $0801. We'll have to discuss these...

Majikeyric commented 4 years ago

Thanks for the info ! I'm excited too helping porting XCBASIC to other platforms I love (with the C64!). I must launch the "dub build --force" command at the root of feature/multiarch ? I get errors... I have installed dmd2 and there is the dub.exe in its bin directory. I suppose it's ok

Majikeyric commented 4 years ago

The VIC20 implementation is complete there are a lot of similarities with the C64. I can't do a "push upsteam", I get an authentication failed error, I don't know why....

BUT there are 3 different memory configurations for VIC20. So I don't how you can deal with it. unexpanded: basic start: $1001 highest ram address : $1fff screen: $1e00 colors: $9600

3K expansion: basic start: $0401 highest ram address : $1fff screen: $1e00 colors: $9600

8K expansion and more: basic start: $1201 highest ram address : $7fff screen: $1000 colors: $9400

some remarks:

The STDLIB_MEMSETUP SUBROUTINE is not required as there is no bank switching on VIC20 so I just let a RTS if you call it anyway.

STDLIB_RND SUBROUTINE I knew this RND routine, there is an errror, a missing CLC see http://sleepingelephant.com/ipw-web/bulletin/bb/viewtopic.php?f=2&t=2304 (first post from Kweepa)

The current device number is probably hardcoded ? ($BA) $BA is ok for VIC20 but it is $AE for C16/+4

$02fe-$02ff location to store USR function return address should be ok on VIC20/C16+4

Does XCBASIC check when C64 code is located at $a000-$bfff ? and how does it manage the BASIC banking-in in this case ?

There will a bit more complex case with C+4, as ROMs (BASIC+KERNAL) are located at $8000-$ffff and can only be turned on/off at once, not separately. For the CPU to read RAM at that location, the complete ROM (BASIC+KERNAL) must be disabled involving the IRQs to be disabled as well. if code is located above $8000 it can't access BASIC and KERNAL routines directly from there.

EDIT maybe it could be solved using IRQ/KERNAL/BASIC calls wrappers allowing to use 64K RAM permanently. code below should be located < $8000.

IRQ call :

bintr STA $FF3E ;enables ROM STA *+11 ;saves AC LDA #>rintr PHA LDA #<rintr PHA PHP LDA #0 PHA TXA PHA TYA PHA JMP ($314) ;ROM IRQ handler rintr STA $FF3F ;turn RAM on RTI

You should place bintr address to $fffe.

KERNAL/BASIC calls:

SEI STA $FF3E ;enables ROM jsr xxxx STA $FF3F ;turn RAM on CLI RTS

neilsf commented 4 years ago

Thanks for the info ! I'm excited too helping porting XCBASIC to other platforms I love (with the C64!). I must launch the "dub build --force" command at the root of feature/multiarch ? I get errors... I have installed dmd2 and there is the dub.exe in its bin directory. I suppose it's ok

On Windows you have a DUB command line launcher in your start menu. Run it and cd to the project root. Then issue the command and it should run fine. It creates the xcbasic64.exe which you should copy to the bin directory. What errors do you get?

neilsf commented 4 years ago

BUT there are 3 different memory configurations for VIC20.

I think I'll add a PRAGMA for this. Now I see that it's very important to make BASIC start and screen addresses variable...

I'll move on to your other questions a bit later, my weekend is busy, sorry.

neilsf commented 4 years ago

I can't do a "push upsteam", I get an authentication failed error, I don't know why....

I added you as a collaborator now, maybe this will solve it.

neilsf commented 4 years ago

Does XCBASIC check when C64 code is located at $a000-$bfff ? and how does it manage the BASIC banking-in in this case ?

It is not checked at all :-( To be honest I think this is a minor issue now as BASIC is only banked in for floating point routines. If the program doesn't use floats then BASICIN/BASICOUT will only be called on the program start/end. Three options I can see now for fixing this:

+1 idea: drop floats and use fixed point.

neilsf commented 4 years ago

STDLIB_RND SUBROUTINE I knew this RND routine, there is an errror, a missing CLC

Can you please fix and also add a reference in a comment. I think I forgot to add credits/reference. Thanks

neilsf commented 4 years ago

I have pushed some code change that gives us these new PRAGMAs:

pragma vic20_memsetup = "default" : rem can be "default", "3k" or "8k"
pragma c64_screen_memory = $0400 : rem can be any value

CHARAT and TEXTAT now takes into account the above settings. I have difficulties with testing on VIC-20, TEXTAT is yet buggy in some situations. I haven't yet tested on Plus/4 at all.

P.S. @Majikeyric would you like to join the XC=BASIC Slack channel where we can discuss the details? I can send you an invitation. Or do you have any other preferred communication method?

Majikeyric commented 4 years ago

CHARAT and TEXTAT now takes into account the above settings. I have difficulties with testing on VIC-20, TEXTAT is yet buggy in some situations. I haven't yet tested on Plus/4 at all.

the VIC20 screen by default at startup has 23 rows and 22 columns (but it can be changed by writing to registers). to get screen dimensions in real time: lda $9002 and #$7f sta columns lda $9003 lsr and #$3f sta rows

I haven't completely implemented C16/Plus/4 yet

P.S. @Majikeyric would you like to join the XC=BASIC Slack channel where we can discuss the details? I can send you an invitation. Or do you have any other preferred communication method?

yes sure! and yes I like Slack! :)

neilsf commented 4 years ago

Thanks. Here's the invite link:

https://join.slack.com/t/xcbasic/shared_invite/enQtODM1NjI3MTE0MDM1LTZlOTg5NmU5OWVkM2ZkZjE4OTU4MjgyM2U0MWUxMzhmZGYwMDlhOWQyYTY5MTYxMzI3ZDQ3MzgzNzA5YzFhODU

It's open for everyone who wants to join.