Jump to content


  • Posts

  • Joined

  • Last visited

  • Days Won


Everything posted by CursorKeys

  1. Thanks for pointing this out! It seems this is for all posts in category tutorial the case. I'll enable it for sure when I post something in the other categories, as I thinks it's an awesome feature.
  2. Thanks for the welcome rje It's cool to be again coding in "old" BASIC, it's been years (feels like eons), I've completely forgotten the struggle with line numbers, 80 character limit, short variable names, and only global variable scope. Then again, it's lovely to poke directly to the hardware instead of going through magic layers that do it all for you. I am liking how easy it is in Basic, but on ASM or C level it seems more tricky, as you need to go through a few registers and prepare them before you poke your data. That'll be sure a challenge when/if manage to get around to code in C or Assembly. For me the python deal breaker is more or less the syntax for blocks. The invisible spaces / tabs, to indicate a subscope. Not my cup of coffee. Give me curly braces any day of the week (Although I did try a neural network in it once, but it became quite annoying to swap to another language with curly braces and back, I kept messing up the tabs in both languages, anyway, I am rambling now, so I better stop, see you in the forums / software library projects ..)
  3. ok, it seems that feature is not there in this category, to specify the executable. (And I'm not really happy to move it to the wrong category), so for now it'll stay without the try it now feature. Maybe the end result, when the tutorial is done, can get it's own entry in games, if it turn out interesting enough
  4. True. I haven't figured out yet how to add this option, it's been on my todo list to ask, but I wanted to search more myself, in case I am missing the obvious, to avoid a stupid question Anyway, I want to add it. And I was thinking I was not having enough creds or something to activate it. If you have any tips how to do it, I'll do it immediately.
  5. Hi all, I recently stumbled onto this website. My reason for being here is mostly to track progress, and as a potential buyer when x16 is for sale. I really like the project, it is almost like looking forward to the next cool computer, but a next cool computer in an alternative past. I am a developer/techlead myself, doing solutions for b2b. But as a Hobby I have spend tons of time playing with and programming the C64 and the Amiga, programmed basic, c & assembly 6502/68000. Also other weird and wonderful languages, and a bit of hardware soldering. No Python though, not really my thing. Right now though I am doing "hobby coding" in Javascript, a X16 sprite exporter to my paint program, and deciding if I will do some c or ASM stuff as well for the X16, or keep to BASIC. I got here when I was playing around with BASIC a bit. I started at a web page where you can directly type in and run Apple basic, but soon ended up modifying Apple basic to become more like commodore basic. (I was adding things like sprite support and so on to the Basic, and a commodore 64 sprite displaying capability. Anyway while doing that I happen to stumble on the X16 emulator webpage, which already had all that. So yeah apple basic with c64 sprites is how I got here I really hope the web ide / emulator will continues to be developed, as I like it a lot, almost more then the "real" emulator. Fantastic project otherwise. keep up the good work! Same for the YouTube channels 8-bit guy, and retro recipes, just a tad to addictive Greetings from Sweden
  6. Ok two chars for the device, that makes sense. But yes, it also throws I/O ERROR for me. I tried many device numbers. I guess I have to find some other route in assembly. Maybe I'll give cc65 a try. Thanks!
  7. Hi! I hope I am not repeating and old question, but I am just getting into the X16, and I did search the forums, and found no answer. I am trying the monitor "MON", inside the X16 emulator, to write a rudimentary assembly program. However I have issues with the "S" command. I checked the syntax for the save (S) command over here: https://rr.pokefinder.org/rrwiki/images/7/70/Final_Cartridge_III_english_Manual.pdf (search for THE MONITOR [12.0] ) Syntax: S "<file-name>",xx,yyyy,zzzz xx = device number 01 for tape 08 for disk yyyy = the start location of the program zzzz = the end location of the program + 1 I tried to save memory location $2000 to $2100 to disk, below are my attempts: Attempt1, assume, device is 8 S "TST",8,2000,2100 fails, output -> S "TST",8,?000,2100 (see the ? sign in the output on the left) Attempt2, assume, device is 1 S "TST",1,2000,2100 fails, output -> S "TST",1,?000,2100 Attempt3, assume, device is not needed S "TST",2000,2100 fails, output -> S "TST",20?0,2100 So I assume the second param must be the device, as well on the X16, but I am not sure which. Since attempt 3 marked the second param as wrong. So I tried from 0 up to 9, no differences. Then I maybe the syntax of the start address is wrong. Attempt4, assume, address starts with $ S "TST",8,$2000,$2100 fails, output -> S "TST",8,?2000,$2100 Then I was thinking maybe param nr 3 is a string, so I tried as well, and what about if the addresses are supposed to be "large" addresses, which I tried as well. No luck so far. Any help appreciated! Thanks /C
  8. Version 1.0.4


    A simple game fully in Basic. NOTE: If you just want to run the latest version of this game on the Web based emulator do like this. 1. Copy the code from: https://raw.githubusercontent.com/JoystickAndCursorKeys/x16basic/main/fallingsnake.v4.bas.txt (CTRL-C) 2. Go here: https://www.commanderx16.com/emulator/x16emu.html and paste the code. (CTRL-V) 3. Press "Run" This (version 0 of the game) is a very little game I wrote on the commodore 64 ages ago, I changed it a little to work with vpeek, vpoke, the new color command, and the new screen resolution. To me starting with a simple game in basic is how I learned about the c64, and now the X16, before jumping in machine language. In the code for this game you can see practical examples, on how to set characters on the screen, read characters from the screen, change colors for characters, listen to the keyboard, set a screen mode. What surprised me was that I needed a delay in the code in order to have it not run too fast. This was not the case on the c64. I really like the way you can use the emulator in the browser, as it allows you to type in basic inside the browser, using "regular key mappings", and the run it. When I wanted to save it, I copy-pasted it into the installed emulator (hats off for who added he paste function there), and types the save command. This was done, because in the browser you cannot save it, and see it on disk (as far as I know) I added many REMs in the code, in order so it can be understood, and it is more of a tutorial, then a "real" game. Below I will go through the code. From line 5, the program initializes From line 9, the title screen is drawn From line 49, the game is initialized From line 199, the game loop starts From line 300, the game over screen is drawn Some miscelanious notes: The SCREEN command is used to set the screen in text mode (Petscii) 40x30 The color command is used to set character fore and background colors. Unlike the c64 each char has its own background color. There is no "global" background color CHR$(113) is used to draw the Petscii circle character, used on the title screen. Adding the actual character into the code listing, makes it hard to edit outside the emulator. CHR$(119) is another Petscii character VPOKE 0,0,x, pokes a character on the top level corner of the screen. So the text screen address = 0 (not like on the C64) On line 52 the bottom of the screen offset is calulated. NOTE: Even though the screen is 40 chars long, to get to VPOKE address of the next line, you need to add 256 bytes. SI and PI (StoneImage and PlayerImage) are Petsci chars, that are used in the game. NOTE: Petscii chars have different values in the PRINT or the VPOKE commands. Reminder: In C64/Microsoft basic a variable name is only two characters long max. Reminder: Lines in Basic should not be longer then 80 chars. When you make them longer, the emulator ignores them. A good place to see all PETSCII character codes is here: https://www.commanderx16.com/forum/index.php?/files/file/23-vera-chars/ Have fun! And the code itself: (it is easier to copy paste it in the browsers emulator and be able to modify it more easy here: https://www.commanderx16.com/emulator/x16emu.html ----- code below for copy & pasting, also you can get it by downloading FALLSNAKE.PRG or checked out at: https://github.com/JoystickAndCursorKeys/x16basic/blob/main/fallingsnake.v0.bas.txt----- 5 REM SET TO 40X30 CHARS SCREEN 6 SCREEN 0 7 HM$=CHR$(19) 9 REM TITLE SCREEN ----------------- 10 REM SET COLORS TO BLACK AND WHITE, CLEAR SCREEN 11 COLOR 1,0: CLS 12 PRINT:PRINT:PRINT:PRINT : REM PRINT TITLE 13 PRINT " FALLING SNAKE": PRINT: COLOR 15 14 PRINT " YOU ARE FALLING DOWN A HOLE" 15 PRINT " AVOID ALL OBSTACLES" 16 COLOR 7: PRINT " PRESS SPACE TO START" 17 BA$=CHR$(113):BB$=CHR$(119) : REM BALL SYMBOLS 18 COLOR 2,0 : PRINT " "+BA$ 19 PRINT " "+BA$:PRINT " "+BA$ 20 PRINT " "+BA$+BA$+BA$+BA$+BA$+BA$+BA$+BA$+BA$;:COLOR 8:PRINT BB$ 25 GET A$: IF A$="" GOTO 25 : REM WAIT FOR KEY 35 TS=0 : REM SET TOP SCORE 49 REM START GAME ----------------- 50 COLOR 1,0: CLS 51 FOR T=1TO29:PRINT:NEXT 52 BO=29*256:SI=42: : REM BOTTOMSCREENOFFSET, STONEIMAGE 53 PO=15*256:PI=81:PC=2:PX=20 : REM PLAYEROFFSET, PLAYERIMAGE, PLAYERCOLOR 54 DE=1000 : REM DELAY VALUE 55 S=0 : REM SET SCORE 199 REM GAME LOOP ----------------- 200 GET A$ 201 IF A$=CHR$(29) AND PX<40 THEN PX=PX+1 : REM GO RIGHT 202 IF A$=CHR$(157) AND PX>0 THEN PX=PX-1: REM GO LEFT 210 X=INT(RND(1)*40)*2: C=INT(RND(1)*15)+1 : REM GET RANDOM STONE POSITION 211 PE=VPEEK( 0, PO+(PX*2)) 212 IF PE=SI THEN GOTO 400 220 VPOKE 0, BO+X, SI: VPOKE 0, BO+X+1, C 221 VPOKE 0, PO+(PX*2), PI: VPOKE 0, PO+(PX*2)+1, PC 296 FOR W=1 TO DE: NEXT : REM DELAY, SLOW DOWN CODE 297 PRINT : S=S+1 : DE=DE-1 : IF DE<0 THEN DE=0 298 GOTO 200 399 REM GAME OVER ----------------- 400 IF S>TS THEN TS=S 401 PRINT HM$:PRINT:PRINT:PRINT " GAME OVER": PRINT 402 PRINT " SCORE: "+STR$(S); 405 PRINT " TOP SCORE="+STR$(TS) 410 COLOR 7: PRINT: PRINT " PRESS SPACE TRY AGAIN" : PRINT:PRINT 420 GET A$ 421 IF A$ = "" OR A$=CHR$(29) OR A$=CHR$(157) THEN GOTO 420 422 GOTO 50 ---------------------------------------------------------- End of Code First Version ---------------------------------------------------------- The way I normally work when creating a game, I create first the skeleton, and then add more and more niceties, like effects, and game play elements. Above, we have the skeleton, we have a minimal game. We have a title screen, we have a playable section, we have a score, a game over section, and a high score. Below I will show the improvements I made so far, and are saved in FALLSNAKE2. In the init section of the program, I rearranged the line numbers, so I would not overlap with the rest of the program, when adding two more lines. The added lines are in Bold/Underline. Line 3, I allocate an array called EX to store the "petscii picture" of an "explosion". It is 9 chars. The "picture" is 3x3 chars. No colors. 3x3=9, which is how much we need to allocate with the DIM command. Line 4, reads data from the DATA statements at the end of the program into the array called "EX". 0 REM SET TO 40X30 CHARS SCREEN 1 SCREEN 0 2 HM$=CHR$(19) : REM HOME CHARACTER 3 DIM EX(9) 4 FOR T=0TO8: READ C : EX(T)=C: NEXT : REM READ PETSCII EXPLOSION In the "Game over" section of the game, I added the drawing of the explosion picture, and a flashing color effect to go with it. Again, I renumbered the code around it a bit. We iterate through the characters in the EX array, by looping x and y from 0 to 2, and calculating the offset to EX (called DO, data offset). We use VPOKE to put the bytes on the screen memory, at address SO (screen offset). SO is calculated by using the xx + the player y coordinate, minus 1 (this will be XS). Similar will be done for y, but to calculate SO, we add XS*2 (each char takes two bytes) + YS*256 (from one row to the next the distance offset is 256 chars) 401 REM DRAW EXPLOSION 402 FOR XX=0TO2:FOR YY=0TO2 403 XS=XX+PX-1: YS=YY+15-1 : REM SCREEN X,Y 404 IF PX<1 THEN XS=XX+1 : REM CHECK PLAYER X TO BE ON SCREEN 405 IF PX>38 THEN XS=XX+38 406 DO=XX+(YY*3):SO=(XS*2)+(YS*256) : REM CALC DATA OFFSET, SCREEN OFFSET 407 VPOKE 0,SO,EX(DO) : REM WRITE TO SCREEN 408 NEXT:NEXT Below there is a simple color cycling effect for the background, this is done by adding random values into palette register for color 0. The register is stored in two addresses, $FA00 and $FA01. Actually some bytes are not used, but for a random effect we ignore that. If we want to have for example a red explosion flicker, we need to be more careful on the values we put into the register. 410 REM EXPLOSION COLOR EFFECT 411 FOR T=1 TO 50 412 C0=INT(RND(1)*255) 413 C1=INT(RND(1)*255) 414 VPOKE 1,$FA00,C0: VPOKE 1,$FA01,C1 415 NEXT: VPOKE 1,$FA00,0: VPOKE 1,$FA01,0 and the last part (after renumbering even more lines of code), we added the data for the explosion petscii "picture". 2000 REM PETSCI EXPLOSION 2001 DATA $4D, $20 , $4E, $20, $D6, $20, $4E, $20, $4D The complete code can be found in FALLSNAKE1.PRG, or checked out at: https://github.com/JoystickAndCursorKeys/x16basic/blob/main/fallingsnake.v1.bas.txt One thing that keeps me going when creating a game, is but adding sessions where I make the game look nicer, without adding functionality. The changes below (1.0.2 version, FALLSNAKE2.PRG), is all about this. Just Renumber it To start off, we have been renumbering again the lines of the source code. For those that are not used to using old school type basic, it is very easy to add extra code and run out of numbers. And it is important to "reserve" numbers. So for example if you make a program like this. 1 PRINT "HELLO WORLD" 2 GOTO 1 And you want to add something between line 1 and 2, you cannot do it, unless you renumber the existing lines. For that reason it is a better idea to start coding like this: 10 PRINT "HELLO WORLD" 20 GOTO 10 This way you have some space in between, and you could easily add a line 15 to print something else, if you want to. Nevertheless it can still happen even when you have reserve ranges, and they get to be "full". This is especially the case when you add new sections of verbose code between other code. And this is exactly why I am once more renumbering. -- -- -- To add sprites, you need to have the images stored some where. The old school way of doing it, is to add "DATA" commands to the code, like below. I will not write it completely here, since it becomes very verbose, but it looks something like this: 11000 DATA $00, $00, $22, $22, $22, $22, $00, $00 11001 DATA $00, $22, $82, $82, $82, $82, $22, $00 11002 DATA $02, $88, $88, $28, $28, $28, $28, $20 11003 DATA $28, $08, $08, $22, $22, $22, $82, $8b 11004 DATA $28, $88, $88, $20, $00, $28, $28, $b0 11005 DATA $02, $82, $82, $00, $02, $82, $8b, $00 11006 DATA $00, $22, $20, $00, $28, $22, $b0, $00 ..... Many more lines of this NOTE: Only in the 80s would you type in lines and lines of DATA like this. Now there are easier ways, for example a sprite editor with an export function. There are many options, below is one of them that I am coding on myself. The important thing is to export to a sprite data that the X16 understands. In this case 16x16 dimensions, 16 colors, so 4bpp (4 bits per pixel for color info), and basic support HEX numbers. And to use them, you write something like this. 1000 REM READ SPRITE DATA 1001 FOR I=O TO 255 1011 READ PX : REM READ ONE NUMBER FROM THE DATA. 1012 VPOKE $0,$4000+I,PX: REM USE VPOKE TO MOVE THE DATA IN VIDEO MEMORY 1013 NEXT I 1014 RETURN At the end of these lines of code, you see the command RETURN. What is this about? Well, with basic we can simulate calling a function/subrouting, with GOSUB. RETURN returns back to where it was called. The code is being called in the beginning, something like this: 10 GOSUB 1000 : REM READ SPRITE DATA After the call to the subroutine at line 1000, it continues to the next line. This is one way to organize the code inside Commodore/Micro$oft basic. I will not mention all the details of setting up the sprite here, you can check the code yourself, if you want to. Later I will go deep into this topic, but not here. However to get the sprite in the right position we have another subroutine. 1070 REM SET SPRITE 0,X0,Y0 1171 VPOKE $1,$FC12,X0 AND $FF 1172 VPOKE $1,$FC13,(X0 AND $0300)/$100 : REM MAGIC TO GET HI BYTE OF THE X COORDINATE 1173 VPOKE $1,$FC14,Y0 : REM YPOS 128 1174 VPOKE $1,$FC15,$00 : REM WE DON'T CALCULATE THE HI BYTE OF THE Y COORDINATE 1175 RETURN Which I call in the title screen build up like this. 75 X0=150: Y0=68: GOSUB 1070 : REM SET SPRITE X,Y Note that for calling the subroutine with parameters, we simply assign global variables. To keep from clashing with other global variables, use a naming convention. Here I used 0 (zero) as the second 'letter' in the name as the naming convention. In the game, the position changes all the time, so instead we do like this: 295 X0=PX*8: Y0=122: GOSUB 1070 : REM SET SPRITE X,Y X0 is calculated. Y0 is static, but X0 is PlayerX (PX) times 8 (the width of a character on screen in bits) Color effect Now for the colour effect, we chose one color to be the one that has the effect, and we draw our blinking characters with this color. Like below. 60 PRINT "FALLING SNAKE";: COLOR 14: PRINT "**": PRINT: COLOR 15 And we cycle / blink, by doing something like this. 80 C0=C0+1: IF C0>2 THEN C0=0: C1=C1+1: IF C1>255 THEN C1=0: 82 VPOKE 1,$FA1C,C1: VPOKE 1,$FA1D,C1 Offset $FA1C and $FA1D in the VERA video ram, control the palette registers for color 14. Each color has two bytes, so if you want to find the color register for color 0, you just substract 28 decimal (2*14) from hex $FA1C. (Convert 28 to hex first) Feel free to check out the code or the PRG file, at this stage. Code: https://github.com/JoystickAndCursorKeys/x16basic/blob/main/fallingsnake.v2.bas.txt PRG file: FALLSNAKE2.PRG -- In the next session we will concentrate a bit more on gameplay. It is no use to pimp up the graphics, if the gameplay is boring. Since this is really a simple game, we easily can do a few things to spice it up. So now it is time to look a little at the game play. So far the gameplay has been very simplistic. Avoid obstacles, and do it as long as you can. And the obstacles are the same. And the speed is the same always. ...... Hold on, not so fast. In the previous sections I managed to sneak in two lines of code that change the play speed over time. The longer you play the quicker the game becomes. This was done as such. 54 DE=1000 : REM DELAY VALUE Here the delay between each "cycle" in the game is defined as 1000, before the game starts. And then to use the delay, we have: 296 FOR W=1 TO DE: NEXT : REM DELAY, SLOW DOWN CODE And to decrease we have: 297 ......................... DE=DE-1 : IF DE<0 THEN DE=0 This already gives a little variation in the game. Let's add even more. (ps, you can see all the latest changes here on github https://github.com/JoystickAndCursorKeys/x16basic/commit/83b422502739076f2f01ad45223f3d66e9258428#diff-e83889dbe05ea5d067f684fe8fd1dbfc372ed11215335bcf8b85f2ef850ad047) Slow and Extra Points The two gameplay elements I intend to add are "Slow down" and "Extra (Bonus) Points"' Since the game goes faster and faster it it reasonable tro asume that the player wants to slow down from time to time. With this "feature", this will be possible. How will it work? Some of the objects that need to be avoided will look different. (Arrow up sign) And to make them recognizable they also have a blue blinking color. When you catch one, your speed (DE) will be increased. Extra points is implemented in a similar way. There is another symbol (a green clover, to symbolize snake food (yes Simon is a vegetarian snake :) ). When you run into this symbol, your score will be increased by a fixed amount. NOTE: In order to do all this, we needed to renumber a few things again. You see that happening alot in old school basics, at least when I am programing there To do all this, first we defined all the colors characters for the different types of obstacles. #COLORS 6 DIM CO(6): CO(0)=9: CO(1)=11: CO(2)=12: CO(3)=15: CO(4)=5: CO(5)=6 #CHARACTERS. see any Petscii table like on page https://www.linusakesson.net/art/three-petscii-pieces/index.php 7 DIM IO(6): IO(0)=$66: IO(1)=$6F: IO(2)=$54: IO(3)=$75: IO(4)=$58: IO(5)=$1E Now we have 6 characters defined, we can select a random one by just doing a INT(RND(1)*6) But actually I do a little differently, to make the changes to select a special character lower, my code looks like this. 225 R=( INT(RND(1)*5) IF RND(1) > .95 THEN R=5 226 C=CO(R): I=IO(R) C = the value for the color, I is the value for the character (I=image) And we poke them on the screen like so: 231 VPOKE 0, BO+X, I: VPOKE 0, BO+X+1, C But now we cannot just jump to "explosion", when we hit something, we we also adjust our code here: IF PE<>32 THEN O0=O: C0=PE: D0=1: GOSUB 500 : IF D0=1 THEN GOTO 400 O0,C0 are the input parameters for the gosub, and D0 is the output. O0, is the object offset on the screen of the object we collide with. C0, is the character code of this object. D0, is returned. It is 1 if we died, zero otherwise. If D0 is returned 1, we jump to 400, where we go into the "die/explosion" state. The handling of the different collisions with "slow" and "extra points" is done at line 500. 500 REM CHECK COLISSION 501 D0 = 1 502 IF C0 = $58 THEN S=S+50 : D0=0: GOSUB600 : REM GOT FOOD = EXTRA POINTS 503 IF C0 = $1E THEN DE=DE+100 : D0=0: GOSUB630 : REM GOT "SLOW DOWN" SYMBOL 505 RETURN Write "50" on the screen. 600 VPOKE 0,O0-256,$35 : VPOKE 0,2+O0-256,$30 601 VPOKE 0,1+O0-256,1 : VPOKE 0,3+O0-256,1 602 RETURN Write Slow on the screen 630 VPOKE 0,O0-4-256,$13 : VPOKE 0,2+O0-4-256,$0C: 631 VPOKE 0,4+O0-4-256,$0F :VPOKE 0,6+O0-4-256,$17 632 VPOKE 0,1+O0-4-256,1 : VPOKE 0,3+O0-4-256,1 633 VPOKE 0,5+O0-4-256,1 : VPOKE 0,7+O0-4-256,1 634 RETURN And this i basically our changes. Feel free to copy the code from: https://raw.githubusercontent.com/JoystickAndCursorKeys/x16basic/main/fallingsnake.v3.bas.txt To test it in the emulator. As I mentioned before, in order to keep the interest for such a game, I usually sneak in some visual improvements, so that also happened during my focus on game play. The "slow" character has been made to flash blue/cyan. This is done like this. 1. The character is always drawn with color 6 2. The pallette color for color 6 flips between 2 presets. This is done with these 3 lines of code. 280 CL=CL+1 Increase a counter. This counter has only one purpose, to control the speed of the blinking. 281 IF CL>2 THEN CL=0: CC=1-CC : LO=255:HI=8: IF CC=1 THEN LO=15:HI=1 If the counter is larger then 2, then reset it, and flip a flag called CC, by inverting it's value with CC=1-CC Set the low and high value of the color index. If the flag is set, overwrite the color low and high value with different values. 284 VPOKE 1,$FA0C,LO: VPOKE 1,$FA0D,HI And this last line, writes it into the palette register, so it becomes visible. Remember to only now use color 6 for things that should blink. (And the same goes for color 15, which is blinking during the title screen) To make it a little more looking like a professional game, we add a score display on the screen. While we are add it, we also add the speed. Making it finally look like this: Let's have a look on how we added this. The problem: Writing the information to the top of the screen buffer would not work very well, since the whole screen buffer is scrolling upwards, and so it would keep dissapearing, resulting in a flicker. Also, since this is Basic, updating 80 bytes for each cycle, would create alot of delays. A solution: The X16 has hardware support for two layers of text. And the top layer can have transparency, so you can still see the bottom layer. The transparency is enabled by using color 0, which is black. The score is "printed" in the frontmost layer. We can add this extra layer by direcly poking in Vera's registers. There are some things to keep in mind: The extra text layer is not accessible through "PRINT", so it needs to be changed by POKING directly in the buffer. Per default BASIC uses layer 1, which is the front layer. We want BASIC to use layer 0, which is the background, since we're printing everything on the background with basic commands. Writing a number to the screen, is time consuming, and slows down the game. So for now, we only update the score-bar, each ten cycles, to save on speed. We start out by adding a new routing, to setup the layered text based screens. 1030 REM SETUP 2 LAYERS SCREEN 1031 POKE $9F29,($20 OR $10 OR PEEK($9F29)) Enable layer 0 and 1. 1032 POKE $9F2F, PEEK( $9F36) 1033 POKE $9F2D, PEEK( $9F34) Swap screens. Move layer 0 pointers to layer 1 pointers. These registers point to the tilebase and the layer 0 config. So layer 0 looks now like layer 1. Same font, same screen dimensions. 1034 POKE $9F2E, $00: POKE $9F35, $0F Now setting layer 0 to point to screen memory offset 0, and layer 1 to screen offset "$0F" (note this is only the "high byte" of the offset) And last, we clear the screen with the right colors. (this affects now layer 0, after our changes) 1035 COLOR 1,0: CLS 1040 RETURN More problems to solve: Since one of our layer is now in a different memory space then basic looks at, we need to manually update this layer with the poke command. By running a simple for loop, we can clear the while screen, while poking a value into the screen buffer. The code turned out so, that it was very slow. So I created a "fill text line" routine, which is somewhat quicker. When I want to clear the screen, I call it with the right parameters (offset, draw character, draw color) The code below, as you see is repeating alot of pokes, instead of doing a for loop with one poke in it. This not-so-nice trick, gets us just a tiny bit of speed improvement. Since clearing the screen takes long, any improvement in speed is worth is. 2499 REM CLEAR LINE FAST(O0,P0,C0) 2500 FOR X=0TO39 STEP 10: O=(X*2)+O0 Many pokes below. Instead of just one poke. To get this tiny speed improvement. 2501 VPOKE 0,O,P0: VPOKE 0,O+1,C0:VPOKE 0,O+2,P0: VPOKE 0,O+3,C0 2503 VPOKE 0,O+4,P0: VPOKE 0,O+5,C0:VPOKE 0,O+6,P0: VPOKE 0,O+7,C0 2505 VPOKE 0,O+8,P0: VPOKE 0,O+9,C0:VPOKE 0,O+10,P0: VPOKE 0,O+11,C0 2507 VPOKE 0,O+12,P0: VPOKE 0,O+13,C0:VPOKE 0,O+14,P0: VPOKE 0,O+15,C0 2509 VPOKE 0,O+16,P0: VPOKE 0,O+17,C0:VPOKE 0,O+18,P0: VPOKE 0,O+19,C0 2515 NEXT 2516 RETURN Note that O0, P0, and C0 are the "input parameters" to the routine. (offset, draw character, draw color) The next part is the routine to draw a number on the screen, for the score. We have the similar routine for the speed, but the code is basically a copy-paste. The trick is to get the score, which is a number, into a sequence of printable (pokeable) characters. We want the score to also always have the same "size", which is six digits. There are not commands in Basic to format the string nicely for us, so we use tricks. 2999 REM UPDATE SCORE 3000 S$=STR$(N0 + 1000000) We convert N0 (the input of the routing, which is the Score in our case), to a string with STR$. But before that we add 1000000 to it so the output is always score + 1000000, which is 7 digits always. (unless you get more the 1 millions points, then the code stops working fine) And the trick is to use the last 6 characters from the string only. Example: Score = 555 -> 10000000 + Score = 1000555 -> last 6 digits is -> 000555 To get the last 6 digits, we start our loop below at position 2. Then we use MID$ to get one character from the string, and ASC to convert that character to a pokeable number. 3001 FOR T=2TOLEN(S$)-1 3002 C=ASC(MID$(S$,T+1)) 3004 VPOKE 0,7676+O0+(T*2),C And here we poke it to the video memory. (O0 is the offset) 3005 NEXT 3006 RETURN And we're done. So far this tutorial. The code can be found at: https://github.com/JoystickAndCursorKeys/x16basic/blob/main/fallingsnake.v4.bas.txt FALLSNAKE4.PRG is the final program. Recreating this old program on the X16 was fun, and quite informative on how the VERA video chip worked. There is many more things you can do to improve the game. One thing we found is that the game currently is "almost" a little on the slow side. So adding more features, would need rewrites of certain sections, or moving things into assembly language. Since this is a "simple game basic manual", I will not do this here, but the game may evolve in that way in the future. Things you can easily add to the program, without compromising speed, is "cutscenes", dedicated character graphics, and perhaps some simple sound effects. On the code itself. For the snake and snake head, I could have used character graphics instead of sprites. In fact there is no real need to use sprites here, but then again, in the end it made the snake head less flickery, which is a nice bonus. Using text mode was a design decision, since Basic has the build in scroll-screen feature, if you print a newline on the bottom line. This is what this game utilizes to it's fullest. Why does the snake fall? In fact it has nothing to do with the story, it is more that it is the simplest way of having a scrolling game. It started out as a car racing game, but the care left trails. So calling the trails for snake was easiest. And since it went down, falling seemed appropriate. If you want a more interesting background story, I can also provide. Simon is domesticated snake, and he goes out one day, and falls down a hole. He needs to avoid obstacles like branches and so on to survive, so he can splash down in the water at the bottom safely, before climbing up again. Feel free to clone the code, and make a more convincing background story if you wish. Color palette changes. Changing the palette is a really cool way to change many things on the screen, with only one command. Which is excellent for BASIC since it saves in CPU usage, and you do not loose to much speed. Even though running fine in the beginning, almost too fast. When you add features to the game main loop, it is very noticeable how the game slows down, and the delay constant DE needs to be set to lower, to run at the same speed. At the end I was running into a limit, since if the delay is too small, you cannot decrease and decrease the delay during the game, since there would be not much to decrease. Going to Assembly, would be an obvious next move. The ability to very simply set the extra layer is a very nice feature. The layer is hardware, so it does not slow the game down at all, and you can overlay semi static information like the score. Sprites: There are so many sprites on the X16, this game is not utilizing them at all, so there is alot of room for improvement for the visuals when it comes to that. Most design goals were also marked by the fact that the reason why the game is simple, is that it uses PETSCII, and PRINT. I wanted to keep that look and feel, so only minimal use of graphics, to spice it up only a little. The future. This game will probably be possihed a while more, since it is fun to do, but that will not be part of this tutorial. However feel free to watch the download section / games, to see the next version being worked on. Check out as well the youtube video below, where I do a (quick-ish) "coding basic on x16" + game + code walk-through: Have fun, and thanks for reading! Especially thanks to all who helped me with my questions, when creating this short (medium sized ;)) tutorial.
    Short and simple, but a perfect tutorial code to get you up and running with sprites in no time! This is my starting point to the X16.
  • Create New...

Important Information

Please review our Terms of Use