[HN Gopher] Nine - seemingly impossible C64 demo
       ___________________________________________________________________
        
       Nine - seemingly impossible C64 demo
        
       Author : appleorchard46
       Score  : 244 points
       Date   : 2025-02-04 23:11 UTC (23 hours ago)
        
 (HTM) web link (linusakesson.net)
 (TXT) w3m dump (linusakesson.net)
        
       | kbelder wrote:
       | Neat. Having more than 8 sprites on screen is not hard, it just
       | requires some well-timed interrupts to move a sprite from above
       | the current raster location to below it, so that the same sprite
       | is drawn multiple times.
       | 
       | But I'm not sure about the end of the demo where they are all
       | rotating on the same line. I guess it could be done with
       | interrupts occurring partway through the horizontal scanline, but
       | I didn't think they could be that precise?
        
         | o11c wrote:
         | Youtube comments said something about "multiple apparent
         | sprites per actual sprite, with stretching"?
        
           | pwrrr wrote:
           | Yeah, you can x and/or y expand a sprite, then change it to
           | make it look like it contains more data by cleverly drawing
           | the sprite because 1 pixel becomes 2 pixels wide in expanded
           | mode.
        
         | egypturnash wrote:
         | Nope, that's not it. There's a video out there already that
         | dissects it and figures out the trick.
        
           | peterleiser wrote:
           | I don't know the trick, but take a look at the "7". It looks
           | like it's made from the vertical line in "4" and a portion of
           | another number.
        
             | badc0ffee wrote:
             | This is true, but not relevant to the trick.
        
         | boltzmann-brain wrote:
         | you can't multiplex sprites so that more than 8 appear on the
         | same line.
         | 
         | the secret is to pretend you have a 9th sprite by emulating it
         | with characters that look exactly like one of the sprites
         | would.
        
           | egypturnash wrote:
           | That stops working when you open the borders and put sprites
           | outside the area the video chip will render
           | characters/bitmaps.
        
             | eru wrote:
             | Yes, but the demo is really cheeky about that.
             | 
             | The borders are open when you can still do the normal
             | multiplexing, because there's lots of vertical separation
             | between the sprites.
             | 
             | Later, when they put the sprites together on the same line,
             | the borders are closed.
        
           | jchw wrote:
           | But in this case, that (alone) can't be it because all 9
           | sprites clip (smoothly) in and out of the border. So they've
           | really gotten cheeky with this one.
        
         | Dylan16807 wrote:
         | I don't like how you worded this post. You know the demo's
         | point is having all 9 go at the same time, so it's quite
         | misleading to start off describing something that _sounds_ like
         | the demo 's point, but is _not_ the demo 's point, and saying
         | it's "not hard". Your second paragraph mostly corrects that
         | false impression, but I dislike that you gave a false
         | impression to start with.
        
           | Underphil wrote:
           | This is an extremely common type of comment on articles like
           | this. The commenter has to ensure everyone knows their
           | credentials before offering any sort of praise to the
           | creator. I also despise this type of self-serving comment.
        
           | flohofwoe wrote:
           | 9 sprites on screen at the same time is trivial (this is
           | known as sprite multiplexing), 9 sprites on the same raster
           | line is the actual 'aha effect' because the C64 can only do 8
           | sprites per line.
        
             | Dylan16807 wrote:
             | I'm not sure why you replied to me? Are you nitpicking that
             | I said "go at the same time" because I think it's clear
             | enough in context.
        
         | pinoy420 wrote:
         | All you need is a little "Just"(TM) and everything is possible.
         | 
         | Typical HN comment minimising the immense effort required to do
         | %thing% due to their own arrogance.
        
         | flohofwoe wrote:
         | The VIC-II reads the data for each sprite at hardwired
         | horizontal positions outside the visible area, so this sort of
         | 'horizontal multiplexing' shouldn't work.
        
       | aappleby wrote:
       | Eight hardware sprites and one blitted to the background every
       | frame?
        
         | erik wrote:
         | That works until you see what appears to be 9 sprites on the
         | same scan line in the border region.
        
         | boltzmann-brain wrote:
         | VIC II doesn't have that functionality. the first commodore
         | that could do this was the Amiga series.
        
         | badc0ffee wrote:
         | Not quite. Drawing a full sprite-sized bitmap would not be so
         | smooth on the C64.
        
         | pwrrr wrote:
         | They are in the border, Only sprites, ghostbyte (a repeating
         | byte only shown in black. It is the last byte of the chosen
         | videobank) and background color can be displayed there.
        
       | siltcakes wrote:
       | As soon as I saw who made this, I cranked my speakers and wasn't
       | disappointed! Linus is amazing. I recommend his cover of The Moon
       | from DuckTales:
       | 
       | https://linusakesson.net/chipophone/ducktalesmoon.php
        
         | jetbalsa wrote:
         | I'm a huge fan of his A Mind is born demo 256 byte demo he did
         | awhile back, freaking amazing
         | 
         | https://linusakesson.net/scene/a-mind-is-born/index.php
        
           | userbinator wrote:
           | Discussion of it showed up on HN too:
           | https://news.ycombinator.com/item?id=26511266
           | 
           | I like how the title really invites you to pun it as "a mind
           | is blown", because mine sure was when I first watched it.
        
       | nonane wrote:
       | Here is a video where Martin Piper uses a C64 debug tools to
       | figure out how Nine was created:
       | https://m.youtube.com/watch?v=Ik1vsMM2EuY .
        
       | pimlottc wrote:
       | Just guessing here, but does it have anything to do with the fact
       | that 9 is the same as 6 rotated?
        
         | boltzmann-brain wrote:
         | no. there are 9 separately moving objects and them being
         | visually similar or even the same doesn't mean much
        
       | TheRealPomax wrote:
       | Can we take a moment to appreciate that the music starts in 10/8,
       | too? Because that's just the cherry on top.
        
       | donohoe wrote:
       | I assume it is 8 sprites but the "6" is also used to represent
       | the "9" and jumped (and rotated) from position to position?
        
         | JKCalhoun wrote:
         | That was my guess -- but I'm not familiar with the C-64 and its
         | sprite limitations.
        
         | badc0ffee wrote:
         | The limit on the C64 is, nominally, 8 sprites. Widely known
         | tricks exist to increase that to 8 per raster line, by IIRC
         | repositioning them during horizontal retrace.
         | 
         | This demo actually shows 9 "sprites" on the same raster line
         | using some clever tricks like low-res stretched sprites
         | combined with custom characters. It all makes sense once you
         | know the tricks, but the really impressive thing is how smooth
         | it is. Which I guess is why it features a magician.
        
           | pwrrr wrote:
           | You can't change the sprites every rasterline. Sprites are 21
           | pixels in height in unexpanded mode. So you can only change
           | the sprite after displaying all 21 lines, unless you use
           | sprite-crunching, where the limit is still several lines.
           | Linus has an article on sprite-crunching (mind-blowingly
           | complex).
        
             | Luc wrote:
             | > Linus has an article on sprite-crunching (mind-blowingly
             | complex).
             | 
             | https://www.linusakesson.net/scene/lunatico/misc.php
             | 
             | Great article.
        
               | pwrrr wrote:
               | Indeed :)
        
           | jll29 wrote:
           | The video demonstrates a second common trick: making use of
           | the black frame "outside" the screen buffer. Once the first
           | demos showed it was possible it quickly spread and nearly
           | everyone used it.
           | 
           | It's been a while, but I recall that you had to do some fancy
           | interrupt timing stuff for that. To find where that was in
           | the code, the same procedure applied that we used to find the
           | handler for background in the code of games: search for 0x78
           | (SEI), which temporarily blocked interrupts so background
           | stuff could be installed ("pseudo-multitasking").
           | 
           | We used to purchase a tape or 5 1/4" floppy disk with a game
           | per month and instead of playing the game, we competed who
           | could remove the music from the game the fastest (so that it
           | could play in the background alone, e.g. while writing code).
           | In the end that was a matter of just seconds for previously
           | unseen machine code using a hex monitor/disassembler. The
           | advantage of such a "teenage sports" is you will never forget
           | that "169 = A9 = load accumulator" and the rest of the MOS
           | 6510 opcode table, even after not using it for 40 years.
           | 
           | I wonder what today's kids will remember? (They seem to have
           | to Google each Python keyword, and they can't do anything if
           | WiFi is down for an hour, which worries me.)
        
             | badc0ffee wrote:
             | > they can't do anything if WiFi is down for an hour, which
             | worries me.
             | 
             | I worked with a younger guy on a pre-existing, large
             | project written in C. He saw me use the man command and
             | asked why I would do that - was I expecting to be offline?
             | But I don't think of man pages that way, I still think of
             | them as primary documentation. They're also specific to the
             | software versions on the system I'm logged into, unlike
             | whatever comes up when I Google `man 2 unshare`.
        
       | aqueueaqueue wrote:
       | Rabbit holed to this https://linusakesson.net/music/withering-
       | bytes/index.php
       | 
       | Thia is .... Something else!
        
         | noman-land wrote:
         | This dude's work is incredible. His entire YouTube channel is
         | amazing. My personal recent favorite, The Commodordion: "A
         | fully functional 8-bit accordion with bellows made out of
         | floppy disks." Legend.
         | 
         | https://www.youtube.com/watch?v=EBCYvoC4muc
        
         | junon wrote:
         | I want a Savant remix of that tune. It was so good.
        
         | relistan wrote:
         | Wow
        
       | neuroelectron wrote:
       | I probably don't understand it completely but from what I
       | gathered from Martin Piper's video is that the spite locations
       | and data are updated during the scan lines allowing the renderer
       | to reuse the same hardware sprites before the scanline is
       | complete.
        
       | yumraj wrote:
       | I didn't get. Can someone please explain what's impossible about
       | it?
        
         | themadturk wrote:
         | The problem is presented in the intro screen: The Commodore 64
         | only has eight independent sprites, yet this demo showed what
         | appear to be nine sprites.
        
           | yumraj wrote:
           | Thanks!!
        
           | panic wrote:
           | By putting all the sprites on one horizontal line in the top
           | "border", the demo also proves it's not using any of the
           | standard tricks to fake extra sprites. The only thing that
           | the C64 will draw up there are real sprites (not
           | character/bitmap graphics), and you can't multiplex sprites
           | in the same horizontal line of pixels.
        
           | mdp2021 wrote:
           | Not really the point: that is a tongue-in-cheeck trick, as we
           | know how to solve that problem - but it takes using different
           | stripes of the screen, whereas in the demo they are before
           | 2:00 all put in the same stripe...
           | 
           | At that point we go "Ah."
           | 
           | (It's very normal in illusionism: the practitioner states
           | something that puts you in the relaxed mood of participation
           | to a game you know - then actually surprises you.)
        
       | thih9 wrote:
       | Is there a text explanation of the trick - for those that cannot
       | watch a video?
        
         | exitb wrote:
         | The demo shows nine separate sprites, even though C64 supports
         | showing only eight. It starts off by separating them
         | vertically, which is a common trick, but then moves them all to
         | the same raster lines and overlapping locations, which is much
         | more surprising.
        
         | nottorp wrote:
         | By "cannot" i assume you mean you watched the demo video but
         | your life is too short to waste it on video explanations of
         | assembly tricks that are much better done in text? :)
        
           | account42 wrote:
           | Or he's somewhere where enabling audio is not an option.
        
           | human3047628272 wrote:
           | Some people have sight problems, or are even totally blind.
           | But they still use the Internet.
        
             | nottorp wrote:
             | Yeah but the OP sounds like they saw the demo and are
             | wondering how it's done now.
        
           | stavros wrote:
           | I don't know about the GP, but for me it meant "I have ten
           | seconds to understand this curiosity, but not 32 minutes. If
           | someone wanted to spend ten seconds explaining to the rest of
           | us, I'd be grateful".
        
         | masswerk wrote:
         | There are some basic debugging notes by Martin Piper:
         | https://github.com/martinpiper/DebuggingDetails/blob/main/Ni...
         | 
         | For better understanding: The demo starts with a magician
         | character drawn in the center of the screen, announcing the
         | trick in text (some of this is big text achieved by overlaying
         | sprites). Then, 9 sprites, each in the form of a colored number
         | from 1 to 9, exit the magician's hat to rotate around him (in
         | the notes screen #1), then, the screen gradually widens
         | horizontally beyond the usual borders and the circle of the 9
         | apparent sprites spreads out over the entire screen (screen
         | #2). (At this point, the display of the magician, which was
         | clearly drawn by PETSCII characters, before, shouldn't be
         | viable anymore.) The swirling numbers transition to a narrow
         | ellipse near the top of the screen (screen #3), which then
         | transition to the very top of the screen, above the normal
         | display area, a zone, which is available for sprites only,
         | showing the sprites in a linear rotation (screen #4). Meaning,
         | these must be sprites and these 9 apparent sprites are drawn at
         | the same scan-lines. (So there is no way this could have been
         | achieved by conventional, vertical multiplexing. This is the
         | highlight, the big trick of the magician's show.) At the end,
         | the sprites return to their initial circling motion and vanish,
         | one by one, into the magician's hat.
         | 
         | The demo is a combination of various tricks and artful timing,
         | which enables perfect transitions between them.
        
           | isoprophlex wrote:
           | The music is very, very good too.
        
           | thih9 wrote:
           | Video of the explanation, at the timestamp showing 8 sprites
           | that look like 9 sprites: https://youtu.be/Ik1vsMM2EuY?t=1509
           | 
           | > the last two Sprites there are multicolored mode; (...) we
           | have a different number of of high res mode Sprites and
           | multicolored Sprites and expanded Sprites; and those high res
           | and multicolor and some horizontally expanded Sprites are all
           | munged together and then the apparent view with animation of
           | the Sprite data as well the Sprite frames (...) gives an
           | apparent view of having nine independent Sprites; but we know
           | it's not, we know that it's a great big blob of eight Sprites
           | all grouped together horizontally (...)
           | 
           | via youtubetranscript:
           | https://youtubetranscript.com/?v=Ik1vsMM2EuY
        
       | yuchi wrote:
       | Posted it few days ago but didn't get any traction. All Linus'
       | work on retro computing is fenomenal. Please have a look at its
       | channel, a lot of awesome content there.
        
       | nerdralph wrote:
       | My guess is it is chasing the beam. Change the border color from
       | black to your sprite color, then back to black again. The change
       | takes a minimum of 4 cycles (store absolute), which I think
       | explains the thickness of the numbers. Some calculations
       | involving the PAL scan line frequency could confirm if 4 cycles
       | is quick enough.
       | 
       | edit for further detail: This would be used for one of the
       | numbers, with the other 8 using sprites.
        
         | nerdralph wrote:
         | As mentioned in other posts, the trick is using multi-color
         | sprites to look like multiple single-color sprites.
         | 
         | I did the scan line frequency calculations, and my though of
         | changing the border color would not work. In one cycle the
         | scanline advances 8 pixels, so toggling the border color would
         | be a minimum of 32 pixels in width.
        
       ___________________________________________________________________
       (page generated 2025-02-05 23:02 UTC)