English Amiga Board

English Amiga Board (https://eab.abime.net/index.php)
-   Coders. Tutorials (https://eab.abime.net/forumdisplay.php?f=73)
-   -   I am trying to make my first GFX assembler code (https://eab.abime.net/showthread.php?t=95154)

litwr 24 November 2018 19:47

Quote:

Originally Posted by ross (Post 1287003)
You have used -m68000. tab is a 32 bit address.
How this can be used for a 16 bit displacement?
Remove SECTION directive and use pc relative or better rethink your code :)

Thank you but I need sections.

Quote:

Originally Posted by Leffmann (Post 1287009)
Add
basereg tab,A6
above your code and it will convert to 16-bit offsets.

With a bit more work you can also get absolute references like
move.w stuff,D0
automatically optimized into
move.w (offset,An),D0
.

It works! :) Thank you I really need to do much work studying 68k assembler options and features. Is there any good book or site for this?

EDIT. With basereg I don't need a separate linker invocation. :)

Don_Adan 24 November 2018 20:35

Quote:

Originally Posted by litwr (Post 1286991)
Thanks for the help. IMHO it is better to have separate colors for bg and borders like on the 8-bit Commodores.
And I got another problem. I have a code
Code:

    lea tab,a3
    moveq #0,d1
    lea (a3,d1),a6
    move.w (tab,a6),d2

    section Data
tab dc.w 0,0,0,0,0,0

The VASM doesn't want to work with it, it prints

error 3005: reloc type 10, size 16, mask 0xffffffffffffffff (symbol tab + 0x0) not supported

I used VASM -m68000 -Fhunkexe -o MYFILE MYFILE.asm.

I also tried to use VASM -m68000 --no-opt -Fhunk -m68000 -o MYFILE.o MYFILE.asm. It works, it produces an obj-file. But the linker didn't work. :( I used vlink -bamigahunk -s -o MYFILE MYFILE.o. I get

Error 21: MYFILE.o (CODE+0x14): Reference to undefined symbol _SDA_BASE_.

What is it? Please help me.

Your code looks very strange. No big sense for me.

The mostly used 68000 version is next:

lea tab,a6 ; base
add.w D0,D0 ; offset seems to be only 0 for your example
move.w (a6,D0.W),D2

if is 0, then
lea tab,a6
move.w (a6),D2
is enough.

ross 24 November 2018 20:45

Yes, BASEREG is powerful, but be warned, a6 in Amiga is used for library call.
Anyway define an address register used to access a heap with near displacement.

So you generally does
lea haep,a4
and from here all is a relative access.
Then another lea to your tab with a
(off,a4,dx.x)
or
(tab,a4)
reference.
And then use this new base to access the array with a relative, indexed or not or displaced,
move
.

You can have different heap, or you can use for small (and not so small..) program fast pc relative mode (do not underestimate it, is very very powerful).


EDIT: Don_Adan precedeed me :)
Quote:

Originally Posted by Don_Adan (Post 1287027)
Your code looks very strange. No big sense for me.

That's why I told him to rethink the code.
Sure not a good way to write for 68k..

litwr 24 November 2018 21:00

Quote:

Originally Posted by Don_Adan (Post 1287027)
Your code looks very strange. No big sense for me.

The mostly used 68000 version is next:

lea tab,a6 ; base
add.w D0,D0 ; offset seems to be only 0 for your example
move.w (a6,D0.W),D2

if is 0, then
lea tab,a6
move.w (a6),D2
is enough.

I have a lot of tables in my Data section (tab, tab1, tab121, ...). Thus I need to use a register as a section base(a6), I need also an offset to a particular table (tab, ...) and an index to it (d0). For example,
Code:

    lea tab,a3          ;tab starts the section
    move.b (a4),d1
    add.w d1,d1
 basereg tab,a6
    lea (a3,d1),a6
    move.w (tab1213,a6),d2
    move.w (tab1011,a6),d3
    ...
  endb a6

Is there any sense to use d1.w instead of a plain d1 in lea (a3,d1),a6? The generated code is identical.

BTW I bought my A500 in Warsaw in 1989. It was an adventure. I am sure you know a "gielda" which worked on weekends that time. ;)

EDIT. I have added a line with [b]a3[/3] to the start of my code.

ross 24 November 2018 21:16

ahem.. I dont want to be rude but too much to correct here, better if you stop a bit and re-start studying 68k base properties.
And maybe forget what you have learned for other processors that does not apply here.

You're dealing with a powerful ISA :)

roondar 24 November 2018 21:17

Quote:

Originally Posted by litwr (Post 1286991)
Thanks for the help. IMHO it is better to have separate colors for bg and borders like on the 8-bit Commodores.

In case this is part of what you want to create (border having a separate colour from the background), there is a way achieve this effect. I used this when I wanted a black border, but a copper-changing background.

What you could do is use colour 0 for the border (give it whatever colour you want the border to have). Then you fill the bitmap to display with colour 1 and give that whatever colour you want the background to be. For a tilemap, you'd have to create tiles with colour 1 as background.

This way you can have both a 'border' and a 'background', including copper effects. And should you have picked a useful colour for the border, there's nothing stopping you from using that on screen as well.

Hope this helps.

Quote:

Originally Posted by litwr (Post 1287033)
Is there any sense to use d1.w instead of a plain d1 in lea (a3,d1),a6? The generated code is identical.

Most assemblers default to word sized for the index so you don't have to add the .w. As such, lea (a3,d1.w),a6 and lea (a3,d1),a6 would indeed assemble to be the same. If you change this to lea (a3,d1.l),a6, I expect the generated code to be different.

ross 24 November 2018 21:32

Quote:

Originally Posted by roondar (Post 1287040)
What you could do is use colour 0 for the border (give it whatever colour you want the border to have). Then you fill the bitmap to display with colour 1 and give that whatever colour you want the background to be. For a tilemap, you'd have to create tiles with colour 1 as background.

Or you can use copper to sync to DIW registers and gain COLOR0 for copper gradient.
A more advanced technique, used in some games masterpiece.

Quote:

Most assemblers default to word sized for the index so you don't have to add the .w. As such, lea (a3,d1.w),a6 and lea (a3,d1),a6 would indeed assemble to be the same. If you change this to lea (a3,d1.l),a6, I expect the generated code to be different.
And always remember that you have to handle the upper indexed bits, before a .w if you insert a .b or before a .l if you insert a .w.
(not done in proposed example)

roondar 24 November 2018 21:54

Quote:

Originally Posted by ross (Post 1287044)
Or you can use copper to sync to DIW registers and gain COLOR0 for copper gradient.
A more advanced technique, used in some games masterpiece.

Very true, never forget the flexibility of the copper - it's such a nice tool to have :great

Don_Adan 24 November 2018 22:52

Quote:

Originally Posted by litwr (Post 1287033)
I have a lot of tables in my Data section (tab, tab1, tab121, ...). Thus I need to use a register as a section base(a6), I need also an offset to a particular table (tab, ...) and an index to it (d0). For example,
Code:

    lea tab,a3          ;tab starts the section
    move.b (a4),d1
    add.w d1,d1
 basereg tab,a6
    lea (a3,d1),a6
    move.w (tab1213,a6),d2
    move.w (tab1011,a6),d3
    ...
  endb a6

Is there any sense to use d1.w instead of a plain d1 in lea (a3,d1),a6? The generated code is identical.

BTW I bought my A500 in Warsaw in 1989. It was an adventure. I am sure you know a "gielda" which worked on weekends that time. ;)

EDIT. I have added a line with [b]a3[/3] to the start of my code.

Ok, perhaps i understand, what you need, use next code:

lea Base,A6

move.w tab1213-Base(a6), d2
move.w tab1011-Base(a6),d3

Base
....
tab1011 dc.w 0
...
tab1213 dc.w 0
tab1214 dc.w 0
....

btw. if you use move.b (a4),d1 and add.w d1,d1, be sure than high byte in D0 is 0, or you can set to wrong pointer later.

for assemblers lea (a3,d1),a6 is equal to lea (a3,d1.w),a6.
lea (a3,d1.w),a6 is not equal to lea (a3,d1.l),a6

lea (a3,d1.w),a6
works as next:
move.l a3,a6
add.w d1,a6

lea (a3,d1.l),a6
works as next:
move.l a3,a6
add.l d1,a6


d1.w (16 bit) can be diiferent than d1.l (32 bit)

litwr 25 November 2018 11:45

@roondar Thank you. But your idea takes one color from the main screen. IMHO it is possible to use copper to change the value of color register 0 but it will require not very easy coding, we need to change the register two times for horizontal borders and one time for vertical.
@ross Thank you but please be more specific. Indeed I did moveq #0,d1 - I thought it is obvious for everybody.
Quote:

Originally Posted by Don_Adan (Post 1287067)
Ok, perhaps i understand, what you need, use next code:
lea Base,A6
move.w tab1213-Base(a6), d2
move.w tab1011-Base(a6),d3
Base
....
tab1011 dc.w 0
...
tab1213 dc.w 0
tab1214 dc.w 0
....

Your code skips the usage of index in D1. :(

roondar 25 November 2018 12:48

Quote:

Originally Posted by litwr (Post 1287124)
@roondar Thank you. But your idea takes one color from the main screen. IMHO it is possible to use copper to change the value of color register 0 but it will require not very easy coding, we need to change the register two times for horizontal borders and one time for vertical.

Using the copper is indeed the better option if you need colour 0 to be different for the background and border part. Do note that in my idea you can still use colour 0 on the main screen, though it does indeed mean choosing a border colour that is 'useful' for the main screen as well.

To try and help you a bit more, the copper 'trick' you're referring to here really isn't hard. It's essentially the same thing as is done when you create a copper rainbow but instead of having one wait and one move command per scanline, there are two.

The copper list would look something like this for a PAL Amiga (I did this from memory, so there may be bugs :p):
Code:

; ... whatever init stuff you have goes here ...

; Repeat this next part for every scanline up to VPOS=$fe
dc.w    <waiting_position_left_border>|1,$fffe
dc.w    $0180,$700        ; Set background colour to middle yellow
dc.w    <waiting_position_right_border>|1,$fffe
dc.w    $0180,$000        ; Set border colour to black

; However, for VPOS=$ff do
dc.w    <waiting_position_left_border>|1,$fffe
dc.w    $0180,$700        ; Set background colour to middle yellow
dc.w    <waiting_position_right_border>|1,$fffe
dc.w    $0180,$000        ; Set border colour to black
dc.w    $ffdf,$fffe      ; Wait for start of PAL area

; For the remaining lines continue as before
dc.w    <waiting_position_left_border>|1,$fffe
dc.w    $0180,$700        ; Set background colour to middle yellow
dc.w    <waiting_position_right_border>|1,$fffe
dc.w    $0180,$000        ; Set border colour to black

 ; ... whatever closing stuff you have goes here...
dc.w    $ffff,$fffe            ; End of copperlist

Note that the waiting positions do need to be correctly chosen. I haven't put any values in as the exact positions depend on how wide the screen is. Also note that this method requires the screen edges to be on multiples of 4 pixels due to limits in the Copper wait command.

Hope this helps, as I said - the copper is very nice and can be used for all sorts of tricks.

litwr 25 November 2018 15:18

Thank you very much. :) I like the copper and I also would like to use blitter. However your code is about 1100 lines in size and it should be different for PAL and NTSC machines. I am also going to use several other copper coding and it will be not easy to combine the both codes... Thus it would be better to have a separate color for borders.

roondar 25 November 2018 15:26

Quote:

Originally Posted by litwr (Post 1287151)
...and it should be different for PAL and NTSC machines...

This is, sadly, usually unavoidable for copper lists that have to work in the screen part that only exists on PAL systems. One of the few things in the Copper I don't like, though I understand why it is.

litwr 29 November 2018 21:57

I stuck in a problem. Please help me again. Is there a way to save CPU arithmetic flags (C,Z,N,X,V)? MOVE SR,D0 doesn't work for applications with 68020 and later 68k CPU. Is there any other way?

StingRay 29 November 2018 22:08

Use CCR instead of SR. Or just keep track of the condition codes once you use any instruction which might change them.

Don_Adan 29 November 2018 22:35

Quote:

Originally Posted by StingRay (Post 1288039)
Use CCR instead of SR. Or just keep track of the condition codes once you use any instruction which might change them.

Move ccr, d0 dont exist for 68000.
move sr, d0 works for 68040/68060 only in privillage mode.
If he want, he can set privillage mode and use move sr, d0. he can use superstate and userstate calls from exec.

ross 29 November 2018 22:41

If you want a generic way that work on every 68k use the exec function SetSR
Code:

        oldSR = SetSR(newSR, mask)
        D0              D0    D1

        To get the current SR:
            currentSR = SetSR(0,0);

Or for the interested bits use Scc and after rebuild the CCR in the stack and use RTR instead of RTS.

But the real question is: WHY? :shocked
There is no reason to save all the flags!

Use the ones you need in the right way (or put them aside with Scc) and you're good in all cases.

StingRay 29 November 2018 22:59

Quote:

Originally Posted by Don_Adan (Post 1288046)
Move ccr, d0 dont exist for 68000.
move sr, d0 works for 68040/68060 only in privillage mode.
If he want, he can set privillage mode and use move sr, d0. he can use superstate and userstate calls from exec.


All correct! :) But ultimately, what Ross said here:



Quote:

Originally Posted by ross (Post 1288047)
But the real question is: WHY? :shocked
There is no reason to save all the flags!

Use the ones you need in the right way (or put them aside with Scc) and you're good in all cases.


roondar 30 November 2018 10:11

Quote:

Originally Posted by ross (Post 1288047)
But the real question is: WHY? :shocked
There is no reason to save all the flags!

Use the ones you need in the right way (or put them aside with Scc) and you're good in all cases.

Indeed, it's not usually a big necessity on 68k based machines. I remember stacking/restoring the status register somewhat frequently on the 6502, but I've not really missed it on the 68k. More so since it's not a requirement for exception processing unlike 6502.


@litwr
However, if you really want to (though I'd be very interested in knowing why you want this, like most here) - there is another option. You can run the whole program in supervisor mode if you want. This will allow you use of the move to sr <ea> and move from sr <ea> instructions as you see fit.

You can do this using the Exec function SuperState(). Remember to leave at the end of the program using UserState(). See here: http://amigadev.elowar.com/read/ADCD.../node0385.html for documentation.

Note that it's not really the recommended way to run entire OS legal programs and shouldn't really be required considering what Ross and others wrote above, but it can be done.

ross 30 November 2018 12:55

Quote:

Originally Posted by roondar (Post 1288077)
You can do this using the Exec function SuperState(). Remember to leave at the end of the program using UserState().

For some reason (that I don't remember precisely anymore) was a problem for me using a whole program in SuperState() mode.
Probably something to do with KS1.x dos.library (Tripos legacy..) that messes up with the stack
(be warned! SuperState enter in supervisor mode while running on the user's stack).

No big problems with Supervisor().

Or is the opposite? Need to check it :p
Take with a grain of salt, too much time passed :)


All times are GMT +2. The time now is 19:12.

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

Page generated in 0.08069 seconds with 11 queries