; ROM de test pour cartouche flash, Gameboy Color uniquement
; Pedobear en 4 couleurs avec "displacement map" X/Y
; CC-BY-NC 2010 - furrtek.org

.ROMGBC                         ; WLA-DX s'arrangera pour mettre $C0 à $0143, flag CGB
.COMPUTEGBCHECKSUM              ; WLA-DX écrira le checksum lui-même (nécessaire sur une vraie GB)
.NAME "PEDOBEAR        "        ; Nom du ROM inscrit dans le header
.EMPTYFILL $00                  ; Padding avec des 0

.CARTRIDGETYPE 3                ; ROM+MBC1+RAM+BATT, pas critique
.LICENSEECODENEW "ED"           ; Code de license Nintendo, j'en ai pas donc...
.COMPUTEGBCOMPLEMENTCHECK       ; WLA-DX écrira le code de verif du header (nécessaire sur une vraie GB)

.MEMORYMAP
SLOTSIZE $4000                  ; Deux banks de 16Ko
DEFAULTSLOT 0
SLOT 0 $0000
SLOT 1 $4000
.ENDME

.ROMBANKSIZE $4000
.ROMBANKS 2

.BANK 0 SLOT 0

.org $0000
.db "BANK 0"                    ; Chaîne de test, utile que pour tester les EEPROMS

.define   DISPLACESTART  $C000  ; Variable en RAM (ligne de départ de l'effet)

.org $0040
call      VBlank                ; L'interruption VBlank tombe ici
reti
.org $0048
call      HBlank                ; L'interruption HBlank tombe ici
reti
.org $0050
reti
.org $0058
reti
.org $0060
reti

.org $0100
nop
jp    start                     ; Entry point (nop recommandé)

.org $0104
; Logo Nintendo, obligatoire
.db $CE,$ED,$66,$66,$CC,$0D,$00,$0B,$03,$73,$00,$83,$00,$0C
.db $00,$0D,$00,$08,$11,$1F,$88,$89,$00,$0E,$DC,$CC,$6E,$E6
.db $DD,$DD,$D9,$99,$BB,$BB,$67,$63,$6E,$0E,$EC,$CC,$DD,$DC
.db $99,$9F,$BB,$B9,$33,$3E

.org $014C
.db $00                         ; Version

.org $0150
start:
  di                            ; Interruption désactivées
  ld     sp,$fff4               ; Début du stack à $FFF4 parce que Nintendo le veut

  xor    a
  ld     hl,DISPLACESTART
  ldi    (hl),a                 ; Init de la variable à 0

  ldh    ($26),a                ; Coupe le circuit son

  call   waitvbl                ; Attend d'être dans le VBlank
  ld     a,%00010001            ; Éteint l'écran
  ldh    ($40),a
  
  ld     de,$9108               ; Charge $91 tiles depuis "tiles" vers la VRAM (OAM)
  ld     bc,tiles
  ld     hl,$8000
  call   loadtiles2bit

  ld     de,$120E               ; Charge la map à "map" de taille $21x$0E en VRAM
  ld     hl,$9800+5
  ld     bc,map
  call   map_tiles

  ld     a,%10000000            ; Selectionne la palette 0, et active l'auto-incrémentation
  ldh    ($68),a

  ld     b,$08                  ; Charge 4 couleurs depuis "palette" (2 octets/couleur)
  ld     hl,palette
loadpalette:
  ldi    a,(hl)
  ldh    ($69),a
  dec    b
  jr     nz,loadpalette

  ld     a,%10010001            ; Allume l'écran, BG on, tiles à $8000
  ldh    ($40),a
  
  ld     a,%00011000            ; Interruptions HBlank et VBlank activées
  ldh    ($41),a
  ld     a,%00000011            ; Interruptions LCD STAT et VBlank activées (double activation à la con)
  ldh    ($FF),a
  
  ei

loop:
  jr     loop


HBlank:
  ldh    a,($44)                ; Teste si on dépasse de la table ($80 octets de long)
  ld     hl,DISPLACESTART       ; Si n° de ligne actuelle + départ > $80, on dépasse
  add    (hl)
  cp     $80 ;$80
  jr     nc,ok
  xor    a                      ; Si on la dépasse, laisser les scrolls à 0
  ok:
  and    %01111111              ; Astuce pour limiter la valeur à la largeur de la table ($80-1)
  ld     hl,displace            ; A=(displace+A)
  ld     d,$00
  ld     e,a
  add    hl,de
  ld     a,(hl)
  ldh    ($43),a                ; Nouvelle valeur du scroll X
  ld     b,a
  ld     a,$FF
  sub    b                      ; A=255-A (l'origine de Y est inversée)
  ldh    ($42),a                ; Nouvelle valeur du scroll Y
  ret

VBlank:
  ld     hl,DISPLACESTART       ; Incrémente la variable (défilement de l'effet)
  ld     a,(hl)
  inc    a
  ld     (hl),a
  ret

; ROUTINES
waitvbl:
  ldh    a,($44)                ; Attend le début d'un VBL (première ligne hors de l'écran, Y>144)
  cp     144
  jr     c, waitvbl
  ret


loadtiles2bit:
  ;DE=Tiles08
  ;BC=Début données
  ;HL=Début VRAM
  call    waitforvramaccess
  push    de             ; Stocke DE pour reinitialiser E plus tard
lp2:
  ld      a, (bc)        ; Chope la ligne de pixels (bitplane 1)
  ldi     (hl), a
  inc     bc
  ld      a, (bc)        ; Chope la ligne de pixels (bitplane 2)
  ldi     (hl), a
  inc     bc             ; Prochaine ligne
  dec     e              ; Une ligne en moins à faire
  jr      nz, lp2        ; Pas la dernière ?
  pop     de             ; Récupère le E d'origine
  dec     d              ; Un tile en moins à faire
  push    de             ; Restocke DE
  jr      nz, lp2        ; Pas le dernier tile ?
  pop     de             ; Rend SP heureux
  ret


map_tiles:
  ;DE=LargeurHauteur
  ;HL=Début VRAM
  ;BC=Début Map
  call    waitforvramaccess
  push    de             ; Stocke DE pour reinitialiser E plus tard
  lpm:
  ld      a,(bc)         ; Chope le numéro de tile
  inc     bc             ; Prochain tile
  ldi     (hl),a         ; Le stocke en VRAM
  dec     e              ; Un tile de moins à faire
  jr      nz,lpm         ; Pas le dernier ?
  pop     de             ; Récupère le E d'origine

  ld      a,$20          ; Calcule ce qu'il faut ajouter à HL pour passer à la ligne suivante
  sub     e              ; Ajouter 32-largeur ($20-E) à HL
fillhl:
  inc     hl
  dec     a
  jr      nz,fillhl      ; INC bouclé plutot qu'un ADD 16 bits et des PUSH/POP

  dec     d              ; Une ligne en moins à faire
  push    de             ; Restocke DE
  jr      nz,lpm         ; Pas la derniere ligne ?
  pop     de             ; Rend SP heureux
  ret


waitforvramaccess:
  push    af
  push    hl
  ld      hl,$FF41
waitvram:
  bit     1,(hl)
  jr      nz,waitvram    ; Attend d'être dans un mode d'accès qui permet d'écrire en VRAM
  pop     hl
  pop     af
  ret


tiles:
.include "code/pedobear_tiles.inc"
map:
.include "code/pedobear_map.inc"

palette:
;    vvvrrrrr  0bbbbbVV
.db %11111111,%11111111    ; Blanc
.db %10001111,%00000001    ; Marron clair
.db %01100110,%00000000    ; Marron foncé
.db %00000000,%00000000    ; Noir

; Moyenne de deux sinus, sur 128 octets
displace:
.db $06,$07,$08,$09,$0A,$0B,$0C,$0D
.db $0E,$0F,$10,$11,$12,$13,$13,$14
.db $15,$15,$16,$16,$16,$16,$17,$17
.db $17,$16,$16,$16,$16,$15,$15,$15
.db $14,$14,$13,$13,$12,$12,$11,$11
.db $10,$10,$10,$10,$0F,$0F,$0F,$0F
.db $0F,$0F,$10,$10,$10,$11,$11,$12
.db $13,$14,$14,$15,$16,$17,$18,$19
.db $1A,$1B,$1C,$1D,$1E,$1E,$1F,$20
.db $21,$21,$22,$22,$23,$23,$23,$23
.db $23,$23,$22,$22,$21,$21,$20,$1F
.db $1E,$1D,$1C,$1B,$1A,$18,$17,$16
.db $14,$13,$11,$10,$0E,$0D,$0C,$0A
.db $09,$08,$06,$05,$04,$03,$03,$02
.db $01,$01,$00,$00,$00,$00,$00,$00
.db $00,$01,$01,$02,$02,$03,$04,$05