├── basic-sprite ├── .gitignore ├── smiley.png ├── Makefile └── prolog.inc ├── tools ├── requirements.txt ├── bin2c.py ├── bas2prg.py ├── renumber.py └── png2sprite.py ├── assembly ├── .gitignore ├── mode7-bitmap.bin ├── mode4-palette.bin ├── mode7-palette.bin ├── mode7-bitmap-cut.bin ├── kick-assembler │ ├── Makefile │ └── typing.asm ├── x16-matriculate-text │ ├── system_vars.asm │ ├── matriculate_vars.asm │ ├── LICENSE │ ├── system.asm │ ├── README.md │ ├── style-guide.txt │ ├── vera.inc │ ├── system.inc │ └── matriculate.asm ├── Makefile ├── mode7-demo.asm ├── mode4-demo.asm ├── vera.inc ├── mode4-tilemap.bin ├── mode4-tiles.bin └── sprite-demo.asm ├── .gitignore ├── petdrawx16 ├── Makefile ├── x16help_text.bin ├── pdcharsel_color.bin ├── pdcharsel_text.bin ├── pdcolpick_color.bin ├── pdcolpick_text.bin ├── x16help_color.bin └── MakeWin10.bat ├── cc65-audio ├── test.vgm ├── Makefile └── main.c ├── cc65-sprite ├── balloon.png ├── Makefile └── demo.c ├── layer demo ├── layer-demo.png ├── README.txt └── layer-demo.bas ├── basic ├── maze.bas ├── charfractal.bas ├── chartable.bas ├── time.bas ├── x16-logo.bas ├── blinken.bas ├── balls.bas ├── koala.bas ├── fractal256.bas ├── acey-ducey.bas ├── tile4bpp.bas ├── cx16logo.bas ├── basic-benchmark.bas ├── fastfract256.bas ├── fractalland.bas ├── frog.bas ├── snake-no-dim.bas ├── LOGO.BAS ├── raytracer.bas ├── swimmer.bas ├── snake.bas ├── affine.bas ├── traveller-ship.bas ├── traveller-uwp.bas ├── aritm-x16.bas └── retro_wrestling.bas ├── Makefile ├── README.md └── CONTRIBUTING.md /basic-sprite/.gitignore: -------------------------------------------------------------------------------- 1 | smiley.inc 2 | -------------------------------------------------------------------------------- /tools/requirements.txt: -------------------------------------------------------------------------------- 1 | Click==7.0 2 | -------------------------------------------------------------------------------- /assembly/.gitignore: -------------------------------------------------------------------------------- 1 | *.prg 2 | disk.d64 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore binary files: they muts be build during release 2 | 3 | *.prg -------------------------------------------------------------------------------- /petdrawx16/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | acme -f cbm -o petdrawx16.prg petdrawx16.asm 3 | 4 | -------------------------------------------------------------------------------- /cc65-audio/test.vgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LRFLEW/x16-demo/master/cc65-audio/test.vgm -------------------------------------------------------------------------------- /assembly/mode7-bitmap.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LRFLEW/x16-demo/master/assembly/mode7-bitmap.bin -------------------------------------------------------------------------------- /basic-sprite/smiley.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LRFLEW/x16-demo/master/basic-sprite/smiley.png -------------------------------------------------------------------------------- /cc65-sprite/balloon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LRFLEW/x16-demo/master/cc65-sprite/balloon.png -------------------------------------------------------------------------------- /layer demo/layer-demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LRFLEW/x16-demo/master/layer demo/layer-demo.png -------------------------------------------------------------------------------- /assembly/mode4-palette.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LRFLEW/x16-demo/master/assembly/mode4-palette.bin -------------------------------------------------------------------------------- /assembly/mode7-palette.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LRFLEW/x16-demo/master/assembly/mode7-palette.bin -------------------------------------------------------------------------------- /petdrawx16/x16help_text.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LRFLEW/x16-demo/master/petdrawx16/x16help_text.bin -------------------------------------------------------------------------------- /assembly/mode7-bitmap-cut.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LRFLEW/x16-demo/master/assembly/mode7-bitmap-cut.bin -------------------------------------------------------------------------------- /petdrawx16/pdcharsel_color.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LRFLEW/x16-demo/master/petdrawx16/pdcharsel_color.bin -------------------------------------------------------------------------------- /petdrawx16/pdcharsel_text.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LRFLEW/x16-demo/master/petdrawx16/pdcharsel_text.bin -------------------------------------------------------------------------------- /petdrawx16/pdcolpick_color.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LRFLEW/x16-demo/master/petdrawx16/pdcolpick_color.bin -------------------------------------------------------------------------------- /petdrawx16/pdcolpick_text.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LRFLEW/x16-demo/master/petdrawx16/pdcolpick_text.bin -------------------------------------------------------------------------------- /petdrawx16/x16help_color.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LRFLEW/x16-demo/master/petdrawx16/x16help_color.bin -------------------------------------------------------------------------------- /assembly/kick-assembler/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | java -jar kickass.jar typing.asm 3 | 4 | clean: 5 | rm -f *.prg disk.d64 6 | -------------------------------------------------------------------------------- /assembly/x16-matriculate-text/system_vars.asm: -------------------------------------------------------------------------------- 1 | !ifdef SYSTEM_VARS_ASM !eof 2 | SYSTEM_VARS_ASM=1 3 | 4 | Sys_rand_mem: !byte $00, $00, $00 5 | Sys_mem_end: 6 | -------------------------------------------------------------------------------- /assembly/x16-matriculate-text/matriculate_vars.asm: -------------------------------------------------------------------------------- 1 | !ifdef MATRICULATE_VARIABLES_ASM !eof 2 | MATRICULATE_VARIABLES_ASM=1 3 | 4 | New_frame: !byte $00 5 | All_palettes_cleared: !byte $00 6 | Palette_cycle_index: !byte $00 7 | -------------------------------------------------------------------------------- /cc65-audio/Makefile: -------------------------------------------------------------------------------- 1 | all: audio.prg 2 | 3 | audio.prg: main.c vgm.inc 4 | cl65 -t cx16 -O -o audio.prg main.c 5 | 6 | vgm.inc: test.vgm 7 | python3 ../tools/bin2c.py vgmData test.vgm vgm.inc 8 | 9 | clean: 10 | rm -f *.prg *.inc *.o 11 | -------------------------------------------------------------------------------- /cc65-sprite/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all clean 2 | all: demo.prg 3 | 4 | demo.prg: demo.c balloon.inc 5 | cl65 -t cx16 -O -o $@ $< 6 | 7 | balloon.inc: balloon.png 8 | python3 ../tools/png2sprite.py -n balloon $< $@ 9 | 10 | clean: 11 | rm -f *.inc *.o *.prg 12 | -------------------------------------------------------------------------------- /basic-sprite/Makefile: -------------------------------------------------------------------------------- 1 | all: smiley.bas 2 | 3 | smiley.bas: smiley.inc 4 | cat prolog.inc smiley.inc > smiley.bas 5 | 6 | smiley.inc: smiley.png 7 | python3 ../tools/png2sprite.py -f basic smiley.png smiley.inc 8 | 9 | clean: 10 | rm -f smiley.inc smiley.bas 11 | -------------------------------------------------------------------------------- /petdrawx16/MakeWin10.bat: -------------------------------------------------------------------------------- 1 | @ECHO off 2 | WHERE /q acme.exe 3 | IF ERRORLEVEL 1 ( 4 | ECHO Requires ACME is installed in path location 5 | ECHO Download from https://sourceforge.net/projects/acme-crossass/ 6 | EXIT /B 7 | ) ELSE ( 8 | ECHO Building PetDraw X16 9 | acme -f cbm -o petdrawx16.prg petdrawx16.asm 10 | ) -------------------------------------------------------------------------------- /basic/maze.bas: -------------------------------------------------------------------------------- 1 | 100 REM SEE HTTPS://10PRINT.ORG/ 2 | 105 REM ADAPTED BY GIOVANNI GIORGI 3 | 106 REM V 1.1 4 | 110 PRINT CHR$(147); "OLD SCHOOL MAZE DEMO" 5 | 115 FOR MC = 1 TO 3 6 | 118 PRINT "MAZE TYPE ", MC 7 | 120 FOR ROW = 1 TO 16 8 | 200 FOR I = 1 TO 32 9 | 300 IF MC <=1 THEN PRINT CHR$(205.50+RND(1)); 10 | 310 IF MC =2 THEN PRINT CHR$(205.25+RND(1)); 11 | 320 IF MC =3 THEN PRINT CHR$(204+(RND(1)+.5)*3); 12 | 400 NEXT I 13 | 500 PRINT 14 | 600 NEXT ROW 15 | 700 NEXT MC 16 | -------------------------------------------------------------------------------- /basic/charfractal.bas: -------------------------------------------------------------------------------- 1 | 5 PRINT CHR$(147); 2 | 7 TI$="000000" 3 | 8 DIMSD,V,U,A,B,N,S,I,R,Z,X,H,Y,D 4 | 10 X1=79:Y1=58:NS=48:NE=33:Z=0 5 | 20 I1=-1.0:I2=1.0:R1=-2.0:R2=1.0 6 | 30 H=(R2-R1)/X1:S2=(I2-I1)/Y1:S=127:D=14848:YH=Y1/2 7 | 40 FORY=ZTOYH:I=I1+Y*S2:R=R1 8 | 60 FORX=ZTOX1:V=R:U=I:FORN=48TO33STEP-1:A=V*V:B=U*U 9 | 110 IFA+B<=4THENU=U*V*2+I:V=A-B+R:NEXT 10 | 130 S=S+1:SD=2*S:VPOKE0,SD,N:VPOKE0,SD+D,N:R=R+H:NEXTX:S=S+48:D=D-512:NEXT 11 | 10000 PRINT"TIME: ";TI$; 12 | 10010 GETA$:IF A$="" THEN 10010 13 | -------------------------------------------------------------------------------- /basic/chartable.bas: -------------------------------------------------------------------------------- 1 | 10 PRINT CHR$(147);" 0 1 2 3 4 5 6 7 8 9 A B C D E F" 2 | 20 FOR Y=0 TO 15: FOR X=0 TO 15 3 | 30 C = Y*16+X: CH$ = " " 4 | 40 IF (C>=$20 AND C<=$7F) OR (C>=$A0 AND C<=$FF) THEN CH$ = CHR$(C) 5 | 50 IF X>0 THEN GOTO 90 6 | 60 IF Y<10 THEN GOTO 70 7 | 65 PRINT " ";CHR$(Y+$37);" ";CH$;" "; 8 | 67 GOTO 100 9 | 70 PRINT Y;" ";CH$;" "; 10 | 80 GOTO 100 11 | 90 PRINT CH$;" "; 12 | 100 NEXT X 13 | 110 PRINT:PRINT 14 | 120 NEXT Y 15 | 130 PRINT:PRINT " 0 1 2 3 4 5 6 7 8 9 A B C D E F":PRINT 16 | 140 END 17 | -------------------------------------------------------------------------------- /basic/time.bas: -------------------------------------------------------------------------------- 1 | 1 REM USAGE OF TIME, TIME$ AND PLOT KERNAL CALL 2 | 2 PLOT = $FFF0 3 | 5 X=30:Y=20: REM X,Y USED BY 2000 SUB 4 | 7 PRINT CHR$(147) 5 | 10 FOR I=0 TO 3000 6 | 20 GOSUB 2000 7 | 29 REM TIME IS 1/60 SEC, GET ONLY SECOND FRACTION 8 | 30 S = TIME - INT(TIME / 60) * 60 9 | 34 REM CONVERT 0-59 TO 0-99 10 | 35 S = INT(S*100/60) 11 | 40 PRINT LEFT$(TIME$,2);":";MID$(TIME$,3,2);":";RIGHT$(TIME$,2);".";S 12 | 50 NEXT 13 | 14 | 1999 END 15 | 16 | 2000 REM SET CURSOR AT POSITION X,Y 17 | 2010 POKE $030D,Y: POKE $030E,X: POKE $030F,0: SYS PLOT 18 | 2020 RETURN 19 | -------------------------------------------------------------------------------- /assembly/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | acme -f cbm -DMACHINE_C64=0 -o mode4-demo.prg mode4-demo.asm 3 | acme -f cbm -DMACHINE_C64=1 -o 64mode4-demo.prg mode4-demo.asm 4 | 5 | acme -f cbm -DMACHINE_C64=0 -o mode7-demo.prg mode7-demo.asm 6 | acme -f cbm -DMACHINE_C64=1 -o 64mode7-demo.prg mode7-demo.asm 7 | 8 | acme -f cbm -DMACHINE_C64=0 -o sprite-demo.prg sprite-demo.asm 9 | acme -f cbm -DMACHINE_C64=1 -o 64sprite-demo.prg sprite-demo.asm 10 | 11 | d64: all 12 | c1541 -format 64demo,31 d64 disk.d64 -write 64sprite-demo.prg 13 | # c1541 -format 64demo,31 d64 disk.d64 -write 64mode4-demo.prg -write 64mode7-demo.prg -write 64sprite-demo.prg 14 | 15 | 16 | 1541: d64 17 | d64copy -b disk.d64 10 18 | 19 | clean: 20 | rm -f *.prg disk.d64 -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SUBDIRS := petdrawx16 assembly basic-sprite cc65-audio cc65-sprite 2 | 3 | all: $(SUBDIRS) 4 | rm -rf release 5 | mkdir -p release/basic 6 | mkdir -p release/PRG 7 | cp assembly/mode4-demo.prg release/PRG 8 | cp assembly/mode7-demo.prg release/PRG 9 | cp assembly/sprite-demo.prg release/PRG 10 | cp cc65-audio/audio.prg release/PRG 11 | cp cc65-sprite/demo.prg release/PRG 12 | cp basic-sprite/smiley.bas release/basic 13 | cp basic/* release/basic 14 | cp "layer demo/layer-demo.bas" release/basic 15 | ./tools/bas2prg.py ../x16-emulator/x16emu ./release/basic ./release/PRG 16 | cd release/PRG ; python -c 'import os, sys; [os.rename(a, a.upper()) for a in sys.argv[1:]]' * 17 | 18 | clean: 19 | rm -rf release 20 | 21 | $(SUBDIRS): 22 | $(MAKE) -C $@ 23 | 24 | .PHONY: all $(SUBDIRS) 25 | -------------------------------------------------------------------------------- /basic/x16-logo.bas: -------------------------------------------------------------------------------- 1 | 1000 REM GG: ADDED USAGE EXAMPLE 2 | 1100 PRINT CHR$(147) 3 | 1200 R9=10:C9=10:B9=6:GOSUB 4000 4 | 1300 END 5 | 4000 REMSUB X16 LOGO 6 | 4001 REM R9, C9 AND B9 DEFINE THE SCREEN LOCATION AND BACKGROUND COLOR 7 | 4002 REM EXAMPLE, CALLING ON BLUE BACKGROUND R9=0:C9=0:B9=6:GOSUB 4000 8 | 4005 DIM H9(5) 9 | 4010 DATA $40,0,233,32,105,223,32,95,$E0,0,$30,0,$50,1,$70,0 10 | 4011 DATA 95,32,223,105,32,233,$A0,0,$20,0 11 | 4020 FOR I=0 TO 6 12 | 4030 R8=R9+I: C8=I: IF I>3 THEN C8 = 6 - I 13 | 4040 READ X9, X8: X9=X9+B9 14 | 4050 IF I<1 OR (I>3.5 AND I<4.5) THEN FOR K=0 TO 5: READH9(K): NEXT 15 | 4060 FOR J = 0+X8 TO 2-X8 16 | 4070 VPOKE0,256*(R8)+2*(C9+C8+J),H9(J+3):VPOKE0,256*(R8)+2*(C9+C8+J)+1,X9 17 | 4071 VPOKE0,256*(R8)+2*(11+C9-C8-J)-2,H9(J):VPOKE0,256*(R8)+2*(11+C9-C8-J)-1,X9 18 | 4080 NEXT:NEXT 19 | 4090 RETURN 20 | -------------------------------------------------------------------------------- /basic-sprite/prolog.inc: -------------------------------------------------------------------------------- 1 | 10 REM ADDRESS 12:5 2 | 20 VPOKE $1, $FC00, 0 3 | 30 REM ADDRESS 16:13 (STARTING AT $10000) AND 8 BPP MODE 4 | 40 VPOKE $1, $FC01, $88 5 | 50 REM X COORDINATE 7:0 6 | 60 VPOKE $1, $FC02, 220 7 | 70 REM X COORDINATE 9:8 8 | 80 VPOKE $1, $FC03, 0 9 | 90 REM Y COORDINATE 7:0 10 | 100 VPOKE $1, $FC04, 55 11 | 110 REM Y COORDINATE 9:8 12 | 120 VPOKE $1, $FC05, 0 13 | 130 REM Z-DEPTH: IN FRONT OF LAYER 1 14 | 140 VPOKE $1, $FC06, $0C 15 | 150 REM 16 PIXELS FOR WIDTH AND HEIGHT (01 AND 01) 16 | 160 VPOKE $1, $FC07, $50 17 | 170 REM COPY SMILEY SPRITE DATA TO VIDEO RAM 18 | 180 FOR I=0 TO 255 19 | 190 READ A 20 | 200 VPOKE 1, I, A 21 | 210 NEXT 22 | 220 REM ENABLE SPRITES 23 | 230 REM LOAD DCVIDEO REGISTER 24 | 231 DCVIDEO=PEEK($9F29) 25 | 240 REM SET BIT6 ($40) AND STORE IN DCVIDEO REGISTER 26 | 241 POKE $9F29,DCVIDEO OR $40 27 | -------------------------------------------------------------------------------- /basic/blinken.bas: -------------------------------------------------------------------------------- 1 | 10 REM BLINKENLIGHTS RANDALL BOHN 2019-10-03 FOR MARY 2 | 15 POKE 713,1:PRINT CHR$(147);"BLINKENLIGHTS" 3 | 20 GOSUB 300 :REM SET UP VERA L1 160x120x4 BIG PIXELS 4 | 40 REM MAIN LOOP 5 | 50 CC=$FF:GOSUB 100 6 | 60 CC=$AA:GOSUB 100 7 | 70 CC=$55:GOSUB 100 8 | 80 CC=0 :GOSUB 100 9 | 90 GOTO 40 10 | 100 REM PLOTTING 11 | 110 U0 = INT(RND(1)*155) 12 | 111 VPOKE 15,$1002+INT(RND(1)*6),INT(RND(1)*256) 13 | 120 FOR U = U0 TO U0 +3 14 | 130 X = U AND $FE 15 | 140 GOSUB 700 16 | 150 NEXT U 17 | 160 RETURN 18 | 300 REM VERA CONFIGURATION 19 | 310 VPOKE 15,1,128 :REM 640 WIDE 20 | 320 VPOKE 15,2,64 :REM 240 HIGH 21 | 330 VPOKE 15,$2000,1 :REM L0 MODE 0 22 | 340 VPOKE 15,$2001,2 :REM L0 MAPH 32 TILES, MAPW 128 TILES 23 | 350 VPOKE 15,$3005,16:REM L1 MAP AT $4000 24 | 360 VPOKE 15,$3001,16:REM L1 160 BYTES WIDE 25 | 370 VPOKE 15,$3000,$A1:REM L1 MODE 5 26 | 380 RETURN 27 | 700 FOR Y = 10 TO 99 STEP 2: GOSUB 900:NEXT Y 28 | 710 RETURN 29 | 900 REM PLOT 160X120X4 30 | 910 VB = $4000+320*Y+X 31 | 920 VPOKE 0,VB,CC :REM TOP HALF 32 | 930 VPOKE 0,VB+160,CC :REM BOTTOM HALF 33 | 940 RETURN 34 | -------------------------------------------------------------------------------- /assembly/x16-matriculate-text/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Stephen Horn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | C, Asssembly and B.A.S.I.C. v2 examples for commander-x16 2 | 3 | Basic examples are collected from Facebook group 4 | 5 | 1. basic - A set of simple example. Start from here 6 | 2. basic-sprite - How to use VERA chip to make a sprite. Needs python3 to convert png to "DATA" 7 | 3. layer demo - More complex demo showing VERA "layers" 8 | 4. cc65-sprite - C-language sprite demo with CC65 9 | 5. petdraw - Petdraw Commander X16 version by David Murray 10 | 11 | The tools/ directory contains: 12 | 13 | + bas2prg.py - Convert a basic program to binary png calling the emulator. Used internally during release building 14 | + png2sprite.py - A PNG2Sprite converter. Launch with "-h" to get usage examples 15 | + renumber.py - Renumber a basic program (.bas) Launch with --help to get usage. 16 | + bin2c.py - Converts any bin file to a C array 17 | + requirements.txt - Python requirements for the tools. Use with "pip3 install -r requirements.txt" 18 | 19 | 20 | # How to compile asm files 21 | The Makefile need the acme compiler. 22 | 23 | Install the acme compiler from 24 | wget https://github.com/meonwax/acme/archive/master.zip 25 | and the cc65 toolchain (needed for some files) 26 | -------------------------------------------------------------------------------- /assembly/x16-matriculate-text/system.asm: -------------------------------------------------------------------------------- 1 | ; !ifdef SYSTEM_ASM !eof 2 | ; SYSTEM_ASM=1 3 | 4 | ;================================================= 5 | ;================================================= 6 | ; 7 | ; Random number generation 8 | ; 9 | ;------------------------------------------------- 10 | ; 11 | ; This random number generation routine is based 12 | ; on a linear feedback shift register, or LFSR. 13 | ; It's a common technique for generating complex 14 | ; sequences of values. 15 | ; 16 | ; This specific implementation is based on: 17 | ; https://wiki.nesdev.com/w/index.php/Random_number_generator/Linear_feedback_shift_register_(advanced) 18 | ; 19 | 20 | ;================================================= 21 | ; sys_rand 22 | ; Generate an 8-bit random number. 23 | ;------------------------------------------------- 24 | ; INPUTS: Sys_rand_mem 25 | ; 26 | ;------------------------------------------------- 27 | ; MODIFIES: A, X, Sys_rand_mem 28 | ; 29 | 30 | sys_rand: 31 | ldx #8 32 | lda Sys_rand_mem 33 | - asl 34 | rol Sys_rand_mem+1 35 | rol Sys_rand_mem+2 36 | bcc + 37 | eor #$1B 38 | + dex 39 | bne - 40 | sta Sys_rand_mem 41 | cmp #0 42 | rts 43 | -------------------------------------------------------------------------------- /basic/balls.bas: -------------------------------------------------------------------------------- 1 | 5 REM BALLS...A SLIGHTLY MODIFIED VERSION OF 2 | 6 REM THE ONE SHOWN IN DAVID'S VIDEO. I HOPE HE DON'T MIND. 3 | 10 SCREEN 0 4 | 20 PRINT"NUMBER OF BALLS (1-255)?" 5 | 30 INPUT N 6 | 40 IF N<1 OR N>255 THEN 20 7 | 60 PRINT CHR$(147); 8 | 70 DIM BX(255):DIM BY(255):DIM BC(255) 9 | 75 DIM DX(255):DIM DY(255) 10 | 80 FOR B=0TON 11 | 90 BX(B)=INT(RND(1)*40) 12 | 100 BY(B)=INT(RND(1)*30) 13 | 105 BC(B)=INT(RND(1)*14)+1 14 | 106 DX(B)=INT(RND(1)*2) 15 | 108 REM DY(B)=INT(RND(1)*2) 16 | 109 DY(B)=1 17 | 110 NEXT B 18 | 120 REM 19 | 130 FORY=0TO29:FORX=0TO39 20 | 140 Q=Y*256+X*2 21 | 150 VPOKE0,Q,81:VPOKE0,Q+1,0 22 | 160 NEXTX,Y 23 | 200 FOR B=1TON 24 | 210 VPOKE0,BY(B)*256+BX(B)*2+1,0 25 | 240 IFDX(B)=0THENGOSUB1010 26 | 250 IFDX(B)=1THENGOSUB1040 27 | 260 IFDY(B)=0THENGOSUB1070 28 | 270 IFDY(B)=1THENGOSUB1100 29 | 280 VPOKE0,BY(B)*256+BX(B)*2+1,BC(B) 30 | 290 NEXTB 31 | 300 GOTO 200 32 | 1000 REM 33 | 1010 IFBX(B)=0THENDX(B)=1:RETURN 34 | 1020 BX(B)=BX(B)-1:RETURN 35 | 1030 REM 36 | 1040 IFBX(B)=39THENBX(B)=38:DX(B)=0:RETURN 37 | 1050 BX(B)=BX(B)+1:RETURN 38 | 1060 REM 39 | 1070 IFBY(B)=0THENDY(B)=1:RETURN 40 | 1080 BY(B)=BY(B)-1:RETURN 41 | 1090 REM 42 | 1100 IFBY(B)=29THENBY(B)=28:DY(B)=0:RETURN 43 | 1110 BY(B)=BY(B)+1:RETURN 44 | -------------------------------------------------------------------------------- /assembly/mode7-demo.asm: -------------------------------------------------------------------------------- 1 | !src "vera.inc" 2 | 3 | *=$0801 4 | 5 | !byte $0b,$08,$01,$00,$9e,$32,$30,$36,$31,$00,$00,$00 6 | 7 | +video_init 8 | 9 | +vset 0 | AUTO_INC_1 10 | 11 | ldx #$88 12 | ldy #0 13 | lda #bitmap 16 | sta 3 17 | loop1: lda (2),y 18 | sta veradat 19 | iny 20 | bne loop1 21 | inc 3 22 | dex 23 | bne loop1 24 | 25 | +vset vreg_pal | AUTO_INC_1 26 | 27 | ldx #2 28 | ldy #0 29 | lda #palette 32 | sta 3 33 | loop3: lda (2),y 34 | sta veradat 35 | iny 36 | bne loop3 37 | inc 3 38 | dex 39 | bne loop3 40 | 41 | +vset vreg_lay2 | AUTO_INC_1 42 | 43 | lda #0 ; disabled 44 | sta veradat ; 0 45 | 46 | +vset vreg_lay1 | AUTO_INC_1 47 | 48 | lda #7 << 5 | 1; // mode=7, enabled=1 49 | sta veradat ; 0 50 | ; ignore 51 | sta veradat ; 1 52 | ; ignore 53 | sta veradat ; 2 54 | ; ignore 55 | sta veradat ; 3 56 | lda #(0 >> 2) & 0xff; // map_base 57 | sta veradat; 4 58 | lda #0 >> 10; 59 | sta veradat ; 5 60 | 61 | +vset vreg_cmp + 1 | AUTO_INC_1 62 | 63 | lda #64 64 | sta veradat ; hscale=2x 65 | sta veradat ; vscale=2x 66 | 67 | jmp * 68 | 69 | bitmap: 70 | !bin "mode7-bitmap-cut.bin" 71 | palette: 72 | !bin "mode7-palette.bin" 73 | -------------------------------------------------------------------------------- /basic/koala.bas: -------------------------------------------------------------------------------- 1 | 0 REM A LOADER FOR IMAGES IN KOALA PAINTER FORMAT 2 | 10 TI=0 3 | 15 PRINT CHR$(147):INPUT"PICTURE FILE:";A$ 4 | 18 IF A$="" THEN A$="TESTIMG2.PIC" 5 | 20 GOSUB 20000:GOSUB 10000:TT=TI 6 | 30 GETA$:IFA$=""THEN30 7 | 40 GOSUB 25000:PRINT"TIME: ";TT:END 8 | 10000 LOADA$,8,1,40960 9 | 10015 BS=40960:SS=BS+8000:CS=SS+1000:BG=CS+1000 10 | 10055 MP=0:MC=0:MS=0:YA=0:X=0:Y=0:D=4:BO=PEEK(40801):X2=0 11 | 10060 FORI=0TO7999 12 | 10070 PP=BS+MP:GOSUB 16000:B=PP 13 | 10080 P=INT(B/64):GOSUB 15000:PSET X2,Y,CV:PSET X2+1,Y,CV 14 | 10100 P=(B/16) AND 3:GOSUB 15000:PSET X2+2,Y,CV:PSET X2+3,Y,CV 15 | 10120 P=(B/4) AND 3:GOSUB 15000:PSET X2+4,Y,CV:PSET X2+5,Y,CV 16 | 10140 P=B AND 3:GOSUB 15000:PSET X2+6,Y,CV:PSET X2+7,Y,CV 17 | 10190 X=X+4:MP=MP+8:X2=X2+8 18 | 10200 IF X<160 THEN NEXT:RETURN 19 | 10210 X=0:X2=0:Y=Y+1:MP=MP-319:MC=MC+1:IFMC=8THENMS=MS+320:MP=MS:MC=0:YA=YA+40 20 | 10220 NEXT 21 | 11000 RETURN 22 | 15000 IF P=0 THEN PP=BG:GOSUB 16000:CV=PP AND 15:RETURN 23 | 15010 CP=X/D+YA 24 | 15020 IF P=3 THEN PP=CS+CP:GOSUB 16000:CV=PP AND 15:RETURN 25 | 15030 IF P=2 THEN PP=SS+CP:GOSUB 16000:CV=PP AND 15:RETURN 26 | 15040 IF P=1 THEN PP=SS+CP:GOSUB 16000:CV=PP/16:RETURN 27 | 15050 PRINT "????":GOSUB 25000:END 28 | 16000 BA=1:IF (PP>49151) THEN PP=PP-8192:BA=2 29 | 16015 POKE40801,BA:PP=PEEK(PP):POKE40801,BO:RETURN 30 | 20000 SCREEN 128:RETURN 31 | 25000 SCREEN 2:PRINTCHR$(147);:RETURN 32 | -------------------------------------------------------------------------------- /assembly/mode4-demo.asm: -------------------------------------------------------------------------------- 1 | !src "vera.inc" 2 | 3 | *=$0801 4 | 5 | !byte $0b,$08,$01,$00,$9e,$32,$30,$36,$31,$00,$00,$00 6 | 7 | +video_init 8 | 9 | +vset $00000 | AUTO_INC_1 ; VRAM bank 0 10 | 11 | ldx #8 12 | ldy #0 13 | lda #tilemap 16 | sta 3 17 | loop1: lda (2),y 18 | sta veradat 19 | iny 20 | bne loop1 21 | inc 3 22 | dex 23 | bne loop1 24 | 25 | +vset $10000 | AUTO_INC_1 ; VRAM bank 1 26 | 27 | ldx #14 28 | ldy #0 29 | lda #tiles 32 | sta 3 33 | loop2: lda (2),y 34 | sta veradat 35 | iny 36 | bne loop2 37 | inc 3 38 | dex 39 | bne loop2 40 | 41 | +vset vreg_pal | AUTO_INC_1 42 | 43 | ldx #2 44 | ldy #0 45 | lda #palette 48 | sta 3 49 | loop3: lda (2),y 50 | sta veradat 51 | iny 52 | bne loop3 53 | inc 3 54 | dex 55 | bne loop3 56 | 57 | +vset vreg_lay1 | AUTO_INC_1 58 | 59 | lda #4 << 5 | 1; mode=4, enabled=1 60 | sta veradat 61 | lda #1 << 5 | 1 << 4; // tileh=1, tilew=1 62 | sta veradat 63 | lda #(0 >> 2) & 0xff; // map_base 64 | sta veradat 65 | lda #0 >> 10; 66 | sta veradat 67 | lda #(0x10000 >> 2) & 0xff; // tile_base 68 | sta veradat 69 | lda #0x10000 >> 10; 70 | sta veradat 71 | 72 | jmp * 73 | 74 | tilemap: 75 | !bin "mode4-tilemap.bin" 76 | tiles: 77 | !bin "mode4-tiles.bin" 78 | palette: 79 | !bin "mode4-palette.bin" 80 | -------------------------------------------------------------------------------- /assembly/vera.inc: -------------------------------------------------------------------------------- 1 | ; License: Public Domain 2 | 3 | !if MACHINE_C64 = 1 { 4 | verareg =$df00 5 | } else { 6 | verareg =$9f20 7 | } 8 | veralo = verareg+0 9 | veramid = verareg+1 10 | verahi = verareg+2 11 | veradat = verareg+3 12 | veradat2= verareg+4 13 | veractl = verareg+5 14 | veraien = verareg+6 15 | veraisr = verareg+7 16 | 17 | vreg_cmp = $F0000 18 | vreg_pal = $F1000 19 | vreg_lay1 = $F2000 20 | vreg_lay2 = $F3000 21 | vreg_spr = $F4000 22 | vreg_sprd = $F5000 23 | 24 | AUTO_INC_1 = $100000 25 | 26 | !macro vset .addr { 27 | lda #<(.addr >> 16) | $10 28 | sta verahi 29 | lda #<(.addr >> 8) 30 | sta veramid 31 | lda #<(.addr) 32 | sta veralo 33 | } 34 | 35 | !macro vstore .addr { 36 | pha 37 | +vset .addr 38 | pla 39 | sta veradat 40 | } 41 | 42 | !macro vload .addr { 43 | +vset .addr 44 | lda veradat 45 | } 46 | 47 | !macro sprset .offset { 48 | lda #<(vreg_sprd >> 16) | $10 49 | sta verahi 50 | txa 51 | lsr 52 | lsr 53 | lsr 54 | lsr 55 | lsr 56 | clc 57 | adc #<(vreg_sprd + .offset >> 8) 58 | sta veramid 59 | txa 60 | asl 61 | asl 62 | asl 63 | clc 64 | adc #<((vreg_sprd + .offset)) 65 | sta veralo 66 | } 67 | 68 | !macro sprload .offset { 69 | +sprset .offset 70 | lda veradat 71 | } 72 | 73 | !macro sprstore .offset { 74 | pha 75 | +sprset .offset 76 | pla 77 | sta veradat 78 | } 79 | 80 | !macro video_init { 81 | lda #0 82 | sta veractl ; set ADDR1 active 83 | sta veramid 84 | lda #$1F ; $F0000 increment 1 85 | sta verahi 86 | lda #$00 87 | sta veralo 88 | lda #1 89 | sta veradat ; VGA output 90 | } 91 | -------------------------------------------------------------------------------- /basic/fractal256.bas: -------------------------------------------------------------------------------- 1 | 0 REM FRACTAL256.BAS 2 | 1 REM BY EGONOLSEN71 3 | 2 REM ADAPTED TO VERA 0.9 AND EMU R38 BY SERERRIS 4 | 10 PRINT CHR$(147); 5 | 20 GOSUB 20000:GOSUB 30000 6 | 300 XL = -1.2:XU = -1.185 7 | 310 YL = -0.195:YU = -0.185 8 | 311 REM XL = -2.000:XU = 0.500 9 | 312 REM YL = -1.100:YU = 1.100 10 | 315 REPS = 255 11 | 316 ITERS% = 0 12 | 320 WIDTH = 320:HEIGHT = 200 13 | 330 XINC = (XU-XL)/WIDTH 14 | 340 YINC = (YU-YL)/HEIGHT 15 | 400 REM MAIN 16 | 410 FOR J = 0 TO HEIGHT - 1 17 | 420 FOR I = 0 TO WIDTH - 1 18 | 510 ISMND = -1 19 | 512 NREAL = XL + I * XINC 20 | 513 NIMG = YL + J * YINC 21 | 515 RZ = 0: IZ = 0 22 | 516 R2Z = 0: I2Z = 0 23 | 520 FOR K = 0 TO REPS 24 | 530 R2Z = RZ*RZ - IZ*IZ 25 | 540 I2Z = 2*RZ*IZ 26 | 550 RZ = R2Z+NREAL 27 | 560 IZ = I2Z +NIMG 28 | 565 ITERS%=K 29 | 570 IF (RZ*RZ + IZ*IZ)>4 THEN ISMND=0:K=REPS 30 | 590 NEXT 31 | 620 IF ISMND<>0 THEN CV=0:GOTO 630 32 | 625 CV=ITERS% 33 | 630 GOSUB 10000 34 | 640 NEXT:NEXT 35 | 690 GET A$:IF A$ = "" THEN 690 36 | 750 END 37 | 10000 REM PLOT PIXEL 38 | 10020 PO=J*320+I:BA=0 39 | 10030 IF PO>$FFFF THEN PO=PO-$FFFF:BA=1 40 | 10040 VPOKE BA, PO, CV 41 | 10050 RETURN 42 | 20000 REM SETUP SCREEN 43 | 20009 REM 320x200 HSCALE=52:VSCALE=64 44 | 20010 POKE $9F2A,52:POKE $9F2B,64:POKE 199,40 45 | 20019 REM 8BPP BITMAP MODE: SCREENSTART $00000: LAYER0 ONLY 46 | 20020 POKE $9F2D,$07:POKE $9F2F,$00:POKE $9F29,$11 47 | 20030 RETURN 48 | 30000 REM SETUP COLOR PALETTE 49 | 30010 RP=20:GP=80:BP=100 50 | 30020 FOR I=0TO255 51 | 30030 VPOKE 1, $FA00+I*2, INT(GP/16)*16+INT(BP/16) 52 | 30035 VPOKE 1, $FA00+I*2+1, INT(RP/16) 53 | 30040 RP=RP+7:GP=GP+9:BP=BP+5 54 | 30050 IF RP>255 THEN RP=20 55 | 30060 IF GP>255 THEN GP=20 56 | 30070 IF BP>255 THEN BP=20 57 | 30080 NEXT:RETURN 58 | -------------------------------------------------------------------------------- /basic/acey-ducey.bas: -------------------------------------------------------------------------------- 1 | 5 ?TAB(12)"FROM ORIGINAL BY BILL PALMBY OF PRAIRIE VIEW, ILLINOIS" 2 | 15 ?TAB(25)"MODIFIED BY CARL BURKS" 3 | 20 ?TAB(26)"ACEY DUCEY CARD GAME" 4 | 30 FOR I=1 TO 3:?"":NEXT 5 | 40 ?"ACEY-DUCEY IS PLAYED IN THE FOLLOWING MANNER" 6 | 50 ?"THE DEALER(COMPUTER) DEALS TWO CARDS FACE UP" 7 | 60 ?"YOU HAVE AN OPTION TO BET OR NOT TO BET DEPENDING" 8 | 70 ?"ON WHETHER OR NOR YOU FEEL THE CARD WILL HAVE" 9 | 80 ?"A VALUE BETWEEN THE FIRST TWO" 10 | 90 ?"IF YOU DO NOT WANT TO BET, INPUT A 0" 11 | 100 DEF FN CARD(A)=INT(13*RND(1))+2 12 | 110 N=100 13 | 120 Q=100:REM MONEY 14 | 130 ?"YOU NOW HAVE ";Q;" DOLLARS":REM ROUND START 15 | 140 ?"" 16 | 150 ?"HERE ARE YOUR NEXT TWO CARDS" 17 | 160 A=FN CARD(0) 18 | 170 B=FN CARD(0) 19 | 180 IF (A+3)>(B) THEN 160 20 | 190 ?"FIRST CARD" 21 | 200 C=A 22 | 210 GOTO 240 23 | 220 ?"SECOND CARD" 24 | 230 C=B 25 | 240 IF C<11 THEN 290 26 | 250 IF C>13 THEN 370 27 | 260 IF C>12 THEN 350 28 | 270 IF C>11 THEN 330 29 | 280 IF C=11 THEN 310 30 | 290 ? C 31 | 300 GOTO 380 32 | 310 ?"JACK" 33 | 320 GOTO 380 34 | 330 ?"QUEEN" 35 | 340 GOTO 380 36 | 350 ?"KING" 37 | 360 GOTO 380 38 | 370 ?"ACE" 39 | 380 IF B<>C THEN 220 40 | 390 INPUT"WHAT IS YOUR BET";M:REM START BETTING 41 | 400 IF M>1 THEN 440 42 | 410 ?"CHICKEN!!" 43 | 420 ?"" 44 | 430 GOTO 130 45 | 440 IF M<=Q THEN 470 46 | 450 ?"YOU'VE BET TOO MUCH" 47 | 460 GOTO 390 48 | 470 Q=Q-M 49 | 480 C=FN CARD(0) 50 | 490 ?"LAST CARD" 51 | 500 IF C<11 THEN 550 52 | 510 IF C>13 THEN 610 53 | 520 IF C>12 THEN 600 54 | 530 IF C>11 THEN 590 55 | 540 IF C=11 THEN 570 56 | 550 ?C 57 | 560 GOTO 640 58 | 570 ?"JACK" 59 | 580 GOTO 640 60 | 590 ?"QUEEN" 61 | 600 GOTO 640 62 | 610 ?"KING" 63 | 620 GOTO 640 64 | 630 ?"ACE" 65 | 640 IF CB THEN 690 67 | 660 Q=Q+(M*2) 68 | 670 ?"YOU WIN" 69 | 680 GOTO 130 70 | 690 ?"YOU LOST" 71 | 700 IF Q>0 GOTO 130 72 | 710 ?"YOU ARE OUT OF MONEY." 73 | 720 SYS$FFFF:REM CLOSE THE EMU -------------------------------------------------------------------------------- /basic/tile4bpp.bas: -------------------------------------------------------------------------------- 1 | 100 REM MAKE TILES 4BPP 2 | 110 REM RANDALL BOHN 2019.10.12 3 | 120 GOSUB 2100 :REM RANDOM TILES 4 | 130 GOSUB 400 :REM FILL PALETTE 5 | 140 GOSUB 300 :REM SET UP LAYER ONE 6 | 150 GOSUB 200 :REM PUT TILES ON SCREEN 7 | 160 END 8 | 9 | 200 REM RANDOM TILE FILL 10 | 210 FOR X = 40 TO 79 11 | 220 FOR Y = 0 TO 31 12 | 230 TX=INT(RND(1)*4)+1 13 | 240 VPOKE 0,16*1024+256*Y+X*2, TX :REM RANDOM TILE 14 | 250 VPOKE 0,16*1024+256*Y+X*2+1, $10 :REM PALETTE SHIFT 16 15 | 260 NEXT Y 16 | 270 NEXT X 17 | 280 RETURN 18 | 19 | 300 REM SET UP L1 20 | 310 VPOKE 15,$3005,$18 :REM TILES AT 24*1024 21 | 320 VPOKE 15,$3003,$10 :REM MAP AT 16*1024 22 | 330 VPOKE 15,$3001,$0E :REM MAPH=256 MAPW=128 23 | 340 VPOKE 15,$3000,$61 :REM MODE 3 (4 BPP) 24 | 350 RETURN 25 | 26 | 400 REM FILL PALETTE 16..31 27 | 410 SLOT = $1000+32 28 | 420 FOR X = 0 TO 15 29 | 430 READ R,G,B 30 | 440 VPOKE 15, SLOT+X*2, G*16+B 31 | 450 VPOKE 15, SLOT+X*2+1, R 32 | 460 NEXT X 33 | 470 U=VPEEK(15,SLOT):VPOKE 15,$1000,U :REM COPY ENTRY 16 TO 0 34 | 480 U=VPEEK(15,SLOT+1):VPOKE 15,$1001,U 35 | 490 POKE 713,1:PRINT CHR$(147) :REM CLEAR SCREEN WITH NEW BACKGROUND 36 | 499 RETURN 37 | 38 | 1100 REM "TEMPERATURE" PALETTE 39 | 1110 DATA 0,2,3 40 | 1120 DATA 0,2,5 41 | 1130 DATA 1,3,7 42 | 1140 DATA 3,3,8 43 | 1150 DATA 5,3,9 44 | 1160 DATA 7,4,9 45 | 1170 DATA 8,5,8 46 | 1180 DATA 10,5,8 47 | 1190 DATA 11,6,7 48 | 1200 DATA 13,6,6 49 | 1210 DATA 14,7,5 50 | 1220 DATA 15,8,4 51 | 1230 DATA 15,10,4 52 | 1240 DATA 15,11,4 53 | 1250 DATA 15,13,4 54 | 1260 DATA 14,15,5 55 | 1270 DATA 15,15,10 56 | 57 | 2100 REM MAKE RANDOM TILES 1..4 58 | 2110 N=1:V=0:GOSUB 2200 59 | 2120 N=2:V=4:GOSUB 2200 60 | 2130 N=3:V=8:GOSUB 2200 61 | 2140 N=4:V=12:GOSUB 2200 62 | 2150 RETURN 63 | 2200 TN=24*1024+32*N :REM FILL TILE N 64 | 2210 FOR X = 0 TO 31 65 | 2220 CC = INT(RND(1)*4)+V 66 | 2230 CC = 255 AND (CC*16+CC) 67 | 2240 VPOKE 0,TN+X,CC 68 | 2250 NEXT X 69 | 2260 RETURN 70 | -------------------------------------------------------------------------------- /assembly/mode4-tilemap.bin: -------------------------------------------------------------------------------- 1 |  2 |  3 | 4 | 5 | 6 |  -------------------------------------------------------------------------------- /basic/cx16logo.bas: -------------------------------------------------------------------------------- 1 | 5 REM BY STEVE CLARK https://www.facebook.com/groups/CommanderX16/permalink/518653948885704/ 2 | 10 SCREEN 2 : REM SWITCH TO 80 CHARACTER MODE 3 | 20 FOR I=1 TO 60:PRINT:NEXT 4 | 30 RI=(60-42)/2:CI=(80-66)/2 5 | 110 X=$40:FOR I= 0 TO 5:R0=RI+I:C0=CI+ I:GOSUB 220:NEXT 6 | 120 X=$E0:FOR I= 6 TO 11:R0=RI+I:C0=CI+ I:GOSUB 220:NEXT 7 | 130 X=$30:FOR I=12 TO 17:R0=RI+I:C0=CI+ I:GOSUB 220:NEXT 8 | 140 X=$50:FOR I=18 TO 23:R0=RI+I:C0=CI+24 :GOSUB 220:NEXT 9 | 150 X=$70:FOR I=24 TO 29:R0=RI+I:C0=CI+42-I:GOSUB 220:NEXT 10 | 160 X=$A0:FOR I=30 TO 35:R0=RI+I:C0=CI+42-I:GOSUB 220:NEXT 11 | 170 X=$20:FOR I=36 TO 41:R0=RI+I:C0=CI+42-I:GOSUB 220:NEXT 12 | 180 GOTO 320 13 | 210 REM SUBROUTINE 14 | 220 C1=17:IF (C0+C1)>(40-4) THEN C1=40-C0-4 15 | 230 FOR C=0 TO C1 16 | 240 VPOKE 0,256*(R0+R)+2*( C0+C)+1,X 17 | 250 VPOKE 0,256*(R0+R)+2*(80-C0-C)-1,X 18 | 260 NEXT 19 | 270 RETURN 20 | 310 REM GET A RANDOM LOCATION IN LEFT HALF 21 | 320 RL=INT(RND(1)*60):CL=INT(RND(1)*80):IF CL>40 THEN GOTO 320 22 | 330 XL=VPEEK(0,256*RL+2*CL+1):REM SAVE THE CURRENT BLOCK COLOR 23 | 340 IF (XL AND $F0)=$60 THEN GOTO 320 24 | 350 REM GET A RANDOM LOCATION IN RIGHT HALF 25 | 360 RR=INT(RND(1)*60):CR=INT(RND(1)*80):IF CR<41 THEN GOTO 360 26 | 370 XR=VPEEK(0,256*RR+2*CR+1):REM SAVE THE CURRENT BLOCK COLOR 27 | 380 IF (XR AND $F0)=$60 THEN GOTO 350 28 | 410 REM LOOP 29 | 420 X=XL:R=RL:C=CL:GOSUB 520 30 | 430 XL=X:RL=R:CL=C 31 | 440 X=XR:R=RR:C=CR:GOSUB 520 32 | 450 XR=X:RR=R:CR=C 33 | 460 GOTO 410:REM LOOP 34 | 510 REM SUBROUTINE 35 | 520 D=INT(RND(1)*4):REM GET A RANDOM DIRECTION 36 | 530 R1=R:C1=C 37 | 540 IF D=0 THEN R1=R-1:GOTO 600:REM MOVE UP 38 | 550 IF D=1 THEN R1=R+1:GOTO 600:REM MOVE DOWN 39 | 560 IF D=2 THEN C1=C-1:GOTO 600:REM MOVE LEFT 40 | 570 IF D=3 THEN C1=C+1:GOTO 600:REM MOVE RIGHT 41 | 580 STOP:REM SHOULD NEVER GET HERE 42 | 590 REM MOVE 43 | 600 Y=VPEEK(0,256*R1+2*C1+1):REM GET THE NEW BLOCK COLOR 44 | 610 IF (Y AND $F0)=$60 THEN GOTO 640 45 | 620 VPOKE 0,256*R+2*C+1,Y:VPOKE 0,256*R1+2*C1+1,X 46 | 630 X=Y:R=R1:C=C1 47 | 640 RETURN 48 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Commander X16 Demo Code 2 | 3 | :+1::tada: First off, thanks for taking the time to contribute! :tada::+1: 4 | 5 | How Can I Contribute? 6 | * [Reporting Bugs](#reporting-bugs) 7 | * [Pull Requests](#pull-requests) 8 | 9 | ## Reporting Bugs 10 | Bugs are tracked as [GitHub issues](https://guides.github.com/features/issues/). 11 | 12 | Before reporting a bug, ensure it is new, and add a short, simple way to reproduce it. 13 | 14 | ### Known issues 15 | #### Demo xyz is not working on my emulator. 16 | Because the emulator is growing faster, sometime the last pushed demo code need the last version of the emulator. 17 | 18 | If a code does not work (like sprites) download always the LAST version of the emulator **before submitting** a bug report. 19 | 20 | ## Pull Requests 21 | The easiest way of contributing is forking the repository and submitting a pull request. 22 | 23 | Please follow these steps to have your contribution considered by the maintainers: 24 | 25 | ### For Basic files: 26 | 27 | 1. Contribute with source file ending in .bas extension (not binary). Filename must be without space and lowercase 28 | 2. Bas file must be in ASCII UTF-8 with uppercase letters 29 | 3. If needed renumber them using the renumber tool (see tools directory) 30 | 4. If subroutine, provide at least one usage example 31 | 32 | 5. Do not forget to add AUTHOR AND LICENSE information in the head of the file via REMs 33 | 34 | ### For Assembly code: 35 | 36 | 1. Group your code in one directory per project 37 | 2. Include a Makefile per project 38 | 3. Include the directory in the main Makefile, adding it to the SUBDIRS variable (first line) 39 | 4. Test it (see HOW TO COMPILE in the README.md) 40 | 5. Do not forget to add AUTHOR AND LICENSE information in the head of the file via ';' comments 41 | 42 | ## Documentation 43 | For documentation download a copy of the [Commander X16 Programmers Reference](https://github.com/commanderx16/x16-docs). 44 | 45 | Commander X16 has a BASIC V2 version derived from the C64 one. It will grow and offer more commands in the future. 46 | Take a look at [Commander X16 ROM project](https://github.com/commanderx16/x16-rom) for a short introduction to the Basic and Kernel services. 47 | -------------------------------------------------------------------------------- /tools/bin2c.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2019, Frank Buss 4 | # All rights reserved. 5 | 6 | # Redistribution and use in source and binary forms, with or without 7 | # modification, are permitted provided that the following conditions are met: 8 | 9 | # 1. Redistributions of source code must retain the above copyright notice, this 10 | # list of conditions and the following disclaimer. 11 | 12 | # 2. Redistributions in binary form must reproduce the above copyright notice, 13 | # this list of conditions and the following disclaimer in the documentation 14 | # and/or other materials provided with the distribution. 15 | 16 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | 27 | 28 | import numpy as np 29 | import math 30 | import sys 31 | import argparse 32 | 33 | # parse arguments 34 | parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter, 35 | description='Converts any bin file to a C array.') 36 | parser.add_argument('name', help='the C array name') 37 | parser.add_argument('input', help='the input file name') 38 | parser.add_argument('output', help='the output file name') 39 | args = parser.parse_args() 40 | 41 | # convert data 42 | data = open(args.input, "rb").read() 43 | with open(args.output, "w") as out: 44 | out.write("uint8_t %s[] = {\n" % args.name) 45 | i = 0 46 | for b in data: 47 | out.write("0x%02x," % b) 48 | i = i + 1 49 | if i == 16: 50 | out.write("\n") 51 | i = 0 52 | out.write("};\n") 53 | -------------------------------------------------------------------------------- /basic/basic-benchmark.bas: -------------------------------------------------------------------------------- 1 | 0 REM BASIC-BENCHMARK.BAS BY OLEG-IMANILOV 2 | 1 REM UPDATES BY TOM WILSON FOR RAW/ADJUSTED TIME 3 | 9 REM GITHUB.COM/COMMANDERX16/X16-DEMO 4 | 10 PRINT CHR$(147); 5 | 15 FF=1250: REM NUMBER OF EXECUTIONS TO GET AVERAGE 6 | 20 TXT$ = "EMPTY FOR LOOP" 7 | 30 T0=TI 8 | 40 FOR I=0 TO FF 9 | 45 REM 10 | 50 NEXT 11 | 55 T1 = TI 12 | 60 PRINT "--------------------------+------------+------+----------- 13 | 62 PRINT " OPERATION : OP/SEC : TIME : ADJUSTED 14 | 64 PRINT "--------------------------+------------+------+----------- 15 | 70 GOSUB 32000 16 | 75 PRINT " : : : 17 | 80 Z=T1-T0:Z0=Z:REM ZERO TIME 18 | 90 IF Z<10 THEN PRINT "WARNING: ZERO TIME IS TOO LOW, INCREASE FF!" 19 | 110 TXT$ = "SMALL INT ASSIGNMENT" 20 | 120 A = 0 21 | 130 T0 = TI 22 | 140 FOR I=0 TO FF 23 | 150 A = 55 24 | 160 NEXT 25 | 170 T1=TI 26 | 180 GOSUB 32000 27 | 190 ZI=TE:REM SAVE FOR LATER (TO REMOVE THIS FROM "ADD SMALL INT") 28 | 210 TXT$ = "BIG INT ASSIGNMENT" 29 | 220 A = 100000 30 | 230 T0 = TI 31 | 240 FOR I=0 TO FF 32 | 250 A = 100000 33 | 260 NEXT 34 | 270 T1=TI 35 | 280 GOSUB 32000 36 | 290 ZL=TE 37 | 310 TXT$ = "FLOAT ASSIGNMENT" 38 | 320 A = 123.456 39 | 330 T0 = TI 40 | 340 FOR I=0 TO FF 41 | 350 A = 1234.5678 42 | 360 NEXT 43 | 370 T1=TI 44 | 380 GOSUB 32000 45 | 390 ZF=TE 46 | 410 TXT$ = "SMALL INT ADD" 47 | 420 A = 3 48 | 430 T0 = TI 49 | 440 FOR I=0 TO FF 50 | 450 A = 1+1 51 | 460 NEXT 52 | 470 T1=TI 53 | 475 Z=ZI 54 | 480 GOSUB 32000 55 | 490 Z=Z0 56 | 510 TXT$ = "BIG INT ADD" 57 | 520 A = 3 58 | 530 T0 = TI 59 | 540 FOR I=0 TO FF 60 | 550 A = 500+700 61 | 560 NEXT 62 | 570 T1=TI 63 | 575 Z=ZL 64 | 580 GOSUB 32000 65 | 590 Z=Z0 66 | 610 TXT$ = "FLOAT ADD" 67 | 620 A = 123.456:B=123.456 68 | 630 T0 = TI 69 | 640 FOR I=0 TO FF 70 | 650 A = 12.34+12.34 71 | 660 NEXT 72 | 670 T1=TI 73 | 675 Z=ZF 74 | 680 GOSUB 32000 75 | 690 Z=Z0 76 | 710 TXT$ = "SIN" 77 | 720 A = 123.456 78 | 730 T0 = TI 79 | 740 FOR I=0 TO FF 80 | 750 A = SIN(1.23) 81 | 760 NEXT 82 | 770 T1=TI 83 | 780 GOSUB 32000 84 | 810 TXT$ = "SMALL NUMBER POWER" 85 | 820 A = 10 86 | 830 T0 = TI 87 | 840 FOR I=0 TO FF 88 | 850 A = 2^3 89 | 860 NEXT 90 | 870 T1=TI 91 | 875 Z=ZI 92 | 880 GOSUB 32000 93 | 31999 END 94 | 32000 PRINT TXT$;TAB(26);":"; 95 | 32010 TE=T1-T0:TA=TE-Z:REM ELAPSED, ADJUSTED TIME 96 | 32020 PRINT FF/TA*60; 97 | 32030 PRINT TAB(39);":";TE; 98 | 32040 PRINT TAB(46);":";TA; 99 | 32050 PRINT 100 | 32060 RETURN 101 | -------------------------------------------------------------------------------- /basic/fastfract256.bas: -------------------------------------------------------------------------------- 1 | 0 REM **COMMANDER X16 MANDELBROT ** 2 | 1 REM **BY SERERRIS 16.08.2020 ** 3 | 2 REM **FOR LEARNING AND EDUCATION ** 4 | 3 REM **THIS MANDELBROT USES BOTH VERA DATA REGISTERS TO SPEEDUP 5 | 4 REM **RENDERING 6 | 100 REM VARIABLES SETUP 7 | 110 REM MANDELBROT DIMENSIONS 8 | 120 XL=-2.000:XU=0.500 9 | 130 YL=-1.100:YU=1.100 10 | 140 MI%=20 :REM MAXIMUM ITERATIONS 11 | 150 WI%=320:HI%=240 :REM SCREEN DIMENSIONS 12 | 155 MA=WI%*HI% :REM END OF SCREEN ADDRESS 13 | 160 XI=(XU-XL)/WI% :REM X INCREMENT 14 | 170 YI=(YU-YL)/HI% :REM Y INCREMENT 15 | 300 REM SCREEN SETUP 16 | 310 GOSUB 10000:REM SETUP SCREEN 17 | 320 REM GOSUB 10100:REM CLEAR SCREEN 18 | 330 GOSUB 15000 :REM SETUP PALLETTE 19 | 340 GOSUB 10200:REM SET POINTER TO BEGIN 20 | 500 REM MAIN ROUTINE 21 | 510 XE=XU-XI:YE=YL+(HI%/2*YI) :REM DEFINE LOOP END FOR FASTER LOOPING 22 | 520 TA=MA :REM SET UPPER ADDRESS TO END OF SCREEN 23 | 530 FOR Y0=YL TO YE STEP YI 24 | 540 REM CACULATE UPPER VRAM ADDRESS 25 | 550 TA=TA-WI%:AP%=0:AB=TA 26 | 560 IF AB>$FFFF THEN AP%=1:AB=AB-$10000 :REM SET AP% FOR PAGE 27 | 570 AH%=INT(AB/256) : REM GATHER HI BYTE 28 | 580 AL%=AB-AH%*256 : REM GATHER LOW BYTE 29 | 590 REM SET ADDRESS REGISTER FOR DATA BYTE 1 30 | 600 POKE $9F25,$01:POKE $9F20,AL%:POKE $9F21,AH%:POKE $9F22,($10+AP%) 31 | 610 FOR X0=XL TO XE STEP XI 32 | 620 GOSUB 2000 :REM CALCULATE MANDELBROT 33 | 700 POKE $9F23,IT%:REM PUT ACTUAL ITERATION INTO VRAM LINE 34 | 710 POKE $9F24,IT%:REM PUT ACTUAL ITERATION INTO MIRRORED LINE 35 | 800 NEXT X0 36 | 810 NEXT Y0 37 | 1900 REM THE END 38 | 1910 GET A$:IF A$="" THEN GOTO 900 39 | 1920 GOSUB 10300:REM CLEANUP MODE 40 | 1930 END 41 | 2000 :REM CALCULATE MANDELBROT 42 | 2010 X=0:Y=0:IT%=0 43 | 2020 X2=0:Y2=0 44 | 2030 :REM WHI%LE 45 | 2040 XY=X*Y 46 | 2050 X=X2-Y2+X0 47 | 2060 Y=2*XY+Y0 48 | 2070 IT%=IT%+1 49 | 2080 X2=X*X:Y2=Y*Y 50 | 2090 IF (X2+Y2 <= 4) AND (IT% < MI%) THEN GOTO 2030 51 | 2100 IF IT%=MI% THEN IT%=0 52 | 2110 IT%=IT%-INT(IT%/16)*16 53 | 2200 RETURN 54 | 10000 :REM SETUP SCREEN SCALING 2X = 320X240 55 | 10010 POKE $9F2B,64:POKE $9F2A,64 56 | 10020 REM SETUP BITMAP MODE 4BPP AND BITMAP START $4000 57 | 10030 POKE $9F2F,$00:POKE $9F2D,$07:POKE $9F29, $11 58 | 10031 REM:POKE $9F2F,$00:POKE $9F2D,$07:POKE $9F29,PEEK($9F29) OR $11 59 | 10040 COLOR 6,0 :PRINT CHR$(147); 60 | 10050 RETURN 61 | 10100 :REM CLEAR BITMAP 62 | 10110 GOSUB 10200 63 | 10120 FOR I=0 TO HI%*WI% 64 | 10130 POKE $9F23,$12:NEXT 65 | 10140 RETURN 66 | 10200 :REM SETUP VRAM ADDRESS AND INCREMENT 67 | 10210 POKE $9F21,$00:POKE $9F20,$00:POKE $9F22,$10 -------------------------------------------------------------------------------- /basic/fractalland.bas: -------------------------------------------------------------------------------- 1 | 5 SCREEN 2:PRINTCHR$(147);:GOSUB50000 2 | 10 TI$="000000":WE=1:BR=8:BL=6:GR=5:SC=11 3 | 20 INPUT"X-COORDINATE: X=";X1 4 | 30 INPUT"Y-COORDINATE: Y=";Y1 5 | 40 XC=X1:YC=Y1 6 | 50 GOSUB 10000 7 | 60 PRINT"HEIGHT AT ";X1;"/";Y1;":";INT(Z*1000+.5)/1000 8 | 70 INPUT"VIEWER'S HEIGHT: Z=";H:IF H400 THEN RETURN 38 | 10070 GOTO 10010 39 | 20000 IF ABS(C)>102 THEN C=102*SGN(C) 40 | 20010 IA=160+HO:IB=161+HO:JA=98-C:JB=99-C 41 | 20020 IF JA>199 THEN JA=199 42 | 20030 IF JB>199 THEN JB=199 43 | 20040 IF JA<0 THEN JA=0 44 | 20045 IF JB<0 THEN JB=0 45 | 20050 IF IB<320 THEN LINE IB,199,IB,JA,WE 46 | 20055 IF IA>319 THEN RETURN 47 | 20060 LINE IA,199,IA,JB,BR 48 | 20070 IF C<0 THEN LINE IA,JB,IA,JB,FA 49 | 20080 IF C<=CA+0.3 THEN 20090 50 | 20082 YK=99-CA:IF YK>=0 AND YK<200 THEN LINE IA,YK,IA,JB,SC 51 | 20090 LINE IA,JA,IA,JA,FA:RETURN 52 | 30000 SCREEN 128:RECT 0,0,319,199,14:RETURN 53 | 40000 FORI=4 TO 96 STEP 2 54 | 40010 J=(I/96)^6.6:J=J*94 55 | 40020 BF=RND(0)+0.7:BF=BF*I*0.14 56 | 40030 AP=RND(0)*520-100:BF=BF*(2-RND(0)*0.8) 57 | 40040 FOR HO=-BF TO BF 58 | 40050 XB=HO+AP:IF ABS(XB-160)>160 THEN 40110 59 | 40060 C1=BF*BF-HO*HO:C1=C1/BF 60 | 40070 YB=C1*J*0.006:YC=95-J:YL=YC-C1:YJ=YC-YB:YK=YC+YB 61 | 40072 IF YL<0 THEN YL=0 62 | 40073 IF YJ<0 THEN YJ=0 63 | 40074 IF YC<0 THEN YC=0 64 | 40076 IF YK<0 THEN YK=0 65 | 40078 IF XB<0 OR XB>319 THEN 40110 66 | 40080 LINE XB,YC,XB,YL,WE 67 | 40090 LINE XB,YJ,XB,YK,15 68 | 40100 LINE XB,YJ,XB,YJ,3 69 | 40110 NEXT:NEXT 70 | 40120 LINE 0,98,319,98,WE:RETURN 71 | 50000 PRINT "FRACTALLAND - THE UNCALCULATED COUNTRY" 72 | 50010 PRINT "--------------------------------------" 73 | 50030 PRINT:PRINT "ENTER X,Y POSITION, A HEIGHT AND THE VIEWING ANGLE" 74 | 50040 PRINT "TO RENDER THE FRACTAL LANDSCAPE AT THAT POSITION." 75 | 50050 PRINT "NICE STARTING VALUES ARE: X=1.5, Y=0, HEIGHT=3, ANGLE=270" 76 | 50060 PRINT:RETURN 77 | -------------------------------------------------------------------------------- /basic/frog.bas: -------------------------------------------------------------------------------- 1 | 5 REM DRAWS A FROG... 2 | 10 SCREEN 0 3 | 100 BL=6:ML=40:AD=0.5:TI$="000000":POKE713,1 4 | 110 DIM I(10),XT(BL),YT(BL),XP(BL),YP(BL),XD(BL),YD(BL),SC(BL) 5 | 120 DIM X,Y,B2,B3,P,PP,AC 6 | 130 VP=20000 7 | 140 WP=21000 8 | 160 GOSUB 900 9 | 190 GOSUB 820 10 | 200 GOSUB 670 11 | 220 GOSUB 270 12 | 230 REM JUMP TARGET 13 | 240 PRINTTI 14 | 250 REM GET A$:IF A$="" THEN 230 15 | 260 END 16 | 270 REM JUMP TARGET 17 | 280 FOR Y=5 TO 22 18 | 290 YT=Y*40+VP 19 | 300 X=8 20 | 310 VX=YT+X 21 | 320 FOR I=0 TO BL 22 | 330 IF XT(I)<>0 THEN 560 23 | 340 IF PEEK(VX)=6 THEN X=X+1:VX=VX+1:GOTO 620 24 | 350 XT(I)=X:YT(I)=Y 25 | 360 IF RND(1)<0.4 THEN 410 26 | 370 XP(I)=6+INT(RND(1)*26) 27 | 380 YP(I)=0 28 | 390 IF Y>10 THEN YP(I)=24 29 | 400 GOTO 450 30 | 410 REM JUMP TARGET 31 | 420 XP(I)=0 32 | 430 IF X>20 THEN XP(I)=39 33 | 440 YP(I)=4+INT(RND(1)*18) 34 | 450 LY=ABS(YT(I)-YP(I)):LX=ABS(XT(I)-XP(I)) 35 | 460 DX=0:DY=0 36 | 470 IF LY>LX THEN LX=LY 37 | 480 IF LX=0 THEN 510 38 | 490 DX=(XT(I)-XP(I))/LX 39 | 500 DY=(YT(I)-YP(I))/LX 40 | 510 XD(I)=DX:YD(I)=DY:SC(I)=PEEK(XT(I)+YT(I)*ML+VP) 41 | 520 AC=AC+1 42 | 530 X=X+1:VX=VX+1 43 | 540 B2=XP(I):B3=YP(I) 44 | 550 GOTO 580 45 | 560 B2=XP(I):B3=YP(I):P=INT(B2+AD)+INT(B3+AD)*ML:CP=INT(P/40):CM=CP*256+1 46 | 570 B2=B2+XD(I):B3=B3+YD(I):VPOKE0,CM+(P-40*CP)*2,PEEK(WP+P) 47 | 580 P1=INT(B2+AD):P2=INT(B3+AD):P=P1+P2*ML:CP=INT(P/40):CM=CP*256+1 48 | 590 VPOKE0,CM+(P-40*CP)*2,SC(I):XP(I)=B2:YP(I)=B3 49 | 600 IF P1<>XT(I)ORP2<>YT(I)THEN 620 50 | 610 POKEWP+XT(I)+YT(I)*ML,SC(I):AC=AC-1:XT(I)=0 51 | 620 NEXT 52 | 630 IF X<33 THEN 310 53 | 640 X=8:IF Y=22 AND AC<>0 THEN Y=21 54 | 650 NEXT 55 | 660 RETURN 56 | 670 REM JUMP TARGET 57 | 680 CL=0 58 | 690 Y=5 59 | 700 X=0 60 | 710 REM JUMP TARGET 61 | 720 READ C:IF C=-99 THEN RETURN 62 | 730 IF C<0 THEN CL=ABS(C):GOTO 710 63 | 740 IF C=100 THEN CL=0:GOTO 710 64 | 750 IF C0 THEN Y=Y+1 65 | 760 IF C<>0 THEN X=C 66 | 770 P=VP+Y*40 67 | 780 READ CN 68 | 790 FOR I=P+X TO P+CN+X-1:POKE I,CL:NEXT I 69 | 800 X=X+CN 70 | 810 GOTO 710 71 | 820 REM JUMP TARGET 72 | 840 FOR I=20000 TO 20999:POKEI,6:NEXT 73 | 860 FOR I=21000 TO 21999:POKEI,6:NEXT 74 | 880 FOR Y=0 TO 29:FOR X=0 TO 39 75 | 882 Q=Y*256+X*2 76 | 884 VPOKE0,Q+1,6 77 | 886 VPOKE0,Q,160 78 | 888 NEXTX,Y 79 | 890 RETURN 80 | 900 REM JUMP TARGET 81 | 910 PRINT CHR$(147); 82 | 930 RETURN 83 | 940 DATA -1,12,4,24,4,10,4,100,0,2,-1,0,2,22,4,100,0,2,-1,0,2 84 | 950 DATA 10,2,100,0,4,-1,0,2,-5,0,4,-1,0,2,100,0,4,-1,0,2 85 | 960 DATA 10,2,100,0,4,-1,0,2,-5,0,4,-1,0,2,100,0,4,-1,0,2 86 | 970 DATA -5,10,2,-1,0,4,-5,0,8,-1,0,4,-5,0,2 87 | 980 DATA 8,24,8,24,8,24,100,10,20,-5,10,20,10,20 88 | 990 DATA 12,16,12,6,-1,0,4,-5,0,6,12,4,-1,0,8,-5,0,4 89 | 1000 DATA 8,2,14,2,-1,0,8,-5,0,2,30,2,10,2,14,2,24,2,28,2 90 | 1010 DATA 8,8,24,8,-99 91 | -------------------------------------------------------------------------------- /assembly/x16-matriculate-text/README.md: -------------------------------------------------------------------------------- 1 | # x16-matriculate-text 2 | 3 | A Matrix-inspired text crawl that totally took me to school. 4 | 5 | *This code works with Vera 0.8*. For Vera 0.7 code, as released in r30 and prior, see [the r30 release](https://github.com/indigodarkwolf/x16-matriculate-text/releases/tag/r30). 6 | 7 | ## ma·tric·u·late 8 | 9 | /məˈtrikyəˌlāt/ (_verb_) 10 | 11 | 1. be enrolled at a college or university. 12 | "he matriculated at the University of Vermont" 13 | 14 | ## Building this demo 15 | 16 | `ACME -f cbm -DMACHINE_C64=0 -o matriculate.prg matriculate.asm` 17 | 18 | ## What this does, in order 19 | 20 | * Perform a table-based decrement of each palette index once per frame until all palette colors have been set to black ($0000). 21 | 22 | * Assign a random character to each screen position 23 | 24 | * Assign a random palette index to each character in the top row 25 | 26 | * Set each subsequent row's character palette indices to "whatever it is directly above me, plus 1". There's 256 colors in the X16's palette, and I can use 255 of them (I have to leave color 0 black for the background, so that means if I'm about to assign palette index "0" to a character, I instead assign "1"). 27 | 28 | * Perform a palette-cycling trick, which is to say I've got an array of colors in program memory from white-green to black, and I just write them to a chunk of the system palette, and then increment my starting point by 1 each frame. The Vera's hardware does the rest, choosing what colors to draw based on that palette. 29 | 30 | ## Getting started with assembly on the X16 31 | 32 | For the X16, the basic tools you need are any text editor and a 6502 assembler program. 33 | 34 | For a text editor, I used Visual Studio Code: 35 | 36 | 37 | 38 | For the assembler, I used Acme 0.96.4: 39 | 40 | 41 | 42 | If you're completely new to assembly and the 6502, I feel like this resource is a good starting point: 43 | 44 | 45 | 46 | I made frequent use of this portion, in particular, to experiment with small assembly samples to try and isolate bugs in my code: 47 | 48 | 49 | 50 | After that, you just need some documentation. Well, a fair bit of documentation. For a reference of 6502 instructions, I liked this page: 51 | 52 | 53 | 54 | And the X16 official documentation is crucial when it comes to understanding what memory you can use, for what purposes: 55 | 56 | 57 | 58 | If the Vera documentation feels a bit over your head, maybe you'd prefer my version on Google docs, just keep in mind that it's not "authoritative" in any sense: 59 | 60 | 61 | -------------------------------------------------------------------------------- /tools/bas2prg.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2019, Frank Buss 4 | # All rights reserved. 5 | 6 | # Redistribution and use in source and binary forms, with or without 7 | # modification, are permitted provided that the following conditions are met: 8 | 9 | # 1. Redistributions of source code must retain the above copyright notice, this 10 | # list of conditions and the following disclaimer. 11 | 12 | # 2. Redistributions in binary form must reproduce the above copyright notice, 13 | # this list of conditions and the following disclaimer in the documentation 14 | # and/or other materials provided with the distribution. 15 | 16 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | 27 | import sys 28 | import argparse 29 | import os 30 | import codecs 31 | 32 | # parse arguments 33 | parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter, 34 | description='Converts a BAS files (text format) to PRGs (X16 native format) with the emulator.') 35 | parser.add_argument('emulator', help='path to the x16emu program') 36 | parser.add_argument('input', help='the input directory with BAS files') 37 | parser.add_argument('output', help='the PRG output directory') 38 | args = parser.parse_args() 39 | 40 | for f in os.listdir(args.input): 41 | if f.upper().endswith('.BAS'): 42 | basFilename = args.input + "/" + f 43 | print("converting file %s..." % basFilename) 44 | prg = f.upper()[:-4] + ".PRG" 45 | prgFilename = args.output + "/" + prg 46 | prg = prg + ".TMP" 47 | 48 | # read BASIC text file 49 | with codecs.open(basFilename, "rb") as input: 50 | bas = input.read() 51 | 52 | # add SAVE and exit command, and save as temporary file 53 | bas = bas + ('\nSAVE "' + prg + '\nPOKE $9FB4,0\nSYS $FFFF\n"').encode('iso-8859-1') 54 | tempFilename = args.input + ".tmp" 55 | with open(tempFilename, "wb") as output: 56 | output.write(bas) 57 | 58 | # call the emulator to create the PRG file 59 | os.system(args.emulator + " -bas " + tempFilename) 60 | 61 | # copy output to the final directoy 62 | os.rename(prg, prgFilename) 63 | 64 | # remove the temporary file 65 | os.remove(tempFilename) 66 | -------------------------------------------------------------------------------- /basic/snake-no-dim.bas: -------------------------------------------------------------------------------- 1 | 10 REM ######################################## 2 | 20 REM ### SNAKE GAME WITHOUT USING "DIM" ### 3 | 30 REM ######################################## 4 | 40 REM WIDTH = 79 5 | 50 REM HEIGHT = 58 6 | 60 FG = 0:BG = 0:GOSUB 840: REM SETCOLOR 7 | 70 PRINT CHR$(147); 8 | 80 FG = 8:BG = 2:GOSUB 840: REM SETCOLOR 9 | 90 FOR X=0 TO 79 10 | 100 Y = 0:GOSUB 800: REM SETPOS 11 | 110 PRINT "#"; 12 | 120 Y = 58:GOSUB 800: REM SETPOS 13 | 130 PRINT "#"; 14 | 140 NEXT 15 | 150 FOR Y=1 TO 58 16 | 160 X = 0:GOSUB 800: REM SETPOS 17 | 170 PRINT "#"; 18 | 180 X = 79:GOSUB 800: REM SETPOS 19 | 190 PRINT "#"; 20 | 200 NEXT 21 | 210 FG = 3:BG = 0:GOSUB 840: REM SETCOLOR 22 | 220 REM GAME INIT 23 | 230 POO = 0 24 | 240 SN$ = CHR$(60) + CHR$(20) + CHR$(60) + CHR$(20) 25 | 250 SN$ = SN$ + CHR$(60) + CHR$(20) + CHR$(60) + CHR$(20) 26 | 260 SPD = 10 27 | 270 SD$ = "A":CLC=TI+SPD 28 | 280 GOSUB 880: REM PUTNEWFOOD 29 | 290 REM -------------------------------- 30 | 300 REM GAME LOOPP 31 | 310 X = ASC(SN$): Y = ASC(MID$(SN$,2,1)) 32 | 320 GOSUB 800: REM SETPOS 33 | 330 IF POO <= 0 THEN GOTO 390 34 | 340 FG = 7:BG = 9:GOSUB 840: REM SETCOLOR 35 | 350 PRINT "#"; 36 | 360 POO = POO - 1 37 | 370 FG = 3:BG = 0:GOSUB 840: REM SETCOLOR 38 | 380 GOTO 420 39 | 390 REM 40 | 400 FG = 3:BG = 0:GOSUB 840: REM SETCOLOR 41 | 410 PRINT " "; 42 | 420 GET KEY$ 43 | 430 IF KEY$ = "W" THEN SD$ = "W" 44 | 440 IF KEY$ = "A" THEN SD$ = "A" 45 | 450 IF KEY$ = "S" THEN SD$ = "S" 46 | 460 IF KEY$ = "D" THEN SD$ = "D" 47 | 470 X = ASC(RIGHT$(SN$,2)): Y = ASC(RIGHT$(SN$,1)) 48 | 480 IF SD$ = "W" THEN Y=Y-1 49 | 490 IF SD$ = "A" THEN X=X-1 50 | 500 IF SD$ = "S" THEN Y=Y+1 51 | 510 IF SD$ = "D" THEN X=X+1 52 | 520 CH$ = CHR$(VPEEK(0, Y*256+X*2)) 53 | 530 IF CH$ = " " THEN GOTO 560 54 | 540 IF CH$ = CHR$($24) THEN GOTO 580 55 | 550 GOTO 680 56 | 560 SN$ = MID$(SN$,3) + CHR$(X) + CHR$(Y) 57 | 570 GOTO 610 58 | 580 SN$ = SN$ + CHR$(X) + CHR$(Y) 59 | 590 GOSUB 880: REM PUTNEWFOOD 60 | 600 POO = INT(LEN(SN$)/3) 61 | 610 REM CAN GO 62 | 620 GOSUB 800: REM SETPOS 63 | 630 PRINT "*"; 64 | 640 IF CLC>TI THEN GOTO 640 65 | 650 CLC = TI+SPD 66 | 660 GOTO 300 67 | 670 END 68 | 680 REM -------- GAME OVER --------------- 69 | 690 GOSUB 800: REM SETPOS 70 | 700 FG = 2:BG = 0:GOSUB 840: REM SETCOLOR 71 | 710 PRINT CHR$($76); 72 | 720 X = 35:Y = 23:GOSUB 800: REM SETPOS 73 | 730 PRINT "GAME OVER"; 74 | 740 X = 37:Y = 25:GOSUB 800: REM SETPOS 75 | 750 PRINT (LEN(SN$)/2); 76 | 760 FG = 1:BG = 0:GOSUB 840: REM SETCOLOR 77 | 770 X = 0:Y = 57:GOSUB 800: REM SETPOS 78 | 780 END 79 | 790 REM -------------------------------- 80 | 800 REM SETPOS(X,Y) 81 | 810 POKE $030D,Y: POKE $030E,X: POKE $030F,0: SYS $FFF0 82 | 820 RETURN 83 | 830 REM -------------------------------- 84 | 840 REM SETCOLOR(FG,BG) 85 | 850 POKE 713, (BG AND $F) * 16 + (FG AND $F) 86 | 860 RETURN 87 | 870 REM -------------------------------- 88 | 880 REM PUTNEWFOOD() 89 | 890 XX=X:YY=Y 90 | 900 X = INT(RND(TI)*79)+1: Y = INT(RND(TI)*58)+1 91 | 910 IF VPEEK(0,Y*256+X*2) <> 32 THEN GOTO 900 92 | 920 GOSUB 800: REM SETPOS 93 | 930 FG = 0:BG = 13:GOSUB 840: REM SETCOLOR 94 | 940 PRINT CHR$($24); 95 | 950 FG = 3:BG = 0:GOSUB 840: REM SETCOLOR 96 | 960 X=XX:Y=YY 97 | 970 RETURN 98 | -------------------------------------------------------------------------------- /basic/LOGO.BAS: -------------------------------------------------------------------------------- 1 | 5 REM SET VERA REGISTER VARIABLES 2 | 10 VH = $9F22 3 | 20 VM = $9F21 4 | 30 VL = $9F20 5 | 40 VD = $9F23 6 | 50 C = 0 7 | 60 GOSUB 1000 :REM INITIALIZE COLOR PALLETE IN MEMORY 8 | 100 POKE VH, $11 :REM SET INCREMT TO 1 9 | 110 POKE VM, $FA :REM AND ADDRESS TO $1FA00 10 | 120 POKE VL, $00 11 | 140 FOR X = 0 TO 31 :REM COPY 32 ENTRIES FROM MEMORY TO PALLETTE 12 | 150 C1 = PEEK($A200 +X) 13 | 170 POKE VD, C1 14 | 200 NEXT X 15 | 210 GOSUB 3000 : REM CYCLE PALLETE 16 | 230 GOTO 100 : REM INFITINE LOOP 17 | 999 :REM COLORTABLE AND CYCLING 18 | 1000 POKE $A000, $4 19 | 1010 POKE $A001, $E 20 | 1020 POKE $A002, $3 21 | 1030 POKE $A003, $5 22 | 1040 POKE $A004, $7 23 | 1050 POKE $A005, $8 24 | 1060 POKE $A006, $2 25 | 1070 POKE $A007, $0 26 | 1100 POKE $A100, $00 27 | 1110 POKE $A101, $00 28 | 1120 POKE $A102, $FF 29 | 1130 POKE $A103, $0F 30 | 1140 POKE $A104, $00 31 | 1150 POKE $A105, $08 32 | 1160 POKE $A106, $FE 33 | 1170 POKE $A107, $0A 34 | 1180 POKE $A108, $4C 35 | 1190 POKE $A109, $0C 36 | 1200 POKE $A10A, $C5 37 | 1210 POKE $A10B, $00 38 | 1220 POKE $A10C, $0A 39 | 1230 POKE $A10D, $00 40 | 1240 POKE $A10E, $E7 41 | 1250 POKE $A10F, $0E 42 | 1260 POKE $A110, $85 43 | 1270 POKE $A111, $0D 44 | 1280 POKE $A112, $40 45 | 1290 POKE $A113, $06 46 | 1300 POKE $A114, $77 47 | 1310 POKE $A115, $0F 48 | 1320 POKE $A116, $33 49 | 1330 POKE $A117, $03 50 | 1340 POKE $A118, $77 51 | 1350 POKE $A119, $07 52 | 1360 POKE $A11A, $F6 53 | 1370 POKE $A11B, $0A 54 | 1380 POKE $A11C, $8F 55 | 1390 POKE $A11D, $00 56 | 1400 POKE $A11E, $BB 57 | 1410 POKE $A11F, $0B 58 | 2100 POKE $A200, $00 59 | 2110 POKE $A201, $00 60 | 2120 POKE $A202, $FF 61 | 2130 POKE $A203, $0F 62 | 2140 POKE $A204, $00 63 | 2150 POKE $A205, $08 64 | 2160 POKE $A206, $FE 65 | 2170 POKE $A207, $0A 66 | 2180 POKE $A208, $4C 67 | 2190 POKE $A209, $0C 68 | 2200 POKE $A20A, $C5 69 | 2210 POKE $A20B, $00 70 | 2220 POKE $A20C, $0A 71 | 2230 POKE $A20D, $00 72 | 2240 POKE $A20E, $E7 73 | 2250 POKE $A20F, $0E 74 | 2260 POKE $A210, $85 75 | 2270 POKE $A211, $0D 76 | 2280 POKE $A212, $40 77 | 2290 POKE $A213, $06 78 | 2300 POKE $A214, $77 79 | 2310 POKE $A215, $0F 80 | 2320 POKE $A216, $33 81 | 2330 POKE $A217, $03 82 | 2340 POKE $A218, $77 83 | 2350 POKE $A219, $07 84 | 2360 POKE $A21A, $F6 85 | 2370 POKE $A21B, $0A 86 | 2380 POKE $A21C, $8F 87 | 2390 POKE $A21D, $00 88 | 2400 POKE $A21E, $BB 89 | 2410 POKE $A21F, $0B 90 | 2490 RETURN 91 | 3000 C = C +1 : REM CYCLE ALL COLORS UP 92 | 3010 IF C > 7 THEN C = 0 93 | 3020 FOR Y = 0 TO 7 94 | 3030 A = PEEK($A000 +Y) 95 | 3031 A = A +A 96 | 3040 B = Y +C 97 | 3050 IF B >7 THEN B = B - 8 98 | 3060 B = PEEK($A000 +B) 99 | 3061 B = B+B 100 | 3070 C1 = PEEK($A100 + A) 101 | 3071 C2 = PEEK($A101 + A) 102 | 3080 POKE $A200 + B, C1 103 | 3081 POKE $A201 +B, C2 104 | 3090 NEXT Y 105 | 3100 RETURN 106 | 10000 REM CREATED BY SPYDERTL (HTTPS://GITHUB.COM/SPYDERTL) 107 | 10001 REM CYCLES THE PALETTE ENTRIES FOR THE X16 LOGO AFTER 108 | 10002 REM STARTUP. BE SURE TO SAVE THE PROGRAM AND RESTART 109 | 10003 REM THE MACHINE BEFORE RUNNING THIS PROGRAM. 110 | 10004 REM ADAPTED TO R37 AND 0.9 OF VERA BY SERERRIS 111 | 10005 REM ALSO ADDDED SOME COMMENTS 112 | -------------------------------------------------------------------------------- /basic/raytracer.bas: -------------------------------------------------------------------------------- 1 | 0 REM *** SIMPLE RAYTRACER BY MARCO64 14.06.2008 *** 2 | 1 REM *** PORTED TO THE X16 BY EGONOLSEN71 30.09.2019 *** 3 | 2 REM *** ADAPTED TO R37 AND VERA 0.9 15.08.2020 *** 4 | 3 REM *** BY SERERRIS *** 5 | 5 GOSUB 20000:TI$="000000" 6 | 10 DIM KX(10), KY(10), KZ(10), KR(10), XD(4) 7 | 11 AK=3-1:XD(3)=3:XD(2)=12:XD(1)=48:XD(0)=192 8 | 12 KX(0)=3: KY(0)=9: KZ(0)=50: KR(0)=9 9 | 13 KX(1)=-12: KY(1)=7: KZ(1)=80: KR(1)=7 10 | 14 KX(2)=-3: KY(2)=3: KZ(2)=35: KR(2)=3 11 | 15 BX=0: BY=5: BZ=-17: BE=25 12 | 16 LX=-50: LY=300: LZ=50 13 | 17 GB=10:WI=80 14 | 21 FORY=0TO239:FORX=0TO319 15 | 25 GOSUB10000 16 | 30 REM 17 | 32 ZW=GB/320: RX=X*ZW-GB/2: RY=-Y*ZW+240/2*ZW: RZ=BE 18 | 33 ZW=SQR(RX*RX+RY*RY+RZ*RZ): RX=RX/ZW:RY=RY/ZW: RZ=RZ/ZW 19 | 34 OX=BX: OY=BY: OZ=BZ 20 | 40 :REM 21 | 41 GOSUB 90 22 | 42 ON -((OY+T*RY)>0) GOTO 50 23 | 43 :REM 24 | 44 LA=-OY/RY: SX=OX+LA*RX: SY=0: SZ=OZ+LA*RZ 25 | 45 ZW=(INT(SX/5) AND 1)+(INT(SZ/5) AND 1): FA=(ZW=1)+1 26 | 46 OX=SX: OY=SY: OZ=SZ: RX=OX+LX: RY=OY+LY: RZ=OZ+LZ: GOSUB90 27 | 47 ON -(K=-1) GOTO 80 28 | 48 FA=((X AND 1)<>(Y AND 1))+1 29 | 49 GOTO 80 30 | 50 :REM 31 | 51 IF K=-1 THEN FA=0: GOTO 80 32 | 60 :REM 33 | 62 X1=KX(K)*RX+KY(K)*RY+KZ(K)*RZ:X2=OX*RX+OY*RY+OZ*RZ:X3=RX*RX+RY*RY+RZ*RZ 34 | 63 LA=(X1-X2)/X3:F1=(OX+LA*RX)-KX(K):F2=(OY+LA*RY)-KY(K):F3=(OZ+LA*RZ)-KZ(K) 35 | 64 D=SQR(F1*F1 + F2*F2 + F3*F3) 36 | 65 IF (KR(K)*.95.001)AND(X1.001)AND(X2 (, AND . ON A GERMAN KEYBOAD) 7 | 11 REM - 8 | 12 REM - INIT GAME 9 | 13 REM - C IS CENTER OF STREAM 10 | 14 REM - P IS POSITION OF SWIMMER 11 | 15 REM - R IS ROUND COUNTER 12 | 16 REM - CR IS CHAR AT SWIMMER'S NEXT POSITION 13 | 17 REM - SP IS SPEED, 10 IS SLOWEST 14 | 18 REM - W IS WIDTH 15 | 19 REM - SE IS STATE OF STREAM (ISLAND OR OTHER EVENT) 16 | 20 C=39:P=39:R=0:CR=32:SP=10:W=10:SC=0:SE=0 17 | 30 PRINT CHR$(147) 18 | 40 FOR I=0 TO 59 19 | 50 PRINT "----------------------------------- "; 20 | 60 PRINT " ------------------------------" 21 | 70 NEXT 22 | 23 | 90 REM - 24 | 91 REM - DRAW STREAM 25 | 92 REM - LR IS RANDOM TURN IN STREAM 26 | 99 REM - 27 | 100 LR=0:IF S=0 OR S>2 AND S<8 THEN LR=INT(RND(1)*3)-1 28 | 110 C=C+LR 29 | 120 IF C<10 THEN C=10 30 | 130 IF C>60 THEN C=60 31 | 32 | 140 EV=0:IF SE=0 THEN EV=INT(RND(1)*30) 33 | 150 IF EV=1 THEN SE=1:REM - ONE IN THIRTY CHANCE 34 | 160 IF SE=1 OR SE=10 THEN GOSUB 2200:REM - SPLIT/MERGE STREAM 35 | 180 IF SE>=2 AND SE<=9 THEN GOSUB 2400:REM - ISLAND 36 | 190 IF SE=0 THEN GOSUB 2000:REM - DRAW NORMAL STREAM 37 | 38 | 290 REM - 39 | 291 REM - TEST POSITION AHEAD 40 | 291 REM - 41 | 300 PP=P*2 42 | 310 CR=VPEEK(0,PP) 43 | 320 IF CR<>32 THEN GOTO 1020 44 | 45 | 291 REM - 46 | 291 REM - GET INPUT FROM KEYBOARD, MOVE SWIMMER 47 | 291 REM - 48 | 400 FOR I=0 TO SP*2 49 | 410 GET A$ 50 | 420 IF A$="," THEN GOSUB 1100 51 | 430 IF A$="." THEN GOSUB 1200 52 | 53 | 440 REM - 54 | 441 REM - DRAW SWIMMER, POSSIBLY ADJUST SPEED 55 | 442 REM - 56 | 450 VPOKE 0,(P*2),42 57 | 460 NEXT I 58 | 470 IF R=100 THEN GOSUB 1300 59 | 480 IF SP<3 THEN SP=3 60 | 61 | 990 REM - 62 | 991 REM - CR SHOULD ALWAYS BE 32 AT THIS POINT 63 | 992 REM - INCREASE ROUND AND SCORE 64 | 992 REM - 65 | 1000 IF SE=0 THEN R=R+1 66 | 1005 SC=SC+1 67 | 1010 IF CR=32 THEN GOTO 100 68 | 1020 PRINT "SCORE:";SC 69 | 1030 END 70 | 71 | 1090 REM - 72 | 1091 REM - MOVE TO LEFT REQUESTED, TEST IF STILL IN STREAM 73 | 1092 REM - 74 | 1100 VPOKE 0,(P*2),32 75 | 1110 P=P-1 76 | 1120 PP=P*2 77 | 1130 CR=VPEEK(0,PP) 78 | 1140 IF CR<>32 THEN PRINT "SCORE:";SC:END 79 | 1150 RETURN 80 | 81 | 1090 REM - 82 | 1091 REM - SAME FOR MOVE TO RIGHT 83 | 1092 REM - 84 | 1200 VPOKE 0,(P*2),32 85 | 1210 P=P+1 86 | 1220 PP=P*2 87 | 1230 CR=VPEEK(0,PP) 88 | 1240 IF CR<>32 THEN PRINT "SCORE:";SC:END 89 | 1250 RETURN 90 | 91 | 1290 REM - 92 | 1291 REM - INCREASE SPEED, REDUCE WIDTH 93 | 1292 REM - 94 | 1300 R=0 95 | 1310 SP=SP-1 96 | 1320 W=W-1 97 | 1330 IF W<2 THEN W=2 98 | 1340 RETURN 99 | 100 | 1990 REM - 101 | 1991 REM - NORMAL STREAM, NO ISLAND 102 | 1992 REM - 103 | 2000 FOR I=0 TO (C-INT(W/2)) 104 | 2010 PRINT "-"; 105 | 2020 NEXT I 106 | 2030 FOR I=1 TO W 107 | 2040 PRINT " "; 108 | 2050 NEXT I 109 | 2060 FOR I=(C+INT(W/2)) TO (75-W) 110 | 2070 PRINT "-"; 111 | 2080 NEXT I 112 | 2090 PRINT "-":REM PRINT " SP:";(10-SP) 113 | 2100 RETURN 114 | 115 | 2190 REM - 116 | 2191 REM - STREAM SPLITS IN TWO OR MERGE IT 117 | 2192 REM - 118 | 2200 FOR I=0 TO (C-INT(W/2)-1) 119 | 2210 PRINT "-"; 120 | 2220 NEXT I 121 | 2230 FOR I=1 TO INT(W/2)+1 122 | 2240 PRINT " "; 123 | 2250 NEXT I 124 | 2260 PRINT "-"; 125 | 2270 FOR I=INT(W/2) TO W 126 | 2280 PRINT " "; 127 | 2290 NEXT I 128 | 2300 FOR I=(C-INT(W/2)-1) TO (63-W) 129 | 2310 PRINT "-"; 130 | 2320 NEXT I 131 | 2330 IF SE=1 THEN SE=2 132 | 2340 IF SE>9 THEN SE=0 133 | 2350 PRINT "-":REM PRINT " SE:";SE 134 | 2360 RETURN 135 | 136 | 2390 REM - 137 | 2391 REM - ISLAND 138 | 2392 REM - 139 | 2400 FOR I=0 TO (C-INT(W/2)-2) 140 | 2410 PRINT "-"; 141 | 2420 NEXT I 142 | 2430 FOR I=1 TO INT(W/2)+1 143 | 2440 PRINT " "; 144 | 2450 NEXT I 145 | 2460 PRINT "---"; 146 | 2470 FOR I=INT(W/2) TO W 147 | 2480 PRINT " "; 148 | 2490 NEXT I 149 | 2500 FOR I=(C-INT(W/2)) TO (63-W) 150 | 2510 PRINT "-"; 151 | 2520 NEXT I 152 | 2530 SE=SE+1 153 | 2540 PRINT "-":REM PRINT " SE:";SE 154 | 2550 RETURN 155 | -------------------------------------------------------------------------------- /assembly/sprite-demo.asm: -------------------------------------------------------------------------------- 1 | !src "vera.inc" 2 | 3 | *=$0801 4 | 5 | !byte $0b,$08,$01,$00,$9e,$32,$30,$36,$31,$00,$00,$00 6 | 7 | +video_init 8 | 9 | ; enable sprites 10 | lda #1 11 | +vstore vreg_spr 12 | 13 | MAX_SPRITES = 16 14 | MAX_X = 640 15 | MIN_X = $10000-16 16 | MAX_Y = 480 17 | MIN_Y = $10000-32 18 | 19 | spr_data = $10000 20 | 21 | ; configure sprites 22 | 23 | ldx #0 24 | setup: 25 | txa ; palette offset in bits 0-3 26 | ora #2 << 6 | 1 << 4 ; height=32px, width=16px 27 | +sprstore 7 28 | lda #3 << 2 ; z-depth=3 29 | +sprstore 6 30 | lda #<(spr_data >> 5) 31 | +sprstore 0 32 | lda #>(spr_data >> 5) | 1 << 7 ; mode=1 33 | +sprstore 1 34 | inx 35 | cpx #MAX_SPRITES 36 | beq setup_done 37 | jmp setup 38 | setup_done: 39 | 40 | ; set up sprite shape 41 | +vset spr_data 42 | 43 | ldy #1 ; white 44 | 45 | ldx #0 46 | l1: lda sprite,x 47 | jsr convert_color 48 | sta veradat 49 | inx 50 | bne l1 51 | l2: lda sprite + $100,x 52 | jsr convert_color 53 | sta veradat 54 | inx 55 | bne l2 56 | l3: lda sprite + $200,x 57 | jsr convert_color 58 | sta veradat 59 | inx 60 | bne l3 61 | l4: lda sprite + $300,x 62 | jsr convert_color 63 | sta veradat 64 | inx 65 | bne l4 66 | 67 | loop: 68 | ldx #0 69 | lo2: 70 | 71 | ; set x pos 72 | lda sprx_lo,x 73 | +sprstore 2 74 | lda sprx_hi,x 75 | +sprstore 3 76 | lda spry_lo,x 77 | +sprstore 4 78 | lda spry_hi,x 79 | +sprstore 5 80 | 81 | ; update x pos 82 | lda sprx_lo,x 83 | clc 84 | adc speed_x,x 85 | sta sprx_lo,x 86 | lda #0 87 | adc sprx_hi,x 88 | sta sprx_hi,x 89 | ll1: lda sprx_hi,x 90 | bmi ll2 91 | lda sprx_lo,x 92 | sec 93 | sbc #MAX_X 96 | bcc ll2 97 | lda #MIN_X 100 | sta sprx_hi,x 101 | ll2: 102 | 103 | ; update y pos 104 | lda spry_lo,x 105 | sec 106 | sbc speed_y,x 107 | sta spry_lo,x 108 | lda spry_hi,x 109 | sbc #0 110 | sta spry_hi,x 111 | 112 | lda spry_hi,x 113 | bpl ll4 114 | lda spry_lo,x 115 | sec 116 | sbc #MIN_Y 119 | bcs ll4 120 | lda #MAX_Y 123 | sta spry_hi,x 124 | ll4: 125 | inx 126 | cpx #MAX_SPRITES 127 | beq nlo2 128 | jmp lo2 129 | nlo2: 130 | 131 | lda #10 132 | ldy #0 133 | delay: dey 134 | bne delay 135 | sec 136 | sbc #1 137 | bne delay 138 | 139 | jmp loop 140 | 141 | convert_color: 142 | cmp #'.' 143 | bne cc1 144 | lda #0 145 | rts 146 | cc1: tya 147 | rts 148 | 149 | sprite: 150 | !text "....*******....." 151 | !text "..***********..." 152 | !text ".***.*****.***.." 153 | !text ".****.***.****.." 154 | !text "******.*.******." 155 | !text "******.*.******." 156 | !text "******.*.******." 157 | !text ".****.***.****.." 158 | !text ".***.*****.***.." 159 | !text ".*************.." 160 | !text ".*.*********.*.." 161 | !text "..*.*******.*..." 162 | !text "..*..*****..*..." 163 | !text "...*..***..*...." 164 | !text "...*..***..*...." 165 | !text "....*..*..*....." 166 | !text "....*..*..*....." 167 | !text ".....*****......" 168 | !text ".....*****......" 169 | !text ".....*****......" 170 | !text "......***......." 171 | !text "................" 172 | !text "................" 173 | !text "................" 174 | !text "................" 175 | !text "................" 176 | !text "................" 177 | !text "................" 178 | !text "................" 179 | !text "................" 180 | !text "................" 181 | !text "................" 182 | 183 | sprx_lo: 184 | !byte 216, 47, 111, 171, 118, 34, 129, 97, 164, 168, 41, 29, 228, 207, 140, 17 185 | sprx_hi: 186 | !byte 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0 187 | spry_lo: 188 | !byte 221, 223, 182, 216, 50, 181, 147, 234, 164, 219, 251, 168, 14, 155, 141, 83 189 | spry_hi: 190 | !byte 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 191 | 192 | speed_x: 193 | !byte 2, 0, 2, 1, 2, 1, 3, 3, 4, 3, 0, 2, 2, 2, 4, 0 194 | 195 | speed_y: 196 | !byte 4, 3, 4, 4, 2, 2, 1, 4, 0, 3, 0, 2, 3, 2, 3, 1 197 | 198 | 199 | 200 | -------------------------------------------------------------------------------- /layer demo/README.txt: -------------------------------------------------------------------------------- 1 | This program uses dual tile layers to scroll a pair of animated "electricity" beams 2 | down the screen in front of a grid of scrolling circles in parallax. 3 | 4 | The background is filled using a macine language routine at 11000, loaded in 5 | BASIC lines 400-499. This same loop in BASIC took over 10 seconds to fill the 6 | background with the circle tile. The program could run even faster if the 7 | electricity tile data load were converted to machine language, but I'm not doing that 8 | right now. Feel free to modify that for your own learning exercise. 9 | 10 | The electricity tiles use color index $FF, which is randomly changed on each "frame" 11 | The squares use tile index 24 and color $50 (yellow) 12 | All empty tiles are transparent so you see the original display beneath on layer 0. 13 | 14 | For each frame, the VSCROLL register for layer 1 is lowered by 3, looping back to $FFF. 15 | The VERA chip automatically loops the displayed graphics through the 64 rows of the 16 | tile map area, so there's no need to limit the range of the scroll value to 64*8 17 | 18 | The tile animation is done by moving the TILE_BASE pointer for layr 1. This is much 19 | faster than having to update every tile in video memory which needs to animate. 20 | 21 | Example: 22 | If screen memory has a string ABCDEFG, this would be screen codes 1 2 3 4 5 6 7. 23 | code 1 looks like an A because the TILE_DATA in slot 1 contains the arrangement of 24 | pixels which look like an A. 25 | 26 | If you move the TILE_BASE forward by 8 bytes in vram, the screen would now show 27 | the string BCDEFGH. The screen codes are still 1 2 3 4 5 6 7, but the pixel data is 28 | now off by one slot so they're each drawn as the next letter in the alphabet. 29 | 30 | If you moved the TILE_BASE forward another 8 bytes, the screen would show CDEFGHI 31 | etc. 32 | 33 | This demo does not update TILE_BASE by 8, but by 32. This is because it was 34 | originally designed to have 4 tiles with which to draw the electric beams. 35 | Tile 0 is a blank space. 36 | Tiles 1-3 are electricity. 37 | 4 tiles of 8 bytes each = 32 bytes. 38 | 39 | So the first 32 bytes of tile memory contain the frame 0 pixel data for tiles 0-3. 40 | The next 32 bytes contain the frame 1 pixel data for tiles 0-3. 41 | Since the blank space shouldn't animate, it's drawn the same way again, but 42 | tiles 1-3 are updated with the look they need for frame 1 of the animation cycle. 43 | 44 | The electricity's animation cycle is a left rotation of the pixels A<-B<-C 45 | with the pixels looping back to the right of C. 3 tiles = 24 pixels, moving 4px per 46 | frame. Thus it takes 6 frames to complete the cycle. 47 | 6 frames * 4 tiles means there are 24 tiles' worth of pixel data for the animation. 48 | 49 | Here is how it would look if arranged on the screen in a grid: 50 | id: 0 1 2 3 51 | __,AA,BB,CC (frame0) 52 | __,AB,BC,CA (frame1) 53 | __,BB,CC,AA (frame2) 54 | __,BC,CA,AB (frame3) 55 | __,CC,AA,BB (frame4) 56 | __,CA,AB,BC (frame5) 57 | 58 | Note that the space char is the same for all 6 frames, but has to be repeated 59 | in memory for all 6 frames as well. 60 | 61 | I then decided to add the solid squares at the ends of the electricity beams. 62 | Since the first 24 characters' worth of space is already taken up by the animation 63 | frames for the first 4 tiles, I had to use tile ID 24 to represent the square. 64 | Like the space, it has to be copied into all 6 frames' locations, so it's in the 65 | graphics locations for 24, 28, 32, 36, 40, and 44. 66 | You could make tile 25 also be a non-animated tile by putting the same data in 67 | tile locations 25, 29, 33, 37, 41, and 45. Etc. 68 | 69 | This works for this demo, but the better way to do this for larger programs needing 70 | more tiles would be to move the TILE_BASE pointer by, say 64 tiles' worth of space 71 | instead of 4 tiles' worth. Then you would have 64 non-overlapping tiles. It's also more 72 | common in retro console dev to use power-of-two numbers for the frame count as well, 73 | since this dovetails easily with bitmasks and bit shifts. 74 | So in a game, I would use a 4-frame cycle and spend more time drawing an animation cycle 75 | that looked good in 4 frames. 76 | 77 | This would also save 2 copies of tile data from memory. 78 | 79 | Anyway, I hope this demo is useful. Sorry for the convoluted animation logic, but I 80 | wanted to have something that looked kind of cool. 81 | 82 | -------------------------------------------------------------------------------- /assembly/kick-assembler/typing.asm: -------------------------------------------------------------------------------- 1 | /* Typing Some Stuff On the Screen Slowly Using VBLANK 2 | By: Tim Soderstrom 3 | 4 | This is an example for the Commander x16 for how to use the VBLANK interrupt 5 | to type on the screen slowly. It hopefully is a decent example on how to 6 | use interrupts (at least VBLANK). 7 | 8 | It was written using Kick-Assembler but I tried to include everything you 9 | need here making porting it to other assemblers hopefully easy. 10 | 11 | For more information on the x16 and the VERA: 12 | https://github.com/commanderx16/x16-docs 13 | */ 14 | 15 | // Kernel Routines 16 | .const CHROUT = $ffd2 17 | .const CINT = $ff81 18 | .const KERNEL_ISR = $eb01 19 | .const MONITOR = $ff00 20 | 21 | // VERA Addresses 22 | .const VERAREG = $9f20 23 | .const VERAIEN = $9f26 24 | .const VERAISR = $9f27 25 | 26 | // System Memory Addresses 27 | .const ISR_HANDLER = $0314 28 | 29 | // Zero Page Addresses 30 | .const STRING_POSITION = $01 // The current offset of the string 31 | .const VBLANK_SKIP_MAX = $02 // How many VBLANKs to do nothing for 32 | .const VBLANK_SKIP_COUNT = $03 // Count of current VBLANK skip 33 | .const PREVIOUS_ISR_HANDLER = $04 34 | 35 | // Constants 36 | .const VBLANK_MASK = %00000001 // A mask to make sure we set VERA correctly. 37 | .const VBLANK_SKIPS = $05 // A constant for how many VBLANKs to skip. 38 | .const RETURN = $0d 39 | 40 | :BasicUpstart2(setup) 41 | 42 | // Setup some things before we get going 43 | setup: 44 | // Disable interrupts so we do not get distracted while setting up code 45 | sei 46 | 47 | jsr CINT // Clear the screen 48 | 49 | // Initialize Variables 50 | /* We set the VBLANK_SKIP_MAX to the constant we specified in VBLANK_SKIPS. 51 | This basically adds in a delay so the program "types slower" */ 52 | ldx #VBLANK_SKIPS 53 | stx VBLANK_SKIP_MAX 54 | 55 | /* Set some counters to zero */ 56 | ldx #$00 57 | stx VBLANK_SKIP_COUNT 58 | stx STRING_POSITION 59 | 60 | // Setup typing irq handler 61 | /* First we grab the previous handler and store it, then place our interrupt 62 | into a special memory location. When an interupt triggers, our routine 63 | is the one the CPU will execute. When our routine is done, it will then 64 | jump to the previous routine. */ 65 | ldx #$00 66 | lda ISR_HANDLER,x 67 | sta PREVIOUS_ISR_HANDLER,x 68 | lda #typing_irq 74 | sta ISR_HANDLER,x 75 | 76 | // Enable VBLANK Interrupt 77 | /* We will use VBLANK from the VERA as our time keeper, so we enable 78 | the VBLANK interupt */ 79 | lda #VBLANK_MASK 80 | sta VERAIEN 81 | 82 | // Main loop 83 | loop: 84 | cli // Enable interrupts 85 | jmp loop // Loop while we wait 86 | 87 | /* The main typing interrupt handler. This is what does the actual work */ 88 | typing_irq: 89 | // Disable interrupts since we don't want to be interrupted (hah) 90 | sei 91 | 92 | /* Check to see if the VBLANK was triggered. This is in case the intterupt 93 | was triggered by something else. We just want VBLANK. */ 94 | lda VERAISR // Load contents of VERA's ISR 95 | and #VBLANK_MASK // Mask first bit. 96 | clc 97 | cmp #VBLANK_MASK // If it's not 1, we blanked, continue 98 | bcc typing_irq_end // if it's not 1, return 99 | 100 | /* This is an additional delay. We increment a counter on every VBLANK and 101 | once we reach the max, we continue. Otherwise we jump back to the main 102 | loop. This is what slows the typing down. */ 103 | inc VBLANK_SKIP_COUNT // increment delay counter 104 | ldy VBLANK_SKIP_COUNT // load delay counter 105 | cpy VBLANK_SKIP_MAX // compare delay count to max delay 106 | bcc typing_irq_end // if it's not equal, go back to loop 107 | 108 | // We have finished delaying, so we reset the counter and continue. 109 | ldx #$00 110 | stx VBLANK_SKIP_COUNT 111 | 112 | /* Finally print a character on the screen and increment the position for 113 | the next time */ 114 | ldx STRING_POSITION 115 | lda msg,x 116 | jsr CHROUT 117 | inc STRING_POSITION 118 | 119 | /* If A is not 0, we know we do not need to reset the string so we 120 | jump to the end since we are done. Otherwise, we reset the string 121 | postion back to 0 so we can start printing the string all over again. */ 122 | cmp #0 // Compare A to end of string 123 | bne typing_irq_end // If it's not 0, go to end of handler 124 | ldx #$00 // Otherwise reset string position 125 | stx STRING_POSITION 126 | 127 | typing_irq_end: 128 | /* Jump to the previous ISR handler. Note the use of indirect addressing. */ 129 | jmp (PREVIOUS_ISR_HANDLER) 130 | 131 | /* Message to display on screen. Since we use a string pointer, it has to be 132 | less than 255. */ 133 | msg: .text "ALL WORK AND NO PLAY MAKES JACK A DULL BOY. " 134 | .byte RETURN 135 | .byte 0 136 | -------------------------------------------------------------------------------- /cc65-sprite/demo.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019, Frank Buss 2 | // All rights reserved. 3 | 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | 7 | // 1. Redistributions of source code must retain the above copyright notice, this 8 | // list of conditions and the following disclaimer. 9 | 10 | // 2. Redistributions in binary form must reproduce the above copyright notice, 11 | // this list of conditions and the following disclaimer in the documentation 12 | // and/or other materials provided with the distribution. 13 | 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | 25 | 26 | // Demonstrates how to initialize and move sprites with cc65, synchronized 27 | // to the VSync interrupt. 28 | // Tested with the latest unreleased cc65, V2.18 - Git 18afc7c7 29 | // 30 | // Generate an assembler listing into demo.txt: 31 | // cl65 -t cx16 -O -l demo.txt demo.c 32 | // 33 | // See Makefile how to compile it, and how to convert a PNG image to a C array. 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | static const 41 | #include "balloon.inc" 42 | 43 | #define SPRITE_COUNT 16 44 | #define SPRITE_X_SPACING 30 45 | #define SPRITE_X_START 20 46 | 47 | /* 48 | Python script to generate the table: 49 | import math 50 | cycle=100 51 | ampl=50.0 52 | [int(math.sin(float(i)/cycle*2.0*math.pi)*ampl+0.5) for i in range(cycle)] 53 | */ 54 | static const int sin[] = { 55 | 0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 29, 32, 34, 36, 39, 40, 42, 56 | 44, 45, 46, 48, 48, 49, 50, 50, 50, 50, 50, 49, 48, 48, 46, 45, 57 | 44, 42, 40, 39, 36, 34, 32, 29, 27, 24, 21, 18, 15, 12, 9, 6, 3, 58 | 0, -2, -5, -8, -11, -14, -17, -20, -23, -26, -28, -31, -33, -35, 59 | -38, -39, -41, -43, -44, -45, -47, -47, -48, -49, -49, -49, -49, 60 | -49, -48, -47, -47, -45, -44, -43, -41, -39, -38, -35, -33, -31, 61 | -28, -26, -23, -20, -17, -14, -11, -8, -5, -2 62 | }; 63 | 64 | void main(void) 65 | { 66 | uint16_t i, x; 67 | uint8_t j, ofs = 0; 68 | 69 | // Switch back to the uppercase character set. 70 | cbm_k_bsout(CH_FONT_UPPER); 71 | 72 | // Initialize the sprites' information. 73 | for (i = 0; i < SPRITE_COUNT; i++) { 74 | x = i * SPRITE_X_SPACING + SPRITE_X_START; 75 | 76 | // Inside address bits 12:5. 77 | // Set the outside address to increment with each access. 78 | 79 | vpoke((0x010000 >> 5) & 0xFF, 0x11FC00 + i * 8); 80 | 81 | // 8 Bits-Per-Pixel mode (sprites can have 256 colors). 82 | // Inside address bits 16:13 (sprite pattern starts at 0x010000). 83 | VERA.data0 = (1 << 7) | (0x010000 >> 13); 84 | 85 | // x co-ordinate, bits 7:0 86 | VERA.data0 = x & 0xFF; 87 | 88 | // x co-ordinate, bits 9:8 89 | VERA.data0 = x >> 8; 90 | 91 | // y co-ordinate, bits 7:0 92 | VERA.data0 = 0 & 0xFF; 93 | 94 | // y co-ordinate, bits 9:8 95 | VERA.data0 = 0 >> 8; 96 | 97 | // z-depth: in front of layer 1 98 | VERA.data0 = (3 << 2); 99 | 100 | // 64 pixels for width and height 101 | VERA.data0 = (3 << 6) | (3 << 4); 102 | } 103 | 104 | // Copy the balloon sprite data into the video RAM. 105 | // Set the address to increment with each access. 106 | vpoke(balloon[0], 0x110000); 107 | for (i = 0; ++i < 64*64; ) 108 | VERA.data0 = balloon[i]; 109 | 110 | // Enable the sprites. 111 | vera_sprites_enable(1); 112 | 113 | // Animate those sprites. 114 | puts("\npress any key to stop."); 115 | do { 116 | j = ofs; 117 | 118 | // Wait until the start of the next video frame. 119 | waitvsync(); 120 | 121 | // Update the sprites' y co-ordinates. 122 | for (i = 0; i < SPRITE_COUNT * 8; i += 8) { 123 | vpoke(80 + sin[j], 0x1FC04 + i); 124 | j += 4; 125 | if (j > 99) 126 | j -= 100; 127 | } 128 | 129 | // Update the start offset. 130 | if (++ofs == 100) 131 | ofs = 0; 132 | } while (!kbhit()); 133 | cgetc(); 134 | 135 | // Disable the sprites. 136 | vera_sprites_enable(0); 137 | } 138 | -------------------------------------------------------------------------------- /assembly/x16-matriculate-text/style-guide.txt: -------------------------------------------------------------------------------- 1 | All_names_use_underscore_instead_of_camel_case 2 | Sorry_camel_peeps 3 | 4 | ;================================================= 5 | ;================================================= 6 | ; 7 | ; Section 8 | ; 9 | ;------------------------------------------------- 10 | ; 11 | ; Section comments should precede most major portions of a file. 12 | ; If the section has a description, prefer placing it immediately 13 | ; after the section comment. 14 | ; 15 | 16 | !src "library_macros_and_defines_are_in_a_header_with_an_extension_of.inc" 17 | !src "and_included_at_the_top_of_any_file_that_needs_them.inc" 18 | !src "which_is_hopefully_only_the_main_file_of_the_program.inc" 19 | 20 | ;================================================= 21 | ; Macros_have_a_header_comment 22 | ; Briefly describing their purpose 23 | ;------------------------------------------------- 24 | ; INPUTS: .each_variable Gets a description 25 | ; [.optional_params] When defining multiple macros with the same name, 26 | ; optional params are in brackets. They work like 27 | ; optional params in C++17 - to specify a particular 28 | ; param you must specify all previous ones as well. 29 | ; [.another = 2] Another optional param, but with a default value 30 | ;------------------------------------------------- 31 | ; MODIFIES: A, X, Y, $And_variables_as_appropriate 32 | 33 | !macro MACROS_ARE_ALWAYS_UPPER_CASE {} 34 | 35 | !define DEFINES_ARE_ALSO_UPPER_CASE=1 36 | 37 | Memory_mapped_registers_start_with_upper_case=$9F25 38 | Global_variables_will_also_follow_this_convention=$9F26 39 | 40 | ;================================================= 41 | ; Functions_also_get_a_header_comment 42 | ; Briefly describing their purpose 43 | ;------------------------------------------------- 44 | ; INPUTS: A Register or Variable_as_appropriate 45 | ; 46 | ;------------------------------------------------- 47 | ; MODIFIES: A, X, Y, And_variables_as_appropriate 48 | 49 | function_names_are_lower_case: 50 | jsr 51 | 52 | __labels__that_only_exist_to_create: 53 | __debugging__symbols_or_to_segment_the: 54 | __code__are_decorated: 55 | 56 | ;================================================= 57 | ; And_yes_the_modifies_section_implies 58 | ; That I am using __cdecl() calling semantics 59 | ; and it is up to the caller to preserve anything 60 | ; they need. 61 | ;------------------------------------------------- 62 | ; INPUTS: A Register or Variable_as_appropriate 63 | ; 64 | ;------------------------------------------------- 65 | ; MODIFIES: A, X, Y, And_variables_as_appropriate 66 | 67 | sys_function_names_from_a_lib_are_prefixed_with_a_subsytem_name_or_abbreviation: 68 | jsr ; Single-line, inline comments start on a convenient tab indentation 69 | 70 | ; Multi-line, comments within executable code prefers to start 71 | ; on the same tab indentation as instructions. This is to differentiate 72 | ; from comments outside of an executable context. 73 | 74 | .loop: 75 | Any 76 | loops 77 | that 78 | are 79 | more 80 | than 81 | 12 82 | lines 83 | need 84 | a 85 | real 86 | label 87 | jmp .loop 88 | 89 | - short 90 | loops 91 | dont 92 | jmp - 93 | 94 | .prefer_prefixing_local_labels_with_dots: 95 | ; This is because ACME's treatment of the @ symbol is confusing to me. 96 | ; Their docs say it's a "cheap local", but I don't know what that means, 97 | ; and ran into mysterious errors about name collisions when trying to 98 | ; use it. 99 | 100 | ;================================================= 101 | ; Libs 102 | ; 103 | ;------------------------------------------------- 104 | !src "library_definitions_and_implementations_are_in_a_source_file_with_an_extension_of.asm" 105 | 106 | ;================================================= 107 | ; Data 108 | ; 109 | ;------------------------------------------------- 110 | Constant_data_variables_go_into_their_own_block: 111 | !byte $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 112 | 113 | ;================================================= 114 | ; Variables 115 | ; 116 | ;------------------------------------------------- 117 | Global_variable_labels_begin_with_upper_case: !byte $00 118 | Sys_global_variables_from_a_lib_are_prefixed_with_a_subsystem_name_or_abbreviation: !byte 00 119 | 120 | Large_blocks_of_data_begin_on_the_following_line: 121 | !byte $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 122 | !byte $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 123 | !byte $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 124 | !byte $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 125 | 126 | ; Avoid putting more than 16 bytes on a single line, for readability. 127 | 128 | !src "external_variables_go_into_a_source_file_ending_with_vars.asm" 129 | !src "system_vars.asm" ; system_vars always comes last. 130 | 131 | ; sys_vars.asm includes a label to the end of the variables list 132 | ; which is referenced for defines, such as when reserving complex 133 | ; blocks of memory. -------------------------------------------------------------------------------- /tools/renumber.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Renumber a BASIC PROGRAM. 4 | # Manage GOTO AND GOSUB Calls too 5 | 6 | # Copyright (c) 2019, Giovanni Giorgi 7 | # All rights reserved. 8 | 9 | # Redistribution and use in source and binary forms, with or without 10 | # modification, are permitted provided that the following conditions are met: 11 | 12 | # 1. Redistributions of source code must retain the above copyright notice, this 13 | # list of conditions and the following disclaimer. 14 | 15 | # 2. Redistributions in binary form must reproduce the above copyright notice, 16 | # this list of conditions and the following disclaimer in the documentation 17 | # and/or other materials provided with the distribution. 18 | 19 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | 31 | import sys,re 32 | from pathlib import Path 33 | import click 34 | 35 | LINE_FINDER=re.compile("([0-9]+)", re.IGNORECASE) 36 | 37 | 38 | def collect_numbers(fname, start_from=10, increment=10): 39 | old2new={} 40 | new_line_number=start_from 41 | with open(fname, "r") as f: 42 | for current_line in f: 43 | possibile_number=LINE_FINDER.findall(current_line) 44 | #print(current_line,possibile_number) 45 | if(len(possibile_number)>=1): 46 | current_number=int(possibile_number[0]) 47 | old2new[current_number]=new_line_number 48 | new_line_number=new_line_number+increment 49 | return old2new 50 | 51 | def renumber_file(fname,old2new, postfix=".new"): 52 | dest_filename=fname+postfix 53 | with open(dest_filename, "w") as dest: 54 | with open(fname,"r") as source: 55 | for current_line in source: 56 | possibile_number=LINE_FINDER.findall(current_line) 57 | if(len(possibile_number)>=1): 58 | new_number=old2new[int(possibile_number[0])] 59 | ## renumbered_line=re.sub("([0-9]+) ",str(new_number)+" ",current_line,count=1) 60 | renumbered_line=LINE_FINDER.sub(str(new_number),current_line,count=1) 61 | #print(current_line," ->", renumbered_line) 62 | dest.write(renumbered_line) 63 | else: 64 | dest.write(current_line) 65 | return dest_filename 66 | 67 | def fix_goto_gosub(fname,old2new): 68 | """ 69 | A second pass is needed to correct the GOTO/GOSUB 70 | This code also work with on...goto/gosub 71 | """ 72 | GOTO_FINDER=re.compile(r'GO(TO|SUB| TO) ([0-9]+)([:]*)', re.IGNORECASE) 73 | temp_filename=fname+".tmp" 74 | with open(temp_filename, "w") as dest: 75 | with open(fname,"r") as source: 76 | for current_line in source: 77 | possible_goto=GOTO_FINDER.findall(current_line) 78 | dest_line=current_line 79 | for m in GOTO_FINDER.finditer(current_line.rstrip("\n\r")): 80 | goto_str=m.group(1) 81 | old_line=int(m.group(2)) 82 | new_goto_number=old2new[old_line] 83 | # Compose the new GO TO GOSUB etc 84 | new_goto="GO"+m.group(1)+" "+str(new_goto_number)+m.group(3) 85 | # Single replace 86 | dest_line=dest_line.replace(m.group(0), new_goto,1) 87 | #print ("s/"+m.group(0)+"/"+new_goto+"/",dest_line) 88 | dest.write(dest_line) 89 | return (Path(temp_filename)).replace(fname) 90 | 91 | @click.option("--start", default=10, help="Start renumber from") 92 | @click.option("--increment", default=10, help="Increment factor") 93 | @click.argument("basic_files", nargs=-1, required=True) 94 | @click.command() 95 | def main(basic_files: list, start,increment): 96 | """ Renumber BASIC v2 Programs 97 | Support GOTO/GOSUB renumbering via a simple two-pass algorithm 98 | 99 | Known limitations: also renumber strings containing GOTO because it is unable to skip 100 | quoted strings. 101 | 102 | Author: Giovanni Giorgi 103 | """ 104 | for fname in basic_files: 105 | print("Renumbering",fname) 106 | old2new=collect_numbers(fname,start,increment) 107 | dest_filename=renumber_file(fname,old2new) 108 | fix_goto_gosub(dest_filename,old2new) 109 | Path(dest_filename).replace(fname) 110 | 111 | 112 | if __name__ == "__main__": 113 | main() 114 | -------------------------------------------------------------------------------- /basic/snake.bas: -------------------------------------------------------------------------------- 1 | 5 PRINT CHR$(147) 2 | 6 P = 6480 3 | 7 GOTO 98 4 | 10 REM A SNAKE GAME FOR THE COMMANDER X16 BY @JOHNNWFS (JOHNNWFS.NET) 5 | 11 REM 6 | 12 REM USING THIS REM SET TO REMIND ME WHICH IS WHAT 7 | 13 REM P = POSITION = THE SPECIFIC SCREEN POSITION OF THE SNAKE HEAD 8 | 14 REM X = X POSITION OF THIS P POSITION 9 | 15 REM Y = Y POSITION OF THIS P POSITION 10 | 16 REM M(#) = HOLDS P FOR ALL LENGTHS OF SNAKE 11 | 18 REM Z(#) = TEMPORARY - ALSO HOLDS P 12 | 19 REM TIMER = COUNTER FOR AUTO MOVE 13 | 20 REM HEAD = POSITION IN ARRAY THAT THE HEAD SITS AT 14 | 21 REM TM = CLOCK TIMER FOR SNAKE INCREASE 15 | 22 REM TT = TRIGGER FOR SNAKE SECTION ADDITION 16 | 30 REM DIR = SNAKE DIRECTION FOR AUTO MOVE 17 | 31 REM HW = HIT WALL FLAG 18 | 35 REM L = SNAKE LENGTH 19 | 36 REM LC$= LAST DIRECTION CHARACTER 20 | 90 REM T2 = CLOCK TIMER FOR SNAKE AUTO MOVE 21 | 91 REM T3 = TRIGGER FOR SNAKE AUTO MOVE 22 | 92 REM SY = BORDER SYMBOL:S1 = SNAKEHEAD SYMBOL 23 | 93 REM NP = NEXT CHARACTER FOR SNAKE 24 | 94 REM T4 = COUNTER FOR RANDOM ITEM APPEARING 25 | 95 REM T5 = TRIGGER FOR RANDOM ITEM APPEARING 26 | 96 REM S9 = SYMBOL FOR THE TRIGGER CHARACTER 27 | 98 GOSUB 8000 28 | 99 PRINT CHR$(147) 29 | 100 REM MAIN ROUTINE 30 | 105 GOSUB 7000 31 | 110 X = 20:Y = 20:DIM M(100):DIM Z(100):FLAG = 0:HEAD = 1:S1 = 0:L = 1 32 | 112 TM = 0: TT = 500: T2 = 0:T3 = 50:LC$="W":T4 = 0: T5 = 400 33 | 120 M(1) = P: Z(1) = P:NP = 0: S9 = 43 34 | 125 REM SET UP BORDER 35 | 130 FOR I = 1576 - 256 TO 1656 - 256:VPOKE 0,I,SY: NEXT 36 | 140 FOR I = 0 TO 40 : VPOKE 0, 1319 +(I*256), SY:NEXT 37 | 150 FOR I =11307+ 256 - 2 TO 11383 +2 +256:VPOKE 0, I, SY: NEXT 38 | 160 FOR I = 0 TO 40 : VPOKE 0, 1401 +(I*256), SY:NEXT 39 | 161 REM 40 | 162 REM 41 | 200 NP = S1 42 | 205 FOR I = 1 TO L 43 | 210 VPOKE 0, M(I), NP 44 | 220 NEXT 45 | 250 TM = TM + 1: T2 = T2 +1: T4 = T4 +1 46 | 300 GET A$ 47 | 500 IF A$ = "W" THEN FLAG = 1:LC$ = "W" 48 | 520 IF A$ = "S" THEN FLAG = 1:LC$ = "S" 49 | 540 IF A$ = "A" THEN FLAG = 1:LC$ = "A" 50 | 560 IF A$ = "D" THEN FLAG = 1:LC$ = "D" 51 | 600 IF A$ = " " THEN GOTO 9999 52 | 650 REM 53 | 651 REM 54 | 652 REM 55 | 660 REM PRINT LENGTH 56 | 661 PK = L 57 | 662 I1$ = "" 58 | 663 I2$ = "" 59 | 665 II$ = "" 60 | 667 IF PK < 10 THEN VPOKE 0, 1076, PK+48 61 | 670 IF PK > 9 AND PK < 100 THEN II$ = STR$(PK) 62 | 677 IF PK > 9 THEN VPOKE 0,1076, ASC(MID$(II$,2,1)) 63 | 679 IF PK > 9 THEN VPOKE 0,1078, ASC(MID$(II$,3,1)) 64 | 700 IF T4 >T5 THEN GOSUB 4000 65 | 701 IF T2 >T3 THEN GOTO 1000 66 | 702 IF FLAG = 0 THEN GOTO 9000: REM SKIP NEXT IF NOT DIRECTION CHANGE 67 | 710 FLAG = 0 68 | 720 REM 69 | 750 REM 70 | 800 GOTO 120:REM JUMP BACK AS THE NEXT PART IS TRIGGERED IF LENGTH INCREASES 71 | 1000 T2 = 0 72 | 1020 A$ = LC$: VPOKE 0, M(L), 32 73 | 1025 FOR I = 1 TO L: Z(I)= M(I): NEXT I 74 | 1030 IF LC$ = "W" THEN P = P - 256: Y = Y - 1 75 | 1040 IF LC$ = "S" THEN P = P + 256: Y = Y + 1 76 | 1050 IF LC$ = "A" THEN P = P - 2 : X = X - 1 77 | 1060 IF LC$ = "D" THEN P = P + 2: X = X + 1 78 | 1061 M(1) = P 79 | 1064 IF L >1 THEN GOSUB 2000 80 | 1065 IF L = 1 THEN VPOKE 0, M(L), S1:VPOKE 0, Z(L), 32 81 | 1100 IF T3 > 10 THEN T3 = T3 -1 :REM SPEED UP SNAKE 82 | 1198 REM 83 | 1199 REM 84 | 1200 REM CHECK FOR WALL HITS 85 | 1220 IF X = 0 OR Y = 0 THEN HW = 1 86 | 1240 IF X = 40 OR Y = 40 THEN HW = 1 87 | 1250 REM 88 | 1300 IF HW = 1 THEN GOTO 9990 89 | 1310 REM 90 | 1311 REM 91 | 1312 REM 92 | 1400 HH = VPEEK(0,M(1)) 93 | 1401 REM IF HH <>0 AND HH < > 32 THEN PRINT STR$(HH)+" "+STR$(S9)+" "+STR$(TM) 94 | 1410 IF HH = S9 THEN L = L + 1 95 | 1415 FL = 0 96 | 1420 FOR I = 2 TO L 97 | 1430 IF M(1)= M(I)AND L > 1 THEN FL = 1 98 | 1440 NEXT 99 | 1450 IF FL = 1 THEN GOTO 9996 100 | 1500 GOTO 200:GO BACK TO THE KEYBOARD ROUTINE 101 | 2000 REM 102 | 2001 REM VPOKE 0, M(L),32: REM VPOKE 0, M(1), 32 103 | 2002 FOR I = 2 TO L:M(I) = Z(I-1):NEXT 104 | 2005 REM 105 | 2010 REM 106 | 2020 REM 107 | 2030 REM 108 | 2040 RETURN 109 | 2041 REM 110 | 4000 REM HANDLE RANDOM ITEM APPEARING 111 | 4005 T4 = 0 112 | 4010 X1= INT(RND(1)*40+1) 113 | 4020 Y1= INT(RND(1)*40+1) 114 | 4030 XP = 1320 + (2*X1)+ (256*Y1) 115 | 4040 VPOKE 0, XP, S9 116 | 4050 REM WILL HAVE TO MAKE SURE NOTHING APPEARS IN OCCUPIED SPACE 117 | 4990 RETURN 118 | 7000 REM 119 | 7010 DATA 12, 5, 14, 7, 20, 8, 58 120 | 7020 FOR I = 1 TO 7 121 | 7030 READ A 122 | 7040 VPOKE 0,1060+(2*I), A 123 | 7050 NEXT 124 | 7990 RETURN 125 | 8000 PRINT CHR$(147) 126 | 8010 PRINT "A SNAKE GAME FOR THE COMMANDER X16" 127 | 8020 PRINT "" 128 | 8025 PRINT "W A S D FOR MOVEMENT" 129 | 8030 PRINT "YOU ARE THE @ AND WILL GROW OVER TIME AND" 130 | 8045 PRINT "WHEN YOU PICK UP A +" 131 | 8050 PRINT 132 | 8055 PRINT "GAME ENDS WHEN YOU HIT A WALL OR YOURSELF" 133 | 8060 PRINT "CODE IS VERY VERY MESSY." 134 | 8065 PRINT "" 135 | 8070 PRINT"WOULD LOVE TO SEE MODS AND IMPROVEMENTS" 136 | 8075 PRINT "HIT ME UP ON TWITTER @JOHNNWFS OR FACEBOOK JOHNHOFFER" 137 | 8080 PRINT:PRINT"ANY KEY TO CONTINUE..." 138 | 8085 GET A$:IF A$ = "" GOTO 8085 139 | 8095 RETURN 140 | 8841 REM JUST SOME DEBUGGING FOR THE SNAKE MOVEMENT. HANGING ON TO IT IN CASE 141 | 8850 REM I NEED IT LATER 142 | 8880 VPOKE 0, M(I), NP: IF T2 > 49 OR T2 = 0 THEN PRINT STR$(P) +"�"+STR$(I); 143 | 8881 IF T2 >49 OR T2 = 0 THEN PRINT "NP:" +STR$(NP);:PRINT Z(1);:PRINT Z(2) 144 | 9000 REM HANDLE SNAKE TIMER 145 | 9002 IF TM < TT THEN GOTO 9100 146 | 9004 TM = 0 147 | 9006 REM M(1)= P:CLOSEM(L) = M(L-1):M(L) = P 148 | 9010 L = L +1: REM LENGTH ADDED 149 | 9020 IF T3 >1 THEN T3 = T3 - 1 150 | 9030 IF T5 >20 THEN T5 = T5 - 5 151 | 9100 GOTO 200 152 | 9990 VPOKE 0, P ,S1:REM SHOW SNAKE HEAD IN WALL 153 | 9991 PRINT CHR$(32)+"GAME OVER!�YOU HIT A WALL. MADE IT TO LENGTH "+STR$(L) 154 | 9992 GOTO 10000 155 | 9996 PRINT CHR$(32)+"GAME OVER!�YOU HIT YOURSELF! FINAL LENGTH "+STR$(L) 156 | 9997 GOTO 10000 157 | 9998 PRINT "GAME OVER:�YOU MADE IT TO LENGTH :"+STR$(L) 158 | 9999 PRINT"SPACE PRESSED": END 159 | 10000 GET B$: IF B$="" THEN 10000 160 | 10010 IF B$ = "�"THEN END 161 | 10020 RUN 162 | 163 | 164 | 165 | 166 | -------------------------------------------------------------------------------- /layer demo/layer-demo.bas: -------------------------------------------------------------------------------- 1 | 1 REM ---- SCROLLING ELECTRICITY DEMO BY BARRY YOST SEP 7 2019 ---- 2 | 2 REM 3 | 3 REM DEMONSTRATES: 4 | 4 REM - MULTI-LAYER SCREEN 5 | 5 REM - ANIMATED TILES (HORIZONTAL MOTION OF WAVE PATTERN) 6 | 6 REM - ANIMATED COLOR 7 | 7 REM - VERTICAL SCROLL FOR LAYER 1 8 | 8 REM 9 | 9 REM 10 | 10 REM 11 | 11 REM ==COPY LAYER 1 REGISTERS to LAYER 0== 12 | 12 REM 13 | 13 FOR I=0 TO 9 : A = VPEEK($F,$3000+I) : VPOKE $F,$2000+I,A : NEXT I 14 | 14 REM 15 | 15 REM ==INITIALIZATION== 16 | 16 REM 17 | 30 POKE $9F20,0 : POKE $9F21,$80 : REM POINT TRANSFER PORT0 TO $00:8000 18 | 40 POKE $9F22,$10 : REM SET VRAM STEPPING=1 19 | 50 FOR I=1 TO 192 : REM TRANSFER 192 BYTES OF CHR DATA 20 | 51 READ A : POKE $9F23,A : NEXT I : REM SEND BYTE TO VERA DATA PORT0 21 | 60 VPOKE $F,$3000,$21 : VPOKE $F,$3001,6 : REM SET LAYER1 AS 8BPP TEXT 22 | 70 VPOKE $F,$3002,$0 : VPOKE $F,$3003,$10 : REM $004000 FOR LAYER 1 TILE MAP 23 | 80 VPOKE $F,$3004,$0 : VPOKE $F,$3005,$20 : REM USE $008000 AS TILE DATA AREA 24 | 100 REM 25 | 101 REM == SET CHR DATA FOR TILE 24 IN ALL 6 FRAMES AS $FF (A SOLID SQUARE) 26 | 102 REM 27 | 110 POKE $9F22,$10 : REM SET VRAM STEPPING=1 28 | 120 FOR I=24 TO 44 STEP 4 : REM I=TILE 24 FOR EACH FRAME 29 | 130 POKE $9F20,(8 * I)AND $FF : POKE $9F21,$80 : REM POINT TO VRAM @ TILE 30 | 140 IF 8*I >255 THEN POKE $9F21,$81 : REM IF > 255, INC HI BYTE 31 | 150 FOR J=1 TO 8 :POKE $9F23,$FF : NEXT J : REM WRITE 8 BYTES PER TILE 32 | 160 NEXT I 33 | 300 REM 34 | 301 REM == DRAW THE ELECTRICITY/SQUARES ON ROW 0 OF LAYER 1 == 35 | 302 REM 36 | 310 POKE $9F20,0:POKE $9F21,$40:POKE $9F22,$10 : REM POINT @ LYR1 TILEMAP 37 | 320 C=0 : REM C IS THE ELEC. TILE TO USE 38 | 330 FOR I=1TO80 : REM DRAW 80 TILES ON THE ROW 39 | 340 C=C+1:IF C>3 THEN C=1 : REM C CYCLES 1,2,3,1,2,3,1,2,3,ETC... 40 | 350 REM 41 | 351 REM DRAW SQUARES AT THE ENDS OF THE BEAM, SPACES IN THE MIDDLE, AND 42 | 352 REM DRAW ELECTRICITY ON ALL OTHER COLUMNS. 43 | 353 REM 44 | 360 IF I=1 OR I=35 OR I=45 OR I=80 THEN POKE $9F23,24:POKE $9F23,$50:NEXT I 45 | 370 IF I>35 AND I<45 THEN POKE $9F23,0:POKE $9F23,0 :NEXT I 46 | 380 IF I<81 THEN POKE $9F23,C:POKE $9F23,$FF:NEXT I 47 | 400 REM 48 | 401 REM == FILL LAYER0 WITH A CHARACTER == 49 | 403 REM 50 | 410 POKE $9F20,0:POKE $9F21,0:POKE $9F22,$10 51 | 420 REM FOR I=1 TO 64*128 : POKE $9F23,81: POKE $9F23,$6E : NEXT I 52 | 430 FOR I=0 TO 41 :READ A : POKE $9000+I,A : NEXT I 53 | 440 SYS $9000 54 | 1000 REM 55 | 1001 REM === MAIN LOOP === 56 | 1002 REM 57 | 1010 S=3: F=-1 : SO=0 : REM INITIALIZE SCROLL/FRAME COUNTERS 58 | 1020 S=S-3:IF S<0 THEN S=S+$FFF : REM CYCLE SCROLL AMOUNT -3, 0..$FFF 59 | 1030 H=S AND $F00 : H=H/256 : L=S AND $FF : REM SPLIT S INTO HI/LO BYTES 60 | 1040 VPOKE $F,$3008,L : VPOKE $F,$3009,H : REM UPDATE LYR 1 VSCROLL REGISTERS 61 | 1050 C=INT(255*RND(1)) : VPOKE $F,$11FE,C 62 | 1060 F=F+1 : IF F>5 THEN F=0 : REM CYCLE ZAP ANIMATION FRAME 0..5 63 | 1070 VPOKE $F,$3004,F*8 : REM MOVE CHR DATA POINTER (32BYTE/FRAME) 64 | 1071 REM NOTE: VERA MULTIPLIES THIS BY 4 HENCE WE USE F*8 INSTEAD OF F*32. 65 | 1080 SO=SO-1:IF SO<0 THEN SO=$FFF 66 | 1090 H=SO AND $F00 : H=H/256 : L=SO AND $FF 67 | 1100 VPOKE $F,$2008,L : VPOKE $F,$2009,H 68 | 9900 GET K$ : IF K$="" THEN 1020 : REM CHECK FOR KEYPRESS TO EXIT 69 | 9910 VPOKE $F,$3000,0 : REM HIDE LAYER 1 70 | 9920 VPOKE $F,$2008,0 : VPOKE $F,$2009,0 : REM RESET H/VSCROLL ON LAYER 0 71 | 9930 PRINT "\XF4" 72 | 9999 END 73 | 10000 REM TILE GRAPHICS DATA : REM FRAME CHAR CHR DATA POINTER 74 | 10001 DATA 0,0,0,0,0,0,0,0 : REM 0 BLANK <-- HERE FRAME 0 75 | 10002 DATA 1,2,2,100,148,20,8,0 : REM 0 ZAP-A 76 | 10003 DATA 0,128,64,64,88,36,5,2 : REM 0 ZAP-B 77 | 10004 DATA 0,0,0,64,162,165,24,0 : REM 0 ZAP-C 78 | 10005 DATA 0,0,0,0,0,0,0,0 : REM 1 BLANK <-- HERE FRAME 1 79 | 10006 DATA 16,40,36,68,69,66,128,0 : REM 1 ZAP-A 80 | 10007 DATA 0,0,0,4,138,74,81,32 : REM 1 ZAP-B 81 | 10008 DATA 0,0,0,6,41,81,128,0 : REM 1 ZAP-C 82 | 10009 DATA 0,0,0,0,0,0,0,0 : REM 2 BLANK <-- HERE FRAME 2 83 | 10010 DATA 0,128,64,64,88,36,5,2 : REM 2 ZAP-A 84 | 10011 DATA 0,0,0,64,162,165,24,0 : REM 2 ZAP-B 85 | 10012 DATA 1,2,2,100,148,20,8,0 : REM 2 ZAP-C 86 | 10013 DATA 0,0,0,0,0,0,0,0 : REM 3 BLANK <-- HERE FRAME 3 87 | 10014 DATA 0,0,0,4,138,74,81,32 : REM 3 ETC... 88 | 10015 DATA 0,0,0,6,41,81,128,0 : REM 3 89 | 10016 DATA 16,40,36,68,69,66,128,0 : REM 3 90 | 10017 DATA 0,0,0,0,0,0,0,0 : REM 4 91 | 10018 DATA 0,0,0,64,162,165,24,0 : REM 4 92 | 10019 DATA 1,2,2,100,148,20,8,0 : REM 4 93 | 10020 DATA 0,128,64,64,88,36,5,2 : REM 4 94 | 10021 DATA 0,0,0,0,0,0,0,0 : REM 5 95 | 10022 DATA 0,0,0,6,41,81,128,0 : REM 5 96 | 10023 DATA 16,40,36,68,69,66,128,0 : REM 5 97 | 10024 DATA 0,0,0,4,138,74,81,32 : REM 5 98 | 11000 REM 99 | 11001 REM - MACHINE CODE FOR QUICK SCREEN FILL 100 | 11010 DATA 120 : REM SEI 101 | 11040 DATA 169,0 : REM LDA #$00 ; 102 | 11050 DATA 141,33,159 : REM STA $9F20 ; 103 | 11060 DATA 141,32,159 : REM STA $9F21 ; 104 | 11020 DATA 169,16 : REM LDA #$10 ; SET VERA POINTER TO 00:0000 STEP 1 105 | 11030 DATA 141,34,159 : REM STA $9F22 ; 106 | 11070 DATA 162,110 : REM LDX #$6E ; COLOR CODE 107 | 11080 DATA 169,64 : REM LDA #$40 108 | 11090 DATA 133,31 : REM STA $1F ; SET $1F TO 64 (64 ROWS OF TILES) 109 | 11100 DATA 169,81 : REM LDA #$51 ; TILE CODE 110 | 11110 DATA 198,31 : REM DEC $1F 111 | 11120 DATA 48,14 : REM BMI $9028 ; JMP TO END IF DONE WITH 64 ROWS 112 | 11130 DATA 160,128 : REM LDY #$80 ; SET Y INDEX TO 128 COLUMNS 113 | 11140 DATA 136 : REM DEY 114 | 11150 DATA 48,247 : REM BMI $9016 ; LOOP TO NEXT ROW IF DONE W/ 128 COLS 115 | 11160 DATA 141,35,159 : REM STA $9F23 ; PUSH TILE TO VRAM 116 | 11170 DATA 142,35,159 : REM STX $9F23 ; PUSH COLOR TO VRAM 117 | 11180 DATA 76,28,144 : REM JMP $901C 118 | 11190 DATA 88 : REM CLI 119 | 11200 DATA 96 : REM RTS 120 | -------------------------------------------------------------------------------- /cc65-audio/main.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019, Frank Buss 2 | // All rights reserved. 3 | 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | 7 | // 1. Redistributions of source code must retain the above copyright notice, this 8 | // list of conditions and the following disclaimer. 9 | 10 | // 2. Redistributions in binary form must reproduce the above copyright notice, 11 | // this list of conditions and the following disclaimer in the documentation 12 | // and/or other materials provided with the distribution. 13 | 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | 25 | // YM2151 VGM player 26 | 27 | #include 28 | #include 29 | #include 30 | #include <6502.h> 31 | 32 | #include "vgm.inc" 33 | 34 | struct YM2151_t { 35 | uint8_t reg; 36 | uint8_t data; 37 | }; 38 | 39 | #define YM2151 (*(volatile struct YM2151_t*) 0x9fe0) 40 | 41 | static uint8_t run; 42 | static uint16_t ofs, start; 43 | 44 | static void startWrite() 45 | { 46 | vpoke(0, 0x01fa0c); 47 | } 48 | 49 | static void endWrite() 50 | { 51 | vpoke(15, 0x01fa0c); 52 | } 53 | 54 | static void wait(uint16_t samples) 55 | { 56 | // assumes 60 Hz VGM files 57 | uint16_t frames = samples / 735; 58 | 59 | while (frames--) waitvsync(); 60 | } 61 | 62 | static void writeYM2151Reg(uint8_t reg, uint8_t value) 63 | { 64 | uint8_t i; 65 | YM2151.reg = reg; 66 | YM2151.data = value; 67 | 68 | // delay between writes must be at least 64 YM2151 cyclces, which is 69 | // 224 cyckes if tge 6502, if it runs at 14 MHz, and the YM2151 at 4 MHz. 70 | // The function and call needs about 50 cycles. One loop 22 cycles. 71 | // Add some reserve in case CC65 optimizes it better in future versions. 72 | for (i = 0; i < 10; i++) { 73 | asm("nop"); 74 | } 75 | } 76 | 77 | static void resetYM2151() 78 | { 79 | uint16_t i; 80 | for (i = 0; i < 256; i++) { 81 | writeYM2151Reg(i, 0); 82 | } 83 | } 84 | 85 | char* readWideString(uint16_t* pos) 86 | { 87 | static uint8_t buf[256]; 88 | uint8_t i = 0; 89 | while (1) { 90 | uint16_t wc = vgmData[*pos]; 91 | (*pos)++; 92 | wc |= vgmData[*pos]; 93 | (*pos)++; 94 | if (wc >= 65 && wc <= 90) { 95 | wc += 32; 96 | } else if (wc >= 97 && wc <= 122) { 97 | wc -= 32; 98 | } 99 | buf[i++] = wc; 100 | if (wc == 0) break; 101 | } 102 | return buf; 103 | } 104 | 105 | void play() 106 | { 107 | while (1) { 108 | ofs = start; 109 | run = 1; 110 | while (run) { 111 | uint8_t cmd = vgmData[ofs++]; 112 | startWrite(); 113 | switch (cmd) { 114 | case 0x54: 115 | { 116 | uint8_t reg = vgmData[ofs++]; 117 | uint8_t value = vgmData[ofs++]; 118 | writeYM2151Reg(reg, value); 119 | break; 120 | } 121 | case 0x61: 122 | { 123 | uint16_t n = vgmData[ofs++]; 124 | n += vgmData[ofs++] << 8; 125 | endWrite(); 126 | wait(n); 127 | break; 128 | } 129 | case 0x62: 130 | { 131 | endWrite(); 132 | wait(735); 133 | break; 134 | } 135 | case 0x63: 136 | { 137 | endWrite(); 138 | wait(882); 139 | break; 140 | } 141 | case 0x66: 142 | { 143 | run = 0; 144 | break; 145 | } 146 | case 0xc0: 147 | { 148 | // ignore Sega PCM write 149 | ofs += 3; 150 | break; 151 | } 152 | default: 153 | { 154 | if (cmd >= 0x70 && cmd <= 0x7f) { 155 | endWrite(); 156 | wait(cmd & 0xf); 157 | } else { 158 | printf("unknown command: $%02x\n", cmd); 159 | } 160 | break; 161 | } 162 | } 163 | if (kbhit()) { 164 | cgetc(); 165 | return; 166 | } 167 | } 168 | } 169 | } 170 | 171 | int main() 172 | { 173 | uint16_t gd3; 174 | 175 | resetYM2151(); 176 | clrscr(); 177 | printf("\nVGM player by Frank Buss\n\n"); 178 | 179 | // calculate absolute data offset 180 | start = vgmData[0x34]; 181 | start |= vgmData[0x35] << 8; 182 | start += 0x34; 183 | 184 | // calculate GD3 offset 185 | gd3 = vgmData[0x14]; 186 | gd3 |= vgmData[0x15] << 8; 187 | 188 | // parse GD3 info 189 | if (gd3) { 190 | gd3 += 29; 191 | readWideString(&gd3); 192 | printf(" Song title : %s\n", readWideString(&gd3)); 193 | readWideString(&gd3); 194 | readWideString(&gd3); 195 | readWideString(&gd3); 196 | readWideString(&gd3); 197 | readWideString(&gd3); 198 | printf(" Author name: %s\n", readWideString(&gd3)); 199 | } 200 | 201 | // play song until key press 202 | printf("\npress any key to stop\n"); 203 | play(); 204 | endWrite(); 205 | resetYM2151(); 206 | 207 | return 0; 208 | } 209 | -------------------------------------------------------------------------------- /assembly/x16-matriculate-text/vera.inc: -------------------------------------------------------------------------------- 1 | !ifdef VERA_INC !eof 2 | VERA_INC=1 3 | 4 | ;================================================= 5 | ;================================================= 6 | ; 7 | ; Memory-mapped registers 8 | ; 9 | ;------------------------------------------------- 10 | 11 | !addr { 12 | !if MACHINE_C64 = 1 { 13 | VERA_base = $df00 14 | } else { 15 | VERA_base = $9f20 16 | } 17 | VERA_addr_low = VERA_base+0 18 | VERA_addr_high = VERA_base+1 19 | VERA_addr_bank = VERA_base+2 20 | VERA_data = VERA_base+3 21 | VERA_data2 = VERA_base+4 22 | VERA_ctrl = VERA_base+5 23 | VERA_irq_ctrl = VERA_base+6 24 | VERA_irq = VERA_base+7 25 | 26 | VRAM_composer = $F0000 27 | VRAM_palette = $F1000 28 | VRAM_layer1 = $F2000 29 | VRAM_layer2 = $F3000 30 | VRAM_sprinfo = $F4000 31 | VRAM_sprdata = $F5000 32 | 33 | VROM_petscii = $1F000 34 | } 35 | 36 | ;================================================= 37 | ;================================================= 38 | ; 39 | ; Macros 40 | ; 41 | ;------------------------------------------------- 42 | 43 | ;================================================= 44 | ; VERA_SELECT_ADDR 45 | ; Select which address channel to configure (VERA_data vs. VERA_data2) 46 | ;------------------------------------------------- 47 | ; INPUTS: .addr 0 for VERA_data 48 | ; 1 for VERA_data2 49 | ; 50 | ;------------------------------------------------- 51 | ; MODIFIES: A 52 | ; 53 | !macro VERA_SELECT_ADDR .addr { 54 | lda #.addr 55 | sta VERA_ctrl 56 | } 57 | 58 | ;================================================= 59 | ; VERA_SET_ADDR (multiple) 60 | ; Set the current address channel's address 61 | ;------------------------------------------------- 62 | ; INPUTS: .addr VRAM address to set to 63 | ; [.stride = 1] Address stride/auto-increment 64 | ; value: increment 65 | ; 0: disabled 66 | ; 1: 1 byte 67 | ; 2: 2 byte 68 | ; 3: 4 byte 69 | ; 4: 8 byte 70 | ; 5: 16 byte 71 | ; 6: 32 byte 72 | ; 7: 64 byte 73 | ; 8: 128 byte 74 | ; 9: 256 byte 75 | ; 10: 512 byte 76 | ; 11: 1024 byte 77 | ; 12: 2048 byte 78 | ; 13: 4096 byte 79 | ; 14: 8192 byte 80 | ; 15: 16384 byte 81 | ; 82 | ;------------------------------------------------- 83 | ; MODIFIES: A 84 | ; 85 | !macro VERA_SET_ADDR .addr, .stride { 86 | lda #<(.addr) 87 | sta VERA_addr_low 88 | lda #<(.addr >> 8) 89 | sta VERA_addr_high 90 | lda #<(.addr >> 16) | (.stride << 4) 91 | sta VERA_addr_bank 92 | } 93 | 94 | !macro VERA_SET_ADDR .addr { 95 | +VERA_SET_ADDR .addr, 1 96 | } 97 | 98 | ;================================================= 99 | ; VERA_WRITE (multiple) 100 | ; Write values to VERA_data. 101 | ; If more than 8 values are needed, consider 102 | ; the SYS_STREAM_* family. 103 | ;------------------------------------------------- 104 | ; INPUTS: .v0 - .v7 Values to write 105 | ; 106 | ;------------------------------------------------- 107 | ; MODIFIES: A 108 | ; 109 | !macro VERA_WRITE .v0 { 110 | lda #.v0 111 | sta VERA_data 112 | } 113 | 114 | !macro VERA_WRITE .v0, .v1 { 115 | +VERA_WRITE .v0 116 | +VERA_WRITE .v1 117 | } 118 | 119 | !macro VERA_WRITE .v0, .v1, .v2 { 120 | +VERA_WRITE .v0, .v1 121 | +VERA_WRITE .v2 122 | } 123 | 124 | !macro VERA_WRITE .v0, .v1, .v2, .v3 { 125 | +VERA_WRITE .v0, .v1 126 | +VERA_WRITE .v2, .v3 127 | } 128 | 129 | !macro VERA_WRITE .v0, .v1, .v2, .v3, .v4, .v5, .v6, .v7 { 130 | +VERA_WRITE .v0, .v1, .v2, .v3 131 | +VERA_WRITE .v4, .v5, .v6, .v7 132 | } 133 | 134 | ;================================================= 135 | ; VPEEK 136 | ; It's... VPEEK(), but in assembly. 137 | ;------------------------------------------------- 138 | ; INPUTS: .addr VRAM address to read from. 139 | ; 140 | ;------------------------------------------------- 141 | ; MODIFIES: A 142 | ; 143 | !macro VPEEK .addr { 144 | +VERA_SET_ADDR .addr 145 | lda VERA_data 146 | } 147 | 148 | ;================================================= 149 | ; VERA_SET_SPRITE 150 | ; Set the current address channel to target 151 | ; an indexed sprite_data entry in VRAM_sprdata 152 | ;------------------------------------------------- 153 | ; INPUTS: .sprite_index Sprite index to target 154 | ; 155 | ;------------------------------------------------- 156 | ; MODIFIES: A 157 | ; 158 | !macro VERA_SET_SPRITE .sprite_index { 159 | +VERA_SET_ADDR (VRAM_sprdata + (.sprite_index << 3)) 160 | } 161 | 162 | ;================================================= 163 | ; VERA_SET_PALETTE 164 | ; Set the current address channel to target 165 | ; an indexed palette entry in VRAM_palette 166 | ;------------------------------------------------- 167 | ; INPUTS: .palette_index Palette index to target 168 | ; [.color_offset = 0] Which color within the palette to target 169 | ; 170 | ;------------------------------------------------- 171 | ; MODIFIES: A 172 | ; 173 | !macro VERA_SET_PALETTE .palette_index { 174 | +VERA_SET_ADDR (VRAM_palette + (.palette_index << 5)) 175 | } 176 | 177 | !macro VERA_SET_PALETTE .palette_index, .color_offset { 178 | +VERA_SET_ADDR (VRAM_palette + (.palette_index << 5) + (.color_offset << 1)) 179 | } 180 | 181 | ;================================================= 182 | ; VERA_RESET 183 | ; Reset the Vera to its default settings. 184 | ; See official documentation for specifics. 185 | ;------------------------------------------------- 186 | ; INPUTS: (none) 187 | ; 188 | ;------------------------------------------------- 189 | ; MODIFIES: A 190 | ; 191 | !macro VERA_RESET { 192 | lda #$80 193 | sta VERA_ctrl 194 | } 195 | 196 | ;================================================= 197 | ; VERA_END_IRQ 198 | ; Reset the Vera IRQ flag so that it generates interrupts. 199 | ;------------------------------------------------- 200 | ; INPUTS: (none) 201 | ; 202 | ;------------------------------------------------- 203 | ; MODIFIES: A 204 | ; 205 | !macro VERA_END_IRQ { 206 | lda #$1 207 | sta VERA_irq 208 | } 209 | 210 | ;================================================= 211 | ; VIDEO_INIT 212 | ; Turn on the video display. 213 | ;------------------------------------------------- 214 | ; INPUTS: (none) 215 | ; 216 | ;------------------------------------------------- 217 | ; MODIFIES: A 218 | ; 219 | !macro VIDEO_INIT { 220 | lda #0 221 | sta VERA_ctrl ; set ADDR1 active 222 | sta VERA_addr_high 223 | lda #$14 ; $40040 - Composer output mode and chroma toggle 224 | sta VERA_addr_bank 225 | lda #$40 226 | sta VERA_addr_low 227 | lda #1 228 | sta VERA_data ; VGA output 229 | } 230 | -------------------------------------------------------------------------------- /tools/png2sprite.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2019, Frank Buss 4 | # All rights reserved. 5 | 6 | # Redistribution and use in source and binary forms, with or without 7 | # modification, are permitted provided that the following conditions are met: 8 | 9 | # 1. Redistributions of source code must retain the above copyright notice, this 10 | # list of conditions and the following disclaimer. 11 | 12 | # 2. Redistributions in binary form must reproduce the above copyright notice, 13 | # this list of conditions and the following disclaimer in the documentation 14 | # and/or other materials provided with the distribution. 15 | 16 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | 27 | 28 | # Converts a PNG image to a C style array to be used as a sprite with Commander X16 29 | 30 | from PIL import Image 31 | import numpy as np 32 | import math 33 | import sys 34 | import argparse 35 | 36 | # parse arguments 37 | parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter, 38 | description='Converts a PNG file to Commander X16 sprite data.\n\n' 39 | 'Examples:\n\n' 40 | 'png2sprite.py -n balloon.png balloon.c balloon.inc\n' 41 | 'Read the PNG image balloon.png and create a file with a C array named "balloon".\n\n' 42 | 'png2sprite.py -c ffffff mini.png test.bas\n' 43 | 'Read the PNG image mini.png and create a file test.bas with a BASIC file with\n' 44 | 'DATA statements starting at line 10000, using white for transparent color.\n\n' 45 | 'Note: the PNG file must have a fully transparent background, which is then used for index 0.') 46 | parser.add_argument('input', help='the PNG input file name') 47 | parser.add_argument('output', help='the output file name') 48 | parser.add_argument('-f', default='c', choices=['c','basic','acme'], help='output format: c for C array, basic for BASIC, acme for ACME assembler, default: c') 49 | parser.add_argument('-n', default='', help='array / label / start line number for C / assembler / BASIC, default: sprite/10000') 50 | args = parser.parse_args() 51 | if args.n == '': 52 | if args.f == 'c' or args.f =='acme': 53 | args.n = 'sprite' 54 | if args.f == 'basic': 55 | args.n = '10000' 56 | 57 | # default x16 palette 58 | default_palette = [ 59 | 0x0000,0xfff,0x800,0xafe,0xc4c,0x0c5,0x00a,0xee7,0xd85,0x640,0xf77,0x333,0x777,0xaf6,0x08f,0xbbb,0x000,0x111,0x222,0x333,0x444,0x555,0x666,0x777,0x888,0x999,0xaaa,0xbbb,0xccc,0xddd,0xeee,0xfff,0x211,0x433,0x644,0x866,0xa88,0xc99,0xfbb,0x211,0x422,0x633,0x844,0xa55,0xc66,0xf77,0x200,0x411,0x611,0x822,0xa22,0xc33,0xf33,0x200,0x400,0x600,0x800,0xa00,0xc00,0xf00,0x221,0x443,0x664,0x886,0xaa8,0xcc9,0xfeb,0x211,0x432,0x653,0x874,0xa95,0xcb6,0xfd7,0x210,0x431,0x651,0x862,0xa82,0xca3,0xfc3,0x210,0x430,0x640,0x860,0xa80,0xc90,0xfb0,0x121,0x343,0x564,0x786,0x9a8,0xbc9,0xdfb,0x121,0x342,0x463,0x684,0x8a5,0x9c6,0xbf7,0x120,0x241,0x461,0x582,0x6a2,0x8c3,0x9f3,0x120,0x240,0x360,0x480,0x5a0,0x6c0,0x7f0,0x121,0x343,0x465,0x686,0x8a8,0x9ca,0xbfc,0x121,0x242,0x364,0x485,0x5a6,0x6c8,0x7f9,0x020,0x141,0x162,0x283,0x2a4,0x3c5,0x3f6,0x020,0x041,0x061,0x082,0x0a2,0x0c3,0x0f3,0x122,0x344,0x466,0x688,0x8aa,0x9cc,0xbff,0x122,0x244,0x366,0x488,0x5aa,0x6cc,0x7ff,0x022,0x144,0x166,0x288,0x2aa,0x3cc,0x3ff,0x022,0x044,0x066,0x088,0x0aa,0x0cc,0x0ff,0x112,0x334,0x456,0x668,0x88a,0x9ac,0xbcf,0x112,0x224,0x346,0x458,0x56a,0x68c,0x79f,0x002,0x114,0x126,0x238,0x24a,0x35c,0x36f,0x002,0x014,0x016,0x028,0x02a,0x03c,0x03f,0x112,0x334,0x546,0x768,0x98a,0xb9c,0xdbf,0x112,0x324,0x436,0x648,0x85a,0x96c,0xb7f,0x102,0x214,0x416,0x528,0x62a,0x83c,0x93f,0x102,0x204,0x306,0x408,0x50a,0x60c,0x70f,0x212,0x434,0x646,0x868,0xa8a,0xc9c,0xfbe,0x211,0x423,0x635,0x847,0xa59,0xc6b,0xf7d,0x201,0x413,0x615,0x826,0xa28,0xc3a,0xf3c,0x201,0x403,0x604,0x806,0xa08,0xc09,0xf0b 60 | ] 61 | default_palette.reverse() 62 | 63 | # load image 64 | im = Image.open(args.input) 65 | im = im.convert('RGBA') 66 | p = np.array(im) 67 | 68 | # convert to sprite data 69 | i = 0 70 | with open(args.output, "w") as file: 71 | if args.f == 'c': 72 | file.write("uint8_t %s[] = {\n" % args.n) 73 | if args.f == 'acme': 74 | file.write("%s:\n" % args.n) 75 | if args.f == 'basic': 76 | line = int(args.n) 77 | for y in range(im.height): 78 | for x in range(im.width): 79 | if i == 0: 80 | if args.f == 'acme': 81 | file.write(" !byte ") 82 | if args.f == 'basic': 83 | file.write("%i DATA " % line) 84 | line = line + 1 85 | 86 | # get pixel color 87 | r, g, b, a = p[y][x] 88 | 89 | # use index 0 for transparent color 90 | if a == 0: 91 | best = 0 92 | else: 93 | # find best palette match, start searching from top to allow index 16 for black color 94 | d = 1e9 95 | best = 0 96 | j = 255 97 | for entry in default_palette: 98 | rp = ((entry >> 8) & 0xf) << 4 99 | gp = ((entry >> 4) & 0xf) << 4 100 | bp = (entry & 0xf) << 4 101 | dr = r - rp 102 | dg = g - gp 103 | db = b - bp 104 | d0 = dr * dr + dg * dg + db * db 105 | if d0 < d: 106 | best = j 107 | d = d0 108 | j = j - 1 109 | 110 | # write palette index 111 | if args.f == 'c': 112 | file.write("0x%02x," % best) 113 | if args.f == 'acme' or args.f == 'basic': 114 | file.write("$%02x" % best) 115 | if i < 15: 116 | file.write(",") 117 | i = i + 1 118 | if i == 16: 119 | file.write("\n") 120 | i = 0 121 | if i != 0: 122 | file.write("\n") 123 | if args.f == 'c': 124 | file.write("};") 125 | -------------------------------------------------------------------------------- /basic/affine.bas: -------------------------------------------------------------------------------- 1 | 100 REM 2 | 110 TI=0:DIM XD%(4):XD%(0)=0:XD%(1)=6 3 | 115 XD%(2)=1:XD%(3)=2 4 | 120 DIM CS%(18), XY%(18), TS%(12), AG(3), IV%(7) 5 | 130 W=40 6 | 140 TX=$8000:TZ=0:DI=128 7 | 150 MP=25:TW=64:XD=.:YD=.:XH=.:YH=.:TC=.:T=.:L=.:R=. 8 | 160 TT=.:TL=.:TR=.:DL=.:DR=.:U0=.:U1=.:V0=.:V1=. 9 | 170 N=.:DF=.:DE=.:XS=.:XE=.:US=.:UE=.:VS=.:VE=.:KP=. 10 | 180 U=.:V=.:LE=.:DU=.:DV=.:X=.:Y=.:Z=.:TP=.:SI=. 11 | 190 CO=.:C=.:TV=.:MT=.:MA=.:XC=.:YV=.:ZC=.:XN=.:YN=.:ZN=. 12 | 200 GOSUB 2400 13 | 220 GOSUB 20000 14 | 230 GOSUB 30000 15 | 240 GOSUB 440 16 | 250 TT=TI 17 | 260 GET A$:IF A$=""THEN 260 18 | 280 GOSUB 25000:PRINT "TIME: ";TT 19 | 290 END 20 | 440 REM JUMP TARGET 21 | 450 GOSUB 2190 22 | 460 XD=200:YD=200 23 | 470 XH=XD/2:YH=YD/2 24 | 490 W=0.3 25 | 500 GOSUB 520 26 | 510 RETURN 27 | 520 REM JUMP TARGET 28 | 530 AG(0)=W:AG(1)=0:AG(2)=W 29 | 540 GOSUB 1840 30 | 550 GOSUB 570 31 | 560 RETURN 32 | 570 REM JUMP TARGET 33 | 590 TC=0 34 | 600 FOR I=0 TO 17 STEP 9 35 | 610 T=0:L=3:R=6 36 | 620 TT=0:TL=2:TR=4 37 | 630 IF XY%(I+4)>=XY%(I+1) THEN 660 38 | 640 T=3:L=6:R=0 39 | 650 TT=2:TL=4:TR=0 40 | 660 REM JUMP TARGET 41 | 670 IF XY%(I+7)>=XY%(I+T+1) THEN 700 42 | 680 T=6:L=0:R=3 43 | 690 TT=4:TL=0:TR=2 44 | 700 REM JUMP TARGET 45 | 710 T=T+I 46 | 720 L=L+I 47 | 730 R=R+I 48 | 740 TT=TT+TC 49 | 750 TL=TL+TC 50 | 760 TR=TR+TC 51 | 770 DL=(XY%(L)-XY%(T))*DI 52 | 780 DR=(XY%(R)-XY%(T))*DI 53 | 790 U0=(TS%(TL)-TS%(TT))*DI 54 | 800 U1=(TS%(TR)-TS%(TT))*DI 55 | 810 V0=(TS%(TL+1)-TS%(TT+1))*DI 56 | 820 V1=(TS%(TR+1)-TS%(TT+1))*DI 57 | 830 N=L 58 | 840 IF XY%(N+1)<=XY%(R+1) THEN 860 59 | 850 N=R 60 | 860 REM JUMP TARGET 61 | 870 DF=XY%(L+1)-XY%(T+1) 62 | 880 IF DF<>0 THEN 910 63 | 890 DL=0:U0=0:V0=0 64 | 900 GOTO 950 65 | 910 REM JUMP TARGET 66 | 920 DL=DL/DF 67 | 930 U0=U0/DF 68 | 940 V0=V0/DF 69 | 950 REM JUMP TARGET 70 | 960 DE=XY%(R+1)-XY%(T+1) 71 | 970 IF DE<>0 THEN 1000 72 | 980 DR=0:U1=0:V1=0 73 | 990 GOTO 1040 74 | 1000 REM JUMP TARGET 75 | 1010 DR=DR/DE 76 | 1020 U1=U1/DE 77 | 1030 V1=V1/DE 78 | 1040 REM JUMP TARGET 79 | 1050 XS=XY%(T)*DI 80 | 1060 US=TS%(TT)*DI 81 | 1070 VS=TS%(TT+1)*DI 82 | 1080 KP=(XY%(L)-XY%(T))*(XY%(R+1)-XY%(T+1)) 83 | 1090 KP=KP-(XY%(L+1)-XY%(T+1))*(XY%(R)-XY%(T)) 84 | 1100 SW=0 85 | 1110 IF KP<=0 THEN 1190 86 | 1120 SW=1 87 | 1130 Q=DL:DL=DR:DR=Q 88 | 1140 Q=DF:DF=DE:DE=Q 89 | 1150 Q=L:L=R:R=Q 90 | 1160 Q=TL:TL=TR:TR=Q 91 | 1170 Q=U0:U0=U1:U1=Q 92 | 1180 Q=V0:V0=V1:V1=Q 93 | 1190 REM JUMP TARGET 94 | 1200 Y=XY%(T+1) 95 | 1210 UE=US 96 | 1220 VE=VS 97 | 1230 XE=XY%(R)*DI-DE*DR 98 | 1240 REM JUMP TARGET 99 | 1250 FOR IT=0 TO 1 100 | 1260 REM JUMP TARGET 101 | 1270 U=US:V=VS 102 | 1280 LE=(XE-XS)/DI 103 | 1290 DU=0:DV=0 104 | 1300 IF LE=0 THEN 1330 105 | 1310 DU=(UE-US)/LE 106 | 1320 DV=(VE-VS)/LE 107 | 1330 REM JUMP TARGET 108 | 1350 FOR X=INT(XS/DI) TO INT(XE/DI) 109 | 1360 TP=((V/2) AND 4032)+INT(U/DI) 110 | 1370 CV=XD%(PEEK(TX+(TP AND 4095))) 111 | 1380 PSET X,Y,CV 112 | 1390 U=U+DU:V=V+DV 113 | 1400 NEXT X 114 | 1410 XS=XS+DL:XE=XE+DR 115 | 1420 US=US+U0:VS=VS+V0 116 | 1430 UE=UE+U1:VE=VE+V1 117 | 1440 Y=Y+1 118 | 1450 IF Y<=XY%(N+1) THEN 1260 119 | 1460 IF N=R THEN 1630 120 | 1470 N=R 121 | 1480 DL=(XY%(R)-XY%(L))*DI 122 | 1490 DF=XY%(R+1)-XY%(L+1) 123 | 1500 XS=XY%(L)*DI 124 | 1510 U0=(TS%(TR)-TS%(TL))*DI 125 | 1520 V0=(TS%(TR+1)-TS%(TL+1))*DI 126 | 1530 US=TS%(TL)*DI 127 | 1540 VS=TS%(TL+1)*DI 128 | 1550 IF DF<>0 THEN 1580 129 | 1560 DL=0:U0=0:V0=0 130 | 1570 GOTO 1790 131 | 1580 REM JUMP TARGET 132 | 1590 DL=DL/DF 133 | 1600 U0=U0/DF 134 | 1610 V0=V0/DF 135 | 1620 GOTO 1790 136 | 1630 REM JUMP TARGET 137 | 1640 N=L 138 | 1650 DR=(XY%(L)-XY%(R))*DI 139 | 1660 DF=XY%(L+1)-XY%(R+1) 140 | 1670 XE=XY%(R)*DI 141 | 1680 U1=(TS%(TL)-TS%(TR))*DI 142 | 1690 V1=(TS%(TL+1)-TS%(TR+1))*DI 143 | 1700 UE=TS%(TR)*DI 144 | 1710 VE=TS%(TR+1)*DI 145 | 1720 IF DF<>0 THEN 1750 146 | 1730 DR=0:U1=0:V1=0 147 | 1740 GOTO 1790 148 | 1750 REM JUMP TARGET 149 | 1760 DR=DR/DF 150 | 1770 U1=U1/DF 151 | 1780 V1=V1/DF 152 | 1790 REM JUMP TARGET 153 | 1800 NEXT IT 154 | 1810 TC=TC+6 155 | 1820 NEXT I 156 | 1830 RETURN 157 | 1840 REM JUMP TARGET 158 | 1850 C=0 159 | 1860 FOR P=0 TO 17 STEP 3 160 | 1870 XC=CS%(P) 161 | 1880 YC=CS%(P+1) 162 | 1890 ZC=CS%(P+2)+MP 163 | 1900 XN=XC:YN=YC:ZN=ZC 164 | 1910 IF AG(0)=0 THEN 1980 165 | 1920 SI=SIN(AG(0)) 166 | 1930 CO=COS(AG(0)) 167 | 1940 YN=(YC*CO-ZC*SI) 168 | 1950 ZN=(YC*SI+ZC*CO) 169 | 1960 YC=YN 170 | 1970 ZC=ZN 171 | 1980 REM JUMP TARGET 172 | 1990 IF AG(1)=0 THEN 2060 173 | 2000 SI=SIN(AG(1)) 174 | 2010 CO=COS(AG(1)) 175 | 2020 ZN=(ZC*CO-XC*SI) 176 | 2030 XN=(ZC*SI+XC*CO) 177 | 2040 XC=XN 178 | 2050 ZC=ZN 179 | 2060 REM JUMP TARGET 180 | 2070 IF AG(2)=0 THEN 2120 181 | 2080 SI=SIN(AG(2)) 182 | 2090 CO=COS(AG(2)) 183 | 2100 XN=(XC*CO-YC*SI) 184 | 2110 YN=(XC*SI+YC*CO) 185 | 2120 REM JUMP TARGET 186 | 2130 ZN=ZN-MP 187 | 2140 XY%(C)=(XH+((XN*DI)/ZN))*1.3:C=C+1 188 | 2150 XY%(C)=YH+((YN*DI)/ZN):C=C+1 189 | 2160 XY%(C)=Z:C=C+1 190 | 2170 NEXT P 191 | 2180 RETURN 192 | 2190 REM JUMP TARGET 193 | 2200 CS%(0)=-10:CS%(1)=10:CS%(2)=-MP 194 | 2210 CS%(3)=10:CS%(4)=-10:CS%(5)=-MP 195 | 2220 CS%(6)=-10:CS%(7)=-10:CS%(8)=-MP 196 | 2230 CS%(9)=10:CS%(10)=10:CS%(11)=-MP 197 | 2240 CS%(12)=10:CS%(13)=-10:CS%(14)=-MP 198 | 2250 CS%(15)=-10:CS%(16)=10:CS%(17)=-MP 199 | 2260 TS%(0)=TW:TS%(1)=0:TS%(2)=0 200 | 2270 TS%(3)=TW:TS%(4)=TW:TS%(5)=TW 201 | 2280 TS%(6)=0:TS%(7)=0:TS%(8)=0 202 | 2290 TS%(9)=TW:TS%(10)=TW:TS%(11)=0 203 | 2300 RETURN 204 | 2400 REM JUMP TARGET 205 | 2410 PRINTCHR$(147);"UNPACKING TEXTURE..." 206 | 2420 P=TX 207 | 2430 REM JUMP TARGET 208 | 2440 READ C,V 209 | 2450 IF C=0 THEN 2520 210 | 2460 FOR I=1 TO C 211 | 2470 POKEP,V 212 | 2490 P=P+4 213 | 2500 NEXTI 214 | 2510 GOTO 2430 215 | 2520 REM JUMP TARGET 216 | 2530 FOR I=TX TO TX+4095 STEP 4 217 | 2540 V=PEEK(I) 218 | 2550 POKE I+0, (V AND 192)/64 219 | 2560 POKE I+1, (V AND 48)/16 220 | 2570 POKE I+2, (V AND 12)/4 221 | 2580 POKE I+3, (V AND 3) 222 | 2600 NEXT I 223 | 2610 RETURN 224 | 2620 DATA 199,170,1,85,1,90,13,170,1,149,2,85,12,170,1,169 225 | 2630 DATA 3,85,12,170,1,165,3,85,12,170,4,85,11,170,1,169 226 | 2640 DATA 4,85,11,170,1,169,4,85,11,170,1,165,4,85,11,170 227 | 2650 DATA 1,149,2,85,1,170,1,169,11,170,1,149,1,85,1,90 228 | 2660 DATA 13,170,2,85,1,106,2,170,3,85,1,106,7,170,2,85 229 | 2670 DATA 3,170,3,85,8,170,1,85,1,86,3,170,2,85,1,86,8,170 230 | 2680 DATA 1,85,1,86,3,170,2,85,1,90,7,170,1,169,1,85,1,86 231 | 2690 DATA 3,170,2,85,1,106,7,170,1,169,1,85,1,86,3,170,2 232 | 2700 DATA 85,8,170,1,169,1,85,1,86,13,170,1,169,1,85,1,86 233 | 2710 DATA 13,170,1,169,1,85,1,86,3,170,2,255,1,106,7,170 234 | 2720 DATA 1,169,1,85,1,86,3,170,2,255,1,218,8,170,1,85,1 235 | 2730 DATA 86,3,170,2,255,1,250,8,170,2,85,3,170,2,255,1 236 | 2740 DATA 254,8,170,2,85,3,170,3,255,8,170,1,149,1,85,1 237 | 2750 DATA 106,2,170,3,255,1,234,7,170,1,149,1,85,1,86,13 238 | 2760 DATA 170,1,165,2,85,1,106,1,165,11,170,1,165,4,85,11 239 | 2770 DATA 170,1,169,4,85,12,170,4,85,12,170,1,149,3,85,12 240 | 2780 DATA 170,1,169,3,85,13,170,3,85,13,170,1,169,1,85,1 241 | 2790 DATA 86,40,170,1,165,8,170,1,169,6,170,1,154,8,170 242 | 2800 DATA 1,169,6,170,1,90,1,165,1,90,1,85,1,150,1,153,1 243 | 2810 DATA 101,1,165,1,106,1,89,1,165,1,105,1,154,1,90,2 244 | 2820 DATA 170,1,106,1,166,1,150,1,105,1,166,1,154,1,105 245 | 2830 DATA 1,166,1,153,1,105,1,150,1,153,1,105,1,166,2,170 246 | 2840 DATA 1,90,1,166,1,150,1,105,1,165,1,154,1,105,1,150 247 | 2850 DATA 1,153,1,105,1,154,1,153,1,105,1,86,2,170,1,150 248 | 2860 DATA 1,166,1,154,1,105,1,165,1,154,1,105,1,166,1,153 249 | 2870 DATA 1,105,1,150,1,153,1,169,1,106,2,170,2,169,1,106 250 | 2880 DATA 1,105,1,166,1,154,1,105,1,169,1,106,1,85,1,165 251 | 2890 DATA 1,105,1,170,1,86,160,170,1,170 252 | 2900 DATA 0,0 253 | 20000 REM 254 | 20010 SCREEN 128:RECT 0,0,319,199,0 255 | 20130 RETURN 256 | 25000 SCREEN 2:RETURN 257 | 30000 P=0 258 | 30010 RETURN 259 | -------------------------------------------------------------------------------- /basic/traveller-ship.bas: -------------------------------------------------------------------------------- 1 | 10 ? "******************************************" 2 | 15 ? "* *" 3 | 20 ? "* TRAVELLER STARSHIP BUILDER V1.0 *" 4 | 25 ? "* *" 5 | 30 ? "* USE THIS MENU SYSTEM TO DESIGN A *" 6 | 35 ? "* STARSHIP ACCORDING TO YOUR SPECS *" 7 | 45 ? "* *" 8 | 50 ? "******************************************" 9 | 55 ? 10 | 11 | 90 HX$ = "0123456789ABCDEFGHJKLMNPQRSTUVWXYZ" 12 | 91 HY$ = "000000000000000000111111222222222222" 13 | 92 HS$ = "B": HV = 2: J$ = " ": M$ = " ": P$ = " ": CC$ = "1" 14 | 95 DIM HP$(24) 15 | 100 REM ****************************************** 16 | 101 REM MAIN LOOP 17 | 109 REM ****************************************** 18 | 110 GOSUB 200: REM SUMMARY 19 | 120 ? "************** MAIN MENU ****************":? 20 | 130 ?:? " Q - QUIT" 21 | 131 ?:? " 1 - SELECT MISSION (" MC$ ")" 22 | 132 ?:? " 2 - SELECT HULL CODE (" HS$ ")" 23 | 133 ?:? " 3 - SELECT HULL CONFIG (" HC$ ")" 24 | 134 ?:? " 4 - SELECT LANDING GEAR (" LG$ ")" 25 | 135 ?:? " 5 - SELECT JUMP DRIVE (" J ")" 26 | 136 ?:? " 6 - SELECT MANEUVER DRIVE (" M ")" 27 | 137 ?:? " 7 - SELECT COMPUTER (MODEL/" CC$ ")" 28 | 138 IF HS$ <> "" THEN ?:? " 8 - SELECT DEFENSES" 29 | 139 ? 30 | 140 GET K$:IF K$="" GOTO 140 31 | 141 IF K$ = "Q" GOTO 300 32 | 142 IF K$ = "8" AND HS$ = "" GOTO 140 33 | 143 IF K$ < "1" OR K$ > "8" GOTO 140 34 | 145 ON VAL(K$) GOSUB 1100,1200,1300,1400,1500,1600,1650,1700 35 | 190 GOTO 110 36 | 37 | 200 ? "************** SUMMARY *****************":? 38 | 210 W$="": FOR X=0 TO HP%: W$ = W$ + LEFT$(HP$(X),1): NEXT 39 | 220 ? " QSP: " MC$ "-" HS$ HC$ LG$ M$ J$ "-" CC$ " " W$:? 40 | 221 HV$ = RIGHT$(" "+STR$(HV*100),5) 41 | 222 HC=HV: REM TODO 42 | 230 J = VAL(J$): IF J$ = "H" THEN J = 1 43 | 231 JT = 5 + INT(J * HV * 2.5): IF JT = 5 THEN JT = 0 44 | 232 JT$ = RIGHT$(" "+STR$(JT),5) 45 | 233 M = VAL(M$) 46 | 234 MT = INT(M * HV): IF MT > 2 THEN MT = MT - 1 47 | 235 MT$ = RIGHT$(" "+STR$(MT),5) 48 | 236 P$ = M$: IF J$ > M$ THEN P$ = J$ 49 | 237 P = VAL(P$) 50 | 238 PT = 1 + INT(P * HV): IF PT = 1 THEN PT = 0 51 | 239 PT$ = RIGHT$(" "+STR$(PT),5) 52 | 240 FU = HV * (J*10 + M) 53 | 241 FU$ = RIGHT$(" "+STR$(FU),5) 54 | 250 H$ = LEFT$(HS$+HC$+LG$ + " ",3) 55 | 251 CT = VAL(CC$) * (VAL(CC$) + 0.5) 56 | 260 ? " TONS COMPONENT MCR" 57 | 261 ? " ---- ----------- ----" 58 | 262 ? HV$ " HULL " H$ " " RIGHT$(" "+STR$(HC),5) 59 | 263 ? " ---- " 60 | 264 ? " " CC$ " MODEL/" CC$ " " RIGHT$(" " + STR$(CT ), 4) 61 | 265 ? JT$ " J-DRIVE-" J$ " " RIGHT$(" " + STR$(JT ), 4) 62 | 266 ? MT$ " M-DRIVE-" M$ " " RIGHT$(" " + STR$(MT*2), 4) 63 | 267 ? PT$ " P-PLANT-" P$ " " RIGHT$(" " + STR$(PT ), 4) 64 | 268 ? FU$ " FUEL -" 65 | 270 WT=0:FOR X=0 TO HP%: IF LEN(HP$(X)) = 0 GOTO 279 66 | 271 WT=WT+1 67 | 278 ? " 1 " HP$(X) " 1" 68 | 279 NEXT 69 | 280 TF=INT(HV*100 - JT - MT - PT - FU - WT - VAL(CC$)) 70 | 281 TF$ = RIGHT$(" "+STR$(TF),5) 71 | 282 TC = HC+JT+MT*2+PT+WT+CT 72 | 283 TC$ = RIGHT$(" "+STR$(TC),5) 73 | 284 ? TF$ " CARGO -" 74 | 290 ? " ----" 75 | 291 ? " " TC$ 76 | 292 ? 77 | 299 RETURN 78 | 79 | 300 REM ****************************************** 80 | 301 REM QUIT 81 | 309 REM ****************************************** 82 | 320 ? " QSP: " MC$ "-" HS$ HC$ LG$ M$ J$ "-" CC$ " " W$:? 83 | 399 END 84 | 85 | 1100 REM ****************************************** 86 | 1101 REM MISSION CODE 87 | 1109 REM ****************************************** 88 | 1110 ? "SHIP MISSION CODE":? 89 | 1111 ? " A - TRADER" 90 | 1112 ? " C - CRUISER" 91 | 1113 ? " E - ESCORT" 92 | 1114 ? " F - FREIGHTER" 93 | 1115 ? " G - FRIGATE" 94 | 1116 ? " J - PROSPECTOR" 95 | 1117 ? " K - TOURING SHIP" 96 | 1118 ? " L - LAB SHIP" 97 | 1119 ? " M - LINER" 98 | 1120 ? " P - CORSAIR" 99 | 1121 ? " R - MERCHANT" 100 | 1122 ? " S - SCOUT/COURIER" 101 | 1123 ? " T - TRANSPORT" 102 | 1124 ? " U - PACKET" 103 | 1125 ? " V - CORVETTE" 104 | 1126 ? " X - EXPRESS" 105 | 1127 ? " Y - YACHT" 106 | 1128 ? 107 | 1130 GET K$: IF K$ < "A" OR K$ > "Z" GOTO 1130 108 | 1140 MC$ = K$ 109 | 1190 RETURN 110 | 111 | 1200 REM ****************************************** 112 | 1201 REM HULL CODE 113 | 1209 REM ****************************************** 114 | 1210 ? "HULL SIZE CODE":? 115 | 1215 FOR X = 1 TO 24 116 | 1220 ? " " MID$(HX$,X+10,1) " -" X * 100 "TONS" 117 | 1230 NEXT:? 118 | 1240 GET K$:IF K$ < "A" OR K$="I" OR K$="O" OR K$>"Z" GOTO 1240 119 | 1250 HS$ = K$ 120 | 1255 HV = ASC(HS$)-64 121 | 1260 IF HS$ > "H" THEN HV = HV - 1 122 | 1265 IF HS$ > "N" THEN HV = HV - 1 123 | 1290 RETURN 124 | 125 | 1300 REM ****************************************** 126 | 1301 REM HULL CONFIG 127 | 1309 REM ****************************************** 128 | 1310 ? "HULL CONFIGURATION":? 129 | 1311 ? " 1 - PLANETOID" 130 | 1312 ? " 2 - CLUSTER" 131 | 1313 ? " 3 - BRACED" 132 | 1314 ? " 4 - UNSTREAMLINED" 133 | 1315 ? " 5 - STREAMLINED" 134 | 1316 ? " 6 - AIRFRAME" 135 | 1317 ? " 7 - LIFTING BODY" 136 | 1320 ? 137 | 1325 GET K$: IF K$ < "1" OR K$ > "7" GOTO 1325 138 | 1330 HC$ = MID$("PCBUSAL",VAL(K$),1) 139 | 1390 RETURN 140 | 141 | 1400 REM ****************************************** 142 | 1401 REM LANDING GEAR 143 | 1409 REM ****************************************** 144 | 1410 ? "LANDING GEAR":? 145 | 1411 ? " 1 - NONE" 146 | 1412 ? " 2 - SKIDS" 147 | 1413 ? " 3 - LANDERS" 148 | 1414 ? " 4 - WHEELS" 149 | 1420 ? 150 | 1425 GET K$: IF K$ < "1" OR K$ > "4" GOTO 1425 151 | 1430 LG$ = MID$("NSLW",VAL(K$),1) 152 | 1490 RETURN 153 | 154 | 1500 REM ****************************************** 155 | 1501 REM JUMP DRIVE 156 | 1509 REM ****************************************** 157 | 1510 ? "JUMP DRIVE":? 158 | 1511 ? " 1 - JUMP-1" 159 | 1512 ? " 2 - JUMP-2" 160 | 1513 ? " 3 - JUMP-3" 161 | 1514 ? " 4 - JUMP-4" 162 | 1515 ? " 5 - JUMP-5" 163 | 1516 ? " 6 - JUMP-6" 164 | 1517 ? " 7 - JUMP-7" 165 | 1518 ? " H - HOP-1" 166 | 1520 ? 167 | 1525 GET K$: IF K$ = "H" GOTO 1535 168 | 1530 IF K$ < "1" OR K$ > "7" GOTO 1525 169 | 1535 J$ = K$ 170 | 1590 RETURN 171 | 172 | 1600 REM ****************************************** 173 | 1601 REM MANEUVER DRIVE 174 | 1609 REM ****************************************** 175 | 1610 ? "MANEUVER DRIVE" 176 | 1611 ? " 1 - 1G" 177 | 1612 ? " 2 - 2G" 178 | 1613 ? " 3 - 3G" 179 | 1614 ? " 4 - 4G" 180 | 1615 ? " 5 - 5G" 181 | 1616 ? " 6 - 6G" 182 | 1617 ? " 7 - 7G" 183 | 1618 ? " 8 - 8G" 184 | 1619 ? " 9 - 9G" 185 | 1620 ? 186 | 1625 GET K$ 187 | 1630 IF K$ < "1" OR K$ > "9" GOTO 1625 188 | 1635 M$ = K$ 189 | 1649 RETURN 190 | 191 | 1650 REM ****************************************** 192 | 1651 REM COMPUTER 193 | 1659 REM ****************************************** 194 | 1660 ? "COMPUTER MODEL" 195 | 1661 ? " 1 - MODEL/1" 196 | 1662 ? " 2 - MODEL/2" 197 | 1663 ? " 3 - MODEL/3" 198 | 1664 ? " 4 - MODEL/4" 199 | 1665 ? " 5 - MODEL/5" 200 | 1666 ? " 6 - MODEL/6" 201 | 1667 ? " 7 - MODEL/7" 202 | 1668 ? " 8 - MODEL/8" 203 | 1669 ? " 9 - MODEL/9" 204 | 1670 ? 205 | 1675 GET K$ 206 | 1680 IF K$ < "1" OR K$ > "9" GOTO 1675 207 | 1685 CC$ = K$ 208 | 1699 RETURN 209 | 210 | 1700 REM ****************************************** 211 | 1701 REM HARDPOINTS 212 | 1709 REM ****************************************** 213 | 1710 S% = 0: MA% = 0 214 | 1711 IF MC$ = "C" OR MC$ = "E" OR MC$ = "G" OR MC$ = "V" THEN MA% = 1 215 | 1712 HP% = HV-1: IF HP% > 9 THEN HP% = 9 216 | 1714 ? " TURRET / CONTENTS " 217 | 1715 ? " ------ ---------------------" 218 | 1716 FOR X = 0 TO HP% 219 | 1717 IF S% = X THEN ? "*"; 220 | 1718 IF S% <> X THEN ? " "; 221 | 1719 ? " " X ": " HP$(X) 222 | 1720 NEXT X 223 | 1721 ? " K : PULSE LASER TURRET" 224 | 1722 ? " L : BEAM LASER TURRET" 225 | 1723 ? " M : MISSILE LAUNCHER TURRET" 226 | 1724 ? " S : SANDCASTER TURRET" 227 | 1725 IF MA% = 1 THEN ? " P : PLASMA BARBETTE" 228 | 1729 ? " Q : QUIT MENU":? 229 | 1730 GET A$: IF A$ = "" GOTO 1730 230 | 1740 IF A$ = "K" THEN HP$(S%) = "K (PULSE L)" 231 | 1741 IF A$ = "L" THEN HP$(S%) = "L (BEAM L) " 232 | 1742 IF A$ = "M" THEN HP$(S%) = "MISSILE " 233 | 1743 IF A$ = "S" THEN HP$(S%) = "SANDCASTER " 234 | 1744 IF MA% = 1 AND A$ = "P" THEN HP$(S%) = "PLASMA " 235 | 1750 IF A$ = "Q" GOTO 1790 236 | 1755 IF A$ >= "0" AND A$ <= MID$(STR$(HP%),2,1) THEN S% = VAL(A$): GOTO 1714 237 | 1760 GOTO 1714 238 | 1790 RETURN 239 | 240 | -------------------------------------------------------------------------------- /basic/traveller-uwp.bas: -------------------------------------------------------------------------------- 1 | 10 HX$ = "0123456789ABCDEFGHJKLMNPQRSTUVWXYZ" 2 | 15 DIM NN$(11) 3 | 20 ? "**************************************" 4 | 25 ? " " 5 | 30 ? " TRAVELLER MAINWORLD GENERATOR " 6 | 40 ? " " 7 | 50 ? " INSTRUCTIONS: " 8 | 60 ? " ENTER A 4-DIGIT 'RING' COORD " 9 | 70 ? " AND A 5-DIGIT 'RAY' COORD " 10 | 75 ? " " 11 | 80 ? " GENERATES A ROW OF 10 'HEXES' " 12 | 85 ? " " 13 | 90 ? "**************************************" 14 | 100 RI = 9930 : REM FOR EXAMPLE 15 | 110 RA = 62723 16 | 120 INPUT "RING (4 DIGITS)"; RI 17 | 130 INPUT "RAY (5 DIGITS)"; RA 18 | 131 ? RI "RING/RAY" RA : ? 19 | 140 FOR RA = RA TO RA + 7:FOR RI = RI TO RI + 9 20 | 141 GOSUB 1100: REM COL+ROW 21 | 160 GOSUB 200: REM INIT 22 | 165 IF P = 0 THEN ? CR$ " *":GOTO 195 23 | 170 GOSUB 1000: REM UWP 24 | 172 GOSUB 1200: REM NAME 25 | 173 RS$ = " ": REM SPECIAL REMARKS (N/A) 26 | 174 GOSUB 1300: REM BASES 27 | 175 GOSUB 1350: REM B+G 28 | 176 Z$ = " ": REM ZONE (N/A) 29 | 177 AL$ = " ": REM ALLEG (N/A) 30 | 180 REM ? CR$ Z$ NA$ UW$ BA$ " " BG$ " " RM$ 31 | 181 ? CR$ " " UW$ " " BA$ " " RM$ " " BG$ " " NA$ 32 | 195 NEXT RI: NEXT RA 33 | 199 END 34 | 35 | 200 REM ------------------------ 36 | 201 REM INITIALIZE DICE 37 | 202 REM ------------------------ 38 | 205 RR = RI*10000 + RA 39 | 210 P=RND(-RR) 40 | 215 REM ------------------------ 41 | 216 REM SYSTEM PRESENCE 42 | 217 REM ------------------------ 43 | 219 P=RND(1) 44 | 220 IF P >= 0.5 THEN P=1 45 | 221 IF P < 0.5 THEN P=0 46 | 249 RETURN 47 | 48 | 250 REM ------------------------ 49 | 251 REM ROLL DICE 50 | 252 REM ------------------------ 51 | 255 DM = 0:GOTO 270 52 | 260 DM = -1:GOTO 270 53 | 265 DM = -2 54 | 270 D1 = INT(RND(1)*6)+1 55 | 275 D2 = INT(RND(1)*6) + INT(RND(1)*6) + 2 + DM 56 | 280 DF = INT(RND(1)*6) - INT(RND(1)*6) + DM 57 | 299 RETURN 58 | 59 | 300 REM ------------------------ 60 | 301 REM STARPORT 61 | 302 REM ------------------------ 62 | 305 GOSUB 260 63 | 307 SP$ = MID$("AAABBCCDEEX",D2,1) 64 | 309 RETURN 65 | 66 | 310 REM ------------------------ 67 | 311 REM SIZE, ATMOSPHERE, HYDRO 68 | 312 REM ------------------------ 69 | 315 GOSUB 265: SZ = D2 70 | 320 GOSUB 250: AT = DF + SZ 71 | 325 IF AT < 0 OR SZ = 0 THEN AT = 0 72 | 330 GOSUB 250: HY = DF + AT 73 | 335 IF HY < 0 THEN HY = 0 74 | 336 IF AT = 0 THEN HY = 0 75 | 340 IF HY > 10 THEN HY = 10 76 | 341 SZ$ = MID$(HX$,SZ+1,1) 77 | 342 AT$ = MID$(HX$,AT+1,1) 78 | 343 HY$ = MID$(HX$,HY+1,1) 79 | 349 RETURN 80 | 81 | 350 REM ------------------------ 82 | 351 REM POP, GOV, LAW 83 | 352 REM ------------------------ 84 | 355 GOSUB 265: PO = D2 85 | 360 GOSUB 250: GV = DF + PO 86 | 365 IF GV < 0 THEN GV = 0 87 | 370 GOSUB 250: LA = DF + GV 88 | 375 IF LA < 0 THEN LA = 0 89 | 380 PO$ = MID$(HX$,PO+1,1) 90 | 381 GV$ = MID$(HX$,GV+1,1) 91 | 382 LA$ = MID$(HX$,LA+1,1) 92 | 399 RETURN 93 | 94 | 400 REM ------------------------ 95 | 401 REM TL 96 | 402 REM ------------------------ 97 | 405 GOSUB 270: TL = D1 98 | 410 IF SP$ = "A" THEN TL = TL + 6 99 | 411 IF SP$ = "B" THEN TL = TL + 4 100 | 412 IF SP$ = "C" THEN TL = TL + 2 101 | 413 IF SP$ = "X" THEN TL = TL - 4 102 | 414 IF SP$ = "F" THEN TL = TL + 1 103 | 420 IF SZ < 2 THEN TL = TL + 1 104 | 421 IF SZ < 5 THEN TL = TL + 1:REM FALL-THRU 105 | 422 IF AT < 4 OR AT > 9 THEN TL = TL + 1 106 | 423 IF HY = 9 THEN TL = TL + 1 107 | 424 IF HY = 10 THEN TL = TL + 2 108 | 425 IF PO > 0 AND PO < 6 THEN TL = TL + 1 109 | 426 IF PO = 9 THEN TL = TL + 2 110 | 427 IF PO > 9 THEN TL = TL + 4 111 | 428 IF GV = 0 OR GV = 5 THEN TL = TL + 1 112 | 429 IF GV = 13 THEN TL = TL + 2 113 | 430 IF TL < 0 THEN TL = 0 114 | 440 TL$ = MID$(HX$,TL+1,1) 115 | 449 RETURN 116 | 117 | 500 REM ------------------------ 118 | 501 REM REMARKS (UW$ REQUIRED) 119 | 502 REM ------------------------ 120 | 510 RM$ = "" 121 | 511 IN$ = ".444..-. .988..-. AG":GOSUB 550 122 | 512 IN$ = "000...-. 000...-. AS":GOSUB 550 123 | 513 IN$ = "...0..-0 ...0..-0 BA":GOSUB 550 124 | 514 IN$ = "200...-. 900...-. DE":GOSUB 550 125 | 515 IN$ = "...0..-1 ...0..-Z DI":GOSUB 550 126 | 516 IN$ = ".A1...-. .CA...-. FL":GOSUB 550 127 | 517 IN$ = "655...-. 887...-. GA":GOSUB 550 128 | 518 IN$ = "320...-. CC2...-. HE":GOSUB 550 129 | 519 IN$ = "...9..-. ...F..-. HI":GOSUB 550 130 | 520 IN$ = ".01...-. .1A...-. IC":GOSUB 550 131 | 521 REM IN /^..[012479ABC].[9A-F]/ 132 | 522 IF PO < 9 GOTO 525 133 | 523 IF AT < 3 OR AT = 4 OR AT = 7 OR AT > 8 THEN RM$ = RM$ + " IN" 134 | 525 IN$ = "...1..-. ...3..-. LO":GOSUB 550 135 | 526 IN$ = ".006..-. .33F..-. NA":GOSUB 550 136 | 527 IN$ = "...4..-. ...6..-. NI":GOSUB 550 137 | 528 IN$ = ".20...-. .53...-. PO":GOSUB 550 138 | 530 REM RI /^..[68].[678]/ 139 | 531 IF AT <> 6 AND AT <> 8 GOTO 535 140 | 532 IF PO > 5 AND PO < 9 THEN RM$ = RM$ + " RI" 141 | 535 IN$ = "A3A...-. FFA...-. OC":GOSUB 550 142 | 536 IN$ = ".0....-. .0....-. VA":GOSUB 550 143 | 537 IN$ = "33A...-. 9FA...-. WA":GOSUB 550 144 | 545 REM RM$ = MID$(RM$,2): REM NON-PADDED 145 | 546 RM$ = MID$(RM$+" ",2,15):REM PADDED 146 | 549 RETURN 147 | 148 | 550 REM ------------------------ 149 | 551 REM LOOP CHECK IN$ 150 | 552 REM IN$ = "320...-. CC2...-. HE" 151 | 553 REM UW$ = "A11567-8" 152 | 554 REM ------------------------ 153 | 555 M = 0:FOR X = 1 TO 8 154 | 560 CC$ = MID$(UW$,X+1,1) 155 | 565 LO$ = MID$(IN$,X,1) 156 | 570 HI$ = MID$(IN$,X+9,1) 157 | 571 REM ? CC$; 158 | 575 IF LO$ = "." GOTO 590 159 | 580 IF CC$ < LO$ GOTO 599 160 | 585 IF CC$ > HI$ GOTO 599 161 | 590 M = M + 1 162 | 595 NEXT 163 | 597 IF M = 8 THEN RM$ = RM$ + " " + MID$(IN$,19,2) 164 | 599 RETURN 165 | 166 | 1000 REM ------------------------ 167 | 1001 REM DETERMINE UWP 168 | 1002 REM ------------------------ 169 | 1010 GOSUB 300: REM SP$ 170 | 1020 GOSUB 310: REM SZ AT HY 171 | 1030 GOSUB 350: REM PO GV LA 172 | 1040 GOSUB 400: REM TL 173 | 1045 REM ? "UWP: " SP$; SZ; AT; HY; PO; GV; LA; "-" TL 174 | 1050 UW$ = SP$ + SZ$ + AT$ + HY$ + PO$ + GV$ + LA$ + "-" + TL$ 175 | 1060 GOSUB 500: REM RM$ 176 | 1099 RETURN 177 | 178 | 1100 REM ------------------------ 179 | 1101 REM DETERMINE HEX 180 | 1102 REM ------------------------ 181 | 1110 C% = INT(RA-INT(RA/32)*32)+1 182 | 1120 R% = INT(RI-INT(RI/40)*40)+1 183 | 1130 CR$ = RIGHT$(STR$(C%),2) + RIGHT$(STR$(R%),2) 184 | 1135 IF LEFT$(CR$,1) = " " THEN CR$ = "0" + RIGHT$(CR$,3) 185 | 1140 IF MID$(CR$,3,1) = " " THEN CR$ = LEFT$(CR$,2) + "0" + RIGHT$(CR$,1) 186 | 1190 RETURN 187 | 188 | 1200 REM ------------------------ 189 | 1201 REM DETERMINE NAME 190 | 1202 REM ------------------------ 191 | 1210 NN$(0) = "CO DA AS SI ME EA AR RA IZ AT TA DA RA LE IG EN " 192 | 1211 NN$(1) = "IX AG TI ID RO GA EX OX LO CA NI ME LI TO LA WO " 193 | 1212 NN$(2) = "DE RU DE AG RO PO TA SE IN MO LU DE RI PE ST ER " 194 | 1213 NN$(3) = "ST RO TA SO AR RU WA WO AD AK WA EN EG DE AC OC " 195 | 1214 NN$(4) = "OP OR PA RE RI NU TI VE WI VI JU MO ME NE UT A " 196 | 1215 NN$(5) = "I U E O BECTLEFLESHOONAORAPHOSHOFORGUELANLAS" 197 | 1216 NN$(6) = "DENTINARTORTERTANGINGENGONGANTONTINTINDUNDENDTRI" 198 | 1217 NN$(7) = "ITOMERALUBELDECREMMENDUCSCOTHEDREOWNEPICENCANSAR" 199 | 1218 NN$(8) = "GENTERAGEATEBITHENHOSGRAGNOCIDCANARDCORCREOUSATH" 200 | 1219 NN$(9) = "AINWHELUCLINMATMEDMISMELMARNECNORNESNOUOSTPELPRO" 201 | 1220 NN$(10) = "PORPRIPLAFRIREGSANSALINESOLSEMSECSULSCASCISHERAN" 202 | 1221 NN$(11) = "MERMIRSPISTATECAPHTELTOLTOMTENTORTERLOCVALVERERG" 203 | 204 | 1260 P = RND(1) 205 | 1265 NA$ = "" 206 | 1270 X = 3 : IF P <= 0.15 THEN X = 2 207 | 1275 FOR Y = 1 TO X 208 | 1280 NR% = RND(1)*12 209 | 1281 NC% = INT(RND(1)*16) * 3 + 1 210 | 1283 F$ = MID$(NN$(NR%),NC%,3) 211 | 1285 NA$ = NA$ + F$ : LN = LEN(NA$) 212 | 1290 IF RIGHT$(NA$,1) = " " THEN NA$ = LEFT$(NA$,LN-1) 213 | 1295 NEXT 214 | 1298 REM NA$ = LEFT$(NA$+" ",10) <- PADDING 215 | 1299 RETURN 216 | 217 | 1300 REM ------------------------ 218 | 1301 REM DETERMINE BASES 219 | 1302 REM ------------------------ 220 | 1310 N$ = " ": GOSUB 260 221 | 1311 IF SP$ = "A" THEN N$ = MID$("NNNNN ",D2,1) 222 | 1312 IF SP$ = "B" THEN N$ = MID$("NNNN ",D2,1) 223 | 1320 S$ = " ": GOSUB 260 224 | 1321 IF SP$ = "A" THEN S$ = MID$("SSS ",D2,1) 225 | 1322 IF SP$ = "B" THEN S$ = MID$("SSSS ",D2,1) 226 | 1323 IF SP$ = "C" THEN S$ = MID$("SSSSS ",D2,1) 227 | 1324 IF SP$ = "D" THEN S$ = MID$("SSSSSS ",D2,1) 228 | 1330 BA=1 229 | 1331 IF N$ = "N" THEN BA = BA + 1 230 | 1332 IF S$ = "S" THEN BA = BA + 2 231 | 1335 BA$ = MID$(" NS2",BA,1) 232 | 1349 RETURN 233 | 234 | 1350 REM ------------------------ 235 | 1351 REM BELTS AND GAS GIANTS 236 | 1352 REM ------------------------ 237 | 1360 GOSUB 260 238 | 1370 G$ = MID$("00001122334", D2, 1) 239 | 1380 B$ = MID$("000123", D1, 1) 240 | 1390 BG = 1 241 | 1391 IF B$ > "0" THEN BG = 2 242 | 1392 IF G$ > "0" THEN BG = BG + 2 243 | 1395 BG$ = MID$(" BG2",BG,1) 244 | 1399 RETURN 245 | -------------------------------------------------------------------------------- /basic/aritm-x16.bas: -------------------------------------------------------------------------------- 1 | 1000 REM ARITM V0.3.5 FOR COMMANDER X16 BASIC 2.0 IS FOSS. 2 | 1020 REM (C) 1992-2022 BY MIKAEL O. BONNIER, LUND, SWEDEN. 3 | 1030 REM E-MAIL: . 4 | 1040 REM ABSOLUTELY NO WARRANTY. 5 | 1050 REM LICENSE GPLV3+, SEE 6 | 1060 REM . 7 | 1070 REM MORE PROGRAMS AT 8 | 1080 REM . ~ IS TILDE. 9 | 1090 REM DOCUMENTATION: 10 | 1100 REM 876543210, 8:TYPE, 7-5:OP1, 4-3:OP2, 2:RES'D, 1-0:#TODO. 11 | 1110 REM PROGRAM: 12 | 1112 GOTO 1115 13 | 1113 MD%=INT((X/Y-INT(X/Y))*Y+.5):RETURN 14 | 1114 DIV=INT(X/Y+.5):RETURN 15 | 1115 LET R=RND(-TIME):LET R=RND(0) 16 | 1116 OPEN 1,0:SCREEN $FF:? CHR$($8E);CHR$($90);CHR$(1);CHR$($9E);CHR$($93) 17 | 1117 DIM A(590) 18 | 1120 REM LBL C 19 | 1130 GOSUB 3410:REM CLS 20 | 1140 LET A%=0 21 | 1150 IF (L%>0)*M THEN GOTO 3000:REM CONTMENU 22 | 1160 IF 0=M THEN LET M=10 23 | 1170 GOTO 3030:REM MENU 24 | 1180 REM LBL S 25 | 1190 GOSUB 3410:REM CLS 26 | 1200 PRINT "GENERATING" 27 | 1210 PRINT "PROBLEMS..." 28 | 1220 LET U%=1 29 | 1230 REM DIM A(N%) 30 | 1240 REM LBL ADD1 31 | 1250 X=M:Y=10:GOSUB 1114:X=DIV:GOSUB 1113 32 | 1255 IF 0=MD% THEN GOTO 1320:REM ADD2 33 | 1260 FOR I=0 TO 9 34 | 1270 FOR J=0 TO 9 35 | 1280 LET A(U%)=100000000+I*100000+J*1000+1 36 | 1290 LET U%=U%+1 37 | 1300 NEXT J 38 | 1310 NEXT I 39 | 1320 REM LBL ADD2 40 | 1330 X=M:Y=100:GOSUB 1114:X=DIV:Y=10:GOSUB 1113 41 | 1335 IF 0=MD% THEN GOTO 1410:REM SUB1 42 | 1340 FOR I=0 TO 9 43 | 1350 FOR J=0 TO 9 44 | 1360 LET T%=10*(INT(8*RND(1))+1) 45 | 1370 LET A(U%)=200000000+(T%+I)*100000+J*1000+1 46 | 1380 LET U%=U%+1 47 | 1390 NEXT J 48 | 1400 NEXT I 49 | 1410 REM LBL SUB1 50 | 1420 X=M:Y=1000:GOSUB 1114:X=DIV:Y=10:GOSUB 1113 51 | 1425 IF 0=MD% THEN GOTO 1490:REM SUB2 52 | 1430 FOR I=0 TO 9 53 | 1440 FOR J=I TO 9+I 54 | 1450 LET A(U%)=300000000+J*100000+I*1000+1 55 | 1460 LET U%=U%+1 56 | 1470 NEXT J 57 | 1480 NEXT I 58 | 1490 REM LBL SUB2 59 | 1500 X=M:Y=10000:GOSUB 1114:X=DIV:Y=10:GOSUB 1113 60 | 1505 IF 0=MD% THEN GOTO 1580:REM MUL 61 | 1510 FOR I=0 TO 9 62 | 1520 FOR J=I TO 9+I 63 | 1530 LET T%=10*(INT(9*RND(1))+1) 64 | 1540 LET A(U%)=400000000+(T%+J)*100000+I*1000+1 65 | 1550 LET U%=U%+1 66 | 1560 NEXT J 67 | 1570 NEXT I 68 | 1580 REM LBL MUL 69 | 1590 X=M:Y=100000:GOSUB 1114:X=DIV:Y=10:GOSUB 1113 70 | 1595 IF 0=MD% THEN GOTO 1660:REM DIV 71 | 1600 FOR I=0 TO 9 72 | 1610 FOR J=0 TO 9 73 | 1620 LET A(U%)=500000000+I*100000+J*1000+1 74 | 1630 LET U%=U%+1 75 | 1640 NEXT J 76 | 1650 NEXT I 77 | 1660 REM LBL DIV 78 | 1670 X=M:Y=1000000:GOSUB 1114:X=DIV:Y=10:GOSUB 1113 79 | 1675 IF 0=MD% THEN GOTO 1750:REM ENDIF 80 | 1680 FOR I=0 TO 9 81 | 1690 FOR J=1 TO 9 82 | 1700 LET T%=I*J+INT(J*RND(1)) 83 | 1710 LET A(U%)=600000000+T%*100000+J*1000+1 84 | 1720 LET U%=U%+1 85 | 1730 NEXT J 86 | 1740 NEXT I 87 | 1750 REM LBL ENDIF 88 | 1760 LET U%=U%-1 89 | 1770 LET L%=U% 90 | 1780 REM LBL U 91 | 1790 PRINT "SHUFFLING..." 92 | 1800 FOR I=U% TO 2 STEP -1 93 | 1810 LET J%=INT(I*RND(1))+1 94 | 1820 LET T=A(I) 95 | 1830 LET A(I)=A(J%) 96 | 1840 LET A(J%)=T 97 | 1850 NEXT I 98 | 1860 LET K%=1 99 | 1870 REM LBL K 100 | 1880 GOSUB 3410:REM CLS 101 | 1890 PRINT MID$(STR$(L%),2);" PROBLEMS LEFT. -1 ESC" 102 | 1900 LET T=A(K%) 103 | 1910 X=T:Y=100000000:GOSUB 1114 104 | 1915 LET C%=DIV 105 | 1920 IF 6=C% THEN PRINT "INTEGER PART OF "; 106 | 1930 X=T:Y=100000:GOSUB 1114:X=DIV:Y=1000:GOSUB 1113 107 | 1935 LET I%=MD% 108 | 1940 PRINT MID$(STR$(I%),2); 109 | 1950 GOSUB 3280:REM SIGN 110 | 1960 X=T:Y=1000:GOSUB 1114:X=DIV:Y=100:GOSUB 1113 111 | 1965 LET J%=MD% 112 | 1970 PRINT MID$(STR$(J%),2); 113 | 1980 PRINT " = ";:INPUT#1,A$:A%=VAL(A$) 114 | 1985 PRINT 115 | 1990 IF -1=A% OR ".1"=A$ OR "01"=A$ THEN GOTO 1120:REM C 116 | 2000 IF (1=C%)+(2=C%) THEN LET R%=I%+J%:GOTO 2040:REM ENDIF 117 | 2010 IF (3=C%)+(4=C%) THEN LET R%=I%-J%:GOTO 2040:REM ENDIF 118 | 2020 IF 5=C% THEN LET R%=I%*J%:GOTO 2040:REM ENDIF 119 | 2030 IF 6=C% THEN LET R%=INT(I%/J%) 120 | 2040 REM LBL ENDIF 121 | 2050 IF R%<>A% THEN GOTO 2140:REM WRONG 122 | 2060 PRINT "RIGHT! "; 123 | 2070 X=T:Y=100:GOSUB 1113 124 | 2075 IF 0>=MD% THEN GOTO 2100:REM ENDIF 125 | 2080 LET L%=L%-1 126 | 2090 LET A(K%)=T-1 127 | 2100 REM LBL ENDIF 128 | 2110 LET K%=K%+1 129 | 2120 IF 0=L% GOTO 2390:REM W 147 | 2280 PRINT "CHECKING..." 148 | 2290 LET N%=1 149 | 2300 FOR K=1 TO U% 150 | 2310 LET T=A(K) 151 | 2320 X=T:Y=100:GOSUB 1113 152 | 2325 IF 0=MD% THEN GOTO 2350:REM ENDIF 153 | 2330 LET A(N%)=T 154 | 2340 LET N%=N%+1 155 | 2350 REM ENDIF 156 | 2360 NEXT K 157 | 2370 LET U%=N%-1 158 | 2380 GOTO 1780:REM U 159 | 2390 REM LBL W 160 | 2400 PRINT "GOOD!!! WELL DONE!" 161 | 2410 LET D=5000:GOSUB 3402:REM DELAY 162 | 2420 GOTO 1120:REM C 163 | 2430 REM LBL E 164 | 2440 GOSUB 3410:REM CLS 165 | 2450 LET A%=0 166 | 2460 LET N%=0 167 | 2470 LET T=M 168 | 2480 GOSUB 2640:REM SUB 169 | 2490 PRINT "ADDITION 1" 170 | 2500 GOSUB 2640:REM SUB 171 | 2510 PRINT "ADDITION 2" 172 | 2520 GOSUB 2640:REM SUB 173 | 2530 PRINT "SUBTRACTION 1" 174 | 2540 GOSUB 2640:REM SUB 175 | 2550 PRINT "SUBTRACTION 2" 176 | 2560 GOSUB 2640:REM SUB 177 | 2570 PRINT "MULTIPLICATION" 178 | 2580 GOSUB 2640:REM SUB 179 | 2590 PRINT "DIVISION y -1 ESC" 180 | 2600 PRINT "0 OK AND GO"; 181 | 2605 PRINT STR$(N%) 182 | 2610 GOTO 2780:REM INPUT 183 | 2640 REM SUB 184 | 2650 LET A%=A%+1 185 | 2660 X=T:Y=10:GOSUB 1114 186 | 2665 LET T=DIV 187 | 2670 PRINT MID$(STR$(A%),2); 188 | 2680 X=T:Y=10:GOSUB 1113 189 | 2685 IF 0=MD% THEN GOTO 2720:REM ELSE 190 | 2690 PRINT "*"; 191 | 2700 LET N%=N%+100+10*(6=A%) 192 | 2710 GOTO 2740:REM ENDIF 193 | 2720 REM LBL ELSE 194 | 2730 PRINT " "; 195 | 2740 REM LBL ENDIF 196 | 2750 RETURN 197 | 2780 REM LBL INPUT 198 | 2790 PRINT "TOGGLE ITEM 1-6, OR CHOOSE 0 OR -1: ";:INPUT#1,A$:A%=VAL(A$) 199 | 2795 PRINT:REM C64 INPUT# DOESN'T LINEFEED 200 | 2800 IF (-1>A%)+(60)),2);": "; 235 | 3140 INPUT#1,A$:S%=VAL(A$) 236 | 3145 PRINT 237 | 3150 IF (1>S%)+(4-(L%>0)0 254 | 3360 LET R=1 255 | 3370 FOR I=1 TO A% 256 | 3380 LET R=R*10 257 | 3390 NEXT I 258 | 3400 RETURN 259 | 3402 REM DELAY 260 | 3404 LET T1=TIME 261 | 3405 LET D=60*D/1000 262 | 3406 IF TIME-T1." 275 | 3520 LET D=5000:GOSUB 3402:REM DELAY 276 | 3530 RETURN 277 | 3540 REM SUB ABOUT 278 | 3550 GOSUB 3410:REM CLS 279 | 3560 PRINT "ABOUT" 280 | 3570 PRINT "ARITM 0.3 (C) 1992-2022 BY" 281 | 3575 PRINT "MIKAEL O. BONNIER, LUND, SWEDEN." 282 | 3580 PRINT "ABSOLUTELY NO WARRANTY." 283 | 3585 PRINT "FOSS, SEE LICENSE GPLV3+." 284 | 3590 LET D=5000:GOSUB 3402:REM DELAY 285 | 3600 RETURN 286 | 3610 REM SUB SOUND 287 | 3620 PRINT CHR$(7); 288 | 3670 FOR X=1 TO 250:NEXT 289 | 3690 RETURN 290 | -------------------------------------------------------------------------------- /assembly/x16-matriculate-text/system.inc: -------------------------------------------------------------------------------- 1 | !ifdef SYSTEM_INC !eof 2 | SYSTEM_INC=1 3 | 4 | ;================================================= 5 | ; SYS_HEADER_0801 6 | ; File header of a PRG loaded at $0801. Includes 7 | ; encoded BASIC commands to start execution 8 | ; without needing a SYS() command. 9 | ;------------------------------------------------- 10 | ; INPUTS: (none) 11 | ; 12 | ;------------------------------------------------- 13 | ; MODIFIES: (none) 14 | ; 15 | !macro SYS_HEADER_0801 { 16 | !ifdef HEADER_A000_IN_USE { 17 | !warn "SYS_HEADER_A000 already in use. This second call may not do what you think, and may break file size detection." 18 | } 19 | HEADER_0801_IN_USE=1 20 | *=$0801 21 | !byte $0b,$08,$01,$00,$9e,$32,$30,$36,$31,$00,$00,$00 22 | } 23 | 24 | ;================================================= 25 | ; SYS_HEADER_A000 26 | ; File header for a file loaded into $0A00. This 27 | ; may include executable code and/or data, but 28 | ; needs to be loaded in separate from the main 29 | ; .PRG because of the address it needs to occupy. 30 | ;------------------------------------------------- 31 | ; INPUTS: (none) 32 | ; 33 | ;------------------------------------------------- 34 | ; MODIFIES: (none) 35 | ; 36 | !macro SYS_HEADER_A000 { 37 | !ifdef HEADER_0801_IN_USE { 38 | !warn "SYS_HEADER_0801 already in use. This second call may not do what you think, and may break file size detection." 39 | } 40 | HEADER_A000_IN_USE=1 41 | *=$0A00 42 | } 43 | 44 | ;================================================= 45 | ; SYS_FOOTER 46 | ; File footer for any file. This provides a warning 47 | ; in case the file has exceeded the bounds of 48 | ; the memory into which it is intended to be loaded. 49 | ;------------------------------------------------- 50 | ; INPUTS: (none) 51 | ; 52 | ;------------------------------------------------- 53 | ; MODIFIES: (none) 54 | ; 55 | !macro SYS_FOOTER { 56 | 57 | !ifndef HEADER_0801_IN_USE { 58 | !ifndef HEADER_A000_IN_USE { 59 | !warn "SYS_HEADER_* macro in use. Add SYS_HEADER_0801 or SYS_HEADER_A000, depending on where you expect to load this file." 60 | } 61 | } 62 | 63 | !ifdef HEADER_0801_IN_USE { 64 | !if * > $9EFF { 65 | !warn "Program size exceeds Fixed RAM space." 66 | } 67 | } 68 | 69 | !ifdef HEADER_A000_IN_USE { 70 | !if * > $BFFF { 71 | !warn "Program size exceeds Fixed RAM space." 72 | } 73 | } 74 | } 75 | 76 | ;================================================= 77 | ;================================================= 78 | ; 79 | ; IRQ Handling 80 | ; 81 | ;------------------------------------------------- 82 | 83 | ;================================================= 84 | ; SYS_SET_IRQ 85 | ; Set where the kernal should jump to after 86 | ; its own interrupt handling. 87 | ;------------------------------------------------- 88 | ; INPUTS: .address Label or address of IRQ handler 89 | ; 90 | ;------------------------------------------------- 91 | ; MODIFIES: A 92 | ; 93 | !macro SYS_SET_IRQ .address { 94 | lda #<.address 95 | sta $0314 96 | lda #>.address 97 | sta $0315 98 | } 99 | 100 | ;================================================= 101 | ; SYS_END_IRQ 102 | ; Restore registers and return control to 103 | ; interrupted process. 104 | ;------------------------------------------------- 105 | ; INPUTS: (none) 106 | ; 107 | ;------------------------------------------------- 108 | ; MODIFIES: A, X, Y 109 | ; 110 | !macro SYS_END_IRQ { 111 | PLA 112 | TAY 113 | PLA 114 | TAX 115 | PLA 116 | RTI 117 | } 118 | 119 | ;================================================= 120 | ;================================================= 121 | ; 122 | ; Random number generation 123 | ; 124 | ;------------------------------------------------- 125 | 126 | ;================================================= 127 | ; SYS_RAND_SEED 128 | ; Seed the PRNG implementation with the selected 129 | ; values. 130 | ;------------------------------------------------- 131 | ; INPUTS: (none) 132 | ; 133 | ;------------------------------------------------- 134 | ; MODIFIES: A 135 | ; 136 | !macro SYS_RAND_SEED .v0, .v1, .v2 { 137 | lda #.v0 138 | sta Sys_rand_mem 139 | lda #.v1 140 | sta Sys_rand_mem+1 141 | lda #.v2 142 | sta Sys_rand_mem+2 143 | } 144 | 145 | ;================================================= 146 | ;================================================= 147 | ; 148 | ; Copy macros 149 | ; 150 | ;------------------------------------------------- 151 | 152 | ;================================================= 153 | ; SYS_COPY 154 | ; Generic "copy a block of data from A to B" macro 155 | ;------------------------------------------------- 156 | ; INPUTS: .src Source address 157 | ; .dst Destination address 158 | ; .size Number of bytes to copy 159 | ; 160 | ;------------------------------------------------- 161 | ; MODIFIES: A, X, Y, $FB-$FF 162 | ; 163 | !macro SYS_COPY .src, .dst, .size { 164 | lda #<.src ;.src to $FC $FB 165 | sta $FB 166 | lda #>.src 167 | sta $FC 168 | lda #<.dst ;.dst to $FE $FD 169 | sta $FD 170 | lda #>.dst 171 | sta $FE 172 | !if .size > $FF { 173 | ; If we have at least 1 full page to copy, then include the 174 | ; page copy portion which needs a 5th byte to track the number 175 | ; of pages to copy. 176 | 177 | lda #>.size ; number of pages to copy 178 | sta $FF 179 | 180 | ldy #$00 ; reset y for our loop 181 | 182 | - lda ($FB),Y ; indirect index source memory address 183 | sta ($FD),Y ; indirect index dest memory address 184 | iny 185 | bne - ; loop until our dest goes over 255 186 | 187 | inc $FC ; increment high order source memory address 188 | inc $FE ; increment high order dest memory address 189 | 190 | dec $FF ; decrement number of pages remaining 191 | bne - ; If we still have at least 1 page to copy, go back and copy it 192 | } 193 | !if <.size > 0 { 194 | ; If we're not copying exactly some number of pages, include 195 | ; the "copy the rest of it" section 196 | ldy #0 197 | ldx #<.size 198 | 199 | - lda ($FB),Y 200 | sta ($FD),Y 201 | iny 202 | dex 203 | bne - 204 | } 205 | } 206 | 207 | ;================================================= 208 | ; SYS_STREAM_OUT 209 | ; Copy a block of data starting at a source address, 210 | ; to exactly one destination address, because it's 211 | ; memory-mapped IO that will auto-increment its own 212 | ; destination. 213 | ;------------------------------------------------- 214 | ; INPUTS: .src Source address 215 | ; .dst Destination address 216 | ; .size Number of bytes to copy 217 | ; 218 | ;------------------------------------------------- 219 | ; MODIFIES: A, X, Y, $FB-$FC, $FF 220 | ; 221 | !macro SYS_STREAM_OUT .src, .dst, .size { 222 | lda #<.src ;.src to $FC $FB 223 | sta $FB 224 | lda #>.src 225 | sta $FC 226 | 227 | !if .size > $FF { 228 | ; If we have at least 1 full page to copy, then include the 229 | ; page copy portion which needs a 5th byte to track the number 230 | ; of pages to copy. 231 | 232 | lda #>.size ; number of pages to copy 233 | sta $FF 234 | 235 | ldy #$00 ; reset y for our loop 236 | 237 | - lda ($FB),Y ; indirect index source memory address 238 | sta .dst 239 | iny 240 | bne - ; loop until our dest goes over 255 241 | 242 | inc $FC ; increment high order source memory address 243 | 244 | dec $FF ; decrement number of pages remaining 245 | bne - ; If we still have at least 1 page to copy, go back and copy it 246 | } 247 | !if <.size > 0 { 248 | ; If we're not copying exactly some number of pages, include 249 | ; the "copy the rest of it" section 250 | ldy #0 251 | ldx #<.size 252 | 253 | - lda ($FB),Y 254 | sta .dst 255 | iny 256 | dex 257 | bne - 258 | } 259 | } 260 | 261 | ;================================================= 262 | ; SYS_STREAM_IN 263 | ; Copy a block of data from exactly one source address, 264 | ; because it's memory-mapped IO that will auto-increment 265 | ; its own source, to a destination starting at some address. 266 | ;------------------------------------------------- 267 | ; INPUTS: .src Source address 268 | ; .dst Destination address 269 | ; .size Number of bytes to copy 270 | ; 271 | ;------------------------------------------------- 272 | ; MODIFIES: A, X, Y, $FD-$FF 273 | ; 274 | !macro SYS_STREAM_IN .src, .dst, .size { 275 | lda #<.dst ;.dst to $FE $FD 276 | sta $FD 277 | lda #>.dst 278 | sta $FE 279 | 280 | !if .size > $FF { 281 | ; If we have at least 1 full page to copy, then include the 282 | ; page copy portion which needs a 5th byte to track the number 283 | ; of pages to copy. 284 | 285 | lda #>.size ; number of pages to copy 286 | sta $FF 287 | 288 | ldy #$00 ; reset y for our loop 289 | .loop: 290 | lda .src 291 | sta ($FD),Y ; indirect index dest memory address 292 | iny 293 | bne .loop ; loop until our dest goes over 255 294 | 295 | inc $FE ; increment high order dest memory address 296 | 297 | dec $FF ; decrement number of pages remaining 298 | bne .loop ; If we still have at least 1 page to copy, go back and copy it 299 | } 300 | !if <.size > 0 { 301 | ; If we're not copying exactly some number of pages, include 302 | ; the "copy the rest of it" section 303 | ldy #0 304 | ldx #<.size 305 | 306 | - lda .src 307 | sta ($FD),Y 308 | iny 309 | dex 310 | bne - 311 | } 312 | } 313 | 314 | ;================================================= 315 | ; SYS_STREAM 316 | ; Copy a block of data from exactly one source address, 317 | ; because it's memory-mapped IO that will auto-increment 318 | ; its own source, to exactly one destination address, 319 | ; because it too is memory-mapped IO. 320 | ;------------------------------------------------- 321 | ; INPUTS: .src Source address 322 | ; .dst Destination address 323 | ; .size Number of bytes to copy 324 | ; 325 | ;------------------------------------------------- 326 | ; MODIFIES: A, X, Y, $FF 327 | ; 328 | !macro SYS_STREAM .src, .dst, .size { 329 | !if .size > $FF { 330 | ; If we have at least 1 full page to copy, then include the 331 | ; page copy portion which needs a 5th byte to track the number 332 | ; of pages to copy. 333 | 334 | lda #>.size ; number of pages to copy 335 | sta $FF 336 | 337 | ldy #0 ; reset y for our loop 338 | 339 | - lda .src 340 | sta .dst 341 | iny 342 | bne - ; loop until our dest goes over 255 343 | 344 | dec $FF ; decrement number of pages remaining 345 | bne - ; If we still have at least 1 page to copy, go back and copy it 346 | } 347 | !if <.size > 0 { 348 | ; If we're not copying exactly some number of pages, include 349 | ; the "copy the rest of it" section 350 | ldy #0 351 | ldx #<.size 352 | 353 | - lda .src 354 | sta .dst 355 | iny 356 | dex 357 | bne - 358 | } 359 | } -------------------------------------------------------------------------------- /basic/retro_wrestling.bas: -------------------------------------------------------------------------------- 1 | 4 REM --TERIMAKASIH J.C.--C2019-- 2 | 5 GOSUB1050:GOSUB2000 3 | 6 REM G=1WEAK GRAPPLE;G=2STRONG;U CAN ONLY BE KO'D FROM STRONG GRAPPLE MOVE 4 | 7 REMDIM P$(5,5):DIMPT$(5,5) 5 | 8 XO=19:XT=20:SG=1:MX=27:MN=12:E(1)=50:E(2)=50:K$(1)="\X1E\X12 \X92":K$(2)="\X1E\X12 \X92":PR=0 6 | 9 REM SG=1 IN RING/SG=2 OUT RING 7 | 10 PRINT"\X93":N$(1)="PLR 1":N$(2)="PLR 2" 8 | 15 ONSGGOSUB1000,1100 9 | 16 PRINT"\X13\X11\X11\X11\X11\X11\X11\X11\X11\X11\X11";:IFSG=2THENPRINT"\X11\X11\X11\X11"; 10 | 18 PRINT TAB(XO);PO$ 11 | 20 PRINT"\X13\X11\X11\X11\X11\X11\X11\X11\X11\X11\X11";:IFSG=2THENPRINT"\X11\X11\X11\X11"; 12 | 22 PRINT TAB(XT);PT$ 13 | 30 GETA$ 14 | 31 IFE(1)<50THENE(1)=E(1)+.05 15 | 32 IFE(2)<50THENE(2)=E(2)+.05 16 | 33 IFA$=""THEN30 17 | 34 IFA$="\X1D"ANDXOXTTHENXO=XO+1:GOTO15 18 | 35 IFA$="\X9D"ANDXO>MNTHENXO=XO-1:GOTO15 19 | 36 IFA$="A"ANDXT>MNANDXT-1<>XOTHENXT=XT-1:GOTO15 20 | 38 IFA$="D"ANDXT36THENK$(L)="\X1E\X12 \X92" 38 | 124 IFE(L)<37THENIFE(L)>24THENK$(L)="\X9E\X12 \X92" 39 | 126 IFE(L)<25THENIFE(L)>12THENK$(L)="\X1C\X12 \X92" 40 | 128 IFE(L)>0THENIFE(L)<13THENK$(L)="\X9A\X12 \X92" 41 | 130 IFE(L)<1THENK$(L)="\X90\X12 \X92" 42 | 140 IFG=2THENIFE(L)<1THENR=INT(RND(1)*2+1) 43 | 142 IFR=2THENPRINT"\X9A\X13\X11\X11\X11\X11\X11\X11\X11\X11\X1D\X1D\X1D\X1D\X1D\X1D\X1D\X1D\X1D\X1D";N$(L);" GOT K.O.'D":END 44 | 144 IFE(L)<1THENIFS=1THENPRINT"\X9A\X13\X11\X11\X11\X11\X11\X11\X11\X11\X1D\X1D\X1D\X1D\X1D\X1D\X1D\X1D\X1D\X1D";N$(L);" GOT K.O.'D":END 45 | 199 GOTO15 46 | 200 IFSG=2THEND$="\X11\X11\X11\X11" 47 | 201 PRINT"\X13\X11\X11\X11\X11\X11\X11\X11\X11\X11\X11";D$;TAB(XT);C$(1,2);"\X11\XBD":U=XO:PR=2:L=2 48 | 202 GETA$:IFA$=""THEN202:REM WEAK 49 | 204 IFA$="\X91"ANDXO=MX-1THENM$="\X91\X91\X91\X91\X1D\X1D"+P$(1,1):MT$=PT$(1,1):GOTO100 50 | 206 IFA$="\X91"THENM$=P$(1,1):MT$=PT$(1,1):GOTO100 51 | 208 IFA$="\X11"THENM$=P$(1,6):MT$=PT$(1,6):GOTO100 52 | 210 GOTO16 53 | 250 IFSG=2THEND$="\X11\X11\X11\X11" 54 | 251 PRINT"\X13\X11\X11\X11\X11\X11\X11\X11\X11\X11\X11";D$;TAB(XT);C$(1,2);"\X11\XBD":U=XO:PR=5:L=2 55 | 252 GETA$:IFA$=""THEN252:REM STRONG 56 | 254 REMIFA$="\X11"ANDXO=MX-1THENM$="\X91\X91\X91\X91\X1D\X1D"+P$(2,2):MT$=PT$(2,2):GOTO100 57 | 256 IFA$="\X11"THENM$=P$(1,2):MT$=PT$(1,2):GOTO100 58 | 258 IFA$="\X91"THENM$=P$(1,3):MT$=PT$(1,3):GOTO100 59 | 260 IFA$="\X1D"THENM$=P$(1,4):MT$=PT$(1,4):GOTO100 60 | 262 IFA$="\X9D"THENM$=P$(1,5):MT$=PT$(1,5):GOTO100 61 | 264 GOTO16 62 | 300 IFSG=2THEND$="\X11\X11\X11\X11" 63 | 301 PRINT"\X13\X11\X11\X11\X11\X11\X11\X11\X11\X11\X11";D$;TAB(XO);C$(2,2);"\X11\XAD":U=XT:PR=2:L=1 64 | 302 GETA$:IFA$=""THEN302:REM WEAK 65 | 304 IFA$="W"ANDXT=MN+1THENM$="\X91\X91\X91\X91\X9D\X9D"+P$(2,1):MT$=PT$(2,1):GOTO100 66 | 306 IFA$="W"THENM$=P$(2,1):MT$=PT$(2,1):GOTO100 67 | 308 IFA$="S"THENM$=P$(2,6):MT$=PT$(2,6):GOTO100 68 | 310 GOTO16 69 | 350 IFSG=2THEND$="\X11\X11\X11\X11" 70 | 351 PRINT"\X13\X11\X11\X11\X11\X11\X11\X11\X11\X11\X11";D$;TAB(XO);C$(2,2);"\X11\XAD":U=XT:PR=5:L=1 71 | 352 GETA$:IFA$=""THEN352:REM STRONG 72 | 354 IFA$="S"THENM$=P$(2,2):MT$=PT$(2,2):GOTO100 73 | 356 IFA$="W"THENM$=P$(2,3):MT$=PT$(2,3):GOTO100 74 | 358 IFA$="A"THENM$=P$(2,4):MT$=PT$(2,4):GOTO100 75 | 360 IFA$="D"THENM$=P$(2,5):MT$=PT$(2,5):GOTO100 76 | 362 GOTO16 77 | 1000 REM -DRAW RING- 78 | 1010 PRINT"\X13\X11\X11\X11"; 79 | 1012 PRINT" " 80 | 1014 PRINT" " 81 | 1016 PRINT" " 82 | 1018 PRINT" " 83 | 1020 PRINT" " 84 | 1022 PRINT" " 85 | 1024 PRINT" " 86 | 1026 PRINT" \X81\XAB\X05\XC3\XC3\XC3\XC3\XC3\XC3\XC3\XC3\XC3\XC3\XC3\XC3\XC3\XC3\XC3\XC3\X81\XB3 " 87 | 1028 PRINT" \X05\XCE\X81\XAB\X05\XC3\XC3\XC3\XC3\XC3\XC3\XC3\XC3\XC3\XC3\XC3\XC3\XC3\XC3\XC3\XC3\X81\XB3\X05\XCD " 88 | 1030 PRINT"\X9B\XAF\XAF\XAF\XAF\XAF\XAF\XAF\XAF\XAF\X05\XCE\XCE\X81\XAB\X05\XC3\XC3\XC3\XC3\XC3\XC3\XC3\XC3\XC3\XC3\XC3\XC3\XC3\XC3\XC3\XC3\X81\XB3\X05\XCD\XCD\X9B\XAF\XAF\XAF\XAF\XAF\XAF\XAF\XAF" 89 | 1032 PRINT" \X81\XAB\X05\XCE\XCE\X9B\XCE\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XCD\X05\XCD\XCD\X81\XB3 " 90 | 1034 PRINT" \X81\XAB\X05\XCE\X9B\XCE \XCD\X05\XCD\X81\XB3 " 91 | 1036 PRINT" \X81\XAB\X9B\XCE \XCD\X81\XB3 " 92 | 1038 PRINT" \X12\X9BRETRO \X92 " 93 | 1039 PRINT" \X12\X9BWRESTLING \X92\X9A " 94 | 1040 PRINTTAB(9);K$(1);" \X9A";N$(1):PRINTTAB(9);K$(2);" \X9A";N$(2) 95 | 1042 PRINT"\X9B\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7" 96 | 1044 IFEG=1THENPRINT"\X9A8-BIT GUY VS LGR!" 97 | 1046 RETURN 98 | 1050 C$(1,1)="\X9E":C$(1,2)="\X9E":C$(1,3)="\X90":C$(1,4)="\X05" 99 | 1052 C$(2,1)="\X9E":C$(2,2)="\X9E":C$(2,3)="\X90":C$(2,4)="\X05" 100 | 1054 PO$=C$(1,1)+"\XD1\X11\X9D"+C$(1,2)+"\XAB\X11\X9D"+C$(1,3)+"\XDD\X11\X9D"+C$(1,4)+"\XAD" 101 | 1056 PT$=C$(2,1)+"\XD1\X11\X9D"+C$(2,2)+"\XB3\X11\X9D"+C$(2,3)+"\XDD\X11\X9D"+C$(2,4)+"\XBD" 102 | 1058 RETURN 103 | 1100 PRINT"\X13\X11\X11\X11\X11\X11\X11\X11"; 104 | 1102 PRINT" " 105 | 1104 PRINT" " 106 | 1106 PRINT" " 107 | 1108 PRINT" \X81\XAB\X05\XC3\XC3\XC3" 108 | 1110 PRINT" \X81\XAB\X05\XCD\XC3\XC3" 109 | 1112 PRINT"\X9B\XAF\XAF\XAF\XAF\XAF\XAF\XAF\XAF\XAF\XAF\XAF\XAF\XAF\XAF\XAF\XAF\XAF\XAF\XAF\XAF\XAF\XAF\XAF\XAF\XAF\XAF\XAF\XAF\XAF\XAF\XAF\XAF\XAF\XAF\XAF\X81\XAB\X05\XCD\XCD\XC3" 110 | 1114 PRINT" \X9B\XAA\X12\XDF\X92\X05\XCD\XCD\X81\XAB" 111 | 1116 PRINT" \X95\X12\XA9 \X92\XA9\X98\XB4 \X9B\XAA\X12 \XDF\X92\X05\XCD\X81\XAB" 112 | 1118 PRINT" \X95\X12\XA9 \X92\XA9 \X98\XB4 \X9B\XDF\X12 \XDF\X92\X81\XAB" 113 | 1120 PRINT" \X98\XCF\XD0 \X9B\XDF\X12 \X92" 114 | 1122 PRINT" \X98\XB4\XAA \X9B\XDF\X12 \X92" 115 | 1124 PRINT" " 116 | 1126 PRINT" " 117 | 1128 PRINT"\X9B\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7\XB7" 118 | 1130 PRINTTAB(9);K$(1);" \X9A";N$(1):PRINTTAB(9);K$(2);" \X9A";N$(2) 119 | 1132 RETURN 120 | 2000 GOSUB3114:GOSUB3010:P$(1,1)="\X91\X91\X91"+BB$+"\X9D"+B$ 121 | 2002 GOSUB3122:GOSUB3020:PT$(1,1)="\X11\X11\X11\X9D\X9D\X9D\X9D\X9D\X9D"+BB$+"\X9D"+B$ 122 | 2004 GOSUB3010:GOSUB3122:P$(1,2)="\X9D"+BB$+"\X9D\X9D\X9D"+B$ 123 | 2006 PT$(1,2)=B$+"\X1D"+BB$ 124 | 2010 GOSUB3016:GOSUB3112:P$(2,1)="\X91\X91\X91"+B$+"\X9D"+BB$ 125 | 2012 GOSUB3122:GOSUB3020:PT$(2,1)="\X11\X11\X11\X1D\X1D\X1D"+B$+"\X9D\X9D\X9D\X9D\X9D\X9D\X9D"+BB$ 126 | 2014 GOSUB3112:GOSUB3020:P$(2,2)="\X9D\X9D"+B$+"\X9D\X9D"+BB$ 127 | 2016 PT$(2,2)="\X11\X11\X11\X9D\X9D\X9D\X9D\X9D"+B$+"\X91\X91\X91\X1D"+BB$ 128 | 2020 B$=PO$:GOSUB3116:P$(1,3)="\X91\X91\X1D"+BB$+"\X91\X9D\X9D"+B$ 129 | 2022 GOSUB3030:PT$(1,3)="\X1D"+BB$+"\X91\X91\X9D\X9D"+B$ 130 | 2024 GOSUB3012:GOSUB3124:P$(1,4)=B$+"\X91\X91\X9D"+BB$ 131 | 2026 GOSUB3036:PT$(1,4)="\X9D\X9D\X11\X11\X11"+B$+"\X11\X9D"+BB$ 132 | 2030 BB$=PT$:GOSUB3014:P$(2,3)="\X9D\X91\X91"+B$+"\X91"+BB$ 133 | 2032 GOSUB3130:PT$(2,3)="\X9D"+B$+"\X91\X91"+BB$ 134 | 2036 GOSUB3110:GOSUB3026:P$(2,4)=BB$+"\X91\X91\X9D\X9D\X9D\X9D"+B$ 135 | 2038 GOSUB3136:PT$(2,4)="\X11\X11"+BB$+"\X9D\X9D\X9D\X9D\X9D\X9D"+B$ 136 | 2040 B$=PO$:GOSUB3132:P$(1,5)=B$+"\X91\X91\X9D"+BB$ 137 | 2042 GOSUB3020:GOSUB3134:PT$(1,5)="\X11\X11\X11\X9D\X9D\X9D"+B$+"\X9D\X9D\X9D\X91\X91"+BB$ 138 | 2050 GOSUB3038:BB$=PT$:P$(1,6)=B$+"\X91\X91"+BB$ 139 | 2052 GOSUB3040:GOSUB3122:PT$(1,6)="\X11\X11\X11\X9D\X9D"+BB$+"\X91\X91\X9D\X9D"+B$ 140 | 2060 BB$=PT$:GOSUB3032:P$(2,5)=BB$+"\X91\X9D\X9D\X9D"+B$ 141 | 2062 GOSUB3122:GOSUB3034:PT$(2,5)="\X11\X11\X11"+BB$+"\X9D\X9D\X9D\X91\X91"+B$ 142 | 2070 GOSUB3138:B$=PO$:P$(2,6)="\X9D"+BB$+"\X91\X91\X9D\X9D"+B$ 143 | 2072 GOSUB3140:GOSUB3022:PT$(2,6)="\X11\X11\X11\X9D\X9D"+B$+"\X9D\X9D\X91\X91"+BB$ 144 | 2099 BB$="":B$="" 145 | 2100 RETURN 146 | 3000 REM -POSITIONS-LATEST UPDATE SINCE C64'S LATEST ONE- 147 | 3009 REM -PLR 1- 148 | 3010 B$=C$(1,1)+"\XD1\X11\X9D"+C$(1,2)+"\XAB\X11\X9D"+C$(1,3)+"\XDD\X11\X9D"+C$(1,4)+"\XAD":REM S R 149 | 3011 RETURN 150 | 3012 B$=C$(1,1)+"\XD1\X11\X9D"+C$(1,2)+"\XB3\X11\X9D"+C$(1,3)+"\XDD\X11\X9D"+C$(1,4)+"\XBD":REM S L 151 | 3013 RETURN 152 | 3014 B$=C$(1,4)+"\XB0\X11\X9D"+C$(1,3)+"\XDD\X11\X9D"+C$(1,2)+"\XAB\X11\X9D"+C$(1,1)+"\XD1":REM USD R 153 | 3015 RETURN 154 | 3016 B$=C$(1,4)+"\XAE\X11\X9D"+C$(1,3)+"\XDD\X11\X9D"+C$(1,2)+"\XB3\X11\X9D"+C$(1,1)+"\XD1":REM USD L 155 | 3017 RETURN 156 | 3019 REM -LYING DOWN- 157 | 3020 B$=C$(1,1)+"\XD1"+C$(1,2)+"\XB1"+C$(1,3)+"\XC3"+C$(1,4)+"\XBD":REM FUL 158 | 3021 RETURN 159 | 3022 B$=C$(1,4)+"\XAD"+C$(1,3)+"\XC3"+C$(1,2)+"\XB1"+C$(1,1)+"\XD1":REM FUR 160 | 3023 RETURN 161 | 3024 B$=C$(1,1)+"\XD1"+C$(1,2)+"\XB2"+C$(1,3)+"\XC3"+C$(1,4)+"\XAE":REM FDL 162 | 3025 RETURN 163 | 3026 B$=C$(1,4)+"\XB0"+C$(1,3)+"\XC3"+C$(1,2)+"\XB2"+C$(1,1)+"\XD1":REM FDR 164 | 3027 RETURN 165 | 3030 B$=C$(1,1)+"\XD1"+C$(1,2)+"\X11\X9D\XAB"+C$(1,3)+"\X11\X9D\XAD"+C$(1,4)+"\XBD":REM SR 166 | 3031 RETURN 167 | 3032 B$=C$(1,4)+"\XAD\X91\X9D"+C$(1,3)+"\XB0"+C$(1,2)+"\XB2"+C$(1,1)+"\XD1":REM RS RR 168 | 3033 RETURN 169 | 3034 B$=C$(1,4)+"\XB0"+C$(1,3)+"\XAE"+C$(1,2)+"\X11\X9D\XB3"+C$(1,1)+"\X11\X9D\XD1":REM RS RD 170 | 3035 RETURN 171 | 3036 B$=C$(1,4)+"\XAD"+C$(1,3)+"\XC3"+C$(1,2)+"\XBD"+C$(1,1)+"\X91\X9D\XD1":REM BULLDOG 172 | 3037 RETURN 173 | 3038 B$=C$(1,3)+"\XB0"+C$(1,4)+"\XBD"+C$(1,2)+"\X11\X9D\X9D\XB3"+C$(1,1)+"\X11\X9D\XD1":RETURN 174 | 3040 B$=C$(1,1)+"\XD1"+C$(1,2)+"\X11\X9D\XAB"+C$(1,3)+"\X11\X9D\XBD":RETURN 175 | 3109 REM -PLR 2- 176 | 3110 BB$=C$(2,1)+"\XD1\X11\X9D"+C$(2,2)+"\XAB\X11\X9D"+C$(2,3)+"\XDD\X11\X9D"+C$(2,4)+"\XAD":REM S R 177 | 3111 RETURN 178 | 3112 BB$=C$(2,1)+"\XD1\X11\X9D"+C$(2,2)+"\XB3\X11\X9D"+C$(2,3)+"\XDD\X11\X9D"+C$(2,4)+"\XBD":REM S L 179 | 3113 RETURN 180 | 3114 BB$=C$(2,4)+"\XB0\X11\X9D"+C$(2,3)+"\XDD\X11\X9D"+C$(2,2)+"\XAB\X11\X9D"+C$(2,1)+"\XD1":REM USD R 181 | 3115 RETURN 182 | 3116 BB$=C$(2,4)+"\XAE\X11\X9D"+C$(2,3)+"\XDD\X11\X9D"+C$(2,2)+"\XB3\X11\X9D"+C$(2,1)+"\XD1":REM USD L 183 | 3117 RETURN 184 | 3119 REM -LYING DOWN- 185 | 3120 BB$=C$(2,1)+"\XD1"+C$(2,2)+"\XB1"+C$(2,3)+"\XC3"+C$(2,4)+"\XBD":REM FUL 186 | 3121 RETURN 187 | 3122 BB$=C$(2,4)+"\XAD"+C$(2,3)+"\XC3"+C$(2,2)+"\XB1"+C$(2,1)+"\XD1":REM FUR 188 | 3123 RETURN 189 | 3124 BB$=C$(2,1)+"\XD1"+C$(2,2)+"\XB2"+C$(2,3)+"\XC3"+C$(2,4)+"\XAE":REM FDL 190 | 3125 RETURN 191 | 3126 BB$=C$(2,4)+"\XB0"+C$(2,3)+"\XC3"+C$(2,2)+"\XB2"+C$(2,1)+"\XD1":REM FDR 192 | 3127 RETURN 193 | 3130 BB$=C$(2,1)+"\XD1"+C$(2,2)+"\X11\X9D\XB3"+C$(2,4)+"\X11\X9D\X9D\XAD"+C$(2,3)+"\XBD":REM SL 194 | 3131 RETURN 195 | 3132 BB$=C$(1,1)+"\XD1"+C$(1,2)+"\XB2"+C$(1,3)+"\XAE"+C$(1,4)+"\X11\X9D\XBD":REM LS RL 196 | 3133 RETURN 197 | 3134 BB$=C$(2,3)+"\XB0"+C$(2,4)+"\XAE"+C$(2,2)+"\X11\X9D\X9D\XAB"+C$(2,1)+"\X11\X9D\XD1":REM LS RD 198 | 3135 RETURN 199 | 3136 BB$=C$(2,1)+"\XD1\X11\X9D"+C$(2,2)+"\XAD"+C$(2,3)+"\XC3"+C$(2,4)+"\XBD":REM BULLDOG 200 | 3137 RETURN 201 | 3138 BB$=C$(2,4)+"\XAD"+C$(2,3)+"\XAE"+C$(2,2)+"\X11\X9D\XAB"+C$(2,1)+"\X11\X9D\XD1":RETURN 202 | 3140 BB$=C$(2,1)+"\XD1"+C$(2,2)+"\X11\X9D\XAB"+C$(2,3)+"\X11\X9D\XBD":RETURN 203 | -------------------------------------------------------------------------------- /assembly/x16-matriculate-text/matriculate.asm: -------------------------------------------------------------------------------- 1 | !symbollist "matriculate.sym" 2 | 3 | ;================================================= 4 | ;================================================= 5 | ; 6 | ; Headers 7 | ; 8 | ;------------------------------------------------- 9 | 10 | !src "vera.inc" 11 | !src "system.inc" 12 | 13 | ;================================================= 14 | ; Macros 15 | ; 16 | ;------------------------------------------------- 17 | 18 | DEFAULT_SCREEN_ADDR = 0 19 | DEFAULT_SCREEN_SIZE = (128*64)*2 20 | 21 | ;================================================= 22 | ; MOD 23 | ; Module the accumulator by a value. 24 | ;------------------------------------------------- 25 | ; INPUTS: .v Divisor of the modulo 26 | ; 27 | ;------------------------------------------------- 28 | ; MODIFIES: A 29 | ; 30 | !macro MOD .v { 31 | - sec 32 | sbc #.v 33 | bcs - 34 | adc #.v 35 | } 36 | 37 | +SYS_HEADER_0801 38 | 39 | ;================================================= 40 | ;================================================= 41 | ; 42 | ; main code 43 | ; 44 | ;------------------------------------------------- 45 | start: 46 | +SYS_RAND_SEED $34, $56, $fe 47 | 48 | .decrement_palette: 49 | ; This is an optimistic flag: have we cleared the entire palette? 50 | ; We'll falsify if not. 51 | lda #1 52 | sta All_palettes_cleared 53 | 54 | ; Let's assume the system is starting in Mode 0 with the default palette. 55 | ; And fade out the screen because we can. 56 | +VERA_SELECT_ADDR 0 57 | +VERA_SET_PALETTE 0 58 | +VERA_SELECT_ADDR 1 59 | +VERA_SET_PALETTE 0 60 | 61 | ldy #0 ; 256 colors in the palette 62 | 63 | .decrement_palette_entry: 64 | lda VERA_data 65 | ; Don't need to decrement if already #0 (black) 66 | cmp #0 67 | beq + 68 | 69 | ; The first byte is %0000rrrr, which means we could get away just a 70 | ; decrement. But the second is %ggggbbbb, so we need to decrement 71 | ; each half if not 0. Instead of complex assembly to do that, I'm just 72 | ; going to precompute to a table and do a lookup of the next value. 73 | ; And since I did it that way for the second byte, do it the same 74 | ; way for the first as well since that answer is good for both. 75 | tax 76 | 77 | lda #0 78 | sta All_palettes_cleared 79 | 80 | lda Palette_decrement_table, X 81 | + sta VERA_data2 82 | 83 | lda VERA_data 84 | 85 | ; Still don't need to decrement 0. 86 | cmp #0 87 | beq + 88 | 89 | tax 90 | 91 | lda #0 92 | sta All_palettes_cleared 93 | 94 | lda Palette_decrement_table, X 95 | + sta VERA_data2 96 | 97 | dey 98 | bne .decrement_palette_entry 99 | 100 | +SYS_SET_IRQ inc_new_frame 101 | cli 102 | ; Tight loop until next frame 103 | - lda New_frame 104 | cmp #$01 105 | bne - 106 | 107 | sei 108 | 109 | __start__is_palette_fade_done: 110 | lda #0 111 | sta New_frame 112 | 113 | lda All_palettes_cleared 114 | cmp #0 115 | beq .decrement_palette 116 | 117 | ; 118 | ; Palette memory should now be all 0s, or a black screen. 119 | ; If only the composer gave us a brightness setting, I could 120 | ; have used that. Mei banfa. 121 | ; 122 | 123 | +VERA_SELECT_ADDR 0 124 | 125 | +VERA_SET_ADDR VRAM_layer1 126 | +VERA_WRITE ($01 << 5) | $01 ; Mode 1 (256-color text), enabled 127 | +VERA_WRITE %00000110 ; 8x8 tiles, 128x64 map 128 | +VERA_WRITE <(DEFAULT_SCREEN_ADDR >> 2) ; Map indices at VRAM address 0 129 | +VERA_WRITE >(DEFAULT_SCREEN_ADDR >> 2) ; 130 | +VERA_WRITE <(VROM_petscii >> 2) ; Tile data immediately after map indices 131 | +VERA_WRITE >(VROM_petscii >> 2) ; Tile data immediately after map indices 132 | +VERA_WRITE 0, 0, 0, 0 ; Hscroll and VScroll to 0 133 | 134 | !zn __start__fill_text_buffer_with_random_chars { 135 | __start__fill_text_buffer_with_random_chars: 136 | +VERA_SET_ADDR DEFAULT_SCREEN_ADDR, 2 137 | 138 | ldx #128 139 | ldy #64 140 | 141 | .yloop: 142 | tya 143 | pha 144 | .xloop: 145 | txa 146 | 147 | jsr sys_rand 148 | and #$7F 149 | tay 150 | 151 | lda Petscii_table,Y 152 | sta VERA_data 153 | 154 | tax 155 | dex 156 | bne .xloop 157 | 158 | pla 159 | tay 160 | dey 161 | bne .yloop 162 | } 163 | 164 | !zn __start__offset_palette_of_each_column { 165 | __start__offset_palette_of_each_column: 166 | +VERA_SET_ADDR DEFAULT_SCREEN_ADDR+1, 2 167 | 168 | lda #128 169 | 170 | .xloop: 171 | pha 172 | 173 | jsr sys_rand 174 | ; If we're about to assign palette index 0 (background), increment to 1 175 | cmp #0 176 | beq + 177 | clc 178 | adc #1 179 | + sta VERA_data 180 | 181 | pla 182 | sec 183 | sbc #1 184 | bne .xloop 185 | } 186 | 187 | !zn __start__fill_palette_of_remaining_chars { 188 | __start__fill_palette_of_remaining_chars: 189 | +VERA_SET_ADDR DEFAULT_SCREEN_ADDR+1, 2 190 | +VERA_SELECT_ADDR 1 191 | +VERA_SET_ADDR DEFAULT_SCREEN_ADDR+257, 2 192 | +VERA_SELECT_ADDR 0 193 | 194 | ldx #127 195 | ldy #64 196 | 197 | .yloop: 198 | tya 199 | pha 200 | .xloop: 201 | txa 202 | pha 203 | 204 | lda VERA_data 205 | clc 206 | adc #1 207 | ; If we're about to assign palette index 0 (background), increment to 1 208 | cmp #0 209 | bne + 210 | clc 211 | adc #1 212 | + sta VERA_data2 213 | 214 | pla 215 | tax 216 | dex 217 | bne .xloop 218 | 219 | pla 220 | tay 221 | dey 222 | bne .yloop 223 | } 224 | 225 | +SYS_SET_IRQ irq_handler 226 | cli 227 | 228 | jmp * 229 | 230 | ; +VERA_RESET 231 | 232 | ;================================================= 233 | ;================================================= 234 | ; 235 | ; IRQ Handlers 236 | ; 237 | ;------------------------------------------------- 238 | 239 | ;================================================= 240 | ; irq_handler 241 | ; This is essentially my "do_frame". Several others have been doing this as well. 242 | ; Since the IRQ is triggered at the beginning of the VGA/NTSA front porch, we don't 243 | ; get the benefit of the entire VBLANK, but it's still useful as a "do this code 244 | ; once per frame" function. 245 | ;------------------------------------------------- 246 | ; INPUTS: (none) 247 | ; 248 | ;------------------------------------------------- 249 | ; MODIFIES: A, X, Y, VRAM_palette 250 | ; 251 | irq_handler: 252 | ; Increment which palette index we're starting at 253 | lda Palette_cycle_index 254 | clc 255 | adc #1 256 | ; Skip index zero, that's the background, we want to leave it black. 257 | adc #0 258 | sta Palette_cycle_index 259 | 260 | ; 261 | ; Palette cycle for the letters glowing and stuff 262 | ; 263 | 264 | ; Set the starting address of the VRAM palette we're going to cycle 265 | asl ; Palette_cycle_index * 2 == Address offset into palette memory 266 | ; adc #<(VRAM_palette) ; We happen to know that #<(VRAM_palette) is 0. Being able to skip this also preserves Carry in case it was set 267 | sta VERA_addr_low 268 | lda #<(VRAM_palette >> 8) 269 | adc #0 ; Add carry bit for indices 128-255 270 | sta VERA_addr_high 271 | lda #<(VRAM_palette >> 16) | (1 << 4) 272 | sta VERA_addr_bank 273 | 274 | lda #Matrix_palette 277 | sta $FC 278 | 279 | NUM_MATRIX_PALETTE_ENTRIES = ((Matrix_palette_end - Matrix_palette) >> 1) 280 | 281 | ldx Palette_cycle_index 282 | ldy #0 283 | 284 | - lda ($FB),Y 285 | sta VERA_data 286 | iny 287 | lda ($FB),Y 288 | sta VERA_data 289 | iny 290 | inx 291 | bne + 292 | +VERA_SET_PALETTE 0, 1 293 | + cpy #(Matrix_palette_end - Matrix_palette) 294 | bne - 295 | 296 | ; 297 | ; Palette cycle (redux) for double-density! 298 | ; 299 | lda Palette_cycle_index 300 | adc #127 301 | clc 302 | 303 | ; Set the starting address of the VRAM palette we're going to cycle 304 | asl ; Palette_cycle_index * 2 == Address offset into palette memory 305 | ; adc #<(VRAM_palette) ; We happen to know that #<(VRAM_palette) is 0. Being able to skip this also preserves Carry in case it was set 306 | sta VERA_addr_low 307 | lda #<(VRAM_palette >> 8) 308 | adc #0 ; Add carry bit for indices 128-255 309 | sta VERA_addr_high 310 | lda #<(VRAM_palette >> 16) | (1 << 4) 311 | sta VERA_addr_bank 312 | 313 | lda #Matrix_palette 316 | sta $FC 317 | 318 | NUM_MATRIX_PALETTE_ENTRIES = ((Matrix_palette_end - Matrix_palette) >> 1) 319 | 320 | lda Palette_cycle_index 321 | adc #128 ; "But you did `adc #127` above." Yes, and it created a sneaky off-by-one bug. So this is a sneaky off-by-one fix. 322 | clc 323 | tax 324 | ldy #0 325 | 326 | - lda ($FB),Y 327 | sta VERA_data 328 | iny 329 | lda ($FB),Y 330 | sta VERA_data 331 | iny 332 | inx 333 | bne + 334 | +VERA_SET_PALETTE 0, 1 335 | + cpy #(Matrix_palette_end - Matrix_palette) 336 | bne - 337 | +VERA_END_IRQ 338 | +SYS_END_IRQ 339 | 340 | ;================================================= 341 | ; inc_new_frame 342 | ; This is essentially my "do_frame". Several others have been doing this as well. 343 | ; Since the IRQ is triggered at the beginning of the VGA/NTSA front porch, we don't 344 | ; get the benefit of the entire VBLANK, but it's still useful as a "do this code 345 | ; once per frame" function. 346 | ;------------------------------------------------- 347 | ; INPUTS: Sys_rand_mem 348 | ; 349 | ;------------------------------------------------- 350 | ; MODIFIES: A, X, Sys_rand_mem 351 | ; 352 | inc_new_frame: 353 | inc New_frame 354 | +VERA_END_IRQ 355 | +SYS_END_IRQ 356 | 357 | ;================================================= 358 | ;================================================= 359 | ; 360 | ; Miscellaneous data copying 361 | ; 362 | ;------------------------------------------------- 363 | ; 364 | ; I wasn't sure what to do with this. I already have 365 | ; SYS_STREAM_OUT, but I basically needed it for 366 | ; a source address and quantity of data that can 367 | ; only be determined at run-time. I'm I'll eventually 368 | ; convert this into some kind of other 369 | ; SYS_STREAM_OUT-like macro, so that I can 370 | ; easily declare function definitions for a variety 371 | ; of fixed destinations, and then come back and do 372 | ; the same for fixed sources with runtime destinations 373 | ; and of course a function to just handle everything 374 | ; being runtime data. 375 | ; 376 | 377 | ;============================================== 378 | ; VERA_stream_out_data 379 | ; Stream out a block of memory to VERA_data 380 | ;---------------------------------------------- 381 | ; INPUT: X - number of pages to stream 382 | ; Y - number of bytes to stream 383 | ; $FB - low byte of starting address 384 | ; $FC - high byte of starting address 385 | ;---------------------------------------------- 386 | ; Modifies: A, X, Y, $FC 387 | ; 388 | VERA_stream_out_data: 389 | tya 390 | pha 391 | ; If no pages to copy, skip to bytes 392 | txa 393 | cmp #0 394 | tax 395 | beq .no_blocks 396 | 397 | ; Copy X pages to VERA_data 398 | ldy #0 399 | .loop: 400 | lda ($FB),Y 401 | sta VERA_data 402 | iny 403 | bne .loop 404 | 405 | inc $FC 406 | dex 407 | bne .loop 408 | 409 | .no_blocks: 410 | ; Copy X bytes to VERA_data 411 | pla 412 | tax 413 | ldy #0 414 | .loop2: 415 | lda ($FB),Y 416 | sta VERA_data 417 | iny 418 | dex 419 | bne .loop2 420 | rts 421 | 422 | ;================================================= 423 | ;================================================= 424 | ; 425 | ; Libs 426 | ; 427 | ;------------------------------------------------- 428 | !src "system.asm" 429 | 430 | ;================================================= 431 | ;================================================= 432 | ; 433 | ; Data 434 | ; 435 | ;------------------------------------------------- 436 | Petscii_table: 437 | !for i,1,$60 { 438 | !byte i 439 | } 440 | !for i,0,$20 { 441 | !byte i+$A0 442 | } 443 | 444 | Matrix_palette: 445 | !le16 $0000, $0000, $0020, $0020, $0030, $0030, $0040, $0040 446 | !le16 $0050, $0050, $0060, $0060, $0070, $0070, $0080, $0080 447 | !le16 $0090, $0090, $00A0, $00A0, $00B0, $00B0, $00C0, $00C0 448 | !le16 $00D0, $00D0, $00E0, $00E0, $00F0, $00F0, $08FC 449 | Matrix_palette_end: 450 | Matrix_palette_rev: 451 | !le16 $0000, $0000, $08FC, $00F0, $00F0, $00E0, $00E0, $00D0 452 | !le16 $00D0, $00C0, $00C0, $00B0, $00B0, $00A0, $00A0, $0090 453 | !le16 $0090, $0080, $0080, $0070, $0070, $0060, $0060, $0050 454 | !le16 $0050, $0040, $0040, $0030, $0030, $0020, $0020 455 | Matrix_palette_rev_end: 456 | 457 | Palette_decrement_table: 458 | ; $X0, $X1, $X2, $X3, $X4, $X5, $X6, $X7, $X8, $X9, $XA, $XB, $XC, $XD, $XE, $XF 459 | !byte $00, $00, $01, $02, $03, $04, $05, $06, $07, $08, $09, $0A, $0B, $0C, $0D, $0E ; $0X 460 | !byte $00, $00, $01, $02, $03, $04, $05, $06, $07, $08, $09, $0A, $0B, $0C, $0D, $0E ; $1X 461 | !byte $10, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $1A, $1B, $1C, $1D, $1E ; $2X 462 | !byte $20, $20, $21, $22, $23, $24, $25, $26, $27, $28, $29, $2A, $2B, $2C, $2D, $2E ; $3X 463 | !byte $30, $30, $31, $32, $33, $34, $35, $36, $37, $38, $39, $3A, $3B, $3C, $3D, $3E ; $4X 464 | !byte $40, $40, $41, $42, $43, $44, $45, $46, $47, $48, $49, $4A, $4B, $4C, $4D, $4E ; $5X 465 | !byte $50, $50, $51, $52, $53, $54, $55, $56, $57, $58, $59, $5A, $5B, $5C, $5D, $5E ; $6X 466 | !byte $60, $60, $61, $62, $63, $64, $65, $66, $67, $68, $69, $6A, $6B, $6C, $6D, $6E ; $7X 467 | !byte $70, $70, $71, $72, $73, $74, $75, $76, $77, $78, $79, $7A, $7B, $7C, $7D, $7E ; $8X 468 | !byte $80, $80, $81, $82, $83, $84, $85, $86, $87, $88, $89, $8A, $8B, $8C, $8D, $8E ; $9X 469 | !byte $90, $90, $91, $92, $93, $94, $95, $96, $97, $98, $99, $9A, $9B, $9C, $9D, $9E ; $AX 470 | !byte $A0, $A0, $A1, $A2, $A3, $A4, $A5, $A6, $A7, $A8, $A9, $AA, $AB, $AC, $AD, $AE ; $BX 471 | !byte $B0, $B0, $B1, $B2, $B3, $B4, $B5, $B6, $B7, $B8, $B9, $BA, $BB, $BC, $BD, $BE ; $CX 472 | !byte $C0, $C0, $C1, $C2, $C3, $C4, $C5, $C6, $C7, $C8, $C9, $CA, $CB, $CC, $CD, $CE ; $DX 473 | !byte $D0, $D0, $D1, $D2, $D3, $D4, $D5, $D6, $D7, $D8, $D9, $DA, $DB, $DC, $DD, $DE ; $EX 474 | !byte $E0, $E0, $E1, $E2, $E3, $E4, $E5, $E6, $E7, $E8, $E9, $EA, $EB, $EC, $ED, $EE ; $FX 475 | 476 | ;================================================= 477 | ;================================================= 478 | ; 479 | ; Variables 480 | ; 481 | ;------------------------------------------------- 482 | !src "matriculate_vars.asm" 483 | !src "system_vars.asm" 484 | 485 | +SYS_FOOTER --------------------------------------------------------------------------------