Scrolling.pp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  1. unit scrolling;
  2. interface
  3. uses
  4. ctypes, nds9, RotBackgrounds, TextBackgrounds, Multilayer;
  5. procedure scroll(id, width, height: cint);
  6. procedure scrollText();
  7. procedure scrollRotation();
  8. procedure scrollVertical();
  9. procedure scrollHorizontalText();
  10. procedure scrollHorizontalExRotation();
  11. procedure scroll4wayText();
  12. procedure scroll4wayExRotation();
  13. implementation
  14. //reusable scroll function to allow the user to explore
  15. //the maps somewhat
  16. procedure scroll(id, width, height: cint);
  17. var
  18. keys, sx, sy: integer;
  19. begin
  20. keys := 0;
  21. sx := 0;
  22. sy := 0;
  23. while (keys and KEY_B) = 0 do
  24. begin
  25. scanKeys();
  26. keys := keysHeld();
  27. if (keys and KEY_UP) <> 0 then dec(sy);
  28. if (keys and KEY_DOWN) <> 0 then inc(sy);
  29. if (keys and KEY_LEFT) <> 0 then dec(sx);
  30. if (keys and KEY_RIGHT) <> 0 then inc(sx);
  31. if (sx < 0) then sx := 0;
  32. if (sx >= width - 256) then sx := width - 1 - 256;
  33. if (sy < 0) then sy := 0;
  34. if (sy >= height - 192) then sy := height - 1 - 192;
  35. swiWaitForVBlank();
  36. bgSetScroll(id, sx, sy);
  37. bgUpdate();
  38. consoleClear();
  39. iprintf('Scroll x: %d Scroll y: %d'#10, sx, sy);
  40. iprintf('Press ''B'' to exit');
  41. end;
  42. end;
  43. procedure scrollText();
  44. var
  45. keys, sx, sy, width, height: integer;
  46. bg: cint;
  47. begin
  48. keys := 0;
  49. sx := 0;
  50. sy := 0;
  51. width := 256;
  52. height := 512;
  53. //set up a simple text background
  54. videoSetMode(MODE_0_2D);
  55. vramSetBankA(VRAM_A_MAIN_BG);
  56. bg := bgInit(0, BgType_Text8bpp, BgSize_T_256x512, 0,1);
  57. dmaCopy(@TextBackgroundsTiles, bgGetGfxPtr(bg), sizeof(TextBackgroundsTiles));
  58. dmaCopy(@Layer256x512Map, bgGetMapPtr(bg), Layer256x512MapLen);
  59. dmaCopy(@TextBackgroundsPal, BG_PALETTE, sizeof(TextBackgroundsPal));
  60. while (keys and KEY_B) = 0 do
  61. begin
  62. scanKeys();
  63. keys := keysHeld();
  64. if (keys and KEY_UP) <> 0 then dec(sy);
  65. if (keys and KEY_DOWN) <> 0 then inc(sy);
  66. if (keys and KEY_LEFT) <> 0 then dec(sx);
  67. if (keys and KEY_RIGHT) <> 0 then inc(sx);
  68. //clamp the scroll value to the map width and height
  69. if (sx < 0) then sx := 0;
  70. if (sx >= width - 256) then sx := width - 1 - 256;
  71. if (sy < 0) then sy := 0;
  72. if (sy >= height - 192) then sy := height - 1 - 192;
  73. swiWaitForVBlank();
  74. //normally would call bgSetScroll(id, sx, sy) here
  75. //but to demonstrate the hardware difference between
  76. //scrolling rotation and text backgrounds we will use
  77. //direct register access
  78. REG_BG0HOFS^ := sx;
  79. REG_BG0VOFS^ := sy;
  80. consoleClear();
  81. iprintf('Scroll x: %d Scroll y: %d'#10, sx, sy);
  82. iprintf('Press ''B'' to exit');
  83. end;
  84. end;
  85. procedure scrollRotation();
  86. var
  87. keys, sx, sy, width, height: integer;
  88. bg: cint;
  89. begin
  90. keys := 0;
  91. sx := 0;
  92. sy := 0;
  93. width := 512;
  94. height := 512;
  95. videoSetMode(MODE_5_2D);
  96. vramSetBankA(VRAM_A_MAIN_BG);
  97. bg := bgInit(3, BgType_ExRotation, BgSize_ER_512x512, 0,1);
  98. dmaCopy(@TextBackgroundsTiles, bgGetGfxPtr(bg), sizeof(TextBackgroundsTiles));
  99. dmaCopy(@TextBackgroundsPal, BG_PALETTE, sizeof(TextBackgroundsPal));
  100. dmaCopy(@Layer512x512Map, bgGetMapPtr(bg), Layer512x512MapLen);
  101. while (keys and KEY_B)=0 do
  102. begin
  103. scanKeys();
  104. keys := keysHeld();
  105. if (keys and KEY_UP) <> 0 then dec(sy);
  106. if (keys and KEY_DOWN) <> 0 then inc(sy);
  107. if (keys and KEY_LEFT) <> 0 then dec(sx);
  108. if (keys and KEY_RIGHT) <> 0 then inc(sx);
  109. //clamp the scroll value to the map width and height
  110. if (sx < 0) then sx := 0;
  111. if (sx >= width - 256) then sx := width - 1 - 256;
  112. if (sy < 0) then sy := 0;
  113. if (sy >= height - 192) then sy := height - 1 - 192;
  114. swiWaitForVBlank();
  115. //normally would call bgSetScroll(id, sx, sy) here
  116. //but to demonstrate the hardware difference between
  117. //scrolling rotation and text backgrounds we will use
  118. //direct register access
  119. REG_BG3X^ := sx shl 8;
  120. REG_BG3Y^ := sy shl 8;
  121. consoleClear();
  122. iprintf('Scroll x: %d Scroll y: %d'#10, sx, sy);
  123. iprintf('Press ''B'' to exit');
  124. end;
  125. end;
  126. procedure scrollVertical();
  127. var
  128. scroll_y: integer = 0;
  129. map: pcuint16;
  130. bg: cint;
  131. keys: integer = 0;
  132. offset: integer = 0;
  133. begin
  134. videoSetMode(MODE_0_2D);
  135. vramSetBankA(VRAM_A_MAIN_BG);
  136. scroll_y := 0;
  137. bg := bgInit(0, BgType_Text8bpp, BgSize_T_256x256, 0,1);
  138. dmaCopy(@TextBackgroundsTiles, bgGetGfxPtr(bg), sizeof(TextBackgroundsTiles));
  139. dmaCopy(@TextBackgroundsPal, BG_PALETTE, sizeof(TextBackgroundsPal));
  140. map := pcuint16(bgGetMapPtr(bg));
  141. dmaCopy(@Layer256x512Map, map, 32*32*2);
  142. keys := 0;
  143. offset := 0;
  144. while (keys and KEY_B)= 0 do
  145. begin
  146. scanKeys();
  147. keys := keysHeld();
  148. swiWaitForVBlank();
  149. if (keys and KEY_UP) <> 0 then
  150. begin
  151. offset := scroll_y div 8 - 1;
  152. dmaCopy(@Layer256x512Map[(offset and 63) * 32], @map[(offset and 31) * 32], 32 * 2);
  153. dec(scroll_y);
  154. end;
  155. if (keys and KEY_DOWN) <> 0 then
  156. begin
  157. offset := scroll_y div 8 + 24;
  158. dmaCopy(@Layer256x512Map[(offset and 63) * 32], @map[(offset and 31) * 32], 32 * 2);
  159. inc(scroll_y);
  160. end;
  161. bgSetScroll(bg, 0, scroll_y);
  162. bgUpdate();
  163. end;
  164. end;
  165. procedure scrollHorizontalText();
  166. var
  167. scroll_x: integer = 0;
  168. bg: cint;
  169. map: pcuint16;
  170. iy: integer;
  171. keys: integer = 0;
  172. layerOffset: integer = 0;
  173. mapOffset: integer = 0;
  174. begin
  175. videoSetMode(MODE_5_2D);
  176. vramSetBankA(VRAM_A_MAIN_BG);
  177. bg := bgInit(0, BgType_Text8bpp, BgSize_T_512x256, 0,1);
  178. dmaCopy(@TextBackgroundsTiles, bgGetGfxPtr(bg), sizeof(TextBackgroundsTiles));
  179. dmaCopy(@TextBackgroundsPal, BG_PALETTE, sizeof(TextBackgroundsPal));
  180. map := pcuint16(bgGetMapPtr(bg));
  181. for iy := 0 to 23 do
  182. dmaCopy(@Layer512x256Map[iy * 64], @map[iy * 32], 32*2);
  183. while (keys and KEY_B) = 0 do
  184. begin
  185. scanKeys();
  186. keys := keysHeld();
  187. swiWaitForVBlank();
  188. if (keys and KEY_LEFT) <> 0 then
  189. begin
  190. mapOffset := scroll_x div 8 - 1;
  191. layerOffset := (mapOffset and 63);
  192. if(layerOffset >= 32) then layerOffset := layerOffset + (32 * 32 - 32);
  193. for iy := 0 to 23 do
  194. map[layerOffset + (iy * 32)] := Layer512x256Map[(mapOffset and 63) + (iy * 64)] ;
  195. dec(scroll_x);
  196. end;
  197. if (keys and KEY_RIGHT) <> 0 then
  198. begin
  199. mapOffset := scroll_x div 8 + 32;
  200. layerOffset := (mapOffset and 63);
  201. if(layerOffset >= 32) then layerOffset := layerOffset + (32 * 32 - 32);
  202. for iy := 0 to 23 do
  203. map[layerOffset + (iy * 32)] := Layer512x256Map[(mapOffset and 63) + (iy * 64)] ;
  204. inc(scroll_x);
  205. end;
  206. bgSetScroll(bg, scroll_x, 0);
  207. bgUpdate();
  208. end;
  209. end;
  210. procedure scrollHorizontalExRotation();
  211. var
  212. scroll_x: integer = 0;
  213. bg: cint;
  214. map: pcuint16;
  215. iy: integer;
  216. keys: integer = 0;
  217. offset: integer = 0;
  218. begin
  219. videoSetMode(MODE_5_2D);
  220. vramSetBankA(VRAM_A_MAIN_BG);
  221. bg := bgInit(3, BgType_ExRotation, BgSize_ER_512x512, 0,1);
  222. dmaCopy(@TextBackgroundsTiles, bgGetGfxPtr(bg), sizeof(TextBackgroundsTiles));
  223. dmaCopy(@TextBackgroundsPal, BG_PALETTE, sizeof(TextBackgroundsPal));
  224. map := pcuint16(bgGetMapPtr(bg));
  225. bgSetControlBits(bg, BG_WRAP_ON);
  226. for iy := 0 to 23 do
  227. dmaCopy(@Layer512x256Map[iy * 64], @map[iy * 64], 32*2);
  228. while (keys and KEY_B) = 0 do
  229. begin
  230. scanKeys();
  231. keys := keysHeld();
  232. swiWaitForVBlank();
  233. if (keys and KEY_LEFT) <> 0 then
  234. begin
  235. offset := scroll_x div 8 - 1;
  236. for iy := 0 to 23 do
  237. map[(offset and 63) + (iy * 64)] := Layer512x256Map[(offset and 63) + (iy * 64)] ;
  238. dec(scroll_x);
  239. end;
  240. if (keys and KEY_RIGHT) <> 0 then
  241. begin
  242. offset := scroll_x div 8 + 32;
  243. for iy := 0 to 23 do
  244. map[(offset and 63) + (iy * 64)] := Layer512x256Map[(offset and 63) + (iy * 64)] ;
  245. inc(scroll_x);
  246. end;
  247. bgSetScroll(bg, scroll_x, 0);
  248. bgUpdate();
  249. end;
  250. end;
  251. //scrolls a 1024 by 1024 map on a 512x512 layer
  252. procedure scroll4wayText();
  253. var
  254. scroll_x: integer = 0;
  255. scroll_y: integer = 0;
  256. bg: cint;
  257. bgTileMap, bgLeftHalf, bgRightHalf: pcuint16;
  258. ix, iy: integer;
  259. keys: integer = 0;
  260. offset_x: integer = 0;
  261. offset_y: integer = 0;
  262. movingHorizontal: boolean = false;
  263. movingVertical: boolean = false;
  264. bgTemp: pcuint16;
  265. const
  266. tileWidth : integer = 8; //width of a tile in pixels
  267. mapWidth : integer = 1024 div 8; //width of the big map in tiles
  268. mapHeight : integer = 1024 div 8; //heigh of the big map in tiles
  269. bgWidth : integer = 256 div 8; //width of the hardware map in tiles
  270. bgHeight : integer = 256 div 8; //height of the hardware map in tiles
  271. screenWidth : integer = 256 div 8; //screen width in tiles
  272. screenHeight: integer = 192 div 8; //screen height in tiles
  273. begin
  274. videoSetMode(MODE_0_2D);
  275. vramSetBankA(VRAM_A_MAIN_BG);
  276. bg := bgInit(3, BgType_Text8bpp, BgSize_T_512x256, 0,1);
  277. dmaCopy(@TextBackgroundsTiles, bgGetGfxPtr(bg), sizeof(TextBackgroundsTiles));
  278. dmaCopy(@TextBackgroundsPal, BG_PALETTE, sizeof(TextBackgroundsPal));
  279. bgTileMap := pcuint16(bgGetMapPtr(bg));
  280. bgLeftHalf := bgTileMap;
  281. bgRightHalf := bgTileMap + 32 * 32;
  282. for iy := 0 to screenHeight - 1 do
  283. dmaCopy(@Layer1024x1024Map[iy * mapWidth], @bgTileMap[iy * bgWidth], screenWidth * 2);
  284. while (keys and KEY_B) = 0 do
  285. begin
  286. movingHorizontal := false;
  287. movingVertical := false;
  288. scanKeys();
  289. keys := keysHeld();
  290. swiWaitForVBlank();
  291. if (keys and KEY_LEFT) <> 0 then
  292. begin
  293. offset_x := scroll_x div 8 - 1;
  294. dec(scroll_x);
  295. if(scroll_x < 0) then
  296. scroll_x := 0
  297. else
  298. movingHorizontal := true;
  299. end else
  300. if (keys and KEY_RIGHT) <> 0 then
  301. begin
  302. offset_x := scroll_x div 8 + screenWidth;
  303. inc(scroll_x);
  304. if (scroll_x >= (mapWidth - screenWidth) * tileWidth) then
  305. scroll_x := (mapWidth - screenWidth) * tileWidth - 1
  306. else
  307. movingHorizontal := true;
  308. end;
  309. if (keys and KEY_UP) <> 0 then
  310. begin
  311. offset_y := scroll_y div 8 - 1;
  312. dec(scroll_y);
  313. if(scroll_y < 0) then
  314. scroll_y := 0
  315. else
  316. movingVertical := true;
  317. end else
  318. if (keys and KEY_DOWN) <> 0 then
  319. begin
  320. offset_y := scroll_y div 8 + screenHeight;
  321. inc(scroll_y);
  322. if(scroll_y >= (mapHeight - screenHeight) * tileWidth) then
  323. scroll_y := (mapHeight - screenHeight) * tileWidth - 1
  324. else
  325. movingVertical := true;
  326. end;
  327. if (movingHorizontal) then
  328. begin
  329. if (offset_x and 63) >= bgWidth then
  330. bgTemp := bgRightHalf
  331. else
  332. bgTemp := bgLeftHalf;
  333. for iy := scroll_y div 8 - 1 to scroll_y div 8 + screenHeight do
  334. bgTemp[(offset_x and (bgWidth - 1)) + (iy and (bgHeight - 1)) * 32] := Layer1024x1024Map[offset_x + iy * mapWidth];
  335. end;
  336. if (movingVertical) then
  337. begin
  338. for ix := scroll_x div 8 - 1 to scroll_x div 8 + screenWidth do
  339. begin
  340. if ((ix and 63) >= bgWidth) then
  341. bgTemp := bgRightHalf
  342. else
  343. bgTemp := bgLeftHalf;
  344. bgTemp[(ix and (bgWidth - 1)) + (offset_y and (bgHeight - 1))* 32] := Layer1024x1024Map[ix + offset_y * mapWidth];
  345. end;
  346. end;
  347. bgSetScroll(bg, scroll_x, scroll_y);
  348. bgUpdate();
  349. end;
  350. end;
  351. procedure scroll4wayExRotation();
  352. var
  353. scroll_x: integer = 0;
  354. scroll_y: integer = 0;
  355. bgTileMap: pcuint16;
  356. iy, ix: integer;
  357. keys: integer = 0;
  358. offset_x: integer = 0;
  359. offset_y: integer = 0;
  360. movingHorizontal: boolean = false;
  361. movingVertical: boolean = false;
  362. bg: cint;
  363. const
  364. tileWidth : integer = 8;
  365. mapWidth : integer = 1024 div 8;
  366. mapHeight : integer = 1024 div 8;
  367. bgWidth : integer = 512 div 8;
  368. bgHeight : integer = 512 div 8;
  369. screenWidth : integer = 256 div 8;
  370. screenHeight: integer = 192 div 8;
  371. begin
  372. videoSetMode(MODE_5_2D);
  373. vramSetBankA(VRAM_A_MAIN_BG);
  374. bg := bgInit(3, BgType_ExRotation, BgSize_ER_512x512, 0,1);
  375. dmaCopy(@TextBackgroundsTiles, bgGetGfxPtr(bg), sizeof(TextBackgroundsTiles));
  376. dmaCopy(@TextBackgroundsPal, BG_PALETTE, sizeof(TextBackgroundsPal));
  377. bgTileMap := pcuint16(bgGetMapPtr(bg));
  378. bgSetControlBits(bg, BG_WRAP_ON);
  379. for iy := 0 to screenHeight - 1 do
  380. dmaCopy(@Layer1024x1024Map[iy * mapWidth], @bgTileMap[iy * bgWidth], screenWidth * 2);
  381. while (keys and KEY_B) = 0 do
  382. begin
  383. movingHorizontal := false;
  384. movingVertical := false;
  385. scanKeys();
  386. keys := keysHeld();
  387. swiWaitForVBlank();
  388. if (keys and KEY_LEFT) <> 0 then
  389. begin
  390. offset_x := scroll_x div 8 - 1;
  391. dec(scroll_x);
  392. if(scroll_x < 0) then
  393. scroll_x := 0
  394. else
  395. movingHorizontal := true;
  396. end else
  397. if (keys and KEY_RIGHT) <> 0 then
  398. begin
  399. offset_x := scroll_x div 8 + screenWidth;
  400. inc(scroll_x);
  401. if (scroll_x >= (mapWidth - screenWidth) * tileWidth) then
  402. scroll_x := (mapWidth - screenWidth) * tileWidth - 1
  403. else
  404. movingHorizontal := true;
  405. end;
  406. if (keys and KEY_UP) <> 0 then
  407. begin
  408. offset_y := scroll_y div 8 - 1;
  409. dec(scroll_y);
  410. if(scroll_y < 0) then
  411. scroll_y := 0
  412. else
  413. movingVertical := true;
  414. end else
  415. if(keys and KEY_DOWN) <> 0 then
  416. begin
  417. offset_y := scroll_y div 8 + screenHeight;
  418. inc(scroll_y);
  419. if(scroll_y >= (mapHeight - screenHeight) * tileWidth) then
  420. scroll_y := (mapHeight - screenHeight) * tileWidth - 1
  421. else
  422. movingVertical := true;
  423. end;
  424. if (movingHorizontal) then
  425. begin
  426. for iy := scroll_y div 8 - 1 to scroll_y div 8 + screenHeight do
  427. bgTileMap[(offset_x and (bgWidth - 1)) + (iy and (bgHeight - 1)) * bgWidth] := Layer1024x1024Map[offset_x + iy * mapWidth];
  428. end;
  429. if (movingVertical) then
  430. begin
  431. for ix := scroll_x div 8 - 1 to scroll_x div 8 + screenWidth do
  432. bgTileMap[(ix and (bgWidth - 1)) + (offset_y and (bgHeight - 1))* bgWidth] := Layer1024x1024Map[ix + offset_y * mapWidth];
  433. end;
  434. bgSetScroll(bg, scroll_x, scroll_y);
  435. bgUpdate();
  436. end;
  437. end;
  438. end.