Author Topic: How to read sprite #0 collision detection in huc ??  (Read 1537 times)

Arkhan

  • Hero Member
  • *****
  • Posts: 14142
  • Fuck Elmer.
    • Incessant Negativity Software
Re: How to read sprite #0 collision detection in huc ??
« Reply #15 on: September 07, 2009, 03:35:44 AM »
Writing compilers is boring...and I know this because I have one of my own. :(

yea it started as a school project.   Then school ended and so did the motivation, lol.
[Fri 19:34]<nectarsis> been wanting to try that one for awhile now Ope
[Fri 19:33]<Opethian> l;ol huge dong

I'm a max level Forum Warrior.  I'm immortal.
If you're not ready to defend your claims, don't post em.

nodtveidt

  • Guest
Re: How to read sprite #0 collision detection in huc ??
« Reply #16 on: September 07, 2009, 04:53:41 AM »
yea it started as a school project.   Then school ended and so did the motivation, lol.

Nada on both. It's an actively developed project:
http://www.bsdbasic.com/

Arkhan

  • Hero Member
  • *****
  • Posts: 14142
  • Fuck Elmer.
    • Incessant Negativity Software
Re: How to read sprite #0 collision detection in huc ??
« Reply #17 on: September 07, 2009, 10:11:14 AM »
yea it started as a school project.   Then school ended and so did the motivation, lol.

Nada on both. It's an actively developed project:
http://www.bsdbasic.com/


I meant mine, not yours. :)
[Fri 19:34]<nectarsis> been wanting to try that one for awhile now Ope
[Fri 19:33]<Opethian> l;ol huge dong

I'm a max level Forum Warrior.  I'm immortal.
If you're not ready to defend your claims, don't post em.

nodtveidt

  • Guest
Re: How to read sprite #0 collision detection in huc ??
« Reply #18 on: September 07, 2009, 11:40:56 AM »
I meant mine, not yours. :)
Ok, I didn't know you had one too...you didn't say that. :P hehe

Arkhan

  • Hero Member
  • *****
  • Posts: 14142
  • Fuck Elmer.
    • Incessant Negativity Software
Re: How to read sprite #0 collision detection in huc ??
« Reply #19 on: September 09, 2009, 10:02:31 AM »
oh I did i just didnt specify.

PCC:

PC Engine C Compiler

I have most of the grammar/C instruction recognition in place and it generates intermediate 6502...

but it needs fine tuned.
[Fri 19:34]<nectarsis> been wanting to try that one for awhile now Ope
[Fri 19:33]<Opethian> l;ol huge dong

I'm a max level Forum Warrior.  I'm immortal.
If you're not ready to defend your claims, don't post em.

touko

  • Hero Member
  • *****
  • Posts: 953
Re: How to read sprite #0 collision detection in huc ??
« Reply #20 on: October 12, 2009, 02:39:39 AM »
Hi ..

I have a doubt, slow array access in HUC ,are only for far data ??
or near are so slow ??

« Last Edit: October 12, 2009, 03:21:15 AM by touko »

Tom

  • Guest
Re: How to read sprite #0 collision detection in huc ??
« Reply #21 on: October 12, 2009, 06:44:56 PM »
Hi ..

I have a doubt, slow array access in HUC ,are only for far data ??
or near are so slow ??

 Far data access is sloooow in HuC. And all near data accessed via array is treated as far data. So yes to both ;)

 Regular "global" variables are fine/fast as long as they aren't arrays.

touko

  • Hero Member
  • *****
  • Posts: 953
Re: How to read sprite #0 collision detection in huc ??
« Reply #22 on: October 12, 2009, 08:22:11 PM »
Far data access is sloooow in HuC. And all near data accessed via array is treated as far data. So yes to both ;)

 Regular "global" variables are fine/fast as long as they aren't arrays.

Thank's ...

I 'am testing arrays access with ASM ..
I use for a new project ,a custom fade_in fuction based on aramis's function, and there is lightly slow down when i 'am using it (caus some arrays access) with multiples parallaxes ..

I try to make arrays read/write in ASM, in this function first ..

The drama is  " I LIKE THAT "  :shock:

touko

  • Hero Member
  • *****
  • Posts: 953
Re: How to read sprite #0 collision detection in huc ??
« Reply #23 on: October 12, 2009, 10:47:46 PM »
How to use an array pointer in ASM ???

in C

int *tab;

tab = pic_pal; (tab take address of pic_pal array (who contain bgnd colors for exemple) ..

My code is
Code: [Select]
#asm
   ldx _x_val
   lda _tmp_pal,x
   sta _b2
   inx
   lda _tmp_pal,x
   sta _b2+1 
   inx
   stx _x_val
#endasm
tmp_pal is my array pointer, and b2 a global int ..
And i want to load each value in tmp_pal to b2.

In c an array pointer work like an array,but in ASM ...

PS: array load to a global int ,work fine.
« Last Edit: October 13, 2009, 09:30:58 PM by touko »

Tom

  • Guest
Re: How to read sprite #0 collision detection in huc ??
« Reply #24 on: October 13, 2009, 09:53:04 AM »
A few rules;

 Try to keep ALL variables as global in HuC. They are much faster and they are passed in function calls MUCH faster. Global Vars ftw :D
 Split your INT arrays into high/low (MSB/LSB) segments.
 Try to use direct addressing with indexing over traditional pointers of C, when possible.

 Ok, some examples:

 BYTE size array. BYTE length array.
Code: [Select]
char array1[256];
.
.
.
 array1[x] = 3;
is..
Code: [Select]
ldy _x
 lda #$03
 sta _array1,x



 WORD size array. BYTE length array.
Code: [Select]
int array1[256];
.
.
.
 array1[x] = 3;
is..
Code: [Select]
lda _x
 asl a
 tax
 bcs .upper
.lower
 lda #$03
 sta _array1,x
 lda #$00
 sta _array1+$1,x
 bra .skip
.upper
 lda #$03
 sta _array1+$100,x
 lda #$00
 sta _array1+$101,x
.skip



 WORD size array. BYTE length array.
Code: [Select]
int array1[256];
.
.
.
 array1[x] = var;
is..
Code: [Select]
lda _x
 asl a
 tax
 bcs .upper
.lower
 lda low(_var)
 sta _array1,x
 lda high(_var)
 sta _array1+$1,x
 bra .skip
.upper
 lda low(_var)
 sta _array1+$100,x
 lda high(_var)
 sta _array1+$101,x
.skip



 WORD size array. WORD length array.
Code: [Select]
int array1[2048];
.
.
.
 array1[x] = var;
is..
Code: [Select]
lda low(_x)
 asl a
 sta <_ZP
 lda high(_x)
 rol a
 sta <ZP+1
 lda #low(_array1)
 adc <_ZP           ;<- no need for carry because previous shift should clear it already. Unless you have an illegal length (because >$7fff WORDs is greater than 64kbytes)
 sta <_ZP
 lda #high(_array1)
 adc <_ZP+1
 sta <_ZP+1

 lda low(_var)
 sta [_ZP]
 lda high(_var)
 ldy #$01
 sta [_ZP],y




 BYTE size array. WORD length array.
Code: [Select]
char array1[2048];
.
.
.
 array1[x] = var;
is..
Code: [Select]
lda _x
 clc
 adc #low(_array1)
 sta <_ZP
 lda #high(_array1)
 adc #$00
 sta <ZP+1

 lda _var
 sta [_ZP]


 All examples assume the global array define is near, which is should be since it's work ram. Reading from an array is a little bit different since the data could be far. You better know before hand.

 Here are some optimizations examples:

 WORD size array (split array). BYTE length array.
Code: [Select]
char array1_lo[256];
char array1_hi[256];
.
.
.
 array1_lo[x] = var;
 array1_hi[x] = var>>8;
is..
Code: [Select]
ldx _x
 lda low(_var)
 sta _array1_lo,x
 lda high(_var)
 sta _array1_hi,x

 You can see the above example is the same as "int array1[ x ]=var", but less code. Also, in the later examples - don't forget if you're accessing the array's sequentially, you can optimize for that.


 WORD size array. WORD length array.
Code: [Select]
int array1[2048];
.
.
.
 array1[x++] = var;
 array1[x++] = var2;
 array1[x++] = var3;
is..
Code: [Select]
lda low(_x)
 asl a
 sta <_ZP
 lda high(_x)
 rol a
 sta <ZP+1
 lda #low(_array1)
 adc <_ZP           
 sta <_ZP
 lda #high(_array1)
 adc <_ZP+1
 sta <_ZP+1

 lda low(_var)
 sta [_ZP]
 lda high(_var)
 ldy #$01
 sta [_ZP],y

 iny
 lda low(_var2)
 sta [_ZP]
 lda high(_va2)
 iny
 sta [_ZP],y

 iny
 lda low(_var3)
 sta [_ZP]
 lda high(_va3)
 iny
 sta [_ZP],y

 I'll post some more examples later.
 

Tom

  • Guest
Re: How to read sprite #0 collision detection in huc ??
« Reply #25 on: October 13, 2009, 12:26:25 PM »
Ok... back.

 So declaring an array is the same thing as a "static" pointer in C. Or a constant pointer. Because that pointer never changes.

 This means you can access small arrays in work ram, with direct addressing plus indexing (as shown in the BYTE/BYTE example). I not entirely sure, but I think Huc, being Small C, doesn't allow the creation of pointers like you can in normal C. But that doesn't mean you can't do it in ASM.

Code: [Select]
char *pointer;
.
.
.
 pointer = &label_1

 equates to...

Code: [Select]
lda #low(_label1)
 sta <_pointer
 lda #high(_label1)
 sta <_pointer+1

 So now 'pointer' holds the address of 'label1'

Code: [Select]
*pointer=var
 pointer++;

Code: [Select]
lda _var
 sta [_pointer]
 inc <_pointer
 bne .skip
 inc <_pointer+1
.skip

 There are 128 possible 'address' vectors or pointer slots on the 65x. In HuC and/or the system card, some of those are reserved so you actually have less than that. But in reality, you don't usually need more than 20-30 pointers/address vectors. The cool thing about the 65x's hardware ZeroPage registers, is that since there are soo many address vectors definable, it's not a problem just to leave the vector setup. I.e. you don't have to keep loading and unloading pointers when you need to use them.

 The 65x allows a few other things. First thing to note is; all indexing on the HuC6280 is free. And you can index pre and post index registers. Here are some examples:

Code: [Select]
*pointer[x++]=var;

Code: [Select]
ldy _x
 lda _var
 sta [_pointer],y
 inc _x

 In that example, the pointer isn't destroyed or altered. This means you can randomly and quickly access up to 256 elements from the base pointer address. Very fast and flexible. The only downside is the limited size of the indexing to 256, but there are clever and fast ways to extend this further.

 Another example of pointer flexibility:

Code: [Select]
*(pointer_array[x])=var;

Code: [Select]
lda _var
 ldx _x
 sta [_pointer_array,x]

 So you can index a pointer table array. I hope my C syntax (C99) is correct on those, but if not - you should be able to get the idea I'm trying to convey.

 Now, this has all been for accessing near data. Accessing far is exactly the same thing, except for one minor difference. Far data needs a 24bit address. Unfortunately, Hudson didn't add a long addressing mode to the custom R65C02S. It's not too big of a problem though, but it does require prioritizing and optimization of you need specific access in relation to speed. Basically how you map out your logical cpu address range.

 Any, for far data - the process I've described above is exactly the same. It just requires you mapping in a far page/block of memory, into the local address range. Once this is down, all that I've written applies exactly. Work ram, you never want to map that out - except for extreme conditions. Mostly because the stack and address vectors get replaced with whatever you map in - in that address range/page. You'll definitely have a problem with interrupts and such. So leave that page alone. The last page and the very first page also, normally shouldn't be changed. If you design your code from the ground up, it's not much a problem. But if you plan to use HuC or any of the Mkit libs or setup, you're mostly restricted to leaving that 24k fixed in local address range.

 Not sure if I'm forgetting anything :P


 Edit: Oh yeah. Some closing information/suggestions.

 Most array/pointer data is accessed in some sort of sequential method. Take advantage of this. You can using the free indexing even if the source array/requires are longer than 256bytes/128words. Just use the indexing reg as a counter, then increment the MSB of the pointer. Like such:

Code: [Select]
for(int x=0,x<384,x++)
 {
   *pointer &= 0x03;
   *pointer++;
}

Code: [Select]
clx
.loop_outer
 cly
.loop_inner
 lda [_pointer],y
 and #$03
 sta [_pointer],y
 iny
 cpy #128
 bcc .loop_inner
 inx
 cpx #03
 beq .out
 tya
 clc
 adc <_pointer
 sta <_pointer
 bne .loop_outer
 inc <_pointer+1
 bra .loop_outer
.out

 384 is an easy multiple of 128. So here's an example of a variable length loop, but still using indexing for addressing and a counter:

Code: [Select]
; lets assume len is 521
 for(int x=0,x<len,x++)
 {
   *pointer &= 0x03;
   *pointer++;
}

Code: [Select]
clx
.loop_outer
 cly
.loop_inner
 lda [_pointer],y     ;7
 and #$03             ;2
 sta [_pointer],y     ;7
 cpy low(_len)        ;5
 beq .check_msb       ;2
.cont
 iny                  ;2
 bne .loop_inner      ;4
 inc <_pointer+1
 inx
 cpx high(_len)
 bne .loop_outer
 bra .out
.check_msb
 cpx high(_len)
 bne .cont
.out


 Compare that with this normal, non index method:

Code: [Select]
.loop
 lda [_pointer]       ;7
 and #$03             ;2
 sta [_pointer]       ;7

 lda <_pointer        ;4
 clc                  ;2
 adc #$01             ;2
 sta <_pointer        ;4
 lda <_pointer+1      ;4
 adc #$00             ;4
 sta <_pointer+1      ;4

 cmp high(_len)       ;5
 bcc .loop            ;4
 
 lda <_pointer+1      ;4
 cmp low(_len)        ;5
 bne .loop            ;4
.out

 The index version of the loop is 29 cycles per single cycle of the for/loop. You have a tiny amount of over head on X rollover - which happens once every 256 increment of Y. That translate into less than a single cycle over all into the loop count of cycles.

 On the other hand, the normal method is 49 cycles per single cycle of the for/loop. And when the MSB is aligned, you put on another 13 cycles on top of that 49 cycles per single cycle of the for/loop. So if 'len' was $1ff, the last $ff of cycles would be 62cycles per instance. So if len was $1ff, the average would be 55.5cycles.

 55cycles VS 29cycles. The index method is more abstract, but clearly the winner. 1.9 times as fast. If you did the same thing in HuC, it'd take around 200 or more cycles per for/loop instance.
« Last Edit: October 13, 2009, 01:32:36 PM by Tom »

touko

  • Hero Member
  • *****
  • Posts: 953
Re: How to read sprite #0 collision detection in huc ??
« Reply #26 on: October 13, 2009, 09:27:30 PM »
wahouuu, great  =P~
Thank you very,very much ..

I 'll need many century for undestand all  :mrgreen:

Your exemples are useful for my, to understand how arrays work in asm.

My fisrt exemple work fine for load a 16 bits array to an int  :wink: (and it's simple) ..

Quote
Not sure if I'm forgetting anything Razz

Yes, in fact only my question  :-"
 :wink:

I use first only inline ASM (i'am not completely mad  :mrgreen:)
i have declared in huc an int pointer .
I'll want to use multiples int arrays in a same function who contain ASM.

This pointer take address of an int array : for exmple

Code: [Select]
#incpal(logo_pic_pal,"pcx/tg16.pcx") (array containing all the bcgnd colors)

int *datas_pointer;
int var;
.
.
.
.
datas_pointer = logo_pic_pal;

I 'll want to do this in ASM
var = *(data_pointer++);
.
.
.
.
var = *(data_pointer++)

 #asm
   i'll want to read datas_pointer values here  8)
 #endasm


I 'am initializing  datas_pointer with logo_pic_pal's address in C before.

And i 'll want to read datas in asm with pointer datas_pointer !!

if i'am declaring datas_pointer as an int array, and i'am copying all logo_pic_pal in, i can read all values perfectly.

Code: [Select]
sta [_pointer],y
The same for load  :-k

Ah , if i do, for reading datas_pointer content at his start address
Code: [Select]
  lda [_datas_pointer] (for exemple)

Compiler says " Incorrect zero page address"

Huum [_datas_pointer] or <_datas_pointer ,seems not working on HUC  #-o
« Last Edit: October 14, 2009, 02:04:38 AM by touko »

Tom

  • Guest
Re: How to read sprite #0 collision detection in huc ??
« Reply #27 on: October 14, 2009, 04:23:45 AM »
Quote
Compiler says " Incorrect zero page address"

Huum [_datas_pointer] or <_datas_pointer ,seems not working on HUC

 Correct. HuC is not optimized to keep pointers in Zeropage. The compiler is simple, and unfortunately treats the 65x like any other load/store processors. That makes the design simple, but the speed slow.

 This means you have to manually copy the pointer into ZP address vector. And the catch is.... HuC itself doesn't allow you to define anything in ZP, be it a fast ram variable or address vector/pointer. So, you must define a ZP variable in ASM. Either in startup.asm or somewhere in the asm library, or using the #ASM/ENDASM function near the beginning of the main C file.

Code: [Select]
#asm
  .zp
  __pointer1: .ds 2
  __pointer2: .ds 2
  __pointer3: .ds 2
  ;etc
#endasm

 then you have to prep the pointer because it's null.

Code: [Select]
lda low(datas_pointer)
 sta <__pointer1
 lda high(datas_pointer)
 sta <__pointer1+1

 now you can do
Code: [Select]
lda [__pointer1]

 __pointer1 will always keep its value. The compiler won't erase it or use it. It has its ZP vectors reserved for internal operations.



 When/if you get more comfortable with HuC and ASM, I can show you how to have complete control over the C function style of calling and passing parameters. It's directly compatible with the assembly side. You can use registers, ZP fast ram, pointers, etc to pass arguments directly to an ASM function, but the compiler will treat the function as if its internal. You can write whole functions in pure asm (and without using #asm/endasm) and not have to worry about a lot of compiler overhead/memory layout issues. But to be honest, if you get that comfortable/familiar with the system - you there isn't really a need for HuC at that point at all. You'll want to reclaim all that wasted lib space HuC and Mkit eat up.



touko

  • Hero Member
  • *****
  • Posts: 953
Re: How to read sprite #0 collision detection in huc ??
« Reply #28 on: October 14, 2009, 05:02:15 AM »
Thanks man, your explanations are clear ..

For the moment i'am not familiar enough with pc-engine hardware, for migrate in all asm, or advanced asm functions,but i keep your proposition  :wink:  ..
Cool stuffs of asm are not easily mixable with HUC for a noob ..

I'll try your soluce for pointer ..

touko

  • Hero Member
  • *****
  • Posts: 953
Re: How to read sprite #0 collision detection in huc ??
« Reply #29 on: October 14, 2009, 08:27:30 PM »
hi i have included
Code: [Select]
#asm
  .zp
  __pointer1: .ds 2 
#endasm

before any huc code.

now <__pointer1 or [__pointer1] is working, but this pointer is not available directly in HUC  :cry:
I must pass it with an intermediate global variable declared in HUC.

i have tried this
Code: [Select]
#asm     
     ldx #$0
     lda logo_pic_pal,x
     sta #low(__pointr)
     inx
     lda logo_pic_pal,x
     sta #high(__pointr)     
#endasm

And " incorrect addressing mode"   re  :cry:

I thing that i must use only < and [] for ZP pointers .

I have tried this
Code: [Select]
#asm         
     lda #low(_logo_pic_pal)
     sta <__pointr     
     lda #high(_logo_pic_pal)
     sta <__pointr+1   
  #endasm

Equate to :
Code: [Select]
int logo_pic_pal[16];
int *pointr;

pointr = logo_pic_pal;

???
« Last Edit: October 14, 2009, 09:59:24 PM by touko »