News:

Printed Amstrad Addict magazine announced, check it out here!

Main Menu
avatar_AMSDOS

Understanding SCR HORIZONTAL & SCR VERTICAL

Started by AMSDOS, 07:14, 04 February 11

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

AMSDOS

I've been playing around with SCR HORIZONTAL, trying to make some sense of it to see if I could use them for making some sprites.

My inital findings found:

         
  • I can use them in CP/M
  • They operate on X-coordinate, Y-coordinate manner, though resolution is set (0-320)x(0-199) in mode 1 for example
  • Writes to screen based on current write mode - which is based the write mode set by SCR ACCESS (&BC59) which can be Fill, XOR, AND, OR.
From this I thought perhaps I could use these in CP/M for writing to screen. Though the other problems I'm having reflect to how they work.

Same principals I think apply with both of these routines (SCR Horiz and SCR Vertical) where the firmware guide specifies the Accumulator "A" contains an Encoded Pen which is to be used. I'm imagining part of the problem is this is some other value which represents what's going to be drawn, I was hoping it was like a Colour Mask, and have been trying with Colour Masks to produce something. The second problem seems to be a third paramater this routine uses. HL & DE contain the YPOS & XPOS though in this case, BC is also used which contains an end value for XPOS - rightfully named since this routine draws from one point to another using an Encoded pen number.

Has anyone come across this or used it before, and if so is it worth checking out or simply another routine to avoid?

Below is my failed attempt in using SCR HORIZONTAL, it doesn't crash or anything, though what I was trying to do was poke the byte masks (&D0 and &60) and while it appears that &D0 is being been successfully poked to screen, &60 isn't happening. :(

org &8000
ld hl,byte
ld a,(hl)
ld hl,(ypos)
ld de,(xpos)
ld bc,(x2)
call &bc5f
ld hl,(bytaddr)
inc (hl)
ld (bytaddr),hl
ld a,(hl)
ld hl,(ypos)
ld de,(xpos)
ld bc,(x2)
inc de
inc bc
call &bc5f
ret
.xpos defw 0
.x2 defw 8
.ypos defw 199
.bytaddr
defw byte
.byte defb &d0
defb &60


* Using the old Amstrad Languages :D   * with the Firmware :P
* I also like to problem solve code in BASIC :)   * And type-in Type-Ins! :D

Home Computing Weekly Programs
Popular Computing Weekly Programs
Your Computer Programs
Updated Other Program Links on Profile Page (Update April 16/15 phew!)
Programs for Turbo Pascal 3

Axelay

The part where you are using:


ld hl,(bytaddr)
inc (hl)
ld (bytaddr),hl
ld a,(hl)


probably isnt doing what you intend.  With that you are loading HL with the address of byte, incrementing the contents of the address pointed to by it (mask &d0 becomes &d1) and loading the unchanged pointer to byte back to bytaddr and loading &d1 into a.  I guess you meant to use inc hl  rather than inc (hl)?


I think you would see the result better if you changed ypos for the second print too, currently it mostly overwrites the first print because of the small change you make to the x start and finish positions with those single incs of de/bc at the end.


Afraid I cant tell you whether the firmware routine in question is worth using though.  I use firmware in loaders and that's about it! ;)


AMSDOS

Ooops yeah I fairly much forgot to change the "INC (HL)" - initally it was "INC HL", and I cannot even remember why I changed it (hot and humid wet weather isn't helping).

With that change it is sort of producing part of what I was trying to draw, but not exactly. Instead now it's poking &E0 and &40 instead of &D0 and &60!

Well I'm not sure if what I'm applying here is correct or suitable, I was interpreting Encoded PEN which is what the firmware guide calls it as Masked Pen, in my example I'm trying to draw a line at cursor length, which is 8 pixels along, &D0 and &60 are what represent those in MODE 1. I've tried adjusting the end-line which is stored in BC as X2, though have had no luck with that. In this case this routine may only be there to draw a Horizontal Line across the screen in a given Colour (why it's encoded is maybe so it can do some pattern effect). SCR VERTICAL likewise would cater for the Vertical Drawing.

Initally I was interested in SCR PIXELS (&BC5C), though the firmware manual states this writing to the screen doesn't take into account the Write Mode which can be set by SCR_ACCESS (@ &BC59), which is more of a blow than anything! :(

* Using the old Amstrad Languages :D   * with the Firmware :P
* I also like to problem solve code in BASIC :)   * And type-in Type-Ins! :D

Home Computing Weekly Programs
Popular Computing Weekly Programs
Your Computer Programs
Updated Other Program Links on Profile Page (Update April 16/15 phew!)
Programs for Turbo Pascal 3

AMSDOS

Okay this is what I've come up with, but it's riddled with problems.

For the amount of effort required, I can see why nobody in the right mind would adopt using something like this!  ???

org &8000
ld hl,byte
ld a,(hl)
ld hl,(ypos)
ld de,(xpos)
ld bc,(x2)
call &bc5f
ld hl,(bytaddr)
inc hl
ld (bytaddr),hl
ld a,(hl)
ld hl,(x2)
inc hl
ld (xpos),hl
ld hl,(x2)
inc hl
inc hl
inc hl
ld (x2),hl
ld hl,(ypos)
ld de,(xpos)
ld bc,(x2)
call &bc5f
ret

.xpos defw 0
.x2 defw 3
.ypos defw 199
.bytaddr
defw byte
.byte defb &d0
defb &60


The code focuses on display two pen masks, in mode 1 a mask is 4 pixels (0-3), this program simply sets up the first mask & displays it, by the time it needs to display the next pixel mask, "BC" register needs to change to account for the next end point - the value of xpos also needs to move along to show the second pen mask in the right spot. This obviously only works once cause critical points need changing and simply specifying an end point makes the whole purpose of this impractical! So like I said earlier, only really useful for displaying patterns along Horizontal or Vertical lines, not specifically designed for anything else!  :-[ 
* Using the old Amstrad Languages :D   * with the Firmware :P
* I also like to problem solve code in BASIC :)   * And type-in Type-Ins! :D

Home Computing Weekly Programs
Popular Computing Weekly Programs
Your Computer Programs
Updated Other Program Links on Profile Page (Update April 16/15 phew!)
Programs for Turbo Pascal 3

AMSDOS

Curiosity and sheer stubbornness made this program:

org &8000

ld a,1
call &bc59
 
ld b,8

ld a,(byte) 
ld hl,(ypos)
ld de,(xpos)
.loop
push bc   
ld bc,(xend)
call &bc5f
ld hl,(bytaddr) 
inc hl
ld (bytaddr),hl
ld a,(hl)
ld hl,(ypos)
ld de,(x2)
ld bc,(x2end)
call &bc5f
ld hl,(bytaddr)   
inc hl   
ld (bytaddr),hl 
ld a,(hl)
ld hl,(ypos)
dec hl
ld (ypos),hl
ld de,(xpos)
pop bc
djnz loop

ld hl,bytaddr
ld de,(resaddr)
ld (hl),e
inc hl
ld (hl),d
ld de,199
ld hl,ypos
ld (hl),e
inc hl
ld (hl),d

ret

.resaddr defw byte
.xpos  defw 0
.xend  defw 3
.x2  defw 4
.x2end  defw 7
.ypos  defw 199
.bytaddr defw byte
.byte  defb &D0,&60
  defb &77,&CC
  defb &03,&08
  defb &03,&08
  defb &03,&08
  defb &03,&08
  defb &03,&08
  defb &10,&00


After those earlier attempts, I've added more variables used set values (instead of alternating critical values), thinking along the lines of what are constant values and which variables need changing has allowed me to produce an 8 x 8 sprite using SCR HORIZONTAL.

The program above sets up the screen write mode to XOR - to use Fill change:

LD A,1
CALL &BC59


to:

LD A,0
CALL &BC59


Still in order to make this routine execute every time I wanted to call it, I would need to restore some of the variables, I've written it in such a way that the X-Coordinates remain constant, however the Y-Coordinate needs to be adjusted to deal with the 8 rows the sprite has.  I've also setup a Pointer which points to Sprite Data, in order to move though that, the value of the Pointer is incremented. Obviously once the program has ran though that the value isn't restored and following after main loop and on return to BASIC in my case those values are returned to the pointer and YPOS.

As it is at the moment, it's only drawing the image to one spot, top left corner, to have the thing moving around on screen, further variables are needed to hold proper X, Y positions onscreen, which would need to be recalculated in relation to the positions of the sprite.

Currently speed wise doesn't appear to be an issue, those extra demands may dictate the way that may perform though, time wise I trialed it against Sean McManus' XOR Sprite Routine:

org &9000
ld hl,198
ld de,0
call &bc1d
push hl
ld de,rocket
ex de,hl
ld c,(hl)
inc hl
ld b,(hl)
inc hl
ex de,hl
pop hl
.notzero
push bc
push hl
.loop
ld a,(de)
xor (hl)
ld (hl),a
inc hl
inc de
djnz loop
pop hl
ld bc,&0800
add hl,bc
jr nc,exit
ld bc,&c050
add hl,bc
.exit
pop bc
dec c
jr nz,notzero
ret
.rocket defb &08,&02
defb &d0,&60
defb &77,&cc
defb &03,&08
defb &03,&08
defb &03,&08
defb &03,&08
defb &03,&08
defb &10,&00


Sean's routine appears to have a slight edge and given it's ready position the sprite anywere around the screen, makes it more efficent.

I've also attached a commented copy of the SCR HORIZONTAL routine.
* Using the old Amstrad Languages :D   * with the Firmware :P
* I also like to problem solve code in BASIC :)   * And type-in Type-Ins! :D

Home Computing Weekly Programs
Popular Computing Weekly Programs
Your Computer Programs
Updated Other Program Links on Profile Page (Update April 16/15 phew!)
Programs for Turbo Pascal 3

AMSDOS

#5
This is my scrappy bit of Pseudocode which in theory if that's correctly applying everything right, could be another way of make a sprite routine (as governed by the write mode set by SCR access).

MODE 1 SCR HORIZ ROUTINE

variables for first value reached and second value reached for loops needs to be applied.

first value reached may equal 0 (after first call to screen horiz has been done this can be incremented), only needs to loop twice before it's set back to 0.

second value reached = 0 (loop will only need to be applied 8 times then it can exit)

load address of sprite (uses a predefined sprite setup in memory - pen mask)
load address of xpos (wherever that maybe - co-ordinate based)
load address of ypos (wherever that maybe - co-ordinate based as well)
endxpos = xpos + 3 (the rules of the screen horiz means this must be applied)

begin loop

call screen horiz

(all of the following below needs to be loaded back into the registers since SCR HORIZ has now corrupted those registers)

sprite = sprite + 1 (sprite is a byte)
xpos = endxpos + 1 (Is 4 positions off the original value)
endxpos = xpos + 3 (Is also 4 positions off the original value)
load ypos (original value)

first value reached needs to be checked here in order for loop to jump

does loop counter equal 2 - return to loop if not otherwise continue

first value reached = 0
Decrease ypos by 1
Return XPOS value to original point (perhaps subtract 4 will work)
Return ENDXPOS value to original point (= 3 more than XPOS, subtract 4 maybe desiriable unless a quicker approach could be applied?)

Second value reached needs to be checked here in order for loop to jump

Has this reached 8 passes, if not return to original loop, otherwise exit.


I maybe able to conjure up some assembly from this (my notes in brackets are trying to reflect what has to happen in assembly for it to work), though I'm posting this routine here in case there's a problem with it (something I overlooked), or it could be improved.

EDIT: I forgot to mention this is based on an 8x8 sprite.  :)
* Using the old Amstrad Languages :D   * with the Firmware :P
* I also like to problem solve code in BASIC :)   * And type-in Type-Ins! :D

Home Computing Weekly Programs
Popular Computing Weekly Programs
Your Computer Programs
Updated Other Program Links on Profile Page (Update April 16/15 phew!)
Programs for Turbo Pascal 3

AMSDOS

#6
This is what I've come up with for an 8x8 Sprite Effect using SCR HORIZONTAL (I've attached the original Source file):

;; 8x8 Sprite Demonstration using SCR HORIZONTAL
;; Entry from BASIC:
;; CALL &4000,<address of sprite>,<x-coordinate>,<y-coordinate>
;; E.g. CALL &4000,&40B4,104,100

org &4000

ld hl,stor_xpos
ld e,(ix+02)
ld d,(ix+03)  ;; Routine to collect second paramater from call
ld (hl),e  ;; and put it into stor_xpos
inc hl
ld (hl),d
ld hl,(stor_xpos) ;; Simply takes value from that stored spot
ld (xpos),hl  ;; puts it into x-coordinate for main loop to use.
inc e
inc e   ;; Increment that 3 times
inc e
ld hl,stor_xend
ld (hl),e
inc hl   ;; This is the value for end base x-coordinate
ld (hl),d
ld hl,(stor_xend) ;; Put that stored value into the
ld (xend),hl  ;; end base x-coordinate for main routine.
ld hl,ypos
ld e,(ix+00)
ld d,(ix+01)  ;; Collect data from third paramater which 
ld (hl),e  ;; becomes position for y-coordinate.
inc hl
ld (hl),d
ld hl,spprt
ld e,(ix+04)  ;; First paramater has the address of the sprite,
ld d,(ix+05)  ;; it acts as an pointer as it has a place in
ld (hl),e  ;; memory.
inc hl
ld (hl),d
.loop ld de,(xpos)  ;; Base x-coordinate goes into DE
ld hl,(spprt)  ;; Pointer address to sprite in HL
ld a,(hl)  ;; Contents of that address into A (Sprite)
ld hl,(ypos)  ;; Base y-coordinate goes into HL
ld bc,(xend)  ;; Base end x-coordinate goto into BC
call &bc5f  ;; call SCR_HORIZONTAL

ld hl,(spprt)
inc hl   ;; Increment to next byte of sprite
ld (spprt),hl
ld de,(xend)
inc e   ;; New base x-coordinate now equals one more
ld hl,xpos  ;; than old base end x-coordinate
ld (hl),e

ld hl,(xpos)
inc l   ;; Which means New base end x-coordinate equals
inc l   ;; 3 more than new base end x-coordinate
inc l
ex hl,de  ;; shifting contents here so I can use HL to poke
ld hl,xend
ld (hl),e  ;; new value for new base end x-coordinate.
ld a,(cl1)
inc a   ;; routine to check if first pass loop has been
ld (cl1),a  ;; reached. If it has not been reached will return
ld b,a   ;; back to loop and use that new detail, otherwise
ld a,(loop1)  ;; will proceed to continue to next line
cp b

jr nz,loop
ld a,(cl1)  ;; reverts first loop counter back to 0
xor a
ld (cl1),a
ld hl,(ypos)  ;; new line so base y-coordinate
dec hl
ld (ypos),hl  ;; can be decreased by 1
ld hl,(stor_xpos) ;; use our stor_xpos value to revert 
ld (xpos),hl  ;; base x-coordinate position to original spot.

ld hl,(stor_xend) ;; same as above except return base end
ld (xend),hl  ;; x-coordinate back to where it was.
ld a,(cl2)
inc a   ;; the routine to check if second loop has been
ld (cl2),a  ;; reached. Like the first one will return back to
ld b,a   ;; the main loop when 8 lines have been written.
ld a,(loop2)
cp b
jr nz,loop

ld a,(cl2)  ;; and this returns that second loop back to 0
xor a   ;; otherwise something odd happens and slows down
ld (cl2),a  ;; routine!

ret   ;; return to BASIC if called from there.
.cl1 defb 0   ;; counter position for first loop
.cl2 defb 0   ;; counter position for second loop
.loop1  defb 2   ;; loop one will loop until counter position = 2
.loop2  defb 8   ;; loop two will loop until counter position = 8
.xpos defw 0   ;; Where base x-coordinate goes.
.ypos defb 0   ;; Where base y-coordinate goes.
defb 0
.xend defw 0   ;; Where base end x-coordinate goes.
.stor_xend
defw 0   ;; Base end x-coordinate goes here for safe keeping
.stor_xpos
defw 0   ;; Likewise for base x-coordinate
.spprt defw &0   ;; Address pointer to where the sprite could be
.sprite defb &D0,&60  ;; I've decided to put my sprite here of all places!
defb &77,&CC
defb &03,&08
defb &03,&08
defb &03,&08
defb &03,&08
defb &03,&08
defb &10,&00


Using it with this:


org &5000

ld a,1
call &bc59
ret


I can get XOR Sprites. It's only limitation (which I should have realised earlier though didn't really try more values) is the x-coordinate horizion. My sprite is 8 pixels across, moving it in 1 byte increments changes the appearance of the image ( ??? ), though I can change it for 8 pixel increments (e.g. 0,8,16,24,32,40, etc). No problems with y-coordinate positioning so can smoothly move my sprite (rocket) down the screen! Of course if I apply SCR VERTICAL so it becomes something like the SCR HORIZONTAL, I'll be able to smoothly move something across the screen (maybe)!
* Using the old Amstrad Languages :D   * with the Firmware :P
* I also like to problem solve code in BASIC :)   * And type-in Type-Ins! :D

Home Computing Weekly Programs
Popular Computing Weekly Programs
Your Computer Programs
Updated Other Program Links on Profile Page (Update April 16/15 phew!)
Programs for Turbo Pascal 3

arnoldemu

You should look at my pixel drawing examples. I am sure one of these could be used to draw sprites under CPM.
Using SCR DOT POSITION, and then using SCR PIXELS to write your raw pixels (in the encoded form for the mode) should be good enough.

But it is interesting to see how SCR HORIZONTAL and SCR VERTICAL can be used.



My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

AMSDOS

Quote from: arnoldemu on 13:39, 28 April 11
You should look at my pixel drawing examples. I am sure one of these could be used to draw sprites under CPM.

Sorry I've been holding off with those just to see what I could get from these routines. I'm presuming your referring to the 4 plotting routines on your site.

* Plot 1 is of course plotting using GRA_PLOT_ABSOLUTE. (Did you get the numerous versions I made of it? I'll attach a copy of plot image.asm for everyone!  ;D ). This is handy if your making a graphical status bar in games, or want some kind of large animation without requiring constant animination or just want background without loading in a whole 17k screen!

QuoteUsing SCR DOT POSITION, and then using SCR PIXELS to write your raw pixels (in the encoded form for the mode) should be good enough.

* Plot 2 (I just had a look at it), sounds good, unfortunately SCR PIXELS doesn't comply with write mode set by SCR ACCESS :( True perhaps it can simply be overcomed having 0 byte around the image. I just tried this with the Firmware Indirective - SCR WRITE in CP/M which appears to have worked, though I was under the impression Firmware Indirectives don't go too well in CP/M (is it something to do with the state of the ROM?). SCR WRITE unlike SCR PIXELS will actually write in state of the Graphics write mode, so perhaps that's worth looking into as well.

QuoteBut it is interesting to see how SCR HORIZONTAL and SCR VERTICAL can be used.

And the good thing about the SCR HORIZONTAL routine is it appears quick enough to have constant animations moving along the screen. Just needs a bit of overhead information to setup the graphic to draw.
* Using the old Amstrad Languages :D   * with the Firmware :P
* I also like to problem solve code in BASIC :)   * And type-in Type-Ins! :D

Home Computing Weekly Programs
Popular Computing Weekly Programs
Your Computer Programs
Updated Other Program Links on Profile Page (Update April 16/15 phew!)
Programs for Turbo Pascal 3

AMSDOS

I was having a few problems understanding how SCR VERTICAL would work cause for one thing everything is working vertically - I can understand how the Encoded PEN would work with SCR HORIZONTAL cause the screen is made up of them (in MODE 1 for example &C000 deals with pixels 0 to 3, &C001 deals with pixels 4,7 and so on rounding off the first line at &C04F). SCR VERTICAL is now after a start base  Y-coordinate position as well as a end base Y-coordinate. However after playing around with the Plot Image routine and made some small adjustments to it, it's now a SCR VERTICAL routine.

SCR VERTICAL is good in one way cause I can use the same Y-coordinate position for my start and end base points and for SCR VERTICAL it's only asking for one position for the X-coordinate. I'm still unsure how this Encoded PEN works with this, so in a sense I'm treating SCR VERTICAL as a all-in-one plotting routine to display my image to. To resolve the Encoded PEN issue I'm using SCR INK ENCODE to convert that image (stored in PEN numbers), into Encoded PEN. Good news is it works! This approach also allows pixel perfect movement in all directions (this might work for SCR HORIZONTAL if I use SCR INK ENCODE for encoding PEN values while displaying it as well instead of jumping 8 frames along). The only setback I can think of is having the extra routine (SCR INK ENCODE) going though every PEN value, which means going through every single byte - for which an 8x8 sprite means 64 times as opposed to using Encoded PEN combinations, each Encoded PEN byte = 4 pixels, so to get 8x8 sprite, the routine only needs to run though 16 times to produce the same thing. Anyway I've attached by SCR VERTICAL for those who want to have a look at it!  ;D  I haven't developed it as far as the SCR HORIZONTAL yet, cause I was doing this one with my fingers crossed!  ;D
* Using the old Amstrad Languages :D   * with the Firmware :P
* I also like to problem solve code in BASIC :)   * And type-in Type-Ins! :D

Home Computing Weekly Programs
Popular Computing Weekly Programs
Your Computer Programs
Updated Other Program Links on Profile Page (Update April 16/15 phew!)
Programs for Turbo Pascal 3

sigh

Quote from: CP/M User on 10:31, 30 April 11
This approach also allows pixel perfect movement in all directions

Does this mean that you could use this method to have 1 pixel/perfect pixel  multiscrolling in a game?

AMSDOS

#11
Quote from: sigh on 12:40, 30 April 11
Does this mean that you could use this method to have 1 pixel/perfect pixel  multiscrolling in a game?

No sorry, it means a Sprite can be moved around 1 pixel at a time. What you can do with this last routine I posted (SCR VERT 3.ASM) is adjust the positioning of XPOS & YPOS, I use the Winape Assembler to make it a little bit easier and by using various values along side one another, it will move it around byte by byte without messing up the image. Just needs some further tweaks so it can be perform like SCR HORIZ.

I have been pondering on some kind of scroller though I don't think it would be multiscrolling! There was a reasonible one posted a few months ago in one of the scrolling threads, which had the traits of Parallax Scrolling, though I'm unsure what's out there (Sub Hunter seems to have some nice scrolling too!)
* Using the old Amstrad Languages :D   * with the Firmware :P
* I also like to problem solve code in BASIC :)   * And type-in Type-Ins! :D

Home Computing Weekly Programs
Popular Computing Weekly Programs
Your Computer Programs
Updated Other Program Links on Profile Page (Update April 16/15 phew!)
Programs for Turbo Pascal 3

Powered by SMFPacks Menu Editor Mod