7

I was hoping someone could just share a small code snippet with all the requisite POKEs that would illustrate how this is done. I would think for someone who knows what they were doing that this is a common problem that many CoCo3 developers have encountered and probably isn't that difficult for an expert to solve.

I know next to nothing about Assembly Language.

I know GrafExpress can do this, in addition to many other great things, but I am concerned about how much memory GE uses. I also only really need this feature, and not all the stuff that comes with GE.

I also don't want to learn a new language like Basic09, although I know it also handles this really well.

1
  • I knew how to do that on Apple computers, but I have not idea with a TRS-80... Feb 3, 2023 at 18:54

1 Answer 1

8

Page flipping is possible in high resolution graphics modes on the Color Computer 3 but there are a couple of caveats. First, the type of drawing and how much drawing your perform will certainly affect performance due to how the BASIC interpreter works. The second problem you may face is that it requires 512k since BASIC uses 32k when the ROM is copied into RAM and patched, 32k for BASIC programs, and 32k for housekeeping and extra data like HGET and HPUT buffers which leaves only 32k for a single 320x192 16 color screen.

In order to achieve page flipping you will need to manage the active and display pages yourself as there are no facilities provided by BASIC to do this. There only one region of memory that you will need to access in order to accomplish this - the MMU.

The memory you need to access contains the memory mapped MMU registers located from $FFA0 to $FFAF. The Color Computer 3 divides this region into two logical MMU regions colloquially known as Task 0 ($FFA0 to $FFA7) and Task 1 ($FFA8 to $FFAF). Note that only one Task can be active at a time. Each register in a MMU task maps in an 8k block of memory with the first MMU register of a Task block controlling memory from $0000 to $1FFF all the way to the last register of the Task controlling $E000 to $FFFF.

This is important because the implementation of BASIC in the Color Computer 3 uses Task 0 to map in the memory for BASIC programs and the ROM (which is copied to RAM on startup). It uses Task 1 to map in the graphics screen in order to perform drawing. This is where we will be working in order to achieve page flipping.

When BASIC switches from Task 0 to Task 1 to perform rendering it expects the frame buffer to be mapped into memory from $2000 to $9FFF. It does this by initializing 4 registers in MMU Task 1 from $FFA9 to $FFAC. This initialization is performed in a few places such as BASIC's HSCREEN command so it is important to be mindful of using commands like this when drawing.

To achieve page flipping we simply change the MMU registers in Task 1 to use the region of memory we want for our frame buffer, perform all drawing, then set the video offset registers at $FF9D and $FF9E to display our frame buffer.

For our example we are going to use the first 64K of the 512K memory and create two routines in BASIC to map in each of the frame buffers for drawing. To map in the first page we POKE values 0, 1, 2, and 3 into the Task 1 registers from $FFA9 to $FFAC respectively.

100 REM MAP IN PAGE 0 FOR DRAWING
101 POKE&HFFA9,0
102 POKE&HFFAA,1
103 POKE&HFFAB,2
104 POKE&HFFAC,3
105 RETURN

This will map in physical memory $00000 to $07FFF for drawing by BASIC. To map in the second frame buffer we do the same thing but with values 4, 5, 6, and 7.

110 REM MAP IN PAGE 1 FOR DRAWING
111 POKE&HFFA9,4
112 POKE&HFFAA,5
113 POKE&HFFAB,6
114 POKE&HFFAC,7
115 RETURN

This will map in physical memory $08000 to $0FFFF for drawing by BASIC. Now we need to be able to display each page and for that we POKE in specific values into the high byte of the video offset register at $FF9D. Keep in mind that the video offset register is 16 bits ($FF9D and $FF9E) and allows you to view all 512k of memory at 8 byte intervals. This means that to convert the physical address to the values that needs to be POKEd into the registers you just divide the address by 8. So for frame buffer 0 the value will be $0000 and for frame buffer 1 the value will be $1000. Since the least significant byte of each value of $00 we don't need to do anything with the register at $FF9E.

200 REM DISPLAY PAGE 0
201 POKE&HFF9D,0:RETURN
210 REM DISPLAY PAGE 1
211 POKE&HFF9D,&H10:RETURN

Now to put this all together we'll create a simple program to enable the 320x192 16 color video mode and animate a line being drawn at an angle using HCLS and HLINE along with our page flipping code.

0 POKE65497,0:HSCREEN2
1 FOR I=0 TO 319:PAGE=I AND 1
2 IF PAGE <> 0 THEN GOSUB 100 ELSE GOSUB 110
3 HCLS:HLINE(I,0)-(319-I,191),PSET
4 IF PAGE <> 0 THEN GOSUB 201 ELSE GOSUB 211
5 NEXT I:GOTO1
100 REM MAP IN PAGE 0 FOR DRAWING
101 POKE&HFFA9,0
102 POKE&HFFAA,1
103 POKE&HFFAB,2
104 POKE&HFFAC,3
105 RETURN
110 REM MAP IN PAGE 1 FOR DRAWING
111 POKE&HFFA9,4
112 POKE&HFFAA,5
113 POKE&HFFAB,6
114 POKE&HFFAC,7
115 RETURN
200 REM DISPLAY PAGE 0
201 POKE&HFF9D,0:Return
210 REM DISPLAY PAGE 1
211 POKE&HFF9D,&H10:RETURN

This is of course very slow since we are erasing the entire screen (32k) on each flip. On the plus side you don't actually see the screen being erased and redrawn each frame, just the end result. Keep in mind that there is no way to sync with the vertical refresh from BASIC, even with peeks and pokes, so if you end up needing that you may have to drop to assembly language.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .