5

Simple program...

10 print chr$(147);chr$(5)
20 poke 53280,4: poke 53281,0
30 y=0 : for x = 1 to 35
40 poke 214,y : print : poke 211,x
50 print chr$(171);chr$(177);chr$(179);
60 next x : print : print

This is a program from a book 'Step by step programming: Commodore 64' - page 38

I can't understand why the characters are printed on the third line (index = 2) when y = 0 in the program, and there is a single print between the pokes before the characters are printed - which would move the cursor down a single line to line 2 (index 1). Can anyone explain why it behaves like this?

screenshot

Just to clarify the Y position, here's another screenshot showing the cursor, and also with the print statement removed. So shouldn't that be now on line 1 (index = 0).

screenshot 2

And here's a simpler program that I think hones in on the issue:

10 print chr$(147);chr$(5)
40 poke 211,0: poke 214,0
50 print chr$(171);chr$(177);chr$(179);

This program doesn't show anything, which is unexpected.

enter image description here

If I change this code to poke 214,1 (Y-ord) I get an expected output..

enter image description here

So this is correctly at <0,1>, but I can't use y = 0 here. Maybe this is related to the question. There is something off about all this.

7
  • Is it actually the third line? The screenshot shows it's printed in the second. Feb 24, 2023 at 6:17
  • that is the third line, I'll update the question to show a bit more info that shows that. Feb 24, 2023 at 6:28
  • Okay, now I see. Still, I cannot reproduce: i.stack.imgur.com/Wpx73.png Feb 24, 2023 at 7:18
  • A bug in the emulator, maybe?
    – UncleBod
    Feb 24, 2023 at 9:51
  • Just ran that code again after being AFK for some time. And I got a different result - looks like yours now, but I can still produce other weird results, like poking different values into 214 (for y coordinate) and all characters are printed over each other on the same line. I'll try another emulator, I'm using CCS64 V3.9.3. Feb 24, 2023 at 10:50

2 Answers 2

7

It's not enough to poke the values into those locations - there's other information held elsewhere that also needs to be updated. See, for example, the following (slightly paraphrased) text from this page:

By using locations 211 and 214, we can position the cursor on the screen very easily. POKE the column into 211, the line into 214.

Of course, that isn't enough; the operating system doesn't know that the cursor has been moved. There's a ROM routine that will take care of the whole business for us. You can call it with SYS 58732, as per:

POKE 211, COLUMN : POKE 214, LINE : SYS 58732

The code at that 58732 location is needed because:

  • the C64 screen memory lines are spread across different pages of screen memory and are not always in a fixed spot; and
  • the physical lines on the screen are 40 columns but the logical lines (as used by the screen editor and output routines) can be longer.

This means there's more information that needs updating, over and above just the lower-level physical line/column bytes.

Specifically, a data table contains, for each physical line, enough information to work out its memory location and whether it is the first/only or subsequent physical line of a logical line. This table is used to update all the other information, by calling the ROM routine at $E56C (58732).


If you really want to understand, there's a great site with analysis of the C64 ROM (the specific code mentioned in this answer is here), which goes into a stunning level of detail on how things work.

But, if you just want to get it working, make sure you call that ROM routine before you try to PRINT anything, after having used POKE to change the line and/or column values.

1
  • Positioning is possible without the SYS call when using a PRINT after POKE 214,Y as the OP did it. But it adds one line to the coordinate. Other than that this is faster than using the SYS call, see my answer for details.
    – Peter B.
    Feb 27, 2023 at 21:52
1

In your approach, the commands poke 214,y:print:poke 211,x position the cursor one line below the given y value. The reason is that the following carriage return (issued by the single print command) is positioning the cursor but also entering the next line. Since poke 214,-1 is not possible, this means you can only position the cursor to lines below the top one.

An alternative is to use poke 214,y:poke 211,x:sys 58732, which exactly positions the cursor at x,y. But this version with the SYS call is about 50% slower than your approach.

So if you do not need to position into the top line, using poke 214,y:print:poke 211,x is fine as long as you use a number one less than the intended line for y.

2
  • 1
    I'm not totally certain that will work in all situations (but I can't be sure one way or the other so you may be right). If the line you end up on already holds a multi-line virtual line, the locations may end up being wrong. It would probably need some testing. If you really wanted speed, you could probably just bypass the translation issue by marking all lines as non-extended in the line-in-memory table, using that table to get the addresses of each line, and poking the characters in there directly rather than using print :-)
    – paxdiablo
    Feb 28, 2023 at 8:11
  • I just tested, both the Poke-Poke-Sys version and the Poke-Print-Poke version work the same when multi-line virtual lines are present, i.e. they go to the specified physical line (+1).
    – Peter B.
    Mar 3, 2023 at 17:56

You must log in to answer this question.

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