Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Tricking c64 basic into clearing a hi-res screen quickly (retro64.altervista.org)
61 points by amichail on Dec 12, 2024 | hide | past | favorite | 16 comments


Back in the day, one of IBM's early databases worked by storing memory into the graphics buffer, outside the field of view of the monitor, because writing directly to that memory space was faster on the hardware than anywhere else. (My dad wrote it when working for National Mutual).

Tricks like these, intentionally causing overflows, used to be the norm. You've got a tiny bit of hardware, which makes it easier to reason about overall behaviour (until the inevitable BSOD). You can generally tell when its safe to blow up your whole stack. And that kind of thing is fine to do.


The TI-99/4A came with 256 bytes of system RAM. Everything in TI BASIC had to be stored in video RAM -- program code, variables, etc. -- which was not directly accessible to the CPU and had to be accessed through register reads/writes to the video chip. This process was slow, and so TI BASIC was slow.

The TMS9900 was a fast (for 1979) 16-bit CPU, however, and some fast routines could be tucked away in those 256 bytes of RAM to achieve some interesting effects (for example smooth horizontal scrolling in Parsec, on a machine with no scrolling registers).


And on the Atari 2600, the fastest way to write to consecutive video registers is to set the stack pointer to its address and do push instructions. You take advantage of getting the stack pointer decremented for free on each push. The stack pointer can be hijacked for this since the machine has no interrupts.

The 2600 can also run self-modifying code in RAM, which I did: http://www.dos486.com/atari/


Though at least part of the slowness was TI's decision to write BASIC in GPL (an interpreted middle-level language, for those unfamiliar) instead of directly in 9900 assembly, which made it even worse.


Graphic Programming Language [0] for the curious.

      FMT                       Enter sub-interpreter
      HTEX 'Hello, world'       Displays horizontal text
      FEND                      Exits sub-interpreter
[0] http://unige.ch/medecine/nouspikel/ti99/gpl.htm


And another part was due to the fact that the CPU couldn't access video memory during scanout -- it went into a wait state -- so your program only actually ran during hblank and vblank!


I’ve always wondered what your first paragraph would look like, if it was shifted into the actual visible address space. I’m imagining a bit like white noise static but with colour? Anyone tried it and had a screenshot?


Kind of, ASCII isn't really random. You can give it a try yourself in your terminal:

  $ text="Back in the day, one of IBM's early databases worked by storing memory into the graphics buffer, outside the field of view of the monitor, because writing directly to that memory space was faster on the hardware than anywhere else. (My dad wrote it when working for National Mutual)." && printf "P6\n$((${#text} / 3)) 1\n255\n$text" > test.ppm
The result is kind of dim because none of the characters are greater than 0x80. You can brighten it by changing the 255 to, say, 127.

The resulting file should open in most image viewing programs, though somewhat amusingly while writing this I messed up the format accidentally found a denial-of-service in Apple's ImageIO NetPBM parser :P


The effect of seeing a program run in visible video RAM was actually pretty common on the C64.

Memory was really tight and every byte was valuable. Also external memory was slow. Programs were often loaded in a compressed form and then uncompressed. Since the uncompressed version filled the available memory to the last byte it raised the question where to put the unpackers code.

A natural choice was to run it from video ram, which would be overwritten when the game started and the unpacker was not needed anymore. As slow as the C64 was, you could clearly identify the unpackers loop counters.

I have also heard the story that this trick was especially popular for pirated games. The crackers used to add their intros and they had to fit in somewhere into already filled to the brim memory. So they used compression to squeeze their intros in.


There's a lot of 0s for preallocated space. And all-0 bitmap is just white. So mostly like white snow, with pickles of random colours in short blocks here and there, for headers.


It took me some time to get why this is faster than simply poking in a for-next loop - nice hack (for those who don't know I can recommend one of Ben Eater's latest BASIC hacking videos)!

But why add only 1 character each time, why not add the string to itself? That would grow it exponentially and would require much fewer steps. Or is string concatenation much slower than character concatenation?


Too much growth can be a problem too, according to this other article strings are at most 255 bytes long:

https://retro64.altervista.org/blog/garbage-collection-commo...

Which would limit the loop to 1 + 2 + 4 ... 128 = 255. You could start off with this, but making it work and filling exactly 8000 might be too complicated.


The 1..125 loop stores 8000 bytes of string and they need to clear 8000 bytes.

There may be a fast path for adding one character, but in any case bytes of program are a valuable resource with only 64k ram so having a second loop from nearest power of two to 8000 would be a waste of bytes.


One of the great things about C64 BASIC and similar MS BASIC derivatives is it's extensibility. It defines a bunch of pointers, including $0033 this article uses, that control the memory layout. Manipulating them carefully allows you to free up blocks of memory that BASIC won't trash. Or deliberately "trash" for hacks like this.

On top of that, a handful of key internal BASIC routines are called indirectly through pointers. BASIC itself is in ROM and more or less immutable, but by redirecting those pointers you can have it call out to new code in RAM.


You can copy C64 Basic to its underlying RAM (starting at $A000) and disable the ROM. Then it is mutable. https://www.lemon64.com/forum/viewtopic.php?t=69655


That was our favourite trick. Copying BASIC ROM to the RAM below and then changing "ERROR" to "TERROR". My 13 year old self was always amused by:

?SYNTAX TERROR




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: