Duh, I didn't realize he was talking about the 256 color mode...
You're right about the paging, it's not too difficult. I never bothered to sit down and write the ASM routine, but I started work on it last night. I wrote a basic program that would calculate the proper 8k bank to have activated, and what memory location within that range, and determine if you should set the left or right pixel as each byte controls 2 pixels in the 320x192x16 color mode.
It's actually pretty easy to do... While in HSCREEN 2 (320x200x16) you feed the routine the X and Y values for to point you want to set.
(Bear in miind, this isn't standard CoCo BASIC, I'm using BASIC style statements just to show the flow.)
The actual Extended Color Basic code appears below this explanation, and can be typed in and ran on a CoCo 3. It asks for an x and y value (0 to 319 for x, 0 to 191 for y), and then it turns on the high resolution screen and sets the point, after pressing any key, it displays the calculated location, bank number, bank offset, and which pixel was set (either left or right) $10 means left, $01 means right.
So... to get started:
LOCATION = Y * 160
This gets you to the horizontal row you need
LOCATION =LOCATION + INT (X)/2
This gets you to the location.
At this point, you have the location within the entire 32K range that you
would write to if you were not bank switching, so we still need to calculate that.
BANK_NUMBER = INT(LO/8192)
Any value from 0 to 8K will return a zero, which is the bank we want to write to.
Any value from 8192 to 16383 will return a 1, 16384 to 24575 a 2, and 24576
to 32768 will return a 3.
The high resolution screens start at $60000 in the 512K memory range.
Both the 128K and 512K map to the last 8 8K banks, so the address range is the same
for either 128K or 512K Color Computer 3s. In other words, 128k CoCos are missing the
lower 384k of memory, not the upper. If you load an MMU register with the value $30, that
offsets you to $60000 where the HSCREEN memory starts, so we need to add $30 to our
bank offset so we can set the proper value to the MMU register to bank in the proper bank.
I'm using MMU register $FFA2 (MMU range is $FFA0-$FFA7 and $FFA8-FFAF (2 sets).
$FFA0 contains the zero page and low res text display video RAM, so I'm using $FFA2
which covers the range $4000 thru $5FFF. This is the range you'll write to when the
proper bank is active. Since the video memory for the high resolution screen starts at
$60000, if we divide that by 8K (8192 or $2000) we get a value of decimal 48, or $30 hex.
Therfore, we need to add that to the calculated bank number
BANK_NUMBER=BANK_NUMBER + $30
We now have the proper bank to activate (either $30,$31,$32 or $33) Those
values represent the 4 8K chunks from $60000 to $67FFF.
Ok, now, we need to know what offset within the 8K range to write to. If you're writing
to the first 8K chunk, then the offset is zero, and we can simply write to the
LOCATION value we calculated earlier, otherwise, if the bank number is 1, 2 or 3,
then we need to adjust the bank offset so that our location falls within the range values of
$0000 - $1FFF, then add $4000 to that so we point to the logical address that we
need to write to therefore:
IF BANK_NUMBER = 0 THEN BANK_OFFSET = LOCATION
IF BANK_NUMBER = 1 THEN BANK_OFFSET = LOCATION-8192
IF BANK_NUMBER = 2 THEN BANK_OFFSET = LOCATION-16384
IF BANK_NUMBER = 3 THEN BANK_OFFSET = LOCATION-24576
BANK_OFFSET = BANK_OFFSET + $4000
We're almost ready to write the pixel, but we still need to know if you're
setting the left or right pixel within the byte. All of the left pixels are even
addresses, and right are odd... therefore:
IF VALUE = INT(VALUE) THEN POINT=$10 ELSE POINT=$01
This calculates X/2, and if it's even, then it will equal the integer of
VALUE, and set POINT to $10 (setting left dot) or if it's odd, $10
(setting right dot). At this point we now have everything we need.
The location that needs to be written to (BANK_OFFSET), and
know if we're setting the left or right pixel at that location (POINT).
We also know what bank to have activated (BANK_NUMBER), so
all that's left is to do it.
Ok, we're ready to write so we need to activate the bank and perform our write!!!
First, save the value in the MMU register, then bank in our bank...
TEMP = PEEK($FFA2)
This saves what's already in $FFA2, and then banks in the 8K chunk of video
RAM into $4000-$5FFF which is addressable space we can reach with the 6809.
POKE BANK_OFFSET, POINT
Store point to bank offset, then restore MMU, and...
That's it!! We've converted an X,Y input to what needs to be done to write it via
machine code, all that's left is to code it in machine language... I'll post that when
it's up and working and ready.
Under normal circumstances, you would OR values into memory so as not to disturb the
other pixel, and any value 0 thru F will select the corresponding color pallete, and
whatever color is in that palette will be displayed. Also, any blitter you many write can
set both dots to any of the 16 palette values at the same time. I did it this way just for
Here's the ECB code, you can type this in and run on a CoCo 3
10 PALETTE 0,0:PALETTE 1,63:PALETTE 8,63:WIDTH 80
20 CLS 1
30 INPUT "X,Y";X,Y
40 HSCREEN 2
50 LO=Y * 160
80 IF BN=0 THEN BO=LO
90 IF BN=1 THEN BO=LO-8192
100 IF BN=2 THEN BO=LO-16384
110 IF BN=3 THEN BO=LO-24576
140 IF VA=INT(VA) THEN PT=&H10 ELSE PT=&H01
160 POKE &HFFA2,BN
170 POKE BO+$4000,PT
180 POKE &HFFA2,TP
190 SOUND 200,1
200 A$=INKEY$:IF A$="" THEN 200
210 PRINT "LOC:";HEX$(LO);", BANK NO;";HEX$(BN);", BANK OFFSET:";HEX$(BO);", POINT:",HEX$(PT)
220 HSCREEN 0
230 GOTO 30
As far as BASIC is concerned, this is a drawn out way of doing this since CoCo3 BASIC includes HSET(x,y,c) and HRESET(x,y) to turn pixels on
and off, but because it works, it demonstrates I'm calculating all the proper things I would need to do from assembly language. I'll post the ASM
code when I'm done with that for anyone interested in seeing it. It actually took a bit of work to flesh all this out, but once done, it's actually
pretty simple as was stated earlier... an annoyance, once it's boiled down to it's constituent parts.