Jump to content
  • 0
Stefan

Howto get banked RAM size

Question

Hi,

I'm working on X16 Edit, a text editor. There's a thread in Software Library Chat discussing the program in depth. My program uses banked RAM to store text that's edited.

However, I have a general question regarding the hardware.

It's said that the final product will have banked RAM of 512 KB expandable to 1 MB, 1.5 MB or 2 MB (by populating 1, 2 or 3 sockets).

Is there a way for a program to determine what memory banks are actually available?

If there is no other option, would it be possible to write a routine that tests certain memory addresses by first writing values and then reading them back?

I guess that approach could work, but it depends on what the hardware does when you access an unpopulated address in banked RAM.

A test routine would probably work if the data bus floats (returning a random value) or if it's tied high or low (returning ff or 00).

Share this post


Link to post
Share on other sites

22 answers to this question

Recommended Posts

  • 0

You can set the carry flag and then call memtop at $ff99.  This will return the number of ram banks on A and a pointer to the top of memory in X and Y.  Keep in mind that bank 0 is used by the kernal, so really only 1 on are free.

  • Thanks 1

Share this post


Link to post
Share on other sites
  • 0

At present, you have to write to a memory cell and read its value back. If you assume you can take over all of upper memory (not necessarily a safe assumption), then you will need to write at least 3 values to each bank and then read them back.

What I'd probably do is write $00, $FF, bankno to each bank, then cycle back through and read them back. Every bank that gives you back the correct value has RAM in it. 

You may also be able to shorten the test by just testing banks 64, 128, and 192, since the banked memory consists of 4 512K chips.

 

 

  • Like 1

Share this post


Link to post
Share on other sites
  • 0

MEMTOP does not appear to work in the emulator, at least. You will need to simply test the higher banks. Bank 65 is a safe one, as it will be a mirror of bank 1 if there is only 512k (64 banks). Bank 64 will be a mirror of bank 0, so you don't want to mess with that without knowing first. So, I made this simple BASIC program that tells you (it would be similarly trivial to check at the beginning of an assembly program):

image.png.d874bdfcbeb85bec48483a2a6948659e.png

Here you can see that I poked the value 42 to the top of bank 65, then zero to the top of bank 1. Going back to bank 65, if it's no longer 42, then I know it was overwritten by the poke to bank 1, which it simply mirrors in the 512k configuration. If it was still 42 (as you can see in the screencap, it wasn't), then you can assume that all 256 banks are installed. AFAIK, there is no intention of having an in-between configuration (e.g. 1MB/128 banks).

Share this post


Link to post
Share on other sites
  • 0
7 minutes ago, SlithyMatt said:

AFAIK, there is no intention of having an in-between configuration (e.g. 1MB/128 banks).

Don't trust that, as people can install their own memory modules. 

Share this post


Link to post
Share on other sites
  • 0
10 minutes ago, SlithyMatt said:

MEMTOP does not appear to work in the emulator, at least.

In what way? I just tested it and it seems to work for me.

Share this post


Link to post
Share on other sites
  • 0
10 minutes ago, Ender said:

In what way? I just tested it and it seems to work for me.

The code that I see when debugging R38 pre-built for Windows shows MEMTOP just being a function that reads from three memory addresses, which are all zero for me. Maybe if you use an earlier release or build from code it works?

Share this post


Link to post
Share on other sites
  • 0

This is with R38 right after returning from $ff99.  You can see that $40 is in A.

Screenshot_1.png

Share this post


Link to post
Share on other sites
  • 0
Posted (edited)

Yep, I just get all zeros. Did you build the emulator yourself?

UPDATE: I restarted the emulator, and now it's working for me. It seems that MEMTOP is fragile, and may not work after running other programs.

Edited by SlithyMatt
update
  • Like 1

Share this post


Link to post
Share on other sites
  • 0

P.S. The memory addresses MEMTOP returns are at $0259-$025B, which get put into X, Y, and A, respectively. So really, you can just peek at $025B for the bank count, but that address is subject to change with later ROM revisions, but MEMTOP should always be placed in the jump table at $FF99.

Share this post


Link to post
Share on other sites
  • 0

OK. I will use MEMTOP. It seems to work in emulator r38 on macOS. 

One more question though.

That Kernal function returns the number of banks, for instance $40 (64) with banks 0-$3f populated.

What will it return if all banks are populated? I suppose it might wrap around to zero.

Share this post


Link to post
Share on other sites
  • 0
Posted (edited)

Good question. I just tested it with starting the emulator with "-ram 2048" and yeah, it looks like it returns 0.

Edited by Ender
  • Like 1

Share this post


Link to post
Share on other sites
  • 0
5 hours ago, Ender said:

Good question. I just tested it with starting the emulator with "-ram 2048" and yeah, it looks like it returns 0.

Just to try it out, I tested it with 1024 and got $80, and then attempted to run with zero banked RAM, but the emulator didn't allow that. I think it's a safe assumption that nobody is going to entirely de-populate the banked RAM and then expect any software to actually work, including the kernal and BASIC, which depend on bank 0 to be present. So, 0 = 2MB should be a safe assumption for the programmer.

  • Like 1

Share this post


Link to post
Share on other sites
  • 0
Posted (edited)

I wasn't aware of the -ram option.

I don't think it's mentioned in the emulator docs. But I can see it's in the emulator -help.

The emulator seems to accept any -ram value dividable by 8 between 8 K and 2048 K.

However, as I understand, the hardware will have four memory IC slots of 512 K each, and the only possible values in real life would then be 512, 1024, 1536 and 2048 K.

Maybe the best solution is to support all memory size options available in the emulator, even though only four of those options will be supported by the hardware.

Edited by Stefan

Share this post


Link to post
Share on other sites
  • 0
16 hours ago, Stefan said:

I wasn't aware of the -ram option.

I don't think it's mentioned in the emulator docs. But I can see it's in the emulator -help.

The emulator seems to accept any -ram value dividable by 8 between 8 K and 2048 K.

However, as I understand, the hardware will have four memory IC slots of 512 K each, and the only possible values in real life would then be 512, 1024, 1536 and 2048 K.

Maybe the best solution is to support all memory size options available in the emulator, even though only four of those options will be supported by the hardware.

This *should* do the job... I suppose I should go test it. 🙂

;
; MEMTEST
; Returns highest upper memory bank in A
; Preserves: None
;
MEMVAL = $AA ; 1010 1010 pattern. 
MEMTEST:
STZ $01   ; Set bank 1. Bank 0 is used by the KERNAL, so don't mess with it.
MEMTEST1:
LDA #MEMVAL  ; 1010 1010 pattern
STA $A000
LDA $A000
CMP #MEMVAL
BNE MEMFAIL
INC $00
JNZ MEMTEST1
LDA #$FF;
RTS  ; The full 2MB is available
; This bank failed. So subtract 1 and return the last bank that succeeded. 
MEMFAIL:
DEC $00 ; Select the previous bank, which passed
LDA $00 ; Get the selected bank
RTS  ; Returns the last available bank





 

 

Share this post


Link to post
Share on other sites
  • 0
On 10/4/2020 at 5:26 AM, TomXP411 said:

This *should* do the job... I suppose I should go test it. 🙂

;
; MEMTEST
; Returns highest upper memory bank in A
; Preserves: None
;
MEMVAL = $AA ; 1010 1010 pattern. 
MEMTEST:
STZ $01   ; Set bank 1. Bank 0 is used by the KERNAL, so don't mess with it.
MEMTEST1:
LDA #MEMVAL  ; 1010 1010 pattern
STA $A000
LDA $A000
CMP #MEMVAL
BNE MEMFAIL
INC $00
JNZ MEMTEST1
LDA #$FF;
RTS  ; The full 2MB is available
; This bank failed. So subtract 1 and return the last bank that succeeded. 
MEMFAIL:
DEC $00 ; Select the previous bank, which passed
LDA $00 ; Get the selected bank
RTS  ; Returns the last available bank





 

 

I think there might be a problem with this solution.

When you go beyond the last bank, it will first mirror bank 0, as @SlithyMatt pointed out above. For instance, if 64 banks are populated (bank 0-63), bank 64 will mirror bank 0.

I think your code will overwrite at least one byte of bank 0 that is used by the Kernal before you know that you have reached end of banked RAM, which is not a safe thing to do.

If you're going down the memory test lane, you might succeed by backing up the value of bank 0 address $A000, and restore it after the memory test is finished.

Or you may go easy on yourself and use the Kernal function 🙂

  • Like 1

Share this post


Link to post
Share on other sites
  • 0
Posted (edited)
On 10/5/2020 at 12:31 PM, Stefan said:

When you go beyond the last bank, it will first mirror bank 0, as @SlithyMatt pointed out above. For instance, if 64 banks are populated (bank 0-63), bank 64 will mirror bank 0.

I don't think anyone has explained why that would be... if the chips aren't populated on the board, then the lines will float and either have random values, be all zero, or be all one. There's no mechanism I can think of for reads and writes to "mirror" lower banks. To actually write to a chip, the CS line must be set for that socket, and the CS for the first RAM chip would not be set if you're writing to bank 64.

If the emulator is doing that now, I'm going to pin that down as an emulator bug, rather than the correct behavior of the final board.

Of course, if all 256 banks are populated, the test does not actually write to 0. It falls past the JNZ MEMTEST1 and sets the top bank to $FF. 

as to using MEMTOP... @SlithyMatt explained above that it doesn't always work. 

 

Edited by TomXP411
  • Like 1

Share this post


Link to post
Share on other sites
  • 0
2 hours ago, TomXP411 said:

as to using MEMTOP... @SlithyMatt explained above that it doesn't always work. 

About that, I figured out what I was doing wrong. If you call MEMTOP with the carry bit clear, it will permanently blow away the values in RAM and replace them with whatever you have in A,X,Y. Just make sure you always do a SEC beforehand, and you should be good. Of course, you can't depend on another program not blowing it away before your program is run, so you may need to do a RAM test in that case or just document your requirement for the X16 to be reset prior to loading your program.

Share this post


Link to post
Share on other sites
  • 0
Posted (edited)
18 minutes ago, SlithyMatt said:

If you call MEMTOP with the carry bit clear, it will permanently blow away the values in RAM and replace them with whatever you have in A,X,Y. 

Right.  MEMTOP doubles as a READ MEMTOP and SET MEMTOP based on CC.  MEMBOT is similar...

Edited by rje

Share this post


Link to post
Share on other sites
  • 0
2 hours ago, TomXP411 said:

I don't think anyone has explained why that would be... if the chips aren't populated on the board, then the lines will float and either have random values, be all zero, or be all one. There's no mechanism I can think of for reads and writes to "mirror" lower banks. To actually write to a chip, the CS line must be set for that socket, and the CS for the first RAM chip would not be set if you're writing to bank 64.

If the emulator is doing that now, I'm going to pin that down as an emulator bug, rather than the correct behavior of the final board.

Of course, if all 256 banks are populated, the test does not actually write to 0. It falls past the JNZ MEMTEST1 and sets the top bank to $FF. 

as to using MEMTOP... @SlithyMatt explained above that it doesn't always work. 

 

The behavior of ramtas, which is what initializes memory and detects the number of banks and reports the total memory at bootup, seems to rely on it working this way.  If it doesn't work on actual hardware, wouldn't they have seen it in their testing?

Share this post


Link to post
Share on other sites
  • 0
On 10/7/2020 at 1:43 AM, TomXP411 said:

I don't think anyone has explained why that would be... if the chips aren't populated on the board, then the lines will float and either have random values, be all zero, or be all one. There's no mechanism I can think of for reads and writes to "mirror" lower banks. To actually write to a chip, the CS line must be set for that socket, and the CS for the first RAM chip would not be set if you're writing to bank 64.

If the emulator is doing that now, I'm going to pin that down as an emulator bug, rather than the correct behavior of the final board.

Of course, if all 256 banks are populated, the test does not actually write to 0. It falls past the JNZ MEMTEST1 and sets the top bank to $FF. 

as to using MEMTOP... @SlithyMatt explained above that it doesn't always work. 

 

I agree that it's unlikely that the hardware chip select wraps around to skip unpopulated memory. At the beginning of this thread, I also assumed that we would see random, ff or 0 on the data bus when reading unpopulated memory. I guess we just have to wait and see when the board is done. Reading a recent post by @Lorin Millsap elsewhere on this site, it is a work in progress. Maybe the Board works in mysterious ways 🙂

Share this post


Link to post
Share on other sites
  • 0

On that, the RAM works perfectly.

For unpopulated chips there is no wrap around or skip. Reads from unpopulated chips will give erratic results, mostly random residual values.

To check how much ram is present you need to write a non-random sequence then attempt to read that sequence back. If the sequence returned matches the sequence written that RAM is populated. Otherwise it is either unpopulated or there is a fault.


Sent from my iPhone using Tapatalk

  • Like 2
  • Thanks 1

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
Answer this question...

×   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.


×
×
  • Create New...

Important Information

Please review our Terms of Use