;==============================================================
; WLA-DX banking setup
;==============================================================
.memorymap
defaultslot 0
slotsize $8000
slot 0 $0000
.endme

.rombankmap
bankstotal 1
banksize $8000
banks 1
.endro

;==============================================================
; SMS defines
;==============================================================
.define VDPControl $bf
.define VDPData $be
.define VRAMWrite $4000
.define CRAMWrite $c000
.define VRAMRead $0000
.define VDPStatus $bf
.define ControlInput $dc
.define RandomNumberGeneratorWord $c000
.define RandomNumber $c002
.define PipeYCoOrdinates $c003
.define PipeXCoOrdinates $c004
.define PipePattern $c018
.define HOffset $c020
.define ScrollCounter $c021
.define CurrentColumn $c022
.define PixelScrollCount $c023
.define PipeHeightTileIndex $c024
.define PipeGenerateTimer $c025
.define PipeGenerateState $c026
.define PipeHeightCount $c027
.define OpaSpeed $c030
.define Direction $c029
.define GravConstant $01
.define SpeedAddConstant $08
.define MoveCounter $c031
.define MoveConstant $2
.define ButtonLock $c032
.define GapSize $6
.define GameState $c033   ;0 = title screen, 1 = playing, 2 = dead and falling, 3 = dead, 4 = paused
.define PipeDistance1 $c034
.define PipeDistance2 $c035
.define PipeTop1 $c036
.define PipeBottom1 $c037
.define PipeTop2 $c038
.define PipeBottom2 $c039
.define PipeDistanceStartConstant $70
.define FirstPipeGenerated $c040
.define InsidePipeDistance $c041
.define CurrentlyInsidePipe $c042
.define ScoreThousands $c043
.define ScoreHundreds $c044
.define ScoreTens $c045
.define ScoreUnits $c046
.define ZeroTileConstant $4D
.define VDPThousands $3f89
.define VDPHundreds $3f8b
.define VDPTens $3f8d
.define VDPUnits $3f8f


;==============================================================
; SDSC tag and SMS rom header
;==============================================================
.sdsctag 1.3,"Flip-Flap","WIP","Bradley Garlick"

.bank 0 slot 0
.org $0000
;==============================================================
; Boot section
;==============================================================
    di		    ; enable interrupts
    im 1	    ; Interrupt mode 1
    jp main	    ; jump to main program

;==============================================================
; VBlank handler
;==============================================================
.org $38
  push af
    in a,(VDPStatus) ; satisfy interrupt
    push hl
      ;ld hl,VDPStatus
      call VBlankRoutine
    pop hl
  pop af
  ei
  reti

CallHL:
  jp (hl)

.org $0066
;==============================================================
; Pause button handler
;==============================================================
    ld a,(GameState)
    ld b,$1
    sub b
    jp z,PauseGame
    ld a,(GameState)
    ld b,$4
    sub b
    jp z,UnpauseGame
    retn
    PauseGame:
    ld a,$4
    ld (GameState),a
    retn
    UnpauseGame:
    ld a,$1
    ld (GameState),a
    retn

;==============================================================
; Main program
;==============================================================
main:
    ld sp, $dff0	    ;Sets stack to the end of the RAM
    ld a, $01
    ld (CurrentColumn),a

    ;==============================================================
    ; Set up VDP registers
    ;==============================================================
    ld hl,VDPInitData
    ld b,VDPInitDataEnd-VDPInitData
    ld c,VDPControl
    otir

    ;==============================================================
    ; Clear VRAM
    ;==============================================================
    ; 1. Set VRAM write address to $0000
    ld hl,$0000 | VRAMWrite
    call SetVDPAddress
    ; 2. Output 16KB of zeroes
    ld bc,$4000     ; Counter for 16KB of VRAM
-:  xor a
    out (VDPData),a ; Output to VRAM address, which is auto-incremented after each write
    dec bc
    ld a,b
    or c
    jr nz,-

    ;==============================================================
    ; Load palette
    ;==============================================================
    ; 1. Set VRAM write address to CRAM (palette) address 0
    ld hl,$0000 | CRAMWrite
    call SetVDPAddress
    ; 2. Output colour data
    ld hl,TitlePaletteData
    ld bc,TitlePaletteDataEnd-TitlePaletteData
    call CopyToVDP
    ;==============================================================
    ; Load tiles
    ;==============================================================
    ; 1. Set VRAM write address to tile index 0
    ld hl,$0000 | VRAMWrite
    call SetVDPAddress
    ; 2. Output tile data
    ld hl,TileData	       ; Location of tile data
    ld bc,TileDataEnd-TileData	       ; Counter for number of bytes to write
    call CopyToVDP
    ld hl,FontData              ; Location of tile data
    ld bc,FontDataSize          ; Counter for number of bytes to write
    call CopyToVDP

    ;==============================================================
    ; Draw background
    ;==============================================================
    ; 1. Set VRAM write address to tilemap index 0
     ld hl,$39D6 | VRAMWrite
    call SetVDPAddress
    ; 2. Output tilemap data
    ld hl,TitleName
-:  ld a,(hl)
    cp $ff
    jr z,+
    out (VDPData),a
    xor a
    out (VDPData),a
    inc hl
    jr -
 +:
    ld hl,$3B54 | VRAMWrite
    call SetVDPAddress
    ; 2. Output tilemap data
    ld hl,Instructions
-:  ld a,(hl)
    cp $ff
    jr z,+
    out (VDPData),a
    xor a
    out (VDPData),a
    inc hl
    jr -
 +:
    ld hl,$3CC2 | VRAMWrite
    call SetVDPAddress
    ; 2. Output tilemap data
    ld hl,Info1
-:  ld a,(hl)
    cp $ff
    jr z,+
    out (VDPData),a
    xor a
    out (VDPData),a
    inc hl
    jr -
 +:
     ld hl,$3D02 | VRAMWrite
    call SetVDPAddress
    ; 2. Output tilemap data
    ld hl,Info2
-:  ld a,(hl)
    cp $ff
    jr z,+
    out (VDPData),a
    xor a
    out (VDPData),a
    inc hl
    jr -
 +:
    ld hl,$3D42 | VRAMWrite
    call SetVDPAddress
    ; 2. Output tilemap data
    ld hl,Info3
-:  ld a,(hl)
    cp $ff
    jr z,+
    out (VDPData),a
    xor a
    out (VDPData),a
    inc hl
    jr -
 +:
    ld hl,$3D82 | VRAMWrite
    call SetVDPAddress
    ; 2. Output tilemap data
    ld hl,Info4
-:  ld a,(hl)
    cp $ff
    jr z,+
    out (VDPData),a
    xor a
    out (VDPData),a
    inc hl
    jr -
 +:
    ld hl,$3DC2 | VRAMWrite
    call SetVDPAddress
    ; 2. Output tilemap data
    ld hl,Info5
-:  ld a,(hl)
    cp $ff
    jr z,+
    out (VDPData),a
    xor a
    out (VDPData),a
    inc hl
    jr -
 +:
    ; Turn screen on
    ld a,%01100000
;	   ||||||`- Zoomed sprites -> 16x16 pixels
;	   |||||`-- Doubled sprites -> 2 tiles per sprite, 8x16
;	   ||||`--- Mega Drive mode 5 enable
;	   |||`---- 30 row/240 line mode
;	   ||`----- 28 row/224 line mode
;	   |`------ VBlank interrupts
;	   `------- Enable display
    out (VDPControl),a
    ld a,$81
    out (VDPControl),a
    ld a,MoveConstant
    ld (MoveCounter),a
    ei
-:  halt
    jr -

    ; Infinite loop to stop program
;-:  jr -

;==============================================================
; Helper functions
;==============================================================

SetVDPAddress:
; Sets the VDP address
; Parameters: hl = address
    push af
	ld a,l
	out (VDPControl),a
	ld a,h
	out (VDPControl),a
    pop af
    ret

 LoadGamePalette:

    call GetRandomNumber
    ld a,(RandomNumber)
    ld b,$80
    sub b
    jp m,LoadNight
 ; 1. Set VRAM write address to CRAM (palette) address 0
    ld hl,$0000 | CRAMWrite
    call SetVDPAddress
    ; 2. Output colour data
    ld hl,PaletteDataDay
    ld bc,PaletteDataDayEnd-PaletteDataDay
    call CopyToVDP
    ret
    LoadNight:
    ld hl,$0000 | CRAMWrite
    call SetVDPAddress
    ; 2. Output colour data
    ld hl,PaletteDataNight
    ld bc,PaletteDataNightEnd-PaletteDataNight
    call CopyToVDP
    ret

 LoadGameBackground:
 ; 1. Set VRAM write address to tilemap index 0
    ld a,$00
    out ($bf),a
    ld a,$38|$40
    out ($bf),a
    ; 2. Output tilemap data
    ld hl,Tilemap
    ld bc,TilemapEnd-Tilemap
-:  ld a,(hl)	 ; Get data byte
    out ($be),a
    inc hl	 ; Point to next letter
    dec bc
    ld a,b
    or c
    jr nz,-
    ret

LoadGameSprites:
; 1. Set VRAM write address to sprite table y index 0
    ld hl,$3f00 | VRAMWrite
    call SetVDPAddress
    ; 2. Output sprite Y data
    ld hl,SpriteTableY	       ; Location of sprite y co-ordinate data
    ld bc,SpriteTableYEnd-SpriteTableY	       ; Counter for number of bytes to write
    call CopyToVDP
    ; 3. Set VRAM write address to sprite x/pattern table index 0
    ld hl,$3f80 | VRAMWrite
    call SetVDPAddress
    ; 4. Output sprite X data
    ld hl,SpriteTable	       ; Location of tile data
    ld bc,SpriteTableEnd-SpriteTable	       ; Counter for number of bytes to write
    call CopyToVDP
    ret

CopyToVDP:
; Copies data to the VDP
; Parameters: hl = data address, bc = data length
; Affects: a, hl, bc
-:  ld a,(hl)	 ; Get data byte
    out (VDPData),a
    inc hl	 ; Point to next tile
    dec bc
    ld a,b
    or c
    jr nz,-
    ret

VBlankRoutine:
    ld a,(GameState)
    ld b,$0
    sub b
    jp z,AtTitle
    ld a,(GameState)
    ld b,$1
    sub b
    jp z,GameRunning
    ld a,(GameState)
    ld b,$2
    sub b
    jp z,GameFalling
    ld a,(GameState)
    ld b,$3
    sub b
    jp z,Dead
    ret

Dead:
    in a,(ControlInput)  ;Places contents of the current controller input into the accumulator
    ld b, %00010000
    and b
    jp z,Restart
    in a,(ControlInput)  ;Places contents of the current controller input into the accumulator
    ld b, %00100000
    and b
    jp z,Restart
    in a,(ControlInput)  ;Places contents of the current controller input into the accumulator
    ld b, %00110000
    and b
    jp z,Restart
    ret

Restart:
    ld a,$0
    out (VDPControl),a
    ld a,%10001000 ;Write to register 08
    out (VDPControl),a
    call LoadGamePalette
    call LoadGameBackground
    call LoadGameSprites
    ld b,$50
    ld c,$0
    ld h,$c0
    ld l,$00
    -:
    ld (hl),c
    inc hl
    dec b
    jp nz,-
    ld a,$1
    ld (GameState),a
    ld (MoveCounter),a
    ld (CurrentColumn),a
    ret

GameFalling:
    ld hl,$3f00 | VRAMRead
    call SetVDPAddress
    in a,VDPData
    ld b,$98
    cp b
    jp z,FellToGround
    jp nc,FellToGround
DropDown:
    ld a,GravConstant
    ld b,a
    ld a,(OpaSpeed)
    add a,b
    ld (OpaSpeed),a
    ld hl,$3f00 | VRAMRead
    call SetVDPAddress
    in a,VDPData
    ld b,a
    ld a,(OpaSpeed)
    ld c,b
    ld b,a
    ld a,c
    add a,b
    ld hl, $3f00 | VRAMWrite
    call SetVDPAddress
    out (VDPData),a
    ld hl,$3f01 | VRAMRead
    call SetVDPAddress
    in a,VDPData
    ld b,a
    ld a,(OpaSpeed)
    ld c,b
    ld b,a
    ld a,c
    add a,b
    ld hl, $3f01 | VRAMWrite
    call SetVDPAddress
    out (VDPData),a
    ld hl,$3f02 | VRAMRead
    call SetVDPAddress
    in a,VDPData
    ld b,a
    ld a,(OpaSpeed)
    ld c,b
    ld b,a
    ld a,c
    add a,b
    ld hl, $3f02 | VRAMWrite
    call SetVDPAddress
    out (VDPData),a
    ld hl,$3f03 | VRAMRead
    call SetVDPAddress
    in a,VDPData
    ld b,a
    ld a,(OpaSpeed)
    ld c,b
    ld b,a
    ld a,c
    add a,b
    ld hl, $3f03 | VRAMWrite
    call SetVDPAddress
    out (VDPData),a
    jp EndMove
    ret
FellToGround:
    ld b,$AC
    cp b
    jp z,DropDown
    jp nc,DropDown
    ld a,$9C
    ld hl, $3f00 | VRAMWrite
    call SetVDPAddress
    out (VDPData),a
    ld hl, $3f01 | VRAMWrite
    call SetVDPAddress
    out (VDPData),a
    ld a,$A4
    ld hl, $3f02 | VRAMWrite
    call SetVDPAddress
    out (VDPData),a
    ld hl, $3f03 | VRAMWrite
    call SetVDPAddress
    out (VDPData),a
    ld a,$3
    ld (GameState),a
    jp EndMove
    ret

AtTitle:
    call GetRandomNumber
    in a,(ControlInput)  ;Places contents of the current controller input into the accumulator
    ld b, %00010000
    and b
    jp z,StartGame
    ret
StartGame:
    call LoadGamePalette
    call LoadGameBackground
    call LoadGameSprites
    ld a,$1
    ld (GameState),a
    ret


GameRunning:
;Increment scrolling offset
    ld a,(HOffset)
    dec a
    ld (HOffset),a
    out (VDPControl),a
    ld a,%10001000 ;Write to register 08
    out (VDPControl),a
    ;Increment pixel counter
    ld a, (PixelScrollCount)
    inc a
    ld (PixelScrollCount),a
    ;Check for collisions
    ld a,(CurrentlyInsidePipe)
    ld b,$1
    sub b
    jp nz,DecPipes
    ld hl,$3f00 | VRAMRead
    call SetVDPAddress
    in a,VDPData
    ld b,a
    ld a,(PipeTop1)
    dec a
    dec a
    ld c,b
    ld b,a
    ld a,c
    Check1:
    cp b
    jp nc,+
    jp z,+
    jp Collide
    +:
    ld a,(PipeBottom1)
    inc a
    inc a
    ld b,a
    ld a,c
    ld d,$b
    add a,d
    Check2:
    cp b
    jp m,+
    jp nc,Collide
    +:
    ld a,(InsidePipeDistance)
    dec a
    ld (InsidePipeDistance),a
    jp nz, DecPipes
    ld a,$0
    ld (CurrentlyInsidePipe),a
    ld a,(PipeDistance2)
    ld (PipeDistance1),a
    ld a,(PipeTop2)
    ld (PipeTop1),a
    ld a,(PipeBottom2)
    ld (PipeBottom1),a
    ld a,$0
    ld (PipeDistance2),a
    ld (PipeTop2),a
    ld (PipeBottom2),a

    IncrementUnits:
    ld a,(ScoreUnits)
    inc a
    ld b,$a
    cp b
    jp z, TenReached
    ld (ScoreUnits),a
    ld b,a
    ld a,ZeroTileConstant
    add a,b
    ld hl, VDPUnits | VRAMWrite
    call SetVDPAddress
    out (VDPData),a
    jp DecPipes

    TenReached:
    ld a,$0
    ld (ScoreUnits),a
    ld a,ZeroTileConstant
    ld hl, VDPUnits | VRAMWrite
    call SetVDPAddress
    out (VDPData),a

    ld a,(ScoreTens)
    inc a
    ld b,$a
    cp b
    jp z, HundredReached
    ld (ScoreTens),a
    ld b,a
    ld a,ZeroTileConstant
    add a,b
    ld hl, VDPTens | VRAMWrite
    call SetVDPAddress
    out (VDPData),a
    jp DecPipes

    HundredReached:
    ld a,$0
    ld (ScoreTens),a
    ld a,ZeroTileConstant
    ld hl, VDPUnits | VRAMWrite
    call SetVDPAddress
    out (VDPData),a

    ld a,(ScoreHundreds)
    inc a
    ld b,$a
    cp b
    jp z, ThousandReached
    ld (ScoreHundreds),a
    ld b,a
    ld a,ZeroTileConstant
    add a,b
    ld hl, VDPHundreds | VRAMWrite
    call SetVDPAddress
    out (VDPData),a
    jp DecPipes

    ThousandReached:
    ld a,$0
    ld (ScoreHundreds),a
    ld a,ZeroTileConstant
    ld hl, VDPUnits | VRAMWrite
    call SetVDPAddress
    out (VDPData),a

    ld a,(ScoreThousands)
    inc a
    ld b,$a
    cp b
    ld (ScoreThousands),a
    ld b,a
    ld a,ZeroTileConstant
    add a,b
    ld hl, VDPThousands | VRAMWrite
    call SetVDPAddress
    out (VDPData),a
    jp DecPipes

    Collide:
    ld a,$2
    ld (GameState),a
    ret
    DecPipes:
    ;When scrolling screen, decrease distance between player and pipes
    ld a,(PipeDistance2)
    inc a
    dec a
    jp z,DecreasePipe1
    dec a
    ld (PipeDistance2),a
    DecreasePipe1:
    ld a,(PipeDistance1)
    inc a
    dec a
    jp z, ContinueScroll
    dec a
    ld (PipeDistance1),a
    jp nz,ContinueScroll
    ld a,$1
    ld (CurrentlyInsidePipe),a
    ld a,$30
    ld (InsidePipeDistance),a


    ;Compares scroll counter with the number 9: if it is not 9, skip straight to controls. Otherwise, continue
    ContinueScroll:
    ld a,(PixelScrollCount)
    ld b, %00001000
    XOR b
    jp nz,ReadControls
    ;After the 8th pixel is scrolled, redraw the hidden column
    ld a,$0
    ld (PixelScrollCount),a ;Resets the counter to 0
    ld a, (CurrentColumn) ;Gets the current column
    ld c,a                ;Places the current column in register c

    ;****Stuff about loading the new column goes here  ****
    ld a, (PipeGenerateTimer)
    ld b, $8
    sub b                          ;If PipeGenerateTimer is 8 (meaning 8 columns have been generated since the last pipe), generate a new pipe
    jp z,GenerateNewNum
    ld a,(PipeGenerateState)
    inc a
    dec a
    jp nz, LoadPipe                ;If currently in the process of building a pipe, skip straight to LoadPipe
    ld a, (PipeGenerateTimer)
    inc a
    ld (PipeGenerateTimer),a       ;Increment PipeGenerateTimer by 1
    ld a, (CurrentColumn)
    ld c,a
    add a,c
    ld c,a
    ld b,$38
    ld hl,Tilemap
    push bc
    ld b,$0
    add hl,bc
    pop bc
    ld d,$18
    -:
    ld a,c
    out ($bf),a
    ld a, b
    OR $40
    out ($bf),a          ;sets VDP write address to the current tile at bc
    ld a, (hl)   ; Get data byte
    out ($be),a      ; Output it
    inc hl
    ld a, (hl)
    out ($be),a
    dec hl
    push hl
    ld h,b
    ld l,c
    ld b,$0          ;adds $40 to bc
    ld c,$40
    add hl,bc
    ld b,h
    ld c,l
    pop hl
    push bc
    ld b,$0
    ld c,$40
    add hl,bc
    pop bc
    ld a,d
    dec a
    ld d,a
    jp nz,-

    jp FinishingScroll


    GenerateNewNum:
    ld a,$0
    ld (PipeGenerateTimer),a
    call GetRandomNumber
    ld b,%00001111
    AND b                             ;Removes the 4 most significant bits
    ld b, $c
    sub b
    jp m,numberSmallEnough
    ld a, $b                          ;if number is greater than 13, make it equal to 13 (I don't like this way of doing things as it makes 13 3 times more likely but oh well)
    jp storeRandomNumber
    numberSmallEnough:
    add a,b
    ld b,$02
    sub b
    jp m,numberTooSmall
    add a,b
    jp storeRandomNumber

    numberTooSmall:
    ld a, $2
    storeRandomNumber:
    ld (PipeHeightTileIndex),a
    StorePipeDetails:
    ld a,(PipeDistance1)
    inc a
    dec a
    jp nz,StoreInSlot2

    StoreInSlot1:
    ld a,$1
    ld (FirstPipeGenerated),a
    ld a,PipeDistanceStartConstant
    ld (PipeDistance1),a
    ;Finding the top and bottom y values of the new pipe
    ld a,(PipeHeightTileIndex)
    inc a
    ld b,a
    ld a,$0
    ld c,$8
    -:
    add a,b
    dec c
    jp nz,-

    ld (PipeTop1),a
    ld b,$30
    add a,b
    ld (PipeBottom1),a
    jp LoadPipe

    StoreInSlot2:
    ld a,PipeDistanceStartConstant
    ld (PipeDistance2),a
    ;Finding the top and bottom y values of the new pipe
    ld a,(PipeHeightTileIndex)
    inc a
    ld b,a
    ld a,$0
    ld c,$8
    -:
    add a,b
    dec c
    jp nz,-

    ld (PipeTop2),a
    ld b,$30
    add a,b
    ld (PipeBottom2),a


    ;Now that the height of the top pipe has been stored, it's time for the hard part - loading new pipes into the current column.
    LoadPipe:
    ld a, (PipeGenerateState)
    inc a
    ld (PipeGenerateState),a
    ld b, $4
    sub b
    jp nz,+                                 ;Increments the GenerateState. If it reaches 4, reset to 0.
    ld a, $0
    ld (PipeGenerateState),a
    +:
    ld a, (PipeGenerateState)
    push af
    ld b, $1
    sub b
    jp z,TopColumn1
    pop af
    push af
    inc b
    sub b
    jp z,TopColumn2
    pop af
    push af
    inc b
    sub b
    jp z,TopColumn3
    pop af
    push af
    ld b, $0
    sub b
    jp z,TopColumn4
    ;Top pipe drawn first:
    TopColumn1:
    pop af
    ld de, TopPipeColumn1
    jp DrawTopPipe
    TopColumn2:
    pop af
    ld de, TopPipeColumn2
    jp DrawTopPipe
    TopColumn3:
    pop af
    ld de, TopPipeColumn3
    jp DrawTopPipe
    TopColumn4:
    pop af
    ld de, TopPipeColumn4
    DrawTopPipe:
    ld bc, (CurrentColumn)
    ld a, $0
    add a,c
    add a,c
    ld c,a
    ld b,$0
    ld hl, Tilemap
    add hl, bc                              ;hl is currently address of the current background tile
    ld b, $38
    push hl
    ld hl,(PipeHeightTileIndex)
    dec hl
    ld (PipeHeightCount),hl
    pop hl
    -:
    ld a,c
    out ($bf),a
    ld a, b
    OR $40                                  ;Sets VDP Write Address to address bc
    out ($bf),a
    ld a, (de)   ; Get data byte
    out ($be),a      ; Output it
    inc de
    ld a, (de)   ; Get next data byte
    out ($be),a  ;Output it
    dec de
    push de
    ld d,$0
    ld e,$40
    add hl,de
    push hl                                 ;Store hl
    ld h,b
    ld l,c
    add hl,de
    ld b,h
    ld c,l
    pop hl
    pop de
    ld a,(PipeHeightCount)
    dec a
    ld (PipeHeightCount),a
    jp nz,-
    inc de
    inc de
    ld a,c
    out ($bf),a                             ;Draw the last two tiles of the top pipe, then skip down 4 places
    ld a, b
    OR $40                                  ;Sets VDP Write Address to address bc
    out ($bf),a
    ld a, (de)   ; Get data byte
    out ($be),a      ; Output it
    inc de
    ld a, (de)   ; Get next data byte
    out ($be),a  ;Output it
    inc de
    push de
    ld d,$0
    ld e,$40
    add hl,de
    push hl                                 ;Store hl
    ld h,b
    ld l,c
    add hl,de
    ld b,h
    ld c,l
    pop hl
    add hl,de
    pop de
    ld a,c
    out ($bf),a                             ;Draw the last two tiles of the top pipe, then skip down 4 places
    ld a, b
    OR $40                                  ;Sets VDP Write Address to address bc
    out ($bf),a
    ld a, (de)   ; Get data byte
    out ($be),a      ; Output it
    inc de
    ld a, (de)   ; Get next data byte
    out ($be),a  ;Output it
    DrawGap:
    ld a,GapSize
    ld (PipeHeightCount),a
    ld d,h
    ld e,l
    push de
    push hl
    ld h,b
    ld l,c
    ld d,$0
    ld e,$40
    add hl,de
    ld b,h
    ld c,l
    pop hl
    pop de
    -:
    ld a,c
    out ($bf),a
    ld a, b
    OR $40                                  ;Sets VDP Write Address to address bc
    out ($bf),a
    ld a, (de)   ; Get data byte
    out ($be),a      ; Output it
    inc de
    ld a, (de)   ; Get next data byte
    out ($be),a  ;Output it
    dec de
    push de
    ld d,$0
    ld e,$40
    add hl,de
    push hl                                 ;Store hl
    ld h,b
    ld l,c
    add hl,de
    ld b,h
    ld c,l
    pop hl
    pop de
    push hl
    push bc
    ld b,$0
    ld c,$40
    ld h,d
    ld l,e
    add hl,bc
    ld d,h
    ld e,l
    pop bc
    pop hl
    ld a,(PipeHeightCount)
    dec a
    ld (PipeHeightCount),a
    jp nz,-



    DetermineBottomColumn:
    ld a, (PipeGenerateState)
    push bc
    push af
    ld b, $1
    sub b
    jp z,BottomColumn1
    pop af
    push af
    inc b
    sub b
    jp z,BottomColumn2
    pop af
    push af
    inc b
    sub b
    jp z,BottomColumn3
    pop af
    push af
    ld b, $0
    sub b
    jp z,BottomColumn4
    BottomColumn1:
    pop af
    ld de, BottomPipeColumn1
    jp DrawBottomPipe
    BottomColumn2:
    pop af
    ld de, BottomPipeColumn2
    jp DrawBottomPipe
    BottomColumn3:
    pop af
    ld de, BottomPipeColumn3
    jp DrawBottomPipe
    BottomColumn4:
    pop af
    ld de, BottomPipeColumn4
    DrawBottomPipe:
    pop bc                     ;Jumps ahead 4 rows, now draw the top 2 tiles of bottom pipe
    ld a,c
    out ($bf),a                             ;Draw the last two tiles of the top pipe, then skip down 4 places
    ld a, b
    OR $40                                  ;Sets VDP Write Address to address bc
    out ($bf),a
    ld a, (de)   ; Get data byte
    out ($be),a      ; Output it
    inc de
    ld a, (de)   ; Get next data byte
    out ($be),a  ;Output it
    inc de
    push de
    ld d, $0
    ld e, $40
    ld h, b
    ld l, c
    add hl,de
    ld b,h
    ld c,l
    pop de
    ld a,c
    out ($bf),a                             ;Draw the last two tiles of the top pipe, then skip down 4 places
    ld a, b
    OR $40                                  ;Sets VDP Write Address to address bc
    out ($bf),a
    ld a, (de)   ; Get data byte
    out ($be),a      ; Output it
    inc de
    ld a, (de)   ; Get next data byte
    out ($be),a  ;Output it
    inc de
    push de
    ld d, $0
    ld e, $40
    ld h, b
    ld l, c
    add hl,de
    ld b,h
    ld c,l
    pop de
    push bc
    ld a, (PipeHeightTileIndex)                                        ;The number of times to draw the neck of the bottom pipe is 20 - (random number+6)
    ld c, $8
    add a,c
    ld c,a
    ld a,$14
    sub c
    ld (PipeHeightCount),a
    pop bc
    -:
    ld a,c
    out ($bf),a
    ld a, b
    OR $40                                  ;Sets VDP Write Address to address bc
    out ($bf),a
    ld a, (de)   ; Get data byte
    out ($be),a      ; Output it
    inc de
    ld a, (de)   ; Get next data byte
    out ($be),a  ;Output it
    dec de
    push de
    ld d,$0
    ld e,$40
    add hl,de
    push hl                                 ;Store hl
    ld h,b
    ld l,c
    add hl,de
    ld b,h
    ld c,l
    pop hl
    pop de
    ld a,(PipeHeightCount)
    dec a
    ld (PipeHeightCount),a
    jp nz,-


    ;****ENDSTUFF****

    FinishingScroll:
    ld a,$1F
    ld b,a
    ld a,(CurrentColumn)
    sub b
    jp z, FinalColumnReached          ;If CurrentColumn is 1F, do not increment
    ld a,(CurrentColumn)
    inc a
    ld (CurrentColumn),a
    jp +
    FinalColumnReached:
    ld a, $0
    ld (CurrentColumn),a              ;If CurrentColumn is 1F, reset to 0
    +:
;Read controller inputs
ReadControls:
    in a,(ControlInput)  ;Places contents of the current controller input into the accumulator
    ld b, %00010000
    and b
    jp z,ButtonPressed
    in a,(ControlInput)  ;Places contents of the current controller input into the accumulator
    ld b, %00100000
    and b
    jp z,ButtonPressed
    in a,(ControlInput)  ;Places contents of the current controller input into the accumulator
    ld b, %00110000
    and b
    jp z,ButtonPressed

NoButtonPressed:
    ld a,(ButtonLock)
    inc a
    dec a
    jp nz,UnlockPresses
    jp CheckIfMove

UnlockPresses:
    ld a,$0
    ld (ButtonLock),a
    jp CheckIfMove

ButtonPressed:
    ld hl,$3f00 | VRAMRead
    call SetVDPAddress
    in a,VDPData
    ld b,$98
    cp b
    jp z,+
    jp nc,CheckIfMove
    +:
    ld a,(ButtonLock)
    inc a
    dec a
    jp nz,CheckIfMove
    ld a,$1
    ld (ButtonLock),a
    ld a,SpeedAddConstant
    ld (OpaSpeed),a
    ld a,$0
    ld (Direction),a


CheckIfMove:
    ld a,(MoveCounter)
    inc a
    dec a
    jp z, MovePlayer
    dec a
    ld (MoveCounter),a
    jp EndMove

MovePlayer:
    ld a,MoveConstant
    ld (MoveCounter),a
    ld a,(OpaSpeed)
ChangeGrav:
    ld a,(Direction)
    inc a
    dec a
    jp z, ChangeGravPos

ChangeGravNeg:
    ld a,(OpaSpeed)
    ld b,GravConstant
    add a,b
    ld (OpaSpeed),a
    jp DetermineMoveDirection

ChangeGravPos:
    ld a,(OpaSpeed)
    ld b,GravConstant
    sub b
    jp m,GravNowNegative
    ld (OpaSpeed),a
    jp DetermineMoveDirection

GravNowNegative:
    ld b,$1
    sub b
    cpl
    ld (OpaSpeed),a
    ld a,$1
    ld (Direction),a


DetermineMoveDirection:
    ld a,(Direction)
    inc a
    dec a
    jp z,MoveUp
    ld hl,$3f00 | VRAMRead
    call SetVDPAddress
    in a,VDPData
    ld b,$98
    cp b
    jp z,GroundTouched
    jp nc,GroundTouched
MoveDown:
    ld hl,$3f00 | VRAMRead
    call SetVDPAddress
    in a,VDPData
    ld b,a
    ld a,(OpaSpeed)
    ld c,b
    ld b,a
    ld a,c
    add a,b
    ld hl, $3f00 | VRAMWrite
    call SetVDPAddress
    out (VDPData),a
    ld hl,$3f01 | VRAMRead
    call SetVDPAddress
    in a,VDPData
    ld b,a
    ld a,(OpaSpeed)
    ld c,b
    ld b,a
    ld a,c
    add a,b
    ld hl, $3f01 | VRAMWrite
    call SetVDPAddress
    out (VDPData),a
    ld hl,$3f02 | VRAMRead
    call SetVDPAddress
    in a,VDPData
    ld b,a
    ld a,(OpaSpeed)
    ld c,b
    ld b,a
    ld a,c
    add a,b
    ld hl, $3f02 | VRAMWrite
    call SetVDPAddress
    out (VDPData),a
    ld hl,$3f03 | VRAMRead
    call SetVDPAddress
    in a,VDPData
    ld b,a
    ld a,(OpaSpeed)
    ld c,b
    ld b,a
    ld a,c
    add a,b
    ld hl, $3f03 | VRAMWrite
    call SetVDPAddress
    out (VDPData),a
    jp EndMove

GroundTouched:
    ld b,$AC
    cp b
    jp z,MoveDown
    jp nc,MoveDown
    ld a,$9C
    ld hl, $3f00 | VRAMWrite
    call SetVDPAddress
    out (VDPData),a
    ld hl, $3f01 | VRAMWrite
    call SetVDPAddress
    out (VDPData),a
    ld a,$A4
    ld hl, $3f02 | VRAMWrite
    call SetVDPAddress
    out (VDPData),a
    ld hl, $3f03 | VRAMWrite
    call SetVDPAddress
    out (VDPData),a
    ld a,$3
    ld (GameState),a
    jp EndMove



MoveUp:
    ld hl,$3f00 | VRAMRead
    call SetVDPAddress
    in a,VDPData
    ld b,a
    ld a,(OpaSpeed)
    ld c,b
    ld b,a
    ld a,c
    sub b
    ld hl, $3f00 | VRAMWrite
    call SetVDPAddress
    out (VDPData),a
    ld hl,$3f01 | VRAMRead
    call SetVDPAddress
    in a,VDPData
    ld b,a
    ld a,(OpaSpeed)
    ld c,b
    ld b,a
    ld a,c
    sub b
    ld hl, $3f01 | VRAMWrite
    call SetVDPAddress
    out (VDPData),a
    ld hl,$3f02 | VRAMRead
    call SetVDPAddress
    in a,VDPData
    ld b,a
    ld a,(OpaSpeed)
    ld c,b
    ld b,a
    ld a,c
    sub b
    ld hl, $3f02 | VRAMWrite
    call SetVDPAddress
    out (VDPData),a
    ld hl,$3f03 | VRAMRead
    call SetVDPAddress
    in a,VDPData
    ld b,a
    ld a,(OpaSpeed)
    ld c,b
    ld b,a
    ld a,c
    sub b
    ld hl, $3f03 | VRAMWrite
    call SetVDPAddress
    out (VDPData),a
EndMove:


ret



GetRandomNumber:
; Uses a 16-bit RAM variable called RandomNumberGeneratorWord
; Returns an 8-bit pseudo-random number in a
    push hl
    -:	ld hl,(RandomNumberGeneratorWord)
	ld a,h	       ; get high byte
	rrca	       ; rotate right by 2
	rrca
	xor h	       ; xor with original
	rrca	       ; rotate right by 1
	xor l	       ; xor with low byte
	rrca	       ; rotate right by 4
	rrca
	rrca
	rrca
	xor l	       ; xor again
	rra	       ; rotate right by 1 through carry
	adc hl,hl      ; add RandomNumberGeneratorWord to itself
	jr nz,+
	ld hl,$733c    ; if last xor resulted in zero then re-seed random number generator
+:	ld a,r	       ; r = refresh register = semi-random number
	xor l	       ; xor with l which is fairly random
	ld (RandomNumberGeneratorWord),hl
	pop hl
	ld (RandomNumber),a
	ret	       ; return random number in a
	+:
	    pop af
	    jr -

;==============================================================
; Data
;==============================================================

VDPInitData:
.db $24,$80,$00,$81,$ff,$82,$ff,$85,$fb,$86,$ff,$87,$00,$88,$00,$89,$ff,$8a
VDPInitDataEnd:

TitlePaletteData:
.db $00 $3F $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00
.db $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00
TitlePaletteDataEnd:

PaletteDataNight:
.db $00 $14 $08 $18 $1D $14 $14 $1B $1F $0b $14 $28 $00 $00 $00 $00   ;background palette
.db $3F $00 $08 $0A $00 $22 $28 $2A $3F $03 $0C $0F $30 $33 $3C $3F			      ;sprite palette
PaletteDataNightEnd:

PaletteDataDay:
.db $00 $14 $08 $18 $1D $38 $39 $1B $1F $3A $3E $3F $00 $00 $00 $00   ;background palette
.db $3F $00 $08 $0A $00 $22 $28 $2A $3F $03 $0C $0F $30 $33 $3C $3F			      ;sprite palette
PaletteDataDayEnd:

TileData:
; Tile index $000
.db $FF $00 $FF $00 $FF $00 $FF $00 $FF $00 $FF $00 $FF $00 $FF $00 $FF $00 $FF $00 $FF $00 $FF $00 $FF $00 $FF $00 $FF $00 $FF $00
; Tile index $001
.db $FF $00 $FF $00 $FF $00 $FF $00 $FF $00 $FF $00 $FF $00 $FF $00 $FF $00 $FF $00 $FF $00 $FF $00 $FF $00 $FF $00 $FF $00 $07 $F8
; Tile index $002
.db $FF $F8 $01 $FE $FF $FE $00 $FF $FF $FF $00 $FF $FF $FF $00 $FF $FF $FF $00 $FF $FF $FF $00 $FF $FF $FF $00 $FF $FF $FF $00 $FF
; Tile index $003
.db $FF $00 $FF $00 $FF $00 $7F $80 $FF $80 $3F $C0 $FF $C0 $1F $E0 $FF $E0 $0F $F0 $FF $F0 $07 $F8 $FF $F0 $06 $F9 $FF $F9 $00 $FF
; Tile index $004
.db $FF $00 $FF $00 $FF $00 $FF $00 $FF $00 $FF $00 $FF $00 $FF $00 $FF $00 $FF $00 $FF $00 $83 $7C $FF $7C $00 $FF $FF $FF $00 $FF
; Tile index $005
.db $FF $00 $FF $00 $FF $00 $FF $00 $FF $00 $FC $03 $FF $03 $F8 $07 $FF $07 $F0 $0F $FF $0F $E0 $1F $FF $1F $C0 $3F $FF $1F $00 $FF
; Tile index $006
.db $FF $00 $C1 $3E $FF $3E $00 $FF $FF $FF $00 $FF $FF $FF $00 $FF $FF $FF $00 $FF $FF $FF $00 $FF $FF $FF $00 $FF $FF $FF $00 $FF
; Tile index $007
.db $FF $00 $FF $00 $FF $00 $7F $80 $FF $80 $1F $E0 $FF $E0 $0F $F0 $FF $F0 $06 $F9 $FF $F9 $00 $FF $FF $FF $00 $FF $FF $FF $00 $FF
; Tile index $008
.db $FF $00 $FF $00 $FF $00 $F0 $0F $FF $0F $C0 $3F $FF $3F $00 $FF $FF $FF $00 $FF $FF $FF $00 $FF $FF $FF $00 $FF $FF $FF $00 $FF
; Tile index $009
.db $FF $FF $00 $FF $FF $FF $00 $FF $FF $FF $00 $FF $FF $FF $00 $FF $FF $FF $00 $FF $FF $FF $00 $FF $FF $FF $00 $FF $FF $FF $00 $FF
; Tile index $00A
.db $FF $FF $00 $FF $FF $FF $00 $FF $FE $FF $01 $FE $FE $FF $01 $FE $FE $FF $01 $FE $FC $FF $03 $FC $FC $FF $02 $FD $FC $FF $02 $FD
; Tile index $00B
.db $FF $FF $00 $FF $FF $FF $00 $FF $0F $FF $F0 $0F $00 $FF $1F $E0 $00 $FF $11 $EE $00 $FF $F1 $0E $00 $FF $01 $FE $92 $6D $01 $FE
; Tile index $00C
.db $FF $FF $00 $FF $FF $FF $00 $FF $FF $FF $00 $FF $FF $FF $00 $FF $FF $FF $00 $FF $FF $FF $00 $FF $1F $FF $E0 $1F $1F $FF $20 $DF
; Tile index $00D
.db $F0 $FF $0F $F0 $F0 $FF $08 $F7 $F0 $FF $08 $F7 $F3 $FC $08 $F7 $F3 $FC $08 $F7 $00 $FF $FF $00 $00 $FF $80 $7F $49 $B6 $80 $7F
; Tile index $00E
.db $04 $FF $FA $05 $04 $FF $0A $F5 $04 $FF $0A $F5 $04 $FF $0A $F5 $04 $FF $0A $F5 $04 $FF $FA $05 $04 $FF $0A $F5 $24 $DF $0A $F5
; Tile index $00F
.db $92 $6D $01 $FE $92 $6D $01 $FE $00 $FF $01 $FE $00 $FF $01 $FE $92 $6D $01 $FE $92 $6D $01 $FE $92 $6D $01 $FE $00 $FF $01 $FE
; Tile index $010
.db $1F $FF $20 $DF $00 $FF $FF $00 $00 $FF $00 $FF $92 $6D $00 $FF $92 $6D $00 $FF $92 $6D $00 $FF $00 $FF $00 $FF $00 $FF $00 $FF
; Tile index $011
.db $FF $FF $00 $FF $7F $FF $80 $7F $7F $FF $80 $7F $7F $FF $80 $7F $7F $FF $80 $7F $7F $FF $80 $7F $7F $FF $80 $7F $7F $FF $80 $7F
; Tile index $012
.db $49 $B6 $80 $7F $49 $B6 $80 $7F $00 $FF $80 $7F $49 $B6 $80 $7F $49 $B6 $80 $7F $49 $B6 $80 $7F $00 $FF $81 $7E $24 $DB $81 $7E
; Tile index $013
.db $24 $DF $0A $F5 $24 $DF $0A $F5 $04 $FF $0A $F5 $24 $DF $0A $F5 $24 $DF $0A $F5 $24 $DF $0A $F5 $00 $FF $FE $01 $00 $FF $02 $FD
; Tile index $014
.db $92 $6D $00 $FF $92 $6D $00 $FF $92 $6D $00 $FF $00 $FF $00 $FF $00 $FF $00 $FF $92 $6D $00 $FF $92 $6D $00 $FF $92 $6D $00 $FF
; Tile index $015
.db $7F $FF $80 $7F $7F $FF $80 $7F $7F $FF $80 $7F $7F $FF $80 $7F $7F $FF $80 $7F $7F $FF $80 $7F $7F $FF $80 $7F $7F $FF $80 $7F
; Tile index $016
.db $FF $E3 $00 $E3 $FF $9C $00 $80 $FF $7F $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FC $00 $00 $FF $63 $00 $00
; Tile index $017
.db $24 $DB $C1 $3E $03 $FC $C0 $3C $CF $31 $00 $30 $FF $CE $00 $00 $FF $EF $00 $00 $FF $DF $00 $00 $FF $5F $00 $00 $FF $9F $00 $00
; Tile index $018
.db $E0 $1F $02 $1D $F9 $E6 $02 $04 $FF $F9 $00 $00 $FF $7E $00 $00 $FF $9E $00 $00 $FF $EE $00 $00 $FF $E9 $00 $00 $FF $E7 $00 $00
; Tile index $019
.db $F2 $0D $01 $8E $FE $71 $01 $02 $FF $FC $00 $00 $FF $E3 $00 $00 $FF $9C $00 $00 $FF $3B $00 $00 $FF $CB $00 $00 $FF $F7 $00 $00
; Tile index $01A
.db $03 $FC $00 $FC $0F $F3 $00 $F0 $BF $47 $00 $C0 $FF $39 $00 $00 $FF $FE $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00
; Tile index $01B
.db $FF $78 $00 $78 $FF $97 $00 $10 $FF $E3 $00 $00 $FF $FD $00 $00 $FF $7D $00 $00 $FF $BC $00 $00 $FF $B3 $00 $00 $FF $CF $00 $00
; Tile index $01C
.db $FF $FF $00 $FF $FF $3F $00 $3F $FF $CC $00 $0C $FF $83 $00 $00 $FF $BF $00 $00 $FF $4F $00 $00 $FF $F1 $00 $00 $FF $FE $00 $00
; Tile index $01D
.db $FF $9F $00 $00 $FF $7F $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00
; Tile index $01E
.db $FF $E7 $00 $00 $FF $FB $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00
; Tile index $01F
.db $FF $DF $00 $00 $FF $DF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00
; Tile index $020
.db $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00
; Tile index $021
.db $FF $DF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00
; Tile index $022
.db $FF $FF $00 $00 $FF $FE $00 $00 $FF $FD $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00
; Tile index $023
.db $00 $00 $00 $00 $00 $CC $33 $00 $00 $99 $66 $00 $00 $99 $66 $00 $00 $33 $CC $00 $00 $00 $00 $00 $FF $FF $FF $00 $00 $00 $00 $FF
; Tile index $024
.db $00 $00 $00 $FF $00 $00 $00 $FF $00 $00 $00 $FF $00 $00 $00 $FF $00 $00 $00 $FF $00 $00 $00 $FF $00 $00 $00 $FF $00 $00 $00 $FF
; Tile index $025 - Green Square
.db $FF $00 $00 $00 $FF $00 $00 $00 $FF $00 $00 $00 $FF $00 $00 $00 $FF $00 $00 $00 $FF $00 $00 $00 $FF $00 $00 $00 $FF $00 $00 $00
; Tile index $026 - Opa-Opa1
.db $00 $00 $03 $00 $02 $03 $0D $03 $0A $03 $15 $0B $1A $03 $25 $1B $FF $FF $FF $FF $3F $3F $3F $3F $1E $0E $2F $1E $1F $00 $20 $0F
; Tile index $027 - Opa-Opa2
.db $00 $00 $C0 $00 $00 $80 $E0 $C0 $40 $E0 $F8 $E0 $30 $F8 $FC $F8 $00 $FC $FE $FC $FE $FE $01 $FE $00 $00 $FF $00 $00 $7E $81 $7E
; Tile index $028
.db $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $80 $00 $00 $00
; Tile index $029
.db $45 $05 $1A $20 $45 $05 $1A $20 $45 $05 $1A $20 $45 $05 $1A $20 $45 $05 $1A $20 $45 $05 $1A $20 $45 $05 $1A $20 $45 $05 $1A $20
; Tile index $02A
.db $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00
; Tile index $02B
.db $EA $FC $00 $00 $EA $FC $00 $00 $EA $FC $00 $00 $EA $FC $00 $00 $EA $FC $00 $00 $EA $FC $00 $00 $EA $FC $00 $00 $EA $FC $00 $00
; Tile index $02C
.db $FF $00 $00 $00 $80 $00 $40 $3F $8B $0B $34 $40 $8B $0B $34 $40 $8B $0B $34 $40 $8B $0B $34 $40 $8B $0B $34 $40 $8B $0B $34 $40
; Tile index $02D
.db $FF $00 $00 $00 $00 $00 $00 $FF $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00
; Tile index $02E
.db $FF $00 $00 $00 $00 $00 $17 $E8 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00
; Tile index $02F
.db $FF $00 $00 $00 $01 $02 $FC $00 $F5 $FE $00 $00 $F5 $FE $00 $00 $F5 $FE $00 $00 $F5 $FE $00 $00 $F5 $FE $00 $00 $F5 $FE $00 $00
; Tile index $030 - OpaOpa3
.db $0E $00 $11 $02 $00 $01 $0E $00 $00 $00 $03 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00
; Tile index $031 - OpaOpa4
.db $00 $FC $02 $F8 $00 $F0 $0C $00 $00 $00 $F0 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00
; Tile index $032
.db $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00
; Tile index $033
.db $8B $0B $34 $40 $8B $0B $34 $40 $8B $0B $34 $40 $8B $0B $34 $40 $8B $0B $34 $40 $8B $0B $34 $40 $80 $7F $00 $00 $FF $00 $00 $00
; Tile index $034
.db $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $00 $FF $00 $00 $FF $00 $00 $00
; Tile index $035
.db $F5 $FE $00 $00 $F5 $FE $00 $00 $F5 $FE $00 $00 $F5 $FE $00 $00 $F5 $FE $00 $00 $F5 $FE $00 $00 $01 $FE $00 $00 $FF $00 $00 $00
; Tile index $036
.db $FF $00 $00 $00 $80 $7F $00 $00 $8B $0B $34 $40 $8B $0B $34 $40 $8B $0B $34 $40 $8B $0B $34 $40 $8B $0B $34 $40 $8B $0B $34 $40
; Tile index $037
.db $FF $00 $00 $00 $00 $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00
; Tile index $038
.db $FF $00 $00 $00 $01 $FE $00 $00 $F5 $FE $00 $00 $F5 $FE $00 $00 $F5 $FE $00 $00 $F5 $FE $00 $00 $F5 $FE $00 $00 $F5 $FE $00 $00
; Tile index $039
.db $8B $0B $34 $40 $8B $0B $34 $40 $8B $0B $34 $40 $8B $0B $34 $40 $8B $0B $34 $40 $8B $0B $34 $40 $80 $00 $40 $3F $FF $00 $00 $00
; Tile index $03A
.db $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $00 $00 $00 $FF $FF $00 $00 $00
; Tile index $03B
.db $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $FF $FF $00 $00 $00 $00 $17 $E8 $FF $00 $00 $00
; Tile index $03C
.db $F5 $FE $00 $00 $F5 $FE $00 $00 $F5 $FE $00 $00 $F5 $FE $00 $00 $F5 $FE $00 $00 $F5 $FE $00 $00 $01 $02 $FC $00 $FF $00 $00 $00
TileDataEnd:

Tilemap:
.dw $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000
.dw $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000
.dw $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000
.dw $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000
.dw $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000
.dw $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000
.dw $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000
.dw $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000
.dw $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000
.dw $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000
.dw $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000
.dw $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000
.dw $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000
.dw $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000 $0000
.dw $0001 $0000 $0000 $0000 $0000 $0000 $0000 $0201 $0001 $0000 $0000 $0000 $0000 $0000 $0000 $0201 $0001 $0000 $0000 $0000 $0000 $0000 $0000 $0201 $0001 $0000 $0000 $0000 $0000 $0000 $0000 $0201
.dw $0002 $0003 $0004 $0005 $0006 $0007 $0008 $0202 $0002 $0003 $0004 $0005 $0006 $0007 $0008 $0202 $0002 $0003 $0004 $0005 $0006 $0007 $0008 $0202 $0002 $0003 $0004 $0005 $0006 $0007 $0008 $0202
.dw $0009 $0009 $000A $000B $000C $0009 $0009 $0009 $0009 $000A $000B $000C $0009 $0009 $0009 $0009 $000A $000B $000C $0009 $0009 $0009 $0009 $000A $000B $000C $0009 $0009 $0009 $0009 $000A $000B
.dw $0009 $000D $000E $000F $0010 $0011 $0009 $0009 $000D $000E $000F $0010 $0011 $0009 $0009 $000D $000E $000F $0010 $0011 $0009 $0009 $000D $000E $000F $0010 $0011 $0009 $0009 $000D $000E $000F
.dw $0009 $0012 $0013 $040F $0014 $0015 $0009 $0009 $0012 $0013 $040F $0014 $0015 $0009 $0009 $0012 $0013 $040F $0014 $0015 $0009 $0009 $0012 $0013 $040F $0014 $0015 $0009 $0009 $0012 $0013 $040F
.dw $0016 $0017 $0018 $0019 $001A $001B $001C $0016 $0017 $0018 $0019 $001A $001B $001C $0016 $0017 $0018 $0019 $001A $001B $001C $0016 $0017 $0018 $0019 $001A $001B $001C $0016 $0017 $0018 $0019
.dw $001D $001E $001F $0020 $0020 $0021 $0022 $001D $001E $001F $0020 $0020 $0021 $0022 $001D $001E $001F $0020 $0020 $0021 $0022 $001D $001E $001F $0020 $0020 $0021 $0022 $001D $001E $001F $0020
.dw $1023 $1023 $1023 $1023 $1023 $1023 $1023 $1023 $1023 $1023 $1023 $1023 $1023 $1023 $1023 $1023 $1023 $1023 $1023 $1023 $1023 $1023 $1023 $1023 $1023 $1023 $1023 $1023 $1023 $1023 $1023 $1023
.dw $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024
.dw $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024 $1024
TilemapEnd:

SpriteTableY:
.db $60 $60 $68 $68 $30 $30 $30 $30
SpriteTableYEnd:

SpriteTable:
.db $80 $26 $88 $27 $80 $30 $88 $31 $6c $3d $74 $3d $7C $3d $84 $4d
SpriteTableEnd:

PipeColumn:
.db $39 $36 $2c $33 $29 $29 $29 $29 $29 $29 $29 $29 $29 $29
PipeColumnEnd:

TopPipeColumn1:
.dw $0029 $0036 $0039

BottomPipeColumn1:
.dw $002C $0033 $0029

TopPipeColumn2:
.dw $002A $0037 $003A

BottomPipeColumn2:
.dw $002D $0034 $002A

TopPipeColumn3:
.dw $002A $0037 $003B

BottomPipeColumn3:
.dw $002E $0034 $002A

TopPipeColumn4:
.dw $002B $0038 $003C

BottomPipeColumn4:
.dw $002F $0035 $002B

FontData:
.incbin "font.bin" fsize FontDataSize

.asciitable
map " " to "~" = $3D
.enda


TitleName:
.asc "Flip-Flap"
.db $ff

Instructions:
.asc "Press start"
.db $ff

Info1:
.asc "Original game \"FlappyBird\" 2013"
.db $ff

Info2:
.asc "By Dong Nguyen/.GEARS"
.db $ff

Info3:
.asc "Master System version 2015 by"
.db $ff

Info4:
.asc "Bradley Garlick (BrambleG)"
.db $ff

Info5:
.asc "For SMSPower! Competition 2015"
.db $ff
