CPCWiki forum

General Category => Programming => Topic started by: Morri on 07:37, 30 December 15

Title: Scrolling in BASIC
Post by: Morri on 07:37, 30 December 15
Over the Christmas break I have been playing around with scrolling in BASIC. With the help of AA and CWTA I have managed to come up with the following...


10 DIM b$(69,12)
20 MODE 1
30 BORDER 0
40 INK 0,26:INK 1,0:INK 2,23:INK 3,10
50 LOCATE 7,4:PRINT"Press RIGHT arrow to scroll"
60 FOR a=1 TO 12
70 READ a$
80 FOR b=1 TO 69
90 b$(b,a)=MID$(a$,b,1)
100 IF b<41 AND b$(b,a)="X" THEN LOCATE b,a+7:PRINT CHR$(143)
110 NEXT:NEXT
120 f=&3000
130 IF INKEY(1)=0 AND f<&301D THEN GOSUB 150
140 GOTO 130
150 f=f+1
160 CALL &BD19
170 a=INT(f/256)
180 b=(f AND 255)
190 OUT &BC00,12:OUT &BD00,a
200 OUT &BC00,13:OUT &BD00,b
210 WINDOW#1,b,b,1,25:CLS#1
220 FOR c=1 TO 12:d=b+40:IF b$(d,c)="X" THEN LOCATE b,c+8:PRINT CHR$(143)
230 NEXT:RETURN
240 DATA XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
250 DATA X                                                                   X
260 DATA X    XXXXXX  XX   XX   XXX    XXXXXX   XXXXXX    XXXXXX   XXXXXX    X
270 DATA X   XXXXXXXX XXX XXX  XX XX    XX  XX   XX  XX     XX    XXXXXXXX   X
280 DATA X   X  XX  X XXXXXXX XX   XX   XX  XX   XX  XX     XX    X  XX  X   X
290 DATA X   XXXXXXXX XXXXXXX XX   XX   XXXXX    XXXXX      XX    XXXXXXXX   X
300 DATA X   X XXXX X XX X XX XX   XX   XX XX    XX XX      XX    X XXXX X   X
310 DATA X   XX    XX XX   XX  XX XX    XX  XX   XX  XX     XX    XX    XX   X
320 DATA X   XXXXXXXX XX   XX   XXX    XXX   X  XXX   X   XXXXXX  XXXXXXXX   X
330 DATA X    XXXXXX                                               XXXXXX    X
340 DATA X                                                                   X
350 DATA XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX


If I can figure it out I was thinking of trying to code a game in BASIC that uses scrolling like this.
Does anyone have anything similar. Or any tweaks they would like to add to my code?
Title: Re: Scrolling in BASIC
Post by: AMSDOS on 11:02, 30 December 15
There's a small program I wrote here (http://www.cpcwiki.eu/forum/programming/about-hardware-scrolling-with-crtc-reg-3/msg82268/#msg82268) which moves the screen with Reg 3 of the CRTC.
Title: Re: Scrolling in BASIC
Post by: Morri on 17:59, 11 August 16
Found the following code on cpc-power. Poked machine code but still accessible via basic call so close enough.  ;)
Added the stars to scroll off the screen. Should be able to add graphics to the right hand side to continue the scroll (press space).

Seems to simply move the screen to the left only 4 pixels at a time. Similar to invasion of the zombie monsters for example.


10 BORDER 0
20 INK 0,10:INK 1,0:INK 2,25:INK 3,14
30 MODE 1
40 WINDOW#3,1,40,23,25:PAPER#3,1:CLS#3
50 addr=15000
60 FOR n=addr TO addr+44:READ a:POKE n,a:NEXT
70 m=49152:y=INT(m/256):x=m-(256*y)
80 POKE addr+1,x:POKE addr+2,y
90 a=21
100 POKE addr+4,a
110 b=80
120 POKE addr+11,b:POKE addr+16,b
130 DATA 33,&80,&c2,6,8,197,229,6,8,197,6,&4f,229,126,229,17
140 DATA &4f,0,25,119,225,35,126,43,119,35,16,249,225,17,0,8
150 DATA 25,193,16,229,225,17,&50,0,25,193,16,217,201
171 TAG:FOR b=384 TO 80 STEP -16:FOR a=1 TO 40
172 c=INT(RND*10)+1
173 IF c=1 THEN MOVE (a*16)-16,b:PRINT"*";
174 NEXT:NEXT
180 IF INKEY(47)=0 THEN CALL 15000
190 GOTO 180
Title: Re: Scrolling in BASIC
Post by: ZbyniuR on 16:52, 13 August 16
I know how to scroll screen. :)

20 t1=48+t\256:t2=t MOD 256:CALL &BD19:OUT &BC00,13:OUT &BD00,t2:OUT &BC00,12:OUT &BD00,t1
30 IF INKEY(1)=0 THEN t=t-1 ELSE IF INKEY(8 )=0 THEN t=t+1
40 IF INKEY(2)=0 THEN t=t-40 ELSE IF INKEY(0)=0 THEN t=t+40
50 IF t<0 THEN t=t+1024 ELSE IF t>1024 THEN t=t-1024
60 GOTO 20


But I don't know what to do, to after change those registers, WINDOW 1,1,1,25   still stay on left edge of screen. :( 
Any ideas?
Title: Re: Scrolling in BASIC
Post by: arnoldemu on 19:50, 13 August 16
Quote from: ZbyniuR on 16:52, 13 August 16
I know how to scroll screen. :)

20 t1=48+t\256:t2=t MOD 256:CALL &BD19:OUT &BC00,13:OUT &BD00,t2:OUT &BC00,12:OUT &BD00,t1
30 IF INKEY(1)=0 THEN t=t-1 ELSE IF INKEY(8 )=0 THEN t=t+1
40 IF INKEY(2)=0 THEN t=t-40 ELSE IF INKEY(0)=0 THEN t=t+40
50 IF t<0 THEN t=t+1024 ELSE IF t>1024 THEN t=t-1024
60 GOTO 20


But I don't know what to do, to after change those registers, WINDOW 1,1,1,25   still stay on left edge of screen. :( 
Any ideas?
basic and firmware don't know you have set the screen base and window will not work correctly.

Two things you can do:
1. Do not use window and translate your print coordinates (if you scroll right, 2 is the first column).
2. You need to use a bit of asm and use this function: &bc05 - SCR SET OFFSET. This will scroll the screen and firmware/basic will know about it.

Title: Re: Scrolling in BASIC
Post by: Morri on 20:43, 13 August 16
Quote from: ZbyniuR on 16:52, 13 August 16But I don't know what to do, to after change those registers, WINDOW 1,1,1,25   still stay on left edge of screen. :( Any ideas?
I remember having the same issue when I first looked at this.
My solution in my first listing above was to use value in "b" (in your case I think it is "t") which changes as the screen scrolls.
For moving right it will be something like WINDOW#1,t,t,2,24:CLS#1. You won't be able to use the top most line and the bottom most line because when the scroll happens line 1 begins to wrap to the bottom of the screen, so keep graphics in the centre of the screen (3 -22 should be enough). I just used trial and error with the values until I got it right. I also discovered that my value b can only go to 69 or 70 before the screen wants to wrap again so I made this my maximum value. This is also why in my game coolbox each level is set to this length of scrolling.
Title: Re: Scrolling in BASIC
Post by: ZbyniuR on 22:57, 13 August 16
"firmware/basic will know about it" - So, is "know" mean keep this offset somewhere in RAM, where?

I hope just POKE there, new offset make "Ready" appear in other column etc with LOCATE and WINDOW coordinate. :)
Title: Re: Scrolling in BASIC
Post by: AMSDOS on 23:05, 13 August 16
"Know" as in BASIC/Firmware sense the screen has moved, "WINDOW" can be used. If OUT is used alone, BASIC/Firmware won't sense it, WINDOW won't work.


My example I pulled from the other thread:


10 DIM map%(20):MODE 1:INK 1,26:INK 3,19:BORDER 0
20 GOSUB 2010:GOSUB 3010
30 FOR x=1 TO 10
40 LOCATE x+10,10:PEN 1
50 IF map%(x)=1 THEN PRINT CHR$(143)
60 NEXT x
70 PEN 2:LOCATE 15,12:PRINT CHR$(250)
80 place%=10
90 WHILE INKEY(18)=-1
100 IF INKEY(47)<>-1 THEN place%=place%+1:GOSUB 1010
110 WEND
120 MODE 2:CALL &BC02:PEN 1:END
1000 REM Space has been Pressed, Time to Move Scenery
1010 IF place%=21 THEN place%=1
1020 PEN 1:LOCATE 15,12:PRINT" "
1030 CALL &BD19:CALL &100
1040 OUT &BC00,3:OUT &BD00,5
1050 CALL &BD19
1060 OUT &BC00,3:OUT &BD00,&BE
1070 LOCATE 10,10:PRINT" "
1080 PEN 2:LOCATE 15,12:PRINT CHR$(250);
1090 PEN 1:LOCATE 20,10:IF map%(place%)=1 THEN PRINT CHR$(143)
1100 RETURN
2000 REM Scenery Data
2010 FOR n%=1 TO 20:READ map%(n%):NEXT n%
2020 RETURN
2030 DATA 1,1,1,0,0,1,1,0,1,1,1,0,1,1,0,1,0,1,1,1
3000 REM M/C to Firmware Scroll
3010 FOR addr=&100 TO &108
3020 READ a$:POKE addr,VAL("&"+a$)
3030 NEXT addr:RETURN
3040 DATA cd,0b,bc,23,23,cd,05,bc,c9
Title: Re: Scrolling in BASIC
Post by: AMSDOS on 23:09, 13 August 16
when CALL &BC0B and CALL &BC05 have been used (with a couple of Increments or Decrements in between), the  screen rolls Horizontally, anything on the Left Side of Screen moves to the Right and Visa-Versa.
Title: Re: Scrolling in BASIC
Post by: arnoldemu on 08:56, 14 August 16
Quote from: ZbyniuR on 22:57, 13 August 16
"firmware/basic will know about it" - So, is "know" mean keep this offset somewhere in RAM, where?
Yes.

Unofficial Amstrad WWW Resource (http://www.cpctech.org.uk/docs/firmware.pdf)

6128: &B7C4       
464: &B1C9

2          bytes screen       offset


OUT is direct to hardware, firmware and basic don't know so they draw in the previous place.

Those calls I mentioned tell the firmware the correct place.


Title: Re: Scrolling in BASIC
Post by: AMSDOS on 01:00, 21 August 16
Quote from: Morri on 17:59, 11 August 16
Found the following code on cpc-power. Poked machine code but still accessible via basic call so close enough.  ;)
Added the stars to scroll off the screen. Should be able to add graphics to the right hand side to continue the scroll (press space).

Seems to simply move the screen to the left only 4 pixels at a time. Similar to invasion of the zombie monsters for example.



Yep, so I've taken that BASIC program, Disassembled the M/C and heavily commented it to work out the process:




org &8000

ld hl,&c000

;; ld b,&1 ;; Number of Lines to Move


.all_lines_reached
;; push bc
push hl ;; Save Address of Screen
ld b,&08 ;; Height of Character


.nextline
push bc ;; Save Height of Character
ld b,&50 ;; Length of area to scroll
push hl ;; Save Screen Address
ld a,(hl) ;; But put contents at Screen Address into A
push hl ;; And Save Screen Address again
ld de,&0040 ;; Where to position the Character when
;; it reaches the left edge of the screen
add hl,de ;; Add New Position to the Screen Address
ld (hl),a ;; Place Contents from Old Position into the New one.
pop hl ;; Restore Screen Address
.move_data
inc hl ;; Increment it
ld a,(hl) ;; Place Details from it into A
dec hl ;; Decrement back to other position
ld (hl),a ;; Move Information to it
inc hl ;; Increment again (this is so we can get back to
;; the next new position and move data again).
djnz move_data ;; Has Length of Area been reached?


;; At this point the top line to move has been reached, so now we need to
;; work on the next pixel line and then the process continues all over
;; again until the Height of the Character has been reached.


pop hl ;; Restore Screen Address
ld de,&0800 ;; Next Line to calculate
add hl,de ;; Add to Screen Address
pop bc ;; Restore Height
djnz nextline ;; Return if no Reached
pop hl
;; ld de,&0040 ;; Comes into play if more than
;; add hl,de ;; one line to move
;; pop bc
;; djnz all_lines_reached
ret





I've commented out the last part of the program, because that's where it begins dealing in Moving Multiple Lines and have left it as a Single Line. I've poked around with values to work out what role they play, I've tried to make it clear what they represent, but the labels maybe confusing.
The routine I've called Next Line essentially sets up where everything is, and if it's on the edge of the screen to move it to the right, move data continues along that line, going back and forwards shifting Bytes, this is where your 4 pixels comes in at a time because you're in Mode 1 a Byte represents 4 Pixels, so in Mode 0 it will be 2 Pixels and in Mode 2 all 8 Pixels gets shifted. Once a line (a pixel line that is) has been reached, the next Line is looked at and the whole process continues again until 8 Pixel lines (the height of the text) is reached.
Title: Re: Scrolling in BASIC
Post by: Morri on 06:18, 21 August 16
@AMSDOS (http://www.cpcwiki.eu/forum/index.php?action=profile;u=330) I've been playing around with this code but it just seems a little too slow to use in a game I had in mind.
It may still come in handy in the future though. Thanks for looking at it.
Now, if you ever think of ways of speeding it up... 8)
Title: Re: Scrolling in BASIC
Post by: AMSDOS on 09:23, 21 August 16

Quote from: Morri on 06:18, 21 August 16
@AMSDOS (http://www.cpcwiki.eu/forum/index.php?action=profile;u=330) I've been playing around with this code but it just seems a little too slow to use in a game I had in mind.
It may still come in handy in the future though. Thanks for looking at it.
Now, if you ever think of ways of speeding it up...


It's probably the sort of routine you could get away with if you didn't have the whole screen to move, having said that it's faster than the small Firmware routine I've been using, in terms of how far to Rolling the Screen Horizontally, the firmware has the advantage, which is simply a matter of how many INC HLs or DEC HLs are place between SCR GET LOCATION and SCR SET OFFSET. Doing the same thing in this program means rewriting the area to move_data, so in MODE 2 because 1 Byte holds a whole Line (8 Pixels), this routine is faster in MODE 2, compared with MODE 1 or 0, which use more Bytes for a Single Character (as weird as that sounds), which is why it doesn't Roll the Whole Character to the Adjoining Row.


There are other ways of Scrolling, LDI I think is supposed to be Faster, but takes up more memory due to the amount of LDIs needed, I wrote one routine which used LDI, but it was a Vertical rather than Horizontal Scroller.


Really depends on what you're after, Pixel scrolling? Byte scrolling? or Character Scrolling? With Character Scrolling, you're shifting a whole chunk of something from one spot to another, so can be quicker, though may appear jerky, Pixel Scrolling looks smooth, but takes longer to fill a screen.
Title: Re: Scrolling in BASIC
Post by: Morri on 01:22, 22 August 16
Quote from: AMSDOS on 09:23, 21 August 16
Really depends on what you're after, Pixel scrolling? Byte scrolling? or Character Scrolling? With Character Scrolling, you're shifting a whole chunk of something from one spot to another, so can be quicker, though may appear jerky, Pixel Scrolling looks smooth, but takes longer to fill a screen.
Not sure what I want  ::) . I would just make a game to suit the tools I have available.
I would be happy with 4 pixels at a time in mode 1 as long as it was fast enough to avoid flickering which was the only problem with the routine we've been looking at. Was really just wondering if there were other routines available / able to be made for me that I could use in CPC BASIC 3 using CALL's and compatible with ESD2. If so, I have heaps of game ideas that I would explore.
Title: Re: Scrolling in BASIC
Post by: AMSDOS on 11:23, 22 August 16
Quote from: Morri on 01:22, 22 August 16
Not sure what I want  ::) . I would just make a game to suit the tools I have available.
I would be happy with 4 pixels at a time in mode 1 as long as it was fast enough to avoid flickering which was the only problem with the routine we've been looking at. Was really just wondering if there were other routines available / able to be made for me that I could use in CPC BASIC 3 using CALL's and compatible with ESD2. If so, I have heaps of game ideas that I would explore.


I think that converted Assembly can be adjusted to 8 pixels at a time with some rewriting of the "move_data" code, but will probably still result in flickering or Jerky. Flickering was a problem in my game in it's early phase, but was able to eliminate that by not scrolling the screen, but it doesn't have to move a lot of sprites or draw up whole screens, so probably won't work in your situation.


There are other ways of scrolling, lots of Assembly examples unfortunately (since that's the best approach).  I've just been starting to think what Harrier Attack might of used because it only partially Scrolled the Screen, it's in MODE 1, but it appears to shift 8 pixels (2 Bytes), rolling the scenery, only your plane has to be redrawn, which is probably only UDG, unsure if it's Text Mapped or using TAG graphics.


The routines situation is probably where CPC BASIC 3 is going to be limited with the likes of CPCTelera/SDCC/Z88DK. CPC BASIC 3 code can be converted to CCZ80, though I'm unsure what sort of libraries are available. So the scroll routine would have to be coded in Conventional BASIC, Firmware or Independent Scroll Routine unfortunately.
Title: Re: Scrolling in BASIC
Post by: AMSDOS on 04:31, 24 August 16
I've had a look at Harrier Attack and found what appears to be a LDIR routine. I haven't been able to figure out how they get the multiple lines to work and for the section of code I disassembled, there's some other code which may relate to fetching more scenery after the screen has moved, and then it appears another &50 is added to get the next line down and then the whole thing loops around again to do the next line, so I presume that happens until a certain size has been reached, which is the size of the playing field.
Title: Re: Scrolling in BASIC
Post by: AMSDOS on 07:15, 24 August 16
This is what I came up with, which is based around the Harrier Attack code for Horizontally going the screen. I've put it into a BASIC program to show the process, using this approach it's possible to adjust the offset, which determines the jump size and the larger the initial loop the larger the area to scroll. Not a good idea to put something on the last row or it will roll along the whole line (messing up the screen). To Scroll the other direction, the origin label has "defw &c04d" and destination is "defw &c04f" and the program works the rest out.




org &4000


ld hl,(origin)
ld (storeorigin),hl
ld hl,(dest)
ld (storedest),hl




ld b,8 ;; 8 Lines

.scroll
push bc
ld hl,(storeorigin)
ld de,(storedest)


ld b,8 ;; 8 Pixel Lines


.loop
push bc
push hl
push de


ld bc,&4e
ldir

ld bc,&800
pop hl
add hl,bc


ex hl,de
pop hl
add hl,bc


pop bc
djnz loop


ld bc,&50
ld hl,(storeorigin)
add hl,bc
ld (storeorigin),hl


ld hl,(storedest)
add hl,bc
ld (storedest),hl


pop bc
djnz scroll


ret


.origin
defw &c002
.dest
defw &c000
.storeorigin
defw &0000
.storedest
defw &0000





10 MODE 1:GOSUB 1010
20 x%=1
30 WHILE x%<>10
40 FOR y%=1 TO 8
50 LOCATE 39,y%
60 PRINT CHR$(207);
70 NEXT y%
80 CALL &4000
90 CALL &BD19:x%=x%+1
100 WEND:END
1000 ' Horizontal Scroll
1010 MEMORY &3FFF:RESTORE 1070
1020 FOR addr%=&4000 TO &4047
1030   READ a$
1040   POKE addr%,VAL("&"+a$)
1050 NEXT addr%
1060 RETURN
1070 DATA 2A,40,40,22,44,40,2A,42
1080 DATA 40,22,46,40,06,08,C5,2A
1090 DATA 44,40,ED,5B,46,40,06,08
1100 DATA C5,E5,D5,01,4E,00,ED,B0
1110 DATA 01,00,08,E1,09,EB,E1,09
1120 DATA C1,10,ED,01,50,00,2A,44
1130 DATA 40,09,22,44,40,2A,46,40
1140 DATA 09,22,46,40,C1,10,CF,C9
1150 DATA 02,C0,00,C0,00,00,00,00
Title: Re: Scrolling in BASIC
Post by: Morri on 21:10, 24 August 16
Nice work! Question - what values do you need to alter to change the size screen that scrolls and the starting line? For example, only scroll lines 10-20.

I also found the following listing (which I have altered) in Amstrad User Issue 26 for a smooth looking hardware scroll. Just use the arrows to scroll left or right.
Advantage is a very fast smooth scroll. I still need to work out the OUT values for a smooth right scroll (when pressing the left key) as they weren't given.
Disadvantages, scrolls the entire screen with offset effect (changes where LOCATE x,y are). So not so easy to have score panels etc which you would want to be in the same place all the time.


10 MODE 1
20 LOCATE 1,5
30 DATA cd0bbc2323c305bccd0bbc2b2bc305bc
40 oldmem=HIMEM:MEMORY (oldmem-16)
50 READ b$
60 a=HIMEM+1
70 FOR b=1 TO LEN(b$) STEP 2
80 POKE a,VAL("&"+MID$(b$,b,2)):PRINT MID$(b$,b,2)
90 a=a+1
100 NEXT
110 scleft=HIMEM+1:scright=HIMEM+9
120 IF INKEY(=0 THEN GOSUB 160
130 IF INKEY(1)=0 THEN GOSUB 150
140 GOTO 120
150 FRAME:CALL scleft:OUT &BC00,3:OUT &BD00,5:FRAME:OUT &BC00,3:OUT &BD00,&BE:RETURN
160 FRAME:CALL scright:RETURN
Title: Re: Scrolling in BASIC
Post by: AMSDOS on 22:57, 24 August 16
Quote from: Morri on 21:10, 24 August 16
Nice work! Question - what values do you need to alter to change the size screen that scrolls and the starting line? For example, only scroll lines 10-20.


Ok, so using the 16k Screen Map (http://www.cpcwiki.eu/forum/programming/16k-cpc-screen-map/), Line 10 begins at &C2D0, so ".dest" becomes defw &c2d0, and ".origin" can be "defw &c2d1" for example. To move 10 Lines of that is simply changing the number where I've commented ";; 8 Lines", so when "ld b,10" it will only scroll lines 10-20.

QuoteI also found the following listing (which I have altered) in Amstrad User Issue 26 for a smooth looking hardware scroll. Just use the arrows to scroll left or right.
Advantage is a very fast smooth scroll. I still need to work out the OUT values for a smooth right scroll (when pressing the left key) as they weren't given.
Disadvantages, scrolls the entire screen with offset effect (changes where LOCATE x,y are). So not so easy to have score panels etc which you would want to be in the same place all the time.

Yes so that program uses SCR GET LOCATION (&BC0B) & SCR SET OFFSET (&BC05) with a couple of "DEC HLs" or "INC HLs" in between to do a Left or Right Horizontal Roll. The disadvantage as you say, it scrolls the whole screen. Unfortunately I'm rather limited when it comes to the OUT commands, I think in either case the same OUT commands are used, though I had problems when I was trying to convert my program to move the other way.


In the routine I posted earlier, I was moving the screen 2 Bytes at a time (8 pixels in mode 1), so like the program you posted earlier it can be made to shift 1 Byte at a time. I'm unsure if it's faster than the program you posted earlier, but the idea is to take the Left Corner of the screen and roll each Pixel line (so bc holds close the length of the screen "&4e"), once it's done 8 pixel lines of that, the program works out the next line and goes back to do it all again. I think I can improve it though because I don't think I need to PUSH HL or PUSH DE and likewise POP those now (because I'm storing the values for safe keeping).
Title: Re: Scrolling in BASIC
Post by: AMSDOS on 06:45, 25 August 16
Quote from: AMSDOS on 07:15, 24 August 16
To Scroll the other direction, the origin label has "defw &c04d" and destination is "defw &c04f" and the program works the rest out.
I tested this theory out and discovered I was telling a Lie!

In order to Scrol the other way, a whole other Scroll routine is required!


   org &5000

   ld hl,(origin)
   ld (storeorigin),hl
   ld hl,(dest)
   ld (storedest),hl

   ld b,8            ;; 8 Lines

.scroll
   push bc
   ld hl,(storeorigin)
   ld de,(storedest)   

   ld b,8            ;; 8 Pixel Lines

.loop
   push bc
   push hl
   push de

   ld bc,&4e
   lddr
   
   ld bc,&800
   pop hl
   add hl,bc

   ex hl,de
   pop hl
   add hl,bc

   pop bc
   djnz loop

   ld bc,&50
   ld hl,(storeorigin)
   add hl,bc
   ld (storeorigin),hl

   ld hl,(storedest)
   add hl,bc
   ld (storedest),hl

   pop bc
   djnz scroll

   ret   

.origin
   defw &c04d
.dest
   defw &c04f
.storeorigin
   defw &0000
.storedest
   defw &0000



So this one has to use LDDR (which simply counts down along a line - opposite to LDIR), to get the Left to Right motion, though like I said earlier the Right Edge of the Screen is used to create the offset, BC in this case is the same, earlier I had it too big and some other Data just outside the screen area was creeping in.  :-[ 


With this example I've turned it into a CPC BASIC 3, to give you an idea of how fast it runs.

Title: Re: Scrolling in BASIC
Post by: AMSDOS on 08:43, 27 August 16
I have @ervin (http://www.cpcwiki.eu/forum/index.php?action=profile;u=82) help me with some code some years ago to produce a 8x8 playing field and push a larger area through it. With that code, I've been able to make a small example for Horizontally Rolling Left or Right some Scenery.


I guess you could say, it behaves like Green Beret.




10 ' Scroll Scenary Left and Right
20 DIM area%(20,8),playarea%(8,8)
30 GOSUB 3010:GOSUB 1010
40 FOR x%=1 TO 8
50   FOR y%=1 TO 8
60     playarea%(x%,y%)=0
70   NEXT y%
80 NEXT x%
90 MODE 1:INK 0,0:INK 1,25:INK 2,9
100 PLOT 128,398,1
110 DRAW 128,270
120 DRAW 0,270
130 x2%=1:y2%=1:xoffset%=8:xoffset2%=1
140 FOR y%=1 TO 8
150   FOR x%=1 TO 8
160     WHILE playarea%(x%,y%)<>area%(x2%,y2%)
170       playarea%(x%,y%)=area%(x2%,y2%)
180       LOCATE x%,y%
190       IF area%(x2%,y2%)=1 THEN PEN 2:PRINT CHR$(207);
200     WEND
210       x2%=x2%+1
220   NEXT x%
230 y2%=y2%+1
240 x2%=1
250 NEXT y%
260 WHILE INKEY(18)=-1
270   IF NOT(INKEY(1)) AND (xoffset%<20) THEN POKE &401C,&10:POKE &401F,&B0:POKE &4040,&2:POKE &4042,&0:GOSUB 2010
280   IF NOT(INKEY(8)) AND (xoffset2%>1) THEN POKE &401C,&E:POKE &401F,&B8:POKE &4040,&D:POKE &4042,&F:GOSUB 2110
290 WEND
300 PEN 1:END
1000 ' Poke Area Data to Area Array
1010 RESTORE 1080
1020 FOR y%=1 TO 8
1030   FOR x%=1 TO 20
1040     READ area%(x%,y%)
1050   NEXT x%
1060 NEXT y%
1070 RETURN
1080 DATA 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
1090 DATA 1,0,0,0,0,1,0,1,0,0,0,0,1,0,0,0,0,1,0,1
1100 DATA 1,1,1,0,0,1,0,1,1,0,0,1,1,0,0,0,1,1,0,1
1110 DATA 1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1
1120 DATA 1,0,0,1,0,0,0,0,0,0,1,1,0,1,1,1,0,0,0,1
1130 DATA 1,0,1,0,1,0,0,0,0,1,0,0,1,0,1,0,0,0,0,1
1140 DATA 1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1
1150 DATA 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
2000 ' Move Scenary Right
2010 CALL &4000
2020 ORIGIN 0,0,112,126,398,272
2030 CLG
2040 x%=8:xoffset%=xoffset%+1:xoffset2%=xoffset2%+1
2050 FOR y%=1 TO 8
2060   IF area%(xoffset%,y%)=1 THEN LOCATE x%,y%:PRINT CHR$(207);
2070 NEXT y%
2080 RETURN
2100 ' Move Scenary Left
2110 CALL &4000
2120 ORIGIN 0,0,0,14,398,272
2130 CLG
2140 x%=1:xoffset%=xoffset%-1:xoffset2%=xoffset2%-1
2150 FOR y%=1 TO 8
2160   IF area%(xoffset2%,y%)=1 THEN LOCATE x%,y%:PRINT CHR$(207);
2170 NEXT y%
2180 RETURN
3000 ' Poke Scroll Routine to Memory
3010 RESTORE 3070:MEMORY &3FFF
3020 FOR addr%=&4000 TO &4047
3030   READ a$
3040   POKE addr%,VAL("&"+a$)
3050 NEXT addr%
3060 RETURN
3070 DATA 2A,40,40,22,44,40,2A,42
3080 DATA 40,22,46,40,06,08,C5,2A
3090 DATA 44,40,ED,5B,46,40,06,08
3100 DATA C5,E5,D5,01,10,00,ED,B0
3110 DATA 01,00,08,E1,09,EB,E1,09
3120 DATA C1,10,ED,01,50,00,2A,44
3130 DATA 40,09,22,44,40,2A,46,40
3140 DATA 09,22,46,40,C1,10,CF,C9
3150 DATA 02,C0,00,C0,00,00,00,00
Title: Re: Scrolling in BASIC
Post by: AMSDOS on 10:58, 03 September 16
Quote from: AMSDOS on 07:15, 24 August 16



   org &4000


   ld hl,(origin)
   ld (storeorigin),hl
   ld hl,(dest)
   ld (storedest),hl




   ld b,8            ;; 8 Lines
   
.scroll
   push bc
   ld hl,(storeorigin)
   ld de,(storedest)   


   ld b,8            ;; 8 Pixel Lines


.loop
   push bc
   push hl
   push de


   ld bc,&4e
   ldir
   
   ld bc,&800
   pop hl
   add hl,bc


   ex hl,de
   pop hl
   add hl,bc


   pop bc
   djnz loop


   ld bc,&50
   ld hl,(storeorigin)
   add hl,bc
   ld (storeorigin),hl


   ld hl,(storedest)
   add hl,bc
   ld (storedest),hl


   pop bc
   djnz scroll


   ret   


.origin
   defw &c002
.dest
   defw &c000
.storeorigin
   defw &0000
.storedest
   defw &0000

This code I posted earlier can be enhanced by removing the PUSH & POP statements. In this routine I'm unsure how to remove the preservation of BC with PUSH BC / POP BC without adding more code which would be slower than it, other Loops are available in Assembly and it's possible to store values in memory, though requires code to obtain that code, compare it & Jump if a condition is met. With DJNZ I suppose you'd have to:



ld a,b
ld (num),a
....
ld a,(num)
ld b,a
djnz loop



I guess that could work as opposed to push bc / pop bc.


The other push / pop bits of code are used in this scroll routine because LDIR or LDDR alters the values of HL & DE registers, but their only increasing or decreasing the Low Byte. So it's possible to simply:



dec l
dec e



or



inc l
inc e



which only uses 4 clock cycles, as opposed to push / pop which is over 10 clock cycles. But I can't remember which way it's meant to be. I think "dec" can be used for the LDIR because it's increasing HL & DE (which we don't want) and LDDR is decreasing so INC is used I think.
Powered by SMFPacks Menu Editor Mod