(This question applies also to the low-resolution graphics video buffer, since that uses the same frame buffer as text mode, just displaying it differently.)

As described on page 1-12 et seq. of The CRT Controller Handbook by Gerry Kane, a video system generating characters on a display from a list of (byte-sized) character codes generally re-read each character code multiple times during the course of displaying it, once for each line in the character matrix. (Thus, a 5x7 character matrix would require each character code to be read 7 times in the course of displaying a row of characters on the screen.) He goes on to describe how this is handled in some video controllers via a separate line buffer that's filled by the computer and then scanned in this way.

In the Apple II the video circuit seems to read character codes directly from the frame buffer in system RAM. However, if it scanned each character code row several times while generating the multiple scan lines to display those characters on the screen, the CPU might change some of the characters during the display of a row, causing the top part of those character cells to display the previous character but the bottom part to display the new character. I've never seen this happen on an Apple II.

How did the Apple II video system design prevent this from happening? Or does it happen and I've just never noticed it? Please provide references to support your answer.

  • I worked with Apple II from the assembly code side many years ago for a gaming company. I just remember that you could split the screen so that you could show graphics and text at the same time. I remember it being pretty well behaved. You could not easily do the same thing on the Commoredore 64. We had to do special coding to switch between graphics and text when it was 'drawing' the screen.
    – kevlray
    Mar 5, 2020 at 20:27
  • That split screen you're talking about is probably the ability to have four lines of text at the bottom of an otherwise graphics-mode screen. That's unrelated to whether or not text/GR lines are re-read and possibly rendered differently for each scan row, since that split is done between text lines, not within one.
    – cjs
    Mar 9, 2020 at 7:51

2 Answers 2


The screen refreshes 60 times per second (or 50 times in PAL countries) so a cell with one character in the top half and a different one in the bottom half would only be visible for 1/60th or 1/50th of a second. Under ordinary conditions, you won't notice it.

  • 1
    Oh, duh. That hadn't occurred to me. So this could presumably be tested by writing a program that changes several locations back and forth between an inverse and non-inverse character at 16.66 ms. intervals to get an actual split character, right?
    – cjs
    Mar 5, 2020 at 5:27
  • 1
    @cjs to test it you may want to simply synchronize character writes (changing) with HBL, which should allow precise changes on a scan line base.
    – Raffzahn
    Mar 5, 2020 at 10:03
  • 1
    @Raffzahn Great idea! How do I get an HBL signal on the Apple II?
    – cjs
    Mar 5, 2020 at 11:31
  • @cjs reading the soft switches. When in Text mode, reading $C051 will give the last fetched character. It's a bit tight in timing, but can be done. Essential when one wants to mix sections of Highres, Lowres and Text in one screen.
    – Raffzahn
    Mar 5, 2020 at 14:26
  • 1
    See deater.net/weave/vmwprod/space_bars for an example software title that (mostly) uses low-resolution mode, but synchronises itself to the raster in order to rewrite the display as it is being drawn. In that case to get a higher resolution vertical resolution and, in some scenes, for horizontally-mixed modes.
    – Tommy
    Mar 5, 2020 at 15:18

I've written a small program that confirms that lines of text do tear if modified while being scanned. It's not easy to see (it would have been a large amount of extra work to do the exact sync that would make it really clear), but as it runs, amongst all the flickering you can see diagonal lines across the line of text where the line tears due to reading different characters over the course of the eight scans of the text line.

Unfortunately, the camera on my phone won't let me set the shutter speed to be able to capture this, but perhaps I'll be able to dig up one of my proper digital cameras later to do so.

In the meantime, here's the program listing as assembled by the Apple DOS 3.3 assembler, EDASM. It's just a quick hack, so the code quality is far from the best. And I have no idea what it will do on an emulator.

0000:            1 * SET HIMEM=36864 TO LEAVE $9000-$9600 FREE
9000:            2         ORG  $9000
9000:            3 *
9000:            5 *
9000:            6 * SCREEN CODES FOR FILL
00A0:            7 CHR1    EQU  $A0         ;NORMAL ' '
0020:            8 CHR2    EQU  $20         ;INVERSE ' '
9000:            9 *
008D:           10 CR      EQU  $8D         ;ASCII CARRIAGE RETURN
9000:           11 *
FDED:           12 COUT    EQU  $FDED
FC58:           13 HOME    EQU  $FC58       ;CLEARS SCREEN
FCA8:           14 WAIT    EQU  $FCA8       ; EXPONENTIAL DELAY IN A
9000:           15 *
9000:20 58 FC   16 MAIN    JSR  HOME
9003:20 0A 90   17         JSR  INITLINES
9006:20 39 90   18         JSR  LOOPLINE    ;NEVER RETURNS
9009:60         19         RTS
900A:A9 8D      20 INITLINES LDA #CR
900C:20 ED FD   21         JSR  COUT
900F:20 ED FD   22         JSR  COUT
9012:20 ED FD   23         JSR  COUT
9015:A9 04      24         LDA  #$04
9017:85 EC      25         STA  FILLBASE+1
9019:A9 00      26         LDA  #$00
901B:85 EB      27         STA  FILLBASE
901D:A9 A0      28         LDA  #CHR1       
901F:20 5A 90   29         JSR  FILL        ;ROW 1 
9022:A9 80      30         LDA  #$80
9024:85 EB      31         STA  FILLBASE
9026:A9 20      32         LDA  #CHR2
9028:20 5A 90   33         JSR  FILL        ;ROW 2 
902B:A9 05      34         LDA  #$5
902D:85 EC      35         STA  FILLBASE+1
902F:A9 00      36         LDA  #$00
9031:85 EB      37         STA  FILLBASE
9033:A9 A0      38         LDA  #CHR1
9035:20 5A 90   39         JSR  FILL        ;ROW 3 
9038:60         40         RTS
9039:A9 04      41 LOOPLINE LDA #$04
903B:85 EC      42         STA  FILLBASE+1
903D:A9 80      43         LDA  #$80
903F:85 EB      44         STA  FILLBASE    ;ROW 2
9041:A9 A0      45 LOOP    LDA  #CHR1
9043:20 5A 90   46         JSR  FILL
9046:20 54 90   47         JSR  LWAIT
9049:A9 20      48         LDA  #CHR2
904B:20 5A 90   49         JSR  FILL
904E:20 54 90   50         JSR  LWAIT
9051:18         51         CLC
9052:90 ED      52         BCC  LOOP
9054:           53 *
9054:           54 * WAIT ABOUT, BUT NOT EXACTLY, 1 FRAME.
9054:A9 7B      55 LWAIT   LDA  #$7B        ;<1 FRAME
9056:20 A8 FC   56         JSR  WAIT
9059:60         57         RTS
905A:           58 * 
905A:A0 28      59 FILL:   LDY  #40
905C:88         60 FILL1:  DEY
905D:91 EB      61         STA  (FILLBASE),Y
905F:D0 FB      62         BNE  FILL1
9061:60         63         RTS


   A0 CHR1             20 CHR2           FDED COUT             8D CR            
 905C FILL1            EB FILLBASE       905A FILL           FC58 HOME          
 900A INITLINES      9039 LOOPLINE       9041 LOOP           9054 LWAIT         
?9000 MAIN           FCA8 WAIT          
                                           20 CHR2             8D CR               A0 CHR1             EB FILLBASE      
?9000 MAIN           900A INITLINES      9039 LOOPLINE       9041 LOOP          
 9054 LWAIT          905A FILL           905C FILL1          FC58 HOME          
 FCA8 WAIT           FDED COUT

You must log in to answer this question.

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