News:

11 March 2016 - Forum Rules

Main Menu

Armips BEQ (branch if equal) jump distance calculation?

Started by weissvulf, May 31, 2013, 03:35:47 PM

Previous topic - Next topic

weissvulf

I've spent a day trying to figure this out, and I'm still not sure I understand what armips is doing. Can someone explain how to calculate branch jump distances for the armips input file (asm)?

Branch jump distnces are relative to the current position (PC), so I was expecting that if I enter two identical branch distances, armips would generate two identical op-codes. But it seems to be trying to auto-infer the branch distance I want.

So if I input:         
beq v0, s5, 0x90
nop   
beq v0, s5, 0x90
nop
beq v0, s5, 0x90

I get:
1055 0012
0000 0000
1055 0010
0000 0000
1055 000e

What do I do if I actually want my 2nd and 3rd BEQ to jump 0x90 ahead?  :banghead:

EDIT: Is it that all additional Branch distances are relative to the first BEQ jump entry?

KC

You don't enter the distance of the branch, but the destination. The branch distance is then calculated relative to the position of the branch opcode. All your branches will branch to position 0x90. If you want to jump 0x90 bytes ahead, you can use the "." dummy label for the current memory address.

beq v0,s5,.+0x90

weissvulf

Thank you KC, for the lightning fast response.  Very helpful :cookie:
So 0x90 would set the branch destination to 0x90 in the current op-code block.  That means you can't add or remove lines to the asm file above the branch unless you use ".+0x90" format.

That explains why I was having trouble. I'm using these op codes in multiple places (save-states, exe, and disk image), so I have my asm file configured to output all my new codes to a dummy file. I was then using manual copy/paste to transfer the op-codes from the dummy file to wherever I was working.  So I guess armips was calculating the branch jump locations relative to my dummy file.

KC

You can of course use labels so that you don't need to hard code addresses. That is highly recommended. Also remember to specify the correct header size. All addresses are relative to the header size of the currently opened file (ie. the file starts at the offset given as the headersize).

weissvulf

If "labels" work like I expect,  they should make what I'm doing much easier. Thanks for that info.
I'm relatively new to the armips so I'm still learning how to arrange things efficiently.

Variable width goodness- brought to you by armips!!!

Xenesis

Yeah, if you set up something like:

beq LabelBlah
nop
nop
nop
LabelBlah:
str r0,[r1,0x0]


Provided that it's in range, the beq will update itself at compile to be the correct distance - it really takes the headaches out of it.

weissvulf

Perfect! Thanks for that example.
Wish I'd taken the time to learn that about 200 manual corrections ago   :thumbsup:

KC

The readme is very detailed and explains all features of the assembler with sample code. I recommend to read it thoroughly. Be sure to get the latest version, too, which I should probably submit to this site. Until then, you can get it here: http://aerie.wingdreams.net/?p=201

Gideon Zhi

Brigandine, eh? I must admit I'm not particularly fond of the game; I found that it moved far too slowly. Nice to see you branching out from Daisenryaku titles, though!

Xenesis

Quote from: KC on June 02, 2013, 09:00:30 AM
The readme is very detailed and explains all features of the assembler with sample code. I recommend to read it thoroughly. Be sure to get the latest version, too, which I should probably submit to this site. Until then, you can get it here: http://aerie.wingdreams.net/?p=201

Whoa, I had no idea it'd been updated recently. That changelog fills me with <3.  ;D

weissvulf

KC : I think that's why I missed the "Label" feature; somehow ditched the readme when I got 0.7c. I didn't even know there was one. Thanks for the 0.7d update. Great work!

Gideon Zhi: Brigandine Grand Edition was actually the first game I ever worked on, but the amount Japanese text and audio it has was quite intimidating so I put it down until recently. It is a slow game, but Grand Edition plays a bit faster since they removed the attack cut-scenes. Also. it has options to do immediate moves/attacks. I guess turn based strategy games are slow by nature though.
8)

Gideon Zhi

Quote from: weissvulf on June 02, 2013, 01:57:08 PM
Gideon Zhi: Brigandine Grand Edition was actually the first game I ever worked on, but the amount Japanese text and audio it has was quite intimidating so I put it down until recently. It is a slow game, but Grand Edition plays a bit faster since they removed the attack cut-scenes. Also. it has options to do immediate moves/attacks. I guess turn based strategy games are slow by nature though.
8)

It's true that turn-based strategy is slow! I think my beef with Brigandine though was that it was turn-based strategy within turn-based strategy, so it was slow^2.

weissvulf

I get that; the world map organization phase, and the battle micro management . . .
But dude... you can equip accessories on DRAGONS!!!! How cool is that??  :laugh:

Anyways, using armips 'labels' was exactly what was needed.
In case it helps anyone else who stumbles on this thread,
below is an example of how labels can be set up with 'branch'
tests for a variable width font. Labels will let you add
more "letter tests" without having to rework any previous
code. Helpful if you decide to change fonts or such.  Cool!

In my project, r17 holds the "letter spacing" value.
lbu r3, 0x0(r16) ;Loads current letter from memory to r3

addiu r4,r0,0x20 ;"Sapce" check
beq r4,r3,Menu4Wide ;if true branch to 4 width settings
addiu r4,r0,0x69 ;i check
beq r4,r3,Menu2Wide ;if true branch to 2 width settings
addiu r4,r0,0x6c ;l check
beq r4,r3,Menu2Wide ;if true branch to 2 width settings
addiu r4,r0,0x72 ;r check
beq r4,r3,Menu4Wide ;if true branch to 4 width settings
addiu r4,r0,0x74 ;t check
beq r4,r3,Menu5Wide ;if true branch to 5 width settings
addiu r4,r0,0x49 ;I check
beq r4,r3,Menu4Wide ;if true branch to 4 width settings
addiu r4,r0,0x6a ;j check
beq r4,r3,Menu4Wide ;if true branch to 4 width settings
addiu r4,r0,0x6b ;k check
beq r4,r3,Menu5Wide ;if true branch to 5 width settings
addiu r4,r0,0x27 ;' check
beq r4,r3,Menu3Wide ;if true branch to 3 width settings
addiu r4,r0,0x31 ;1 check
beq r4,r3,Menu4Wide ;if true branch to 4 width settings
nop ;nop for branch delay

beq r0,r0,MenuFinalize ;jump to finalize
addiu r17, r17, 0x6 ;set normal spacing value of 6 pixels
Menu2Wide: ;2 width settings
beq r0,r0,MenuFinalize ;jump to finalize
addiu r17, r17, 0x2 ;set 2 spacing value
Menu3Wide: ;3 width settings
beq r0,r0,MenuFinalize ;jump to finalize
addiu r17, r17, 0x3 ;set 3 spacing value
Menu4Wide: ;4 width settings
beq r0,r0,MenuFinalize ;jump to finalize
addiu r17, r17, 0x4 ;set 4 spacing value
Menu5Wide: ;5 width settings
addiu r17, r17, 0x5 ;set 5 spacing value
MenuFinalize:
j 0x20550 ;jump back

KC

You should use a lookup table for the width. That's much easier to maintain.


li r17,WidthTable ; load width table offset
addu r17,r17,r3 ; use character number as index
lbu r17,(r17) ; load width
nop

....

WidthTable:
.byte 0,0,0,0,0,0,0,0,0 ; one byte per character index
...


You can also use li to load immediates, as shown in my example. And I'd recommend using @@ for local labels so that you don't run out of label names fast. They are valid until the next global (without @@) label and can be redefined after that.

weissvulf

Thanks for those optimization tips KC.  :)
I've found 4 completely separate text drawing routines (so far) in the game I'm working on, so I'll have plenty of opportunity to try them out! :banghead:

furrykef

Quote from: KC on June 10, 2013, 04:44:21 PMYou should use a lookup table for the width. That's much easier to maintain.
This is what I did for Animal Land (an MSX game that Torbjorn and I are translating). But I also added comments so you can easily see what's what, like this:

char_widths:
        ;       [the digits and period here are bold]
        ;       0  1  2  3  4  5  6  7  8  9  .  *
        db      7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 3, 4, 0, 0, 0, 0

        ;       [first char here is <mnl> ("menu newline") control code]
        ;       [displays as space when not in a menu]
        db      3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0

        ;       [first char here is space]
        ;       [asterisk in this row is not the one we use]
        ;          !  "  #  $  %  &  '  (  )  *  +  ,  -  .  /
        db      3, 2, 5, 6, 6, 6, 6, 3, 3, 3, 6, 6, 3, 5, 2, 4

        ;       0  1  2  3  4  5  6  7  8  9  :  ;  <  =  >  ?
        db      5, 3, 6, 6, 6, 6, 6, 6, 6, 6, 2, 3, 6, 6, 6, 6

        ;       @  A  B  C  D  E  F  G  H  I  J  K  L  M  N  O
        db      6, 6, 6, 6, 6, 5, 5, 6, 6, 2, 5, 5, 5, 6, 6, 6

        ;       P  Q  R  S  T  U  V  W  X  Y  Z  [  ¥  ]  ^  _
        db      6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6

        ;       `  a  b  c  d  e  f  g  h  i  j  k  l  m  n  o
        db      6, 6, 5, 5, 5, 5, 4, 5, 5, 2, 3, 5, 2, 6, 5, 5

        ;       p  q  r  s  t  u  v  w  x  y  z  {  |  }  ~
        db      5, 5, 4, 5, 4, 5, 5, 6, 5, 5, 5, 6, 6, 6, 6, 0

        ;       [first char here is the odd "N"-like character]
        ;       [after skipping a control code, next 5 are "PRESS SPACE"]
        db      7, 0, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0

        ;       [monospace font for passwords]
        ;          A  B  C  D  E  F  G  H  I  J  K  L  M  N  O
        db      0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8

        ;       P  Q  R  S  T  U  V  W  X  Y  Z
        db      8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0

        ;       [bold font]
        ;       A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  P
        db      7, 7, 7, 7, 6, 6, 7, 7, 3, 6, 6, 6, 7, 7, 7, 7

        ;       Q  R  S  T  U  V  W  X  Y  Z  :  ?
        db      7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 3, 7, 0, 0, 0, 0

        db      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0

        ;       a  b  c  d  e  f  g  h  i  j  k  l  m  n  o  p
        db      7, 6, 6, 6, 6, 5, 6, 6, 3, 4, 6, 3, 7, 6, 6, 6

        ;       q  r  s  t  u  v  w  x  y  z
        db      6, 5, 6, 5, 6, 6, 7, 6, 6, 6, 0, 0, 0, 0, 0, 0


Since each row has 16 entries, it lines up perfectly with how the graphics show up in Tile Layer Pro.

weissvulf

Thanks for adding that furrykef.  I think real-world examples like these are invaluable to anyone trying to wrap their brain around ASM.  :thumbsup:

weissvulf

A simple question about Armips that isn't worth making it's own thread:
For the ".word/.halfword" commands, is there a way to toggle armips' reversing endian-ness on or off?

KC

So far all platforms it was made for are little endian, so no, writing values as big endian is not supported.

You could create a macro though, I guess.

.macro hwbe,value
.halfword (value >> 8) | (value << 8)
.endmacro

weissvulf

Thank you KC; that's fine. Some of the dimensions for text boxes in Brigandine are defined in runs of single bytes next to each other. They aren't handled as "words" by the game, but I was using ".word" to edit them in the ASM - since 4 single bytes define each box, just to save a little clutter.  :)