FireAndSprites.pp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. program FireAndSprites;
  2. {$L build/ball.pcx.o}
  3. {$mode objfpc}
  4. uses
  5. ctypes, nds9;
  6. {$include inc/ball.pcx.inc}
  7. const
  8. NUM_SPRITES = 128;
  9. var
  10. OAMCopySub: array [0..127] of SpriteEntry;
  11. type
  12. TSprite = record
  13. x, y: cint; //location
  14. dx, dy: cint; //speed
  15. oam: PSpriteEntry;
  16. gfxID: integer; //graphics location
  17. end;
  18. PSprite = ^TSprite;
  19. procedure MoveSprite(var sp: TSprite);
  20. var
  21. x, y: integer;
  22. begin
  23. x := sp.x shr 8;
  24. y := sp.y shr 8;
  25. sp.oam^.y := y;
  26. sp.oam^.x := x;
  27. end;
  28. procedure initOAM();
  29. var
  30. i: integer;
  31. begin
  32. for i := 0 to 127 do
  33. OAMCopySub[i].attribute[0] := ATTR0_DISABLED;
  34. end;
  35. procedure updateOAM();
  36. begin
  37. memcpy(OAM_SUB, @OAMCopySub, 128 * sizeof(SpriteEntry));
  38. //dmaCopy(@OAMCopySub, OAM_SUB, 128 * sizeof(SpriteEntry));
  39. end;
  40. var
  41. back, front: pcuint16;
  42. sprites: array [0..NUM_SPRITES - 1] of TSprite;
  43. i, delta: integer;
  44. ix, iy: integer;
  45. screen: integer;
  46. map0, map1: pcuint16;
  47. red: cuint16;
  48. ball: sImage;
  49. begin
  50. randomize;
  51. back := VRAM_A;
  52. front := VRAM_B;
  53. i := 0;
  54. delta := 0;
  55. ix := 0;
  56. iy := 0;
  57. screen := 1;
  58. map0 := pcuint16(SCREEN_BASE_BLOCK_SUB(1));
  59. map1 := pcuint16(SCREEN_BASE_BLOCK_SUB(2));
  60. //set main display to render directly from the frame buffer
  61. videoSetMode(MODE_FB1);
  62. //set up the sub display
  63. videoSetModeSub(MODE_0_2D or
  64. DISPLAY_SPR_1D_LAYOUT or
  65. DISPLAY_SPR_ACTIVE or
  66. DISPLAY_BG0_ACTIVE or
  67. DISPLAY_BG1_ACTIVE );
  68. //vram banks are somewhat complex
  69. vramSetPrimaryBanks(VRAM_A_LCD, VRAM_B_LCD, VRAM_C_SUB_BG, VRAM_D_SUB_SPRITE);
  70. //load our ball pcx file into an image
  71. loadPCX(pcuint8(ball_pcx), @ball);
  72. //tile it so it is useful as sprite data
  73. imageTileData(@ball);
  74. // Sprite initialisation
  75. for i := 0 to 255 do
  76. SPRITE_PALETTE_SUB[i] := cuint32(ball.palette[i]);
  77. for i := 0 to 32*16 - 1 do
  78. SPRITE_GFX_SUB[i] := cuint32(ball.image.data16[i]);
  79. //turn off sprites
  80. initOAM();
  81. for i := 0 to NUM_SPRITES - 1 do
  82. begin
  83. //random place and speed
  84. sprites[i].x := random($FFFF);
  85. sprites[i].y := random($7FFF);
  86. sprites[i].dx := (random($FF)) + $100;
  87. sprites[i].dy := (random($FF)) + $100;
  88. if random(2) = 1 then
  89. sprites[i].dx := -sprites[i].dx;
  90. if random(2) = 1 then
  91. sprites[i].dy := -sprites[i].dy;
  92. sprites[i].oam := @OAMCopySub[i];
  93. sprites[i].gfxID := 0;
  94. //set up our sprites OAM entry attributes
  95. sprites[i].oam^.attribute[0] := ATTR0_COLOR_256 or ATTR0_SQUARE;
  96. sprites[i].oam^.attribute[1] := ATTR1_SIZE_32;
  97. sprites[i].oam^.attribute[2] := sprites[i].gfxID;
  98. end;
  99. //set up two backgrounds to scroll around
  100. REG_BG0CNT_SUB^ := BG_COLOR_256 or (1 shl MAP_BASE_SHIFT);
  101. REG_BG1CNT_SUB^ := BG_COLOR_256 or (2 shl MAP_BASE_SHIFT);
  102. BG_PALETTE_SUB[0] := RGB15(10,10,10);
  103. BG_PALETTE_SUB[1] := RGB15(0,16,0);
  104. BG_PALETTE_SUB[2] := RGB15(0,0,31);
  105. //load the maps with alternating tiles (0,1 for bg0 and 0,2 for bg1)
  106. for iy := 0 to 31 do
  107. for ix := 0 to 31 do
  108. begin
  109. map0[iy * 32 + ix] := (ix xor iy) and 1;
  110. map1[iy * 32 + ix] := ((ix xor iy) and 1) shl 1;
  111. end;
  112. //fill 2 tiles with different colors
  113. for i := 0 to (64 div 2) - 1 do
  114. begin
  115. BG_GFX_SUB[i+32] := $0101;
  116. BG_GFX_SUB[i+32+32] := $0202;
  117. end;
  118. while (true) do
  119. begin
  120. //scroll the background
  121. REG_BG0HOFS^ := delta;
  122. inc(delta);
  123. REG_BG0VOFS^ := delta;
  124. //move the sprites
  125. for i := 0 to NUM_SPRITES - 1 do
  126. begin
  127. sprites[i].x := sprites[i].x + sprites[i].dx;
  128. sprites[i].y := sprites[i].y + sprites[i].dy;
  129. //check for collision with the screen boundries
  130. if (sprites[i].x < (1 shl 8)) or (sprites[i].x > (247 shl 8)) then
  131. sprites[i].dx := -sprites[i].dx;
  132. if (sprites[i].y < (1 shl 8)) or (sprites[i].y > (182 shl 8)) then
  133. sprites[i].dy := -sprites[i].dy;
  134. //reposition the sprites
  135. MoveSprite(sprites[i]);
  136. end;
  137. //do the plasma/fire
  138. for ix := 0 to SCREEN_WIDTH - 1 do
  139. begin
  140. back[ix + SCREEN_WIDTH * (SCREEN_HEIGHT - 1)] := random($FFFF);
  141. back[ix + SCREEN_WIDTH * (SCREEN_HEIGHT - 2)] := random($FFFF);
  142. end;
  143. back := back + 1;
  144. for iy := 1 to SCREEN_HEIGHT - 3 do
  145. begin
  146. for ix := 1 to SCREEN_WIDTH - 2 do
  147. begin
  148. red := 0;
  149. red := red + front[0];
  150. red := red + front[2];
  151. front := front + SCREEN_WIDTH;
  152. red := red + front[0];
  153. red := red + front[1];
  154. red := red + front[2];
  155. front := front + SCREEN_WIDTH;
  156. red := red + front[0];
  157. red := red + front[1];
  158. red := red + front[2];
  159. front := front - ((2 * SCREEN_WIDTH) - 1);
  160. back[0] := (red shr 3);
  161. back := back + 1;
  162. end;
  163. back := back + 2;
  164. front := front + 2;
  165. end;
  166. swiWaitForVBlank();
  167. updateOAM();
  168. //flip screens
  169. if (screen) <> 0 then
  170. begin
  171. videoSetMode(MODE_FB1);
  172. front := VRAM_B;
  173. back := VRAM_A;
  174. screen := 0;
  175. end else
  176. begin
  177. videoSetMode(MODE_FB0);
  178. front := VRAM_A;
  179. back := VRAM_B;
  180. screen := 1;
  181. end;
  182. end;
  183. end.