Hmmmm if this expands it would make a nice wiki article... Want me to make this a sticky topic?yes.
setbank:
ld (BuffBank),a
and &3f
or &c0
ld b,&7f
out (c),a
ret
BuffBank: defb 0
;; CALL loadbank,<filename>,<address>,<bank>
;; e.g. a$="filename":call @a$, &4000,&c4
loadbank:
;; load address
ld l,(ix+2)
ld h,(ix+3)
push hl
;; string descriptor (note this is in main ram, so we can't change bank until
;; we have read the value. In addition cas in open needs to see it too. So either
;; copy filename to a buffer, or change bank when we read data.
;; Note, the buffer for AMSDOS or tape, needs to be above &8000. Normally for disc it is around &a700, and for tape a bit higher.
ld l,(ix+4)
ld h,(ix+5)
;; length
ld b,(hl)
inc hl
;; address of chars in string
ld a,(hl)
inc hl
ld h,(hl)
ld l,a
;; address of string
ld a,(ix+0)
push af
;; this 2k buffer needs to be outside of &4000-&7fff. With binary it can be any value because the buffer is not used.
ld de,&c000
call cas_in_open
pop af
call setbank
pop hl
call cas_in_direct
call cas_in_close
;; restore back for basic
ld a,&c0
call setbank
;; return to basic
ret
org &4000
ld a,8
call &bb1e
jr nz,left
ld a,1
call &bb1e
jr nz,right
ld a,0
call &bb1e
jr nz,jump
ld hl,value
ld a,255
ld (hl),a
ret
.left
ld hl,value
ld a,8
ld (hl),a
ret
.right
ld hl,value
ld a,1
ld (hl),a
ret
.jump
ld hl,value
ld a,0
ld (hl),a
ret
.value
defb 0
10 MODE 1: BORDER 0:INK 1,26:x=20:y=13
11 WHILE 1
20 a$=INKEY$:oldx=x:oldy=y
30 IF a$=CHR$(242) AND x>1 THEN x=x-1
40 IF a$=CHR$(243) AND x<40 THEN x=x+1
41 IF a$=CHR$(240) AND y>1 THEN y=y-1
42 IF a$=CHR$(241) AND y<25 THEN y=y+1
50 LOCATE oldx,oldy:PRINT" ";:LOCATE x,y:PRINT CHR$(248);
60 WEND
1000 MODE 1:BORDER 0:INK 1,26:x=20:y=13
1010 WHILE 1:CALL &4000:oldx=x:oldy=y
1020 IF PEEK(&403F)=8 AND x>1 THEN x=x-1
1030 IF PEEK(&403F)=1 AND x<40 THEN x=x+1
1040 IF PEEK(&403F)=0 AND y>1 THEN y=y-1
1050 IF PEEK(&403F)=2 AND y<25 THEN y=y+1
1060 LOCATE oldx,oldy:PRINT" ";:LOCATE x,y:PRINT CHR$(248);
1070 WEND
org &4000
ld a,8
call &bb1e
jr nz,left
ld a,1
call &bb1e
jr nz,right
ld a,0
call &bb1e
jr nz,up
ld a,2
call &bb1e
jr nz,down
ld hl,value
ld a,255
ld (hl),a
ret
.left
ld hl,value
ld a,8
ld (hl),a
ret
.right
ld hl,value
ld a,1
ld (hl),a
ret
.up
ld hl,value
ld a,0
ld (hl),a
ret
.down
ld hl,value
ld a,2
ld (hl),a
ret
.value
defb 0
1 ' Serpent
2 ' by T Magee
3 ' Amstrad Action June 87
10 MODE 1
20 ORIGIN 320,200
30 GOSUB 60:a=a-2
40 IF a>-0.1 THEN GOSUB 60
50 a=a+2.1:GOTO 30
60 MOVE 220*SIN(a/2),98*COS(a),,1
70 DRAW 200*COS(a/2),198*SIN(a)
80 RETURN
1 ' Serpent
2 ' by T Magee
3 ' Amstrad Action June 87
10 MODE 1
20 ORIGIN 320,200
30 GOSUB 60:a=a-2
40 IF a>-0.1 THEN GOSUB 90
50 a=a+2.1:GOTO 30
60 MOVE 220*SIN(a/2),98*COS(a)
70 DRAW 200*COS(a/2),198*SIN(a),1
80 RETURN
90 MOVE 220*SIN(a/2),98*COS(a)
100 DRAW 200*COS(a/2),198*SIN(a),0
110 RETURN
1 ' Serpent
2 ' by T Magee
3 ' Amstrad Action June 87
10 MODE 1
20 ORIGIN 320,200:PRINT CHR$(23);CHR$(1);
30 GOSUB 60:a=a-2
40 IF a>-0.1 THEN GOSUB 60
50 a=a+2.1:GOTO 30
60 MOVE 220*SIN(a/2),98*COS(a)
70 DRAW 200*COS(a/2),198*SIN(a)
80 RETURN
1 ' Cursor
2 ' by David Ware
10 SYMBOL 255,128,192,224,240,224,32,16,16
20 tag:x=0:y=0
30 MOVE x,y,2,1:PRINT CHR$(255);
40 FRAME:MOVE x,y,2,1:PRINT CHR$(255);
50 a$=INKEY$
60 IF INKEY(0)=0 THEN y=y+6:GOTO 120
70 IF INKEY(2)=0 THEN y=y-6:GOTO 120
80 IF INKEY(8)=0 THEN x=x-6:GOTO 120
90 IF INKEY(1)=0 THEN x=x+6:GOTO 120
100 MOVE x,y,2,1:PRINT CHR$(255);
110 GOTO 40
120 FRAME:MOVE x,y,2,1:PRINT CHR$(255);
130 GOTO 40
1 ' Cursor
2 ' by David Ware
10 SYMBOL 255,128,192,224,240,224,32,16,16
20 x=322:y=232:PLOT -2,-2,2
30 MOVE x,y:PRINT CHR$(23);CHR$(1);:TAG:PRINT CHR$(255);:TAGOFF
40 CALL &BD19:MOVE x,y:PRINT CHR$(23);CHR$(1);:TAG:PRINT CHR$(255);:TAGOFF
50 a$=INKEY$
60 IF INKEY(0)=0 THEN y=y+6:GOTO 120
70 IF INKEY(2)=0 THEN y=y-6:GOTO 120
80 IF INKEY(8)=0 THEN x=x-6:GOTO 120
90 IF INKEY(1)=0 THEN x=x+6:GOTO 120
100 MOVE x,y:PRINT CHR$(23);CHR$(1);:TAG:PRINT CHR$(255);:TAGOFF
110 GOTO 40
120 CALL &BD19:MOVE x,y:PRINT CHR$(23);CHR$(1);:TAG:PRINT CHR$(255);:TAGOFF
130 GOTO 40
MOVE x,y,2,1
PLOT -2,-2,2
PRINT CHR$(23);CHR$(1);
100 MOVE x,y:LOCATE 1,1:PRINT CHR$(23);CHR$(1):TAG:PRINT CHR$(255);:TAGOFF
You should change line 100 to this:Code: [Select]100 MOVE x,y:LOCATE 1,1:PRINT CHR$(23);CHR$(1):TAG:PRINT CHR$(255);:TAGOFF
Otherwise you will see your screen move up after a (longer) while...
Sure you didn't see the screen wandering up, because the ; @ end of PRINT.
In MODE 1 you have 40x25 chars (=1000) first before the screen moves up. (Long time for testing it, you need more than 999 keystrokes until it takes effect, but it will take effect)
100 MOVE x,y:PRINT CHR$(143);CHR$(23);CHR$(1);:TAG:PRINT CHR$(255);:TAGOFF
1 ' Cursor
2 ' by David Ware
10 SYMBOL 255,128,192,224,240,224,32,16,16
20 x=322:y=232:PLOT -2,-2,2
30 MOVE x,y:PRINT CHR$(23);CHR$(1);:TAG:PRINT CHR$(255);
40 CALL &BD19:MOVE x,y:PRINT CHR$(255);
50 a$=INKEY$
60 IF INKEY(0)=0 THEN y=y+6:GOTO 120
70 IF INKEY(2)=0 THEN y=y-6:GOTO 120
80 IF INKEY(8)=0 THEN x=x-6:GOTO 120
90 IF INKEY(1)=0 THEN x=x+6:GOTO 120
100 MOVE x,y:PRINT CHR$(255);
110 GOTO 40
120 CALL &BD19:MOVE x,y:PRINT CHR$(255);
130 GOTO 40
50 a$=INKEY$
Tested and optimized:Code: [Select]1 ' Cursor
2 ' by David Ware
10 SYMBOL 255,128,192,224,240,224,32,16,16
20 x=322:y=232:PLOT -2,-2,2
30 MOVE x,y:PRINT CHR$(23);CHR$(1);:TAG:PRINT CHR$(255);
40 CALL &BD19:MOVE x,y:PRINT CHR$(255);
50 a$=INKEY$
60 IF INKEY(0)=0 THEN y=y+6:GOTO 120
70 IF INKEY(2)=0 THEN y=y-6:GOTO 120
80 IF INKEY(8)=0 THEN x=x-6:GOTO 120
90 IF INKEY(1)=0 THEN x=x+6:GOTO 120
100 MOVE x,y:PRINT CHR$(255);
110 GOTO 40
120 CALL &BD19:MOVE x,y:PRINT CHR$(255);
130 GOTO 40
1 ' Cursor
2 ' by David Ware
10 SYMBOL 255,128,192,224,240,224,32,16,16
20 x=322:y=232:PLOT -2,-2,2
30 MOVE x,y:PRINT CHR$(23);CHR$(1);:TAG:PRINT CHR$(255);
40 CALL &BD19:MOVE x,y:PRINT CHR$(255);
50 IF INKEY(0)=0 THEN y=y+6:p=1:IF y>398 THEN y=398
60 IF INKEY(2)=0 THEN y=y-6:p=1:IF y<16 THEN y=16
70 IF INKEY(8)=0 THEN x=x-6:p=1:IF x<0 THEN x=0
80 IF INKEY(1)=0 THEN x=x+6:p=1:IF x>630 THEN x=630
90 IF p=1 THEN p=0:GOTO 120
100 MOVE x,y:PRINT CHR$(255);
110 GOTO 40
120 CALL &BD19:MOVE x,y:PRINT CHR$(255);
130 GOTO 40
myhighbyte = myvar / 256 : highbyte = FIX ( myhighbyte )
lowbyte = myvar MOD 256
myhighbyte = myvar \ 256 : lowbyte = myvar AND 255
try that.
Thanks.
Still getting overflow when myvar = 33924.
Does it only work within signed limited (i.e. -32768 to 32768)...?
Thanks.a% will be signed
Still getting overflow when myvar = 33924.
Does it only work within signed limited (i.e. -32768 to 32768)...?
a% will be signed
a will end up being floating point
c=&aaaa actually ends up being unsigned 16-bit.
I've got one for all of you BASIC aficionados...
I have a 16-bit number in myvar (i.e. from range 0 - 65535). I want to convert it to high byte & low byte.
alter=VAL("&"+HEX$(myvar))
If you have a number from range 0 - 65535 then it's necessary to convert to 16 bit number (-32768 - 32767)See UNT (http://www.cpcwiki.eu/index.php/Locomotive_BASIC#UNT_.28add.29), which uses the Firmware Math function INTEGER TO REAL (No need to reinvent the wheel :)Code: [Select]alter=VAL("&"+HEX$(myvar))
alter=UNT(myvar)
I'm not sure however that a BASIC keyword exists to do the other way around (eg. based on the Firmware Math function REAL TO INTEGER).myvar = 33924
hi = int(myvar / 256)
lo = myvar - 256*hi
It should work whatever type myvar is.See UNT (http://www.cpcwiki.eu/index.php/Locomotive_BASIC#UNT_.28add.29), which uses the Firmware Math function INTEGER TO REAL (No need to reinvent the wheel :)Oh! well, I didn't know that command :o Thanks :)Code: [Select]alter=UNT(myvar)
One way to avoid all that mess with variable type:Code: [Select]myvar = 33924
It should work whatever type myvar is.
hi = int(myvar / 256)
lo = myvar - 256*hi
myvar = 33924
hi = int(myvar / 256)
lo = unt(myvar) and 255
Indeed! It's better that way! (smaller, faster and still works with any numeric type)Code: [Select]myvar = 33924
is 2 bytes less, and it's a little faster, isn't it?
hi = int(myvar / 256)
lo = unt(myvar) and 255
See UNT (http://www.cpcwiki.eu/index.php/Locomotive_BASIC#UNT_.28add.29), which uses the Firmware Math function INTEGER TO REAL (No need to reinvent the wheel :)Code: [Select]alter=UNT(myvar)
I'm not sure however that a BASIC keyword exists to do the other way around (eg. based on the Firmware Math function REAL TO INTEGER).
Code: [Select]myvar = 33924
hi = int(myvar / 256)
lo = unt(myvar) and 255
hi and lo here are still reals, using 5 bytes and being slightly slower. I'd definitely rather use hi% and lo%, or DEFINT h,l :-)
Sadly I can't confirm this because there is no \ key in CPCBox.
Wouldn't you just co-erce the result of FIX, INT or ROUND into an integer type? i.e., a%=ROUND(3.14,0) would give an signed integer with a value of 3.Nay. ROUND, FIX, CINT, INT & co are real-to-real functions, they expect a real (ie. 40-bit float) as input (and will convert the input automagically if necessary) and output a real. So ROUND(33000) is exactly the same as writing 33000 directly, both result with the same real number. So when trying to fit that real number into a signed integer variable (a%), if the real is beyond the signed integer range (-32768 to 32767), the conversion will overflow (eg a%=33000).
It is practically impossible to teach good programming to students that have had a prior exposure to BASIC: as potential programmers they are mentally mutilated beyond hope of regeneration.
Nay. ROUND, FIX, CINT, INT & co are real-to-real functions, they expect a real (ie. 40-bit float) as input (and will convert the input automagically if necessary) and output a real. So ROUND(33000) is exactly the same as writing 33000 directly, both result with the same real number. So when trying to fit that real number into a signed integer variable (a%), if the real is beyond the signed integer range (-32768 to 32767), the conversion will overflow (eg a%=33000).
The issue Redbox had was that he was trying to apply 16-bit signed integer operations (such as MOD or AND like in myvar MOD 256) to unsigned 16-bit values stored as real number (For real! Aye! Ye're still there floating with me? :)
490 FOR A=1 TO 5:SOUND 1,220,4:SOUND 1,90,4:NEXT A:LOCATE X+1,20:CALL 360:K= PEEK(367):IF K=32 THEN 510
490 FOR A=1 TO 5:SOUND 1,220,4:SOUND 1,90,4:NEXT A:LOCATE X+1,20:CALL 360:K= PEEK(367):IF (X>12 AND X<21) AND K=32 THEN 510
10 REM DAMBUSTERS
20 REM @ PAUL STANLEY.
30 MODE 1:BORDER 4:INK 0,16:INK 1,0:INK 2,20:INK 3,6:WINDOW #1,1,40,1,25:PAPER #1, 0:PEN #1,1:CLS
40 HS=0
50 GOSUB 960
60 GOSUB 770
70 GOSUB 620
80 BORDER 1:INK 0,0:INK 1,24:INK 2,20:INK 3,6:WINDOW #0,5,36,1,25:PAPER #0, 0:PEN #0,1:CLS #0
90 PEN 2:LOCATE 1,1:PRINT"SCORE:0":PEN 1
100 PEN 3:LOCATE 19,1:PRINT"HI-SCORE:";:PEN 2:PRINT HS:PEN 1
110 LOCATE 1,22:PRINT CHR$(24); STRING$(64,58);CHR$(24)
120 FOR F=1 TO 150 :PLOT 64+RND*506,RND*400+128,2:NEXT
130 G=0:FOR F=1 TO 5:PLOT G*2+64,15+F*2+48,2:DRAWR 508-4*G,0:G=G+2:NEXT
140 PLOT 100,72,2:DRAWR 216,40:PLOT 532,72:DRAWR -216,40
150 PLOT 64,64,3:DRAWR 0,32:DRAWR 8,0:DRAWR 16,16:DRAWR 4,- 4:DRAWR -16,-16:DRAWR 0,-20
160 PLOT 572,64,3:DRAWR 0,32:DRAWR -8,0:DRAWR -16,16:DRAWR -4,-4:DRAWR 16,-16:DRAWR 0,-20
170 D=1:S=0:A=1:P=17
180 Y=9
190 X=INT(RND*20)+6
200 PRINT CHR$(22);CHR$(1);:FOR F=1 TO 5 STEP 2:PEN 1:LOCATE X+1,6:PRINT MID$(B$,F,1);MID$(B$,F+1,1);:SOUND 1,120,4:PEN 0:LOCATE X+1,6:PRINT MID$(B$,F,1);MID$(B$,(F+1),1);:NEXT F
210 FOR F= 1 TO 4:PEN 1:LOCATE X+1,6-F:PRINT MID$(B$,5,1);MID$(B$,6,1):LOCATE X+1,6+F:PRINT CHR$(232);
220 SOUND 1,180,4:PEN 0:LOCATE X+1,6-F:PRINT MID$(B$,5,1);MID$(B$,6,1);: LOCATE X+1,6+F:PRINT CHR$(232);:NEXT F:PEN 1:PRINT CHR$(22);CHR$(0);
230 F=INT(RND*25)+3:G=5+INT(RND*11)
240 A$=CHR$(231)+CHR$(232)+CHR$(233)+CHR$(234)+CHR$(235)+CHR$(235)+CHR$(236):HT=10
250 PEN 1: LOCATE X+1,Y+1:PRINT CHR$(22);CHR$(1);MID$(A$,A,1);CHR$(22);CHR$(0);
260 F=F-(INKEY(1)=0 AND F<29)+(INKEY(8)=0 AND F>2):G=G-(INKEY(2)=0 AND G<17)+(INKEY(0)=0 AND G>3)
270 PEN 2:LOCATE F+1,G+1:PRINT CHR$(22);CHR$(1);"+";CHR$(22);CHR$(0);:PEN 1
280 LOSS=LOSS+LEEK
290 IF LOSS>1000 THEN 550
300 IF INKEY (47)=0 THEN IF S<10 THEN GOSUB 430
310 SOUND 1,100,4
320 PEN 0: LOCATE X+1,Y+1:PRINT CHR$(22);CHR$(1);MID$(A$,A,1);CHR$(22);CHR$(0);
330 PEN 0: LOCATE F+1,G+1:PRINT CHR$(22);CHR$(1);"+";CHR$(22);CHR$(0);:PEN 1
340 PLOT 100,72,2:DRAWR 216,40:PLOT 532,72:DRAWR -216,40
350 Y=Y+D
360 IF RND>0.6 THEN F=F+INT(RND*1.5)-INT(RND*1.5)
370 IF F<0 THEN F=0
380 IF RND<0.4 THEN G=G+INT(RND*1.5 AND G<18)-INT(RND*1.5)
390 IF Y=HT THEN P=P+1:D=1:A=A+1
400 IF Y=P THEN SOUND 1,180,4:A=A+1:D=-1:HT=HT-3
410 IF A=7 THEN 490
420 GOTO 250
430 PLOT 90,112,2:DRAW (F+1)*16+54,(24-G)*16+8,2:PLOT 546,110,2:DRAW (F+1)*16+54,(24-G)*16+8,2
440 S=S+1
450 PLOT 90,112,0:DRAW (F+1)*16+54,(24-G)*16+8,0:PLOT 546,110,0:DRAW (F+1)*16+54,(24-G)*16+8,0
460 IF G=Y THEN IF X=F THEN 480
470 RETURN
480 SC=SC+10: LOCATE 7,1:PRINT SC;:LOCATE F+1,G+1:PRINT CHR$(238);:SOUND 1,180,4:SOUND 1,120,4:SOUND 1,90,4:SOUND 1,50,4:LOCATE F+1,G+1:PRINT" ";: GOTO 170
490 FOR A=1 TO 5:SOUND 1,220,4:SOUND 1,90,4:NEXT A:LOCATE X+1,20:CALL 360:K= PEEK(367):IF (X>12 AND X<21) AND K=32 THEN 510
500 LOCATE X+1,20:PRINT" ";:GOTO 170
510 LOCATE X+1,21:CALL 360:K=PEEK(367):IF K<>58 THEN 540
520 LEEK=LEEK +1
530 LOCATE X+1,21:PRINT" ";:LOCATE X+1,22:PRINT CHR$(237);:GOTO 170
540 LET LEEK = LEEK +2:LOCATE X,20:PRINT" ";:LOCATE X,21:PRINT" ";:LOCATE X,22:PRINT CHR$(237);CHR$(237);CHR$(237);:GOTO 170
550 LOCATE 6,11:PRINT"- G A M E O V E R -":LOCATE 3,14:PRINT"PRESS ANY KEY TO PLAY AGAIN": FOR F= 1 TO 20:SOUND 1,(F+100),4:NEXT
560 IF SC>HS THEN HS=SC
570 LOSS=0:SC=0:LEEK=0
580 IF INKEY$<>"" THEN 580
590 IF INKEY$ = "" THEN 590
600 CLS: RESTORE: GOTO 80
610 GOTO 610
620 SYMBOL AFTER 230
630 SYMBOL 231,0,0,0,16,0,0,0,0
640 SYMBOL 232,0,0,0,24,24,0,0,0
650 SYMBOL 233,0,0,0,56,56,0,0,0
660 SYMBOL 234,0,0,0,60,60,60,0,0
670 SYMBOL 235,0,0,126,126,126,126,0,0
680 SYMBOL 236,0,0,254,254,254,254,254,0
690 SYMBOL 237,73,145,73,37,74,145,74,73
700 SYMBOL 238,153,58,36,219,219,36,58,153
710 SYMBOL 239,0,0,0,8,62,0,0,0
720 SYMBOL 240,0,0,24,255,66,0,0,0
730 SYMBOL 241,0,0,1,255,37,0,0,0
740 SYMBOL 242,0,0,128,255,164,0,0,0
750 B$=CHR$(239)+" "+CHR$(240)+" "+CHR$(242)+CHR$(242)
760 RETURN
770 LOCATE 11,1:PRINT CHR$(24);"D A M B U S T E R S":LOCATE 11,2:PRINT" @ PAUL STANLEY ";CHR$(24)
780 PRINT:PRINT"The year is 1943.You are in charge of a powerful Beam weapon with which you are to protect a Dam from the bouncing bombsof the British attackers."
790 PRINT
800 PRINT"They have several Lancaster bombers which fly towards you and release their dangerous bombs, which might miss their target."
810 PRINT
820 PRINT"However,your task is not all that simplefor your weapon is unable to reach the Lancasters so you must just shoot at thebombs instead. You can move your cross-hair sights withthe cursor keys."
830 PRINT:PRINT:PRINT" PRESS ANY KEY TO CONTINUE."
840 IF INKEY$="" THEN 840 ELSE CLS
850 LOCATE 11,1:PRINT CHR$(24);"D A M B U S T E R S":LOCATE 11,2:PRINT" @ PAUL STANLEY ";CHR$(24)
860 PRINT:PRINT:PRINT
870 PRINT"Even adjusting the sights is difficult because there is a strong Wind which causes your sights to move about."
880 PRINT
890 PRINT"USE THE SPACE BAR TO FIRE."
900 PRINT:PRINT
910 PRINT"Because of the power of your weapon, after 10 shots it is drained of power and will only be ready by the next time an aeroplane attacks.Your battle is over";
920 PRINT"when too much water has poured through the broken Dam."
930 PRINT:PRINT:PRINT:PRINT" PRESS ANY KEY TO START."
940 IF INKEY$="" THEN 940 ELSE CLS
950 RETURN
960 RESTORE 970:FOR x=360 TO 366:READ a:POKE x,a:NEXT:RESTORE: RETURN
970 DATA 205,96,187,50,111,1,201
Damn that was hard :D
10 MODE 1:INK 1,26:BORDER 2
20 SYMBOL 255,60,126,126,126,126,126,126,60
30 BALL$=CHR$(255)
40 X=14:DIR=1
50 GOSUB 1000:GOSUB 2000:GOSUB 3000
60 WHILE INKEY(47)=-1
70 CALL &BD19:CALL &BD19
80 LOCATE X,11:PRINT CHR$(255)
90 LOCATE X+DIR,11:CALL 360:RESULT%=PEEK(367)
100 IF RESULT%<>32 THEN DIR=NOT DIR-1
110 OLDX=X:X=X+DIR
120 LOCATE OLDX,11:PRINT" "
130 WEND:MODE 2:CALL &BC02:END
1000 PLOT 200,150,2:DRAW 200,300:DRAW 350,300:DRAW 350,150:DRAW 200,150
1010 RETURN
2000 LOCATE 2,5:PRINT CHR$(150);STRING$(36,CHR$(154));CHR$(156)
2010 FOR Y=6 TO 20:LOCATE 2,Y:PRINT CHR$(149):LOCATE 39,Y:PRINT CHR$(149):NEXT Y
2020 LOCATE 2,21:PRINT CHR$(147);STRING$(36,CHR$(154));CHR$(153)
2030 RETURN
3000 FOR addr=&168 TO &16F
3010 READ a$
3020 POKE addr,VAL("&"+a$)
3030 NEXT addr:RETURN
3040 DATA cd,60,bb,32,6f,01,c9,00
10 BORDER 0
20 OUT &BC00,2
30 OUT &BD00,46
40 OUT &BD00,45
45 OUT &BD00,45
50 OUT &BD00,44
60 OUT &BD00,45
65 OUT &BD00,45
70 OUT &BD00,46
80 OUT &BD00,47
85 OUT &BD00,47
90 OUT &BD00,48
100 OUT &BD00,47
105 OUT &BD00,47
106 OUT &BC00,2
110 GOTO 20
I'd love to add this blinking tape effects on the borders ,can it be done in basic?
10 CALL &BC02
20 MODE 0
30 GOSUB 160
40 CALL &BB18
50 MODE 0:GOSUB 100
60 CALL &BB18
70 PEN 1
80 END
100 cols$="00261102010306162522151319181409"
110 i%=1
120 FOR p%=0 TO 15
130 INK p%,VAL(MID$(cols$,i%,2))
140 i%=i%+2
150 NEXT p%
160 FOR p%=0 TO 15
170 PEN p%
180 PRINT "Pen ";p%
190 NEXT p%
200 RETURN
Palette in string?
10 c$="\0@@\1zz\2kk\3bb\4aa\5cc\6ff\7pp\8yy\9vv\:oo\;mm\<ss\=rr\>nn\?ii":PRINT c$
Type it but instead "\" put ctrl+"\" and effect is the same, without FOR-NEXT. This is exactly your palette. :)
Palette in string?
10 c$="\0@@\1zz\2kk\3bb\4aa\5cc\6ff\7pp\8yy\9vv\:oo\;mm\<ss\=rr\>nn\?ii":PRINT c$
Type it but instead "\" put ctrl+"\" and effect is the same, without FOR-NEXT. This is exactly your palette. :)
Being able to set colours and move the cursor using control codes lets you do overprinting. Set transparent mode, set the first colour, print a character, move the cursor back, set the second colour, print the second character, repeat.I might be wrong, but this seemed different. I created my sprite using the technique you have just mentioned (my sprite is 16x16, 2 colour, 8 characters in all), but if you *break* ZbyniuR's code and type the character set, there are multi-coloured characters immediately (i.e. no over printing). This is what I am referring to.
Wow! You blew my mind with the GUI code.
I didn't know the multi-coloured characters were even possible. How did you do that? I assume it has something to do with your .fnt file but to be fair, trying to read control codes is near impossible so I have no idea what happening past the first line setting MODE and INKS. :laugh:
I nearly forgot, I typed in this program (http://www.cpc-power.com/index.php?page=detail&num=10865) from Home Computing Weekly from 1985. So the concept is very old, but their using CHR$ instead of control codes to get the job done. :)For my new game, I have decided on a mixture of using CHR$ and control codes.
For my new game, I have decided on a mixture of using CHR$ and control codes.
It was far easier to use the SYMBOL command over the control code equivalent CHR$(25) or CTRL-Y, but putting a multicoloured sprite into a string with all needed control codes makes for much shorter code.
10 MODE 1:SYMBOL 244,60,56,60,24,24,24,56,24:SYMBOL 245,20,56,60,24,58,26,52,48:SYMBOL 246,0,40,56,60,24,24,60,102:SYMBOL 247,24,60,60,24,24,28,120,76:WHILE-1:FOR a=244 TO 247:PRINT CHR$(a)CHR$(8 );:FOR b=1 TO 80:NEXT:NEXT:WEND
The first rule of inventiveness is: Everything can be done better.
Here you are. Bunch of colorful Lemmings moving on screen.
Still in 1 line of pure Basic. I'm proud about myself. ;)
If you swap digits 7 and 2 in RIGHT$ and LEFT$ they walk backward. :D
Do you need combination space and arrow simultaneous?
If not, maybe better is use INKEY$ insted INKEY(). One more benefit is you can KEY DEF left, right and fire in joystick the same codes as arrows and space and both way of steering will be work without extra INKEY$.
The first rule of inventiveness is: Everything can be done better.I missed this post until now. This is awesome.
I missed this post until now. This is awesome.
10 a=1
20 IF a=1 THEN b=1
30 IF a=3 THEN b=-1
40 PRINT a
50 a=a+b
60 GOTO 20
5 DEFINT a-b
Not quite was I was meaning (but you are right). More like is there a BASIC command (i.e. MOD, XOR, AND etc...) that could do this sequence without the IF statements. I feel that is the section that slows the program down.Code: [Select]5 DEFINT a-b
??
5 DEFINT a
10 a=1
20 a=a+1
30 PRINT a MOD 3+1
40 GOTO 20
10 PRINT "1 2 3 2 ":GOTO 10
Not quite was I was meaning (but you are right). More like is there a BASIC command (i.e. MOD, XOR, AND etc...) that could do this sequence without the IF statements. I feel that is the section that slows the program down.I've seen the functions MAX & MIN being used instead of IF statements to determine if a variable reaches a certain value. There's a little bit of information about it in Basically BASIC Amstrad Amstrad article in Issue 112. The idea there is MIN can be used so the variable never becomes larger than the number you want and MAX is used so the number never drops below the number you want.
20 IF a=MAX(a,3) THEN b=-1
30 IF a=MIN(a,1) THEN b=1
40 PRINT a;
50 a=a+b
20 IF MAX(a,3)=3 THEN b=-1
30 IF MIN(a,1)=1 THEN b=1
Easiest way I can think ofCode: [Select]10 PRINT "1 2 3 2 ":GOTO 10
5 DEFINT a
10 a=0
20 a=a MOD 4+1
30 PRINT 2-(8*a)/3+2*a*a-a*a*a/3
40 GOTO 20
10 DEFINT a,b:a=3
20 DIM b(3):b(0)=1:b(1)=2:b(2)=3:b(3)=2
30 a=(a+1) MOD 4
40 PRINT b(a):GOTO 30
a better approach...Code: [Select]30 PRINT 2-(8*a)/3+2*a*a-a*a*a/3
30 PRINT ((a+2)*a*a+2) MOD 4
10 DEFINT a:a=0
20 c$="1 2 3 2 "
30 a=a MOD 8+1
40 PRINT MID$(c$,a,1);:GOTO 30
How to put machine code in Basic without FOR READ POKE NEXT DATA. Short and fast way, just in one PRINT. :D
Line 5 is need only once to generate 32 characters. Place them in quotes in PRINT in line 10. Now line 5 is no needed any more. Save and RUN and press any keys. ;)
This is LDIR demonstration. Working after reset or after SYMBOL AFTER 240. :)
Of course CAT is just tu show whatever on screen. Because CALL HIMEM+13 make copy from &c000 to &4000, and CALL HIMEM+1 opposite. :)
5 FOR a=1 TO 63 STEP 2:PRINT CHR$(1)CHR$(VAL("&"+MID$("19F02101401101C001D019F13FEDB0C92101C01119F2014001D03FEDB0C90432",a,2)));:NEXT:EDIT 10
10 PRINT"":CAT:CALL HIMEM+13:WHILE-1:CLS:CALL &BB18:CALL HIMEM+1:CALL &BB18:WEND
code$="<the code string>"
address = peek(@code$+1)+peek(code$+2)*256
call address
The advantage of adding machine code this way is obvious, but what are the disadvantages (if any)?
this is specific to Amstrad, not compatible with all basic (or CPU)
Thanks for all the great answers guys. I knew there would be a formula to work this out.Don't know what your exact goal is, but here you are 2 proposals that may be of interest:
I have gone for the combination of @remax (http://www.cpcwiki.eu/forum/index.php?action=profile;u=314) and @Urusergi (http://www.cpcwiki.eu/forum/index.php?action=profile;u=923) formula as it is the result I am after not the actual printing on the screen.
I must admit the array solutions were clever but of no use in what I am hoping to do. :P
10 DEFINT a-z
' Generate numbers consecutively
20 FOR i=1 to 3:?i:NEXT:?2:GOTO 20
10 DEFINT a-z
' initialize: i=generated num, m,n=generation parameters
20 i=1:m=3:n=2
30 GOSUB 100:?i:GOTO 30
' Generate next i number
100 i=i XOR m:m=m XOR n:n=n XOR 2:RETURN
10 for n=100 to 0 step -1
20 a$=right$("00"+mid$(str$(n),2),3)
30 print a$
40 next
I have another question which I'm hoping is very simple.
I have a variable counting down from 100. I would like it to print as a 3 digit number therefore adding 0's in front if below 100.
i.e. 99 = 099 and 9 = 009.
I have tried using the PRINT USING command but can't get it to work.
Any ideas?
10 FOR i=100 TO 0 STEP -1
20 a$=HEX$(96*(i\100)+6*(i\10)+i,3)
30 PRINT a$
40 NEXT
Thanks @ronaldo (http://www.cpcwiki.eu/forum/index.php?action=profile;u=1227)
I like your use of the XOR to get the desired sequence.
I wanted something for an animation sequence (in BASIC) where I have 3 frames of animation but wanted frame 2 to be displayed every 2nd time. 1,2,3,2,1,2,3 etc...
I haven't ever had time to do anything with it though as I ended up doing other things instead.
FOR I=0 to 1000:NEXT
FOR I=0 TO 1000:NEXT I
10 FOR I=100 TO 0 STEP -1:NEXT
10 FOR I=100TO 0STEP-1:NEXT
Yes, generally REMAIN is not necessary to be used with AFTER. It is necessary when, depending on player choices in the game, you want to stop the execution of AFTER subroutine.
Imagine for example that (for your game) you give 30 seconds to the player to make his choice. For this, you can use AFTER, and after 30 seconds print <you lose!>. In this case, AFTER has to be disabled by REMAIN in most cases, in which the player has made the choice before 30 seconds. If it is not, then <You lose> will appear in the next turn
Another problem i had has to do with where the program goes after calling the AFTER subroutine, as it doesn't seem to go in the same line every time (as i wanted to send the execution back to the next turn). Using GOTO in the subroutine wasn't the best choice, because the end of the subroutine by RETURN will not be recognized. What i did is setting a variable to 1 in the AFTER subroutine, and then using IF/THEN commands in 2-3 lines in different places in the list i send the program back to the next turn. Hopefully, this works
Nice game in only 10 lines! Well done! Needing careful observing!
I looked again to what i had done, as it couldn't remember exactly. We are talking about the situation when player loses, because he has not made the choice and we want to go to the next turn.
Not quite sure I follow, the AFTER statement is a condition where by when it's set, that will initiate after the time has elapsed from within anywhere in the program, it's possible that if your program is doing something else with variables which might interfere with variables within your programs AFTER subroutine, that may cause problems. Normally what happens in that case is if you have areas of code you need protected from the Event Jump from AFTER, you can use DI to Disable Interrupts & EI to Enable Interrupts.
I looked again to what i had done, as it couldn't remember exactly. We are talking about the situation when player loses, because he has not made the choice and we want to go to the next turn.
So, in that case, AFTER subroutine has been runned. I create a new unused variable in the subroutine, and define A=1. So, in case the subroutine has been runned, A=1.
Then, in the area of inputing, just after X$=inkey$ and before the input choices i entered a line <if A=1 then GOTO> (go the next turn). Of course, A is set to 0 in the start of each turn.
In that way, the game does not wait for inputing of the player choice, and goes to next turn. If not done, after displaying <you lose>, the game will continue the same turn, not the next turn
No, maybe my english is not so good and i could't make it clear.
One more simple question!
When we have an INPUT question of an a$ variable, is there a way to specify that characters must not be over a specific number? (for example i want a$ variable to be not more than 15 characters).
I found LEN, but i wonder if there is a quicker way
1000 if LEN(a$)>15 THEN r=15 ELSE r=LEN(a$)
1010 w$=MID$(a$,1,r)
1010 w$=LEFT$(a$,r)
10 MODE 2:ZONE 6:DEFINT a-y:z=TIME:p=3:m=1000:c=SQR(m+1):DIM s(m+1):PRINT 2,:WHILE p<c:PRINT p,:FOR i=p+p*2 TO m STEP p*2:s(i)=1:NEXT:p=p+2:WHILE s(p):p=p+2:WEND:WEND:WHILE p<m:PRINT p,:p=p+2:WHILE s(p):p=p+2:WEND:WEND:PRINT:PRINT(TIME-z)/300;"seconds"
20 CALL &BB18:MODE 2:z=TIME:p=3:PRINT 2,:WHILE p<m:PRINT p,:p=p+2:WHILE s(p):p=p+2:WEND:WEND:PRINT:PRINT(TIME-z)/300;"seconds"
I think this question has been asked before, but:
Is there anyway to (from BASIC) fetch the character or character-code currently on the screen on a certain position?
This would require a character-memory-map of some kind, which I don't think the CPC has?
Something like CHARCODE(x,y)
Or what about using PEEKS?
Not sure if it's what you're after, but COPYCHR$ might be worth a look:Interesting. Will take a closer look. But it would be nice with something for the 464, since that's the one I'm using for this. (Small enough to be on the same desk as my PC).
http://www.cpcwiki.eu/index.php/Locomotive_BASIC#COPYCHR.24_.28st.29 (http://www.cpcwiki.eu/index.php/Locomotive_BASIC#COPYCHR.24_.28st.29)
I don't think it works on a 464, but I seem to remember a discussion on cpcwiki a few years ago about a 464 equivalent.
(I could be remembering incorrectly though).
10 FOR a=1 TO 17:POKE 39999+a,VAL("&"+MID$("DD7E00CDB4BBF5CD60BB320000F1C3B4BB",a*2-1,2)):NEXThttp://www.cpcwiki.eu/forum/programming/basic-efficient-collision-detection-routine/
20 LOCATE x,y:CALL 40000,0:PRINT CHR$(PEEK(0)) ' this works as COPYCHR$ in any CPC
I used to found this in some magazine. :)
And remember about TEST command, could be usefull to detect pixel color. :)
I think this question has been asked before, but:
Is there anyway to (from BASIC) fetch the character or character-code currently on the screen on a certain position?
This would require a character-memory-map of some kind, which I don't think the CPC has?
Something like CHARCODE(x,y)
Or what about using PEEKS?
Would have to know more about how that character onscreen got there. If it's a program placing and removing characters onscreen, using an array is faster than copychr$(#0) or it's TXT RD CHAR (#BB60) counterpart.
If you were gathering information from a Disk Catalog (#BC9B) through, the firmware can be told where to place that information with the DE register being the address to where the buffer is to go.
100 MODE 2:CALL &BC02
110 DIM g$(20,25)
120 DEFINT a-z
130 ' Test 1 - Store value into 2D Array through Nested Loop
140 t!=TIME
150 FOR y=1 TO 25
160 FOR x=1 TO 20
170 g$(x,y)=CHR$(32)
180 NEXT x
190 NEXT y
200 t1!=TIME:PRINT"Time 1 (2D Array in Nested Loop) =";(t1!-t!)/300
210 CLEAR:DEFINT a-z
220 ' Test 2 - Poke from Nested Loop
230 MEMORY &9FFF
240 t!=TIME
250 FOR y=1 TO 25
260 FOR x=1 TO 20
270 POKE &9FEB+x+(y*20),32
280 NEXT x
290 NEXT y
300 t1!=TIME:PRINT"Time 2 (Memory Poke in Nested Loop) =";(t1!-t!)/300
310 ' Test 3 - Single Loop
320 DEFINT a-z
330 t!=TIME
340 FOR a=1 TO 500
350 POKE &A1FF+a,32
360 NEXT a
370 t1!=TIME:PRINT"Time 3 (Memory Poke in Single Loop) =";(t1!-t!)/300
380 CLEAR:DEFINT a-z:DIM g$(500)
390 ' Test 4 - Store value into Single Array through Single Loop
400 t!=TIME
410 FOR a=1 TO 500
420 g$(a)=CHR$(225)
430 NEXT a
440 t1!=TIME:PRINT"Time 4 (Singular Array in Single Loop) =";(t1!-t!)/300
450 CALL &BB18
460 MODE 0:b=-20
470 FOR y=1 TO 25
480 FOR x=1 TO 20
490 PEN 15:LOCATE x,y:PRINT g$(b+x+(y*20));
500 NEXT x
510 NEXT y
520 CALL &BB18
530 PEN 1:PRINT CHR$(224):CLEAR:END
100 MODE 0:BORDER 0:INK 14,15:INK 15,9
110 DEFINT a-z
120 w=20
130 FOR a=1 TO 500
140 y=(a+19)\w
150 x=(a+w)-(y*w)
160 PEN INT(RND*15)+1:LOCATE x,y:PRINT CHR$(248);
170 NEXT a
180 CALL &BB18:PEN 1:END
130 for y=1 to 25
140 for x=1 to 20
150 PEN INT(RND*15)+1:LOCATE x,y:PRINT CHR$(248);
160 next x
170 next y
That's a very interesting test.
I couldn't help but try it with nested loops, and then compare the running times.
The following times are SCIENTIFICALLY CALCULATED with a stopwatch app on my phone. :laugh:
single loop: 10.6 seconds
nested loops: 7.8 seconds
...
130 FOR a=0 TO 499
140 y=(a+20)\20
150 x=1+a MOD 20
...
100 MODE 0:BORDER 0:INK 14,15:INK 15,9
110 DEFINT a-z
120 t1!=TIME
130 FOR a=1 TO 500
140 PEN INT(RND*15)+1
150 PRINT CHR$(248);
160 NEXT a
170 t2!=TIME
180 PEN 1:PRINT"Time =";(t2!-t1!)/300
190 END
100 MODE 2:BORDER 0:INK 1,26:INK 3,3
110 SYMBOL 255,255,0,24,36,66,129,0,255
120 SYMBOL 254,129,129,255,129,129,129,255,129
130 GOTO 1000
140 FOR x=1 TO 20
150 POKE &9FEB+x+(y*20),255
160 p=3:GOSUB 270
170 NEXT x
180 RETURN
200 FOR y=3 TO 20
210 GOSUB 250
220 GOSUB 270
230 NEXT y
240 RETURN
250 POKE &9FEB+x+(y*20),v
260 RETURN
270 POKE &A1EB+x+(y*20),p
280 RETURN
300 MODE 0:t1!=TIME
310 FOR a=0 TO 479
311 IF PEEK(&A000+a)=255 THEN PAPER 8 ELSE PAPER 0
320 PEN PEEK(&A200+a):PRINT CHR$(PEEK(&A000+a));
330 NEXT a
340 t2!=TIME
350 PEN 1:LOCATE 1,23:PRINT"Draw Time = ";USING"#.##";(t2!-t1!)/300
360 RETURN
1000 DEFINT a-z:MEMORY &9FFF:t1!=TIME
1010 FOR a=1 TO 500
1020 POKE &9FFF+a,32
1030 NEXT a
1040 FOR y=3 TO 21 STEP 3
1050 GOSUB 140
1060 IF y<>21 THEN x=2:v=32:GOSUB 250:x=18:GOSUB 250
1070 NEXT y
1080 x=2:v=254:p=1:GOSUB 200
1090 x=18:GOSUB 200
1100 t2!=TIME
1110 LOCATE 1,1:PRINT"Setup Time =";(t2!-t1!)/300
1120 CALL &BB18
1130 GOSUB 300
1140 END
Is there a way in pure BASIC (+ possibly ROM-only routines) to read the character at a given position, e.g., cursor position.I know the CPC only has graphics screens. I supposed that a text buffer is used. I have seen simply Assembly used in BASIC to do that. I have not found a BASIC-only (+ROM-only routines) solution. My solution has been to implement myself a buffer to remember the characters on the screen.Does anyone here have a better idea?
100 MODE 1:DEFINT a-z:a$(0)=CHR$(32):a$(1)=CHR$(127):DIM m$(40):DEF FNxp=((x-1)*16):DEF FNyp=398-((y-1)*16)
110 BORDER 0:INK 0,11:INK 1,26
120 LOCATE 1,10:PRINT STRING$(40,127);
130 FOR x=1 TO 40:m$(x)=CHR$(127):NEXT x
140 FOR a=1 TO 3
150 x=(RND*38)+1
160 WHILE TEST(FNxp,398-(9*16))=0
170 x=(RND*38)+1
180 WEND
190 m$(x)=" ":MOVE FNxp,398-(9*16):TAG:PRINT CHR$(32);:TAGOFF
200 NEXT a
210 x=1:y=10
220 LOCATE x,y:a$=COPYCHR$(#0)
230 PRINT CHR$(250);
240 t1!=TIME
250 WHILE x<>40
260 LOCATE x,y
270 x=x+1
280 PRINT a$;
290 LOCATE x,y:a$=COPYCHR$(#0)
300 PRINT CHR$(250);
310 WEND
320 t2!=TIME
330 LOCATE 1,1:PRINT "COPYCHR$ Time =";USING"##.##";(t2!-t1!)/300
340 CALL &BB18
350 LOCATE 40,10:PRINT CHR$(127);
360 x=1:y=10
370 p=TEST(FNxp,FNyp)
380 MOVE FNxp,FNyp:TAG:PRINT CHR$(250);:TAGOFF
390 t1!=TIME
400 WHILE x<>40
410 MOVE FNxp,FNyp
420 x=x+1
430 TAG:PRINT a$(p);
440 MOVE FNxp,FNyp
450 p=TEST(FNxp,FNyp)
460 PRINT CHR$(250);:TAGOFF
470 WEND
480 t2!=TIME
490 LOCATE 1,2:PRINT "TEST using Functions Time =";USING"##.##";(t2!-t1!)/300
500 CALL &BB18
510 LOCATE 40,10:PRINT CHR$(127);
520 x=0:y=254
530 p=TEST(x,y)
540 MOVE x,y:TAG:PRINT CHR$(250);:TAGOFF
550 t1!=TIME
560 WHILE x<>624
570 MOVE x,y
580 x=x+16
590 TAG:PRINT a$(p);
600 MOVE x,y
610 p=TEST(x,y)
620 PRINT CHR$(250);:TAGOFF
630 WEND
640 t2!=TIME
650 LOCATE 1,3:PRINT "TEST with direct values Time =";USING"##.##";(t2!-t1!)/300
660 CALL &BB18
670 LOCATE 40,10:PRINT CHR$(127);
680 x=1:y=10
690 v$=m$(x)
700 LOCATE 1,10:PRINT CHR$(250);
710 t1!=TIME
720 WHILE x<>40
730 LOCATE x,y
740 x=x+1
750 PRINT v$;
760 LOCATE x,y
770 v$=m$(x)
780 PRINT CHR$(250);
790 WEND
800 t2!=TIME
810 LOCATE 1,4:PRINT "Array Time =";USING"##.##";(t2!-t1!)/300
820 END
For anyone interested, I made a simple comparision programme to test COPYCHR$, ...Hey, great! Without knowing about your test (I will try it later), I also made a test for COPYCHR$, today. It has also some machine code for all CPCs...
10 REM fancy - test copychr$
20 MODE 1:CLEAR:DEFINT a-z:RANDOMIZE TIME:PEN 1:PAPER 0
30 useCopychr=0: 'set this to use copychr$
40 c$=CHR$(&CD)+CHR$(&60)+CHR$(&BB)+CHR$(&32)+CHR$(0)+CHR$(0)+CHR$(&C9): 'call &BB60 (TXT RD CHAR)
50 fancy$="F"+CHR$(15)+CHR$(2)+"a"+CHR$(15)+CHR$(3)+"n"+CHR$(15)+CHR$(1)+CHR$(24)+"cy"+CHR$(24)+" s"+CHR$(14)+CHR$(2)+"t"+CHR$(14)+CHR$(3)+"u"+CHR$(14)+CHR$(0)+"ff"+"!"
60 LOCATE 1,1:PRINT fancy$;" ";fancy$
70 ' pixelize the first 12 characters
80 xstart=0
90 FOR i=1 TO 12
100 ckeep=1:IF i=2 OR i=3 OR i=7 OR i=10 THEN ckeep=0: 'the color to keep (1=pen or 0=paper)
110 FOR y=0 TO 7:FOR x=0 TO 7
120 xp=xstart+x*2:yp=399-y*2
130 IF TEST(xp,yp)=ckeep THEN 160
140 c=INT(RND*3+0.5):IF c=ckeep THEN 140
150 PLOT xp,yp,c :'set random color which is not the kept color
160 NEXT x,y
170 xstart=xstart+2*8
180 CALL &BD19:NEXT i
190 ' recognize characters in first line
200 a$="":FOR i=1 TO 12*2+1:LOCATE i,1:
210 GOSUB 290
220 a$=a$+t$
230 NEXT
240 LOCATE 1,5:PRINT a$;
250 t!=TIME+600:WHILE TIME<t! AND INKEY$="":CALL &BD19:WEND:LOCATE 1,5:PRINT CHR$(18);
260 GOTO 80
270 '
280 'call &BB60 (TXT RD CHAR) as COPYCHR$ on any CPC
290 IF useCopychr OR PEEK(&BB60)<>&CF THEN t$=COPYCHR$(#0):GOTO 330: 'flag set or CPCBasic
300 a%=UNT(PEEK(@c$+1)+PEEK(@c$+2)*&100)
310 CALL a%:b%=PEEK(0)
320 t$=CHR$(b%)
330 RETURN
Did you know that COPYCHR$ (or call &BB60, TXT RD CHAR) not only recognizes a character with the selected PEN, but also its inverse with the selected PAPER?
That means the PEN or PAPER can be pixelized without affecting the result, but not both. This also means that an inverted character cannot be recognized.
And if no PEN bits and no PAPER bits are set, there is a slight difference: The CPC 664/6128 returns space (char 32) and the CPC 464 the inverse of space (char 143).
Any more subtle findings?
60000 a=&170
60010 v=PEEK(&170)
60020 n=0
60030 FOR l=1 TO 10
60040 PRINT v
60050 n = a + v
60060 a = n
60070 v = PEEK(n)
60080 CALL &BB18
60090 NEXT l
But this will increase your listing length 😄
a=&170:v=PEEK(&170):n=0:FOR L=1 TO 10:PRINT v:n = a + v:a = n:v = PEEK(n):CALL &BB18:NEXT L
102
80
89
115
66
113
127
108
91
71
Does anyone have some simple BASIC code to have the following sequence of numbers...I am surprised not to have read a such simple solution :
1 2 3 2 1 2 3 2 1 2 3 etc...
I can do it in the following code but just wondering if someone can do it faster
10 FOR x=-1 to 2:PRINT 1+ABS(x);:NEXT