[ASM] Tips and tricks

hu, cd, scd, acd, supergrafx discussions.
Post Reply
User avatar
MooZ
Site Admin
Posts: 401
Joined: Sun Jun 22, 2008 3:19 pm
Location: Lvl 3
Contact:

[ASM] Tips and tricks

Post by MooZ » Tue Aug 30, 2011 3:11 pm

Heya,

This thread will be about assembly tips and tricks. If you have any cool piece of code or some ninja technique, this is the place to post them!
Let me start with a simple one for pceas.

Align some piece of code or data to 256 bytes boundary:

Code: Select all

    .org ((*+$ff) & $ff00)
* is a special operand that'll return the current address/offset. So basically, the formula calculates the smallest multiple of 256 greater or equal to the current offset. It can be generalized to:

Code: Select all

align_org .macro
    .org (* + (\1 - 1)) & ( ~(\1 - 1) )
    .endm
Note that the macro argument must be a power of 2. Otherwise you'll get funky results.

Charles MacDonald
Posts: 38
Joined: Sun Jun 22, 2008 5:18 pm
Contact:

Re: [ASM] Tips and tricks

Post by Charles MacDonald » Wed Aug 31, 2011 11:46 pm

Accessing quantities larger than 8 bits can be problematic on the HuC6280. Normally you have to do something like this to get a 16-bit word from a table:

Code: Select all

lda <index
asl a
tax
lda table+0, x
sta <lowByte
lda table+1, x
sta <highByte
;
table:
.dw $1234
.dw $5678
Here, 'index' is limited to 0-127 which is even more frustrating. A better way is to split the word data into two tables of byte data, one being the LSB and the other being the MSB:

Code: Select all

ldx <index
lda lowTable, x
sta lowByte
lda highTable, x
sta highByte
;
lowTable:
.db $34, $78
highTable:
.db $12, $56
Because the HuC6280 doesn't wrap addresses at page boundaries you don't have to worry about page-aligning tables. This method can be expanded to words of any width, such as 24 or 32-bit, etc.
Don't forget your two NOPs after CSH.

User avatar
MooZ
Site Admin
Posts: 401
Joined: Sun Jun 22, 2008 3:19 pm
Location: Lvl 3
Contact:

Re: [ASM] Tips and tricks

Post by MooZ » Thu Sep 01, 2011 9:18 am

The identity sin(x + PI/2) = cos(x) helps you save space when you want to store tables for sine and cosine. For example if you want 128 bytes long tables, you just have to generate a 160 (32+128) bytes long table containing sin(i * 2 * PI / 128). The cosine table will start at sinTable+32 (2PI is 128, so 32 is PI/2).
Here's what it will look like:

Code: Select all

; sinTable = sin(i*2*PI/128)*128 for i=0..160
sinTable:
    .db $00, $06, $0c, $12, $18, $1f, $25, $2b, $30, $36, $3c, $41, $47, $4c, $51, 55,
    .db $5a, $5e, $62, $66, $6a, $6d, $70, $73, $76, $78, $7a, $7c, $7d, $7e, $7f, 7f
cosTable:
    .db $80, $7f, $7f, $7e, $7d, $7c, $7a, $78, $76, $73, $70, $6d, $6a, $66, $62, 5e,
    .db $5a, $55, $51, $4c, $47, $41, $3c, $36, $30, $2b, $25, $1f, $18, $12, $0c, 06,
    .db $00, $f9, $f3, $ed, $e7, $e0, $da, $d4, $cf, $c9, $c3, $be, $b8, $b3, $ae, aa,
    .db $a5, $a1, $9d, $99, $95, $92, $8f, $8c, $89, $87, $85, $83, $82, $81, $80, 80,
    .db $80, $80, $80, $81, $82, $83, $85, $87, $89, $8c, $8f, $92, $95, $99, $9d, a1,
    .db $a5, $aa, $ae, $b3, $b8, $be, $c3, $c9, $cf, $d4, $da, $e0, $e7, $ed, $f3, f9,
    .db $00, $06, $0c, $12, $18, $1f, $25, $2b, $30, $36, $3c, $41, $47, $4c, $51, 55,
    .db $5a, $5e, $62, $66, $6a, $6d, $70, $73, $76, $78, $7a, $7c, $7d, $7e, $7f, 7f
extra tip: You can generate this table using Wolfram Alpha by typing:

Code: Select all

Table[int(sin(2*PI*x/128) * 128), {x, 0, 159}] to base 16

Post Reply