Warhawk DS (HK & Flash's DS Diary)

flash · 261528

Offline flash

  • Administrator
  • Blue Gene Super Computer
  • **********
    • Posts: 13180
on: December 20, 2008, 06:04:08 pm
EDIT: Sorry for the dullness of the first few entries in this diary, They are more about learning the DS and Arm than Warhawk. I have kept them in because it goes some way to show how it has developed from my early beginnings in the learning of the DS hardware (thanks HK). And as such, may still be of some help to others who wish to learn ASM on the DS

Been playing with hk's ds post instructions and made a wobbly colour effect from the sample code by hitting the keybord to see what happens :)

Not really, just having a play with the mnomics that are in the tutorial code to change the colours. It is a five minute thing, but as with any coding it is a good idea to start with an example and play with it to learn, then break out from there.

I will have to look into interupts on the ds to time changes to screen refresh, but I am at work at the mo and had a few minutes to play..

« Last Edit: February 18, 2009, 07:11:48 pm by Flash »

Coding for the love of it!


Offline headkaze

  • Administrator
  • Blue Gene Super Computer
  • **********
    • Posts: 7838
Reply #1 on: December 21, 2008, 04:27:52 pm
I can see your copying the register that is being used as the iterator to the screen. Also an interesting effect is to alter the screen's x pos using a sine LUT during hblank to create a wobble effect.

I just added an example to display a bitmap :)

BTW You will have to download the source again for the first example because I had to modify the makefile to work with embedded data.
« Last Edit: December 21, 2008, 05:35:29 pm by headkaze »



Offline flash

  • Administrator
  • Blue Gene Super Computer
  • **********
    • Posts: 13180
Reply #2 on: December 21, 2008, 06:01:19 pm
Yeah, I had a few minutes at work sat night to have a little fiddle. I was mostly playing with the "Programers notepad" more than anything just to get used to it. You have to remember that this is a world away from the far simpler TurboAsm and Action Replay ;)

Coding for the love of it!


Offline flash

  • Administrator
  • Blue Gene Super Computer
  • **********
    • Posts: 13180
Reply #3 on: December 21, 2008, 11:36:58 pm
Was trying to place a 180x21 pixel bitmap to the screen on the DS, And i really cannot see why I get this big gap?

Bloody Arm... Smash the DS all up!! :)


Coding for the love of it!


Offline Grapple

  • Dragon 32
  • **
    • Posts: 60
Reply #4 on: December 22, 2008, 07:57:49 am
Damn this looks like fun... if/when i get some spare time i will definately have to try it out...

Once you cut people open you realise we are pretty much the same.....


Offline headkaze

  • Administrator
  • Blue Gene Super Computer
  • **********
    • Posts: 7838
Reply #5 on: December 22, 2008, 11:25:15 am
I'm really starting to see how difficult it would be to code a full game in arm asm! Anyway I'm enjoying the challenge. I tried a slightly different approach to you Flash but finally got the logo displaying correctly. I think you would be better off using tiles to display the logo but anyway here's my solution attached :)
« Last Edit: December 22, 2008, 11:44:09 am by headkaze »



Offline flash

  • Administrator
  • Blue Gene Super Computer
  • **********
    • Posts: 13180
Reply #6 on: December 22, 2008, 12:55:01 pm
Thanks HK,

I just wanted to stick with a bit of learning the bitmap mode.

I still cannot understand why my version leaves that gap? I have not had a look today and perhaps I was getting a bit too tired last night, god knows!

Thanks for working that out!

I was trying to do it using a simple x and y counter and adding the value needed to the screen pointer to simulate a carriage return (start next line). I did it that way as it was easier to ref with the c64 and doing things in a similar fashion makes things clearer to me :) Things were also easier when all you had was C, X, Y and direct increments of memory adresses.
The framebuffer mode is something that I wanted to get used to so I could code a true starfield, and the bitmap plot was a way to work out a routine (library :) ) to plot a pixel at a location when given an x,y coord.

Thanks HK..
« Last Edit: December 22, 2008, 05:33:55 pm by Flash »

Coding for the love of it!


Offline flash

  • Administrator
  • Blue Gene Super Computer
  • **********
    • Posts: 13180
Reply #7 on: December 22, 2008, 05:04:03 pm
Done a little plot routine

plotstar:
   mov r0,r7,lsl #8            @ mul r7 (y) by 256 and store in r0
   add r0,r6               @ add x value to r0
   add r0,#BG_BMP_RAM(0)         @ add screen location to result
   mov r8,#0xff            @ set r8 to white pixel (I only get black)
   str r8,[r0]            @ store r8 at screen location
   mov r15,r14            @ return to main code

set r6 and r7 to x and y and call and this will plot a pixel at x,y. This plots a pixel where indicated, though it is always black :) I cannot/haven't worked out the pallets yet.. Grrrr. There is always something.

using the final mov command to return the location prior to the call is the only way I can implement a JSR and RET subroutine..

HK: Is there anyway to call "Plotstar (20,121)" to pass the coords to the sub rather than preloading the registers? In final code the modified registers would then be pushed onto the stack for preservation and then restored prior to the return to the main code.

Also, If I wanted (ide question) to store the x and y refs of 100 stars in memory, using the ide, how can i set a memory space to do so?
i.e. Xcoord  EQU 0,0,0,0,0,0,0,0,0,0 or Xcoord EQU 0*100. I only ask this because on the c64 you would just pick an area of memory and use it! That is not really very tidy though.

Coding for the love of it!


Offline flash

  • Administrator
  • Blue Gene Super Computer
  • **********
    • Posts: 13180
Reply #8 on: December 22, 2008, 05:20:19 pm
Just realised that you can make the code smaller and tighter like this

plotstar:
   add r0,r6,r7,lsl #8               @ add x + (y *256) store in r0
   add r0,#BG_BMP_RAM(0)            @ add screen location to result
   mov r8,#255               @ set r8 to white pixel (I only get black)
   str r8,[r0]               @ store r8 at screen location
   mov r15,r14               @ return to main code

Still can only get black stars though :)
« Last Edit: December 23, 2008, 05:41:05 pm by Flash »

Coding for the love of it!


Offline headkaze

  • Administrator
  • Blue Gene Super Computer
  • **********
    • Posts: 7838
Reply #9 on: December 23, 2008, 12:17:56 am
If your using a 16 bit video mode then the bit format is X1B5G5R5. You have to set Bit 15 on to display a pixel otherwise it will remain black. That little doosy has got a few people in trouble ;)



Offline flash

  • Administrator
  • Blue Gene Super Computer
  • **********
    • Posts: 13180
Reply #10 on: December 23, 2008, 11:11:11 am
madness! :) C64 was a simple 11 10 01 00 he he

Managed to fill the screen with dots, but not exactly where I wanted....?

adds r0,r6,r7,lsl #8

if the result excedes the 256 boundry, it wraps round...

Lsl should work across all bits?

must be an adressing mode and perhaps I need to use 2 registers?

Coding for the love of it!


Offline flash

  • Administrator
  • Blue Gene Super Computer
  • **********
    • Posts: 13180
Reply #11 on: December 23, 2008, 06:40:06 pm
ok, Stars are now white..

What is strange in this code is that if the Y value (r7) is not an even number, then the result appears shifted 128 to the right and not the required amount? I take it that the ds stores 2 bytes per pixel, and in that I have multiplied the x by 2 to get a word location. With the Y coord, doing an lsl or 9 (x512) fails. For every pixel down it needs to move 512 bytes.
X coords work fine... grrrr!

x is not fine as it now only plots 128 pixels across?

plotstar:
   stmfd r13!,{r0,r6,r7,r8}      @ stack registers
   lsl r6,#1                  @ 2 bytes per pixel
   add r0,r6,r7,lsl #8         @ add x + (y *256) store in r0
   add r0,#BG_BMP_RAM(0)         @ add screen location to result
   ldr r8,=65535               @ set r8 to white pixel
   str r8,[r0]                  @ store r8 at screen location
   ldmfd r13!,{r0,r6,r7,r8}      @ restore rgisters
   mov r15,r14

Coding for the love of it!


Offline headkaze

  • Administrator
  • Blue Gene Super Computer
  • **********
    • Posts: 7838
Reply #12 on: December 24, 2008, 12:13:15 am
I take it that the ds stores 2 bytes per pixel, and in that I have multiplied the x by 2 to get a word location.

Well it's 16 bit mode so yes 2 bytes per pixel in the format X1B5G5R5 ie. 5 bits per color.

The registers are 32 bits so you need to write 16 bits or 0xFFFF which is a white pixel. You need to use strh instead of str so it only copies over the halfword.

Code: [Select]
strh r8,[r0]
Also note you wouldn't use ldr if you were moving the stars in realtime as it's very slow (it stores the value in ROM where it performs the operation). We use ldr because you can only load values with "mov" that are shifted 8 bit values. But it would be faster to use a mov and then an add.
« Last Edit: December 24, 2008, 12:52:59 am by headkaze »



Offline flash

  • Administrator
  • Blue Gene Super Computer
  • **********
    • Posts: 13180
Reply #13 on: December 24, 2008, 12:38:05 am
Yeah,  sorta worked it out in the end..

Have really (REALLY) found it hard to find something on the net to instruct on direct adressing of the ds screen in asm.
Well.. I failed... :)

Not to worry.. Had over an hour at home today and got an early starfield working a treat.

Coding for the love of it!


Offline flash

  • Administrator
  • Blue Gene Super Computer
  • **********
    • Posts: 13180
Reply #14 on: December 24, 2008, 12:56:58 am
Right, moving on a bit and working on direct screen addressing, I have been heading toward doing a starfield (how oldschool do ya want it?) on the ds as part of a bigger thing.  have set a goal to replicate the Warhawk title screen with the addition of a starfield and using (MOD/WAVE/MP3) music from asm only on the ds. Well, I have got someway toward the starfield. It mow works fine with as as many stars as you want (20 in the demo cause i am lazy)
The only thing it does not do is run under an interupt to work at 60hz and be smooth. To be honest, I have not even looked into interupts yet, I was just happy to have the starfield working. :)
I have posted the source using HK's code as a construct, though that by doing so, he will work it out and have it working in an interupt in no time.

Ok, Starfield only displays 20 stars in X speeds. The source does not limit the amount of stars. If I could be bothered to work out random numbers, I would have done more... :)

ps. the total arm9 learnng so far has taken 6-8 hours. Still having problems puting this in the context of the ds hardware. The Arm9 code is fairly easy, the ds isnt!
This uses HK's dualpics project (I cant be bothered to make a new project :) )

« Last Edit: December 24, 2008, 02:01:34 am by Flash »

Coding for the love of it!


Offline headkaze

  • Administrator
  • Blue Gene Super Computer
  • **********
    • Posts: 7838
Reply #15 on: December 24, 2008, 01:38:55 am
Hey thats cool! Great work :)

Did you see the waitforvblank routine in the dualpic demo? That should make it smoother if you draw during vblank.

Another thing to consider; it would be much faster to draw the stars once and then use the BG's scroll registers (ie. REG_BGxX & REG_BGxY) to move the stars. You could also have them moving vertically as well as horizontally.

Something else I think would be a great effect would be to add a sine LUT and have the starfield move around using it.

Attached is a cool program called SINUSLAB which can generate sine LUT's :) (Save as "Bytes, TassC64-Style" format)
« Last Edit: December 24, 2008, 01:42:25 am by headkaze »



Offline flash

  • Administrator
  • Blue Gene Super Computer
  • **********
    • Posts: 13180
Reply #16 on: December 24, 2008, 01:57:41 am
I did try to use the existing vblank code you put in the original project, but it just hung..

What would be great is to set the starfield to and nmi.. :)

The main tihng is that I am learning.. Have a try and get the code running under vblank for smoothness, go on can ya? :)

Again, thanks for all your help!

couple of things,

1) can you put more than one command pr line in the ide?

2) can you help me with lamens (as close to bits and bytes) terms for the ds registers! Without YOUR code to set the screens, I would have been lost. If you were a c64 coder - you would understand.. :)

Coding for the love of it!


Offline Grapple

  • Dragon 32
  • **
    • Posts: 60
Reply #17 on: December 24, 2008, 08:49:09 pm
HiHi... well some progress there... Nice to see

Once you cut people open you realise we are pretty much the same.....


Offline flash

  • Administrator
  • Blue Gene Super Computer
  • **********
    • Posts: 13180
Reply #18 on: December 24, 2008, 08:57:22 pm
I have spent a while and cannot find a way to generate random numbers.

I thought that a reseed of the stars when they exit the end of the screen would look good.

Coding for the love of it!


Offline Grapple

  • Dragon 32
  • **
    • Posts: 60
Reply #19 on: December 24, 2008, 10:11:25 pm
Yep that would definately not look to static... :)

Once you cut people open you realise we are pretty much the same.....


Offline flash

  • Administrator
  • Blue Gene Super Computer
  • **********
    • Posts: 13180
Reply #20 on: December 24, 2008, 10:14:52 pm
Sadly, I cannot find any method to pull random numbers in Arm9. Lots of C code and several forms... But way ahead of me at the moment to convert to asm, even the MOD command frightens me!

Coding for the love of it!


Offline headkaze

  • Administrator
  • Blue Gene Super Computer
  • **********
    • Posts: 7838
Reply #21 on: December 24, 2008, 11:20:45 pm
I was researching this as well and found some example code for generating a random number on the GBA here.

I also got the waitvblank code working in your demo just but adding it to the end of your loop

Code: [Select]
ldr r0, =REG_VCOUNT                @ This will actually make the assembler put the number REG_VCOUNT in the "pool" and
                                @ the actual operation performed is a load from memory (likely ROM if you're not writting code to be
                                @ copied to RAM). This is an operation you want to avoid if you want speed (in that case, mov 0x4000000
                                @ and then add 6. The C compiler chooses this over an LDR quite often).
waitVBlank:
ldrh r1, [r0]                    @ read REG_VCOUNT

cmp r1, #(SCREEN_HEIGHT + 1)    @ 193 is, of course, the first scanline of vblank

bne waitVBlank                    @ loop if r1 is not equal to (NE condition) 193
                                @ (CMP does a compare (it's purpose is to set the status)).
b loop                            @ lets keep doing it!
« Last Edit: December 25, 2008, 01:20:05 am by headkaze »



Offline flash

  • Administrator
  • Blue Gene Super Computer
  • **********
    • Posts: 13180
Reply #22 on: December 25, 2008, 12:27:10 am
Well done HK, I will have to look at the random number code tomorrow (well - today now). I could find tons in x86, but would have been too hard to convert.

I removed the vblank from my source when writing the code to do the stars, more to keep it tidy for me while coding it and perhaps did something wrong when I edited it back in... It was about 2am when I had finished as I was late from work due to Christmas - well that is my excuse anyway :)

Thanks as always HK..

PS. How is your Arm coding/playing coming along (please don't show me up :) )

PPS. I think i have a slight "ps" and "smilie" obsession... :)

Coding for the love of it!


Offline flash

  • Administrator
  • Blue Gene Super Computer
  • **********
    • Posts: 13180
Reply #23 on: December 25, 2008, 12:34:46 am
I was researching this as well and found some example code for generating a random number on the GBA here.

I also got the waitvblank code working in your demo just but adding it to the end of your loop

For some reason this does not work for me - the stars all move flat out at full process and do not stop and wait for the vblank.. Must be doing something stupid but it is !:30 am and the kids will be up soon (good god) so I will have another look tomorrow..
« Last Edit: December 25, 2008, 01:03:33 am by headkaze »

Coding for the love of it!


Offline headkaze

  • Administrator
  • Blue Gene Super Computer
  • **********
    • Posts: 7838
Reply #24 on: December 25, 2008, 12:57:05 am
I haven't really done much at all just been working on some of your problems like random numbers and things like that. I'm thinking about working on some of my old projects I never got finished like a port of Cleudo from the Amiga and The Detective Game from C64.

BTW I realised that waitforvblank code is wrong it should be REG_VCOUNT not REG_DISPSTAT and it should be looping over until it reaches vblank. I reposted the code in my original post.
« Last Edit: December 25, 2008, 01:02:41 am by headkaze »



Offline flash

  • Administrator
  • Blue Gene Super Computer
  • **********
    • Posts: 13180
Reply #25 on: December 25, 2008, 09:47:48 pm
You are right. Works a treat now! The Ideas emu does not run it very smoothly though.

I decided to put it on a real DS and tried both R4DS and CycloneDS and it will not run on either? Just a black screen and that is all?

We must be missing something in the headers?

Coding for the love of it!


Offline flash

  • Administrator
  • Blue Gene Super Computer
  • **********
    • Posts: 13180
Reply #26 on: December 25, 2008, 10:58:10 pm
Another thing to consider; it would be much faster to draw the stars once and then use the BG's scroll registers (ie. REG_BGxX & REG_BGxY) to move the stars. You could also have them moving vertically as well as horizontally.

Something else I think would be a great effect would be to add a sine LUT and have the starfield move around using it.

Attached is a cool program called SINUSLAB which can generate sine LUT's :) (Save as "Bytes, TassC64-Style" format)
Sorry, missed some bits from earlier posts.

It would be quicker to use the scroll registers (when I work them out - Ug!) but I want the stars to randomise on exit from the screen in both y location and speed. I really want to keep as close to the kind of code you would use on the c64 (it would be the same, but in chars in say a 8x8 repeated grid, or using multiplexed sprites) as this makes it easier to pick up and help when you are trying to make a correlation between them. This is the same way I worked with the Amiga and also x86 on both the 486 and the Psion 3a. I know it is madness, but it helps.. (silly fool that I am)

Using luts would be quite fun at some point... Perhaps using "words" to store off-screen data and doing rotating stars? Thanks for posting sinuslab, That is a really handy peice of software for an oldschool coder like me :)

Regarding the mention of ldr as a slow way of loading the register. Yeah, I did read that and ldr is fine to use out of loops I know, but it does make the code easier to initially write. I will not use ldr at a later stage, especially when speed is important. At the moment, it will easily run 256 stars even with ldr.

Strange compiler issue. If you add a few more stars to the data .sx .sy etc, sometimes the compiler trips and complains about an error in a command earlier for no reason and refuses to compile. You prob already know why, but I am at a loss? Try it!

Thanks as always and sorry for the delay on the reply to these points.

p.s Had a good look at the gba rand function and cannot work it out...? It is messy code after all, with non descriptive variables and branches. Perhaps I will print it out to see how to convert/modify it to the nds?
« Last Edit: December 25, 2008, 11:14:40 pm by Flash »

Coding for the love of it!


Offline headkaze

  • Administrator
  • Blue Gene Super Computer
  • **********
    • Posts: 7838
Reply #27 on: December 26, 2008, 01:36:35 am
Okay mate I got them running on hardware it was an error that I forgot to fix in system.h

Here is the correct code in system.h (I removed the BIT macro thinking the asm compiler wouldn't work with them but it did and I forgot to put them back in)

Code: [Select]
#define POWER_LCD            BIT(0)
#define POWER_2D_A            BIT(1)
#define POWER_MATRIX        BIT(2)
#define POWER_3D_CORE        BIT(3)
#define POWER_2D_B            BIT(9)
#define POWER_SWAP_LCDS        BIT(15)

Attached is the starfield source with the fixed code and starfield.nds file that runs on hardware. I also uploaded the fixed dualpics source code and that runs okay on hardware too :)
« Last Edit: December 26, 2008, 02:01:52 am by headkaze »



Offline Grapple

  • Dragon 32
  • **
    • Posts: 60
Reply #28 on: December 26, 2008, 09:13:08 am
Wee that looks good.. :)

Once you cut people open you realise we are pretty much the same.....


Offline flash

  • Administrator
  • Blue Gene Super Computer
  • **********
    • Posts: 13180
Reply #29 on: December 26, 2008, 10:55:33 pm
Well, had another play and got my title screen working almost as intended. All that is missing it the music (asm mod/mp3/wav player, or perhaps called to a arm7 c compile).

I have put some images on and made the stars avoid drawing over them.. Yes - I have not looked into the layers and have not even got any idea if you can use layers on a bitmap screen.. But Hey, I like doing it the c64 way.. It works and that is the main thing.

Added a load more stars, hand typed. HK, I cannot get the random code to work, have tried to compile it and I cannot get a random number. Stars go off the left and never appear again :) Also, a downside of 100% asm, you have no way to know what a value is returned as unless you write a routine to display the value (good idea - perhaps I will do that) or plot a single pixel holding the value to a safe area to pick out in photoshop.

The next step is learning tile mode and doing a scroller that uses both screens vertically for the playfield.
Initially scrolling junk but eventually moving a large level map (warhawk had 10 levels).
This could be fun and also is something that I need HK's C experience for, to bridge the gap between the C code and assembly.

Anyway, the code is posted for anyone to learn from or laugh at. It has not been optimised in any way (seeing as it runs full speed fine) and also has a few errors in it by way of instructions used - I would not pass at assembly school. All the ldrb, ldr, ldrh... and I also have not touched one of the arms leading features, adding conditions to single operations. So - presented as is, and heavily commented..

:)

PS. The graphics are straight from the c64 and I will touch them up at come point to add more colour and higher detail.

« Last Edit: August 29, 2009, 11:42:06 pm by Flash »

Coding for the love of it!