My first real computer. Sure, the school I went to had Ohio Scientific Challenger C1-P (6502 CPU), but they also had the Commodore VIC-20 a-plenty, which had colour, sound and good documentation. We eventually got one for home with a datasette, programmer's reference and introduction to BASIC, so I became quite good at Commodore BASIC V2, writing dozens of my own programs.
Downloads | scuba.prg for the VIC-20 +8K (22x23chars). STANDARD. |
scuba27x34.prg for the VIC-20 +16K (27x34chars). VICE. | |
scuba28x28.prg for the VIC-20 +16K (28x28chars). THEVIC-20. | |
screen3k.prg screen resize utility for VIC-20 unexpanded / +3K | |
screen8k.prg screen resize utility for VIC-20 8K+ |
How do you get the prg on your VIC-20? (1) buy an SSD 1541 emulator gadget, (2) convert prg to wav format then record the wav to cassette or audio out to audio in on a datasette adapter, (3) use VICE to run an emulator on your modern computer.
Inspired by the Oric game by Ronald Jeffs 1984, of which I have only seen a minute or so on YouTube. The Oric is bit mapped / sprite where as mine would be chunky character based. Why chunky characters? Well I thought I actually could fit everything into unexpanded memory. Wrong. Rather than dump everything and go full sprite, I added more RAM and persisted until the project was done.
CONTROLS WASDX (S and D both move your character down) or Joystick! The joystick allows you to move diagonally, which is nice.
Quick and dirty. There you go. Done! My first brand new VIC-20 game in many decades.
CODING Using TRSE I cobbled together a few screens of a game with user defined characters, but quickly ran out of memory - the unexpanded VIC-20 has under 4K to play with, so I revised the code to work with an 8K expansion. There are likely plenty of optimisations I could have made . I ran into some issues that I couldn't work out and after contacting the TRSE developer, I received some prompt help from AndyH - thank you very much!
Below is the code snippet that AndyH helped with. The issue is that unexpanded and +3K expansion have the screen and character set locations in nice convenient places, but when you expand to 8K or more then the memory locations change, so you need a series of @ directives to tell the TRSE compiler where to place the code and avoid stomping over the user defined character memory area.
@VicMemoryConfig "8k" @projectsettings "ignorebasicsysstart" 0 @projectsettings "basicsysaddress" $1201 @projectsettings "startaddress" $1610 VAR // ... charset: incbin("charset6.bin", $1400); BEGIN setcharsetlocation ($1400); // ... END.
22 columns by 23 rows should be enough for anyone's needs! But it really isn't much. Sure 22x23 (=506) ensures the screen fits nicely into 512 bytes but it is really on the wrong side of the border of usefulness for most applications. Also, only having 3583 bytes makes giving up another 400 or 500 on screen realestate a large expense. Note that colour memory has a bunch of unused memory just sitting there unused. Lawrence Woodman's article covers the method to expand the screen. Below are some hints for changing the screen dimensions using TRSE.
Target system : you can expand the screen, and move the display about quite easily. However you will need to test what your display device can show you. VICE (28x34=952bytes) can show an awful lot more than my HDMI TV (28x28=784bytes), and I hear that NTSC display capabilities are different to PAL ... if you're making software for the broadest base possible then you should probably limit the size that you expand screen. I have made two utilities Screen3K and Screen8K to allow you to explore the possibilities on your device(s).
You will also need to tell the VIC-20 to move the memory around so you don't run into memory that BASIC programs use or ROM or non-RAM blocks of memory. Briefly: unexpanded/3K machines need to move the screen address ($1E00) and colour address ($9600) back $200 (512bytes); 8K+ expanded VIC-20 needs to protect the $400 above screen RAM which starts at $1000 {even further if you want to place user defined characters at $1400}, and also ensure colour address is at $9400.
// unexpanded/3K code VAR BIGSCREEN_COLS : byte = 28; BIGSCREEN_ROWS : byte = 28; BIGSCREEN_OFFX : byte = 6; // location of the display screen left-right BIGSCREEN_OFFY : byte = 27; // location of the display screen up-down SCREENLOC, COLOURLOC, moveToLoc: INTEGER; scrsz_loch : byte at $9000; // loc horiz $9000 = 36864 scrsz_locv : byte at $9001; // loc vert $9001 = 36865 scrsz_cols : byte at $9002; // nr cols $9002 = 36866 scrsz_rows : byte at $9003; // nr rows(x2) $9003 = 36867 scrsz_scrmem : byte at $9005;// bit7-4 $1000,$1200,$1400,$1600,$1800,$1A00,$1C00,$1E00 int1,int2,int3 : integer; tmptr : pointer; // Change screen dimensions. Call once at start procedure BigScreenSetup(BIGSCREEN_COLS, BIGSCREEN_ROWS, BIGSCREEN_OFFX, BIGSCREEN_OFFY : global byte); begin scrsz_cols := ((scrsz_cols & 128) | BIGSCREEN_COLS); scrsz_rows := ((scrsz_rows & 129) | BIGSCREEN_ROWS * 2); scrsz_loch := BIGSCREEN_OFFX; scrsz_locv := BIGSCREEN_OFFY; end; // Fill the screen with a character and a colour // example: BigScreenFill(32,BLACK); // blank the screen procedure BigScreenFill(thisChar,thisColour:byte); begin int1 := BIGSCREEN_COLS * BIGSCREEN_ROWS; tmptr := SCREENLOC; WHILE int1 > 0 DO BEGIN if int1 > 255 then begin Fill(tmptr,thisChar,255); tmptr := tmptr + 255; int1 := int1 - 255; end else begin Fill(tmptr,thisChar,LO(int1)); int1 := 0; end; END; int1 := BIGSCREEN_COLS * BIGSCREEN_ROWS; tmptr := COLOURLOC; WHILE int1 > 0 DO BEGIN if int1 > 255 then begin Fill(tmptr,thisColour,255); tmptr := tmptr + 255; int1 := int1 - 255; end else begin Fill(tmptr,thisColour,LO(int1)); int1 := 0; end; END; end; // Use mymoveto instead of moveto, works with print* procedures procedure mymoveto(mtx,mty:byte); begin int1 := CreateInteger($00,mtx); int2 := CreateInteger($00,mty); int3 := int1 + int2 * BIGSCREEN_COLS; int1 := int3 / 22; int2 := int3 - (int1 * 22); InitMoveTo(); moveto(lo(int2),lo(int1),moveToLoc); end; // ### MAIN BEGIN DefineScreen(); SCREENLOC := $1C00; // replace SCREEN_CHAR_LOC (unexpanded/3K=$1E00) COLOURLOC := $9400; // replace SCREEN_COL_LOC // unexpanded/+3K needs the screen memory start moved back $0200 to allow for the extra memory that the screen will need SetScreenLocation(SCREENLOC); // $1E00=7608 vs $1C00=7168 // unexpanded/+3K needs the colour memory start moved back $0200 to allow for the extra memory that the screen will need // SetColorMemoryAddress(); // ignore this and force the bit 7 to 0 : bit7=0 -> $9600=38400 || bit7=1 -> $9400=37888 scrsz_cols := (scrsz_cols & 127); // clear bit 7 to set colour memory to $9400 moveToLoc := HI(SCREENLOC); BIGSCREEN_COLS := ; BIGSCREEN_ROWS := ; BIGSCREEN_OFFX := ; BIGSCREEN_OFFY := ; BigScreenSetup (BIGSCREEN_COLS, BIGSCREEN_ROWS, BIGSCREEN_OFFX, BIGSCREEN_OFFY); AUX_COLOR_AND_VOLUME := %00000010; SCREEN_BG_COLOR := BLACK + SCREEN_BG_BLUE; // border + background colours // ... do the suff // ... etc END.
Contact zapusten@lo5.me