| |
Jammer
Registered: Nov 2002 Posts: 1336 |
C64/C128 combo program compilation
Question might turn out plainly stupid so bear with me but I'm total noob on C128.
Can C64 program be compiled to run both on C64 and C128 in its native 128k mode if it has appropriate branches in code? Or it's always two separate tailored builds?
I've already learnt that C128 program startup is either $1C01 or $4001 but if C128 startup was embedded at the right spot, would it still launch? |
|
| |
wil
Registered: Jan 2019 Posts: 63 |
If the I/O area is set to be visible via the MMU, the layout of VIC registers, SID registers, screen (at $400) and color ram ($d800) are identical to the C64, so it should be possible to write a program that starts for example at $1c0d and if executed on the C64, transfers the program there first. Of course, this requires the user to load the program with ",8" on the C64; otherwise, the Basic Sysline is not at $801.
When using Sprites while having the Kernal active, the C128 needs to be told to get its fingers off the sprite registers (by clearing bit 1 of $A04). Note that the user could also have used the GRAPHICS command before loading the program, then the start adress is even at $4001. |
| |
Count Zero
Registered: Jan 2003 Posts: 1940 |
BASIC programs can be made "multi platform" more or less easily. Likely in the BBS/terminal field such 64/128 cross platform support can be found.
I remember some filebrowser source which had vc20/c16/c64/c128 code included but that produced several binaries. |
| |
Jammer
Registered: Nov 2002 Posts: 1336 |
I'm mostly concerned with asm code run via sysline. |
| |
Krill
Registered: Apr 2002 Posts: 2981 |
X-Y problem time! =)
C-128 programs usually run via the boot block. You insert the disk, power up or reset the computer, program boots.
As such, you wouldn't really have to have the very same program run natively on both C-64 and C-128. It'd be an academic exercise with little practical relevance.
So, what do you actually want to achieve? |
| |
Jammer
Registered: Nov 2002 Posts: 1336 |
One-filed C64 fps game which runs at slightly better framerate if it detects C128 😃 |
| |
chatGPZ
Registered: Dec 2001 Posts: 11390 |
for that, just always do the d030 switching in the border. no need to detect anything :) (and then it will automagically also work with other turbos that use that bit) |
| |
Krill
Registered: Apr 2002 Posts: 2981 |
Quoting JammerOne-filed C64 fps game which runs at slightly better framerate if it detects C128 😃 So not running in native C-128 mode? |
| |
chatGPZ
Registered: Dec 2001 Posts: 11390 |
BTW, crafting a file that would load and start in c128 mode instead of c64 mode (and still works in c64 mode) is probably possible too (not trivial, and you'll be forced to load ,8 only in one of the modes). I doubt it makes sense for the sort of thing you have in mind though :) |
| |
Krill
Registered: Apr 2002 Posts: 2981 |
Quoting chatGPZand you'll be forced to load ,8 only in one of the modes) Could be quite possible to craft an ",8,1" (or BLOAD) autorun program that would work in both C-64 and native C-128 modes.
But then again, quite pointless when there is a boot block (plus not a sensible notion of "one-filer" on C-128). |
| |
chatGPZ
Registered: Dec 2001 Posts: 11390 |
oh yeah, with autorun. sure. even more messier :=) |
| |
tlr
Registered: Sep 2003 Posts: 1791 |
For the record, it's quite common to have load addr independent sys starts on the vic20 because the basic start may be at different addresses depending on memory expansion.
Simply include $2c/PEEK(44) in your address calculations.
Using this method you can make a binary that starts from basic on most/all commodore 8-bits. |
| |
JackAsser
Registered: Jun 2002 Posts: 2014 |
Quote: for that, just always do the d030 switching in the border. no need to detect anything :) (and then it will automagically also work with other turbos that use that bit)
As GP said. Just flip the bit in the border regardless if it's a C128 or C64. It doesn't matter for the C64, and a C128 user will get the boost. No problems. |
| |
MagerValp
Registered: Dec 2001 Posts: 1078 |
Quoting tlrSimply include $2c/PEEK(44) in your address calculations.
Using this method you can make a binary that starts from basic on most/all commodore 8-bits.
In C128 mode basic start is at $2d/$2e instead, so it requires a little more logic. Certainly still doable, but I don't think I've seen a ready to use basic stub for both C64 and C128? |
| |
Jammer
Registered: Nov 2002 Posts: 1336 |
If I can switch to 2MHz in C64 mode as well, that's perfectly what I need. Thanks! |
| |
oziphantom
Registered: Oct 2014 Posts: 490 |
just doing 2Mhz in the borders, leaves a lot of performance on the table though. If you are doing a native version then you can make full use of the 128.
But if you want to do it in a single load that might be a problem, you would probably need to load "128 patches" after the main binary to replace the 64 versions with the faster 128 versions. |
| |
Jammer
Registered: Nov 2002 Posts: 1336 |
Should Vice C128 switch back to 128 mode and crash the machine if I only attach/load file in GO64 mode? |
| |
oziphantom
Registered: Oct 2014 Posts: 490 |
if you autostart it, it will then reset the machine and hence boot in 128 mode. You need to attach the d64 and then load in C64 mode. |
| |
tlr
Registered: Sep 2003 Posts: 1791 |
Quote: Quoting tlrSimply include $2c/PEEK(44) in your address calculations.
Using this method you can make a binary that starts from basic on most/all commodore 8-bits.
In C128 mode basic start is at $2d/$2e instead, so it requires a little more logic. Certainly still doable, but I don't think I've seen a ready to use basic stub for both C64 and C128?
Aha, didn't know that. Seems it's different on the PET as well now that I look it up. It's apparently only the kernal that is somewhat compatible. |
| |
Krill
Registered: Apr 2002 Posts: 2981 |
Quoting JammerIf I can switch to 2MHz in C64 mode as well, that's perfectly what I need. Thanks! Great! :)
Your original "C128 in its native 128k mode" implied actual native C-128 mode usage, such as using all 128 KB of RAM, relocateable zeropage and stack, double-buffered $D800 colour RAM and whatnot.
But if you only need 2 MHz, awesome. =)
Take care to have smoother but not faster gameplay with various turbo speeds of up to 48 MHz (update state in VBL or using the timers).
Wolfenstein engine thingy in One-Der is a good example for that, plays silky-smooth on U64@48MHz. |
| |
Jammer
Registered: Nov 2002 Posts: 1336 |
Quoting oziphantomif you autostart it, it will then reset the machine and hence boot in 128 mode. You need to attach the d64 and then load in C64 mode.
There's 'Autostart' option and 'Attach/Load' which, I guess, shouldn't reset the machine, only fill memory with file data. It works properly for x64sc at least but I suppose it's that bootblock mechanism, inherent to C128? |
| |
oziphantom
Registered: Oct 2014 Posts: 490 |
Oh you are using a GTK version, yeah "attach/load" just attaches the image for me. But that is on 3.7.1 might be different on a newer version. |
| |
Jammer
Registered: Nov 2002 Posts: 1336 |
Quoting JackAsserAs GP said. Just flip the bit in the border regardless if it's a C128 or C64. It doesn't matter for the C64, and a C128 user will get the boost. No problems.
I understood you here that I need to keep constant track of switching $d030 for border and visible area but from what I test the thing, it works fine just after switching $d030 to 1 for good and machine keeps track on its own. Anyway, it works, yay! :D |
| |
tlr
Registered: Sep 2003 Posts: 1791 |
Quote: Quoting JackAsserAs GP said. Just flip the bit in the border regardless if it's a C128 or C64. It doesn't matter for the C64, and a C128 user will get the boost. No problems.
I understood you here that I need to keep constant track of switching $d030 for border and visible area but from what I test the thing, it works fine just after switching $d030 to 1 for good and machine keeps track on its own. Anyway, it works, yay! :D
Uhm, are you sure about that? It screws big time with VIC-II output on the c128s I’ve tested. What machine are you running on? |
| |
Jammer
Registered: Nov 2002 Posts: 1336 |
Quoting tlrUhm, are you sure about that? It screws big time with VIC-II output on the c128s I’ve tested. What machine are you running on?
x128, C64 compatible mode in GTK Vice 3.8 r44982. No access to real machine. |
| |
chatGPZ
Registered: Dec 2001 Posts: 11390 |
beware, x128 does not emulate the ViCIIe garbage that you see when switching to 2MHz - try z64k (and certainly the real thing) |
| |
Jammer
Registered: Nov 2002 Posts: 1336 |
Thanks, guys, for the heads up! <3 Is it also same problem with SuperCPU and other accelerators? |
| |
chatGPZ
Registered: Dec 2001 Posts: 11390 |
No, the others don't result in that kind of garbage display. SCPU is an entirely different beast though :) |
| |
zzarko
Registered: Feb 2003 Posts: 77 |
3rd place at Revision 2024 Wild category:
https://www.pouet.net/prod.php?which=96567
The same binary (although with some caveats) works on C64, MSDOS, Linux, SNES, NDS, Gameboy, Gamecube, can be unpacked as a ZIP file (then it contains its complete source) and can be openbed as PDF. For any of these, just change the extension.
So I would guess there is definitely a way to make one binary that runs on C64 and C128 without modifications (I am not saying that I can make one!). |
| |
Martin Piper
Registered: Nov 2007 Posts: 726 |
Quote: 3rd place at Revision 2024 Wild category:
https://www.pouet.net/prod.php?which=96567
The same binary (although with some caveats) works on C64, MSDOS, Linux, SNES, NDS, Gameboy, Gamecube, can be unpacked as a ZIP file (then it contains its complete source) and can be openbed as PDF. For any of these, just change the extension.
So I would guess there is definitely a way to make one binary that runs on C64 and C128 without modifications (I am not saying that I can make one!).
This is nice. As long as the prg is loaded with ,8 and not ,8,1 then it would be relatively easy to make a prg that detects if it is running in C64 or C128. |
| |
oziphantom
Registered: Oct 2014 Posts: 490 |
I guess you could use BASIC to detect which machine you are on, or maybe which version of BASIC you are running?
Set the BASIC error vector to something custom and then try and run a BASIC 7.0 command, if it fails you know you are BASIC 2, if it passes you know you are BASIC 7 and hence then know were the asm code starts. Both the 64 and 128 have the BASIC error vector at $300/1.
However you then still have the issue that your code has to handle being in two different memory locations, but I guess at that point you could jump to a known address at the end of code on a 128 that then copies the main code down to 0801 or wherever you want to start, then apply your patches and then jump to it. |
| |
aeeben
Registered: May 2002 Posts: 44 |
@Jammer, if this is for the project I think it is, why not do a native version for C-128 in the VDC 80 column display, then you can run all calculations at 2 kHz :) [Ouch, actually, writing to VDC is probably too slow...]
Almost related bits from VIC 20 world: I used this loader in Hare Basic - it does autostart on both VIC 20 and C-64, and loads&runs either the file "A000" or "C000". As a little bonus, it can be also loaded with ",8" on both machines, but then obviously requires a RUN.
(Inspired by Mike's VIC 20 memory-configuration-independent-autostart code on Denial forum.)
processor 6502
SETLFS equ $ffba
SETNAM equ $ffbd
LOAD equ $ffd5
RESTOR equ $ff8a
CHROUT equ $ffd2
CLRCHN equ $ffcc
SCREEN equ $ffed
; C-64 / VIC 20 Autostart
;
; load"*",8 or load"boot",8 (and run)
; load"*",8,1 or load"boot",8,1 (autostart)
start equ $02a7
org start
incbin "autostart-basic.bin" ; 2024 syspeek(44)*256+peek(43)+21
basic
ldy #bootend-start-1
.1
lda ($2b),y
sta start,y
dey
bne .1
jmp boot
boot
jsr SCREEN ; detect C-64 or VIC 20 by number of rows
cpy #$19
beq .c64
.vic20
jsr $e45b ; restore basic vectors (VIC 20)
lda #$a0
sta start_+2 ; modify start address to $a000
lda #$41
sta filename ; modify filename to "A000"
bne .load
.c64
jsr $e453 ; restore basic vectors (C-64)
.load
ldx #<filename ; set up filename
ldy #>filename
lda #$04
jsr SETNAM
lda #$01 ; set up file
sta $9d
ldx $ba
tay
jsr SETLFS
lda #$00 ; load and execute
jsr LOAD
start_
jmp $c000
filename
dc.b "C000"
bootend
org $0300
dc.w boot
dc.w boot
|
| |
oziphantom
Registered: Oct 2014 Posts: 490 |
yeah but the VIC-20 and C64 have the same version of BASIC with the same vectors and ROM in the same place. The 128 is not a slightly bigger C64 it's a smaller Amiga.
Putting that code on a 128 will trash
02a2-02ae 674-686 Kernal RAM
02a2-02ae Bank Peek Subroutine
02af-02bd Bank Poke Subroutine
02be-02cc Bank Compare Subroutine
02cd-02e2 JSR to Another Bank
02e3-02fb JMP to Another Bank
02fc-02fd Function Execute Hook [4c78]
which will cause crashes |
| |
chatGPZ
Registered: Dec 2001 Posts: 11390 |
Quote:The 128 is not a slightly bigger C64 it's a smaller Amiga.
It has more in common with a Spectrum than with an Amiga though :D |
| |
Jammer
Registered: Nov 2002 Posts: 1336 |
Amiga is a direct descendent of Atari, deal with it ;) |
| |
MagerValp
Registered: Dec 2001 Posts: 1078 |
Writing a big basic program with branching logic to detect C128 or C64 is easy enough, but I'd prefer something compact even if a bit hacky. The best I could come up with on my lunch break is SYS(PEEK(57532)-219)*256+30.
Sample project here: https://github.com/MagerValp/C128-C64-PIBS |
| |
oziphantom
Registered: Oct 2014 Posts: 490 |
SYS(PEEK(46)*256+30) would do it I think. |
| |
MagerValp
Registered: Dec 2001 Posts: 1078 |
Quoting oziphantomSYS(PEEK(46)*256+30) would do it I think.
No that points to the end of the loaded program on the C64, which unless it's really short doesn't give you $08. |
| |
Martin Piper
Registered: Nov 2007 Posts: 726 |
Quote: yeah but the VIC-20 and C64 have the same version of BASIC with the same vectors and ROM in the same place. The 128 is not a slightly bigger C64 it's a smaller Amiga.
Putting that code on a 128 will trash
02a2-02ae 674-686 Kernal RAM
02a2-02ae Bank Peek Subroutine
02af-02bd Bank Poke Subroutine
02be-02cc Bank Compare Subroutine
02cd-02e2 JSR to Another Bank
02e3-02fb JMP to Another Bank
02fc-02fd Function Execute Hook [4c78]
which will cause crashes
43/44 on the C128 are also not the start of basic. |
| |
zzarko
Registered: Feb 2003 Posts: 77 |
CBM FileBrowser v1.6 implements a basic stub that checks if the machine is VIC-20, C64, C128, C64DTV or Plus/4 and loads binary for recognized one:
https://github.com/0cjs/cbm-filebrowser/blob/master/sources/fb... |
| |
chatGPZ
Registered: Dec 2001 Posts: 11390 |
A stub loader is easy to do - the challenge is to make it a single self contained binary :) |
| |
zzarko
Registered: Feb 2003 Posts: 77 |
Knowing the machine is knowing the address of the loaded program. Binary could be attached to similar BASIC code. A few more data lines could hold some adjusting values, like to where to copy binary part, and then to jump to that address. Binary part could even have machine-specific sub-parts and so on. No? |
| |
MagerValp
Registered: Dec 2001 Posts: 1078 |
Quoting chatGPZA stub loader is easy to do - the challenge is to make it a single self contained binary :)
My sample project above does that, although I was lazy and only did an 8-bit code relocator and the "program" is just inc $d020. But it's a single .prg that loads and runs on both C64 and C128. |
| |
Krill
Registered: Apr 2002 Posts: 2981 |
While this thread seems to degra^Wmorph into a code golf challenge, i need to re-emphasise that having a single binary run in both C-64 and native C-128 modes is a pointless exercise wrt actual real-life use-cases. =) |
| |
Martin Piper
Registered: Nov 2007 Posts: 726 |
I think the examples given above demonstrate real life use cases.
They are real applications, they have use...
A nice puzzle is to have the BASIC start with only a SYS <simple number>.
It's doable. |
| |
MagerValp
Registered: Dec 2001 Posts: 1078 |
True, you can just use SYS7181 and put startup code at two different offsets in the .prg.
And I disagree that it's useless, file browsers are a good example where it makes sense. Games though maybe not so much. |