English Amiga Board

English Amiga Board (http://eab.abime.net/index.php)
-   Coders. Asm / Hardware (http://eab.abime.net/forumdisplay.php?f=112)
-   -   why does my setPixel method not work correctly? (http://eab.abime.net/showthread.php?t=99739)

geldo79 20 November 2019 22:10

why does my setPixel method not work correctly?
 
Hi,

Who can tell me what's wrong with my method? It works, but only for lines < 187. Ok, I think in principle i know whats wrong: each lines consists of 44 Bytes in my case (16 Pixel hidden space on each side), and i use interleaved bitplanes (4 bitplanes). Thus, i have to multiply y by 4x44 = 176 to get the correct offset. At line 186, this gives 176x186 = 32736. At line 187, the value is more than word size. But, i use longwords. So what's wrong? :confused

SetPixel:

* d0 : x
* d1 : y

move.l BITPLANE,a0
add.w #2,a0
divu #8,d0
mulu.w #4*44,d1

add.l d0,d1
Swap d0
Move.b #-1,d2
Sub.b d0,d2
move.w #3,d3

plane_loop:

bset d2,(a0,d1)
add.w #44,d1
dbra d3,plane_loop

rts

deimos 20 November 2019 22:15

I don't think you're specifying that you're using longs:

bset d2,(a0,d1)

might need to be:

bset d2,(a0,d1.L)

Galahad/FLT 20 November 2019 22:21

Your error is to do with your division.

You haven't allowed for your DIVU to have a remainder in the high word of D0.

If your number divides equally with no remainder, your add.l d0,d1 will be ok.

If your number has a remainder, your add.l d0,d1 will NOT be ok, because you will be essentially adding a really big longword instead (it will interpret the remainder as a memory address)

meynaf 21 November 2019 10:20

Your routine would be better written this way :
Code:

move.l BITPLANE,a0
addq.w #2,a0
moveq #-1,d2
sub.b d0,d2
lsr.l #3,d0
mulu.w #4*44,d1
add.l d0,d1
add.l d1,a0

moveq #3,d3

plane_loop:

bset d2,(a0)
add.w #44,a0
dbra d3,plane_loop

rts

There were 3 errors in your code :
- as said, (a0,d1) instead of (a0,d1.l)
- as said, remainder of divu
- and a nice time bomb : add.w #44,d1 instead of add.l #44,d1

ross 21 November 2019 11:06

Or to be picky
Code:

moveq #3,d3

plane_loop:

bset d2,(a0)
lea 44(a0),a0
dbra d3,plane_loop

rts

16 cycles less on 68k :)

Cyprian 21 November 2019 15:56

Instead of that:
Code:

moveq #3,d3

plane_loop:

bset d2,(a0)
lea 44(a0),a0
dbra d3,plane_loop

faster one:
Code:

bset d2,(a0)
bset d2,44(a0)
bset d2,88(a0)
bset d2,132(a0)


Exodous 21 November 2019 16:51

Divides and multiplies are also quite slow. I can't remember the cycle timings off the top of my head, but you would replace:

Code:

        divu #8,d0                ; Divide by 8 is shift 3 places right
with

Code:

        moveq.l        #7,d3
        and.l        d0,d3                ; d3 = remainder for use later
        asr.l        #3,d0                ; d0 = d0 / 8

You need to use the remainder in d3 lower down to calculate the bit to set.


Code:

        mulu.w #4*44,d1
Is probably quicker re-written as shifts and adds like:

Code:

        asl.l        #4,d1                ; d1 = 'y' * 16
        add.l        d1,a0                ; add *16
        add.l        d1,a0                ; add *16
        add.l        d1,a0                ; add *16
        asl.l        #3,d1                ; d1 = 'y' * 128
        add.l        d1,a0                ; add *128
        add.l        d0,a0                ; a0 now points to the first memory address


geldo79 21 November 2019 23:02

Ok.....think i got it. Thanks! But another question: if i want to set a complete Byte to 1 (white), why can't i use

move.b $FF,(a0,d1.l)

instead of

bset d2,(a0,d1.l).

It does not crash, but it's drawing some pixels white, and some pixels black. I don't understand that. And if i use instead

move.w $FFFF,(a0,d1.l)

or

move.l $FFFFFFFF,(a0,d1.l)

my program crashes. Why? :confused

ross 21 November 2019 23:21

This:
Quote:

Originally Posted by geldo79 (Post 1360496)
move.b $FF,(a0,d1.l)

or in a more compact form:
Quote:

st (a0,d1.l)
set 8 consecutive pixels but only on one plane.
If you have four plane you need to do four of this instructions, a write for every plane (and color 15 is then used).


This:
Quote:

move.w $FFFF,(a0,d1.l)
or
move.l $FFFFFFFF,(a0,d1.l)
EDIT: sure a word/longword read from an odd memory address,
but for the intended immediate form (#$) could also end up to a word/longword write to an odd memory address, depending on d1.l value.
Both crash on bare 68k processor.

geldo79 22 November 2019 00:10

Ok. But

move.b $FF,(a0,d1.l)

and

st (a0,d1.l)

doesn't do the same :nervous Only the second method does what i want.

Don_Adan 22 November 2019 00:13

Quote:

Originally Posted by geldo79 (Post 1360506)
Ok. But

move.b $FF,(a0,d1.l)

and

st (a0,d1.l)

doesn't do the same :nervous Only the second method does what i want.

No, your code is buggy.
You must use
Move.b #$ff, (a0,d1.l)

ross 22 November 2019 00:17

Thanks Don.

@geldo79, of course I meant #$ff for the st equivalency ;)
$ff is a memory location.

geldo79 22 November 2019 00:40

Ooops....yes, of course!

hooverphonique 22 November 2019 11:49

Quote:

Originally Posted by geldo79 (Post 1360496)
And if i use instead

move.w $FFFF,(a0,d1.l)

or

move.l $FFFFFFFF,(a0,d1.l)

my program crashes. Why? :confused


$FFFF/$FFFFFFFF are odd addresses - you can only access even addresses with word or longword size.
As mentioned above, you probably meant #$FFFF, but even then it would crash if a0+d1 is odd.

on 68020+ odd addressing for word/long is allowed.

geldo79 22 November 2019 14:16

Ok. So, my next question is : If i would like to set a graphic of 3x3 pixel size, how can I set it properly if it overlaps two bytes? Of course, i could calculate the fraction which is in the first byte and set it, and calculate the fraction for the second byte and set it. But is there an easier way to do it? Would be nice if i could just set a word, and if the shift to e.g. the right side is big enough to show the graphic completely on the next byte, i would set the word on the next byte location. But this is not allowed it it is an odd number.....:confused

DanScott 22 November 2019 14:47

you could store your 3 pixel wide data in a low word of a data register, shifted to the pixel position

and then:

move.b d0,1(a0)
ror.w #8,d0
move.b d0,0(a0)

a0 can point to an odd address then

deimos 22 November 2019 15:05

Quote:

Originally Posted by geldo79 (Post 1360634)
Ok. So, my next question is : If i would like to set a graphic of 3x3 pixel size, how can I set it properly if it overlaps two bytes? Of course, i could calculate the fraction which is in the first byte and set it, and calculate the fraction for the second byte and set it. But is there an easier way to do it? Would be nice if i could just set a word, and if the shift to e.g. the right side is big enough to show the graphic completely on the next byte, i would set the word on the next byte location. But this is not allowed it it is an odd number.....:confused

You can do byte accesses to memory at any address. On a 68000 words accesses always need to be aligned to an even address. On 68020 or higher this restriction is lifted, but comes with a performance penalty (2 memory accesses). Access to memory is always according to the width of the bus. Probably oversimplified, but whatever.

No matter whether you access memory 8, 16, 32 bits at a time, you will have to account for your objects wrapping past the edge of your words. For such small objects I would consider pre-calculating the shifts across a word - there's only 16 of them, and only 2 of them involve overlapping into a second word.

Edit: You'd probably get some savings by making your objects 4x4, even if you never used that last pixel.

geldo79 23 November 2019 19:24

I'll try to precalculate. But at the moment, I wonder if my project is possible on the amiga. I try to code some spacewar like game. My spaceship is a sprite....and it moves very smoothly. But now as i try to implement the shooting mechanism of the ship, it seems to be difficult to keep the game speed at the actual level. Problem is that every laser cannon bob (or at least graphic object...not sure if i will use the blitter or cpu) has to be updated concerning its position for every frame. Up to now, the cpu does not seem to be able to calculate everything in time. I use a bresenham algorithm to calculate the positions. And in order to be able to detect collisions, i do an update pixel by pixel. Otherwise i could increase or decrease x or y of the bob by a larger amount (depending on its speed), but then collision detection will be difficult. Its a bit frustrating at the moment.

deimos 24 November 2019 08:30

Quote:

Originally Posted by geldo79 (Post 1360929)
Up to now, the cpu does not seem to be able to calculate everything in time. I use a bresenham algorithm to calculate the positions. And in order to be able to detect collisions, i do an update pixel by pixel. Otherwise i could increase or decrease x or y of the bob by a larger amount (depending on its speed), but then collision detection will be difficult. Its a bit frustrating at the moment.

I think you should consider changing your approach, calculate positions, physics, collisions, etc. at whatever accuracy is needed and using line intersections, bounding boxes, etc. for efficiency, then convert to screen resolution to draw as a separate step.


All times are GMT +2. The time now is 13:50.

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2020, vBulletin Solutions Inc.

Page generated in 0.05020 seconds with 11 queries