Before discussing the Beeb way of doing things, it is important that you understand how the video section of a typical, old fashioned, micro works. The following account is based on the old PET's video section.
An area of 1000 bytes of memory is used by both the computer and the video circuitry. To the computer this area appears as a normal block of memory, starting at address 32768 and continuing to 33767, assuming the screen format is 25 lines of 40 characters. The video circuitry translates data stored in the memory to the pictures you see on the screen. It does so by accessing each character position of the block in turn, and then displaying the correct character at the correct point on the screen. A description follows the circuit diagram.
This circuit is simplified -- some of the important points and features have been left out. Each character on the PET screen is made up out of an 8 by 8 matrix, the same as the BBC micro in modes 0 to 6. Thus, there are 64 bits needed to make up each character. These bits are stored in the 'character generator' like this:
ADDRESS | BINARY DATA |
0000 | 00000000 |
0001 | 00111100 |
0002 | 00100100 |
0003 | 00100100 |
0004 | 00100100 |
0005 | 00100100 |
0006 | 00111100 |
0007 | 00000000 |
Low order 3 bits -- character row (0 to 7)
High order 8 bits -- character select (0 to 255)
So to access the data stored in the 5th row of the 45th character, we need to put the following data on the character generator's address lines:
A0 to A2 -- 5
A3 to A10 -- 45.
You can see the 11 lines going in to the character generator in the diagram. The data bus of the character generator is connected to a serializer, which is a simple chip which accepts eight bits, and then clocks the bits out at a pre-determined rate, one at a time. This chip is typically a 74165.
Thus, to display the fifth row of the 45th character, the above procedure should be carried out, and the required byte will be clocked to the TV by the serializer.
You can also see from the diagram where the eight 'character select' inputs to the character generator come from -- they are simply the contents of the memory location currently being accessed in the VDU RAM. The 'row select' signal comes from the TTL bits and pieces. These pieces access the VDU RAM at the right time, with the right row output to the character generator, eight times, once for each row of each character.
The point of that explanation was to show you how the character generator works. This arrangement is similar to that used in the teletext mode of the BBC computer, except a special character generator is used, the SA5050, and the matrix for each character is much larger, 16 by 16.
The other modes are dot resolution modes. Before discussing these modes, we have to make another comparison, this time with the Atom. The Atom's highest resolution screen is mapped like this, with reference to the start of VDU RAM, which is again 32768:
Contrast this to the BBC's arrangement:
It looks a little odd compared to the Atom arrangement, but we shall see that it is logical.
To put off the moment when we have to start on the rest of the hardware, here are the details of how the individual bits map on to the display.
In all modes with two possible colours, the arrangement is as follows:
Pixels: | p0 | p1 | p2 | p3 | p4 | p5 | p6 | p7 |
Bits: | b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 |
In modes with 4 colours, each byte only accounts for four pixels. The arrangement is like this:
Pixel | p0 | p1 | p2 | p3 |
Bits: | b0/b4 | b1/b5 | b2/b6 | b3/b7 |
Mode 2 is mapped like this:
Pixels: | p0 | p1 |
Bits: | b0/b2/b4/b6 | b1/b3/b5/b7 |
Back to the BBC computer's circuits:
I have chosen mode 4 as an example, but all modes work roughly the same, except mode 7.
The 6845 is a clever piece of equipment, which basically acts as the TTL bits and pieces in the PET. There are some more sophisticated things it can do. It generates the cursor, scrolls the screen and deals with the light pen.
Take a look at the circuit diagram:
The first important point to note is the absence of a character generator. The second difference between this diagram and the first is that the PET VDU takes 1000 bytes of RAM, but the BBC computer takes a vast 10K to generate a picture.
The same process is carried out to generate a picture as on the PET, except that the character generator row address makes up the lowest three bits of the VDU RAM address. Thus, rather than the code for a particular character being held in VDU RAM, the dot pattern for the entire character is held, byte by byte in VDU RAM.
Each VDU RAM location is only accessed once, but if you forget about the low order three bits for the moment, each group of eight VDU RAM locations is accessed eight times, once for each row of each character.
In the case of graphics, because each screen location is in effect its own character generator, VDU RAM can be written bit (as in byte) by bit.
The role of the ULA is to deal with the scrolling mechanism, the colours, and the addressing mechanism, because the character generator is only used in mode 7.
All communications between you and the 6845 are carried out via 18 'ports'. These ports are like variables, except that some may only be written to, and some others may only be read and two can be both written to and read from. These ports are referred to as 'register'.
There are ways to get a number into a register. You can either use the command 'VDU 23, 0, reg, val, 0;0;0;' to copy the number 'val' into register number 'reg' (the registers are numbered 0 to 17), or you can execute the statements '?&FE00=reg: ?&FE01=val'. The second way is usually best to use in machine language, and the first is the neater way in BASIC.
There is only one way to read the number held in a register. Execute '?&FE00=reg: val=?&FE01' to copy the value in register 'reg' to variable 'val'.
If you have your machine turned on, you will find it helpful to enter the following procedure and function, used to read and write to the registers, so you can experiment with the registers discussed in the next few pages.
900 REM **************************** 910 REM This procedure loads register 920 REM 'reg' with 'val'. 930 REM **************************** 1000 DEF PROCLOAD(reg,val) 1010 VDU 23,0,reg,val,0,0,0,0,0,0 1020 ENDPROC 1030 REM **************************** 1910 REM This function returns the 1920 REM value in register 'reg'. 1930 REM **************************** 2000 DEF FNREAD(reg) 2010 ?&FE00=reg 2020=?&FE01 2030 REM ****************************
There follows a description of each of the 18 registers.
The first few registers are not very interesting, in that altering them serves no useful purpose, except sometimes collapsing your display, so I'll skate over them quickly.
Register 0 -- 'Horizontal total'. (Write only).
The contents of this register determine the total time allocated to each scan line in terms of character clocks. In other words it contains the total number of displayed and undisplayed characters on the screen, minus one, per horizontal line. Thus it determines the horizontal SYNC frequency. Its contents in the various modes are as follows:
Mode -- | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
Contents -- | 127 | 127 | 127 | 127 | 63 | 63 | 63 | 63 |
It transpires that modes 0 to 3 have 80 characters to a line, and the others have 40. The reason why modes 1,2, and 5 do not appear to have the right number of characters per line is that they allow more than two colours. The range of values for register 0 is 0 to 255.
Register 1 -- 'Characters per line'. (Write only).
This register determines the number of characters to be displayed on each horizontal line. This register is loaded with the number of characters actually displayed per line. Thus, the difference between this register and register 0 are the borders on the sides of the display.
The contents of this register in each of the modes are as follows:
Mode -- | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
Contents | 80 | 80 | 80 | 80 | 40 | 40 | 40 | 40 |
You can put anything you like in this register and see the effect, but if you make the contents of this register larger than the contents of register 0, the display collapses. This is because the border will be a negative number of characters, which confuses the 6845.
If you just increment or decrement this register from its normal value, you get a slanted display, which can be quite dramatic. This program uses register 1 in a number of ways.
10 MODE 5 20 VDU 19,3,4,0,0,0,19,0,7,0,0,0,19, 2,0,0,0,0 30 FOR T=0 TO 14 40 COLOUR RND(3) 50 PRINT "Interface..."' 60 NEXT T 61 TIME=0 62 REPEAT UNTIL TIME>100 70 TIME=0 80 REPEAT 90 FOR T=1 TO 40 100 PROCLOAD(1,T) 110 G=TIME 120 REPEAT UNTIL (TIME-G)>20 130 NEXT T 135 G=TIME 136 REPEAT UNTIL (TIME-G)>50 140 FOR T=39 TO 2 STEP -1 150 PROCLOAD(1,T) 160 G=TIME 170 REPEAT UNTIL (TIME-G)>20 180 NEXT T 190 UNTIL TIME>1000 200 TIME=0 210 REPEAT UNTIL TIME>100 220 MODE 2 230 PROCLOAD(1,79) 240 TIME=0 250 REPEAT 260 COLOUR RND(7) 270 VDU 8,8,42 280 UNTIL TIME>1000 290 REPEAT UNTIL FALSE 999 REM **************************** 1000 DEF PROCLOAD(reg,val) 1010 VDU 23,0,reg,val,0,0,0,0,0,0 1020 ENDPROC 2000 DEF FNREAD(reg) 2010 ?&FE00=reg 2020=?&FE01
The range of values for register 1 is 0 to 255 -- but more realistically the upper limit is the contents of register 0.
Register 2 -- 'Horizontal SYNC position'. (Write only).
This register establishes the point where the horizontal SYNC signal switches. It is specified in terms of characters. The reference point is the left most character position displayed on the screen.
What this means is that this register determines the displacement from the left-hand side of the screen of the left most character in the display. The contents of this register in each of the 8 modes are as follows:
Mode -- | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
Contents -- | 98 | 98 | 98 | 98 | 49 | 49 | 49 | 51 |
The range for this register is 0 to 255.
Register 3 -- 'Horizontal SYNC width'. (Write only).
This register establishes the duration of the horizontal SYNC pulse. DO NOT ADJUST IT!!!
Register 4 -- 'Vertical total'. (Write only).
This register gives the total number of displayed and undisplayed character rows, or lines. The contents of this register in the 8 modes are as follows:
Mode -- | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
Contents -- | 38 | 38 | 38 | 30 | 38 | 38 | 30 | 30 |
There is a little point in altering this register, except that if you reduce its value by about 1 or 2, it is possible to move the display up the screen a bit.
The range of this register is 0 to 127.
Register 5 -- 'Vertical SYNC adjust'. (Write only).
It was stated above that register 4 helps determine the frame refresh rate. Register 4 is a coarse adjustment, while register 5 enables more accurate, fine, adjustments to be made. Zero is usually stored in this register, except in mode 7, where 2 is stored.
If you alter this, you can move the vertical position of the display a little, but numbers should be kept fairly low -- some televisions are not very tolerant of differences in the SYNC pulse, and so many cause the picture to collapse.
The range of register 5 is 0 to 31.
Register 6 -- 'Character rows per frame'. (Write only).
This register allows you to alter the number of lines displayed on the screen. There are, however, some severe limitations. In mode 7, altering the number of lines causes characters to be sliced up, and in other modes, increasing the number of lines beyond the normal will lead to repetitions, ie some lines appear twice! Also, the height of the lines is not affected, so if you ask the computer to display 40 lines in mode 0, it will, but six of them will probably be off the display. Reducing the number of lines is quite possible.
The range of this register is 0 to 127.
Register 7 -- 'Vertical SYNC position'. (Write only).
This register normally contains the number of lines on the screen, plus three.
Altering this register gives you another way of moving the picture up and down the screen. Increasing it from its normal value moves the display up, and decreasing it moves the display down. A similar function is performed by the *TV MOS command.
The range of this register is 0 to 127.
Register 8 -- 'Interlace mode'. (Write only).
This register holds a number between 0 and 3 inclusive. The effects of the numbers are as follows:
0 -- Non-interlaced picture
1 -- Interlaced SYNC picture
2 -- Non-interlaced picture
3 -- Interlaced SYNC and VIDEO picture
Mode 7 is interlaced with SYNC and VIDEO. All other modes are just interlaced SYNC.
Interlaced pictures are more complete than non-interlaced pictures -- if you turn off interlace (which you can't do in mode 7) the lines that made up characters become visible.
There is little point in altering this register. If you do want to, you are better off using *TV with a second argument, as described in the User Guide.
Register 9 -- 'Scan lines per row'. (Write only).
The contents of this register determine the total number of vertical dots that go to make up each character. Its contents in each mode are as follows:
Mode -- | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
Contents -- | 7 | 7 | 7 | 9 | 7 | 7 | 9 | 18 |
You can see the size of the mode 7 matrix from the last value in the table.
Register 10 -- 'Cursor start line'. (Write only).
Each character on the display stretches over a number of 'scan lines'. The exact number for each mode is given in the section on register 9. The cursor can extend between any two of these scan lines. In mode 7, for example, the cursor starts and stops on the last scan line of the character, giving the impression of a single bar, but in modes 3 and 6 it starts on scan line 7, and finishes on scan line 9, which is why the cursor appears thicker in these modes.
The contents of this register determined the first scan line on which the cursor will appear. Thus, its contents in each of the 8 modes are as follows:
Mode -- | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
Contents -- | 7 | 7 | 7 | 7 | 7 | 7 | 7 | 18 |
Number to be added | Attribute |
0 | Cursor doesn't blink |
32 | Cursor invisible |
64 | Cursor flashes quickly |
96 | Cursor flashes slowly |
Mode --0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | |
Contents -- | 103 | 103 | 103 | 103 | 103 | 103 | 103 | 114 |
(96+7) | (96+7) | (96+7) | (96+7) | (96+7) | (96+7) | (96+7) | (96+18) |
One application of this register is to alter the cursor's appearance in a program to show which mode you're in (I don't mean screen mode). I will give some examples of cursors after the discussion of the next register. The range of the first part of this register is 0 to 31.
Mode -- | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
Contents -- | 7 | 7 | 7 | 9 | 7 | 7 | 9 | 19 |
All of the following examples are to be tried in any mode but mode 7.
Start scan line | Stop scan line | Effect |
0 | 0 | Underlines the |
character above the | ||
cursor | ||
4 | 4 | Gives a narrow, |
centralized, dash | ||
cursor | ||
3 | 6 | Gives a thick dash as |
a cursor | ||
4 | 7 | Gives a cursor |
occupying half the | ||
space allocated to it. |
Registers 12 &13 -- 'Top of page'. (Write only).
MODES 0 TO 6:
In these modes, registers 12 and 13 indicate the lowest memory address that is being used by the current screen mode. For this purpose the least significant byte of the address is stored in register 13, and the most significant is stored in register 12. However, you don't store the actual address in these registers -- you have to use the address divided by 8. So this procedure will, in combination with the one you've already got in memory, make the current screen mode start at any address you choose:
30 REM This procedure makes 40 REM VDU RAM set any address 50 REM (modes 0 to 6 only) 800 DEF PROCSTART(address) 805 address=address DIV 8 810 PROCLOAD(12,address DIV 256) 820 PROCLOAD(13,address MOD 256) 830 ENDPROC 999 REM **************************** 1000 DEF PROCLOAD(reg,val) 1010 VDU 23,0,reg,val,0,0,0,0,0,0 1020 ENDPROC 2000 DEF FNREAD(reg) 2010 ?&FE00=reg 2020=?&FE01
One interesting thing you can do with this procedure is to set the display to start at address 0. If you do, you can see all the lower memory locations being changed very rapidly. Run through the following examples:
Execute MODE 0/VDU 28,0,10,79,0/PROCSTART(0) to put you in mode 0, with screen memory starting at 0. The VDU 28 command defines a text window which keeps the cursor in the visible part of the screen. (MODE 0 takes up 20K, if you make it start at address 0 the screen will overlap the old mode 0 -- ie you can see what you type, which you can't do if you do all this in mode 4.) The screen should look something like this:
I have annotated the diagram to show where various things are stored. Try the following, and watch the relevant areas of the screen as you do so. Insert some extra lines (REM statements, perhaps) in your program. You will see the area labelled 'PROGRAM' expand. If you then delete some lines , you can see the same area contracting, as less memory is used up.
Execute 'FOR T%=TOP TO HIMEM:?T%=0:NEXT'. This will clear the unused area of memory.
Define a user defined key. The area labelled 'KEYS' will expand slightly.
Type a SOUND statement and you will see the 'SOUND QUEUE' area become active. Similarly, type an ENVELOPE and you will see the ENVELOPE storage area, labelled 'ENVELOPES', pop into life.
Try redefining the letter 'A', using VDU 23,65,1,2,3,4,5,6,7,8. The area labelled 'CHARS 64 TO 95' will get filled with the dot patterns of the aforementioned characters.
Similarly defining any character will bring that labelled area of memory into life. If you've got a long program in memory, though, you are likely to overwrite it -- so be careful!
Watch the area labelled 'KEYBOARD BUFFER' as you type text in at the keyboard.
Then execute a loop such as 'TIME=0:REPEAT UNTIL TIME=10@100'. While the loop is executing, watch the area labelled 'RUN TIME BUFFER' as you type text in. When the loop is finished, the 'KEYBOARD BUFFER' will get filled up.
Watch the area called 'COPY' when you use the copy key to copy characters. If you are a little confused at this stage, no need to worry as all the things you are watching will be explained in subsequent chapters.
Back now to more serious matters:
If you make screen memory start at an address before its normal address (ie lower than HIMEM), you will see that only a part of the normal screen will be shown, if any, but if you make the start address larger than normal, the screen 'wraps around'. This means that instead of starting to display characters above the place where memory should stop, it goes back to the start of official screen RAM, and displays that instead. This is how the scrolling of memory is done so fast on the computer -- it doesn't have to alter anything to scroll the screen, except these registers.
This program uses the scrolling principle outlined above to print in mode 4, and then allows you to 'roll' the screen in any direction, using the cursor control keys.
Just type RUN, then manipulate the cursor keys. Various games using this principle spring to mind. (INKEY is used with a negative argument, so you can press combinations of keys for diagonal movement).
10 REM Movement 20 REM For modes 4 and 5. 30 REM Modes 0,1 & 2 - see below. 40 REM (C) Jeremy Ruston. 50 REM ******************* 60 MODE 4 70 PRINT TAB(7,16);"The BBC Micro Rev ealed..." 80 PROCASSEMBLE 90 START=HIMEM/8 100 X=0 110 Y=0 120 REM ******************* 130 REPEAT 140 IF INKEY(-42) THEN Y=(Y+31) MOD 32 150 IF INKEY(-58) THEN Y=(Y+1) MOD 32 160 IF INKEY(-26) THEN X=(X+1) MOD 40 170 IF INKEY(-122) THEN X=(X+39) MOD 40 180 S=START+X+Y*40 190 ?&D00=S DIV 256 200 ?&D01=S MOD 256 210 CALL &D10 220 UNTIL FALSE 230 REM ******************* 240 REM Machine code routine to load 250 REM register 12 with the contents 260 REM of &D00 and 13 with that of 270 REM &D01. Has to be in MC for 280 REM high speed. 290 DEF PROCASSEMBLE 300 P%=&D10 310 [OPT 0 320 LDA #12:STA &FE00 330 LDA &D00:STA &FE01 340 LDA #13:STA &FE00 350 LDA &D01:STA &FE01 360 RTS:] 370 ENDPROC 380 REM ******************* 390 For modes 0,1 and 2, make these 400 changes: 410 420 Line 180 becomes : 430 IF INKEY(-26) THEN X=(X+1) MOD 80 440 Line 190 becomes : 450 IF INKEY(-122) THEN X=(X+79) MOD 8 460 Line 200 becomes : 470 S=START+X+Y*80
Before scrolling takes place in any of these modes, the value in register 13 is always zero. So you can do a certain amount of work just using register 13 for scrolling from side to side. For example:
10 MODE 2 20 VDU 29,640;512; 30 VDU 24,-639;-511;639;511; 40 GCOL 0,132 50 CLG 60 VDU 24,-499;-399;499;399; 70 GCOL 0,128 80 CLG 90 FOR T=1 TO 100 100 X=RND(640)-1 110 Y=RND(512)-1 120 GCOL 0,RND(7) 130 FOR ones=-1 TO 1 STEP 2 140 FOR twos=-1 TO 1 STEP 2 150 MOVE 0,0 160 PLOT 1,ones*X,twos*Y 170 NEXT twos 180 NEXT ones 190 NEXT T 200 DELAY=0 210 FOR T=1 TO 79 STEP 2 220 FOR A=1 TO T 230 PROCLOAD(13,A) 240 PROCDELAY(DELAY) 250 NEXT A 260 FOR A=T-1 TO 2 STEP -1 270 PROCLOAD(13,A) 280 PROCDELAY(DELAY) 290 NEXT A 300 NEXT T 310 PROCLOAD(13,0) 320 END 330 DEF PROCLOAD(reg,val) 340 VDU 23,0,reg,val,0,0,0,0,0,0 350 ENDPROC 360 DEF PROCDELAY(TIM) 370 TIME=0 380 REPEAT UNTIL TIME>TIM 390 ENDPROC
Notice that the scrolling from side to side used here is not the same as the rolling you can achieve with register 2, since with register 2 you often lose characters off the edge of the screen. With register 13 you get full wrap around, to stop you losing any characters.
You should now be able to see why these two registers are called 'TOP of page', and not 'Screen memory start'.
MODE 7:
Things work similarly in mode 7 -- except that the address loaded does not have to be divided by 8. The complication is that the start of mode 7 is not quite where you would expect it to be -- try it and see. Also, if you decrease the top of page value, to below the normal value, you will not move back by a few bytes -- you will move forward by 6700 bytes. This is complex and only amounts to making these registers rather trickier to use. Messing about with register 13 is easy in mode 7, however.
Register 14 & 15 -- 'Cursor address'. (Read and write).
Thus, at a CLS or mode change (under program control, to stop the prompt appearing), the address in these two registers is the same as the address in registers 12 & 13.
Registers 16 & 17 -- 'Light pen position'. (Read only).
That completes the description of the 6845's internal registers.
For completeness, here is a table showing the contents of the various registers in each of the modes:
Mode -- | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
0 Register | 127 | 127 | 127 | 127 | 63 | 63 | 63 | 63 |
1 | 80 | 80 | 80 | 80 | 40 | 40 | 40 | 40 |
2 | 98 | 98 | 98 | 98 | 49 | 49 | 49 | 51 |
4 | 38 | 38 | 38 | 30 | 38 | 38 | 30 | 30 |
5 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
6 | 32 | 32 | 32 | 25 | 32 | 32 | 25 | 25 |
7 | 35 | 35 | 35 | 28 | 35 | 35 | 28 | 28 |
8 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 3 |
9 | 7 | 7 | 7 | 9 | 7 | 7 | 9 | 18 |
10 | 103 | 103 | 103 | 103 | 103 | 103 | 103 | 114 |
11 | 7 | 7 | 7 | 9 | 7 | 7 | 9 | 19 |
Designing your own modes.
To test our understanding of the registers, let's see if we can use them to make up a screen mode to our own specifications. The only way we can do this is by altering the number of lines and number of characters displayed in an existing mode.
I'll work slowly through the way I managed to get a mode of 16 lines of 32 characters, then it would be instructive for you to see if you can go on to make other modes, of different numbers of characters.
Before we start, make sure you've got PROCLOAD defined at the top of memory, say at line 1000, and then type an END statement at about line 500. This will ensure that as we add extra lines to our program, when we execute it, we won't go charging through the procedure definition, which could cause problems.
Our first choice is to choose an existing mode with which to start work. I chose mode 4, since it is slightly bigger than the format we are aiming at. So, the first line of our program is:
10 MODE 4
We're aiming for a mode with 16 lines. At the moment there are 32, so we've got to get rid of 16 of them. Looking back at our tour of 6845 registers, we can see that the relevant one to change is register 6. So by setting the contents of register 6 to 16 we will instruct the 6845 to display 16 lines of characters. To do this, add the following to your program.
20 PROCLOAD(6,16)
Now run the program. The screen will probably give a little kick, and then settle down to look like a normal mode 4 screen. If you execute 'VDU 19,1,0,0,0,0,19,0,7,0,0,0' you will see that this is not the case. Now that you've got a white background, you can see that only the top half of the screen is being used. That's all very well, but it would be nicer if the 16 lines could be spaced out a little, to fill up all the available screen area. We'll do it in the same way as the extra spaces are inserted into modes 3 and 6. To achieve this spacing, we allow for 16 scan lines per line of text, instead of the normal 8. If you look back a few pages, you will see why this line is the one to be added:
40 PROCLOAD(9,15)
This display should now appear to be spaced out correctly, but there will probably be a good deal of flicker on the screen, and the first line of text will not start at its accustomed place at the top of the screen.
The reason for the display being half way down the screen is that the vertical total register, register 18, has not been informed of the reduction in the number of screen lines, and so is pumping out a vast border at the top of the screen, which shifts everything else on the screen down a few lines. So we update the vertical total register with:
50 PROCLOAD(4,18)
The display should now start at the right place, but you may find that the picture rolls rather a lot. After much experimentation, it transpires that all we have to do to remove the rolling is to adjust the position of the vertical SYNC pulse. Actually the experimentation consisted of looking at the table of register contents under various modes, seeing which registers held some connection with the number of lines displayed and ensuring that all those had been adjusted. Register 7 was the only one which hadn't. From the table, I expected this register to hold two more than the number of screen lines, but I get steadier picture with 17 in this register. So the line we can finally add is:
60 PROCLOAD(7,17)
We should now have a perfect display of 16 lines by 40 characters. So now all we have to do is remove 8 characters from the end of each line. Before we do so, you may like to add:
70 PROCLOAD(11,15)
which gives an odd cursor.
To adjust the number of characters in the line, we use:
80 PROCLOAD(1,32)
We now have a screen of 16 lines of 32 characters -- but the computer is still treating it as a screen of 32 lines of 40 characters, and so printing will not work as you want.
Finally in this section, here is a table of the 6845 registers:
6845 REGISTERS:
Register | Name/function |
0 | Horizontal total |
1 | Characters/row |
2 | HSYNC position |
3 | HSYNC width |
4 | Vertical total |
5 | VSYNC adjust |
6 | Character rows/frame |
7 | VSYNC position |
8 | Interlace mode |
9 | Scan lines/row |
10 | Cursor start scan line |
11 | Cursor stop scan line |
12 | MSB Start address (top of page) |
13 | LSB Start address (top of page) |
14 | MSB Cursor position |
15 | LSB Cursor position |
16 | MSB Light pen position |
17 | LSB Light pen position |