Hi All,
I've got my small assembly program working where I control a pixel around the screen and check for the x/y pos when it hits the screen border. The method that I've adopted is to keep things afloat in the DE/HL registers. That's all fine, however, I would prefer to start saving values in memory and retrieving as and when required. I've got the following test code which works fine up to 255 but not greater than that.
org &4000
ld de,320
ld (xpos),de
inc de
ld de,(xpos)
ret
xpos: defb 2
I obviously haven't grasped something yet because I just can't get things to work. Searched around but not found any examples. Can anybody show what I'm doing wrong?
Thanks
Quote from: IndyUK on 16:14, 21 December 18
Hi All,
I've got my small assembly program working where I control a pixel around the screen and check for the x/y pos when it hits the screen border. The method that I've adopted is to keep things afloat in the DE/HL registers. That's all fine, however, I would prefer to start saving values in memory and retrieving as and when required. I've got the following test code which works fine up to 255 but not greater than that.
org &4000
ld de,320
ld (xpos),de
inc de
ld de,(xpos)
ret
xpos: defb 2
I obviously haven't grasped something yet because I just can't get things to work. Searched around but not found any examples. Can anybody show what I'm doing wrong?
Thanks
use defw instead of defb. defb defines storage for a byte a not for a word.
DEFW is just one part of it which is used to store 16bit numbers, retrieval takes a bit more code, but the 1st part of your code is correctly storing, you just need to remember that 16bit numbers use 2 bytes. I find a Scientific Calculator is useful for this in Base-N mode, otherwise it's PRINT HEX$(PEEK(lobyte));HEX$(PEEK(hibyte)) in BASIC.
This is my little example:
org &4000
ld de,320 ;; de = 320
ld (xpos),de ;; store into xpos
ld hl,xpos ;; address of xpos label
ld e,(hl) ;; store contents of HL @ xpos into E
inc hl ;; increase HL+1 to xpos+1
ld d,(hl) ;; store contents of HL @ xpos+1 into D
ld a,e
call &bb5a
ld a,d
call &bb90
ret
xpos: defw 0
I put a little example on the end of that, so if you compile that, change to PEN 2 in MODE 1, CALL &4000 will display an '@' character in PEN 2 before returning to PEN 1.
The reason for that is when the value 320 is transformed into a 2 byte hexadecimal number, it becomes &140, &40 is stored into the E register and &01 into the D.
Quote from: AMSDOS on 08:26, 22 December 18
DEFW is just one part of it which is used to store 16bit numbers, retrieval takes a bit more code, but the 1st
This is not true - retrieval takes the same amount of code. You can do both 'ld (xpos), de' and 'ld de, (xpos)' and you'll get the expected results - store the contents of de into memory at xpos, xpos+1 and retrieve memory contents at xpos, xpos+1 into de.
You can replace the following code in your example
...
ld hl,xpos ;; address of xpos label
ld e,(hl) ;; store contents of HL @ xpos into E
inc hl ;; increase HL+1 to xpos+1
ld d,(hl) ;; store contents of HL @ xpos+1 into D
...
with single ld de, (xpos)
For a single spot in memory you can do that certainly, I'm usually gathering a series of 16-bit data, which usually for that I have a place in memory which points to that information.
@IndyUK (http://www.cpcwiki.eu/forum/index.php?action=profile;u=2915) - Here's my Assembly routine which is using PLOT to draw lines around the screen, I've also put in the checks to test the edge of the screen. What I've done to get the line across the entire screen is to use:
ld hl,(xpos)
inc hl
ld (xpos),hl
for example.
If it something like:
ld hl,xpos
inc (hl)
then only 1 byte is updated before reaching it's threshold and emerging back on the other side.
Anyway, this is what I came up with:
org &8000
ld b,9
ld c,b
call &bc38 ;; border 9
ld a,1
call &bc0e ;; mode 1
ld hl,320 ;; initial position
ld (xpos),hl ;; for xpos
ld hl,200 ;; initial position
ld (ypos),hl ;; for ypos
ld a,1
call &bbde ;; graphics pen 1
call plot ;; draw plot centre of screen
.mainloop
ld a,1
call &bb1e ;; test right arrow key
call nz,moveright ;; if found move right
ld a,8
call &bb1e ;; test left arrow key
call nz,moveleft ;; if found move left
ld a,0
call &bb1e ;; test up arrow key
call nz,moveup ;; if found move up
ld a,2
call &bb1e ;; test down arrow key
call nz,movedown ;; if found move down
ld a,18
call &bb1e ;; test if enter/return pressed
jr z,mainloop ;; jump to main loop if not found
ret ;; else exit to BASIC
.moveright
ld hl,(xpos) ;; check if value of xpos
ld de,638 ;; equals right side of screen
and a
sbc hl,de
jr z,rghtedgefnd ;; if true jump to right edge found (rghtedgefnd)
ld hl,(xpos)
inc hl ;; otherwise increase value of xpos
ld (xpos),hl
call plot ;; and plot it's new position.
.rghtedgefnd
ret ;; before returning to main loop
.moveleft
ld hl,(xpos)
ld de,0
and a
sbc hl,de
jr z,lftedgefnd
ld hl,(xpos)
dec hl
ld (xpos),hl
call plot
.lftedgefnd
ret
.moveup
ld hl,(ypos)
ld de,398
and a
sbc hl,de
jr z,topedgefnd
ld hl,(ypos)
inc hl
ld (ypos),hl
call plot
.topedgefnd
ret
.movedown
ld hl,(ypos)
ld de,0
and a
sbc hl,de
jr z,btmedgefnd
ld hl,(ypos)
dec hl
ld (ypos),hl
call plot
.btmedgefnd
ret
.plot
ld hl,(xpos)
ex hl,de ;; xpos data goes into de register.
ld hl,(ypos)
call &bbea ;; plot xpos,ypos
ret
.xpos defw 0
.ypos defw 0
Docent/AMSDOS
Thanks guys for the pointers and advise. I thought I was missing something.
AMSODOS - Thank you for the example of moving a pixel around the screen and storing the x/y pos in memory. It was so amazing to see how your code was similar to mine. I did see in yours some quicker ways of checking the screen boundary, which I would like to use if it's ok with you(?)
Thanks
Absolutely! :) And if you need to alter the boundary, the value assigned to DE is the one to change.
I've also made some adjustments to that routine I posted above, so it now works with a Sprite Driver out of my Assembly Language book, if you're interested in that, I can post it as well, though that only needs a 8-bit data checker. Might be worth posting the original program too just to show how I transformed it from a simple Move a Single Multicoloured Image across the screen, to an interactive Moving a Single Multicoloured Image anywhere onscreen, though perhaps for another thread?