Advertisement
Leap_

fjdsklfsd

Jul 19th, 2015
189
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. JOYPAD_REGISTER                 equ             $00             ; joypad
  2. PAD_PORT_DPAD                   equ             %00100000       ; select d-pad buttons
  3. PAD_PORT_BUTTONS                equ             %00010000       ; select other buttons
  4. PAD_OUTPUT_MASK                 equ             %00001111       ; mask for the output buttons
  5. DPAD_DOWN                               equ             7 ; down is 7, example: cp 7 is it the down button?
  6. DPAD_UP                                 equ             6 ; up is 6
  7. DPAD_LEFT                               equ             5 ; left is 5
  8. DPAD_RIGHT                              equ             4 ; right is 4
  9. START_BUTTON                    equ             3
  10. SELECT_BUTTON                   equ             2
  11. B_BUTTON                                equ             1
  12. A_BUTTON                                equ             0 ; down to here
  13. DPAD_DOWN_MASK                  equ             %10000000 ; masks for the buttons
  14. DPAD_UP_MASK                    equ             %01000000
  15. DPAD_LEFT_MASK                  equ             %00100000
  16. DPAD_RIGHT_MASK                 equ             %00010000
  17. START_BUTTON_MASK               equ             %00001000
  18. SELECT_BUTTON_MASK              equ             %00000100
  19. B_BUTTON_MASK                   equ             %00000010
  20. A_BUTTON_MASK                   equ             %00000001
  21.  
  22. DIV_REGISTER                    equ             $04             ; divide timer... read to get time, write to reset it to 0
  23. TIMA_REGISTER                   equ             $05             ; main timer... freq is set in TAC reg, generates interupt when overflows
  24. TMA_REGISTER                    equ             $06             ; Timer Modulo... main timer loaded with this value after it overflows
  25. TAC_REGISTER                    equ             $07             ; Timer Control
  26. TIMER_STOP                              equ             %00000100       ; timer halt flag... 0=stop, 1=run
  27. TIMER_FREQ_MASK                 equ             %00000011       ; mask for timer frequency bits
  28. TIMER_FREQ_4KHz                 equ             %00000000       ; main timer runs at 4.096 KHz
  29. TIMER_FREQ_262KHz               equ             %00000001       ; main timer runs at 262.144 KHz
  30. TIMER_FREQ_65KHZ                equ             %00000010       ; main timer runs at 65.536 KHz
  31. TIMER_FREQ_16KHz                equ             %00000011       ; main timer runs at 15.384 KHz
  32.  
  33. IRQ_FLAG_REGISTER               equ             $0F             ; Interrupt Flag
  34. VBLANK_INT                              equ             %00000001       ; bit 0 = vblank interrupt on/off
  35. LCDC_INT                                equ             %00000010       ; bit 1 = LCDC interrupt on/off
  36. TIMER_INT                               equ             %00000100       ; bit 2 = Timer Overflow interrupt on/off
  37. SERIAL_INT                              equ             %00001000       ; bit 3 = Serial I/O Transfer Completion interrupt on/off
  38. CONTROLLER_INT                  equ             %00010000       ; bit 4 = ??
  39.  
  40. LCDC_CONTROL                    equ             $40             ; LCD (Graphics) Control
  41. BKG_DISP_FLAG                   equ             %00000001       ; bit 0 = background tile map is on if set
  42. SPRITE_DISP_FLAG                equ             %00000010       ; bit 1 = sprites are on if set
  43. SPRITE_DISP_SIZE                equ             %00000100       ; bit 2 = sprite size (0=8x8 pixels, 1=16x8)
  44. BKG_MAP_LOC                             equ             %00001000       ; bit 3 = background tile map location (0=$9800-$9bff, 1=$9c00-$9fff)
  45. TILES_LOC                               equ             %00010000       ; bit 4 = tile data location (0=$8800-$97ff, 1=$8000-$8fff)
  46. WINDOW_DISP_FLAG                equ             %00100000       ; bit 5 = window tile map is on if set
  47. WINDOW_MAP_LOC                  equ             %01000000       ; bit 6 = window tile map location (0=$9800-$9bff, 1=$9c00-9fff)
  48. DISPLAY_FLAG                    equ             %10000000       ; bit 7 = LCD display on if set
  49.  
  50. LCDC_STATUS                             equ             $41             ; LCDC Status
  51. DISP_CYCLE_MODE                 equ             %00000011       ; mask for the display cycle mode bits
  52. VBLANK_MODE                             equ             %00000000       ; system is in vertical blanking interval
  53. HBLANK_MODE                             equ             %00000001       ; system is in a horizontal blanking interval
  54. SPRITE_MODE                             equ             %00000010       ; system is reading sprite RAM
  55. LCD_TRANSFER                    equ             %00000011       ; system is transfering data to the LCD driver
  56.  
  57. SCROLL_BKG_Y                    equ             $42             ; vertical scroll position of background tile map
  58. SCROLL_BKG_X                    equ             $43             ; horizontal scroll position of background tile map
  59.  
  60. LCDC_LY_COUNTER                 equ             $44             ; increments every scan line (0..143 = display, 144-153 = vblank)
  61. LY_COMPARE                              equ             $45             ; ??
  62.  
  63. DMA_REGISTER                    equ             $46             ; DMA Transfer and Start Address
  64.  
  65. PALETTE_BKG                             equ             $47             ; palette data for background tile map
  66. PALETTE_SPRITE_0                equ             $48             ; sprite palette 0 data
  67. PALETTE_SPRITE_1                equ             $49             ; sprite palette 1 data
  68.  
  69. POS_WINDOW_Y                    equ             $4A             ; window tile map Y position
  70. POS_WINDOW_X                    equ             $4B             ; window tile map X position
  71.  
  72. INTERRUPT_ENABLE                equ             $ff             ; Interrupt Enable
  73.  
  74. ; $ff80 to $fffe is 128 bytes of internal RAM
  75. STACK_TOP                               equ             $fff4           ; put the stack here
  76.  
  77. ; video ram display locations
  78. TILES_MEM_LOC_0                 equ             $8800           ; tile map tiles only
  79. TILES_MEM_LOC_1                 equ             $8000           ; tile maps and sprite tiles
  80.  
  81. MAP_MEM_LOC_0                   equ             $9800           ; background and window tile maps
  82. MAP_MEM_LOC_1                   equ             $9c00           ; (select which uses what mem loc in LCDC_CONTROL register)
  83.  
  84. SPRITE_ATTRIB_MEM_LOC   equ             $fe00           ; OAM memory (sprite attributes)
  85.  
  86. ; sprite attribute flags
  87. SPRITE_FLAGS_PAL                equ             %00010000       ; palette (0=sprite pal 0, 1=sprite pal 1)
  88. SPRITE_FLAGS_XFLIP              equ             %00100000       ; sprite is horizontal flipped
  89. SPRITE_FLAGS_YFLIP              equ             %01000000       ; sprite is vertical flipped
  90. SPRITE_FLAGS_PRIORITY   equ             %10000000       ; sprite display priority (0=on top bkg & win, 1=behind bkg & win)
  91.  
  92.  
  93.  
  94. ;-------------------------------------------------------------------------
  95. ; start of the game rom (address 0000)
  96. ;-------------------------------------------------------------------------
  97. SECTION "rst 00", ROM0 [$00]
  98.         rst $38
  99. SECTION "rst 08", ROM0 [$08]
  100.         rst $38
  101. SECTION "rst 10", ROM0 [$10]
  102.         rst $38
  103. SECTION "rst 18", ROM0 [$18]
  104.         rst $38
  105. SECTION "rst 20", ROM0 [$20]
  106.         rst $38
  107. SECTION "rst 28", ROM0 [$28]
  108.         rst $38
  109. SECTION "rst 30", ROM0 [$30]
  110.         rst $38
  111. SECTION "rst 38", ROM0 [$38]
  112.         rst $38
  113.  
  114. ; NOTE: the hardware requires the interrupt jumps to be at these addresses
  115.  
  116. SECTION "VBlank_IRQ_Jump",HOME[$0040]
  117. ; Vertical Blanking interrupt
  118.         jp      VBlankFunc
  119.  
  120. SECTION "LCDC_IRQ_Jump",HOME[$0048]
  121. ; LCDC Status interrupt (can be set for H-Blanking interrupt)
  122.         rst $38
  123.  
  124. SECTION "Timer_Overflow_IRQ_Jump",HOME[$0050]
  125. ; Main Timer Overflow interrupt
  126.         reti
  127.  
  128. SECTION "Serial_IRQ_Jump",HOME[$0058]
  129. ; Serial Transfer Completion interrupt
  130.         reti
  131.  
  132. SECTION "Joypad_IRQ_Jump",HOME[$0060]
  133. ; Joypad Button Interrupt
  134.         reti
  135.  
  136.  
  137.  
  138.  
  139. SECTION "GameBoy_Header_Start",HOME[$0100]
  140. GameBoyHeaderStart::
  141.         ; begining of Game Boy game header
  142.         nop ; cpu cycle once
  143.        
  144.         jp      title_stuff         ; goto beginning of game code
  145.  
  146. ; Game Boy standard header... DO NOT CHANGE!
  147. db $CE,$ED,$66,$66,$CC,$0D,$00,$0B,$03,$73,$00,$83,$00,$0C,$00,$0D
  148. db $00,$08,$11,$1F,$88,$89,$00,$0E,$DC,$CC,$6E,$E6,$DD,$DD,$D9,$99
  149. db $BB,$BB,$67,$63,$6E,$0E,$EC,$CC,$DD,$DC,$99,$9F,$BB,$B9,$33,$3E
  150.  
  151. db "SILVER          "   ; game name (must be 16 bytes)
  152. db $00,$00,$00                  ; unused
  153. db $00                                  ; cart type
  154. db $00                                  ; ROM Size (32 k)
  155. db $00                                  ; RAM Size (0 k)
  156. db $00,$00                              ; maker ID
  157. db $01                                  ; Version     =1
  158. db $DA                                  ; Complement check (Important)
  159. db $ff,$ff                              ; checksum, calculate
  160.  
  161.  
  162.  
  163. SECTION "Game_Code_Start",HOME
  164. ; begining of game code
  165. ; this routine sets up some registers and values, and starts the game
  166. title_stuff::
  167.     ld      sp, STACK_TOP ; put stack where it wants it
  168.     ld      a, VBLANK_INT ; get the vblank int
  169.     ldh     [INTERRUPT_ENABLE], a ; load it into the interrupt enable
  170.     sub     a ; default accumulator value is 1, apparently
  171.     ldh     [LCDC_STATUS], a ; 0
  172.     ldh     [LCDC_CONTROL], a ; 0
  173.     ld      a, 0 ; why do we have this?
  174.     ld      [vblank_flag], a ; reset vblank flag
  175.     ld      bc, TitleScreenData ; load our title screen into here
  176.     call    LoadTitleScreen ; load the title screen, uses the bc register to load
  177.     ; setup the screen and other formats
  178.     ld          a, DISPLAY_FLAG | BKG_DISP_FLAG | SPRITE_DISP_FLAG | TILES_LOC | WINDOW_MAP_LOC ; load this
  179.         ldh             [LCDC_CONTROL],a ; into the LCD control
  180.     call    wait_for_key ; wait for a key to be pressed
  181.    
  182.    
  183. ; this routine loads our title screen and shows it.    
  184. LoadTitleScreen::
  185.         ld              hl, TILES_MEM_LOC_1     ; load the tiles to tiles bank 1
  186.  
  187.         ld              de, 4 * 16
  188.         ld              d, $10  ; 16 bytes per tile
  189.         ld              e, $05  ; number of tiles to load
  190.  
  191. .load_title_loop
  192.         ; only write during
  193.         ldh             a, [LCDC_STATUS]        ; get the status
  194.         and             SPRITE_MODE                     ; don't write during sprite and transfer modes
  195.         jr              nz, .load_title_loop ; ^ loop
  196.  
  197.         ld              a, [bc]         ; get the next value from the source
  198.         ld              [hli], a        ; load the value to the destination, incrementing dest. ptr
  199.         inc             bc                      ; increment the source ptr
  200.  
  201.         ; now loop <DE> times
  202.     ; eli5 wait for d/e = 0
  203.         dec             d
  204.         jp              nz, .load_title_loop ; is d = 0?
  205.         dec             e
  206.         jp              nz, .load_title_loop ; is e = 0?
  207.  
  208.         ret ; make sure we return back
  209.  
  210.  
  211. ; this function waits for A to be pressed
  212. ; when A is pressed, it starts the game, loads the sprites, and the main stuff
  213. ; make sure we add a corporate logo too for "xetoro" lol
  214. wait_for_key::
  215.     call    ReadJoypad ; read the joypad
  216.     ld      a, [joypad_down] ; get the button pressed
  217.     bit     A_BUTTON, a ; was it the a button?
  218.     jr      z, .key_loop ; if not, keep looping
  219.     ld      a, [vblank_flag] ; get the vblank flag
  220.     cp      0 ; check the vblank flag
  221.     jr      z, wait_for_key ; are we in vblank? go back to waiting for a key...
  222.     jp      start ; otherwise, if the a button was pressed, start the game
  223.  
  224.      
  225.    
  226. .key_loop
  227.     jp      wait_for_key ; looping function
  228.    
  229.  
  230.    
  231. ; function to wait for vblank
  232. ; it waits for vblank then rets
  233. WaitVBL::
  234.     ld      a, [vblank_flag] ; get the vblank flag
  235.     cp      0 ; are we in vblank?
  236.     jr      z, WaitVBL ; no, keep looping
  237.  
  238.  
  239. start::
  240.         ld              a, 16
  241.         ldh             [SCROLL_BKG_X], a       ; background map will start at 16,16
  242.         ldh             [SCROLL_BKG_Y], a
  243.  
  244.         ; load the tiles
  245.         ld              bc, TileData
  246.         call    LoadTiles
  247.  
  248.         ; load the background map
  249.         ld              bc, BkgMapData
  250.         call    LoadMapToBkg
  251.  
  252.     call    InitSprites ; clear sprites
  253.    
  254.     call    InitPalettes ; init the palettes
  255.    
  256.  
  257.         ; init player sprite
  258.         ld              a, $40
  259.         ld              [spaceship_xpos], a
  260.         ld              [spaceship_ypos], a
  261.         ld              a, 2
  262.         ld              [spaceship_tile], a
  263.         ld              a, 0
  264.         ld              [spaceship_flags], a
  265.  
  266.        
  267.         ; allow interrupts to start occuring
  268.         ei
  269.    
  270.     jp      Game_Loop
  271.  
  272.    
  273.    
  274.  
  275. ; main game loop
  276. Game_Loop::
  277.         ; don't do a frame update unless we have had a vblank
  278.         ld              a, [vblank_flag]
  279.         cp              0
  280.         jp              z, .end_game_loop
  281.  
  282.         ; get this frame's joypad info
  283.         call    ReadJoypad
  284.  
  285.         ; adjust sprite due to d-pad presses
  286.         call    MoveSpaceship ; yeah I know, I'm dumb
  287.  
  288.         ; reset vblank flag
  289.         ld              a, 0
  290.         ld              [vblank_flag], a
  291.  
  292. .end_game_loop
  293. ; time to loop!
  294.         jp              Game_Loop
  295.  
  296.  
  297.  
  298.  
  299. ;-----------------------------------------------------------------------
  300. ; copy a block of data
  301. ;
  302. ; in:   de - destination ptr
  303. ;               hl - source ptr
  304. ;               b - number of bytes to copy
  305. ;-----------------------------------------------------------------------
  306. CopyBlock::
  307.         push    af ; save af
  308.  
  309. .copy_block_loop
  310.         ld      a, [hli] ; inc hl
  311.         ld              [de], a ; load it into de
  312.         inc             de ; inc that
  313.         dec             b ; dec that
  314.         jr              nz, .copy_block_loop ; then loop
  315.  
  316.         pop             af ; restore af and return
  317.         ret ;
  318.  
  319.  
  320.  
  321.  
  322. ;------------------------------------------
  323. ; init the local copy of the sprites
  324. ;------------------------------------------
  325. InitSprites::
  326.         ld              hl, $c000       ; my sprites are at $c000
  327.         ld              b, 40*4         ; 40 sprites, 4 bytes per sprite
  328.         ld              a, $ff
  329. .init_sprites_loop
  330.         ld              [hli], a
  331.         dec             b
  332.         jr              nz, .init_sprites_loop
  333.     ret
  334.  
  335.  
  336.  
  337. ;----------------------------------------------------
  338. ; load the tiles from ROM into the tile video memory
  339. ;
  340. ; IN:   bc = address of tile data to load
  341. ;----------------------------------------------------
  342. LoadTiles::
  343.         ld              hl, TILES_MEM_LOC_1     ; load the tiles to tiles bank 1
  344.  
  345.         ld              de, 4 * 16
  346.         ld              d, $10  ; 16 bytes per tile
  347.         ld              e, $05  ; number of tiles to load
  348.  
  349. .load_tiles_loop
  350.         ; only write during
  351.         ldh             a, [LCDC_STATUS]        ; get the status
  352.         and             SPRITE_MODE                     ; don't write during sprite and transfer modes
  353.         jr              nz, .load_tiles_loop
  354.  
  355.         ld              a, [bc]         ; get the next value from the source
  356.         ld              [hli], a        ; load the value to the destination, incrementing dest. ptr
  357.         inc             bc                      ; increment the source ptr
  358.  
  359.         ; now loop de times
  360.         dec             d
  361.         jp              nz, .load_tiles_loop
  362.         dec             e
  363.         jp              nz, .load_tiles_loop
  364.  
  365.         ret
  366.  
  367.  
  368.  
  369. ;----------------------------------------------------
  370. ; load the tile map to the background
  371. ;
  372. ; IN:   bc = address of map to load
  373. ;----------------------------------------------------
  374. LoadMapToBkg::
  375.         ld              hl, MAP_MEM_LOC_0       ; load the map to map bank 0
  376.  
  377.         ld              d, $00  ; 256 bytes per "block"
  378.         ld              e, $04  ; 4 blocks (32x32 tiles, 1024 bytes)
  379.  
  380. .load_map_loop
  381.         ; only write during
  382.         ldh             a, [LCDC_STATUS]        ; get the status
  383.         and             SPRITE_MODE                     ; don't write during sprite and transfer modes
  384.         jr              nz, .load_map_loop
  385.  
  386.         ld              a, [bc]         ; get the next value from the source
  387.         ld              [hli], a        ; load the value to the destination, incrementing dest. ptr
  388.         inc             bc                      ; increment the source ptr
  389.  
  390.         ; now loop de times
  391.         dec             d
  392.         jp              nz, .load_map_loop
  393.         dec             e
  394.         jp              nz, .load_map_loop
  395.  
  396.         ret
  397.  
  398.  
  399.  
  400.  
  401. ;----------------------------------------------------
  402. ; init the palettes to basic
  403. ;----------------------------------------------------
  404. InitPalettes::
  405.         ld              a, %10010011    ; set palette colors
  406.  
  407.         ; load it to all the palettes
  408.         ldh             [PALETTE_BKG], a
  409.         ldh             [PALETTE_SPRITE_0], a
  410.         ldh             [PALETTE_SPRITE_1], a
  411.  
  412.         ret
  413.  
  414.  
  415.  
  416. ;-----------------------------------------------------------------------
  417. ; read the joypad
  418. ;
  419. ; output:
  420. ;               This loads two variables:
  421. ;                       joypad_held             - what buttons are currently held
  422. ;                       joypad_down             - what buttons went down since last joypad read
  423. ;-----------------------------------------------------------------------
  424. ReadJoypad::
  425.         ; get the d-pad buttons
  426.         ld              a, PAD_PORT_DPAD                ; select d-pad
  427.         ldh             [JOYPAD_REGISTER], a    ; send it to the joypad
  428.         ldh             a, [JOYPAD_REGISTER]
  429.         ldh             a, [JOYPAD_REGISTER]
  430.         ldh             a, [JOYPAD_REGISTER]
  431.         ldh             a, [JOYPAD_REGISTER]
  432.         ldh             a, [JOYPAD_REGISTER]
  433.         ldh             a, [JOYPAD_REGISTER]    ; get the result back (takes a few cycles)
  434.         cpl                     ; bit-flip the result
  435. ;  ld   b, a
  436.         and             PAD_OUTPUT_MASK         ; mask out the output bits
  437.         swap    a                                       ; put the d-pad button results to top nibble
  438.         ld              b, a                            ; and store it
  439.  
  440.         ; get A / B / SELECT / START buttons
  441.         ld              a, PAD_PORT_BUTTONS             ; select buttons
  442.         ldh             [JOYPAD_REGISTER], a    ; send it to the joypad
  443.         ldh             a, [JOYPAD_REGISTER]
  444.         ldh             a, [JOYPAD_REGISTER]
  445.         ldh             a, [JOYPAD_REGISTER]
  446.         ldh             a, [JOYPAD_REGISTER]
  447.         ldh             a, [JOYPAD_REGISTER]
  448.         ldh             a, [JOYPAD_REGISTER]    ; get the result back (takes even more cycles?)
  449.         cpl                     ; bit-flip the result
  450.         and             PAD_OUTPUT_MASK         ; mask out the output bits
  451.         or              b                                       ; add it to the other button bits
  452.         ld              b, a                    ; put it back in c
  453.  
  454.         ; calculate the buttons that went down since last joypad read
  455.         ld              a, [joypad_held]        ; grab last button bits
  456.         cpl                                                     ; invert them
  457.         and             b                                       ; combine the bits with current bits
  458.         ld              [joypad_down], a        ; store just-went-down button bits
  459.  
  460.         ld              a, b
  461.         ld      [joypad_held], a        ; store the held down button bits
  462.  
  463.         ld              a, $30       ; reset joypad
  464.     ldh         [JOYPAD_REGISTER],A
  465.  
  466.         ret                     ; done
  467.  
  468.  
  469.  
  470.  
  471. ;
  472. ; some random text that will be incorporated into the game later
  473. ; or maybe not, who knows. this is just here for later when we get a printtext routine going
  474. ;
  475. IGText::
  476.     db      "Welcome to Silver!", 0
  477.    
  478. ;---------------------------------------------------
  479. ; my vblank routine - do all graphical changes here
  480. ; while the display is not drawing
  481. ;---------------------------------------------------
  482. VBlankFunc::
  483.         di              ; disable interrupts
  484.         push    af
  485.  
  486.         ; increment my little timer
  487.         ld              a, [ScrollTimer]                        ; get the scroll timer
  488.         inc             a                                       ; increment it
  489.         ld              [ScrollTimer], a
  490.  
  491.         ; is it time to scroll yet?
  492.         and             %00000001
  493.         jr              nz, .vblank_sprite_DMA  ; only scroll ever other vblank
  494.  
  495. .vblank_do_scroll
  496.         ld              c, 3    ; scroll 3 pixels
  497.         ld              a, [scrl_dir_flag]
  498.         cp              0
  499.         jr              z, .vblank_scroll_up
  500.         call    ScrollScreenDown
  501.         jr              .vblank_scrolled_down
  502. .vblank_scroll_up
  503.         call    ScrollScreenUp
  504. .vblank_scrolled_down
  505.  
  506. ; load the sprite attrib table to OAM memory
  507. .vblank_sprite_DMA
  508.         ld              a, $c0                          ; dma from $c000 (where I have my local copy of the attrib table)
  509.         ldh             [DMA_REGISTER], a       ; start the dma
  510.  
  511.         ld              a, $28          ; wait for 160 microsec (using a loop)
  512. .vblank_dma_wait
  513.         dec             a
  514.         jr              nz, .vblank_dma_wait
  515.  
  516.         ld              hl, SPRITE_ATTRIB_MEM_LOC
  517.  
  518.         ; set the vblank occured flag
  519.         ld              a, 1
  520.         ld              [vblank_flag], a
  521.  
  522.  
  523.         pop af
  524.         ei              ; enable interrupts
  525.         reti    ; and done
  526.  
  527.  
  528.  
  529.  
  530. MoveSpaceship::
  531.         push    af
  532.  
  533.         ; check buttons for d-pad presses
  534. .check_for_up
  535.         ld              a, [joypad_held]
  536.         bit             DPAD_UP, a
  537.         jp              z, .check_for_down      ; if button not pressed then done
  538.  
  539.         ; up was held down
  540. .check_for_upright
  541.         ; is right also held?
  542.         ld              a, [joypad_held]
  543.         bit             DPAD_RIGHT, a
  544.         jp              z, .check_for_upleft
  545.  
  546.         ; up + right held, so sprite needs to be diagonal
  547.         ld              a, 1                            ; diagonal sprite is tile 1
  548.         ld              [spaceship_tile], a
  549.         ld              a, 0                            ; flags are no x or y flip
  550.         ld              [spaceship_flags], a
  551.  
  552.         jp              .adjust_up_pos
  553.  
  554. .check_for_upleft
  555.         ; is left also held?
  556.         ld              a, [joypad_held]
  557.         bit             DPAD_LEFT, a
  558.         jp              z, .set_up_only
  559.  
  560.         ; up + left held, so sprite needs to be diagonal
  561.         ld              a, 1                            ; diagonal sprite is tile 1
  562.         ld              [spaceship_tile], a
  563.         ld              a, SPRITE_FLAGS_XFLIP   ; sprite should be x flipped
  564.         ld              [spaceship_flags], a
  565.  
  566.         jp              .adjust_up_pos
  567.  
  568. .set_up_only
  569.         ; only up was held, so sprite needs to be up
  570.         ld              a, 0    ; vertical sprite is tile 0
  571.         ld              [spaceship_tile], a
  572.         ld              a, 0
  573.         ld              [spaceship_flags], a
  574.  
  575. .adjust_up_pos
  576.         ; adjust the sprite's position
  577.         ld              a, [ScrollTimer]        ; only move sprite every 2nd vblank
  578.         and             %00000001
  579.         jr              nz, .check_for_left
  580.  
  581.         ; move sprite up a pixel
  582.         ld              a, [spaceship_ypos]
  583.         dec             a
  584.         ld              [spaceship_ypos], a
  585.  
  586.         ; don't check down, since up + down should never occur
  587.         jp              .check_for_left
  588.  
  589. .check_for_down
  590.         ld              a, [joypad_held]
  591.         bit             DPAD_DOWN, a
  592.         jp              z, .check_for_left      ; if button not pressed then done
  593.  
  594.         ; down was held down
  595. .check_for_downright
  596.         ; is right also held?
  597.         ld              a, [joypad_held]
  598.         bit             DPAD_RIGHT, a
  599.         jp              z, .check_for_downleft
  600.  
  601.         ; down + right held, so sprite needs to be diagonal
  602.         ld              a, 1                            ; diagonal sprite is tile 1
  603.         ld              [spaceship_tile], a
  604.         ld              a, SPRITE_FLAGS_YFLIP   ; y flip the sprite
  605.         ld              [spaceship_flags], a
  606.  
  607.         jp              .adjust_down_pos
  608.  
  609. .check_for_downleft
  610.         ; is left also held?
  611.         ld              a, [joypad_held]
  612.         bit             DPAD_LEFT, a
  613.         jp              z, .set_down_only
  614.  
  615.         ; down + left held, so sprite needs to be diagonal
  616.         ld              a, 1                            ; diagonal sprite is tile 1
  617.         ld              [spaceship_tile], a
  618.         ld              a, SPRITE_FLAGS_XFLIP + SPRITE_FLAGS_YFLIP      ; sprite should be x and y flipped
  619.         ld              [spaceship_flags], a
  620.  
  621.         jp              .adjust_down_pos
  622.  
  623. .set_down_only
  624.         ; only down was held, so sprite needs to be down
  625.         ld              a, 0    ; vertical sprite is tile 0
  626.         ld              [spaceship_tile], a
  627.         ld              a, SPRITE_FLAGS_YFLIP
  628.         ld              [spaceship_flags], a
  629.  
  630. .adjust_down_pos
  631.         ; adjust the sprite's position
  632.         ld              a, [ScrollTimer]        ; only move sprite every 2nd vblank
  633.         and             %00000001
  634.         jr              nz, .check_for_left
  635.  
  636.         ; move sprite up a pixel
  637.         ld              a, [spaceship_ypos]
  638.         inc             a
  639.         ld              [spaceship_ypos], a
  640.  
  641. .check_for_left
  642.         ld              a, [joypad_held]
  643.         bit             DPAD_LEFT, a
  644.         jp              z, .check_for_right     ; if button not pressed then done
  645.  
  646.         ; left was pressed
  647. .check_left_andUpOrDown
  648.         ld              a, [joypad_held]
  649.         and             DPAD_UP_MASK + DPAD_DOWN_MASK
  650.         jp              nz, .adjust_left_pos    ; if up or down was pressed, then we already set the sprite attribs
  651.  
  652.         ; sprite needs to be horizontal
  653.         ld              a, 2            ; horizontal sprite is tile 2
  654.         ld              [spaceship_tile], a
  655.         ld              a, SPRITE_FLAGS_XFLIP
  656.         ld              [spaceship_flags], a
  657.  
  658. .adjust_left_pos
  659.         ld              a, [ScrollTimer]        ; only move sprite every 2nd vblank
  660.         and             %00000001
  661.         jr              nz, .done_checking_dpad
  662.  
  663.         ; move sprite left one pixel
  664.         ld              a, [spaceship_xpos]
  665.         dec             a
  666.         ld              [spaceship_xpos], a
  667.  
  668.         jp              .done_checking_dpad     ; if left was pressed, don't check right
  669.  
  670. .check_for_right
  671.         ld              a, [joypad_held]
  672.         bit             DPAD_RIGHT, a
  673.         jp              z, .done_checking_dpad  ; if button not pressed then done
  674.  
  675.         ; right was pressed
  676. .check_right_andUpOrDown
  677.         ld              a, [joypad_held]
  678.         and             DPAD_UP_MASK + DPAD_DOWN_MASK
  679.         jp              nz, .adjust_right_pos   ; if up or down was pressed, then we already set the sprite attribs
  680.  
  681.         ; sprite needs to be horizontal
  682.         ld              a, 2            ; horizontal sprite is tile 2
  683.         ld              [spaceship_tile], a
  684.         ld              a, 0
  685.         ld              [spaceship_flags], a
  686.  
  687. .adjust_right_pos
  688.         ld              a, [ScrollTimer]        ; only move sprite every 2nd vblank
  689.         and             %00000001
  690.         jr              nz, .done_checking_dpad
  691.  
  692.         ; move sprite left one pixel
  693.         ld              a, [spaceship_xpos]
  694.         inc             a
  695.         ld              [spaceship_xpos], a
  696.  
  697.         jp              .done_checking_dpad     ; if left was pressed, don't check right
  698.  
  699. .done_checking_dpad
  700.         ld              a, [joypad_down]
  701.         bit             A_BUTTON, a
  702.         jr              z, .check_b_button
  703.  
  704.  
  705. .check_b_button
  706.         ld              a, [joypad_down]
  707.         bit             B_BUTTON, a
  708.         jr              z, .done_move_ship
  709.  
  710.         ld              a, [scrl_dir_flag]
  711.         xor             1
  712.         ld              [scrl_dir_flag], a      ; toggle the scroll direction flag
  713.  
  714. .done_move_ship
  715.         pop             af
  716.         ret
  717.  
  718.  
  719.  
  720.  
  721.  
  722. ;-------------------------------------------------------------
  723. ; scroll the screen up a few pixels, adding new tiles to the
  724. ; bottom of the screen map as necessary
  725. ;
  726. ; in:   c = # pixels to scroll
  727. ;-------------------------------------------------------------
  728. ScrollScreenUp::
  729.         push    af
  730.         push    bc
  731.         push    de
  732.         push    hl
  733.  
  734.         ; get the number of pixels we have scrolled since the last tile load
  735.         ld              a, [y_scrl_accum]
  736.         add             a, c
  737.         cp              8       ; has the accum gone past 7?
  738.         jr              c, .scroll_screen_up_done       ; no, we don't need to add any tiles
  739.  
  740.         ; yes, we need to add some tiles to the bottom of the screen
  741. .scroll_screen_up_tiles_loop
  742.         ; calc the line we need to add tiles to
  743.         push    af              ; save the loop variable
  744.         ldh             a, [SCROLL_BKG_Y]       ;get the current y screen position
  745.         srl             a
  746.         srl             a
  747.         srl             a       ; divide by 8 (get tile pos from pixel pos)
  748.         add             a, 20   ; screen is 18 tiles hi, so add tiles 20 lines down from screen pos
  749.         cp              32              ; did we go past the end of the bkg map?
  750.         jr              c, .scroll_screen_up_add_tiles  ; no, we have the tile line we need
  751.  
  752.         ; yes, we need to wrap
  753.         sub             32
  754.  
  755. .scroll_screen_up_add_tiles
  756.         ld      b, a    ; store line number for input to routine
  757.         ld              a, [world_y]    ; get our world screen position (lo byte)
  758.         ld              d, a
  759.         ld              a, [world_y+1]  ; hi byte
  760.         srl             a
  761.         rr              d       ; left shift the hi and low bytes
  762.         srl             a
  763.         rr              d       ; left shift the hi and low bytes
  764.         srl             a
  765.         rr              d       ; left shift the hi and low bytes - div by 8!
  766.         ld              a, d    ; the low byte hold the interesting data after ths shift
  767.         add             a, 20   ; go down 20 tiles to tile we want to add
  768.         cp              64      ; world is 64 tiles tall
  769.         jr              c, .scroll_screen_up_wrap_world
  770.  
  771.         sub             64      ; wrap
  772.  
  773. .scroll_screen_up_wrap_world
  774.         ld              e, a
  775.         ld              d, 0
  776.         sla             e
  777.         rl              d       ; shift de up one bit
  778.         sla             e
  779.         rl              d       ; shift de up one bit
  780.         sla             e
  781.         rl              d       ; shift de up one bit
  782.         sla             e
  783.         rl              d       ; shift de up one bit
  784.         sla             e
  785.         rl              d       ; shift de up one bit - multiply world_y by 32
  786.  
  787.         ld              hl, WorldMap    ; get the top of the world map
  788.         add             hl, de  ; set address of line to load
  789.  
  790.         call    AddWorldTilesLine       ; add the line of tiles!
  791.  
  792.         pop             af              ; restore the loop variable
  793.  
  794.         sub             8       ; did one tile line (8 pixels)
  795.         cp              7       ; still greater than 7?
  796.         jr              nc, .scroll_screen_up_tiles_loop        ; yes, do another line of tiles!
  797.  
  798. .scroll_screen_up_done
  799.         ; update the y scroll accumulator and the world pos
  800.         ld              [y_scrl_accum], a
  801.  
  802.         ld              a, [world_y+1]  ; get world y pos hi byte
  803.         ld              b, a
  804.         ld              a, [world_y]    ; lo byte
  805.         add             a, c    ; adjust world pos
  806.         jr              nc, .scroll_screen_up_nocarry
  807.  
  808.         inc             b       ; carry flag... increase hi byte
  809.  
  810. .scroll_screen_up_nocarry
  811.         ld              d, a
  812.         ld              a, b    ; get hi byte of world y
  813.         cp      $02             ; less than hi byte of world height (64 tiles * 8 pixels/byte = 512)?
  814.         jr      c, .scroll_screen_up_worldwrap
  815.         ld              a, d
  816.         cp              $00             ; lo byte of world x < lo byte of 512?
  817.         jr              c, .scroll_screen_up_worldwrap
  818.  
  819.         ; world y is greater than world map y... we need to wrap
  820.         ld              b, 0    ; clear hi byte, leave lo byte alone (now $20x becomes $00x)
  821.  
  822. .scroll_screen_up_worldwrap
  823.         ld              a, d
  824.         ld              [world_y], a
  825.         ld              a, b
  826.         ld              [world_y+1], a
  827.  
  828.         ; update the background scroll plane scroll
  829.         ldh             a, [SCROLL_BKG_Y]
  830.         add             a, c
  831.         ldh             [SCROLL_BKG_Y], a
  832.  
  833.         pop             hl
  834.         pop     de
  835.         pop             bc
  836.         pop             af
  837.         ret
  838.  
  839.  
  840. ;-------------------------------------------------------------
  841. ; scroll the screen down a few pixels, adding new tiles to the
  842. ; top of the screen map as necessary
  843. ;
  844. ; in:   c = # pixels to scroll
  845. ;-------------------------------------------------------------
  846. ScrollScreenDown::
  847.         push    af
  848.         push    bc
  849.         push    de
  850.         push    hl
  851.  
  852.         ; get the number of pixels we have scrolled since the last tile load
  853.         ld              a, [y_scrl_accum]
  854.         sub             c
  855.         cp              8       ; has the accum gone below 0?
  856.         jr              c, .scroll_screen_down_done     ; no, we don't need to add any tiles
  857.  
  858.         ; yes, we need to add some tiles to the top of the screen
  859. .scroll_screen_down_tiles_loop
  860.         ; calc the line we need to add tiles to
  861.         push    af              ; save the loop variable
  862.         ldh             a, [SCROLL_BKG_Y]       ;get the current y screen position
  863.         srl             a
  864.         srl             a
  865.         srl             a       ; divide by 8 (get tile pos from pixel pos)
  866.         sub             2       ; add tiles to line two tiles off the top of the screen
  867.         cp              32              ; did we go past the end of the bkg map?
  868.         jr              c, .scroll_screen_down_add_tiles        ; no, we have the tile line we need
  869.  
  870.         ; yes, we need to wrap
  871.         add             a, 32
  872.  
  873. .scroll_screen_down_add_tiles
  874.         ld      b, a    ; store line number for input to routine
  875.         ld              a, [world_y]    ; get our world screen position (lo byte)
  876.         ld              d, a
  877.         ld              a, [world_y+1]  ; hi byte
  878.         srl             a
  879.         rr              d       ; left shift the hi and low bytes
  880.         srl             a
  881.         rr              d       ; left shift the hi and low bytes
  882.         srl             a
  883.         rr              d       ; left shift the hi and low bytes - div by 8!
  884.         ld              a, d    ; the low byte hold the interesting data after ths shift
  885.         sub             2       ; go up two tiles to tile we want to add
  886.         cp              64      ; world is 64 tiles tall
  887.         jr              c, .scroll_screen_down_wrap_world
  888.  
  889.         add             a, 64   ; wrap
  890.  
  891. .scroll_screen_down_wrap_world
  892.         ld              e, a
  893.         ld              d, 0
  894.         sla             e
  895.         rl              d       ; shift de up one bit
  896.         sla             e
  897.         rl              d       ; shift de up one bit
  898.         sla             e
  899.         rl              d       ; shift de up one bit
  900.         sla             e
  901.         rl              d       ; shift de up one bit
  902.         sla             e
  903.         rl              d       ; shift de up one bit - multiply world_y by 32
  904.  
  905.         ld              hl, WorldMap    ; get the top of the world map
  906.         add             hl, de  ; set address of line to load
  907.  
  908.         call    AddWorldTilesLine       ; add the line of tiles!
  909.  
  910.         pop             af              ; restore the loop variable
  911.  
  912.         add             a, 8    ; did one tile line (8 pixels)
  913.         cp              8       ; still less than zero (greater than 8)?
  914.         jr              nc, .scroll_screen_down_tiles_loop      ; yes, do another line of tiles!
  915.  
  916. .scroll_screen_down_done:
  917.         ; update the y scroll accumulator and the world pos
  918.         ld              [y_scrl_accum], a
  919.  
  920.         ld              a, [world_y+1]  ; get world y pos hi byte
  921.         ld              b, a
  922.         ld              a, [world_y]    ; lo byte
  923.         sub             c       ; adjust world pos
  924.         jr              nc, .scroll_screen_down_nocarry
  925.  
  926.         dec             b       ; carry flag... increase hi byte
  927.  
  928. .scroll_screen_down_nocarry
  929.         ld              d, a
  930.         ld              a, b    ; get hi byte of world y
  931.         cp      $02             ; less than hi byte of world height (64 tiles * 8 pixels/byte = 512)?
  932.         jr      c, .scroll_screen_down_worldwrap
  933.         ld              a, d
  934.         cp              $00             ; lo byte of world x < lo byte of 512?
  935.         jr              c, .scroll_screen_down_worldwrap
  936.  
  937.         ; world y is greater than world map y... we need to wrap
  938.         ld              b, 1    ; set hi byte to 1 (now $fffx becomes $01fx)
  939.  
  940. .scroll_screen_down_worldwrap
  941.         ld              a, d
  942.         ld              [world_y], a
  943.         ld              a, b
  944.         ld              [world_y+1], a
  945.  
  946.         ; update the background scroll plane scroll
  947.         ldh             a, [SCROLL_BKG_Y]
  948.         sub             c
  949.         ldh             [SCROLL_BKG_Y], a
  950.  
  951.         pop             hl
  952.         pop     de
  953.         pop             bc
  954.         pop             af
  955.         ret
  956.  
  957.  
  958. ;-----------------------------------------------------
  959. ; add a line of tiles to the background map
  960. ;
  961. ; in:   b = bkg map line number to add tiles to
  962. ;               hl = ptr to 1st tile to add
  963. ;-----------------------------------------------------
  964. AddWorldTilesLine::
  965.         push    af
  966.         push    bc
  967.         push    de
  968.  
  969.         ldh             a, [SCROLL_BKG_X]       ; get the horiz bkg map scroll value
  970.         srl             a
  971.         srl             a
  972.         srl             a       ; divide by 8 (convert pixel value to tile value)
  973.         sub             2       ; go left two more tiles
  974.         cp              32      ; did we go past 0?
  975.         jr              c, .add_tiles_line_get_vram_addr        ; no
  976.  
  977.         ; yes, wrap us back
  978.         add             a, 32
  979.  
  980. .add_tiles_line_get_vram_addr
  981.         ld              c, a    ; store the x tile number
  982.         ld              e, b    ; get the bkg line number
  983.         ld              d, 0
  984.         sla             e
  985.         rl              d       ; shift de up one bit
  986.         sla             e
  987.         rl              d       ; shift de up one bit
  988.         sla             e
  989.         rl              d       ; shift de up one bit
  990.         sla             e
  991.         rl              d       ; shift de up one bit
  992.         sla             e
  993.         rl              d       ; shift de up one bit - multiply de by 32
  994.         ld              a, e
  995.         add             a, c
  996.         ld              e, a    ; add the xpos to de
  997.         push    hl
  998.         ld              hl, MAP_MEM_LOC_0       ; load to map 0
  999.         add             hl, de  ; hl now points at map memory to load to
  1000.         ld              d, h
  1001.         ld              e, l    ; store it in de
  1002.         pop             hl              ; and restore hl = world tile ptr
  1003.  
  1004.         ld              b, 24   ; load 24 tiles
  1005. .add_tiles_line_loop
  1006.         ; only write during
  1007. ;       ldh             a, [LCDC_STATUS]        ; get the status
  1008. ;       and             SPRITE_MODE                     ; don't write during sprite and transfer modes
  1009. ;       jr              nz, add_tiles_line_loop
  1010.  
  1011.         ld              a, [hli]
  1012.         ld              [de], a         ; load a tile ref
  1013.         inc             c               ; inc the x pos
  1014.         ld              a, c
  1015.         cp              32
  1016.         jr              c, .add_tiles_line_loop_end
  1017.  
  1018.         sub             32
  1019.         ld              c, a    ; wrap back
  1020.  
  1021.         ld              a, e
  1022.         sub             32
  1023.         ld              e, a
  1024.         cp              32
  1025.         jr              c, .add_tiles_line_loop_end
  1026.  
  1027.         dec             d               ; subtract 32 from de
  1028.  
  1029. .add_tiles_line_loop_end
  1030.         ld              a, e    ; increment de
  1031.         inc             e
  1032.         jr              nz, .add_tiles_line_incDE
  1033.         inc             d       ; e became $00, so we need to carry the add to top byte
  1034. .add_tiles_line_incDE
  1035.         dec             b
  1036.         jp              nz, .add_tiles_line_loop
  1037.  
  1038.         pop             de
  1039.         pop             bc
  1040.         pop             af
  1041.         ret
  1042.  
  1043.  
  1044.  
  1045.  
  1046.  
  1047.  
  1048.  
  1049.  
  1050.  
  1051.  
  1052. ; tiles are here
  1053. TileData:
  1054. INCLUDE "tgTiles.dat" ; spaceship etc
  1055.  
  1056. TitleScreenData:
  1057. INCLUDE "titleScreen.dat" ; title screen
  1058.  
  1059. ; map is here
  1060. WorldMap:
  1061. BkgMapData
  1062. INCLUDE "tgMap.dat"
  1063.  
  1064.  
  1065.  
  1066. ;-------------------------------------------------------------------------
  1067. ; Internal RAM... store dynamic data here
  1068. ;-------------------------------------------------------------------------
  1069. SECTION "RAM_Start_Sprites",BSS[$C000]
  1070.  
  1071. ; local version of sprite attrib table
  1072. spaceship_ypos:
  1073. ds              1
  1074. spaceship_xpos:
  1075. ds              1
  1076. spaceship_tile:
  1077. ds              1
  1078. spaceship_flags:
  1079. ds              1
  1080.  
  1081.  
  1082.  
  1083.  
  1084.  
  1085.  
  1086. SECTION "RAM_Other_Variables",BSS[$C0A0]
  1087. ; other variables
  1088.  
  1089. ; joypad values
  1090. joypad_held:
  1091. ds              1               ; what buttons are currently held
  1092. joypad_down:
  1093. ds              1               ; what buttons went down since last joypad read
  1094.  
  1095. ; scroll values
  1096. world_x:
  1097. ds              2
  1098. world_y:
  1099. ds              2
  1100.  
  1101. x_scrl_accum:
  1102. ds              1
  1103. y_scrl_accum:
  1104. ds              1
  1105.  
  1106. ; bullets (16 of them, 2 bytes for each)
  1107. ;       1st byte = orientation (3 bits) - if $ff, this bullet is unused
  1108. ;       2nd byte = time left to live (in vblanks)
  1109. bullet_data:
  1110. ds              32
  1111.  
  1112. ; frame timing
  1113. vblank_flag:
  1114. ds              1               ; set if a vblank occured since last pass through game loop
  1115.  
  1116. ; scroll direction flag
  1117. scrl_dir_flag:
  1118. ds              1
  1119.  
  1120. ; temp variables
  1121. ScrollTimer:
  1122. ds              1               ; temp variable for slowing down scroll speed
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement