Friday, 22 November 2019

Writing the 2019 Christmas Demo

Today we have another guest post, this time from Anton, describing how he created the nice little Christmas Demo for the C64, C65 and MEGA65.  This is a nice little program to explore, because it works out which machine you are on, and varies the display accordingly.  But let's have Anton explain it in his own words...
Hi everybody, i wanted to present you with a small background info about the
MEGA65 BASIC 2 christmas demo I have just coded together with Paul.
A Forum64 member (ZeHa), started last year a project on forum64.
The idea was, to bring back the times of the 80’s, when you went to your local store, bought the latest computer magazine and started, once at home, to type the listings into your beloved 8-bit machine. So he collected last years, xmas themed BASIC listings from board members and put them together in a magazine.

So, this year, he contacted us, the MEGA65 team, if we wouldn’t be interested in providing a nice program as well. We’ve discussed this in the team and we all loved the idea. So I agreed to program something in BASIC. (I haven’t done any BASIC coding since the 80’s…..)

I knew from the beginning, that I would like to code something, that would run on every C64 but I also wanted to demonstrate, what the MEGA65 is capable of.
So that’s when I settled on BASIC 2. One of the biggest advantages of the MEGA65 really is, that you can be in normal C64 mode, you activate the VIC-IV features by Poking :

POKE 53295,71:POKE 53295,83


and you have all the VIC-IV features available at your hand. Easy as that !!!

I started to think about the demo and xmas-themed requirements and slowly an idea formed into my head. I contacted Paul and asked him, if there is a way to find out, if  there is a VIC-II present, like on the c64 or a VIC-III like on the c65 or a VIC-IV, the MEGA65 is using. So after some testing we had a nice code snippet ready to check, what machine our program is running on:
(I love the name, we call it “Knock Knock”-routine)

13710 REM *** "knock knock" TO CHECK WHAT VIC IS USED (c64/c65/MEGA65) ***
13720 REM In c65 Mode we cannot safely write to 53295, so we test a different way
13810 IF PEEK(V+24)AND32THENGOTO14410
13910 POKEV,1:POKEV+47,71:POKEV+47,83
14010 POKEV+256,0:IFPEEK(V)=1THEN VC=65:C$="VIC-IV":RETURN
14110 POKEV,1:POKEV+47,165:POKEV+47,150
14210 POKEV+256,0:IFPEEK(V)=1THEN VC=65:C$="VIC-III":RETURN
14310 VC=64:C$="VIC-II":RETURN
14320 REM we assume we have a c65 here
14410 V1=PEEK(V+80):V2=PEEK(V+80):V3=PEEK(V+80)
14510 IF V1<>V2 OR V1<>V3ORV2<>V3THEN VC=65:C$="VIC-IV":RETURN
14610 GOTO14110
So after I was able now to check, what machine my code is getting executed on, I could start with my demo. I wanted to make something simple, nice to watch and completely in BASIC.
Several people have asked already, how the 15 colour sprites on the MEGA65 are working, so I thought, this should go into the demo as well.

The idea shaped. After I found out, with a lot of help from Paul (Thanks Paul !), how the 15 colour sprite works, I started to design a 15 color sprite.

For a rough understanding:
The c64 sprites are using in HiRes mode 24bit x 21 bits so a standard sprite is 24 by 21 pixels
The multicolor sprites are using 2  bits for each color which leaves us with 12 doublewide pixels x 21 pixels. So a sprite on the c64 is using 63B (64)Bytes (one Byte stays empty).
The  MEGA65 VIC-IV is able to show a 15 color sprite, which is 16 pixels horizontally x 21 pixels vertically.
Each pixels colour is set by one Nibble (4bits) so a MEGA65 15colour sprite is 64bits horizontally and 21 bits vertically. This means:
4bits x 16 =  64 bits horizontally (8 Bytes)
64 x 21 = 1344 bits or 168 Bytes.
This means, that for a 15 color VIC-IV sprite you have 168B of Data.
The memory area at $0340 would be perfect. So I started drawing a concept.
Have a look: (PS, the blank middle line was removed by moving the right side of the tree one pixel to the left)
I have to say I was amazed, to see how much you can realize with a sprite with such dimensions !
Paul wrote a nice code snippet, which might not be the fastest routine to get the 15 colour sprite poked to the right memory address area, but it was a very good study example of HOW it works.
Have a look here:
(all the standard sprite commands like, positioning, sprite pointer, etc. remain exactly like it would be a normal HiRes sprite. here in this part you only see the commands, that are different from VIC-II)
(You can see, that I am using in this routine already the checks done in the previous code snippet, to see, what VIC is used.)

45 REM IF MEGA65 ENABLE VIC-IV FEATURES
48
IFC$="VIC-IV"THEN POKE V+47,71:POKE V+47,83

255 REM *** VIC-IV 15 COLOR SPRITE SETUP ***
260
REM IF NO MEGA65 JUMP TO 390
265
IF C$="VIC-II" OR C$="VIC-III" then goto 390
270
REM SET ADDRESS 15COL SPRITE TO $0340 (832)
275
AD=768+64
280
REM MAKE SPRITE 3 - 8 AS 15COLOR SPRITES AND MAKE THEM USE 64 BIT
285
POKE V+107,252:POKE V+87,252
290
REM COPY STANDARD COLORS OVER FOR MULTICOL SPRITES 3 - 8
295
FORI=16TO255:FORJ=1TO3:POKEV+256*J+I,PEEK(V+256*J+(I AND 15)):NEXTJ,I
315
REM READ 15COL SPRITE DATA
320
READN$:IFN$="end"THEN 390
325
REM JUMP TO DECODE ROUTINE
330
GOSUB 345
335
GOTO 320
340
REM DECODE STRING OF NYBLS IN N$ AT ADDRESS AD (832)
345
L=LEN(N$)
350
FOR I=1 TO (L/2+1):POKE AD+I,0
355
FOR I= 1 TO L:N=ASC(MID$(N$,I,1))-64:IFN<0THEN N=0
360
B=AD+INT((I-1)/2):IF (I AND 1)=1 THEN N=N*16
365
VA=PEEK(B):POKE B,VA OR N:PRINT"{home}";VA:NEXTI
370
AD=AD+INT(I/2)375 IF (L AND 1) THEN AD=AD+1
380 RETURN

1445 REM 15 COLOR TREESPRITE DATA 
1450 REM "-" = TRANSPARENT, "A"-"O"" = COLOURS 1 TO 15 
1455 DATA "------HGH-------"
1460 DATA "------GGG-------"
1465 DATA "------HGH-------"
1470 DATA "-------G--------"
1475 DATA "------EEH-------"
1480 DATA "-----E-EBE------"
1485 DATA "------ENB-------"
1490 DATA "-----EEEEM------"
1495 DATA "----EHEEEEE-----"
1500 DATA "---E-B-EE--E----"
1505 DATA "----EBEEENE-H---"
1510 DATA "---CEEEHEEEEB---"
1515 DATA "--EE--EBE--EB---"
1520 DATA "---HEEEBCEE-----"
1525 DATA "---BEEEEEEEE----"
1530 DATA "--EBE-EEEEEHE---"
1535 DATA "-EE--EEMEE-BEE--"
1540 DATA "H--EEEEECEEB----"
1545 DATA "BEEENEEEEEEEEE--"
1550 DATA "BEEEE--I--EECEE-"
1555 DATA "-------I--------"
1560 DATA "END"


I would like to mention, by setting the sprite color, you define the transparent color.
So if our Tree is sprite 3, by setting 53290 ($D02A) to 0 (Poke53290,0) you set Black(0) as transparent color for sprite 3 (53290).
Line 290 & 295 might also be worth mentioning as well. There we copy the RGB values of the 16 standard colors from Sprite 1 color bank over to the Sprite colour bank of sprite 3 – 8.
This means, you can set not only 15 colours per sprite, but also can define how these colors look like.
You have the RGB values under your control.



  
OK, but back to the demo. So I was drawing several other sprites (since I already knew, that people who have  a normal c64 or a c65 wouldn’t be able to see the 15color sprite), and started to put everything together as I continued to program in BASIC 2 I realized soon, that on a normal c64 with 1 MHz I would not be able to realise all the things I wanted to show.
But the MEGA65 is able to switch between 1MHz/2MHz/3.5MHz and 40MHz !!!




This was the idea I was looking for !!!  enable certain features of the demo, only if the machine is able to support a certain speed:
C64 max 1MHz.
C128 max 1MHz (2MHz not useable, since FAST mode on c128 disables screen)
C65 1MHz/3.5 MHz
MEGA65 max 40 MHz
 

So after I knew, what VIC my program is running on, I was able to tell what the maximum speed would be, that this machine can support.
So I needed some code to do the frequency change. After checking the VIC-III and VIC-IV registers, since the official MEGA65 manual is having all the necessary information:


I came up with this code snippet:


935 REM *** FREQUENCY CHANGE ***
940 REM SWITCH TO 2MHZ
945 IF MH=1 AND C$="VIC-IV" THEN GOSUB985:POKEV+48,1:MH=2:GOTO995
950 REM SWITCH TO 3.5 MHZ
952 IF MH=1 AND C$="VIC-III" THEN POKEV+49,64:MH=3.5:RETURN
955 IF MH=2 THEN GOSUB985 POKE0,64:MH=3.5:GOTO995
960 REM SWITCH TO 40MHZ
965 IF MH=3.5 AND C$="VIC-IV"THEN GOSUB985:POKE0,65:MH=40:GOTO995
970 REM SWITCH TO 1 MHZ
972 IF MH=3.5 AND C$="VIC-III" THEN POKEV+49,0:MH=1:RETURN
975 IF MH=40 THEN GOSUB985:POKE0,64:MH=1:GOTO995 
980 REM DISABLE VIC-IV FEATURES
985 POKEV+47,0:POKEV+48,0:RETURN 990 REM ENABLE VIC-IV FEATURES
995 POKEV+47,71:POKEV+47,83
1000 IF MH=40 THEN POKEV+49,0
1005 IF MH=3.5 THEN POKEV+49,64
1010 RETURN

So the c64 would run our nice Christmas demo with the least functions, while on the MEGA65
You can see all the functions implemented (including the 15 colour demo Sprite).
So if the demo is running on a machine > c64/c128 an extra text is shown, which asks you to press
(depending again on what machine it’s running) “SPACE” to cycle between standard Multicolour Sprite and 15 colour VIC-IV Sprite, or “F” to cycle through the freqencies.

This is more or less, the main idea behind the demo. It will run on a c64 also on a c65 and on the MEGA65 and it shows some of the features the MEGA65 offers.
So if you are interested in the demo, hop over to forum64 (this is also the official MEGA65 forum)
Just mention in the Thread, that you want to receive a copy of the forum64 2019 christmas magazine.

So to conclude: I want to wish all of you a merry Christmas 80’s style...

Anton


5 comments:

  1. Great!!!!!!!!!! This was developed in the M65 or the emulator? Thanks.

    ReplyDelete
  2. No, Anton wrote it using one of the MEGA65 pre-series machines. But it would be possible to do so in the emulator.

    ReplyDelete
  3. to be honest, i wrote the code with CBMprgStudio & C64studio, transfered it to a real 3.5 floppydisc and then tested it on the MEGA65 (floppydrive)and the Nexysboard(microSD d81) ;-)
    Since i was using BASIC 2, this was easy. Next Year it will be more interesting, when i re-code the Demo in BASIC 10

    ReplyDelete
  4. Ha, I havent read any BASIC listing since the DATA BECKER Books from the 80ies.

    ReplyDelete
    Replies
    1. Then we really hope, you have enjoyed the read. This code is probably something you have never seen before ;-)

      The last time, i had SO much fun coding in BASIC, was in the 80's. It was exactly the same feeling of dicovering something new...

      Delete