CPCWiki forum

General Category => Programming => Topic started by: AMSDOS on 11:52, 29 August 12

Title: Moving Graphical Images Down the Screen.
Post by: AMSDOS on 11:52, 29 August 12
Hi folks,


I've been trying to work on a specific method of moving graphical images down a screen and I came up with this program:


10 MODE 1: RANDOMIZE TIME
20 DIM r%(200),a%(10)
30 r$=CHR$(225)
40 y%=398:p%=(398*RND)+1
50 x%=x%+1:IF x%>200 THEN x%=1
60 r%(x%)=p%
70 MOVE r%(x%),y%
80 TAG:PRINT a$;:TAGOFF
90 y%=y%-1:IF y%>0 THEN GOTO 70
100 GOTO 40



I've managed to get this routine going with a single image moving down the screen, though I'm a bit stumped how I could set this up so I could get multiple images moving down the screen.
I've setup the a% in that program which doesn't do anything at the moment, I thought a second array needs to be used to gather where the multiple images need to be stored. The r% stores the xpos information though perhaps the size of it (200) is questionable.
Title: Re: Moving Graphical Images Down the Screen.
Post by: MacDeath on 14:34, 29 August 12
you mean a vertical scrolling ?
Title: Re: Moving Graphical Images Down the Screen.
Post by: AMSDOS on 09:58, 30 August 12
Quote from: MacDeath on 14:34, 29 August 12
you mean a vertical scrolling ?


The effect might make it seem like vertical scrolling is happening, though what I was looking to recreate is a BASIC demonstration of something which focuses on a series of objects and move them down the screen.


I've already made a routine using LDIR to produce a vertical scrolling effect:


Silly Programming Ideas - Turning Text into Graphics (http://www.cpcwiki.eu/forum/programming/silly-programming-ideas-turning-text-into-graphics/msg48474/#msg48474)


though it's nature is to physically shift the screen which makes everything shift, which also has it's setbacks.


The small BASIC example I've put here in this case is targeting a specific thing and moving it.


I hope that makes sense.


I think for this example I have to think more about setting up more loops and fetching and storing data from an array. Ultimately BASIC will be a bit slow at this :( though it will help me understanding process better (I hope).
Title: Re: Moving Graphical Images Down the Screen.
Post by: AMSDOS on 14:00, 01 September 12
This is what I came up with which is a bit closer to the truth, but it's still buggy, the problem is my pixels make it to the bottom line and then the others which I've displaced are left sitting on the screen stranded.



10 MODE 1:RANDOMIZE TIME
20 DIM x%(50),y%(200)
30 loop%=1:FOR n%=398 TO 0 STEP -2:y%(loop%)=n%:loop%=loop%+1:NEXT n%
31 FOR n%=1 TO 5: GOSUB 2000:NEXT n%
40 n%=1: oldn%=n%:a%=1: olda%=a%
60 GOSUB 1000
80 GOTO 60
1000 FOR z%=1 TO 200
1010 FOR s%=1 TO 200
1020 PLOT x%(n%),y%(a%),1
1021 IF a%>50 THEN PLOT x%(n%+1),y%(a%-50)
1022 IF a%>100 THEN PLOT x%(n%+2),y%(a%-100)
1023 IF a%>150 THEN PLOT x%(n%+3),y%(a%-150)
1030 olda%=a%
1040 IF a%<>200 THEN a%=a%+1
1041 IF a%=200 THEN a%=1
1050 PLOT x%(n%),y%(olda%),0
1051 IF a%>50 THEN PLOT x%(n%+1),y%(olda%-50)
1052 IF a%>100 THEN PLOT x%(n%+2),y%(olda%-100)
1053 IF a%>150 THEN PLOT x%(n%+3),y%(olda%-150)
1060 NEXT s%
1090 NEXT z%
1100 RETURN
2000 p%=(RND*398)+1
2010 x%(n%)=p%
2020 RETURN



I'm a bit over this now given I've spent hours on this program today and it shows.
Title: Re: Moving Graphical Images Down the Screen.
Post by: Border_7 on 06:56, 14 December 12
I only just copied and pasted this into Winape and ran this now.... looks like rain! Only the first three are left on the screen - the fourth one isn't. Why? something different going on there?
Title: Re: Moving Graphical Images Down the Screen.
Post by: AMSDOS on 09:25, 14 December 12
Quote from: Border_7 on 06:56, 14 December 12
I only just copied and pasted this into Winape and ran this now.... looks like rain! Only the first three are left on the screen - the fourth one isn't. Why? something different going on there?


This was my attempt in moving some graphical imagery down the screen in a process I could understand a little better, though as you point out some of the objects are left on the screen. It's got something to do with the fetching cycle, my idea of a fetching cycle and the computers fetching cycle are different. The best example I can think of where this can be applied is a Starfield and I think I've got one somewhere which I'll need to check out because it's not using INK switching to make it look like it's a moving Starfield.


What I was trying to do here was simulate a moving starfield like found in Space Storm 2 which simply moves a single cluster of something without actually moving the screen. :( Handy because you don't need to worry about other objects being moved out of place.  The Game which was in The PC Mag I just sent you I thought was a perfect example of where it could be applied. Though I would of been happier to understand the process, rather than do a rip-off job of Space Storm 2. :(
Title: Re: Moving Graphical Images Down the Screen.
Post by: AMSDOS on 09:48, 10 August 13
With some help from a friend at work with a clear understanding of conditions, I've been able to interpret their Pseudocode into BASIC using the process outlined and then enhanced the program further by making 3 Dimensional Arrays with the 3 parameter relating to each pixel (star) which needs to be moved and simply using a FOR loop to count between those stars and move them to the next position, which is simply down the screen. Using this approach I can plot multiple pixels on the screen and move them accordingly without actually physically moving the screen. So while this example is written in BASIC, I hope that it can be written in other languages to that it will improve results, my only concern with this approach is the 3 Dimensional Array.

10 DIM a%(1,2,10),olda%(1,2,10)
20 FOR n%=1 TO 10:a%(1,1,n%)=(RND*160):a%(1,2,n%)=(RND*398):NEXT n%
30 MODE 0:INK 0,0:INK 1,26
40 WHILE 1
50  FOR n%=1 TO 10
60   olda%(1,1,n%)=a%(1,1,n%):olda%(1,2,n%)=a%(1,2,n%)
70   IF a%(1,2,n%)>2 THEN a%(1,2,n%)=a%(1,2,n%)-2 ELSE tst%=1
80   IF tst%=1 THEN a%(1,1,n%)=(RND*160):a%(1,2,n%)=398:tst%=0
90   PLOT a%(1,1,n%),a%(1,2,n%),1
100  PLOT olda%(1,1,n%),olda%(1,2,n%),0
110 NEXT n%
120 WEND


Title: Re: Moving Graphical Images Down the Screen.
Post by: AMSDOS on 12:25, 31 August 13
This time around what I have done is created an array with an object in it and I'm moving it down the screen, I've made two examples in BASIC (to show the process), the first is text orientated using LOCATE & PRINT (solid block) to position the image, move it's position and redraw it. I'm using 0 from the 3rd Array I've setup (for the Ball Data), to delete the image.

10 DIM ball%(128),oldball%(128),grid%(64)
20 GOSUB 500
30 xn%=1:yn%=1
40 FOR no%=1 TO 128 STEP 2
50  x%=no%:y%=no%+1
60  ball%(x%)=xn%:xn%=xn%+1
70  IF xn%=9 THEN tst%=1:xn%=1
80  ball%(y%)=yn%
90  IF tst%=1 THEN yn%=yn%+1:tst%=0
100  IF yn%=9 THEN yn%=1
110 NEXT no%
120 MODE 0:INK 0,0:INK 1,26
130 WHILE 1:num%=1
140 FOR no%=1 TO 128 STEP 2
150  x%=no%:y%=no%+1
160  IF ball%(y%)<20 THEN ball%(y%)=ball%(y%)+1 ELSE tst%=1
170  IF tst%=1 THEN ball%(y%)=1:tst%=0
180  oldball%(x%)=ball%(x%):oldball%(y%)=ball%(y%)
190  LOCATE ball%(x%),ball%(y%):IF grid%(num%)=1 THEN PRINT CHR$(143);
200  LOCATE oldball%(x%),oldball%(y%):IF grid%(num%)=0 THEN PRINT CHR$(32);
210  num%=num%+1
220 NEXT no%
230 num%=1
240 WEND
500 FOR num%=1 TO 64
510 READ c%
520 grid%(num%)=c%
530 NEXT num%
540 RETURN
550 DATA 0,0,0,0,0,0,0,0
560 DATA 0,0,0,1,1,0,0,0
570 DATA 0,0,1,0,0,1,0,0
580 DATA 0,0,1,0,0,1,0,0
590 DATA 0,0,1,0,0,1,0,0
600 DATA 0,0,1,0,0,1,0,0
610 DATA 0,0,0,1,1,0,0,0
620 DATA 0,0,0,0,0,0,0,0


The second program is a little bit different and to get a similar effect, a few changes had to be taken place with the variables for the effects to take place.

10 DIM ball%(128),oldball%(128),grid%(64)
20 GOSUB 500
30 xn%=0:yn%=398
40 FOR no%=1 TO 128 STEP 2
50  x%=no%:y%=no%+1
60  ball%(x%)=xn%:xn%=xn%+4
70  IF xn%=32 THEN tst%=1:xn%=0
80  ball%(y%)=yn%
90  IF tst%=1 THEN yn%=yn%-2:tst%=0
100  IF yn%=18 THEN yn%=398
110 NEXT no%
120 MODE 0:INK 0,0:INK 1,26
130 WHILE 1:num%=1
140 FOR no%=1 TO 128 STEP 2
150  x%=no%:y%=no%+1
160  IF ball%(y%)>18 THEN ball%(y%)=ball%(y%)-2 ELSE tst%=1
170  IF tst%=1 THEN ball%(y%)=398:tst%=0
180  oldball%(x%)=ball%(x%):oldball%(y%)=ball%(y%)
190  IF grid%(num%)=1 THEN PLOT ball%(x%),ball%(y%),1
200  IF grid%(num%)=0 THEN PLOT oldball%(x%),oldball%(y%),0
210  num%=num%+1
220 NEXT no%
230 num%=1
240 WEND
500 FOR num%=1 TO 64
510 READ c%
520 grid%(num%)=c%
530 NEXT num%
540 RETURN
550 DATA 0,0,0,0,0,0,0,0
560 DATA 0,0,0,1,1,0,0,0
570 DATA 0,0,1,0,0,1,0,0
580 DATA 0,0,1,1,1,1,0,0
590 DATA 0,0,1,0,0,1,0,0
600 DATA 0,0,1,0,0,1,0,0
610 DATA 0,0,0,1,1,0,0,0
620 DATA 0,0,0,0,0,0,0,0


The process may not be much to look at, though with these sort of programs done in other languages, it may be possible to have user designed levels specifically in games or something of that nature which make it look as if the screen is moving around.

I made some attempt at making an Assembly equivalent a couple of weeks ago with the random star version, though I didn't have much luck, but certainly feel to make one if it's no hassle, cause I'd certainly like to see the process.  :D
Title: Re: Moving Graphical Images Down the Screen.
Post by: Devilmarkus on 17:31, 31 August 13
You use very slow routines here.
Is that wanted?
Title: Re: Moving Graphical Images Down the Screen.
Post by: AMSDOS on 22:32, 31 August 13
Quote from: Devilmarkus on 17:31, 31 August 13
You use very slow routines here.
Is that wanted?

Er no. I'm using BASIC to show the process.  :)
The idea here was to make a pattern and move it accordingly, which I've done here successfully.

I can rework it like I reworked the random stars program above so it exists in Pascal and Small-C which will improve the speed of it, though I'm keen to see an Assembly equivalent of it. I'll see if I can use CPC BASIC 3 to knock up something.
Title: Re: Moving Graphical Images Down the Screen.
Post by: AMSDOS on 08:39, 02 September 13
Quote from: Devilmarkus on 17:31, 31 August 13
You use very slow routines here.
Is that wanted?

Yes I see what you mean. I took the second example and used CPC BASIC 3 to make an Assembly file of it, but it was very slow, however the program is wrong in the context I'm writing it for. I don't know why I decided to make a graphical plot version of it now, I was mucking about with the Text Version and perhaps thought the graphical version would present some challenge.  Using it to make an Assembly equivalent of the program was just stupid of me.

The first example with the 8x8 Squares is perhaps a closer representation and wrote that just to see how to move a pattern from an array, though eventually I thought it would be good to use it for generating some sort of Level Data and have that Data (represented as Large 16x16 Sprites) move around the screen without physically moving the screen. I can probably play around with that idea soon and post something in here.
Title: Re: Moving Graphical Images Down the Screen.
Post by: AMSDOS on 12:49, 03 September 13
This is more like what I'm trying to produce:

10 DIM ball%(128),oldball%(128),grid%(64)
20 GOSUB 250
30 xn%=1:yn%=20
40 FOR no%=1 TO 128 STEP 2
50  x%=no%:y%=no%+1
60  ball%(x%)=xn%:xn%=xn%+1
70  IF xn%=9 THEN tst%=1:xn%=1
80  ball%(y%)=yn%
90  IF tst%=1 THEN yn%=yn%-1:tst%=0
100  IF yn%=1 THEN yn%=20
110 NEXT no%
120 MODE 0:INK 0,0:INK 1,26
130 WHILE 1:num%=1
140 FOR no%=1 TO 128 STEP 2
150  x%=no%:y%=no%+1
151  oldball%(x%)=ball%(x%):oldball%(y%)=ball%(y%)
160  IF ball%(y%)>2 THEN ball%(y%)=ball%(y%)-1 ELSE tst%=1
170  IF tst%=1 THEN ball%(y%)=20:tst%=0
190  LOCATE ball%(x%),ball%(y%):IF grid%(num%)=1 THEN PRINT CHR$(143);
200  LOCATE oldball%(x%),oldball%(y%):IF grid%(num%)=1 THEN PRINT" ";
210  num%=num%+1
220 NEXT no%
230 num%=1
240 WEND
250 FOR num%=1 TO 64
260 READ c%
270 grid%(num%)=c%
280 NEXT num%
290 RETURN
300 DATA 0,0,0,0,0,0,0,1
310 DATA 1,0,0,0,0,0,0,0
320 DATA 0,0,1,0,0,1,0,0
330 DATA 0,0,0,0,0,0,0,0
340 DATA 0,1,0,0,0,0,0,0
350 DATA 1,0,1,0,0,0,0,0
360 DATA 0,0,0,1,1,0,0,0
370 DATA 0,0,0,0,0,0,0,1


So in this example I've define a pattern using the array and then that pattern gets moved, this example seems to be faster in BASIC.

Only problem with this example is I've told it to setup the Y-coordinate in Line 30 to be 20, so what happens is when the Data from the Array gets displayed the Y position is reversed - so the top line starts at the bottom and the bottom line at the top for example. So to fix that the setup needs to be altered:

30 xn%=1:yn%=1
90  IF tst%=1 THEN yn%=yn%+1:tst%=0
100  IF yn%=20 THEN yn%=1


But I haven't fixed this in the attached file.
Title: Re: Moving Graphical Images Down the Screen.
Post by: AMSDOS on 10:59, 07 September 13
This is the latest version I've done which is more of an example of making a maze like effect and moving it along.

10 DIM ball%(320),oldball%(320),grid%(160)
20 GOSUB 250
30 xn%=1:yn%=3
40 FOR no%=1 TO 320 STEP 2
50  x%=no%:y%=no%+1
60  ball%(x%)=xn%:xn%=xn%+1
70  IF xn%=9 THEN tst%=1:xn%=1
80  ball%(y%)=yn%
90  IF tst%=1 THEN yn%=yn%+1:tst%=0
110 NEXT no%
120 MODE 0:INK 0,0:INK 1,26
130 num%=1:WHILE 1
140 FOR no%=1 TO 320 STEP 2
150  x%=no%:y%=no%+1
151  oldball%(x%)=ball%(x%):oldball%(y%)=ball%(y%)
160  IF ball%(y%)>2 THEN ball%(y%)=ball%(y%)-1 ELSE tst%=1
170  IF tst%=1 THEN ball%(y%)=24:tst%=0
190  LOCATE ball%(x%),ball%(y%):IF grid%(num%)=1 THEN PRINT CHR$(143)
200  LOCATE oldball%(x%),oldball%(y%):IF grid%(num%)=1 THEN PRINT" "
210  IF num%<160 THEN num%=num%+1
220 NEXT no%
230 IF num%=160 THEN num%=1
240 WEND
250 FOR num%=1 TO 160
260 READ c%
270 grid%(num%)=c%
280 NEXT num%
290 RETURN
300 DATA 0,0,0,0,0,0,0,1
310 DATA 1,0,0,0,0,0,0,0
320 DATA 0,0,1,0,0,1,0,0
330 DATA 0,0,0,0,0,0,0,0
340 DATA 0,1,0,0,0,0,0,0
350 DATA 1,0,1,0,0,0,0,0
360 DATA 0,0,0,1,1,0,0,0
370 DATA 0,0,0,0,0,0,0,1
440 DATA 0,0,0,0,0,0,0,0
450 DATA 0,0,0,0,0,0,0,0
460 DATA 1,0,0,0,0,1,1,1
470 DATA 1,1,1,0,0,0,0,1
480 DATA 1,1,1,0,0,0,0,1
490 DATA 1,0,0,1,1,0,0,1
500 DATA 0,0,0,0,0,0,0,0
520 DATA 0,0,0,0,0,0,0,0
530 DATA 1,0,0,1,0,0,1,1
540 DATA 1,0,0,1,1,0,0,1
550 DATA 1,0,0,0,0,0,0,1
560 DATA 1,1,0,0,1,1,1,1


But I'm having problems with it in regards to what I'm trying to do (but this example works though). The issue I'm having is when I'm trying to limit the size of the moving area to an area of 8x8, the rest of my Maze Data is coming in and overwriting the first bit of the Data for it, which I don't want. What I would like instead is to draw the first bit of the array, move that to a spot and as that moves, move in the next bit of the array to the bottom and the top bit disappears, never to return sort of thing. I know it has something to do with how I've setup the num% variable, which points to the position of the Maze Array (I called it Grid%) and I feel I'm missing some condition and I'm not calculating the next position of that array properly, which I'm having difficulty working out.  Can anyone help please? :'(
Title: Re: Moving Graphical Images Down the Screen.
Post by: AMSDOS on 12:16, 08 September 13
I've had a bit more of a play around with this program above, but it looks like I'll have to go back to the idea of having a 3D Array for this to work, I'm not sure, it's coming up with Subscript out of Range error, even though I'm telling my loop to exit when it's supposed to be going past a certain number.
Title: Re: Moving Graphical Images Down the Screen.
Post by: ervin on 15:05, 08 September 13
Hi there.

I'm not sure what isn't working as I'm not sure what exactly you're trying to do, but I have noticed that line 170 sets ball(y) to 24.
Is that what you want to do?
In the setup in lines 40 to 110, ball(y) maxes out at 22.

You could probably speed things up a little bit by rearranging lines 190 and 200 to look like this:

190  IF grid%(num%)=1 THEN LOCATE ball%(x%),ball%(y%):PRINT CHR$(143)
200  IF grid%(num%)=1 THEN LOCATE oldball%(x%),oldball%(y%):PRINT" "


Also, if you take out the "WHILE 1" in line 130, and change the WEND in 240 to GOTO 130, you can remove 230, and "num" will always reset back to 1 before each run through the FOR loop starting on 140.
You'll also be able to take out the IF check in 210, and simply increment num.

You can also simplify (and make slightly faster) the initialisation code by removing tst%.

40 FOR no%=1 TO 320 STEP 2
50  x%=no%:y%=no%+1
60  ball%(x%)=xn%:ball%(y%)=yn%
70  xn%=xn%+1:IF xn%=9 THEN xn%=1:yn%=yn%+1
110 NEXT no%


On that note, you can remove tst% from lines 160 and 170 (in fact remove 170 altogether), and change 160 to this:

160  IF ball%(y%)>2 THEN ball%(y%)=ball%(y%)-1 ELSE ball%(y%)=24


You can also combine lines 190 and 200, and remove a repeated IF check.

190  IF grid%(num%)=1 THEN LOCATE ball%(x%),ball%(y%):PRINT CHR$(143):LOCATE oldball%(x%),oldball%(y%):PRINT " "


You can do more to speed up your initialisation code:

250 FOR num%=1 TO 160
260 READ grid%(num%)
280 NEXT num%
290 RETURN


Also, I've just noticed that you don't need oldball%(x%) in this code.
Just use ball%(x%).

(I love optimising stuff, and I couldn't resist!)

Here's how the code looks now in my editor:

10 DIM ball%(320),oldball%(320),grid%(160)
20 GOSUB 250
30 xn%=1:yn%=3

40 FOR no%=1 TO 320 STEP 2
50  x%=no%:y%=no%+1
60  ball%(x%)=xn%:ball%(y%)=yn%
70  xn%=xn%+1:IF xn%=9 THEN xn%=1:yn%=yn%+1
110 NEXT no%

120 MODE 0:INK 0,0:INK 1,26

130 num%=1
140 FOR no%=1 TO 320 STEP 2
150  x%=no%:y%=no%+1
151  oldball%(y%)=ball%(y%)
160  IF ball%(y%)>2 THEN ball%(y%)=ball%(y%)-1 ELSE ball%(y%)=22
190  IF grid%(num%)=1 THEN LOCATE ball%(x%),ball%(y%):PRINT CHR$(143):LOCATE ball%(x%),oldball%(y%):PRINT " "
210  num%=num%+1
220 NEXT no%

240 GOTO 130

250 FOR num%=1 TO 160
260 READ grid%(num%)
280 NEXT num%
290 RETURN

300 DATA 0,0,0,0,0,0,0,1
310 DATA 1,0,0,0,0,0,0,0
320 DATA 0,0,1,0,0,1,0,0
330 DATA 0,0,0,0,0,0,0,0
340 DATA 0,1,0,0,0,0,0,0
350 DATA 1,0,1,0,0,0,0,0
360 DATA 0,0,0,1,1,0,0,0
370 DATA 0,0,0,0,0,0,0,1
440 DATA 0,0,0,0,0,0,0,0
450 DATA 0,0,0,0,0,0,0,0
460 DATA 1,0,0,0,0,1,1,1
470 DATA 1,1,1,0,0,0,0,1
480 DATA 1,1,1,0,0,0,0,1
490 DATA 1,0,0,1,1,0,0,1
500 DATA 0,0,0,0,0,0,0,0
520 DATA 0,0,0,0,0,0,0,0
530 DATA 1,0,0,1,0,0,1,1
540 DATA 1,0,0,1,1,0,0,1
550 DATA 1,0,0,0,0,0,0,1
560 DATA 1,1,0,0,1,1,1,1
Title: Re: Moving Graphical Images Down the Screen.
Post by: ervin on 00:50, 09 September 13
Here's a rewritten version that does away with the need for 2 PRINTs for each cell.
I've also discarded the ball% and oldball% arrays.
It's quite a bit faster.


10 dim map%(160),scr%(160)
100 FOR n%=1 TO 160
110 scr%(n%)=0
120 READ map%(n%)
130 NEXT n%
200 MODE 0:INK 0,0:INK 1,26
210 base%=1
300 s%=1:m%=base%
310 for y%=3 to 22
320 for x%=1 to 8
330 if scr%(s%)=map%(m%) then goto 360
340 scr%(s%)=map%(m%)
350 locate x%,y%:if map%(m%)=1 then print chr$(143) else print " "
360 s%=s%+1:m%=m%+1
370 NEXT x%
380 if m%>160 then m%=1
390 next y%
500 base%=base%+8
510 if base%>160 then base%=1
520 goto 300
600 DATA 0,0,0,0,0,0,0,1
610 DATA 1,0,0,0,0,0,0,0
620 DATA 0,0,1,0,0,1,0,0
630 DATA 0,0,0,0,0,0,0,0
640 DATA 0,1,0,0,0,0,0,0
650 DATA 1,0,1,0,0,0,0,0
660 DATA 0,0,0,1,1,0,0,0
670 DATA 0,0,0,0,0,0,0,1
680 DATA 0,0,0,0,0,0,0,0
690 DATA 0,0,0,0,0,0,0,0
700 DATA 1,0,0,0,0,1,1,1
710 DATA 1,1,1,0,0,0,0,1
720 DATA 1,1,1,0,0,0,0,1
730 DATA 1,0,0,1,1,0,0,1
740 DATA 0,0,0,0,0,0,0,0
750 DATA 0,0,0,0,0,0,0,0
760 DATA 1,0,0,1,0,0,1,1
770 DATA 1,0,0,1,1,0,0,1
780 DATA 1,0,0,0,0,0,0,1
790 DATA 1,1,0,0,1,1,1,1
Title: Re: Moving Graphical Images Down the Screen.
Post by: ervin on 01:22, 09 September 13
And here's the 8x8 version.


10 dim map%(160),scr%(64)
100 FOR n%=1 TO 160:READ map%(n%):next n%
110 FOR n%=1 TO 64:scr%(n%)=0:next n%
200 MODE 0:INK 0,0:INK 1,26
210 base%=1
300 s%=1:m%=base%
310 for y%=1 to 8
320 for x%=1 to 8
330 if scr%(s%)=map%(m%) then goto 360
340 scr%(s%)=map%(m%)
350 locate x%,y%:if map%(m%)=1 then print chr$(143) else print " "
360 s%=s%+1:m%=m%+1
370 NEXT x%
380 if m%>160 then m%=1
390 next y%
500 base%=base%+8
510 if base%>160 then base%=1
520 goto 300
600 DATA 0,0,0,0,0,0,0,1
610 DATA 1,0,0,0,0,0,0,0
620 DATA 0,0,1,0,0,1,0,0
630 DATA 0,0,0,0,0,0,0,0
640 DATA 0,1,0,0,0,0,0,0
650 DATA 1,0,1,0,0,0,0,0
660 DATA 0,0,0,1,1,0,0,0
670 DATA 0,0,0,0,0,0,0,1
680 DATA 0,0,0,0,0,0,0,0
690 DATA 0,0,0,0,0,0,0,0
700 DATA 1,0,0,0,0,1,1,1
710 DATA 1,1,1,0,0,0,0,1
720 DATA 1,1,1,0,0,0,0,1
730 DATA 1,0,0,1,1,0,0,1
740 DATA 0,0,0,0,0,0,0,0
750 DATA 0,0,0,0,0,0,0,0
760 DATA 1,0,0,1,0,0,1,1
770 DATA 1,0,0,1,1,0,0,1
780 DATA 1,0,0,0,0,0,0,1
790 DATA 1,1,0,0,1,1,1,1
Title: Re: Moving Graphical Images Down the Screen.
Post by: ervin on 01:46, 09 September 13
Wow... I just compiled the program using CPC Basic 3 (no changes needed in this case), and the speed difference is astonishing!

Despite using the same print routine (I believe locomotive basic and cpc basic 3 both call the firmware for PRINT), the cpc basic 3 version is much, much faster.
Title: Re: Moving Graphical Images Down the Screen.
Post by: AMSDOS on 02:59, 09 September 13
That's Fantastic, thanks very much for doing that.  :)

The 8x8 is the sort of code I'm looking for. I can see the trouble was I was using one variable called num% to try and move through the array that way, but it wasn't working. Originally I had the ball% & oldball% array from when I was using arrays for the graphical Starfield, though Text Based Objects don't need an array to store those sorts of values and as you say it slows things down.
Title: Re: Moving Graphical Images Down the Screen.
Post by: ervin on 03:01, 09 September 13
Cool, glad I could help.
:)

(I was paranoid that I was stepping on your toes a bit).
:-[
Title: Re: Moving Graphical Images Down the Screen.
Post by: ervin on 03:11, 09 September 13
Just out of interest, I replaced the PRINT commands with POKES directly into screen memory.

In Locomotive Basic, it's horrendously slow (MUCH slower than using PRINT). Just shows how slow direct memory access is from Basic!

But in CPC Basic 3... WOW!!!
You'll be amazed at the difference.


10 dim map%(160),scr%(160)
100 FOR n%=1 TO 160
110 scr%(n%)=0
120 READ map%(n%)
130 NEXT n%
200 MODE 0:INK 0,0:INK 1,26
210 base%=1
300 s%=1:m%=base%
301 charAddr=&c0a0
310 for y%=3 to 22
320 for x%=1 to 8
330 if scr%(s%)=map%(m%) then goto 360
340 scr%(s%)=map%(m%)
350 if map%(m%)=1 then colour%=&c0 else colour%=0
351 for addr=0 to &3800 step &800
352 poke charAddr+addr,colour%
353 poke charAddr+addr+1,colour%
354 poke charAddr+addr+2,colour%
355 poke charAddr+addr+3,colour%
356 next addr
360 s%=s%+1:m%=m%+1
365 charAddr=charAddr+4
370 NEXT x%
380 if m%>160 then m%=1
381 charAddr=charAddr-32+&50
390 next y%
500 base%=base%+8
510 if base%>160 then base%=1
520 goto 300
600 DATA 0,0,0,0,0,0,0,1
610 DATA 1,0,0,0,0,0,0,0
620 DATA 0,0,1,0,0,1,0,0
630 DATA 0,0,0,0,0,0,0,0
640 DATA 0,1,0,0,0,0,0,0
650 DATA 1,0,1,0,0,0,0,0
660 DATA 0,0,0,1,1,0,0,0
670 DATA 0,0,0,0,0,0,0,1
680 DATA 0,0,0,0,0,0,0,0
690 DATA 0,0,0,0,0,0,0,0
700 DATA 1,0,0,0,0,1,1,1
710 DATA 1,1,1,0,0,0,0,1
720 DATA 1,1,1,0,0,0,0,1
730 DATA 1,0,0,1,1,0,0,1
740 DATA 0,0,0,0,0,0,0,0
750 DATA 0,0,0,0,0,0,0,0
760 DATA 1,0,0,1,0,0,1,1
770 DATA 1,0,0,1,1,0,0,1
780 DATA 1,0,0,0,0,0,0,1
790 DATA 1,1,0,0,1,1,1,1
Title: Re: Moving Graphical Images Down the Screen.
Post by: ervin on 03:19, 09 September 13
Of course it can be made considerably faster by unrolling the FOR loop that the pokes live in.
(Try this in CPC Basic 3).
8)


10 dim map%(160),scr%(160)
100 FOR n%=1 TO 160
110 scr%(n%)=0
120 READ map%(n%)
130 NEXT n%
200 MODE 0:INK 0,0:INK 1,26
210 base%=1
300 s%=1:m%=base%
301 charAddr=&c0a0
310 for y%=3 to 22
320 for x%=1 to 8
330 if scr%(s%)=map%(m%) then goto 360
340 scr%(s%)=map%(m%)
350 if map%(m%)=1 then colour%=&c0 else colour%=0
351 poke charAddr+0,colour%:poke charAddr+1,colour%:poke charAddr+2,colour%:poke charAddr+3,colour%
352 poke charAddr+&800,colour%:poke charAddr+&801,colour%:poke charAddr+&802,colour%:poke charAddr+&803,colour%
353 poke charAddr+&1000,colour%:poke charAddr+&1001,colour%:poke charAddr+&1002,colour%:poke charAddr+&1003,colour%
354 poke charAddr+&1800,colour%:poke charAddr+&1801,colour%:poke charAddr+&1802,colour%:poke charAddr+&1803,colour%
355 poke charAddr+&2000,colour%:poke charAddr+&2001,colour%:poke charAddr+&2002,colour%:poke charAddr+&2003,colour%
356 poke charAddr+&2800,colour%:poke charAddr+&2801,colour%:poke charAddr+&2802,colour%:poke charAddr+&2803,colour%
357 poke charAddr+&3000,colour%:poke charAddr+&3001,colour%:poke charAddr+&3002,colour%:poke charAddr+&3003,colour%
358 poke charAddr+&3800,colour%:poke charAddr+&3801,colour%:poke charAddr+&3802,colour%:poke charAddr+&3803,colour%
360 s%=s%+1:m%=m%+1
365 charAddr=charAddr+4
370 NEXT x%
380 if m%>160 then m%=1
381 charAddr=charAddr-32+&50
390 next y%
500 base%=base%+8
510 if base%>160 then base%=1
520 goto 300
600 DATA 0,0,0,0,0,0,0,1
610 DATA 1,0,0,0,0,0,0,0
620 DATA 0,0,1,0,0,1,0,0
630 DATA 0,0,0,0,0,0,0,0
640 DATA 0,1,0,0,0,0,0,0
650 DATA 1,0,1,0,0,0,0,0
660 DATA 0,0,0,1,1,0,0,0
670 DATA 0,0,0,0,0,0,0,1
680 DATA 0,0,0,0,0,0,0,0
690 DATA 0,0,0,0,0,0,0,0
700 DATA 1,0,0,0,0,1,1,1
710 DATA 1,1,1,0,0,0,0,1
720 DATA 1,1,1,0,0,0,0,1
730 DATA 1,0,0,1,1,0,0,1
740 DATA 0,0,0,0,0,0,0,0
750 DATA 0,0,0,0,0,0,0,0
760 DATA 1,0,0,1,0,0,1,1
770 DATA 1,0,0,1,1,0,0,1
780 DATA 1,0,0,0,0,0,0,1
790 DATA 1,1,0,0,1,1,1,1
Title: Re: Moving Graphical Images Down the Screen.
Post by: AMSDOS on 06:34, 09 September 13
Quote from: ervin on 03:01, 09 September 13
Cool, glad I could help.
:)

(I was paranoid that I was stepping on your toes a bit).
:-[

Not at all, I'm only trying to get an idea of the approach used in making a redefined maze so that anyone could implement it possibly to their language.

I think this code is extremely useful and you were even able to optimise the code, something I'm not terribly good at because I turn to Compiled Languages or Assembly if I want to enhance code.
I think it's good to be able to show the process and doing it in BASIC will allow people to see a working version of the program, earlier on I was able to take the Starfield routine and write it into Pascal & Small-C, which also took advantage of those routines when they were converted into Machine Code.
The CPC BASIC 3 situation has done the same thing and indeed using a printing workaround with POKE instead of PRINT I think means you're using LD instructions instead of the firmware &BB5A for TXT OUTPUT, I'm unsure if CPC BASIC 3 uses TXT OUTPUT in conjunction with PRINT, though the alternative is to use TXT WR CHAR (&BB5D), which does the same thing, though doesn't preserve the registers, which I think makes it a little bit faster.
Title: Re: Moving Graphical Images Down the Screen.
Post by: ervin on 06:44, 09 September 13
Interesting... CPC Basic 3 compiles to CCZ80 before compiling to machine code.
CCZ80 is my CPC language of choice, so I had a look at the generated code... and I felt right at home.

I converted the code that writes direct to VRAM (the equivalent of the POKEs in the Basic code) into hastily optimised inline assembly, and now it is running at around 27 fps!
Title: Re: Moving Graphical Images Down the Screen.
Post by: AMSDOS on 07:06, 09 September 13
Quote from: ervin on 06:44, 09 September 13
Interesting... CPC Basic 3 compiles to CCZ80 before compiling to machine code.
CCZ80 is my CPC language of choice, so I had a look at the generated code... and I felt right at home.

I converted the code that writes direct to VRAM (the equivalent of the POKEs in the Basic code) into hastily optimised inline assembly, and now it is running at around 27 fps!

Yeah, I had a little look at that and generated some CCZ80 Source Code Files which look pretty good, I haven't had much to do with CCZ80, though I should be able to take that BASIC code and make working versions of it from Pascal & Small-C. Don't know if they will be running at 27 fps, how do you measure the fps?
Title: Re: Moving Graphical Images Down the Screen.
Post by: ervin on 07:35, 09 September 13
If you do decide to delve into CCZ80, there are some gotchas related to low-level operations.

It looks like C, and behaves like it in many ways, but it's actually simpler. It's like a pre-C language in some ways, that feels like it has some feet in the assembler pond, though it doesn't actually involve assembly language unless you need to inline it.

The upshot of this is that it produces fast binaries!
If you decide to try it and have any questions, feel free to ask away!

My fps testing method is not very scientific. It's fairly accurate, but it's not perfect.
:)

I have an 8-bit counter variable (data type BYTE in ccz80 terms), which I set to 0 at the start of the program.
After a frame of my game/program is displayed, I increment the counter variable, and print it to the screen.


counter++;
locate(18,25);
printb(counter);


Now, I use an ULTRA HIGH TECH method called... the stopwatch!
(Well, the stopwatch app on my phone).  8)
At the same moment I hit Enter to run my program, I also start the stopwatch.
When the counter gets to 250, I stop the stopwatch, and take note of the time elapsed.

Now, this program I've been looking at today takes 12.6 seconds to render 250 frames.
However, I know that calling PRINTB 250 times takes 3.5 seconds.
I know this because putting in a second PRINTB alongside the first one makes the program take 3.5 seconds longer to get to 250 frames.
So, I subtract the 3.5 seconds because I don't want that being factored into the fps. That leaves 9.1 seconds.

250 frames in 9.1 seconds is approx 27 fps.

It's not ultra precise, but it's a handy way to check that optimisations are going in the right direction.
Title: Re: Moving Graphical Images Down the Screen.
Post by: AMSDOS on 08:25, 09 September 13
Quote from: ervin on 07:35, 09 September 13
If you do decide to delve into CCZ80, there are some gotchas related to low-level operations.

It looks like C, and behaves like it in many ways, but it's actually simpler. It's like a pre-C language in some ways, that feels like it has some feet in the assembler pond, though it doesn't actually involve assembly language unless you need to inline it.

The upshot of this is that it produces fast binaries!
If you decide to try it and have any questions, feel free to ask away!

It looks interesting, though I don't seem to have much time have a look at it properly and seem to play around with the old languages found on Amstrad.  :D Though I was wondering how good the Assembly files were compared with CPC BASIC 3, or are they sort of on par with one another? The Assembly Files produced with CPC BASIC 3 are okay, though a bit of a nightmare trying to get them to work in Winape Assembler.

QuoteMy fps testing method is not very scientific. It's fairly accurate, but it's not perfect.
:)

I have an 8-bit counter variable (data type BYTE in ccz80 terms), which I set to 0 at the start of the program.
After a frame of my game/program is displayed, I increment the counter variable, and print it to the screen.


counter++;
locate(18,25);
printb(counter);


Now, I use an ULTRA HIGH TECH method called... the stopwatch!
(Well, the stopwatch app on my phone).  8)
At the same moment I hit Enter to run my program, I also start the stopwatch.
When the counter gets to 250, I stop the stopwatch, and take note of the time elapsed.

Now, this program I've been looking at today takes 12.6 seconds to render 250 frames.
However, I know that calling PRINTB 250 times takes 3.5 seconds.
I know this because putting in a second PRINTB alongside the first one makes the program take 3.5 seconds longer to get to 250 frames.
So, I subtract the 3.5 seconds because I don't want that being factored into the fps. That leaves 9.1 seconds.

250 frames in 9.1 seconds is approx 27 fps.

It's not ultra precise, but it's a handy way to check that optimisations are going in the right direction.

That's interesting. So I presume that if the playing field was smaller like the 8x8 example and POKEs were used instead of PRINT, then the fps would be higher? I guess that would explain why a lot of the later Amstrad games used Spectrum size screen to increase the speed of the game.
Title: Re: Moving Graphical Images Down the Screen.
Post by: ervin on 14:59, 09 September 13
The asm files produced by each one are largely on par, though CPC Basic 3-produced asm files seem to involve some wrapper functions which may slow them down a tad.
Though any slowdown may be un-noticable in real-world scenarios.

If you find CPC Basic 3 easier to use, I have no hesitation recommending it.
Except that its handling of REAL numbers can be kind of tricky (REAL number functions are handled as RSXs and require a bit of tricky setup to get working).

Regarding the fps, 8*8 would indeed be considerably faster than 8*20.
I'll try to measure the difference tomorrow (I left the ccz80 code on my work network, and don't have access to it now!)

In the case of games, yes indeed, spectrum-sized screens are certainly faster than full cpc-sized screens to redraw.
Even so, a spectrum-sized screen on the cpc is still considerably heavier on the cpu than the same sized screen would be on the speccy.
In fact, for the same sized screen, the cpc's screen would need around twice the number of bytes written to memory, not taking the speccy's colour attribute table into account.

I believe this is the primary reason why speccy games are pretty much always faster (some considerably so) than the amstrad version of the same game. There are some exceptions of course, but they are typically games that may use the cpc's hardware scroll to relieve the load on the z80, and to be honest I can't think of any examples right now!

[EDIT] Using the ccz80 version with optimised inlined assembler, on an 8*8 display, I seem to be getting 65-70 fps! It certainly looks amazingly quick!

Here's the ccz80 code:


include "cpc6128.ccz80", "cpcbasic.ccz80";

array word Data_00600 = { "0", "0", "0", "0", "0", "0", "0", "1" };
array word Data_00610 = { "1", "0", "0", "0", "0", "0", "0", "0" };
array word Data_00620 = { "0", "0", "1", "0", "0", "1", "0", "0" };
array word Data_00630 = { "0", "0", "0", "0", "0", "0", "0", "0" };
array word Data_00640 = { "0", "1", "0", "0", "0", "0", "0", "0" };
array word Data_00650 = { "1", "0", "1", "0", "0", "0", "0", "0" };
array word Data_00660 = { "0", "0", "0", "1", "1", "0", "0", "0" };
array word Data_00670 = { "0", "0", "0", "0", "0", "0", "0", "1" };
array word Data_00680 = { "0", "0", "0", "0", "0", "0", "0", "0" };
array word Data_00690 = { "0", "0", "0", "0", "0", "0", "0", "0" };
array word Data_00700 = { "1", "0", "0", "0", "0", "1", "1", "1" };
array word Data_00710 = { "1", "1", "1", "0", "0", "0", "0", "1" };
array word Data_00720 = { "1", "1", "1", "0", "0", "0", "0", "1" };
array word Data_00730 = { "1", "0", "0", "1", "1", "0", "0", "1" };
array word Data_00740 = { "0", "0", "0", "0", "0", "0", "0", "0" };
array word Data_00750 = { "0", "0", "0", "0", "0", "0", "0", "0" };
array word Data_00760 = { "1", "0", "0", "1", "0", "0", "1", "1" };
array word Data_00770 = { "1", "0", "0", "1", "1", "0", "0", "1" };
array word Data_00780 = { "1", "0", "0", "0", "0", "0", "0", "1" };
array word Data_00790 = { "1", "1", "0", "0", "1", "1", "1", "1" };

byte VarByte_Base;
word VarWord_Charaddr;
byte VarByte_Colour;
byte VarByte_M;
byte VarByte_N;
byte VarByte_S;
byte VarByte_X;
byte VarByte_Y;

byte counter;
counter=0;

array byte TabByte_Map[161 * 1];
// array byte TabByte_Scr[161 * 1];
array byte TabByte_Scr[65 * 1];

SetDataPointer(Data_00600);

for (VarByte_N = 1; 160 >= VarByte_N; ++VarByte_N)
  *(TabByte_Map + VarByte_N) = Val(Data());

// for (VarByte_N = 1; 160 >= VarByte_N; ++VarByte_N)
//   *(TabByte_Scr + VarByte_N) = 0;

for (VarByte_N = 1; 64 >= VarByte_N; ++VarByte_N)
  *(TabByte_Scr + VarByte_N) = 0;

Mode(0);
Ink(0, 0, 0);
Ink(1, 26, 26);

VarByte_Base = 1;

Line_00300:
VarByte_S = 1;
VarByte_M = VarByte_Base;
VarWord_Charaddr = 49312;

// for (VarByte_Y = 3; 22 >= VarByte_Y; ++VarByte_Y)
for (VarByte_Y = 1; 8 >= VarByte_Y; ++VarByte_Y)
{
  for (VarByte_X = 1; 8 >= VarByte_X; ++VarByte_X)
  {
    if (*(TabByte_Scr + VarByte_S) == *(TabByte_Map + VarByte_M))
      GoTo Line_00360;

    *(TabByte_Scr + VarByte_S) = *(TabByte_Map + VarByte_M);

    if (*(TabByte_Map + VarByte_M) == 1)
      VarByte_Colour = 192;
    else
      VarByte_Colour = 0;

    asm
    {
      "ld a,(_VarByte_Colour)",
      "ld bc,2048",
      "ld de,8192",

      "ld hl,(_VarWord_Charaddr)","ld (hl),a",
      "inc hl","ld (hl),a",
      "inc hl","ld (hl),a",
      "inc hl","ld (hl),a",

      "ld hl,(_VarWord_Charaddr)","add hl,bc","ld (hl),a",
      "inc hl","ld (hl),a",
      "inc hl","ld (hl),a",
      "inc hl","ld (hl),a",

      "ld hl,(_VarWord_Charaddr)","add hl,bc","add hl,bc","ld (hl),a",
      "inc hl","ld (hl),a",
      "inc hl","ld (hl),a",
      "inc hl","ld (hl),a",

      "ld hl,(_VarWord_Charaddr)","add hl,bc","add hl,bc","add hl,bc","ld (hl),a",
      "inc hl","ld (hl),a",
      "inc hl","ld (hl),a",
      "inc hl","ld (hl),a",

      "ld hl,(_VarWord_Charaddr)","add hl,de","ld (hl),a",
      "inc hl","ld (hl),a",
      "inc hl","ld (hl),a",
      "inc hl","ld (hl),a",

      "ld hl,(_VarWord_Charaddr)","add hl,de","add hl,bc","ld (hl),a",
      "inc hl","ld (hl),a",
      "inc hl","ld (hl),a",
      "inc hl","ld (hl),a",

      "ld hl,(_VarWord_Charaddr)","add hl,de","add hl,bc","add hl,bc","ld (hl),a",
      "inc hl","ld (hl),a",
      "inc hl","ld (hl),a",
      "inc hl","ld (hl),a",

      "ld hl,(_VarWord_Charaddr)","add hl,de","add hl,bc","add hl,bc","add hl,bc","ld (hl),a",
      "inc hl","ld (hl),a",
      "inc hl","ld (hl),a",
      "inc hl","ld (hl),a",
    }

Line_00360:
    VarByte_S = (VarByte_S + 1);
    VarByte_M = (VarByte_M + 1);
    VarWord_Charaddr = (VarWord_Charaddr + 4);
  }

  if (VarByte_M > 160)
    VarByte_M = 1;

  VarWord_Charaddr = ((VarWord_Charaddr - 32) + 80);
}

VarByte_Base = (VarByte_Base + 8);

if (VarByte_Base > 160)
  VarByte_Base = 1;

// counter++;
// locate(16,25);
// printb(counter);

GoTo Line_00300;

return;

Title: Re: Moving Graphical Images Down the Screen.
Post by: AMSDOS on 11:20, 10 September 13
Quote from: ervin on 14:59, 09 September 13
The asm files produced by each one are largely on par, though CPC Basic 3-produced asm files seem to involve some wrapper functions which may slow them down a tad.
Though any slowdown may be un-noticable in real-world scenarios.

You'll have to excuse my whinging cause I like to see neat and tidy Assembly source code, and I like to see Data in DEFB or DEFW statements and not DEFB or DEFW statements which points to a variable which points to a value that way which just looks messy.  :'(

QuoteIf you find CPC Basic 3 easier to use, I have no hesitation recommending it.
Except that its handling of REAL numbers can be kind of tricky (REAL number functions are handled as RSXs and require a bit of tricky setup to get working).

I can probably do some mockup in CPC BASIC 3, the next phase will be using Sprites, just trying to remember the dimensions of the sprites cause they were larger than 8x8, I think they were 16x16, the one I'm using for the Square blocks I think is 16x16, so will be able to space them or just space the X & Y variables.
I was also going to play around with this in Hisoft Pascal, though the easiest way to make level data to get it into an array (cause it doesn't support constant array's), is to write the data into assembly, save it, convert it to a Hisoft file to load into an array, which I have made programs to do this.

QuoteRegarding the fps, 8*8 would indeed be considerably faster than 8*20.
I'll try to measure the difference tomorrow (I left the ccz80 code on my work network, and don't have access to it now!)

In the case of games, yes indeed, spectrum-sized screens are certainly faster than full cpc-sized screens to redraw.
Even so, a spectrum-sized screen on the cpc is still considerably heavier on the cpu than the same sized screen would be on the speccy.
In fact, for the same sized screen, the cpc's screen would need around twice the number of bytes written to memory, not taking the speccy's colour attribute table into account.

I believe this is the primary reason why speccy games are pretty much always faster (some considerably so) than the amstrad version of the same game. There are some exceptions of course, but they are typically games that may use the cpc's hardware scroll to relieve the load on the z80, and to be honest I can't think of any examples right now!

So if an Amstrad adjusted the size of the screen to a Spectrum screen, it slows it down normally, but if the screen remained as an Amstrad standard screen, but was made to look like a Spectrum Size screen, it would run faster?

Quote[EDIT] Using the ccz80 version with optimised inlined assembler, on an 8*8 display, I seem to be getting 65-70 fps! It certainly looks amazingly quick!

Here's the ccz80 code:


include "cpc6128.ccz80", "cpcbasic.ccz80";

array word Data_00600 = { "0", "0", "0", "0", "0", "0", "0", "1" };
array word Data_00610 = { "1", "0", "0", "0", "0", "0", "0", "0" };
array word Data_00620 = { "0", "0", "1", "0", "0", "1", "0", "0" };
array word Data_00630 = { "0", "0", "0", "0", "0", "0", "0", "0" };
array word Data_00640 = { "0", "1", "0", "0", "0", "0", "0", "0" };
array word Data_00650 = { "1", "0", "1", "0", "0", "0", "0", "0" };
array word Data_00660 = { "0", "0", "0", "1", "1", "0", "0", "0" };
array word Data_00670 = { "0", "0", "0", "0", "0", "0", "0", "1" };
array word Data_00680 = { "0", "0", "0", "0", "0", "0", "0", "0" };
array word Data_00690 = { "0", "0", "0", "0", "0", "0", "0", "0" };
array word Data_00700 = { "1", "0", "0", "0", "0", "1", "1", "1" };
array word Data_00710 = { "1", "1", "1", "0", "0", "0", "0", "1" };
array word Data_00720 = { "1", "1", "1", "0", "0", "0", "0", "1" };
array word Data_00730 = { "1", "0", "0", "1", "1", "0", "0", "1" };
array word Data_00740 = { "0", "0", "0", "0", "0", "0", "0", "0" };
array word Data_00750 = { "0", "0", "0", "0", "0", "0", "0", "0" };
array word Data_00760 = { "1", "0", "0", "1", "0", "0", "1", "1" };
array word Data_00770 = { "1", "0", "0", "1", "1", "0", "0", "1" };
array word Data_00780 = { "1", "0", "0", "0", "0", "0", "0", "1" };
array word Data_00790 = { "1", "1", "0", "0", "1", "1", "1", "1" };

byte VarByte_Base;
word VarWord_Charaddr;
byte VarByte_Colour;
byte VarByte_M;
byte VarByte_N;
byte VarByte_S;
byte VarByte_X;
byte VarByte_Y;

byte counter;
counter=0;

array byte TabByte_Map[161 * 1];
// array byte TabByte_Scr[161 * 1];
array byte TabByte_Scr[65 * 1];

SetDataPointer(Data_00600);

for (VarByte_N = 1; 160 >= VarByte_N; ++VarByte_N)
  *(TabByte_Map + VarByte_N) = Val(Data());

// for (VarByte_N = 1; 160 >= VarByte_N; ++VarByte_N)
//   *(TabByte_Scr + VarByte_N) = 0;

for (VarByte_N = 1; 64 >= VarByte_N; ++VarByte_N)
  *(TabByte_Scr + VarByte_N) = 0;

Mode(0);
Ink(0, 0, 0);
Ink(1, 26, 26);

VarByte_Base = 1;

Line_00300:
VarByte_S = 1;
VarByte_M = VarByte_Base;
VarWord_Charaddr = 49312;

// for (VarByte_Y = 3; 22 >= VarByte_Y; ++VarByte_Y)
for (VarByte_Y = 1; 8 >= VarByte_Y; ++VarByte_Y)
{
  for (VarByte_X = 1; 8 >= VarByte_X; ++VarByte_X)
  {
    if (*(TabByte_Scr + VarByte_S) == *(TabByte_Map + VarByte_M))
      GoTo Line_00360;

    *(TabByte_Scr + VarByte_S) = *(TabByte_Map + VarByte_M);

    if (*(TabByte_Map + VarByte_M) == 1)
      VarByte_Colour = 192;
    else
      VarByte_Colour = 0;

    asm
    {
      "ld a,(_VarByte_Colour)",
      "ld bc,2048",
      "ld de,8192",

      "ld hl,(_VarWord_Charaddr)","ld (hl),a",
      "inc hl","ld (hl),a",
      "inc hl","ld (hl),a",
      "inc hl","ld (hl),a",

      "ld hl,(_VarWord_Charaddr)","add hl,bc","ld (hl),a",
      "inc hl","ld (hl),a",
      "inc hl","ld (hl),a",
      "inc hl","ld (hl),a",

      "ld hl,(_VarWord_Charaddr)","add hl,bc","add hl,bc","ld (hl),a",
      "inc hl","ld (hl),a",
      "inc hl","ld (hl),a",
      "inc hl","ld (hl),a",

      "ld hl,(_VarWord_Charaddr)","add hl,bc","add hl,bc","add hl,bc","ld (hl),a",
      "inc hl","ld (hl),a",
      "inc hl","ld (hl),a",
      "inc hl","ld (hl),a",

      "ld hl,(_VarWord_Charaddr)","add hl,de","ld (hl),a",
      "inc hl","ld (hl),a",
      "inc hl","ld (hl),a",
      "inc hl","ld (hl),a",

      "ld hl,(_VarWord_Charaddr)","add hl,de","add hl,bc","ld (hl),a",
      "inc hl","ld (hl),a",
      "inc hl","ld (hl),a",
      "inc hl","ld (hl),a",

      "ld hl,(_VarWord_Charaddr)","add hl,de","add hl,bc","add hl,bc","ld (hl),a",
      "inc hl","ld (hl),a",
      "inc hl","ld (hl),a",
      "inc hl","ld (hl),a",

      "ld hl,(_VarWord_Charaddr)","add hl,de","add hl,bc","add hl,bc","add hl,bc","ld (hl),a",
      "inc hl","ld (hl),a",
      "inc hl","ld (hl),a",
      "inc hl","ld (hl),a",
    }

Line_00360:
    VarByte_S = (VarByte_S + 1);
    VarByte_M = (VarByte_M + 1);
    VarWord_Charaddr = (VarWord_Charaddr + 4);
  }

  if (VarByte_M > 160)
    VarByte_M = 1;

  VarWord_Charaddr = ((VarWord_Charaddr - 32) + 80);
}

VarByte_Base = (VarByte_Base + 8);

if (VarByte_Base > 160)
  VarByte_Base = 1;

// counter++;
// locate(16,25);
// printb(counter);

GoTo Line_00300;

return;


That's just nuts, sounds like a pretty difficult game, may have to adjust the level data around cause that information looks like it would work well on one of the later levels.  :o
Title: Re: Moving Graphical Images Down the Screen.
Post by: ervin on 14:05, 10 September 13
Quote from: AMSDOS on 11:20, 10 September 13
So if an Amstrad adjusted the size of the screen to a Spectrum screen, it slows it down normally, but if the screen remained as an Amstrad standard screen, but was made to look like a Spectrum Size screen, it would run faster?

No, that's not quite how it works.
It's all about how many bytes need to be written to video ram in order to display a frame.

Reading back my previous message, I can see that I kind of rambled on a bit (I do that from time to time, sorry about that).
Because the spectrum screen takes between 6 and 7 KB (I can't remember the exact figure), and the cpc screen takes up 16KB, it simply takes longer to paint graphics on the cpc than it does on the spectrum, because more bytes need to be written to.

So a number of tricks and techniques need to be employed to speed up the display of sprites etc.
You used one of those techniques in your program - only update parts of the screen that have changed.

Yes, you're right about the messy tables in the ccz80 code I posted.
I largely left the generated code alone (from compiling with cpc basic 3), so it still contains a number of cpc basic 3 wrappers.
I'll have a go at removing some of those and see what happens...
Title: Re: Moving Graphical Images Down the Screen.
Post by: ervin on 15:21, 10 September 13
Okay, the 20*8 version is now running at 31 fps.
I removed the CPC Basic 3 wrapper functions, and optimised things a bit further.


include "cpc6128.ccz80";

byte counter;
counter=0;

byte base;
byte colour;
byte n;

word charPtr;
word mapPtr;
word scrPtr;

array byte scr[160];

array byte map={
0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,
0,0,1,0,0,1,0,0,
0,0,0,0,0,0,0,0,
0,1,0,0,0,0,0,0,
1,0,1,0,0,0,0,0,
0,0,0,1,1,0,0,0,
0,0,0,0,0,0,0,1,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
1,0,0,0,0,1,1,1,
1,1,1,0,0,0,0,1,
1,1,1,0,0,0,0,1,
1,0,0,1,1,0,0,1,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
1,0,0,1,0,0,1,1,
1,0,0,1,1,0,0,1,
1,0,0,0,0,0,0,1,
1,1,0,0,1,1,1,1,
};

for (n=0;n<=159;n++)
  *(scr+n)=0;

base=0;

mode(0);
ink(0, 0, 0);
ink(1, 26, 26);

LINE_00300:

charPtr=#c0a0;
mapPtr=map+base;
scrPtr=scr;

repeat(20) // 20 rows
{
  repeat( // 8 columns
  {
    if (*(scrPtr)==*(mapPtr))
      goto LINE_00360;

    *(scrPtr)=*(mapPtr);

    if (*(mapPtr)==0)
      colour=0;
    else
      colour=#c0;

    asm
    {
    "ld a,(_colour)",
    "ld bc,2048",
    "ld de,8192",

    "ld hl,(_charPtr)","ld (hl),a",
    "inc hl","ld (hl),a",
    "inc hl","ld (hl),a",
    "inc hl","ld (hl),a",

    "ld hl,(_charPtr)","add hl,bc","ld (hl),a",
    "inc hl","ld (hl),a",
    "inc hl","ld (hl),a",
    "inc hl","ld (hl),a",

    "ld hl,(_charPtr)","add hl,bc","add hl,bc","ld (hl),a",
    "inc hl","ld (hl),a",
    "inc hl","ld (hl),a",
    "inc hl","ld (hl),a",

    "ld hl,(_charPtr)","add hl,bc","add hl,bc","add hl,bc","ld (hl),a",
    "inc hl","ld (hl),a",
    "inc hl","ld (hl),a",
    "inc hl","ld (hl),a",

    "ld hl,(_charPtr)","add hl,de","ld (hl),a",
    "inc hl","ld (hl),a",
    "inc hl","ld (hl),a",
    "inc hl","ld (hl),a",

    "ld hl,(_charPtr)","add hl,de","add hl,bc","ld (hl),a",
    "inc hl","ld (hl),a",
    "inc hl","ld (hl),a",
    "inc hl","ld (hl),a",

    "ld hl,(_charPtr)","add hl,de","add hl,bc","add hl,bc","ld (hl),a",
    "inc hl","ld (hl),a",
    "inc hl","ld (hl),a",
    "inc hl","ld (hl),a",

    "ld hl,(_charPtr)","add hl,de","add hl,bc","add hl,bc","add hl,bc","ld (hl),a",
    "inc hl","ld (hl),a",
    "inc hl","ld (hl),a",
    "inc hl","ld (hl),a",
    }

LINE_00360:

    charPtr+=4;
    mapPtr++;
    scrPtr++;
  }

  if (mapPtr==(map+160))
    mapPtr=map;

  charPtr+=80-32;
}

base+=8;

if (base==160)
  base=0;

// counter++;
// locate(16,25);
// printb(counter);

goto LINE_00300;

return;
Title: Re: Moving Graphical Images Down the Screen.
Post by: AMSDOS on 11:51, 11 September 13
I'm having a look at the earlier BASIC code to see how I could write it in Assembly, at the moment I'm unsure how successful it will be writing it straight into Assembly cause I haven't really compared the contents of Array's before and do a jump based on that. Other little things will need to be changed too I think, to do with the start value for the array. I could probably gather some assembly code from CPC BASIC 3 which reflects how assembly tackles, if I need clues.
Title: Re: Moving Graphical Images Down the Screen.
Post by: ervin on 13:19, 11 September 13
As I've been learning assembly, I've found the asm files spat out by ccz80 to be incredibly helpful.
It leaves the actual ccz80 code in the comments, and the relevant asm code is placed with each commented-out bit of ccz80 code.
This of course means the entire program is broken down into small blocks of asm, which is very easy to learn from and understand.
(Also helps with a bit of optimisation).

So yes, using the asm generated by CPC Basic 3 will be very useful indeed.
The only thing to watch out for is that CPC Basic 3 compiles to ccz80 code, with some Basic-related wrapper functions.
This is then compiled into a binary file (and is where the asm is derived from).

Good luck!
(I'm happy to help if you need any ideas/tips - I'm enjoying this stuff).
Title: Re: Moving Graphical Images Down the Screen.
Post by: AMSDOS on 14:06, 13 September 13
Quote from: ervin on 13:19, 11 September 13
As I've been learning assembly, I've found the asm files spat out by ccz80 to be incredibly helpful.
It leaves the actual ccz80 code in the comments, and the relevant asm code is placed with each commented-out bit of ccz80 code.
This of course means the entire program is broken down into small blocks of asm, which is very easy to learn from and understand.
(Also helps with a bit of optimisation).

So yes, using the asm generated by CPC Basic 3 will be very useful indeed.
The only thing to watch out for is that CPC Basic 3 compiles to ccz80 code, with some Basic-related wrapper functions.
This is then compiled into a binary file (and is where the asm is derived from).

Good luck!
(I'm happy to help if you need any ideas/tips - I'm enjoying this stuff).

Well this is what I have at the moment:


org &4000

ld a,0
ld bc,0
call &bc32
ld a,1
ld bc,&1a1a
call &bc32

.setbase
ld a,(isone)
ld (base),a

.return ld a,(isone)
ld (s),a
ld a,(base)
ld (m),a

.y_loop ld a,(y)
inc a
ld (y),a

.x_loop ld a,(x)
inc a
ld (x),a

ld hl,scr
ld a,(s)
ld c,a
ld b,0
add hl,bc
push hl
ld hl,map
ld a,(m)
ld c,a
ld b,0
add hl,bc
ld a,(hl)
pop hl
cp (hl)
jr z,skip

ld hl,map
ld a,(m)
ld c,a
ld b,0
add hl,bc
ex hl,de
ld hl,scr
ld a,(s)
ld c,a
ld b,0
add hl,bc

ld (hl),e
inc hl
ld (hl),d

ld hl,(y) ;; {
;; ld h,a ;; {
;; ld a,(y) ;; { Position Cursor
;; ld l,a ;; {
call &bb75 ;; {

ld hl,map
ld a,(m)
ld c,a
ld b,0
add hl,bc
ld a,(hl)
cp 1
jr nz,skip2

ld a,143
call &bb5a

cp 0
jr z,skip

.skip2 ld a,32
call &bb5a

.skip ld a,(s)
inc a
ld (s),a

ld a,(m)
inc a
ld (m),a

ld a,(x)
ld b,a
ld a,(xcount)
cp b
jr nz,x_loop

ld a,(m)
ld b,a
ld a,160
cp b
jr nc,chk_y

ld a,(isone)
ld (m),a

.chk_y ld a,(x)
xor a
ld (x),a

ld a,(y)
ld b,a
ld a,(ycount)
cp b
jp nz,y_loop

ld a,(x)
xor a
ld (x),a

ld a,(y)
xor a
ld (y),a

ld a,(base)
add a,8
ld (base),a
ld b,a
ld a,160
cp b
jp c,setbase

jp return
ret

.isone defb 1
.base defb 1
.m defb 0
.s defb 0
.y defb 0
.x defb 0
.xcount defb 8
.ycount defb 7
.scr defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0

.map defb 0,0,0,0,0,0,0,1
defb 1,0,0,0,0,0,0,0
defb 0,0,1,0,0,1,0,0
defb 0,0,0,0,0,0,0,0
defb 0,1,0,0,0,0,0,0
defb 1,0,1,0,0,0,0,0
defb 0,0,0,1,1,0,0,0
defb 0,0,0,0,0,0,0,1
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 1,0,0,0,0,1,1,1
defb 1,1,1,0,0,0,0,1
defb 1,1,1,0,0,0,0,1
defb 1,0,0,1,1,0,0,1
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 1,0,0,1,0,0,1,1
defb 1,0,0,1,1,0,0,1
defb 1,0,0,0,0,0,0,1
defb 1,0,0,0,0,0,0,1
defb 1,1,0,0,1,1,1,1


which seems to work, though I think it'll need some adjustments, I'm not 100% sure the pattern I've made in map is the pattern which is being produced here either and there's some other funny things happening as well when I pause the emulator, the loop structure seems fine, but the poking of scr seems to be bigger than 64 bytes if I have xcount & ycount set to 8. I set ycount to 7 which seems to prevent anything being written over into map though, where before this was being overwritten.
The use of Firmware in this circumstance I think is in reality slowing the program down, though for demonstration purposes it looks fine.

Some of the ideas here I grabbed from CPC BASIC 3 Assembly Code, I could probably improve this by having SCRPOS & MAPPOS variables which point to those Arrays in particular, I tried this earlier, but was crashing the system, I was having a lot of problems happening when I tried that, which I've since figured out and other bits of code which CPC BASIC 3 used I could seriously cut-down by simplifying the conditions and setting conditional jumping to the relevant routine.
Title: Re: Moving Graphical Images Down the Screen.
Post by: AMSDOS on 01:38, 14 September 13
Here's an update which looks a bit better & it's showing the data correctly (based on the 8x8 BASIC version) and I've added some comments:

org &4000

ld a,0
ld bc,0
call &bc32 ;; Set up Inks
ld a,1
ld bc,&1a1a
call &bc32

.setbase
ld a,(isone)
ld (base),a ;; base = 1

.return ld a,(isone)
ld (s),a ;; s = 1 (for position of Scr Array)
ld a,(base)
ld (m),a ;; m = base ( for position of map array)

.y_loop ld a,(y)
inc a
ld (y),a ;; increment y

.x_loop ld a,(x)
inc a
ld (x),a ;; increment x

ld hl,scr ;; setup scr array
ld a,(s) ;; s determines position
ld c,a ;; has to be incremented
ld b,0 ;; using bc
add hl,bc ;; hl holds position of scr
push hl ;; needs to be preserved
ld hl,map ;; setup map array
ld a,(m) ;; with m as position of it
ld c,a ;; again using
ld b,0 ;; bc to incrment with
add hl,bc ;; hl holds position of map
ld a,(hl) ;; store this into accumulator
pop hl ;; restore position of scr array
cp (hl) ;; compare contents scr with map position
jr z,skip ;; if it's the same then jump to skip

ld hl,map ;; }
ld a,(m) ;; }
ld c,a ;; }
ld b,0 ;; }
add hl,bc ;; }
ex hl,de ;; }
ld hl,scr ;; } Otherwise scr position
ld a,(s) ;; } equals map position
ld c,a ;; }
ld b,0 ;; }
add hl,bc ;; }
ld (hl),e ;; }
inc hl ;; }
ld (hl),d ;; }

ld hl,(y) ;; Position
call &bb75 ;; Cursor

ld hl,map ;;
ld a,(m) ;;
ld c,a ;;
ld b,0 ;; if position of map
add hl,bc ;; is not equal 1 then
ld a,(hl) ;; jump to skip2
cp 1 ;;
jr nz,skip2 ;;

ld a,143 ;; Otherwise
call &bb5a ;; print block

.skip2 ld a,32 ;; else area
call &bb5a ;; is blank

.skip ld a,(s)
inc a ;; increment s to next position
ld (s),a

ld a,(m)
inc a ;; increment m to next position
ld (m),a

ld a,(x) ;; if x has not reached
ld b,a
ld a,(xcount) ;; value determine by xcount
cp b
jr nz,x_loop ;; jump back to x_loop for another pass

ld a,(m) ;; }
ld b,a ;; } if m has not reached a value 
ld a,161 ;; } of 161 or more then jump to chk_y
cp b ;; }
jr nc,chk_y ;; }

ld a,(isone)
ld (m),a ;; otherwise m = 1

.chk_y ld a,(x)
xor a
ld (x),a ;; x = 0

ld a,(y) ;; if y has not reached
ld b,a
ld a,(ycount) ;; value determine by ycount
cp b
jp nz,y_loop ;; jump back to y_loop for another pass

ld a,(x)
xor a
ld (x),a ;; x = 0

ld a,(y)
xor a
ld (y),a ;; y = 0

ld a,(base) ;; }
add a,8 ;; } increment base by 8
ld (base),a ;; }
ld b,a
ld a,161 ;; if base > 161
cp b
jp c,setbase ;; jump to setbase if value has been reached

jp return ;; otherwise jump to return position
ret

.isone defb 1 ;; Constant value of 1
.base defb 0
.m defb 0
.s defb 0
.y defb 0
.x defb 0
.xcount defb 8
.ycount defb 8
.scr defb 0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0

.map defb 0
defb 0,0,0,0,0,0,0,1
defb 1,0,0,0,0,0,0,0
defb 0,0,1,0,0,1,0,0
defb 0,0,0,0,0,0,0,0
defb 0,1,0,0,0,0,0,0
defb 1,0,1,0,0,0,0,0
defb 0,0,0,1,1,0,0,0
defb 0,0,0,0,0,0,0,1
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 1,0,0,0,0,1,1,1
defb 1,1,1,0,0,0,0,1
defb 1,1,1,0,0,0,0,1
defb 1,0,0,1,1,0,0,1
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 1,0,0,1,0,0,1,1
defb 1,0,0,1,1,0,0,1
defb 1,0,0,0,0,0,0,1
defb 1,0,0,0,0,0,0,1
defb 1,1,0,0,1,1,1,1


I'm not sure if it's really necessary to have the code to check if scr = map bit and if it does jump to skip, it works with or without it. Likewise with the BASIC version - Line 330, however I noticed with the BASIC version having that bit of code there, speeds up the program. From assembly the code seems to swiftly function, I've left the code there to make it easier to follow the BASIC<->Assembly Versions, though it could be removed if one desires.
Title: Re: Moving Graphical Images Down the Screen.
Post by: ervin on 02:38, 16 September 13
It seems that you're doing something wrong in this bit:


ld hl,map  ;; }
ld a,(m)  ;; }
ld c,a   ;; }
ld b,0   ;; }
add hl,bc  ;; }

;; ex hl,de  ;; }
ld e,(hl)

ld hl,scr  ;; } Otherwise scr position
ld a,(s)  ;; } equals map position
ld c,a   ;; }
ld b,0   ;; }
add hl,bc  ;; }

ld (hl),e  ;; }
;; inc hl   ;; }
;; ld (hl),d  ;; }


With the EX DE,HL you were putting the memory location of MAP+(m) into DE.
And then you're putting the low & high bytes of that memory location into the contents of memory location SCR+(s).

I think you should be putting the contents of memory location MAP+(m) into the contents of memory location SCR+(s).

I've commented out the EX DE,HL and put in LD E,(HL). This stores the contents of memory location MAP+(m) in the E register.

I've then written the value in E to memory location SCR+(s), and commented out the last 2 lines.

This has made the program quite a bit faster.
Title: Re: Moving Graphical Images Down the Screen.
Post by: ervin on 02:59, 16 September 13
Here are some more tidy-ups to x_loop.


.x_loop
ld a,(x)
inc a
ld (x),a  ;; increment x

ld hl,scr
ld bc,(s)
ld b,0
add hl,bc
ld a,(hl)

ld hl,map
ld bc,(m)
ld b,0
add hl,bc

cp (hl)   ;; compare contents scr with map position
jr z,skip  ;; if it's the same then jump to skip

ld hl,map  ;; }
ld bc,(m)
ld b,0
add hl,bc  ;; }
ld a,(hl)

ld hl,scr  ;; } Otherwise scr position
ld bc,(s)
ld b,0
add hl,bc  ;; }
ld (hl),a  ;; }

ld hl,(y)  ;; Position
call &bb75  ;; Cursor

ld hl,map  ;;
ld bc,(m)
ld b,0
add hl,bc  ;; is not equal 1 then
ld a,(hl)  ;; jump to skip2

cp 1   ;;
jr nz,skip2  ;;

ld a,143  ;; Otherwise
call &bb5a  ;; print block
Title: Re: Moving Graphical Images Down the Screen.
Post by: ervin on 08:11, 16 September 13
Some minor algorithm changes, and a number of optimisations, so it's a bit faster.
The code is a bit shorter too, and hopefully easier to understand.

I've also used &BB5D (txt wr char) to print the characters, which may be a tiny bit faster as well.

Also, I'm not really sure how, but now 8 columns are being printed (which I presume is the desired behaviour), as 9 were being printed before. I'm not sure which of my changes did it though!  8)


org &4000
ld a,0
ld bc,0
call &bc32 
ld a,1
ld bc,&1a1a
call &bc32
.setbase
ld a,isone
ld (base),a 
.return
ld a,isone
ld (s),a 

ld a,(base)
ld (m),a 
.y_loop
ld hl,y
inc (hl)
.x_loop
ld hl,x
inc (hl)

ld hl,map
ld de,(m)
ld d,0
add hl,de
ld a,(hl)

ld hl,scr
ld bc,(s)
ld b,0
add hl,bc

cp (hl)   
jr z,skip 

ld (hl),a 

ld hl,(y) 
call &bb75 

ld hl,map 
add hl,de
ld a,(hl) 
cp 1   
jr nz,skip2 

ld a,143 
call &bb5d 
jp skip
.skip2
ld a,32   
call &bb5d 
.skip
ld hl,s
inc (hl)
ld hl,m
inc (hl)
ld a,(x) 
cp xcount
jr nz,x_loop 

ld a,(m) 
cp 161
jr nz,chk_y
ld a,isone
ld (m),a 
.chk_y
xor a
ld (x),a 

ld a,(y) 
cp ycount
jr nz,y_loop 
xor a
ld (y),a 
ld a,(base) 
add a,8   
ld (base),a 
cp 161
jp nc,setbase
jp return 
.isone equ 1 
.base defb 0
.m defb 0
.s defb 0
.y defb 0
.x defb 0
.xcount equ 8
.ycount equ 8
.scr defb 0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
.map defb 0
defb 0,0,0,0,0,0,0,1
defb 1,0,0,0,0,0,0,0
defb 0,0,1,0,0,1,0,0
defb 0,0,0,0,0,0,0,0
defb 0,1,0,0,0,0,0,0
defb 1,0,1,0,0,0,0,0
defb 0,0,0,1,1,0,0,0
defb 0,0,0,0,0,0,0,1
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 1,0,0,0,0,1,1,1
defb 1,1,1,0,0,0,0,1
defb 1,1,1,0,0,0,0,1
defb 1,0,0,1,1,0,0,1
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 1,0,0,1,0,0,1,1
defb 1,0,0,1,1,0,0,1
defb 1,0,0,0,0,0,0,1
defb 1,0,0,0,0,0,0,1
defb 1,1,0,0,1,1,1,1
Title: Re: Moving Graphical Images Down the Screen.
Post by: AMSDOS on 09:32, 17 September 13
Those changes look good, unfortunately I was in the process of changing the program around when you posted those, though I still haven't quite got it the way I want it to work, I also moved around the x & y counter and changed those loops to be just one mainloop.

But the optimisations look interesting and I had no idea you could simply increase the value in memory with "inc (hl)" like that. Normally I like to make the most out of HL or (HL) cause I can follow the program a little bit easier which is why I use ex hl,de to put things into DE, and it works out the same as a LD DE,(xxxx). I don't understand why I cannot do an "ADD HL,A", why is that illegal? It would have been so handy to increment a Register Pair with just a Register instead of a Register Pair with a Register pair. I was thinking perhaps it would be better to sacrifice a byte, by leaving it as 0 and have the high Register bit (i.e. "H","D" or "B") point to that value, like of like how I setup the Y co-ordinate value, so L holds the "Y" coordinate value and "H" goes into the "X" coordinate value and it just saves doing a "LD B,0" or whatever.

I wasn't fussed about the Displaying routine and after I nutted out these changes I wanted to make, I was going to try and some a sprite routine working in there instead.
Title: Re: Moving Graphical Images Down the Screen.
Post by: ervin on 13:06, 17 September 13
Quote from: AMSDOS on 09:32, 17 September 13
But the optimisations look interesting and I had no idea you could simply increase the value in memory with "inc (hl)" like that. Normally I like to make the most out of HL or (HL) cause I can follow the program a little bit easier which is why I use ex hl,de to put things into DE, and it works out the same as a LD DE,(xxxx). I don't understand why I cannot do an "ADD HL,A", why is that illegal? It would have been so handy to increment a Register Pair with just a Register instead of a Register Pair with a Register pair. I was thinking perhaps it would be better to sacrifice a byte, by leaving it as 0 and have the high Register bit (i.e. "H","D" or "B") point to that value, like of like how I setup the Y co-ordinate value, so L holds the "Y" coordinate value and "H" goes into the "X" coordinate value and it just saves doing a "LD B,0" or whatever.

Yes indeed, I have on MANY occasions wished that there was something like ADD HL,A.
Unfortunately that command simply doesn't exist.
:(
Title: Re: Moving Graphical Images Down the Screen.
Post by: TFM on 17:30, 17 September 13
A is a 8 bit register. HL is a 16 bit register. So they don't fit.

But instead of LD HL,A you can do:

LD H,&00
LD L,A

Now it some of your registers is zero by accident (maybe B after an LDIR), then you could do:

LD H,B
LD L,A

Title: Re: Moving Graphical Images Down the Screen.
Post by: cngsoft on 14:30, 19 September 13
TFM is right, and there's more: if you absolutely need to do ADD HL,A and you don't mind losing the contents of A or getting flags without the expected meanings, you can do this:

ADD L
LD L,A
ADC H
SUB L
LD H,A

5 bytes of 4 T each.
Title: Re: Moving Graphical Images Down the Screen.
Post by: TFM on 16:02, 19 September 13
Quote from: cngsoft on 14:30, 19 September 13
ADD L
LD L,A
ADC H
SUB L
LD H,A

Excellent!
Title: Re: Moving Graphical Images Down the Screen.
Post by: AMSDOS on 13:21, 20 September 13
I appreciate working solutions to the ADD HL,A problem, unfortunately I was only wondering why an 8bit register couldn't be added into a 16bit register, it doesn't bug me to add a 16bit register with another 16bit register, I just thought it was a bit of a waste using another 16bit register to add to the first one.  ;D
I guess the problem in this context is I dabble with High-Level Languages where it's normally custom to use a Variable Type specifically what it's meant to do.  ;D
Title: Re: Moving Graphical Images Down the Screen.
Post by: TFM on 17:02, 20 September 13
Oh, well it's like apples and pears.
Title: Re: Moving Graphical Images Down the Screen.
Post by: AMSDOS on 09:40, 01 October 13
Well I've tried to come up with a more graphical example which works, but the graphics which is a brick I've grabbed from EgoTrips screenshot are moving across the screen rather than up the screen. I'm not sure what's happening there. There is also a problem with the size of the data which is going across the screen, I'm still trying say that the data is 8x8, but the bricks I've defined are 16x16 in size, so I'm trying to space them more across the screen, though when the program begins with the two bricks at the top of the screen, there should only be one on the first line and one at the start of the 3rd line.
Not sure if it has something to do with where things are finishing and returning when the drawing takes place in the sprite routine, it's about the only thing I haven't checked. The rest of the program seemed to work when I had the Simple Squares.
Title: Re: Moving Graphical Images Down the Screen.
Post by: ervin on 12:35, 01 October 13
Oooh I'm looking forward to figuring out what you've done here.
These little programming projects are fun.  :)
Title: Re: Moving Graphical Images Down the Screen.
Post by: AMSDOS on 10:10, 02 October 13
Quote from: ervin on 12:35, 01 October 13
Oooh I'm looking forward to figuring out what you've done here.
These little programming projects are fun.  :)

I tried applying some of your earlier routines to see if that would make a difference, though I've had no luck with them. It looks like there's a problem with the Loop Counter(s) not returning back to where their suppose to be which maybe why things are moving upward diagonally with that previous post, so maybe if one issue is fixed, it will solve the other?
Title: Re: Moving Graphical Images Down the Screen.
Post by: ervin on 16:42, 02 October 13
I'm converting your code to ccz80, so that I can understand it more easily in order to find the problem.
Fingers crossed!  :)

[EDIT] Getting there, but I've gotta come back to it next week, as I won't have access to my PC for the next few days!  :'( Catch you then.
Title: Re: Moving Graphical Images Down the Screen.
Post by: AMSDOS on 07:40, 07 October 13
I've prepared an example of this from BASIC which is using Sean McManus' Easi-Sprite Definer, so the process seems to be working with that, though the y-loop is only counting one at a time and my x-loop increments twice, so that might be what's wrong with the assembly.

The assembly I'm only writing as an example if people want to show the process of moving something without actually moving the screen, though it's fairly basic in nature and makes good use the firmware, though anyone is more than welcome to analyse it and enhance it, so I'm not overly bothered if I cannot find a solution for it.   :D

At this stage this BASIC looks interesting cause it's moving quite well, probably due to the use of ESD to display the Bricks, so it'll be interesting to compare when it gets compiled.

Title: Re: Moving Graphical Images Down the Screen.
Post by: ervin on 13:49, 07 October 13
Looking good!
Just got back from a few days on holiday (touring caves and stuff) - it's great to see how this has progressed in that time.

If you change line 310, does it give the effect you are after?


310 FOR y%=3 TO 18 step 2


Title: Re: Moving Graphical Images Down the Screen.
Post by: AMSDOS on 02:05, 08 October 13
Quote from: ervin on 13:49, 07 October 13
Looking good!
Just got back from a few days on holiday (touring caves and stuff) - it's great to see how this has progressed in that time.

If you change line 310, does it give the effect you are after?


310 FOR y%=3 TO 18 step 2


Hmm, funny cause I'm on Hols too and just came back from camping out over the last wkend.

I thought the way I had it was correct, but I'll try that out. ESD works a bit differently from the other Sprite routine I made, but I made it so it uses SCR CHAR POS (&BC1A) which is the same as ESD, though ESD uses XOR Sprites so a sprite is only deleted when it's drawn over itself, so it's a bit different from simply deleting it
Title: Re: Moving Graphical Images Down the Screen.
Post by: ervin on 02:17, 08 October 13
 :)
Where'd you go camping? We went down to the south-east of south australia with the kids.
Had a great time.

Alrighty, since ESD uses XOR to draw the sprites, you can gain a tiny speed-up by simplifying line 350.


350 |SPRITE,1,x%,y%


Also, you won't be able to compile your program, as CPC Basic 3 doesn't allow loading BIN files using the LOAD command, and the MEMORY command doesn't do anything either.  :(
Title: Re: Moving Graphical Images Down the Screen.
Post by: AMSDOS on 04:20, 08 October 13
Quote from: ervin on 02:17, 08 October 13
Alrighty, since ESD uses XOR to draw the sprites, you can gain a tiny speed-up by simplifying line 350.


350 |SPRITE,1,x%,y%

Ok, I actually found a problem in my original program, it appears that when I used ESD to GRAB the sprite, I'd only GRAB half of it (might of been due to me saving half the sprite in Bytes rather than Hexadecimal Bytes), so when I was using the Y-Loop to STEP 2, there was a gap. This updated version corrects that, so the Y-LOOP steps twice and I've altered 350 to read that, so now it's working a bit faster again.  :D

QuoteAlso, you won't be able to compile your program, as CPC Basic 3 doesn't allow loading BIN files using the LOAD command, and the MEMORY command doesn't do anything either.  :(

So it would be easier to load all those things from a BASIC Loader, followed by the CPC BASIC 3 program? To be honest I haven't looked to see how CPC BASIC 3 deals with RSXes, so I'll need to see how that works.
Title: Re: Moving Graphical Images Down the Screen.
Post by: ervin on 04:24, 08 October 13
Nice job - it's working well now.
ESD would have been very useful in the dark old days of magazine type-ins!

Yeah, that might be worth a shot (loading the compiled BIN from loco BASIC)!
(I hadn't thought of that).

Title: Re: Moving Graphical Images Down the Screen.
Post by: AMSDOS on 07:27, 08 October 13
Quote from: ervin on 04:24, 08 October 13
Nice job - it's working well now.
ESD would have been very useful in the dark old days of magazine type-ins!

Yeah, that might be worth a shot (loading the compiled BIN from loco BASIC)!
(I hadn't thought of that).

Yeah check this out. All I had to do to make this work was delete lines 20 & 30 which load ESD & the Brick Sprite. I used CPCBASIC 3 to output the code to a Disk Image, but I guess you can just as easily make it assembly source, ccz80, etc and just added the ESD program and Brick Sprite to that disc along with a BASIC Loader. At compile time it wasn't worried about the ESD or the Sprite data not being there, though obviously Running the code in the Emulator wouldn't work and as long as the RSXes are there before the main program is executed, it'll work in nicely with it.

ESD is pretty old, on Sean's "The Sprite Idea" website, Sean stated that The Sprite Definer & Driver Software appeared on the June 1992 Covertape, which is true, though the Driver component which is ESD, was first a Type-in Issue 55 (April 1990), which came with a demonstration of Batman. This nifty driver came about because Pat McDonald wrote a Sprite Editor which was a Type-In in AA43 and then some corrections were made to it in AA46, which isn't a bad little program if you don't exit the program. In between that period AA were hinting at having a Sprite Driver and they had an interesting little Assembly Guide to which some Sprite Drivers were published, though I think people were quite happy when ESD come out, because it simply meant they could type it in and use it without much fuss.
The Sprite Definer Sean made after ESD is a bit fiddly to use I thought, though the sprites you make with it will obviously be usable with ESD immediately, though the beauty of ESD is it was designed so you can grab your Sprites from screenshots, the Grab Routine is a little bit tricky to use because the Width is in Bytes & Height is in Pixels, though with all that sorted out it's pretty straightforward to use.
It wasn't written to be an 1-Pixel Perfect Program, with that Sean wrote "ESD Advanced", and it's using Text Based Coordinates from 0,0 to 79,24 to draw the Sprites, though benefits in it's speed. I guess given the size of ESD, I never saw any Type-ins afterwards which used it, though it wouldn't surprise me if Sean had it in some of his later Type-ins like Gribbet (AA66) or Alien Intenvention (AA91), the Public Domain game Sean wrote "The Further Adventures Of Fred", is perhaps an example of what you can do with ESD cause everything in that game is Character Based and it moves around very well.
Title: Re: Moving Graphical Images Down the Screen.
Post by: ervin on 07:32, 08 October 13
WOW! That's an amazing speed difference!
Well done on your excellent work-around to get it working in CPC BASIC 3.
That's really useful info for the future.
Title: Re: Moving Graphical Images Down the Screen.
Post by: AMSDOS on 07:52, 18 October 13
I've just made some slight adjustments to the last program, in this example instead of relying on ESD, I've taken the BASIC Source Code (OUTPUT.ASC) and am using one of my own routines to plot the image which I've included in the Disk Image as DISP.ASM. Originally I had my plotting routine occupying the same space to which CBASIC 3 Assembles the code, though had no problems relocating it. I've also taken the OUTPUT.ASC BASIC code and made OUTPUT.CC which is the CCZ80. I had to modify my BASIC code cause it appears the SCR FLOOD BOX doesn't support XOR mode which explains for the slow down from the previous ESD version.

I only came up with this version to see if the SCR FLOOD BOX routine was perhaps shifting the Bricks Diagonally across the screen, however this code seems to be working in the appropriate manner, which suggests there's a flaw in my earlier Assembly code which is shifting the Bricks Diagonally.
Title: Re: Moving Graphical Images Down the Screen.
Post by: AMSDOS on 07:14, 27 January 14
I've done some modifications which has addressed the problem of the Bricks Moving Up the Screen Diagonally, the problem seemed related to how I was using the Loop to Double Count. What I've done to change this is to have it as a Single Count and use "sla" to space things out. It's worked out well with the Bricks moving straight up the screen, though there's some odd things happening with Bricks Appearing/Disappearing along the 8th Row & the Bottom Row is doing a bit of the same, so I'm not quite sure why that's happening.

org &4000

xor a
call &bc0e

xor a
ld b,a
ld c,a
call &bc32 ;; Set up Inks
ld a,1
ld bc,&0d0d
call &bc32
ld a,2
ld bc,&0a0a
call &bc32
ld a,3
ld bc,&0202
call &bc32

ld a,(x)
sla a
ld (pos_x),a

ld a,(y)
sla a
ld (pos_y),a

.setbase
xor a ;; ld a,(isone)
ld (base),a ;; base = 1

.return xor a ;; ld a,(isone)
ld (s),a ;; s = 1 (for position of Scr Array)
ld a,(base)
ld (m),a ;; m = base ( for position of map array)

.mainloop

ld hl,scr ;; setup scr array
ld a,(s) ;; s determines position
ld c,a ;; has to be incremented
ld b,0 ;; using bc
add hl,bc ;; hl holds position of scr
push hl ;; needs to be preserved
ld hl,map ;; setup map array
ld a,(m) ;; with m as position of it
ld c,a ;; again using
ld b,0 ;; bc to incrment with
add hl,bc ;; hl holds position of map
ld a,(hl) ;; store this into accumulator
pop hl ;; restore position of scr array
cp (hl) ;; compare contents scr with map position
jr z,skip ;; if it's the same then jump to skip

ld hl,map ;; }
ld a,(m) ;; }
ld c,a ;; }
ld b,0 ;; }
add hl,bc ;; }
ex hl,de ;; }
ld hl,scr ;; } Otherwise scr position
ld a,(s) ;; } equals map position
ld c,a ;; }
ld b,0 ;; }
add hl,bc ;; }
ld (hl),e ;; }
;; inc hl ;; }
;; ld (hl),d ;; }

;; ld hl,blank
;; ld (addrimg),hl
;; ld hl,(y)

ld hl,map ;;
ld a,(m) ;;
ld c,a ;;
ld b,0 ;; if position of map
add hl,bc ;; is not equal 1 then
ld a,(hl) ;; jump to skip2
cp 1 ;;
jr nz,skip2 ;;


ld hl,bricks
ld (addrimg),hl

;; push af
ld hl,(pos_y)
call begin
;; pop af

cp 0
jr z,skip


.skip2 ld hl,blank
ld (addrimg),hl
ld hl,(pos_y)
call begin

.skip ld a,(s)
inc a ;; increment s to next position
ld (s),a

ld a,(m)
inc a ;; increment m to next position
ld (m),a

ld a,(x) ;; if x has not reached
ld b,a
ld a,(xcount) ;; value determine by xcount
cp b
jr z,chk_m ;; jump back to x_loop for another pass

ld a,(x)
inc a
ld (x),a
sla a
ld (pos_x),a

jp mainloop

.chk_m ld a,(m) ;; }
ld b,a ;; } if m has not reached a value 
ld a,161 ;; } of 161 or more then jump to chk_y
cp b ;; }
jr nc,chk_y ;; }

xor a ;; ld a,(isone)
ld (m),a ;; otherwise m = 1

.chk_y  xor a ;;ld a,(isone)
ld (x),a

ld a,(y) ;; if y has not reached
ld b,a
ld a,(ycount) ;; value determine by ycount
cp b
jr z,resval ;; jump back to y_loop for another pass

ld a,(y)
inc a
ld (y),a ;; increment y
sla a
ld (pos_y),a

jp mainloop

.resval
xor a ;; ld a,(isone)
ld (x),a

;; xor a ;; ld a,(isone)
ld (y),a

ld a,(base) ;; }
add a,8 ;; } increment base by 8
ld (base),a ;; }
ld b,a
ld a,161 ;; if base > 161
cp b
jp c,setbase ;; jump to setbase if value has been reached

jp return ;; otherwise jump to return position
ret

.begin call &bc1a ;; SCR CHAR POSITION coverts this into a Screen Address

ld (scraddr),hl ;; Screen Address of Location
ld (storscraddr),hl ;; This is used because Scradr has to be Incremented

.sprloop ld d,1 ;; Width of the Image
ld e,d ;; Height of the Image

ld hl,(addrimg) ;; This points to the Bit Mask Data (the patten which
ld c,(hl) ;; gets drawn), and gets stored into the C register.

ld hl,(scraddr) ;; Address of the screen address.

call &bc47 ;; SCR FLOOD BOX.
;; Entry: C = Encoded INK
;; D = Width of the Image
;; E = Height of the Image
;; HL = Address to draw the Image.

ld hl,(scraddr) ;; I then have to increment the value of screen
inc hl ;; address to the next position to draw the next spot
ld (scraddr),hl ;; along. It gets stored so I can reuse my registers.

ld hl,(addrimg) ;; The address for the Bit Mask Pattern is also
inc hl ;; increment to point to the next value and is also
ld (addrimg),hl ;; stored as well.

ld a,(count1) ;; This is my loop sequence and again I needed to store
inc a ;; values into memory. I wanted to use my old friend
ld (count1),a ;; DJNZ, though was proving to be a nightmare.
ld b,a ;; This one checks if count1 equals loop1 and if it

ld a,(loop1) ;; doesn't it will jump back to loop to do another pass.

cp b
jr nz,sprloop ;; The Jump is applied here back to the loop label.

ld a,(count1) ;; If it has reacted this point then count1 equals loop1
xor a ;; it must be set back to zero so it can work when it
ld (count1),a ;; returns back to the main loop.

ld hl,(storscraddr) ;; This is used to calculate the previous line.
call &bc26 ;; SCR NEXT LINE
ld (scraddr),hl ;; I store the value into scraddr for the main loop
ld (storscraddr),hl ;; and I also store the screen address for this routine.

ld a,(count2) ;; Once all that is done I have to do the same thing
inc a ;; here and check to see if count2 equals loop2. And
ld (count2),a ;; again the values need to be stored in memory and
ld b,a ;; recalled again for when I need to check.

ld a,(loop2) ;; As long as count2 is not equal to loop 2, it will

cp b ;; return back to the main loop, otherwise it will
jr nz,sprloop ;; proceed to exit, back to BASIC if called from there.


ld a,(count2) ;; though upon exit count2 needs to return to 0
xor a ;; Just so this routine can be recalled again.
ld (count2),a ;; values are returned into it's rightful place.

ret


.loop1 defb 8 ;; Width of the Image
.loop2 defb 16 ;; Height of the Image
.count1 defb 0 ;; Checks for when the Width of the Image is Reached
.count2 defb 0 ;; Checks for when the Height of the Image is Reached
.scraddr defw 0 ;; Holds the screen address in relation to the Width.
.storscraddr defw 0 ;; Retains original screen address to calculate next line.
.addofimage defw 0 ;; Points to the address of the image to Display
.bricks defb 0,0,0,0,0,0,0,0
defb 192,12,12,12,12,12,12,0
defb 192,12,12,12,12,12,12,0
defb 204,12,12,12,12,12,12,0
defb 0,0,0,0,0,0,0,0
defb 12,12,12,0,192,12,12,12
defb 12,12,12,0,192,12,12,12
defb 192,192,192,0,204,192,192,192
defb 0,0,0,0,0,0,0,0
defb 192,12,12,12,12,12,12,0
defb 192,12,12,12,12,12,12,0
defb 204,12,12,12,12,12,12,0
defb 0,0,0,0,0,0,0,0
defb 12,12,12,0,192,12,12,12
defb 12,12,12,0,192,12,12,12
defb 192,192,192,0,204,192,192,192

.blank defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
.isone defb 1 ;; Constant value of 1
.base defb 0
.m defb 0
.s defb 0
.y defb 0
.x defb 0
.pos_y defb 0
.pos_x defb 0
.addrimg
defw 0
.xcount defb 7
.ycount defb 7
.scr ;; defb 0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0

.map defb 0
defb 0,0,0,0,0,0,0,1
defb 1,0,0,0,0,0,0,0
defb 0,0,1,0,0,1,0,0
defb 0,0,0,0,0,0,0,0
defb 0,1,0,0,0,0,0,0
defb 1,0,1,0,0,0,0,0
defb 0,0,0,1,1,0,0,0
defb 0,0,0,0,0,0,0,1
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 1,0,0,0,0,1,1,1
defb 1,1,1,0,0,0,0,1
defb 1,1,1,0,0,0,0,1
defb 1,0,0,1,1,0,0,1
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 1,0,0,1,0,0,1,1
defb 1,0,0,1,1,0,0,1
defb 1,0,0,0,0,0,0,1
defb 1,0,0,0,0,0,0,1
defb 1,1,0,0,1,1,1,1
Title: Re: Moving Graphical Images Down the Screen.
Post by: redbox on 18:29, 27 January 14
Quote from: AMSDOS on 07:14, 27 January 14
I've done some modifications which has addressed the problem of the Bricks Moving Up the Screen Diagonally, the problem seemed related to how I was using the Loop to Double Count. What I've done to change this is to have it as a Single Count and use "sla" to space things out. It's worked out well with the Bricks moving straight up the screen, though there's some odd things happening with Bricks Appearing/Disappearing along the 8th Row & the Bottom Row is doing a bit of the same, so I'm not quite sure why that's happening.

What are you trying to do here?

When I assembled and run the program I got the bricks appearing and disappearing randomly on the screen.
Title: Re: Moving Graphical Images Down the Screen.
Post by: Axelay on 08:50, 28 January 14
Quote from: AMSDOS on 07:14, 27 January 14
I've done some modifications which has addressed the problem of the Bricks Moving Up the Screen Diagonally, the problem seemed related to how I was using the Loop to Double Count. What I've done to change this is to have it as a Single Count and use "sla" to space things out. It's worked out well with the Bricks moving straight up the screen, though there's some odd things happening with Bricks Appearing/Disappearing along the 8th Row & the Bottom Row is doing a bit of the same, so I'm not quite sure why that's happening.



The main problem I can see is that on a couple of occasions (after the chk_y and resval labels) you have not kept pos_x or pos_y in sync with the x or y values.  I'm attaching the fixed source, with two other changes.  One is that the update of the screen buffer didnt appear to be handled correctly in mainloop, so every block would be updated whether it needed to or not, and the other is that with SCR FLOOD BOX being used to write a single byte to the screen, I just couldnt resist replacing that with a simple load!  ;)  I've preceded the changes I made with a row of semi colons so you can spot them easily.


   
org &4000

xor a
call &bc0e

xor a
ld b,a
ld c,a
call &bc32 ;; Set up Inks
ld a,1
ld bc,&0d0d
call &bc32
ld a,2
ld bc,&0a0a
call &bc32
ld a,3
ld bc,&0202
call &bc32

ld a,(x)
sla a
ld (pos_x),a

ld a,(y)
sla a
ld (pos_y),a

.setbase
xor a ;; ld a,(isone)
ld (base),a ;; base = 1

.return xor a ;; ld a,(isone)
ld (s),a ;; s = 1 (for position of Scr Array)
ld a,(base)
ld (m),a ;; m = base ( for position of map array)

.mainloop

ld hl,scr ;; setup scr array
ld a,(s) ;; s determines position
ld c,a ;; has to be incremented
ld b,0 ;; using bc
add hl,bc ;; hl holds position of scr
push hl ;; needs to be preserved
ld hl,map ;; setup map array
ld a,(m) ;; with m as position of it
ld c,a ;; again using
ld b,0 ;; bc to incrment with
add hl,bc ;; hl holds position of map
ld a,(hl) ;; store this into accumulator
pop hl ;; restore position of scr array
cp (hl) ;; compare contents scr with map position
jr z,skip ;; if it's the same then jump to skip

ld hl,map ;; }
ld a,(m) ;; }
ld c,a ;; }
ld b,0 ;; }
add hl,bc ;; }
ex hl,de ;; }
ld hl,scr ;; } Otherwise scr position
ld a,(s) ;; } equals map position
ld c,a ;; }
ld b,0 ;; }
add hl,bc ;; }
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ld (hl),e ;; }
        ld a,(de) ;; get new value from map
ld (hl),a ;; and write it to screen
;; inc hl ;; }
;; ld (hl),d ;; }

;; ld hl,blank
;; ld (addrimg),hl
;; ld hl,(y)

ld hl,map ;;
ld a,(m) ;;
ld c,a ;;
ld b,0 ;; if position of map
add hl,bc ;; is not equal 1 then
ld a,(hl) ;; jump to skip2
cp 1 ;;
jr nz,skip2 ;;


ld hl,bricks
ld (addrimg),hl

;; push af
ld hl,(pos_y)
call begin
;; pop af

cp 0
jr z,skip


.skip2 ld hl,blank
ld (addrimg),hl
ld hl,(pos_y)
call begin

.skip ld a,(s)
inc a ;; increment s to next position
ld (s),a

ld a,(m)
inc a ;; increment m to next position
ld (m),a

ld a,(x) ;; if x has not reached
ld b,a
ld a,(xcount) ;; value determine by xcount
cp b
jr z,chk_m ;; jump back to x_loop for another pass

ld a,(x)
inc a
ld (x),a
sla a
ld (pos_x),a

jp mainloop

.chk_m ld a,(m) ;; }
ld b,a ;; } if m has not reached a value 
ld a,161 ;; } of 161 or more then jump to chk_y
cp b ;; }
jr nc,chk_y ;; }

xor a ;; ld a,(isone)
ld (m),a ;; otherwise m = 1

.chk_y  xor a ;;ld a,(isone)
ld (x),a
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
sla a
ld (pos_x),a ;; maintain pos_x

ld a,(y) ;; if y has not reached
ld b,a
ld a,(ycount) ;; value determine by ycount
cp b
jr z,resval ;; jump back to y_loop for another pass

ld a,(y)
inc a
ld (y),a ;; increment y
sla a
ld (pos_y),a

jp mainloop

.resval
xor a ;; ld a,(isone)
ld (x),a
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
sla a
ld (pos_x),a ;; maintain pos_x

;; xor a ;; ld a,(isone)
ld (y),a
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
sla a
ld (pos_y),a ;; maintain pos_y

ld a,(base) ;; }
add a,8 ;; } increment base by 8
ld (base),a ;; }
ld b,a
ld a,161 ;; if base > 161
cp b
jp c,setbase ;; jump to setbase if value has been reached

jp return ;; otherwise jump to return position
ret

.begin call &bc1a ;; SCR CHAR POSITION coverts this into a Screen Address

ld (scraddr),hl ;; Screen Address of Location
ld (storscraddr),hl ;; This is used because Scradr has to be Incremented

.sprloop ld d,1 ;; Width of the Image
ld e,d ;; Height of the Image

ld hl,(addrimg) ;; This points to the Bit Mask Data (the patten which
ld c,(hl) ;; gets drawn), and gets stored into the C register.

ld hl,(scraddr) ;; Address of the screen address.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ld (hl),c ;; much faster than using SCR FLOOD BOX for a 1x1 byte area!!!
; call &bc47 ;; SCR FLOOD BOX.
;; Entry: C = Encoded INK
;; D = Width of the Image
;; E = Height of the Image
;; HL = Address to draw the Image.

ld hl,(scraddr) ;; I then have to increment the value of screen
inc hl ;; address to the next position to draw the next spot
ld (scraddr),hl ;; along. It gets stored so I can reuse my registers.

ld hl,(addrimg) ;; The address for the Bit Mask Pattern is also
inc hl ;; increment to point to the next value and is also
ld (addrimg),hl ;; stored as well.

ld a,(count1) ;; This is my loop sequence and again I needed to store
inc a ;; values into memory. I wanted to use my old friend
ld (count1),a ;; DJNZ, though was proving to be a nightmare.
ld b,a ;; This one checks if count1 equals loop1 and if it

ld a,(loop1) ;; doesn't it will jump back to loop to do another pass.

cp b
jr nz,sprloop ;; The Jump is applied here back to the loop label.

ld a,(count1) ;; If it has reacted this point then count1 equals loop1
xor a ;; it must be set back to zero so it can work when it
ld (count1),a ;; returns back to the main loop.

ld hl,(storscraddr) ;; This is used to calculate the previous line.
call &bc26 ;; SCR NEXT LINE
ld (scraddr),hl ;; I store the value into scraddr for the main loop
ld (storscraddr),hl ;; and I also store the screen address for this routine.

ld a,(count2) ;; Once all that is done I have to do the same thing
inc a ;; here and check to see if count2 equals loop2. And
ld (count2),a ;; again the values need to be stored in memory and
ld b,a ;; recalled again for when I need to check.

ld a,(loop2) ;; As long as count2 is not equal to loop 2, it will

cp b ;; return back to the main loop, otherwise it will
jr nz,sprloop ;; proceed to exit, back to BASIC if called from there.


ld a,(count2) ;; though upon exit count2 needs to return to 0
xor a ;; Just so this routine can be recalled again.
ld (count2),a ;; values are returned into it's rightful place.

ret


.loop1 defb 8 ;; Width of the Image
.loop2 defb 16 ;; Height of the Image
.count1 defb 0 ;; Checks for when the Width of the Image is Reached
.count2 defb 0 ;; Checks for when the Height of the Image is Reached
.scraddr defw 0 ;; Holds the screen address in relation to the Width.
.storscraddr defw 0 ;; Retains original screen address to calculate next line.
.addofimage defw 0 ;; Points to the address of the image to Display
.bricks defb 0,0,0,0,0,0,0,0
defb 192,12,12,12,12,12,12,0
defb 192,12,12,12,12,12,12,0
defb 204,12,12,12,12,12,12,0
defb 0,0,0,0,0,0,0,0
defb 12,12,12,0,192,12,12,12
defb 12,12,12,0,192,12,12,12
defb 192,192,192,0,204,192,192,192
defb 0,0,0,0,0,0,0,0
defb 192,12,12,12,12,12,12,0
defb 192,12,12,12,12,12,12,0
defb 204,12,12,12,12,12,12,0
defb 0,0,0,0,0,0,0,0
defb 12,12,12,0,192,12,12,12
defb 12,12,12,0,192,12,12,12
defb 192,192,192,0,204,192,192,192

.blank defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
.isone defb 1 ;; Constant value of 1
.base defb 0
.m defb 0
.s defb 0
.y defb 0
.x defb 0
.pos_y defb 0
.pos_x defb 0
.addrimg
defw 0
.xcount defb 7
.ycount defb 7
.scr ;; defb 0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0

.map defb 0
defb 0,0,0,0,0,0,0,1
defb 1,0,0,0,0,0,0,0
defb 0,0,1,0,0,1,0,0
defb 0,0,0,0,0,0,0,0
defb 0,1,0,0,0,0,0,0
defb 1,0,1,0,0,0,0,0
defb 0,0,0,1,1,0,0,0
defb 0,0,0,0,0,0,0,1
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 1,0,0,0,0,1,1,1
defb 1,1,1,0,0,0,0,1
defb 1,1,1,0,0,0,0,1
defb 1,0,0,1,1,0,0,1
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 1,0,0,1,0,0,1,1
defb 1,0,0,1,1,0,0,1
defb 1,0,0,0,0,0,0,1
defb 1,0,0,0,0,0,0,1
defb 1,1,0,0,1,1,1,1
Title: Re: Moving Graphical Images Down the Screen.
Post by: AMSDOS on 08:57, 28 January 14
Quote from: redbox on 18:29, 27 January 14
What are you trying to do here?

When I assembled and run the program I got the bricks appearing and disappearing randomly on the screen.

Well I was only getting the bricks appearing and disappearing around the edge and bottom of the screen, I could still see some of my data being supplied working accordingly. Have a look my early assembly example (movshp.asm) which is using TXT OUTPUT (&BB5A) which works if that's of any help. The idea here is to supply data from "map" and to patch it into "scr", but it's moving it through that to generate an 8x8 field, so as it moves the data further into "map" gets displayed.

It's only an example though I was interested to see how it could be applied in a graphical sense, I wasn't critical about what Sprite Driver to use for this, which is why it's a bit on the slow side.
Title: Re: Moving Graphical Images Down the Screen.
Post by: AMSDOS on 10:10, 28 January 14
Quote from: Axelay on 08:50, 28 January 14

The main problem I can see is that on a couple of occasions (after the chk_y and resval labels) you have not kept pos_x or pos_y in sync with the x or y values.  I'm attaching the fixed source, with two other changes.  One is that the update of the screen buffer didnt appear to be handled correctly in mainloop, so every block would be updated whether it needed to or not, and the other is that with SCR FLOOD BOX being used to write a single byte to the screen, I just couldnt resist replacing that with a simple load!  ;)  I've preceded the changes I made with a row of semi colons so you can spot them easily.

Thanks for that, yes I can now why not updating the pos_x or pos_y would cause those problems with the blinking. Not quite sure what you mean about the Screen Buffer, unfortunately my comments are vague in that area. Funny that SCR FLOOD BOX would irritate someone and even funnier that a simple LD (HL),C fixes it.  ;D

I made the sprite routine a little more compact by commenting out the ld d,1 ld e,d which SCR FLOOD BOX uses. Also I've removed the first defb 0 at the start of map, so now it's correctly displaying the maze that I had in my early text version of the program.  :D



org &4000

xor a
call &bc0e

xor a
ld b,a
ld c,a
call &bc32 ;; Set up Inks
ld a,1
ld bc,&0d0d
call &bc32
ld a,2
ld bc,&0a0a
call &bc32
ld a,3
ld bc,&0202
call &bc32

ld a,(x)
sla a
ld (pos_x),a

ld a,(y)
sla a
ld (pos_y),a

.setbase
xor a ;; ld a,(isone)
ld (base),a ;; base = 1

.return xor a ;; ld a,(isone)
ld (s),a ;; s = 1 (for position of Scr Array)
ld a,(base)
ld (m),a ;; m = base ( for position of map array)

.mainloop

ld hl,scr ;; setup scr array
ld a,(s) ;; s determines position
ld c,a ;; has to be incremented
ld b,0 ;; using bc
add hl,bc ;; hl holds position of scr
push hl ;; needs to be preserved
ld hl,map ;; setup map array
ld a,(m) ;; with m as position of it
ld c,a ;; again using
ld b,0 ;; bc to incrment with
add hl,bc ;; hl holds position of map
ld a,(hl) ;; store this into accumulator
pop hl ;; restore position of scr array
cp (hl) ;; compare contents scr with map position
jr z,skip ;; if it's the same then jump to skip

ld hl,map ;; }
ld a,(m) ;; }
ld c,a ;; }
ld b,0 ;; }
add hl,bc ;; }
ex hl,de ;; }
ld hl,scr ;; } Otherwise scr position
ld a,(s) ;; } equals map position
ld c,a ;; }
ld b,0 ;; }
add hl,bc ;; }
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ld (hl),e ;; }
        ld a,(de) ;; get new value from map
ld (hl),a ;; and write it to screen
;; inc hl ;; }
;; ld (hl),d ;; }

;; ld hl,blank
;; ld (addrimg),hl
;; ld hl,(y)

ld hl,map ;;
ld a,(m) ;;
ld c,a ;;
ld b,0 ;; if position of map
add hl,bc ;; is not equal 1 then
ld a,(hl) ;; jump to skip2
cp 1 ;;
jr nz,skip2 ;;


ld hl,bricks
ld (addrimg),hl

;; push af
ld hl,(pos_y)
call begin
;; pop af

cp 0
jr z,skip


.skip2 ld hl,blank
ld (addrimg),hl
ld hl,(pos_y)
call begin

.skip ld a,(s)
inc a ;; increment s to next position
ld (s),a

ld a,(m)
inc a ;; increment m to next position
ld (m),a

ld a,(x) ;; if x has not reached
ld b,a
ld a,(xcount) ;; value determine by xcount
cp b
jr z,chk_m ;; jump back to x_loop for another pass

ld a,(x)
inc a
ld (x),a
sla a
ld (pos_x),a

jp mainloop

.chk_m ld a,(m) ;; }
ld b,a ;; } if m has not reached a value 
ld a,161 ;; } of 161 or more then jump to chk_y
cp b ;; }
jr nc,chk_y ;; }

xor a ;; ld a,(isone)
ld (m),a ;; otherwise m = 1

.chk_y  xor a ;;ld a,(isone)
ld (x),a
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
sla a
ld (pos_x),a ;; maintain pos_x

ld a,(y) ;; if y has not reached
ld b,a
ld a,(ycount) ;; value determine by ycount
cp b
jr z,resval ;; jump back to y_loop for another pass

ld a,(y)
inc a
ld (y),a ;; increment y
sla a
ld (pos_y),a

jp mainloop

.resval
xor a ;; ld a,(isone)
ld (x),a
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
sla a
ld (pos_x),a ;; maintain pos_x

;; xor a ;; ld a,(isone)
ld (y),a
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
sla a
ld (pos_y),a ;; maintain pos_y

ld a,(base) ;; }
add a,8 ;; } increment base by 8
ld (base),a ;; }
ld b,a
ld a,161 ;; if base > 161
cp b
jp c,setbase ;; jump to setbase if value has been reached

jp return ;; otherwise jump to return position
ret

.begin call &bc1a ;; SCR CHAR POSITION coverts this into a Screen Address

ld (scraddr),hl ;; Screen Address of Location
ld (storscraddr),hl ;; This is used because Scradr has to be Incremented

.sprloop ;; ld d,1 ;; Width of the Image
;; ld e,d ;; Height of the Image

ld hl,(addrimg) ;; This points to the Bit Mask Data (the patten which
ld c,(hl) ;; gets drawn), and gets stored into the C register.

ld hl,(scraddr) ;; Address of the screen address.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ld (hl),c ;; much faster than using SCR FLOOD BOX for a 1x1 byte area!!!
; call &bc47 ;; SCR FLOOD BOX.
;; Entry: C = Encoded INK
;; D = Width of the Image
;; E = Height of the Image
;; HL = Address to draw the Image.

ld hl,(scraddr) ;; I then have to increment the value of screen
inc hl ;; address to the next position to draw the next spot
ld (scraddr),hl ;; along. It gets stored so I can reuse my registers.

ld hl,(addrimg) ;; The address for the Bit Mask Pattern is also
inc hl ;; increment to point to the next value and is also
ld (addrimg),hl ;; stored as well.

ld a,(count1) ;; This is my loop sequence and again I needed to store
inc a ;; values into memory. I wanted to use my old friend
ld (count1),a ;; DJNZ, though was proving to be a nightmare.
ld b,a ;; This one checks if count1 equals loop1 and if it

ld a,(loop1) ;; doesn't it will jump back to loop to do another pass.

cp b
jr nz,sprloop ;; The Jump is applied here back to the loop label.

ld a,(count1) ;; If it has reacted this point then count1 equals loop1
xor a ;; it must be set back to zero so it can work when it
ld (count1),a ;; returns back to the main loop.

ld hl,(storscraddr) ;; This is used to calculate the previous line.
call &bc26 ;; SCR NEXT LINE
ld (scraddr),hl ;; I store the value into scraddr for the main loop
ld (storscraddr),hl ;; and I also store the screen address for this routine.

ld a,(count2) ;; Once all that is done I have to do the same thing
inc a ;; here and check to see if count2 equals loop2. And
ld (count2),a ;; again the values need to be stored in memory and
ld b,a ;; recalled again for when I need to check.

ld a,(loop2) ;; As long as count2 is not equal to loop 2, it will

cp b ;; return back to the main loop, otherwise it will
jr nz,sprloop ;; proceed to exit, back to BASIC if called from there.


ld a,(count2) ;; though upon exit count2 needs to return to 0
xor a ;; Just so this routine can be recalled again.
ld (count2),a ;; values are returned into it's rightful place.

ret


.loop1 defb 8 ;; Width of the Image
.loop2 defb 16 ;; Height of the Image
.count1 defb 0 ;; Checks for when the Width of the Image is Reached
.count2 defb 0 ;; Checks for when the Height of the Image is Reached
.scraddr defw 0 ;; Holds the screen address in relation to the Width.
.storscraddr defw 0 ;; Retains original screen address to calculate next line.
.addofimage defw 0 ;; Points to the address of the image to Display
.bricks defb 0,0,0,0,0,0,0,0
defb 192,12,12,12,12,12,12,0
defb 192,12,12,12,12,12,12,0
defb 204,12,12,12,12,12,12,0
defb 0,0,0,0,0,0,0,0
defb 12,12,12,0,192,12,12,12
defb 12,12,12,0,192,12,12,12
defb 192,192,192,0,204,192,192,192
defb 0,0,0,0,0,0,0,0
defb 192,12,12,12,12,12,12,0
defb 192,12,12,12,12,12,12,0
defb 204,12,12,12,12,12,12,0
defb 0,0,0,0,0,0,0,0
defb 12,12,12,0,192,12,12,12
defb 12,12,12,0,192,12,12,12
defb 192,192,192,0,204,192,192,192

.blank defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
.isone defb 1 ;; Constant value of 1
.base defb 0
.m defb 0
.s defb 0
.y defb 0
.x defb 0
.pos_y defb 0
.pos_x defb 0
.addrimg
defw 0
.xcount defb 7
.ycount defb 7
.scr ;; defb 0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0

.map ;; defb 0
defb 0,0,0,0,0,0,0,1
defb 1,0,0,0,0,0,0,0
defb 0,0,1,0,0,1,0,0
defb 0,0,0,0,0,0,0,0
defb 0,1,0,0,0,0,0,0
defb 1,0,1,0,0,0,0,0
defb 0,0,0,1,1,0,0,0
defb 0,0,0,0,0,0,0,1
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 1,0,0,0,0,1,1,1
defb 1,1,1,0,0,0,0,1
defb 1,1,1,0,0,0,0,1
defb 1,0,0,1,1,0,0,1
defb 0,0,0,0,0,0,0,0
defb 0,0,0,0,0,0,0,0
defb 1,0,0,1,0,0,1,1
defb 1,0,0,1,1,0,0,1
defb 1,0,0,0,0,0,0,1
defb 1,0,0,0,0,0,0,1
defb 1,1,0,0,1,1,1,1
Title: Re: Moving Graphical Images Down the Screen.
Post by: Axelay on 12:41, 30 January 14
Quote from: AMSDOS on 10:10, 28 January 14
Not quite sure what you mean about the Screen Buffer, unfortunately my comments are vague in that area.


I was referring to the second block of code in mainloop, where you originally had:



   ld hl,map      ;; }
   ld a,(m)      ;; }
   ld c,a         ;; }
   ld b,0         ;; }
   add hl,bc      ;; }
   ex hl,de      ;; }
   ld hl,scr      ;; } Otherwise scr position
   ld a,(s)      ;; } equals map position
   ld c,a         ;; }
   ld b,0         ;; }
   add hl,bc      ;; }
   ld (hl),e      ;; }
This bit of code in mainloop is only executed if the preceding part of code found the contents pointed to in the scr buffer did not match the contents of the memory location pointed to in map.  So this section of code above would presumably be updating the scr table to reflect what is about to be printed to screen at the current location so when it next updates that block, it wont print anything if the block is the same.  But this code ends with ld (hl),e, where e is the low byte of the pointer to map, which means it's almost certainly marking scr with a value different to what it will find in map next time in the preceding code, so that the block will subsequently be updated whether it changes or not.  What it actually needs to be writing to scr is the contents pointed to by de in map, so it should be ld a,(de):ld (hl),a.


It is worth noting though that at the point of that branch in mainloop just before the code segment I posted above, a already contains the value of the new block, and hl already contains a pointer to the appropriate location in scr, so the entire segment of code above could be replaced with ld (hl),a.  :)
Title: Re: Moving Graphical Images Down the Screen.
Post by: AMSDOS on 22:15, 31 January 14
Quote from: Axelay on 12:41, 30 January 14

I was referring to the second block of code in mainloop, where you originally had:



   ld hl,map      ;; }
   ld a,(m)      ;; }
   ld c,a         ;; }
   ld b,0         ;; }
   add hl,bc      ;; }
   ex hl,de      ;; }
   ld hl,scr      ;; } Otherwise scr position
   ld a,(s)      ;; } equals map position
   ld c,a         ;; }
   ld b,0         ;; }
   add hl,bc      ;; }
   ld (hl),e      ;; }
This bit of code in mainloop is only executed if the preceding part of code found the contents pointed to in the scr buffer did not match the contents of the memory location pointed to in map.  So this section of code above would presumably be updating the scr table to reflect what is about to be printed to screen at the current location so when it next updates that block, it wont print anything if the block is the same.  But this code ends with ld (hl),e, where e is the low byte of the pointer to map, which means it's almost certainly marking scr with a value different to what it will find in map next time in the preceding code, so that the block will subsequently be updated whether it changes or not.  What it actually needs to be writing to scr is the contents pointed to by de in map, so it should be ld a,(de):ld (hl),a.


It is worth noting though that at the point of that branch in mainloop just before the code segment I posted above, a already contains the value of the new block, and hl already contains a pointer to the appropriate location in scr, so the entire segment of code above could be replaced with ld (hl),a.  :)

I think what happened initially was I was using CPC BASIC 3 to translate my BASIC code into Assembly, which is what I pretty much came up with, which probably explains the lack of comments and it's pretty much a pile of high-level language turned into Assembly.
That would probably be right in that I make a whole lump of code and it could potentially be replaced by a single instruction.  :(
Title: Re: Moving Graphical Images Down the Screen.
Post by: redbox on 22:57, 31 January 14
Quote from: AMSDOS on 22:15, 31 January 14
I think what happened initially was I was using CPC BASIC 3 to translate my BASIC code into Assembly, which is what I pretty much came up with, which probably explains the lack of comments and it's pretty much a pile of high-level language turned into Assembly.
That would probably be right in that I make a whole lump of code and it could potentially be replaced by a single instruction.  :(

Nothing wrong with turning a high level language into assembler to see what's going on, it's just another way of learning.

Even C programmers have to resort to inline assembler sometimes when they realise their loops just aren't fast enough ;)
Title: Re: Moving Graphical Images Down the Screen.
Post by: ervin on 02:33, 01 February 14
That's how I write my code.
I use ccz80 to get something working (and it creates fast code anyway), but then I use inline asm to speed up loops.

Title: Re: Moving Graphical Images Down the Screen.
Post by: AMSDOS on 06:33, 01 February 14
I didn't mean to make it sound as if it was a bad thing and in a way the earlier code reinforces what the earlier BASIC program was doing even though all the information was already there when I was asking for it again, when I didn't need to and the information could simply be copied over to the scr array.  :D

It just overwhelms me that I can get bogged down in Assembly that things tend to get blown out to the point things can be extremely simplified because you've had the wool pulled over your eyes.  :o
Powered by SMFPacks Menu Editor Mod