2
0

SimpleBGScroll.pp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. program SimpleBGScroll;
  2. {$mode objfpc}
  3. {$H+}
  4. uses
  5. ctypes, gba;
  6. {$l build\r6502_portfont.bin.o}
  7. {$include inc\r6502_portfont.bin.inc}
  8. var
  9. MAPADDRESS: pcuint16;
  10. const
  11. DELAY = 2; // slow things down
  12. TILEWIDTH = 8; // how much to scroll
  13. ROW = 10; // what row to place text at
  14. // --------------------------------------------------------------------
  15. var
  16. palette: array [0..6] of cuint16;
  17. // --------------------------------------------------------------------
  18. const
  19. message = ' ' +
  20. 'Hello, this is an example of an oldschool simple tile scroller ' +
  21. 'not unlike how it was done in days of yore. The ''@'' symbol ' +
  22. 'at the top of your screen is intentional, to dispel the illusion ' +
  23. 'of this scroller, to demonstrate the simple concept behind it. ' +
  24. 'Check out the source to learn how it works. It is very simple! ' +
  25. 'This exercise brought to you by r6502... ' +
  26. 'Text is about to restart... ';
  27. procedure updatescrolltext(idx: cuint32);
  28. var
  29. i: integer;
  30. temppointer: pcuint16;
  31. begin
  32. temppointer := pcuint16(MAPADDRESS + (ROW * 32));
  33. // write out a whole row of text to the map
  34. for i := 0 to 31 do
  35. begin
  36. // check for end of message so we can wrap around properly
  37. if (message[idx] = #0) then
  38. idx := 0;
  39. // write a character - we subtract 32, because the font graphics
  40. // start at tile 0, but our text is in ascii (starting at 32 and up)
  41. // in other words, tile 0 is a space in our font, but in ascii a
  42. // space is 32 so we must account for that difference between the two.
  43. temppointer^ := Ord(message[idx]) - 32;
  44. inc(temppointer);
  45. inc(idx);
  46. end;
  47. end;
  48. var
  49. i, scrollx, scrolldelay, textindex: integer;
  50. temppointer: pcuint16;
  51. begin
  52. MAPADDRESS := MAP_BASE_ADR(31); // our base map address
  53. palette[0] := RGB8($40,$80,$c0);
  54. palette[1] := RGB8($FF,$FF,$FF);
  55. palette[2] := RGB8($F5,$FF,$FF);
  56. palette[3] := RGB8($DF,$FF,$F2);
  57. palette[4] := RGB8($CA,$FF,$E2);
  58. palette[5] := RGB8($B7,$FD,$D8);
  59. palette[6] := RGB8($2C,$4F,$8B);
  60. // Set up the interrupt handlers
  61. irqInit();
  62. // Enable Vblank Interrupt to allow VblankIntrWait
  63. irqEnable(IRQ_VBLANK);
  64. // Allow Interrupts
  65. REG_IME^ := 1;
  66. // load the palette for the background, 7 colors
  67. temppointer := BG_COLORS;
  68. for i := 0 to 6 do
  69. begin
  70. temppointer^ := cuint32(palette[i]); // u32 cast avoids u8 memory writing
  71. inc(temppointer);
  72. end;
  73. // load the font into gba video mem (48 characters, 4bit tiles)
  74. CpuFastSet(@r6502_portfont_bin, pcuint16(VRAM), (r6502_portfont_bin_size div 4) or COPY32);
  75. // clear screen map with tile 0 ('space' tile) (256x256 halfwords)
  76. //MAP_BASE_ADR(31) := nil;
  77. CpuFastSet( MAP_BASE_ADR(31), MAP_BASE_ADR(31), FILL or COPY32 or ($800 div 4));
  78. // set screen H and V scroll positions
  79. BG_OFFSET[0].x := 0;
  80. BG_OFFSET[0].y := 0;
  81. // initialize our variables
  82. scrollx := 0;
  83. textindex := 0;
  84. scrolldelay := 0;
  85. // put the '@' symbol on the top of the screen to show how
  86. // the screen is only scrolling 7 pixels - to reveal the
  87. // illusion of how the scroller works
  88. pcuint16((MAPADDRESS + 1))^ := $20; // 0x20 == '@'
  89. // draw a row of text from beginning of message
  90. updatescrolltext(0);
  91. // set the screen base to 31 (0x600F800) and char base to 0 (0x6000000)
  92. BGCTRL[0] := SCREEN_BASE(31);
  93. // screen mode & background to display
  94. SetMode( MODE_0 or BG0_ON );
  95. while true do
  96. begin
  97. VBlankIntrWait();
  98. // check if we reached our delay
  99. if (scrolldelay = DELAY) then
  100. begin
  101. // yes, the delay is complete, so let's reset it
  102. scrolldelay := 0;
  103. // check if we reached our scrollcount
  104. if (scrollx = (TILEWIDTH-1)) then
  105. begin
  106. // yes, we've scrolled enough, so let's reset the count
  107. scrollx := 0;
  108. // check if we reached the end of our scrolltext
  109. // and if so we need to restart our index
  110. if (message[textindex] = #0) then
  111. textindex := 0
  112. else
  113. inc(textindex);
  114. // finally, let's update the scrolltext with the current text index
  115. updatescrolltext(textindex);
  116. end else
  117. inc(scrollx);
  118. end else
  119. inc(scrolldelay);
  120. // update the hardware horizontal scroll register
  121. BG_OFFSET[0].x := scrollx;
  122. end;
  123. end.