SimpleBGScroll.pp 4.4 KB

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