-
Another day, another cat drawing. This time our more blocky version of a feline fellow creature. Sketch in ibisPaint X and final drawing in Commodore 64 multicolor bitmap (160 x 200 resolution, 16 colors). If I could, I’d knit him a cozy sweater.
๐ฑ๐จ๐จโ๐ป๐น๏ธ๐พ -
It’s always good to have a firm mental picture of one’s (artistic) process, as to not get bogged down by the details. I’ve updated the C64 multicolor illustration I did yesterday, and separated it into 4 “colors”:
- background color 0 (white)
- ditto 1 (black)
- ditto 2 (red)
- other colors
-
I had a few lock up with my iPad lately. Now it’s even in recovery mode, trying to restore from iCloudโฆ
Update: I’m back on the iPad. Pfew!
-
I think I’m starting to grasp how to draw in C64 multicolor. You get three colors that can be used anywhere, and per 8 by 8 pixels block you get to pick another color out of 16 possible colors. Careful placement of the pixels is key. If you do it right, you can have a very colorful image
๐จ๐จโ๐ป๐น๏ธ๐พ -
Just for kicks, I tried to color a random doodle I made. I had to redraw some of it to be able to work around the limitations of multicolor bitmap graphics on the Commodore 64. Other than that, and that it takes a lot of time, it went well.
-
Another day, another cat drawing for the old Commodore 64
๐ป ๐จ ๐จโ๐ป ๐น๏ธ ๐พ -
I reworked an older self-portrait that I made last year as a pixel art drawing, and turned it into an image on the Commodore 64. I like that the limited color palette doesn’t seem to limit me as much as it used to. It takes some effort (well, a lot of effort), but I think it was worth the time.
๐จ ๐จโ๐ป ๐น๏ธ ๐พ -
Here are some of the steps I took to create a multicolor pixel art drawing of a cat.
drawn in ibisPaint X in 4 colors
traced and redrawn in Pixaki
made into C64 runnable multicolor art with MultiPaint, loaded into VICE C64
It’s a process, taking many hours to complete. I think I’m improving.
๐จโ๐ป๐จ
-
Making room for two text screens, so I can use them for buffering is great, but running it from C64 Basic is one ugly hack, and slow too. But I’ve done it, which is great, since I learned a lot from it, and that was the whole point here. The code I keep, in case I need (some of) it ๐จโ๐ป
-
Flipped ๐ท
-
I fired up my art app and sculpted on a canvas the size of a retro-computer’s text character (8 pixel wide and 8 pixels high). I had to struggle, because the app wanted it to look nicer than it really was.
I suppose you can already guess what it represents. You can do a lot in 64 bits of data ๐จโ๐ป๐จ
-
Okay, I have a Basic loader with M/L code that enables a screen buffer and has a handy relocatable M/L routine at
$C000
that copies 1024 bytes. Bits 4 - 7 of$D018
control which part of memory is used to display the screen. Now I have all I need for moving a block of characters in C64 Basic, right? ๐จโ๐ป -
Make room for a screen buffer in C64 Basic
In my previous post in which I moved a box across the screen with a Basic program, I wanted to use a screen buffer. The default screen location starts in memory at
$0400
(1024 decimal), and we can move the screen in units of 1024 bytes. The next location would be$0800
(2048 decimal), which is where Basic text lives. Luckily we can move the start of Basic up with apoke
at location 44, but we also have to move the bytes of the Basic text to the new location, or you’d get a jibberish Basic text. The most obvious location is$0c01
(3097 decimal), and it makes sense to do this outside of Basic, with the raw power of the 6510 CPU.The machine language (M/L) program
enablebuffer
does just that. Here’s the source code listing. It has some Basic code to run the M/L code and relocate the start of Basic text. The M/L code is a bit more complicated than it needed to be, but I like some headroom in case I want to include more Basic text in front of the M/L code or put some M/L code in a convenient location, so we cansys
orusr()
to it. The code should be able to copy Basic text in front of the M/L code, no matter how big it would grow.; enablebuffer.asm ; ; Move the start of basic from $0801 to $0c01 ; ; Now both 1024 - 2023 and 2048 - 3047 ; can be used as screen memory. ; This makes it possible to use a screen buffer ; in Basic. PROCESSOR 6502 ORG $0801 ; Basic text in front of ML code ; 10 SYSXXXX:POKE44,12:CLR BASIC1: HEX 14 08 0a 00 9e .dc sys_address ; replaces the "XXXX" BASIC2: HEX 3a 97 34 34 2c 31 32 3a 9c 00 00 00 sys_address: eqm (start_ML)d ; start of ML code start_ML: vect1: eqm $02 vect2: eqm $04 BASstart: eqm $2B LDA BASstart+1 CMP #$08 ; is start of basic at $0801 ? BNE exit ; no, then exit ; set up copy process ; copy $0801 to $0C01 until the end of file ; copy start at the end towards the beginning CLC LDA #
exit STA vect1+1 ADC #$04 ; move 1024 positions higher in memory STA vect2+1 LDY #$00 loop1: LDA vect1+1 ; copy in blocks of 256 bytes CMP #$08 ; less than 256 bytes to copy? BEQ loop2 ; yes, then loop2 instead loop1a: LDA (vect1),Y ; fast copy 256 bytes STA (vect2),Y DEY BNE loop1a DEC vect1 ; next 256 byte DEC vect2 BNE loop1 DEC vect1+1 DEC vect2+1 BNE loop1 loop2: LDA (vect1),Y ; copy remainder of bytes STA (vect2),Y ; between 1 and 255 DEC vect1 DEC vect2 BNE loop2b DEC vect1+1 DEC vect2+1 loop2b: LDA vect1+1 CMP #$07 BNE loop2 exit: RTS We can load the program as an ordinary Basic program and then run it.
After that we can
new
the Basic program and start writing a new Basic program, at location$0C01
instead of the default$0801
! Of course, the M/L code will be overwritten by that new Basic program, but that’s okay, since we no longer need it at that point. -
With all the blogging I do daily, I wanted to automate correct capitalization. I reworked an shortcut that no longer worked to a working state. Select text, share, pick one, paste.
- all lower case
- UPPER CASE
- Title Case in Case You Want It
- Capitalize A Okay
- Sentence. After each. Sentence.
-
Moving a box across the text screen in C64 Basic
I was wondering how to move a collection of characters (e.g. a box) across a Commodore 64 text screen. It’s rather easy to do this destructively. In Basic, I wrote something that horizontally moves a 3-by-3 character rectangle constructed out of PETSCII characters.
10 rem *** 11 rem *** setup 12 rem *** 20 restore:read w,h:for i=0 to w*h-1 30 read a(i):next i 40 data 3,3 50 data 112,64,110,93,32,93,109,64,125 60 te=200 100 rem *** 101 rem *** main loop 102 rem *** 110 os=0 120 for p=1024+12*40top+40-w 130 gosub 200:gosub 300:next p 140 os=w-1 150 for p=1024+13*40-w to p-39+w step-1 160 gosub 200:gosub 300:next p 170 goto 100 199 end 200 rem *** 201 rem *** draw a box 202 rem *** 210 for x=0 to w-1:for y=0 to h-1 220 poke p+y*40+x,a(y*w+x) 230 nexty:nextx:fort=0tote:nextt:return 300 rem *** 301 rem *** clear column 302 rem *** 310 for y=0toh-1:poke p+y*40+os,32:next 320 return
The program has to do some clean-up after it has drawn a box with the subroutine
draw a box
. It fills the box’s trailing text column with space characters (screen code 32). For instance, if the box moves to the right and the box has been drawn in its current position, the left-most text column of that box has to be “cleared” (filled with spaces). Otherwise it will leave behind box characters when the next position of the box is drawnโone position to the right. Themain loop
uses the variableos
(offset) to determine which text column should be filled with spaces, using the same subroutineclear column
when moving the text box to the left or to the right.It’s all very limited in what this program can do. It can move the box either one character position to the right or the same to the left, nothing more.
For a more sophisticated
draw a box
subroutine, it has to know where it was before:- restore the original content of the previous position (if any)
- read the current content where the box will appear and store it for later
- draw the box onto its position on the text screen
We can do this in Basic as well, even though it’s rather slow and has clear visual artifacts. Here’s the code for the same 3 by 3 text box, now jumping to arbitrary positions on the screen, while keeping the screen intact.
10 rem *** 11 rem *** setup 12 rem *** 20 restore:read w,h:for i=0 to w*h-1 30 read a(i):next i 40 data 3,3 50 data 112,64,110,93,32,93,109,64,125 60 te=200 70 first = (1 = 1) 100 rem *** 101 rem *** main loop 102 rem *** 110 x=int(rnd(ti)*(40-w)) 120 y=int(rnd(ti)*(25-h)) 130 gosub 200 140 goto 100 199 end 200 rem *** 201 rem *** draw a box 202 rem *** 210 rem *** restore any orig'l content 211 rem *** 220 if first then first=(1=0):goto 300 230 for xx =0 to w-1:for yy=0 to h-1 240 poke p+yy*40+xx,a1(yy*w+xx) 250 nextyy:nextxx 300 rem *** 301 rem *** read current text content 302 rem *** 310 p=1024+40*y+x 320 for xx=0 to w-1:for yy=0 to h-1 330 a1(xx+yy*w)=peek(p+xx+yy*40): 340 nextyy:nextxx 400 rem *** 401 rem *** put box on screen 402 rem *** 410 for xx=0 to w-1:for yy=0 to h-1 420 poke p+yy*40+xx,a(yy*w+xx) 440 nextyy:nextxx 450 for t=0 to te:next 460 return
The long wait loop (which makes the program perform so slow) is so that you can spot the random 3-by-3 box, while also making the artifacts less noticeable. You can see the box long enough, so it disappearing from screen will feel less jarring. A better solution than waiting a while would be to use a screen buffer to do the drawing and switch screen buffers when all the drawing is done for the new position of the box.
I guess that would require some machine language I have yet to write.
-
I wondered if a sprite rendered as a text character would make sense. It would have to move to one of the 1000 positions on a text screen of 25 lines and 40 columns in a C64. The character is 2 by 2 text characters, has 3 walking poses, and two extra text characters for the SFX. It could work ๐จโ๐ป
-
I found this video game poster via an image search, which clearly isn’t from a C64 (size 640 x 400 pixels, different 16 colors than C64). I thought about recreating it in C64 multicolor for self-education. The first step in my analysis was recoloring it into the Colodore color palette, an idealized version of the C64 color palette(s). It seems to be drawn for the Amiga. It has 3 shades of red and of green; the C64 has only 2 of those. Plus, it has a flesh color, which the C64 sorely lacks.
I found an interview with the mentioned Peter Johnson on Codetapper’s Amiga Site. And it appears he rewrote the C64 version for the Amiga. No mention of who drew the poster. Peter did draw the game art, I assume. Alas, there’s no date stamp on the article, but judging from the copyright notice it’s probably from 2020, but it could be as early as 2016.
Now will I recreate the poster? Probably not, but it’s a good reference to have, to see what good illustrators were able to whip up in a short amount of time. Even back then, the games industry was brutal. Games did last as long as they were popular. There was always something newer and better to draw the attention of gamers. Time was a-wastin', always.
๐ฎ
-
Luckily, the SPEEDLINK SL-650212 BKRD Competition EXTRA Joystick I bought off Dutch Amazon works with VICE C64 on my Raspberry Pi-400 computer. I read a review somewhere that it did, but reviews can be wrong, high ratings bought by the manufacturer. So I took a chance and it paid off ๐ฎ
-
I would prefer owning a Mac, but I simply canโt rationalize the “Apple tax.” I used to be Mac or Die. A computer is more like a way to access the Internet nowadays, anyway ๐จโ๐ป๐พ
-
It’s all very technical, this Commodore 64 multicolor mode. I made a special 2x1 grid in my iPad pixel editor to help me, but still I need to check in an actual multicolor editor if I made a mistake. Anyway, I’m improving as a C64 pixel artist, and that’s very cool ๐จโ๐ป