Page 2 of 4

XC16 Memory location bank 0 address $A000 till $A7FF

Posted: Sun Mar 27, 2022 4:51 am
by Scott Robison


On 3/26/2022 at 10:28 PM, svenvandevelde said:




So is this space between A000 and A7FF not available due to hardware defined addressing? (address line logic on the board).









 



No, the space between $9F00 and $9FFF is IO space, so loading into it is not possible (whether because the kernal disallows it or it just corrupts IO space by overwriting it). You can load into $A000-$BFFF but it must be a separate load from a load into the main system memory.

Bank 0 of high RAM is just reserved by the system, and if you overwrite it you do so at your own risk. Bank 1 and higher are available.


XC16 Memory location bank 0 address $A000 till $A7FF

Posted: Sun Mar 27, 2022 9:23 am
by svenvandevelde


On 3/27/2022 at 6:51 AM, Scott Robison said:




No, the space between $9F00 and $9FFF is IO space,



Thank you. The documentation of the CX16 actually writes it and I oversaw this. It is clear for me now. Strange that the IO space is at such low area in memory. Was this done by design?

And also, I had been noticed that A800 till BFFF was available for use in bank 0 in an earlier post ...


 


XC16 Memory location bank 0 address $A000 till $A7FF

Posted: Sun Mar 27, 2022 12:27 pm
by rje


On 3/27/2022 at 4:23 AM, svenvandevelde said:




Strange that the IO space is at such low area in memory. Was this done by design?



It was -- I seem to remember 8-Bit-Guy's second video laying out his suggested "flat + banks" memory model.

 

The constraints worked like this:  the design allows a banked 16K block to switch out "KERNAL + BASIC ROM", so that's $C000 to $FFFF.  In retrospect that is a smart and potentially useful move.

Then he has the 8K banked RAM window.  That's $A000 to $BFFF.

The only room left for I/O is either high or low main RAM, because he didn't want to bank that.

 

Here:  at time index 7:16 in his video 





 

1506464047_ScreenShot2022-03-27at7_30_34AM.png.34f003aeee78154466f51c199cf14eeb.png

 


XC16 Memory location bank 0 address $A000 till $A7FF

Posted: Sun Mar 27, 2022 12:36 pm
by rje


On 3/27/2022 at 4:23 AM, svenvandevelde said:




Strange that the IO space is at such low area in memory. Was this done by design?



 

At the time of that video, I wonder if the system used Bank 0 yet?

If not.... I wonder if I/O could be shoved into an upper slice of Bank 0.

On the other hand, that would make I/O less friendly.  Although it could enable a 256 byte window into VERA.


XC16 Memory location bank 0 address $A000 till $A7FF

Posted: Sun Mar 27, 2022 12:56 pm
by BruceMcF


On 3/27/2022 at 5:23 AM, svenvandevelde said:




Thank you. The documentation of the CX16 actually writes it and I oversaw this. It is clear for me now. Strange that the IO space is at such low area in memory. Was this done by design?



And also, I had been noticed that A800 till BFFF was available for use in bank 0 in an earlier post ...



First, the second point: None of that is guaranteed to stay free. As they add functionality to the Kernel, they are free to use any of that space. So relying on any of that being free will break your program if/when they use more of that space. And note, that could be AFTER release, when they fix a bug that comes to their attention!

Also on the second point, if the use of Bank0 was an issue, just switch to Bank1, Bank2, Bank3 (repeat 255 times) and the problem would have gone away, so redesigning the Bank0 layout to allow it would be totally unnecessary.

On the first point, yes, it was by design.

When it was decided to go with a 64K memory map with a 16KB ROM window an 8KB High RAM window, and a page of I/O divided into 8 32byte spaces, ROM with a 6502 typically needs to include the interrupt vectors in the $FFxx page, so the 16KB ROM window is in $C000-$FFFF. The $00xx page and $01xx page are the zero page and hardware stack, so the beginning of the memory map is Low RAM. And so the 8KB HighRAM window and 256 byte I/O page are at $A000-$BFFF and $9F00-$9FFF respectively to give the largest contiguous Low RAM.

Being able to use ANY High RAM bank for a program in Low RAM to overflow into was never an objective. The intended use of HighRAM was for extended data space, so that more of the LowRAM is available for program space.

Now, a couple of year ago, several of us were on FB arguing that the I/O page should be at $0400. $0000-$00FF is zero page, $0100-$01FF is the stack page, the CBM Kernel and Basic make heavy use of $0200-$03FF, but $0400-$07FF was the default text screen, which Vera made redundant, so it would have eliminated the "barrier" between LowRAM and HighRAM.

However, even using HighRAM for program space, using it as "overflow" ONLY allows ONE to be used! It opens up MANY more possibilities to package modules so that they fit into 8KB of RAM (possibly multiple modules in the same one), and have MULTIPLES of 8KB modules that can all be resident and can all be called from the same "master" code in LowRAM. The "overflow into HighRAM" option only increases program RAM from 30KB to 38KB ... 26% more space. Making 8 "packages" of 8KB modules increases program RAM from 30KB to 94KB ... 213% more space! And plenty more where that came from!

In Assembly, that is pretty natural, since you don't program such a large assembly language as one long program, you program in functional pieces and include them.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

A little bit about why they said $04xx as I/O page was "harder" back then.

Consider Ben Eater's breadboard 6502 board, with a single quad NAND chip used for selecting RAM, ROM and I/O, with (for example), three VIA's and three ACIA's possible with room to spare:


  • /ROM_CS = NAND(A15,A15)


  • /ROM_OE = /ROM_CS


  • /RAM_CS = NAND(PHI2,/ROM_CS)


  • /RAM_OE = A14


  • /IO_CS = NAND(A14,/CS_ROM)


  • VIA1_C0 = A13


  • VIA2_C0 = A12


  • VIA3_C0 = A11


  • ACIA1_C1 = A10


  • ACIA2_C1 = A9


  • ACIA3_C1 = A8


This gives the 32K ROM from $8000-$FFFF, 16KB of RAM at $0000-$3FFF, and IO in the $4000-$7FFF space. It could be brought closer to the CX16 memory map using the fourth NAND on the Quad NAND:


  • /ROM_CS = NAND(A15,A14)


  • /ROM_OE = /ROM_CS


  • /A15 = NAND(A15,A15)


  • /RAM_CS = NAND(PHI2,/A15)


  • /RAM_OE = A15


  • /IO_CS = NAND(/RAM_CS,/ROM_CS)


  • VIA1_C0 = A13


  • VIA2_C0 = A12


  • VIA3_C0 = A11


  • ACIA1_C1 = A10


  • ACIA2_C1 = A9


  • ACIA3_C1 = A8


Now, RAM is $0000-$7FFF, ROM is $C000-$FFFF, and I/O is $8000-$BFFF. But I/O select is three logic layers deep, so if you are trying to run at 8MHz and that is pressing any of your I/O close to its limit, that could be a problem. That can be fixed by used a dual 2 to 4 active low decoder/demultiplexer, a 74xx156, which has two inputs, A and B, two sets of outputs, 1Y1-1Y3 and 2Y1-2Y3 and two sets of strobe inputs, G1 and G2, and data inputs, C1 and C2, where to select a set of outputs,  G1 & G2 must be low, while C1 must be high for its set and C2 must be low for it's set. If you tie the strobes together and the data inputs together, you have a 3 to 8 decoder. So invert Phi2 and tie that to Strobe, tie A15 to C1 ad C2, A14 to A and A13 to B, and you have eight selects, each one selecting an 8KB space, so, say, $8000-$9FFF could be I/O, and $A000-$BFFF could select a second "data bank" RAM, getting it's address lines above A12 from some VIA port B lines. If you have 32KB ROMs and 32KB RAMs, you could have:


  • /ROM_CS = NAND(A15,A14)


  • /ROM_OE = /ROM_CS


  • ROM_A14 = VIA1_PB5


  • /A15 = NAND(A15,A15)


  • /RAM1_CS = NAND(PHI2,/A15)


  • /RAM1_OE = A15


  • DECODE_G1 = DECODE_G2 = NAND(PHI2,PHI2)


  • DECODE_C1 = DECODE_C2 = A15


  • DECODE_A = A14


  • DECODE_B = A13


  • /IO_CS = DECODE_1Y0


  • /RAM2_CS = /RAM2_OE = DECODE_1Y1


  • RAM2_A14 = VIA1_PB4


  • RAM2_A13 = VIA1_PB3


  • VIA1_C0 = A12


  • VIA2_C0 = A13


  • VIA3_C0 = A10


  • ACIA1_C1 = A9


  • ACIA2_C1 = A8


  • ACIA3_C1 = A7


And have LowRAM at $000-$7FFF, I/O in $8000-$9FFF, HighRAM at $A000-$BFFF, and ROM at $CFFF-$FFFF.

Now, that's just a "poor man's" version of the CX16 memory map. The actual CX 16 doesn't have the sparse I/O space, but eight "spaces" in a single page, so there is another 3 to 8 decode going on, and a narrowing down to a page in the 8KB I/O range. And the LowRAM extends right up to $9EFF, so it's CS and OE are more complex than above. But it might give a clue as to why they were arguing that $9Fxx was easier address decoding than $04xx would have been.


XC16 Memory location bank 0 address $A000 till $A7FF

Posted: Sun Mar 27, 2022 12:59 pm
by BruceMcF


On 3/27/2022 at 8:36 AM, rje said:




 



At the time of that video, I wonder if the system used Bank 0 yet?



If not.... I wonder if I/O could be shoved into an upper slice of Bank 0.



On the other hand, that would make I/O less friendly.  Although it could enable a 256 byte window into VERA.



You wouldn't put the I/O in a Bank ... then you would have to include the contents of the RAM Bank register in the RAM /OE logic, because RAM output cannot be enabled at the same time as IO or there will be bus contention when an I/O device is read.


XC16 Memory location bank 0 address $A000 till $A7FF

Posted: Sun Mar 27, 2022 2:04 pm
by svenvandevelde

@BruceMcF Thank you for your extensive answer. It was very clarifying and a very interesting read.


On 3/27/2022 at 2:56 PM, BruceMcF said:




Now, a couple of year ago, several of us were on FB arguing that the I/O page should be at $0400.



You are right, moving IO into banked ram is not a good idea, and indeed, the alternative would have been to move I/O totally to the front.

It makes a lot of sense to move I/O to address $0400. But would that not have had side effects to the CX16 compatibility of the C64 programs written in BASIC?


On 3/27/2022 at 2:56 PM, BruceMcF said:




A little bit about why they said $04xx as I/O page was "harder" back then.



I am going to read the detailed explanation in a very detailed manner, as this information is extremely interesting to learn.

It is amazing how I am now also starting to understand how actually the C64 hardware worked, address lines etc, and how the addresses were "calculated".

And what you've written is very interesting to analyze and trying to understand. I never learned electronics, you see.

Sven

 


XC16 Memory location bank 0 address $A000 till $A7FF

Posted: Sun Mar 27, 2022 2:13 pm
by BruceMcF


On 3/27/2022 at 10:04 AM, svenvandevelde said:




@BruceMcF Thank you for your extensive answer. It was very clarifying and a very interesting read.



[1] You are right, moving IO into banked ram is not a good idea, and indeed, the alternative would have been to move I/O totally to the front.

It makes a lot of sense to move I/O to address $0400. But would that not have had side effects to the CX16 compatibility of the C64 programs written in BASIC?



[2] I am going to read the detailed explanation in a very detailed manner, as this information is extremely interesting to learn.

It is amazing how I am now also starting to understand how actually the C64 hardware worked, address lines etc, and how the addresses were "calculated".

And what you've written is very interesting to analyze and trying to understand. I never learned electronics, you see.



Sven



[1] $0400-$07FF was the text mode display screen, so with Vera instead of the VIC-II that area is redundant. Basic relied on the KERNAL for those hardware details, and the parts of the C64 KERNAL that used it have already been modified in the CX16.

[2] I always wanted to have a try at tinkering with hardware on the C64 User Port, but when I had the time, I didn't have the money, and visa versa, so I never had a chance to ... but I did for a time have access to a University library that some good 74xxyyy glue logic databooks, so I drew up more than a few fantasy circuits. It was only later reading forums at 6502.org and discussion by Garth Miner at his site that I found out how little I knew about the games you could play with glue logic.

I think one way to get from the above to the actual CX16 memory map (not saying this is the circuit that the CX16 uses!) uses an octal (8bit) inverter and two more 3 to 8 decoders:


  • Run A8-A12 through the inverter, and "wire them together" in a wired or, along with the /IO_CS above. Wired-ORs are cheap, but they are tricky, since the load they will take when they are high depend on how many high signals are included. Anyway, then when A8-A12 is high, the inverted values will be low (and the inverter will isolate the address lines from the wiring together), and when the inverted values AND the $8000-$9FFF output from the 1st decoder are all low, that will be low.


  • Run that as the strobe into the second decoder, and feed A7, A6 and A5 into C1=C2, A and B, and you have eight I/O select lines in $9F00-$9F1F, $9F20-$9F3F,...,$9FE0-$9FFF.


  • Run Phi2 through another one of the inverter lines and use that as Low RAM chip select, /RAM1_CS. An inverter has a low delay, so that puts very little delay between PHI2 rising and /CS falling.


  • For the /RAM1_OE, use the third decoder as an arbitrary 3 input to 1 output logic chip. Feed /ROM_CS, /RAM2_CS and /DECODE2_G1 (the strobe for the IO page decoder) into C1=C2, A and B, and the low output when all three are high is the /RAM1_OE, so there is no contention between LowRAM and IO, Low_RAM and HighRAM, and LowRAM and ROM.


 

 


XC16 Memory location bank 0 address $A000 till $A7FF

Posted: Sun Mar 27, 2022 10:51 pm
by Scott Robison


On 3/27/2022 at 3:23 AM, svenvandevelde said:




And also, I had been noticed that A800 till BFFF was available for use in bank 0 in an earlier post ...



It is available at this instant in time but who knows what the future holds. If you are writing a program that is so tight on memory and you need that space, take a chance on the future and use it. Otherwise, just treat bank 0 of high RAM as "reserved for future expansion".


XC16 Memory location bank 0 address $A000 till $A7FF

Posted: Mon Mar 28, 2022 12:15 am
by BruceMcF


On 3/27/2022 at 6:51 PM, Scott Robison said:




It is available at this instant in time but who knows what the future holds. If you are writing a program that is so tight on memory and you need that space, take a chance on the future and use it. Otherwise, just treat bank 0 of high RAM as "reserved for future expansion".



Oh, and allocate from the top working down, because they way they got the first quarter filled is starting from the bottom, working up.

But given a program that can't be done with 2,088,996 bytes to work with, it seems unlikely that adding another 6,144 bytes is going to get it over the top.