Jump to content
IGNORED

Turning PLATOTerm Lite into 8k


Recommended Posts

I really want to try and make PLATOTerm able to load into more flash carts. Right now it's a 16K ROM, but I'd like to try and bank it into, e.g. SpartaDOS X, AtariMax 1mbit, etc.. so that it can be slammed onto more flash cartridges.

 

but I really have no idea where to start.

 

I do have a question for @flashjazzcat - What banking format is the Graphical OS bank on the U1MB? On a lark I tried to take my 16k image, and pad it out, unsuccessfully.. :)

 

-Thom

  • Like 1
Link to comment
Share on other sites

I'm having a hard time wrapping my head around the necessary changes to the linker, here's the config file that generates a 16k cart:

 

 

 
FEATURES {
    STARTADDRESS: default = $2000;
}
SYMBOLS {
    __CARTSIZE__:        type = weak,   value = $4000; # possible values: $2000 and $4000
    __CART_HEADER__:     type = import;
    __STACKSIZE__:       type = weak,   value = $0800; # 2k stack
    __STARTADDRESS__:    type = export, value = %S;
    __RESERVED_MEMORY__: type = export, value = $0000;
    __CARTFLAGS__:       type = weak,   value = $05;   # see documentation for other possible values
}
MEMORY {
    ZP:     file = "", define = yes, start = $0082,                size = $007E;
    MAIN:   file = "", define = yes, start = %S,                   size = __CARTSIZE__;
    ROM:    file = %O, define = yes, start = $C000 - __CARTSIZE__, size = __CARTSIZE__ - 6, fill = yes, fillval = $FF;
    CARTID: file = %O,               start = $BFFA,                size = $0006;
}
SEGMENTS {
    ZEROPAGE: load = ZP,              type = zp,                optional = yes;
    EXTZP:    load = ZP,              type = zp,                optional = yes;
    STARTUP:  load = ROM,             type = ro,  define = yes, optional = yes;
    LOWBSS:   load = MAIN,            type = bss,               optional = yes;  # not zero initialized
    LOWCODE:  load = ROM,             type = ro,  define = yes, optional = yes;
    ONCE:     load = ROM,             type = ro,                optional = yes;
    CODE:     load = ROM,             type = ro,  define = yes;
    RODATA:   load = ROM,             type = ro,                optional = yes;
    DATA:     load = ROM, run = MAIN, type = rw,  define = yes, optional = yes;
    INIT:     load = MAIN,            type = bss,               optional = yes;
    BSS:      load = MAIN,            type = bss, define = yes, optional = yes;
    CARTHDR:  load = CARTID,          type = ro;
}
FEATURES {
    CONDES: type    = constructor,
            label   = __CONSTRUCTOR_TABLE__,
            count   = __CONSTRUCTOR_COUNT__,
            segment = ONCE;
    CONDES: type    = destructor,
            label   = __DESTRUCTOR_TABLE__,
            count   = __DESTRUCTOR_COUNT__,
            segment = RODATA;
    CONDES: type    = interruptor,
            label   = __INTERRUPTOR_TABLE__,
            count   = __INTERRUPTOR_COUNT__,
            segment = RODATA,
            import  = __CALLIRQ__;
 

 

And here's one that generates "overlays" that could be used for bank switching (you can use a pragma to specify the current segment for the compiler):

 

 

FEATURES {
    STARTADDRESS: default = $2000;
}
SYMBOLS {
    __EXEHDR__:          type = import;
    __SYSTEM_CHECK__:    type = import;  # force inclusion of "system check" load chunk
    __AUTOSTART__:       type = import;  # force inclusion of autostart "trailer"
    __STACKSIZE__:       type = weak, value = $0800; # 2k stack
    __OVERLAYSIZE__:     type = weak, value = $1000; # 4k overlay
    __STARTADDRESS__:    type = export, value = %S;
    __RESERVED_MEMORY__: type = weak, value = $0000;
}
MEMORY {
    ZP:         file = "", define = yes, start = $0082,                size = $007E;
 
# file header, just $FFFF
    HEADER:     file = %O,               start = $0000,                size = $0002;
 
# "system check" load chunk
    SYSCHKHDR:  file = %O,               start = $0000,                size = $0004;
    SYSCHKCHNK: file = %O,               start = $2E00,                size = $0300;
    SYSCHKTRL:  file = %O,               start = $0000,                size = $0006;
 
# "main program" load chunk
    MAINHDR:    file = %O,               start = $0000,                size = $0004;
    MAIN:       file = %O, define = yes, start = %S + __OVERLAYSIZE__, size = $BC20 - __OVERLAYSIZE__ - __STACKSIZE__ - __RESERVED_MEMORY__ - %S;
    TRAILER:    file = %O,               start = $0000,                size = $0006;
 
# overlays
    OVL1:       file = "%O.1",           start = %S,                   size = __OVERLAYSIZE__;
    OVL2:       file = "%O.2",           start = %S,                   size = __OVERLAYSIZE__;
    OVL3:       file = "%O.3",           start = %S,                   size = __OVERLAYSIZE__;
    OVL4:       file = "%O.4",           start = %S,                   size = __OVERLAYSIZE__;
    OVL5:       file = "%O.5",           start = %S,                   size = __OVERLAYSIZE__;
    OVL6:       file = "%O.6",           start = %S,                   size = __OVERLAYSIZE__;
    OVL7:       file = "%O.7",           start = %S,                   size = __OVERLAYSIZE__;
    OVL8:       file = "%O.8",           start = %S,                   size = __OVERLAYSIZE__;
    OVL9:       file = "%O.9",           start = %S,                   size = __OVERLAYSIZE__;
}
SEGMENTS {
    ZEROPAGE:  load = ZP,         type = zp;
    EXTZP:     load = ZP,         type = zp,                optional = yes;
    EXEHDR:    load = HEADER,     type = ro;
    SYSCHKHDR: load = SYSCHKHDR,  type = ro,                optional = yes;
    SYSCHK:    load = SYSCHKCHNK, type = rw,  define = yes, optional = yes;
    SYSCHKTRL: load = SYSCHKTRL,  type = ro,                optional = yes;
    MAINHDR:   load = MAINHDR,    type = ro;
    STARTUP:   load = MAIN,       type = ro,  define = yes;
    LOWBSS:    load = MAIN,       type = rw,                optional = yes;  # not zero initialized
    LOWCODE:   load = MAIN,       type = ro,  define = yes, optional = yes;
    ONCE:      load = MAIN,       type = ro,                optional = yes;
    CODE:      load = MAIN,       type = ro,  define = yes;
    RODATA:    load = MAIN,       type = ro;
    DATA:      load = MAIN,       type = rw;
    INIT:      load = MAIN,       type = rw,                optional = yes;
    BSS:       load = MAIN,       type = bss, define = yes;
    AUTOSTRT:  load = TRAILER,    type = ro;
    OVERLAY1:  load = OVL1,       type = ro,  define = yes, optional = yes;
    OVERLAY2:  load = OVL2,       type = ro,  define = yes, optional = yes;
    OVERLAY3:  load = OVL3,       type = ro,  define = yes, optional = yes;
    OVERLAY4:  load = OVL4,       type = ro,  define = yes, optional = yes;
    OVERLAY5:  load = OVL5,       type = ro,  define = yes, optional = yes;
    OVERLAY6:  load = OVL6,       type = ro,  define = yes, optional = yes;
    OVERLAY7:  load = OVL7,       type = ro,  define = yes, optional = yes;
    OVERLAY8:  load = OVL8,       type = ro,  define = yes, optional = yes;
    OVERLAY9:  load = OVL9,       type = ro,  define = yes, optional = yes;
}
FEATURES {
    CONDES: type    = constructor,
            label   = __CONSTRUCTOR_TABLE__,
            count   = __CONSTRUCTOR_COUNT__,
            segment = ONCE;
    CONDES: type    = destructor,
            label   = __DESTRUCTOR_TABLE__,
            count   = __DESTRUCTOR_COUNT__,
            segment = RODATA;
    CONDES: type    = interruptor,
            label   = __INTERRUPTOR_TABLE__,
            count   = __INTERRUPTOR_COUNT__,
            segment = RODATA,
            import  = __CALLIRQ__;
}
Link to comment
Share on other sites

I'm totally unfamiliar with the CC65 linker, and I'd be reluctant to even attempt to port to a banked cartridge format software which wasn't written with banked cartridges specifically in mind from the outset. I found it to be quite a juggling act, although once you've done it once, it gets easier. Something as simple as ensuring code can always see the data it needs (i.e. that code isn't in one bank while the data is in the other) requires a bit of forethought (one method being to unpack all data into RAM first).

Edited by flashjazzcat
Link to comment
Share on other sites

I think the AtariMax carts are limited to $A000-$BFFF, but if you're not taking advantage of ROM banking anyway, you might as well just unpack the original EXE version from two or more arbitrary cartridge banks into RAM and then turn the cartridge off. The result would basically be an executable deliverable in cartridge form for people who prefer it that way.

  • Like 2
Link to comment
Share on other sites

Different approach: Use Exomizer/other packer to compress 8k to 16k and unpack upon start?

Not sure how well your binary will compress, for games and demos this usually works well.

 

 

And your program is not required to run as ROM.

Even if it does not fit into 8k this way, Atarimax Maxflash Studio can handle 16k cartridges, and it does it by using multiple banks.

So no need to fight limits...

Link to comment
Share on other sites

If you adopt the strategy I suggested and pack the unexpurgated EXE version into ROM and unpack it into RAM at runtime (then jump to the run address after turning off the cart ROM), only the unpacking module will have to worry about the cartridge banking method.

 

The only other method I would adopt is to go right back to the drawing board and re-write the application so that it scales easily to banked cartridges which occupy 8K banking windows. This would require a lot of time and effort, though, and since running the software directly from ROM does not appear to be functionally advantageous, I'd just go with option one.

 

Had you committed to using a banked cartridge right from day one, you could probably have avoided all the shrinkage methods you implemented over the past few months, since even a 128K banked cartridge would contain ample room for unrolled code and big lookup tables. Right now, though, I think it's best to take the path of least resistance.

Edited by flashjazzcat
  • Like 1
Link to comment
Share on other sites

Also XEX is the recommended format for Atarimax as it uses the banks like disk sectors and does normally not emulate ROMs.

 

>But only a MyIDE2 can run 16K ROMs flashed in this manner.

No. 16k carts are loaded to RAM like XEXs also on normal Atarimax carts.

  • Like 1
Link to comment
Share on other sites

I don't think there's a magical soluton which will be invoked by repeating the question. I expected you'd need to develop your own unpacker at least in order to accomplish exactly what you want on several different carts.

 

It's either that or completely redesign the thing to run in banked ROM. Or abandon the cart idea... Or motivate someone else to do it for you.

Link to comment
Share on other sites

For now, I'll just provide the 16K cart rom images, and I'm seeing if I can get enough bytes to squeeze the joystick and koala pad touch drivers together, and will revisit this.

 

I have had a flurry of people who have asked me, point blank, "I want this, but can I get it in a cartridge please?" so I am trying to do this.

 

-Thom

Link to comment
Share on other sites

One of my future experiments will be to literally ditch DOS altogether, and lay out the programs and driver on disk directly, and just do direct disk I/O (cc65 has an API called DIO, which on the Atari provides an abstraction for direct DCB/SIO access) So this may be a way forward, if I can cram the touch drivers, and R: handlers in one image that can be smashed onto a disk or flash cart effectively.

 

-Thom

Link to comment
Share on other sites

@Sanny I wanted to say thank you so much for adding the necessary patches to CC65 to allow cartridge ROMs to be created. It has made a version of PLATOTerm that pretty much will work anywhere. :)

 

I'm just reading that now. Thank you very much.

And it feels good that somebody is actually using it and my work was not just for the ivory tower...

 

regards,

chris

  • Like 1
Link to comment
Share on other sites

I'd love somebody to take what I've written and do a faster assembler version.

 

 

-Thom

Well I’ve poked around and converted a few routines and looked into tgi. An assembler version is certainly doable, but I’m a bit puzzled as to what would make the most sense. With all those integers and plotting, Platoterm looks like a good candidate for a 65816 version, but that’s probably low priority to you. I gather getting it into a cartridge is what you want, but that seems a bit limiting. If space is freed up by using assembler, maybe speed could be boosted by reintroducing some discarded lookup tables.

 

I’m not saying I’ll do it, but if I had a clear idea of what end product was desired, I might poke around for a while.

Link to comment
Share on other sites

Well I’ve poked around and converted a few routines and looked into tgi. An assembler version is certainly doable, but I’m a bit puzzled as to what would make the most sense. With all those integers and plotting, Platoterm looks like a good candidate for a 65816 version, but that’s probably low priority to you. I gather getting it into a cartridge is what you want, but that seems a bit limiting. If space is freed up by using assembler, maybe speed could be boosted by reintroducing some discarded lookup tables.

 

I’m not saying I’ll do it, but if I had a clear idea of what end product was desired, I might poke around for a while.

The feature set is pretty much stable. The last major addition would be to add a Micro TUTOR interpreter, which could take another 8 to 16k, which is why I looked heavily into cartridge form factor. This is very long term however, as I am having to do a ton of research and forensic analysis of the extant interpreter, which is written in Z80.

 

Sent from my SM-G920F using Tapatalk

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...