Jump to content
Sign in to follow this  
patjomki

Initialising RAM under ROM

Recommended Posts

Hi all,

 

I try to find a meaningful use for the RAM below the ROM of the ATARI 8-Bit computers as one of my programs in development needs more than 48K.

 

I can read and write to the RAM from adress $c000 and beyond so that is no problem (interrupt handling is a different story but to keep things easy just think about my program as if all interrupts are disabled).

 

Due to the fact that you can only use this part of the memory when the OS is OFF I want to fill this part of the RAM with additional level data, Player-Missile data, character sets etc. and copy it when necessary to a RAM area that can be used when the OS is ON.

 

But when I initiate the ram area with an org statement

 

----------------------------

   org $c000 ; RAM under ROM

 

  dta $01,$02,$03,$04 ; etc.

----------------------------

 

 

it is obvious that this cannot work because when I load my .xex file from DOS the OS is still ON. So one solution could be to fill my level data, Player-Missile data, character set to a different part of the memory ($8000 for example) then load my .xex file, switch the OS OFF, copy all the data from $8000... to $C000..., switch the OS ON again and load the data that was missing with OS loading commands to $8000...

 

Well, apart from the fact that this seems to be a little bit complicated it also just takes too much time to copy 16K of data and there is no advantage to reading additional level data etc. from disk later in the program.

 

So my idea is to have a little loader program that just switches OS OFF and loads 16K to $c0000... switches OS ON and reads the rest of the program but then again when there is no OS present how can I load the content of a file to a designated ram area? Or is there another solution?

Share this post


Link to post
Share on other sites

You can copy 16K (well, 14K) of code/data into the Shadow RAM in next to no time; this is exactly what The Last Word and Turbo BASIC XL do. I suggest you run the mainline code under the OS (copied there by INIT segments during the binary load process) and then use conventional RAM freely with the OS enabled (via wrapper code to handle NMIs, IRQs and calls to the CIO).

 

I started a thread about this exact matter a decade ago:

I learned a lot from the responses. :)

 

Edited by flashjazzcat
  • Like 2

Share this post


Link to post
Share on other sites

Well, actually I already read that thread (that's the reason why reading and writing to Shadow RAM is no problem) but couldn't find a solution for my task. The only thing I could find was:

 

On 12/30/2008 at 2:29 PM, Heaven/TQA said:

in the past I have loaded the stuff to main ram, switched off rom and then moved the stuff over...

 

To be honest I don't understand your idea of running the mainline program under the OS. Which INIT segments are necessary to enable that?

 

P.S.: Why only 14K?

Share this post


Link to post
Share on other sites

You intonated that you'd like to be able to read level data, etc, into the extra RAM. It makes sense, therefore, to keep the 'static' code/data (or as much of it as possible) where it's more difficult to get at: this allows one to access the lower 48K without any special techniques.

 

You would basically assemble your 'OS RAM' code in two chunks: a 4K chunk with the origin starting at $C000, and a 10K chunk starting at $D800. While the origin (i.e. the location counter) would reflect the address under the OS ROM, the LOAD addresses of both segments would be much lower in memory, below the OS. Let's say your 4K segment loads at $4000. You follow that with an INIT segment which turns off the OS and copies that 4K of code to $C000-CFFF, before re-enabling the OS and allowing the binary load to continue. You would do the same with the 10K segment. The move routine could be loaded via an earlier segment and called with argments via small INIT segments. Finally, you install your CIO/interrupt wrapper code, turn off the OS, and jump into your start address. This is how The Last Word works, at least, although it also stores some code in the $2000-$3xxx area.

 

Instead of calling the CIO directly, all your program (under the OS) needs to do is call the CIO wrapper which first enables the OS, calls CIOV, disables the OS and returns with the CIO status code. Interrupts are transparently handled in a similar manner using code which I think was posted in that older thread.

 

You'll only be able to access 14K under the OS since 2K of it is occupied by hardware registers. It's impossible to access the 2K of RAM under that area without the 'MAPRAM' mod, which is basically useless since hardly any machine has it. Other devices such as Ultimate 1MB are able to access that RAM, but it's not normally accessible via software.

 

Edited by flashjazzcat
  • Like 2

Share this post


Link to post
Share on other sites
35 minutes ago, patjomki said:

Well, actually I already read that thread (that's the reason why reading and writing to Shadow RAM is no problem) but couldn't find a solution for my task. The only thing I could find was:

 

 

To be honest I don't understand your idea of running the mainline program under the OS. Which INIT segments are necessary to enable that?

 

P.S.: Why only 14K?

 

11 years ago??? Jesus Christ... how long I am hanging here around... 

 

14k because not like C64 Atari does not have RAM in IO area means d000-d7ff (for code/data) so we have a 62kb machine and not a 64kb one ;).

 

well... what you can do

is something (untested writing on phone).

 

org $0600

Movedata

Wait lda 14

cmp 14

beq wait

 

sei

lda #0

sta d40e

lda #fe

sta d301

 

now rom is gone

 

do your data copy here to upper ram

 

lda #ff

sta d301

lda #40

sta d40e

cli

rts

 

org 2e2

ini movedata

 

all values in hex.

 

 

 

 

Edited by Heaven/TQA
  • Like 2

Share this post


Link to post
Share on other sites

Regarding 14K: Understood. $d000-$d7ff is unavailable on a stock machine.

 

So I can have an area from $c000-$cfff (4K chunk) and an area from $d800-$fff9 (~10K chunk as the last 6 bytes are where the interrupt routines are located).

 

What I do not get: What is the advantage of loading e.g. level 2 (14K) of my game to $4000, moving 4K to $c0000 and 10K to $d800, then load level 1 (14K) again to $4000 and finally start my game instead of loading only level 1 (14K) to $4000 and when I reach level 2 load the next level data (14K) to $4000 from disk?  

 

@heaven: why do you wait until $14 (RTCLOK) indicates that a vbl occured (in Movedata)?

Share this post


Link to post
Share on other sites

I'm suggesting you keep code, not level data, under the OS. Then you can just burst read your levels into - say - $4000-$7FFF without having to move anything at all. The program code gets moved under the OS once and stays there. It would seem to greatly simplify the management of dynamic data being loaded from disk.

 

 

 

  • Like 1

Share this post


Link to post
Share on other sites
37 minutes ago, patjomki said:

Regarding 14K: Understood. $d000-$d7ff is unavailable on a stock machine.

 

So I can have an area from $c000-$cfff (4K chunk) and an area from $d800-$fff9 (~10K chunk as the last 6 bytes are where the interrupt routines are located).

 

What I do not get: What is the advantage of loading e.g. level 2 (14K) of my game to $4000, moving 4K to $c0000 and 10K to $d800, then load level 1 (14K) again to $4000 and finally start my game instead of loading only level 1 (14K) to $4000 and when I reach level 2 load the next level data (14K) to $4000 from disk?  

 

@heaven: why do you wait until $14 (RTCLOK) indicates that a vbl occured (in Movedata)?

 

I wait til a VBL occured just to be on the save side when switching OS off and setting I flag etc 

Share this post


Link to post
Share on other sites

@Heaven: Thanks for the explanation of your wait code. Another question regarding custom font: When OS is OFF $2f4 (CHBAS) and $d409 (CHBASE) do not work. So you first have to copy your font data back to a memory location in the first 48K to use your font (and switch OS ON of course)?

 

@flashjazzcat: Ah, think I finally understood. Supposed my program code does not exceed ~14K and I put it into shadow ram below the OS I have the normal ram for pure data (48K minus zeropage minus page 1 (stackpage)), right?

 

What about pages 2 to 6 ($200 - $6ff)? I think I can use them similar to ram areas $c000... and $d800... as long as the OS is OFF? And what about page 7 ($700 to ???) and beyond where DOS is located?

Share this post


Link to post
Share on other sites
12 minutes ago, patjomki said:

Supposed my program code does not exceed ~14K and I put it into shadow ram below the OS I have the normal ram for pure data (48K minus zeropage minus page 1 (stackpage)), right?

Exactly so. My word processor has about 20K of code, but I simply placed some of it at $2000 (Turbo BASIC XL is arranged in a very similar way). The text buffer spans the entire extended banking window at $4000-7FFF and the program reads and writes files using DOS as if everything were normal. :)

 

Indeed your font data will need to be stored somewhere else unless you happen to use an exact copy of the ROM font and want to store it at the exact same address, but in RAM.

 

If the OS is not needed, all of page zero and everything from $200 and beyond is yours (and even the lower part of the stack). If you use the OS but don't need DOS, everything from $600 and beyond is free. You may also use the entire upper half of page zero if you don't need to call the floating point math library. $400-$5FF are OS line input and printer buffers and can be used as a temporary scratch area if you really need the space. If you want the OS and DOS, best to load at $2000.

 

Edited by flashjazzcat
  • Like 3

Share this post


Link to post
Share on other sites

It was mentioned here and in other posts how to use RAM under ROM, but for me, it is still a struggle. I did some tests but all failed. Mad Pascal includes some examples (for example PacMad and MadKingdom, great games, btw) that show the way how it is done for the purposes of each game.

 

I am in the making of a game which currently uses graphics mode 15 screens. I will migrate screen data to Antic mode 4 layout later, now I am just making a mockup version. I developed my own way to compress 160*192 data so more images can be put in available RAM. In Mad Pascal I use resource files (RCDATA and RCASM) linked to memory address to show screens. To make more interesting scenes I need more space for my data.

So, I would be more than grateful for a very simple working example in Mad Pascal for putting screen bytes in memory locations starting at $C000 or $d800 and reading them back to show a screen using this data. No special DLIs or VBI.

Thanks!

 

Edited by Gury

Share this post


Link to post
Share on other sites
17 hours ago, sanny said:

You could use cc65's "atarixl" target 😊

Sorry I neither use cc65 nor Mad Pascal. Plain mads/wudsn. 😀

Share this post


Link to post
Share on other sites

I didn't mean you should write your program in C. If you could live with ca65 (the assembler included in cc65) instead of mads, you could write a main() Program in C which does nothing more than calling your assembler routine. You would have the memory under the ROM directly accessible. Some caveats exist, bunt in general that's the case.

Edited by sanny
typo

Share this post


Link to post
Share on other sites
50 minutes ago, flashjazzcat said:

This is all much, much easier in assembly language if you're already adept in 6502, IMHO.

 

A response to what exactly is this?

Share this post


Link to post
Share on other sites
8 minutes ago, flashjazzcat said:

Any suggestion of turning to a higher level language.

 

Yup.... esp. when switching off OS...

Share this post


Link to post
Share on other sites
3 minutes ago, sanny said:

Nobody (at least not I) suggested that.

Yep: I read your clarification. But just taking the bull by the horns and figuring out how to organise one's code under the OS in MA65 is preferable, IMHO, for someone already heavily invested in MADS than delegating the job to a CC65 linker profile and obfuscating a lot of the complexity. This is my generalised opinion on the matter and I wasn't attempting to directly gainsay your suggestion, however. I don't want a quarrel about it either.

 

Share this post


Link to post
Share on other sites

"MA65"? IDK it.

 

But sure, everyone has his opinion and his way to tackle problems. cc65 linker scripts are difficult at the beginning, and then a "breeze". That's my opinion, others might disagree.

 

I just wanted to give the OP another option. And, of course, I'm biased, since I wrote the support for the "atarixl" target in cc65.

  • Like 1

Share this post


Link to post
Share on other sites
15 hours ago, sanny said:

"MA65"? IDK it.

LOL. I meant MADS. MA65 is the Macro Assembler I wrote in the 1990s. Perhaps I have a subconscious bias too. :)

 

I appreciate there's more than one way to shell a nut. MADS has its own linking facilities as well (I wrote a symbolic linking loader for the WIP GOS which uses MADS' relocatable binaries as executables), but I never played with them.

Share this post


Link to post
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.

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...
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...